Subject: ctags very slow when processing kernel (#179)
Index:	ucb/ctags.c 2.11BSD

Description:
	The 'ctags' program slows very noticeably when creating the
	kernel tags file (/sys/sys/tags).

Repeat-By:
	cd /sys/GENERIC
	make tags

Fix:
	All updates are available via anonymous FTP to ftp.iipo.gtegsc.com
	in the directory /pub/2.11BSD.

	Most of the slow down is due to ctags running almost out of memory,
	there is not sufficient malloc'able memory left to allocate a buffer
	when 'fopen' is used to read the input files.

	The fix was to allocate a buffer on the stack and use 'setbuf'
	to assign the buffer before the first read or write.  This speed
	up the ctags run for the kernel by a factor of 2 to 3.

	There were local routines to perform case insensitive string
	comaprison, character searching and dynamic string duplication.  
	These were removed and the references to them changed to the 
	system provided routines in libc.a (strcasecmp, rindex, and 
	strdup respectively).

	Apply the patch below and reinstall 'ctags':

		1) Save the patch to /tmp/patchfile
		2) patch -p0 < /tmp/patchfile
		3) cd /usr/src/ucb
		4) make ctags
		5) install -s ctags /usr/ucb

==============cut here
*** /usr/src/ucb/ctags.c.old	Mon Feb 16 22:11:08 1987
--- /usr/src/ucb/ctags.c	Wed Feb 16 23:47:07 1994
***************
*** 4,27 ****
   * specifies the terms and conditions for redistribution.
   */
  
! #ifndef lint
  char copyright[] =
  "@(#) Copyright (c) 1980 Regents of the University of California.\n\
   All rights reserved.\n";
- #endif not lint
  
! #ifndef lint
! static char sccsid[] = "@(#)ctags.c	5.1 (Berkeley) 5/31/85";
! #endif not lint
  
  #include <stdio.h>
  #include <ctype.h>
  
  /*
   * ctags: create a tags file
   */
  
- #define	reg	register
  #define	bool	char
  
  #define	TRUE	(1)
--- 4,25 ----
   * specifies the terms and conditions for redistribution.
   */
  
! #if	!defined(lint) && defined(DOSCCS)
  char copyright[] =
  "@(#) Copyright (c) 1980 Regents of the University of California.\n\
   All rights reserved.\n";
  
! static char sccsid[] = "@(#)ctags.c	5.1.1 (2.11BSD) 2/16/94";
! #endif
  
  #include <stdio.h>
  #include <ctype.h>
+ #include <strings.h>
  
  /*
   * ctags: create a tags file
   */
  
  #define	bool	char
  
  #define	TRUE	(1)
***************
*** 94,101 ****
  
  NODE	*head;			/* the head of the sorted binary tree	*/
  
- char	*savestr();
- char	*rindex(), *index();
  char	*toss_comment();
  
  main(ac,av)
--- 92,97 ----
***************
*** 102,108 ****
  int	ac;
  char	*av[];
  {
! 	char cmd[100];
  	int i;
  
  	while (ac > 1 && av[1][0] == '-') {
--- 98,104 ----
  int	ac;
  char	*av[];
  {
! 	char cmd[100], outfbuf[BUFSIZ];
  	int i;
  
  	while (ac > 1 && av[1][0] == '-') {
***************
*** 178,183 ****
--- 174,181 ----
  		perror(outfile);
  		exit(1);
  	}
+ 	setbuf(outf, outfbuf);
+ 
  	put_entries(head);
  	fclose(outf);
  	if (uflag) {
***************
*** 198,205 ****
  init()
  {
  
! 	reg	char	*sp;
! 	reg	int	i;
  
  	for (i = 0; i < 0177; i++) {
  		_wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
--- 196,203 ----
  init()
  {
  
! 	register char	*sp;
! 	register int	i;
  
  	for (i = 0; i < 0177; i++) {
  		_wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
***************
*** 224,236 ****
  find_entries(file)
  char	*file;
  {
! 	char *cp;
  
  	if ((inf = fopen(file,"r")) == NULL) {
  		perror(file);
  		return;
  	}
! 	curfile = savestr(file);
  	lineno = 0;
  	cp = rindex(file, '.');
  	/* .l implies lisp or lex source code */
--- 222,236 ----
  find_entries(file)
  char	*file;
  {
! 	char *cp, infbuf[BUFSIZ];
  
  	if ((inf = fopen(file,"r")) == NULL) {
  		perror(file);
  		return;
  	}
! 	setbuf(inf, infbuf);
! 
! 	curfile = strdup(file);
  	lineno = 0;
  	cp = rindex(file, '.');
  	/* .l implies lisp or lex source code */
***************
*** 300,306 ****
  			*fp = 0;
  		name = nbuf;
  	}
! 	np->entry = savestr(name);
  	np->file = curfile;
  	np->f = f;
  	np->lno = ln;
--- 300,306 ----
  			*fp = 0;
  		name = nbuf;
  	}
! 	np->entry = strdup(name);
  	np->file = curfile;
  	np->f = f;
  	np->lno = ln;
***************
*** 310,316 ****
  		strcat(lbuf, "$");
  		lbuf[50] = 0;
  	}
! 	np->pat = savestr(lbuf);
  	if (head == NULL)
  		head = np;
  	else
--- 310,316 ----
  		strcat(lbuf, "$");
  		lbuf[50] = 0;
  	}
! 	np->pat = strdup(lbuf);
  	if (head == NULL)
  		head = np;
  	else
***************
*** 447,453 ****
  char	**lp,*token,*tp;
  int	*f;
  {
! 	reg	char	c,*sp,*tsp;
  	static	bool	found;
  	bool	firsttok;		/* T if have seen first token in ()'s */
  	int	bad;
--- 447,453 ----
  char	**lp,*token,*tp;
  int	*f;
  {
! 	register char	c,*sp,*tsp;
  	static	bool	found;
  	bool	firsttok;		/* T if have seen first token in ()'s */
  	int	bad;
***************
*** 699,707 ****
  }
  
  put_entries(node)
! reg NODE	*node;
  {
! 	reg char	*sp;
  
  	if (node == NULL)
  		return;
--- 699,707 ----
  }
  
  put_entries(node)
! register NODE	*node;
  {
! 	register char	*sp;
  
  	if (node == NULL)
  		return;
***************
*** 860,900 ****
  	pfcnt++;
  }
  
- char *
- savestr(cp)
- 	char *cp;
- {
- 	register int len;
- 	register char *dp;
- 
- 	len = strlen(cp);
- 	dp = (char *)malloc(len+1);
- 	strcpy(dp, cp);
- 	return (dp);
- }
- 
  /*
-  * Return the ptr in sp at which the character c last
-  * appears; NULL if not found
-  *
-  * Identical to v7 rindex, included for portability.
-  */
- 
- char *
- rindex(sp, c)
- register char *sp, c;
- {
- 	register char *r;
- 
- 	r = NULL;
- 	do {
- 		if (*sp == c)
- 			r = sp;
- 	} while (*sp++);
- 	return(r);
- }
- 
- /*
   * lisp tag functions
   * just look for (def or (DEF
   */
--- 860,866 ----
***************
*** 913,921 ****
  		    (dbp[2] == 'E' || dbp[2] == 'e') &&
  		    (dbp[3] == 'F' || dbp[3] == 'f')) {
  			dbp += 4;
! 			if (striccmp(dbp, "method") == 0 ||
! 			    striccmp(dbp, "wrapper") == 0 ||
! 			    striccmp(dbp, "whopper") == 0)
  				special = TRUE;
  			else
  				special = FALSE;
--- 879,887 ----
  		    (dbp[2] == 'E' || dbp[2] == 'e') &&
  		    (dbp[3] == 'F' || dbp[3] == 'f')) {
  			dbp += 4;
! 			if (strcasecmp(dbp, "method") == 0 ||
! 			    strcasecmp(dbp, "wrapper") == 0 ||
! 			    strcasecmp(dbp, "whopper") == 0)
  				special = TRUE;
  			else
  				special = FALSE;
***************
*** 963,994 ****
  }
  
  /*
-  * striccmp:
-  *	Compare two strings over the length of the second, ignoring
-  *	case distinctions.  If they are the same, return 0.  If they
-  *	are different, return the difference of the first two different
-  *	characters.  It is assumed that the pattern (second string) is
-  *	completely lower case.
-  */
- striccmp(str, pat)
- register char	*str, *pat;
- {
- 	register int	c1;
- 
- 	while (*pat) {
- 		if (isupper(*str))
- 			c1 = tolower(*str);
- 		else
- 			c1 = *str;
- 		if (c1 != *pat)
- 			return c1 - *pat;
- 		pat++;
- 		str++;
- 	}
- 	return 0;
- }
- 
- /*
   * first_char:
   *	Return the first non-blank character in the file.  After
   *	finding it, rewind the input file so we start at the beginning
--- 929,934 ----
***************
*** 1026,1029 ****
  			return;
  	}
  }
- 
--- 966,968 ----
