home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / mkid / lid.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  16.0 KB  |  836 lines

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