This source file includes following definitions.
- streq
- filename_eq
- set_flag
- has_flag
- yyerror
- xmalloc
- xrealloc
- xstrdup
- init_sym
- add_sym
- add_link
- find_member
- add_member_decl
- add_member_defn
- add_define
- add_global_defn
- add_global_decl
- add_member
- mark_virtual
- mark_inherited_virtual
- make_namespace
- check_namespace
- find_namespace
- check_namespace_alias
- register_namespace_alias
- enter_namespace
- leave_namespace
- putstr
- ensure_scope_buffer_room
- sym_scope_1
- sym_scope
- dump_members
- dump_sym
- dump_tree
- dump_roots
- process_pp_line
- yylex
- matching_regexp
- token_string
- re_init_scanner
- insert_keyword
- init_scanner
- skip_to
- skip_matching
- skip_initializer
- match_qualified_namespace_alias
- re_init_parser
- parm_list
- print_info
- member
- class_body
- parse_classname
- operator_name
- parse_qualified_ident_or_type
- parse_qualified_param_ident_or_type
- class_definition
- add_declarator
- declaration
- globals
- yyparse
- add_search_path
- open_file
- usage
- version
- process_file
- read_line
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22 #include <stddef.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <assert.h>
27 #include <getopt.h>
28
29 #include <attribute.h>
30 #include <flexmember.h>
31 #include <min-max.h>
32 #include <unlocked-io.h>
33
34
35
36 enum { READ_CHUNK_SIZE = 100 * 1024 };
37
38
39
40 static bool
41 streq (char const *x, char const *y)
42 {
43 return strcmp (x, y) == 0;
44 }
45
46 static bool
47 filename_eq (char const *x, char const *y)
48 {
49 #ifdef __MSDOS__
50 return strcasecmp (x, y) == 0;
51 #elif defined WINDOWSNT
52 return stricmp (x, y) == 0;
53 #else
54 return streq (x, y);
55 #endif
56 }
57
58
59
60 #define DEFAULT_OUTFILE "BROWSE"
61
62
63
64
65 #define EBROWSE_FILE_VERSION "ebrowse 5.0"
66
67
68
69
70
71 #define TREE_HEADER_STRUCT "[ebrowse-hs "
72 #define TREE_STRUCT "[ebrowse-ts "
73 #define MEMBER_STRUCT "[ebrowse-ms "
74 #define CLASS_STRUCT "[ebrowse-cs "
75
76
77
78
79 #define GLOBALS_NAME "*Globals*"
80
81
82
83 enum token
84 {
85 YYEOF = 0,
86 CSTRING = 256,
87 CCHAR,
88 CINT,
89 CFLOAT,
90
91 ELLIPSIS,
92 LSHIFTASGN,
93 RSHIFTASGN,
94 ARROWSTAR,
95 IDENT,
96 DIVASGN,
97 INC,
98 ADDASGN,
99 DEC,
100 ARROW,
101 SUBASGN,
102 MULASGN,
103 MODASGN,
104 LOR,
105 ORASGN,
106 LAND,
107 ANDASGN,
108 XORASGN,
109 POINTSTAR,
110 DCOLON,
111 EQ,
112 NE,
113 LE,
114 LSHIFT,
115 GE,
116 RSHIFT,
117
118
119
120 #undef BOOL
121 #undef TRUE
122 #undef FALSE
123
124 ASM,
125 AUTO,
126 BREAK,
127 CASE,
128 CATCH,
129 CHAR,
130 CLASS,
131 CONST,
132 CONTINUE,
133 DEFAULT,
134 DELETE,
135 DO,
136 DOUBLE,
137 ELSE,
138 ENUM,
139 EXTERN,
140 FLOAT,
141 FOR,
142 FRIEND,
143 GOTO,
144 IF,
145 T_INLINE,
146 INT,
147 LONG,
148 NEW,
149 OPERATOR,
150 PRIVATE,
151 PROTECTED,
152 PUBLIC,
153 REGISTER,
154 RETURN,
155 SHORT,
156 SIGNED,
157 SIZEOF,
158 STATIC,
159 STRUCT,
160 SWITCH,
161 TEMPLATE,
162 THIS,
163 THROW,
164 TRY,
165 TYPEDEF,
166 UNION,
167 UNSIGNED,
168 VIRTUAL,
169 VOID,
170 VOLATILE,
171 WHILE,
172 MUTABLE,
173 BOOL,
174 TRUE,
175 FALSE,
176 SIGNATURE,
177 NAMESPACE,
178 EXPLICIT,
179 TYPENAME,
180 CONST_CAST,
181 DYNAMIC_CAST,
182 REINTERPRET_CAST,
183 STATIC_CAST,
184 TYPEID,
185 USING,
186 WCHAR,
187 FINAL
188 };
189
190
191
192 enum sc
193 {
194 SC_UNKNOWN,
195 SC_MEMBER,
196 SC_STATIC,
197 SC_FRIEND,
198 SC_TYPE
199 };
200
201
202
203 enum visibility
204 {
205 V_PUBLIC,
206 V_PROTECTED,
207 V_PRIVATE
208 };
209
210
211
212 #define F_VIRTUAL 1
213 #define F_INLINE 2
214 #define F_CONST 4
215 #define F_PURE 8
216 #define F_MUTABLE 16
217 #define F_TEMPLATE 32
218 #define F_EXPLICIT 64
219 #define F_THROW 128
220 #define F_EXTERNC 256
221 #define F_DEFINE 512
222
223
224
225 static void
226 set_flag (int *f, int flag)
227 {
228 *f |= flag;
229 }
230
231 static bool
232 has_flag (int f, int flag)
233 {
234 return (f & flag) != 0;
235 }
236
237
238
239 struct member
240 {
241 struct member *next;
242 struct member *anext;
243 struct member **list;
244 unsigned param_hash;
245 int vis;
246 int flags;
247 char *regexp;
248 const char *filename;
249 int pos;
250 char *def_regexp;
251 const char *def_filename;
252 int def_pos;
253 char name[FLEXIBLE_ARRAY_MEMBER];
254 };
255
256
257
258
259 struct link
260 {
261 struct sym *sym;
262 struct link *next;
263 };
264
265
266
267 struct alias
268 {
269 struct alias *next;
270 struct sym *namesp;
271 struct link *aliasee;
272 char name[FLEXIBLE_ARRAY_MEMBER];
273 };
274
275
276
277
278 struct sym
279 {
280 int flags;
281 unsigned char visited;
282 struct sym *next;
283 struct link *subs;
284 struct link *supers;
285 struct member *vars;
286 struct member *fns;
287 struct member *static_vars;
288 struct member *static_fns;
289 struct member *friends;
290 struct member *types;
291 char *regexp;
292 int pos;
293 const char *filename;
294 const char *sfilename;
295 struct sym *namesp;
296 char name[FLEXIBLE_ARRAY_MEMBER];
297 };
298
299
300
301
302 #define P_DEFN 1
303 #define P_DECL 2
304
305 static int info_where;
306 static struct sym *info_cls = NULL;
307 static struct member *info_member = NULL;
308
309
310
311
312
313 static int info_position = -1;
314
315
316
317 static struct option const options[] =
318 {
319 {"append", no_argument, NULL, 'a'},
320 {"files", required_argument, NULL, 'f'},
321 {"help", no_argument, NULL, -2},
322 {"min-regexp-length", required_argument, NULL, 'm'},
323 {"max-regexp-length", required_argument, NULL, 'M'},
324 {"no-nested-classes", no_argument, NULL, 'n'},
325 {"no-regexps", no_argument, NULL, 'x'},
326 {"no-structs-or-unions", no_argument, NULL, 's'},
327 {"output-file", required_argument, NULL, 'o'},
328 {"position-info", required_argument, NULL, 'p'},
329 {"search-path", required_argument, NULL, 'I'},
330 {"verbose", no_argument, NULL, 'v'},
331 {"version", no_argument, NULL, -3},
332 {"very-verbose", no_argument, NULL, 'V'},
333 {NULL, 0, NULL, 0}
334 };
335
336
337
338 static unsigned yyival;
339 static char *yytext;
340 static char *yytext_end;
341
342
343
344 static FILE *yyout;
345
346
347
348 static int yyline;
349
350
351
352 static const char *filename;
353
354
355
356
357 static char is_ident[255];
358 static char is_digit[255];
359 static char is_white[255];
360
361 #define IDENTP(C) is_ident[(unsigned char) (C)]
362 #define DIGITP(C) is_digit[(unsigned char) (C)]
363 #define WHITEP(C) is_white[(unsigned char) (C)]
364
365
366
367 static int f_append;
368 static int f_verbose;
369 static int f_very_verbose;
370 static int f_structs = 1;
371 static int f_regexps = 1;
372 static int f_nested_classes = 1;
373
374
375
376
377
378 static int min_regexp = 5;
379 static int max_regexp = 50;
380
381
382
383 static char *inbuffer;
384 static char *in;
385 static size_t inbuffer_size;
386
387
388
389 #define BUFFER_POS() (in - inbuffer)
390
391
392
393
394
395 static char *string_start;
396
397
398
399
400 #define TABLE_SIZE 1001
401
402
403
404 static struct sym *class_table[TABLE_SIZE];
405
406
407
408
409
410 static struct member *member_table[TABLE_SIZE];
411
412
413
414 static struct alias *namespace_alias_table[TABLE_SIZE];
415
416
417
418
419 static struct sym *global_symbols;
420
421
422
423 static struct sym *current_namespace;
424
425
426
427 static struct sym *all_namespaces;
428
429
430
431 static struct sym **namespace_stack;
432 static int namespace_stack_size;
433 static int namespace_sp;
434
435
436
437 static int tk = -1;
438
439
440
441 struct kw
442 {
443 const char *name;
444 int tk;
445 struct kw *next;
446 };
447
448
449
450 #define KEYWORD_TABLE_SIZE 1001
451 static struct kw *keyword_table[KEYWORD_TABLE_SIZE];
452
453
454
455 struct search_path
456 {
457 char *path;
458 struct search_path *next;
459 };
460
461 static struct search_path *search_path;
462 static struct search_path *search_path_tail;
463
464
465
466 static char *matching_regexp (void);
467 static struct sym *add_sym (const char *, struct sym *);
468 static void add_global_defn (char *, char *, int, unsigned, int, int, int);
469 static void add_global_decl (char *, char *, int, unsigned, int, int, int);
470 static struct member *add_member (struct sym *, char *, int, int, unsigned);
471 static void class_definition (struct sym *, const char *, int, int, int);
472 static char *operator_name (int *);
473 static void parse_qualified_param_ident_or_type (char **);
474
475
476
477
478
479
480
481
482 static void
483 yyerror (const char *format, const char *s)
484 {
485 fprintf (stderr, "%s:%d: ", filename, yyline);
486 fprintf (stderr, format, s);
487 putc ('\n', stderr);
488 }
489
490
491
492
493
494 static void * ATTRIBUTE_MALLOC
495 xmalloc (size_t nbytes)
496 {
497 void *p = malloc (nbytes);
498 if (p == NULL)
499 {
500 yyerror ("out of memory", NULL);
501 exit (EXIT_FAILURE);
502 }
503 return p;
504 }
505
506
507
508
509 static void *
510 xrealloc (void *p, size_t sz)
511 {
512 p = realloc (p, sz);
513 if (p == NULL)
514 {
515 yyerror ("out of memory", NULL);
516 exit (EXIT_FAILURE);
517 }
518 return p;
519 }
520
521
522
523
524
525 static char *
526 xstrdup (char *s)
527 {
528 if (s)
529 return strcpy (xmalloc (strlen (s) + 1), s);
530 return s;
531 }
532
533
534
535
536
537
538
539
540
541
542 static void
543 init_sym (void)
544 {
545 global_symbols = add_sym (GLOBALS_NAME, NULL);
546 }
547
548
549
550
551
552
553
554
555
556 static struct sym *
557 add_sym (const char *name, struct sym *nested_in_class)
558 {
559 struct sym *sym;
560 unsigned h;
561 const char *s;
562 struct sym *scope = nested_in_class ? nested_in_class : current_namespace;
563
564 for (s = name, h = 0; *s; ++s)
565 h = (h << 1) ^ *s;
566 h %= TABLE_SIZE;
567
568 for (sym = class_table[h]; sym; sym = sym->next)
569 if (streq (name, sym->name)
570 && ((!sym->namesp && !scope)
571 || (sym->namesp && scope
572 && streq (sym->namesp->name, scope->name))))
573 break;
574
575 if (sym == NULL)
576 {
577 if (f_very_verbose)
578 {
579 putchar ('\t');
580 puts (name);
581 }
582
583 sym = xmalloc (FLEXSIZEOF (struct sym, name, strlen (name) + 1));
584 memset (sym, 0, offsetof (struct sym, name));
585 strcpy (sym->name, name);
586 sym->namesp = scope;
587 sym->next = class_table[h];
588 class_table[h] = sym;
589 }
590
591 return sym;
592 }
593
594
595
596
597 static void
598 add_link (struct sym *super, struct sym *sub)
599 {
600 struct link *lnk, *lnk2, *p, *prev;
601
602
603 for (p = super->subs, prev = NULL;
604 p && strcmp (sub->name, p->sym->name) > 0;
605 prev = p, p = p->next)
606 ;
607
608
609 if (p == NULL || p->sym != sub)
610 {
611 lnk = (struct link *) xmalloc (sizeof *lnk);
612 lnk2 = (struct link *) xmalloc (sizeof *lnk2);
613
614 lnk->sym = sub;
615 lnk->next = p;
616
617 if (prev)
618 prev->next = lnk;
619 else
620 super->subs = lnk;
621
622 lnk2->sym = super;
623 lnk2->next = sub->supers;
624 sub->supers = lnk2;
625 }
626 }
627
628
629
630
631
632
633
634
635
636
637 static struct member *
638 find_member (struct sym *cls, char *name, int var, int sc, unsigned int hash)
639 {
640 struct member **list;
641 struct member *p;
642 unsigned name_hash = 0;
643 char *s;
644 int i;
645
646 switch (sc)
647 {
648 case SC_FRIEND:
649 list = &cls->friends;
650 break;
651
652 case SC_TYPE:
653 list = &cls->types;
654 break;
655
656 case SC_STATIC:
657 list = var ? &cls->static_vars : &cls->static_fns;
658 break;
659
660 default:
661 list = var ? &cls->vars : &cls->fns;
662 break;
663 }
664
665 for (s = name; *s; ++s)
666 name_hash = (name_hash << 1) ^ *s;
667 i = name_hash % TABLE_SIZE;
668
669 for (p = member_table[i]; p; p = p->anext)
670 if (p->list == list && p->param_hash == hash && streq (name, p->name))
671 break;
672
673 return p;
674 }
675
676
677
678
679
680
681
682
683
684
685
686
687 static void
688 add_member_decl (struct sym *cls, char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int vis, int flags)
689 {
690 struct member *m;
691
692 m = find_member (cls, name, var, sc, hash);
693 if (m == NULL)
694 m = add_member (cls, name, var, sc, hash);
695
696
697 if (!cls->filename || !filename_eq (cls->filename, filename))
698 m->filename = filename;
699
700 m->regexp = regexp;
701 m->pos = pos;
702 m->flags = flags;
703
704 switch (vis)
705 {
706 case PRIVATE:
707 m->vis = V_PRIVATE;
708 break;
709
710 case PROTECTED:
711 m->vis = V_PROTECTED;
712 break;
713
714 case PUBLIC:
715 m->vis = V_PUBLIC;
716 break;
717 }
718
719 info_where = P_DECL;
720 info_cls = cls;
721 info_member = m;
722 }
723
724
725
726
727
728
729
730
731
732
733
734
735 static void
736 add_member_defn (struct sym *cls, char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int flags)
737 {
738 struct member *m;
739
740 if (sc == SC_UNKNOWN)
741 {
742 m = find_member (cls, name, var, SC_MEMBER, hash);
743 if (m == NULL)
744 {
745 m = find_member (cls, name, var, SC_STATIC, hash);
746 if (m == NULL)
747 m = add_member (cls, name, var, sc, hash);
748 }
749 }
750 else
751 {
752 m = find_member (cls, name, var, sc, hash);
753 if (m == NULL)
754 m = add_member (cls, name, var, sc, hash);
755 }
756
757 if (!cls->sfilename)
758 cls->sfilename = filename;
759
760 if (!filename_eq (cls->sfilename, filename))
761 m->def_filename = filename;
762
763 m->def_regexp = regexp;
764 m->def_pos = pos;
765 m->flags |= flags;
766
767 info_where = P_DEFN;
768 info_cls = cls;
769 info_member = m;
770 }
771
772
773
774
775
776
777 static void
778 add_define (char *name, char *regexp, int pos)
779 {
780 add_global_defn (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
781 add_global_decl (name, regexp, pos, 0, 1, SC_FRIEND, F_DEFINE);
782 }
783
784
785
786
787
788
789
790
791
792
793
794
795 static void
796 add_global_defn (char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int flags)
797 {
798 int i;
799 struct sym *sym;
800
801
802
803 if (!var)
804 for (i = 0; i < TABLE_SIZE; ++i)
805 for (sym = class_table[i]; sym; sym = sym->next)
806 if (sym != global_symbols && sym->friends)
807 if (find_member (sym, name, 0, SC_FRIEND, hash))
808 add_member_defn (sym, name, regexp, pos, hash, 0,
809 SC_FRIEND, flags);
810
811
812 add_member_defn (global_symbols, name, regexp, pos, hash, var, sc, flags);
813 }
814
815
816
817
818
819
820
821
822
823
824
825
826 static void
827 add_global_decl (char *name, char *regexp, int pos, unsigned int hash, int var, int sc, int flags)
828 {
829
830
831
832 struct member *m;
833 struct member *found;
834
835 m = found = find_member (global_symbols, name, var, sc, hash);
836 if (m == NULL)
837 m = add_member (global_symbols, name, var, sc, hash);
838
839
840
841
842 if (!found)
843 {
844 if (!global_symbols->filename
845 || !filename_eq (global_symbols->filename, filename))
846 m->filename = filename;
847
848 m->regexp = regexp;
849 m->pos = pos;
850 m->vis = V_PUBLIC;
851 m->flags = flags;
852
853 info_where = P_DECL;
854 info_cls = global_symbols;
855 info_member = m;
856 }
857 }
858
859
860
861
862
863
864
865 static struct member *
866 add_member (struct sym *cls, char *name, int var, int sc, unsigned int hash)
867 {
868 struct member *m = xmalloc (FLEXSIZEOF (struct member, name,
869 strlen (name) + 1));
870 struct member **list;
871 struct member *p;
872 struct member *prev;
873 unsigned name_hash = 0;
874 int i;
875 char *s;
876
877 strcpy (m->name, name);
878 m->param_hash = hash;
879
880 m->vis = 0;
881 m->flags = 0;
882 m->regexp = NULL;
883 m->filename = NULL;
884 m->pos = 0;
885 m->def_regexp = NULL;
886 m->def_filename = NULL;
887 m->def_pos = 0;
888
889 assert (cls != NULL);
890
891 switch (sc)
892 {
893 case SC_FRIEND:
894 list = &cls->friends;
895 break;
896
897 case SC_TYPE:
898 list = &cls->types;
899 break;
900
901 case SC_STATIC:
902 list = var ? &cls->static_vars : &cls->static_fns;
903 break;
904
905 default:
906 list = var ? &cls->vars : &cls->fns;
907 break;
908 }
909
910 for (s = name; *s; ++s)
911 name_hash = (name_hash << 1) ^ *s;
912 i = name_hash % TABLE_SIZE;
913 m->anext = member_table[i];
914 member_table[i] = m;
915 m->list = list;
916
917
918
919 for (prev = NULL, p = *list;
920 p && strcmp (name, p->name) > 0;
921 prev = p, p = p->next)
922 ;
923
924 m->next = p;
925 if (prev)
926 prev->next = m;
927 else
928 *list = m;
929 return m;
930 }
931
932
933
934
935
936
937 static void
938 mark_virtual (struct sym *r)
939 {
940 struct link *p;
941 struct member *m, *m2;
942
943 for (p = r->subs; p; p = p->next)
944 {
945 for (m = r->fns; m; m = m->next)
946 if (has_flag (m->flags, F_VIRTUAL))
947 {
948 for (m2 = p->sym->fns; m2; m2 = m2->next)
949 if (m->param_hash == m2->param_hash && streq (m->name, m2->name))
950 set_flag (&m2->flags, F_VIRTUAL);
951 }
952
953 mark_virtual (p->sym);
954 }
955 }
956
957
958
959
960
961 static void
962 mark_inherited_virtual (void)
963 {
964 struct sym *r;
965 int i;
966
967 for (i = 0; i < TABLE_SIZE; ++i)
968 for (r = class_table[i]; r; r = r->next)
969 if (r->supers == NULL)
970 mark_virtual (r);
971 }
972
973
974
975
976 static struct sym *
977 make_namespace (char *name, struct sym *context)
978 {
979 struct sym *s = xmalloc (FLEXSIZEOF (struct sym, name, strlen (name) + 1));
980 memset (s, 0, offsetof (struct sym, name));
981 strcpy (s->name, name);
982 s->next = all_namespaces;
983 s->namesp = context;
984 all_namespaces = s;
985 return s;
986 }
987
988
989
990
991 static struct sym *
992 check_namespace (char *name, struct sym *context)
993 {
994 struct sym *p = NULL;
995
996 for (p = all_namespaces; p; p = p->next)
997 {
998 if (streq (p->name, name) && (p->namesp == context))
999 break;
1000 }
1001
1002 return p;
1003 }
1004
1005
1006
1007
1008 static struct sym *
1009 find_namespace (char *name, struct sym *context)
1010 {
1011 struct sym *p = check_namespace (name, context);
1012
1013 if (p == NULL)
1014 p = make_namespace (name, context);
1015
1016 return p;
1017 }
1018
1019
1020
1021
1022 static struct link *
1023 check_namespace_alias (char *name)
1024 {
1025 struct link *p = NULL;
1026 struct alias *al;
1027 unsigned h;
1028 char *s;
1029
1030 for (s = name, h = 0; *s; ++s)
1031 h = (h << 1) ^ *s;
1032 h %= TABLE_SIZE;
1033
1034 for (al = namespace_alias_table[h]; al; al = al->next)
1035 if (streq (name, al->name) && (al->namesp == current_namespace))
1036 {
1037 p = al->aliasee;
1038 break;
1039 }
1040
1041 return p;
1042 }
1043
1044
1045
1046 static void
1047 register_namespace_alias (char *new_name, struct link *old_name)
1048 {
1049 unsigned h;
1050 char *s;
1051 struct alias *al;
1052
1053 for (s = new_name, h = 0; *s; ++s)
1054 h = (h << 1) ^ *s;
1055 h %= TABLE_SIZE;
1056
1057
1058
1059 for (al = namespace_alias_table[h]; al; al = al->next)
1060 if (streq (new_name, al->name) && (al->namesp == current_namespace))
1061 return;
1062
1063 al = xmalloc (FLEXSIZEOF (struct alias, name, strlen (new_name) + 1));
1064 strcpy (al->name, new_name);
1065 al->next = namespace_alias_table[h];
1066 al->namesp = current_namespace;
1067 al->aliasee = old_name;
1068 namespace_alias_table[h] = al;
1069 }
1070
1071
1072
1073
1074 static void
1075 enter_namespace (char *name)
1076 {
1077 struct sym *p = find_namespace (name, current_namespace);
1078
1079 if (namespace_sp == namespace_stack_size)
1080 {
1081 int size = max (10, 2 * namespace_stack_size);
1082 namespace_stack
1083 = (struct sym **) xrealloc ((void *)namespace_stack,
1084 size * sizeof *namespace_stack);
1085 namespace_stack_size = size;
1086 }
1087
1088 namespace_stack[namespace_sp++] = current_namespace;
1089 current_namespace = p;
1090 }
1091
1092
1093
1094
1095 static void
1096 leave_namespace (void)
1097 {
1098 assert (namespace_sp > 0);
1099 current_namespace = namespace_stack[--namespace_sp];
1100 }
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111 static void
1112 putstr (const char *s, FILE *fp)
1113 {
1114 if (!s)
1115 {
1116 putc ('(', fp);
1117 putc (')', fp);
1118 putc (' ', fp);
1119 }
1120 else
1121 {
1122 putc ('"', fp);
1123 fputs (s, fp);
1124 putc ('"', fp);
1125 putc (' ', fp);
1126 }
1127 }
1128
1129
1130
1131 static char *scope_buffer;
1132 static int scope_buffer_size;
1133 static int scope_buffer_len;
1134
1135
1136
1137
1138 static void
1139 ensure_scope_buffer_room (int len)
1140 {
1141 if (scope_buffer_len + len >= scope_buffer_size)
1142 {
1143 int new_size = max (2 * scope_buffer_size, scope_buffer_len + len);
1144 scope_buffer = (char *) xrealloc (scope_buffer, new_size);
1145 scope_buffer_size = new_size;
1146 }
1147 }
1148
1149
1150
1151
1152
1153
1154 static char *
1155 sym_scope_1 (struct sym *p)
1156 {
1157 int len;
1158
1159 if (p->namesp)
1160 sym_scope_1 (p->namesp);
1161
1162 if (*scope_buffer)
1163 {
1164 ensure_scope_buffer_room (3);
1165 strcpy (scope_buffer + scope_buffer_len, "::");
1166 scope_buffer_len += 2;
1167 }
1168
1169 len = strlen (p->name);
1170 ensure_scope_buffer_room (len + 1);
1171 strcpy (scope_buffer + scope_buffer_len, p->name);
1172 scope_buffer_len += len;
1173
1174 if (has_flag (p->flags, F_TEMPLATE))
1175 {
1176 ensure_scope_buffer_room (3);
1177 strcpy (scope_buffer + scope_buffer_len, "<>");
1178 scope_buffer_len += 2;
1179 }
1180
1181 return scope_buffer;
1182 }
1183
1184
1185
1186
1187
1188 static char *
1189 sym_scope (struct sym *p)
1190 {
1191 if (!scope_buffer)
1192 {
1193 scope_buffer_size = 1024;
1194 scope_buffer = (char *) xmalloc (scope_buffer_size);
1195 }
1196
1197 *scope_buffer = '\0';
1198 scope_buffer_len = 0;
1199
1200 if (p->namesp)
1201 sym_scope_1 (p->namesp);
1202
1203 return scope_buffer;
1204 }
1205
1206
1207
1208
1209 static void
1210 dump_members (FILE *fp, struct member *m)
1211 {
1212 putc ('(', fp);
1213
1214 for (; m; m = m->next)
1215 {
1216 fputs (MEMBER_STRUCT, fp);
1217 putstr (m->name, fp);
1218 putstr (NULL, fp);
1219 fprintf (fp, "%u ", (unsigned) m->flags);
1220 putstr (m->filename, fp);
1221 putstr (m->regexp, fp);
1222 fprintf (fp, "%u ", (unsigned) m->pos);
1223 fprintf (fp, "%u ", (unsigned) m->vis);
1224 putc (' ', fp);
1225 putstr (m->def_filename, fp);
1226 putstr (m->def_regexp, fp);
1227 fprintf (fp, "%u", (unsigned) m->def_pos);
1228 putc (']', fp);
1229 putc ('\n', fp);
1230 }
1231
1232 putc (')', fp);
1233 putc ('\n', fp);
1234 }
1235
1236
1237
1238
1239 static void
1240 dump_sym (FILE *fp, struct sym *root)
1241 {
1242 fputs (CLASS_STRUCT, fp);
1243 putstr (root->name, fp);
1244
1245
1246 if (root->namesp)
1247 putstr (sym_scope (root), fp);
1248 else
1249 putstr (NULL, fp);
1250
1251
1252 fprintf (fp, "%d", root->flags);
1253 putstr (root->filename, fp);
1254 putstr (root->regexp, fp);
1255 fprintf (fp, "%u", (unsigned) root->pos);
1256 putstr (root->sfilename, fp);
1257 putc (']', fp);
1258 putc ('\n', fp);
1259 }
1260
1261
1262
1263
1264 static void
1265 dump_tree (FILE *fp, struct sym *root)
1266 {
1267 dump_sym (fp, root);
1268
1269 if (f_verbose)
1270 {
1271 putchar ('+');
1272 fflush (stdout);
1273 }
1274
1275 putc ('(', fp);
1276
1277 for (struct link *lk = root->subs; lk; lk = lk->next)
1278 {
1279 fputs (TREE_STRUCT, fp);
1280 dump_tree (fp, lk->sym);
1281 putc (']', fp);
1282 }
1283
1284 putc (')', fp);
1285
1286 dump_members (fp, root->vars);
1287 dump_members (fp, root->fns);
1288 dump_members (fp, root->static_vars);
1289 dump_members (fp, root->static_fns);
1290 dump_members (fp, root->friends);
1291 dump_members (fp, root->types);
1292
1293
1294 putc ('(', fp);
1295 putc (')', fp);
1296
1297
1298 putc ('(', fp);
1299 putc (')', fp);
1300
1301 putc ('\n', fp);
1302 }
1303
1304
1305
1306
1307 static void
1308 dump_roots (FILE *fp)
1309 {
1310
1311
1312 if (!f_append)
1313 {
1314 fputs (TREE_HEADER_STRUCT, fp);
1315 putstr (EBROWSE_FILE_VERSION, fp);
1316
1317 putc ('\"', fp);
1318 if (!f_structs)
1319 fputs (" -s", fp);
1320 if (f_regexps)
1321 fputs (" -x", fp);
1322 putc ('\"', fp);
1323 fputs (" ()", fp);
1324 fputs (" ()", fp);
1325 putc (']', fp);
1326 }
1327
1328
1329
1330 mark_inherited_virtual ();
1331
1332
1333 for (int i = 0; i < TABLE_SIZE; ++i)
1334 for (struct sym *r = class_table[i]; r; r = r->next)
1335 if (!r->supers)
1336 {
1337 fputs (TREE_STRUCT, fp);
1338 dump_tree (fp, r);
1339 putc (']', fp);
1340 }
1341
1342 if (f_verbose)
1343 putchar ('\n');
1344 }
1345
1346
1347
1348
1349
1350
1351
1352 #ifdef DEBUG
1353 #define INCREMENT_LINENO \
1354 do { \
1355 if (f_very_verbose) \
1356 { \
1357 ++yyline; \
1358 printf ("%d:\n", yyline); \
1359 } \
1360 else \
1361 ++yyline; \
1362 } while (0)
1363 #else
1364 #define INCREMENT_LINENO ++yyline
1365 #endif
1366
1367
1368
1369
1370
1371 #define GET(C) ((C) = *in++)
1372 #define UNGET() (--in)
1373
1374
1375
1376
1377
1378 static int
1379 process_pp_line (void)
1380 {
1381 int in_comment = 0, in_string = 0;
1382 int c;
1383 char *p = yytext;
1384
1385
1386 while (WHITEP (GET (c)))
1387 ;
1388
1389
1390 while (IDENTP (c))
1391 {
1392 *p++ = c;
1393 GET (c);
1394 }
1395
1396
1397 *p = '\0';
1398
1399 if (*yytext && streq (yytext, "define"))
1400 {
1401 p = yytext;
1402 while (WHITEP (c))
1403 GET (c);
1404 while (IDENTP (c))
1405 {
1406 *p++ = c;
1407 GET (c);
1408 }
1409
1410 *p = '\0';
1411
1412 if (*yytext)
1413 {
1414 char *regexp = matching_regexp ();
1415 int pos = BUFFER_POS ();
1416 add_define (yytext, regexp, pos);
1417 }
1418 }
1419
1420 while (c && (c != '\n' || in_comment || in_string))
1421 {
1422 if (c == '\\')
1423 GET (c);
1424 else if (c == '/' && !in_comment)
1425 {
1426 if (GET (c) == '*')
1427 in_comment = 1;
1428 }
1429 else if (c == '*' && in_comment)
1430 {
1431 if (GET (c) == '/')
1432 in_comment = 0;
1433 }
1434 else if (c == '"')
1435 in_string = !in_string;
1436
1437 if (c == '\n')
1438 INCREMENT_LINENO;
1439
1440 GET (c);
1441 }
1442
1443 return c;
1444 }
1445
1446
1447
1448
1449 static int
1450 yylex (void)
1451 {
1452 int c;
1453 char end_char;
1454 char *p;
1455
1456 for (;;)
1457 {
1458 while (WHITEP (GET (c)))
1459 ;
1460
1461 switch (c)
1462 {
1463 case '\n':
1464 INCREMENT_LINENO;
1465 break;
1466
1467 case '\r':
1468 break;
1469
1470 case 0:
1471
1472 return YYEOF;
1473
1474 case '\\':
1475 GET (c);
1476 break;
1477
1478 case '"':
1479 case '\'':
1480
1481 end_char = c;
1482 string_start = in;
1483 while (GET (c) && c != end_char)
1484 {
1485 switch (c)
1486 {
1487 case '\\':
1488
1489 if (!GET (c))
1490 {
1491 if (end_char == '\'')
1492 yyerror ("EOF in character constant", NULL);
1493 else
1494 yyerror ("EOF in string constant", NULL);
1495 goto end_string;
1496 }
1497 else switch (c)
1498 {
1499 case '\n':
1500 INCREMENT_LINENO;
1501 case 'a':
1502 case 'b':
1503 case 'f':
1504 case 'n':
1505 case 'r':
1506 case 't':
1507 case 'v':
1508 break;
1509
1510 case 'x':
1511 {
1512
1513 int i;
1514 for (i = 0; i < 2; ++i)
1515 {
1516 GET (c);
1517
1518 if (c >= '0' && c <= '7')
1519 ;
1520 else if (c >= 'a' && c <= 'f')
1521 ;
1522 else if (c >= 'A' && c <= 'F')
1523 ;
1524 else
1525 {
1526 UNGET ();
1527 break;
1528 }
1529 }
1530 }
1531 break;
1532
1533 case '0':
1534 {
1535
1536 int i;
1537 for (i = 0; i < 3; ++i)
1538 {
1539 GET (c);
1540
1541 if (c >= '0' && c <= '7')
1542 ;
1543 else
1544 {
1545 UNGET ();
1546 break;
1547 }
1548 }
1549 }
1550 break;
1551
1552 default:
1553 break;
1554 }
1555 break;
1556
1557 case '\n':
1558 if (end_char == '\'')
1559 yyerror ("newline in character constant", NULL);
1560 else
1561 yyerror ("newline in string constant", NULL);
1562 INCREMENT_LINENO;
1563 break;
1564
1565 default:
1566 break;
1567 }
1568 }
1569
1570 end_string:
1571 return end_char == '\'' ? CCHAR : CSTRING;
1572 case 'R':
1573 if (GET (c) == '"')
1574 {
1575
1576
1577 #define RSTRING_EOF_CHECK \
1578 do { \
1579 if (c == '\0') \
1580 { \
1581 yyerror ("unterminated c++11 rstring", NULL); \
1582 UNGET (); \
1583 return CSTRING; \
1584 } \
1585 } while (0)
1586
1587 char *rstring_prefix_start = in;
1588
1589 while (GET (c) != '(')
1590 {
1591 RSTRING_EOF_CHECK;
1592 if (c == '"')
1593 {
1594 yyerror ("malformed c++11 rstring", NULL);
1595 return CSTRING;
1596 }
1597 }
1598 char *rstring_prefix_end = in - 1;
1599 while (TRUE)
1600 {
1601 switch (GET (c))
1602 {
1603 default:
1604 RSTRING_EOF_CHECK;
1605 break;
1606 case '\n':
1607 INCREMENT_LINENO;
1608 break;
1609 case ')':
1610 {
1611 char *in_saved = in;
1612 char *prefix = rstring_prefix_start;
1613 while (prefix != rstring_prefix_end && GET (c) == *prefix)
1614 {
1615 RSTRING_EOF_CHECK;
1616 prefix++;
1617 }
1618 if (prefix == rstring_prefix_end)
1619 {
1620 if (GET (c) == '"')
1621 return CSTRING;
1622 RSTRING_EOF_CHECK;
1623 }
1624 in = in_saved;
1625 }
1626 }
1627 }
1628 }
1629
1630 UNGET ();
1631
1632 FALLTHROUGH;
1633
1634 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
1635 case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
1636 case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
1637 case 'v': case 'w': case 'x': case 'y': case 'z':
1638 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
1639 case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
1640 case 'O': case 'P': case 'Q': case 'S': case 'T': case 'U':
1641 case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_':
1642 {
1643
1644 unsigned hash;
1645 struct kw *k;
1646
1647 p = yytext;
1648 *p++ = hash = c;
1649
1650 while (IDENTP (GET (*p)))
1651 {
1652 hash = (hash << 1) ^ *p++;
1653 if (p == yytext_end - 1)
1654 {
1655 int size = yytext_end - yytext;
1656 yytext = (char *) xrealloc (yytext, 2 * size);
1657 yytext_end = yytext + 2 * size;
1658 p = yytext + size - 1;
1659 }
1660 }
1661
1662 UNGET ();
1663 *p = 0;
1664
1665 for (k = keyword_table[hash % KEYWORD_TABLE_SIZE]; k; k = k->next)
1666 if (streq (k->name, yytext))
1667 return k->tk;
1668
1669 return IDENT;
1670 }
1671
1672 case '/':
1673
1674 switch (GET (c))
1675 {
1676 case '*':
1677 while (GET (c))
1678 {
1679 switch (c)
1680 {
1681 case '*':
1682 if (GET (c) == '/')
1683 goto comment_end;
1684 UNGET ();
1685 break;
1686 case '\\':
1687 GET (c);
1688 break;
1689 case '\n':
1690 INCREMENT_LINENO;
1691 break;
1692 }
1693 }
1694 comment_end:;
1695 break;
1696
1697 case '=':
1698 return DIVASGN;
1699
1700 case '/':
1701 while (GET (c) && c != '\n')
1702 ;
1703
1704
1705 if (c == 0)
1706 return YYEOF;
1707
1708 INCREMENT_LINENO;
1709 break;
1710
1711 default:
1712 UNGET ();
1713 return '/';
1714 }
1715 break;
1716
1717 case '+':
1718 if (GET (c) == '+')
1719 return INC;
1720 else if (c == '=')
1721 return ADDASGN;
1722 UNGET ();
1723 return '+';
1724
1725 case '-':
1726 switch (GET (c))
1727 {
1728 case '-':
1729 return DEC;
1730 case '>':
1731 if (GET (c) == '*')
1732 return ARROWSTAR;
1733 UNGET ();
1734 return ARROW;
1735 case '=':
1736 return SUBASGN;
1737 }
1738 UNGET ();
1739 return '-';
1740
1741 case '*':
1742 if (GET (c) == '=')
1743 return MULASGN;
1744 UNGET ();
1745 return '*';
1746
1747 case '%':
1748 if (GET (c) == '=')
1749 return MODASGN;
1750 UNGET ();
1751 return '%';
1752
1753 case '|':
1754 if (GET (c) == '|')
1755 return LOR;
1756 else if (c == '=')
1757 return ORASGN;
1758 UNGET ();
1759 return '|';
1760
1761 case '&':
1762 if (GET (c) == '&')
1763 return LAND;
1764 else if (c == '=')
1765 return ANDASGN;
1766 UNGET ();
1767 return '&';
1768
1769 case '^':
1770 if (GET (c) == '=')
1771 return XORASGN;
1772 UNGET ();
1773 return '^';
1774
1775 case '.':
1776 if (GET (c) == '*')
1777 return POINTSTAR;
1778 else if (c == '.')
1779 {
1780 if (GET (c) != '.')
1781 yyerror ("invalid token '..' ('...' assumed)", NULL);
1782 UNGET ();
1783 return ELLIPSIS;
1784 }
1785 else if (!DIGITP (c))
1786 {
1787 UNGET ();
1788 return '.';
1789 }
1790 goto mantissa;
1791
1792 case ':':
1793 if (GET (c) == ':')
1794 return DCOLON;
1795 UNGET ();
1796 return ':';
1797
1798 case '=':
1799 if (GET (c) == '=')
1800 return EQ;
1801 UNGET ();
1802 return '=';
1803
1804 case '!':
1805 if (GET (c) == '=')
1806 return NE;
1807 UNGET ();
1808 return '!';
1809
1810 case '<':
1811 switch (GET (c))
1812 {
1813 case '=':
1814 return LE;
1815 case '<':
1816 if (GET (c) == '=')
1817 return LSHIFTASGN;
1818 UNGET ();
1819 return LSHIFT;
1820 }
1821 UNGET ();
1822 return '<';
1823
1824 case '>':
1825 switch (GET (c))
1826 {
1827 case '=':
1828 return GE;
1829 case '>':
1830 if (GET (c) == '=')
1831 return RSHIFTASGN;
1832 UNGET ();
1833 return RSHIFT;
1834 }
1835 UNGET ();
1836 return '>';
1837
1838 case '#':
1839 c = process_pp_line ();
1840 if (c == 0)
1841 return YYEOF;
1842 break;
1843
1844 case '(': case ')': case '[': case ']': case '{': case '}':
1845 case ';': case ',': case '?': case '~':
1846 return c;
1847
1848 case '0':
1849 yyival = 0;
1850
1851 if (GET (c) == 'x' || c == 'X')
1852 {
1853 while (GET (c))
1854 {
1855 if (DIGITP (c))
1856 yyival = yyival * 16 + c - '0';
1857 else if (c >= 'a' && c <= 'f')
1858 yyival = yyival * 16 + c - 'a' + 10;
1859 else if (c >= 'A' && c <= 'F')
1860 yyival = yyival * 16 + c - 'A' + 10;
1861 else
1862 break;
1863 }
1864
1865 goto int_suffixes;
1866 }
1867 else if (c == '.')
1868 goto mantissa;
1869
1870 while (c >= '0' && c <= '7')
1871 {
1872 yyival = (yyival << 3) + c - '0';
1873 GET (c);
1874 }
1875
1876 int_suffixes:
1877
1878 while (isalpha (c))
1879 GET (c);
1880 UNGET ();
1881 return CINT;
1882
1883 case '1': case '2': case '3': case '4': case '5': case '6':
1884 case '7': case '8': case '9':
1885
1886 yyival = c - '0';
1887
1888 while (GET (c) && DIGITP (c))
1889 yyival = 10 * yyival + c - '0';
1890
1891 if (c != '.')
1892 goto int_suffixes;
1893
1894 mantissa:
1895
1896 while (DIGITP (c))
1897 GET (c);
1898
1899
1900 if (c == 'E' || c == 'e')
1901 {
1902 if (GET (c) == '-' || c == '+')
1903 GET (c);
1904
1905 while (DIGITP (c))
1906 GET (c);
1907 }
1908
1909
1910 while (isalpha (c))
1911 GET (c);
1912 UNGET ();
1913 return CFLOAT;
1914
1915 default:
1916 break;
1917 }
1918 }
1919 }
1920
1921
1922
1923
1924
1925 static char *matching_regexp_buffer, *matching_regexp_end_buf;
1926
1927
1928
1929
1930
1931
1932 static char *
1933 matching_regexp (void)
1934 {
1935 char *p;
1936 char *s;
1937 char *t;
1938
1939 if (!f_regexps)
1940 return NULL;
1941
1942 if (matching_regexp_buffer == NULL)
1943 {
1944 matching_regexp_buffer = (char *) xmalloc (max_regexp);
1945 matching_regexp_end_buf = &matching_regexp_buffer[max_regexp] - 1;
1946 }
1947
1948
1949 for (p = in - 1; p > inbuffer && *p != '\n'; --p)
1950 ;
1951
1952 if (*p == '\n')
1953 {
1954 while (in - p < min_regexp && p > inbuffer)
1955 {
1956
1957 for (--p; p > inbuffer && *p != '\n'; --p)
1958 ;
1959 }
1960 if (*p == '\n')
1961 ++p;
1962 }
1963
1964
1965
1966
1967 for (s = matching_regexp_end_buf - 1, t = in;
1968 s > matching_regexp_buffer && t > p;)
1969 {
1970 *--s = *--t;
1971
1972 if (*s == '"' || *s == '\\')
1973 {
1974 if (s > matching_regexp_buffer)
1975 *--s = '\\';
1976 else
1977 {
1978 s++;
1979 break;
1980 }
1981 }
1982 }
1983
1984 *(matching_regexp_end_buf - 1) = '\0';
1985 return xstrdup (s);
1986 }
1987
1988
1989
1990
1991 static const char *
1992 token_string (int t)
1993 {
1994 static char b[3];
1995
1996 switch (t)
1997 {
1998 case CSTRING: return "string constant";
1999 case CCHAR: return "char constant";
2000 case CINT: return "int constant";
2001 case CFLOAT: return "floating constant";
2002 case ELLIPSIS: return "...";
2003 case LSHIFTASGN: return "<<=";
2004 case RSHIFTASGN: return ">>=";
2005 case ARROWSTAR: return "->*";
2006 case IDENT: return "identifier";
2007 case DIVASGN: return "/=";
2008 case INC: return "++";
2009 case ADDASGN: return "+=";
2010 case DEC: return "--";
2011 case ARROW: return "->";
2012 case SUBASGN: return "-=";
2013 case MULASGN: return "*=";
2014 case MODASGN: return "%=";
2015 case LOR: return "||";
2016 case ORASGN: return "|=";
2017 case LAND: return "&&";
2018 case ANDASGN: return "&=";
2019 case XORASGN: return "^=";
2020 case POINTSTAR: return ".*";
2021 case DCOLON: return "::";
2022 case EQ: return "==";
2023 case NE: return "!=";
2024 case LE: return "<=";
2025 case LSHIFT: return "<<";
2026 case GE: return ">=";
2027 case RSHIFT: return ">>";
2028 case ASM: return "asm";
2029 case AUTO: return "auto";
2030 case BREAK: return "break";
2031 case CASE: return "case";
2032 case CATCH: return "catch";
2033 case CHAR: return "char";
2034 case CLASS: return "class";
2035 case CONST: return "const";
2036 case CONTINUE: return "continue";
2037 case DEFAULT: return "default";
2038 case DELETE: return "delete";
2039 case DO: return "do";
2040 case DOUBLE: return "double";
2041 case ELSE: return "else";
2042 case ENUM: return "enum";
2043 case EXTERN: return "extern";
2044 case FLOAT: return "float";
2045 case FOR: return "for";
2046 case FRIEND: return "friend";
2047 case GOTO: return "goto";
2048 case IF: return "if";
2049 case T_INLINE: return "inline";
2050 case INT: return "int";
2051 case LONG: return "long";
2052 case NEW: return "new";
2053 case OPERATOR: return "operator";
2054 case PRIVATE: return "private";
2055 case PROTECTED: return "protected";
2056 case PUBLIC: return "public";
2057 case REGISTER: return "register";
2058 case RETURN: return "return";
2059 case SHORT: return "short";
2060 case SIGNED: return "signed";
2061 case SIZEOF: return "sizeof";
2062 case STATIC: return "static";
2063 case STRUCT: return "struct";
2064 case SWITCH: return "switch";
2065 case TEMPLATE: return "template";
2066 case THIS: return "this";
2067 case THROW: return "throw";
2068 case TRY: return "try";
2069 case TYPEDEF: return "typedef";
2070 case UNION: return "union";
2071 case UNSIGNED: return "unsigned";
2072 case VIRTUAL: return "virtual";
2073 case VOID: return "void";
2074 case VOLATILE: return "volatile";
2075 case WHILE: return "while";
2076 case MUTABLE: return "mutable";
2077 case BOOL: return "bool";
2078 case TRUE: return "true";
2079 case FALSE: return "false";
2080 case SIGNATURE: return "signature";
2081 case NAMESPACE: return "namespace";
2082 case EXPLICIT: return "explicit";
2083 case TYPENAME: return "typename";
2084 case CONST_CAST: return "const_cast";
2085 case DYNAMIC_CAST: return "dynamic_cast";
2086 case REINTERPRET_CAST: return "reinterpret_cast";
2087 case STATIC_CAST: return "static_cast";
2088 case TYPEID: return "typeid";
2089 case USING: return "using";
2090 case WCHAR: return "wchar_t";
2091 case YYEOF: return "EOF";
2092 case FINAL: return "final";
2093
2094 default:
2095 if (t < 255)
2096 {
2097 b[0] = t;
2098 b[1] = '\0';
2099 return b;
2100 }
2101 else
2102 return "???";
2103 }
2104 }
2105
2106
2107
2108
2109 static void
2110 re_init_scanner (void)
2111 {
2112 in = inbuffer;
2113 yyline = 1;
2114
2115 if (yytext == NULL)
2116 {
2117 int size = 256;
2118 yytext = (char *) xmalloc (size * sizeof *yytext);
2119 yytext_end = yytext + size;
2120 }
2121 }
2122
2123
2124
2125
2126
2127 static void
2128 insert_keyword (const char *name, int tkv)
2129 {
2130 const char *s;
2131 unsigned h = 0;
2132 struct kw *k = (struct kw *) xmalloc (sizeof *k);
2133
2134 for (s = name; *s; ++s)
2135 h = (h << 1) ^ *s;
2136
2137 h %= KEYWORD_TABLE_SIZE;
2138 k->name = name;
2139 k->tk = tkv;
2140 k->next = keyword_table[h];
2141 keyword_table[h] = k;
2142 }
2143
2144
2145
2146
2147
2148 static void
2149 init_scanner (void)
2150 {
2151 int i;
2152
2153
2154 inbuffer_size = READ_CHUNK_SIZE + 1;
2155 inbuffer = in = (char *) xmalloc (inbuffer_size);
2156 yyline = 1;
2157
2158
2159 for (i = 0; i < sizeof is_ident; ++i)
2160 {
2161 if (i == '_' || isalnum (i))
2162 is_ident[i] = 1;
2163
2164 if (i >= '0' && i <= '9')
2165 is_digit[i] = 1;
2166
2167 if (i == ' ' || i == '\t' || i == '\f' || i == '\v')
2168 is_white[i] = 1;
2169 }
2170
2171
2172 insert_keyword ("and", LAND);
2173 insert_keyword ("and_eq", ANDASGN);
2174 insert_keyword ("asm", ASM);
2175 insert_keyword ("auto", AUTO);
2176 insert_keyword ("bitand", '&');
2177 insert_keyword ("bitor", '|');
2178 insert_keyword ("bool", BOOL);
2179 insert_keyword ("break", BREAK);
2180 insert_keyword ("case", CASE);
2181 insert_keyword ("catch", CATCH);
2182 insert_keyword ("char", CHAR);
2183 insert_keyword ("class", CLASS);
2184 insert_keyword ("compl", '~');
2185 insert_keyword ("const", CONST);
2186 insert_keyword ("const_cast", CONST_CAST);
2187 insert_keyword ("continue", CONTINUE);
2188 insert_keyword ("default", DEFAULT);
2189 insert_keyword ("delete", DELETE);
2190 insert_keyword ("do", DO);
2191 insert_keyword ("double", DOUBLE);
2192 insert_keyword ("dynamic_cast", DYNAMIC_CAST);
2193 insert_keyword ("else", ELSE);
2194 insert_keyword ("enum", ENUM);
2195 insert_keyword ("explicit", EXPLICIT);
2196 insert_keyword ("extern", EXTERN);
2197 insert_keyword ("false", FALSE);
2198 insert_keyword ("final", FINAL);
2199 insert_keyword ("float", FLOAT);
2200 insert_keyword ("for", FOR);
2201 insert_keyword ("friend", FRIEND);
2202 insert_keyword ("goto", GOTO);
2203 insert_keyword ("if", IF);
2204 insert_keyword ("inline", T_INLINE);
2205 insert_keyword ("int", INT);
2206 insert_keyword ("long", LONG);
2207 insert_keyword ("mutable", MUTABLE);
2208 insert_keyword ("namespace", NAMESPACE);
2209 insert_keyword ("new", NEW);
2210 insert_keyword ("not", '!');
2211 insert_keyword ("not_eq", NE);
2212 insert_keyword ("operator", OPERATOR);
2213 insert_keyword ("or", LOR);
2214 insert_keyword ("or_eq", ORASGN);
2215 insert_keyword ("private", PRIVATE);
2216 insert_keyword ("protected", PROTECTED);
2217 insert_keyword ("public", PUBLIC);
2218 insert_keyword ("register", REGISTER);
2219 insert_keyword ("reinterpret_cast", REINTERPRET_CAST);
2220 insert_keyword ("return", RETURN);
2221 insert_keyword ("short", SHORT);
2222 insert_keyword ("signed", SIGNED);
2223 insert_keyword ("sizeof", SIZEOF);
2224 insert_keyword ("static", STATIC);
2225 insert_keyword ("static_cast", STATIC_CAST);
2226 insert_keyword ("struct", STRUCT);
2227 insert_keyword ("switch", SWITCH);
2228 insert_keyword ("template", TEMPLATE);
2229 insert_keyword ("this", THIS);
2230 insert_keyword ("throw", THROW);
2231 insert_keyword ("true", TRUE);
2232 insert_keyword ("try", TRY);
2233 insert_keyword ("typedef", TYPEDEF);
2234 insert_keyword ("typeid", TYPEID);
2235 insert_keyword ("typename", TYPENAME);
2236 insert_keyword ("union", UNION);
2237 insert_keyword ("unsigned", UNSIGNED);
2238 insert_keyword ("using", USING);
2239 insert_keyword ("virtual", VIRTUAL);
2240 insert_keyword ("void", VOID);
2241 insert_keyword ("volatile", VOLATILE);
2242 insert_keyword ("wchar_t", WCHAR);
2243 insert_keyword ("while", WHILE);
2244 insert_keyword ("xor", '^');
2245 insert_keyword ("xor_eq", XORASGN);
2246 }
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256 #define MATCH() (tk = yylex ())
2257
2258
2259
2260
2261 #define LA1 (tk == -1 ? (tk = yylex ()) : tk)
2262
2263
2264
2265 #define LOOKING_AT(T) (tk == (T))
2266
2267
2268
2269 #define LOOKING_AT2(T1, T2) (tk == (T1) || tk == (T2))
2270
2271
2272
2273 #define LOOKING_AT3(T1, T2, T3) (tk == (T1) || tk == (T2) || tk == (T3))
2274
2275
2276
2277 #define LOOKING_AT4(T1, T2, T3, T4) \
2278 (tk == (T1) || tk == (T2) || tk == (T3) || tk == (T4))
2279
2280
2281
2282 #define MATCH_IF(T) if (LOOKING_AT (T)) MATCH (); else ((void) 0)
2283
2284
2285
2286 #define SKIP_MATCHING_IF(T) \
2287 if (LOOKING_AT (T)) skip_matching (); else ((void) 0)
2288
2289
2290
2291
2292
2293 static int
2294 skip_to (int token)
2295 {
2296 while (!LOOKING_AT2 (YYEOF, token))
2297 MATCH ();
2298 return tk;
2299 }
2300
2301
2302
2303
2304 static void
2305 skip_matching (void)
2306 {
2307 int open, close, n;
2308
2309 switch (open = LA1)
2310 {
2311 case '{':
2312 close = '}';
2313 break;
2314
2315 case '(':
2316 close = ')';
2317 break;
2318
2319 case '<':
2320 close = '>';
2321 break;
2322
2323 case '[':
2324 close = ']';
2325 break;
2326
2327 default:
2328 abort ();
2329 }
2330
2331 for (n = 0;;)
2332 {
2333 if (LOOKING_AT (open))
2334 ++n;
2335 else if (LOOKING_AT (close))
2336 --n;
2337 else if (LOOKING_AT (YYEOF))
2338 break;
2339
2340 MATCH ();
2341
2342 if (n == 0)
2343 break;
2344 }
2345 }
2346
2347 static void
2348 skip_initializer (void)
2349 {
2350 for (;;)
2351 {
2352 switch (LA1)
2353 {
2354 case ';':
2355 case ',':
2356 case YYEOF:
2357 return;
2358
2359 case '{':
2360 case '[':
2361 case '(':
2362 skip_matching ();
2363 break;
2364
2365 default:
2366 MATCH ();
2367 break;
2368 }
2369 }
2370 }
2371
2372
2373
2374 static struct link *
2375 match_qualified_namespace_alias (void)
2376 {
2377 struct link *head = NULL;
2378 struct link *cur = NULL;
2379 struct link *tmp = NULL;
2380
2381 for (;;)
2382 {
2383 MATCH ();
2384 switch (LA1)
2385 {
2386 case IDENT:
2387 tmp = (struct link *) xmalloc (sizeof *cur);
2388 tmp->sym = find_namespace (yytext, cur ? cur->sym : NULL);
2389 tmp->next = NULL;
2390 if (head)
2391 {
2392 cur = cur->next = tmp;
2393 }
2394 else
2395 {
2396 head = cur = tmp;
2397 }
2398 break;
2399 case DCOLON:
2400
2401 break;
2402 default:
2403 return head;
2404 break;
2405 }
2406 }
2407 }
2408
2409
2410
2411 static void
2412 re_init_parser (void)
2413 {
2414 tk = -1;
2415 }
2416
2417
2418
2419
2420
2421
2422
2423
2424 static unsigned
2425 parm_list (int *flags)
2426 {
2427 unsigned hash = 0;
2428 int type_seen = 0;
2429
2430 while (!LOOKING_AT2 (YYEOF, ')'))
2431 {
2432 switch (LA1)
2433 {
2434
2435
2436 case '(':
2437 skip_matching ();
2438 break;
2439
2440
2441 case ',':
2442 MATCH ();
2443 type_seen = 0;
2444 break;
2445
2446
2447
2448
2449
2450
2451 case IDENT:
2452 if (!type_seen)
2453 {
2454 char *last_id;
2455 unsigned ident_type_hash = 0;
2456
2457 parse_qualified_param_ident_or_type (&last_id);
2458 if (last_id)
2459 {
2460
2461 for (; *last_id; ++last_id)
2462 ident_type_hash = (ident_type_hash << 1) ^ *last_id;
2463 hash = (hash << 1) ^ ident_type_hash;
2464 type_seen = 1;
2465 }
2466 }
2467 else
2468 MATCH ();
2469 break;
2470
2471 case VOID:
2472
2473
2474 type_seen = 1;
2475 MATCH ();
2476 if (!LOOKING_AT (')'))
2477 hash = (hash << 1) ^ VOID;
2478 break;
2479
2480 case BOOL: case CHAR: case CLASS: case CONST:
2481 case DOUBLE: case ENUM: case FLOAT: case INT:
2482 case LONG: case SHORT: case SIGNED: case STRUCT:
2483 case UNION: case UNSIGNED: case VOLATILE: case WCHAR:
2484 case ELLIPSIS:
2485 type_seen = 1;
2486 hash = (hash << 1) ^ LA1;
2487 MATCH ();
2488 break;
2489
2490 case '*': case '&': case '[': case ']':
2491 hash = (hash << 1) ^ LA1;
2492 MATCH ();
2493 break;
2494
2495 default:
2496 MATCH ();
2497 break;
2498 }
2499 }
2500
2501 if (LOOKING_AT (')'))
2502 {
2503 MATCH ();
2504
2505 if (LOOKING_AT (CONST))
2506 {
2507
2508 hash = (hash << 1) ^ CONST;
2509 set_flag (flags, F_CONST);
2510 MATCH ();
2511 }
2512
2513 if (LOOKING_AT (THROW))
2514 {
2515 MATCH ();
2516 SKIP_MATCHING_IF ('(');
2517 set_flag (flags, F_THROW);
2518 }
2519
2520 if (LOOKING_AT ('='))
2521 {
2522 MATCH ();
2523 if (LOOKING_AT (CINT) && yyival == 0)
2524 {
2525 MATCH ();
2526 set_flag (flags, F_PURE);
2527 }
2528 }
2529 }
2530
2531 return hash;
2532 }
2533
2534
2535
2536
2537 static void
2538 print_info (void)
2539 {
2540 if (info_position >= 0 && BUFFER_POS () <= info_position)
2541 if (info_cls)
2542 printf ("(\"%s\" \"%s\" \"%s\" %d)\n",
2543 info_cls->name, sym_scope (info_cls),
2544 info_member->name, info_where);
2545 }
2546
2547
2548
2549
2550
2551
2552 static void
2553 member (struct sym *cls, int vis)
2554 {
2555 char *id = NULL;
2556 int sc = SC_MEMBER;
2557 char *regexp = NULL;
2558 int pos;
2559 int is_constructor;
2560 int flags = 0;
2561 int class_tag;
2562 char *class_name;
2563 int type_seen = 0;
2564 int paren_seen = 0;
2565 unsigned hash = 0;
2566 int tilde = 0;
2567
2568 while (!LOOKING_AT4 (';', '{', '}', YYEOF))
2569 {
2570 switch (LA1)
2571 {
2572 default:
2573 MATCH ();
2574 break;
2575
2576
2577 case TEMPLATE:
2578 MATCH ();
2579 set_flag (&flags, F_TEMPLATE);
2580
2581 SKIP_MATCHING_IF ('<');
2582 break;
2583
2584 case EXPLICIT:
2585 set_flag (&flags, F_EXPLICIT);
2586 goto typeseen;
2587
2588 case MUTABLE:
2589 set_flag (&flags, F_MUTABLE);
2590 goto typeseen;
2591
2592 case T_INLINE:
2593 set_flag (&flags, F_INLINE);
2594 goto typeseen;
2595
2596 case VIRTUAL:
2597 set_flag (&flags, F_VIRTUAL);
2598 goto typeseen;
2599
2600 case '[':
2601 skip_matching ();
2602 break;
2603
2604 case ENUM:
2605 sc = SC_TYPE;
2606 goto typeseen;
2607
2608 case TYPEDEF:
2609 sc = SC_TYPE;
2610 goto typeseen;
2611
2612 case FRIEND:
2613 sc = SC_FRIEND;
2614 goto typeseen;
2615
2616 case STATIC:
2617 sc = SC_STATIC;
2618 goto typeseen;
2619
2620 case '~':
2621 tilde = 1;
2622 MATCH ();
2623 break;
2624
2625 case IDENT:
2626
2627
2628 id = (char *) xrealloc (id, strlen (yytext) + 2);
2629 if (tilde)
2630 {
2631 *id = '~';
2632 strcpy (id + 1, yytext);
2633 }
2634 else
2635 strcpy (id, yytext);
2636 MATCH ();
2637 break;
2638
2639 case OPERATOR:
2640 {
2641 char *s = operator_name (&sc);
2642 id = (char *) xrealloc (id, strlen (s) + 1);
2643 strcpy (id, s);
2644 }
2645 break;
2646
2647 case '(':
2648
2649 MATCH ();
2650 paren_seen = 1;
2651
2652 if (id && cls)
2653 {
2654 if (!(is_constructor = streq (id, cls->name)))
2655 regexp = matching_regexp ();
2656 }
2657 else
2658 is_constructor = 0;
2659
2660 pos = BUFFER_POS ();
2661 hash = parm_list (&flags);
2662
2663 if (is_constructor)
2664 regexp = matching_regexp ();
2665
2666 if (id && cls != NULL)
2667 add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, flags);
2668
2669 while (!LOOKING_AT3 (';', '{', YYEOF))
2670 MATCH ();
2671
2672 if (LOOKING_AT ('{') && id && cls)
2673 add_member_defn (cls, id, regexp, pos, hash, 0, sc, flags);
2674
2675 free (id);
2676 id = NULL;
2677 sc = SC_MEMBER;
2678 break;
2679
2680 case STRUCT: case UNION: case CLASS:
2681
2682 class_tag = LA1;
2683 type_seen = 1;
2684 MATCH ();
2685 class_name = NULL;
2686
2687
2688
2689
2690 while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
2691 {
2692 if (LOOKING_AT (IDENT))
2693 {
2694 if (class_name)
2695 {
2696 int size = strlen (yytext);
2697
2698 if(strlen (class_name) < size)
2699 {
2700 class_name = (char *) xrealloc(class_name, size + 1);
2701 }
2702
2703 memcpy(class_name, yytext, size + 1);
2704 }
2705 else
2706 {
2707 class_name = xstrdup(yytext);
2708 }
2709 }
2710
2711 MATCH ();
2712 }
2713
2714 if (LOOKING_AT2 (':', '{'))
2715 class_definition (class_name ? cls : NULL, class_name ? class_name : yytext, class_tag, flags, 1);
2716 else
2717 skip_to (';');
2718
2719 free(class_name);
2720 break;
2721
2722 case INT: case CHAR: case LONG: case UNSIGNED:
2723 case SIGNED: case CONST: case DOUBLE: case VOID:
2724 case SHORT: case VOLATILE: case BOOL: case WCHAR:
2725 case TYPENAME:
2726 typeseen:
2727 type_seen = 1;
2728 MATCH ();
2729 break;
2730 }
2731 }
2732
2733 if (LOOKING_AT (';'))
2734 {
2735
2736
2737 if (id && sc != SC_FRIEND && cls)
2738 {
2739 regexp = matching_regexp ();
2740 pos = BUFFER_POS ();
2741
2742 if (cls != NULL)
2743 {
2744 if (type_seen || !paren_seen)
2745 add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
2746 else
2747 add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, 0);
2748 }
2749 }
2750
2751 MATCH ();
2752 print_info ();
2753 }
2754 else if (LOOKING_AT ('{'))
2755 {
2756
2757 if (sc == SC_TYPE && id && cls)
2758 {
2759 regexp = matching_regexp ();
2760 pos = BUFFER_POS ();
2761
2762 if (cls != NULL)
2763 {
2764 add_member_decl (cls, id, regexp, pos, 0, 1, sc, vis, 0);
2765 add_member_defn (cls, id, regexp, pos, 0, 1, sc, 0);
2766 }
2767 }
2768
2769 skip_matching ();
2770 print_info ();
2771 }
2772
2773 free (id);
2774 }
2775
2776
2777
2778
2779
2780 static void
2781 class_body (struct sym *cls, int tag)
2782 {
2783 int vis = tag == CLASS ? PRIVATE : PUBLIC;
2784 int temp;
2785
2786 while (!LOOKING_AT2 (YYEOF, '}'))
2787 {
2788 switch (LA1)
2789 {
2790 case PRIVATE: case PROTECTED: case PUBLIC:
2791 temp = LA1;
2792 MATCH ();
2793
2794 if (LOOKING_AT (':'))
2795 {
2796 vis = temp;
2797 MATCH ();
2798 }
2799 else
2800 {
2801
2802
2803
2804 do
2805 {
2806 MATCH ();
2807 }
2808 while (LOOKING_AT2 (IDENT, ',')
2809 || LOOKING_AT3 (PUBLIC, PROTECTED, PRIVATE));
2810 }
2811 break;
2812
2813 case TYPENAME:
2814 case USING:
2815 skip_to (';');
2816 break;
2817
2818
2819 case CHAR: case CLASS: case CONST:
2820 case DOUBLE: case ENUM: case FLOAT: case INT:
2821 case LONG: case SHORT: case SIGNED: case STRUCT:
2822 case UNION: case UNSIGNED: case VOID: case VOLATILE:
2823 case TYPEDEF: case STATIC: case T_INLINE: case FRIEND:
2824 case VIRTUAL: case TEMPLATE: case IDENT: case '~':
2825 case BOOL: case WCHAR: case EXPLICIT: case MUTABLE:
2826 member (cls, vis);
2827 break;
2828
2829 default:
2830 MATCH ();
2831 break;
2832 }
2833 }
2834 }
2835
2836
2837
2838
2839
2840
2841 static struct sym *
2842 parse_classname (void)
2843 {
2844 struct sym *last_class = NULL;
2845
2846 while (LOOKING_AT (IDENT))
2847 {
2848 last_class = add_sym (yytext, last_class);
2849 MATCH ();
2850
2851 if (LOOKING_AT ('<'))
2852 {
2853 skip_matching ();
2854 set_flag (&last_class->flags, F_TEMPLATE);
2855 }
2856
2857 if (!LOOKING_AT (DCOLON))
2858 break;
2859
2860 MATCH ();
2861 }
2862
2863 return last_class;
2864 }
2865
2866
2867
2868
2869
2870
2871 static char *
2872 operator_name (int *sc)
2873 {
2874 static size_t id_size = 0;
2875 static char *id = NULL;
2876 const char *s;
2877 size_t len;
2878
2879 MATCH ();
2880
2881 if (LOOKING_AT2 (NEW, DELETE))
2882 {
2883
2884 if (*sc != SC_FRIEND)
2885 *sc = SC_STATIC;
2886
2887 s = token_string (LA1);
2888 MATCH ();
2889
2890 ptrdiff_t slen = strlen (s);
2891 len = slen + 10;
2892 if (len > id_size)
2893 {
2894 size_t new_size = max (len, 2 * id_size);
2895 id = (char *) xrealloc (id, new_size);
2896 id_size = new_size;
2897 }
2898 char *z = stpcpy (id, s);
2899
2900
2901 if (LOOKING_AT ('['))
2902 {
2903 z = stpcpy (z, "[");
2904 MATCH ();
2905
2906 if (LOOKING_AT (']'))
2907 {
2908 strcpy (z, "]");
2909 MATCH ();
2910 }
2911 }
2912 }
2913 else
2914 {
2915 size_t tokens_matched = 0;
2916
2917 len = 20;
2918 if (len > id_size)
2919 {
2920 int new_size = max (len, 2 * id_size);
2921 id = (char *) xrealloc (id, new_size);
2922 id_size = new_size;
2923 }
2924 char *z = stpcpy (id, "operator");
2925
2926
2927
2928
2929 while (!(LOOKING_AT ('(') && tokens_matched)
2930 && !LOOKING_AT2 (';', YYEOF))
2931 {
2932 s = token_string (LA1);
2933 len += strlen (s) + 2;
2934 if (len > id_size)
2935 {
2936 ptrdiff_t idlen = z - id;
2937 size_t new_size = max (len, 2 * id_size);
2938 id = (char *) xrealloc (id, new_size);
2939 id_size = new_size;
2940 z = id + idlen;
2941 }
2942
2943 if (*s != ')' && *s != ']')
2944 *z++ = ' ';
2945 z = stpcpy (z, s);
2946 MATCH ();
2947
2948
2949 if (!isalpha ((unsigned char) *s) && *s != '(' && *s != '[')
2950 break;
2951
2952 ++tokens_matched;
2953 }
2954 }
2955
2956 return id;
2957 }
2958
2959
2960
2961
2962
2963
2964 static struct sym *
2965 parse_qualified_ident_or_type (char **last_id)
2966 {
2967 struct sym *cls = NULL;
2968 char *id = NULL;
2969 size_t id_size = 0;
2970 int enter = 0;
2971
2972 while (LOOKING_AT (IDENT))
2973 {
2974 int len = strlen (yytext) + 1;
2975 if (len > id_size)
2976 {
2977 id = (char *) xrealloc (id, len);
2978 id_size = len;
2979 }
2980 strcpy (id, yytext);
2981 *last_id = id;
2982 MATCH ();
2983
2984 SKIP_MATCHING_IF ('<');
2985
2986 if (LOOKING_AT (DCOLON))
2987 {
2988 struct sym *pcn = NULL;
2989 struct link *pna = check_namespace_alias (id);
2990 if (pna)
2991 {
2992 do
2993 {
2994 enter_namespace (pna->sym->name);
2995 enter++;
2996 pna = pna->next;
2997 }
2998 while (pna);
2999 }
3000 else if ((pcn = check_namespace (id, current_namespace)))
3001 {
3002 enter_namespace (pcn->name);
3003 enter++;
3004 }
3005 else
3006 cls = add_sym (id, cls);
3007
3008 *last_id = NULL;
3009 free (id);
3010 id = NULL;
3011 id_size = 0;
3012 MATCH ();
3013 }
3014 else
3015 break;
3016 }
3017
3018 while (enter--)
3019 leave_namespace ();
3020
3021 return cls;
3022 }
3023
3024
3025
3026
3027
3028
3029 static void
3030 parse_qualified_param_ident_or_type (char **last_id)
3031 {
3032 struct sym *cls = NULL;
3033 static char *id = NULL;
3034 static int id_size = 0;
3035
3036 assert (LOOKING_AT (IDENT));
3037
3038 do
3039 {
3040 int len = strlen (yytext) + 1;
3041 if (len > id_size)
3042 {
3043 id = (char *) xrealloc (id, len);
3044 id_size = len;
3045 }
3046 strcpy (id, yytext);
3047 *last_id = id;
3048 MATCH ();
3049
3050 SKIP_MATCHING_IF ('<');
3051
3052 if (LOOKING_AT (DCOLON))
3053 {
3054 cls = add_sym (id, cls);
3055 *last_id = NULL;
3056 MATCH ();
3057 }
3058 else
3059 break;
3060 }
3061 while (LOOKING_AT (IDENT));
3062 }
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074 static void
3075 class_definition (struct sym *containing, const char *class_name, int tag, int flags, int nested)
3076 {
3077 struct sym *current;
3078 struct sym *base_class;
3079
3080
3081
3082
3083 if ((tag != CLASS && !f_structs) || (nested && !f_nested_classes))
3084 current = NULL;
3085 else
3086 {
3087 current = add_sym (class_name, containing);
3088 current->pos = BUFFER_POS ();
3089 current->regexp = matching_regexp ();
3090 current->filename = filename;
3091 current->flags = flags;
3092 }
3093
3094
3095 if (LOOKING_AT (':'))
3096 {
3097 int done = 0;
3098 MATCH ();
3099
3100 while (!done)
3101 {
3102 switch (LA1)
3103 {
3104 case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE:
3105 MATCH ();
3106 break;
3107
3108 case IDENT:
3109 base_class = parse_classname ();
3110 if (base_class && current && base_class != current)
3111 add_link (base_class, current);
3112 break;
3113
3114
3115
3116
3117
3118
3119
3120
3121 case ',':
3122 MATCH ();
3123 break;
3124
3125 default:
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135 while (!LOOKING_AT3 (';', YYEOF, '{'))
3136 MATCH ();
3137 FALLTHROUGH;
3138 case '{':
3139 done = 1;
3140 break;
3141 }
3142 }
3143 }
3144
3145
3146 if (LOOKING_AT ('{'))
3147 {
3148 if (tag != CLASS && !f_structs)
3149 skip_matching ();
3150 else
3151 {
3152 MATCH ();
3153 class_body (current, tag);
3154
3155 if (LOOKING_AT ('}'))
3156 {
3157 MATCH ();
3158 if (LOOKING_AT (';') && !nested)
3159 MATCH ();
3160 }
3161 }
3162 }
3163 }
3164
3165
3166
3167
3168
3169
3170 static void
3171 add_declarator (struct sym **cls, char **id, int flags, int sc)
3172 {
3173 if (LOOKING_AT2 (';', ','))
3174 {
3175
3176
3177
3178 if (*id)
3179 {
3180 char *regexp = matching_regexp ();
3181 int pos = BUFFER_POS ();
3182
3183 if (*cls)
3184 add_member_defn (*cls, *id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
3185 else
3186 add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
3187 }
3188
3189 MATCH ();
3190 print_info ();
3191 }
3192 else if (LOOKING_AT ('{'))
3193 {
3194 if (sc == SC_TYPE && *id)
3195 {
3196
3197 char *regexp = matching_regexp ();
3198 int pos = BUFFER_POS ();
3199 add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
3200 }
3201
3202 skip_matching ();
3203 print_info ();
3204 }
3205
3206 free (*id);
3207 *id = NULL;
3208 *cls = NULL;
3209 }
3210
3211
3212
3213 static void
3214 declaration (int flags)
3215 {
3216 char *id = NULL;
3217 struct sym *cls = NULL;
3218 char *regexp = NULL;
3219 int pos = 0;
3220 unsigned hash = 0;
3221 int is_constructor;
3222 int sc = 0;
3223
3224 while (!LOOKING_AT3 (';', '{', YYEOF))
3225 {
3226 switch (LA1)
3227 {
3228 default:
3229 MATCH ();
3230 break;
3231
3232 case '[':
3233 skip_matching ();
3234 break;
3235
3236 case ENUM:
3237 case TYPEDEF:
3238 sc = SC_TYPE;
3239 MATCH ();
3240 break;
3241
3242 case STATIC:
3243 sc = SC_STATIC;
3244 MATCH ();
3245 break;
3246
3247 case INT: case CHAR: case LONG: case UNSIGNED:
3248 case SIGNED: case CONST: case DOUBLE: case VOID:
3249 case SHORT: case VOLATILE: case BOOL: case WCHAR:
3250 MATCH ();
3251 break;
3252
3253 case CLASS: case STRUCT: case UNION:
3254
3255
3256 if (id)
3257 {
3258 free (id);
3259 return;
3260 }
3261 FALLTHROUGH;
3262 case '=':
3263
3264
3265 skip_initializer ();
3266 break;
3267
3268 case ',':
3269 add_declarator (&cls, &id, flags, sc);
3270 break;
3271
3272 case OPERATOR:
3273 {
3274 char *s = operator_name (&sc);
3275 id = (char *) xrealloc (id, strlen (s) + 1);
3276 strcpy (id, s);
3277 }
3278 break;
3279
3280 case T_INLINE:
3281 set_flag (&flags, F_INLINE);
3282 MATCH ();
3283 break;
3284
3285 case '~':
3286 MATCH ();
3287 if (LOOKING_AT (IDENT))
3288 {
3289 id = (char *) xrealloc (id, strlen (yytext) + 2);
3290 *id = '~';
3291 strcpy (id + 1, yytext);
3292 MATCH ();
3293 }
3294 break;
3295
3296 case IDENT:
3297 cls = parse_qualified_ident_or_type (&id);
3298 break;
3299
3300 case '(':
3301
3302 if (cls)
3303 {
3304 MATCH ();
3305
3306 if (id && cls)
3307 {
3308 if (!(is_constructor = streq (id, cls->name)))
3309 regexp = matching_regexp ();
3310 }
3311 else
3312 is_constructor = 0;
3313
3314 pos = BUFFER_POS ();
3315 hash = parm_list (&flags);
3316
3317 if (is_constructor)
3318 regexp = matching_regexp ();
3319
3320 if (id && cls)
3321 add_member_defn (cls, id, regexp, pos, hash, 0,
3322 SC_UNKNOWN, flags);
3323 }
3324 else
3325 {
3326
3327
3328
3329 MATCH ();
3330
3331 if (id)
3332 {
3333 regexp = matching_regexp ();
3334 pos = BUFFER_POS ();
3335 hash = parm_list (&flags);
3336 add_global_decl (id, regexp, pos, hash, 0, sc, flags);
3337 }
3338
3339
3340
3341
3342 if (LOOKING_AT3 (CLASS, STRUCT, UNION))
3343 return;
3344 }
3345
3346 while (!LOOKING_AT3 (';', '{', YYEOF))
3347 MATCH ();
3348
3349 if (!cls && id && LOOKING_AT ('{'))
3350 add_global_defn (id, regexp, pos, hash, 0, sc, flags);
3351
3352 free (id);
3353 id = NULL;
3354 break;
3355 }
3356 }
3357
3358 add_declarator (&cls, &id, flags, sc);
3359 }
3360
3361
3362
3363
3364
3365
3366
3367 static int
3368 globals (int start_flags)
3369 {
3370 int class_tk;
3371 char *class_name;
3372 int flags = start_flags;
3373
3374 for (;;)
3375 {
3376 char *prev_in = in;
3377
3378 switch (LA1)
3379 {
3380 case NAMESPACE:
3381 {
3382 MATCH ();
3383
3384 if (LOOKING_AT (IDENT))
3385 {
3386 char *namespace_name = xstrdup (yytext);
3387 MATCH ();
3388
3389 if (LOOKING_AT ('='))
3390 {
3391 struct link *qna = match_qualified_namespace_alias ();
3392 if (qna)
3393 register_namespace_alias (namespace_name, qna);
3394
3395 if (skip_to (';') == ';')
3396 MATCH ();
3397 }
3398 else if (LOOKING_AT ('{'))
3399 {
3400 MATCH ();
3401 enter_namespace (namespace_name);
3402 globals (0);
3403 leave_namespace ();
3404 MATCH_IF ('}');
3405 }
3406
3407 free (namespace_name);
3408 }
3409 }
3410 break;
3411
3412 case EXTERN:
3413 MATCH ();
3414 if (LOOKING_AT (CSTRING) && *string_start == 'C'
3415 && *(string_start + 1) == '"')
3416 {
3417
3418 MATCH ();
3419
3420 if (LOOKING_AT ('{'))
3421 {
3422 MATCH ();
3423 globals (F_EXTERNC);
3424 MATCH_IF ('}');
3425 }
3426 else
3427 set_flag (&flags, F_EXTERNC);
3428 }
3429 break;
3430
3431 case TEMPLATE:
3432 MATCH ();
3433 SKIP_MATCHING_IF ('<');
3434 set_flag (&flags, F_TEMPLATE);
3435 break;
3436
3437 case CLASS: case STRUCT: case UNION:
3438 class_tk = LA1;
3439 MATCH ();
3440 class_name = NULL;
3441
3442
3443
3444
3445
3446 while (!LOOKING_AT4 (YYEOF, ';', ':', '{'))
3447 {
3448 if (LOOKING_AT (IDENT))
3449 {
3450 if (class_name)
3451 {
3452 int size = strlen (yytext);
3453
3454 if(strlen (class_name) < size)
3455 {
3456 class_name = (char *) xrealloc(class_name, size + 1);
3457 }
3458
3459 memcpy(class_name, yytext, size + 1);
3460 }
3461 else
3462 {
3463 class_name = xstrdup(yytext);
3464 }
3465 }
3466
3467 MATCH ();
3468 }
3469
3470
3471 if (LOOKING_AT2 (':', '{') && class_name)
3472 class_definition (NULL, class_name, class_tk, flags, 0);
3473 else
3474 {
3475 if (skip_to (';') == ';')
3476 MATCH ();
3477 }
3478
3479 free(class_name);
3480 flags = start_flags;
3481 break;
3482
3483 case YYEOF:
3484 return 1;
3485
3486 case '}':
3487 return 0;
3488
3489 default:
3490 declaration (flags);
3491 flags = start_flags;
3492 break;
3493 }
3494
3495 if (prev_in == in)
3496 yyerror ("parse error", NULL);
3497 }
3498 }
3499
3500
3501
3502
3503 static void
3504 yyparse (void)
3505 {
3506 while (globals (0) == 0)
3507 MATCH_IF ('}');
3508 }
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519 static void
3520 add_search_path (char *path_list)
3521 {
3522 while (*path_list)
3523 {
3524 char *start = path_list;
3525 struct search_path *p;
3526
3527 while (*path_list && *path_list != SEPCHAR)
3528 ++path_list;
3529
3530 p = (struct search_path *) xmalloc (sizeof *p);
3531 p->path = (char *) xmalloc (path_list - start + 1);
3532 memcpy (p->path, start, path_list - start);
3533 p->path[path_list - start] = '\0';
3534 p->next = NULL;
3535
3536 if (search_path_tail)
3537 {
3538 search_path_tail->next = p;
3539 search_path_tail = p;
3540 }
3541 else
3542 search_path = search_path_tail = p;
3543
3544 while (*path_list == SEPCHAR)
3545 ++path_list;
3546 }
3547 }
3548
3549
3550
3551
3552
3553
3554 static FILE *
3555 open_file (char *file)
3556 {
3557 FILE *fp = NULL;
3558 static char *buffer;
3559 static int buffer_size;
3560 struct search_path *path;
3561 int flen = strlen (file) + 1;
3562
3563 filename = xstrdup (file);
3564
3565 for (path = search_path; path && fp == NULL; path = path->next)
3566 {
3567 int len = strlen (path->path) + flen;
3568
3569 if (len + 1 >= buffer_size)
3570 {
3571 buffer_size = max (len + 1, 2 * buffer_size);
3572 buffer = (char *) xrealloc (buffer, buffer_size);
3573 }
3574
3575 char *z = stpcpy (buffer, path->path);
3576 *z++ = '/';
3577 strcpy (z, file);
3578 fp = fopen (buffer, "r");
3579 }
3580
3581
3582 if (fp == NULL)
3583 fp = fopen (file, "r");
3584
3585 if (fp == NULL)
3586 yyerror ("cannot open", NULL);
3587
3588 return fp;
3589 }
3590
3591
3592
3593
3594 static char const *const usage_message[] =
3595 {
3596 "\
3597 Usage: ebrowse [options] {files}\n\
3598 \n\
3599 -a, --append append output to existing file\n\
3600 -f, --files=FILES read input file names from FILE\n\
3601 -I, --search-path=LIST set search path for input files\n\
3602 -m, --min-regexp-length=N set minimum regexp length to N\n\
3603 -M, --max-regexp-length=N set maximum regexp length to N\n\
3604 ",
3605 "\
3606 -n, --no-nested-classes exclude nested classes\n\
3607 -o, --output-file=FILE set output file name to FILE\n\
3608 -p, --position-info print info about position in file\n\
3609 -s, --no-structs-or-unions don't record structs or unions\n\
3610 -v, --verbose be verbose\n\
3611 -V, --very-verbose be very verbose\n\
3612 -x, --no-regexps don't record regular expressions\n\
3613 --help display this help\n\
3614 --version display version info\n\
3615 \n\
3616 "
3617 };
3618
3619 static _Noreturn void
3620 usage (int error)
3621 {
3622 int i;
3623 for (i = 0; i < sizeof usage_message / sizeof *usage_message; i++)
3624 fputs (usage_message[i], stdout);
3625 exit (error ? EXIT_FAILURE : EXIT_SUCCESS);
3626 }
3627
3628
3629
3630
3631 static _Noreturn void
3632 version (void)
3633 {
3634 fputs (("ebrowse " PACKAGE_VERSION "\n"
3635 COPYRIGHT "\n"
3636 "This program is distributed under the same terms as Emacs.\n"),
3637 stdout);
3638 exit (EXIT_SUCCESS);
3639 }
3640
3641
3642
3643
3644
3645 static void
3646 process_file (char *file)
3647 {
3648 FILE *fp;
3649
3650 fp = open_file (file);
3651 if (fp)
3652 {
3653 size_t nread, nbytes;
3654
3655
3656 if (f_very_verbose)
3657 {
3658 puts (filename);
3659 fflush (stdout);
3660 }
3661 else if (f_verbose)
3662 {
3663 putchar ('.');
3664 fflush (stdout);
3665 }
3666
3667
3668 for (nread = 0;;)
3669 {
3670 if (nread + READ_CHUNK_SIZE >= inbuffer_size)
3671 {
3672 inbuffer_size = nread + READ_CHUNK_SIZE + 1;
3673 inbuffer = (char *) xrealloc (inbuffer, inbuffer_size);
3674 }
3675
3676 nbytes = fread (inbuffer + nread, 1, READ_CHUNK_SIZE, fp);
3677 if (nbytes == 0)
3678 break;
3679 nread += nbytes;
3680 }
3681 inbuffer[nread] = '\0';
3682
3683
3684 re_init_scanner ();
3685 re_init_parser ();
3686
3687
3688 yyparse ();
3689 fclose (fp);
3690 }
3691 }
3692
3693
3694
3695
3696
3697
3698 static char *
3699 read_line (FILE *fp)
3700 {
3701 static char *buffer;
3702 static int buffer_size;
3703 int i = 0, c;
3704
3705 while ((c = getc (fp)) != EOF && c != '\n')
3706 {
3707 if (i >= buffer_size)
3708 {
3709 buffer_size = max (100, buffer_size * 2);
3710 buffer = (char *) xrealloc (buffer, buffer_size);
3711 }
3712
3713 buffer[i++] = c;
3714 }
3715
3716 if (c == EOF && i == 0)
3717 return NULL;
3718
3719 if (i == buffer_size)
3720 {
3721 buffer_size = max (100, buffer_size * 2);
3722 buffer = (char *) xrealloc (buffer, buffer_size);
3723 }
3724
3725 buffer[i] = '\0';
3726 if (i > 0 && buffer[i - 1] == '\r')
3727 buffer[i - 1] = '\0';
3728 return buffer;
3729 }
3730
3731
3732
3733
3734 int
3735 main (int argc, char **argv)
3736 {
3737 int i;
3738 int any_inputfiles = 0;
3739 static const char *out_filename = DEFAULT_OUTFILE;
3740 static char **input_filenames = NULL;
3741 static int input_filenames_size = 0;
3742 static int n_input_files;
3743
3744 filename = "command line";
3745 yyout = stdout;
3746
3747 while ((i = getopt_long (argc, argv, "af:I:m:M:no:p:svVx",
3748 options, NULL)) != EOF)
3749 {
3750 switch (i)
3751 {
3752
3753 case 'p':
3754 info_position = atoi (optarg);
3755 break;
3756
3757 case 'n':
3758 f_nested_classes = 0;
3759 break;
3760
3761 case 'x':
3762 f_regexps = 0;
3763 break;
3764
3765
3766 case 'f':
3767 if (n_input_files == input_filenames_size)
3768 {
3769 input_filenames_size = max (10, 2 * input_filenames_size);
3770 input_filenames = xrealloc (input_filenames,
3771 (input_filenames_size
3772 * sizeof *input_filenames));
3773 }
3774 input_filenames[n_input_files++] = xstrdup (optarg);
3775 break;
3776
3777
3778 case 'a':
3779 f_append = 1;
3780 break;
3781
3782
3783 case 's':
3784 f_structs = 0;
3785 break;
3786
3787
3788 case 'v':
3789 f_verbose = 1;
3790 break;
3791
3792
3793 case 'V':
3794 f_verbose = 1;
3795 f_very_verbose = 1;
3796 break;
3797
3798
3799 case 'o':
3800 out_filename = optarg;
3801 break;
3802
3803
3804
3805 case 'm':
3806 min_regexp = atoi (optarg);
3807 break;
3808
3809
3810
3811 case 'M':
3812 max_regexp = atoi (optarg);
3813 break;
3814
3815
3816 case 'I':
3817 add_search_path (optarg);
3818 break;
3819
3820
3821 case -2:
3822 usage (0);
3823 break;
3824
3825 case -3:
3826 version ();
3827 break;
3828 }
3829 }
3830
3831
3832
3833
3834 init_scanner ();
3835 init_sym ();
3836
3837
3838 if (*out_filename)
3839 {
3840 if (f_append)
3841 {
3842
3843
3844
3845
3846 FILE *fp;
3847 int rc;
3848
3849 fp = fopen (out_filename, "r");
3850 if (fp == NULL)
3851 {
3852 yyerror ("file '%s' must exist for --append", out_filename);
3853 exit (EXIT_FAILURE);
3854 }
3855
3856 rc = fseek (fp, 0, SEEK_END);
3857 if (rc == -1)
3858 {
3859 yyerror ("error seeking in file '%s'", out_filename);
3860 exit (EXIT_FAILURE);
3861 }
3862
3863 rc = ftell (fp);
3864 if (rc == -1)
3865 {
3866 yyerror ("error getting size of file '%s'", out_filename);
3867 exit (EXIT_FAILURE);
3868 }
3869
3870 else if (rc == 0)
3871 {
3872 yyerror ("file '%s' is empty", out_filename);
3873
3874
3875 }
3876
3877 fclose (fp);
3878 }
3879
3880 yyout = fopen (out_filename, f_append ? "a" : "w");
3881 if (yyout == NULL)
3882 {
3883 yyerror ("cannot open output file '%s'", out_filename);
3884 exit (EXIT_FAILURE);
3885 }
3886 }
3887
3888
3889 while (optind < argc)
3890 {
3891 process_file (argv[optind++]);
3892 any_inputfiles = 1;
3893 }
3894
3895
3896 if (!any_inputfiles && n_input_files == 0)
3897 {
3898 char *file;
3899 while ((file = read_line (stdin)) != NULL)
3900 process_file (file);
3901 }
3902 else
3903 {
3904
3905
3906 for (i = 0; i < n_input_files; ++i)
3907 {
3908 FILE *fp = fopen (input_filenames[i], "r");
3909
3910 if (fp == NULL)
3911 yyerror ("cannot open input file '%s'", input_filenames[i]);
3912 else
3913 {
3914 char *file;
3915 while ((file = read_line (fp)) != NULL)
3916 process_file (file);
3917 fclose (fp);
3918 }
3919 }
3920 }
3921
3922
3923 dump_roots (yyout);
3924
3925
3926 if (yyout != stdout)
3927 fclose (yyout);
3928
3929 return EXIT_SUCCESS;
3930 }
3931
3932