# 2.11BSD#431 - /usr/src/ucb/ctags.c

##### Functions

    C_entries         X
    L_funcs           X
    L_getit           X
    PF_funcs          X
    Y_entries         X
    add_node          X
    find_entries      X
    first_char        X
    free_tree         X
    getit             X
    getline           X
    init              X
    main              X
    pfnote            X
    put_entries       X
    start_entry       X
    tail              X
    takeprec          X
    toss_comment      X
    toss_yysec        X

##### Variables

    aflag             X
    copyright         X
    curfile           X
    dbp               X
    file_num          X
    head              X
    lbuf              X
    line              X
    lineftell         X
    lineno            X
    outfile           X
    pfcnt             X
    searchar          X
    tflag             X
    uflag             X
    vflag             X
    wflag             X
    xflag             X

##### Macros

    FALSE             X
    TRUE              X
    begtoken          X
    bool              X
    endtoken          X
    intoken           X
    isgood            X
    iswhite           X
    max               X

##### struct's

    nd_st             X

##### typedef's

    NODE              X

       1: /*
       2:  * Copyright (c) 1980 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  */
       6:
       7: #if !defined(lint) && defined(DOSCCS)
       8: char copyright[] =
       9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
      10:  All rights reserved.\n";
      11:
      12: static char sccsid[] = "@(#)ctags.c	5.1.1 (2.11BSD) 2/16/94";
      13: #endif
      14:
      15: #include <stdio.h>
      16: #include <ctype.h>
      17: #include <strings.h>
      18:
      19: /*
      20:  * ctags: create a tags file
      21:  */
      22:
      23: #define bool    char
      24:
      25: #define TRUE    (1)
      26: #define FALSE   (0)
      27:
      28: #define iswhite(arg)    (_wht[arg]) /* T if char is white		*/
      29: #define begtoken(arg)   (_btk[arg]) /* T if char can start token	*/
      30: #define intoken(arg)    (_itk[arg]) /* T if char can be in token	*/
      31: #define endtoken(arg)   (_etk[arg]) /* T if char ends tokens	*/
      32: #define isgood(arg) (_gd[arg])  /* T if char can be after ')'	*/
      33:
      34: #define max(I1,I2)  (I1 > I2 ? I1 : I2)
      35:
      36: struct  nd_st {         /* sorting structure			*/
      37:     char    *entry;         /* function or type name	*/
      38:     char    *file;          /* file name			*/
      39:     bool    f;          /* use pattern or line no	*/
      40:     int lno;            /* for -x option		*/
      41:     char    *pat;           /* search pattern		*/
      42:     bool    been_warned;        /* set if noticed dup		*/
      43:     struct  nd_st   *left,*right;   /* left and right sons		*/
      44: };
      45:
      46: long    ftell();
      47: typedef struct  nd_st   NODE;
      48:
      49: bool    number,             /* T if on line starting with #	*/
      50:     term    = FALSE,        /* T if print on terminal	*/
      51:     makefile= TRUE,         /* T if to creat "tags" file	*/
      52:     gotone,             /* found a func already on line	*/
      53:                     /* boolean "func" (see init)	*/
      54:     _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177];
      55:
      56:     /* typedefs are recognized using a simple finite automata,
      57: 	 * tydef is its state variable.
      58: 	 */
      59: typedef enum {none, begin, middle, end } TYST;
      60:
      61: TYST tydef = none;
      62:
      63: char    searchar = '/';         /* use /.../ searches 		*/
      64:
      65: int lineno;             /* line number of current line */
      66: char    line[4*BUFSIZ],     /* current input line			*/
      67:     *curfile,       /* current input file name		*/
      68:     *outfile= "tags",   /* output file				*/
      69:     *white  = " \f\t\n",    /* white chars				*/
      70:     *endtk  = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?",
      71:                 /* token ending chars			*/
      72:     *begtk  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz",
      73:                 /* token starting chars			*/
      74:     *intk   = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789",
      75:                 /* valid in-token chars			*/
      76:     *notgd  = ",;";     /* non-valid after-function chars	*/
      77:
      78: int file_num;       /* current file number			*/
      79: int aflag;          /* -a: append to tags */
      80: int tflag;          /* -t: create tags for typedefs */
      81: int uflag;          /* -u: update tags */
      82: int wflag;          /* -w: suppress warnings */
      83: int vflag;          /* -v: create vgrind style index output */
      84: int xflag;          /* -x: create cxref style output */
      85:
      86: char    lbuf[BUFSIZ];
      87:
      88: FILE    *inf,           /* ioptr for current input file		*/
      89:     *outf;          /* ioptr for tags file			*/
      90:
      91: long    lineftell;      /* ftell after getc( inf ) == '\n' 	*/
      92:
      93: NODE    *head;          /* the head of the sorted binary tree	*/
      94:
      95: char    *toss_comment();
      96:
      97: main(ac,av)
      98: int ac;
      99: char    *av[];
     100: {
     101:     char cmd[100], outfbuf[BUFSIZ];
     102:     int i;
     103:
     104:     while (ac > 1 && av[1][0] == '-') {
     105:         for (i=1; av[1][i]; i++) {
     106:             switch(av[1][i]) {
     107:               case 'B':
     108:                 searchar='?';
     109:                 break;
     110:               case 'F':
     111:                 searchar='/';
     112:                 break;
     113:               case 'a':
     114:                 aflag++;
     115:                 break;
     116:               case 't':
     117:                 tflag++;
     118:                 break;
     119:               case 'u':
     120:                 uflag++;
     121:                 break;
     122:               case 'w':
     123:                 wflag++;
     124:                 break;
     125:               case 'v':
     126:                 vflag++;
     127:                 xflag++;
     128:                 break;
     129:               case 'x':
     130:                 xflag++;
     131:                 break;
     132:               case 'f':
     133:                 if (ac < 2)
     134:                     goto usage;
     135:                 ac--, av++;
     136:                 outfile = av[1];
     137:                 goto next;
     138:               default:
     139:                 goto usage;
     140:         }
     141:         }
     142:     next:
     143:         ac--; av++;
     144:     }
     145:
     146:     if (ac <= 1) {
     147: usage:
     148:         printf("Usage: ctags [-BFatuwvx] [-f tagsfile] file ...\n");
     149:         exit(1);
     150:     }
     151:
     152:     init();         /* set up boolean "functions"		*/
     153:     /*
     154: 	 * loop through files finding functions
     155: 	 */
     156:     for (file_num = 1; file_num < ac; file_num++)
     157:         find_entries(av[file_num]);
     158:
     159:     if (xflag) {
     160:         put_entries(head);
     161:         exit(0);
     162:     }
     163:     if (uflag) {
     164:         for (i=1; i<ac; i++) {
     165:             sprintf(cmd,
     166:                 "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
     167:                 outfile, av[i], outfile);
     168:             system(cmd);
     169:         }
     170:         aflag++;
     171:     }
     172:     outf = fopen(outfile, aflag ? "a" : "w");
     173:     if (outf == NULL) {
     174:         perror(outfile);
     175:         exit(1);
     176:     }
     177:     setbuf(outf, outfbuf);
     178:
     179:     put_entries(head);
     180:     fclose(outf);
     181:     if (uflag) {
     182:         sprintf(cmd, "sort %s -o %s", outfile, outfile);
     183:         system(cmd);
     184:     }
     185:     exit(0);
     186: }
     187:
     188: /*
     189:  * This routine sets up the boolean psuedo-functions which work
     190:  * by seting boolean flags dependent upon the corresponding character
     191:  * Every char which is NOT in that string is not a white char.  Therefore,
     192:  * all of the array "_wht" is set to FALSE, and then the elements
     193:  * subscripted by the chars in "white" are set to TRUE.  Thus "_wht"
     194:  * of a char is TRUE if it is the string "white", else FALSE.
     195:  */
     196: init()
     197: {
     198:
     199:     register char   *sp;
     200:     register int    i;
     201:
     202:     for (i = 0; i < 0177; i++) {
     203:         _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE;
     204:         _gd[i] = TRUE;
     205:     }
     206:     for (sp = white; *sp; sp++)
     207:         _wht[*sp] = TRUE;
     208:     for (sp = endtk; *sp; sp++)
     209:         _etk[*sp] = TRUE;
     210:     for (sp = intk; *sp; sp++)
     211:         _itk[*sp] = TRUE;
     212:     for (sp = begtk; *sp; sp++)
     213:         _btk[*sp] = TRUE;
     214:     for (sp = notgd; *sp; sp++)
     215:         _gd[*sp] = FALSE;
     216: }
     217:
     218: /*
     219:  * This routine opens the specified file and calls the function
     220:  * which finds the function and type definitions.
     221:  */
     222: find_entries(file)
     223: char    *file;
     224: {
     225:     char *cp, infbuf[BUFSIZ];
     226:
     227:     if ((inf = fopen(file,"r")) == NULL) {
     228:         perror(file);
     229:         return;
     230:     }
     231:     setbuf(inf, infbuf);
     232:
     233:     curfile = strdup(file);
     234:     lineno = 0;
     235:     cp = rindex(file, '.');
     236:     /* .l implies lisp or lex source code */
     237:     if (cp && cp[1] == 'l' && cp[2] == '\0') {
     238:         if (index(";([", first_char()) != NULL) {   /* lisp */
     239:             L_funcs(inf);
     240:             fclose(inf);
     241:             return;
     242:         }
     243:         else {                      /* lex */
     244:             /*
     245: 			 * throw away all the code before the second "%%"
     246: 			 */
     247:             toss_yysec();
     248:             getline();
     249:             pfnote("yylex", lineno, TRUE);
     250:             toss_yysec();
     251:             C_entries();
     252:             fclose(inf);
     253:             return;
     254:         }
     255:     }
     256:     /* .y implies a yacc file */
     257:     if (cp && cp[1] == 'y' && cp[2] == '\0') {
     258:         toss_yysec();
     259:         Y_entries();
     260:         C_entries();
     261:         fclose(inf);
     262:         return;
     263:     }
     264:     /* if not a .c or .h file, try fortran */
     265:     if (cp && (cp[1] != 'c' && cp[1] != 'h') && cp[2] == '\0') {
     266:         if (PF_funcs(inf) != 0) {
     267:             fclose(inf);
     268:             return;
     269:         }
     270:         rewind(inf);    /* no fortran tags found, try C */
     271:     }
     272:     C_entries();
     273:     fclose(inf);
     274: }
     275:
     276: pfnote(name, ln, f)
     277: char    *name;
     278: int ln;
     279: bool    f;      /* f == TRUE when function */
     280: {
     281:     register char *fp;
     282:     register NODE *np;
     283:     char nbuf[BUFSIZ];
     284:
     285:     if ((np = (NODE *) malloc(sizeof (NODE))) == NULL) {
     286:         fprintf(stderr, "ctags: too many entries to sort\n");
     287:         put_entries(head);
     288:         free_tree(head);
     289:         head = np = (NODE *) malloc(sizeof (NODE));
     290:     }
     291:     if (xflag == 0 && !strcmp(name, "main")) {
     292:         fp = rindex(curfile, '/');
     293:         if (fp == 0)
     294:             fp = curfile;
     295:         else
     296:             fp++;
     297:         sprintf(nbuf, "M%s", fp);
     298:         fp = rindex(nbuf, '.');
     299:         if (fp && fp[2] == 0)
     300:             *fp = 0;
     301:         name = nbuf;
     302:     }
     303:     np->entry = strdup(name);
     304:     np->file = curfile;
     305:     np->f = f;
     306:     np->lno = ln;
     307:     np->left = np->right = 0;
     308:     if (xflag == 0) {
     309:         lbuf[50] = 0;
     310:         strcat(lbuf, "$");
     311:         lbuf[50] = 0;
     312:     }
     313:     np->pat = strdup(lbuf);
     314:     if (head == NULL)
     315:         head = np;
     316:     else
     317:         add_node(np, head);
     318: }
     319:
     320: /*
     321:  * This routine finds functions and typedefs in C syntax and adds them
     322:  * to the list.
     323:  */
     324: C_entries()
     325: {
     326:     register int c;
     327:     register char *token, *tp;
     328:     bool incomm, inquote, inchar, midtoken;
     329:     int level;
     330:     char *sp;
     331:     char tok[BUFSIZ];
     332:
     333:     number = gotone = midtoken = inquote = inchar = incomm = FALSE;
     334:     level = 0;
     335:     sp = tp = token = line;
     336:     lineno++;
     337:     lineftell = ftell(inf);
     338:     for (;;) {
     339:         *sp = c = getc(inf);
     340:         if (feof(inf))
     341:             break;
     342:         if (c == '\n')
     343:             lineno++;
     344:         else if (c == '\\') {
     345:             c = *++sp = getc(inf);
     346:             if (c == '\n')
     347:                 c = ' ';
     348:         }
     349:         else if (incomm) {
     350:             if (c == '*') {
     351:                 while ((*++sp=c=getc(inf)) == '*')
     352:                     continue;
     353:                 if (c == '\n')
     354:                     lineno++;
     355:                 if (c == '/')
     356:                     incomm = FALSE;
     357:             }
     358:         }
     359:         else if (inquote) {
     360:             /*
     361: 			 * Too dumb to know about \" not being magic, but
     362: 			 * they usually occur in pairs anyway.
     363: 			 */
     364:             if (c == '"')
     365:                 inquote = FALSE;
     366:             continue;
     367:         }
     368:         else if (inchar) {
     369:             if (c == '\'')
     370:                 inchar = FALSE;
     371:             continue;
     372:         }
     373:         else switch (c) {
     374:           case '"':
     375:             inquote = TRUE;
     376:             continue;
     377:           case '\'':
     378:             inchar = TRUE;
     379:             continue;
     380:           case '/':
     381:             if ((*++sp=c=getc(inf)) == '*')
     382:                 incomm = TRUE;
     383:             else
     384:                 ungetc(*sp, inf);
     385:             continue;
     386:           case '#':
     387:             if (sp == line)
     388:                 number = TRUE;
     389:             continue;
     390:           case '{':
     391:             if (tydef == begin) {
     392:                 tydef=middle;
     393:             }
     394:             level++;
     395:             continue;
     396:           case '}':
     397:             if (sp == line)
     398:                 level = 0;  /* reset */
     399:             else
     400:                 level--;
     401:             if (!level && tydef==middle) {
     402:                 tydef=end;
     403:             }
     404:             continue;
     405:         }
     406:         if (!level && !inquote && !incomm && gotone == FALSE) {
     407:             if (midtoken) {
     408:                 if (endtoken(c)) {
     409:                     int f;
     410:                     int pfline = lineno;
     411:                     if (start_entry(&sp,token,tp,&f)) {
     412:                         strncpy(tok,token,tp-token+1);
     413:                         tok[tp-token+1] = 0;
     414:                         getline();
     415:                         pfnote(tok, pfline, f);
     416:                         gotone = f; /* function */
     417:                     }
     418:                     midtoken = FALSE;
     419:                     token = sp;
     420:                 }
     421:                 else if (intoken(c))
     422:                     tp++;
     423:             }
     424:             else if (begtoken(c)) {
     425:                 token = tp = sp;
     426:                 midtoken = TRUE;
     427:             }
     428:         }
     429:         if (c == ';'  &&  tydef==end)   /* clean with typedefs */
     430:             tydef=none;
     431:         sp++;
     432:         if (c == '\n' || sp > &line[sizeof (line) - BUFSIZ]) {
     433:             tp = token = sp = line;
     434:             lineftell = ftell(inf);
     435:             number = gotone = midtoken = inquote = inchar = FALSE;
     436:         }
     437:     }
     438: }
     439:
     440: /*
     441:  * This routine  checks to see if the current token is
     442:  * at the start of a function, or corresponds to a typedef
     443:  * It updates the input line * so that the '(' will be
     444:  * in it when it returns.
     445:  */
     446: start_entry(lp,token,tp,f)
     447: char    **lp,*token,*tp;
     448: int *f;
     449: {
     450:     register char   c,*sp,*tsp;
     451:     static  bool    found;
     452:     bool    firsttok;       /* T if have seen first token in ()'s */
     453:     int bad;
     454:
     455:     *f = 1;         /* a function */
     456:     sp = *lp;
     457:     c = *sp;
     458:     bad = FALSE;
     459:     if (!number) {      /* space is not allowed in macro defs	*/
     460:         while (iswhite(c)) {
     461:             *++sp = c = getc(inf);
     462:             if (c == '\n') {
     463:                 lineno++;
     464:                 if (sp > &line[sizeof (line) - BUFSIZ])
     465:                     goto ret;
     466:             }
     467:         }
     468:     /* the following tries to make it so that a #define a b(c)	*/
     469:     /* doesn't count as a define of b.				*/
     470:     }
     471:     else {
     472:         if (!strncmp(token, "define", 6))
     473:             found = 0;
     474:         else
     475:             found++;
     476:         if (found >= 2) {
     477:             gotone = TRUE;
     478: badone:         bad = TRUE;
     479:             goto ret;
     480:         }
     481:     }
     482:     /* check for the typedef cases		*/
     483:     if (tflag && !strncmp(token, "typedef", 7)) {
     484:         tydef=begin;
     485:         goto badone;
     486:     }
     487:     if (tydef==begin && (!strncmp(token, "struct", 6) ||
     488:         !strncmp(token, "union", 5) || !strncmp(token, "enum", 4))) {
     489:         goto badone;
     490:     }
     491:     if (tydef==begin) {
     492:         tydef=end;
     493:         goto badone;
     494:     }
     495:     if (tydef==end) {
     496:         *f = 0;
     497:         goto ret;
     498:     }
     499:     if (c != '(')
     500:         goto badone;
     501:     firsttok = FALSE;
     502:     while ((*++sp=c=getc(inf)) != ')') {
     503:         if (c == '\n') {
     504:             lineno++;
     505:             if (sp > &line[sizeof (line) - BUFSIZ])
     506:                 goto ret;
     507:         }
     508:         /*
     509: 		 * This line used to confuse ctags:
     510: 		 *	int	(*oldhup)();
     511: 		 * This fixes it. A nonwhite char before the first
     512: 		 * token, other than a / (in case of a comment in there)
     513: 		 * makes this not a declaration.
     514: 		 */
     515:         if (begtoken(c) || c=='/')
     516:             firsttok++;
     517:         else if (!iswhite(c) && !firsttok)
     518:             goto badone;
     519:     }
     520:     while (iswhite(*++sp=c=getc(inf)))
     521:         if (c == '\n') {
     522:             lineno++;
     523:             if (sp > &line[sizeof (line) - BUFSIZ])
     524:                 break;
     525:         }
     526: ret:
     527:     *lp = --sp;
     528:     if (c == '\n')
     529:         lineno--;
     530:     ungetc(c,inf);
     531:     return !bad && (!*f || isgood(c));
     532:                     /* hack for typedefs */
     533: }
     534:
     535: /*
     536:  * Y_entries:
     537:  *	Find the yacc tags and put them in.
     538:  */
     539: Y_entries()
     540: {
     541:     register char   *sp, *orig_sp;
     542:     register int    brace;
     543:     register bool   in_rule, toklen;
     544:     char        tok[BUFSIZ];
     545:
     546:     brace = 0;
     547:     getline();
     548:     pfnote("yyparse", lineno, TRUE);
     549:     while (fgets(line, sizeof line, inf) != NULL)
     550:         for (sp = line; *sp; sp++)
     551:             switch (*sp) {
     552:               case '\n':
     553:                 lineno++;
     554:                 /* FALLTHROUGH */
     555:               case ' ':
     556:               case '\t':
     557:               case '\f':
     558:               case '\r':
     559:                 break;
     560:               case '"':
     561:                 do {
     562:                     while (*++sp != '"')
     563:                         continue;
     564:                 } while (sp[-1] == '\\');
     565:                 break;
     566:               case '\'':
     567:                 do {
     568:                     while (*++sp != '\'')
     569:                         continue;
     570:                 } while (sp[-1] == '\\');
     571:                 break;
     572:               case '/':
     573:                 if (*++sp == '*')
     574:                     sp = toss_comment(sp);
     575:                 else
     576:                     --sp;
     577:                 break;
     578:               case '{':
     579:                 brace++;
     580:                 break;
     581:               case '}':
     582:                 brace--;
     583:                 break;
     584:               case '%':
     585:                 if (sp[1] == '%' && sp == line)
     586:                     return;
     587:                 break;
     588:               case '|':
     589:               case ';':
     590:                 in_rule = FALSE;
     591:                 break;
     592:               default:
     593:                 if (brace == 0  && !in_rule && (isalpha(*sp) ||
     594:                                 *sp == '.' ||
     595:                                 *sp == '_')) {
     596:                     orig_sp = sp;
     597:                     ++sp;
     598:                     while (isalnum(*sp) || *sp == '_' ||
     599:                            *sp == '.')
     600:                         sp++;
     601:                     toklen = sp - orig_sp;
     602:                     while (isspace(*sp))
     603:                         sp++;
     604:                     if (*sp == ':' || (*sp == '\0' &&
     605:                                first_char() == ':'))
     606:                     {
     607:                         strncpy(tok, orig_sp, toklen);
     608:                         tok[toklen] = '\0';
     609:                         strcpy(lbuf, line);
     610:                         lbuf[strlen(lbuf) - 1] = '\0';
     611:                         pfnote(tok, lineno, TRUE);
     612:                         in_rule = TRUE;
     613:                     }
     614:                     else
     615:                         sp--;
     616:                 }
     617:                 break;
     618:             }
     619: }
     620:
     621: char *
     622: toss_comment(start)
     623: char    *start;
     624: {
     625:     register char   *sp;
     626:
     627:     /*
     628: 	 * first, see if the end-of-comment is on the same line
     629: 	 */
     630:     do {
     631:         while ((sp = index(start, '*')) != NULL)
     632:             if (sp[1] == '/')
     633:                 return ++sp;
     634:             else
     635:                 start = ++sp;
     636:         start = line;
     637:         lineno++;
     638:     } while (fgets(line, sizeof line, inf) != NULL);
     639: }
     640:
     641: getline()
     642: {
     643:     long saveftell = ftell( inf );
     644:     register char *cp;
     645:
     646:     fseek( inf , lineftell , 0 );
     647:     fgets(lbuf, sizeof lbuf, inf);
     648:     cp = rindex(lbuf, '\n');
     649:     if (cp)
     650:         *cp = 0;
     651:     fseek(inf, saveftell, 0);
     652: }
     653:
     654: free_tree(node)
     655: NODE    *node;
     656: {
     657:
     658:     while (node) {
     659:         free_tree(node->right);
     660:         cfree(node);
     661:         node = node->left;
     662:     }
     663: }
     664:
     665: add_node(node, cur_node)
     666:     NODE *node,*cur_node;
     667: {
     668:     register int dif;
     669:
     670:     dif = strcmp(node->entry, cur_node->entry);
     671:     if (dif == 0) {
     672:         if (node->file == cur_node->file) {
     673:             if (!wflag) {
     674: fprintf(stderr,"Duplicate entry in file %s, line %d: %s\n",
     675:     node->file,lineno,node->entry);
     676: fprintf(stderr,"Second entry ignored\n");
     677:             }
     678:             return;
     679:         }
     680:         if (!cur_node->been_warned)
     681:             if (!wflag)
     682: fprintf(stderr,"Duplicate entry in files %s and %s: %s (Warning only)\n",
     683:     node->file, cur_node->file, node->entry);
     684:         cur_node->been_warned = TRUE;
     685:         return;
     686:     }
     687:
     688:     if (dif < 0) {
     689:         if (cur_node->left != NULL)
     690:             add_node(node,cur_node->left);
     691:         else
     692:             cur_node->left = node;
     693:         return;
     694:     }
     695:     if (cur_node->right != NULL)
     696:         add_node(node,cur_node->right);
     697:     else
     698:         cur_node->right = node;
     699: }
     700:
     701: put_entries(node)
     702: register NODE   *node;
     703: {
     704:     register char   *sp;
     705:
     706:     if (node == NULL)
     707:         return;
     708:     put_entries(node->left);
     709:     if (xflag == 0)
     710:         if (node->f) {      /* a function */
     711:             fprintf(outf, "%s\t%s\t%c^",
     712:                 node->entry, node->file, searchar);
     713:             for (sp = node->pat; *sp; sp++)
     714:                 if (*sp == '\\')
     715:                     fprintf(outf, "\\\\");
     716:                 else if (*sp == searchar)
     717:                     fprintf(outf, "\\%c", searchar);
     718:                 else
     719:                     putc(*sp, outf);
     720:             fprintf(outf, "%c\n", searchar);
     721:         }
     722:         else {      /* a typedef; text pattern inadequate */
     723:             fprintf(outf, "%s\t%s\t%d\n",
     724:                 node->entry, node->file, node->lno);
     725:         }
     726:     else if (vflag)
     727:         fprintf(stdout, "%s %s %d\n",
     728:                 node->entry, node->file, (node->lno+63)/64);
     729:     else
     730:         fprintf(stdout, "%-16s%4d %-16s %s\n",
     731:             node->entry, node->lno, node->file, node->pat);
     732:     put_entries(node->right);
     733: }
     734: char    *dbp = lbuf;
     735: int pfcnt;
     736:
     737: PF_funcs(fi)
     738:     FILE *fi;
     739: {
     740:
     741:     pfcnt = 0;
     742:     while (fgets(lbuf, sizeof(lbuf), fi)) {
     743:         lineno++;
     744:         dbp = lbuf;
     745:         if ( *dbp == '%' ) dbp++ ;  /* Ratfor escape to fortran */
     746:         while (isspace(*dbp))
     747:             dbp++;
     748:         if (*dbp == 0)
     749:             continue;
     750:         switch (*dbp |' ') {
     751:
     752:           case 'i':
     753:             if (tail("integer"))
     754:                 takeprec();
     755:             break;
     756:           case 'r':
     757:             if (tail("real"))
     758:                 takeprec();
     759:             break;
     760:           case 'l':
     761:             if (tail("logical"))
     762:                 takeprec();
     763:             break;
     764:           case 'c':
     765:             if (tail("complex") || tail("character"))
     766:                 takeprec();
     767:             break;
     768:           case 'd':
     769:             if (tail("double")) {
     770:                 while (isspace(*dbp))
     771:                     dbp++;
     772:                 if (*dbp == 0)
     773:                     continue;
     774:                 if (tail("precision"))
     775:                     break;
     776:                 continue;
     777:             }
     778:             break;
     779:         }
     780:         while (isspace(*dbp))
     781:             dbp++;
     782:         if (*dbp == 0)
     783:             continue;
     784:         switch (*dbp|' ') {
     785:
     786:           case 'f':
     787:             if (tail("function"))
     788:                 getit();
     789:             continue;
     790:           case 's':
     791:             if (tail("subroutine"))
     792:                 getit();
     793:             continue;
     794:           case 'p':
     795:             if (tail("program")) {
     796:                 getit();
     797:                 continue;
     798:             }
     799:             if (tail("procedure"))
     800:                 getit();
     801:             continue;
     802:         }
     803:     }
     804:     return (pfcnt);
     805: }
     806:
     807: tail(cp)
     808:     char *cp;
     809: {
     810:     register int len = 0;
     811:
     812:     while (*cp && (*cp&~' ') == ((*(dbp+len))&~' '))
     813:         cp++, len++;
     814:     if (*cp == 0) {
     815:         dbp += len;
     816:         return (1);
     817:     }
     818:     return (0);
     819: }
     820:
     821: takeprec()
     822: {
     823:
     824:     while (isspace(*dbp))
     825:         dbp++;
     826:     if (*dbp != '*')
     827:         return;
     828:     dbp++;
     829:     while (isspace(*dbp))
     830:         dbp++;
     831:     if (!isdigit(*dbp)) {
     832:         --dbp;      /* force failure */
     833:         return;
     834:     }
     835:     do
     836:         dbp++;
     837:     while (isdigit(*dbp));
     838: }
     839:
     840: getit()
     841: {
     842:     register char *cp;
     843:     char c;
     844:     char nambuf[BUFSIZ];
     845:
     846:     for (cp = lbuf; *cp; cp++)
     847:         ;
     848:     *--cp = 0;  /* zap newline */
     849:     while (isspace(*dbp))
     850:         dbp++;
     851:     if (*dbp == 0 || !isalpha(*dbp))
     852:         return;
     853:     for (cp = dbp+1; *cp && (isalpha(*cp) || isdigit(*cp)); cp++)
     854:         continue;
     855:     c = cp[0];
     856:     cp[0] = 0;
     857:     strcpy(nambuf, dbp);
     858:     cp[0] = c;
     859:     pfnote(nambuf, lineno);
     860:     pfcnt++;
     861: }
     862:
     863: /*
     864:  * lisp tag functions
     865:  * just look for (def or (DEF
     866:  */
     867:
     868: L_funcs (fi)
     869: FILE *fi;
     870: {
     871:     register int    special;
     872:
     873:     pfcnt = 0;
     874:     while (fgets(lbuf, sizeof(lbuf), fi)) {
     875:         lineno++;
     876:         dbp = lbuf;
     877:         if (dbp[0] == '(' &&
     878:             (dbp[1] == 'D' || dbp[1] == 'd') &&
     879:             (dbp[2] == 'E' || dbp[2] == 'e') &&
     880:             (dbp[3] == 'F' || dbp[3] == 'f')) {
     881:             dbp += 4;
     882:             if (strcasecmp(dbp, "method") == 0 ||
     883:                 strcasecmp(dbp, "wrapper") == 0 ||
     884:                 strcasecmp(dbp, "whopper") == 0)
     885:                 special = TRUE;
     886:             else
     887:                 special = FALSE;
     888:             while (!isspace(*dbp))
     889:                 dbp++;
     890:             while (isspace(*dbp))
     891:                 dbp++;
     892:             L_getit(special);
     893:         }
     894:     }
     895: }
     896:
     897: L_getit(special)
     898: int special;
     899: {
     900:     register char   *cp;
     901:     register char   c;
     902:     char        nambuf[BUFSIZ];
     903:
     904:     for (cp = lbuf; *cp; cp++)
     905:         continue;
     906:     *--cp = 0;      /* zap newline */
     907:     if (*dbp == 0)
     908:         return;
     909:     if (special) {
     910:         if ((cp = index(dbp, ')')) == NULL)
     911:             return;
     912:         while (cp >= dbp && *cp != ':')
     913:             cp--;
     914:         if (cp < dbp)
     915:             return;
     916:         dbp = cp;
     917:         while (*cp && *cp != ')' && *cp != ' ')
     918:             cp++;
     919:     }
     920:     else
     921:         for (cp = dbp + 1; *cp && *cp != '(' && *cp != ' '; cp++)
     922:             continue;
     923:     c = cp[0];
     924:     cp[0] = 0;
     925:     strcpy(nambuf, dbp);
     926:     cp[0] = c;
     927:     pfnote(nambuf, lineno,TRUE);
     928:     pfcnt++;
     929: }
     930:
     931: /*
     932:  * first_char:
     933:  *	Return the first non-blank character in the file.  After
     934:  *	finding it, rewind the input file so we start at the beginning
     935:  *	again.
     936:  */
     937: first_char()
     938: {
     939:     register int    c;
     940:     register long   off;
     941:
     942:     off = ftell(inf);
     943:     while ((c = getc(inf)) != EOF)
     944:         if (!isspace(c) && c != '\r') {
     945:             fseek(inf, off, 0);
     946:             return c;
     947:         }
     948:     fseek(inf, off, 0);
     949:     return EOF;
     950: }
     951:
     952: /*
     953:  * toss_yysec:
     954:  *	Toss away code until the next "%%" line.
     955:  */
     956: toss_yysec()
     957: {
     958:     char        buf[BUFSIZ];
     959:
     960:     for (;;) {
     961:         lineftell = ftell(inf);
     962:         if (fgets(buf, BUFSIZ, inf) == NULL)
     963:             return;
     964:         lineno++;
     965:         if (strncmp(buf, "%%", 2) == 0)
     966:             return;
     967:     }
     968: }

#### Defined functions

C_entries defined in line 324; used 3 times

- in line 251, 260, 272

L_funcs defined in line 868; used 1 times

- in line 239

L_getit defined in line 897; used 1 times

- in line 892

PF_funcs defined in line 737; used 1 times

- in line 266

Y_entries defined in line 539; used 1 times

- in line 259

add_node defined in line 665; used 3 times

- in line 317, 690, 696

find_entries defined in line 222; used 1 times

- in line 157

first_char defined in line 937; used 2 times

- in line 238, 605

free_tree defined in line 654; used 2 times

- in line 288, 659

getit defined in line 840; used 4 times

- in line 788-800(4)

getline defined in line 641; used 3 times

- in line 248, 414, 547

init defined in line 196; used 1 times

- in line 152

main defined in line 97; never used
pfnote defined in line 276; used 6 times

- in line 249, 415, 548, 611, 859, 927

put_entries defined in line 701; used 5 times

- in line 160, 179, 287, 708, 732

start_entry defined in line 446; used 1 times

- in line 411

tail defined in line 807; used 11 times

- in line 753-774(7), 787-799(4)

takeprec defined in line 821; used 4 times

- in line 754-766(4)

toss_comment defined in line 621; used 2 times

- in line 95, 574

toss_yysec defined in line 956; used 3 times

- in line 247-250(2), 258

#### Defined variables

aflag defined in line 79; used 3 times

- in line 114, 170-172(2)

copyright defined in line 8; never used
curfile defined in line 67; used 4 times

- in line 233, 292-294(2), 304

dbp defined in line 734; used 55 times

- in line 744-750(7), 770-772(3), 780-784(4), 812-815(2), 824-837(10), 849-857(6), 876-891(16), 907-925(7)

file_num defined in line 78; used 4 times

- in line 156-157(4)

head defined in line 93; used 8 times

- in line 160, 179, 287-289(3), 314-317(3)

lbuf defined in line 86; used 19 times

- in line 309-313(4), 609-610(3), 647-648(3), 734, 742-744(3), 846, 874-876(3), 904

line defined in line 66; used 20 times

- in line 335, 387, 397, 432-433(3), 464(2), 505(2), 523(2), 549-550(3), 585, 609, 636-638(3)

lineftell defined in line 91; used 4 times

- in line 337, 434, 646, 961

lineno defined in line 65; used 20 times

- in line 234, 249, 336, 343, 354, 410, 463, 504, 522, 529, 548-553(2), 611, 637, 675, 743, 859, 875, 927, 964

outfile defined in line 68; used 7 times

- in line 136, 167-174(4), 182(2)

pfcnt defined in line 735; used 5 times

- in line 741, 804, 860, 873, 928

sccsid defined in line 12; never used
searchar defined in line 63; used 6 times

- in line 108-111(2), 712-720(4)

tflag defined in line 80; used 2 times

- in line 117, 483

uflag defined in line 81; used 3 times

- in line 120, 163, 181

vflag defined in line 83; used 2 times

- in line 126, 726

wflag defined in line 82; used 3 times

- in line 123, 673, 681

xflag defined in line 84; used 6 times

- in line 127-130(2), 159, 291, 308, 709

#### Defined struct's

nd_st defined in line 36; used 4 times

- in line 43-47(4)

#### Defined typedef's

NODE defined in line 47; used 9 times

- in line 93, 655, 666, 702-289(6)

#### Defined macros

FALSE defined in line 26; used 14 times

- in line 50, 203, 215, 333, 356, 365-370(2), 406, 418, 435, 458, 501, 590, 887

TRUE defined in line 25; used 20 times

- in line 51, 204-213(5), 249, 375-382(3), 388, 426, 477-478(2), 548, 611-612(2), 684, 885, 927

begtoken defined in line 29; used 2 times

- in line 424, 515

bool defined in line 23; used 8 times

- in line 39-42(2), 49, 279, 328, 451-452(2), 543

endtoken defined in line 31; used 1 times

- in line 408

intoken defined in line 30; used 1 times

- in line 421

isgood defined in line 32; used 1 times

- in line 531

iswhite defined in line 28; used 3 times

- in line 460, 517-520(2)

max defined in line 34; never used

Last modified: 1994-02-17 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2120 |