diff options
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/etags.c | 887 |
1 files changed, 422 insertions, 465 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c index 5fe855bcd6d..95e23589393 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Tags file maker to go with GNU Emacs | 1 | /* Tags file maker to go with GNU Emacs |
| 2 | Copyright (C) 1984, 1987, 1988, 1989, 1992 Free Software Foundation, Inc. and Ken Arnold | 2 | Copyright (C) 1984, 1987, 1988, 1989, 1993 Free Software Foundation, Inc. and Ken Arnold |
| 3 | 3 | ||
| 4 | This file is part of GNU Emacs. | 4 | This file is part of GNU Emacs. |
| 5 | 5 | ||
| @@ -86,8 +86,6 @@ char *savenstr (); | |||
| 86 | * | 86 | * |
| 87 | * long GET_CHARNO (pos) | 87 | * long GET_CHARNO (pos) |
| 88 | * returns absolute char number. | 88 | * returns absolute char number. |
| 89 | * long GET_COOKIE (pos) | ||
| 90 | * returns ftell () cookie. | ||
| 91 | * void SET_FILEPOS (pos, fp, charno) | 89 | * void SET_FILEPOS (pos, fp, charno) |
| 92 | * FILE *fp; long charno; | 90 | * FILE *fp; long charno; |
| 93 | * sets `pos' from the current file | 91 | * sets `pos' from the current file |
| @@ -105,44 +103,29 @@ char *savenstr (); | |||
| 105 | * | 103 | * |
| 106 | * Implementation notes: the `+ 0' is to enforce rvalue-ness. | 104 | * Implementation notes: the `+ 0' is to enforce rvalue-ness. |
| 107 | */ | 105 | */ |
| 108 | #ifdef VMS | ||
| 109 | typedef struct | ||
| 110 | { | ||
| 111 | long cookie; | ||
| 112 | long charno; | ||
| 113 | } FILEPOS; | ||
| 114 | 106 | ||
| 115 | #define GET_CHARNO(pos) ((pos).charno + 0) | ||
| 116 | #define GET_COOKIE(pos) ((pos).cookie + 0) | ||
| 117 | #define SET_FILEPOS(pos, fp, cno) \ | ||
| 118 | ((void) ((pos).cookie = ftell (fp), (pos).charno = (cno))) | ||
| 119 | #else | ||
| 120 | #ifndef DEBUG | 107 | #ifndef DEBUG |
| 121 | /* UNIX real implementation */ | 108 | /* real implementation */ |
| 122 | typedef long FILEPOS; | 109 | typedef long FILEPOS; |
| 123 | #define GET_CHARNO(pos) ((pos) + 0) | 110 | #define GET_CHARNO(pos) ((pos) + 0) |
| 124 | #define GET_COOKIE(pos) GET_CHARNO (pos) | ||
| 125 | #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno))) | 111 | #define SET_FILEPOS(pos, fp, cno) ((void) ((pos) = (cno))) |
| 126 | #else | 112 | #else |
| 127 | /* UNIX debugging implementation */ | 113 | /* debugging implementation */ |
| 128 | typedef struct | 114 | typedef struct |
| 129 | { | 115 | { |
| 130 | long charno; | 116 | long charno; |
| 131 | } FILEPOS; | 117 | } FILEPOS; |
| 132 | 118 | ||
| 133 | #define GET_CHARNO(pos) ((pos).charno + 0) | 119 | #define GET_CHARNO(pos) ((pos).charno + 0) |
| 134 | #define GET_COOKIE(pos) GET_CHARNO (pos) | ||
| 135 | #define SET_FILEPOS(pos, fp, cno) \ | 120 | #define SET_FILEPOS(pos, fp, cno) \ |
| 136 | ((void) ((pos).charno = (cno), \ | 121 | ((void) ((pos).charno = (cno), \ |
| 137 | (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \ | 122 | (cno) != ftell (fp) ? (error ("SET_FILEPOS inconsistency"), 0) \ |
| 138 | : 0)) | 123 | : 0)) |
| 139 | #endif | 124 | #endif |
| 140 | #endif | ||
| 141 | 125 | ||
| 142 | #define streq(s, t) (strcmp (s, t) == 0) | 126 | #define streq(s, t) (strcmp (s, t) == 0) |
| 143 | #define strneq(s, t, n) (strncmp (s, t, n) == 0) | 127 | #define strneq(s, t, n) (strncmp (s, t, n) == 0) |
| 144 | #define reg register | 128 | #define logical int |
| 145 | #define logical char | ||
| 146 | 129 | ||
| 147 | #define TRUE 1 | 130 | #define TRUE 1 |
| 148 | #define FALSE 0 | 131 | #define FALSE 0 |
| @@ -151,7 +134,6 @@ typedef struct | |||
| 151 | #define begtoken(arg) (_btk[arg]) /* T if char can start token */ | 134 | #define begtoken(arg) (_btk[arg]) /* T if char can start token */ |
| 152 | #define intoken(arg) (_itk[arg]) /* T if char can be in token */ | 135 | #define intoken(arg) (_itk[arg]) /* T if char can be in token */ |
| 153 | #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */ | 136 | #define endtoken(arg) (_etk[arg]) /* T if char ends tokens */ |
| 154 | #define isgood(arg) (_gd[arg]) /* T if char can be after ')' */ | ||
| 155 | 137 | ||
| 156 | #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2)) | 138 | #define max(I1,I2) ((I1) > (I2) ? (I1) : (I2)) |
| 157 | 139 | ||
| @@ -171,10 +153,9 @@ struct nd_st | |||
| 171 | long ftell (); | 153 | long ftell (); |
| 172 | typedef struct nd_st NODE; | 154 | typedef struct nd_st NODE; |
| 173 | 155 | ||
| 174 | logical gotone, /* found a func already on line */ | 156 | logical header_file; /* TRUE if .h file, FALSE o.w. */ |
| 175 | /* boolean "func" (see init) */ | 157 | /* boolean "functions" (see init) */ |
| 176 | header_file, /* TRUE if .h file, FALSE o.w. */ | 158 | logical _wht[0177], _etk[0177], _itk[0177], _btk[0177]; |
| 177 | _wht[0177], _etk[0177], _itk[0177], _btk[0177], _gd[0177]; | ||
| 178 | 159 | ||
| 179 | 160 | ||
| 180 | char *concat (); | 161 | char *concat (); |
| @@ -348,87 +329,20 @@ typedef struct | |||
| 348 | { | 329 | { |
| 349 | char *p; | 330 | char *p; |
| 350 | int len; | 331 | int len; |
| 351 | FILEPOS linestart; | ||
| 352 | LINENO lineno; | 332 | LINENO lineno; |
| 353 | logical rewritten; | 333 | logical rewritten; |
| 354 | } TOKEN; | 334 | } TOKEN; |
| 355 | |||
| 356 | |||
| 357 | /* typedefs are recognized using a simple finite automaton. | ||
| 358 | * tydef is its state variable. | ||
| 359 | */ | ||
| 360 | typedef enum | ||
| 361 | { | ||
| 362 | none, begin, middle, end | ||
| 363 | } TYST; | ||
| 364 | |||
| 365 | TYST tydef = none; | ||
| 366 | |||
| 367 | |||
| 368 | /* struct tags for C++ are recognized using another simple | ||
| 369 | * finite automaton. `structdef' is its state variable. | ||
| 370 | * This machinery is only invoked for C++; otherwise structdef | ||
| 371 | * should remain snone. However, this machinery can easily be | ||
| 372 | * adapted to find structure tags in normal C code. | ||
| 373 | */ | ||
| 374 | typedef enum | ||
| 375 | { | ||
| 376 | snone, /* nothing seen yet */ | ||
| 377 | skeyseen, /* struct-like keyword seen */ | ||
| 378 | stagseen, /* struct-like tag seen */ | ||
| 379 | scolonseen, /* colon seen after struct-like tag */ | ||
| 380 | sinbody /* in a class body: recognize member func defs */ | ||
| 381 | } STRUCTST; | ||
| 382 | STRUCTST structdef = snone; | ||
| 383 | /* | ||
| 384 | * When structdef is stagseen, scolonseen, or sinbody, structtag is the | ||
| 385 | * struct tag, and structkey is the preceding struct-like keyword. | ||
| 386 | */ | ||
| 387 | char structtag[512]; | ||
| 388 | Stab_entry *structkey; | ||
| 389 | 335 | ||
| 390 | /* | 336 | /* C extensions. |
| 391 | * Yet another little state machine to deal with preprocessor lines. | ||
| 392 | */ | ||
| 393 | typedef enum | ||
| 394 | { | ||
| 395 | dnone, /* nothing seen */ | ||
| 396 | dsharpseen, /* '#' seen as first char on line */ | ||
| 397 | ddefineseen, /* '#' and 'define' seen */ | ||
| 398 | dignorerest /* ignore rest of line */ | ||
| 399 | } DEFINEST; | ||
| 400 | DEFINEST definedef; | ||
| 401 | |||
| 402 | /* | ||
| 403 | * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body. | ||
| 404 | * Currently tydef and structdef stuff (typedefs and struct definitions) are | ||
| 405 | * only noticed when level==0, but that may change. | ||
| 406 | * | ||
| 407 | * Note that this macro may only be evaluated inside C_entries(). It is | ||
| 408 | * for self-documentation only. | ||
| 409 | */ | 337 | */ |
| 410 | #define LEVEL_OK_FOR_FUNCDEF() \ | 338 | #define C_PLPL 0x00001 /* C++ */ |
| 411 | (level==0 || (c_ext && level==1 && structdef==sinbody)) | 339 | #define C_STAR 0x00003 /* C* */ |
| 412 | 340 | #define YACC 0x10000 /* yacc file */ | |
| 413 | /* | ||
| 414 | * next_token_is_func | ||
| 415 | * set this to TRUE, and the next token considered is called a function. | ||
| 416 | */ | ||
| 417 | logical next_token_is_func; | ||
| 418 | |||
| 419 | /* C extensions. Currently all listed extensions are C++ dialects, so | ||
| 420 | * `c_ext' is used as an abbreviation for `c_ext&C_PLPL'. If a non-C++ | ||
| 421 | * dialect is added, this must change. | ||
| 422 | */ | ||
| 423 | #define C_PLPL 0x1 /* C++ */ | ||
| 424 | #define C_STAR 0x3 /* C* */ | ||
| 425 | 341 | ||
| 426 | char searchar = '/'; /* use /.../ searches */ | 342 | char searchar = '/'; /* use /.../ searches */ |
| 427 | 343 | ||
| 428 | LINENO lineno; /* line number of current line */ | 344 | LINENO lineno; /* line number of current line */ |
| 429 | long charno; /* current character number */ | 345 | long charno; /* current character number */ |
| 430 | FILEPOS linepos; /* start of line (C only) */ | ||
| 431 | FILEPOS prev_linepos; /* start of previous line (C only) */ | ||
| 432 | 346 | ||
| 433 | long linecharno; /* charno of start of line; not used by C, but | 347 | long linecharno; /* charno of start of line; not used by C, but |
| 434 | * by every other language. | 348 | * by every other language. |
| @@ -437,10 +351,11 @@ long linecharno; /* charno of start of line; not used by C, but | |||
| 437 | char *curfile, /* current input file name */ | 351 | char *curfile, /* current input file name */ |
| 438 | *outfile, /* output file */ | 352 | *outfile, /* output file */ |
| 439 | *white = " \f\t\n", /* white chars */ | 353 | *white = " \f\t\n", /* white chars */ |
| 440 | *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */ | 354 | *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", /* token ending chars */ |
| 441 | *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$", /* token starting chars */ | 355 | /* token starting chars */ |
| 442 | *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789", /* valid in-token chars */ | 356 | *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$", |
| 443 | *notgd = ",;"; /* non-valid after-function chars */ | 357 | /* valid in-token chars */ |
| 358 | *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789"; | ||
| 444 | 359 | ||
| 445 | int append_to_tagfile; /* -a: append to tags */ | 360 | int append_to_tagfile; /* -a: append to tags */ |
| 446 | int emacs_tags_format; /* emacs style output (no -e option any more) */ | 361 | int emacs_tags_format; /* emacs style output (no -e option any more) */ |
| @@ -502,10 +417,13 @@ struct linebuffer | |||
| 502 | }; | 417 | }; |
| 503 | 418 | ||
| 504 | struct linebuffer lb; /* the current line */ | 419 | struct linebuffer lb; /* the current line */ |
| 505 | struct linebuffer lb1; /* sometimes, a previous line in which a token lies */ | ||
| 506 | struct linebuffer filename_lb; /* used to read in filenames */ | 420 | struct linebuffer filename_lb; /* used to read in filenames */ |
| 421 | struct | ||
| 422 | { | ||
| 423 | FILEPOS linepos; | ||
| 424 | struct linebuffer lb; /* used by C_entries instead of lb */ | ||
| 425 | } lbs[2]; | ||
| 507 | 426 | ||
| 508 | |||
| 509 | void | 427 | void |
| 510 | print_version () | 428 | print_version () |
| 511 | { | 429 | { |
| @@ -758,7 +676,8 @@ main (argc, argv) | |||
| 758 | init (); /* set up boolean "functions" */ | 676 | init (); /* set up boolean "functions" */ |
| 759 | 677 | ||
| 760 | initbuffer (&lb); | 678 | initbuffer (&lb); |
| 761 | initbuffer (&lb1); | 679 | initbuffer (&lbs[0].lb); |
| 680 | initbuffer (&lbs[1].lb); | ||
| 762 | initbuffer (&filename_lb); | 681 | initbuffer (&filename_lb); |
| 763 | /* | 682 | /* |
| 764 | * loop through files finding functions | 683 | * loop through files finding functions |
| @@ -791,7 +710,7 @@ main (argc, argv) | |||
| 791 | this_file = massage_name (this_file); | 710 | this_file = massage_name (this_file); |
| 792 | #if 0 | 711 | #if 0 |
| 793 | } | 712 | } |
| 794 | } /* solely to balance out the ifdef'd parens above */ | 713 | } /* solely to balance out the ifdef'd parens above */ |
| 795 | #endif | 714 | #endif |
| 796 | #else | 715 | #else |
| 797 | for (; optind < argc; optind++) | 716 | for (; optind < argc; optind++) |
| @@ -915,14 +834,11 @@ process_file (file) | |||
| 915 | void | 834 | void |
| 916 | init () | 835 | init () |
| 917 | { | 836 | { |
| 918 | reg char *sp; | 837 | register char *sp; |
| 919 | reg int i; | 838 | register int i; |
| 920 | 839 | ||
| 921 | for (i = 0; i < 0177; i++) | 840 | for (i = 0; i < 0177; i++) |
| 922 | { | 841 | _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE; |
| 923 | _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE; | ||
| 924 | _gd[i] = TRUE; | ||
| 925 | } | ||
| 926 | for (sp = white; *sp; sp++) | 842 | for (sp = white; *sp; sp++) |
| 927 | _wht[*sp] = TRUE; | 843 | _wht[*sp] = TRUE; |
| 928 | for (sp = endtk; *sp; sp++) | 844 | for (sp = endtk; *sp; sp++) |
| @@ -931,13 +847,10 @@ init () | |||
| 931 | _itk[*sp] = TRUE; | 847 | _itk[*sp] = TRUE; |
| 932 | for (sp = begtk; *sp; sp++) | 848 | for (sp = begtk; *sp; sp++) |
| 933 | _btk[*sp] = TRUE; | 849 | _btk[*sp] = TRUE; |
| 934 | for (sp = notgd; *sp; sp++) | ||
| 935 | _gd[*sp] = FALSE; | ||
| 936 | _wht[0] = _wht['\n']; | 850 | _wht[0] = _wht['\n']; |
| 937 | _etk[0] = _etk['\n']; | 851 | _etk[0] = _etk['\n']; |
| 938 | _btk[0] = _btk['\n']; | 852 | _btk[0] = _btk['\n']; |
| 939 | _itk[0] = _itk['\n']; | 853 | _itk[0] = _itk['\n']; |
| 940 | _gd[0] = _gd['\n']; | ||
| 941 | } | 854 | } |
| 942 | 855 | ||
| 943 | /* | 856 | /* |
| @@ -998,8 +911,11 @@ find_entries (file) | |||
| 998 | fclose (inf); | 911 | fclose (inf); |
| 999 | return; | 912 | return; |
| 1000 | } | 913 | } |
| 1001 | /* Assume that ".s" or ".a" is assembly code. -wolfgang. */ | 914 | /* Assume that ".s" or ".a" is assembly code. -wolfgang. |
| 1002 | if (cp && (cp[1] == 's' || cp[1] == 'a') && cp[2] == '\0') | 915 | Or even ".sa". */ |
| 916 | if (cp && (streq (cp + 1, "s") | ||
| 917 | || streq (cp + 1, "a") | ||
| 918 | || streq (cp + 1, "sa"))) | ||
| 1003 | { | 919 | { |
| 1004 | Asm_funcs (inf); | 920 | Asm_funcs (inf); |
| 1005 | fclose (inf); | 921 | fclose (inf); |
| @@ -1016,13 +932,20 @@ find_entries (file) | |||
| 1016 | goto close_and_return; | 932 | goto close_and_return; |
| 1017 | } | 933 | } |
| 1018 | /* .cs or .hs: a C* file */ | 934 | /* .cs or .hs: a C* file */ |
| 1019 | if (cp && (cp[1] == 'c' || cp[1] == 'h') && cp[2] == 's' && cp[3] == '\0') | 935 | if (cp && (streq (cp + 1, "cs") |
| 936 | || streq (cp + 1, "hs"))) | ||
| 1020 | { | 937 | { |
| 1021 | C_entries (C_STAR); | 938 | C_entries (C_STAR); |
| 1022 | goto close_and_return; | 939 | goto close_and_return; |
| 1023 | } | 940 | } |
| 941 | /* .y: a yacc file */ | ||
| 942 | if (cp && (streq (cp + 1, "y"))) | ||
| 943 | { | ||
| 944 | C_entries (YACC); | ||
| 945 | goto close_and_return; | ||
| 946 | } | ||
| 1024 | /* .pl implies prolog source code */ | 947 | /* .pl implies prolog source code */ |
| 1025 | if (cp && !strcmp (cp + 1, "pl")) | 948 | if (cp && streq (cp + 1, "pl")) |
| 1026 | { | 949 | { |
| 1027 | prolog_funcs (inf); | 950 | prolog_funcs (inf); |
| 1028 | goto close_and_return; | 951 | goto close_and_return; |
| @@ -1035,7 +958,8 @@ find_entries (file) | |||
| 1035 | goto close_and_return; | 958 | goto close_and_return; |
| 1036 | } | 959 | } |
| 1037 | /* If .f or .for, assume it is fortran or nothing. */ | 960 | /* If .f or .for, assume it is fortran or nothing. */ |
| 1038 | if (cp && (streq (cp + 1, "f") || streq (cp + 1, "for"))) | 961 | if (cp && (streq (cp + 1, "f") |
| 962 | || streq (cp + 1, "for"))) | ||
| 1039 | { | 963 | { |
| 1040 | PF_funcs (inf); | 964 | PF_funcs (inf); |
| 1041 | goto close_and_return; | 965 | goto close_and_return; |
| @@ -1072,7 +996,6 @@ string_numeric_p (str) | |||
| 1072 | 996 | ||
| 1073 | /* Record a tag. */ | 997 | /* Record a tag. */ |
| 1074 | /* Should take a TOKEN* instead!! */ | 998 | /* Should take a TOKEN* instead!! */ |
| 1075 | |||
| 1076 | void | 999 | void |
| 1077 | pfnote (name, is_func, rewritten, linestart, linelen, lno, cno) | 1000 | pfnote (name, is_func, rewritten, linestart, linelen, lno, cno) |
| 1078 | char *name; /* tag name */ | 1001 | char *name; /* tag name */ |
| @@ -1238,9 +1161,9 @@ add_node (node, cur_node_p) | |||
| 1238 | 1161 | ||
| 1239 | void | 1162 | void |
| 1240 | put_entries (node) | 1163 | put_entries (node) |
| 1241 | reg NODE *node; | 1164 | register NODE *node; |
| 1242 | { | 1165 | { |
| 1243 | reg char *sp; | 1166 | register char *sp; |
| 1244 | 1167 | ||
| 1245 | if (node == NULL) | 1168 | if (node == NULL) |
| 1246 | return; | 1169 | return; |
| @@ -1319,9 +1242,9 @@ number_len (num) | |||
| 1319 | */ | 1242 | */ |
| 1320 | int | 1243 | int |
| 1321 | total_size_of_entries (node) | 1244 | total_size_of_entries (node) |
| 1322 | reg NODE *node; | 1245 | register NODE *node; |
| 1323 | { | 1246 | { |
| 1324 | reg int total; | 1247 | register int total; |
| 1325 | 1248 | ||
| 1326 | if (node == NULL) | 1249 | if (node == NULL) |
| 1327 | return 0; | 1250 | return 0; |
| @@ -1352,8 +1275,8 @@ Stab *C_stab, *C_PLPL_stab, *C_STAR_stab; | |||
| 1352 | * SYNOPSIS | 1275 | * SYNOPSIS |
| 1353 | * Stab *get_C_stab (int c_ext); | 1276 | * Stab *get_C_stab (int c_ext); |
| 1354 | */ | 1277 | */ |
| 1355 | #define get_C_stab(c_ext) ((c_ext&C_STAR) ? C_STAR_stab : \ | 1278 | #define get_C_stab(c_ext) ((c_ext & C_STAR) ? C_STAR_stab : \ |
| 1356 | c_ext ? C_PLPL_stab : \ | 1279 | (c_ext & C_PLPL) ? C_PLPL_stab : \ |
| 1357 | C_stab) | 1280 | C_stab) |
| 1358 | 1281 | ||
| 1359 | void | 1282 | void |
| @@ -1391,6 +1314,10 @@ C_create_stab (c_ext) | |||
| 1391 | add_keyword (stab, "double", st_C_typespec); | 1314 | add_keyword (stab, "double", st_C_typespec); |
| 1392 | add_keyword (stab, "signed", st_C_typespec); | 1315 | add_keyword (stab, "signed", st_C_typespec); |
| 1393 | add_keyword (stab, "unsigned", st_C_typespec); | 1316 | add_keyword (stab, "unsigned", st_C_typespec); |
| 1317 | add_keyword (stab, "auto", st_C_typespec); | ||
| 1318 | add_keyword (stab, "void", st_C_typespec); | ||
| 1319 | add_keyword (stab, "extern", st_C_typespec); | ||
| 1320 | add_keyword (stab, "static", st_C_typespec); | ||
| 1394 | add_keyword (stab, "const", st_C_typespec); | 1321 | add_keyword (stab, "const", st_C_typespec); |
| 1395 | add_keyword (stab, "volatile", st_C_typespec); | 1322 | add_keyword (stab, "volatile", st_C_typespec); |
| 1396 | 1323 | ||
| @@ -1405,50 +1332,142 @@ C_create_stabs () | |||
| 1405 | C_STAR_stab = C_create_stab (C_STAR | C_PLPL); | 1332 | C_STAR_stab = C_create_stab (C_STAR | C_PLPL); |
| 1406 | } | 1333 | } |
| 1407 | 1334 | ||
| 1335 | /* | ||
| 1336 | * etags.c 4.2 1993/03/22 12:13:40 pot Exp | ||
| 1337 | * C functions are recognized using a simple finite automaton. | ||
| 1338 | * funcdef is its state variable. | ||
| 1339 | */ | ||
| 1340 | typedef enum | ||
| 1341 | { | ||
| 1342 | fnone, ftagseen, finlist, flistseen | ||
| 1343 | } FUNCST; | ||
| 1344 | FUNCST funcdef; | ||
| 1345 | |||
| 1346 | |||
| 1347 | /* typedefs are recognized using a simple finite automaton. | ||
| 1348 | * typeddef is its state variable. | ||
| 1349 | */ | ||
| 1350 | typedef enum | ||
| 1351 | { | ||
| 1352 | tnone, ttypedseen, tinbody, tend | ||
| 1353 | } TYPEDST; | ||
| 1354 | TYPEDST typdef; | ||
| 1355 | |||
| 1356 | |||
| 1357 | /* struct tags for C++ are recognized using another simple | ||
| 1358 | * finite automaton. `structdef' is its state variable. | ||
| 1359 | * This machinery is only invoked for C++; otherwise structdef | ||
| 1360 | * should remain snone. However, this machinery can easily be | ||
| 1361 | * adapted to find structure tags in normal C code. | ||
| 1362 | */ | ||
| 1363 | typedef enum | ||
| 1364 | { | ||
| 1365 | snone, /* nothing seen yet */ | ||
| 1366 | skeyseen, /* struct-like keyword seen */ | ||
| 1367 | stagseen, /* struct-like tag seen */ | ||
| 1368 | scolonseen, /* colon seen after struct-like tag */ | ||
| 1369 | sinbody /* in class body: recognize member func defs */ | ||
| 1370 | } STRUCTST; | ||
| 1371 | STRUCTST structdef; | ||
| 1372 | /* | ||
| 1373 | * When structdef is stagseen, scolonseen, or sinbody, structtag is the | ||
| 1374 | * struct tag, and structkey is the preceding struct-like keyword. | ||
| 1375 | */ | ||
| 1376 | char structtag[BUFSIZ]; | ||
| 1377 | Stab_entry *structkey; | ||
| 1378 | |||
| 1379 | /* | ||
| 1380 | * Yet another little state machine to deal with preprocessor lines. | ||
| 1381 | */ | ||
| 1382 | typedef enum | ||
| 1383 | { | ||
| 1384 | dnone, /* nothing seen */ | ||
| 1385 | dsharpseen, /* '#' seen as first char on line */ | ||
| 1386 | ddefineseen, /* '#' and 'define' seen */ | ||
| 1387 | dignorerest /* ignore rest of line */ | ||
| 1388 | } DEFINEST; | ||
| 1389 | DEFINEST definedef; | ||
| 1390 | |||
| 1391 | /* | ||
| 1392 | * Set this to TRUE, and the next token considered is called a function. | ||
| 1393 | * Used only for GNUmacs's function-defining macros. | ||
| 1394 | */ | ||
| 1395 | logical next_token_is_func; | ||
| 1396 | |||
| 1397 | /* | ||
| 1398 | * TRUE in the rules part of a yacc file, FALSE outside (parse as C). | ||
| 1399 | */ | ||
| 1400 | logical yacc_rules; | ||
| 1401 | |||
| 1408 | /* | 1402 | /* |
| 1409 | * C_entries () | 1403 | * C_entries () |
| 1410 | * This routine finds functions and typedefs in C syntax and adds them | 1404 | * This routine finds functions, typedefs, #define's and |
| 1405 | * struct/union/enum definitions in C syntax and adds them | ||
| 1411 | * to the list. | 1406 | * to the list. |
| 1412 | */ | 1407 | */ |
| 1413 | 1408 | ||
| 1409 | /* | ||
| 1410 | * LEVEL_OK_FOR_FUNCDEF allows C++ function definition within class body. | ||
| 1411 | * Currently typdef and structdef stuff (typedefs and struct | ||
| 1412 | * definitions) are only noticed when level==0, but that may change. | ||
| 1413 | */ | ||
| 1414 | #define LEVEL_OK_FOR_FUNCDEF() \ | ||
| 1415 | (level==0 || (cplpl && level==1 && structdef==sinbody)) | ||
| 1416 | |||
| 1417 | #define curlb (lbs[curndx].lb) | ||
| 1418 | #define othlb (lbs[1-curndx].lb) | ||
| 1419 | #define newlb (lbs[newndx].lb) | ||
| 1420 | #define curlinepos (lbs[curndx].linepos) | ||
| 1421 | #define othlinepos (lbs[1-curndx].linepos) | ||
| 1422 | #define newlinepos (lbs[newndx].linepos) | ||
| 1423 | |||
| 1414 | #define CNL_SAVE_DEFINEDEF \ | 1424 | #define CNL_SAVE_DEFINEDEF \ |
| 1415 | { \ | 1425 | do { \ |
| 1416 | quotednl = FALSE; \ | 1426 | SET_FILEPOS (curlinepos, inf, charno); \ |
| 1417 | prev_linepos = linepos; \ | ||
| 1418 | SET_FILEPOS (linepos, inf, charno); \ | ||
| 1419 | lineno++; \ | 1427 | lineno++; \ |
| 1420 | charno += readline (&lb, inf); \ | 1428 | charno += readline (&curlb, inf); \ |
| 1421 | lp = lb.buffer; \ | 1429 | lp = curlb.buffer; \ |
| 1422 | } | 1430 | quotednl = FALSE; \ |
| 1431 | newndx = curndx; \ | ||
| 1432 | } while (FALSE) | ||
| 1423 | 1433 | ||
| 1424 | #define CNL \ | 1434 | #define CNL \ |
| 1425 | { \ | 1435 | do { \ |
| 1426 | CNL_SAVE_DEFINEDEF; \ | 1436 | CNL_SAVE_DEFINEDEF; \ |
| 1427 | definedef = dnone; \ | 1437 | definedef = dnone; \ |
| 1428 | } | 1438 | } while (FALSE) |
| 1439 | |||
| 1440 | #define MAKE_TAG_FROM_NEW_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \ | ||
| 1441 | newlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (newlinepos)) | ||
| 1442 | #define MAKE_TAG_FROM_OTH_LB(isfun) pfnote (tokb, isfun, tok.rewritten, \ | ||
| 1443 | othlb.buffer, tokoff + toklen + 1, tok.lineno, GET_CHARNO (othlinepos)) | ||
| 1429 | 1444 | ||
| 1430 | void | 1445 | void |
| 1431 | C_entries (c_ext) | 1446 | C_entries (c_ext) |
| 1432 | int c_ext; /* extension of C? */ | 1447 | int c_ext; /* extension of C? */ |
| 1433 | { | 1448 | { |
| 1434 | register int c; /* latest char read; '\0' for end of line */ | 1449 | register char c; /* latest char read; '\0' for end of line */ |
| 1435 | register int tokoff; /* offset in line of start of latest token*/ | ||
| 1436 | register int toklen; /* length of latest token */ | ||
| 1437 | register char *lp; /* pointer one beyond the character `c' */ | 1450 | register char *lp; /* pointer one beyond the character `c' */ |
| 1438 | logical incomm, inquote, inchar, quotednl, midtoken; | 1451 | int curndx, newndx; /* indices for current and new lb */ |
| 1452 | TOKEN tok; /* latest token read for funcdef & structdef */ | ||
| 1453 | char tokb[BUFSIZ]; /* latest token name for funcdef & structdef */ | ||
| 1454 | register int tokoff; /* offset in line of start of latest token */ | ||
| 1455 | register int toklen; /* length of latest token */ | ||
| 1439 | int level; /* current curly brace level */ | 1456 | int level; /* current curly brace level */ |
| 1440 | char tokb[BUFSIZ]; | 1457 | logical incomm, inquote, inchar, quotednl, midtoken; |
| 1458 | logical cplpl; | ||
| 1441 | 1459 | ||
| 1460 | curndx = newndx = 0; | ||
| 1442 | lineno = 0; | 1461 | lineno = 0; |
| 1443 | charno = 0; | 1462 | charno = 0; |
| 1444 | lp = lb.buffer; | 1463 | lp = curlb.buffer; |
| 1445 | *lp = 0; | 1464 | *lp = 0; |
| 1446 | 1465 | ||
| 1447 | definedef = dnone; | 1466 | definedef = dnone; funcdef = fnone; typdef= tnone; structdef= snone; |
| 1448 | gotone = midtoken = inquote = inchar = incomm = quotednl = FALSE; | 1467 | next_token_is_func = yacc_rules = FALSE; |
| 1468 | midtoken = inquote = inchar = incomm = quotednl = FALSE; | ||
| 1449 | level = 0; | 1469 | level = 0; |
| 1450 | tydef = none; | 1470 | cplpl = c_ext & C_PLPL; |
| 1451 | next_token_is_func = 0; | ||
| 1452 | 1471 | ||
| 1453 | C_create_stabs (); | 1472 | C_create_stabs (); |
| 1454 | 1473 | ||
| @@ -1460,9 +1479,9 @@ C_entries (c_ext) | |||
| 1460 | /* If we're at the end of the line, the next character is a | 1479 | /* If we're at the end of the line, the next character is a |
| 1461 | '\0'; don't skip it, because it's the thing that tells us | 1480 | '\0'; don't skip it, because it's the thing that tells us |
| 1462 | to read the next line. */ | 1481 | to read the next line. */ |
| 1463 | if (*lp == 0) | 1482 | if (*lp == '\0') |
| 1464 | { | 1483 | { |
| 1465 | quotednl =TRUE; | 1484 | quotednl = TRUE; |
| 1466 | continue; | 1485 | continue; |
| 1467 | } | 1486 | } |
| 1468 | lp++; | 1487 | lp++; |
| @@ -1470,18 +1489,38 @@ C_entries (c_ext) | |||
| 1470 | } | 1489 | } |
| 1471 | else if (incomm) | 1490 | else if (incomm) |
| 1472 | { | 1491 | { |
| 1473 | if (c == '*' && *lp == '/') | 1492 | switch (c) |
| 1474 | { | 1493 | { |
| 1475 | c = *lp++; | 1494 | case '*': |
| 1476 | incomm = FALSE; | 1495 | if (*lp == '/') |
| 1496 | { | ||
| 1497 | c = *lp++; | ||
| 1498 | incomm = FALSE; | ||
| 1499 | } | ||
| 1500 | break; | ||
| 1501 | case '\0': | ||
| 1502 | /* Newlines inside comments do not end macro definitions in | ||
| 1503 | traditional cpp. */ | ||
| 1504 | CNL_SAVE_DEFINEDEF; | ||
| 1505 | break; | ||
| 1477 | } | 1506 | } |
| 1507 | continue; | ||
| 1478 | } | 1508 | } |
| 1479 | else if (inquote) | 1509 | else if (inquote) |
| 1480 | { | 1510 | { |
| 1481 | if (c == '"') | 1511 | switch (c) |
| 1482 | inquote = FALSE; | 1512 | { |
| 1483 | else if (c == '\\') | 1513 | case '"': |
| 1484 | c = *lp++; | 1514 | inquote = FALSE; |
| 1515 | break; | ||
| 1516 | case '\0': | ||
| 1517 | /* Newlines inside strings, do not end macro definitions | ||
| 1518 | in traditional cpp, even though compilers don't | ||
| 1519 | usually accept them. */ | ||
| 1520 | CNL_SAVE_DEFINEDEF; | ||
| 1521 | break; | ||
| 1522 | } | ||
| 1523 | continue; | ||
| 1485 | } | 1524 | } |
| 1486 | else if (inchar) | 1525 | else if (inchar) |
| 1487 | { | 1526 | { |
| @@ -1489,7 +1528,7 @@ C_entries (c_ext) | |||
| 1489 | inchar = FALSE; | 1528 | inchar = FALSE; |
| 1490 | continue; | 1529 | continue; |
| 1491 | } | 1530 | } |
| 1492 | else | 1531 | else |
| 1493 | switch (c) | 1532 | switch (c) |
| 1494 | { | 1533 | { |
| 1495 | case '"': | 1534 | case '"': |
| @@ -1503,77 +1542,44 @@ C_entries (c_ext) | |||
| 1503 | { | 1542 | { |
| 1504 | lp++; | 1543 | lp++; |
| 1505 | incomm = TRUE; | 1544 | incomm = TRUE; |
| 1545 | continue; | ||
| 1506 | } | 1546 | } |
| 1507 | else if (c_ext && *lp == '/') | 1547 | else if (cplpl && *lp == '/') |
| 1508 | { | 1548 | { |
| 1509 | c = 0; | 1549 | c = 0; |
| 1510 | break; | 1550 | break; |
| 1511 | } | 1551 | } |
| 1512 | continue; | 1552 | continue; |
| 1553 | case '%': | ||
| 1554 | if ((c_ext & YACC) && *lp == '%') | ||
| 1555 | { | ||
| 1556 | /* entering or exiting rules section in yacc file */ | ||
| 1557 | lp++; | ||
| 1558 | definedef = dnone; funcdef = fnone; | ||
| 1559 | typdef= tnone; structdef= snone; | ||
| 1560 | next_token_is_func = FALSE; | ||
| 1561 | midtoken = inquote = inchar = incomm = quotednl = FALSE; | ||
| 1562 | level = 0; | ||
| 1563 | yacc_rules = !yacc_rules; | ||
| 1564 | continue; | ||
| 1565 | } | ||
| 1513 | case '#': | 1566 | case '#': |
| 1514 | if (lp == lb.buffer + 1 && definedef == dnone) | 1567 | if (lp == newlb.buffer + 1 && definedef == dnone) |
| 1515 | definedef = dsharpseen; | 1568 | definedef = dsharpseen; |
| 1516 | continue; | 1569 | continue; |
| 1570 | } /* switch (c) */ | ||
| 1517 | 1571 | ||
| 1518 | /* | ||
| 1519 | * The next two are to help the strucdef state machine. | ||
| 1520 | * They break when they are finished, so they don't interfere | ||
| 1521 | * with anything else that is going on. | ||
| 1522 | */ | ||
| 1523 | case ':': | ||
| 1524 | if (structdef == stagseen) | ||
| 1525 | structdef = scolonseen; | ||
| 1526 | break; | ||
| 1527 | /* Not a struct definition when semicolon seen | ||
| 1528 | in non-sinbody context. */ | ||
| 1529 | case ';': | ||
| 1530 | if (structdef != snone && structdef != sinbody) | ||
| 1531 | { | ||
| 1532 | structdef = snone; | ||
| 1533 | (void) strcpy (structtag, "<error 1>"); | ||
| 1534 | } | ||
| 1535 | break; | ||
| 1536 | 1572 | ||
| 1537 | case '{': | 1573 | if (LEVEL_OK_FOR_FUNCDEF () |
| 1538 | if (tydef == begin) | 1574 | && definedef != dignorerest |
| 1539 | { | 1575 | && structdef != scolonseen |
| 1540 | tydef = middle; | 1576 | && funcdef != finlist) |
| 1541 | } | ||
| 1542 | switch (structdef) | ||
| 1543 | { | ||
| 1544 | case skeyseen: /* unnamed struct */ | ||
| 1545 | structtag[0] = '\0'; | ||
| 1546 | /* FALLTHRU */ | ||
| 1547 | case stagseen: | ||
| 1548 | case scolonseen: /* named struct */ | ||
| 1549 | structdef = sinbody; | ||
| 1550 | break; | ||
| 1551 | } | ||
| 1552 | level++; | ||
| 1553 | continue; | ||
| 1554 | case '}': | ||
| 1555 | if (!noindentypedefs && lp == lb.buffer + 1) | ||
| 1556 | level = 0; /* reset level if first column */ | ||
| 1557 | else if (level > 0) | ||
| 1558 | level--; | ||
| 1559 | if (level == 0 && tydef == middle) | ||
| 1560 | { | ||
| 1561 | tydef = end; | ||
| 1562 | } | ||
| 1563 | if (level == 0) | ||
| 1564 | { | ||
| 1565 | structdef = snone; | ||
| 1566 | (void) strcpy (structtag, "<error 2>"); | ||
| 1567 | } | ||
| 1568 | continue; | ||
| 1569 | } | ||
| 1570 | if (LEVEL_OK_FOR_FUNCDEF () && !inquote && !incomm && gotone == FALSE) | ||
| 1571 | { | 1577 | { |
| 1572 | if (midtoken) | 1578 | if (midtoken) |
| 1573 | { | 1579 | { |
| 1574 | if (endtoken (c)) | 1580 | if (endtoken (c)) |
| 1575 | { | 1581 | { |
| 1576 | if (c_ext && c == ':' && *lp == ':' && intoken (*(lp + 1))) | 1582 | if (cplpl && c == ':' && *lp == ':' && intoken (*(lp + 1))) |
| 1577 | { | 1583 | { |
| 1578 | /* | 1584 | /* |
| 1579 | * This handles :: in the middle, but not at beginning | 1585 | * This handles :: in the middle, but not at beginning |
| @@ -1584,72 +1590,22 @@ C_entries (c_ext) | |||
| 1584 | } | 1590 | } |
| 1585 | else | 1591 | else |
| 1586 | { | 1592 | { |
| 1587 | /* The following is no longer true, | ||
| 1588 | now that we advance to the next line | ||
| 1589 | at the end of processing the character. */ | ||
| 1590 | /* | ||
| 1591 | * We've just finished lexing an identifier. | ||
| 1592 | * Note that if `c' is '\0', `lb' is the NEXT | ||
| 1593 | * line, `lp' points to the beginning of it, and | ||
| 1594 | * old pointers into `lb.buffer' may no longer be | ||
| 1595 | * valid, since `lb.buffer' may have been | ||
| 1596 | * reallocated. In this case (which corresponds | ||
| 1597 | * to an identifier followed immediately by a | ||
| 1598 | * newline), we re-read the line into lb1. | ||
| 1599 | * | ||
| 1600 | * This would be faster if the previous line's | ||
| 1601 | * buffer were always saved. | ||
| 1602 | */ | ||
| 1603 | logical is_func; | 1593 | logical is_func; |
| 1604 | char *tok_linebuf; | ||
| 1605 | TOKEN tok; | ||
| 1606 | logical bingo, tok_at_end_of_line; | ||
| 1607 | char *lp_tmp; /* addressable */ | ||
| 1608 | 1594 | ||
| 1609 | #if 0 | 1595 | tok.lineno = lineno; |
| 1610 | if (c == '\0') | 1596 | tok.p = newlb.buffer + tokoff; |
| 1611 | { | ||
| 1612 | getline (GET_COOKIE (prev_linepos)); | ||
| 1613 | tok_linebuf = lb1.buffer; | ||
| 1614 | tok_at_end_of_line = TRUE; | ||
| 1615 | tok.linestart = prev_linepos; | ||
| 1616 | tok.lineno = lineno - 1; | ||
| 1617 | } | ||
| 1618 | else | ||
| 1619 | #endif | ||
| 1620 | { | ||
| 1621 | tok_linebuf = lb.buffer; | ||
| 1622 | tok_at_end_of_line = FALSE; | ||
| 1623 | tok.linestart = linepos; | ||
| 1624 | tok.lineno = lineno; | ||
| 1625 | } | ||
| 1626 | tok.p = tok_linebuf + tokoff; | ||
| 1627 | tok.len = toklen; | 1597 | tok.len = toklen; |
| 1628 | tok.rewritten = FALSE; | 1598 | tok.rewritten = FALSE; |
| 1629 | lp_tmp = lp; | 1599 | if (yacc_rules |
| 1630 | bingo = consider_token (c, &lp_tmp, &tok, | 1600 | || consider_token (c, lp, &tok, |
| 1631 | &is_func, c_ext, level); | 1601 | c_ext, level, &is_func)) |
| 1632 | lp = lp_tmp; | ||
| 1633 | if (bingo) | ||
| 1634 | { | 1602 | { |
| 1635 | if (GET_CHARNO (tok.linestart) != GET_CHARNO(linepos) | ||
| 1636 | && !tok_at_end_of_line) | ||
| 1637 | { | ||
| 1638 | /* | ||
| 1639 | * Resynchronize tok.p to point into the right | ||
| 1640 | * linebuffer. | ||
| 1641 | */ | ||
| 1642 | getline (GET_COOKIE (tok.linestart)); | ||
| 1643 | if (!tok.rewritten) | ||
| 1644 | tok.p = lb1.buffer + (tok.p - tok_linebuf); | ||
| 1645 | tok_linebuf = lb1.buffer; | ||
| 1646 | } | ||
| 1647 | if (structdef == sinbody | 1603 | if (structdef == sinbody |
| 1648 | && definedef == dnone && is_func) | 1604 | && definedef == dnone && is_func) |
| 1649 | { /* function defined in C++ class body */ | 1605 | { /* function defined in C++ class body */ |
| 1650 | sprintf (tokb, "%s::%.*s", | 1606 | sprintf (tokb, "%s::%.*s", |
| 1651 | structtag[0] == '\0' ? "_anonymous_" | 1607 | ((structtag[0] == '\0') |
| 1652 | : structtag, | 1608 | ? "_anonymous_" : structtag), |
| 1653 | tok.len, tok.p); | 1609 | tok.len, tok.p); |
| 1654 | tok.rewritten = TRUE; | 1610 | tok.rewritten = TRUE; |
| 1655 | } | 1611 | } |
| @@ -1657,49 +1613,148 @@ C_entries (c_ext) | |||
| 1657 | { | 1613 | { |
| 1658 | sprintf (tokb, "%.*s", tok.len, tok.p); | 1614 | sprintf (tokb, "%.*s", tok.len, tok.p); |
| 1659 | } | 1615 | } |
| 1660 | pfnote (tokb, is_func, tok.rewritten, tok_linebuf, | 1616 | |
| 1661 | tokoff + toklen + (tok_at_end_of_line ? 0 : 1), | 1617 | if (funcdef == ftagseen || structdef == stagseen) |
| 1662 | tok.lineno, GET_CHARNO (tok.linestart)); | 1618 | { |
| 1663 | gotone = is_func; /* function */ | 1619 | if (newndx == curndx) |
| 1620 | curndx = 1 - curndx; /* switch line buffers */ | ||
| 1621 | } | ||
| 1622 | else | ||
| 1623 | MAKE_TAG_FROM_NEW_LB (is_func); | ||
| 1664 | } | 1624 | } |
| 1665 | midtoken = FALSE; | 1625 | midtoken = FALSE; |
| 1666 | } | 1626 | } |
| 1667 | } | 1627 | } /* if (endtoken (c)) */ |
| 1668 | else if (intoken (c)) | 1628 | else if (intoken (c)) |
| 1669 | toklen++; | 1629 | { |
| 1670 | } | 1630 | toklen++; |
| 1631 | continue; | ||
| 1632 | } | ||
| 1633 | } /* if (midtoken) */ | ||
| 1671 | else if (begtoken (c)) | 1634 | else if (begtoken (c)) |
| 1672 | { | 1635 | { |
| 1673 | tokoff = lp - 1 - lb.buffer; | 1636 | switch (funcdef) |
| 1674 | toklen = 1; | 1637 | { |
| 1675 | midtoken = TRUE; | 1638 | case flistseen: |
| 1639 | MAKE_TAG_FROM_OTH_LB (TRUE); | ||
| 1640 | /* FALLTHRU */ | ||
| 1641 | case ftagseen: | ||
| 1642 | funcdef = fnone; | ||
| 1643 | break; | ||
| 1644 | } | ||
| 1645 | if (structdef == stagseen) | ||
| 1646 | structdef = snone; | ||
| 1647 | if (!yacc_rules || lp == newlb.buffer + 1) | ||
| 1648 | { | ||
| 1649 | tokoff = lp - 1 - newlb.buffer; | ||
| 1650 | toklen = 1; | ||
| 1651 | midtoken = TRUE; | ||
| 1652 | } | ||
| 1653 | continue; | ||
| 1676 | } | 1654 | } |
| 1677 | } | 1655 | } /* if must look at token */ |
| 1678 | /* Detect end of line, having handled the last token on the line. */ | 1656 | |
| 1679 | if (c == 0) | 1657 | |
| 1658 | /* Detect end of line, colon, comma, semicolon and various braces | ||
| 1659 | after having handled the last token on the line.*/ | ||
| 1660 | switch (c) | ||
| 1680 | { | 1661 | { |
| 1681 | if (incomm || inquote || quotednl) | 1662 | case ':': |
| 1663 | if (structdef == stagseen) | ||
| 1664 | structdef = scolonseen; | ||
| 1665 | else if (yacc_rules && funcdef == ftagseen) | ||
| 1682 | { | 1666 | { |
| 1683 | CNL_SAVE_DEFINEDEF; | 1667 | MAKE_TAG_FROM_OTH_LB (FALSE); |
| 1668 | funcdef == fnone; | ||
| 1684 | } | 1669 | } |
| 1685 | else | 1670 | break; |
| 1671 | case ';': | ||
| 1672 | funcdef = fnone; | ||
| 1673 | /* FALLTHRU */ | ||
| 1674 | case ',': | ||
| 1675 | if (funcdef != finlist) | ||
| 1676 | funcdef = fnone; | ||
| 1677 | if (level == 0 && typdef == tend) | ||
| 1678 | typdef = tnone; | ||
| 1679 | /* FALLTHRU */ | ||
| 1680 | case '[': | ||
| 1681 | if (funcdef != finlist) | ||
| 1682 | funcdef = fnone; | ||
| 1683 | if (structdef == stagseen) | ||
| 1684 | structdef = snone; | ||
| 1685 | break; | ||
| 1686 | case '(': | ||
| 1687 | switch (funcdef) | ||
| 1686 | { | 1688 | { |
| 1687 | CNL; | 1689 | case ftagseen: |
| 1690 | funcdef = finlist; | ||
| 1691 | break; | ||
| 1692 | case finlist: | ||
| 1693 | case flistseen: | ||
| 1694 | funcdef = fnone; | ||
| 1695 | break; | ||
| 1688 | } | 1696 | } |
| 1689 | gotone = FALSE; | 1697 | break; |
| 1690 | } | 1698 | case ')': |
| 1691 | if (c == ';' && tydef == end) /* clean with typedefs */ | 1699 | if (funcdef == finlist) |
| 1692 | tydef = none; | 1700 | funcdef = flistseen; |
| 1693 | } | 1701 | break; |
| 1702 | case '{': | ||
| 1703 | if (typdef == ttypedseen) | ||
| 1704 | typdef = tinbody; | ||
| 1705 | switch (structdef) | ||
| 1706 | { | ||
| 1707 | case skeyseen: /* unnamed struct */ | ||
| 1708 | structtag[0] = '\0'; | ||
| 1709 | structdef = sinbody; | ||
| 1710 | break; | ||
| 1711 | case stagseen: | ||
| 1712 | case scolonseen: /* named struct */ | ||
| 1713 | structdef = sinbody; | ||
| 1714 | MAKE_TAG_FROM_OTH_LB (FALSE); | ||
| 1715 | break; | ||
| 1716 | } | ||
| 1717 | level++; | ||
| 1718 | /* FALLTHRU */ | ||
| 1719 | case '*': | ||
| 1720 | if (funcdef == flistseen) | ||
| 1721 | { | ||
| 1722 | MAKE_TAG_FROM_OTH_LB (TRUE); | ||
| 1723 | funcdef = fnone; | ||
| 1724 | } | ||
| 1725 | break; | ||
| 1726 | case '}': | ||
| 1727 | if (!noindentypedefs && lp == newlb.buffer + 1) | ||
| 1728 | level = 0; /* reset level if first column */ | ||
| 1729 | else if (level > 0) | ||
| 1730 | level--; | ||
| 1731 | if (level == 0) | ||
| 1732 | { | ||
| 1733 | if (typdef == tinbody) | ||
| 1734 | typdef = tend; | ||
| 1735 | structdef = snone; | ||
| 1736 | (void) strcpy (structtag, "<error 2>"); | ||
| 1737 | } | ||
| 1738 | break; | ||
| 1739 | case '\0': | ||
| 1740 | /* If a macro spans multiple lines don't reset its state. */ | ||
| 1741 | if (quotednl) | ||
| 1742 | CNL_SAVE_DEFINEDEF; | ||
| 1743 | else | ||
| 1744 | CNL; | ||
| 1745 | break; | ||
| 1746 | } /* switch (c) */ | ||
| 1747 | |||
| 1748 | } /* while not eof */ | ||
| 1694 | } | 1749 | } |
| 1695 | 1750 | ||
| 1696 | /* | 1751 | /* |
| 1697 | * consider_token () | 1752 | * consider_token () |
| 1698 | * checks to see if the current token is at the start of a | 1753 | * checks to see if the current token is at the start of a |
| 1699 | * function, or corresponds to a typedef. It updates the input | 1754 | * function, or corresponds to a typedef, or is a struct/union/enum |
| 1700 | * line pointer *LPP so that the '(' will be in it when it returns. | 1755 | * tag. |
| 1701 | * | 1756 | * |
| 1702 | * *IS_FUNC gets TRUE iff the token is a function. | 1757 | * *IS_FUNC gets TRUE iff the token is a function or macro with args. |
| 1703 | * C_EXT is which language we are looking at. | 1758 | * C_EXT is which language we are looking at. |
| 1704 | * | 1759 | * |
| 1705 | * In the future we will need some way to adjust where the end of | 1760 | * In the future we will need some way to adjust where the end of |
| @@ -1708,31 +1763,30 @@ C_entries (c_ext) | |||
| 1708 | * whatever follows `operator'. | 1763 | * whatever follows `operator'. |
| 1709 | * | 1764 | * |
| 1710 | * Globals | 1765 | * Globals |
| 1711 | * structdef IN OUT | 1766 | * funcdef IN OUT |
| 1712 | * definedef IN OUT | 1767 | * structdef IN OUT |
| 1713 | * tydef IN OUT | 1768 | * definedef IN OUT |
| 1769 | * typdef IN OUT | ||
| 1770 | * next_token_is_func IN OUT | ||
| 1714 | */ | 1771 | */ |
| 1715 | 1772 | ||
| 1716 | logical | 1773 | logical |
| 1717 | consider_token (c, lpp, tokp, is_func, c_ext, level) | 1774 | consider_token (c, lp, tokp, c_ext, level, is_func) |
| 1718 | reg char c; /* IN: first char after the token */ | 1775 | register char c; /* IN: first char after the token */ |
| 1719 | char **lpp; /* IN OUT: *lpp points | 1776 | register char *lp; /* IN: lp points to 2nd char after the token */ |
| 1720 | to 2nd char after the token */ | 1777 | register TOKEN *tokp; /* IN */ |
| 1721 | reg TOKEN *tokp; /* IN */ | ||
| 1722 | logical *is_func; /* OUT */ | ||
| 1723 | int c_ext; /* IN */ | 1778 | int c_ext; /* IN */ |
| 1724 | int level; /* IN */ | 1779 | int level; /* IN */ |
| 1780 | logical *is_func; /* OUT */ | ||
| 1725 | { | 1781 | { |
| 1726 | reg char *lp = *lpp; | ||
| 1727 | logical firsttok; /* TRUE if have seen first token in ()'s */ | 1782 | logical firsttok; /* TRUE if have seen first token in ()'s */ |
| 1728 | Stab_entry *tokse = stab_find (get_C_stab (c_ext), tokp->p, tokp->len); | 1783 | Stab_entry *tokse = stab_find (get_C_stab (c_ext), tokp->p, tokp->len); |
| 1729 | enum sym_type toktype = stab_type (tokse); | 1784 | enum sym_type toktype = stab_type (tokse); |
| 1730 | 1785 | ||
| 1731 | *is_func = TRUE; /* a function */ | 1786 | *is_func = FALSE; /* not a function */ |
| 1732 | 1787 | ||
| 1733 | /* | 1788 | /* |
| 1734 | * Advance the definedef state machine. We set `gotone' for good measure; | 1789 | * Advance the definedef state machine. |
| 1735 | * it's redundant. | ||
| 1736 | */ | 1790 | */ |
| 1737 | switch (definedef) | 1791 | switch (definedef) |
| 1738 | { | 1792 | { |
| @@ -1743,95 +1797,63 @@ consider_token (c, lpp, tokp, is_func, c_ext, level) | |||
| 1743 | if (toktype == st_C_define) | 1797 | if (toktype == st_C_define) |
| 1744 | { | 1798 | { |
| 1745 | definedef = ddefineseen; | 1799 | definedef = ddefineseen; |
| 1746 | gotone = FALSE; | ||
| 1747 | } | 1800 | } |
| 1748 | else | 1801 | else |
| 1749 | { | 1802 | { |
| 1750 | definedef = dignorerest; | 1803 | definedef = dignorerest; |
| 1751 | gotone = TRUE; | ||
| 1752 | } | 1804 | } |
| 1753 | goto badone; | 1805 | return (FALSE); |
| 1754 | case ddefineseen: | 1806 | case ddefineseen: |
| 1755 | /* | 1807 | /* |
| 1756 | * Make a tag for any macro. | 1808 | * Make a tag for any macro. |
| 1757 | * This will flub up if there is a newline immediately following | ||
| 1758 | * the macro name. | ||
| 1759 | */ | 1809 | */ |
| 1760 | *is_func = (c == '('); | ||
| 1761 | definedef = dignorerest; | 1810 | definedef = dignorerest; |
| 1762 | gotone = TRUE; | 1811 | *is_func = (c == '('); |
| 1763 | if (!*is_func && !constantypedefs) | 1812 | if (!*is_func && !constantypedefs) |
| 1764 | goto badone; | 1813 | return (FALSE); |
| 1765 | goto goodone; | 1814 | else |
| 1815 | return (TRUE); | ||
| 1766 | case dignorerest: | 1816 | case dignorerest: |
| 1767 | goto badone; | 1817 | return (FALSE); |
| 1768 | default: | 1818 | default: |
| 1769 | error ("internal error: definedef value"); | 1819 | error ("internal error: definedef value"); |
| 1770 | } | 1820 | } |
| 1771 | 1821 | ||
| 1772 | /* | 1822 | /* |
| 1773 | * Skip whitespace and comments after the token. This loop should | 1823 | * Now typedefs |
| 1774 | * also skip C++ comments. | ||
| 1775 | */ | 1824 | */ |
| 1776 | while (1) | 1825 | switch (typdef) |
| 1777 | { | 1826 | { |
| 1778 | /* At whitespace => skip it. */ | 1827 | case tnone: |
| 1779 | if (iswhite (c)) | 1828 | if (toktype == st_C_typedef) |
| 1780 | { | 1829 | { |
| 1781 | c = *lp++; | 1830 | if (typedefs) |
| 1831 | typdef = ttypedseen; | ||
| 1832 | return (FALSE); | ||
| 1782 | } | 1833 | } |
| 1783 | /* At a comment => skip to end of comment. */ | 1834 | break; |
| 1784 | else if (c == '/' && *lp == '*') | 1835 | case ttypedseen: |
| 1785 | { | 1836 | switch (toktype) |
| 1786 | /* If we find a comment, skip it. */ | ||
| 1787 | while (!(c == '*' && *lp == '/')) | ||
| 1788 | { | ||
| 1789 | c = *lp++; | ||
| 1790 | if (c == 0) | ||
| 1791 | { | ||
| 1792 | lp--; | ||
| 1793 | break; | ||
| 1794 | } | ||
| 1795 | } | ||
| 1796 | if (c == '*' && *lp == '/') | ||
| 1797 | { | ||
| 1798 | lp++; /* lp now points past the '/' */ | ||
| 1799 | c = *lp++; /* c is now the --whatever-- after the '/' */ | ||
| 1800 | } | ||
| 1801 | } | ||
| 1802 | else | ||
| 1803 | break; | ||
| 1804 | |||
| 1805 | /* If we arrived at eof or eol, decide which one it is. | ||
| 1806 | If it's eol, advance to the next line. */ | ||
| 1807 | |||
| 1808 | if (c == 0) | ||
| 1809 | { | 1837 | { |
| 1810 | lp--; | 1838 | case st_none: |
| 1839 | case st_C_typespec: | ||
| 1840 | typdef = tend; | ||
| 1841 | break; | ||
| 1842 | case st_C_struct: | ||
| 1843 | case st_C_enum: | ||
| 1811 | break; | 1844 | break; |
| 1812 | } | 1845 | } |
| 1813 | } | 1846 | /* Do not return here, so the structdef stuff has a chance. */ |
| 1814 | |||
| 1815 | /* | ||
| 1816 | * If you have custom token types, or when configuration files can | ||
| 1817 | * define custom token types, this switch will be larger. | ||
| 1818 | */ | ||
| 1819 | switch (toktype) | ||
| 1820 | { | ||
| 1821 | case st_C_typedef: | ||
| 1822 | if (typedefs) | ||
| 1823 | { | ||
| 1824 | tydef = begin; | ||
| 1825 | goto badone; | ||
| 1826 | } | ||
| 1827 | break; | 1847 | break; |
| 1828 | case st_C_typespec: | 1848 | case tend: |
| 1829 | if (tydef == begin || tydef == end) | 1849 | switch (toktype) |
| 1830 | { | 1850 | { |
| 1831 | tydef = end; | 1851 | case st_C_typespec: |
| 1832 | goto badone; | 1852 | case st_C_struct: |
| 1853 | case st_C_enum: | ||
| 1854 | return (FALSE); | ||
| 1833 | } | 1855 | } |
| 1834 | break; | 1856 | return (TRUE); |
| 1835 | } | 1857 | } |
| 1836 | 1858 | ||
| 1837 | /* | 1859 | /* |
| @@ -1843,71 +1865,45 @@ consider_token (c, lpp, tokp, is_func, c_ext, level) | |||
| 1843 | * file is plain C. This is because a struct tag may have the same | 1865 | * file is plain C. This is because a struct tag may have the same |
| 1844 | * name as another tag, and this loses with ctags. | 1866 | * name as another tag, and this loses with ctags. |
| 1845 | * | 1867 | * |
| 1846 | * This if statement deals with the tydef state machine as follows: if | 1868 | * This if statement deals with the typdef state machine as |
| 1847 | * tydef==begin and token is struct/union/class/enum, goto badone. | 1869 | * follows: if typdef==ttypedseen and token is struct/union/class/enum, |
| 1848 | * All the other code here is for the structdef state machine. | 1870 | * return (FALSE). All the other code here is for the structdef |
| 1871 | * state machine. | ||
| 1849 | */ | 1872 | */ |
| 1850 | switch (toktype) | 1873 | switch (toktype) |
| 1851 | { | 1874 | { |
| 1852 | case st_C_struct: | 1875 | case st_C_struct: |
| 1853 | case st_C_enum: | 1876 | case st_C_enum: |
| 1854 | if (tydef == begin | 1877 | if (typdef == ttypedseen |
| 1855 | || (typedefs_and_cplusplus && level == 0 && structdef == snone)) | 1878 | || (typedefs_and_cplusplus && level == 0 && structdef == snone)) |
| 1856 | { | 1879 | { |
| 1857 | structdef = skeyseen; | 1880 | structdef = skeyseen; |
| 1858 | structkey = tokse; | 1881 | structkey = tokse; |
| 1859 | } | 1882 | } |
| 1860 | goto badone; | 1883 | return (FALSE); |
| 1861 | } | 1884 | } |
| 1862 | |||
| 1863 | if (structdef == skeyseen) | 1885 | if (structdef == skeyseen) |
| 1864 | { | 1886 | { |
| 1865 | /* If next char is '{' or (for C++) ':', found a structure tag. */ | 1887 | if (stab_type (structkey) == st_C_struct) |
| 1866 | if (c == '{' || (c_ext && c == ':')) | ||
| 1867 | { | 1888 | { |
| 1868 | /* | 1889 | (void) strncpy (structtag, tokp->p, tokp->len); |
| 1869 | * We should do this slightly differently for straight C: | 1890 | structtag[tokp->len] = '\0'; /* for struct/union/class */ |
| 1870 | * instead of defining `tag', as we now do, we should define | ||
| 1871 | * `struct tag'. (Do this only if the find-tag defaulting is | ||
| 1872 | * done on a sophisticated per-mode basis, so that if the user | ||
| 1873 | * says meta-. anywhere in `struct foo', the default comes out | ||
| 1874 | * `struct foo', not `struct' or `foo'.) This will require | ||
| 1875 | * remembering which keyword (struct/union/class/enum) we saw, as a | ||
| 1876 | * Stab_entry* -- this will also make it possible to merge the | ||
| 1877 | * skeyseen and senumseen states, if we want. | ||
| 1878 | */ | ||
| 1879 | if (stab_type (structkey) == st_C_struct) | ||
| 1880 | { | ||
| 1881 | (void) strncpy (structtag, tokp->p, tokp->len); | ||
| 1882 | structtag[tokp->len] = '\0'; /* for struct/union/class */ | ||
| 1883 | structdef = stagseen; | ||
| 1884 | } | ||
| 1885 | else | ||
| 1886 | { | ||
| 1887 | structtag[0] = '\0'; /* for enum */ | ||
| 1888 | } | ||
| 1889 | *is_func = FALSE; /* not a function */ | ||
| 1890 | goto goodone; | ||
| 1891 | } | 1891 | } |
| 1892 | else | 1892 | else |
| 1893 | { | 1893 | { |
| 1894 | /* Not a definition: reset structdef */ | 1894 | structtag[0] = '\0'; /* for enum (why is it treated differently?) */ |
| 1895 | structdef = snone; | ||
| 1896 | (void) strcpy (structtag, "<error 3>"); | ||
| 1897 | } | 1895 | } |
| 1898 | /* Now what? And how does/should this stuff interact with tydef?? */ | 1896 | structdef = stagseen; |
| 1899 | /* Also maybe reset lp to *lpp for sake of function-finding code. */ | 1897 | return (TRUE); |
| 1900 | } | ||
| 1901 | if (tydef == begin) | ||
| 1902 | { | ||
| 1903 | tydef = end; | ||
| 1904 | goto badone; | ||
| 1905 | } | 1898 | } |
| 1906 | if (tydef == end) | 1899 | |
| 1900 | /* Avoid entering funcdef stuff if typdef is going on. */ | ||
| 1901 | if (typdef != tnone) | ||
| 1907 | { | 1902 | { |
| 1908 | *is_func = 0; | 1903 | definedef = dnone; |
| 1909 | goto goodone; | 1904 | return (FALSE); |
| 1910 | } | 1905 | } |
| 1906 | |||
| 1911 | /* Detect GNUmacs's function-defining macros. */ | 1907 | /* Detect GNUmacs's function-defining macros. */ |
| 1912 | if (definedef == dnone) | 1908 | if (definedef == dnone) |
| 1913 | { | 1909 | { |
| @@ -1917,70 +1913,31 @@ consider_token (c, lpp, tokp, is_func, c_ext, level) | |||
| 1917 | || strneq (tokp->p, "PSEUDO", 6)) | 1913 | || strneq (tokp->p, "PSEUDO", 6)) |
| 1918 | { | 1914 | { |
| 1919 | next_token_is_func = TRUE; | 1915 | next_token_is_func = TRUE; |
| 1920 | goto badone; | 1916 | return (FALSE); |
| 1921 | } | 1917 | } |
| 1922 | else if (strneq (tokp->p, "EXFUN", 5)) | 1918 | if (strneq (tokp->p, "EXFUN", 5)) |
| 1923 | { | 1919 | { |
| 1924 | next_token_is_func = FALSE; | 1920 | next_token_is_func = FALSE; |
| 1925 | goto badone; | 1921 | return (FALSE); |
| 1926 | } | 1922 | } |
| 1927 | } | 1923 | } |
| 1928 | if (next_token_is_func) | 1924 | if (next_token_is_func) |
| 1929 | { | 1925 | { |
| 1930 | next_token_is_func = FALSE; | 1926 | next_token_is_func = FALSE; |
| 1931 | goto goodone; | 1927 | return (TRUE); |
| 1932 | } | ||
| 1933 | if (c != '(') | ||
| 1934 | goto badone; | ||
| 1935 | firsttok = FALSE; | ||
| 1936 | while ((c = *lp++) != ')') | ||
| 1937 | { | ||
| 1938 | if (c == 0) | ||
| 1939 | { | ||
| 1940 | lp--; | ||
| 1941 | break; | ||
| 1942 | } | ||
| 1943 | /* | ||
| 1944 | * This line used to confuse ctags: | ||
| 1945 | * int (*oldhup)(); | ||
| 1946 | * This fixes it. A nonwhite char before the first | ||
| 1947 | * token, other than a / (in case of a comment in there) | ||
| 1948 | * makes this not a declaration. | ||
| 1949 | */ | ||
| 1950 | if (begtoken (c) || c == '/') | ||
| 1951 | firsttok++; | ||
| 1952 | else if (!iswhite (c) && !firsttok) | ||
| 1953 | goto badone; | ||
| 1954 | } | 1928 | } |
| 1955 | while (iswhite (c = *lp++)) | 1929 | |
| 1930 | /* A function? */ | ||
| 1931 | switch (toktype) | ||
| 1956 | { | 1932 | { |
| 1957 | if (c == 0) | 1933 | case st_C_typespec: |
| 1958 | { | 1934 | funcdef == fnone; /* should be useless */ |
| 1959 | lp--; | 1935 | return (FALSE); |
| 1960 | break; | 1936 | default: |
| 1961 | } | 1937 | funcdef = ftagseen; |
| 1938 | *is_func = TRUE; | ||
| 1939 | return (TRUE); | ||
| 1962 | } | 1940 | } |
| 1963 | if (!isgood (c)) | ||
| 1964 | goto badone; | ||
| 1965 | |||
| 1966 | goodone: | ||
| 1967 | *lpp = lp - 1; | ||
| 1968 | return TRUE; | ||
| 1969 | |||
| 1970 | badone: | ||
| 1971 | *lpp = lp - 1; | ||
| 1972 | return FALSE; | ||
| 1973 | } | ||
| 1974 | |||
| 1975 | void | ||
| 1976 | getline (atcookie) | ||
| 1977 | long atcookie; | ||
| 1978 | { | ||
| 1979 | long saveftell = ftell (inf); | ||
| 1980 | |||
| 1981 | (void) fseek (inf, atcookie, 0); | ||
| 1982 | (void) readline (&lb1, inf); | ||
| 1983 | (void) fseek (inf, saveftell, 0); | ||
| 1984 | } | 1941 | } |
| 1985 | 1942 | ||
| 1986 | /* Fortran parsing */ | 1943 | /* Fortran parsing */ |