Mercurial > emacs
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 (®exbuf); | |
4755 while (readline_internal (®exbuf, 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 (®exbuf); | 4780 } |
4256 while (readline_internal (®exbuf, 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) |