comparison lib-src/etags.c @ 26262:c416a18b0a5d

Checked in at last a lot of improvementes and bug fixes. The oldest dating back to 1997-06-04. Please look at Changelog for details. Main changes are: - lots of code cleanups and optimizations - --globals is used not only for C-like languages - new option --ignore-case-regex - understands "operator" in C++ - support DOS file names by handling e.g. foo.cgz as if it were foo.c.gz. - Fortran: no tags for "procedure" - new option --declarations - regular expressions can be read from a file - regular expressions can be bound to a given language - Ada and Python languages added - my and local variables recognised in Perl - "(defstruct (foo", "(defun (operator" and similar Lisp constructs - interface in Java
author Francesco Potortì <pot@gnu.org>
date Mon, 01 Nov 1999 02:48:57 +0000
parents 134b57acef68
children 98d99afb5ffb
comparison
equal deleted inserted replaced
26261:b8f223ecc689 26262:c416a18b0a5d
29 * Regexp tags by Tom Tromey. 29 * Regexp tags by Tom Tromey.
30 * 30 *
31 * Francesco Potorti` (F.Potorti@cnuce.cnr.it) 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 12.11"; 34 char pot_etags_version[] = "@(#) pot revision number is 13.31";
35 35
36 #define TRUE 1 36 #define TRUE 1
37 #define FALSE 0 37 #define FALSE 0
38 38
39 #define _GNU_SOURCE /* enables some compiler checks on GNU */
39 #ifndef DEBUG 40 #ifndef DEBUG
40 # define DEBUG FALSE 41 # define DEBUG FALSE
41 #endif 42 #endif
42 43
43 #ifdef HAVE_CONFIG_H 44 #ifdef HAVE_CONFIG_H
44 # include <config.h> 45 # include <config.h>
45 /* On some systems, Emacs defines static as nothing for the sake 46 /* On some systems, Emacs defines static as nothing for the sake
46 of unexec. We don't want that here since we don't use unexec. */ 47 of unexec. We don't want that here since we don't use unexec. */
47 # undef static 48 # undef static
48 # define ETAGS_REGEXPS 49 # define ETAGS_REGEXPS /* use the regexp features */
49 # define LONG_OPTIONS 50 # define LONG_OPTIONS /* accept long options */
50 #endif 51 #endif /* HAVE_CONFIG_H */
51 52
52 #ifdef MSDOS 53 #ifdef MSDOS
53 # include <string.h>
54 # include <fcntl.h> 54 # include <fcntl.h>
55 # include <sys/param.h> 55 # include <sys/param.h>
56 # include <io.h>
57 # ifndef HAVE_CONFIG_H
58 # define DOS_NT
59 # include <sys/config.h>
60 # endif
56 #endif /* MSDOS */ 61 #endif /* MSDOS */
57 62
58 #ifdef WINDOWSNT 63 #ifdef WINDOWSNT
59 # include <stdlib.h> 64 # include <stdlib.h>
60 # include <fcntl.h> 65 # include <fcntl.h>
61 # include <string.h> 66 # include <string.h>
62 # include <io.h> 67 # include <io.h>
63 # define MAXPATHLEN _MAX_PATH 68 # define MAXPATHLEN _MAX_PATH
64 #endif 69 # ifdef HAVE_CONFIG_H
65 70 # undef HAVE_NTGUI
66 #if !defined (MSDOS) && !defined (WINDOWSNT) && defined (STDC_HEADERS) 71 # else
72 # define DOS_NT
73 # endif /* not HAVE_CONFIG_H */
74 # ifndef HAVE_GETCWD
75 # define HAVE_GETCWD
76 # endif /* undef HAVE_GETCWD */
77 #endif /* WINDOWSNT */
78
79 #if !defined (WINDOWSNT) && defined (STDC_HEADERS)
67 #include <stdlib.h> 80 #include <stdlib.h>
68 #include <string.h> 81 #include <string.h>
69 #endif 82 #endif
83
84 #ifdef HAVE_UNISTD_H
85 # include <unistd.h>
86 #else
87 # ifdef HAVE_GETCWD
88 extern char *getcwd ();
89 # endif
90 #endif /* HAVE_UNISTD_H */
70 91
71 #include <stdio.h> 92 #include <stdio.h>
72 #include <ctype.h> 93 #include <ctype.h>
73 #include <errno.h> 94 #include <errno.h>
74 #ifndef errno 95 #ifndef errno
75 extern int errno; 96 extern int errno;
76 #endif 97 #endif
77 #include <sys/types.h> 98 #include <sys/types.h>
78 #include <sys/stat.h> 99 #include <sys/stat.h>
79
80 /* This is to declare getcwd. */
81 #ifdef HAVE_UNISTD_H
82 #include <unistd.h>
83 #endif
84 100
85 #if !defined (S_ISREG) && defined (S_IFREG) 101 #if !defined (S_ISREG) && defined (S_IFREG)
86 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) 102 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
87 #endif 103 #endif
88 104
129 && (abort (), 1)) || !strncmp (s, t, n)) 145 && (abort (), 1)) || !strncmp (s, t, n))
130 146
131 #define lowcase(c) tolower ((char)c) 147 #define lowcase(c) tolower ((char)c)
132 148
133 #define CHARS 256 /* 2^sizeof(char) */ 149 #define CHARS 256 /* 2^sizeof(char) */
134 #define CHAR(x) ((int)x & (CHARS - 1)) 150 #define CHAR(x) ((unsigned int)x & (CHARS - 1))
135 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */ 151 #define iswhite(c) (_wht[CHAR(c)]) /* c is white */
136 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */ 152 #define notinname(c) (_nin[CHAR(c)]) /* c is not in a name */
137 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */ 153 #define begtoken(c) (_btk[CHAR(c)]) /* c can start token */
138 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */ 154 #define intoken(c) (_itk[CHAR(c)]) /* c can be in token */
139 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */ 155 #define endtoken(c) (_etk[CHAR(c)]) /* c ends tokens */
140 156
141 #ifdef DOS_NT
142 # define absolutefn(fn) (fn[0] == '/' \
143 || (fn[1] == ':' && fn[2] == '/'))
144 #else
145 # define absolutefn(fn) (fn[0] == '/')
146 #endif
147
148 157
149 /* 158 /*
150 * xnew -- allocate storage 159 * xnew, xrnew -- allocate, reallocate storage
151 * 160 *
152 * SYNOPSIS: Type *xnew (int n, Type); 161 * SYNOPSIS: Type *xnew (int n, Type);
162 * Type *xrnew (OldPointer, int n, Type);
153 */ 163 */
154 #ifdef chkmalloc 164 #ifdef chkmalloc
155 # include "chkmalloc.h" 165 # include "chkmalloc.h"
156 # define xnew(n,Type) ((Type *) trace_xmalloc (__FILE__, __LINE__, \ 166 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \
157 (n) * sizeof (Type))) 167 (n) * sizeof (Type)))
168 # define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \
169 (op), (n) * sizeof (Type)))
158 #else 170 #else
159 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type))) 171 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type)))
172 # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type)))
160 #endif 173 #endif
161 174
162 typedef int bool; 175 typedef int bool;
163 176
164 typedef struct nd_st 177 typedef void Lang_function ();
165 { /* sorting structure */ 178
166 char *name; /* function or type name */ 179 typedef struct
167 char *file; /* file name */ 180 {
168 bool is_func; /* use pattern or line no */ 181 char *suffix;
169 bool been_warned; /* set if noticed dup */ 182 char *command; /* Takes one arg and decompresses to stdout */
170 int lno; /* line number tag is on */ 183 } compressor;
171 long cno; /* character number line starts on */ 184
172 char *pat; /* search pattern */ 185 typedef struct
173 struct nd_st *left, *right; /* left and right sons */ 186 {
174 } NODE; 187 char *name;
188 Lang_function *function;
189 char **suffixes;
190 char **interpreters;
191 } language;
175 192
176 extern char *getenv (); 193 extern char *getenv ();
177 194
178 char *concat ();
179 char *savenstr (), *savestr ();
180 char *etags_strchr (), *etags_strrchr ();
181 char *etags_getcwd ();
182 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
183 void grow_linebuffer ();
184 long *xmalloc (), *xrealloc ();
185
186 typedef void Lang_function ();
187 /* Many compilers barf on this: 195 /* Many compilers barf on this:
188 Lang_function Asm_labels; 196 Lang_function Ada_funcs;
189 so let's write it this way */ 197 so let's write it this way */
198 void Ada_funcs ();
190 void Asm_labels (); 199 void Asm_labels ();
191 void C_entries (); 200 void C_entries ();
192 void default_C_entries (); 201 void default_C_entries ();
193 void plain_C_entries (); 202 void plain_C_entries ();
194 void Cjava_entries (); 203 void Cjava_entries ();
201 void Lisp_functions (); 210 void Lisp_functions ();
202 void Pascal_functions (); 211 void Pascal_functions ();
203 void Perl_functions (); 212 void Perl_functions ();
204 void Postscript_functions (); 213 void Postscript_functions ();
205 void Prolog_functions (); 214 void Prolog_functions ();
215 void Python_functions ();
206 void Scheme_functions (); 216 void Scheme_functions ();
207 void TeX_functions (); 217 void TeX_functions ();
208 void just_read_file (); 218 void just_read_file ();
209 219
210 Lang_function *get_language_from_name (); 220 compressor *get_compressor_from_suffix ();
211 Lang_function *get_language_from_interpreter (); 221 language *get_language_from_name ();
212 Lang_function *get_language_from_suffix (); 222 language *get_language_from_interpreter ();
223 language *get_language_from_suffix ();
213 int total_size_of_entries (); 224 int total_size_of_entries ();
214 long readline (); 225 long readline (), readline_internal ();
215 long readline_internal (); 226 void get_tag ();
227
216 #ifdef ETAGS_REGEXPS 228 #ifdef ETAGS_REGEXPS
217 void analyse_regex (); 229 void analyse_regex ();
218 void add_regex (); 230 void add_regex ();
231 void free_patterns ();
219 #endif /* ETAGS_REGEXPS */ 232 #endif /* ETAGS_REGEXPS */
220 void add_node ();
221 void error (); 233 void error ();
222 void suggest_asking_for_help (); 234 void suggest_asking_for_help ();
223 void fatal (), pfatal (); 235 void fatal (), pfatal ();
236 void add_node ();
237
238 void init ();
239 void initbuffer ();
224 void find_entries (); 240 void find_entries ();
225 void free_tree (); 241 void free_tree ();
226 void getit ();
227 void init ();
228 void initbuffer ();
229 void pfnote (), new_pfnote (); 242 void pfnote (), new_pfnote ();
230 void process_file (); 243 void process_file ();
231 void put_entries (); 244 void put_entries ();
232 void takeprec (); 245 void takeprec ();
233 246
247 char *concat ();
248 char *skip_spaces (), *skip_non_spaces ();
249 char *savenstr (), *savestr ();
250 char *etags_strchr (), *etags_strrchr ();
251 char *etags_getcwd ();
252 char *relative_filename (), *absolute_filename (), *absolute_dirname ();
253 bool filename_is_absolute ();
254 void canonicalize_filename ();
255 void grow_linebuffer ();
256 long *xmalloc (), *xrealloc ();
257
234 258
235 char searchar = '/'; /* use /.../ searches */ 259 char searchar = '/'; /* use /.../ searches */
236 260
237 int lineno; /* line number of current line */
238 long charno; /* current character number */
239 long linecharno; /* charno of start of line */
240
241 char *curfile; /* current input file name */
242 char *tagfile; /* output file */ 261 char *tagfile; /* output file */
243 char *progname; /* name this program was invoked with */ 262 char *progname; /* name this program was invoked with */
244 char *cwd; /* current working directory */ 263 char *cwd; /* current working directory */
245 char *tagfiledir; /* directory of tagfile */ 264 char *tagfiledir; /* directory of tagfile */
246
247 FILE *tagf; /* ioptr for tags file */ 265 FILE *tagf; /* ioptr for tags file */
248 NODE *head; /* the head of the binary tree of tags */ 266
267 char *curfile; /* current input file name */
268 language *curlang; /* current language */
269
270 int lineno; /* line number of current line */
271 long charno; /* current character number */
272 long linecharno; /* charno of start of current line */
273 char *dbp; /* pointer to start of current tag */
274
275 typedef struct node_st
276 { /* sorting structure */
277 char *name; /* function or type name */
278 char *file; /* file name */
279 bool is_func; /* use pattern or line no */
280 bool been_warned; /* set if noticed dup */
281 int lno; /* line number tag is on */
282 long cno; /* character number line starts on */
283 char *pat; /* search pattern */
284 struct node_st *left, *right; /* left and right sons */
285 } node;
286
287 node *head; /* the head of the binary tree of tags */
249 288
250 /* 289 /*
251 * A `struct linebuffer' is a structure which holds a line of text. 290 * A `linebuffer' is a structure which holds a line of text.
252 * `readline' reads a line from a stream into a linebuffer and works 291 * `readline_internal' reads a line from a stream into a linebuffer
253 * regardless of the length of the line. 292 * and works regardless of the length of the line.
254 * SIZE is the size of BUFFER, LEN is the length of the string in 293 * SIZE is the size of BUFFER, LEN is the length of the string in
255 * BUFFER after readline reads it. 294 * BUFFER after readline reads it.
256 */ 295 */
257 struct linebuffer 296 typedef struct
258 { 297 {
259 long size; 298 long size;
260 int len; 299 int len;
261 char *buffer; 300 char *buffer;
262 }; 301 } linebuffer;
263 302
264 struct linebuffer lb; /* the current line */ 303 linebuffer lb; /* the current line */
265 struct linebuffer token_name; /* used by C_entries as a temporary area */ 304 linebuffer token_name; /* used by C_entries as a temporary area */
266 struct 305 struct
267 { 306 {
268 long linepos; 307 long linepos;
269 struct linebuffer lb; /* used by C_entries instead of lb */ 308 linebuffer lb; /* used by C_entries instead of lb */
270 } lbs[2]; 309 } lbs[2];
271 310
272 /* boolean "functions" (see init) */ 311 /* boolean "functions" (see init) */
273 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS]; 312 bool _wht[CHARS], _nin[CHARS], _itk[CHARS], _btk[CHARS], _etk[CHARS];
274 char 313 char
275 /* white chars */ 314 /* white chars */
276 *white = " \f\t\n\013", 315 *white = " \f\t\n\r",
277 /* not in a name */ 316 /* not in a name */
278 *nonam =" \f\t\n\013(=,[;", 317 *nonam = " \f\t\n\r(=,[;",
279 /* token ending chars */ 318 /* token ending chars */
280 *endtk = " \t\n\013\"'#()[]{}=-+%*/&|^~!<>;,.:?", 319 *endtk = " \t\n\r\"'#()[]{}=-+%*/&|^~!<>;,.:?",
281 /* token starting chars */ 320 /* token starting chars */
282 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@", 321 *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$~@",
283 /* valid in-token chars */ 322 /* valid in-token chars */
284 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789"; 323 *midtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789";
285 324
286 bool append_to_tagfile; /* -a: append to tags */ 325 bool append_to_tagfile; /* -a: append to tags */
287 /* The following four default to TRUE for etags, but to FALSE for ctags. */ 326 /* The following four default to TRUE for etags, but to FALSE for ctags. */
288 bool typedefs; /* -t: create tags for C typedefs */ 327 bool typedefs; /* -t: create tags for C and Ada typedefs */
289 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */ 328 bool typedefs_and_cplusplus; /* -T: create tags for C typedefs, level */
290 /* 0 struct/enum/union decls, and C++ */ 329 /* 0 struct/enum/union decls, and C++ */
291 /* member functions. */ 330 /* member functions. */
292 bool constantypedefs; /* -d: create tags for C #define, enum */ 331 bool constantypedefs; /* -d: create tags for C #define, enum */
293 /* constants and variables. */ 332 /* constants and variables. */
294 /* -D: opposite of -d. Default under ctags. */ 333 /* -D: opposite of -d. Default under ctags. */
295 bool globals; /* create tags for C global variables */ 334 bool declarations; /* --declarations: tag them and extern in C&Co*/
335 bool globals; /* create tags for global variables */
296 bool members; /* create tags for C member variables */ 336 bool members; /* create tags for C member variables */
297 bool update; /* -u: update tags */ 337 bool update; /* -u: update tags */
298 bool vgrind_style; /* -v: create vgrind style index output */ 338 bool vgrind_style; /* -v: create vgrind style index output */
299 bool no_warnings; /* -w: suppress warnings */ 339 bool no_warnings; /* -w: suppress warnings */
300 bool cxref_style; /* -x: create cxref style output */ 340 bool cxref_style; /* -x: create cxref style output */
301 bool cplusplus; /* .[hc] means C++, not C */ 341 bool cplusplus; /* .[hc] means C++, not C */
302 bool noindentypedefs; /* -I: ignore indentation in C */ 342 bool noindentypedefs; /* -I: ignore indentation in C */
343 bool packages_only; /* --packages-only: in Ada, only tag packages*/
303 344
304 #ifdef LONG_OPTIONS 345 #ifdef LONG_OPTIONS
305 struct option longopts[] = 346 struct option longopts[] =
306 { 347 {
307 { "append", no_argument, NULL, 'a' }, 348 { "packages-only", no_argument, &packages_only, TRUE },
308 { "backward-search", no_argument, NULL, 'B' }, 349 { "append", no_argument, NULL, 'a' },
309 { "c++", no_argument, NULL, 'C' }, 350 { "backward-search", no_argument, NULL, 'B' },
310 { "cxref", no_argument, NULL, 'x' }, 351 { "c++", no_argument, NULL, 'C' },
311 { "defines", no_argument, NULL, 'd' }, 352 { "cxref", no_argument, NULL, 'x' },
312 { "no-defines", no_argument, NULL, 'D' }, 353 { "defines", no_argument, NULL, 'd' },
313 { "globals", no_argument, &globals, TRUE }, 354 { "declarations", no_argument, &declarations, TRUE },
314 { "no-globals", no_argument, &globals, FALSE }, 355 { "no-defines", no_argument, NULL, 'D' },
315 { "help", no_argument, NULL, 'h' }, 356 { "globals", no_argument, &globals, TRUE },
316 { "help", no_argument, NULL, 'H' }, 357 { "no-globals", no_argument, &globals, FALSE },
317 { "ignore-indentation", no_argument, NULL, 'I' }, 358 { "help", no_argument, NULL, 'h' },
318 { "include", required_argument, NULL, 'i' }, 359 { "help", no_argument, NULL, 'H' },
319 { "language", required_argument, NULL, 'l' }, 360 { "ignore-indentation", no_argument, NULL, 'I' },
320 { "members", no_argument, &members, TRUE }, 361 { "include", required_argument, NULL, 'i' },
321 { "no-members", no_argument, &members, FALSE }, 362 { "language", required_argument, NULL, 'l' },
322 { "no-warn", no_argument, NULL, 'w' }, 363 { "members", no_argument, &members, TRUE },
323 { "output", required_argument, NULL, 'o' }, 364 { "no-members", no_argument, &members, FALSE },
324 #ifdef ETAGS_REGEXPS 365 { "no-warn", no_argument, NULL, 'w' },
325 { "regex", required_argument, NULL, 'r' }, 366 { "output", required_argument, NULL, 'o' },
326 { "no-regex", no_argument, NULL, 'R' }, 367 #ifdef ETAGS_REGEXPS
327 #endif /* ETAGS_REGEXPS */ 368 { "regex", required_argument, NULL, 'r' },
328 { "typedefs", no_argument, NULL, 't' }, 369 { "no-regex", no_argument, NULL, 'R' },
329 { "typedefs-and-c++", no_argument, NULL, 'T' }, 370 { "ignore-case-regex", required_argument, NULL, 'c' },
330 { "update", no_argument, NULL, 'u' }, 371 #endif /* ETAGS_REGEXPS */
331 { "version", no_argument, NULL, 'V' }, 372 { "typedefs", no_argument, NULL, 't' },
332 { "vgrind", no_argument, NULL, 'v' }, 373 { "typedefs-and-c++", no_argument, NULL, 'T' },
333 { 0 } 374 { "update", no_argument, NULL, 'u' },
375 { "version", no_argument, NULL, 'V' },
376 { "vgrind", no_argument, NULL, 'v' },
377 { NULL }
334 }; 378 };
335 #endif /* LONG_OPTIONS */ 379 #endif /* LONG_OPTIONS */
336 380
337 #ifdef ETAGS_REGEXPS 381 #ifdef ETAGS_REGEXPS
338 /* Structure defining a regular expression. Elements are 382 /* Structure defining a regular expression. Elements are
339 the compiled pattern, and the name string. */ 383 the compiled pattern, and the name string. */
340 struct pattern 384 typedef struct pattern
341 { 385 {
386 struct pattern *p_next;
387 language *language;
388 char *regex;
342 struct re_pattern_buffer *pattern; 389 struct re_pattern_buffer *pattern;
343 struct re_registers regs; 390 struct re_registers regs;
344 char *name_pattern; 391 char *name_pattern;
345 bool error_signaled; 392 bool error_signaled;
393 } pattern;
394
395 /* List of all regexps. */
396 pattern *p_head = NULL;
397
398 /* How many characters in the character set. (From regex.c.) */
399 #define CHAR_SET_SIZE 256
400 /* Translation table for case-insensitive matching. */
401 char lc_trans[CHAR_SET_SIZE];
402 #endif /* ETAGS_REGEXPS */
403
404 compressor compressors[] =
405 {
406 { "z", "gzip -d -c"},
407 { "Z", "gzip -d -c"},
408 { "gz", "gzip -d -c"},
409 { "GZ", "gzip -d -c"},
410 { "bz2", "bzip2 -d -c" },
411 { NULL }
346 }; 412 };
347
348 /* Number of regexps found. */
349 int num_patterns = 0;
350
351 /* Array of all regexps. */
352 struct pattern *patterns = NULL;
353 #endif /* ETAGS_REGEXPS */
354 413
355 /* 414 /*
356 * Language stuff. 415 * Language stuff.
357 */ 416 */
358 417
359 /* Non-NULL if language fixed. */ 418 /* Non-NULL if language fixed. */
360 Lang_function *lang_func = NULL; 419 language *forced_lang = NULL;
420
421 /* Ada code */
422 char *Ada_suffixes [] =
423 { "ads", "adb", "ada", NULL };
361 424
362 /* Assembly code */ 425 /* Assembly code */
363 char *Asm_suffixes [] = { "a", /* Unix assembler */ 426 char *Asm_suffixes [] = { "a", /* Unix assembler */
364 "asm", /* Microcontroller assembly */ 427 "asm", /* Microcontroller assembly */
365 "def", /* BSO/Tasking definition includes */ 428 "def", /* BSO/Tasking definition includes */
413 "m", /* Objective C file */ 476 "m", /* Objective C file */
414 "lm", /* Objective lex file */ 477 "lm", /* Objective lex file */
415 NULL }; 478 NULL };
416 479
417 char *Postscript_suffixes [] = 480 char *Postscript_suffixes [] =
418 { "ps", NULL }; 481 { "ps", "psw", NULL }; /* .psw is for PSWrap */
419 482
420 char *Prolog_suffixes [] = 483 char *Prolog_suffixes [] =
421 { "prolog", NULL }; 484 { "prolog", NULL };
422 485
486 char *Python_suffixes [] =
487 { "py", NULL };
488
423 /* Can't do the `SCM' or `scm' prefix with a version number. */ 489 /* Can't do the `SCM' or `scm' prefix with a version number. */
424 char *Scheme_suffixes [] = 490 char *Scheme_suffixes [] =
425 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "t", NULL }; 491 { "SCM", "SM", "oak", "sch", "scheme", "scm", "sm", "ss", "t", NULL };
426 492
427 char *TeX_suffixes [] = 493 char *TeX_suffixes [] =
428 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL }; 494 { "TeX", "bib", "clo", "cls", "ltx", "sty", "tex", NULL };
429 495
430 char *Yacc_suffixes [] = 496 char *Yacc_suffixes [] =
431 { "y", "ym", "yy", "yxx", "y++", NULL }; /* .ym is Objective yacc file */ 497 { "y", "ym", "yy", "yxx", "y++", NULL }; /* .ym is Objective yacc file */
432 498
433 /* Table of language names and corresponding functions, file suffixes 499 /*
434 and interpreter names. 500 * Table of languages.
435 It is ok for a given function to be listed under more than one 501 *
436 name. I just didn't. */ 502 * It is ok for a given function to be listed under more than one
437 struct lang_entry 503 * name. I just didn't.
438 { 504 */
439 char *name; 505
440 Lang_function *function; 506 language lang_names [] =
441 char **suffixes; 507 {
442 char **interpreters; 508 { "ada", Ada_funcs, Ada_suffixes, NULL },
443 };
444
445 struct lang_entry lang_names [] =
446 {
447 { "asm", Asm_labels, Asm_suffixes, NULL }, 509 { "asm", Asm_labels, Asm_suffixes, NULL },
448 { "c", default_C_entries, default_C_suffixes, NULL }, 510 { "c", default_C_entries, default_C_suffixes, NULL },
449 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL }, 511 { "c++", Cplusplus_entries, Cplusplus_suffixes, NULL },
450 { "c*", Cstar_entries, Cstar_suffixes, NULL }, 512 { "c*", Cstar_entries, Cstar_suffixes, NULL },
451 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL }, 513 { "cobol", Cobol_paragraphs, Cobol_suffixes, NULL },
456 { "pascal", Pascal_functions, Pascal_suffixes, NULL }, 518 { "pascal", Pascal_functions, Pascal_suffixes, NULL },
457 { "perl", Perl_functions, Perl_suffixes, Perl_interpreters }, 519 { "perl", Perl_functions, Perl_suffixes, Perl_interpreters },
458 { "postscript", Postscript_functions, Postscript_suffixes, NULL }, 520 { "postscript", Postscript_functions, Postscript_suffixes, NULL },
459 { "proc", plain_C_entries, plain_C_suffixes, NULL }, 521 { "proc", plain_C_entries, plain_C_suffixes, NULL },
460 { "prolog", Prolog_functions, Prolog_suffixes, NULL }, 522 { "prolog", Prolog_functions, Prolog_suffixes, NULL },
523 { "python", Python_functions, Python_suffixes, NULL },
461 { "scheme", Scheme_functions, Scheme_suffixes, NULL }, 524 { "scheme", Scheme_functions, Scheme_suffixes, NULL },
462 { "tex", TeX_functions, TeX_suffixes, NULL }, 525 { "tex", TeX_functions, TeX_suffixes, NULL },
463 { "yacc", Yacc_entries, Yacc_suffixes, NULL }, 526 { "yacc", Yacc_entries, Yacc_suffixes, NULL },
464 { "auto", NULL }, /* default guessing scheme */ 527 { "auto", NULL }, /* default guessing scheme */
465 { "none", just_read_file }, /* regexp matching only */ 528 { "none", just_read_file }, /* regexp matching only */
466 { NULL, NULL } /* end of list */ 529 { NULL, NULL } /* end of list */
467 }; 530 };
468
469 531
470 void 532 void
471 print_language_names () 533 print_language_names ()
472 { 534 {
473 struct lang_entry *lang; 535 language *lang;
474 char **ext; 536 char **ext;
475 537
476 puts ("\nThese are the currently supported languages, along with the\n\ 538 puts ("\nThese are the currently supported languages, along with the\n\
477 default file name suffixes:"); 539 default file name suffixes:");
478 for (lang = lang_names; lang->name != NULL; lang++) 540 for (lang = lang_names; lang->name != NULL; lang++)
486 puts ("Where `auto' means use default language for files based on file\n\ 548 puts ("Where `auto' means use default language for files based on file\n\
487 name suffix, and `none' means only do regexp processing on files.\n\ 549 name suffix, and `none' means only do regexp processing on files.\n\
488 If no language is specified and no matching suffix is found,\n\ 550 If no language is specified and no matching suffix is found,\n\
489 the first line of the file is read for a sharp-bang (#!) sequence\n\ 551 the first line of the file is read for a sharp-bang (#!) sequence\n\
490 followed by the name of an interpreter. If no such sequence is found,\n\ 552 followed by the name of an interpreter. If no such sequence is found,\n\
491 Fortran is tried first; if no tags are found, C is tried next."); 553 Fortran is tried first; if no tags are found, C is tried next.\n\
554 Compressed files are supported using gzip and bzip2.");
492 } 555 }
493 556
494 #ifndef VERSION 557 #ifndef VERSION
495 # define VERSION "19" 558 # define VERSION "20"
496 #endif 559 #endif
497 void 560 void
498 print_version () 561 print_version ()
499 { 562 {
500 printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION); 563 printf ("%s (GNU Emacs %s)\n", (CTAGS) ? "ctags" : "etags", VERSION);
514 puts ("You may use unambiguous abbreviations for the long option names."); 577 puts ("You may use unambiguous abbreviations for the long option names.");
515 #else 578 #else
516 puts ("Long option names do not work with this executable, as it is not\n\ 579 puts ("Long option names do not work with this executable, as it is not\n\
517 linked with GNU getopt."); 580 linked with GNU getopt.");
518 #endif /* LONG_OPTIONS */ 581 #endif /* LONG_OPTIONS */
519 puts ("A - as file name means read names from stdin."); 582 puts ("A - as file name means read names from stdin (one per line).");
520 if (!CTAGS) 583 if (!CTAGS)
521 printf (" Absolute names are stored in the output file as they\n\ 584 printf (" Absolute names are stored in the output file as they are.\n\
522 are. Relative ones are stored relative to the output file's directory."); 585 Relative ones are stored relative to the output file's directory.");
523 puts ("\n"); 586 puts ("\n");
524 587
525 puts ("-a, --append\n\ 588 puts ("-a, --append\n\
526 Append tag entries to existing tags file."); 589 Append tag entries to existing tags file.");
590
591 puts ("--packages-only\n\
592 For Ada files, only generate tags for packages .");
527 593
528 if (CTAGS) 594 if (CTAGS)
529 puts ("-B, --backward-search\n\ 595 puts ("-B, --backward-search\n\
530 Write the search commands for the tag entries using '?', the\n\ 596 Write the search commands for the tag entries using '?', the\n\
531 backward-search command instead of '/', the forward-search command."); 597 backward-search command instead of '/', the forward-search command.");
532 598
533 puts ("-C, --c++\n\ 599 puts ("-C, --c++\n\
534 Treat files whose name suffix defaults to C language as C++ files."); 600 Treat files whose name suffix defaults to C language as C++ files.");
601
602 puts ("--declarations\n\
603 In C and derived languages, create tags for function declarations,");
604 if (CTAGS)
605 puts ("\tand create tags for extern variables if --globals is used.");
606 else
607 puts
608 ("\tand create tags for extern variables unless --no-globals is used.");
535 609
536 if (CTAGS) 610 if (CTAGS)
537 puts ("-d, --defines\n\ 611 puts ("-d, --defines\n\
538 Create tag entries for C #define constants and enum constants, too."); 612 Create tag entries for C #define constants and enum constants, too.");
539 else 613 else
552 named language up to the next --language=LANG option."); 626 named language up to the next --language=LANG option.");
553 } 627 }
554 628
555 if (CTAGS) 629 if (CTAGS)
556 puts ("--globals\n\ 630 puts ("--globals\n\
557 Create tag entries for global variables in C and derived languages."); 631 Create tag entries for global variables in some languages.");
558 else 632 else
559 puts ("--no-globals\n\ 633 puts ("--no-globals\n\
560 Do not create tag entries for global variables in C and\n\ 634 Do not create tag entries for global variables in some\n\
561 derived languages. This makes the tags file smaller."); 635 languages. This makes the tags file smaller.");
562 puts ("--members\n\ 636 puts ("--members\n\
563 Create tag entries for member variables in C and derived languages."); 637 Create tag entries for member variables in C and derived languages.");
564 638
565 #ifdef ETAGS_REGEXPS 639 #ifdef ETAGS_REGEXPS
566 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\ 640 puts ("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
567 Make a tag for each line matching pattern REGEXP in the\n\ 641 Make a tag for each line matching pattern REGEXP in the following\n\
568 following files. regexfile is a file containing one REGEXP\n\ 642 files. {LANGUAGE}/REGEXP/ uses REGEXP for LANGUAGE files only.\n\
569 per line. REGEXP is anchored (as if preceded by ^).\n\ 643 regexfile is a file containing one REGEXP per line.\n\
570 The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\ 644 REGEXP is anchored (as if preceded by ^).\n\
571 named tags can be created with:\n\ 645 The form /REGEXP/NAME/ creates a named tag.\n\
646 For example Tcl named tags can be created with:\n\
572 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/."); 647 --regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
648 puts ("-c /REGEXP/, --ignore-case-regex=/REGEXP/ or --ignore-case-regex=@regexfile\n\
649 Like -r, --regex but ignore case when matching expressions.");
573 puts ("-R, --no-regex\n\ 650 puts ("-R, --no-regex\n\
574 Don't create tags from regexps for the following files."); 651 Don't create tags from regexps for the following files.");
575 #endif /* ETAGS_REGEXPS */ 652 #endif /* ETAGS_REGEXPS */
576 puts ("-o FILE, --output=FILE\n\ 653 puts ("-o FILE, --output=FILE\n\
577 Write the tags to FILE."); 654 Write the tags to FILE.");
582 definition in C and C++."); 659 definition in C and C++.");
583 660
584 if (CTAGS) 661 if (CTAGS)
585 { 662 {
586 puts ("-t, --typedefs\n\ 663 puts ("-t, --typedefs\n\
587 Generate tag entries for C typedefs."); 664 Generate tag entries for C and Ada typedefs.");
588 puts ("-T, --typedefs-and-c++\n\ 665 puts ("-T, --typedefs-and-c++\n\
589 Generate tag entries for C typedefs, C struct/enum/union tags,\n\ 666 Generate tag entries for C typedefs, C struct/enum/union tags,\n\
590 and C++ member functions."); 667 and C++ member functions.");
591 puts ("-u, --update\n\ 668 puts ("-u, --update\n\
592 Update the tag entries for the given files, leaving tag\n\ 669 Update the tag entries for the given files, leaving tag\n\
625 702
626 enum argument_type 703 enum argument_type
627 { 704 {
628 at_language, 705 at_language,
629 at_regexp, 706 at_regexp,
630 at_filename 707 at_filename,
708 at_icregexp
631 }; 709 };
632 710
633 /* This structure helps us allow mixing of --lang and file names. */ 711 /* This structure helps us allow mixing of --lang and file names. */
634 typedef struct 712 typedef struct
635 { 713 {
636 enum argument_type arg_type; 714 enum argument_type arg_type;
637 char *what; 715 char *what;
638 Lang_function *function; 716 language *lang; /* language of the regexp */
639 } argument; 717 } argument;
640 718
641 #ifdef VMS /* VMS specific functions */ 719 #ifdef VMS /* VMS specific functions */
642 720
643 #define EOS '\0' 721 #define EOS '\0'
772 unsigned int nincluded_files; 850 unsigned int nincluded_files;
773 char **included_files; 851 char **included_files;
774 char *this_file; 852 char *this_file;
775 argument *argbuffer; 853 argument *argbuffer;
776 int current_arg, file_count; 854 int current_arg, file_count;
777 struct linebuffer filename_lb; 855 linebuffer filename_lb;
778 #ifdef VMS 856 #ifdef VMS
779 bool got_err; 857 bool got_err;
780 #endif 858 #endif
781 859
782 #ifdef DOS_NT 860 #ifdef DOS_NT
793 is small. */ 871 is small. */
794 argbuffer = xnew (argc, argument); 872 argbuffer = xnew (argc, argument);
795 873
796 #ifdef ETAGS_REGEXPS 874 #ifdef ETAGS_REGEXPS
797 /* Set syntax for regular expression routines. */ 875 /* Set syntax for regular expression routines. */
798 re_set_syntax (RE_SYNTAX_EMACS); 876 re_set_syntax (RE_SYNTAX_EMACS | RE_INTERVALS);
877 /* Translation table for case-insensitive search. */
878 for (i = 0; i < CHAR_SET_SIZE; i++)
879 lc_trans[i] = lowcase (i);
799 #endif /* ETAGS_REGEXPS */ 880 #endif /* ETAGS_REGEXPS */
800 881
801 /* 882 /*
802 * If etags, always find typedefs and structure tags. Why not? 883 * If etags, always find typedefs and structure tags. Why not?
803 * Also default is to find macro constants, enum constants and 884 * Also default is to find macro constants, enum constants and
804 * global variables. 885 * global variables.
805 */ 886 */
806 if (!CTAGS) 887 if (!CTAGS)
807 { 888 {
808 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE; 889 typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
809 globals = TRUE; 890 globals = TRUE;
814 { 895 {
815 int opt; 896 int opt;
816 char *optstring; 897 char *optstring;
817 898
818 #ifdef ETAGS_REGEXPS 899 #ifdef ETAGS_REGEXPS
819 optstring = "-aCdDf:Il:o:r:RStTi:BuvxwVhH"; 900 optstring = "-aCdDf:Il:o:r:c:RStTi:BuvxwVhH";
820 #else 901 #else
821 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH"; 902 optstring = "-aCdDf:Il:o:StTi:BuvxwVhH";
822 #endif /* ETAGS_REGEXPS */ 903 #endif /* ETAGS_REGEXPS */
823 904
824 #ifndef LONG_OPTIONS 905 #ifndef LONG_OPTIONS
861 case 'I': 942 case 'I':
862 case 'S': /* for backward compatibility */ 943 case 'S': /* for backward compatibility */
863 noindentypedefs = TRUE; 944 noindentypedefs = TRUE;
864 break; 945 break;
865 case 'l': 946 case 'l':
866 argbuffer[current_arg].function = get_language_from_name (optarg); 947 {
867 argbuffer[current_arg].arg_type = at_language; 948 language *lang = get_language_from_name (optarg);
868 ++current_arg; 949 if (lang != NULL)
950 {
951 argbuffer[current_arg].lang = lang;
952 argbuffer[current_arg].arg_type = at_language;
953 ++current_arg;
954 }
955 }
869 break; 956 break;
870 #ifdef ETAGS_REGEXPS 957 #ifdef ETAGS_REGEXPS
871 case 'r': 958 case 'r':
872 argbuffer[current_arg].arg_type = at_regexp; 959 argbuffer[current_arg].arg_type = at_regexp;
873 argbuffer[current_arg].what = optarg; 960 argbuffer[current_arg].what = optarg;
874 ++current_arg; 961 ++current_arg;
875 break; 962 break;
876 case 'R': 963 case 'R':
877 argbuffer[current_arg].arg_type = at_regexp; 964 argbuffer[current_arg].arg_type = at_regexp;
878 argbuffer[current_arg].what = NULL; 965 argbuffer[current_arg].what = NULL;
966 ++current_arg;
967 break;
968 case 'c':
969 argbuffer[current_arg].arg_type = at_icregexp;
970 argbuffer[current_arg].what = optarg;
879 ++current_arg; 971 ++current_arg;
880 break; 972 break;
881 #endif /* ETAGS_REGEXPS */ 973 #endif /* ETAGS_REGEXPS */
882 case 'V': 974 case 'V':
883 print_version (); 975 print_version ();
970 for (i = 0; i < current_arg; ++i) 1062 for (i = 0; i < current_arg; ++i)
971 { 1063 {
972 switch (argbuffer[i].arg_type) 1064 switch (argbuffer[i].arg_type)
973 { 1065 {
974 case at_language: 1066 case at_language:
975 lang_func = argbuffer[i].function; 1067 forced_lang = argbuffer[i].lang;
976 break; 1068 break;
977 #ifdef ETAGS_REGEXPS 1069 #ifdef ETAGS_REGEXPS
978 case at_regexp: 1070 case at_regexp:
979 analyse_regex (argbuffer[i].what); 1071 analyse_regex (argbuffer[i].what, FALSE);
1072 break;
1073 case at_icregexp:
1074 analyse_regex (argbuffer[i].what, TRUE);
980 break; 1075 break;
981 #endif 1076 #endif
982 case at_filename: 1077 case at_filename:
983 #ifdef VMS 1078 #ifdef VMS
984 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL) 1079 while ((this_file = gfnames (argbuffer[i].what, &got_err)) != NULL)
994 } 1089 }
995 #else 1090 #else
996 this_file = argbuffer[i].what; 1091 this_file = argbuffer[i].what;
997 #endif 1092 #endif
998 /* Input file named "-" means read file names from stdin 1093 /* Input file named "-" means read file names from stdin
999 and use them. */ 1094 (one per line) and use them. */
1000 if (streq (this_file, "-")) 1095 if (streq (this_file, "-"))
1001 while (readline_internal (&filename_lb, stdin) > 0) 1096 while (readline_internal (&filename_lb, stdin) > 0)
1002 process_file (filename_lb.buffer); 1097 process_file (filename_lb.buffer);
1003 else 1098 else
1004 process_file (this_file); 1099 process_file (this_file);
1007 #endif 1102 #endif
1008 break; 1103 break;
1009 } 1104 }
1010 } 1105 }
1011 1106
1107 #ifdef ETAGS_REGEXPS
1108 free_patterns ();
1109 #endif /* ETAGS_REGEXPS */
1110
1012 if (!CTAGS) 1111 if (!CTAGS)
1013 { 1112 {
1014 while (nincluded_files-- > 0) 1113 while (nincluded_files-- > 0)
1015 fprintf (tagf, "\f\n%s,include\n", *included_files++); 1114 fprintf (tagf, "\f\n%s,include\n", *included_files++);
1016 1115
1021 /* If CTAGS, we are here. process_file did not write the tags yet, 1120 /* If CTAGS, we are here. process_file did not write the tags yet,
1022 because we want them ordered. Let's do it now. */ 1121 because we want them ordered. Let's do it now. */
1023 if (cxref_style) 1122 if (cxref_style)
1024 { 1123 {
1025 put_entries (head); 1124 put_entries (head);
1125 free_tree (head);
1126 head = NULL;
1026 exit (GOOD); 1127 exit (GOOD);
1027 } 1128 }
1028 1129
1029 if (update) 1130 if (update)
1030 { 1131 {
1044 1145
1045 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w"); 1146 tagf = fopen (tagfile, append_to_tagfile ? "a" : "w");
1046 if (tagf == NULL) 1147 if (tagf == NULL)
1047 pfatal (tagfile); 1148 pfatal (tagfile);
1048 put_entries (head); 1149 put_entries (head);
1150 free_tree (head);
1151 head = NULL;
1049 fclose (tagf); 1152 fclose (tagf);
1050 1153
1051 if (update) 1154 if (update)
1052 { 1155 {
1053 char cmd[BUFSIZ]; 1156 char cmd[BUFSIZ];
1056 } 1159 }
1057 return GOOD; 1160 return GOOD;
1058 } 1161 }
1059 1162
1060 1163
1164
1061 /* 1165 /*
1062 * Return a Lang_function given the name. 1166 * Return a compressor given the file name. If EXTPTR is non-zero,
1167 * return a pointer into FILE where the compressor-specific
1168 * extension begins. If no compressor is found, NULL is returned
1169 * and EXTPTR is not significant.
1170 * Idea by Vladimir Alexiev <vladimir@cs.ualberta.ca>
1063 */ 1171 */
1064 Lang_function * 1172 compressor *
1173 get_compressor_from_suffix (file, extptr)
1174 char *file;
1175 char **extptr;
1176 {
1177 compressor *compr;
1178 char *slash, *suffix;
1179
1180 /* This relies on FN to be after canonicalize_filename,
1181 so we don't need to consider backslashes on DOS_NT. */
1182 slash = etags_strrchr (file, '/');
1183 suffix = etags_strrchr (file, '.');
1184 if (suffix == NULL || suffix < slash)
1185 return NULL;
1186 if (extptr != NULL)
1187 *extptr = suffix;
1188 suffix += 1;
1189 /* Let those poor souls who live with DOS 8+3 file name limits get
1190 some solace by treating foo.cgz as if it were foo.c.gz, etc.
1191 Only the first do loop is run if not MSDOS */
1192 do
1193 {
1194 for (compr = compressors; compr->suffix != NULL; compr++)
1195 if (streq (compr->suffix, suffix))
1196 return compr;
1197 #ifndef MSDOS
1198 break;
1199 #endif
1200 if (extptr != NULL)
1201 *extptr = ++suffix;
1202 } while (*suffix != '\0');
1203 return NULL;
1204 }
1205
1206
1207
1208 /*
1209 * Return a language given the name.
1210 */
1211 language *
1065 get_language_from_name (name) 1212 get_language_from_name (name)
1066 char *name; 1213 char *name;
1067 { 1214 {
1068 struct lang_entry *lang; 1215 language *lang;
1069 1216
1070 if (name != NULL) 1217 if (name == NULL)
1071 for (lang = lang_names; lang->name != NULL; lang++) 1218 error ("empty language name", (char *)NULL);
1072 { 1219 else
1220 {
1221 for (lang = lang_names; lang->name != NULL; lang++)
1073 if (streq (name, lang->name)) 1222 if (streq (name, lang->name))
1074 return lang->function; 1223 return lang;
1075 } 1224 error ("unknown language \"%s\"", name);
1076 1225 }
1077 error ("language \"%s\" not recognized.", optarg); 1226
1078 suggest_asking_for_help (); 1227 return NULL;
1079
1080 /* This point should never be reached. The function should either
1081 return a function pointer or never return. Note that a NULL
1082 pointer cannot be considered as an error, as it means that the
1083 language has not been explicitely imposed by the user ("auto"). */
1084 return NULL; /* avoid warnings from compiler */
1085 } 1228 }
1086 1229
1087 1230
1088 /* 1231 /*
1089 * Return a Lang_function given the interpreter name. 1232 * Return a language given the interpreter name.
1090 */ 1233 */
1091 Lang_function * 1234 language *
1092 get_language_from_interpreter (interpreter) 1235 get_language_from_interpreter (interpreter)
1093 char *interpreter; 1236 char *interpreter;
1094 { 1237 {
1095 struct lang_entry *lang; 1238 language *lang;
1096 char **iname; 1239 char **iname;
1097 1240
1098 if (interpreter == NULL) 1241 if (interpreter == NULL)
1099 return NULL; 1242 return NULL;
1100 for (lang = lang_names; lang->name != NULL; lang++) 1243 for (lang = lang_names; lang->name != NULL; lang++)
1101 if (lang->interpreters != NULL) 1244 if (lang->interpreters != NULL)
1102 for (iname = lang->interpreters; *iname != NULL; iname++) 1245 for (iname = lang->interpreters; *iname != NULL; iname++)
1103 if (streq (*iname, interpreter)) 1246 if (streq (*iname, interpreter))
1104 return lang->function; 1247 return lang;
1105 1248
1106 return NULL; 1249 return NULL;
1107 } 1250 }
1108 1251
1109 1252
1110 1253
1111 /* 1254 /*
1112 * Return a Lang_function given the file suffix. 1255 * Return a language given the file name.
1113 */ 1256 */
1114 Lang_function * 1257 language *
1115 get_language_from_suffix (suffix) 1258 get_language_from_suffix (file)
1116 char *suffix; 1259 char *file;
1117 { 1260 {
1118 struct lang_entry *lang; 1261 language *lang;
1119 char **ext; 1262 char **ext, *suffix;
1120 1263
1264 suffix = etags_strrchr (file, '.');
1121 if (suffix == NULL) 1265 if (suffix == NULL)
1122 return NULL; 1266 return NULL;
1267 suffix += 1;
1123 for (lang = lang_names; lang->name != NULL; lang++) 1268 for (lang = lang_names; lang->name != NULL; lang++)
1124 if (lang->suffixes != NULL) 1269 if (lang->suffixes != NULL)
1125 for (ext = lang->suffixes; *ext != NULL; ext++) 1270 for (ext = lang->suffixes; *ext != NULL; ext++)
1126 if (streq (*ext, suffix)) 1271 if (streq (*ext, suffix))
1127 return lang->function; 1272 return lang;
1128
1129 return NULL; 1273 return NULL;
1130 } 1274 }
1275
1131 1276
1132 1277
1133 /* 1278 /*
1134 * This routine is called on each file argument. 1279 * This routine is called on each file argument.
1135 */ 1280 */
1137 process_file (file) 1282 process_file (file)
1138 char *file; 1283 char *file;
1139 { 1284 {
1140 struct stat stat_buf; 1285 struct stat stat_buf;
1141 FILE *inf; 1286 FILE *inf;
1142 #ifdef DOS_NT 1287 compressor *compr;
1143 char *p; 1288 char *compressed_name, *uncompressed_name;
1144 1289 char *ext, *real_name;
1145 for (p = file; *p != '\0'; p++) 1290
1146 if (*p == '\\') 1291
1147 *p = '/'; 1292 canonicalize_filename (file);
1148 #endif
1149
1150 if (stat (file, &stat_buf) == 0 && !S_ISREG (stat_buf.st_mode))
1151 {
1152 error ("skipping %s: it is not a regular file.", file);
1153 return;
1154 }
1155 if (streq (file, tagfile) && !streq (tagfile, "-")) 1293 if (streq (file, tagfile) && !streq (tagfile, "-"))
1156 { 1294 {
1157 error ("skipping inclusion of %s in self.", file); 1295 error ("skipping inclusion of %s in self.", file);
1158 return; 1296 return;
1159 } 1297 }
1160 inf = fopen (file, "r"); 1298 if ((compr = get_compressor_from_suffix (file, &ext)) == NULL)
1299 {
1300 compressed_name = NULL;
1301 real_name = uncompressed_name = savestr (file);
1302 }
1303 else
1304 {
1305 real_name = compressed_name = savestr (file);
1306 uncompressed_name = savenstr (file, ext - file);
1307 }
1308
1309 /* If the canonicalised uncompressed name has already be dealt with,
1310 skip it silently, else add it to the list. */
1311 {
1312 typedef struct processed_file
1313 {
1314 char *filename;
1315 struct processed_file *next;
1316 } processed_file;
1317 static processed_file *pf_head = NULL;
1318 register processed_file *fnp;
1319
1320 for (fnp = pf_head; fnp != NULL; fnp = fnp->next)
1321 if (streq (uncompressed_name, fnp->filename))
1322 goto exit;
1323 fnp = pf_head;
1324 pf_head = xnew (1, struct processed_file);
1325 pf_head->filename = savestr (uncompressed_name);
1326 pf_head->next = fnp;
1327 }
1328
1329 if (stat (real_name, &stat_buf) != 0)
1330 {
1331 /* Reset real_name and try with a different name. */
1332 real_name = NULL;
1333 if (compressed_name != NULL) /* try with the given suffix */
1334 {
1335 if (stat (uncompressed_name, &stat_buf) == 0)
1336 real_name = uncompressed_name;
1337 }
1338 else /* try all possible suffixes */
1339 {
1340 for (compr = compressors; compr->suffix != NULL; compr++)
1341 {
1342 compressed_name = concat (file, ".", compr->suffix);
1343 if (stat (compressed_name, &stat_buf) != 0)
1344 {
1345 #ifdef MSDOS
1346 char *suf = compressed_name + strlen (file);
1347 size_t suflen = strlen (compr->suffix) + 1;
1348 for ( ; suf[1]; suf++, suflen--)
1349 {
1350 memmove (suf, suf + 1, suflen);
1351 if (stat (compressed_name, &stat_buf) == 0)
1352 {
1353 real_name = compressed_name;
1354 break;
1355 }
1356 }
1357 if (real_name != NULL)
1358 break;
1359 #endif
1360 free (compressed_name);
1361 compressed_name = NULL;
1362 }
1363 else
1364 {
1365 real_name = compressed_name;
1366 break;
1367 }
1368 }
1369 }
1370 if (real_name == NULL)
1371 {
1372 perror (file);
1373 goto exit;
1374 }
1375 } /* try with a different name */
1376
1377 if (!S_ISREG (stat_buf.st_mode))
1378 {
1379 error ("skipping %s: it is not a regular file.", real_name);
1380 goto exit;
1381 }
1382 if (real_name == compressed_name)
1383 {
1384 char *cmd = concat (compr->command, " ", real_name);
1385 inf = popen (cmd, "r");
1386 free (cmd);
1387 }
1388 else
1389 inf = fopen (real_name, "r");
1161 if (inf == NULL) 1390 if (inf == NULL)
1162 { 1391 {
1163 perror (file); 1392 perror (real_name);
1164 return; 1393 goto exit;
1165 } 1394 }
1166 1395
1167 find_entries (file, inf); 1396 find_entries (uncompressed_name, inf);
1397
1398 if (real_name == compressed_name)
1399 pclose (inf);
1400 else
1401 fclose (inf);
1168 1402
1169 if (!CTAGS) 1403 if (!CTAGS)
1170 { 1404 {
1171 char *filename; 1405 char *filename;
1172 1406
1173 if (absolutefn (file)) 1407 if (filename_is_absolute (uncompressed_name))
1174 { 1408 {
1175 /* file is an absolute file name. Canonicalise it. */ 1409 /* file is an absolute file name. Canonicalise it. */
1176 filename = absolute_filename (file, cwd); 1410 filename = absolute_filename (uncompressed_name, cwd);
1177 } 1411 }
1178 else 1412 else
1179 { 1413 {
1180 /* file is a file name relative to cwd. Make it relative 1414 /* file is a file name relative to cwd. Make it relative
1181 to the directory of the tags file. */ 1415 to the directory of the tags file. */
1182 filename = relative_filename (file, tagfiledir); 1416 filename = relative_filename (uncompressed_name, tagfiledir);
1183 } 1417 }
1184 fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head)); 1418 fprintf (tagf, "\f\n%s,%d\n", filename, total_size_of_entries (head));
1185 free (filename); 1419 free (filename);
1186 put_entries (head); 1420 put_entries (head);
1187 free_tree (head); 1421 free_tree (head);
1188 head = NULL; 1422 head = NULL;
1189 } 1423 }
1424
1425 exit:
1426 if (compressed_name) free(compressed_name);
1427 if (uncompressed_name) free(uncompressed_name);
1428 return;
1190 } 1429 }
1191 1430
1192 /* 1431 /*
1193 * This routine sets up the boolean pseudo-functions which work 1432 * This routine sets up the boolean pseudo-functions which work
1194 * by setting boolean flags dependent upon the corresponding character 1433 * by setting boolean flags dependent upon the corresponding character.
1195 * Every char which is NOT in that string is not a white char. Therefore, 1434 * Every char which is NOT in that string is not a white char. Therefore,
1196 * all of the array "_wht" is set to FALSE, and then the elements 1435 * all of the array "_wht" is set to FALSE, and then the elements
1197 * subscripted by the chars in "white" are set to TRUE. Thus "_wht" 1436 * subscripted by the chars in "white" are set to TRUE. Thus "_wht"
1198 * of a char is TRUE if it is the string "white", else FALSE. 1437 * of a char is TRUE if it is the string "white", else FALSE.
1199 */ 1438 */
1202 { 1441 {
1203 register char *sp; 1442 register char *sp;
1204 register int i; 1443 register int i;
1205 1444
1206 for (i = 0; i < CHARS; i++) 1445 for (i = 0; i < CHARS; i++)
1207 _wht[i] = _nin[i] = _etk[i] = _itk[i] = _btk[i] = FALSE; 1446 iswhite(i) = notinname(i) = begtoken(i) = intoken(i) = endtoken(i) = FALSE;
1208 for (sp = white; *sp; sp++) _wht[*sp] = TRUE; _wht[0] = _wht['\n']; 1447 for (sp = white; *sp != '\0'; sp++) iswhite (*sp) = TRUE;
1209 for (sp = nonam; *sp; sp++) _nin[*sp] = TRUE; _nin[0] = _nin['\n']; 1448 for (sp = nonam; *sp != '\0'; sp++) notinname (*sp) = TRUE;
1210 for (sp = endtk; *sp; sp++) _etk[*sp] = TRUE; _etk[0] = _etk['\n']; 1449 for (sp = begtk; *sp != '\0'; sp++) begtoken (*sp) = TRUE;
1211 for (sp = midtk; *sp; sp++) _itk[*sp] = TRUE; _btk[0] = _btk['\n']; 1450 for (sp = midtk; *sp != '\0'; sp++) intoken (*sp) = TRUE;
1212 for (sp = begtk; *sp; sp++) _btk[*sp] = TRUE; _itk[0] = _itk['\n']; 1451 for (sp = endtk; *sp != '\0'; sp++) endtoken (*sp) = TRUE;
1452 iswhite('\0') = iswhite('\n');
1453 notinname('\0') = notinname('\n');
1454 begtoken('\0') = begtoken('\n');
1455 intoken('\0') = intoken('\n');
1456 endtoken('\0') = endtoken('\n');
1213 } 1457 }
1214 1458
1215 /* 1459 /*
1216 * This routine opens the specified file and calls the function 1460 * This routine opens the specified file and calls the function
1217 * which finds the function and type definitions. 1461 * which finds the function and type definitions.
1218 */ 1462 */
1463 node *last_node = NULL;
1464
1219 void 1465 void
1220 find_entries (file, inf) 1466 find_entries (file, inf)
1221 char *file; 1467 char *file;
1222 FILE *inf; 1468 FILE *inf;
1223 { 1469 {
1224 char *cp; 1470 char *cp;
1225 Lang_function *function; 1471 language *lang;
1226 NODE *old_last_node; 1472 node *old_last_node;
1227 extern NODE *last_node; 1473
1228 1474 /* Memory leakage here: the string pointed by curfile is
1229 1475 never released, because curfile is copied into np->file
1230 /* Memory leakage here: the memory block pointed by curfile is never 1476 for each node, to be used in CTAGS mode. The amount of
1231 released. The amount of memory leaked here is the sum of the 1477 memory leaked here is the sum of the lengths of the
1232 lengths of the input file names. */ 1478 file names. */
1233 curfile = savestr (file); 1479 curfile = savestr (file);
1234 1480
1235 /* If user specified a language, use it. */ 1481 /* If user specified a language, use it. */
1236 function = lang_func; 1482 lang = forced_lang;
1237 if (function != NULL) 1483 if (lang != NULL && lang->function != NULL)
1238 { 1484 {
1239 function (inf); 1485 curlang = lang;
1240 fclose (inf); 1486 lang->function (inf);
1241 return; 1487 return;
1242 } 1488 }
1243 1489
1244 cp = etags_strrchr (file, '.'); 1490 /* Try to guess the language given the file name. */
1245 if (cp != NULL) 1491 lang = get_language_from_suffix (file);
1246 { 1492 if (lang != NULL && lang->function != NULL)
1247 cp += 1; 1493 {
1248 function = get_language_from_suffix (cp); 1494 curlang = lang;
1249 if (function != NULL) 1495 lang->function (inf);
1250 { 1496 return;
1251 function (inf);
1252 fclose (inf);
1253 return;
1254 }
1255 } 1497 }
1256 1498
1257 /* Look for sharp-bang as the first two characters. */ 1499 /* Look for sharp-bang as the first two characters. */
1258 if (readline_internal (&lb, inf) 1500 if (readline_internal (&lb, inf) > 0
1259 && lb.len >= 2 1501 && lb.len >= 2
1260 && lb.buffer[0] == '#' 1502 && lb.buffer[0] == '#'
1261 && lb.buffer[1] == '!') 1503 && lb.buffer[1] == '!')
1262 { 1504 {
1263 char *lp; 1505 char *lp;
1267 the first successive blank and terminate the string. */ 1509 the first successive blank and terminate the string. */
1268 lp = etags_strrchr (lb.buffer+2, '/'); 1510 lp = etags_strrchr (lb.buffer+2, '/');
1269 if (lp != NULL) 1511 if (lp != NULL)
1270 lp += 1; 1512 lp += 1;
1271 else 1513 else
1272 for (lp = lb.buffer+2; *lp != '\0' && isspace (*lp); lp++) 1514 lp = skip_spaces (lb.buffer + 2);
1273 continue; 1515 cp = skip_non_spaces (lp);
1274 for (cp = lp; *cp != '\0' && !isspace (*cp); cp++)
1275 continue;
1276 *cp = '\0'; 1516 *cp = '\0';
1277 1517
1278 if (strlen (lp) > 0) 1518 if (strlen (lp) > 0)
1279 { 1519 {
1280 function = get_language_from_interpreter (lp); 1520 lang = get_language_from_interpreter (lp);
1281 if (function != NULL) 1521 if (lang != NULL && lang->function != NULL)
1282 { 1522 {
1283 function (inf); 1523 curlang = lang;
1284 fclose (inf); 1524 lang->function (inf);
1285 return; 1525 return;
1286 } 1526 }
1287 } 1527 }
1288 } 1528 }
1529 /* We rewind here, even if inf may be a pipe. We fail if the
1530 length of the first line is longer than the pipe block size,
1531 which is unlikely. */
1289 rewind (inf); 1532 rewind (inf);
1290 1533
1291 /* Try Fortran. */ 1534 /* Try Fortran. */
1292 old_last_node = last_node; 1535 old_last_node = last_node;
1536 curlang = get_language_from_name ("fortran");
1293 Fortran_functions (inf); 1537 Fortran_functions (inf);
1294 1538
1295 /* No Fortran entries found. Try C. */ 1539 /* No Fortran entries found. Try C. */
1296 if (old_last_node == last_node) 1540 if (old_last_node == last_node)
1297 { 1541 {
1542 /* We do not tag if rewind fails.
1543 Only the file name will be recorded in the tags file. */
1298 rewind (inf); 1544 rewind (inf);
1545 curlang = get_language_from_name (cplusplus ? "c++" : "c");
1299 default_C_entries (inf); 1546 default_C_entries (inf);
1300 } 1547 }
1301 fclose (inf);
1302 return; 1548 return;
1303 } 1549 }
1304 1550
1305 /* Record a tag. */ 1551 /* Record a tag. */
1306 void 1552 void
1310 char *linestart; /* start of the line where tag is */ 1556 char *linestart; /* start of the line where tag is */
1311 int linelen; /* length of the line where tag is */ 1557 int linelen; /* length of the line where tag is */
1312 int lno; /* line number */ 1558 int lno; /* line number */
1313 long cno; /* character number */ 1559 long cno; /* character number */
1314 { 1560 {
1315 register NODE *np; 1561 register node *np;
1316 1562
1317 if (CTAGS && name == NULL) 1563 if (CTAGS && name == NULL)
1318 return; 1564 return;
1319 1565
1320 np = xnew (1, NODE); 1566 np = xnew (1, node);
1321 1567
1322 /* If ctags mode, change name "main" to M<thisfilename>. */ 1568 /* If ctags mode, change name "main" to M<thisfilename>. */
1323 if (CTAGS && !cxref_style && streq (name, "main")) 1569 if (CTAGS && !cxref_style && streq (name, "main"))
1324 { 1570 {
1325 register char *fp = etags_strrchr (curfile, '/'); 1571 register char *fp = etags_strrchr (curfile, '/');
1326 np->name = concat ("M", fp == 0 ? curfile : fp + 1, ""); 1572 np->name = concat ("M", fp == NULL ? curfile : fp + 1, "");
1327 fp = etags_strrchr (np->name, '.'); 1573 fp = etags_strrchr (np->name, '.');
1328 if (fp && fp[1] != '\0' && fp[2] == '\0') 1574 if (fp != NULL && fp[1] != '\0' && fp[2] == '\0')
1329 fp[0] = 0; 1575 fp[0] = '\0';
1330 } 1576 }
1331 else 1577 else
1332 np->name = name; 1578 np->name = name;
1333 np->been_warned = FALSE; 1579 np->been_warned = FALSE;
1334 np->file = curfile; 1580 np->file = curfile;
1352 np->pat = savenstr (linestart, linelen); 1598 np->pat = savenstr (linestart, linelen);
1353 1599
1354 add_node (np, &head); 1600 add_node (np, &head);
1355 } 1601 }
1356 1602
1357 /* Date: Wed, 22 Jan 1997 02:56:31 -0500 1603 /* Date: Wed, 22 Jan 1997 02:56:31 -0500 [last amended 18 Sep 1997]
1358 * From: Sam Kendall <kendall@cybercom.net> 1604 * From: Sam Kendall <kendall@mv.mv.com>
1359 * Subject: Proposal for firming up the TAGS format specification 1605 * Subject: Proposal for firming up the TAGS format specification
1360 * To: F.Potorti@cnuce.cnr.it 1606 * To: F.Potorti@cnuce.cnr.it
1361 * 1607 *
1362 * pfnote should emit the optimized form [unnamed tag] only if: 1608 * pfnote should emit the optimized form [unnamed tag] only if:
1363 * 1. name does not contain any of the characters " \t\r\n()"; 1609 * 1. name does not contain any of the characters " \t\r\n(),;";
1364 * 2. linestart contains name as either a rightmost, or rightmost but 1610 * 2. linestart contains name as either a rightmost, or rightmost but
1365 * one character, substring; 1611 * one character, substring;
1366 * 3. the character, if any, immediately before name in linestart must 1612 * 3. the character, if any, immediately before name in linestart must
1367 * be one of the characters " \t()"; 1613 * be one of the characters " \t(),;";
1368 * 4. the character, if any, immediately after name in linestart must 1614 * 4. the character, if any, immediately after name in linestart must
1369 * also be one of the characters " \t()". 1615 * also be one of the characters " \t(),;".
1616 *
1617 * The real implementation uses the notinname() macro, which recognises
1618 * characters slightly different form " \t\r\n(),;". See the variable
1619 * `nonam'.
1370 */ 1620 */
1371 #define traditional_tag_style TRUE 1621 #define traditional_tag_style TRUE
1372 void 1622 void
1373 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno) 1623 new_pfnote (name, namelen, is_func, linestart, linelen, lno, cno)
1374 char *name; /* tag name, or NULL if unnamed */ 1624 char *name; /* tag name, or NULL if unnamed */
1397 || notinname (cp[-1])) /* rule #3 */ 1647 || notinname (cp[-1])) /* rule #3 */
1398 && strneq (name, cp, namelen)) /* rule #2 */ 1648 && strneq (name, cp, namelen)) /* rule #2 */
1399 named = FALSE; /* use unnamed tag */ 1649 named = FALSE; /* use unnamed tag */
1400 } 1650 }
1401 } 1651 }
1402 1652
1403 if (named) 1653 if (named)
1404 name = savenstr (name, namelen); 1654 name = savenstr (name, namelen);
1405 else 1655 else
1406 name = NULL; 1656 name = NULL;
1407 pfnote (name, is_func, linestart, linelen, lno, cno); 1657 pfnote (name, is_func, linestart, linelen, lno, cno);
1410 /* 1660 /*
1411 * free_tree () 1661 * free_tree ()
1412 * recurse on left children, iterate on right children. 1662 * recurse on left children, iterate on right children.
1413 */ 1663 */
1414 void 1664 void
1415 free_tree (node) 1665 free_tree (np)
1416 register NODE *node; 1666 register node *np;
1417 { 1667 {
1418 while (node) 1668 while (np)
1419 { 1669 {
1420 register NODE *node_right = node->right; 1670 register node *node_right = np->right;
1421 free_tree (node->left); 1671 free_tree (np->left);
1422 if (node->name != NULL) 1672 if (np->name != NULL)
1423 free (node->name); 1673 free (np->name);
1424 free (node->pat); 1674 free (np->pat);
1425 free ((char *) node); 1675 free (np);
1426 node = node_right; 1676 np = node_right;
1427 } 1677 }
1428 } 1678 }
1429 1679
1430 /* 1680 /*
1431 * add_node () 1681 * add_node ()
1434 * an ordered tree, with no attempt at balancing. 1684 * an ordered tree, with no attempt at balancing.
1435 * 1685 *
1436 * add_node is the only function allowed to add nodes, so it can 1686 * add_node is the only function allowed to add nodes, so it can
1437 * maintain state. 1687 * maintain state.
1438 */ 1688 */
1439 NODE *last_node = NULL;
1440 void 1689 void
1441 add_node (node, cur_node_p) 1690 add_node (np, cur_node_p)
1442 NODE *node, **cur_node_p; 1691 node *np, **cur_node_p;
1443 { 1692 {
1444 register int dif; 1693 register int dif;
1445 register NODE *cur_node = *cur_node_p; 1694 register node *cur_node = *cur_node_p;
1446 1695
1447 if (cur_node == NULL) 1696 if (cur_node == NULL)
1448 { 1697 {
1449 *cur_node_p = node; 1698 *cur_node_p = np;
1450 last_node = node; 1699 last_node = np;
1451 return; 1700 return;
1452 } 1701 }
1453 1702
1454 if (!CTAGS) 1703 if (!CTAGS)
1455 { 1704 {
1456 /* Etags Mode */ 1705 /* Etags Mode */
1457 if (last_node == NULL) 1706 if (last_node == NULL)
1458 fatal ("internal error in add_node", (char *)NULL); 1707 fatal ("internal error in add_node", (char *)NULL);
1459 last_node->right = node; 1708 last_node->right = np;
1460 last_node = node; 1709 last_node = np;
1461 } 1710 }
1462 else 1711 else
1463 { 1712 {
1464 /* Ctags Mode */ 1713 /* Ctags Mode */
1465 dif = strcmp (node->name, cur_node->name); 1714 dif = strcmp (np->name, cur_node->name);
1466 1715
1467 /* 1716 /*
1468 * If this tag name matches an existing one, then 1717 * If this tag name matches an existing one, then
1469 * do not add the node, but maybe print a warning. 1718 * do not add the node, but maybe print a warning.
1470 */ 1719 */
1471 if (!dif) 1720 if (!dif)
1472 { 1721 {
1473 if (streq (node->file, cur_node->file)) 1722 if (streq (np->file, cur_node->file))
1474 { 1723 {
1475 if (!no_warnings) 1724 if (!no_warnings)
1476 { 1725 {
1477 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n", 1726 fprintf (stderr, "Duplicate entry in file %s, line %d: %s\n",
1478 node->file, lineno, node->name); 1727 np->file, lineno, np->name);
1479 fprintf (stderr, "Second entry ignored\n"); 1728 fprintf (stderr, "Second entry ignored\n");
1480 } 1729 }
1481 } 1730 }
1482 else if (!cur_node->been_warned && !no_warnings) 1731 else if (!cur_node->been_warned && !no_warnings)
1483 { 1732 {
1484 fprintf 1733 fprintf
1485 (stderr, 1734 (stderr,
1486 "Duplicate entry in files %s and %s: %s (Warning only)\n", 1735 "Duplicate entry in files %s and %s: %s (Warning only)\n",
1487 node->file, cur_node->file, node->name); 1736 np->file, cur_node->file, np->name);
1488 cur_node->been_warned = TRUE; 1737 cur_node->been_warned = TRUE;
1489 } 1738 }
1490 return; 1739 return;
1491 } 1740 }
1492 1741
1493 /* Actually add the node */ 1742 /* Actually add the node */
1494 add_node (node, dif < 0 ? &cur_node->left : &cur_node->right); 1743 add_node (np, dif < 0 ? &cur_node->left : &cur_node->right);
1495 } 1744 }
1496 } 1745 }
1497 1746
1498 void 1747 void
1499 put_entries (node) 1748 put_entries (np)
1500 register NODE *node; 1749 register node *np;
1501 { 1750 {
1502 register char *sp; 1751 register char *sp;
1503 1752
1504 if (node == NULL) 1753 if (np == NULL)
1505 return; 1754 return;
1506 1755
1507 /* Output subentries that precede this one */ 1756 /* Output subentries that precede this one */
1508 put_entries (node->left); 1757 put_entries (np->left);
1509 1758
1510 /* Output this entry */ 1759 /* Output this entry */
1511 1760
1512 if (!CTAGS) 1761 if (!CTAGS)
1513 { 1762 {
1514 if (node->name != NULL) 1763 if (np->name != NULL)
1515 fprintf (tagf, "%s\177%s\001%d,%ld\n", 1764 fprintf (tagf, "%s\177%s\001%d,%ld\n",
1516 node->pat, node->name, node->lno, node->cno); 1765 np->pat, np->name, np->lno, np->cno);
1517 else 1766 else
1518 fprintf (tagf, "%s\177%d,%ld\n", 1767 fprintf (tagf, "%s\177%d,%ld\n",
1519 node->pat, node->lno, node->cno); 1768 np->pat, np->lno, np->cno);
1520 } 1769 }
1521 else 1770 else
1522 { 1771 {
1523 if (node->name == NULL) 1772 if (np->name == NULL)
1524 error ("internal error: NULL name in ctags mode.", (char *)NULL); 1773 error ("internal error: NULL name in ctags mode.", (char *)NULL);
1525 1774
1526 if (cxref_style) 1775 if (cxref_style)
1527 { 1776 {
1528 if (vgrind_style) 1777 if (vgrind_style)
1529 fprintf (stdout, "%s %s %d\n", 1778 fprintf (stdout, "%s %s %d\n",
1530 node->name, node->file, (node->lno + 63) / 64); 1779 np->name, np->file, (np->lno + 63) / 64);
1531 else 1780 else
1532 fprintf (stdout, "%-16s %3d %-16s %s\n", 1781 fprintf (stdout, "%-16s %3d %-16s %s\n",
1533 node->name, node->lno, node->file, node->pat); 1782 np->name, np->lno, np->file, np->pat);
1534 } 1783 }
1535 else 1784 else
1536 { 1785 {
1537 fprintf (tagf, "%s\t%s\t", node->name, node->file); 1786 fprintf (tagf, "%s\t%s\t", np->name, np->file);
1538 1787
1539 if (node->is_func) 1788 if (np->is_func)
1540 { /* a function */ 1789 { /* a function */
1541 putc (searchar, tagf); 1790 putc (searchar, tagf);
1542 putc ('^', tagf); 1791 putc ('^', tagf);
1543 1792
1544 for (sp = node->pat; *sp; sp++) 1793 for (sp = np->pat; *sp; sp++)
1545 { 1794 {
1546 if (*sp == '\\' || *sp == searchar) 1795 if (*sp == '\\' || *sp == searchar)
1547 putc ('\\', tagf); 1796 putc ('\\', tagf);
1548 putc (*sp, tagf); 1797 putc (*sp, tagf);
1549 } 1798 }
1550 putc (searchar, tagf); 1799 putc (searchar, tagf);
1551 } 1800 }
1552 else 1801 else
1553 { /* a typedef; text pattern inadequate */ 1802 { /* a typedef; text pattern inadequate */
1554 fprintf (tagf, "%d", node->lno); 1803 fprintf (tagf, "%d", np->lno);
1555 } 1804 }
1556 putc ('\n', tagf); 1805 putc ('\n', tagf);
1557 } 1806 }
1558 } 1807 }
1559 1808
1560 /* Output subentries that follow this one */ 1809 /* Output subentries that follow this one */
1561 put_entries (node->right); 1810 put_entries (np->right);
1562 } 1811 }
1563 1812
1564 /* Length of a number's decimal representation. */ 1813 /* Length of a number's decimal representation. */
1565 int 1814 int
1566 number_len (num) 1815 number_len (num)
1567 long num; 1816 long num;
1568 { 1817 {
1569 int len = 0; 1818 int len = 1;
1570 if (!num) 1819 while ((num /= 10) > 0)
1571 return 1; 1820 len += 1;
1572 for (; num; num /= 10)
1573 ++len;
1574 return len; 1821 return len;
1575 } 1822 }
1576 1823
1577 /* 1824 /*
1578 * Return total number of characters that put_entries will output for 1825 * Return total number of characters that put_entries will output for
1580 * we are not ctags, but called only in that case. This count 1827 * we are not ctags, but called only in that case. This count
1581 * is irrelevant with the new tags.el, but is still supplied for 1828 * is irrelevant with the new tags.el, but is still supplied for
1582 * backward compatibility. 1829 * backward compatibility.
1583 */ 1830 */
1584 int 1831 int
1585 total_size_of_entries (node) 1832 total_size_of_entries (np)
1586 register NODE *node; 1833 register node *np;
1587 { 1834 {
1588 register int total; 1835 register int total;
1589 1836
1590 if (node == NULL) 1837 if (np == NULL)
1591 return 0; 1838 return 0;
1592 1839
1593 total = 0; 1840 for (total = 0; np != NULL; np = np->right)
1594 for (; node; node = node->right)
1595 { 1841 {
1596 /* Count left subentries. */ 1842 /* Count left subentries. */
1597 total += total_size_of_entries (node->left); 1843 total += total_size_of_entries (np->left);
1598 1844
1599 /* Count this entry */ 1845 /* Count this entry */
1600 total += strlen (node->pat) + 1; 1846 total += strlen (np->pat) + 1;
1601 total += number_len ((long) node->lno) + 1 + number_len (node->cno) + 1; 1847 total += number_len ((long) np->lno) + 1 + number_len (np->cno) + 1;
1602 if (node->name != NULL) 1848 if (np->name != NULL)
1603 total += 1 + strlen (node->name); /* \001name */ 1849 total += 1 + strlen (np->name); /* \001name */
1604 } 1850 }
1605 1851
1606 return total; 1852 return total;
1607 } 1853 }
1608 1854
1614 st_none, 1860 st_none,
1615 st_C_objprot, st_C_objimpl, st_C_objend, 1861 st_C_objprot, st_C_objimpl, st_C_objend,
1616 st_C_gnumacro, 1862 st_C_gnumacro,
1617 st_C_ignore, 1863 st_C_ignore,
1618 st_C_javastruct, 1864 st_C_javastruct,
1619 st_C_struct, st_C_enum, st_C_define, st_C_typedef, st_C_typespec 1865 st_C_operator,
1866 st_C_struct, st_C_extern, st_C_enum, st_C_define, st_C_typedef, st_C_typespec
1620 }; 1867 };
1621 1868
1622 /* Feed stuff between (but not including) %[ and %] lines to: 1869 /* Feed stuff between (but not including) %[ and %] lines to:
1623 gperf -c -k 1,3 -o -p -r -t 1870 gperf -c -k 1,3 -o -p -r -t
1624 %[ 1871 %[
1625 struct C_stab_entry { char *name; int c_ext; enum sym_type type; } 1872 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }
1626 %% 1873 %%
1874 if, 0, st_C_ignore
1875 for, 0, st_C_ignore
1876 while, 0, st_C_ignore
1877 switch, 0, st_C_ignore
1878 return, 0, st_C_ignore
1627 @interface, 0, st_C_objprot 1879 @interface, 0, st_C_objprot
1628 @protocol, 0, st_C_objprot 1880 @protocol, 0, st_C_objprot
1629 @implementation,0, st_C_objimpl 1881 @implementation,0, st_C_objimpl
1630 @end, 0, st_C_objend 1882 @end, 0, st_C_objend
1631 import, C_JAVA, st_C_ignore 1883 import, C_JAVA, st_C_ignore
1632 package, C_JAVA, st_C_ignore 1884 package, C_JAVA, st_C_ignore
1633 friend, C_PLPL, st_C_ignore 1885 friend, C_PLPL, st_C_ignore
1634 extends, C_JAVA, st_C_javastruct 1886 extends, C_JAVA, st_C_javastruct
1635 implements, C_JAVA, st_C_javastruct 1887 implements, C_JAVA, st_C_javastruct
1888 interface, C_JAVA, st_C_struct
1636 class, C_PLPL, st_C_struct 1889 class, C_PLPL, st_C_struct
1637 namespace, C_PLPL, st_C_struct 1890 namespace, C_PLPL, st_C_struct
1638 domain, C_STAR, st_C_struct 1891 domain, C_STAR, st_C_struct
1639 union, 0, st_C_struct 1892 union, 0, st_C_struct
1640 struct, 0, st_C_struct 1893 struct, 0, st_C_struct
1894 extern, 0, st_C_extern
1641 enum, 0, st_C_enum 1895 enum, 0, st_C_enum
1642 typedef, 0, st_C_typedef 1896 typedef, 0, st_C_typedef
1643 define, 0, st_C_define 1897 define, 0, st_C_define
1898 operator, C_PLPL, st_C_operator
1644 bool, C_PLPL, st_C_typespec 1899 bool, C_PLPL, st_C_typespec
1645 long, 0, st_C_typespec 1900 long, 0, st_C_typespec
1646 short, 0, st_C_typespec 1901 short, 0, st_C_typespec
1647 int, 0, st_C_typespec 1902 int, 0, st_C_typespec
1648 char, 0, st_C_typespec 1903 char, 0, st_C_typespec
1650 double, 0, st_C_typespec 1905 double, 0, st_C_typespec
1651 signed, 0, st_C_typespec 1906 signed, 0, st_C_typespec
1652 unsigned, 0, st_C_typespec 1907 unsigned, 0, st_C_typespec
1653 auto, 0, st_C_typespec 1908 auto, 0, st_C_typespec
1654 void, 0, st_C_typespec 1909 void, 0, st_C_typespec
1655 extern, 0, st_C_typespec
1656 static, 0, st_C_typespec 1910 static, 0, st_C_typespec
1657 const, 0, st_C_typespec 1911 const, 0, st_C_typespec
1658 volatile, 0, st_C_typespec 1912 volatile, 0, st_C_typespec
1659 explicit, C_PLPL, st_C_typespec 1913 explicit, C_PLPL, st_C_typespec
1660 mutable, C_PLPL, st_C_typespec 1914 mutable, C_PLPL, st_C_typespec
1669 #EXFUN, 0, st_C_gnumacro 1923 #EXFUN, 0, st_C_gnumacro
1670 #DEFVAR_, 0, st_C_gnumacro 1924 #DEFVAR_, 0, st_C_gnumacro
1671 %] 1925 %]
1672 and replace lines between %< and %> with its output. */ 1926 and replace lines between %< and %> with its output. */
1673 /*%<*/ 1927 /*%<*/
1674 /* starting time is 10:31:16 */ 1928 /* C code produced by gperf version 2.7.1 (19981006 egcs) */
1675 /* C code produced by gperf version 2.1 (K&R C version) */
1676 /* Command-line: gperf -c -k 1,3 -o -p -r -t */ 1929 /* Command-line: gperf -c -k 1,3 -o -p -r -t */
1677
1678
1679 struct C_stab_entry { char *name; int c_ext; enum sym_type type; }; 1930 struct C_stab_entry { char *name; int c_ext; enum sym_type type; };
1680 1931
1681 #define MIN_WORD_LENGTH 3 1932 #define TOTAL_KEYWORDS 46
1933 #define MIN_WORD_LENGTH 2
1682 #define MAX_WORD_LENGTH 15 1934 #define MAX_WORD_LENGTH 15
1683 #define MIN_HASH_VALUE 15 1935 #define MIN_HASH_VALUE 13
1684 #define MAX_HASH_VALUE 128 1936 #define MAX_HASH_VALUE 123
1685 /* 1937 /* maximum key range = 111, duplicates = 0 */
1686 39 keywords 1938
1687 114 is the maximum key range 1939 #ifdef __GNUC__
1688 */ 1940 __inline
1689 1941 #endif
1690 static int 1942 static unsigned int
1691 hash (str, len) 1943 hash (str, len)
1692 register char *str; 1944 register const char *str;
1693 register unsigned int len; 1945 register unsigned int len;
1694 { 1946 {
1695 static unsigned char hash_table[] = 1947 static unsigned char asso_values[] =
1696 { 1948 {
1697 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 1949 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1698 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 1950 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1699 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 1951 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1700 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 1952 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1701 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 1953 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1702 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 1954 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1703 128, 128, 128, 128, 39, 128, 128, 128, 54, 48, 1955 124, 124, 124, 124, 3, 124, 124, 124, 43, 6,
1704 46, 128, 128, 128, 128, 128, 128, 128, 128, 128, 1956 11, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1705 28, 128, 128, 40, 32, 128, 128, 128, 128, 128, 1957 11, 124, 124, 58, 7, 124, 124, 124, 124, 124,
1706 128, 128, 128, 128, 128, 128, 128, 24, 30, 47, 1958 124, 124, 124, 124, 124, 124, 124, 57, 7, 42,
1707 62, 7, 60, 27, 128, 60, 128, 128, 59, 16, 1959 4, 14, 52, 0, 124, 53, 124, 124, 29, 11,
1708 31, 23, 45, 128, 4, 14, 2, 55, 5, 128, 1960 6, 35, 32, 124, 29, 34, 59, 58, 51, 24,
1709 128, 128, 128, 128, 128, 128, 128, 128, 1961 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1710 }; 1962 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1711 return len + hash_table[str[2]] + hash_table[str[0]]; 1963 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1712 } 1964 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
1713 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
1975 };
1976 register int hval = len;
1977
1978 switch (hval)
1979 {
1980 default:
1981 case 3:
1982 hval += asso_values[(unsigned char)str[2]];
1983 case 2:
1984 case 1:
1985 hval += asso_values[(unsigned char)str[0]];
1986 break;
1987 }
1988 return hval;
1989 }
1990
1991 #ifdef __GNUC__
1992 __inline
1993 #endif
1714 struct C_stab_entry * 1994 struct C_stab_entry *
1715 in_word_set (str, len) 1995 in_word_set (str, len)
1716 register char *str; 1996 register const char *str;
1717 register unsigned int len; 1997 register unsigned int len;
1718 { 1998 {
1719 1999 static struct C_stab_entry wordlist[] =
1720 static struct C_stab_entry wordlist[] = 2000 {
1721 { 2001 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
1722 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 2002 {""}, {""}, {""}, {""},
1723 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 2003 {"@end", 0, st_C_objend},
1724 {"extern", 0, st_C_typespec}, 2004 {""}, {""}, {""}, {""},
1725 {"extends", C_JAVA, st_C_javastruct}, 2005 {"ENTRY", 0, st_C_gnumacro},
1726 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 2006 {"@interface", 0, st_C_objprot},
1727 {"struct", 0, st_C_struct}, 2007 {""},
1728 {"mutable", C_PLPL, st_C_typespec}, 2008 {"domain", C_STAR, st_C_struct},
1729 {"",}, {"",}, {"",}, {"",}, 2009 {""},
1730 {"auto", 0, st_C_typespec}, 2010 {"PSEUDO", 0, st_C_gnumacro},
1731 {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 2011 {""}, {""},
1732 {"",}, {"",}, 2012 {"namespace", C_PLPL, st_C_struct},
1733 {"short", 0, st_C_typespec}, 2013 {""}, {""},
1734 {"",}, 2014 {"@implementation",0, st_C_objimpl},
1735 {"static", 0, st_C_typespec}, 2015 {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
1736 {"",}, {"",}, 2016 {"long", 0, st_C_typespec},
1737 {"signed", 0, st_C_typespec}, 2017 {"signed", 0, st_C_typespec},
1738 {"",}, {"",}, {"",}, {"",}, 2018 {"@protocol", 0, st_C_objprot},
1739 {"@protocol", 0, st_C_objprot}, 2019 {""}, {""}, {""}, {""},
1740 {"",}, 2020 {"bool", C_PLPL, st_C_typespec},
1741 {"typedef", 0, st_C_typedef}, 2021 {""}, {""}, {""}, {""}, {""}, {""},
1742 {"typename", C_PLPL, st_C_typespec}, 2022 {"const", 0, st_C_typespec},
1743 {"namespace", C_PLPL, st_C_struct}, 2023 {"explicit", C_PLPL, st_C_typespec},
1744 {"bool", C_PLPL, st_C_typespec}, 2024 {"if", 0, st_C_ignore},
1745 {"",}, {"",}, 2025 {""},
1746 {"explicit", C_PLPL, st_C_typespec}, 2026 {"operator", C_PLPL, st_C_operator},
1747 {"",}, {"",}, {"",}, {"",}, 2027 {""},
1748 {"int", 0, st_C_typespec}, 2028 {"DEFUN", 0, st_C_gnumacro},
1749 {"enum", 0, st_C_enum}, 2029 {""}, {""},
1750 {"",}, {"",}, 2030 {"define", 0, st_C_define},
1751 {"void", 0, st_C_typespec}, 2031 {""}, {""}, {""}, {""}, {""},
1752 {"@implementation", 0, st_C_objimpl}, 2032 {"double", 0, st_C_typespec},
1753 {"",}, 2033 {"struct", 0, st_C_struct},
1754 {"volatile", 0, st_C_typespec}, 2034 {""}, {""}, {""}, {""},
1755 {"",}, 2035 {"short", 0, st_C_typespec},
1756 {"@end", 0, st_C_objend}, 2036 {""},
1757 {"char", 0, st_C_typespec}, 2037 {"enum", 0, st_C_enum},
1758 {"class", C_PLPL, st_C_struct}, 2038 {"mutable", C_PLPL, st_C_typespec},
1759 {"unsigned", 0, st_C_typespec}, 2039 {""},
1760 {"",}, {"",}, 2040 {"extern", 0, st_C_extern},
1761 {"@interface", 0, st_C_objprot}, 2041 {"extends", C_JAVA, st_C_javastruct},
1762 {"",}, 2042 {"package", C_JAVA, st_C_ignore},
1763 {"PSEUDO", 0, st_C_gnumacro}, 2043 {"while", 0, st_C_ignore},
1764 {"const", 0, st_C_typespec}, 2044 {""},
1765 {"domain", C_STAR, st_C_struct}, 2045 {"for", 0, st_C_ignore},
1766 {"ENTRY", 0, st_C_gnumacro}, 2046 {""}, {""}, {""},
1767 {"",}, 2047 {"volatile", 0, st_C_typespec},
1768 {"SYSCALL", 0, st_C_gnumacro}, 2048 {""}, {""},
1769 {"float", 0, st_C_typespec}, 2049 {"import", C_JAVA, st_C_ignore},
1770 {"",}, {"",}, {"",}, {"",}, {"",}, 2050 {"float", 0, st_C_typespec},
1771 {"long", 0, st_C_typespec}, 2051 {"switch", 0, st_C_ignore},
1772 {"",}, {"",}, {"",}, {"",}, 2052 {"return", 0, st_C_ignore},
1773 {"package", C_JAVA, st_C_ignore}, 2053 {"implements", C_JAVA, st_C_javastruct},
1774 {"",}, {"",}, {"",}, {"",}, {"",}, 2054 {""},
1775 {"DEFUN", 0, st_C_gnumacro}, 2055 {"static", 0, st_C_typespec},
1776 {"",}, {"",}, {"",}, {"",}, {"",}, 2056 {"typedef", 0, st_C_typedef},
1777 {"import", C_JAVA, st_C_ignore}, 2057 {"typename", C_PLPL, st_C_typespec},
1778 {"",}, {"",}, {"",}, 2058 {"unsigned", 0, st_C_typespec},
1779 {"implements", C_JAVA, st_C_javastruct}, 2059 {""}, {""},
1780 {"",}, {"",}, {"",}, {"",}, 2060 {"char", 0, st_C_typespec},
1781 {"union", 0, st_C_struct}, 2061 {"class", C_PLPL, st_C_struct},
1782 {"",}, {"",}, 2062 {""}, {""}, {""},
1783 {"double", 0, st_C_typespec}, 2063 {"void", 0, st_C_typespec},
1784 {"",}, {"",}, 2064 {""}, {""},
1785 {"friend", C_PLPL, st_C_ignore}, 2065 {"friend", C_PLPL, st_C_ignore},
1786 {"",}, 2066 {""}, {""}, {""},
1787 {"define", 0, st_C_define}, 2067 {"int", 0, st_C_typespec},
2068 {"union", 0, st_C_struct},
2069 {""}, {""}, {""},
2070 {"auto", 0, st_C_typespec},
2071 {"interface", C_JAVA, st_C_struct},
2072 {""},
2073 {"SYSCALL", 0, st_C_gnumacro}
1788 }; 2074 };
1789 2075
1790 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) 2076 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
1791 { 2077 {
1792 register int key = hash (str, len); 2078 register int key = hash (str, len);
1793 2079
1794 if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE) 2080 if (key <= MAX_HASH_VALUE && key >= 0)
1795 { 2081 {
1796 register char *s = wordlist[key].name; 2082 register const char *s = wordlist[key].name;
1797 2083
1798 if (*s == *str && !strncmp (str + 1, s + 1, len - 1)) 2084 if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
1799 return &wordlist[key]; 2085 return &wordlist[key];
1800 } 2086 }
1801 } 2087 }
1802 return 0; 2088 return 0;
1803 } 2089 }
1804 /* ending time is 10:31:16 */
1805 /*%>*/ 2090 /*%>*/
1806 2091
1807 enum sym_type 2092 enum sym_type
1808 C_symtype (str, len, c_ext) 2093 C_symtype (str, len, c_ext)
1809 char *str; 2094 char *str;
1822 * finite automaton. fvdef is its state variable. 2107 * finite automaton. fvdef is its state variable.
1823 */ 2108 */
1824 enum 2109 enum
1825 { 2110 {
1826 fvnone, /* nothing seen */ 2111 fvnone, /* nothing seen */
2112 foperator, /* func: operator keyword seen (cplpl) */
1827 fvnameseen, /* function or variable name seen */ 2113 fvnameseen, /* function or variable name seen */
1828 fstartlist, /* func: just after open parenthesis */ 2114 fstartlist, /* func: just after open parenthesis */
1829 finlist, /* func: in parameter list */ 2115 finlist, /* func: in parameter list */
1830 flistseen, /* func: after parameter list */ 2116 flistseen, /* func: after parameter list */
1831 fignore, /* func: before open brace */ 2117 fignore, /* func: before open brace */
1832 vignore /* var-like: ignore until ';' */ 2118 vignore /* var-like: ignore until ';' */
1833 } fvdef; 2119 } fvdef;
1834 2120
2121 bool fvextern; /* func or var: extern keyword seen; */
1835 2122
1836 /* 2123 /*
1837 * typedefs are recognized using a simple finite automaton. 2124 * typedefs are recognized using a simple finite automaton.
1838 * typdef is its state variable. 2125 * typdef is its state variable.
1839 */ 2126 */
1840 enum 2127 enum
1841 { 2128 {
1842 tnone, /* nothing seen */ 2129 tnone, /* nothing seen */
1843 ttypedseen, /* typedef keyword seen */ 2130 tkeyseen, /* typedef keyword seen */
2131 ttypeseen, /* defined type seen */
1844 tinbody, /* inside typedef body */ 2132 tinbody, /* inside typedef body */
1845 tend, /* just before typedef tag */ 2133 tend, /* just before typedef tag */
1846 tignore /* junk after typedef tag */ 2134 tignore /* junk after typedef tag */
1847 } typdef; 2135 } typdef;
1848 2136
1917 bool named; 2205 bool named;
1918 int linelen; 2206 int linelen;
1919 int lineno; 2207 int lineno;
1920 long linepos; 2208 long linepos;
1921 char *buffer; 2209 char *buffer;
1922 } TOKEN; 2210 } token;
1923 TOKEN tok; /* latest token read */ 2211
1924 2212 token tok; /* latest token read */
1925 2213
1926 /* 2214 /*
1927 * Set this to TRUE, and the next token considered is called a function. 2215 * Set this to TRUE, and the next token considered is called a function.
1928 * Used only for GNU emacs's function-defining macros. 2216 * Used only for GNU emacs's function-defining macros.
1929 */ 2217 */
1945 * function or variable, or corresponds to a typedef, or 2233 * function or variable, or corresponds to a typedef, or
1946 * is a struct/union/enum tag, or #define, or an enum constant. 2234 * is a struct/union/enum tag, or #define, or an enum constant.
1947 * 2235 *
1948 * *IS_FUNC gets TRUE iff the token is a function or #define macro 2236 * *IS_FUNC gets TRUE iff the token is a function or #define macro
1949 * with args. C_EXT is which language we are looking at. 2237 * with args. C_EXT is which language we are looking at.
1950 *
1951 * In the future we will need some way to adjust where the end of
1952 * the token is; for instance, implementing the C++ keyword
1953 * `operator' properly will adjust the end of the token to be after
1954 * whatever follows `operator'.
1955 * 2238 *
1956 * Globals 2239 * Globals
1957 * fvdef IN OUT 2240 * fvdef IN OUT
1958 * structdef IN OUT 2241 * structdef IN OUT
1959 * definedef IN OUT 2242 * definedef IN OUT
2016 { 2299 {
2017 case tnone: 2300 case tnone:
2018 if (toktype == st_C_typedef) 2301 if (toktype == st_C_typedef)
2019 { 2302 {
2020 if (typedefs) 2303 if (typedefs)
2021 typdef = ttypedseen; 2304 typdef = tkeyseen;
2305 fvextern = FALSE;
2022 fvdef = fvnone; 2306 fvdef = fvnone;
2023 return FALSE; 2307 return FALSE;
2024 } 2308 }
2025 break; 2309 break;
2026 case ttypedseen: 2310 case tkeyseen:
2027 switch (toktype) 2311 switch (toktype)
2028 { 2312 {
2029 case st_none: 2313 case st_none:
2030 case st_C_typespec: 2314 case st_C_typespec:
2031 typdef = tend;
2032 break;
2033 case st_C_struct: 2315 case st_C_struct:
2034 case st_C_enum: 2316 case st_C_enum:
2317 typdef = ttypeseen;
2035 break; 2318 break;
2036 } 2319 }
2037 /* Do not return here, so the structdef stuff has a chance. */ 2320 /* Do not return here, so the structdef stuff has a chance. */
2038 break; 2321 break;
2039 case tend: 2322 case tend:
2061 { 2344 {
2062 case st_C_javastruct: 2345 case st_C_javastruct:
2063 if (structdef == stagseen) 2346 if (structdef == stagseen)
2064 structdef = scolonseen; 2347 structdef = scolonseen;
2065 return FALSE; 2348 return FALSE;
2066 break;
2067 case st_C_struct: 2349 case st_C_struct:
2068 case st_C_enum: 2350 case st_C_enum:
2069 if (typdef == ttypedseen 2351 if (typdef == tkeyseen
2070 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone)) 2352 || (typedefs_and_cplusplus && cblev == 0 && structdef == snone))
2071 { 2353 {
2072 structdef = skeyseen; 2354 structdef = skeyseen;
2073 structtype = toktype; 2355 structtype = toktype;
2074 } 2356 }
2085 structtag = "<enum>"; 2367 structtag = "<enum>";
2086 structdef = stagseen; 2368 structdef = stagseen;
2087 return TRUE; 2369 return TRUE;
2088 } 2370 }
2089 2371
2090 /* Avoid entering fvdef stuff if typdef is going on. */
2091 if (typdef != tnone) 2372 if (typdef != tnone)
2092 { 2373 definedef = dnone;
2093 definedef = dnone;
2094 return FALSE;
2095 }
2096 2374
2097 /* Detect GNU macros. 2375 /* Detect GNU macros.
2098 2376
2099 DEFUN note for writers of emacs C code: 2377 Writers of emacs code are recommended to put the
2378 first two args of a DEFUN on the same line.
2379
2100 The DEFUN macro, used in emacs C source code, has a first arg 2380 The DEFUN macro, used in emacs C source code, has a first arg
2101 that is a string (the lisp function name), and a second arg that 2381 that is a string (the lisp function name), and a second arg that
2102 is a C function name. Since etags skips strings, the second arg 2382 is a C function name. Since etags skips strings, the second arg
2103 is tagged. This is unfortunate, as it would be better to tag the 2383 is tagged. This is unfortunate, as it would be better to tag the
2104 first arg. The simplest way to deal with this problem would be 2384 first arg. The simplest way to deal with this problem would be
2105 to name the tag with a name built from the function name, by 2385 to name the tag with a name built from the function name, by
2106 removing the initial 'F' character and substituting '-' for '_'. 2386 removing the initial 'F' character and substituting '-' for '_'.
2107 Anyway, this assumes that the conventions of naming lisp 2387 Anyway, this assumes that the conventions of naming lisp
2108 functions will never change. Currently, this method is not 2388 functions will never change. Currently, this method is not
2109 implemented, so writers of emacs code are recommended to put the 2389 implemented. */
2110 first two args of a DEFUN on the same line. */
2111 if (definedef == dnone && toktype == st_C_gnumacro) 2390 if (definedef == dnone && toktype == st_C_gnumacro)
2112 { 2391 {
2113 next_token_is_func = TRUE; 2392 next_token_is_func = TRUE;
2114 return FALSE; 2393 return FALSE;
2115 } 2394 }
2194 } 2473 }
2195 2474
2196 /* A function, variable or enum constant? */ 2475 /* A function, variable or enum constant? */
2197 switch (toktype) 2476 switch (toktype)
2198 { 2477 {
2478 case st_C_extern:
2479 fvextern = TRUE;
2480 /* FALLTHRU */
2199 case st_C_typespec: 2481 case st_C_typespec:
2200 if (fvdef != finlist && fvdef != fignore && fvdef != vignore) 2482 if (fvdef != finlist && fvdef != fignore && fvdef != vignore)
2201 fvdef = fvnone; /* should be useless */ 2483 fvdef = fvnone; /* should be useless */
2202 return FALSE; 2484 return FALSE;
2203 case st_C_ignore: 2485 case st_C_ignore:
2486 fvextern = FALSE;
2204 fvdef = vignore; 2487 fvdef = vignore;
2205 return FALSE; 2488 return FALSE;
2489 case st_C_operator:
2490 fvdef = foperator;
2491 *is_func_or_var = TRUE;
2492 return TRUE;
2206 case st_none: 2493 case st_none:
2494 if ((c_ext & C_PLPL) && strneq (str+len-10, "::operator", 10))
2495 {
2496 fvdef = foperator;
2497 *is_func_or_var = TRUE;
2498 return TRUE;
2499 }
2207 if (constantypedefs && structdef == sinbody && structtype == st_C_enum) 2500 if (constantypedefs && structdef == sinbody && structtype == st_C_enum)
2208 return TRUE; 2501 return TRUE;
2209 if (fvdef == fvnone) 2502 if (fvdef == fvnone)
2210 { 2503 {
2211 fvdef = fvnameseen; /* function or variable */ 2504 fvdef = fvnameseen; /* function or variable */
2212 *is_func_or_var = TRUE; 2505 *is_func_or_var = TRUE;
2213 return TRUE; 2506 return TRUE;
2214 } 2507 }
2508 break;
2215 } 2509 }
2216 2510
2217 return FALSE; 2511 return FALSE;
2218 } 2512 }
2219 2513
2220 /* 2514 /*
2221 * C_entries () 2515 * C_entries ()
2222 * This routine finds functions, variables, typedefs, 2516 * This routine finds functions, variables, typedefs,
2223 * #define's, enum constants and struct/union/enum definitions in 2517 * #define's, enum constants and struct/union/enum definitions in
2224 * #C syntax and adds them to the list. 2518 * C syntax and adds them to the list.
2225 */ 2519 */
2226 #define current_lb_is_new (newndx == curndx) 2520 #define current_lb_is_new (newndx == curndx)
2227 #define switch_line_buffers() (curndx = 1 - curndx) 2521 #define switch_line_buffers() (curndx = 1 - curndx)
2228 2522
2229 #define curlb (lbs[curndx].lb) 2523 #define curlb (lbs[curndx].lb)
2231 #define newlb (lbs[newndx].lb) 2525 #define newlb (lbs[newndx].lb)
2232 #define curlinepos (lbs[curndx].linepos) 2526 #define curlinepos (lbs[curndx].linepos)
2233 #define othlinepos (lbs[1-curndx].linepos) 2527 #define othlinepos (lbs[1-curndx].linepos)
2234 #define newlinepos (lbs[newndx].linepos) 2528 #define newlinepos (lbs[newndx].linepos)
2235 2529
2236 #define CNL_SAVE_DEFINEDEF \ 2530 #define CNL_SAVE_DEFINEDEF() \
2237 do { \ 2531 do { \
2238 curlinepos = charno; \ 2532 curlinepos = charno; \
2239 lineno++; \ 2533 lineno++; \
2240 linecharno = charno; \ 2534 linecharno = charno; \
2241 charno += readline (&curlb, inf); \ 2535 charno += readline (&curlb, inf); \
2242 lp = curlb.buffer; \ 2536 lp = curlb.buffer; \
2243 quotednl = FALSE; \ 2537 quotednl = FALSE; \
2244 newndx = curndx; \ 2538 newndx = curndx; \
2245 } while (0) 2539 } while (0)
2246 2540
2247 #define CNL \ 2541 #define CNL() \
2248 do { \ 2542 do { \
2249 CNL_SAVE_DEFINEDEF; \ 2543 CNL_SAVE_DEFINEDEF(); \
2250 if (savetok.valid) \ 2544 if (savetok.valid) \
2251 { \ 2545 { \
2252 tok = savetok; \ 2546 tok = savetok; \
2253 savetok.valid = FALSE; \ 2547 savetok.valid = FALSE; \
2254 } \ 2548 } \
2298 char *qualifier; /* string used to qualify names */ 2592 char *qualifier; /* string used to qualify names */
2299 int qlen; /* length of qualifier */ 2593 int qlen; /* length of qualifier */
2300 int cblev; /* current curly brace level */ 2594 int cblev; /* current curly brace level */
2301 int parlev; /* current parenthesis level */ 2595 int parlev; /* current parenthesis level */
2302 bool incomm, inquote, inchar, quotednl, midtoken; 2596 bool incomm, inquote, inchar, quotednl, midtoken;
2303 bool cplpl, cjava; 2597 bool purec, cplpl, cjava;
2304 TOKEN savetok; /* token saved during preprocessor handling */ 2598 token savetok; /* token saved during preprocessor handling */
2305 2599
2306 2600
2601 tokoff = toklen = 0; /* keep compiler quiet */
2307 curndx = newndx = 0; 2602 curndx = newndx = 0;
2308 lineno = 0; 2603 lineno = 0;
2309 charno = 0; 2604 charno = 0;
2310 lp = curlb.buffer; 2605 lp = curlb.buffer;
2311 *lp = 0; 2606 *lp = 0;
2312 2607
2313 fvdef = fvnone; typdef = tnone; structdef = snone; 2608 fvdef = fvnone; fvextern = FALSE; typdef = tnone;
2314 definedef = dnone; objdef = onone; 2609 structdef = snone; definedef = dnone; objdef = onone;
2315 next_token_is_func = yacc_rules = FALSE; 2610 next_token_is_func = yacc_rules = FALSE;
2316 midtoken = inquote = inchar = incomm = quotednl = FALSE; 2611 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2317 tok.valid = savetok.valid = FALSE; 2612 tok.valid = savetok.valid = FALSE;
2318 cblev = 0; 2613 cblev = 0;
2319 parlev = 0; 2614 parlev = 0;
2615 purec = !(c_ext & ~YACC); /* no extensions (apart from possibly yacc) */
2320 cplpl = (c_ext & C_PLPL) == C_PLPL; 2616 cplpl = (c_ext & C_PLPL) == C_PLPL;
2321 cjava = (c_ext & C_JAVA) == C_JAVA; 2617 cjava = (c_ext & C_JAVA) == C_JAVA;
2322 if (cjava) 2618 if (cjava)
2323 { qualifier = "."; qlen = 1; } 2619 { qualifier = "."; qlen = 1; }
2324 else 2620 else
2352 } 2648 }
2353 break; 2649 break;
2354 case '\0': 2650 case '\0':
2355 /* Newlines inside comments do not end macro definitions in 2651 /* Newlines inside comments do not end macro definitions in
2356 traditional cpp. */ 2652 traditional cpp. */
2357 CNL_SAVE_DEFINEDEF; 2653 CNL_SAVE_DEFINEDEF ();
2358 break; 2654 break;
2359 } 2655 }
2360 continue; 2656 continue;
2361 } 2657 }
2362 else if (inquote) 2658 else if (inquote)
2368 break; 2664 break;
2369 case '\0': 2665 case '\0':
2370 /* Newlines inside strings do not end macro definitions 2666 /* Newlines inside strings do not end macro definitions
2371 in traditional cpp, even though compilers don't 2667 in traditional cpp, even though compilers don't
2372 usually accept them. */ 2668 usually accept them. */
2373 CNL_SAVE_DEFINEDEF; 2669 CNL_SAVE_DEFINEDEF ();
2374 break; 2670 break;
2375 } 2671 }
2376 continue; 2672 continue;
2377 } 2673 }
2378 else if (inchar) 2674 else if (inchar)
2379 { 2675 {
2380 switch (c) 2676 switch (c)
2381 { 2677 {
2382 case '\0': 2678 case '\0':
2383 /* Hmmm, something went wrong. */ 2679 /* Hmmm, something went wrong. */
2384 CNL; 2680 CNL ();
2385 /* FALLTHRU */ 2681 /* FALLTHRU */
2386 case '\'': 2682 case '\'':
2387 inchar = FALSE; 2683 inchar = FALSE;
2388 break; 2684 break;
2389 } 2685 }
2393 switch (c) 2689 switch (c)
2394 { 2690 {
2395 case '"': 2691 case '"':
2396 inquote = TRUE; 2692 inquote = TRUE;
2397 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) 2693 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2398 fvdef = fvnone; 2694 {
2695 fvextern = FALSE;
2696 fvdef = fvnone;
2697 }
2399 continue; 2698 continue;
2400 case '\'': 2699 case '\'':
2401 inchar = TRUE; 2700 inchar = TRUE;
2402 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore) 2701 if (fvdef != finlist && fvdef != fignore && fvdef !=vignore)
2403 fvdef = fvnone; 2702 {
2703 fvextern = FALSE;
2704 fvdef = fvnone;
2705 }
2404 continue; 2706 continue;
2405 case '/': 2707 case '/':
2406 if (*lp == '*') 2708 if (*lp == '*')
2407 { 2709 {
2408 lp++; 2710 lp++;
2419 case '%': 2721 case '%':
2420 if ((c_ext & YACC) && *lp == '%') 2722 if ((c_ext & YACC) && *lp == '%')
2421 { 2723 {
2422 /* entering or exiting rules section in yacc file */ 2724 /* entering or exiting rules section in yacc file */
2423 lp++; 2725 lp++;
2424 definedef = dnone; fvdef = fvnone; 2726 definedef = dnone; fvdef = fvnone; fvextern = FALSE;
2425 typdef = tnone; structdef = snone; 2727 typdef = tnone; structdef = snone;
2426 next_token_is_func = FALSE; 2728 next_token_is_func = FALSE;
2427 midtoken = inquote = inchar = incomm = quotednl = FALSE; 2729 midtoken = inquote = inchar = incomm = quotednl = FALSE;
2428 cblev = 0; 2730 cblev = 0;
2429 yacc_rules = !yacc_rules; 2731 yacc_rules = !yacc_rules;
2461 2763
2462 /* Consider token only if some complicated conditions are satisfied. */ 2764 /* Consider token only if some complicated conditions are satisfied. */
2463 if ((definedef != dnone 2765 if ((definedef != dnone
2464 || (cblev == 0 && structdef != scolonseen) 2766 || (cblev == 0 && structdef != scolonseen)
2465 || (cblev == 1 && cplpl && structdef == sinbody) 2767 || (cblev == 1 && cplpl && structdef == sinbody)
2466 || (structdef == sinbody && structtype == st_C_enum)) 2768 || (structdef == sinbody && purec))
2467 && typdef != tignore 2769 && typdef != tignore
2468 && definedef != dignorerest 2770 && definedef != dignorerest
2469 && fvdef != finlist) 2771 && fvdef != finlist)
2470 { 2772 {
2471 if (midtoken) 2773 if (midtoken)
2472 { 2774 {
2473 if (endtoken (c)) 2775 if (endtoken (c))
2474 { 2776 {
2475 if (c == ':' && cplpl && *lp == ':' && begtoken(*(lp + 1))) 2777 bool funorvar = FALSE;
2778
2779 if (c == ':' && cplpl && *lp == ':' && begtoken (lp[1]))
2476 { 2780 {
2477 /* 2781 /*
2478 * This handles :: in the middle, but not at the 2782 * This handles :: in the middle, but not at the
2479 * beginning of an identifier. 2783 * beginning of an identifier. Also, space-separated
2784 * :: is not recognised.
2480 */ 2785 */
2481 lp += 2; 2786 lp += 2;
2482 toklen += 3; 2787 toklen += 2;
2788 c = lp[-1];
2789 goto intoken;
2483 } 2790 }
2484 else 2791 else
2485 { 2792 {
2486 bool funorvar = FALSE;
2487
2488 if (yacc_rules 2793 if (yacc_rules
2489 || consider_token (newlb.buffer + tokoff, toklen, c, 2794 || consider_token (newlb.buffer + tokoff, toklen, c,
2490 c_ext, cblev, parlev, &funorvar)) 2795 c_ext, cblev, parlev, &funorvar))
2491 { 2796 {
2797 if (fvdef == foperator)
2798 {
2799 char *oldlp = lp;
2800 lp = skip_spaces (lp-1);
2801 if (*lp != '\0')
2802 lp += 1;
2803 while (*lp != '\0'
2804 && !isspace (*lp) && *lp != '(')
2805 lp += 1;
2806 c = *lp++;
2807 toklen += lp - oldlp;
2808 }
2492 tok.named = FALSE; 2809 tok.named = FALSE;
2493 if (structdef == sinbody 2810 if (!purec
2811 && funorvar
2494 && definedef == dnone 2812 && definedef == dnone
2495 && funorvar) 2813 && structdef == sinbody)
2496 /* function or var defined in C++ class body */ 2814 /* function or var defined in C++ class body */
2497 { 2815 {
2498 int len = strlen (structtag) + qlen + toklen; 2816 int len = strlen (structtag) + qlen + toklen;
2499 grow_linebuffer (&token_name, len + 1); 2817 grow_linebuffer (&token_name, len + 1);
2500 strcpy (token_name.buffer, structtag); 2818 strcpy (token_name.buffer, structtag);
2528 grow_linebuffer (&token_name, toklen + 1); 2846 grow_linebuffer (&token_name, toklen + 1);
2529 strncpy (token_name.buffer, 2847 strncpy (token_name.buffer,
2530 newlb.buffer + tokoff, toklen); 2848 newlb.buffer + tokoff, toklen);
2531 token_name.buffer[toklen] = '\0'; 2849 token_name.buffer[toklen] = '\0';
2532 token_name.len = toklen; 2850 token_name.len = toklen;
2533 /* Name macros. */ 2851 /* Name macros and members. */
2534 tok.named = (structdef == stagseen 2852 tok.named = (structdef == stagseen
2853 || typdef == ttypeseen
2535 || typdef == tend 2854 || typdef == tend
2536 || (funorvar 2855 || (funorvar
2537 && definedef == dignorerest)); 2856 && definedef == dignorerest)
2857 || (funorvar
2858 && definedef == dnone
2859 && structdef == sinbody));
2538 } 2860 }
2539 tok.lineno = lineno; 2861 tok.lineno = lineno;
2540 tok.linelen = tokoff + toklen + 1; 2862 tok.linelen = tokoff + toklen + 1;
2541 tok.buffer = newlb.buffer; 2863 tok.buffer = newlb.buffer;
2542 tok.linepos = newlinepos; 2864 tok.linepos = newlinepos;
2543 tok.valid = TRUE; 2865 tok.valid = TRUE;
2544 2866
2545 if (definedef == dnone 2867 if (definedef == dnone
2546 && (fvdef == fvnameseen 2868 && (fvdef == fvnameseen
2869 || fvdef == foperator
2547 || structdef == stagseen 2870 || structdef == stagseen
2548 || typdef == tend 2871 || typdef == tend
2549 || objdef != onone)) 2872 || objdef != onone))
2550 { 2873 {
2551 if (current_lb_is_new) 2874 if (current_lb_is_new)
2556 } 2879 }
2557 midtoken = FALSE; 2880 midtoken = FALSE;
2558 } 2881 }
2559 } /* if (endtoken (c)) */ 2882 } /* if (endtoken (c)) */
2560 else if (intoken (c)) 2883 else if (intoken (c))
2884 intoken:
2561 { 2885 {
2562 toklen++; 2886 toklen++;
2563 continue; 2887 continue;
2564 } 2888 }
2565 } /* if (midtoken) */ 2889 } /* if (midtoken) */
2631 make_C_tag (FALSE); /* a yacc function */ 2955 make_C_tag (FALSE); /* a yacc function */
2632 fvdef = fignore; 2956 fvdef = fignore;
2633 } 2957 }
2634 break; 2958 break;
2635 case fstartlist: 2959 case fstartlist:
2960 fvextern = FALSE;
2636 fvdef = fvnone; 2961 fvdef = fvnone;
2637 break; 2962 break;
2638 } 2963 }
2639 break; 2964 break;
2640 case ';': 2965 case ';':
2652 switch (fvdef) 2977 switch (fvdef)
2653 { 2978 {
2654 case fignore: 2979 case fignore:
2655 break; 2980 break;
2656 case fvnameseen: 2981 case fvnameseen:
2657 if ((globals && cblev == 0) || (members && cblev == 1)) 2982 if ((members && cblev == 1)
2983 || (globals && cblev == 0 && (!fvextern || declarations)))
2658 make_C_tag (FALSE); /* a variable */ 2984 make_C_tag (FALSE); /* a variable */
2985 fvextern = FALSE;
2986 fvdef = fvnone;
2987 tok.valid = FALSE;
2988 break;
2989 case flistseen:
2990 if (declarations && (cblev == 0 || cblev == 1))
2991 make_C_tag (TRUE); /* a function declaration */
2659 /* FALLTHRU */ 2992 /* FALLTHRU */
2660 default: 2993 default:
2994 fvextern = FALSE;
2661 fvdef = fvnone; 2995 fvdef = fvnone;
2662 /* The following instruction invalidates the token. 2996 /* The following instruction invalidates the token.
2663 Probably the token should be invalidated in all 2997 Probably the token should be invalidated in all
2664 other cases where some state machine is reset. */ 2998 other cases where some state machine is reset. */
2665 tok.valid = FALSE; 2999 tok.valid = FALSE;
2678 objdef = oinbody; 3012 objdef = oinbody;
2679 break; 3013 break;
2680 } 3014 }
2681 switch (fvdef) 3015 switch (fvdef)
2682 { 3016 {
3017 case foperator:
2683 case finlist: 3018 case finlist:
2684 case fignore: 3019 case fignore:
2685 case vignore: 3020 case vignore:
2686 break; 3021 break;
2687 case fvnameseen: 3022 case fvnameseen:
2688 if ((globals && cblev == 0) || (members && cblev == 1)) 3023 if ((members && cblev == 1)
3024 || (globals && cblev == 0 && (!fvextern || declarations)))
2689 make_C_tag (FALSE); /* a variable */ 3025 make_C_tag (FALSE); /* a variable */
2690 break; 3026 break;
2691 default: 3027 default:
2692 fvdef = fvnone; 3028 fvdef = fvnone;
2693 } 3029 }
2703 make_C_tag (FALSE); /* a typedef */ 3039 make_C_tag (FALSE); /* a typedef */
2704 break; 3040 break;
2705 } 3041 }
2706 switch (fvdef) 3042 switch (fvdef)
2707 { 3043 {
3044 case foperator:
2708 case finlist: 3045 case finlist:
2709 case fignore: 3046 case fignore:
2710 case vignore: 3047 case vignore:
2711 break; 3048 break;
2712 case fvnameseen: 3049 case fvnameseen:
2713 if ((globals && cblev == 0) || (members && cblev == 1)) 3050 if ((members && cblev == 1)
3051 || (globals && cblev == 0 && (!fvextern || declarations)))
2714 make_C_tag (FALSE); /* a variable */ 3052 make_C_tag (FALSE); /* a variable */
2715 /* FALLTHRU */ 3053 /* FALLTHRU */
2716 default: 3054 default:
2717 fvdef = fvnone; 3055 fvdef = fvnone;
2718 } 3056 }
2724 break; 3062 break;
2725 if (objdef == otagseen && parlev == 0) 3063 if (objdef == otagseen && parlev == 0)
2726 objdef = oparenseen; 3064 objdef = oparenseen;
2727 switch (fvdef) 3065 switch (fvdef)
2728 { 3066 {
2729 case fvnone: 3067 case fvnameseen:
2730 switch (typdef) 3068 if (typdef == ttypeseen
3069 && tok.valid
3070 && *lp != '*'
3071 && structdef != sinbody)
2731 { 3072 {
2732 case ttypedseen: 3073 /* This handles constructs like:
2733 case tend: 3074 typedef void OperatorFun (int fun); */
2734 if (tok.valid && *lp != '*') 3075 make_C_tag (FALSE);
2735 { 3076 typdef = tignore;
2736 /* This handles constructs like: 3077 }
2737 typedef void OperatorFun (int fun); */ 3078 /* FALLTHRU */
2738 make_C_tag (FALSE); 3079 case foperator:
2739 typdef = tignore;
2740 }
2741 break;
2742 } /* switch (typdef) */
2743 break;
2744 case fvnameseen:
2745 fvdef = fstartlist; 3080 fvdef = fstartlist;
2746 break; 3081 break;
2747 case flistseen: 3082 case flistseen:
2748 fvdef = finlist; 3083 fvdef = finlist;
2749 break; 3084 break;
2765 case fstartlist: 3100 case fstartlist:
2766 case finlist: 3101 case finlist:
2767 fvdef = flistseen; 3102 fvdef = flistseen;
2768 break; 3103 break;
2769 } 3104 }
2770 if (cblev == 0 && typdef == tend) 3105 if (cblev == 0 && (typdef == tend))
2771 { 3106 {
2772 typdef = tignore; 3107 typdef = tignore;
2773 make_C_tag (FALSE); /* a typedef */ 3108 make_C_tag (FALSE); /* a typedef */
2774 } 3109 }
2775 } 3110 }
2777 parlev = 0; 3112 parlev = 0;
2778 break; 3113 break;
2779 case '{': 3114 case '{':
2780 if (definedef != dnone) 3115 if (definedef != dnone)
2781 break; 3116 break;
2782 if (typdef == ttypedseen) 3117 if (typdef == ttypeseen)
2783 typdef = tinbody; 3118 typdef = tinbody;
2784 switch (structdef) 3119 switch (structdef)
2785 { 3120 {
2786 case skeyseen: /* unnamed struct */ 3121 case skeyseen: /* unnamed struct */
2787 structdef = sinbody; 3122 structdef = sinbody;
2856 case '=': 3191 case '=':
2857 if (definedef != dnone) 3192 if (definedef != dnone)
2858 break; 3193 break;
2859 switch (fvdef) 3194 switch (fvdef)
2860 { 3195 {
3196 case foperator:
2861 case finlist: 3197 case finlist:
2862 case fignore: 3198 case fignore:
2863 case vignore: 3199 case vignore:
2864 break; 3200 break;
2865 case fvnameseen: 3201 case fvnameseen:
2866 if ((globals && cblev == 0) || (members && cblev == 1)) 3202 if ((members && cblev == 1)
3203 || (globals && cblev == 0 && (!fvextern || declarations)))
2867 make_C_tag (FALSE); /* a variable */ 3204 make_C_tag (FALSE); /* a variable */
2868 /* FALLTHRU */ 3205 /* FALLTHRU */
2869 default: 3206 default:
2870 fvdef = vignore; 3207 fvdef = vignore;
2871 } 3208 }
2880 /* FALLTHRU */ 3217 /* FALLTHRU */
2881 case '#': case '~': case '&': case '%': case '/': case '|': 3218 case '#': case '~': case '&': case '%': case '/': case '|':
2882 case '^': case '!': case '<': case '>': case '.': case '?': case ']': 3219 case '^': case '!': case '<': case '>': case '.': case '?': case ']':
2883 if (definedef != dnone) 3220 if (definedef != dnone)
2884 break; 3221 break;
2885 /* These surely cannot follow a function tag. */ 3222 /* These surely cannot follow a function tag in C. */
2886 if (fvdef != finlist && fvdef != fignore && fvdef != vignore) 3223 switch (fvdef)
2887 fvdef = fvnone; 3224 {
3225 case foperator:
3226 case finlist:
3227 case fignore:
3228 case vignore:
3229 break;
3230 default:
3231 fvdef = fvnone;
3232 }
2888 break; 3233 break;
2889 case '\0': 3234 case '\0':
2890 if (objdef == otagseen) 3235 if (objdef == otagseen)
2891 { 3236 {
2892 make_C_tag (TRUE); /* an Objective C class */ 3237 make_C_tag (TRUE); /* an Objective C class */
2893 objdef = oignore; 3238 objdef = oignore;
2894 } 3239 }
2895 /* If a macro spans multiple lines don't reset its state. */ 3240 /* If a macro spans multiple lines don't reset its state. */
2896 if (quotednl) 3241 if (quotednl)
2897 CNL_SAVE_DEFINEDEF; 3242 CNL_SAVE_DEFINEDEF ();
2898 else 3243 else
2899 CNL; 3244 CNL ();
2900 break; 3245 break;
2901 } /* switch (c) */ 3246 } /* switch (c) */
2902 3247
2903 } /* while not eof */ 3248 } /* while not eof */
2904 } 3249 }
2952 FILE *inf; 3297 FILE *inf;
2953 { 3298 {
2954 C_entries (YACC, inf); 3299 C_entries (YACC, inf);
2955 } 3300 }
2956 3301
3302 /* A useful macro. */
3303 #define LOOP_ON_INPUT_LINES(file_pointer, line_buffer, char_pointer) \
3304 for (lineno = charno = 0; /* loop initialization */ \
3305 !feof (file_pointer) /* loop test */ \
3306 && (lineno++, /* instructions at start of loop */ \
3307 linecharno = charno, \
3308 charno += readline (&line_buffer, file_pointer), \
3309 char_pointer = lb.buffer, \
3310 TRUE); \
3311 )
3312
3313
3314 /*
3315 * Read a file, but do no processing. This is used to do regexp
3316 * matching on files that have no language defined.
3317 */
3318 void
3319 just_read_file (inf)
3320 FILE *inf;
3321 {
3322 register char *dummy;
3323
3324 LOOP_ON_INPUT_LINES (inf, lb, dummy)
3325 continue;
3326 }
3327
2957 /* Fortran parsing */ 3328 /* Fortran parsing */
2958
2959 char *dbp;
2960 3329
2961 bool 3330 bool
2962 tail (cp) 3331 tail (cp)
2963 char *cp; 3332 char *cp;
2964 { 3333 {
2965 register int len = 0; 3334 register int len = 0;
2966 3335
2967 while (*cp && lowcase(*cp) == lowcase(dbp[len])) 3336 while (*cp != '\0' && lowcase (*cp) == lowcase (dbp[len]))
2968 cp++, len++; 3337 cp++, len++;
2969 if (*cp == '\0' && !intoken(dbp[len])) 3338 if (*cp == '\0' && !intoken (dbp[len]))
2970 { 3339 {
2971 dbp += len; 3340 dbp += len;
2972 return TRUE; 3341 return TRUE;
2973 } 3342 }
2974 return FALSE; 3343 return FALSE;
2975 } 3344 }
2976 3345
2977 void 3346 void
2978 takeprec () 3347 takeprec ()
2979 { 3348 {
2980 while (isspace (*dbp)) 3349 dbp = skip_spaces (dbp);
2981 dbp++;
2982 if (*dbp != '*') 3350 if (*dbp != '*')
2983 return; 3351 return;
2984 dbp++; 3352 dbp++;
2985 while (isspace (*dbp)) 3353 dbp = skip_spaces (dbp);
2986 dbp++;
2987 if (strneq (dbp, "(*)", 3)) 3354 if (strneq (dbp, "(*)", 3))
2988 { 3355 {
2989 dbp += 3; 3356 dbp += 3;
2990 return; 3357 return;
2991 } 3358 }
3003 getit (inf) 3370 getit (inf)
3004 FILE *inf; 3371 FILE *inf;
3005 { 3372 {
3006 register char *cp; 3373 register char *cp;
3007 3374
3008 while (isspace (*dbp)) 3375 dbp = skip_spaces (dbp);
3009 dbp++;
3010 if (*dbp == '\0') 3376 if (*dbp == '\0')
3011 { 3377 {
3012 lineno++; 3378 lineno++;
3013 linecharno = charno; 3379 linecharno = charno;
3014 charno += readline (&lb, inf); 3380 charno += readline (&lb, inf);
3015 dbp = lb.buffer; 3381 dbp = lb.buffer;
3016 if (dbp[5] != '&') 3382 if (dbp[5] != '&')
3017 return; 3383 return;
3018 dbp += 6; 3384 dbp += 6;
3019 while (isspace (*dbp)) 3385 dbp = skip_spaces (dbp);
3020 dbp++; 3386 }
3021 } 3387 if (!isalpha (*dbp) && *dbp != '_' && *dbp != '$')
3022 if (!isalpha (*dbp)
3023 && *dbp != '_'
3024 && *dbp != '$')
3025 return; 3388 return;
3026 for (cp = dbp + 1; 3389 for (cp = dbp + 1; *cp != '\0' && intoken (*cp); cp++)
3027 (*cp
3028 && (isalpha (*cp) || isdigit (*cp) || (*cp == '_') || (*cp == '$')));
3029 cp++)
3030 continue; 3390 continue;
3031 pfnote (savenstr (dbp, cp-dbp), TRUE, 3391 pfnote (savenstr (dbp, cp-dbp), TRUE,
3032 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3392 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3033 } 3393 }
3034 3394
3395
3035 void 3396 void
3036 Fortran_functions (inf) 3397 Fortran_functions (inf)
3037 FILE *inf; 3398 FILE *inf;
3038 { 3399 {
3039 lineno = 0; 3400 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3040 charno = 0; 3401 {
3041
3042 while (!feof (inf))
3043 {
3044 lineno++;
3045 linecharno = charno;
3046 charno += readline (&lb, inf);
3047 dbp = lb.buffer;
3048 if (*dbp == '%') 3402 if (*dbp == '%')
3049 dbp++; /* Ratfor escape to fortran */ 3403 dbp++; /* Ratfor escape to fortran */
3050 while (isspace (*dbp)) 3404 dbp = skip_spaces (dbp);
3051 dbp++;
3052 if (*dbp == '\0') 3405 if (*dbp == '\0')
3053 continue; 3406 continue;
3054 switch (lowcase (*dbp)) 3407 switch (lowcase (*dbp))
3055 { 3408 {
3056 case 'i': 3409 case 'i':
3070 takeprec (); 3423 takeprec ();
3071 break; 3424 break;
3072 case 'd': 3425 case 'd':
3073 if (tail ("double")) 3426 if (tail ("double"))
3074 { 3427 {
3075 while (isspace (*dbp)) 3428 dbp = skip_spaces (dbp);
3076 dbp++;
3077 if (*dbp == '\0') 3429 if (*dbp == '\0')
3078 continue; 3430 continue;
3079 if (tail ("precision")) 3431 if (tail ("precision"))
3080 break; 3432 break;
3081 continue; 3433 continue;
3082 } 3434 }
3083 break; 3435 break;
3084 } 3436 }
3085 while (isspace (*dbp)) 3437 dbp = skip_spaces (dbp);
3086 dbp++;
3087 if (*dbp == '\0') 3438 if (*dbp == '\0')
3088 continue; 3439 continue;
3089 switch (lowcase (*dbp)) 3440 switch (lowcase (*dbp))
3090 { 3441 {
3091 case 'f': 3442 case 'f':
3098 continue; 3449 continue;
3099 case 'e': 3450 case 'e':
3100 if (tail ("entry")) 3451 if (tail ("entry"))
3101 getit (inf); 3452 getit (inf);
3102 continue; 3453 continue;
3103 case 'p':
3104 if (tail ("program"))
3105 {
3106 getit (inf);
3107 continue;
3108 }
3109 if (tail ("procedure"))
3110 getit (inf);
3111 continue;
3112 case 'b': 3454 case 'b':
3113 if (tail ("blockdata") || tail ("block data")) 3455 if (tail ("blockdata") || tail ("block data"))
3114 { 3456 {
3115 while (isspace (*dbp)) 3457 dbp = skip_spaces (dbp);
3116 dbp++;
3117 if (*dbp == '\0') /* assume un-named */ 3458 if (*dbp == '\0') /* assume un-named */
3118 pfnote (savestr ("blockdata"), TRUE, lb.buffer, 3459 pfnote (savestr ("blockdata"), TRUE,
3119 dbp - lb.buffer, lineno, linecharno); 3460 lb.buffer, dbp - lb.buffer, lineno, linecharno);
3120 else 3461 else
3121 getit (inf); /* look for name */ 3462 getit (inf); /* look for name */
3122 } 3463 }
3123 continue; 3464 continue;
3124 } 3465 }
3125 } 3466 }
3467 }
3468
3469 /*
3470 * Philippe Waroquiers <philippe.waroquiers@eurocontrol.be>, 1998-04-24
3471 * Ada parsing
3472 */
3473 /* Once we are positioned after an "interesting" keyword, let's get
3474 the real tag value necessary. */
3475 void
3476 adagetit (inf, name_qualifier)
3477 FILE *inf;
3478 char *name_qualifier;
3479 {
3480 register char *cp;
3481 char *name;
3482 char c;
3483
3484 while (!feof (inf))
3485 {
3486 dbp = skip_spaces (dbp);
3487 if (*dbp == '\0'
3488 || (dbp[0] == '-' && dbp[1] == '-'))
3489 {
3490 lineno++;
3491 linecharno = charno;
3492 charno += readline (&lb, inf);
3493 dbp = lb.buffer;
3494 }
3495 switch (*dbp)
3496 {
3497 case 'b':
3498 case 'B':
3499 if (tail ("body"))
3500 {
3501 /* Skipping body of procedure body or package body or ....
3502 resetting qualifier to body instead of spec. */
3503 name_qualifier = "/b";
3504 continue;
3505 }
3506 break;
3507 case 't':
3508 case 'T':
3509 /* Skipping type of task type or protected type ... */
3510 if (tail ("type"))
3511 continue;
3512 break;
3513 }
3514 if (*dbp == '"')
3515 {
3516 dbp += 1;
3517 for (cp = dbp; *cp != '\0' && *cp != '"'; cp++)
3518 continue;
3519 }
3520 else
3521 {
3522 dbp = skip_spaces (dbp);
3523 for (cp = dbp;
3524 (*cp != '\0'
3525 && (isalpha (*cp) || isdigit (*cp) || *cp == '_' || *cp == '.'));
3526 cp++)
3527 continue;
3528 if (cp == dbp)
3529 return;
3530 }
3531 c = *cp;
3532 *cp = '\0';
3533 name = concat (dbp, name_qualifier, "");
3534 *cp = c;
3535 pfnote (name, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3536 if (c == '"')
3537 dbp = cp + 1;
3538 return;
3539 }
3540 }
3541
3542 void
3543 Ada_funcs (inf)
3544 FILE *inf;
3545 {
3546 bool inquote = FALSE;
3547
3548 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3549 {
3550 while (*dbp != '\0')
3551 {
3552 /* Skip a string i.e. "abcd". */
3553 if (inquote || (*dbp == '"'))
3554 {
3555 dbp = etags_strchr ((inquote) ? dbp : dbp+1, '"');
3556 if (dbp != NULL)
3557 {
3558 inquote = FALSE;
3559 dbp += 1;
3560 continue; /* advance char */
3561 }
3562 else
3563 {
3564 inquote = TRUE;
3565 break; /* advance line */
3566 }
3567 }
3568
3569 /* Skip comments. */
3570 if (dbp[0] == '-' && dbp[1] == '-')
3571 break; /* advance line */
3572
3573 /* Skip character enclosed in single quote i.e. 'a'
3574 and skip single quote starting an attribute i.e. 'Image. */
3575 if (*dbp == '\'')
3576 {
3577 dbp++ ;
3578 if (*dbp != '\0')
3579 dbp++;
3580 continue;
3581 }
3582
3583 /* Search for beginning of a token. */
3584 if (!begtoken (*dbp))
3585 {
3586 dbp++;
3587 continue; /* advance char */
3588 }
3589
3590 /* We are at the beginning of a token. */
3591 switch (*dbp)
3592 {
3593 case 'f':
3594 case 'F':
3595 if (!packages_only && tail ("function"))
3596 adagetit (inf, "/f");
3597 else
3598 break; /* from switch */
3599 continue; /* advance char */
3600 case 'p':
3601 case 'P':
3602 if (!packages_only && tail ("procedure"))
3603 adagetit (inf, "/p");
3604 else if (tail ("package"))
3605 adagetit (inf, "/s");
3606 else if (tail ("protected")) /* protected type */
3607 adagetit (inf, "/t");
3608 else
3609 break; /* from switch */
3610 continue; /* advance char */
3611 case 't':
3612 case 'T':
3613 if (!packages_only && tail ("task"))
3614 adagetit (inf, "/k");
3615 else if (typedefs && !packages_only && tail ("type"))
3616 {
3617 adagetit (inf, "/t");
3618 while (*dbp != '\0')
3619 dbp += 1;
3620 }
3621 else
3622 break; /* from switch */
3623 continue; /* advance char */
3624 }
3625
3626 /* Look for the end of the token. */
3627 while (!endtoken (*dbp))
3628 dbp++;
3629
3630 } /* advance char */
3631 } /* advance line */
3126 } 3632 }
3127 3633
3128 /* 3634 /*
3129 * Bob Weiner, Motorola Inc., 4/3/94 3635 * Bob Weiner, Motorola Inc., 4/3/94
3130 * Unix and microcontroller assembly tag handling 3636 * Unix and microcontroller assembly tag handling
3134 Asm_labels (inf) 3640 Asm_labels (inf)
3135 FILE *inf; 3641 FILE *inf;
3136 { 3642 {
3137 register char *cp; 3643 register char *cp;
3138 3644
3139 lineno = 0; 3645 LOOP_ON_INPUT_LINES (inf, lb, cp)
3140 charno = 0; 3646 {
3141
3142 while (!feof (inf))
3143 {
3144 lineno++;
3145 linecharno = charno;
3146 charno += readline (&lb, inf);
3147 cp = lb.buffer;
3148
3149 /* If first char is alphabetic or one of [_.$], test for colon 3647 /* If first char is alphabetic or one of [_.$], test for colon
3150 following identifier. */ 3648 following identifier. */
3151 if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$') 3649 if (isalpha (*cp) || *cp == '_' || *cp == '.' || *cp == '$')
3152 { 3650 {
3153 /* Read past label. */ 3651 /* Read past label. */
3164 } 3662 }
3165 } 3663 }
3166 3664
3167 /* 3665 /*
3168 * Perl support by Bart Robinson <lomew@cs.utah.edu> 3666 * Perl support by Bart Robinson <lomew@cs.utah.edu>
3667 * enhanced by Michael Ernst <mernst@alum.mit.edu>
3169 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/ 3668 * Perl sub names: look for /^sub[ \t\n]+[^ \t\n{]+/
3669 * Perl variable names: /^(my|local).../
3170 */ 3670 */
3171 void 3671 void
3172 Perl_functions (inf) 3672 Perl_functions (inf)
3173 FILE *inf; 3673 FILE *inf;
3174 { 3674 {
3175 register char *cp; 3675 register char *cp;
3176 3676
3177 lineno = 0; 3677 LOOP_ON_INPUT_LINES (inf, lb, cp)
3178 charno = 0; 3678 {
3179 3679 if (*cp++ == 's'
3180 while (!feof (inf)) 3680 && *cp++ == 'u'
3181 { 3681 && *cp++ == 'b' && isspace (*cp++))
3182 lineno++; 3682 {
3183 linecharno = charno; 3683 cp = skip_spaces (cp);
3184 charno += readline (&lb, inf); 3684 if (*cp != '\0')
3685 {
3686 char *sp = cp;
3687 while (*cp != '\0'
3688 && !isspace (*cp) && *cp != '{' && *cp != '(')
3689 cp++;
3690 pfnote (savenstr (sp, cp-sp), TRUE,
3691 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3692 }
3693 }
3694 else if (globals /* only if tagging global vars is enabled */
3695 && ((cp = lb.buffer,
3696 *cp++ == 'm'
3697 && *cp++ == 'y')
3698 || (cp = lb.buffer,
3699 *cp++ == 'l'
3700 && *cp++ == 'o'
3701 && *cp++ == 'c'
3702 && *cp++ == 'a'
3703 && *cp++ == 'l'))
3704 && (*cp == '(' || isspace (*cp)))
3705 {
3706 /* After "my" or "local", but before any following paren or space. */
3707 char *varname = NULL;
3708
3709 cp = skip_spaces (cp);
3710 if (*cp == '$' || *cp == '@' || *cp == '%')
3711 {
3712 char* varstart = ++cp;
3713 while (isalnum (*cp) || *cp == '_')
3714 cp++;
3715 varname = savenstr (varstart, cp-varstart);
3716 }
3717 else
3718 {
3719 /* Should be examining a variable list at this point;
3720 could insist on seeing an open parenthesis. */
3721 while (*cp != '\0' && *cp != ';' && *cp != '=' && *cp != ')')
3722 cp++;
3723 }
3724
3725 /* Perhaps I should back cp up one character, so the TAGS table
3726 doesn't mention (and so depend upon) the following char. */
3727 pfnote ((CTAGS) ? savenstr (lb.buffer, cp-lb.buffer) : varname,
3728 FALSE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3729 }
3730 }
3731 }
3732
3733 /*
3734 * Python support by Eric S. Raymond <esr@thyrsus.com>
3735 * Look for /^def[ \t\n]+[^ \t\n(:]+/ or /^class[ \t\n]+[^ \t\n(:]+/
3736 */
3737 void
3738 Python_functions (inf)
3739 FILE *inf;
3740 {
3741 register char *cp;
3742
3743 LOOP_ON_INPUT_LINES (inf, lb, cp)
3744 {
3745 if (*cp++ == 'd'
3746 && *cp++ == 'e'
3747 && *cp++ == 'f' && isspace (*cp++))
3748 {
3749 cp = skip_spaces (cp);
3750 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3751 cp++;
3752 pfnote (NULL, TRUE,
3753 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3754 }
3755
3185 cp = lb.buffer; 3756 cp = lb.buffer;
3186 3757 if (*cp++ == 'c'
3187 if (*cp++ == 's' && *cp++ == 'u' && *cp++ == 'b' && isspace (*cp++)) 3758 && *cp++ == 'l'
3188 { 3759 && *cp++ == 'a'
3189 while (*cp && isspace (*cp)) 3760 && *cp++ == 's'
3761 && *cp++ == 's' && isspace (*cp++))
3762 {
3763 cp = skip_spaces (cp);
3764 while (*cp != '\0' && !isspace (*cp) && *cp != '(' && *cp != ':')
3190 cp++; 3765 cp++;
3191 while (*cp && ! isspace (*cp) && *cp != '{') 3766 pfnote (NULL, TRUE,
3192 cp++;
3193 pfnote (savenstr (lb.buffer, cp-lb.buffer), TRUE,
3194 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3767 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3195 } 3768 }
3196 } 3769 }
3197 } 3770 }
3198 3771
3203 */ 3776 */
3204 void 3777 void
3205 Cobol_paragraphs (inf) 3778 Cobol_paragraphs (inf)
3206 FILE *inf; 3779 FILE *inf;
3207 { 3780 {
3208 register char *cp; 3781 register char *bp, *ep;
3209 3782
3210 lineno = 0; 3783 LOOP_ON_INPUT_LINES (inf, lb, bp)
3211 charno = 0; 3784 {
3212
3213 while (!feof (inf))
3214 {
3215 lineno++;
3216 linecharno = charno;
3217 charno += readline (&lb, inf);
3218
3219 if (lb.len < 9) 3785 if (lb.len < 9)
3220 continue; 3786 continue;
3221 dbp = lb.buffer + 8; 3787 bp += 8;
3222 3788
3223 /* If eoln, compiler option or comment ignore whole line. */ 3789 /* If eoln, compiler option or comment ignore whole line. */
3224 if (dbp[-1] != ' ' || !isalnum (dbp[0])) 3790 if (bp[-1] != ' ' || !isalnum (bp[0]))
3225 continue; 3791 continue;
3226 3792
3227 for (cp = dbp; isalnum (*cp) || *cp == '-'; cp++) 3793 for (ep = bp; isalnum (*ep) || *ep == '-'; ep++)
3228 continue; 3794 continue;
3229 if (*cp++ == '.') 3795 if (*ep++ == '.')
3230 pfnote (savenstr (dbp, cp-dbp), TRUE, 3796 pfnote (savenstr (bp, ep-bp), TRUE,
3231 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 3797 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
3232 } 3798 }
3233 } 3799 }
3234 3800
3235 /* Added by Mosur Mohan, 4/22/88 */ 3801 /* Added by Mosur Mohan, 4/22/88 */
3236 /* Pascal parsing */ 3802 /* Pascal parsing */
3243 */ 3809 */
3244 void 3810 void
3245 Pascal_functions (inf) 3811 Pascal_functions (inf)
3246 FILE *inf; 3812 FILE *inf;
3247 { 3813 {
3248 struct linebuffer tline; /* mostly copied from C_entries */ 3814 linebuffer tline; /* mostly copied from C_entries */
3249 long save_lcno; 3815 long save_lcno;
3250 int save_lineno, save_len; 3816 int save_lineno, save_len;
3251 char c, *cp, *namebuf; 3817 char c, *cp, *namebuf;
3252 3818
3253 bool /* each of these flags is TRUE iff: */ 3819 bool /* each of these flags is TRUE iff: */
3260 verify_tag; /* point has passed the parm-list, so the 3826 verify_tag; /* point has passed the parm-list, so the
3261 next token will determine whether this 3827 next token will determine whether this
3262 is a FORWARD/EXTERN to be ignored, or 3828 is a FORWARD/EXTERN to be ignored, or
3263 whether it is a real tag */ 3829 whether it is a real tag */
3264 3830
3831 save_lcno = save_lineno = save_len = 0; /* keep compiler quiet */
3832 namebuf = NULL; /* keep compiler quiet */
3265 lineno = 0; 3833 lineno = 0;
3266 charno = 0; 3834 charno = 0;
3267 dbp = lb.buffer; 3835 dbp = lb.buffer;
3268 *dbp = '\0'; 3836 *dbp = '\0';
3269 save_len = 0;
3270 initbuffer (&tline); 3837 initbuffer (&tline);
3271 3838
3272 incomment = inquote = FALSE; 3839 incomment = inquote = FALSE;
3273 found_tag = FALSE; /* have a proc name; check if extern */ 3840 found_tag = FALSE; /* have a proc name; check if extern */
3274 get_tagname = FALSE; /* have found "procedure" keyword */ 3841 get_tagname = FALSE; /* have found "procedure" keyword */
3275 inparms = FALSE; /* found '(' after "proc" */ 3842 inparms = FALSE; /* found '(' after "proc" */
3276 verify_tag = FALSE; /* check if "extern" is ahead */ 3843 verify_tag = FALSE; /* check if "extern" is ahead */
3277 3844
3278 /* long main loop to get next char */ 3845
3279 while (!feof (inf)) 3846 while (!feof (inf)) /* long main loop to get next char */
3280 { 3847 {
3281 c = *dbp++; 3848 c = *dbp++;
3282 if (c == '\0') /* if end of line */ 3849 if (c == '\0') /* if end of line */
3283 { 3850 {
3284 lineno++; 3851 lineno++;
3285 linecharno = charno; 3852 linecharno = charno;
3286 charno += readline (&lb, inf); 3853 charno += readline (&lb, inf);
3287 dbp = lb.buffer; 3854 dbp = lb.buffer;
3288 if (*dbp == '\0') 3855 if (*dbp == '\0')
3289 continue; 3856 continue;
3290 if (!((found_tag && verify_tag) || 3857 if (!((found_tag && verify_tag)
3291 get_tagname)) 3858 || get_tagname))
3292 c = *dbp++; /* only if don't need *dbp pointing 3859 c = *dbp++; /* only if don't need *dbp pointing
3293 to the beginning of the name of 3860 to the beginning of the name of
3294 the procedure or function */ 3861 the procedure or function */
3295 } 3862 }
3296 if (incomment) 3863 if (incomment)
3428 3995
3429 int 3996 int
3430 L_isquote (strp) 3997 L_isquote (strp)
3431 register char *strp; 3998 register char *strp;
3432 { 3999 {
3433 return ((*(++strp) == 'q' || *strp == 'Q') 4000 return ((*++strp == 'q' || *strp == 'Q')
3434 && (*(++strp) == 'u' || *strp == 'U') 4001 && (*++strp == 'u' || *strp == 'U')
3435 && (*(++strp) == 'o' || *strp == 'O') 4002 && (*++strp == 'o' || *strp == 'O')
3436 && (*(++strp) == 't' || *strp == 'T') 4003 && (*++strp == 't' || *strp == 'T')
3437 && (*(++strp) == 'e' || *strp == 'E') 4004 && (*++strp == 'e' || *strp == 'E')
3438 && isspace (*(++strp))); 4005 && isspace (*++strp));
3439 } 4006 }
3440 4007
3441 void 4008 void
3442 L_getit () 4009 L_getit ()
3443 { 4010 {
3444 register char *cp; 4011 register char *cp;
3445 4012
3446 if (*dbp == '\'') /* Skip prefix quote */ 4013 if (*dbp == '\'') /* Skip prefix quote */
3447 dbp++; 4014 dbp++;
3448 else if (*dbp == '(' && L_isquote (dbp)) /* Skip "(quote " */ 4015 else if (*dbp == '(')
3449 { 4016 {
3450 dbp += 7; 4017 if (L_isquote (dbp))
3451 while (isspace (*dbp)) 4018 dbp += 7; /* Skip "(quote " */
3452 dbp++; 4019 else
4020 dbp += 1; /* Skip "(" before name in (defstruct (foo)) */
4021 dbp = skip_spaces (dbp);
3453 } 4022 }
4023
3454 for (cp = dbp /*+1*/; 4024 for (cp = dbp /*+1*/;
3455 *cp != '\0' && *cp != '(' && *cp != ' ' && *cp != ')'; 4025 *cp != '\0' && *cp != '(' && !isspace(*cp) && *cp != ')';
3456 cp++) 4026 cp++)
3457 continue; 4027 continue;
3458 if (cp == dbp) 4028 if (cp == dbp)
3459 return; 4029 return;
3460 4030
3464 4034
3465 void 4035 void
3466 Lisp_functions (inf) 4036 Lisp_functions (inf)
3467 FILE *inf; 4037 FILE *inf;
3468 { 4038 {
3469 lineno = 0; 4039 LOOP_ON_INPUT_LINES (inf, lb, dbp)
3470 charno = 0; 4040 {
3471
3472 while (!feof (inf))
3473 {
3474 lineno++;
3475 linecharno = charno;
3476 charno += readline (&lb, inf);
3477 dbp = lb.buffer;
3478 if (dbp[0] == '(') 4041 if (dbp[0] == '(')
3479 { 4042 {
3480 if (L_isdef (dbp)) 4043 if (L_isdef (dbp))
3481 { 4044 {
3482 while (!isspace (*dbp)) 4045 dbp = skip_non_spaces (dbp);
3483 dbp++; 4046 dbp = skip_spaces (dbp);
3484 while (isspace (*dbp))
3485 dbp++;
3486 L_getit (); 4047 L_getit ();
3487 } 4048 }
3488 else 4049 else
3489 { 4050 {
3490 /* Check for (foo::defmumble name-defined ... */ 4051 /* Check for (foo::defmumble name-defined ... */
3491 do 4052 do
3492 dbp++; 4053 dbp++;
3493 while (*dbp && !isspace (*dbp) 4054 while (*dbp != '\0' && !isspace (*dbp)
3494 && *dbp != ':' && *dbp != '(' && *dbp != ')'); 4055 && *dbp != ':' && *dbp != '(' && *dbp != ')');
3495 if (*dbp == ':') 4056 if (*dbp == ':')
3496 { 4057 {
3497 do 4058 do
3498 dbp++; 4059 dbp++;
3499 while (*dbp == ':'); 4060 while (*dbp == ':');
3500 4061
3501 if (L_isdef (dbp - 1)) 4062 if (L_isdef (dbp - 1))
3502 { 4063 {
3503 while (!isspace (*dbp)) 4064 dbp = skip_non_spaces (dbp);
3504 dbp++; 4065 dbp = skip_spaces (dbp);
3505 while (isspace (*dbp))
3506 dbp++;
3507 L_getit (); 4066 L_getit ();
3508 } 4067 }
3509 } 4068 }
3510 } 4069 }
3511 } 4070 }
3514 4073
3515 /* 4074 /*
3516 * Postscript tag functions 4075 * Postscript tag functions
3517 * Just look for lines where the first character is '/' 4076 * Just look for lines where the first character is '/'
3518 * Richard Mlynarik <mly@adoc.xerox.com> 4077 * Richard Mlynarik <mly@adoc.xerox.com>
4078 * Also look at "defineps" for PSWrap
4079 * suggested by Masatake YAMATO <masata-y@is.aist-nara.ac.jp>
3519 */ 4080 */
3520 void 4081 void
3521 Postscript_functions (inf) 4082 Postscript_functions (inf)
3522 FILE *inf; 4083 FILE *inf;
3523 { 4084 {
3524 lineno = 0; 4085 register char *bp, *ep;
3525 charno = 0; 4086
3526 4087 LOOP_ON_INPUT_LINES (inf, lb, bp)
3527 while (!feof (inf)) 4088 {
3528 { 4089 if (bp[0] == '/')
3529 lineno++; 4090 {
3530 linecharno = charno; 4091 for (ep = bp+1;
3531 charno += readline (&lb, inf); 4092 *ep != '\0' && *ep != ' ' && *ep != '{';
3532 dbp = lb.buffer; 4093 ep++)
3533 if (dbp[0] == '/')
3534 {
3535 register char *cp;
3536 for (cp = dbp+1;
3537 *cp != '\0' && *cp != ' ' && *cp != '{';
3538 cp++)
3539 continue; 4094 continue;
3540 pfnote (savenstr (dbp, cp-dbp), TRUE, 4095 pfnote (savenstr (bp, ep-bp), TRUE,
3541 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); 4096 lb.buffer, ep - lb.buffer + 1, lineno, linecharno);
4097 }
4098 else if (strneq (bp, "defineps", 8))
4099 {
4100 bp = skip_non_spaces (bp);
4101 bp = skip_spaces (bp);
4102 get_tag (bp);
3542 } 4103 }
3543 } 4104 }
3544 } 4105 }
3545 4106
3546 4107
3556 4117
3557 void 4118 void
3558 Scheme_functions (inf) 4119 Scheme_functions (inf)
3559 FILE *inf; 4120 FILE *inf;
3560 { 4121 {
3561 lineno = 0; 4122 register char *bp;
3562 charno = 0; 4123
3563 4124 LOOP_ON_INPUT_LINES (inf, lb, bp)
3564 while (!feof (inf)) 4125 {
3565 { 4126 if (bp[0] == '('
3566 lineno++; 4127 && (bp[1] == 'D' || bp[1] == 'd')
3567 linecharno = charno; 4128 && (bp[2] == 'E' || bp[2] == 'e')
3568 charno += readline (&lb, inf); 4129 && (bp[3] == 'F' || bp[3] == 'f'))
3569 dbp = lb.buffer; 4130 {
3570 if (dbp[0] == '(' && 4131 bp = skip_non_spaces (bp);
3571 (dbp[1] == 'D' || dbp[1] == 'd') &&
3572 (dbp[2] == 'E' || dbp[2] == 'e') &&
3573 (dbp[3] == 'F' || dbp[3] == 'f'))
3574 {
3575 while (!isspace (*dbp))
3576 dbp++;
3577 /* Skip over open parens and white space */ 4132 /* Skip over open parens and white space */
3578 while (*dbp && (isspace (*dbp) || *dbp == '(')) 4133 while (isspace (*bp) || *bp == '(')
3579 dbp++; 4134 bp++;
3580 get_scheme (); 4135 get_tag (bp);
3581 } 4136 }
3582 if (dbp[0] == '(' && 4137 if (bp[0] == '('
3583 (dbp[1] == 'S' || dbp[1] == 's') && 4138 && (bp[1] == 'S' || bp[1] == 's')
3584 (dbp[2] == 'E' || dbp[2] == 'e') && 4139 && (bp[2] == 'E' || bp[2] == 'e')
3585 (dbp[3] == 'T' || dbp[3] == 't') && 4140 && (bp[3] == 'T' || bp[3] == 't')
3586 (dbp[4] == '!' || dbp[4] == '!') && 4141 && (bp[4] == '!' || bp[4] == '!')
3587 (isspace (dbp[5]))) 4142 && (isspace (bp[5])))
3588 { 4143 {
3589 while (!isspace (*dbp)) 4144 bp = skip_non_spaces (bp);
3590 dbp++; 4145 bp = skip_spaces (bp);
3591 /* Skip over white space */ 4146 get_tag (bp);
3592 while (isspace (*dbp)) 4147 }
3593 dbp++; 4148 }
3594 get_scheme ();
3595 }
3596 }
3597 }
3598
3599 void
3600 get_scheme ()
3601 {
3602 register char *cp;
3603
3604 if (*dbp == '\0')
3605 return;
3606 /* Go till you get to white space or a syntactic break */
3607 for (cp = dbp + 1;
3608 *cp && *cp != '(' && *cp != ')' && !isspace (*cp);
3609 cp++)
3610 continue;
3611 pfnote (savenstr (dbp, cp-dbp), TRUE,
3612 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
3613 } 4149 }
3614 4150
3615 /* Find tags in TeX and LaTeX input files. */ 4151 /* Find tags in TeX and LaTeX input files. */
3616 4152
3617 /* TEX_toktab is a table of TeX control sequences that define tags. 4153 /* TEX_toktab is a table of TeX control sequences that define tags.
3645 */ 4181 */
3646 void 4182 void
3647 TeX_functions (inf) 4183 TeX_functions (inf)
3648 FILE *inf; 4184 FILE *inf;
3649 { 4185 {
3650 char *lasthit; 4186 char *cp, *lasthit;
3651 register int i; 4187 register int i;
3652
3653 lineno = 0;
3654 charno = 0;
3655 4188
3656 /* Select either \ or ! as escape character. */ 4189 /* Select either \ or ! as escape character. */
3657 TEX_mode (inf); 4190 TEX_mode (inf);
3658 4191
3659 /* Initialize token table once from environment. */ 4192 /* Initialize token table once from environment. */
3660 if (!TEX_toktab) 4193 if (!TEX_toktab)
3661 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv); 4194 TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv);
3662 4195
3663 while (!feof (inf)) 4196 LOOP_ON_INPUT_LINES (inf, lb, cp)
3664 { /* Scan each line in file */ 4197 {
3665 lineno++; 4198 lasthit = cp;
3666 linecharno = charno; 4199 /* Look at each esc in line. */
3667 charno += readline (&lb, inf); 4200 while ((cp = etags_strchr (cp, TEX_esc)) != NULL)
3668 dbp = lb.buffer; 4201 {
3669 lasthit = dbp; 4202 if (*++cp == '\0')
3670 while (dbp = etags_strchr (dbp, TEX_esc)) /* Look at each esc in line */
3671 {
3672 if (!*(++dbp))
3673 break; 4203 break;
3674 linecharno += dbp - lasthit; 4204 linecharno += cp - lasthit;
3675 lasthit = dbp; 4205 lasthit = cp;
3676 i = TEX_Token (lasthit); 4206 i = TEX_Token (lasthit);
3677 if (i >= 0) 4207 if (i >= 0)
3678 { 4208 {
3679 /* We seem to include the TeX command in the tag name. 4209 /* We seem to include the TeX command in the tag name.
3680 register char *p; 4210 register char *p;
3722 { 4252 {
3723 TEX_esc = TEX_SESC; 4253 TEX_esc = TEX_SESC;
3724 TEX_opgrp = '<'; 4254 TEX_opgrp = '<';
3725 TEX_clgrp = '>'; 4255 TEX_clgrp = '>';
3726 } 4256 }
4257 /* If the input file is compressed, inf is a pipe, and rewind may fail.
4258 No attempt is made to correct the situation. */
3727 rewind (inf); 4259 rewind (inf);
3728 } 4260 }
3729 4261
3730 /* Read environment and prepend it to the default string. 4262 /* Read environment and prepend it to the default string.
3731 Build token table. */ 4263 Build token table. */
3749 env = concat (oldenv, defenv, ""); 4281 env = concat (oldenv, defenv, "");
3750 } 4282 }
3751 4283
3752 /* Allocate a token table */ 4284 /* Allocate a token table */
3753 for (size = 1, p = env; p;) 4285 for (size = 1, p = env; p;)
3754 if ((p = etags_strchr (p, ':')) && *(++p)) 4286 if ((p = etags_strchr (p, ':')) && *++p != '\0')
3755 size++; 4287 size++;
3756 /* Add 1 to leave room for null terminator. */ 4288 /* Add 1 to leave room for null terminator. */
3757 tab = xnew (size + 1, struct TEX_tabent); 4289 tab = xnew (size + 1, struct TEX_tabent);
3758 4290
3759 /* Unpack environment string into token table. Be careful about */ 4291 /* Unpack environment string into token table. Be careful about */
3782 } 4314 }
3783 4315
3784 /* If the text at CP matches one of the tag-defining TeX command names, 4316 /* If the text at CP matches one of the tag-defining TeX command names,
3785 return the pointer to the first occurrence of that command in TEX_toktab. 4317 return the pointer to the first occurrence of that command in TEX_toktab.
3786 Otherwise return -1. 4318 Otherwise return -1.
3787 Keep the capital `T' in `Token' for dumb truncating compilers 4319 Keep the capital `T' in `token' for dumb truncating compilers
3788 (this distinguishes it from `TEX_toktab' */ 4320 (this distinguishes it from `TEX_toktab' */
3789 int 4321 int
3790 TEX_Token (cp) 4322 TEX_Token (cp)
3791 char *cp; 4323 char *cp;
3792 { 4324 {
3800 4332
3801 /* 4333 /*
3802 * Prolog support (rewritten) by Anders Lindgren, Mar. 96 4334 * Prolog support (rewritten) by Anders Lindgren, Mar. 96
3803 * 4335 *
3804 * Assumes that the predicate starts at column 0. 4336 * Assumes that the predicate starts at column 0.
3805 * Only the first clause of a predicate is added. 4337 * Only the first clause of a predicate is added.
3806 */ 4338 */
3807 int prolog_pred (); 4339 int prolog_pred ();
3808 void prolog_skip_comment (); 4340 void prolog_skip_comment ();
3809 int prolog_atom (); 4341 int prolog_atom ();
3810 int eat_white ();
3811 4342
3812 void 4343 void
3813 Prolog_functions (inf) 4344 Prolog_functions (inf)
3814 FILE *inf; 4345 FILE *inf;
3815 { 4346 {
3816 char * last; 4347 char *cp, *last;
3817 int len; 4348 int len;
3818 int allocated; 4349 int allocated;
3819 4350
3820 allocated = 0; 4351 allocated = 0;
3821 len = 0; 4352 len = 0;
3822 last = NULL; 4353 last = NULL;
3823 4354
3824 lineno = 0; 4355 LOOP_ON_INPUT_LINES (inf, lb, cp)
3825 linecharno = 0; 4356 {
3826 charno = 0; 4357 if (cp[0] == '\0') /* Empty line */
3827
3828 while (!feof (inf))
3829 {
3830 lineno++;
3831 linecharno += charno;
3832 charno = readline (&lb, inf);
3833 dbp = lb.buffer;
3834 if (dbp[0] == '\0') /* Empty line */
3835 continue; 4358 continue;
3836 else if (isspace (dbp[0])) /* Not a predicate */ 4359 else if (isspace (cp[0])) /* Not a predicate */
3837 continue; 4360 continue;
3838 else if (dbp[0] == '/' && dbp[1] == '*') /* comment. */ 4361 else if (cp[0] == '/' && cp[1] == '*') /* comment. */
3839 prolog_skip_comment (&lb, inf); 4362 prolog_skip_comment (&lb, inf);
3840 else if (len = prolog_pred (dbp, last)) 4363 else if ((len = prolog_pred (cp, last)) > 0)
3841 { 4364 {
3842 /* Predicate. Store the function name so that we only 4365 /* Predicate. Store the function name so that we only
3843 generate a tag for the first clause. */ 4366 generate a tag for the first clause. */
3844 if (last == NULL) 4367 if (last == NULL)
3845 last = xnew(len + 1, char); 4368 last = xnew(len + 1, char);
3846 else if (len + 1 > allocated) 4369 else if (len + 1 > allocated)
3847 last = (char *) xrealloc(last, len + 1); 4370 last = xrnew (last, len + 1, char);
3848 allocated = len + 1; 4371 allocated = len + 1;
3849 strncpy (last, dbp, len); 4372 strncpy (last, cp, len);
3850 last[len] = '\0'; 4373 last[len] = '\0';
3851 } 4374 }
3852 } 4375 }
3853 } 4376 }
3854 4377
3855 4378
3856 void 4379 void
3857 prolog_skip_comment (plb, inf) 4380 prolog_skip_comment (plb, inf)
3858 struct linebuffer *plb; 4381 linebuffer *plb;
3859 FILE *inf; 4382 FILE *inf;
3860 { 4383 {
3861 char *cp; 4384 char *cp;
3862 4385
3863 do 4386 do
3892 pos = prolog_atom (s, 0); 4415 pos = prolog_atom (s, 0);
3893 if (pos < 1) 4416 if (pos < 1)
3894 return 0; 4417 return 0;
3895 4418
3896 len = pos; 4419 len = pos;
3897 pos += eat_white (s, pos); 4420 pos = skip_spaces (s + pos) - s;
3898 4421
3899 if ((s[pos] == '(') || (s[pos] == '.')) 4422 if ((s[pos] == '(') || (s[pos] == '.'))
3900 { 4423 {
3901 if (s[pos] == '(') 4424 if (s[pos] == '(')
3902 pos++; 4425 pos++;
3903 4426
3904 /* Save only the first clause. */ 4427 /* Save only the first clause. */
3905 if (last == NULL 4428 if (last == NULL
3906 || len != strlen (last) 4429 || len != (int)strlen (last)
3907 || !strneq (s, last, len)) 4430 || !strneq (s, last, len))
3908 { 4431 {
3909 pfnote (savenstr (s, len), TRUE, 4432 pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno);
3910 s, pos, lineno, linecharno);
3911 return len; 4433 return len;
3912 } 4434 }
3913 } 4435 }
3914 return 0; 4436 return 0;
3915 } 4437 }
3944 } 4466 }
3945 else if (s[pos] == '\'') 4467 else if (s[pos] == '\'')
3946 { 4468 {
3947 pos++; 4469 pos++;
3948 4470
3949 while (1) 4471 while (1)
3950 { 4472 {
3951 if (s[pos] == '\'') 4473 if (s[pos] == '\'')
3952 { 4474 {
3953 pos++; 4475 pos++;
3954 if (s[pos] != '\'') 4476 if (s[pos] != '\'')
3970 return pos - origpos; 4492 return pos - origpos;
3971 } 4493 }
3972 else 4494 else
3973 return -1; 4495 return -1;
3974 } 4496 }
3975
3976 /* Consume whitespace. Return the number of bytes eaten. */
3977 int
3978 eat_white (s, pos)
3979 char *s;
3980 int pos;
3981 {
3982 int origpos = pos;
3983
3984 origpos = pos;
3985
3986 while (isspace (s[pos]))
3987 pos++;
3988
3989 return pos - origpos;
3990 }
3991 4497
3992 /* 4498 /*
3993 * Support for Erlang -- Anders Lindgren, Feb 1996. 4499 * Support for Erlang -- Anders Lindgren, Feb 1996.
3994 * 4500 *
3995 * Generates tags for functions, defines, and records. 4501 * Generates tags for functions, defines, and records.
3996 * 4502 *
3997 * Assumes that Erlang functions start at column 0. 4503 * Assumes that Erlang functions start at column 0.
4002 4508
4003 void 4509 void
4004 Erlang_functions (inf) 4510 Erlang_functions (inf)
4005 FILE *inf; 4511 FILE *inf;
4006 { 4512 {
4007 char * last; 4513 char *cp, *last;
4008 int len; 4514 int len;
4009 int allocated; 4515 int allocated;
4010 4516
4011 allocated = 0; 4517 allocated = 0;
4012 len = 0; 4518 len = 0;
4013 last = NULL; 4519 last = NULL;
4014 4520
4015 lineno = 0; 4521 LOOP_ON_INPUT_LINES (inf, lb, cp)
4016 linecharno = 0; 4522 {
4017 charno = 0; 4523 if (cp[0] == '\0') /* Empty line */
4018
4019 while (!feof (inf))
4020 {
4021 lineno++;
4022 linecharno += charno;
4023 charno = readline (&lb, inf);
4024 dbp = lb.buffer;
4025 if (dbp[0] == '\0') /* Empty line */
4026 continue; 4524 continue;
4027 else if (isspace (dbp[0])) /* Not function nor attribute */ 4525 else if (isspace (cp[0])) /* Not function nor attribute */
4028 continue; 4526 continue;
4029 else if (dbp[0] == '%') /* comment */ 4527 else if (cp[0] == '%') /* comment */
4030 continue; 4528 continue;
4031 else if (dbp[0] == '"') /* Sometimes, strings start in column one */ 4529 else if (cp[0] == '"') /* Sometimes, strings start in column one */
4032 continue; 4530 continue;
4033 else if (dbp[0] == '-') /* attribute, e.g. "-define" */ 4531 else if (cp[0] == '-') /* attribute, e.g. "-define" */
4034 { 4532 {
4035 erlang_attribute (dbp); 4533 erlang_attribute (cp);
4036 last = NULL; 4534 last = NULL;
4037 } 4535 }
4038 else if (len = erlang_func (dbp, last)) 4536 else if ((len = erlang_func (cp, last)) > 0)
4039 { 4537 {
4040 /* 4538 /*
4041 * Function. Store the function name so that we only 4539 * Function. Store the function name so that we only
4042 * generates a tag for the first clause. 4540 * generates a tag for the first clause.
4043 */ 4541 */
4044 if (last == NULL) 4542 if (last == NULL)
4045 last = xnew (len + 1, char); 4543 last = xnew (len + 1, char);
4046 else if (len + 1 > allocated) 4544 else if (len + 1 > allocated)
4047 last = (char *) xrealloc (last, len + 1); 4545 last = xrnew (last, len + 1, char);
4048 allocated = len + 1; 4546 allocated = len + 1;
4049 strncpy (last, dbp, len); 4547 strncpy (last, cp, len);
4050 last[len] = '\0'; 4548 last[len] = '\0';
4051 } 4549 }
4052 } 4550 }
4053 } 4551 }
4054 4552
4074 pos = erlang_atom (s, 0); 4572 pos = erlang_atom (s, 0);
4075 if (pos < 1) 4573 if (pos < 1)
4076 return 0; 4574 return 0;
4077 4575
4078 len = pos; 4576 len = pos;
4079 pos += eat_white (s, pos); 4577 pos = skip_spaces (s + pos) - s;
4080 4578
4081 /* Save only the first clause. */ 4579 /* Save only the first clause. */
4082 if (s[pos++] == '(' 4580 if (s[pos++] == '('
4083 && (last == NULL 4581 && (last == NULL
4084 || len != strlen (last) 4582 || len != (int)strlen (last)
4085 || !strneq (s, last, len))) 4583 || !strneq (s, last, len)))
4086 { 4584 {
4087 pfnote (savenstr (s, len), TRUE, 4585 pfnote (savenstr (s, len), TRUE, s, pos, lineno, linecharno);
4088 s, pos, lineno, linecharno);
4089 return len; 4586 return len;
4090 } 4587 }
4091 4588
4092 return 0; 4589 return 0;
4093 } 4590 }
4094 4591
4095 4592
4096 /* 4593 /*
4097 * Handle attributes. Currently, tags are generated for defines 4594 * Handle attributes. Currently, tags are generated for defines
4098 * and records. 4595 * and records.
4099 * 4596 *
4100 * They are on the form: 4597 * They are on the form:
4101 * -define(foo, bar). 4598 * -define(foo, bar).
4102 * -define(Foo(M, N), M+N). 4599 * -define(Foo(M, N), M+N).
4109 int pos; 4606 int pos;
4110 int len; 4607 int len;
4111 4608
4112 if (strneq (s, "-define", 7) || strneq (s, "-record", 7)) 4609 if (strneq (s, "-define", 7) || strneq (s, "-record", 7))
4113 { 4610 {
4114 pos = 7 + eat_white (s, 7); 4611 pos = skip_spaces (s + 7) - s;
4115 if (s[pos++] == '(') 4612 if (s[pos++] == '(')
4116 { 4613 {
4117 pos += eat_white (s, pos); 4614 pos = skip_spaces (s + pos) - s;
4118 if (len = erlang_atom (s, pos)) 4615 len = erlang_atom (s, pos);
4119 pfnote (savenstr (& s[pos], len), TRUE, 4616 if (len != 0)
4120 s, pos + len, lineno, linecharno); 4617 pfnote (savenstr (& s[pos], len), TRUE,
4618 s, pos + len, lineno, linecharno);
4121 } 4619 }
4122 } 4620 }
4123 return; 4621 return;
4124 } 4622 }
4125 4623
4147 } 4645 }
4148 else if (s[pos] == '\'') 4646 else if (s[pos] == '\'')
4149 { 4647 {
4150 pos++; 4648 pos++;
4151 4649
4152 while (1) 4650 while (1)
4153 { 4651 {
4154 if (s[pos] == '\'') 4652 if (s[pos] == '\'')
4155 { 4653 {
4156 pos++; 4654 pos++;
4157 break; 4655 break;
4173 else 4671 else
4174 return -1; 4672 return -1;
4175 } 4673 }
4176 4674
4177 #ifdef ETAGS_REGEXPS 4675 #ifdef ETAGS_REGEXPS
4676
4178 /* Take a string like "/blah/" and turn it into "blah", making sure 4677 /* Take a string like "/blah/" and turn it into "blah", making sure
4179 that the first and last characters are the same, and handling 4678 that the first and last characters are the same, and handling
4180 quoted separator characters. Actually, stops on the occurrence of 4679 quoted separator characters. Actually, stops on the occurrence of
4181 an unquoted separator. Also turns "\t" into a Tab character. 4680 an unquoted separator. Also turns "\t" into a Tab character.
4182 Returns pointer to terminating separator. Works in place. Null 4681 Returns pointer to terminating separator. Works in place. Null
4217 *copyto = '\0'; 4716 *copyto = '\0';
4218 return name; 4717 return name;
4219 } 4718 }
4220 4719
4221 /* Look at the argument of --regex or --no-regex and do the right 4720 /* Look at the argument of --regex or --no-regex and do the right
4222 thing. */ 4721 thing. Same for each line of a regexp file. */
4223 void 4722 void
4224 analyse_regex (regex_arg) 4723 analyse_regex (regex_arg, ignore_case)
4225 char *regex_arg; 4724 char *regex_arg;
4226 { 4725 bool ignore_case;
4227 struct stat stat_buf; 4726 {
4228
4229 if (regex_arg == NULL) 4727 if (regex_arg == NULL)
4230 { 4728 free_patterns (); /* --no-regex: remove existing regexps */
4231 /* Remove existing regexps. */ 4729
4232 num_patterns = 0; 4730 /* A real --regexp option or a line in a regexp file. */
4233 patterns = NULL; 4731 switch (regex_arg[0])
4234 return; 4732 {
4235 } 4733 /* Comments in regexp file or null arg to --regex. */
4236 if (regex_arg[0] == '\0') 4734 case '\0':
4237 { 4735 case ' ':
4238 error ("missing regexp", (char *)NULL); 4736 case '\t':
4239 return; 4737 break;
4240 } 4738
4241 if (regex_arg[0] == '@' 4739 /* Read a regex file. This is recursive and may result in a
4242 && stat (regex_arg + 1, &stat_buf) == 0) 4740 loop, which will stop when the file descriptors are exhausted. */
4243 { 4741 case '@':
4244 FILE *regexfp; 4742 {
4245 struct linebuffer regexbuf; 4743 FILE *regexfp;
4246 char *regexfile = regex_arg + 1; 4744 linebuffer regexbuf;
4247 4745 char *regexfile = regex_arg + 1;
4248 /* regexfile is a file containing regexps, one per line. */ 4746
4249 regexfp = fopen (regexfile, "r"); 4747 /* regexfile is a file containing regexps, one per line. */
4250 if (regexfp == NULL) 4748 regexfp = fopen (regexfile, "r");
4251 { 4749 if (regexfp == NULL)
4252 perror (regexfile); 4750 {
4751 pfatal (regexfile);
4752 return;
4753 }
4754 initbuffer (&regexbuf);
4755 while (readline_internal (&regexbuf, regexfp) > 0)
4756 analyse_regex (regexbuf.buffer, ignore_case);
4757 free (regexbuf.buffer);
4758 fclose (regexfp);
4759 }
4760 break;
4761
4762 /* Regexp to be used for a specific language only. */
4763 case '{':
4764 {
4765 language *lang;
4766 char *lang_name = regex_arg + 1;
4767 char *cp;
4768
4769 for (cp = lang_name; *cp != '}'; cp++)
4770 if (*cp == '\0')
4771 {
4772 error ("unterminated language name in regex: %s", regex_arg);
4773 return;
4774 }
4775 *cp = '\0';
4776 lang = get_language_from_name (lang_name);
4777 if (lang == NULL)
4253 return; 4778 return;
4254 } 4779 add_regex (cp + 1, ignore_case, lang);
4255 initbuffer (&regexbuf); 4780 }
4256 while (readline_internal (&regexbuf, regexfp)) 4781 break;
4257 add_regex (regexbuf.buffer); 4782
4258 free (regexbuf.buffer); 4783 /* Regexp to be used for any language. */
4259 fclose (regexfp); 4784 default:
4260 } 4785 add_regex (regex_arg, ignore_case, NULL);
4261 else 4786 break;
4262 {
4263 add_regex (regex_arg);
4264 } 4787 }
4265 } 4788 }
4266 4789
4267 /* Turn a name, which is an ed-style (but Emacs syntax) regular 4790 /* Turn a name, which is an ed-style (but Emacs syntax) regular
4268 expression, into a real regular expression by compiling it. */ 4791 expression, into a real regular expression by compiling it. */
4269 void 4792 void
4270 add_regex (regexp_pattern) 4793 add_regex (regexp_pattern, ignore_case, lang)
4271 char *regexp_pattern; 4794 char *regexp_pattern;
4795 bool ignore_case;
4796 language *lang;
4272 { 4797 {
4273 char *name; 4798 char *name;
4274 const char *err; 4799 const char *err;
4275 struct re_pattern_buffer *patbuf; 4800 struct re_pattern_buffer *patbuf;
4801 pattern *pp;
4276 4802
4277 4803
4278 if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0]) 4804 if (regexp_pattern[strlen(regexp_pattern)-1] != regexp_pattern[0])
4279 { 4805 {
4280 error ("%s: unterminated regexp", regexp_pattern); 4806 error ("%s: unterminated regexp", regexp_pattern);
4287 return; 4813 return;
4288 } 4814 }
4289 (void) scan_separators (name); 4815 (void) scan_separators (name);
4290 4816
4291 patbuf = xnew (1, struct re_pattern_buffer); 4817 patbuf = xnew (1, struct re_pattern_buffer);
4292 patbuf->translate = NULL; 4818 /* Translation table to fold case if appropriate. */
4819 patbuf->translate = (ignore_case) ? lc_trans : NULL;
4293 patbuf->fastmap = NULL; 4820 patbuf->fastmap = NULL;
4294 patbuf->buffer = NULL; 4821 patbuf->buffer = NULL;
4295 patbuf->allocated = 0; 4822 patbuf->allocated = 0;
4296 4823
4297 re_syntax_options = RE_INTERVALS;
4298 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf); 4824 err = re_compile_pattern (regexp_pattern, strlen (regexp_pattern), patbuf);
4299 if (err != NULL) 4825 if (err != NULL)
4300 { 4826 {
4301 error ("%s while compiling pattern", err); 4827 error ("%s while compiling pattern", err);
4302 return; 4828 return;
4303 } 4829 }
4304 4830
4305 num_patterns += 1; 4831 pp = p_head;
4306 if (num_patterns == 1) 4832 p_head = xnew (1, pattern);
4307 patterns = xnew (1, struct pattern); 4833 p_head->regex = savestr (regexp_pattern);
4308 else 4834 p_head->p_next = pp;
4309 patterns = ((struct pattern *) 4835 p_head->language = lang;
4310 xrealloc (patterns, 4836 p_head->pattern = patbuf;
4311 (num_patterns * sizeof (struct pattern)))); 4837 p_head->name_pattern = savestr (name);
4312 patterns[num_patterns - 1].pattern = patbuf; 4838 p_head->error_signaled = FALSE;
4313 patterns[num_patterns - 1].name_pattern = savestr (name);
4314 patterns[num_patterns - 1].error_signaled = FALSE;
4315 } 4839 }
4316 4840
4317 /* 4841 /*
4318 * Do the substitutions indicated by the regular expression and 4842 * Do the substitutions indicated by the regular expression and
4319 * arguments. 4843 * arguments.
4358 } 4882 }
4359 else 4883 else
4360 *t++ = *out; 4884 *t++ = *out;
4361 *t = '\0'; 4885 *t = '\0';
4362 4886
4363 if (DEBUG && (t > result + size || t - result != strlen (result))) 4887 if (DEBUG && (t > result + size || t - result != (int)strlen (result)))
4364 abort (); 4888 abort ();
4365 4889
4366 return result; 4890 return result;
4367 } 4891 }
4892
4893 /* Deallocate all patterns. */
4894 void
4895 free_patterns ()
4896 {
4897 pattern *pp;
4898 while (p_head != NULL)
4899 {
4900 pp = p_head->p_next;
4901 free (p_head->regex);
4902 free (p_head->name_pattern);
4903 free (p_head);
4904 p_head = pp;
4905 }
4906 return;
4907 }
4368 4908
4909 void
4910 get_tag (bp)
4911 register char *bp;
4912 {
4913 register char *cp;
4914
4915 if (*bp == '\0')
4916 return;
4917 /* Go till you get to white space or a syntactic break */
4918 for (cp = bp + 1;
4919 *cp != '\0' && *cp != '(' && *cp != ')' && !isspace (*cp);
4920 cp++)
4921 continue;
4922 pfnote (savenstr (bp, cp-bp), TRUE,
4923 lb.buffer, cp - lb.buffer + 1, lineno, linecharno);
4924 }
4925
4369 #endif /* ETAGS_REGEXPS */ 4926 #endif /* ETAGS_REGEXPS */
4370 /* Initialize a linebuffer for use */ 4927 /* Initialize a linebuffer for use */
4371 void 4928 void
4372 initbuffer (linebuffer) 4929 initbuffer (lbp)
4373 struct linebuffer *linebuffer; 4930 linebuffer *lbp;
4374 { 4931 {
4375 linebuffer->size = 200; 4932 lbp->size = 200;
4376 linebuffer->buffer = xnew (200, char); 4933 lbp->buffer = xnew (200, char);
4377 } 4934 }
4378 4935
4379 /* 4936 /*
4380 * Read a line of text from `stream' into `linebuffer'. 4937 * Read a line of text from `stream' into `lbp', excluding the
4381 * Return the number of characters read from `stream', 4938 * newline or CR-NL, if any. Return the number of characters read from
4382 * which is the length of the line including the newline, if any. 4939 * `stream', which is the length of the line including the newline.
4940 *
4941 * On DOS or Windows we do not count the CR character, if any, before the
4942 * NL, in the returned length; this mirrors the behavior of emacs on those
4943 * platforms (for text files, it translates CR-NL to NL as it reads in the
4944 * file).
4383 */ 4945 */
4384 long 4946 long
4385 readline_internal (linebuffer, stream) 4947 readline_internal (lbp, stream)
4386 struct linebuffer *linebuffer; 4948 linebuffer *lbp;
4387 register FILE *stream; 4949 register FILE *stream;
4388 { 4950 {
4389 char *buffer = linebuffer->buffer; 4951 char *buffer = lbp->buffer;
4390 register char *p = linebuffer->buffer; 4952 register char *p = lbp->buffer;
4391 register char *pend; 4953 register char *pend;
4392 int chars_deleted; 4954 int chars_deleted;
4393 4955
4394 pend = p + linebuffer->size; /* Separate to avoid 386/IX compiler bug. */ 4956 pend = p + lbp->size; /* Separate to avoid 386/IX compiler bug. */
4395 4957
4396 while (1) 4958 while (1)
4397 { 4959 {
4398 register int c = getc (stream); 4960 register int c = getc (stream);
4399 if (p == pend) 4961 if (p == pend)
4400 { 4962 {
4401 linebuffer->size *= 2; 4963 /* We're at the end of linebuffer: expand it. */
4402 buffer = (char *) xrealloc (buffer, linebuffer->size); 4964 lbp->size *= 2;
4403 p += buffer - linebuffer->buffer; 4965 buffer = xrnew (buffer, lbp->size, char);
4404 pend = buffer + linebuffer->size; 4966 p += buffer - lbp->buffer;
4405 linebuffer->buffer = buffer; 4967 pend = buffer + lbp->size;
4968 lbp->buffer = buffer;
4406 } 4969 }
4407 if (c == EOF) 4970 if (c == EOF)
4408 { 4971 {
4409 *p = '\0'; 4972 *p = '\0';
4410 chars_deleted = 0; 4973 chars_deleted = 0;
4433 *p = '\0'; 4996 *p = '\0';
4434 break; 4997 break;
4435 } 4998 }
4436 *p++ = c; 4999 *p++ = c;
4437 } 5000 }
4438 linebuffer->len = p - buffer; 5001 lbp->len = p - buffer;
4439 5002
4440 return linebuffer->len + chars_deleted; 5003 return lbp->len + chars_deleted;
4441 } 5004 }
4442 5005
4443 /* 5006 /*
4444 * Like readline_internal, above, but in addition try to match the 5007 * Like readline_internal, above, but in addition try to match the
4445 * input line against any existing regular expressions. 5008 * input line against relevant regular expressions.
4446 */ 5009 */
4447 long 5010 long
4448 readline (linebuffer, stream) 5011 readline (lbp, stream)
4449 struct linebuffer *linebuffer; 5012 linebuffer *lbp;
4450 FILE *stream; 5013 FILE *stream;
4451 { 5014 {
4452 /* Read new line. */ 5015 /* Read new line. */
4453 long result = readline_internal (linebuffer, stream); 5016 long result = readline_internal (lbp, stream);
4454 #ifdef ETAGS_REGEXPS 5017 #ifdef ETAGS_REGEXPS
4455 int i; 5018 int match;
4456 5019 pattern *pp;
4457 /* Match against all listed patterns. */ 5020
4458 if (linebuffer->len > 0) 5021 /* Match against relevant patterns. */
4459 for (i = 0; i < num_patterns; ++i) 5022 if (lbp->len > 0)
5023 for (pp = p_head; pp != NULL; pp = pp->p_next)
4460 { 5024 {
4461 int match = re_match (patterns[i].pattern, linebuffer->buffer, 5025 /* Only use generic regexps or those for the current language. */
4462 linebuffer->len, 0, &patterns[i].regs); 5026 if (pp->language != NULL && pp->language != curlang)
5027 continue;
5028
5029 match = re_match (pp->pattern, lbp->buffer, lbp->len, 0, &pp->regs);
4463 switch (match) 5030 switch (match)
4464 { 5031 {
4465 case -2: 5032 case -2:
4466 /* Some error. */ 5033 /* Some error. */
4467 if (!patterns[i].error_signaled) 5034 if (!pp->error_signaled)
4468 { 5035 {
4469 error ("error while matching pattern %d", i); 5036 error ("error while matching \"%s\"", pp->regex);
4470 patterns[i].error_signaled = TRUE; 5037 pp->error_signaled = TRUE;
4471 } 5038 }
4472 break; 5039 break;
4473 case -1: 5040 case -1:
4474 /* No match. */ 5041 /* No match. */
4475 break; 5042 break;
4476 default: 5043 default:
4477 /* Match occurred. Construct a tag. */ 5044 /* Match occurred. Construct a tag. */
4478 if (patterns[i].name_pattern[0] != '\0') 5045 if (pp->name_pattern[0] != '\0')
4479 { 5046 {
4480 /* Make a named tag. */ 5047 /* Make a named tag. */
4481 char *name = substitute (linebuffer->buffer, 5048 char *name = substitute (lbp->buffer,
4482 patterns[i].name_pattern, 5049 pp->name_pattern, &pp->regs);
4483 &patterns[i].regs);
4484 if (name != NULL) 5050 if (name != NULL)
4485 pfnote (name, TRUE, 5051 pfnote (name, TRUE, lbp->buffer, match, lineno, linecharno);
4486 linebuffer->buffer, match, lineno, linecharno);
4487 } 5052 }
4488 else 5053 else
4489 { 5054 {
4490 /* Make an unnamed tag. */ 5055 /* Make an unnamed tag. */
4491 pfnote ((char *)NULL, TRUE, 5056 pfnote ((char *)NULL, TRUE,
4492 linebuffer->buffer, match, lineno, linecharno); 5057 lbp->buffer, match, lineno, linecharno);
4493 } 5058 }
4494 break; 5059 break;
4495 } 5060 }
4496 } 5061 }
4497 #endif /* ETAGS_REGEXPS */ 5062 #endif /* ETAGS_REGEXPS */
4498 5063
4499 return result; 5064 return result;
4500 } 5065 }
4501
4502 /*
4503 * Read a file, but do no processing. This is used to do regexp
4504 * matching on files that have no language defined.
4505 */
4506 void
4507 just_read_file (inf)
4508 FILE *inf;
4509 {
4510 lineno = 0;
4511 charno = 0;
4512
4513 while (!feof (inf))
4514 {
4515 ++lineno;
4516 linecharno = charno;
4517 charno += readline (&lb, inf);
4518 }
4519 }
4520
4521 5066
4522 /* 5067 /*
4523 * Return a pointer to a space of size strlen(cp)+1 allocated 5068 * Return a pointer to a space of size strlen(cp)+1 allocated
4524 * with xnew where the string CP has been copied. 5069 * with xnew where the string CP has been copied.
4525 */ 5070 */
4585 return sp; 5130 return sp;
4586 } while (*sp++); 5131 } while (*sp++);
4587 return NULL; 5132 return NULL;
4588 } 5133 }
4589 5134
5135 /* Skip spaces, return new pointer. */
5136 char *
5137 skip_spaces (cp)
5138 char *cp;
5139 {
5140 while (isspace (*cp)) /* isspace('\0')==FALSE */
5141 cp++;
5142 return cp;
5143 }
5144
5145 /* Skip non spaces, return new pointer. */
5146 char *
5147 skip_non_spaces (cp)
5148 char *cp;
5149 {
5150 while (!iswhite (*cp)) /* iswhite('\0')==TRUE */
5151 cp++;
5152 return cp;
5153 }
5154
4590 /* Print error message and exit. */ 5155 /* Print error message and exit. */
4591 void 5156 void
4592 fatal (s1, s2) 5157 fatal (s1, s2)
4593 char *s1, *s2; 5158 char *s1, *s2;
4594 { 5159 {
4605 } 5170 }
4606 5171
4607 void 5172 void
4608 suggest_asking_for_help () 5173 suggest_asking_for_help ()
4609 { 5174 {
4610 fprintf (stderr, "\tTry `%s --help' for a complete list of options.\n", 5175 fprintf (stderr, "\tTry `%s %s' for a complete list of options.\n",
4611 progname); 5176 progname,
5177 #ifdef LONG_OPTIONS
5178 "--help"
5179 #else
5180 "-h"
5181 #endif
5182 );
4612 exit (BAD); 5183 exit (BAD);
4613 } 5184 }
4614 5185
4615 /* Print error message. `s1' is printf control string, `s2' is arg for it. */ 5186 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
4616 void 5187 void
4642 /* Does the same work as the system V getcwd, but does not need to 5213 /* Does the same work as the system V getcwd, but does not need to
4643 guess the buffer size in advance. */ 5214 guess the buffer size in advance. */
4644 char * 5215 char *
4645 etags_getcwd () 5216 etags_getcwd ()
4646 { 5217 {
4647 #if defined (HAVE_GETCWD) || defined (WINDOWSNT) 5218 #ifdef HAVE_GETCWD
4648 int bufsize = 200; 5219 int bufsize = 200;
4649 char *path = xnew (bufsize, char); 5220 char *path = xnew (bufsize, char);
4650 5221
4651 while (getcwd (path, bufsize) == NULL) 5222 while (getcwd (path, bufsize) == NULL)
4652 { 5223 {
4655 bufsize *= 2; 5226 bufsize *= 2;
4656 free (path); 5227 free (path);
4657 path = xnew (bufsize, char); 5228 path = xnew (bufsize, char);
4658 } 5229 }
4659 5230
4660 #if WINDOWSNT 5231 canonicalize_filename (path);
4661 {
4662 /* Convert backslashes to slashes. */
4663 char *p;
4664 for (p = path; *p != '\0'; p++)
4665 if (*p == '\\')
4666 *p = '/';
4667 /* Canonicalize drive letter case. */
4668 if (islower (path[0]))
4669 path[0] = toupper (path[0]);
4670 }
4671 #endif
4672
4673 return path; 5232 return path;
4674 5233
4675 #else /* not HAVE_GETCWD */ 5234 #else /* not HAVE_GETCWD */
4676 #ifdef MSDOS 5235 #ifdef MSDOS
4677 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */ 5236 char *p, path[MAXPATHLEN + 1]; /* Fixed size is safe on MSDOS. */
4684 else 5243 else
4685 *p = lowcase (*p); 5244 *p = lowcase (*p);
4686 5245
4687 return strdup (path); 5246 return strdup (path);
4688 #else /* not MSDOS */ 5247 #else /* not MSDOS */
4689 struct linebuffer path; 5248 linebuffer path;
4690 FILE *pipe; 5249 FILE *pipe;
4691 5250
4692 initbuffer (&path); 5251 initbuffer (&path);
4693 pipe = (FILE *) popen ("pwd 2>/dev/null", "r"); 5252 pipe = (FILE *) popen ("pwd 2>/dev/null", "r");
4694 if (pipe == NULL || readline_internal (&path, pipe) == 0) 5253 if (pipe == NULL || readline_internal (&path, pipe) == 0)
4698 return path.buffer; 5257 return path.buffer;
4699 #endif /* not MSDOS */ 5258 #endif /* not MSDOS */
4700 #endif /* not HAVE_GETCWD */ 5259 #endif /* not HAVE_GETCWD */
4701 } 5260 }
4702 5261
4703 /* Return a newly allocated string containing the file name 5262 /* Return a newly allocated string containing the file name of FILE
4704 of FILE relative to the absolute directory DIR (which 5263 relative to the absolute directory DIR (which should end with a slash). */
4705 should end with a slash). */
4706 char * 5264 char *
4707 relative_filename (file, dir) 5265 relative_filename (file, dir)
4708 char *file, *dir; 5266 char *file, *dir;
4709 { 5267 {
4710 char *fp, *dp, *abs, *res; 5268 char *fp, *dp, *afn, *res;
4711 int i; 5269 int i;
4712 5270
4713 /* Find the common root of file and dir (with a trailing slash). */ 5271 /* Find the common root of file and dir (with a trailing slash). */
4714 abs = absolute_filename (file, cwd); 5272 afn = absolute_filename (file, cwd);
4715 fp = abs; 5273 fp = afn;
4716 dp = dir; 5274 dp = dir;
4717 while (*fp++ == *dp++) 5275 while (*fp++ == *dp++)
4718 continue; 5276 continue;
4719 fp--, dp--; /* back to the first differing char */ 5277 fp--, dp--; /* back to the first differing char */
4720 do { /* look at the equal chars until '/' */ 5278 #ifdef DOS_NT
4721 if (fp == abs) return abs; /* first char differs, give up */ 5279 if (fp == afn && afn[0] != '/') /* cannot build a relative name */
5280 return afn;
5281 #endif
5282 do /* look at the equal chars until '/' */
4722 fp--, dp--; 5283 fp--, dp--;
4723 } while (*fp != '/'); 5284 while (*fp != '/');
4724 5285
4725 /* Build a sequence of "../" strings for the resulting relative file name. */ 5286 /* Build a sequence of "../" strings for the resulting relative file name. */
4726 i = 0; 5287 i = 0;
4727 while ((dp = etags_strchr (dp + 1, '/')) != NULL) 5288 while ((dp = etags_strchr (dp + 1, '/')) != NULL)
4728 i += 1; 5289 i += 1;
4731 while (i-- > 0) 5292 while (i-- > 0)
4732 strcat (res, "../"); 5293 strcat (res, "../");
4733 5294
4734 /* Add the file name relative to the common root of file and dir. */ 5295 /* Add the file name relative to the common root of file and dir. */
4735 strcat (res, fp + 1); 5296 strcat (res, fp + 1);
4736 free (abs); 5297 free (afn);
4737 5298
4738 return res; 5299 return res;
4739 } 5300 }
4740 5301
4741 /* Return a newly allocated string containing the 5302 /* Return a newly allocated string containing the absolute file name
4742 absolute file name of FILE given CWD (which should 5303 of FILE given DIR (which should end with a slash). */
4743 end with a slash). */
4744 char * 5304 char *
4745 absolute_filename (file, cwd) 5305 absolute_filename (file, dir)
4746 char *file, *cwd; 5306 char *file, *dir;
4747 { 5307 {
4748 char *slashp, *cp, *res; 5308 char *slashp, *cp, *res;
4749 5309
4750 if (absolutefn (file)) 5310 if (filename_is_absolute (file))
4751 res = savestr (file); 5311 res = savestr (file);
4752 #ifdef DOS_NT 5312 #ifdef DOS_NT
4753 /* We don't support non-absolute file names with a drive 5313 /* We don't support non-absolute file names with a drive
4754 letter, like `d:NAME' (it's too much hassle). */ 5314 letter, like `d:NAME' (it's too much hassle). */
4755 else if (file[1] == ':') 5315 else if (file[1] == ':')
4756 fatal ("%s: relative file names with drive letters not supported", file); 5316 fatal ("%s: relative file names with drive letters not supported", file);
4757 #endif 5317 #endif
4758 else 5318 else
4759 res = concat (cwd, file, ""); 5319 res = concat (dir, file, "");
4760 5320
4761 /* Delete the "/dirname/.." and "/." substrings. */ 5321 /* Delete the "/dirname/.." and "/." substrings. */
4762 slashp = etags_strchr (res, '/'); 5322 slashp = etags_strchr (res, '/');
4763 while (slashp != NULL && slashp[0] != '\0') 5323 while (slashp != NULL && slashp[0] != '\0')
4764 { 5324 {
4768 && (slashp[3] == '/' || slashp[3] == '\0')) 5328 && (slashp[3] == '/' || slashp[3] == '\0'))
4769 { 5329 {
4770 cp = slashp; 5330 cp = slashp;
4771 do 5331 do
4772 cp--; 5332 cp--;
4773 while (cp >= res && !absolutefn (cp)); 5333 while (cp >= res && !filename_is_absolute (cp));
4774 if (cp < res) 5334 if (cp < res)
4775 cp = slashp; /* the absolute name begins with "/.." */ 5335 cp = slashp; /* the absolute name begins with "/.." */
4776 #ifdef DOS_NT 5336 #ifdef DOS_NT
4777 /* Under MSDOS and NT we get `d:/NAME' as absolute 5337 /* Under MSDOS and NT we get `d:/NAME' as absolute
4778 file name, so the luser could say `d:/../NAME'. 5338 file name, so the luser could say `d:/../NAME'.
4792 } 5352 }
4793 5353
4794 slashp = etags_strchr (slashp + 1, '/'); 5354 slashp = etags_strchr (slashp + 1, '/');
4795 } 5355 }
4796 5356
4797 #ifdef DOS_NT
4798 /* Canonicalize drive letter case. */
4799 if (res[0] && islower (res[0]))
4800 res[0] = toupper (res[0]);
4801 #endif
4802
4803 if (res[0] == '\0') 5357 if (res[0] == '\0')
4804 return savestr ("/"); 5358 return savestr ("/");
4805 else 5359 else
4806 return res; 5360 return res;
4807 } 5361 }
4808 5362
4809 /* Return a newly allocated string containing the absolute 5363 /* Return a newly allocated string containing the absolute
4810 file name of dir where FILE resides given CWD (which should 5364 file name of dir where FILE resides given DIR (which should
4811 end with a slash). */ 5365 end with a slash). */
4812 char * 5366 char *
4813 absolute_dirname (file, cwd) 5367 absolute_dirname (file, dir)
4814 char *file, *cwd; 5368 char *file, *dir;
4815 { 5369 {
4816 char *slashp, *res; 5370 char *slashp, *res;
4817 char save; 5371 char save;
4818 #ifdef DOS_NT 5372
4819 char *p; 5373 canonicalize_filename (file);
4820
4821 for (p = file; *p != '\0'; p++)
4822 if (*p == '\\')
4823 *p = '/';
4824 #endif
4825
4826 slashp = etags_strrchr (file, '/'); 5374 slashp = etags_strrchr (file, '/');
4827 if (slashp == NULL) 5375 if (slashp == NULL)
4828 return savestr (cwd); 5376 return savestr (dir);
4829 save = slashp[1]; 5377 save = slashp[1];
4830 slashp[1] = '\0'; 5378 slashp[1] = '\0';
4831 res = absolute_filename (file, cwd); 5379 res = absolute_filename (file, dir);
4832 slashp[1] = save; 5380 slashp[1] = save;
4833 5381
4834 return res; 5382 return res;
5383 }
5384
5385 /* Whether the argument string is an absolute file name. The argument
5386 string must have been canonicalized with canonicalize_filename. */
5387 bool
5388 filename_is_absolute (fn)
5389 char *fn;
5390 {
5391 return (fn[0] == '/'
5392 #ifdef DOS_NT
5393 || (isalpha(fn[0]) && fn[1] == ':' && fn[2] == '/')
5394 #endif
5395 );
5396 }
5397
5398 /* Translate backslashes into slashes. Works in place. */
5399 void
5400 canonicalize_filename (fn)
5401 register char *fn;
5402 {
5403 #ifdef DOS_NT
5404 /* Convert backslashes to slashes. */
5405 for (; *fn != '\0'; fn++)
5406 if (*fn == '\\')
5407 *fn = '/';
5408 /* Canonicalize drive letter case. */
5409 if (islower (path[0]))
5410 path[0] = toupper (path[0]);
5411 #else
5412 /* No action. */
5413 fn = NULL; /* shut up the compiler */
5414 #endif
4835 } 5415 }
4836 5416
4837 /* Increase the size of a linebuffer. */ 5417 /* Increase the size of a linebuffer. */
4838 void 5418 void
4839 grow_linebuffer (bufp, toksize) 5419 grow_linebuffer (lbp, toksize)
4840 struct linebuffer *bufp; 5420 linebuffer *lbp;
4841 int toksize; 5421 int toksize;
4842 { 5422 {
4843 while (bufp->size < toksize) 5423 while (lbp->size < toksize)
4844 bufp->size *= 2; 5424 lbp->size *= 2;
4845 bufp->buffer = (char *) xrealloc (bufp->buffer, bufp->size); 5425 lbp->buffer = xrnew (lbp->buffer, lbp->size, char);
4846 } 5426 }
4847 5427
4848 /* Like malloc but get fatal error if memory is exhausted. */ 5428 /* Like malloc but get fatal error if memory is exhausted. */
4849 long * 5429 long *
4850 xmalloc (size) 5430 xmalloc (size)