Annotation of coherent/g/usr/bin/vi/ref.c, revision 1.1.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.