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