comparison lib-src/etags.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents de805c49cfc1
children
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
1 /* Tags file maker to go with GNU Emacs 1 /* Tags file maker to go with GNU Emacs
2 Copyright (C) 1984, 87, 88, 89, 93, 94, 95, 98, 99 2 Copyright (C) 1984, 87, 88, 89, 93, 94, 95, 98
3 Free Software Foundation, Inc. and Ken Arnold 3 Free Software Foundation, Inc. and Ken Arnold
4 4
5 This file is not considered part of GNU Emacs. 5 This file is not considered part of GNU Emacs.
6 6
7 This program is free software; you can redistribute it and/or modify 7 This program is free software; you can redistribute it and/or modify
26 * Gnu Emacs TAGS format and modifications by RMS? 26 * Gnu Emacs TAGS format and modifications by RMS?
27 * Sam Kendall added C++. 27 * Sam Kendall added C++.
28 * Francesco Potorti` reorganised C and C++ based on work by Joe Wells. 28 * Francesco Potorti` reorganised C and C++ based on work by Joe Wells.
29 * Regexp tags by Tom Tromey. 29 * Regexp tags by Tom Tromey.
30 * 30 *
31 * Francesco Potorti` (pot@gnu.org) is the current maintainer. 31 * Francesco Potorti` (F.Potorti@cnuce.cnr.it) is the current maintainer.
32 */ 32 */
33 33
34 char pot_etags_version[] = "@(#) pot revision number is 13.44"; 34 char pot_etags_version[] = "@(#) pot revision number is 13.7";
35 35
36 #define TRUE 1 36 #define TRUE 1
37 #define FALSE 0 37 #define FALSE 0
38 38
39 #ifndef DEBUG 39 #ifndef DEBUG
40 # define DEBUG FALSE 40 # define DEBUG FALSE
41 #endif 41 #endif
42 42
43 #if defined(__STDC__) && (__STDC__ || defined(__SUNPRO_C)) 43 #ifdef MSDOS
44 # define P_(proto) proto 44 # include <fcntl.h>
45 #else 45 # include <sys/param.h>
46 # define P_(proto) () 46 # include <io.h>
47 #endif 47 # ifndef HAVE_CONFIG_H
48 # define DOS_NT
49 # include <sys/config.h>
50 # endif
51 #endif /* MSDOS */
52
53 #ifdef WINDOWSNT
54 # include <stdlib.h>
55 # include <fcntl.h>
56 # include <string.h>
57 # include <io.h>
58 # define MAXPATHLEN _MAX_PATH
59 # ifdef HAVE_CONFIG_H
60 # undef HAVE_NTGUI
61 # else
62 # define DOS_NT
63 # define HAVE_GETCWD
64 # endif /* not HAVE_CONFIG_H */
65 #endif /* WINDOWSNT */
48 66
49 #ifdef HAVE_CONFIG_H 67 #ifdef HAVE_CONFIG_H
50 # include <config.h> 68 # include <config.h>
51 /* On some systems, Emacs defines static as nothing for the sake 69 /* On some systems, Emacs defines static as nothing for the sake
52 of unexec. We don't want that here since we don't use unexec. */ 70 of unexec. We don't want that here since we don't use unexec. */
53 # undef static 71 # undef static
54 # define ETAGS_REGEXPS /* use the regexp features */ 72 # define ETAGS_REGEXPS /* use the regexp features */
55 # define LONG_OPTIONS /* accept long options */ 73 # define LONG_OPTIONS /* accept long options */
56 #endif /* HAVE_CONFIG_H */ 74 #endif /* HAVE_CONFIG_H */
57 75
58 #ifndef _GNU_SOURCE 76 #if !defined (WINDOWSNT) && defined (STDC_HEADERS)
59 # define _GNU_SOURCE 1 /* enables some compiler checks on GNU */ 77 #include <stdlib.h>
78 #include <string.h>
60 #endif 79 #endif
61
62 #ifdef WIN32_NATIVE
63 # include <stdlib.h>
64 # include <fcntl.h>
65 # include <string.h>
66 # include <direct.h>
67 # include <io.h>
68 # define MAXPATHLEN _MAX_PATH
69 # ifndef HAVE_GETCWD
70 # define HAVE_GETCWD
71 # endif /* undef HAVE_GETCWD */
72 #else /* !WIN32_NATIVE */
73 # ifdef STDC_HEADERS
74 # include <stdlib.h>
75 # include <string.h>
76 # else
77 extern char *getenv ();
78 # endif
79 #endif /* !WIN32_NATIVE */
80 80
81 #ifdef HAVE_UNISTD_H 81 #ifdef HAVE_UNISTD_H
82 # include <unistd.h> 82 # include <unistd.h>
83 #else 83 #else
84 # if defined (HAVE_GETCWD) && !defined (WIN32_NATIVE) 84 # ifdef HAVE_GETCWD
85 extern char *getcwd (char *buf, size_t size); 85 extern char *getcwd ();
86 # endif 86 # endif
87 #endif /* HAVE_UNISTD_H */ 87 #endif /* HAVE_UNISTD_H */
88 88
89 #include <stdio.h> 89 #include <stdio.h>
90 #include <ctype.h> 90 #include <ctype.h>
169 # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type))) 169 # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type)))
170 #endif 170 #endif
171 171
172 typedef int bool; 172 typedef int bool;
173 173
174 typedef void Lang_function P_((FILE *)); 174 typedef void Lang_function ();
175 175
176 typedef struct 176 typedef struct
177 { 177 {
178 char *suffix; 178 char *suffix;
179 int sufflen;
179 char *command; /* Takes one arg and decompresses to stdout */ 180 char *command; /* Takes one arg and decompresses to stdout */
180 } compressor; 181 } compressor;
181 182
182 typedef struct 183 typedef struct
183 { 184 {
184 char *name; 185 char *name;
185 Lang_function *function; 186 Lang_function *function;
186 char **suffixes; 187 char **suffixes;
187 char **interpreters; 188 char **interpreters;
188 } language; 189 } language;
190
191 extern char *getenv ();
192
193 /* Many compilers barf on this:
194 Lang_function Asm_labels;
195 so let's write it this way */
196 void Asm_labels ();
197 void C_entries ();
198 void default_C_entries ();
199 void plain_C_entries ();
200 void Cjava_entries ();
201 void Cobol_paragraphs ();
202 void Cplusplus_entries ();
203 void Cstar_entries ();
204 void Erlang_functions ();
205 void Fortran_functions ();
206 void Yacc_entries ();
207 void Lisp_functions ();
208 void Pascal_functions ();
209 void Perl_functions ();
210 void Postscript_functions ();
211 void Prolog_functions ();
212 void Python_functions ();
213 void Scheme_functions ();
214 void TeX_functions ();
215 void just_read_file ();
216
217 compressor *get_compressor_from_suffix ();
218 language *get_language_from_name ();
219 language *get_language_from_interpreter ();
220 language *get_language_from_suffix ();
221 int total_size_of_entries ();
222 long readline (), readline_internal ();
223 #ifdef ETAGS_REGEXPS
224 void analyse_regex ();
225 void add_regex ();
226 void free_patterns ();
227 #endif /* ETAGS_REGEXPS */
228 void error ();
229 void suggest_asking_for_help ();
230 void fatal (), pfatal ();
231 void add_node ();
232
233 void init ();
234 void initbuffer ();
235 void find_entries ();
236 void free_tree ();
237 void pfnote (), new_pfnote ();
238 void process_file ();
239 void put_entries ();
240 void takeprec ();
241
242 char *concat ();
243 char *skip_spaces (), *skip_non_spaces ();
244 char *savenstr (), *savestr ();
245 char *etags_strchr (), *etags_strrchr ();
246 char *etags_getcwd ();
247 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
248 bool filename_is_absolute ();
249 void canonicalize_filename ();
250 void grow_linebuffer ();
251 long *xmalloc (), *xrealloc ();
252
253
254 char searchar = '/'; /* use /.../ searches */
255
256 char *tagfile; /* output file */
257 char *progname; /* name this program was invoked with */
258 char *cwd; /* current working directory */
259 char *tagfiledir; /* directory of tagfile */
260 FILE *tagf; /* ioptr for tags file */
261
262 char *curfile; /* current input file name */
263 language *curlang; /* current language */
264
265 int lineno; /* line number of current line */
266 long charno; /* current character number */
267 long linecharno; /* charno of start of current line */
268 char *dbp; /* pointer to start of current tag */
189 269
190 typedef struct node_st 270 typedef struct node_st
191 { /* sorting structure */ 271 { /* sorting structure */
192 char *name; /* function or type name */ 272 char *name; /* function or type name */
193 char *file; /* file name */ 273 char *file; /* file name */
197 long cno; /* character number line starts on */ 277 long cno; /* character number line starts on */
198 char *pat; /* search pattern */ 278 char *pat; /* search pattern */
199 struct node_st *left, *right; /* left and right sons */ 279 struct node_st *left, *right; /* left and right sons */
200 } node; 280 } node;
201 281
282 node *head; /* the head of the binary tree of tags */
283
202 /* 284 /*
203 * A `linebuffer' is a structure which holds a line of text. 285 * A `linebuffer' is a structure which holds a line of text.
204 * `readline_internal' reads a line from a stream into a linebuffer 286 * `readline_internal' reads a line from a stream into a linebuffer
205 * and works regardless of the length of the line. 287 * and works regardless of the length of the line.
206 * SIZE is the size of BUFFER, LEN is the length of the string in 288 * SIZE is the size of BUFFER, LEN is the length of the string in
211 long size; 293 long size;
212 int len; 294 int len;
213 char *buffer; 295 char *buffer;
214 } linebuffer; 296 } linebuffer;
215 297
216 /* Many compilers barf on this:
217 Lang_function Ada_funcs;
218 so let's write it this way */
219 static void Ada_funcs P_((FILE *));
220 static void Asm_labels P_((FILE *));
221 static void C_entries P_((int c_ext, FILE *));
222 static void default_C_entries P_((FILE *));
223 static void plain_C_entries P_((FILE *));
224 static void Cjava_entries P_((FILE *));
225 static void Cobol_paragraphs P_((FILE *));
226 static void Cplusplus_entries P_((FILE *));
227 static void Cstar_entries P_((FILE *));
228 static void Erlang_functions P_((FILE *));
229 static void Fortran_functions P_((FILE *));
230 static void Yacc_entries P_((FILE *));
231 static void Lisp_functions P_((FILE *));
232 static void Pascal_functions P_((FILE *));
233 static void Perl_functions P_((FILE *));
234 static void Postscript_functions P_((FILE *));
235 static void Prolog_functions P_((FILE *));
236 static void Python_functions P_((FILE *));
237 static void Scheme_functions P_((FILE *));
238 static void TeX_functions P_((FILE *));
239 static void just_read_file P_((FILE *));
240
241 static void print_language_names P_((void));
242 static void print_version P_((void));
243 static void print_help P_((void));
244 int main P_((int, char **));
245 static int number_len P_((long));
246
247 static compressor *get_compressor_from_suffix P_((char *, char **));
248 static language *get_language_from_name P_((char *));
249 static language *get_language_from_interpreter P_((char *));
250 static language *get_language_from_suffix P_((char *));
251 static int total_size_of_entries P_((node *));
252 static long readline P_((linebuffer *, FILE *));
253 static long readline_internal P_((linebuffer *, FILE *));
254 static void get_tag P_((char *));
255
256 #ifdef ETAGS_REGEXPS
257 static void analyse_regex P_((char *, bool));
258 static void add_regex P_((char *, bool, language *));
259 static void free_patterns P_((void));
260 #endif /* ETAGS_REGEXPS */
261 static void error P_((const char *, const char *));
262 static void suggest_asking_for_help P_((void));
263 static void fatal P_((char *, char *));
264 static void pfatal P_((char *));
265 static void add_node P_((node *, node **));
266
267 static void init P_((void));
268 static void initbuffer P_((linebuffer *));
269 static void find_entries P_((char *, FILE *));
270 static void free_tree P_((node *));
271 static void pfnote P_((char *, bool, char *, int, int, long));
272 static void new_pfnote P_((char *, int, bool, char *, int, int, long));
273 static void process_file P_((char *));
274 static void put_entries P_((node *));
275 static void takeprec P_((void));
276
277 static char *concat P_((char *, char *, char *));
278 static char *skip_spaces P_((char *));
279 static char *skip_non_spaces P_((char *));
280 static char *savenstr P_((char *, int));
281 static char *savestr P_((char *));
282 static char *etags_strchr P_((const char *, int));
283 static char *etags_strrchr P_((const char *, int));
284 static char *etags_getcwd P_((void));
285 static char *relative_filename P_((char *, char *));
286 static char *absolute_filename P_((char *, char *));
287 static char *absolute_dirname P_((char *, char *));
288 static bool filename_is_absolute P_((char *f));
289 static void canonicalize_filename P_((char *));
290 static void grow_linebuffer P_((linebuffer *, int));
291 static long *xmalloc P_((unsigned int));
292 static long *xrealloc P_((char *, unsigned int));
293
294
295 char searchar = '/'; /* use /.../ searches */
296
297 char *tagfile; /* output file */
298 char *progname; /* name this program was invoked with */
299 char *cwd; /* current working directory */
300 char *tagfiledir; /* directory of tagfile */
301 FILE *tagf; /* ioptr for tags file */
302
303 char *curfile; /* current input file name */
304 language *curlang; /* current language */
305
306 int lineno; /* line number of current line */
307 long charno; /* current character number */
308 long linecharno; /* charno of start of current line */
309 char *dbp; /* pointer to start of current tag */
310
311 node *head; /* the head of the binary tree of tags */
312
313 linebuffer lb; /* the current line */ 298 linebuffer lb; /* the current line */
314 linebuffer token_name; /* used by C_entries as a temporary area */ 299 linebuffer token_name; /* used by C_entries as a temporary area */
315 struct 300 struct
316 { 301 {
317 long linepos; 302 long linepos;
320 305
321 /* boolean "functions" (see init) */ 306 /* boolean "functions" (see init) */
322 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS]; 307 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
323 char 308 char
324 /* white chars */ 309 /* white chars */
325 *white = " \f\t\n\r\v", 310 *white = " \f\t\n\r",
326 /* not in a name */ 311 /* not in a name */
327 *nonam = " \f\t\n\r(=,[;", 312 *nonam = " \f\t\n\r(=,[;",
328 /* token ending chars */ 313 /* token ending chars */
329 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?", 314 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
330 /* token starting chars */ 315 /* token starting chars */
332 /* valid in-token chars */ 317 /* valid in-token chars */
333 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789"; 318 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
334 319
335 bool append_to_tagfile; /* -a: append to tags */ 320 bool append_to_tagfile; /* -a: append to tags */
336 /* The following four default to TRUE for etags, but to FALSE for ctags. */ 321 /* The following four default to TRUE for etags, but to FALSE for ctags. */
337 bool typedefs; /* -t: create tags for C and Ada typedefs */ 322 bool typedefs; /* -t: create tags for C typedefs */
338 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */ 323 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
339 /* 0 struct/enum/union decls, and C++ */ 324 /* 0 struct/enum/union decls, and C++ */
340 /* member functions. */ 325 /* member functions. */
341 bool constantypedefs; /* -d: create tags for C #define, enum */ 326 bool constantypedefs; /* -d: create tags for C #define, enum */
342 /* constants and variables. */ 327 /* constants and variables. */
343 /* -D: opposite of -d. Default under ctags. */ 328 /* -D: opposite of -d. Default under ctags. */
344 bool declarations; /* --declarations: tag them and extern in C&Co*/
345 bool globals; /* create tags for global variables */ 329 bool globals; /* create tags for global variables */
346 bool members; /* create tags for C member variables */ 330 bool members; /* create tags for C member variables */
347 bool update; /* -u: update tags */ 331 bool update; /* -u: update tags */
348 bool vgrind_style; /* -v: create vgrind style index output */ 332 bool vgrind_style; /* -v: create vgrind style index output */
349 bool no_warnings; /* -w: suppress warnings */ 333 bool no_warnings; /* -w: suppress warnings */
350 bool cxref_style; /* -x: create cxref style output */ 334 bool cxref_style; /* -x: create cxref style output */
351 bool cplusplus; /* .[hc] means C++, not C */ 335 bool cplusplus; /* .[hc] means C++, not C */
352 bool noindentypedefs; /* -I: ignore indentation in C */ 336 bool noindentypedefs; /* -I: ignore indentation in C */
353 bool packages_only; /* --packages-only: in Ada, only tag packages*/
354 337
355 #ifdef LONG_OPTIONS 338 #ifdef LONG_OPTIONS
356 struct option longopts[] = 339 struct option longopts[] =
357 { 340 {
358 { "packages-only", no_argument, &packages_only, TRUE }, 341 { "append", no_argument, NULL, 'a' },
359 { "append", no_argument, NULL, 'a' }, 342 { "backward-search", no_argument, NULL, 'B' },
360 { "backward-search", no_argument, NULL, 'B' }, 343 { "c++", no_argument, NULL, 'C' },
361 { "c++", no_argument, NULL, 'C' }, 344 { "cxref", no_argument, NULL, 'x' },
362 { "cxref", no_argument, NULL, 'x' }, 345 { "defines", no_argument, NULL, 'd' },
363 { "defines", no_argument, NULL, 'd' }, 346 { "no-defines", no_argument, NULL, 'D' },
364 { "declarations", no_argument, &declarations, TRUE }, 347 { "globals", no_argument, &globals, TRUE },
365 { "no-defines", no_argument, NULL, 'D' }, 348 { "no-globals", no_argument, &globals, FALSE },
366 { "globals", no_argument, &globals, TRUE }, 349 { "help", no_argument, NULL, 'h' },
367 { "no-globals", no_argument, &globals, FALSE }, 350 { "help", no_argument, NULL, 'H' },
368 { "help", no_argument, NULL, 'h' }, 351 { "ignore-indentation", no_argument, NULL, 'I' },
369 { "help", no_argument, NULL, 'H' }, 352 { "include", required_argument, NULL, 'i' },
370 { "ignore-indentation", no_argument, NULL, 'I' }, 353 { "language", required_argument, NULL, 'l' },
371 { "include", required_argument, NULL, 'i' }, 354 { "members", no_argument, &members, TRUE },
372 { "language", required_argument, NULL, 'l' }, 355 { "no-members", no_argument, &members, FALSE },
373 { "members", no_argument, &members, TRUE }, 356 { "no-warn", no_argument, NULL, 'w' },
374 { "no-members", no_argument, &members, FALSE }, 357 { "output", required_argument, NULL, 'o' },
375 { "no-warn", no_argument, NULL, 'w' }, 358 #ifdef ETAGS_REGEXPS
376 { "output", required_argument, NULL, 'o' }, 359 { "regex", required_argument, NULL, 'r' },
377 #ifdef ETAGS_REGEXPS 360 { "no-regex", no_argument, NULL, 'R' },
378 { "regex", required_argument, NULL, 'r' }, 361 #endif /* ETAGS_REGEXPS */
379 { "no-regex", no_argument, NULL, 'R' }, 362 { "typedefs", no_argument, NULL, 't' },
380 { "ignore-case-regex", required_argument, NULL, 'c' }, 363 { "typedefs-and-c++", no_argument, NULL, 'T' },
381 #endif /* ETAGS_REGEXPS */ 364 { "update", no_argument, NULL, 'u' },
382 { "typedefs", no_argument, NULL, 't' }, 365 { "version", no_argument, NULL, 'V' },
383 { "typedefs-and-c++", no_argument, NULL, 'T' }, 366 { "vgrind", no_argument, NULL, 'v' },
384 { "update", no_argument, NULL, 'u' }, 367 { 0 }
385 { "version", no_argument, NULL, 'V' },
386 { "vgrind", no_argument, NULL, 'v' },
387 { NULL }
388 }; 368 };
389 #endif /* LONG_OPTIONS */ 369 #endif /* LONG_OPTIONS */
390 370
391 #ifdef ETAGS_REGEXPS 371 #ifdef ETAGS_REGEXPS
392 /* Structure defining a regular expression. Elements are 372 /* Structure defining a regular expression. Elements are
400 struct re_registers regs; 380 struct re_registers regs;
401 char *name_pattern; 381 char *name_pattern;
402 bool error_signaled; 382 bool error_signaled;
403 } pattern; 383 } pattern;
404 384
405 /* List of all regexps. */ 385 /* Array of all regexps. */
406 pattern *p_head = NULL; 386 pattern *p_head = NULL;
407
408 /* How many characters in the character set. (From regex.c.) */
409 #define CHAR_SET_SIZE 256
410 /* Translation table for case-insensitive matching. */
411 char lc_trans[CHAR_SET_SIZE];
412 #endif /* ETAGS_REGEXPS */ 387 #endif /* ETAGS_REGEXPS */
413 388
414 compressor compressors[] = 389 compressor compressors[] =
415 { 390 {
416 { "z", "gzip -d -c"}, 391 { "z", 1, "gzip -d -c"},
417 { "Z", "gzip -d -c"}, 392 { "Z", 1, "gzip -d -c"},
418 { "gz", "gzip -d -c"}, 393 { "gz", 2, "gzip -d -c"},
419 { "GZ", "gzip -d -c"}, 394 { "GZ", 2, "gzip -d -c"},
420 { "bz2", "bzip2 -d -c" }, 395 { "bz2", 3, "bzip2 -d -c" },
421 { NULL } 396 { NULL }
422 }; 397 };
423 398
424 /* 399 /*
425 * Language stuff. 400 * Language stuff.
426 */ 401 */
427 402
428 /* Non-NULL if language fixed. */ 403 /* Non-NULL if language fixed. */
429 language *forced_lang = NULL; 404 language *forced_lang = NULL;
430
431 /* Ada code */
432 char *Ada_suffixes [] =
433 { "ads", "adb", "ada", NULL };
434 405
435 /* Assembly code */ 406 /* Assembly code */
436 char *Asm_suffixes [] = { "a", /* Unix assembler */ 407 char *Asm_suffixes [] = { "a", /* Unix assembler */
437 "asm", /* Microcontroller assembly */ 408 "asm", /* Microcontroller assembly */
438 "def", /* BSO/Tasking definition includes */ 409 "def", /* BSO/Tasking definition includes */
486 "m", /* Objective C file */ 457 "m", /* Objective C file */
487 "lm", /* Objective lex file */ 458 "lm", /* Objective lex file */
488 NULL }; 459 NULL };
489 460
490 char *Postscript_suffixes [] = 461 char *Postscript_suffixes [] =
491 { "ps", "psw", NULL }; /* .psw is for PSWrap */ 462 { "ps", NULL };
492 463
493 char *Prolog_suffixes [] = 464 char *Prolog_suffixes [] =
494 { "prolog", NULL }; 465 { "prolog", NULL };
495 466
496 char *Python_suffixes [] = 467 char *Python_suffixes [] =
513 * name. I just didn't. 484 * name. I just didn't.
514 */ 485 */
515 486
516 language lang_names [] = 487 language lang_names [] =
517 { 488 {
518 { "ada", Ada_funcs, Ada_suffixes, NULL },
519 { "asm", Asm_labels, Asm_suffixes, NULL }, 489 { "asm", Asm_labels, Asm_suffixes, NULL },
520 { "c", default_C_entries, default_C_suffixes, NULL }, 490 { "c", default_C_entries, default_C_suffixes, NULL },
521 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL }, 491 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
522 { "c*", Cstar_entries, Cstar_suffixes, NULL }, 492 { "c*", Cstar_entries, Cstar_suffixes, NULL },
523 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL }, 493 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL },
537 { "auto", NULL }, /* default guessing scheme */ 507 { "auto", NULL }, /* default guessing scheme */
538 { "none", just_read_file }, /* regexp matching only */ 508 { "none", just_read_file }, /* regexp matching only */
539 { NULL, NULL } /* end of list */ 509 { NULL, NULL } /* end of list */
540 }; 510 };
541 511
542 static void 512 void
543 print_language_names () 513 print_language_names ()
544 { 514 {
545 language *lang; 515 language *lang;
546 char **ext; 516 char **ext;
547 517
562 followed by the name of an interpreter. If no such sequence is found,\n\ 532 followed by the name of an interpreter. If no such sequence is found,\n\
563 Fortran is tried first; if no tags are found, C is tried next.\n\ 533 Fortran is tried first; if no tags are found, C is tried next.\n\
564 Compressed files are supported using gzip and bzip2."); 534 Compressed files are supported using gzip and bzip2.");
565 } 535 }
566 536
567 #ifndef EMACS_NAME 537 #ifndef VERSION
568 # define EMACS_NAME "GNU Emacs" 538 # define VERSION "20"
569 #endif 539 #endif
570 #ifndef VERSION 540 void
571 # define VERSION "21"
572 #endif
573 static void
574 print_version () 541 print_version ()
575 { 542 {
576 printf ("%s (%s %s)\n", (CTAGS) ? "ctags" : "etags", EMACS_NAME, VERSION); 543 printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
577 puts ("Copyright (C) 1999 Free Software Foundation, Inc. and Ken Arnold"); 544 puts ("Copyright (C) 1996 Free Software Foundation, Inc. and Ken Arnold");
578 puts ("This program is distributed under the same terms as Emacs"); 545 puts ("This program is distributed under the same terms as Emacs");
579 546
580 exit (GOOD); 547 exit (GOOD);
581 } 548 }
582 549
583 static void 550 void
584 print_help () 551 print_help ()
585 { 552 {
586 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\ 553 printf ("Usage: %s [options] [[regex-option ...] file-name] ...\n\
587 \n\ 554 \n\
588 These are the options accepted by %s.\n", progname, progname); 555 These are the options accepted by %s.\n", progname, progname);
599 puts ("\n"); 566 puts ("\n");
600 567
601 puts ("-a, --append\n\ 568 puts ("-a, --append\n\
602 Append tag entries to existing tags file."); 569 Append tag entries to existing tags file.");
603 570
604 puts ("--packages-only\n\
605 For Ada files, only generate tags for packages .");
606
607 if (CTAGS) 571 if (CTAGS)
608 puts ("-B, --backward-search\n\ 572 puts ("-B, --backward-search\n\
609 Write the search commands for the tag entries using '?', the\n\ 573 Write the search commands for the tag entries using '?', the\n\
610 backward-search command instead of '/', the forward-search command."); 574 backward-search command instead of '/', the forward-search command.");
611 575
612 puts ("-C, --c++\n\ 576 puts ("-C, --c++\n\
613 Treat files whose name suffix defaults to C language as C++ files."); 577 Treat files whose name suffix defaults to C language as C++ files.");
614
615 puts ("--declarations\n\
616 In C and derived languages, create tags for function declarations,");
617 if (CTAGS)
618 puts ("\tand create tags for extern variables if --globals is used.");
619 else
620 puts
621 ("\tand create tags for extern variables unless --no-globals is used.");
622 578
623 if (CTAGS) 579 if (CTAGS)
624 puts ("-d, --defines\n\ 580 puts ("-d, --defines\n\
625 Create tag entries for C #define constants and enum constants, too."); 581 Create tag entries for C #define constants and enum constants, too.");
626 else 582 else
649 puts ("--members\n\ 605 puts ("--members\n\
650 Create tag entries for member variables in C and derived languages."); 606 Create tag entries for member variables in C and derived languages.");
651 607
652 #ifdef ETAGS_REGEXPS 608 #ifdef ETAGS_REGEXPS
653 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\ 609 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
654 Make a tag for each line matching pattern REGEXP in the following\n\ 610 Make a tag for each line matching pattern REGEXP in the\n\
655 files. {LANGUAGE}/REGEXP/ uses REGEXP for LANGUAGE files only.\n\ 611 following files. regexfile is a file containing one REGEXP\n\
656 regexfile is a file containing one REGEXP per line.\n\ 612 per line. REGEXP is anchored (as if preceded by ^).\n\
657 REGEXP is anchored (as if preceded by ^).\n\ 613 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
658 The form /REGEXP/NAME/ creates a named tag.\n\ 614 named tags can be created with:\n\
659 For example Tcl named tags can be created with:\n\
660 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/."); 615 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
661 puts ("-c /REGEXP/, --ignore-case-regex=/REGEXP/ or --ignore-case-regex=@regexfile\n\
662 Like -r, --regex but ignore case when matching expressions.");
663 puts ("-R, --no-regex\n\ 616 puts ("-R, --no-regex\n\
664 Don't create tags from regexps for the following files."); 617 Don't create tags from regexps for the following files.");
665 #endif /* ETAGS_REGEXPS */ 618 #endif /* ETAGS_REGEXPS */
666 puts ("-o FILE, --output=FILE\n\ 619 puts ("-o FILE, --output=FILE\n\
667 Write the tags to FILE."); 620 Write the tags to FILE.");
672 definition in C and C++."); 625 definition in C and C++.");
673 626
674 if (CTAGS) 627 if (CTAGS)
675 { 628 {
676 puts ("-t, --typedefs\n\ 629 puts ("-t, --typedefs\n\
677 Generate tag entries for C and Ada typedefs."); 630 Generate tag entries for C typedefs.");
678 puts ("-T, --typedefs-and-c++\n\ 631 puts ("-T, --typedefs-and-c++\n\
679 Generate tag entries for C typedefs, C struct/enum/union tags,\n\ 632 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
680 and C++ member functions."); 633 and C++ member functions.");
681 puts ("-u, --update\n\ 634 puts ("-u, --update\n\
682 Update the tag entries for the given files, leaving tag\n\ 635 Update the tag entries for the given files, leaving tag\n\
705 Print this help message."); 658 Print this help message.");
706 659
707 print_language_names (); 660 print_language_names ();
708 661
709 puts (""); 662 puts ("");
710 puts ("Report bugs to bug-gnu-emacs@gnu.org"); 663 puts ("Report bugs to bug-gnu-emacs@prep.ai.mit.edu");
711 664
712 exit (GOOD); 665 exit (GOOD);
713 } 666 }
714 667
715 668
716 enum argument_type 669 enum argument_type
717 { 670 {
718 at_language, 671 at_language,
719 at_regexp, 672 at_regexp,
720 at_filename, 673 at_filename
721 at_icregexp
722 }; 674 };
723 675
724 /* This structure helps us allow mixing of --lang and file names. */ 676 /* This structure helps us allow mixing of --lang and file names. */
725 typedef struct 677 typedef struct
726 { 678 {
759 */ 711 */
760 712
761 #include <rmsdef.h> 713 #include <rmsdef.h>
762 #include <descrip.h> 714 #include <descrip.h>
763 #define OUTSIZE MAX_FILE_SPEC_LEN 715 #define OUTSIZE MAX_FILE_SPEC_LEN
764 static short 716 short
765 fn_exp (out, in) 717 fn_exp (out, in)
766 vspec *out; 718 vspec *out;
767 char *in; 719 char *in;
768 { 720 {
769 static long context = 0; 721 static long context = 0;
804 756
805 /* 757 /*
806 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the 758 v1.01 nmm 19-Aug-85 gfnames - return in successive calls the
807 name of each file specified by the provided arg expanding wildcards. 759 name of each file specified by the provided arg expanding wildcards.
808 */ 760 */
809 static char * 761 char *
810 gfnames (arg, p_error) 762 gfnames (arg, p_error)
811 char *arg; 763 char *arg;
812 bool *p_error; 764 bool *p_error;
813 { 765 {
814 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"}; 766 static vspec filename = {MAX_FILE_SPEC_LEN, "\0"};
868 linebuffer filename_lb; 820 linebuffer filename_lb;
869 #ifdef VMS 821 #ifdef VMS
870 bool got_err; 822 bool got_err;
871 #endif 823 #endif
872 824
873 #ifdef WIN32_NATIVE 825 #ifdef DOS_NT
874 _fmode = O_BINARY; /* all of files are treated as binary files */ 826 _fmode = O_BINARY; /* all of files are treated as binary files */
875 #endif /* WIN32_NATIVE */ 827 #endif /* DOS_NT */
876 828
877 progname = argv[0]; 829 progname = argv[0];
878 nincluded_files = 0; 830 nincluded_files = 0;
879 included_files = xnew (argc, char *); 831 included_files = xnew (argc, char *);
880 current_arg = 0; 832 current_arg = 0;
885 argbuffer = xnew (argc, argument); 837 argbuffer = xnew (argc, argument);
886 838
887 #ifdef ETAGS_REGEXPS 839 #ifdef ETAGS_REGEXPS
888 /* Set syntax for regular expression routines. */ 840 /* Set syntax for regular expression routines. */
889 re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS); 841 re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS);
890 /* Translation table for case-insensitive search. */
891 for (i = 0; i < CHAR_SET_SIZE; i++)
892 lc_trans[i] = lowcase (i);
893 #endif /* ETAGS_REGEXPS */ 842 #endif /* ETAGS_REGEXPS */
894 843
895 /* 844 /*
896 * If etags, always find typedefs and structure tags. Why not? 845 * If etags, always find typedefs and structure tags. Why not?
897 * Also default is to find macro constants, enum constants and 846 * Also default is to find macro constants, enum constants and
898 * global variables. 847 * global variables.
899 */ 848 */
900 if (!CTAGS) 849 if (!CTAGS)
901 { 850 {
902 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE; 851 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
903 globals = TRUE; 852 globals = TRUE;
908 { 857 {
909 int opt; 858 int opt;
910 char *optstring; 859 char *optstring;
911 860
912 #ifdef ETAGS_REGEXPS 861 #ifdef ETAGS_REGEXPS
913 optstring = "-aCdDf:Il:o:r:c:RStTi:BuvxwVhH"; 862 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH";
914 #else 863 #else
915 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH"; 864 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
916 #endif /* ETAGS_REGEXPS */ 865 #endif /* ETAGS_REGEXPS */
917 866
918 #ifndef LONG_OPTIONS 867 #ifndef LONG_OPTIONS
945 case 'D': constantypedefs = FALSE; break; 894 case 'D': constantypedefs = FALSE; break;
946 case 'f': /* for compatibility with old makefiles */ 895 case 'f': /* for compatibility with old makefiles */
947 case 'o': 896 case 'o':
948 if (tagfile) 897 if (tagfile)
949 { 898 {
950 error ("-o option may only be given once.", (char *)NULL); 899 error ("-%c option may only be given once.", opt);
951 suggest_asking_for_help (); 900 suggest_asking_for_help ();
952 } 901 }
953 tagfile = optarg; 902 tagfile = optarg;
954 break; 903 break;
955 case 'I': 904 case 'I':
974 ++current_arg; 923 ++current_arg;
975 break; 924 break;
976 case 'R': 925 case 'R':
977 argbuffer[current_arg].arg_type = at_regexp; 926 argbuffer[current_arg].arg_type = at_regexp;
978 argbuffer[current_arg].what = NULL; 927 argbuffer[current_arg].what = NULL;
979 ++current_arg;
980 break;
981 case 'c':
982 argbuffer[current_arg].arg_type = at_icregexp;
983 argbuffer[current_arg].what = optarg;
984 ++current_arg; 928 ++current_arg;
985 break; 929 break;
986 #endif /* ETAGS_REGEXPS */ 930 #endif /* ETAGS_REGEXPS */
987 case 'V': 931 case 'V':
988 print_version (); 932 print_version ();
1023 ++file_count; 967 ++file_count;
1024 } 968 }
1025 969
1026 if (nincluded_files == 0 && file_count == 0) 970 if (nincluded_files == 0 && file_count == 0)
1027 { 971 {
1028 error ("no input files specified.", (char *)NULL); 972 error ("no input files specified.", 0);
1029 suggest_asking_for_help (); 973 suggest_asking_for_help ();
1030 } 974 }
1031 975
1032 if (tagfile == NULL) 976 if (tagfile == NULL)
1033 tagfile = CTAGS ? "tags" : "TAGS"; 977 tagfile = CTAGS ? "tags" : "TAGS";
1054 if (!CTAGS) 998 if (!CTAGS)
1055 { 999 {
1056 if (streq (tagfile, "-")) 1000 if (streq (tagfile, "-"))
1057 { 1001 {
1058 tagf = stdout; 1002 tagf = stdout;
1059 #ifdef WIN32_NATIVE 1003 #ifdef DOS_NT
1060 /* Switch redirected `stdout' to binary mode (setting `_fmode' 1004 /* Switch redirected `stdout' to binary mode (setting `_fmode'
1061 doesn't take effect until after `stdout' is already open). */ 1005 doesn't take effect until after `stdout' is already open). */
1062 if (!isatty (fileno (stdout))) 1006 if (!isatty (fileno (stdout)))
1063 setmode (fileno (stdout), O_BINARY); 1007 setmode (fileno (stdout), O_BINARY);
1064 #endif /* WIN32_NATIVE */ 1008 #endif /* DOS_NT */
1065 } 1009 }
1066 else 1010 else
1067 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w"); 1011 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1068 if (tagf == NULL) 1012 if (tagf == NULL)
1069 pfatal (tagfile); 1013 pfatal (tagfile);
1079 case at_language: 1023 case at_language:
1080 forced_lang = argbuffer[i].lang; 1024 forced_lang = argbuffer[i].lang;
1081 break; 1025 break;
1082 #ifdef ETAGS_REGEXPS 1026 #ifdef ETAGS_REGEXPS
1083 case at_regexp: 1027 case at_regexp:
1084 analyse_regex (argbuffer[i].what, FALSE); 1028 analyse_regex (argbuffer[i].what);
1085 break;
1086 case at_icregexp:
1087 analyse_regex (argbuffer[i].what, TRUE);
1088 break; 1029 break;
1089 #endif 1030 #endif
1090 case at_filename: 1031 case at_filename:
1091 #ifdef VMS 1032 #ifdef VMS
1092 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL) 1033 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
1174 } 1115 }
1175 1116
1176 1117
1177 1118
1178 /* 1119 /*
1179 * Return a compressor given the file name. If EXTPTR is non-zero, 1120 * Return a compressor given the file name.
1180 * return a pointer into FILE where the compressor-specific
1181 * extension begins. If no compressor is found, NULL is returned
1182 * and EXTPTR is not significant.
1183 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca> 1121 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca>
1184 */ 1122 */
1185 static compressor * 1123 compressor *
1186 get_compressor_from_suffix (file, extptr) 1124 get_compressor_from_suffix (file)
1187 char *file; 1125 char *file;
1188 char **extptr;
1189 { 1126 {
1190 compressor *compr; 1127 compressor *compr;
1191 char *slash, *suffix; 1128 char *suffix;
1192 1129
1193 /* This relies on FN to be after canonicalize_filename,
1194 so we don't need to consider backslashes on WIN32_NATIVE. */
1195 slash = etags_strrchr (file, '/');
1196 suffix = etags_strrchr (file, '.'); 1130 suffix = etags_strrchr (file, '.');
1197 if (suffix == NULL || suffix < slash) 1131 if (suffix == NULL)
1198 return NULL; 1132 return NULL;
1199 if (extptr != NULL)
1200 *extptr = suffix;
1201 suffix += 1; 1133 suffix += 1;
1202 /* Let those poor souls who live with DOS 8+3 file name limits get 1134 for (compr = compressors; compr->suffix != NULL; compr++)
1203 some solace by treating foo.cgz as if it were foo.c.gz, etc. 1135 if (streq (compr->suffix, suffix))
1204 */ 1136 return compr;
1205 do
1206 {
1207 for (compr = compressors; compr->suffix != NULL; compr++)
1208 if (streq (compr->suffix, suffix))
1209 return compr;
1210 if (1) /* !MSDOS */
1211 break; /* do it only once: not really a loop */
1212 if (extptr != NULL)
1213 *extptr = ++suffix;
1214 } while (*suffix != '\0');
1215 return NULL; 1137 return NULL;
1216 } 1138 }
1217 1139
1218 1140
1219 1141
1220 /* 1142 /*
1221 * Return a language given the name. 1143 * Return a language given the name.
1222 */ 1144 */
1223 static language * 1145 language *
1224 get_language_from_name (name) 1146 get_language_from_name (name)
1225 char *name; 1147 char *name;
1226 { 1148 {
1227 language *lang; 1149 language *lang;
1228 1150
1241 1163
1242 1164
1243 /* 1165 /*
1244 * Return a language given the interpreter name. 1166 * Return a language given the interpreter name.
1245 */ 1167 */
1246 static language * 1168 language *
1247 get_language_from_interpreter (interpreter) 1169 get_language_from_interpreter (interpreter)
1248 char *interpreter; 1170 char *interpreter;
1249 { 1171 {
1250 language *lang; 1172 language *lang;
1251 char **iname; 1173 char **iname;
1264 1186
1265 1187
1266 /* 1188 /*
1267 * Return a language given the file name. 1189 * Return a language given the file name.
1268 */ 1190 */
1269 static language * 1191 language *
1270 get_language_from_suffix (file) 1192 get_language_from_suffix (file)
1271 char *file; 1193 char *file;
1272 { 1194 {
1273 language *lang; 1195 language *lang;
1274 char **ext, *suffix; 1196 char **ext, *suffix;
1288 1210
1289 1211
1290 /* 1212 /*
1291 * This routine is called on each file argument. 1213 * This routine is called on each file argument.
1292 */ 1214 */
1293 static void 1215 void
1294 process_file (file) 1216 process_file (file)
1295 char *file; 1217 char *file;
1296 { 1218 {
1297 struct stat stat_buf; 1219 struct stat stat_buf;
1298 FILE *inf; 1220 FILE *inf;
1299 compressor *compr; 1221 compressor *compr;
1300 char *compressed_name, *uncompressed_name; 1222 char *compressed_name, *uncompressed_name;
1301 char *ext, *real_name; 1223 char *real_name;
1302
1303 1224
1304 canonicalize_filename (file); 1225 canonicalize_filename (file);
1305 if (streq (file, tagfile) && !streq (tagfile, "-")) 1226 if (streq (file, tagfile) && !streq (tagfile, "-"))
1306 { 1227 {
1307 error ("skipping inclusion of %s in self.", file); 1228 error ("skipping inclusion of %s in self.", file);
1308 return; 1229 return;
1309 } 1230 }
1310 if ((compr = get_compressor_from_suffix (file, &ext)) == NULL) 1231 if ((compr = get_compressor_from_suffix (file)) == NULL)
1311 { 1232 {
1312 compressed_name = NULL; 1233 compressed_name = NULL;
1313 real_name = uncompressed_name = savestr (file); 1234 real_name = uncompressed_name = savestr (file);
1314 } 1235 }
1315 else 1236 else
1316 { 1237 {
1317 real_name = compressed_name = savestr (file); 1238 real_name = compressed_name = savestr (file);
1318 uncompressed_name = savenstr (file, ext - file); 1239 uncompressed_name = savenstr (file, strlen(file) - compr->sufflen - 1);
1319 } 1240 }
1320
1321 /* If the canonicalised uncompressed name has already be dealt with,
1322 skip it silently, else add it to the list. */
1323 {
1324 typedef struct processed_file
1325 {
1326 char *filename;
1327 struct processed_file *next;
1328 } processed_file;
1329 static processed_file *pf_head = NULL;
1330 register processed_file *fnp;
1331
1332 for (fnp = pf_head; fnp != NULL; fnp = fnp->next)
1333 if (streq (uncompressed_name, fnp->filename))
1334 goto exit;
1335 fnp = pf_head;
1336 pf_head = xnew (1, struct processed_file);
1337 pf_head->filename = savestr (uncompressed_name);
1338 pf_head->next = fnp;
1339 }
1340
1341 if (stat (real_name, &stat_buf) != 0) 1241 if (stat (real_name, &stat_buf) != 0)
1342 { 1242 {
1343 /* Reset real_name and try with a different name. */ 1243 /* Reset real_name and try with a different name. */
1344 real_name = NULL; 1244 real_name = NULL;
1345 if (compressed_name != NULL) /* try with the given suffix */ 1245 if (compressed_name != NULL) /* try with the given suffix */
1351 { 1251 {
1352 for (compr = compressors; compr->suffix != NULL; compr++) 1252 for (compr = compressors; compr->suffix != NULL; compr++)
1353 { 1253 {
1354 compressed_name = concat (file, ".", compr->suffix); 1254 compressed_name = concat (file, ".", compr->suffix);
1355 if (stat (compressed_name, &stat_buf) != 0) 1255 if (stat (compressed_name, &stat_buf) != 0)
1356 { 1256 free (compressed_name);
1357 /* XEmacs: delete MSDOS code */
1358 free (compressed_name);
1359 compressed_name = NULL;
1360 }
1361 else 1257 else
1362 { 1258 {
1363 real_name = compressed_name; 1259 real_name = compressed_name;
1364 break; 1260 break;
1365 } 1261 }
1381 { 1277 {
1382 char *cmd = concat (compr->command, " ", real_name); 1278 char *cmd = concat (compr->command, " ", real_name);
1383 inf = popen (cmd, "r"); 1279 inf = popen (cmd, "r");
1384 free (cmd); 1280 free (cmd);
1385 } 1281 }
1386 else 1282 else
1387 inf = fopen (real_name, "r"); 1283 inf = fopen (real_name, "r");
1388 if (inf == NULL) 1284 if (inf == NULL)
1389 { 1285 {
1390 perror (real_name); 1286 perror (real_name);
1391 goto exit; 1287 goto exit;
1432 * Every char which is NOT in that string is not a white char. Therefore, 1328 * Every char which is NOT in that string is not a white char. Therefore,
1433 * all of the array "_wht" is set to FALSE, and then the elements 1329 * all of the array "_wht" is set to FALSE, and then the elements
1434 * subscripted by the chars in "white" are set to TRUE. Thus "_wht" 1330 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1435 * of a char is TRUE if it is the string "white", else FALSE. 1331 * of a char is TRUE if it is the string "white", else FALSE.
1436 */ 1332 */
1437 static void 1333 void
1438 init () 1334 init ()
1439 { 1335 {
1440 register char *sp; 1336 register char *sp;
1441 register int i; 1337 register int i;
1442 1338
1443 for (i = 0; i < CHARS; i++) 1339 for (i = 0; i < CHARS; i++)
1444 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE; 1340 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE;
1445 for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE; 1341 for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE;
1446 for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE; 1342 for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE;
1343 for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
1344 for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
1345 for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
1346 iswhite('\0') = iswhite('\n');
1447 notinname('\0') = notinname('\n'); 1347 notinname('\0') = notinname('\n');
1448 for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
1449 begtoken('\0') = begtoken('\n'); 1348 begtoken('\0') = begtoken('\n');
1450 for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
1451 intoken('\0') = intoken('\n'); 1349 intoken('\0') = intoken('\n');
1452 for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
1453 endtoken('\0') = endtoken('\n'); 1350 endtoken('\0') = endtoken('\n');
1454 } 1351 }
1455 1352
1456 /* 1353 /*
1457 * This routine opens the specified file and calls the function 1354 * This routine opens the specified file and calls the function
1458 * which finds the function and type definitions. 1355 * which finds the function and type definitions.
1459 */ 1356 */
1460 node *last_node = NULL; 1357 node *last_node = NULL;
1461 1358
1462 static void 1359 void
1463 find_entries (file, inf) 1360 find_entries (file, inf)
1464 char *file; 1361 char *file;
1465 FILE *inf; 1362 FILE *inf;
1466 { 1363 {
1467 char *cp; 1364 char *cp;
1544 } 1441 }
1545 return; 1442 return;
1546 } 1443 }
1547 1444
1548 /* Record a tag. */ 1445 /* Record a tag. */
1549 static void 1446 void
1550 pfnote (name, is_func, linestart, linelen, lno, cno) 1447 pfnote (name, is_func, linestart, linelen, lno, cno)
1551 char *name; /* tag name, or NULL if unnamed */ 1448 char *name; /* tag name, or NULL if unnamed */
1552 bool is_func; /* tag is a function */ 1449 bool is_func; /* tag is a function */
1553 char *linestart; /* start of the line where tag is */ 1450 char *linestart; /* start of the line where tag is */
1554 int linelen; /* length of the line where tag is */ 1451 int linelen; /* length of the line where tag is */
1614 * The real implementation uses the notinname() macro, which recognises 1511 * The real implementation uses the notinname() macro, which recognises
1615 * characters slightly different form " \t\r\n(),;". See the variable 1512 * characters slightly different form " \t\r\n(),;". See the variable
1616 * `nonam'. 1513 * `nonam'.
1617 */ 1514 */
1618 #define traditional_tag_style TRUE 1515 #define traditional_tag_style TRUE
1619 static void 1516 void
1620 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno) 1517 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno)
1621 char *name; /* tag name, or NULL if unnamed */ 1518 char *name; /* tag name, or NULL if unnamed */
1622 int namelen; /* tag length */ 1519 int namelen; /* tag length */
1623 bool is_func; /* tag is a function */ 1520 bool is_func; /* tag is a function */
1624 char *linestart; /* start of the line where tag is */ 1521 char *linestart; /* start of the line where tag is */
1644 || notinname (cp[-1])) /* rule #3 */ 1541 || notinname (cp[-1])) /* rule #3 */
1645 && strneq (name, cp, namelen)) /* rule #2 */ 1542 && strneq (name, cp, namelen)) /* rule #2 */
1646 named = FALSE; /* use unnamed tag */ 1543 named = FALSE; /* use unnamed tag */
1647 } 1544 }
1648 } 1545 }
1649 1546
1650 if (named) 1547 if (named)
1651 name = savenstr (name, namelen); 1548 name = savenstr (name, namelen);
1652 else 1549 else
1653 name = NULL; 1550 name = NULL;
1654 pfnote (name, is_func, linestart, linelen, lno, cno); 1551 pfnote (name, is_func, linestart, linelen, lno, cno);
1656 1553
1657 /* 1554 /*
1658 * free_tree () 1555 * free_tree ()
1659 * recurse on left children, iterate on right children. 1556 * recurse on left children, iterate on right children.
1660 */ 1557 */
1661 static void 1558 void
1662 free_tree (np) 1559 free_tree (np)
1663 register node *np; 1560 register node *np;
1664 { 1561 {
1665 while (np) 1562 while (np)
1666 { 1563 {
1681 * an ordered tree, with no attempt at balancing. 1578 * an ordered tree, with no attempt at balancing.
1682 * 1579 *
1683 * add_node is the only function allowed to add nodes, so it can 1580 * add_node is the only function allowed to add nodes, so it can
1684 * maintain state. 1581 * maintain state.
1685 */ 1582 */
1686 static void 1583 void
1687 add_node (np, cur_node_p) 1584 add_node (np, cur_node_p)
1688 node *np, **cur_node_p; 1585 node *np, **cur_node_p;
1689 { 1586 {
1690 register int dif; 1587 register int dif;
1691 register node *cur_node = *cur_node_p; 1588 register node *cur_node = *cur_node_p;
1739 /* Actually add the node */ 1636 /* Actually add the node */
1740 add_node (np, dif < 0 ? &cur_node->left : &cur_node->right); 1637 add_node (np, dif < 0 ? &cur_node->left : &cur_node->right);
1741 } 1638 }
1742 } 1639 }
1743 1640
1744 static void 1641 void
1745 put_entries (np) 1642 put_entries (np)
1746 register node *np; 1643 register node *np;
1747 { 1644 {
1748 register char *sp; 1645 register char *sp;
1749 1646
1806 /* Output subentries that follow this one */ 1703 /* Output subentries that follow this one */
1807 put_entries (np->right); 1704 put_entries (np->right);
1808 } 1705 }
1809 1706
1810 /* Length of a number's decimal representation. */ 1707 /* Length of a number's decimal representation. */
1811 static int 1708 int
1812 number_len (num) 1709 number_len (num)
1813 long num; 1710 long num;
1814 { 1711 {
1815 int len = 1; 1712 int len = 1;
1816 while ((num /= 10) > 0) 1713 while ((num /= 10) > 0)
1823 * the nodes in the subtree of the specified node. Works only if 1720 * the nodes in the subtree of the specified node. Works only if
1824 * we are not ctags, but called only in that case. This count 1721 * we are not ctags, but called only in that case. This count
1825 * is irrelevant with the new tags.el, but is still supplied for 1722 * is irrelevant with the new tags.el, but is still supplied for
1826 * backward compatibility. 1723 * backward compatibility.
1827 */ 1724 */
1828 static int 1725 int
1829 total_size_of_entries (np) 1726 total_size_of_entries (np)
1830 register node *np; 1727 register node *np;
1831 { 1728 {
1832 register int total; 1729 register int total;
1833 1730
1858 st_C_objprot, st_C_objimpl, st_C_objend, 1755 st_C_objprot, st_C_objimpl, st_C_objend,
1859 st_C_gnumacro, 1756 st_C_gnumacro,
1860 st_C_ignore, 1757 st_C_ignore,
1861 st_C_javastruct, 1758 st_C_javastruct,
1862 st_C_operator, 1759 st_C_operator,
1863 st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef, st_C_typespec 1760 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
1864 }; 1761 };
1865
1866 static unsigned int hash P_((const char *, unsigned int));
1867 static struct C_stab_entry * in_word_set P_((const char *, unsigned int));
1868 static enum sym_type C_symtype P_((char *, int, int));
1869 1762
1870 /* Feed stuff between (but not including) %[ and %] lines to: 1763 /* Feed stuff between (but not including) %[ and %] lines to:
1871 gperf -c -k 1,3 -o -p -r -t 1764 gperf -c -k 1,3 -o -p -r -t
1872 %[ 1765 %[
1873 struct C_stab_entry { char *name; int c_ext; enum sym_type type; } 1766 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1874 %% 1767 %%
1875 if, 0, st_C_ignore
1876 for, 0, st_C_ignore
1877 while, 0, st_C_ignore
1878 switch, 0, st_C_ignore
1879 return, 0, st_C_ignore
1880 @interface, 0, st_C_objprot 1768 @interface, 0, st_C_objprot
1881 @protocol, 0, st_C_objprot 1769 @protocol, 0, st_C_objprot
1882 @implementation,0, st_C_objimpl 1770 @implementation,0, st_C_objimpl
1883 @end, 0, st_C_objend 1771 @end, 0, st_C_objend
1884 import, C_JAVA, st_C_ignore 1772 import, C_JAVA, st_C_ignore
1890 class, C_PLPL, st_C_struct 1778 class, C_PLPL, st_C_struct
1891 namespace, C_PLPL, st_C_struct 1779 namespace, C_PLPL, st_C_struct
1892 domain, C_STAR, st_C_struct 1780 domain, C_STAR, st_C_struct
1893 union, 0, st_C_struct 1781 union, 0, st_C_struct
1894 struct, 0, st_C_struct 1782 struct, 0, st_C_struct
1895 extern, 0, st_C_extern
1896 enum, 0, st_C_enum 1783 enum, 0, st_C_enum
1897 typedef, 0, st_C_typedef 1784 typedef, 0, st_C_typedef
1898 define, 0, st_C_define 1785 define, 0, st_C_define
1899 operator, C_PLPL, st_C_operator 1786 operator, C_PLPL, st_C_operator
1900 bool, C_PLPL, st_C_typespec 1787 bool, C_PLPL, st_C_typespec
1906 double, 0, st_C_typespec 1793 double, 0, st_C_typespec
1907 signed, 0, st_C_typespec 1794 signed, 0, st_C_typespec
1908 unsigned, 0, st_C_typespec 1795 unsigned, 0, st_C_typespec
1909 auto, 0, st_C_typespec 1796 auto, 0, st_C_typespec
1910 void, 0, st_C_typespec 1797 void, 0, st_C_typespec
1798 extern, 0, st_C_typespec
1911 static, 0, st_C_typespec 1799 static, 0, st_C_typespec
1912 const, 0, st_C_typespec 1800 const, 0, st_C_typespec
1913 volatile, 0, st_C_typespec 1801 volatile, 0, st_C_typespec
1914 explicit, C_PLPL, st_C_typespec 1802 explicit, C_PLPL, st_C_typespec
1915 mutable, C_PLPL, st_C_typespec 1803 mutable, C_PLPL, st_C_typespec
1924 #EXFUN, 0, st_C_gnumacro 1812 #EXFUN, 0, st_C_gnumacro
1925 #DEFVAR_, 0, st_C_gnumacro 1813 #DEFVAR_, 0, st_C_gnumacro
1926 %] 1814 %]
1927 and replace lines between %< and %> with its output. */ 1815 and replace lines between %< and %> with its output. */
1928 /*%<*/ 1816 /*%<*/
1929 /* C code produced by gperf version 2.7.1 (19981006 egcs) */ 1817 /* C code produced by gperf version 2.5 (GNU C++ version) */
1930 /* Command-line: gperf -c -k 1,3 -o -p -r -t */ 1818 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1931 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }; 1819 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
1932 1820
1933 #define TOTAL_KEYWORDS 46 1821 #define TOTAL_KEYWORDS 41
1934 #define MIN_WORD_LENGTH 2 1822 #define MIN_WORD_LENGTH 3
1935 #define MAX_WORD_LENGTH 15 1823 #define MAX_WORD_LENGTH 15
1936 #define MIN_HASH_VALUE 13 1824 #define MIN_HASH_VALUE 20
1937 #define MAX_HASH_VALUE 123 1825 #define MAX_HASH_VALUE 136
1938 /* maximum key range = 111, duplicates = 0 */ 1826 /* maximum key range = 117, duplicates = 0 */
1939 1827
1940 #ifdef __GNUC__
1941 __inline
1942 #endif
1943 static unsigned int 1828 static unsigned int
1944 hash (str, len) 1829 hash (str, len)
1945 register const char *str; 1830 register char *str;
1831 register int unsigned len;
1832 {
1833 static unsigned char asso_values[] =
1834 {
1835 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
1836 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
1837 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
1838 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
1839 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
1840 137, 137, 137, 137, 137, 137, 137, 137, 137, 137,
1841 137, 137, 137, 137, 58, 137, 137, 137, 38, 37,
1842 45, 137, 137, 137, 137, 137, 137, 137, 137, 137,
1843 62, 137, 137, 14, 16, 137, 137, 137, 137, 137,
1844 137, 137, 137, 137, 137, 137, 137, 26, 16, 51,
1845 18, 61, 5, 19, 137, 23, 137, 137, 32, 63,
1846 54, 10, 26, 137, 24, 42, 30, 18, 46, 137,
1847 137, 137, 137, 137, 137, 137, 137, 137,
1848 };
1849 return len + asso_values[str[2]] + asso_values[str[0]];
1850 }
1851
1852 struct C_stab_entry *
1853 in_word_set (str, len)
1854 register char *str;
1946 register unsigned int len; 1855 register unsigned int len;
1947 { 1856 {
1948 static unsigned char asso_values[] =
1949 {
1950 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1951 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1952 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1953 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1954 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1955 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1956 124, 124, 124, 124, 3, 124, 124, 124, 43, 6,
1957 11, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1958 11, 124, 124, 58, 7, 124, 124, 124, 124, 124,
1959 124, 124, 124, 124, 124, 124, 124, 57, 7, 42,
1960 4, 14, 52, 0, 124, 53, 124, 124, 29, 11,
1961 6, 35, 32, 124, 29, 34, 59, 58, 51, 24,
1962 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1963 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1964 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1965 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1966 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1967 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1968 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1969 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1970 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1971 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1972 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1973 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1974 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1975 124, 124, 124, 124, 124, 124
1976 };
1977 register int hval = len;
1978
1979 switch (hval)
1980 {
1981 default:
1982 case 3:
1983 hval += asso_values[(unsigned char)str[2]];
1984 case 2:
1985 case 1:
1986 hval += asso_values[(unsigned char)str[0]];
1987 break;
1988 }
1989 return hval;
1990 }
1991
1992 #ifdef __GNUC__
1993 __inline
1994 #endif
1995 static struct C_stab_entry *
1996 in_word_set (str, len)
1997 register const char *str;
1998 register unsigned int len;
1999 {
2000 static struct C_stab_entry wordlist[] = 1857 static struct C_stab_entry wordlist[] =
2001 { 1858 {
2002 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, 1859 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
2003 {""}, {""}, {""}, {""}, 1860 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
2004 {"@end", 0, st_C_objend}, 1861 {"",}, {"",},
2005 {""}, {""}, {""}, {""}, 1862 {"float", 0, st_C_typespec},
2006 {"ENTRY", 0, st_C_gnumacro}, 1863 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
2007 {"@interface", 0, st_C_objprot}, 1864 {"define", 0, st_C_define},
2008 {""}, 1865 {"bool", C_PLPL, st_C_typespec},
2009 {"domain", C_STAR, st_C_struct}, 1866 {"",}, {"",}, {"",},
2010 {""}, 1867 {"friend", C_PLPL, st_C_ignore},
2011 {"PSEUDO", 0, st_C_gnumacro}, 1868 {"SYSCALL", 0, st_C_gnumacro},
2012 {""}, {""}, 1869 {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
2013 {"namespace", C_PLPL, st_C_struct}, 1870 {"double", 0, st_C_typespec},
2014 {""}, {""}, 1871 {"",}, {"",}, {"",},
2015 {"@implementation",0, st_C_objimpl}, 1872 {"union", 0, st_C_struct},
2016 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, 1873 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
2017 {"long", 0, st_C_typespec}, 1874 {"import", C_JAVA, st_C_ignore},
2018 {"signed", 0, st_C_typespec}, 1875 {"int", 0, st_C_typespec},
2019 {"@protocol", 0, st_C_objprot}, 1876 {"short", 0, st_C_typespec},
2020 {""}, {""}, {""}, {""}, 1877 {"ENTRY", 0, st_C_gnumacro},
2021 {"bool", C_PLPL, st_C_typespec}, 1878 {"implements", C_JAVA, st_C_javastruct},
2022 {""}, {""}, {""}, {""}, {""}, {""}, 1879 {"auto", 0, st_C_typespec},
2023 {"const", 0, st_C_typespec}, 1880 {"",},
2024 {"explicit", C_PLPL, st_C_typespec}, 1881 {"interface", C_JAVA, st_C_struct},
2025 {"if", 0, st_C_ignore}, 1882 {"typedef", 0, st_C_typedef},
2026 {""}, 1883 {"typename", C_PLPL, st_C_typespec},
2027 {"operator", C_PLPL, st_C_operator}, 1884 {"",}, {"",},
2028 {""}, 1885 {"signed", 0, st_C_typespec},
2029 {"DEFUN", 0, st_C_gnumacro}, 1886 {"unsigned", 0, st_C_typespec},
2030 {""}, {""}, 1887 {"",}, {"",}, {"",},
2031 {"define", 0, st_C_define}, 1888 {"struct", 0, st_C_struct},
2032 {""}, {""}, {""}, {""}, {""}, 1889 {"void", 0, st_C_typespec},
2033 {"double", 0, st_C_typespec}, 1890 {"static", 0, st_C_typespec},
2034 {"struct", 0, st_C_struct}, 1891 {"",}, {"",}, {"",}, {"",},
2035 {""}, {""}, {""}, {""}, 1892 {"operator", C_PLPL, st_C_operator},
2036 {"short", 0, st_C_typespec}, 1893 {"",},
2037 {""}, 1894 {"char", 0, st_C_typespec},
2038 {"enum", 0, st_C_enum}, 1895 {"class", C_PLPL, st_C_struct},
2039 {"mutable", C_PLPL, st_C_typespec}, 1896 {"enum", 0, st_C_enum},
2040 {""}, 1897 {"package", C_JAVA, st_C_ignore},
2041 {"extern", 0, st_C_extern}, 1898 {"",},
2042 {"extends", C_JAVA, st_C_javastruct}, 1899 {"volatile", 0, st_C_typespec},
2043 {"package", C_JAVA, st_C_ignore}, 1900 {"domain", C_STAR, st_C_struct},
2044 {"while", 0, st_C_ignore}, 1901 {"DEFUN", 0, st_C_gnumacro},
2045 {""}, 1902 {"",},
2046 {"for", 0, st_C_ignore}, 1903 {"long", 0, st_C_typespec},
2047 {""}, {""}, {""}, 1904 {"@protocol", 0, st_C_objprot},
2048 {"volatile", 0, st_C_typespec}, 1905 {"",}, {"",}, {"",},
2049 {""}, {""}, 1906 {"explicit", C_PLPL, st_C_typespec},
2050 {"import", C_JAVA, st_C_ignore}, 1907 {"",},
2051 {"float", 0, st_C_typespec}, 1908 {"extern", 0, st_C_typespec},
2052 {"switch", 0, st_C_ignore}, 1909 {"extends", C_JAVA, st_C_javastruct},
2053 {"return", 0, st_C_ignore}, 1910 {"",},
2054 {"implements", C_JAVA, st_C_javastruct}, 1911 {"mutable", C_PLPL, st_C_typespec},
2055 {""}, 1912 {"",}, {"",}, {"",}, {"",},
2056 {"static", 0, st_C_typespec}, 1913 {"PSEUDO", 0, st_C_gnumacro},
2057 {"typedef", 0, st_C_typedef}, 1914 {"",}, {"",}, {"",}, {"",},
2058 {"typename", C_PLPL, st_C_typespec}, 1915 {"const", 0, st_C_typespec},
2059 {"unsigned", 0, st_C_typespec}, 1916 {"",}, {"",}, {"",}, {"",}, {"",},
2060 {""}, {""}, 1917 {"@end", 0, st_C_objend},
2061 {"char", 0, st_C_typespec}, 1918 {"",}, {"",}, {"",}, {"",}, {"",},
2062 {"class", C_PLPL, st_C_struct}, 1919 {"@interface", 0, st_C_objprot},
2063 {""}, {""}, {""}, 1920 {"",}, {"",}, {"",},
2064 {"void", 0, st_C_typespec}, 1921 {"namespace", C_PLPL, st_C_struct},
2065 {""}, {""}, 1922 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
2066 {"friend", C_PLPL, st_C_ignore}, 1923 {"@implementation", 0, st_C_objimpl},
2067 {""}, {""}, {""},
2068 {"int", 0, st_C_typespec},
2069 {"union", 0, st_C_struct},
2070 {""}, {""}, {""},
2071 {"auto", 0, st_C_typespec},
2072 {"interface", C_JAVA, st_C_struct},
2073 {""},
2074 {"SYSCALL", 0, st_C_gnumacro}
2075 }; 1924 };
2076 1925
2077 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) 1926 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
2078 { 1927 {
2079 register int key = hash (str, len); 1928 register int key = hash (str, len);
2080 1929
2081 if (key <= MAX_HASH_VALUE && key >= 0) 1930 if (key <= MAX_HASH_VALUE && key >= 0)
2082 { 1931 {
2083 register const char *s = wordlist[key].name; 1932 register char *s = wordlist[key].name;
2084 1933
2085 if (*str == *s && !strncmp (str + 1, s + 1, len - 1)) 1934 if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
2086 return &wordlist[key]; 1935 return &wordlist[key];
2087 } 1936 }
2088 } 1937 }
2089 return 0; 1938 return 0;
2090 } 1939 }
2091 /*%>*/ 1940 /*%>*/
2092 1941
2093 static enum sym_type 1942 enum sym_type
2094 C_symtype (str, len, c_ext) 1943 C_symtype (str, len, c_ext)
2095 char *str; 1944 char *str;
2096 int len; 1945 int len;
2097 int c_ext; 1946 int c_ext;
2098 { 1947 {
2117 flistseen, /* func: after parameter list */ 1966 flistseen, /* func: after parameter list */
2118 fignore, /* func: before open brace */ 1967 fignore, /* func: before open brace */
2119 vignore /* var-like: ignore until ';' */ 1968 vignore /* var-like: ignore until ';' */
2120 } fvdef; 1969 } fvdef;
2121 1970
2122 bool fvextern; /* func or var: extern keyword seen; */
2123 1971
2124 /* 1972 /*
2125 * typedefs are recognized using a simple finite automaton. 1973 * typedefs are recognized using a simple finite automaton.
2126 * typdef is its state variable. 1974 * typdef is its state variable.
2127 */ 1975 */
2128 enum 1976 enum
2129 { 1977 {
2130 tnone, /* nothing seen */ 1978 tnone, /* nothing seen */
2131 tkeyseen, /* typedef keyword seen */ 1979 ttypedseen, /* typedef keyword seen */
2132 ttypeseen, /* defined type seen */
2133 tinbody, /* inside typedef body */ 1980 tinbody, /* inside typedef body */
2134 tend, /* just before typedef tag */ 1981 tend, /* just before typedef tag */
2135 tignore /* junk after typedef tag */ 1982 tignore /* junk after typedef tag */
2136 } typdef; 1983 } typdef;
2137 1984
2225 2072
2226 /* 2073 /*
2227 * methodlen is the length of the method name stored in token_name. 2074 * methodlen is the length of the method name stored in token_name.
2228 */ 2075 */
2229 int methodlen; 2076 int methodlen;
2230
2231 static bool consider_token P_((char *, int, int, int, int, int, bool *));
2232 static void make_C_tag P_((bool));
2233 2077
2234 /* 2078 /*
2235 * consider_token () 2079 * consider_token ()
2236 * checks to see if the current token is at the start of a 2080 * checks to see if the current token is at the start of a
2237 * function or variable, or corresponds to a typedef, or 2081 * function or variable, or corresponds to a typedef, or
2247 * typdef IN OUT 2091 * typdef IN OUT
2248 * objdef IN OUT 2092 * objdef IN OUT
2249 * next_token_is_func IN OUT 2093 * next_token_is_func IN OUT
2250 */ 2094 */
2251 2095
2252 static bool 2096 bool
2253 consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var) 2097 consider_token (str, len, c, c_ext, cblev, parlev, is_func_or_var)
2254 register char *str; /* IN: token pointer */ 2098 register char *str; /* IN: token pointer */
2255 register int len; /* IN: token length */ 2099 register int len; /* IN: token length */
2256 register int c; /* IN: first char after the token */ 2100 register char c; /* IN: first char after the token */
2257 int c_ext; /* IN: C extensions mask */ 2101 int c_ext; /* IN: C extensions mask */
2258 int cblev; /* IN: curly brace level */ 2102 int cblev; /* IN: curly brace level */
2259 int parlev; /* IN: parenthesis level */ 2103 int parlev; /* IN: parenthesis level */
2260 bool *is_func_or_var; /* OUT: function or variable found */ 2104 bool *is_func_or_var; /* OUT: function or variable found */
2261 { 2105 {
2303 { 2147 {
2304 case tnone: 2148 case tnone:
2305 if (toktype == st_C_typedef) 2149 if (toktype == st_C_typedef)
2306 { 2150 {
2307 if (typedefs) 2151 if (typedefs)
2308 typdef = tkeyseen; 2152 typdef = ttypedseen;
2309 fvextern = FALSE;
2310 fvdef = fvnone; 2153 fvdef = fvnone;
2311 return FALSE; 2154 return FALSE;
2312 } 2155 }
2313 break; 2156 break;
2314 case tkeyseen: 2157 case ttypedseen:
2315 switch (toktype) 2158 switch (toktype)
2316 { 2159 {
2317 case st_none: 2160 case st_none:
2318 case st_C_typespec: 2161 case st_C_typespec:
2162 typdef = tend;
2163 break;
2319 case st_C_struct: 2164 case st_C_struct:
2320 case st_C_enum: 2165 case st_C_enum:
2321 typdef = ttypeseen;
2322 break; 2166 break;
2323 } 2167 }
2324 /* Do not return here, so the structdef stuff has a chance. */ 2168 /* Do not return here, so the structdef stuff has a chance. */
2325 break; 2169 break;
2326 case tend: 2170 case tend:
2350 if (structdef == stagseen) 2194 if (structdef == stagseen)
2351 structdef = scolonseen; 2195 structdef = scolonseen;
2352 return FALSE; 2196 return FALSE;
2353 case st_C_struct: 2197 case st_C_struct:
2354 case st_C_enum: 2198 case st_C_enum:
2355 if (typdef == tkeyseen 2199 if (typdef == ttypedseen
2356 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone)) 2200 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
2357 { 2201 {
2358 structdef = skeyseen; 2202 structdef = skeyseen;
2359 structtype = toktype; 2203 structtype = toktype;
2360 } 2204 }
2371 structtag = "<enum>"; 2215 structtag = "<enum>";
2372 structdef = stagseen; 2216 structdef = stagseen;
2373 return TRUE; 2217 return TRUE;
2374 } 2218 }
2375 2219
2220 /* Avoid entering fvdef stuff if typdef is going on. */
2376 if (typdef != tnone) 2221 if (typdef != tnone)
2377 definedef = dnone; 2222 {
2223 definedef = dnone;
2224 return FALSE;
2225 }
2378 2226
2379 /* Detect GNU macros. 2227 /* Detect GNU macros.
2380 2228
2381 Writers of emacs code are recommended to put the 2229 DEFUN note for writers of emacs C code:
2382 first two args of a DEFUN on the same line.
2383
2384 The DEFUN macro, used in emacs C source code, has a first arg 2230 The DEFUN macro, used in emacs C source code, has a first arg
2385 that is a string (the lisp function name), and a second arg that 2231 that is a string (the lisp function name), and a second arg that
2386 is a C function name. Since etags skips strings, the second arg 2232 is a C function name. Since etags skips strings, the second arg
2387 is tagged. This is unfortunate, as it would be better to tag the 2233 is tagged. This is unfortunate, as it would be better to tag the
2388 first arg. The simplest way to deal with this problem would be 2234 first arg. The simplest way to deal with this problem would be
2389 to name the tag with a name built from the function name, by 2235 to name the tag with a name built from the function name, by
2390 removing the initial 'F' character and substituting '-' for '_'. 2236 removing the initial 'F' character and substituting '-' for '_'.
2391 Anyway, this assumes that the conventions of naming lisp 2237 Anyway, this assumes that the conventions of naming lisp
2392 functions will never change. Currently, this method is not 2238 functions will never change. Currently, this method is not
2393 implemented. */ 2239 implemented, so writers of emacs code are recommended to put the
2240 first two args of a DEFUN on the same line. */
2394 if (definedef == dnone && toktype == st_C_gnumacro) 2241 if (definedef == dnone && toktype == st_C_gnumacro)
2395 { 2242 {
2396 next_token_is_func = TRUE; 2243 next_token_is_func = TRUE;
2397 return FALSE; 2244 return FALSE;
2398 } 2245 }
2477 } 2324 }
2478 2325
2479 /* A function, variable or enum constant? */ 2326 /* A function, variable or enum constant? */
2480 switch (toktype) 2327 switch (toktype)
2481 { 2328 {
2482 case st_C_extern:
2483 fvextern = TRUE;
2484 /* FALLTHRU */
2485 case st_C_typespec: 2329 case st_C_typespec:
2486 if (fvdef != finlist && fvdef != fignore && fvdef != vignore) 2330 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2487 fvdef = fvnone; /* should be useless */ 2331 fvdef = fvnone; /* should be useless */
2488 return FALSE; 2332 return FALSE;
2489 case st_C_ignore: 2333 case st_C_ignore:
2490 fvextern = FALSE;
2491 fvdef = vignore; 2334 fvdef = vignore;
2492 return FALSE; 2335 return FALSE;
2493 case st_C_operator: 2336 case st_C_operator:
2494 fvdef = foperator; 2337 fvdef = foperator;
2495 *is_func_or_var = TRUE; 2338 *is_func_or_var = TRUE;
2496 return TRUE; 2339 return TRUE;
2497 case st_none: 2340 case st_none:
2498 if ((c_ext & C_PLPL) && strneq (str+len-10, "::operator", 10))
2499 {
2500 fvdef = foperator;
2501 *is_func_or_var = TRUE;
2502 return TRUE;
2503 }
2504 if (constantypedefs && structdef == sinbody && structtype == st_C_enum) 2341 if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
2505 return TRUE; 2342 return TRUE;
2506 if (fvdef == fvnone) 2343 if (fvdef == fvnone)
2507 { 2344 {
2508 fvdef = fvnameseen; /* function or variable */ 2345 fvdef = fvnameseen; /* function or variable */
2509 *is_func_or_var = TRUE; 2346 *is_func_or_var = TRUE;
2510 return TRUE; 2347 return TRUE;
2511 } 2348 }
2512 break;
2513 } 2349 }
2514 2350
2515 return FALSE; 2351 return FALSE;
2516 } 2352 }
2517 2353
2518 /* 2354 /*
2519 * C_entries () 2355 * C_entries ()
2520 * This routine finds functions, variables, typedefs, 2356 * This routine finds functions, variables, typedefs,
2521 * #define's, enum constants and struct/union/enum definitions in 2357 * #define's, enum constants and struct/union/enum definitions in
2522 * C syntax and adds them to the list. 2358 * #C syntax and adds them to the list.
2523 */ 2359 */
2524 #define current_lb_is_new (newndx == curndx) 2360 #define current_lb_is_new (newndx == curndx)
2525 #define switch_line_buffers() (curndx = 1 - curndx) 2361 #define switch_line_buffers() (curndx = 1 - curndx)
2526 2362
2527 #define curlb (lbs[curndx].lb) 2363 #define curlb (lbs[curndx].lb)
2552 } \ 2388 } \
2553 definedef = dnone; \ 2389 definedef = dnone; \
2554 } while (0) 2390 } while (0)
2555 2391
2556 2392
2557 static void 2393 void
2558 make_C_tag (isfun) 2394 make_C_tag (isfun)
2559 bool isfun; 2395 bool isfun;
2560 { 2396 {
2561 /* This function should never be called when tok.valid is FALSE, but 2397 /* This function should never be called when tok.valid is FALSE, but
2562 we must protect against invalid input or internal errors. */ 2398 we must protect against invalid input or internal errors. */
2581 else if (DEBUG) 2417 else if (DEBUG)
2582 abort (); 2418 abort ();
2583 } 2419 }
2584 2420
2585 2421
2586 static void 2422 void
2587 C_entries (c_ext, inf) 2423 C_entries (c_ext, inf)
2588 int c_ext; /* extension of C */ 2424 int c_ext; /* extension of C */
2589 FILE *inf; /* input file */ 2425 FILE *inf; /* input file */
2590 { 2426 {
2591 register char c; /* latest char read; '\0' for end of line */ 2427 register char c; /* latest char read; '\0' for end of line */
2596 char *qualifier; /* string used to qualify names */ 2432 char *qualifier; /* string used to qualify names */
2597 int qlen; /* length of qualifier */ 2433 int qlen; /* length of qualifier */
2598 int cblev; /* current curly brace level */ 2434 int cblev; /* current curly brace level */
2599 int parlev; /* current parenthesis level */ 2435 int parlev; /* current parenthesis level */
2600 bool incomm, inquote, inchar, quotednl, midtoken; 2436 bool incomm, inquote, inchar, quotednl, midtoken;
2601 bool purec, cplpl, cjava; 2437 bool cplpl, cjava;
2602 token savetok; /* token saved during preprocessor handling */ 2438 token savetok; /* token saved during preprocessor handling */
2603 2439
2604 2440
2605 tokoff = toklen = 0; /* keep compiler quiet */ 2441 tokoff = toklen = 0; /* keep compiler quiet */
2606 curndx = newndx = 0; 2442 curndx = newndx = 0;
2607 lineno = 0; 2443 lineno = 0;
2608 charno = 0; 2444 charno = 0;
2609 lp = curlb.buffer; 2445 lp = curlb.buffer;
2610 *lp = 0; 2446 *lp = 0;
2611 2447
2612 fvdef = fvnone; fvextern = FALSE; typdef = tnone; 2448 fvdef = fvnone; typdef = tnone; structdef = snone;
2613 structdef = snone; definedef = dnone; objdef = onone; 2449 definedef = dnone; objdef = onone;
2614 next_token_is_func = yacc_rules = FALSE; 2450 next_token_is_func = yacc_rules = FALSE;
2615 midtoken = inquote = inchar = incomm = quotednl = FALSE; 2451 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2616 tok.valid = savetok.valid = FALSE; 2452 tok.valid = savetok.valid = FALSE;
2617 cblev = 0; 2453 cblev = 0;
2618 parlev = 0; 2454 parlev = 0;
2619 purec = !(c_ext & ~YACC); /* no extensions (apart from possibly yacc) */
2620 cplpl = (c_ext & C_PLPL) == C_PLPL; 2455 cplpl = (c_ext & C_PLPL) == C_PLPL;
2621 cjava = (c_ext & C_JAVA) == C_JAVA; 2456 cjava = (c_ext & C_JAVA) == C_JAVA;
2622 if (cjava) 2457 if (cjava)
2623 { qualifier = "."; qlen = 1; } 2458 { qualifier = "."; qlen = 1; }
2624 else 2459 else
2693 switch (c) 2528 switch (c)
2694 { 2529 {
2695 case '"': 2530 case '"':
2696 inquote = TRUE; 2531 inquote = TRUE;
2697 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) 2532 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2698 { 2533 fvdef = fvnone;
2699 fvextern = FALSE;
2700 fvdef = fvnone;
2701 }
2702 continue; 2534 continue;
2703 case '\'': 2535 case '\'':
2704 inchar = TRUE; 2536 inchar = TRUE;
2705 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) 2537 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2706 { 2538 fvdef = fvnone;
2707 fvextern = FALSE;
2708 fvdef = fvnone;
2709 }
2710 continue; 2539 continue;
2711 case '/': 2540 case '/':
2712 if (*lp == '*') 2541 if (*lp == '*')
2713 { 2542 {
2714 lp++; 2543 lp++;
2725 case '%': 2554 case '%':
2726 if ((c_ext & YACC) && *lp == '%') 2555 if ((c_ext & YACC) && *lp == '%')
2727 { 2556 {
2728 /* entering or exiting rules section in yacc file */ 2557 /* entering or exiting rules section in yacc file */
2729 lp++; 2558 lp++;
2730 definedef = dnone; fvdef = fvnone; fvextern = FALSE; 2559 definedef = dnone; fvdef = fvnone;
2731 typdef = tnone; structdef = snone; 2560 typdef = tnone; structdef = snone;
2732 next_token_is_func = FALSE; 2561 next_token_is_func = FALSE;
2733 midtoken = inquote = inchar = incomm = quotednl = FALSE; 2562 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2734 cblev = 0; 2563 cblev = 0;
2735 yacc_rules = !yacc_rules; 2564 yacc_rules = !yacc_rules;
2767 2596
2768 /* Consider token only if some complicated conditions are satisfied. */ 2597 /* Consider token only if some complicated conditions are satisfied. */
2769 if ((definedef != dnone 2598 if ((definedef != dnone
2770 || (cblev == 0 && structdef != scolonseen) 2599 || (cblev == 0 && structdef != scolonseen)
2771 || (cblev == 1 && cplpl && structdef == sinbody) 2600 || (cblev == 1 && cplpl && structdef == sinbody)
2772 || (structdef == sinbody && purec)) 2601 || (structdef == sinbody && structtype == st_C_enum))
2773 && typdef != tignore 2602 && typdef != tignore
2774 && definedef != dignorerest 2603 && definedef != dignorerest
2775 && fvdef != finlist) 2604 && fvdef != finlist)
2776 { 2605 {
2777 if (midtoken) 2606 if (midtoken)
2778 { 2607 {
2779 if (endtoken (c)) 2608 if (endtoken (c))
2780 { 2609 {
2781 bool funorvar = FALSE; 2610 if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1)))
2782
2783 if (c == ':' && cplpl && *lp == ':' && begtoken (lp[1]))
2784 { 2611 {
2785 /* 2612 /*
2786 * This handles :: in the middle, but not at the 2613 * This handles :: in the middle, but not at the
2787 * beginning of an identifier. Also, space-separated 2614 * beginning of an identifier.
2788 * :: is not recognised.
2789 */ 2615 */
2790 lp += 2; 2616 lp += 2;
2791 toklen += 2; 2617 toklen += 3;
2792 c = lp[-1];
2793 goto intok;
2794 } 2618 }
2795 else 2619 else
2796 { 2620 {
2621 bool funorvar = FALSE;
2622
2797 if (yacc_rules 2623 if (yacc_rules
2798 || consider_token (newlb.buffer + tokoff, toklen, c, 2624 || consider_token (newlb.buffer + tokoff, toklen, c,
2799 c_ext, cblev, parlev, &funorvar)) 2625 c_ext, cblev, parlev, &funorvar))
2800 { 2626 {
2801 if (fvdef == foperator)
2802 {
2803 char *oldlp = lp;
2804 lp = skip_spaces (lp-1);
2805 if (*lp != '\0')
2806 lp += 1;
2807 while (*lp != '\0'
2808 && !iswhite (*lp) && *lp != '(')
2809 lp += 1;
2810 c = *lp++;
2811 toklen += lp - oldlp;
2812 }
2813 tok.named = FALSE; 2627 tok.named = FALSE;
2814 if (!purec 2628 if (structdef == sinbody
2815 && funorvar
2816 && definedef == dnone 2629 && definedef == dnone
2817 && structdef == sinbody) 2630 && funorvar)
2818 /* function or var defined in C++ class body */ 2631 /* function or var defined in C++ class body */
2819 { 2632 {
2820 int len = strlen (structtag) + qlen + toklen; 2633 int len;
2634 if (fvdef == foperator)
2635 {
2636 char *oldlp = lp;
2637 lp = skip_spaces (lp-1);
2638 while (*lp != '\0'
2639 && !isspace (*lp) && *lp != '(')
2640 lp += 1;
2641 c = *lp++;
2642 toklen += lp - oldlp;
2643 }
2644
2645 len = strlen (structtag) + qlen + toklen;
2821 grow_linebuffer (&token_name, len + 1); 2646 grow_linebuffer (&token_name, len + 1);
2822 strcpy (token_name.buffer, structtag); 2647 strcpy (token_name.buffer, structtag);
2823 strcat (token_name.buffer, qualifier); 2648 strcat (token_name.buffer, qualifier);
2824 strncat (token_name.buffer, 2649 strncat (token_name.buffer,
2825 newlb.buffer + tokoff, toklen); 2650 newlb.buffer + tokoff, toklen);
2850 grow_linebuffer (&token_name, toklen + 1); 2675 grow_linebuffer (&token_name, toklen + 1);
2851 strncpy (token_name.buffer, 2676 strncpy (token_name.buffer,
2852 newlb.buffer + tokoff, toklen); 2677 newlb.buffer + tokoff, toklen);
2853 token_name.buffer[toklen] = '\0'; 2678 token_name.buffer[toklen] = '\0';
2854 token_name.len = toklen; 2679 token_name.len = toklen;
2855 /* Name macros and members. */ 2680 /* Name macros. */
2856 tok.named = (structdef == stagseen 2681 tok.named = (structdef == stagseen
2857 || typdef == ttypeseen
2858 || typdef == tend 2682 || typdef == tend
2859 || (funorvar 2683 || (funorvar
2860 && definedef == dignorerest) 2684 && definedef == dignorerest));
2861 || (funorvar
2862 && definedef == dnone
2863 && structdef == sinbody));
2864 } 2685 }
2865 tok.lineno = lineno; 2686 tok.lineno = lineno;
2866 tok.linelen = tokoff + toklen + 1; 2687 tok.linelen = tokoff + toklen + 1;
2867 tok.buffer = newlb.buffer; 2688 tok.buffer = newlb.buffer;
2868 tok.linepos = newlinepos; 2689 tok.linepos = newlinepos;
2883 } 2704 }
2884 midtoken = FALSE; 2705 midtoken = FALSE;
2885 } 2706 }
2886 } /* if (endtoken (c)) */ 2707 } /* if (endtoken (c)) */
2887 else if (intoken (c)) 2708 else if (intoken (c))
2888 intok:
2889 { 2709 {
2890 toklen++; 2710 toklen++;
2891 continue; 2711 continue;
2892 } 2712 }
2893 } /* if (midtoken) */ 2713 } /* if (midtoken) */
2959 make_C_tag (FALSE); /* a yacc function */ 2779 make_C_tag (FALSE); /* a yacc function */
2960 fvdef = fignore; 2780 fvdef = fignore;
2961 } 2781 }
2962 break; 2782 break;
2963 case fstartlist: 2783 case fstartlist:
2964 fvextern = FALSE;
2965 fvdef = fvnone; 2784 fvdef = fvnone;
2966 break; 2785 break;
2967 } 2786 }
2968 break; 2787 break;
2969 case ';': 2788 case ';':
2981 switch (fvdef) 2800 switch (fvdef)
2982 { 2801 {
2983 case fignore: 2802 case fignore:
2984 break; 2803 break;
2985 case fvnameseen: 2804 case fvnameseen:
2986 if ((members && cblev == 1) 2805 if ((globals && cblev == 0) || (members && cblev == 1))
2987 || (globals && cblev == 0 && (!fvextern || declarations)))
2988 make_C_tag (FALSE); /* a variable */ 2806 make_C_tag (FALSE); /* a variable */
2989 fvextern = FALSE;
2990 fvdef = fvnone;
2991 tok.valid = FALSE;
2992 break;
2993 case flistseen:
2994 if (declarations && (cblev == 0 || cblev == 1))
2995 make_C_tag (TRUE); /* a function declaration */
2996 /* FALLTHRU */ 2807 /* FALLTHRU */
2997 default: 2808 default:
2998 fvextern = FALSE;
2999 fvdef = fvnone; 2809 fvdef = fvnone;
3000 /* The following instruction invalidates the token. 2810 /* The following instruction invalidates the token.
3001 Probably the token should be invalidated in all 2811 Probably the token should be invalidated in all
3002 other cases where some state machine is reset. */ 2812 other cases where some state machine is reset. */
3003 tok.valid = FALSE; 2813 tok.valid = FALSE;
3022 case finlist: 2832 case finlist:
3023 case fignore: 2833 case fignore:
3024 case vignore: 2834 case vignore:
3025 break; 2835 break;
3026 case fvnameseen: 2836 case fvnameseen:
3027 if ((members && cblev == 1) 2837 if ((globals && cblev == 0) || (members && cblev == 1))
3028 || (globals && cblev == 0 && (!fvextern || declarations)))
3029 make_C_tag (FALSE); /* a variable */ 2838 make_C_tag (FALSE); /* a variable */
3030 break; 2839 break;
3031 default: 2840 default:
3032 fvdef = fvnone; 2841 fvdef = fvnone;
3033 } 2842 }
3049 case finlist: 2858 case finlist:
3050 case fignore: 2859 case fignore:
3051 case vignore: 2860 case vignore:
3052 break; 2861 break;
3053 case fvnameseen: 2862 case fvnameseen:
3054 if ((members && cblev == 1) 2863 if ((globals && cblev == 0) || (members && cblev == 1))
3055 || (globals && cblev == 0 && (!fvextern || declarations)))
3056 make_C_tag (FALSE); /* a variable */ 2864 make_C_tag (FALSE); /* a variable */
3057 /* FALLTHRU */ 2865 /* FALLTHRU */
3058 default: 2866 default:
3059 fvdef = fvnone; 2867 fvdef = fvnone;
3060 } 2868 }
3066 break; 2874 break;
3067 if (objdef == otagseen && parlev == 0) 2875 if (objdef == otagseen && parlev == 0)
3068 objdef = oparenseen; 2876 objdef = oparenseen;
3069 switch (fvdef) 2877 switch (fvdef)
3070 { 2878 {
2879 case fvnone:
2880 switch (typdef)
2881 {
2882 case ttypedseen:
2883 case tend:
2884 if (tok.valid && *lp != '*')
2885 {
2886 /* This handles constructs like:
2887 typedef void OperatorFun (int fun); */
2888 make_C_tag (FALSE);
2889 typdef = tignore;
2890 }
2891 break;
2892 } /* switch (typdef) */
2893 break;
2894 case foperator: /* operator() is not handled */
3071 case fvnameseen: 2895 case fvnameseen:
3072 if (typdef == ttypeseen
3073 && tok.valid
3074 && *lp != '*'
3075 && structdef != sinbody)
3076 {
3077 /* This handles constructs like:
3078 typedef void OperatorFun (int fun); */
3079 make_C_tag (FALSE);
3080 typdef = tignore;
3081 }
3082 /* FALLTHRU */
3083 case foperator:
3084 fvdef = fstartlist; 2896 fvdef = fstartlist;
3085 break; 2897 break;
3086 case flistseen: 2898 case flistseen:
3087 fvdef = finlist; 2899 fvdef = finlist;
3088 break; 2900 break;
3104 case fstartlist: 2916 case fstartlist:
3105 case finlist: 2917 case finlist:
3106 fvdef = flistseen; 2918 fvdef = flistseen;
3107 break; 2919 break;
3108 } 2920 }
3109 if (cblev == 0 && (typdef == tend)) 2921 if (cblev == 0 && typdef == tend)
3110 { 2922 {
3111 typdef = tignore; 2923 typdef = tignore;
3112 make_C_tag (FALSE); /* a typedef */ 2924 make_C_tag (FALSE); /* a typedef */
3113 } 2925 }
3114 } 2926 }
3116 parlev = 0; 2928 parlev = 0;
3117 break; 2929 break;
3118 case '{': 2930 case '{':
3119 if (definedef != dnone) 2931 if (definedef != dnone)
3120 break; 2932 break;
3121 if (typdef == ttypeseen) 2933 if (typdef == ttypedseen)
3122 typdef = tinbody; 2934 typdef = tinbody;
3123 switch (structdef) 2935 switch (structdef)
3124 { 2936 {
3125 case skeyseen: /* unnamed struct */ 2937 case skeyseen: /* unnamed struct */
3126 structdef = sinbody; 2938 structdef = sinbody;
3201 case finlist: 3013 case finlist:
3202 case fignore: 3014 case fignore:
3203 case vignore: 3015 case vignore:
3204 break; 3016 break;
3205 case fvnameseen: 3017 case fvnameseen:
3206 if ((members && cblev == 1) 3018 if ((globals && cblev == 0) || (members && cblev == 1))
3207 || (globals && cblev == 0 && (!fvextern || declarations)))
3208 make_C_tag (FALSE); /* a variable */ 3019 make_C_tag (FALSE); /* a variable */
3209 /* FALLTHRU */ 3020 /* FALLTHRU */
3210 default: 3021 default:
3211 fvdef = vignore; 3022 fvdef = vignore;
3212 } 3023 }
3254 3065
3255 /* 3066 /*
3256 * Process either a C++ file or a C file depending on the setting 3067 * Process either a C++ file or a C file depending on the setting
3257 * of a global flag. 3068 * of a global flag.
3258 */ 3069 */
3259 static void 3070 void
3260 default_C_entries (inf) 3071 default_C_entries (inf)
3261 FILE *inf; 3072 FILE *inf;
3262 { 3073 {
3263 C_entries (cplusplus ? C_PLPL : 0, inf); 3074 C_entries (cplusplus ? C_PLPL : 0, inf);
3264 } 3075 }
3265 3076
3266 /* Always do plain ANSI C. */ 3077 /* Always do plain ANSI C. */
3267 static void 3078 void
3268 plain_C_entries (inf) 3079 plain_C_entries (inf)
3269 FILE *inf; 3080 FILE *inf;
3270 { 3081 {
3271 C_entries (0, inf); 3082 C_entries (0, inf);
3272 } 3083 }
3273 3084
3274 /* Always do C++. */ 3085 /* Always do C++. */
3275 static void 3086 void
3276 Cplusplus_entries (inf) 3087 Cplusplus_entries (inf)
3277 FILE *inf; 3088 FILE *inf;
3278 { 3089 {
3279 C_entries (C_PLPL, inf); 3090 C_entries (C_PLPL, inf);
3280 } 3091 }
3281 3092
3282 /* Always do Java. */ 3093 /* Always do Java. */
3283 static void 3094 void
3284 Cjava_entries (inf) 3095 Cjava_entries (inf)
3285 FILE *inf; 3096 FILE *inf;
3286 { 3097 {
3287 C_entries (C_JAVA, inf); 3098 C_entries (C_JAVA, inf);
3288 } 3099 }
3289 3100
3290 /* Always do C*. */ 3101 /* Always do C*. */
3291 static void 3102 void
3292 Cstar_entries (inf) 3103 Cstar_entries (inf)
3293 FILE *inf; 3104 FILE *inf;
3294 { 3105 {
3295 C_entries (C_STAR, inf); 3106 C_entries (C_STAR, inf);
3296 } 3107 }
3297 3108
3298 /* Always do Yacc. */ 3109 /* Always do Yacc. */
3299 static void 3110 void
3300 Yacc_entries (inf) 3111 Yacc_entries (inf)
3301 FILE *inf; 3112 FILE *inf;
3302 { 3113 {
3303 C_entries (YACC, inf); 3114 C_entries (YACC, inf);
3304 } 3115 }
3305 3116
3306 /* A useful macro. */ 3117 /* A useful macro. */
3307 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \ 3118 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3308 for (lineno = charno = 0; /* loop initialization */ \ 3119 for (lineno = charno = 0; /* loop initialization */ \
3309 !feof (file_pointer) /* loop test */ \ 3120 !feof (file_pointer) /* loop test */ \
3310 && (lineno++, /* instructions at start of loop */ \ 3121 && (lineno++, /* instructions at start of loop */ \
3311 linecharno = charno, \ 3122 linecharno = charno, \
3317 3128
3318 /* 3129 /*
3319 * Read a file, but do no processing. This is used to do regexp 3130 * Read a file, but do no processing. This is used to do regexp
3320 * matching on files that have no language defined. 3131 * matching on files that have no language defined.
3321 */ 3132 */
3322 static void 3133 void
3323 just_read_file (inf) 3134 just_read_file (inf)
3324 FILE *inf; 3135 FILE *inf;
3325 { 3136 {
3326 register char *dummy; 3137 register char *dummy;
3327 3138
3329 continue; 3140 continue;
3330 } 3141 }
3331 3142
3332 /* Fortran parsing */ 3143 /* Fortran parsing */
3333 3144
3334 static bool tail P_((char *)); 3145 bool
3335 static void takeprec P_((void));
3336 static void getit P_((FILE *));
3337
3338 static bool
3339 tail (cp) 3146 tail (cp)
3340 char *cp; 3147 char *cp;
3341 { 3148 {
3342 register int len = 0; 3149 register int len = 0;
3343 3150
3344 while (*cp != '\0' && lowcase (*cp) == lowcase (dbp[len])) 3151 while (*cp && lowcase(*cp) == lowcase(dbp[len]))
3345 cp++, len++; 3152 cp++, len++;
3346 if (*cp == '\0' && !intoken (dbp[len])) 3153 if (*cp == '\0' && !intoken(dbp[len]))
3347 { 3154 {
3348 dbp += len; 3155 dbp += len;
3349 return TRUE; 3156 return TRUE;
3350 } 3157 }
3351 return FALSE; 3158 return FALSE;
3352 } 3159 }
3353 3160
3354 static void 3161 void
3355 takeprec () 3162 takeprec ()
3356 { 3163 {
3357 dbp = skip_spaces (dbp); 3164 dbp = skip_spaces (dbp);
3358 if (*dbp != '*') 3165 if (*dbp != '*')
3359 return; 3166 return;
3362 if (strneq (dbp, "(*)", 3)) 3169 if (strneq (dbp, "(*)", 3))
3363 { 3170 {
3364 dbp += 3; 3171 dbp += 3;
3365 return; 3172 return;
3366 } 3173 }
3367 if (!isdigit ((unsigned char) *dbp)) 3174 if (!isdigit (*dbp))
3368 { 3175 {
3369 --dbp; /* force failure */ 3176 --dbp; /* force failure */
3370 return; 3177 return;
3371 } 3178 }
3372 do 3179 do
3373 dbp++; 3180 dbp++;
3374 while (isdigit ((unsigned char) *dbp)); 3181 while (isdigit (*dbp));
3375 } 3182 }
3376 3183
3377 static void 3184 void
3378 getit (inf) 3185 getit (inf)
3379 FILE *inf; 3186 FILE *inf;
3380 { 3187 {
3381 register char *cp; 3188 register char *cp;
3382 3189
3390 if (dbp[5] != '&') 3197 if (dbp[5] != '&')
3391 return; 3198 return;
3392 dbp += 6; 3199 dbp += 6;
3393 dbp = skip_spaces (dbp); 3200 dbp = skip_spaces (dbp);
3394 } 3201 }
3395 if (!isalpha ((unsigned char) *dbp) && *dbp != '_' && *dbp != '$') 3202 if (!isalpha (*dbp)
3203 && *dbp != '_'
3204 && *dbp != '$')
3396 return; 3205 return;
3397 for (cp = dbp + 1; *cp != '\0' && intoken (*cp); cp++) 3206 for (cp = dbp + 1; *cp && intoken (*cp); cp++)
3398 continue; 3207 continue;
3399 pfnote (savenstr (dbp, cp-dbp), TRUE, 3208 pfnote (savenstr (dbp, cp-dbp), TRUE,
3400 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3209 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3401 } 3210 }
3402 3211
3403 3212
3404 static void 3213 void
3405 Fortran_functions (inf) 3214 Fortran_functions (inf)
3406 FILE *inf; 3215 FILE *inf;
3407 { 3216 {
3408 LOOP_ON_INPUT_LINES (inf, lb, dbp) 3217 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3409 { 3218 {
3457 continue; 3266 continue;
3458 case 'e': 3267 case 'e':
3459 if (tail ("entry")) 3268 if (tail ("entry"))
3460 getit (inf); 3269 getit (inf);
3461 continue; 3270 continue;
3271 case 'p':
3272 if (tail ("program") || tail ("procedure"))
3273 getit (inf);
3274 continue;
3462 case 'b': 3275 case 'b':
3463 if (tail ("blockdata") || tail ("block data")) 3276 if (tail ("blockdata") || tail ("block data"))
3464 { 3277 {
3465 dbp = skip_spaces (dbp); 3278 dbp = skip_spaces (dbp);
3466 if (*dbp == '\0') /* assume un-named */ 3279 if (*dbp == '\0') /* assume un-named */
3473 } 3286 }
3474 } 3287 }
3475 } 3288 }
3476 3289
3477 /* 3290 /*
3478 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be>, 1998-04-24
3479 * Ada parsing
3480 */
3481
3482 static void adagetit P_((FILE *, char *));
3483
3484 /* Once we are positioned after an "interesting" keyword, let's get
3485 the real tag value necessary. */
3486 static void
3487 adagetit (inf, name_qualifier)
3488 FILE *inf;
3489 char *name_qualifier;
3490 {
3491 register char *cp;
3492 char *name;
3493 char c;
3494
3495 while (!feof (inf))
3496 {
3497 dbp = skip_spaces (dbp);
3498 if (*dbp == '\0'
3499 || (dbp[0] == '-' && dbp[1] == '-'))
3500 {
3501 lineno++;
3502 linecharno = charno;
3503 charno += readline (&lb, inf);
3504 dbp = lb.buffer;
3505 }
3506 switch (*dbp)
3507 {
3508 case 'b':
3509 case 'B':
3510 if (tail ("body"))
3511 {
3512 /* Skipping body of procedure body or package body or ....
3513 resetting qualifier to body instead of spec. */
3514 name_qualifier = "/b";
3515 continue;
3516 }
3517 break;
3518 case 't':
3519 case 'T':
3520 /* Skipping type of task type or protected type ... */
3521 if (tail ("type"))
3522 continue;
3523 break;
3524 }
3525 if (*dbp == '"')
3526 {
3527 dbp += 1;
3528 for (cp = dbp; *cp != '\0' && *cp != '"'; cp++)
3529 continue;
3530 }
3531 else
3532 {
3533 dbp = skip_spaces (dbp);
3534 for (cp = dbp;
3535 (*cp != '\0'
3536 && (isalpha ((unsigned char) *cp) || isdigit ((unsigned char) *cp) || *cp == '_' || *cp == '.'));
3537 cp++)
3538 continue;
3539 if (cp == dbp)
3540 return;
3541 }
3542 c = *cp;
3543 *cp = '\0';
3544 name = concat (dbp, name_qualifier, "");
3545 *cp = c;
3546 pfnote (name, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3547 if (c == '"')
3548 dbp = cp + 1;
3549 return;
3550 }
3551 }
3552
3553 static void
3554 Ada_funcs (inf)
3555 FILE *inf;
3556 {
3557 bool inquote = FALSE;
3558
3559 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3560 {
3561 while (*dbp != '\0')
3562 {
3563 /* Skip a string i.e. "abcd". */
3564 if (inquote || (*dbp == '"'))
3565 {
3566 dbp = etags_strchr ((inquote) ? dbp : dbp+1, '"');
3567 if (dbp != NULL)
3568 {
3569 inquote = FALSE;
3570 dbp += 1;
3571 continue; /* advance char */
3572 }
3573 else
3574 {
3575 inquote = TRUE;
3576 break; /* advance line */
3577 }
3578 }
3579
3580 /* Skip comments. */
3581 if (dbp[0] == '-' && dbp[1] == '-')
3582 break; /* advance line */
3583
3584 /* Skip character enclosed in single quote i.e. 'a'
3585 and skip single quote starting an attribute i.e. 'Image. */
3586 if (*dbp == '\'')
3587 {
3588 dbp++ ;
3589 if (*dbp != '\0')
3590 dbp++;
3591 continue;
3592 }
3593
3594 /* Search for beginning of a token. */
3595 if (!begtoken (*dbp))
3596 {
3597 dbp++;
3598 continue; /* advance char */
3599 }
3600
3601 /* We are at the beginning of a token. */
3602 switch (*dbp)
3603 {
3604 case 'f':
3605 case 'F':
3606 if (!packages_only && tail ("function"))
3607 adagetit (inf, "/f");
3608 else
3609 break; /* from switch */
3610 continue; /* advance char */
3611 case 'p':
3612 case 'P':
3613 if (!packages_only && tail ("procedure"))
3614 adagetit (inf, "/p");
3615 else if (tail ("package"))
3616 adagetit (inf, "/s");
3617 else if (tail ("protected")) /* protected type */
3618 adagetit (inf, "/t");
3619 else
3620 break; /* from switch */
3621 continue; /* advance char */
3622 case 't':
3623 case 'T':
3624 if (!packages_only && tail ("task"))
3625 adagetit (inf, "/k");
3626 else if (typedefs && !packages_only && tail ("type"))
3627 {
3628 adagetit (inf, "/t");
3629 while (*dbp != '\0')
3630 dbp += 1;
3631 }
3632 else
3633 break; /* from switch */
3634 continue; /* advance char */
3635 }
3636
3637 /* Look for the end of the token. */
3638 while (!endtoken (*dbp))
3639 dbp++;
3640
3641 } /* advance char */
3642 } /* advance line */
3643 }
3644
3645 /*
3646 * Bob Weiner, Motorola Inc., 4/3/94 3291 * Bob Weiner, Motorola Inc., 4/3/94
3647 * Unix and microcontroller assembly tag handling 3292 * Unix and microcontroller assembly tag handling
3648 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]' 3293 * look for '^[a-zA-Z_.$][a-zA_Z0-9_.$]*[: ^I^J]'
3649 */ 3294 */
3650 static void 3295 void
3651 Asm_labels (inf) 3296 Asm_labels (inf)
3652 FILE *inf; 3297 FILE *inf;
3653 { 3298 {
3654 register char *cp; 3299 register char *cp;
3655 3300
3656 LOOP_ON_INPUT_LINES (inf, lb, cp) 3301 LOOP_ON_INPUT_LINES (inf, lb, cp)
3657 { 3302 {
3658 /* If first char is alphabetic or one of [_.$], test for colon 3303 /* If first char is alphabetic or one of [_.$], test for colon
3659 following identifier. */ 3304 following identifier. */
3660 if (isalpha ((unsigned char) *cp) || *cp == '_' || *cp == '.' || *cp == '$') 3305 if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3661 { 3306 {
3662 /* Read past label. */ 3307 /* Read past label. */
3663 cp++; 3308 cp++;
3664 while (isalnum ((unsigned char) *cp) || *cp == '_' || *cp == '.' || *cp == '$') 3309 while (isalnum (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3665 cp++; 3310 cp++;
3666 if (*cp == ':' || iswhite (*cp)) 3311 if (*cp == ':' || isspace (*cp))
3667 { 3312 {
3668 /* Found end of label, so copy it and add it to the table. */ 3313 /* Found end of label, so copy it and add it to the table. */
3669 pfnote (savenstr(lb.buffer, cp-lb.buffer), TRUE, 3314 pfnote ((CTAGS) ? savenstr(lb.buffer, cp-lb.buffer) : NULL, TRUE,
3670 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3315 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3671 } 3316 }
3672 } 3317 }
3673 } 3318 }
3674 } 3319 }
3677 * Perl support by Bart Robinson <lomew@cs.utah.edu> 3322 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3678 * enhanced by Michael Ernst <mernst@alum.mit.edu> 3323 * enhanced by Michael Ernst <mernst@alum.mit.edu>
3679 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/ 3324 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3680 * Perl variable names: /^(my|local).../ 3325 * Perl variable names: /^(my|local).../
3681 */ 3326 */
3682 static void 3327 void
3683 Perl_functions (inf) 3328 Perl_functions (inf)
3684 FILE *inf; 3329 FILE *inf;
3685 { 3330 {
3686 register char *cp; 3331 register char *cp;
3687 3332
3688 LOOP_ON_INPUT_LINES (inf, lb, cp) 3333 LOOP_ON_INPUT_LINES (inf, lb, cp)
3689 { 3334 {
3690 if (*cp++ == 's' 3335 if (*cp++ == 's'
3691 && *cp++ == 'u' 3336 && *cp++ == 'u'
3692 && *cp++ == 'b' && iswhite (*cp++)) 3337 && *cp++ == 'b' && isspace (*cp++))
3693 { 3338 {
3694 cp = skip_spaces (cp); 3339 cp = skip_spaces (cp);
3695 if (*cp != '\0') 3340 if (*cp != '\0')
3696 { 3341 {
3697 char *sp = cp; 3342 char *sp = cp;
3698 while (*cp != '\0' 3343 while (*cp != '\0'
3699 && !iswhite (*cp) && *cp != '{' && *cp != '(') 3344 && !isspace (*cp) && *cp != '{' && *cp != '(')
3700 cp++; 3345 cp++;
3701 pfnote (savenstr (sp, cp-sp), TRUE, 3346 pfnote (savenstr (sp, cp-sp), TRUE,
3702 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3347 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3703 } 3348 }
3704 } 3349 }
3705 else if (globals /* only if tagging global vars is enabled */ 3350 else if (globals /* only if tagging global vars is enabled */
3706 && ((cp = lb.buffer, 3351 && ((cp = lb.buffer,
3707 *cp++ == 'm' 3352 *cp++ == 'm'
3708 && *cp++ == 'y') 3353 && *cp++ == 'y')
3710 *cp++ == 'l' 3355 *cp++ == 'l'
3711 && *cp++ == 'o' 3356 && *cp++ == 'o'
3712 && *cp++ == 'c' 3357 && *cp++ == 'c'
3713 && *cp++ == 'a' 3358 && *cp++ == 'a'
3714 && *cp++ == 'l')) 3359 && *cp++ == 'l'))
3715 && (*cp == '(' || iswhite (*cp))) 3360 && (*cp == '(' || isspace (*cp)))
3716 { 3361 {
3717 /* After "my" or "local", but before any following paren or space. */ 3362 /* After "my" or "local", but before any following paren or space. */
3718 char *varname = NULL; 3363 char *varname = NULL;
3719 3364
3720 cp = skip_spaces (cp); 3365 cp = skip_spaces (cp);
3721 if (*cp == '$' || *cp == '@' || *cp == '%') 3366 if (*cp == '$' || *cp == '@' || *cp == '%')
3722 { 3367 {
3723 char* varstart = ++cp; 3368 char* varstart = ++cp;
3724 while (isalnum ((unsigned char) *cp) || *cp == '_') 3369 while (isalnum (*cp) || *cp == '_')
3725 cp++; 3370 cp++;
3726 varname = savenstr (varstart, cp-varstart); 3371 varname = savenstr (varstart, cp-varstart);
3727 } 3372 }
3728 else 3373 else
3729 { 3374 {
3730 /* Should be examining a variable list at this point; 3375 /* Should be examining a variable list at this point;
3731 could insist on seeing an open parenthesis. */ 3376 could insist on seeing an open parenthesis. */
3732 while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')') 3377 while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
3733 cp++; 3378 cp++;
3734 } 3379 }
3735 3380
3736 /* Perhaps I should back cp up one character, so the TAGS table 3381 /* Perhaps I should back cp up one character, so the TAGS table
3737 doesn't mention (and so depend upon) the following char. */ 3382 doesn't mention (and so depend upon) the following char. */
3738 pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname, 3383 pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname,
3739 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3384 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3740 } 3385 }
3743 3388
3744 /* 3389 /*
3745 * Python support by Eric S. Raymond <esr@thyrsus.com> 3390 * Python support by Eric S. Raymond <esr@thyrsus.com>
3746 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/ 3391 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
3747 */ 3392 */
3748 static void 3393 void
3749 Python_functions (inf) 3394 Python_functions (inf)
3750 FILE *inf; 3395 FILE *inf;
3751 { 3396 {
3752 register char *cp; 3397 register char *cp;
3753 3398
3754 LOOP_ON_INPUT_LINES (inf, lb, cp) 3399 LOOP_ON_INPUT_LINES (inf, lb, cp)
3755 { 3400 {
3756 if (*cp++ == 'd' 3401 if (*cp++ == 'd'
3757 && *cp++ == 'e' 3402 && *cp++ == 'e'
3758 && *cp++ == 'f' && iswhite (*cp++)) 3403 && *cp++ == 'f' && isspace (*cp++))
3759 { 3404 {
3760 cp = skip_spaces (cp); 3405 cp = skip_spaces (cp);
3761 while (*cp != '\0' && !iswhite (*cp) && *cp != '(' && *cp != ':') 3406 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3762 cp++; 3407 cp++;
3763 pfnote (NULL, TRUE, 3408 pfnote (NULL, TRUE,
3764 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3409 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3765 } 3410 }
3766 3411
3767 cp = lb.buffer; 3412 cp = lb.buffer;
3768 if (*cp++ == 'c' 3413 if (*cp++ == 'c'
3769 && *cp++ == 'l' 3414 && *cp++ == 'l'
3770 && *cp++ == 'a' 3415 && *cp++ == 'a'
3771 && *cp++ == 's' 3416 && *cp++ == 's'
3772 && *cp++ == 's' && iswhite (*cp++)) 3417 && *cp++ == 's' && isspace (*cp++))
3773 { 3418 {
3774 cp = skip_spaces (cp); 3419 cp = skip_spaces (cp);
3775 while (*cp != '\0' && !iswhite (*cp) && *cp != '(' && *cp != ':') 3420 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3776 cp++; 3421 cp++;
3777 pfnote (NULL, TRUE, 3422 pfnote (NULL, TRUE,
3778 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3423 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3779 } 3424 }
3780 } 3425 }
3783 /* Idea by Corny de Souza 3428 /* Idea by Corny de Souza
3784 * Cobol tag functions 3429 * Cobol tag functions
3785 * We could look for anything that could be a paragraph name. 3430 * We could look for anything that could be a paragraph name.
3786 * i.e. anything that starts in column 8 is one word and ends in a full stop. 3431 * i.e. anything that starts in column 8 is one word and ends in a full stop.
3787 */ 3432 */
3788 static void 3433 void
3789 Cobol_paragraphs (inf) 3434 Cobol_paragraphs (inf)
3790 FILE *inf; 3435 FILE *inf;
3791 { 3436 {
3792 register char *bp, *ep; 3437 register char *bp, *ep;
3793 3438
3796 if (lb.len < 9) 3441 if (lb.len < 9)
3797 continue; 3442 continue;
3798 bp += 8; 3443 bp += 8;
3799 3444
3800 /* If eoln, compiler option or comment ignore whole line. */ 3445 /* If eoln, compiler option or comment ignore whole line. */
3801 if (bp[-1] != ' ' || !isalnum ((unsigned char) bp[0])) 3446 if (bp[-1] != ' ' || !isalnum (bp[0]))
3802 continue; 3447 continue;
3803 3448
3804 for (ep = bp; isalnum ((unsigned char) *ep) || *ep == '-'; ep++) 3449 for (ep = bp; isalnum (*ep) || *ep == '-'; ep++)
3805 continue; 3450 continue;
3806 if (*ep++ == '.') 3451 if (*ep++ == '.')
3807 pfnote (savenstr (bp, ep-bp), TRUE, 3452 pfnote (savenstr (bp, ep-bp), TRUE,
3808 lb.buffer, ep - lb.buffer + 1, lineno, linecharno); 3453 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
3809 } 3454 }
3816 * Locates tags for procedures & functions. Doesn't do any type- or 3461 * Locates tags for procedures & functions. Doesn't do any type- or
3817 * var-definitions. It does look for the keyword "extern" or 3462 * var-definitions. It does look for the keyword "extern" or
3818 * "forward" immediately following the procedure statement; if found, 3463 * "forward" immediately following the procedure statement; if found,
3819 * the tag is skipped. 3464 * the tag is skipped.
3820 */ 3465 */
3821 static void 3466 void
3822 Pascal_functions (inf) 3467 Pascal_functions (inf)
3823 FILE *inf; 3468 FILE *inf;
3824 { 3469 {
3825 linebuffer tline; /* mostly copied from C_entries */ 3470 linebuffer tline; /* mostly copied from C_entries */
3826 long save_lcno; 3471 long save_lcno;
3851 found_tag = FALSE; /* have a proc name; check if extern */ 3496 found_tag = FALSE; /* have a proc name; check if extern */
3852 get_tagname = FALSE; /* have found "procedure" keyword */ 3497 get_tagname = FALSE; /* have found "procedure" keyword */
3853 inparms = FALSE; /* found '(' after "proc" */ 3498 inparms = FALSE; /* found '(' after "proc" */
3854 verify_tag = FALSE; /* check if "extern" is ahead */ 3499 verify_tag = FALSE; /* check if "extern" is ahead */
3855 3500
3856 3501
3857 while (!feof (inf)) /* long main loop to get next char */ 3502 while (!feof (inf)) /* long main loop to get next char */
3858 { 3503 {
3859 c = *dbp++; 3504 c = *dbp++;
3860 if (c == '\0') /* if end of line */ 3505 if (c == '\0') /* if end of line */
3861 { 3506 {
3862 lineno++; 3507 lineno++;
3993 3638
3994 /* 3639 /*
3995 * lisp tag functions 3640 * lisp tag functions
3996 * look for (def or (DEF, quote or QUOTE 3641 * look for (def or (DEF, quote or QUOTE
3997 */ 3642 */
3998 3643 int
3999 static int L_isdef P_((char *));
4000 static int L_isquote P_((char *));
4001 static void L_getit P_((void));
4002
4003 static int
4004 L_isdef (strp) 3644 L_isdef (strp)
4005 register char *strp; 3645 register char *strp;
4006 { 3646 {
4007 return ((strp[1] == 'd' || strp[1] == 'D') 3647 return ((strp[1] == 'd' || strp[1] == 'D')
4008 && (strp[2] == 'e' || strp[2] == 'E') 3648 && (strp[2] == 'e' || strp[2] == 'E')
4009 && (strp[3] == 'f' || strp[3] == 'F')); 3649 && (strp[3] == 'f' || strp[3] == 'F'));
4010 } 3650 }
4011 3651
4012 static int 3652 int
4013 L_isquote (strp) 3653 L_isquote (strp)
4014 register char *strp; 3654 register char *strp;
4015 { 3655 {
4016 return ((*++strp == 'q' || *strp == 'Q') 3656 return ((*++strp == 'q' || *strp == 'Q')
4017 && (*++strp == 'u' || *strp == 'U') 3657 && (*++strp == 'u' || *strp == 'U')
4018 && (*++strp == 'o' || *strp == 'O') 3658 && (*++strp == 'o' || *strp == 'O')
4019 && (*++strp == 't' || *strp == 'T') 3659 && (*++strp == 't' || *strp == 'T')
4020 && (*++strp == 'e' || *strp == 'E') 3660 && (*++strp == 'e' || *strp == 'E')
4021 && iswhite (*++strp)); 3661 && isspace (*++strp));
4022 } 3662 }
4023 3663
4024 static void 3664 void
4025 L_getit () 3665 L_getit ()
4026 { 3666 {
4027 register char *cp; 3667 register char *cp;
4028 3668
4029 if (*dbp == '\'') /* Skip prefix quote */ 3669 if (*dbp == '\'') /* Skip prefix quote */
4036 dbp += 1; /* Skip "(" before name in (defstruct (foo)) */ 3676 dbp += 1; /* Skip "(" before name in (defstruct (foo)) */
4037 dbp = skip_spaces (dbp); 3677 dbp = skip_spaces (dbp);
4038 } 3678 }
4039 3679
4040 for (cp = dbp /*+1*/; 3680 for (cp = dbp /*+1*/;
4041 *cp != '\0' && *cp != '(' && !iswhite(*cp) && *cp != ')'; 3681 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')';
4042 cp++) 3682 cp++)
4043 continue; 3683 continue;
4044 if (cp == dbp) 3684 if (cp == dbp)
4045 return; 3685 return;
4046 3686
4047 pfnote (savenstr (dbp, cp-dbp), TRUE, 3687 pfnote (savenstr (dbp, cp-dbp), TRUE,
4048 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3688 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4049 } 3689 }
4050 3690
4051 static void 3691 void
4052 Lisp_functions (inf) 3692 Lisp_functions (inf)
4053 FILE *inf; 3693 FILE *inf;
4054 { 3694 {
4055 LOOP_ON_INPUT_LINES (inf, lb, dbp) 3695 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4056 { 3696 {
4065 else 3705 else
4066 { 3706 {
4067 /* Check for (foo::defmumble name-defined ... */ 3707 /* Check for (foo::defmumble name-defined ... */
4068 do 3708 do
4069 dbp++; 3709 dbp++;
4070 while (*dbp != '\0' && !iswhite (*dbp) 3710 while (*dbp != '\0' && !isspace (*dbp)
4071 && *dbp != ':' && *dbp != '(' && *dbp != ')'); 3711 && *dbp != ':' && *dbp != '(' && *dbp != ')');
4072 if (*dbp == ':') 3712 if (*dbp == ':')
4073 { 3713 {
4074 do 3714 do
4075 dbp++; 3715 dbp++;
4089 3729
4090 /* 3730 /*
4091 * Postscript tag functions 3731 * Postscript tag functions
4092 * Just look for lines where the first character is '/' 3732 * Just look for lines where the first character is '/'
4093 * Richard Mlynarik <mly@adoc.xerox.com> 3733 * Richard Mlynarik <mly@adoc.xerox.com>
4094 * Also look at "defineps" for PSWrap 3734 */
4095 * suggested by Masatake YAMATO <masata-y@is.aist-nara.ac.jp> 3735 void
4096 */
4097 static void
4098 Postscript_functions (inf) 3736 Postscript_functions (inf)
4099 FILE *inf; 3737 FILE *inf;
4100 { 3738 {
4101 register char *bp, *ep; 3739 register char *bp, *ep;
4102 3740
4106 { 3744 {
4107 for (ep = bp+1; 3745 for (ep = bp+1;
4108 *ep != '\0' && *ep != ' ' && *ep != '{'; 3746 *ep != '\0' && *ep != ' ' && *ep != '{';
4109 ep++) 3747 ep++)
4110 continue; 3748 continue;
4111 pfnote (savenstr (bp, ep-bp), TRUE, 3749 pfnote ((CTAGS) ? savenstr (bp, ep-bp) : NULL, TRUE,
4112 lb.buffer, ep - lb.buffer + 1, lineno, linecharno); 3750 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4113 }
4114 else if (strneq (bp, "defineps", 8))
4115 {
4116 bp = skip_non_spaces (bp);
4117 bp = skip_spaces (bp);
4118 get_tag (bp);
4119 } 3751 }
4120 } 3752 }
4121 } 3753 }
4122 3754
4123 3755
4127 * look for (def... (xyzzy 3759 * look for (def... (xyzzy
4128 * look for (def ... ((...(xyzzy .... 3760 * look for (def ... ((...(xyzzy ....
4129 * look for (set! xyzzy 3761 * look for (set! xyzzy
4130 */ 3762 */
4131 3763
4132 static void 3764 void get_scheme ();
3765
3766 void
4133 Scheme_functions (inf) 3767 Scheme_functions (inf)
4134 FILE *inf; 3768 FILE *inf;
4135 { 3769 {
4136 register char *bp; 3770 LOOP_ON_INPUT_LINES (inf, lb, dbp)
4137 3771 {
4138 LOOP_ON_INPUT_LINES (inf, lb, bp) 3772 if (dbp[0] == '('
4139 { 3773 && (dbp[1] == 'D' || dbp[1] == 'd')
4140 if (bp[0] == '(' 3774 && (dbp[2] == 'E' || dbp[2] == 'e')
4141 && (bp[1] == 'D' || bp[1] == 'd') 3775 && (dbp[3] == 'F' || dbp[3] == 'f'))
4142 && (bp[2] == 'E' || bp[2] == 'e') 3776 {
4143 && (bp[3] == 'F' || bp[3] == 'f')) 3777 dbp = skip_non_spaces (dbp);
4144 {
4145 bp = skip_non_spaces (bp);
4146 /* Skip over open parens and white space */ 3778 /* Skip over open parens and white space */
4147 while (iswhite (*bp) || *bp == '(') 3779 while (isspace (*dbp) || *dbp == '(')
4148 bp++; 3780 dbp++;
4149 get_tag (bp); 3781 get_scheme ();
4150 } 3782 }
4151 if (bp[0] == '(' 3783 if (dbp[0] == '('
4152 && (bp[1] == 'S' || bp[1] == 's') 3784 && (dbp[1] == 'S' || dbp[1] == 's')
4153 && (bp[2] == 'E' || bp[2] == 'e') 3785 && (dbp[2] == 'E' || dbp[2] == 'e')
4154 && (bp[3] == 'T' || bp[3] == 't') 3786 && (dbp[3] == 'T' || dbp[3] == 't')
4155 && (bp[4] == '!' || bp[4] == '!') 3787 && (dbp[4] == '!' || dbp[4] == '!')
4156 && (iswhite (bp[5]))) 3788 && (isspace (dbp[5])))
4157 { 3789 {
4158 bp = skip_non_spaces (bp); 3790 dbp = skip_non_spaces (dbp);
4159 bp = skip_spaces (bp); 3791 dbp = skip_spaces (dbp);
4160 get_tag (bp); 3792 get_scheme ();
4161 } 3793 }
4162 } 3794 }
3795 }
3796
3797 void
3798 get_scheme ()
3799 {
3800 register char *cp;
3801
3802 if (*dbp == '\0')
3803 return;
3804 /* Go till you get to white space or a syntactic break */
3805 for (cp = dbp + 1;
3806 *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp);
3807 cp++)
3808 continue;
3809 pfnote (savenstr (dbp, cp-dbp), TRUE,
3810 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4163 } 3811 }
4164 3812
4165 /* Find tags in TeX and LaTeX input files. */ 3813 /* Find tags in TeX and LaTeX input files. */
4166 3814
4167 /* TEX_toktab is a table of TeX control sequences that define tags. 3815 /* TEX_toktab is a table of TeX control sequences that define tags.
4180 3828
4181 char *TEX_defenv = "\ 3829 char *TEX_defenv = "\
4182 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\ 3830 :chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem\
4183 :part:appendix:entry:index"; 3831 :part:appendix:entry:index";
4184 3832
4185 static void TEX_mode P_((FILE *)); 3833 void TEX_mode ();
4186 static struct TEX_tabent *TEX_decode_env P_((char *, char *)); 3834 struct TEX_tabent *TEX_decode_env ();
4187 static int TEX_Token P_((char *)); 3835 int TEX_Token ();
4188 3836
4189 char TEX_esc = '\\'; 3837 char TEX_esc = '\\';
4190 char TEX_opgrp = '{'; 3838 char TEX_opgrp = '{';
4191 char TEX_clgrp = '}'; 3839 char TEX_clgrp = '}';
4192 3840
4193 /* 3841 /*
4194 * TeX/LaTeX scanning loop. 3842 * TeX/LaTeX scanning loop.
4195 */ 3843 */
4196 static void 3844 void
4197 TeX_functions (inf) 3845 TeX_functions (inf)
4198 FILE *inf; 3846 FILE *inf;
4199 { 3847 {
4200 char *cp, *lasthit; 3848 char *cp, *lasthit;
4201 register int i; 3849 register int i;
4238 #define TEX_SESC '!' 3886 #define TEX_SESC '!'
4239 #define TEX_cmt '%' 3887 #define TEX_cmt '%'
4240 3888
4241 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping 3889 /* Figure out whether TeX's escapechar is '\\' or '!' and set grouping
4242 chars accordingly. */ 3890 chars accordingly. */
4243 static void 3891 void
4244 TEX_mode (inf) 3892 TEX_mode (inf)
4245 FILE *inf; 3893 FILE *inf;
4246 { 3894 {
4247 int c; 3895 int c;
4248 3896
4273 rewind (inf); 3921 rewind (inf);
4274 } 3922 }
4275 3923
4276 /* Read environment and prepend it to the default string. 3924 /* Read environment and prepend it to the default string.
4277 Build token table. */ 3925 Build token table. */
4278 static struct TEX_tabent * 3926 struct TEX_tabent *
4279 TEX_decode_env (evarname, defenv) 3927 TEX_decode_env (evarname, defenv)
4280 char *evarname; 3928 char *evarname;
4281 char *defenv; 3929 char *defenv;
4282 { 3930 {
4283 register char *env, *p; 3931 register char *env, *p;
4330 /* If the text at CP matches one of the tag-defining TeX command names, 3978 /* If the text at CP matches one of the tag-defining TeX command names,
4331 return the pointer to the first occurrence of that command in TEX_toktab. 3979 return the pointer to the first occurrence of that command in TEX_toktab.
4332 Otherwise return -1. 3980 Otherwise return -1.
4333 Keep the capital `T' in `token' for dumb truncating compilers 3981 Keep the capital `T' in `token' for dumb truncating compilers
4334 (this distinguishes it from `TEX_toktab' */ 3982 (this distinguishes it from `TEX_toktab' */
4335 static int 3983 int
4336 TEX_Token (cp) 3984 TEX_Token (cp)
4337 char *cp; 3985 char *cp;
4338 { 3986 {
4339 int i; 3987 int i;
4340 3988
4346 3994
4347 /* 3995 /*
4348 * Prolog support (rewritten) by Anders Lindgren, Mar. 96 3996 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
4349 * 3997 *
4350 * Assumes that the predicate starts at column 0. 3998 * Assumes that the predicate starts at column 0.
4351 * Only the first clause of a predicate is added. 3999 * Only the first clause of a predicate is added.
4352 */ 4000 */
4353 static int prolog_pred P_((char *, char *)); 4001 int prolog_pred ();
4354 static void prolog_skip_comment P_((linebuffer *, FILE *)); 4002 void prolog_skip_comment ();
4355 static int prolog_atom P_((char *, int)); 4003 int prolog_atom ();
4356 4004
4357 static void 4005 void
4358 Prolog_functions (inf) 4006 Prolog_functions (inf)
4359 FILE *inf; 4007 FILE *inf;
4360 { 4008 {
4361 char *cp, *last; 4009 char *cp, *last;
4362 int len; 4010 int len;
4368 4016
4369 LOOP_ON_INPUT_LINES (inf, lb, cp) 4017 LOOP_ON_INPUT_LINES (inf, lb, cp)
4370 { 4018 {
4371 if (cp[0] == '\0') /* Empty line */ 4019 if (cp[0] == '\0') /* Empty line */
4372 continue; 4020 continue;
4373 else if (iswhite (cp[0])) /* Not a predicate */ 4021 else if (isspace (cp[0])) /* Not a predicate */
4374 continue; 4022 continue;
4375 else if (cp[0] == '/' && cp[1] == '*') /* comment. */ 4023 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
4376 prolog_skip_comment (&lb, inf); 4024 prolog_skip_comment (&lb, inf);
4377 else if ((len = prolog_pred (cp, last)) > 0) 4025 else if ((len = prolog_pred (cp, last)) > 0)
4378 { 4026 {
4388 } 4036 }
4389 } 4037 }
4390 } 4038 }
4391 4039
4392 4040
4393 static void 4041 void
4394 prolog_skip_comment (plb, inf) 4042 prolog_skip_comment (plb, inf)
4395 linebuffer *plb; 4043 linebuffer *plb;
4396 FILE *inf; 4044 FILE *inf;
4397 { 4045 {
4398 char *cp; 4046 char *cp;
4416 * name of the previous clause header. 4064 * name of the previous clause header.
4417 * 4065 *
4418 * Return the size of the name of the predicate, or 0 if no header 4066 * Return the size of the name of the predicate, or 0 if no header
4419 * was found. 4067 * was found.
4420 */ 4068 */
4421 static int 4069 int
4422 prolog_pred (s, last) 4070 prolog_pred (s, last)
4423 char *s; 4071 char *s;
4424 char *last; /* Name of last clause. */ 4072 char *last; /* Name of last clause. */
4425 { 4073 {
4426 int pos; 4074 int pos;
4441 /* Save only the first clause. */ 4089 /* Save only the first clause. */
4442 if (last == NULL 4090 if (last == NULL
4443 || len != (int)strlen (last) 4091 || len != (int)strlen (last)
4444 || !strneq (s, last, len)) 4092 || !strneq (s, last, len))
4445 { 4093 {
4446 pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno); 4094 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4095 s, pos, lineno, linecharno);
4447 return len; 4096 return len;
4448 } 4097 }
4449 } 4098 }
4450 return 0; 4099 return 0;
4451 } 4100 }
4457 * A prolog atom, in this context, could be one of: 4106 * A prolog atom, in this context, could be one of:
4458 * - An alphanumeric sequence, starting with a lower case letter. 4107 * - An alphanumeric sequence, starting with a lower case letter.
4459 * - A quoted arbitrary string. Single quotes can escape themselves. 4108 * - A quoted arbitrary string. Single quotes can escape themselves.
4460 * Backslash quotes everything. 4109 * Backslash quotes everything.
4461 */ 4110 */
4462 static int 4111 int
4463 prolog_atom (s, pos) 4112 prolog_atom (s, pos)
4464 char *s; 4113 char *s;
4465 int pos; 4114 int pos;
4466 { 4115 {
4467 int origpos; 4116 int origpos;
4468 4117
4469 origpos = pos; 4118 origpos = pos;
4470 4119
4471 if (islower((unsigned char) s[pos]) || (s[pos] == '_')) 4120 if (islower(s[pos]) || (s[pos] == '_'))
4472 { 4121 {
4473 /* The atom is unquoted. */ 4122 /* The atom is unquoted. */
4474 pos++; 4123 pos++;
4475 while (isalnum((unsigned char) s[pos]) || (s[pos] == '_')) 4124 while (isalnum(s[pos]) || (s[pos] == '_'))
4476 { 4125 {
4477 pos++; 4126 pos++;
4478 } 4127 }
4479 return pos - origpos; 4128 return pos - origpos;
4480 } 4129 }
4481 else if (s[pos] == '\'') 4130 else if (s[pos] == '\'')
4482 { 4131 {
4483 pos++; 4132 pos++;
4484 4133
4485 while (1) 4134 while (1)
4486 { 4135 {
4487 if (s[pos] == '\'') 4136 if (s[pos] == '\'')
4488 { 4137 {
4489 pos++; 4138 pos++;
4490 if (s[pos] != '\'') 4139 if (s[pos] != '\'')
4507 } 4156 }
4508 else 4157 else
4509 return -1; 4158 return -1;
4510 } 4159 }
4511 4160
4512 /* 4161 /*
4513 * Support for Erlang -- Anders Lindgren, Feb 1996. 4162 * Support for Erlang -- Anders Lindgren, Feb 1996.
4514 * 4163 *
4515 * Generates tags for functions, defines, and records. 4164 * Generates tags for functions, defines, and records.
4516 * 4165 *
4517 * Assumes that Erlang functions start at column 0. 4166 * Assumes that Erlang functions start at column 0.
4518 */ 4167 */
4519 static int erlang_func P_((char *, char *)); 4168 int erlang_func ();
4520 static void erlang_attribute P_((char *)); 4169 void erlang_attribute ();
4521 static int erlang_atom P_((char *, int)); 4170 int erlang_atom ();
4522 4171
4523 static void 4172 void
4524 Erlang_functions (inf) 4173 Erlang_functions (inf)
4525 FILE *inf; 4174 FILE *inf;
4526 { 4175 {
4527 char *cp, *last; 4176 char *cp, *last;
4528 int len; 4177 int len;
4534 4183
4535 LOOP_ON_INPUT_LINES (inf, lb, cp) 4184 LOOP_ON_INPUT_LINES (inf, lb, cp)
4536 { 4185 {
4537 if (cp[0] == '\0') /* Empty line */ 4186 if (cp[0] == '\0') /* Empty line */
4538 continue; 4187 continue;
4539 else if (iswhite (cp[0])) /* Not function nor attribute */ 4188 else if (isspace (cp[0])) /* Not function nor attribute */
4540 continue; 4189 continue;
4541 else if (cp[0] == '%') /* comment */ 4190 else if (cp[0] == '%') /* comment */
4542 continue; 4191 continue;
4543 else if (cp[0] == '"') /* Sometimes, strings start in column one */ 4192 else if (cp[0] == '"') /* Sometimes, strings start in column one */
4544 continue; 4193 continue;
4547 erlang_attribute (cp); 4196 erlang_attribute (cp);
4548 last = NULL; 4197 last = NULL;
4549 } 4198 }
4550 else if ((len = erlang_func (cp, last)) > 0) 4199 else if ((len = erlang_func (cp, last)) > 0)
4551 { 4200 {
4552 /* 4201 /*
4553 * Function. Store the function name so that we only 4202 * Function. Store the function name so that we only
4554 * generates a tag for the first clause. 4203 * generates a tag for the first clause.
4555 */ 4204 */
4556 if (last == NULL) 4205 if (last == NULL)
4557 last = xnew (len + 1, char); 4206 last = xnew (len + 1, char);
4573 * name of the previous clause header. 4222 * name of the previous clause header.
4574 * 4223 *
4575 * Return the size of the name of the function, or 0 if no function 4224 * Return the size of the name of the function, or 0 if no function
4576 * was found. 4225 * was found.
4577 */ 4226 */
4578 static int 4227 int
4579 erlang_func (s, last) 4228 erlang_func (s, last)
4580 char *s; 4229 char *s;
4581 char *last; /* Name of last clause. */ 4230 char *last; /* Name of last clause. */
4582 { 4231 {
4583 int pos; 4232 int pos;
4594 if (s[pos++] == '(' 4243 if (s[pos++] == '('
4595 && (last == NULL 4244 && (last == NULL
4596 || len != (int)strlen (last) 4245 || len != (int)strlen (last)
4597 || !strneq (s, last, len))) 4246 || !strneq (s, last, len)))
4598 { 4247 {
4599 pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno); 4248 pfnote ((CTAGS) ? savenstr (s, len) : NULL, TRUE,
4249 s, pos, lineno, linecharno);
4600 return len; 4250 return len;
4601 } 4251 }
4602 4252
4603 return 0; 4253 return 0;
4604 } 4254 }
4605 4255
4606 4256
4607 /* 4257 /*
4608 * Handle attributes. Currently, tags are generated for defines 4258 * Handle attributes. Currently, tags are generated for defines
4609 * and records. 4259 * and records.
4610 * 4260 *
4611 * They are on the form: 4261 * They are on the form:
4612 * -define(foo, bar). 4262 * -define(foo, bar).
4613 * -define(Foo(M, N), M+N). 4263 * -define(Foo(M, N), M+N).
4614 * -record(graph, {vtab = notable, cyclic = true}). 4264 * -record(graph, {vtab = notable, cyclic = true}).
4615 */ 4265 */
4616 static void 4266 void
4617 erlang_attribute (s) 4267 erlang_attribute (s)
4618 char *s; 4268 char *s;
4619 { 4269 {
4620 int pos; 4270 int pos;
4621 int len; 4271 int len;
4622 4272
4623 if (strneq (s, "-define", 7) || strneq (s, "-record", 7)) 4273 if (strneq (s, "-define", 7) || strneq (s, "-record", 7))
4624 { 4274 {
4625 pos = skip_spaces (s + 7) - s; 4275 pos = skip_spaces (s + 7) - s;
4626 if (s[pos++] == '(') 4276 if (s[pos++] == '(')
4627 { 4277 {
4628 pos = skip_spaces (s + pos) - s; 4278 pos = skip_spaces (s + pos) - s;
4629 len = erlang_atom (s, pos); 4279 len = erlang_atom (s, pos);
4630 if (len != 0) 4280 if (len != 0)
4631 pfnote (savenstr (& s[pos], len), TRUE, 4281 pfnote ((CTAGS) ? savenstr (& s[pos], len) : NULL, TRUE,
4632 s, pos + len, lineno, linecharno); 4282 s, pos + len, lineno, linecharno);
4633 } 4283 }
4634 } 4284 }
4635 return; 4285 return;
4636 } 4286 }
4638 4288
4639 /* 4289 /*
4640 * Consume an Erlang atom (or variable). 4290 * Consume an Erlang atom (or variable).
4641 * Return the number of bytes consumed, or -1 if there was an error. 4291 * Return the number of bytes consumed, or -1 if there was an error.
4642 */ 4292 */
4643 static int 4293 int
4644 erlang_atom (s, pos) 4294 erlang_atom (s, pos)
4645 char *s; 4295 char *s;
4646 int pos; 4296 int pos;
4647 { 4297 {
4648 int origpos; 4298 int origpos;
4649 4299
4650 origpos = pos; 4300 origpos = pos;
4651 4301
4652 if (isalpha ((unsigned char) s[pos]) || s[pos] == '_') 4302 if (isalpha (s[pos]) || s[pos] == '_')
4653 { 4303 {
4654 /* The atom is unquoted. */ 4304 /* The atom is unquoted. */
4655 pos++; 4305 pos++;
4656 while (isalnum ((unsigned char) s[pos]) || s[pos] == '_') 4306 while (isalnum (s[pos]) || s[pos] == '_')
4657 pos++; 4307 pos++;
4658 return pos - origpos; 4308 return pos - origpos;
4659 } 4309 }
4660 else if (s[pos] == '\'') 4310 else if (s[pos] == '\'')
4661 { 4311 {
4662 pos++; 4312 pos++;
4663 4313
4664 while (1) 4314 while (1)
4665 { 4315 {
4666 if (s[pos] == '\'') 4316 if (s[pos] == '\'')
4667 { 4317 {
4668 pos++; 4318 pos++;
4669 break; 4319 break;
4686 return -1; 4336 return -1;
4687 } 4337 }
4688 4338
4689 #ifdef ETAGS_REGEXPS 4339 #ifdef ETAGS_REGEXPS
4690 4340
4691 static char *scan_separators P_((char *));
4692 static void analyse_regex P_((char *, bool));
4693 static void add_regex P_((char *, bool, language *));
4694 static char *substitute P_((char *, char *, struct re_registers *));
4695
4696 /* Take a string like "/blah/" and turn it into "blah", making sure 4341 /* Take a string like "/blah/" and turn it into "blah", making sure
4697 that the first and last characters are the same, and handling 4342 that the first and last characters are the same, and handling
4698 quoted separator characters. Actually, stops on the occurrence of 4343 quoted separator characters. Actually, stops on the occurrence of
4699 an unquoted separator. Also turns "\t" into a Tab character. 4344 an unquoted separator. Also turns "\t" into a Tab character.
4700 Returns pointer to terminating separator. Works in place. Null 4345 Returns pointer to terminating separator. Works in place. Null
4701 terminates name string. */ 4346 terminates name string. */
4702 static char * 4347 char *
4703 scan_separators (name) 4348 scan_separators (name)
4704 char *name; 4349 char *name;
4705 { 4350 {
4706 char sep = name[0]; 4351 char sep = name[0];
4707 char *copyto = name; 4352 char *copyto = name;
4736 return name; 4381 return name;
4737 } 4382 }
4738 4383
4739 /* Look at the argument of --regex or --no-regex and do the right 4384 /* Look at the argument of --regex or --no-regex and do the right
4740 thing. Same for each line of a regexp file. */ 4385 thing. Same for each line of a regexp file. */
4741 static void 4386 void
4742 analyse_regex (regex_arg, ignore_case) 4387 analyse_regex (regex_arg)
4743 char *regex_arg; 4388 char *regex_arg;
4744 bool ignore_case;
4745 { 4389 {
4746 if (regex_arg == NULL) 4390 if (regex_arg == NULL)
4747 free_patterns (); /* --no-regex: remove existing regexps */ 4391 free_patterns (); /* --no-regex: remove existing regexps */
4748 4392
4749 /* A real --regexp option or a line in a regexp file. */ 4393 /* A real --regexp option or a line in a regexp file. */
4770 pfatal (regexfile); 4414 pfatal (regexfile);
4771 return; 4415 return;
4772 } 4416 }
4773 initbuffer (&regexbuf); 4417 initbuffer (&regexbuf);
4774 while (readline_internal (&regexbuf, regexfp) > 0) 4418 while (readline_internal (&regexbuf, regexfp) > 0)
4775 analyse_regex (regexbuf.buffer, ignore_case); 4419 analyse_regex (regexbuf.buffer);
4776 free (regexbuf.buffer); 4420 free (regexbuf.buffer);
4777 fclose (regexfp); 4421 fclose (regexfp);
4778 } 4422 }
4779 break; 4423 break;
4780 4424
4793 } 4437 }
4794 *cp = '\0'; 4438 *cp = '\0';
4795 lang = get_language_from_name (lang_name); 4439 lang = get_language_from_name (lang_name);
4796 if (lang == NULL) 4440 if (lang == NULL)
4797 return; 4441 return;
4798 add_regex (cp + 1, ignore_case, lang); 4442 add_regex (cp + 1, lang);
4799 } 4443 }
4800 break; 4444 break;
4801 4445
4802 /* Regexp to be used for any language. */ 4446 /* Regexp to be used for any language. */
4803 default: 4447 default:
4804 add_regex (regex_arg, ignore_case, NULL); 4448 add_regex (regex_arg, NULL);
4805 break; 4449 break;
4806 } 4450 }
4807 } 4451 }
4808 4452
4809 /* Turn a name, which is an ed-style (but Emacs syntax) regular 4453 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4810 expression, into a real regular expression by compiling it. */ 4454 expression, into a real regular expression by compiling it. */
4811 static void 4455 void
4812 add_regex (regexp_pattern, ignore_case, lang) 4456 add_regex (regexp_pattern, lang)
4813 char *regexp_pattern; 4457 char *regexp_pattern;
4814 bool ignore_case;
4815 language *lang; 4458 language *lang;
4816 { 4459 {
4817 char *name; 4460 char *name;
4818 const char *err; 4461 const char *err;
4819 struct re_pattern_buffer *patbuf; 4462 struct re_pattern_buffer *patbuf;
4832 return; 4475 return;
4833 } 4476 }
4834 (void) scan_separators (name); 4477 (void) scan_separators (name);
4835 4478
4836 patbuf = xnew (1, struct re_pattern_buffer); 4479 patbuf = xnew (1, struct re_pattern_buffer);
4837 /* Translation table to fold case if appropriate. */ 4480 patbuf->translate = NULL;
4838 patbuf->translate = (ignore_case) ? lc_trans : NULL;
4839 patbuf->fastmap = NULL; 4481 patbuf->fastmap = NULL;
4840 patbuf->buffer = NULL; 4482 patbuf->buffer = NULL;
4841 patbuf->allocated = 0; 4483 patbuf->allocated = 0;
4842 4484
4843 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf); 4485 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
4859 4501
4860 /* 4502 /*
4861 * Do the substitutions indicated by the regular expression and 4503 * Do the substitutions indicated by the regular expression and
4862 * arguments. 4504 * arguments.
4863 */ 4505 */
4864 static char * 4506 char *
4865 substitute (in, out, regs) 4507 substitute (in, out, regs)
4866 char *in, *out; 4508 char *in, *out;
4867 struct re_registers *regs; 4509 struct re_registers *regs;
4868 { 4510 {
4869 char *result, *t; 4511 char *result, *t;
4876 if (out[size - 1] == '\\') 4518 if (out[size - 1] == '\\')
4877 fatal ("pattern error in \"%s\"", out); 4519 fatal ("pattern error in \"%s\"", out);
4878 for (t = etags_strchr (out, '\\'); 4520 for (t = etags_strchr (out, '\\');
4879 t != NULL; 4521 t != NULL;
4880 t = etags_strchr (t + 2, '\\')) 4522 t = etags_strchr (t + 2, '\\'))
4881 if (isdigit ((unsigned char) t[1])) 4523 if (isdigit (t[1]))
4882 { 4524 {
4883 dig = t[1] - '0'; 4525 dig = t[1] - '0';
4884 diglen = regs->end[dig] - regs->start[dig]; 4526 diglen = regs->end[dig] - regs->start[dig];
4885 size += diglen - 2; 4527 size += diglen - 2;
4886 } 4528 }
4889 4531
4890 /* Allocate space and do the substitutions. */ 4532 /* Allocate space and do the substitutions. */
4891 result = xnew (size + 1, char); 4533 result = xnew (size + 1, char);
4892 4534
4893 for (t = result; *out != '\0'; out++) 4535 for (t = result; *out != '\0'; out++)
4894 if (*out == '\\' && isdigit ((unsigned char) *++out)) 4536 if (*out == '\\' && isdigit (*++out))
4895 { 4537 {
4896 /* Using "dig2" satisfies my debugger. Bleah. */ 4538 /* Using "dig2" satisfies my debugger. Bleah. */
4897 dig = *out - '0'; 4539 dig = *out - '0';
4898 diglen = regs->end[dig] - regs->start[dig]; 4540 diglen = regs->end[dig] - regs->start[dig];
4899 strncpy (t, in + regs->start[dig], diglen); 4541 strncpy (t, in + regs->start[dig], diglen);
4908 4550
4909 return result; 4551 return result;
4910 } 4552 }
4911 4553
4912 /* Deallocate all patterns. */ 4554 /* Deallocate all patterns. */
4913 static void 4555 void
4914 free_patterns () 4556 free_patterns ()
4915 { 4557 {
4916 pattern *pp; 4558 pattern *pp;
4917 while (p_head != NULL) 4559 while (p_head != NULL)
4918 { 4560 {
4923 p_head = pp; 4565 p_head = pp;
4924 } 4566 }
4925 return; 4567 return;
4926 } 4568 }
4927 4569
4928 static void
4929 get_tag (bp)
4930 register char *bp;
4931 {
4932 register char *cp;
4933
4934 if (*bp == '\0')
4935 return;
4936 /* Go till you get to white space or a syntactic break */
4937 for (cp = bp + 1;
4938 *cp != '\0' && *cp != '(' && *cp != ')' && !iswhite (*cp);
4939 cp++)
4940 continue;
4941 pfnote (savenstr (bp, cp-bp), TRUE,
4942 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4943 }
4944
4945 #endif /* ETAGS_REGEXPS */ 4570 #endif /* ETAGS_REGEXPS */
4946 /* Initialize a linebuffer for use */ 4571 /* Initialize a linebuffer for use */
4947 static void 4572 void
4948 initbuffer (lbp) 4573 initbuffer (lbp)
4949 linebuffer *lbp; 4574 linebuffer *lbp;
4950 { 4575 {
4951 lbp->size = 200; 4576 lbp->size = 200;
4952 lbp->buffer = xnew (200, char); 4577 lbp->buffer = xnew (200, char);
4960 * On DOS or Windows we do not count the CR character, if any, before the 4585 * On DOS or Windows we do not count the CR character, if any, before the
4961 * NL, in the returned length; this mirrors the behavior of emacs on those 4586 * NL, in the returned length; this mirrors the behavior of emacs on those
4962 * platforms (for text files, it translates CR-NL to NL as it reads in the 4587 * platforms (for text files, it translates CR-NL to NL as it reads in the
4963 * file). 4588 * file).
4964 */ 4589 */
4965 static long 4590 long
4966 readline_internal (lbp, stream) 4591 readline_internal (lbp, stream)
4967 linebuffer *lbp; 4592 linebuffer *lbp;
4968 register FILE *stream; 4593 register FILE *stream;
4969 { 4594 {
4970 char *buffer = lbp->buffer; 4595 char *buffer = lbp->buffer;
4995 if (c == '\n') 4620 if (c == '\n')
4996 { 4621 {
4997 if (p > buffer && p[-1] == '\r') 4622 if (p > buffer && p[-1] == '\r')
4998 { 4623 {
4999 p -= 1; 4624 p -= 1;
5000 #ifdef WIN32_NATIVE 4625 #ifdef DOS_NT
5001 /* Assume CRLF->LF translation will be performed by Emacs 4626 /* Assume CRLF->LF translation will be performed by Emacs
5002 when loading this file, so CRs won't appear in the buffer. 4627 when loading this file, so CRs won't appear in the buffer.
5003 It would be cleaner to compensate within Emacs; 4628 It would be cleaner to compensate within Emacs;
5004 however, Emacs does not know how many CRs were deleted 4629 however, Emacs does not know how many CRs were deleted
5005 before any given point in the file. */ 4630 before any given point in the file. */
5024 4649
5025 /* 4650 /*
5026 * Like readline_internal, above, but in addition try to match the 4651 * Like readline_internal, above, but in addition try to match the
5027 * input line against relevant regular expressions. 4652 * input line against relevant regular expressions.
5028 */ 4653 */
5029 static long 4654 long
5030 readline (lbp, stream) 4655 readline (lbp, stream)
5031 linebuffer *lbp; 4656 linebuffer *lbp;
5032 FILE *stream; 4657 FILE *stream;
5033 { 4658 {
5034 /* Read new line. */ 4659 /* Read new line. */
5077 } 4702 }
5078 break; 4703 break;
5079 } 4704 }
5080 } 4705 }
5081 #endif /* ETAGS_REGEXPS */ 4706 #endif /* ETAGS_REGEXPS */
5082 4707
5083 return result; 4708 return result;
5084 } 4709 }
5085 4710
5086 /* 4711 /*
5087 * Return a pointer to a space of size strlen(cp)+1 allocated 4712 * Return a pointer to a space of size strlen(cp)+1 allocated
5088 * with xnew where the string CP has been copied. 4713 * with xnew where the string CP has been copied.
5089 */ 4714 */
5090 static char * 4715 char *
5091 savestr (cp) 4716 savestr (cp)
5092 char *cp; 4717 char *cp;
5093 { 4718 {
5094 return savenstr (cp, strlen (cp)); 4719 return savenstr (cp, strlen (cp));
5095 } 4720 }
5096 4721
5097 /* 4722 /*
5098 * Return a pointer to a space of size LEN+1 allocated with xnew where 4723 * Return a pointer to a space of size LEN+1 allocated with xnew where
5099 * the string CP has been copied for at most the first LEN characters. 4724 * the string CP has been copied for at most the first LEN characters.
5100 */ 4725 */
5101 static char * 4726 char *
5102 savenstr (cp, len) 4727 savenstr (cp, len)
5103 char *cp; 4728 char *cp;
5104 int len; 4729 int len;
5105 { 4730 {
5106 register char *dp; 4731 register char *dp;
5113 4738
5114 /* 4739 /*
5115 * Return the ptr in sp at which the character c last 4740 * Return the ptr in sp at which the character c last
5116 * appears; NULL if not found 4741 * appears; NULL if not found
5117 * 4742 *
5118 * Identical to POSIX strrchr, included for portability. 4743 * Identical to System V strrchr, included for portability.
5119 */ 4744 */
5120 static char * 4745 char *
5121 etags_strrchr (sp, c) 4746 etags_strrchr (sp, c)
5122 register const char *sp; 4747 register char *sp, c;
5123 register int c; 4748 {
5124 { 4749 register char *r;
5125 register const char *r;
5126 4750
5127 r = NULL; 4751 r = NULL;
5128 do 4752 do
5129 { 4753 {
5130 if (*sp == c) 4754 if (*sp == c)
5131 r = sp; 4755 r = sp;
5132 } while (*sp++); 4756 } while (*sp++);
5133 return (char *)r; 4757 return r;
5134 } 4758 }
5135 4759
5136 4760
5137 /* 4761 /*
5138 * Return the ptr in sp at which the character c first 4762 * Return the ptr in sp at which the character c first
5139 * appears; NULL if not found 4763 * appears; NULL if not found
5140 * 4764 *
5141 * Identical to POSIX strchr, included for portability. 4765 * Identical to System V strchr, included for portability.
5142 */ 4766 */
5143 static char * 4767 char *
5144 etags_strchr (sp, c) 4768 etags_strchr (sp, c)
5145 register const char *sp; 4769 register char *sp, c;
5146 register int c;
5147 { 4770 {
5148 do 4771 do
5149 { 4772 {
5150 if (*sp == c) 4773 if (*sp == c)
5151 return (char *)sp; 4774 return sp;
5152 } while (*sp++); 4775 } while (*sp++);
5153 return NULL; 4776 return NULL;
5154 } 4777 }
5155 4778
5156 /* Skip spaces, return new pointer. */ 4779 /* Skip spaces, return new pointer. */
5157 static char * 4780 char *
5158 skip_spaces (cp) 4781 skip_spaces (cp)
5159 char *cp; 4782 char *cp;
5160 { 4783 {
5161 while (iswhite (*cp)) 4784 while (isspace (*cp)) /* isspace('\0')==FALSE */
5162 cp++; 4785 cp++;
5163 return cp; 4786 return cp;
5164 } 4787 }
5165 4788
5166 /* Skip non spaces, return new pointer. */ 4789 /* Skip non spaces, return new pointer. */
5167 static char * 4790 char *
5168 skip_non_spaces (cp) 4791 skip_non_spaces (cp)
5169 char *cp; 4792 char *cp;
5170 { 4793 {
5171 while (*cp != '\0' && !iswhite (*cp)) 4794 while (!iswhite (*cp)) /* iswhite('\0')==TRUE */
5172 cp++; 4795 cp++;
5173 return cp; 4796 return cp;
5174 } 4797 }
5175 4798
5176 /* Print error message and exit. */ 4799 /* Print error message and exit. */
5177 static void 4800 void
5178 fatal (s1, s2) 4801 fatal (s1, s2)
5179 char *s1, *s2; 4802 char *s1, *s2;
5180 { 4803 {
5181 error (s1, s2); 4804 error (s1, s2);
5182 exit (BAD); 4805 exit (BAD);
5183 } 4806 }
5184 4807
5185 static void 4808 void
5186 pfatal (s1) 4809 pfatal (s1)
5187 char *s1; 4810 char *s1;
5188 { 4811 {
5189 perror (s1); 4812 perror (s1);
5190 exit (BAD); 4813 exit (BAD);
5191 } 4814 }
5192 4815
5193 static void 4816 void
5194 suggest_asking_for_help () 4817 suggest_asking_for_help ()
5195 { 4818 {
5196 fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n", 4819 fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n",
5197 progname, 4820 progname,
5198 #ifdef LONG_OPTIONS 4821 #ifdef LONG_OPTIONS
5203 ); 4826 );
5204 exit (BAD); 4827 exit (BAD);
5205 } 4828 }
5206 4829
5207 /* Print error message. `s1' is printf control string, `s2' is arg for it. */ 4830 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
5208 static void 4831 void
5209 error (s1, s2) 4832 error (s1, s2)
5210 const char *s1, *s2; 4833 char *s1, *s2;
5211 { 4834 {
5212 fprintf (stderr, "%s: ", progname); 4835 fprintf (stderr, "%s: ", progname);
5213 fprintf (stderr, s1, s2); 4836 fprintf (stderr, s1, s2);
5214 fprintf (stderr, "\n"); 4837 fprintf (stderr, "\n");
5215 } 4838 }
5216 4839
5217 /* Return a newly-allocated string whose contents 4840 /* Return a newly-allocated string whose contents
5218 concatenate those of s1, s2, s3. */ 4841 concatenate those of s1, s2, s3. */
5219 static char * 4842 char *
5220 concat (s1, s2, s3) 4843 concat (s1, s2, s3)
5221 char *s1, *s2, *s3; 4844 char *s1, *s2, *s3;
5222 { 4845 {
5223 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); 4846 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
5224 char *result = xnew (len1 + len2 + len3 + 1, char); 4847 char *result = xnew (len1 + len2 + len3 + 1, char);
5231 return result; 4854 return result;
5232 } 4855 }
5233 4856
5234 /* Does the same work as the system V getcwd, but does not need to 4857 /* Does the same work as the system V getcwd, but does not need to
5235 guess the buffer size in advance. */ 4858 guess the buffer size in advance. */
5236 static char * 4859 char *
5237 etags_getcwd () 4860 etags_getcwd ()
5238 { 4861 {
5239 #ifdef HAVE_GETCWD 4862 #ifdef HAVE_GETCWD
5240 int bufsize = 200; 4863 int bufsize = 200;
5241 char *path = xnew (bufsize, char); 4864 char *path = xnew (bufsize, char);
5251 4874
5252 canonicalize_filename (path); 4875 canonicalize_filename (path);
5253 return path; 4876 return path;
5254 4877
5255 #else /* not HAVE_GETCWD */ 4878 #else /* not HAVE_GETCWD */
4879 #ifdef MSDOS
4880 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
4881
4882 getwd (path);
4883
4884 for (p = path; *p != '\0'; p++)
4885 if (*p == '\\')
4886 *p = '/';
4887 else
4888 *p = lowcase (*p);
4889
4890 return strdup (path);
4891 #else /* not MSDOS */
5256 linebuffer path; 4892 linebuffer path;
5257 FILE *pipe; 4893 FILE *pipe;
5258 4894
5259 initbuffer (&path); 4895 initbuffer (&path);
5260 pipe = (FILE *) popen ("pwd 2>/dev/null", "r"); 4896 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
5261 if (pipe == NULL || readline_internal (&path, pipe) == 0) 4897 if (pipe == NULL || readline_internal (&path, pipe) == 0)
5262 pfatal ("pwd"); 4898 pfatal ("pwd");
5263 pclose (pipe); 4899 pclose (pipe);
5264 4900
5265 return path.buffer; 4901 return path.buffer;
4902 #endif /* not MSDOS */
5266 #endif /* not HAVE_GETCWD */ 4903 #endif /* not HAVE_GETCWD */
5267 } 4904 }
5268 4905
5269 /* Return a newly allocated string containing the file name of FILE 4906 /* Return a newly allocated string containing the file name of FILE
5270 relative to the absolute directory DIR (which should end with a slash). */ 4907 relative to the absolute directory DIR (which should end with a slash). */
5271 static char * 4908 char *
5272 relative_filename (file, dir) 4909 relative_filename (file, dir)
5273 char *file, *dir; 4910 char *file, *dir;
5274 { 4911 {
5275 char *fp, *dp, *afn, *res; 4912 char *fp, *dp, *afn, *res;
5276 int i; 4913 int i;
5280 fp = afn; 4917 fp = afn;
5281 dp = dir; 4918 dp = dir;
5282 while (*fp++ == *dp++) 4919 while (*fp++ == *dp++)
5283 continue; 4920 continue;
5284 fp--, dp--; /* back to the first differing char */ 4921 fp--, dp--; /* back to the first differing char */
5285 #ifdef WIN32_NATIVE
5286 if (fp == afn && afn[0] != '/') /* cannot build a relative name */
5287 return afn;
5288 #endif
5289 do /* look at the equal chars until '/' */ 4922 do /* look at the equal chars until '/' */
5290 fp--, dp--; 4923 fp--, dp--;
5291 while (*fp != '/'); 4924 while (*fp != '/');
5292 4925
5293 /* Build a sequence of "../" strings for the resulting relative file name. */ 4926 /* Build a sequence of "../" strings for the resulting relative file name. */
5306 return res; 4939 return res;
5307 } 4940 }
5308 4941
5309 /* Return a newly allocated string containing the absolute file name 4942 /* Return a newly allocated string containing the absolute file name
5310 of FILE given DIR (which should end with a slash). */ 4943 of FILE given DIR (which should end with a slash). */
5311 static char * 4944 char *
5312 absolute_filename (file, dir) 4945 absolute_filename (file, dir)
5313 char *file, *dir; 4946 char *file, *dir;
5314 { 4947 {
5315 char *slashp, *cp, *res; 4948 char *slashp, *cp, *res;
5316 4949
5317 if (filename_is_absolute (file)) 4950 if (filename_is_absolute (file))
5318 res = savestr (file); 4951 res = savestr (file);
5319 #ifdef WIN32_NATIVE 4952 #ifdef DOS_NT
5320 /* We don't support non-absolute file names with a drive 4953 /* We don't support non-absolute file names with a drive
5321 letter, like `d:NAME' (it's too much hassle). */ 4954 letter, like `d:NAME' (it's too much hassle). */
5322 else if (file[1] == ':') 4955 else if (file[1] == ':')
5323 fatal ("%s: relative file names with drive letters not supported", file); 4956 fatal ("%s: relative file names with drive letters not supported", file);
5324 #endif 4957 #endif
5338 do 4971 do
5339 cp--; 4972 cp--;
5340 while (cp >= res && !filename_is_absolute (cp)); 4973 while (cp >= res && !filename_is_absolute (cp));
5341 if (cp < res) 4974 if (cp < res)
5342 cp = slashp; /* the absolute name begins with "/.." */ 4975 cp = slashp; /* the absolute name begins with "/.." */
5343 #ifdef WIN32_NATIVE 4976 #ifdef DOS_NT
5344 /* Under Windows we get `d:/NAME' as absolute 4977 /* Under MSDOS and NT we get `d:/NAME' as absolute
5345 file name, so the luser could say `d:/../NAME'. 4978 file name, so the luser could say `d:/../NAME'.
5346 We silently treat this as `d:/NAME'. */ 4979 We silently treat this as `d:/NAME'. */
5347 else if (cp[0] != '/') 4980 else if (cp[0] != '/')
5348 cp = slashp; 4981 cp = slashp;
5349 #endif 4982 #endif
5358 } 4991 }
5359 } 4992 }
5360 4993
5361 slashp = etags_strchr (slashp + 1, '/'); 4994 slashp = etags_strchr (slashp + 1, '/');
5362 } 4995 }
5363 4996
5364 if (res[0] == '\0') 4997 if (res[0] == '\0')
5365 return savestr ("/"); 4998 return savestr ("/");
5366 else 4999 else
5367 return res; 5000 return res;
5368 } 5001 }
5369 5002
5370 /* Return a newly allocated string containing the absolute 5003 /* Return a newly allocated string containing the absolute
5371 file name of dir where FILE resides given DIR (which should 5004 file name of dir where FILE resides given DIR (which should
5372 end with a slash). */ 5005 end with a slash). */
5373 static char * 5006 char *
5374 absolute_dirname (file, dir) 5007 absolute_dirname (file, dir)
5375 char *file, *dir; 5008 char *file, *dir;
5376 { 5009 {
5377 char *slashp, *res; 5010 char *slashp, *res;
5378 char save; 5011 char save;
5389 return res; 5022 return res;
5390 } 5023 }
5391 5024
5392 /* Whether the argument string is an absolute file name. The argument 5025 /* Whether the argument string is an absolute file name. The argument
5393 string must have been canonicalized with canonicalize_filename. */ 5026 string must have been canonicalized with canonicalize_filename. */
5394 static bool 5027 bool
5395 filename_is_absolute (fn) 5028 filename_is_absolute (fn)
5396 char *fn; 5029 char *fn;
5397 { 5030 {
5398 return (fn[0] == '/' 5031 return (fn[0] == '/'
5399 #ifdef WIN32_NATIVE 5032 #ifdef DOS_NT
5400 || (isalpha(fn[0]) && fn[1] == ':' && fn[2] == '/') 5033 || (isalpha(fn[0]) && fn[1] == ':' && fn[2] == '/')
5401 #endif 5034 #endif
5402 ); 5035 );
5403 } 5036 }
5404 5037
5405 /* Translate backslashes into slashes. Works in place. */ 5038 /* Translate backslashes into slashes. Works in place. */
5406 static void 5039 void
5407 canonicalize_filename (fn) 5040 canonicalize_filename (fn)
5408 register char *fn; 5041 register char *fn;
5409 { 5042 {
5410 #ifdef WIN32_NATIVE 5043 #ifdef DOS_NT
5411 /* Canonicalize drive letter case. */
5412 if (islower (fn[0]) && fn[1] == ':')
5413 fn[0] = toupper (fn[0]);
5414 /* Convert backslashes to slashes. */
5415 for (; *fn != '\0'; fn++) 5044 for (; *fn != '\0'; fn++)
5416 if (*fn == '\\') 5045 if (*fn == '\\')
5417 *fn = '/'; 5046 *fn = '/';
5418 #else 5047 #else
5419 /* No action. */ 5048 /* No action. */
5420 fn = NULL; /* shut up the compiler */ 5049 fn = NULL; /* shut up the compiler */
5421 #endif 5050 #endif
5422 } 5051 }
5423 5052
5424 /* Increase the size of a linebuffer. */ 5053 /* Increase the size of a linebuffer. */
5425 static void 5054 void
5426 grow_linebuffer (lbp, toksize) 5055 grow_linebuffer (lbp, toksize)
5427 linebuffer *lbp; 5056 linebuffer *lbp;
5428 int toksize; 5057 int toksize;
5429 { 5058 {
5430 while (lbp->size < toksize) 5059 while (lbp->size < toksize)
5431 lbp->size *= 2; 5060 lbp->size *= 2;
5432 lbp->buffer = xrnew (lbp->buffer, lbp->size, char); 5061 lbp->buffer = xrnew (lbp->buffer, lbp->size, char);
5433 } 5062 }
5434 5063
5435 /* Like malloc but get fatal error if memory is exhausted. */ 5064 /* Like malloc but get fatal error if memory is exhausted. */
5436 static long * 5065 long *
5437 xmalloc (size) 5066 xmalloc (size)
5438 unsigned int size; 5067 unsigned int size;
5439 { 5068 {
5440 long *result = (long *) malloc (size); 5069 long *result = (long *) malloc (size);
5441 if (result == NULL) 5070 if (result == NULL)
5442 fatal ("virtual memory exhausted", (char *)NULL); 5071 fatal ("virtual memory exhausted", (char *)NULL);
5443 return result; 5072 return result;
5444 } 5073 }
5445 5074
5446 static long * 5075 long *
5447 xrealloc (ptr, size) 5076 xrealloc (ptr, size)
5448 char *ptr; 5077 char *ptr;
5449 unsigned int size; 5078 unsigned int size;
5450 { 5079 {
5451 long *result = (long *) realloc (ptr, size); 5080 long *result = (long *) realloc (ptr, size);