home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / emacs / 2873 < prev    next >
Encoding:
Text File  |  1992-08-16  |  15.0 KB  |  572 lines

  1. Path: sparky!uunet!crdgw1!rpi!bu.edu!nntp-read!jbw
  2. From: jbw@bigbird.bu.edu (Joe Wells)
  3. Newsgroups: comp.emacs
  4. Subject: Re: How do I include symbols defined with #define in TAGS ?
  5. Message-ID: <JBW.92Aug16182725@bigbird.bu.edu>
  6. Date: 16 Aug 92 23:27:25 GMT
  7. References: <podi.713814809@chamundi.NSD.3Com.COM>
  8. Sender: news@bu.edu
  9. Distribution: comp.emacs
  10. Organization: Boston University Computer Science Department
  11. Lines: 558
  12. In-reply-to: podi@ESD.3Com.COM's message of 14 Aug 92 17:53:29 GMT
  13.  
  14. In article <podi.713814809@chamundi.NSD.3Com.COM> podi@ESD.3Com.COM (Podibanda Kuruppu) writes:
  15.  
  16.    Keywords: Symbols defined by #defines in TAGS
  17.  
  18.    I would greatly appreciate it if someone could tell me if I could
  19.    include symbols ( defined in .h files with #defines ) in a TAG file.
  20.  
  21. Enclosed below is an earlier article with my solution to this.
  22.  
  23. -- 
  24. Enjoy,
  25.  
  26. Joe Wells <jbw@cs.bu.edu>
  27. Member of the League for Programming Freedom --- send e-mail for details
  28.  
  29. ----------------------------------------------------------------------
  30. Date: Sat, 4 Apr 92 00:46:52 -0500
  31. From: jbw@bigbird.bu.edu (Joe Wells)
  32. Message-Id: <9204040546.AA15208@bigbird.bu.edu>
  33. To: bug-gnu-emacs@prep.ai.mit.edu
  34. Subject: numerous bug fixes for etags
  35.  
  36. Enclosed is a patch with numerous changes for etags.  The following are
  37. the changes and bugs fixed:
  38.  
  39. 1. Improvement: don't waste time calling strncmp (with "struct", "union",
  40.    "enum", "typedef") if the lengths are different.
  41.  
  42. 2. Bug: pfnote placed a NUL in the line buffer after the tag token which caused
  43.    things like `{' or `/*' to be ignored, thus severely screwing up the
  44.    parser.  Or it did something horrible, I don't remember for sure.
  45.  
  46. 3. Improvement: record defining occurrences of struct/union/enum tags.
  47.    This works even if combined with a typedef definition, for example:
  48.  
  49.      typedef struct XXX {
  50.        .....
  51.      } YYY;
  52.  
  53. 4. Bug: when a tag token was the last item on the line before the newline
  54.    character, garbage would be seen as the token.  This is because when a
  55.    NUL was seen in the buffer the buffer was replaced with the next line.
  56.  
  57. 5. Bug: tag tokens immediately followed by a `{' with no intervening space
  58.    were not recorded.  This was only a problem because of improvement 3
  59.    above.
  60.  
  61. 6. Bug: a newline in the middle of a comment zeroed the `number' variable.
  62.    (Just for good measure I made it not zero `number' in strings even when
  63.    the newline is not preceded by `\', in case someone wants to run etags
  64.    on illegal code :-)  (`number' is used only on lines that begin with
  65.    `#'.)
  66.  
  67. 7. Bug: handling of #define lines was severely broken.  I don't actually
  68.    remember what etags did with them, but it was really bad.  It now
  69.    records macro definitions.
  70.  
  71. 8. Bug: when a tag token was the last item on the line except for
  72.    whitespace, etags would replace the contents of the line buffer and
  73.    then later do various string comparisons and inspections against
  74.    garbage values instead of against the token.  Fixing this required
  75.    copying the token into a buffer.  (This is roughly the same as bug 4
  76.    above, but in a different function.)
  77.  
  78. 9. Bug: when a tag token was the last item on the line before the newline
  79.    (and under various other circumstances), etags would skip over the NUL
  80.    in the buffer and skip to the first non-whitespace character in the
  81.    buffer.
  82.  
  83. 10. Improvement (possibly bug fix): parse typedefs even when we aren't
  84.     going to print them out.  I seem to remember that this fixed some bug,
  85.     but I don't remember the specific case that would trigger the bug.
  86.  
  87. 11. An unfinished attempt to detect and record global variable
  88.     definitions.
  89.  
  90. The changes are to the 18.57 version of etags, but the only change in
  91. 18.58 to the C code handling is to initialize some variables when starting
  92. on a new file, so these changes are orthogonal.
  93.  
  94. -- 
  95. Enjoy,
  96.  
  97. Joe Wells <jbw@cs.bu.edu>
  98.  
  99. Member of the League for Programming Freedom --- send e-mail for details
  100.  
  101. ----------------------------------------------------------------------
  102. --- etags.c-dist    Tue Jan  8 14:08:38 1991
  103. +++ etags.c    Sat Apr  4 00:41:22 1992
  104. @@ -62,7 +62,10 @@
  105.  
  106.  /* cause token checking for typedef, struct, union, enum to distinguish
  107.     keywords from identifier-prefixes (e.g. struct vs struct_tag).  */
  108. -#define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len))))
  109. +#define istoken(s, t, len) \
  110. +  (((len) == (sizeof (t) -1)) && \
  111. +   ((strncmp(s, t, len)) == 0) && \
  112. +   (endtoken(*((s)+(len)))))
  113.  
  114.  struct    nd_st {            /* sorting structure            */
  115.      char    *name;            /* function or type name    */
  116. @@ -505,6 +508,7 @@
  117.  {
  118.    register char *fp;
  119.    register NODE *np;
  120. +  char save;
  121.    char *altname;
  122.    char tem[51];
  123.  
  124. @@ -538,6 +542,7 @@
  125.    np->left = np->right = 0;
  126.    if (eflag)
  127.      {
  128. +      save = linestart[linelen];
  129.        linestart[linelen] = 0;
  130.      }
  131.    else if (xflag == 0)
  132. @@ -546,6 +551,7 @@
  133.        linestart = tem;
  134.      }
  135.    np->pat = savestr (linestart);
  136. +  linestart[linelen] = save;
  137.    if (head == NULL)
  138.      head = np;
  139.    else
  140. @@ -725,6 +731,17 @@
  141.    number = 0; \
  142.  }
  143.  
  144. +/* These two are part of a never-finished attempt to record global */
  145. +/* variable definitions.  This is nearly impossible in C without the full */
  146. +/* power of a C compiler due to C's stupid grammar. */
  147. +logical infunc;
  148. +int idents_in_decl;
  149. +
  150. +/* indicates whether the next token (if any) is the tag corresponding to */
  151. +/* `struct', `union', or `enum' */
  152. +logical next_token_is_tag;
  153. +
  154. +
  155.  C_entries ()
  156.  {
  157.    register int c;
  158. @@ -731,6 +748,15 @@
  159.    register char *token, *tp, *lp;
  160.    logical incomm, inquote, inchar, midtoken;
  161.    int level;
  162. +
  163. +  /* there are certain things that must be done when the end of line is */
  164. +  /* encountered, but they must be delayed until after other things are */
  165. +  /* done. */
  166. +  logical new_line_flag;
  167. +
  168. +  /* same as new_line_flag for left braces. */
  169. +  logical left_brace_flag;
  170. +
  171.    char tok[BUFSIZ];
  172.  
  173.    lineno = 0;
  174. @@ -739,17 +765,22 @@
  175.    *lp = 0;
  176.  
  177.    number = 0;
  178. -  gotone = midtoken = inquote = inchar = incomm = FALSE;
  179. +  gotone = midtoken = inquote = inchar = incomm = infunc = FALSE;
  180. +  new_line_flag = FALSE;
  181. +  left_brace_flag = FALSE;
  182.    level = 0;
  183. +  idents_in_decl = 0;
  184. +  next_token_is_tag = FALSE;
  185.  
  186.    while (!feof (inf))
  187.      {
  188.        c = *lp++;
  189.        if (c == 0)
  190. -    {
  191. -      CNL;
  192. -      gotone = FALSE;
  193. -    }
  194. +    new_line_flag = TRUE;
  195. +#ifdef DEBUG
  196. +      if (next_token_is_tag)
  197. +    fprintf (stderr, "E: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
  198. +#endif /* DEBUG */
  199.        if (c == '\\')
  200.      {
  201.        c = *lp++;
  202. @@ -756,15 +787,18 @@
  203.        if (c == 0)
  204.          CNL_SAVE_NUMBER;
  205.        c = ' ';
  206. +      /* is this correct?  I thought escaped newlines disappeared even */
  207. +      /* before the token breaker got to see things. */ 
  208.      } 
  209.        else if (incomm)
  210.      {
  211. +      new_line_flag = FALSE;
  212.        if (c == '*')
  213.          {
  214.            while ((c = *lp++) == '*')
  215.          continue;
  216.            if (c == 0)
  217. -        CNL;
  218. +        CNL_SAVE_NUMBER;
  219.            if (c == '/')
  220.          incomm = FALSE;
  221.          }
  222. @@ -771,6 +805,7 @@
  223.      }
  224.        else if (inquote)
  225.      {
  226. +      new_line_flag = FALSE;
  227.        /*
  228.        * Too dumb to know about \" not being magic, but
  229.        * they usually occur in pairs anyway.
  230. @@ -781,6 +816,7 @@
  231.      }
  232.        else if (inchar)
  233.      {
  234. +      new_line_flag = FALSE;
  235.        if (c == '\'')
  236.          inchar = FALSE;
  237.        continue;
  238. @@ -809,8 +845,8 @@
  239.          {
  240.            tydef=middle;
  241.          }
  242. -      level++;
  243. -      continue;
  244. +      left_brace_flag = TRUE;
  245. +      break;
  246.      case '}':
  247.        if (lp == lb.buffer + 1)
  248.          level = 0;    /* reset */
  249. @@ -820,8 +856,17 @@
  250.          {
  251.            tydef=end;
  252.          }
  253. +      if (level == 0 && infunc)
  254. +        {
  255. +          idents_in_decl = 0;
  256. +          infunc = FALSE;
  257. +        }
  258.        continue;
  259.      }
  260. +#ifdef DEBUG
  261. +      if (next_token_is_tag)
  262. +    fprintf (stderr, "D: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
  263. +#endif /* DEBUG */
  264.        if (!level && !inquote && !incomm && gotone == FALSE)
  265.      {
  266.        if (midtoken)
  267. @@ -852,6 +897,11 @@
  268.                     tp-token+1);
  269.                tok[tp-token+1] = 0;
  270.                pfnote(tok, f, lb1.buffer, endpos, line, linestart);
  271. +#ifdef DEBUG
  272. +              fprintf (stderr,
  273. +                 "f: %d, infunc %d, tok: %s\nlb1.buffer: %s\n",
  274. +                   f, infunc, tok, lb1.buffer);
  275. +#endif /* DEBUG */
  276.              }
  277.                else
  278.              {
  279. @@ -858,8 +908,15 @@
  280.                strncpy (tok, token, tp-token+1);
  281.                tok[tp-token+1] = 0;
  282.                pfnote(tok, f, lb.buffer, endpos, line, linestart);
  283. +#ifdef DEBUG
  284. +              fprintf (stderr,
  285. +                     "f: %d, infunc %d, tok: %s\nlb.buffer:  %s\n",
  286. +                   f, infunc, tok, lb.buffer);
  287. +#endif /* DEBUG */
  288.              }
  289.                gotone = f;    /* function */
  290. +              if (f)
  291. +            infunc = TRUE;
  292.              }
  293.            midtoken = FALSE;
  294.            token = lp - 1;
  295. @@ -873,8 +930,32 @@
  296.            midtoken = TRUE;
  297.          }
  298.      }
  299. +#ifdef DEBUG
  300. +      if (next_token_is_tag)
  301. +    fprintf (stderr, "F: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
  302. +#endif /* DEBUG */
  303. +      if (left_brace_flag)
  304. +    {
  305. +      left_brace_flag = FALSE;
  306. +      next_token_is_tag = FALSE;
  307. +      level++;
  308. +    }
  309. +      if (new_line_flag)
  310. +    {
  311. +      new_line_flag = FALSE;
  312. +      number = 0;
  313. +      gotone = FALSE;
  314. +    }
  315. +      if (lp > lb.buffer && lp[-1] == 0)
  316. +    CNL_SAVE_NUMBER;
  317.        if (c == ';'  &&  tydef==end)    /* clean with typedefs */
  318.      tydef=none;
  319. +      if (c == ';' && level == 0 && !infunc)
  320. +    idents_in_decl = 0;
  321. +#ifdef DEBUG
  322. +      if (next_token_is_tag)
  323. +    fprintf (stderr, "G: c: [%c], lp[-2]: [%c]\n", c, lp[-2]);
  324. +#endif /* DEBUG */
  325.      }
  326.  }
  327.  
  328. @@ -891,70 +972,176 @@
  329.    reg char *lp = *lpp;
  330.    reg char c;
  331.    static logical next_token_is_func;
  332. +
  333. +  /* indicates that the next token will be a macro defined with #define */
  334. +  static logical next_token_is_macro;
  335. +
  336.    logical firsttok;    /* T if have seen first token in ()'s */
  337. -  int bad, win;
  338. +  int bad = FALSE, win = FALSE;
  339. +  int length = (lp - 1) - token;
  340. +  
  341. +  /* used to keep a copy of the token when we have to fill the line buffer */
  342. +  /* with the contents of the next line */
  343. +  static char *tok_buffer = NULL;
  344. +  static long tok_buffer_size = 0;
  345.  
  346.    *f = 1;            /* a function */
  347.    c = lp[-1];
  348. -  bad = FALSE;
  349.    if (!number)
  350.      {        /* space is not allowed in macro defs    */
  351. -      while (iswhite(c))
  352. +      while ((c == 0) || iswhite(c))
  353.      {
  354. -      c = *lp++;
  355. -      if (c == 0)
  356. +#ifdef DEBUG
  357. +      if (next_token_is_tag)
  358. +        fprintf (stderr, "C: token: %s, c: [%c], lp - token: %d\n",
  359. +             token, c, lp - token);
  360. +#endif /* DEBUG */
  361. +      while (c == 0)
  362.          {
  363.            if (feof (inf))
  364. -        break;
  365. +        goto break_while_1;
  366. +          if (token != tok_buffer)
  367. +        {
  368. +          if (length + 1 > tok_buffer_size)
  369. +            if (tok_buffer_size == 0)
  370. +              {
  371. +            tok_buffer_size = length + 1;
  372. +            tok_buffer = (char *) xmalloc (tok_buffer_size);
  373. +              }
  374. +            else
  375. +              {
  376. +            tok_buffer_size = length + 1;
  377. +            tok_buffer =
  378. +              (char *) xrealloc (tok_buffer, tok_buffer_size);
  379. +              }
  380. +          strncpy (tok_buffer, token, length);
  381. +          tok_buffer[length] = '\0';
  382. +          token = tok_buffer;
  383. +        }
  384.            CNL;
  385. +          c = *lp++;
  386.          }
  387. +      while ((c != 0) && iswhite(c))
  388. +        c = *lp++;
  389.      }
  390. -      /* the following tries to make it so that a #define a b(c)    */
  391. -      /* doesn't count as a define of b.                */
  392. +    break_while_1:
  393. +      ;
  394.      }
  395.    else
  396.      {
  397. +      /* the following tries to make it so that a #define a b(c)    */
  398. +      /* doesn't count as a define of b.                */
  399.        number++;
  400. -      if (number >= 4  || (number==2 && strncmp (token, "define", 6)))
  401. -    {
  402. -      gotone = TRUE;
  403. -    badone:
  404. +#ifdef DEBUG
  405. +      fprintf (stderr, "number: %d, n_t_i_m: %d, token: %s\n",
  406. +           number, next_token_is_macro, token);
  407. +#endif /* DEBUG */
  408. +      if (number == 2 && strncmp (token, "define", 6) == 0)
  409. +    next_token_is_macro = TRUE;
  410. +      else if (number == 3 && next_token_is_macro)
  411. +    {
  412. +      next_token_is_macro = FALSE;
  413. +      while ((c != 0) && iswhite(c))
  414. +        {
  415. +#ifdef DEBUG
  416. +          fprintf (stderr, "c: %c, %d\n", c, c);
  417. +#endif /* DEBUG */
  418. +          c = *lp++;
  419. +        }
  420. +#ifdef DEBUG
  421. +      fprintf (stderr, "c: %c, %d\n", c, c);
  422. +#endif /* DEBUG */
  423. +      if (c == 0)        /* ignore plain "#define FLAG" */
  424.        bad = TRUE;
  425. +      else
  426. +        win = TRUE;
  427. +      /* speed up skipping the rest of this line */
  428. +      gotone = TRUE;
  429. +      /* never treat a macro as a function, because it doesn't have a */
  430. +      /* function body, which is what "f" really stands for (now). */
  431. +      *f = FALSE;
  432.        goto ret;
  433.      }
  434. +      else
  435. +    /* speed up skipping the rest of this line */
  436. +    gotone = TRUE;
  437. +      goto badone;
  438.      }
  439. +  idents_in_decl ++;
  440. +#ifdef DEBUG
  441. +  fprintf (stderr,
  442. +       "A: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n",
  443. +       idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c,
  444. +       length + 5, token);
  445. +#endif /* DEBUG */
  446.    /* check for the typedef cases        */
  447. -  if (tflag && istoken(token, "typedef", 7))
  448. +  if (istoken (token, "typedef", length))
  449.      {
  450.        tydef=begin;
  451.        goto badone;
  452.      }
  453. -  if (tydef==begin && (istoken(token, "struct", 6) ||
  454. -               istoken(token, "union", 5) || istoken(token, "enum", 4)))
  455. -  {
  456. +#ifdef DEBUG
  457. +  fprintf (stderr, "D\n");
  458. +#endif /* DEBUG */
  459. +  if (istoken (token, "struct", length) ||
  460. +      istoken (token, "union", length) ||
  461. +      istoken (token, "enum", length))
  462. +    {
  463. +      next_token_is_tag = 1;
  464. +#ifdef DEBUG
  465. +      fprintf (stderr, "A: token: %s\n", token);
  466. +#endif /* DEBUG */
  467. +      if (tydef == begin)
  468.      tydef=tag_ok;      
  469.      goto badone;
  470.    }
  471. -  if (tydef==tag_ok)
  472. +  else if (next_token_is_tag)
  473.      {
  474. +#ifdef DEBUG
  475. +      fprintf (stderr, "B: token: %s, c: [%c]\n", token, c);
  476. +#endif /* DEBUG */
  477. +      if (tydef==tag_ok)
  478.        tydef=middle;
  479. -      goto badone;
  480. +      next_token_is_tag = 0;
  481. +      *f = 0;
  482. +      /* only notice when a tag is being defined, not when it is merely */
  483. +      /* being used. */
  484. +      if (c == '{')
  485. +    win = TRUE;
  486. +      else
  487. +    bad = TRUE;
  488. +      goto ret;
  489.      }
  490. +#ifdef DEBUG
  491. +  fprintf (stderr, "E\n");
  492. +#endif /* DEBUG */
  493.    if (tydef==begin)        /* e.g. typedef ->int<- */
  494.      {
  495.        tydef=end;
  496.        goto badone;
  497.      }
  498. +#ifdef DEBUG
  499. +  fprintf (stderr, "F\n");
  500. +#endif /* DEBUG */
  501.    if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */
  502.      {
  503.        tydef=end;
  504.      }
  505. +#ifdef DEBUG
  506. +  fprintf (stderr, "G\n");
  507. +#endif /* DEBUG */
  508.    if (tydef==end)
  509.      {
  510.        *f = 0;
  511. -      win = 1;
  512. +#ifdef DEBUG
  513. +      fprintf (stderr, "C token: %s\n", token);
  514. +#endif /* DEBUG */
  515. +      win = tflag;
  516.        goto ret;
  517.      }
  518. +#ifdef DEBUG
  519. +  fprintf (stderr, "H\n");
  520. +#endif /* DEBUG */
  521.    /* Detect GNUmacs's function-defining macros. */
  522.    if (!number && !strncmp (token, "DEF", 3))
  523.       
  524. @@ -962,6 +1149,9 @@
  525.        next_token_is_func = 1;
  526.        goto badone;
  527.      }
  528. +#ifdef DEBUG
  529. +  fprintf (stderr, "I\n");
  530. +#endif /* DEBUG */
  531.    if (next_token_is_func)
  532.      {
  533.        next_token_is_func = 0;
  534. @@ -968,9 +1158,15 @@
  535.        win = 1;
  536.        goto ret;
  537.      }
  538. +#ifdef DEBUG
  539. +  fprintf (stderr, "J\n");
  540. +#endif /* DEBUG */
  541.    if (c != '(')
  542.      goto badone;
  543.    firsttok = FALSE;
  544. +#ifdef DEBUG
  545. +  fprintf (stderr, "K\n");
  546. +#endif /* DEBUG */
  547.    while ((c = *lp++) != ')')
  548.      {
  549.        if (c == 0)
  550. @@ -999,9 +1195,20 @@
  551.      }
  552.      }
  553.    win = isgood (c);
  554. +  
  555.  ret:
  556. +#ifdef DEBUG
  557. +  fprintf (stderr,
  558. +       "B: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n",
  559. +       idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c,
  560. +       length + 5, token);
  561. +#endif /* DEBUG */
  562.    *lpp = lp - 1;
  563.    return !bad && win;
  564. +
  565. + badone:
  566. +  bad = TRUE;
  567. +  goto ret;
  568.  }
  569.  
  570.  getline (atchar)
  571. ----------------------------------------------------------------------
  572.