home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / programming / mkid / src / lid.c < prev    next >
C/C++ Source or Header  |  1991-02-01  |  17KB  |  898 lines

  1. static char copyright[] = "@(#)Copyright (c) 1986, Greg McGary";
  2. static char sccsid[] = "@(#)lid.c    1.4 86/11/06";
  3.  
  4. #include    "bool.h"
  5. #include    <stdio.h>
  6. #include    "string.h"
  7. #include    <ctype.h>
  8. #include    "radix.h"
  9. #include    "id.h"
  10. #include    "bitops.h"
  11. #include    "extern.h"
  12. #ifdef AMIGA
  13. #include    <dos.h>
  14. #endif
  15.  
  16. #ifdef REGEX
  17. extern char *regex();
  18. extern char *regcmp();
  19. #endif
  20. #ifdef RE_EXEC
  21. extern char *re_comp();
  22. extern int re_exec();
  23. #endif
  24.  
  25. bool isMagic();
  26. char **bitsToArgv();
  27. char *fileRE();
  28. char *strcpos();
  29. int skipToArgv();
  30. int findAnchor();
  31. int findApropos();
  32. #if REGEX || RE_EXEC
  33. int findRegExp();
  34. #endif
  35. int findNonUnique();
  36. int findNumber();
  37. int findPlain();
  38. int idCompare();
  39. long searchName();
  40. void editId();
  41. void grepId();
  42. void lookId();
  43.  
  44. #ifdef USG
  45. #define    TOLOWER(c)    (isupper(c) ? _tolower(c) : (c))
  46. #else
  47. #define    TOLOWER(c)    (isupper(c) ? tolower(c) : (c))
  48. #endif
  49.  
  50. /*
  51. *  Sorry about all the globals, but it's really cleaner this way.
  52. */
  53. FILE        *IdFILE;
  54. bool        Merging;
  55. bool        Radix;
  56. char        *IdDir;
  57. long        AnchorOffset;
  58. int        BitArraySize;
  59. struct idhead    Idh;
  60. struct idarg    *IdArgs;
  61. int        (*FindFunc)() = NULL;
  62. int        Solo = 0;
  63. #define    IGNORE_SOLO(buf) \
  64. ( \
  65.        (Solo == '-' && !(ID_FLAGS(buf) & IDN_SOLO)) \
  66.     || (Solo == '+' &&  (ID_FLAGS(buf) & IDN_SOLO)) \
  67. )
  68.  
  69. char *MyName;
  70. static void
  71. usage()
  72. {
  73.     fprintf(stderr, "Usage: %s [-f<file>] [-u<n>] [-mewdoxas] patterns...\n", MyName);
  74.     exit(1);
  75. }
  76. main(argc, argv)
  77.     int        argc;
  78.     char        **argv;
  79. {
  80.     char        *idFile = IDFILE;
  81.     char        *arg;
  82.     long        val;
  83.     void        (*doit)();
  84.     bool        forceMerge = FALSE;
  85.     int        uniqueLimit = 0;
  86.     int        op;
  87.  
  88.     MyName = basename(GETARG(argc, argv));
  89.  
  90.     while (argc) {
  91.         arg = GETARG(argc, argv);
  92.         switch (op = *arg++)
  93.         {
  94.         case '-':
  95.         case '+':
  96.             break;
  97.         default:
  98.             UNGETARG(argc, argv);
  99.             goto argsdone;
  100.         }
  101.         while (*arg) switch (*arg++)
  102.         {
  103.         case 'f': idFile = arg; goto nextarg;
  104.         case 'u': uniqueLimit = stoi(arg); goto nextarg;
  105.         case 'm': forceMerge = TRUE; break;
  106. #if REGEX || RE_EXEC
  107.         case 'e': FindFunc = findRegExp; break;
  108. #endif
  109.         case 'w': FindFunc = findPlain; break;
  110.         case 'd': Radix |= RADIX_DEC; break;
  111.         case 'o': Radix |= RADIX_OCT; break;
  112.         case 'x': Radix |= RADIX_HEX; break;
  113.         case 'a': Radix |= RADIX_ALL; break;
  114.         case 's': Solo = op; break;
  115.         default:
  116.             usage();
  117.         }
  118.     nextarg:;
  119.     }
  120. argsdone:
  121.  
  122.     IdDir = getDirToName(idFile);
  123.     idFile = spanPath(IdDir, idFile);
  124.     if ((IdFILE = initID(idFile, &Idh, &IdArgs)) == NULL) {
  125.         filerr("open", idFile);
  126.         exit(1);
  127.     }
  128.     BitArraySize = (Idh.idh_pthc + 7) >> 3;
  129.  
  130.     switch (MyName[0])
  131.     {
  132.     case 'a':
  133.         FindFunc = findApropos;
  134.         /*FALLTHROUGH*/
  135.     case 'l':
  136.         doit = lookId;
  137.         break;
  138.     case 'g':
  139.         doit = grepId;
  140.         break;
  141.     case 'e':
  142.         doit = editId;
  143.         break;
  144.     default:
  145.         MyName = "[alge]id";
  146.         usage();
  147.     }
  148.  
  149.     if (argc == 0) {
  150.         UNGETARG(argc, argv);
  151. #ifdef AMIGA
  152.         *argv = "";
  153. #endif
  154. #ifdef UNIX
  155.         *argv = ".";
  156. #endif
  157.     }
  158.  
  159.     while (argc) {
  160.         arg = GETARG(argc, argv);
  161.         if (FindFunc)
  162.             ;
  163.         else if ((radix(arg)) && (val = stoi(arg)) >= 0)
  164.             FindFunc = findNumber;
  165. #if REGEX || RE_EXEC
  166.         else if (isMagic(arg))
  167.             FindFunc = findRegExp;
  168. #endif
  169.         else if (arg[0] == '^')
  170.             FindFunc = findAnchor;
  171.         else
  172.             FindFunc = findPlain;
  173.  
  174.         if ((doit == lookId && !forceMerge)
  175.         || (FindFunc == findNumber && bitCount(Radix) > 1 && val > 7))
  176.             Merging = FALSE;
  177.         else
  178.             Merging = TRUE;
  179.  
  180.         if (uniqueLimit) {
  181.             if (!findNonUnique(uniqueLimit, doit))
  182.                 fprintf(stderr, "All identifiers are unique within the first %d characters\n", uniqueLimit);
  183.             exit(0);
  184.         } else if (!(*FindFunc)(arg, doit)) {
  185.             fprintf(stderr, "%s: not found\n", arg);
  186.             continue;
  187.         }
  188.     }
  189.     exit(0);
  190. }
  191.  
  192. void
  193. lookId(name, argv)
  194.     char        *name;
  195.     register char    **argv;
  196. {
  197.     register char    *arg;
  198.     register bool    crunching = FALSE;
  199.     register char    *dir;
  200.  
  201.     printf("%-14s ", name);
  202.     while (*argv) {
  203.         arg = *argv++;
  204.         if (*argv && canCrunch(arg, *argv)) {
  205. #ifdef AMIGA
  206.             if (crunching)
  207.                 printf(",%s", rootName(arg));
  208.             else if ((dir = dirname(arg)) != NULL) {
  209.                 if (*dir == '\0')
  210.                     printf("{%s", rootName(arg));
  211.                 else
  212.                     printf("%s%s%s",dir,
  213.                        dir[strlen(dir)-1] == ':' ? "" : "/",
  214.                        rootName(arg));
  215.             }
  216. #endif
  217. #ifdef UNIX
  218.             if (crunching)
  219.                 printf(",%s", rootName(arg));
  220.             else if ((dir = dirname(arg)) && dir[0] == '.' &&
  221.                  dir[1] == '\0')
  222.                 printf("{%s", rootName(arg));
  223.             else
  224.                 printf("%s/{%s", dir, rootName(arg));
  225. #endif
  226.             /*}}*/
  227.             crunching = TRUE;
  228.         } else {
  229.             if (crunching) /*{*/
  230.                 printf(",%s}%s", rootName(arg), suffName(arg));
  231.             else
  232.                 fputs(arg, stdout);
  233.             crunching = FALSE;
  234.             if (*argv)
  235.                 putchar(' ');
  236.         }
  237.     }
  238.     putchar('\n');
  239. }
  240.  
  241. void
  242. grepId(name, argv)
  243.     char        *name;
  244.     char        **argv;
  245. {
  246.     FILE        *gidFILE;
  247.     char        *gidName;
  248.     char        buf[BUFSIZ];
  249.     char        *delimit = "[^a-zA-Z0-9_]";
  250.     char        *re;
  251.     char        *reCompiled;
  252.     int        lineNumber;
  253.  
  254.     if (!Merging || (re = fileRE(name, delimit, delimit)) == NULL)
  255.         re = NULL;
  256. #ifdef REGEX
  257.     else if ((reCompiled = regcmp(re, 0)) == NULL) {
  258.         fprintf(stderr, "%s: Syntax Error: %s\n", MyName, re);
  259.         return;
  260.     }
  261. #endif
  262. #ifdef RE_EXEC
  263.     else if ((reCompiled = re_comp(re)) != NULL) {
  264.         fprintf(stderr, "%s: Syntax Error: %s (%s)\n", MyName, re, reCompiled);
  265.         return;
  266.     }
  267. #endif
  268.  
  269.     buf[0] = ' ';    /* sentry */
  270.     while (*argv) {
  271.         if ((gidFILE = fopen(gidName = *argv++, "r")) == NULL) {
  272.             filerr("open", gidName);
  273.             continue;
  274.         }
  275.         lineNumber = 0;
  276.         while (fgets(&buf[1], sizeof(buf), gidFILE)) {
  277.             lineNumber++;
  278.             if (re) {
  279. #ifdef REGEX
  280.                 if (regex(reCompiled, buf) == NULL)
  281. #endif
  282. #ifdef RE_EXEC
  283.                 if (!re_exec(buf))
  284. #endif
  285.                     continue;
  286.             } else if (!wordMatch(name, buf))
  287.                 continue;
  288.             printf("%s:%d: %s", gidName, lineNumber, &buf[1]);
  289.         }
  290.         fclose(gidFILE);
  291.     }
  292. }
  293.  
  294. void
  295. editId(name, argv)
  296.     char        *name;
  297.     char        **argv;
  298. {
  299.     char        reBuf[BUFSIZ];
  300.     char        edArgBuf[BUFSIZ];
  301.     char        *re;
  302.     int        c;
  303.     int        skip;
  304.     static char    *editor, *eidArg, *eidRightDel, *eidLeftDel;
  305.     static char    editbuf[128];
  306.  
  307.     if (editor == NULL && (editor = getenv("EDITOR")) == NULL) {
  308. #ifdef UNIX
  309.         char    *ucb_vi = "/usr/ucb/vi";
  310.         char    *bin_vi = "/usr/bin/vi";
  311.  
  312.         if (access(ucb_vi, 01) == 0)
  313.             editor = ucb_vi;
  314.         else if (access(bin_vi, 01) == 0)
  315.             editor = bin_vi;
  316.         else
  317.             editor = "/bin/ed";    /* YUCK! */
  318.         if (editor == ucb_vi || editor == bin_vi) {
  319.             eidArg = "+1;/%s/";
  320.             eidLeftDel = "\\<";
  321.             eidRightDel = "\\>";
  322.         }
  323. #endif
  324.     }
  325.     if (eidLeftDel == NULL) {
  326.         eidArg = getenv("EIDARG");
  327.         if ((eidLeftDel = getenv("EIDLDEL")) == NULL)
  328.             eidLeftDel = "";
  329.         if ((eidRightDel = getenv("EIDRDEL")) == NULL)
  330.             eidRightDel = "";
  331.     }
  332.  
  333.     lookId(name, argv);
  334.     savetty();
  335.     for (;;) {
  336.         printf("Edit? [y1-9^S/nq] "); fflush(stdout);
  337.         chartty();
  338.         c = (getchar() & 0177);
  339.         restoretty();
  340.         switch (TOLOWER(c))
  341.         {
  342.         case '/': case ('s'&037):
  343.             putchar('/');
  344.             /*FALLTHROUGH*/
  345.             if ((skip = skipToArgv(argv)) < 0)
  346.                 continue;
  347.             argv += skip;
  348.             goto editit;
  349.         case '1': case '2': case '3': case '4':
  350.         case '5': case '6': case '7': case '8': case '9':
  351.             putchar(c);
  352.             skip = c - '0';
  353.             break;
  354.         case 'y':
  355.             putchar(c);
  356.             /*FALLTHROUGH*/
  357.         case '\n':
  358.         case '\r':
  359.             skip = 0;
  360.             break;
  361.         case 'q':
  362.             putchar(c);
  363.             putchar('\n');
  364.             exit(0);
  365.         case 'n':
  366.             putchar(c);
  367.             putchar('\n');
  368.             return;
  369.         default:
  370.             putchar(c);
  371.             putchar('\n');
  372.             continue;
  373.         }
  374.  
  375.         putchar('\n');
  376.         while (skip--)
  377.             if (*++argv == NULL)
  378.                 continue;
  379.         break;
  380.     }
  381. editit:
  382.  
  383. #ifdef AMIGA
  384.     if (editor == NULL)
  385.     {
  386. /* let's assume getenv mallocs for multitasking */
  387.         printf("\nEditor? ");
  388.         if (!gets(editbuf))
  389.             goto cant_edit;
  390.         editor = editbuf;
  391.     }
  392. #endif
  393.     if (!Merging || (re = fileRE(name, eidLeftDel, eidRightDel)) == NULL)
  394.         sprintf(re = reBuf, "%s%s%s", eidLeftDel, name, eidRightDel);
  395.  
  396. #ifdef UNIX
  397.     switch (fork())
  398.     {
  399.     case -1:
  400.         fprintf(stderr, "%s: Cannot fork (%s)\n", MyName, uerror());
  401.         exit(1);
  402.     case 0:
  403.         argv--;
  404.         if (eidArg) {
  405.             argv--;
  406.             sprintf(edArgBuf, eidArg, re);
  407.             argv[1] = edArgBuf;
  408.         }
  409.         argv[0] = editor;
  410.         execv(editor, argv);
  411.         filerr("exec", editor);
  412.     default:
  413.         wait(0);
  414.         break;
  415.     }
  416. #endif UNIX
  417.  
  418. #ifdef AMIGA 
  419. #ifdef LATTICE
  420.     {
  421.         struct ProcID pid; /* from dos.h */
  422.  
  423.         argv--;
  424.         if (eidArg) {
  425.             argv--;
  426.             sprintf(edArgBuf, eidArg, re);
  427.             argv[1] = edArgBuf;
  428.         }
  429.         argv[0] = editor;
  430. #ifdef DEBUG
  431.         printf("Execing %s %s\n",editor,argv[1]);
  432. #endif
  433.         if (forkv(editor,argv,NULL,&pid) == -1)
  434.             goto cant_edit;
  435.         wait(&pid);
  436.     }
  437.     return;
  438.  
  439. cant_edit:
  440.     printf("Can't fork editor %s!\n",editor);
  441.     editor = NULL;    /* so it'll ask him */
  442. #else
  443.     printf("Fork code not written for non-Lattice!\n");
  444.     editor = NULL;    /* so it'll ask him */
  445. #endif LATTICE
  446. #endif AMIGA
  447. }
  448.  
  449. int
  450. skipToArgv(argv)
  451.     char        **argv;
  452. {
  453.     char        pattern[BUFSIZ];
  454.     int        count;
  455.  
  456.     if (gets(pattern) == NULL)
  457.         return -1;
  458.     
  459.     for (count = 0; *argv; count++, argv++)
  460.         if (strcpos(*argv, pattern))
  461.             return count;
  462.     return -1;
  463. }
  464.  
  465. int
  466. findPlain(arg, doit)
  467.     char        *arg;
  468.     void        (*doit)();
  469. {
  470.     static char    *buf, *bitArray;
  471.     int        size;
  472.  
  473.     if (searchName(arg) == 0)
  474.         return 0;
  475.     if (buf == NULL) {
  476.         buf = malloc(Idh.idh_bsiz);
  477.         bitArray = malloc(BitArraySize);
  478.     }
  479.     bzero(bitArray, BitArraySize);
  480.  
  481.     if ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) == 0)
  482.         return 0;
  483.     size++;
  484.     getsFF(&buf[size], IdFILE);
  485.     if (IGNORE_SOLO(buf))
  486.         return 0;
  487.  
  488.     vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  489.     (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  490.     return 1;
  491. }
  492.  
  493. int
  494. findAnchor(arg, doit)
  495.     register char    *arg;
  496.     void        (*doit)();
  497. {
  498.     static char    *buf, *bitArray;
  499.     int        count, size;
  500.     int        len;
  501.  
  502.     if (searchName(++arg) == 0)
  503.         return 0;
  504.  
  505.     if (buf == NULL) {
  506.         buf = malloc(Idh.idh_bsiz);
  507.         bitArray = malloc(BitArraySize);
  508.     }
  509.     bzero(bitArray, BitArraySize);
  510.  
  511.     len = strlen(arg);
  512.     count = 0;
  513.     while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  514.         size++;
  515.         getsFF(&buf[size], IdFILE);
  516.         if (IGNORE_SOLO(buf))
  517.             continue;
  518.         if (!strnequ(arg, ID_STRING(buf), len))
  519.             break;
  520.         vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  521.         if (!Merging) {
  522.             (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  523.             bzero(bitArray, BitArraySize);
  524.         }
  525.         count++;
  526.     }
  527.     if (Merging && count)
  528.         (*doit)(--arg, bitsToArgv(bitArray));
  529.  
  530.     return count;
  531. }
  532.  
  533. #if REGEX || RE_EXEC
  534. int
  535. findRegExp(re, doit)
  536.     char        *re;
  537.     void        (*doit)();
  538. {
  539.     static char    *buf, *bitArray;
  540.     int        count, size;
  541.     char        *reCompiled;
  542.  
  543. #ifdef REGEX
  544.     if ((reCompiled = regcmp(re, 0)) == NULL) {
  545.         fprintf(stderr, "%s: Syntax Error: %s\n", MyName, re);
  546.         return 0;
  547.     }
  548. #endif
  549. #ifdef RE_EXEC
  550.     if ((reCompiled = re_comp(re)) != NULL) {
  551.         fprintf(stderr, "%s: Syntax Error: %s (%s)\n", MyName, re, reCompiled);
  552.         return 0;
  553.     }
  554. #endif
  555.     fseek(IdFILE, Idh.idh_namo, 0);
  556.  
  557.     if (buf == NULL) {
  558.         buf = malloc(Idh.idh_bsiz);
  559.         bitArray = malloc(BitArraySize);
  560.     }
  561.     bzero(bitArray, BitArraySize);
  562.  
  563.     count = 0;
  564.     while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  565.         size++;
  566.         getsFF(&buf[size], IdFILE);
  567.         if (IGNORE_SOLO(buf))
  568.             continue;
  569. #ifdef REGEX
  570.         if (regex(reCompiled, ID_STRING(buf)) == NULL)
  571. #endif
  572. #ifdef RE_EXEC
  573.         if (!re_exec(ID_STRING(buf)))
  574. #endif
  575.             continue;
  576.         vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  577.         if (!Merging) {
  578.             (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  579.             bzero(bitArray, BitArraySize);
  580.         }
  581.         count++;
  582.     }
  583.     if (Merging && count)
  584.         (*doit)(re, bitsToArgv(bitArray));
  585.  
  586.     return count;
  587. }
  588. #endif
  589.  
  590. int
  591. findNumber(arg, doit)
  592.     char        *arg;
  593.     void        (*doit)();
  594. {
  595.     static char    *buf, *bitArray;
  596.     int        count, size;
  597.     register int    rdx = 0;
  598.     register int    val;
  599.     register bool    hitDigits = FALSE;
  600.  
  601.     if ((val = stoi(arg)) <= 7)
  602.         rdx |= RADIX_ALL;
  603.     else
  604.         rdx = radix(arg);
  605.     fseek(IdFILE, Idh.idh_namo, 0);
  606.  
  607.     if (buf == NULL) {
  608.         buf = malloc(Idh.idh_bsiz);
  609.         bitArray = malloc(BitArraySize);
  610.     }
  611.     bzero(bitArray, BitArraySize);
  612.  
  613.     count = 0;
  614.     while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  615.         size++;
  616.         getsFF(&buf[size], IdFILE);
  617.         if (hitDigits) {
  618.             if (!isdigit(*ID_STRING(buf)))
  619.                 break;
  620.         } else if (isdigit(*ID_STRING(buf)))
  621.             hitDigits = TRUE;
  622.  
  623.         if (!((Radix ? Radix : rdx) & radix(ID_STRING(buf)))
  624.         || stoi(ID_STRING(buf)) != val)
  625.             continue;
  626.         vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  627.         if (!Merging) {
  628.             (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  629.             bzero(bitArray, BitArraySize);
  630.         }
  631.         count++;
  632.     }
  633.     if (Merging && count)
  634.         (*doit)(arg, bitsToArgv(bitArray));
  635.  
  636.     return count;
  637. }
  638.  
  639. /*
  640.     Find identifiers that are non-unique within
  641.     the first `count' characters.
  642. */
  643. int
  644. findNonUnique(limit, doit)
  645.     int        limit;
  646.     void        (*doit)();
  647. {
  648.     static char    *buf1, *buf2, *bitArray;
  649.     register char    *old;
  650.     register char    *new;
  651.     register int    consecutive;
  652.     char        *cptmp;
  653.     int        itmp;
  654.     int        count, oldsize, newsize = 0;    /* added init, REJ */
  655.     char        *name;
  656.  
  657.     if (limit <= 1)
  658.         usage();
  659.  
  660.     fseek(IdFILE, Idh.idh_namo, 0);
  661.  
  662.     if (buf1 == NULL) {
  663.         buf1 = malloc(Idh.idh_bsiz);
  664.         buf2 = malloc(Idh.idh_bsiz);
  665.         bitArray = malloc(BitArraySize);
  666.     }
  667.     bzero(bitArray, BitArraySize);
  668.  
  669.     name = calloc(1, limit+2);
  670.     name[0] = '^';
  671.     old = buf1;
  672.     *ID_STRING(new = buf2) = '\0';
  673.     count = consecutive = 0;
  674.     while ((oldsize = fgets0(old, Idh.idh_bsiz, IdFILE)) > 0) {
  675.         oldsize++;
  676.         getsFF(&old[oldsize], IdFILE);
  677.         if (!(ID_FLAGS(old) & IDN_NAME))
  678.             continue;
  679.         cptmp = old; old = new; new = cptmp;
  680. /* DANGER! newsize is unitialized! REJ (make that was) */
  681.         itmp = oldsize; oldsize = newsize; newsize = itmp;
  682.         if (!strnequ(ID_STRING(new), ID_STRING(old), limit)) {
  683.             if (consecutive && Merging) {
  684.                 strncpy(&name[1], ID_STRING(old), limit); 
  685.                 (*doit)(name, bitsToArgv(bitArray));
  686.             }
  687.             consecutive = 0;
  688.             continue;
  689.         }
  690.         if (!consecutive++) {
  691.             vecToBits(bitArray, &old[oldsize], Idh.idh_vecc);
  692.             if (!Merging) {
  693.                 (*doit)(ID_STRING(old), bitsToArgv(bitArray));
  694.                 bzero(bitArray, BitArraySize);
  695.             }
  696.             count++;
  697.         }
  698.         vecToBits(bitArray, &new[newsize], Idh.idh_vecc);
  699.         if (!Merging) {
  700.             (*doit)(ID_STRING(new), bitsToArgv(bitArray));
  701.             bzero(bitArray, BitArraySize);
  702.         }
  703.         count++;
  704.     }
  705.  
  706.     return count;
  707. }
  708.  
  709. int
  710. findApropos(arg, doit)
  711.     char        *arg;
  712.     void        (*doit)();
  713. {
  714.     static char    *buf, *bitArray;
  715.     int        count, size;
  716.  
  717.     fseek(IdFILE, Idh.idh_namo, 0);
  718.  
  719.     if (buf == NULL) {
  720.         buf = malloc(Idh.idh_bsiz);
  721.         bitArray = malloc(BitArraySize);
  722.     }
  723.     bzero(bitArray, BitArraySize);
  724.  
  725.     count = 0;
  726.     while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  727.         size++;
  728.         getsFF(&buf[size], IdFILE);
  729.         if (IGNORE_SOLO(buf))
  730.             continue;
  731.         if (strcpos(ID_STRING(buf), arg) == NULL)
  732.             continue;
  733.         vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  734.         if (!Merging) {
  735.             (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  736.             bzero(bitArray, BitArraySize);
  737.         }
  738.         count++;
  739.     }
  740.     if (Merging && count)
  741.         (*doit)(arg, bitsToArgv(bitArray));
  742.  
  743.     return count;
  744. }
  745.  
  746. /*
  747.     if string `s2' occurs in `s1', return a pointer to the
  748.     first match.  Ignore differences in alphabetic case.
  749. */
  750. char *
  751. strcpos(s1, s2)
  752.     char        *s1;
  753.     char        *s2;
  754. {
  755.     register char    *s1p;
  756.     register char    *s2p;
  757.     char        *s1last;
  758.  
  759.     for (s1last = &s1[strlen(s1) - strlen(s2)]; s1 <= s1last; s1++)
  760.         for (s1p = s1, s2p = s2; TOLOWER(*s1p) == TOLOWER(*s2p); s1p++)
  761.             if (*++s2p == '\0')
  762.                 return s1;
  763.     return NULL;
  764. }
  765.  
  766. /*
  767.     Convert the regular expression that we used to
  768.     locate identifiers in the id database into one
  769.     suitable for locating the identifiers in files.
  770. */
  771. char *
  772. fileRE(name0, leftDelimit, rightDelimit)
  773.     char        *name0;
  774.     char        *leftDelimit;
  775.     char        *rightDelimit;
  776. {
  777.     static char    reBuf[BUFSIZ];
  778.     register char    *name = name0;
  779.  
  780.     if (FindFunc == findNumber && Merging) {
  781.         sprintf(reBuf, "%s0*[Xx]*0*%d[Ll]*%s", leftDelimit, stoi(name), rightDelimit);
  782.         return reBuf;
  783.     }
  784.  
  785.     if (!isMagic(name) && name[0] != '^')
  786.         return NULL;
  787.  
  788.     if (name[0] == '^')
  789.         name0++;
  790.     else
  791.         leftDelimit = "";
  792.     while (*++name)
  793.         ;
  794.     if (*--name == '$')
  795.         *name = '\0';
  796.     else
  797.         rightDelimit = "";
  798.  
  799.     sprintf(reBuf, "%s%s%s", leftDelimit, name0, rightDelimit);
  800.     return reBuf;
  801. }
  802.  
  803. long
  804. searchName(name)
  805.     char        *name;
  806. {
  807.     long        offset;
  808.  
  809.     AnchorOffset = 0;
  810.     offset = (long)bsearch(name, (char *)(Idh.idh_namo-1), Idh.idh_endo-(Idh.idh_namo-1), 1, idCompare);
  811.     if (offset == 0)
  812.         offset = AnchorOffset;
  813.     if (offset == 0)
  814.         return 0;
  815.     fseek(IdFILE, offset, 0);
  816.     skipFF(IdFILE);
  817.     return ftell(IdFILE);
  818. }
  819.  
  820. int
  821. idCompare(key, offset)
  822.     register char    *key;
  823.     long        offset;
  824. {
  825.     register int    c;
  826.  
  827.     fseek(IdFILE, offset, 0);
  828.     skipFF(IdFILE);
  829.     getc(IdFILE);
  830.  
  831.     while (*key == (c = getc(IdFILE)))
  832.         if (*key++ == '\0')
  833.             return 0;
  834.     if (*key == '\0' && FindFunc == findAnchor)
  835.         AnchorOffset = offset;
  836.  
  837.     return *key - c;
  838. }
  839.  
  840. /*
  841.     Are there any magic Regular Expression meta-characters in name??
  842. */
  843. bool
  844. isMagic(name)
  845.     register char    *name;
  846. {
  847.     char        *magichar = "[]{}().*+^$";
  848.     int        backslash = 0;
  849.  
  850.     if (*name == '^')
  851.         name++;
  852.     while (*name) {
  853.         if (*name == '\\')
  854.             name++, backslash++;
  855.         else if (strchr(magichar, *name))
  856.             return TRUE;
  857.         name++;
  858.     }
  859.     if (backslash)
  860.         while (*name) {
  861.             if (*name == '\\')
  862.                 strcpy(name, name+1);
  863.             name++;
  864.         }
  865.     return FALSE;
  866. }
  867.  
  868. char **
  869. bitsToArgv(bitArray)
  870.     char        *bitArray;
  871. {
  872.     static char    **argv;
  873.     struct idarg    *idArgs;
  874.     register char    **av;
  875.     register int    i;
  876. #define    ARGV1stPATH    3 /* available argv[] slots before first pathname */
  877.  
  878.     if (argv == NULL)
  879.         argv = (char **)malloc(sizeof(char *) * (Idh.idh_pthc + ARGV1stPATH + 2));
  880.  
  881.     av = argv + ARGV1stPATH;
  882.     for (idArgs = IdArgs, i = 0; i < Idh.idh_pthc; i++, idArgs++) {
  883.         if (!BITTST(bitArray, i))
  884.             continue;
  885.         if (idArgs->ida_flags & IDA_BLANK) {
  886.             printf("BOTCH: blank index!\n");
  887.             abort();
  888.         }
  889.         if (!(idArgs->ida_flags & IDA_ADJUST)) {
  890.             idArgs->ida_arg = strsav(spanPath(IdDir, idArgs->ida_arg));
  891.             idArgs->ida_flags |= IDA_ADJUST;
  892.         }
  893.         *av++ = idArgs->ida_arg;
  894.     }
  895.     *av = NULL;
  896.     return (argv + ARGV1stPATH);
  897. }
  898.