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