1 From jbw@bigbird.bu.edu Tue Aug 18 08:07:53 1992
2 From: jbw@bigbird.bu.edu (Joe Wells)
4 Subject: Re: How do I include symbols defined with #define in TAGS ?
5 Date: 16 Aug 92 23:27:25 GMT
6 Distribution: comp.emacs
7 Organization: Boston University Computer Science Department
8 In-reply-to: podi@ESD.3Com.COM's message of 14 Aug 92 17:53:29 GMT
10 In article <podi.713814809@chamundi.NSD.3Com.COM> podi@ESD.3Com.COM (Podibanda Kuruppu) writes:
12 Keywords: Symbols defined by #defines in TAGS
14 I would greatly appreciate it if someone could tell me if I could
15 include symbols ( defined in .h files with #defines ) in a TAG file.
17 Enclosed below is an earlier article with my solution to this.
22 Joe Wells <jbw@cs.bu.edu>
23 Member of the League for Programming Freedom --- send e-mail for details
25 ----------------------------------------------------------------------
26 Date: Sat, 4 Apr 92 00:46:52 -0500
27 From: jbw@bigbird.bu.edu (Joe Wells)
28 Message-Id: <9204040546.AA15208@bigbird.bu.edu>
29 To: bug-gnu-emacs@prep.ai.mit.edu
30 Subject: numerous bug fixes for etags
32 Enclosed is a patch with numerous changes for etags. The following are
33 the changes and bugs fixed:
35 1. Improvement: don't waste time calling strncmp (with "struct", "union",
36 "enum", "typedef") if the lengths are different.
38 2. Bug: pfnote placed a NUL in the line buffer after the tag token which caused
39 things like `{' or `/*' to be ignored, thus severely screwing up the
40 parser. Or it did something horrible, I don't remember for sure.
42 3. Improvement: record defining occurrences of struct/union/enum tags.
43 This works even if combined with a typedef definition, for example:
49 4. Bug: when a tag token was the last item on the line before the newline
50 character, garbage would be seen as the token. This is because when a
51 NUL was seen in the buffer the buffer was replaced with the next line.
53 5. Bug: tag tokens immediately followed by a `{' with no intervening space
54 were not recorded. This was only a problem because of improvement 3
57 6. Bug: a newline in the middle of a comment zeroed the `number' variable.
58 (Just for good measure I made it not zero `number' in strings even when
59 the newline is not preceded by `\', in case someone wants to run etags
60 on illegal code :-) (`number' is used only on lines that begin with
63 7. Bug: handling of #define lines was severely broken. I don't actually
64 remember what etags did with them, but it was really bad. It now
65 records macro definitions.
67 8. Bug: when a tag token was the last item on the line except for
68 whitespace, etags would replace the contents of the line buffer and
69 then later do various string comparisons and inspections against
70 garbage values instead of against the token. Fixing this required
71 copying the token into a buffer. (This is roughly the same as bug 4
72 above, but in a different function.)
74 9. Bug: when a tag token was the last item on the line before the newline
75 (and under various other circumstances), etags would skip over the NUL
76 in the buffer and skip to the first non-whitespace character in the
79 10. Improvement (possibly bug fix): parse typedefs even when we aren't
80 going to print them out. I seem to remember that this fixed some bug,
81 but I don't remember the specific case that would trigger the bug.
83 11. An unfinished attempt to detect and record global variable
86 The changes are to the 18.57 version of etags, but the only change in
87 18.58 to the C code handling is to initialize some variables when starting
88 on a new file, so these changes are orthogonal.
93 Joe Wells <jbw@cs.bu.edu>
95 Member of the League for Programming Freedom --- send e-mail for details
97 ----------------------------------------------------------------------
98 --- etags.c-dist Tue Jan 8 14:08:38 1991
99 +++ etags.c Sat Apr 4 00:41:22 1992
102 /* cause token checking for typedef, struct, union, enum to distinguish
103 keywords from identifier-prefixes (e.g. struct vs struct_tag). */
104 -#define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len))))
105 +#define istoken(s, t, len) \
106 + (((len) == (sizeof (t) -1)) && \
107 + ((strncmp(s, t, len)) == 0) && \
108 + (endtoken(*((s)+(len)))))
110 struct nd_st { /* sorting structure */
111 char *name; /* function or type name */
121 np->left = np->right = 0;
124 + save = linestart[linelen];
125 linestart[linelen] = 0;
131 np->pat = savestr (linestart);
132 + linestart[linelen] = save;
140 +/* These two are part of a never-finished attempt to record global */
141 +/* variable definitions. This is nearly impossible in C without the full */
142 +/* power of a C compiler due to C's stupid grammar. */
146 +/* indicates whether the next token (if any) is the tag corresponding to */
147 +/* `struct', `union', or `enum' */
148 +logical next_token_is_tag;
155 register char *token, *tp, *lp;
156 logical incomm, inquote, inchar, midtoken;
159 + /* there are certain things that must be done when the end of line is */
160 + /* encountered, but they must be delayed until after other things are */
162 + logical new_line_flag;
164 + /* same as new_line_flag for left braces. */
165 + logical left_brace_flag;
170 @@ -739,17 +765,22 @@
174 - gotone = midtoken = inquote = inchar = incomm = FALSE;
175 + gotone = midtoken = inquote = inchar = incomm = infunc = FALSE;
176 + new_line_flag = FALSE;
177 + left_brace_flag = FALSE;
179 + idents_in_decl = 0;
180 + next_token_is_tag = FALSE;
190 + new_line_flag = TRUE;
192 + if (next_token_is_tag)
193 + fprintf (stderr, "E: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
198 @@ -756,15 +787,18 @@
202 + /* is this correct? I thought escaped newlines disappeared even */
203 + /* before the token breaker got to see things. */
207 + new_line_flag = FALSE;
210 while ((c = *lp++) == '*')
222 + new_line_flag = FALSE;
224 * Too dumb to know about \" not being magic, but
225 * they usually occur in pairs anyway.
230 + new_line_flag = FALSE;
240 + left_brace_flag = TRUE;
243 if (lp == lb.buffer + 1)
244 level = 0; /* reset */
249 + if (level == 0 && infunc)
251 + idents_in_decl = 0;
257 + if (next_token_is_tag)
258 + fprintf (stderr, "D: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
260 if (!level && !inquote && !incomm && gotone == FALSE)
266 pfnote(tok, f, lb1.buffer, endpos, line, linestart);
269 + "f: %d, infunc %d, tok: %s\nlb1.buffer: %s\n",
270 + f, infunc, tok, lb1.buffer);
276 strncpy (tok, token, tp-token+1);
278 pfnote(tok, f, lb.buffer, endpos, line, linestart);
281 + "f: %d, infunc %d, tok: %s\nlb.buffer: %s\n",
282 + f, infunc, tok, lb.buffer);
285 gotone = f; /* function */
296 + if (next_token_is_tag)
297 + fprintf (stderr, "F: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
299 + if (left_brace_flag)
301 + left_brace_flag = FALSE;
302 + next_token_is_tag = FALSE;
307 + new_line_flag = FALSE;
311 + if (lp > lb.buffer && lp[-1] == 0)
313 if (c == ';' && tydef==end) /* clean with typedefs */
315 + if (c == ';' && level == 0 && !infunc)
316 + idents_in_decl = 0;
318 + if (next_token_is_tag)
319 + fprintf (stderr, "G: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
324 @@ -891,70 +972,176 @@
327 static logical next_token_is_func;
329 + /* indicates that the next token will be a macro defined with #define */
330 + static logical next_token_is_macro;
332 logical firsttok; /* T if have seen first token in ()'s */
334 + int bad = FALSE, win = FALSE;
335 + int length = (lp - 1) - token;
337 + /* used to keep a copy of the token when we have to fill the line buffer */
338 + /* with the contents of the next line */
339 + static char *tok_buffer = NULL;
340 + static long tok_buffer_size = 0;
342 *f = 1; /* a function */
346 { /* space is not allowed in macro defs */
348 + while ((c == 0) || iswhite(c))
353 + if (next_token_is_tag)
354 + fprintf (stderr, "C: token: %s, c: [%c], lp - token: %d\n",
355 + token, c, lp - token);
361 + goto break_while_1;
362 + if (token != tok_buffer)
364 + if (length + 1 > tok_buffer_size)
365 + if (tok_buffer_size == 0)
367 + tok_buffer_size = length + 1;
368 + tok_buffer = (char *) xmalloc (tok_buffer_size);
372 + tok_buffer_size = length + 1;
374 + (char *) xrealloc (tok_buffer, tok_buffer_size);
376 + strncpy (tok_buffer, token, length);
377 + tok_buffer[length] = '\0';
378 + token = tok_buffer;
383 + while ((c != 0) && iswhite(c))
386 - /* the following tries to make it so that a #define a b(c) */
387 - /* doesn't count as a define of b. */
393 + /* the following tries to make it so that a #define a b(c) */
394 + /* doesn't count as a define of b. */
396 - if (number >= 4 || (number==2 && strncmp (token, "define", 6)))
401 + fprintf (stderr, "number: %d, n_t_i_m: %d, token: %s\n",
402 + number, next_token_is_macro, token);
404 + if (number == 2 && strncmp (token, "define", 6) == 0)
405 + next_token_is_macro = TRUE;
406 + else if (number == 3 && next_token_is_macro)
408 + next_token_is_macro = FALSE;
409 + while ((c != 0) && iswhite(c))
412 + fprintf (stderr, "c: %c, %d\n", c, c);
417 + fprintf (stderr, "c: %c, %d\n", c, c);
419 + if (c == 0) /* ignore plain "#define FLAG" */
423 + /* speed up skipping the rest of this line */
425 + /* never treat a macro as a function, because it doesn't have a */
426 + /* function body, which is what "f" really stands for (now). */
431 + /* speed up skipping the rest of this line */
438 + "A: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n",
439 + idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c,
440 + length + 5, token);
442 /* check for the typedef cases */
443 - if (tflag && istoken(token, "typedef", 7))
444 + if (istoken (token, "typedef", length))
449 - if (tydef==begin && (istoken(token, "struct", 6) ||
450 - istoken(token, "union", 5) || istoken(token, "enum", 4)))
453 + fprintf (stderr, "D\n");
455 + if (istoken (token, "struct", length) ||
456 + istoken (token, "union", length) ||
457 + istoken (token, "enum", length))
459 + next_token_is_tag = 1;
461 + fprintf (stderr, "A: token: %s\n", token);
463 + if (tydef == begin)
468 + else if (next_token_is_tag)
471 + fprintf (stderr, "B: token: %s, c: [%c]\n", token, c);
476 + next_token_is_tag = 0;
478 + /* only notice when a tag is being defined, not when it is merely */
487 + fprintf (stderr, "E\n");
489 if (tydef==begin) /* e.g. typedef ->int<- */
495 + fprintf (stderr, "F\n");
497 if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */
502 + fprintf (stderr, "G\n");
509 + fprintf (stderr, "C token: %s\n", token);
515 + fprintf (stderr, "H\n");
517 /* Detect GNUmacs's function-defining macros. */
518 if (!number && !strncmp (token, "DEF", 3))
521 next_token_is_func = 1;
525 + fprintf (stderr, "I\n");
527 if (next_token_is_func)
529 next_token_is_func = 0;
530 @@ -968,9 +1158,15 @@
535 + fprintf (stderr, "J\n");
541 + fprintf (stderr, "K\n");
543 while ((c = *lp++) != ')')
546 @@ -999,9 +1195,20 @@
554 + "B: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n",
555 + idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c,
556 + length + 5, token);
567 ----------------------------------------------------------------------