[comp.emacs] etags should optionally tag all macros

brennan@rtp.dg.com (Dave Brennan) (05/31/90)

     I've been writing some code that uses a lot macros to hide structure
information from modules that need to know about specific data structures,
and often need to find the macro definitions to make additions or changes.

     But,  alas, etags only generates tags for macros with paramaters.
I just couldn't live with this behavior, so I had to make some changes 
to etags to make this work.  I putting the patch here in the hope other
people will find it useful.  To make etags generate tag entries for all
macros just use the "-d" flag when running it.

     I'd also be interested in any other etags enhancements.  It'd be easy
to make etags recognize other tags (like struct, union and enum tags) but
macro tags are the only ones I feel like I have time to change right now.
I just use typedefs for my structs, unions, and enums - a case which is
already handled.

     Anyhow, here's the patch:

*** etags.c.dist	Wed May 30 18:16:23 1990
--- etags.c	Wed May 30 19:51:12 1990
***************
*** 185,188 ****
--- 185,189 ----
  int	file_num = 0;		/* current file number			*/
  int	aflag = 0;		/* -a: append to tags */
+ int	dflag = 0;		/* -d: create tags for #define macros */
  int	tflag = 0;		/* -t: create tags for typedefs */
  int	uflag = 0;		/* -u: update tags */
***************
*** 291,294 ****
--- 292,298 ----
  	      aflag++;
  	      break;
+ 	    case 'd':
+ 	      dflag++;
+ 	      break;
  	    case 'e':
  	      eflag++;
***************
*** 346,350 ****
        fprintf (stderr, "Usage: %s [-aetwvx] [-f outfile] file ...\n", progname);
  #else
!       fprintf (stderr, "Usage: %s [-BFaetuwvx] [-f outfile] file ...\n", progname);
  #endif
        exit(BAD);
--- 350,354 ----
        fprintf (stderr, "Usage: %s [-aetwvx] [-f outfile] file ...\n", progname);
  #else
!       fprintf (stderr, "Usage: %s [-BFadetuwvx] [-f outfile] file ...\n", progname);
  #endif
        exit(BAD);
***************
*** 861,865 ****
  	  continue;
  	case '#':
! 	  if (lp == lb.buffer + 1)
  	    number = 1;
  	  continue;
--- 865,869 ----
  	  continue;
  	case '#':
! 	  if (lp == lb.buffer + 1)     /* remember if the # is in column 1 */
  	    number = 1;
  	  continue;
***************
*** 950,954 ****
    reg char *lp = *lpp;
    reg char c;
!   static logical next_token_is_func;
    logical firsttok;	/* T if have seen first token in ()'s */
    int bad, win = 0;
--- 954,958 ----
    reg char *lp = *lpp;
    reg char c;
!   static logical next_token_is_func = 0, next_token_is_define = 0;
    logical firsttok;	/* T if have seen first token in ()'s */
    int bad, win = 0;
***************
*** 970,974 ****
  	}
        /* the following tries to make it so that a #define a b(c)	*/
!       /* doesn't count as a define of b.				*/
      }
    else
--- 974,982 ----
  	}
        /* the following tries to make it so that a #define a b(c)	*/
!       /* doesn't count as a define of b.  The token is bad if it	*/
!       /* is `define' and the first one after the #, or if it is	*/
!       /* not the second token on the line.  However, if dflag is	*/
!       /* set, then the macro is valid no matter what.			*/
! 
      }
    else
***************
*** 975,978 ****
--- 983,998 ----
      {
        number++;
+       if (number==2 && !strncmp (token, "define", 6) && dflag)
+ 	{
+ 	  next_token_is_define = 1;
+ 	  goto badone;
+ 	}
+       if (next_token_is_define)
+ 	{
+ 	  next_token_is_define = 0;
+ 	  *f = 0;
+ 	  win = 1;
+ 	  goto ret;
+ 	}
        if (number >= 4  || (number==2 && strncmp (token, "define", 6)))
  	{
***************
*** 1017,1021 ****
    /* Detect GNUmacs's function-defining macros. */
    if (!number && !strncmp (token, "DEF", 3))
- 	 
      {
        next_token_is_func = 1;
--- 1037,1040 ----

                                          |\
Dave Brennan                              | \____oo_     brennan@rtp.dg.com
=========================================((__|  /___>    ...rti!dg-rtp!brennan
User Interfaces, Data General                | //        daveb@rpitsmts.bitnet
Research Triangle Park, NC                   |//         Phone: (919) 248-6330

brennan@rtp.dg.com (Dave Brennan) (05/31/90)

In article <BRENNAN.90May30201623@bach.rtp.dg.com> brennan@rtp.dg.com (Dave Brennan) writes:

     I've been writing some code that uses a lot macros to hide structure
information from modules that need to know about specific data structures,
                         ^^^^^^^^^  
and often need to find the macro definitions to make additions or changes.


     Ooops!  I meant "that don't need".

I've got to keep saying to myself "proofread, Proofread, PROOFREAD!!!"
                                          |\
Dave Brennan                              | \____oo_     brennan@rtp.dg.com
=========================================((__|  /___>    ...rti!dg-rtp!brennan
User Interfaces, Data General                | //        daveb@rpitsmts.bitnet
Research Triangle Park, NC                   |//         Phone: (919) 248-6330

skip@skipnyc (Skip Gilbrech) (06/03/90)

In article <BRENNAN.90May30201623@bach.rtp.dg.com> brennan@rtp.dg.com (Dave Brennan) writes:
>     I've been writing some code that uses a lot macros to hide structure
>information from modules that need to know about specific data structures,
>and often need to find the macro definitions to make additions or changes.
>
>     But,  alas, etags only generates tags for macros with paramaters.
>I just couldn't live with this behavior, so I had to make some changes 
>to etags to make this work.  I putting the patch here in the hope other
>people will find it useful.  To make etags generate tag entries for all
>macros just use the "-d" flag when running it.
>
>     I'd also be interested in any other etags enhancements.  It'd be easy
>to make etags recognize other tags (like struct, union and enum tags) but
>macro tags are the only ones I feel like I have time to change right now.
>I just use typedefs for my structs, unions, and enums - a case which is
>already handled.

Dave inspired me to post a change I made a while ago that I've found useful.
It adds an `-L filename' flag to accept a list of files to process from
another file.  `Filename' can be `-' in which case the list is read from the
standard input.  This is useful for avoiding command-line size limits on
some systems.

The patch below includes Dave's, and is based on the etags.c distributed
with emacs 18.54.

*** etags.c-dist	Thu Jun 23 08:45:37 1988
--- etags.c	Sat Jun  2 20:47:29 1990
***************
*** 92,97 ****
--- 92,113 ----
  You are forbidden to forbid anyone else to use, share and improve
  what you give them.   Help stamp out software-hoarding!  */
  
+ /*
+  * Local changes:
+  *
+  *	Added `-L filename' flag to accept a list of files to process
+  *	  from a file.  If `filename' is `-', the list is read from the
+  *	  standard input.  This is useful for avoiding command-line
+  *	  size limits on some systems.
+  *	  skip@fsg.com (Skip Gilbrech) - Sun Jul 30 20:34:09 EDT 1990
+  *
+  *	Applied Dave Brennan's (brennan@rtp.dg.com) patch: `-d' flag makes
+  *	  etags generate tag entries for all macros, not just those with
+  *	  parameters.
+  *	  skip@fsg.com (Skip Gilbrech) - Sat Jun  2 18:37:16 EDT 1990
+  *
+  */
+ 
  #include <stdio.h>
  #include <ctype.h>
  
***************
*** 182,187 ****
--- 198,204 ----
  
  int	file_num = 0;		/* current file number			*/
  int	aflag = 0;		/* -a: append to tags */
+ int	dflag = 0;		/* -d: create tags for #define macros */
  int	tflag = 0;		/* -t: create tags for typedefs */
  int	uflag = 0;		/* -u: update tags */
  int	wflag = 0;		/* -w: suppress warnings */
***************
*** 249,255 ****
--- 266,275 ----
  
    extern char *gfnames();
    extern char *massage_name();
+ #else
+   int lflag = 0;
  #endif
+   char *file_list = 0;
  
    progname = av[0];
  
***************
*** 288,293 ****
--- 308,316 ----
  	    case 'a':
  	      aflag++;
  	      break;
+ 	    case 'd':
+ 	      dflag++;
+ 	      break;
  	    case 'e':
  	      eflag++;
  	      break;
***************
*** 308,313 ****
--- 331,355 ----
  		}
  	      outfile = av[1];
  	      goto end_loop;
+ #ifndef VMS	/* might work under vms, but I don't know, so... (sg) */
+ 	    case 'L':
+ 	      if (lflag > 0)
+ 		{
+ 		  fprintf(stderr,
+ 			  "%s: -L flag may only be given once\n", progname);
+ 		  goto usage;
+ 		}
+ 	      lflag++, ac--; av++;
+ 	      if (ac <= 1 || av[1][0] == '\0')
+ 		{
+ 		  fprintf(stderr,
+ 			  "%s: -L flag must be followed by a filename\n",
+ 			  progname);
+ 		  goto usage;
+ 		}
+ 	      file_list = av[1];
+ 	      goto end_loop;
+ #endif
  	    case 't':
  	      tflag++;
  	      break;
***************
*** 337,349 ****
        ac--; av++;
      }
  
    if (ac <= 1)
      {
      usage:
  #ifdef VMS
!       fprintf (stderr, "Usage: %s [-aetwvx] [-f outfile] file ...\n", progname);
  #else
!       fprintf (stderr, "Usage: %s [-BFaetuwvx] [-f outfile] file ...\n", progname);
  #endif
        exit(BAD);
      }
--- 379,397 ----
        ac--; av++;
      }
  
+ #ifdef VMS
    if (ac <= 1)
+ #else
+   if (ac <= 1 && ! file_list)
+ #endif
      {
      usage:
  #ifdef VMS
!       fprintf (stderr, "Usage: %s [-adetwvx] [-f outfile] file ...\n", progname);
  #else
!       fprintf (stderr,
! 	       "Usage: %s [-BFadetuwvx] [-f outfile] [-L file-list | -] file ...\n",
! 	       progname);
  #endif
        exit(BAD);
      }
***************
*** 371,376 ****
--- 419,465 ----
  	}
      }
  
+ #ifndef VMS
+   if (file_list)
+   {
+       FILE *flp;
+       struct linebuffer flbuf;
+ 
+       if (file_list[0] == '-' && file_list[1] == '\0')
+ 	  flp = stdin;
+       else
+ 	  flp = fopen(file_list, "r");
+ 
+       if (flp == NULL)
+       {
+ 	  fprintf (stderr, "%s: ", progname);
+ 	  perror(file_list);
+       }
+       else
+       {
+ 	  initbuffer (&flbuf);
+ 	  while (!feof (flp))
+ 	  {
+ 	      if (readline(&flbuf, flp) && flbuf.buffer[0] != '#')
+ 	      {
+ 		  this_file = flbuf.buffer;
+ 		  find_entries (this_file);
+ 		  if (eflag)
+ 		  {
+ 		      fprintf (outf, "\f\n%s,%d\n",
+ 			       this_file, total_size_of_entries (head));
+ 		      put_entries (head);
+ 		      free_tree (head);
+ 		      head = NULL;
+ 		  }
+ 	      }
+ 	  }
+ 	  if (flp != stdin)
+ 	      fclose(flp);
+       }
+   }
+ #endif
+ 
    file_num = 1;
  #ifdef VMS
    for (ac--, av++;
***************
*** 858,864 ****
  	    }
  	  continue;
  	case '#':
! 	  if (lp == lb.buffer + 1)
  	    number = 1;
  	  continue;
  	case '{':
--- 947,953 ----
  	    }
  	  continue;
  	case '#':
! 	  if (lp == lb.buffer + 1)     /* remember if the # is in column 1 */
  	    number = 1;
  	  continue;
  	case '{':
***************
*** 947,953 ****
  {
    reg char *lp = *lpp;
    reg char c;
!   static logical next_token_is_func;
    logical firsttok;	/* T if have seen first token in ()'s */
    int bad, win;
  
--- 1036,1042 ----
  {
    reg char *lp = *lpp;
    reg char c;
!   static logical next_token_is_func = 0, next_token_is_define = 0;
    logical firsttok;	/* T if have seen first token in ()'s */
    int bad, win;
  
***************
*** 967,977 ****
  	    }
  	}
        /* the following tries to make it so that a #define a b(c)	*/
!       /* doesn't count as a define of b.				*/
      }
    else
      {
        number++;
        if (number >= 4  || (number==2 && strncmp (token, "define", 6)))
  	{
  	  gotone = TRUE;
--- 1056,1082 ----
  	    }
  	}
        /* the following tries to make it so that a #define a b(c)	*/
!       /* doesn't count as a define of b.  The token is bad if it	*/
!       /* is `define' and the first one after the #, or if it is	*/
!       /* not the second token on the line.  However, if dflag is	*/
!       /* set, then the macro is valid no matter what.			*/
! 
      }
    else
      {
        number++;
+       if (number==2 && !strncmp (token, "define", 6) && dflag)
+ 	{
+ 	  next_token_is_define = 1;
+ 	  goto badone;
+ 	}
+       if (next_token_is_define)
+ 	{
+ 	  next_token_is_define = 0;
+ 	  *f = 0;
+ 	  win = 1;
+ 	  goto ret;
+ 	}
        if (number >= 4  || (number==2 && strncmp (token, "define", 6)))
  	{
  	  gotone = TRUE;
***************
*** 1014,1020 ****
      }
    /* Detect GNUmacs's function-defining macros. */
    if (!number && !strncmp (token, "DEF", 3))
- 	 
      {
        next_token_is_func = 1;
        goto badone;
--- 1119,1124 ----


--
Skip Gilbrech			email:	skip@fsg.com
Fusion Systems Group			uunet!fsg!skip
225 Broadway, 35th Floor		uunet!skipnyc!skip
New York, NY 10007		phones:	212-285-8001 (work)
					201-825-8732 (home)