Annotation of coherent/g/usr/bin/vi/ref.c, revision 1.1

1.1     ! root        1: /* ref2.c */
        !             2: 
        !             3: /* This is a totally rewritten version of ref.  This version looks for the
        !             4:  * desired function name in the "tags" file, and then reads the header out
        !             5:  * from the source file.  There is no longer any need for a "refs" file.
        !             6:  *
        !             7:  * Usage:      ref [-a] [-t] [-f file] [-c class] tag
        !             8:  * Options:    -t         output tag info, not the description
        !             9:  *             -f file    default filename for static functions
        !            10:  *             -c class   default class names for class functions
        !            11:  */
        !            12: #ifdef __STDC__
        !            13: # include <string.h>
        !            14: # include <stdlib.h>
        !            15: #endif
        !            16: 
        !            17: #include <stdio.h>
        !            18: #include "config.h"
        !            19: 
        !            20: extern char    *cktagdir P_((char *, char *));
        !            21: extern int     getline P_((char *, int, FILE *));
        !            22: extern int     lookup P_((char *, char *));
        !            23: extern int     find P_((char *));
        !            24: extern void    usage P_((void));
        !            25: extern int     countcolons P_((char *));
        !            26: extern void    main P_((int, char **));
        !            27: extern char    *getenv P_((char *));
        !            28: 
        !            29: 
        !            30: /* This is the default path that is searched for tags */
        !            31: #if OSK
        !            32: # define DEFTAGPATH ".:/dd/defs:/dd/defs/sys:/dd/usr/src/lib:../lib:/dd/usr/lib"
        !            33: #else
        !            34: # if ANY_UNIX
        !            35: #  define DEFTAGPATH ".:/usr/include:/usr/include/sys:/usr/src/lib:../lib:/usr/local/lib"
        !            36: # else
        !            37: #  if MSDOS || TOS
        !            38: #   define DEFTAGPATH ".;C:\\include;C:\\include\\sys;C:\\lib;..\\lib"
        !            39: #   define SEP ';'
        !            40: #  else
        !            41: #   if AMIGA
        !            42: #    define DEFTAGPATH ".;Include:;Include:sys"
        !            43: #    define SEP ';'
        !            44: #   else /* any other OS */
        !            45: #    define DEFTAGPATH "."
        !            46: #   endif
        !            47: #  endif
        !            48: # endif
        !            49: #endif
        !            50: 
        !            51: #ifndef SEP
        !            52: # define SEP ':'
        !            53: #endif
        !            54: 
        !            55: 
        !            56: /* These variables reflect the command-line options given by the user. */
        !            57: int    taginfo;        /* boolean: give only the tag info? (not header?) */
        !            58: char   *def_file;      /* default filename for static functions */
        !            59: char   *def_class;     /* default classname for class members */
        !            60: int    colons;         /* #colons in tag: 0=normal, 1=static, 2=member */
        !            61: 
        !            62: /* This function checks for a tag in the "tags" file of given directory.
        !            63:  * If the tag is found, then it returns a pointer to a static buffer which
        !            64:  * contains the filename, a tab character, and a linespec for finding the
        !            65:  * the tag.  If the tag is not found in the "tags" file, or if the "tags"
        !            66:  * file cannot be opened or doesn't exist, then this function returns NULL.
        !            67:  */
        !            68: char *cktagdir(tag, dir)
        !            69:        char    *tag;   /* name of the tag to look for */
        !            70:        char    *dir;   /* name of the directory to check */
        !            71: {
        !            72:        char    buf[BLKSIZE];
        !            73:        static char found[BLKSIZE];
        !            74:        FILE    *tfile;
        !            75:        int     len;
        !            76: 
        !            77: #if AMIGA
        !            78:        if (dir[strlen(dir) - 1] == COLON)
        !            79:            sprintf(buf, "%s%s", dir, TAGS);   /* no slash after colon. */
        !            80:        else
        !            81: #endif
        !            82:        /* construct the name of the "tags" file in this directory */
        !            83:        sprintf(buf, "%s%c%s", dir, SLASH, TAGS);
        !            84: 
        !            85:        /* Try to open the tags file.  Return NULL if can't open */
        !            86: #if AMIGA
        !            87:        if (buf[0] == '.' && buf[1] == SLASH)
        !            88:            tfile = fopen(&buf[2], "r");
        !            89:        else
        !            90: #endif
        !            91:        tfile = fopen(buf, "r");
        !            92:        if (!tfile)
        !            93:        {
        !            94:                return (char *)0;
        !            95:        }
        !            96: 
        !            97:        /* compute the length of the tagname once */
        !            98:        len = strlen(tag);
        !            99: 
        !           100:        /* read lines until we get the one for this tag */
        !           101:        found[0] = '\0';
        !           102:        while (fgets(buf, sizeof buf, tfile))
        !           103:        {
        !           104:                /* is this the one we want? */
        !           105:                if (!strncmp(buf, tag, len) && buf[len] == '\t')
        !           106:                {
        !           107:                        /* we've found a match -- remember it */
        !           108:                        strcpy(found, buf);
        !           109: 
        !           110:                        /* if there is no default file, or this match is in
        !           111:                         * the default file, then we've definitely found the
        !           112:                         * one we want.  Break out of the loop now.
        !           113:                         */
        !           114:                        if (!def_file || !strncmp(&buf[len + 1], def_file, strlen(def_file)))
        !           115:                        {
        !           116:                                break;
        !           117:                        }
        !           118:                }
        !           119:        }
        !           120: 
        !           121:        /* we're through reading */
        !           122:        fclose(tfile);
        !           123: 
        !           124:        /* if there's anything in found[], use it */
        !           125:        if (found[0])
        !           126:        {
        !           127:                return &found[len + 1];
        !           128:        }
        !           129: 
        !           130:        /* else we didn't find it */
        !           131:        return (char *)0;
        !           132: }
        !           133: 
        !           134: /* This function reads a single textline from a binary file.  It returns
        !           135:  * the number of bytes read, or 0 at EOF.
        !           136:  */
        !           137: int getline(buf, limit, fp)
        !           138:        char    *buf;   /* buffer to read into */
        !           139:        int     limit;  /* maximum characters to read */
        !           140:        FILE    *fp;    /* binary stream to read from */
        !           141: {
        !           142:        int     bytes;  /* number of bytes read so far */
        !           143:        int     ch;     /* single character from file */
        !           144: 
        !           145:        for (bytes = 0, ch = 0; ch != '\n' && --limit > 0 && (ch = getc(fp)) != EOF; bytes++)
        !           146:        {
        !           147: #if MSDOS || TOS
        !           148:                /* since this is a binary file, we'll need to manually strip CR's */
        !           149:                if (ch == '\r')
        !           150:                {
        !           151:                        continue;
        !           152:                }
        !           153: #endif
        !           154:                *buf++ = ch;
        !           155:        }
        !           156:        *buf = '\0';
        !           157: 
        !           158:        return bytes;
        !           159: }
        !           160: 
        !           161: 
        !           162: /* This function reads a source file, looking for a given tag.  If it finds
        !           163:  * the tag, then it displays it and returns TRUE.  Otherwise it returns FALSE.
        !           164:  * To display the tag, it attempts to output any introductory comment, the
        !           165:  * tag line itself, and any arguments.  Arguments are assumed to immediately
        !           166:  * follow the tag line, and start with whitespace.  Comments are assumed to
        !           167:  * start with lines that begin with "/*", "//", "(*", or "--", and end at the
        !           168:  * tag line or at a blank line.
        !           169:  */
        !           170: int lookup(dir, entry)
        !           171:        char    *dir;   /* name of the directory that contains the source */
        !           172:        char    *entry; /* source filename, <Tab>, linespec */
        !           173: {
        !           174:        char    buf[BLKSIZE];   /* pathname of sourcefile */
        !           175:        long    lnum;           /* line number */
        !           176:        long    here;           /* seek position where current line began */
        !           177:        long    comment;        /* seek position of introductory comment, or -1L */
        !           178:        FILE    *sfile;         /* used for reading the source file */
        !           179:        int     len;            /* length of string */
        !           180:        char    *ptr;
        !           181: #if COHERENT
        !           182:        char    *modname;
        !           183: #endif
        !           184: 
        !           185:        /* construct the pathname of the source file */
        !           186:        strcpy(buf, dir);
        !           187:        ptr = buf + strlen(buf);
        !           188: #if AMIGA
        !           189:        if (ptr[-1] != COLON)
        !           190: #endif
        !           191:        *ptr++ = SLASH;
        !           192: #if COHERENT
        !           193:        modname = ptr;
        !           194: #endif
        !           195:        while (*entry != '\t')
        !           196:        {
        !           197:                *ptr++ = *entry++;
        !           198:        }
        !           199:        *ptr = '\0';
        !           200: #if COHERENT
        !           201:        printf("--%s--\n", modname);
        !           202: #endif
        !           203:        entry++;
        !           204: 
        !           205:        /* searching for string or number? */
        !           206:        if (*entry >= '0' && *entry <= '9')
        !           207:        {
        !           208:                /* given a specific line number */
        !           209:                lnum = atol(entry);
        !           210:                entry = (char *)0;
        !           211:        }
        !           212:        else
        !           213:        {
        !           214:                /* given a string -- strip off "/^" and "$/\n" */
        !           215:                entry += 2;
        !           216:                len = strlen(entry) - 2;
        !           217:                if (entry[len - 1] == '$')
        !           218:                {
        !           219:                        entry[len - 1] = '\n';
        !           220:                }
        !           221:                lnum = 0L;
        !           222:        }
        !           223: 
        !           224:        /* Open the file.  Note that we open the file in binary mode even
        !           225:         * though we know it is a text file, because ftell() and fseek()
        !           226:         * don't work on text files.
        !           227:         */
        !           228: #if MSDOS || TOS
        !           229:        sfile = fopen(buf, "rb");
        !           230: #else
        !           231: # if AMIGA
        !           232:        if (buf[0] == '.' && buf[1] == SLASH)
        !           233:            sfile = fopen(&buf[2], "r");
        !           234:        else
        !           235: # endif
        !           236:        sfile = fopen(buf, "r");
        !           237: #endif
        !           238:        if (!sfile)
        !           239:        {
        !           240:                /* can't open the real source file.  Try "refs" instead */
        !           241: #if AMIGA
        !           242:                if (dir[strlen(dir) - 1] == COLON)
        !           243:                        sprintf(buf, "%srefs", dir);
        !           244:                else
        !           245: #endif
        !           246:                sprintf(buf, "%s%crefs", dir, SLASH);
        !           247: #if MSDOS || TOS
        !           248:                sfile = fopen(buf, "rb");
        !           249: #else
        !           250: # if AMIGA
        !           251:                if (buf[0] == '.' && buf[1] == SLASH)
        !           252:                    sfile = fopen(&buf[2], "r");
        !           253:                else
        !           254: # endif
        !           255:                sfile = fopen(buf, "r");
        !           256: #endif
        !           257:                if (!sfile)
        !           258:                {
        !           259:                        /* failed! */
        !           260:                        return 0;
        !           261:                }
        !           262:        }
        !           263: 
        !           264:        /* search the file */
        !           265:        for (comment = -1L; here = ftell(sfile), getline(buf, BLKSIZE, sfile) > 0; )
        !           266:        {
        !           267:                /* Is this the start/end of a comment? */
        !           268:                if (comment == -1L)
        !           269:                {
        !           270:                        /* starting a comment? */
        !           271:                        if (buf[0] == '/' && buf[1] == '*'
        !           272:                         || buf[0] == '/' && buf[1] == '/'
        !           273:                         || buf[0] == '(' && buf[1] == '*'
        !           274:                         || buf[0] == '-' && buf[1] == '-')
        !           275:                        {
        !           276:                                comment = here;
        !           277:                        }
        !           278:                }
        !           279:                else
        !           280:                {
        !           281:                        /* ending a comment? */
        !           282:                        if (buf[0] == '\n' || buf[0] == '#')
        !           283:                        {
        !           284:                                comment = -1L;
        !           285:                        }
        !           286:                }
        !           287: 
        !           288:                /* is this the tag line? */
        !           289:                if (--lnum == 0L || (entry && !strncmp(buf, entry, len)))
        !           290:                {
        !           291:                        /* if there were introductory comments, show them */
        !           292:                        if (comment != -1L)
        !           293:                        {
        !           294:                                fseek(sfile, comment, 0);
        !           295:                                while (comment != here)
        !           296:                                {
        !           297:                                        getline(buf, BLKSIZE, sfile);
        !           298:                                        fputs(buf, stdout);
        !           299:                                        comment = ftell(sfile);
        !           300:                                }
        !           301: 
        !           302:                                /* re-fetch the tag line */
        !           303:                                fgets(buf, BLKSIZE, sfile);
        !           304:                        }
        !           305: 
        !           306:                        /* show the tag line */
        !           307:                        fputs(buf, stdout);
        !           308: 
        !           309:                        /* show any argument lines */
        !           310:                        while (getline(buf, BLKSIZE, sfile) > 0
        !           311:                            && buf[0] != '#'
        !           312:                            && strchr(buf, '{') == (char *)0)
        !           313:                        {
        !           314:                                fputs(buf, stdout);
        !           315:                        }
        !           316: 
        !           317:                        /* Done!  Close the file, and return TRUE */
        !           318:                        fclose(sfile);
        !           319:                        return 1;
        !           320:                }
        !           321:        }
        !           322: 
        !           323:        /* not found -- return FALSE */
        !           324:        return 0;
        !           325: }
        !           326: 
        !           327: /* This function searches through the entire search path for a given tag.
        !           328:  * If it finds the tag, then it displays the info and returns TRUE;
        !           329:  * otherwise it returns FALSE.
        !           330:  */
        !           331: int find(tag)
        !           332:        char    *tag;   /* the tag to look up */
        !           333: {
        !           334:        char    *tagpath;
        !           335:        char    dir[80];
        !           336:        char    *ptr;
        !           337:        int     len;
        !           338: 
        !           339:        if (colons == 1)
        !           340:        {
        !           341:                /* looking for static function -- only look in current dir */
        !           342:                tagpath = ".";
        !           343:        }
        !           344:        else
        !           345:        {
        !           346:                /* get the tagpath from the environment.  Default to DEFTAGPATH */
        !           347:                tagpath = getenv("TAGPATH");
        !           348:                if (!tagpath)
        !           349:                {
        !           350:                        tagpath = DEFTAGPATH;
        !           351:                }
        !           352:        }
        !           353: 
        !           354:        /* for each entry in the path... */
        !           355:        while (*tagpath)
        !           356:        {
        !           357:                /* Copy the entry into the dir[] buffer */
        !           358:                for (ptr = dir; *tagpath && *tagpath != SEP; tagpath++)
        !           359:                {
        !           360:                        *ptr++ = *tagpath;
        !           361:                }
        !           362:                if (*tagpath == SEP)
        !           363:                {
        !           364:                        tagpath++;
        !           365:                }
        !           366: 
        !           367:                /* if the entry ended with "/tags", then strip that off */
        !           368:                len = strlen(TAGS);
        !           369:                if (&dir[len] < ptr && ptr[-len - 1] == SLASH && !strncmp(&ptr[-len], TAGS, len))
        !           370:                {
        !           371:                        ptr -= len + 1;
        !           372:                }
        !           373: 
        !           374:                /* if the entry is now an empty string, then assume "." */
        !           375:                if (ptr == dir)
        !           376:                {
        !           377:                        *ptr++ = '.';
        !           378:                }
        !           379:                *ptr = '\0';
        !           380: 
        !           381:                /* look for the tag in this path.  If found, then display it
        !           382:                 * and exit.
        !           383:                 */
        !           384:                ptr = cktagdir(tag, dir);
        !           385:                if (ptr)
        !           386:                {
        !           387:                        /* just supposed to display tag info? */
        !           388:                        if (taginfo)
        !           389:                        {
        !           390:                                /* then do only that! */
        !           391:                                if (strcmp(dir, "."))
        !           392:                                {
        !           393:                                        printf("%s%c%s", dir, SLASH, ptr);
        !           394:                                }
        !           395:                                else
        !           396:                                {
        !           397:                                        /* avoid leading "./" if possible */
        !           398:                                        fputs(ptr, stdout);
        !           399:                                }
        !           400:                                return 1;
        !           401:                        }
        !           402:                        else
        !           403:                        {
        !           404:                                /* else look up the declaration of the thing */
        !           405:                                return lookup(dir, ptr);
        !           406:                        }
        !           407:                }
        !           408:        }
        !           409: 
        !           410:        /* if we get here, then the tag wasn't found anywhere */
        !           411:        return 0;
        !           412: }
        !           413: 
        !           414: void usage()
        !           415: {
        !           416:        fputs("usage: ref [-a] [-t] [-c class] [-f file] tag\n", stderr);
        !           417:        fputs("   -a        function's args may be flush against left margin\n", stderr);
        !           418:        fputs("   -t        output tag info, instead of the function header\n", stderr);
        !           419:        fputs("   -f File   tag might be a static function in File\n", stderr);
        !           420:        fputs("   -c Class  tag might be a member of class Class\n", stderr);
        !           421:        exit(2);
        !           422: }
        !           423: 
        !           424: 
        !           425: int countcolons(str)
        !           426:        char    *str;
        !           427: {
        !           428:        while (*str != ':' && *str)
        !           429:        {
        !           430:                str++;
        !           431:        }
        !           432:        if (str[0] != ':')
        !           433:        {
        !           434:                return 0;
        !           435:        }
        !           436:        else if (str[1] != ':')
        !           437:        {
        !           438:                return 1;
        !           439:        }
        !           440:        return 2;
        !           441: }
        !           442: 
        !           443: void main(argc, argv)
        !           444:        int     argc;
        !           445:        char    **argv;
        !           446: {
        !           447:        char    def_tag[100];   /* used to build tag name with default file/class */
        !           448:        int     i;
        !           449: 
        !           450:        /* parse flags */
        !           451:        for (i = 1; i < argc && argv[i][0] == '-'; i++)
        !           452:        {
        !           453:                switch (argv[i][1])
        !           454:                {
        !           455:                  case 't':
        !           456:                        taginfo = 1;
        !           457:                        break;
        !           458: 
        !           459:                  case 'f':
        !           460:                        if (argv[i][2])
        !           461:                        {
        !           462:                                def_file = &argv[i][2];
        !           463:                        }
        !           464:                        else if (++i < argc)
        !           465:                        {
        !           466:                                def_file = argv[i];
        !           467:                        }
        !           468:                        else
        !           469:                        {
        !           470:                                usage();
        !           471:                        }
        !           472:                        break;
        !           473: 
        !           474:                  case 'c':
        !           475:                        if (argv[i][2])
        !           476:                        {
        !           477:                                def_class = &argv[i][2];
        !           478:                        }
        !           479:                        else if (++i < argc)
        !           480:                        {
        !           481:                                def_class = argv[i];
        !           482:                        }
        !           483:                        else
        !           484:                        {
        !           485:                                usage();
        !           486:                        }
        !           487:                        break;
        !           488: 
        !           489:                  default:
        !           490:                        usage();
        !           491:                }
        !           492:        }
        !           493: 
        !           494:        /* if no tag was given, complain */
        !           495:        if (i + 1 != argc)
        !           496:        {
        !           497:                usage();
        !           498:        }
        !           499: 
        !           500:        /* does the tag have an explicit class or file? */
        !           501:        colons = countcolons(argv[i]);
        !           502: 
        !           503:        /* if not, then maybe try some defaults */
        !           504:        if (colons == 0)
        !           505:        {
        !           506:                /* try a static function in the file first */
        !           507:                if (def_file)
        !           508:                {
        !           509:                        sprintf(def_tag, "%s:%s", def_file, argv[i]);
        !           510:                        colons = 1;
        !           511:                        if (find(def_tag))
        !           512:                        {
        !           513:                                exit(0);
        !           514:                        }
        !           515:                }
        !           516: 
        !           517:                /* try a member function for a class */
        !           518:                if (def_class)
        !           519:                {
        !           520:                        sprintf(def_tag, "%s::%s", def_class, argv[i]);
        !           521:                        colons = 2;
        !           522:                        if (find(def_tag))
        !           523:                        {
        !           524:                                exit(0);
        !           525:                        }
        !           526:                }
        !           527: 
        !           528:                /* oh, well */
        !           529:                colons = 0;
        !           530:        }
        !           531: 
        !           532:        /* find the tag */
        !           533:        if (find(argv[i]))
        !           534:        {
        !           535:                exit(0);
        !           536:        }
        !           537: 
        !           538:        exit(1);
        !           539:        /*NOTREACHED*/
        !           540: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.