home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 211_01 / xsrchr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-12-31  |  21.0 KB  |  1,076 lines

  1. /*XSRCHR.C    VERS:- 01.00  DATE:- 09/26/86  TIME:- 09:38:02 PM */
  2. /*
  3. %CC1 $1.C -O -X -E7A00
  4. %CLINK $1 SCOPE DIO WILDEXP -F CHARFUN STRFUN -S -E7A00
  5. %DELETE $1.CRL 
  6. */
  7. /* 
  8. Description:
  9.  
  10. Search over each record of each file in wildcard filelist; 
  11. if the seach pattern is found in a record, display it, 
  12. with DIO output redirection.
  13.  
  14. If the search pattern is given as the first command line parameter,
  15. the record delimiter is assumed to be '\n'.
  16.  
  17. If the -p option is selected or the search pattern is not given on the
  18. command line, there is full screen input of:
  19.     search patterns;
  20.     record delimiter;
  21.     output delimiters;
  22.     cas_flag;
  23.  
  24. In the case of full screen input, there can be up to 10 search patterns, 
  25. which may be or'd, and'd, or not'd.
  26.  
  27. If the cas_flag is set, the file name is printed at the start of
  28. the first line of output of each record.
  29.  
  30. Strings can include meta characters, such as '*', '?', etc.  
  31. See help_mess for a listing of them.
  32.  
  33.  
  34. Usage:
  35.  
  36. xsrch   [pattern]   input   [>output_ufn (def = crt)]   [-options (-h = help)] 
  37.  
  38. The input parameter is required.  It can be either:
  39.     input_afn1 [input_anf2, ..]   and/or   <input_ufn_list
  40.         
  41. If a pattern to be searched for is given on the command line (rather than
  42. given through full-screen input), it must precede the input parameter.
  43.  
  44. It is best to select full screen input with the option '-p', rather than
  45. trust to default selection.
  46.  
  47. See help_mess for more information on options.
  48.  
  49.  
  50. From public domain code: 
  51.     Van Nuys SEARCH, DIO, WILDEXP (by Eugene H. Mallory):
  52.         WILDEXP modified to allow du: == u/d:.
  53.         DIO modified to avoid cr-cr-lf triple with putchar.
  54.         some functions rewritten from code in SEARCH:
  55.             decode()
  56.             find()
  57.             search()
  58.     CUG SCOPE:
  59.         Full screen input based on the template file XSRCH.ZIP:
  60.             select  and, not, or   strings;
  61.             select parts of record for output;
  62.                 select record delimiter;
  63.             select flags.
  64.  
  65.  
  66. Depending on test, 1-5 x slower than FIND.COM.
  67.  
  68. Effects on efficiency:
  69. major    use of machine coded routines for character and string operations;
  70. major    use of file read() with large block size;
  71. major    inline C-code for touppper in search();
  72. minor    reduced parameter passing;
  73. minor    reduced setting of variables; 
  74. minor    use of ! instead of  == 0;
  75. minor    return from recursive calls of search with longjmp;
  76. minor    expand code of search(), so branching gives fewer operations/branch;
  77. minor    pointer arithmetic instead of arrays in search().
  78.  
  79.  
  80. By J.A. Rupley, Tucson, Arizona
  81. Coded for BDS C compiler, version 1.50a
  82. */
  83.  
  84. /* page eject */
  85. #include "bdscio.h"
  86. #include "dio.h"
  87.  
  88. /*configuration*/
  89. #define READSECS 10
  90. #define BUFLEN (((6 * READSECS) + 1) * 128)
  91. #define DELIM "\n"
  92. #define NO_SUMMARY FALSE
  93. #define LIST_FLAG TRUE
  94. #define RECORD_NUMBERS FALSE
  95. #define INP_PATTERN FALSE
  96. #define DISP_CTRL FALSE
  97. #define SKIP 0
  98. #define CAS_FLAG FALSE
  99.  
  100. /*search constants*/
  101. #define FOUND 0x80
  102. #define NOTFOUND 0x81
  103. #define MATCH 0x82
  104. #define NOTMATCH 0x83
  105. #define NOTBEGIN 0xff
  106. #define NOTEND 0x9d
  107. #define SKIPANY 0x86
  108. #define SKIPONE 0x87
  109. #define IGNOREONE 0x1c
  110. #define LINEEND 0x1d
  111. #define LINESTART 0x7f
  112. #define ANYALPHA 0x1e
  113. #define ANYNUMBER 0x1f
  114.  
  115. /*buffers and arrays*/
  116. #define NPAT 10
  117. #define NDRIVER 7
  118. #define NOUT 10
  119.  
  120. char string[BUFLEN];
  121. char pat_buf[42];
  122. char delim[42];
  123. char pat_array[NPAT][42];
  124. char out_start[NOUT][21];
  125. char out_end[NOUT][21];
  126. char fname[MAXLINE];
  127. char jbuf[JBUFSIZE];
  128.  
  129. /*external constants, used for speed or control*/
  130. int i, j, firstpat, nextpat;
  131. int skip, no_summary, list_flag, record_numbers;
  132. int disp_ctrl, inp_pattern, optionerr;
  133. int cas_flag;
  134. int npat, nout;
  135. char *pattern;
  136. int ioblks, iofile;
  137.  
  138. main(argc, argv)
  139. char **argv;
  140. int argc;
  141. {
  142.     int ii;
  143.     int string_compare();
  144.  
  145.     cas_flag = CAS_FLAG;
  146.     inp_pattern = INP_PATTERN;
  147.     record_numbers = RECORD_NUMBERS;
  148.     no_summary = NO_SUMMARY;
  149.     list_flag = LIST_FLAG;
  150.     optionerr = FALSE;
  151.     disp_ctrl = DISP_CTRL;
  152.     skip = SKIP;
  153.  
  154.     dioinit(&argc, argv);
  155.  
  156.     get_options(&argc, argv);
  157.  
  158.     if (optionerr || ((argc < 2) && !DIOIN))
  159.         help_mess();
  160.  
  161.     /*set up patterns, of all sorts*/
  162.  
  163.     if (((argc < 3) && !DIOIN) || inp_pattern)
  164.     {
  165.         inp_pattern = TRUE;
  166.         full_screen();
  167.     }
  168.     else
  169.     {
  170.         strcpy(delim, DELIM);
  171.  
  172.         pat_decode(argv[1], &pat_array[0][1]);
  173.         pat_array[0][0] = 'O';
  174.         npat = 1;
  175.         argv = &argv[1];
  176.         argc -= 1;
  177.     }
  178.  
  179.     /* now wildcard and sort what is left on command line */
  180.  
  181.     wildexp(&argc, &argv);
  182.     qsort(&argv[1], argc - 1, 2, &string_compare);
  183.  
  184.     /* search filelist from command line, if any*/
  185.  
  186.     for (ii = 1; ii < argc; ii++)
  187.     {
  188.         strcpy(fname, argv[ii]);
  189.         find_all(fname);
  190.     }
  191.  
  192.     /* search filelist from input file, if any*/
  193.  
  194.     if (DIOIN)
  195.         while (!getstring(fname))
  196.             find_all(fname);
  197.  
  198.     dioflush();
  199.     exit();
  200. }
  201. /* END OF MAIN*/
  202.  
  203. /*page eject*/
  204.  
  205. int find_all(fname)
  206. char *fname;
  207. {
  208.     int c, temp;
  209.     int record;
  210.     int next, isave;
  211.     char csave, csavefirst;
  212.     char ichar;
  213.     int find_count;
  214.     int jj, kk;
  215.     int first_char, end_char;
  216.     int first_temp, end_temp;
  217.  
  218.     /*fill after end of file name with spaces to column 20*/
  219.     /*then open file, print filename, and process file*/
  220.     
  221.     for (jj = strlen(fname); jj; jj--)
  222.         if ((c = fname[jj - 1]) != ' ' && c != '\r' && c != '\n')
  223.             break;
  224.     while (jj < 20)
  225.         fname[jj++] = ' ';
  226.     fname[jj] = '\0';
  227.  
  228.     if ((iofile = open(fname, 0)) == ERROR)
  229.     {
  230.         typef("\nFIND_ALL: cannot open file %s.\n", fname);
  231.         close(iofile);
  232.         return (0);
  233.     }
  234.     else
  235.         if (!no_summary)
  236.             printf("\f\n%s\n", fname);
  237.  
  238.     find_count = 0;
  239.     record = 1;
  240.     string[0] = LINESTART;
  241.     string[1] = '\0';
  242.  
  243.     if (skip)
  244.         if ((record += skip_lines(skip)) == ERROR)
  245.         {
  246.             typef(" %s.\n", fname);
  247.             close(iofile);
  248.             return (0);
  249.         }
  250.  
  251.     firstpat = 0;
  252.  
  253.     /*main loop to search file for pattern, record by record*/
  254.     /*first, with -pat_gets- find next record terminated by -delim- */
  255.  
  256.     while ((temp = pat_gets(delim)) != ERROR)
  257.     {
  258.  
  259.         /*intercept console input*/
  260.  
  261.         if (bdos(11))
  262.         {
  263.             if ((c = bdos(1)) == 0x03)        /*ctrl-c*/
  264.             {
  265.                 typef("\nFIND_ALL: Control C intercepted\n");
  266.                 dioexit();
  267.             }
  268.             else
  269.                 if (c == 0x18)        /*ctrl-x*/
  270.             {
  271.                 typef("\nFIND_ALL: Control X intercepted\n");
  272.                 close(iofile);
  273.                 return (1);
  274.             }
  275.         }
  276.  
  277.         /*store end characters of record */
  278.         /*replace by special delimiters for search*/
  279.  
  280.         csavefirst = string[firstpat];
  281.         string[firstpat] = LINEEND;
  282.         isave = firstpat + 1;
  283.         csave = string[isave];
  284.         string[isave] = '\0';
  285.         next = nextpat;
  286.  
  287.         /*with -all_pats- search record for all patterns*/
  288.         /*output as appropriate*/
  289.  
  290.         if (all_pats() == FOUND)
  291.         {
  292.  
  293.             if (!find_count++)
  294.             {
  295.                 outs(delim, MAXLINE, disp_ctrl);
  296.                 printf("\n");
  297.             }
  298.  
  299.             if (list_flag)
  300.             {
  301.                 if (nout)
  302.                 {
  303.                     if (cas_flag)
  304.                         printf("%s", fname);
  305.  
  306.                     if (record_numbers)
  307.                         printf("Record number %-7d ", record);
  308.  
  309.                     first_char = 1;
  310.  
  311.                     for (kk = 0; kk < nout; kk++)
  312.                     {
  313.                         firstpat = first_char;
  314.                         pattern = out_start[kk];
  315.  
  316.                         if (find() != FOUND)
  317.                             continue;
  318.  
  319.                         first_char = firstpat++;
  320.                         pattern = out_end[kk];
  321.  
  322.                         if (find() != FOUND)
  323.                             continue;
  324.  
  325.                         end_char = firstpat;
  326.  
  327.                         outs(&string[first_char], (end_char - first_char), disp_ctrl);
  328.  
  329.                         if (temp == FOUND && kk == (nout - 1))
  330.                             for (jj = 0; (ichar = out_end[kk][jj]); jj++)
  331.                                 if (ichar == LINEEND && (out_end[kk][jj - 1] != '!'))
  332.                                     outs(delim, MAXLINE, disp_ctrl);
  333.                     }
  334.                 }
  335.                 else
  336.                 {
  337.                     if (record_numbers)
  338.                         printf("%7d ", record);
  339.  
  340.                     string[isave - 1] = '\0';
  341.  
  342.                     outs(&string[1], BUFLEN, disp_ctrl);
  343.  
  344.                     if (temp == FOUND)
  345.                         outs(delim, BUFLEN, disp_ctrl);
  346.                 }
  347.             }
  348.  
  349.             /*if not list_flag, ie if select files, not lines*/
  350.  
  351.             else
  352.             {
  353.                 if (!no_summary)
  354.                     summary_output(find_count);
  355.  
  356.                 close(iofile);
  357.                 return (1);
  358.             }
  359.         }
  360.  
  361.         record++;
  362.  
  363.         /*normal exit at end of file*/
  364.  
  365.         if (temp == NOTFOUND)
  366.         {
  367.             outs(delim, MAXLINE, disp_ctrl);
  368.             printf("\n");
  369.  
  370.             if (!no_summary)
  371.             {
  372.                 if (find_count)
  373.                     printf("\n%s\n", fname);
  374.                 summary_output(find_count);
  375.             }
  376.  
  377.             close(iofile);
  378.             return (1);
  379.         }
  380.  
  381.         /*reset string and pointers for search of next record*/
  382.  
  383.         firstpat = 0;
  384.         string[isave - 1] = csavefirst;
  385.         string[isave] = csave;
  386.         strcpy(&string[1], &string[next]);
  387.     }
  388.  
  389.     typef("\nFIND_ALL: line overflows buffer %s.\n", fname);
  390.     close(iofile);
  391.     return (0);
  392. }
  393. /*END OF FIND_ALL*/
  394.  
  395.  
  396.  
  397. /*page eject*/
  398.  
  399. void full_screen()
  400. {
  401.     int iobuf;
  402.     int ii, jj;
  403.     int offset;
  404.  
  405.     char pat_driver[NDRIVER][10];
  406.     strcpy(pat_driver[0], "Aand patt");
  407.     strcpy(pat_driver[1], "Nnot patt");
  408.     strcpy(pat_driver[2], "Oor patte");
  409.     strcpy(pat_driver[3], "Dsearch d");
  410.     strcpy(pat_driver[4], "Routput d");
  411.     strcpy(pat_driver[5], "Ccas_flag");
  412.     strcpy(pat_driver[6], "\0       ");
  413.  
  414.     if ((iobuf = open("xsrch.zip", 0)) == ERROR)
  415.         if ((iobuf = open("a15:xsrch.zip", 0)) == ERROR)
  416.             error("FULL_SCREEN: cannot open XSRCH.ZIP template.");
  417.  
  418.     read(iobuf, string, 20);
  419.     scope(string, 80, 1920, 0);
  420.     string[1920] = '\0';
  421.  
  422.     npat = nout = 0;
  423.  
  424.     for (jj = 0; pat_driver[jj][0]; jj++)
  425.     {
  426.         firstpat = 0;
  427.         pattern = &pat_driver[jj][1];
  428.  
  429.         if (find() != FOUND)
  430.             error("FULL_SCREEN: no pat_driver pattern.");
  431.  
  432.         offset = firstpat;
  433.  
  434.         while (TRUE)
  435.         {
  436.             if (npat == NPAT || nout == NOUT)
  437.                 error("FULL_SCREEN: too many patterns");
  438.  
  439.             offset += 80;
  440.  
  441.             for (ii = 39; ii >= 0; ii--)
  442.                 if (string[offset + ii] != ' ')
  443.                     break;
  444.             if (ii < 0)
  445.                 break;
  446.  
  447.             switch (pat_driver[jj][0])
  448.             {
  449.             case 'C' :
  450.                 cas_flag = string[offset] - '0';
  451.                 break;
  452.             case 'R' :
  453.                 strncpy(pat_buf, &string[offset], ii + 1);
  454.                 if (strlen(pat_buf) > 20)
  455.                 {
  456.                     pat_decode(&pat_buf[20], out_end[nout]);
  457.                     for (ii = 19; ii >= 0; ii--)
  458.                         if (string[offset + ii] != ' ')
  459.                             break;
  460.                     strncpy(pat_buf, &string[offset], ii + 1);
  461.                     pat_decode(pat_buf, out_start[nout]);
  462.                 }
  463.                 else
  464.                     {
  465.                     pat_decode(pat_buf, out_start[nout]);
  466.                     strcpy(out_end[nout], out_end[nout - 1]);
  467.                 }
  468.                 nout++;
  469.                 break;
  470.             case 'D' :
  471.                 strncpy(pat_buf, &string[offset], ii + 1);
  472.                 pat_decode(pat_buf, delim);
  473.                 break;
  474.             case 'A' :
  475.             case 'N' :
  476.             case 'O' :
  477.                 strncpy(pat_buf, &string[offset], ii + 1);
  478.                 pat_decode(pat_buf, &pat_array[npat][1]);
  479.                 pat_array[npat][0] = pat_driver[jj][0];
  480.                 npat++;
  481.                 break;
  482.             default :
  483.                 error("FULL_SCREEN: bad pattern driver");
  484.             }
  485.         }
  486.     }
  487.  
  488.     if (npat < 1)
  489.         error("FULL_SCREEN: no search pattern");
  490.     return;
  491. }
  492. /* END OF FULL_SCREEN*/
  493.  
  494.  
  495.  
  496. /*page eject*/
  497.  
  498. int all_pats()
  499. {
  500.     int itemp;
  501.     int kk;
  502.     int and_flag, or_flag, not_flag;
  503.  
  504.     and_flag = or_flag = not_flag = 0;
  505.  
  506.     for (kk = 0; kk < npat; kk++)
  507.     {
  508.         firstpat = 0;
  509.         pattern = &pat_array[kk][1];
  510.  
  511.         if (find() == FOUND)
  512.         {
  513.             switch (pat_array[kk][0])
  514.             {
  515.             case 'N' :
  516.                 return NOTFOUND;
  517.             case 'A' :
  518.                 and_flag++;
  519.                 break;
  520.             case 'O' :
  521.                 return FOUND;
  522.             default :
  523.                 error("ALL_PATS: bad pat_array[kk][0].");
  524.             }
  525.         }
  526.         else
  527.             {
  528.             switch (pat_array[kk][0])
  529.             {
  530.             case 'A' :
  531.                 return NOTFOUND;
  532.             case 'N' :
  533.                 not_flag++;
  534.             }
  535.         }
  536.     }
  537.  
  538.     if (and_flag || not_flag)
  539.         return FOUND;
  540.     else
  541.         return NOTFOUND;
  542. }
  543. /* END OF ALL_PATS*/
  544.  
  545.  
  546. int pat_gets(pat)
  547. char *pat;
  548. {
  549.     while (TRUE)
  550.     {
  551.         pattern = pat;
  552.  
  553.         if (find() == FOUND)
  554.             return FOUND;
  555.  
  556.         if ((nextpat = strlen(string)) > BUFLEN - 2 * 128)
  557.             return ERROR;
  558.  
  559.         if ((ioblks = read(iofile, &string[nextpat], READSECS)) <= 0)
  560.             return NOTFOUND;
  561.  
  562.         string[nextpat + ioblks * 128] = '\0';
  563.     }
  564.  
  565.     return ERROR;
  566. }
  567. /* END OF PAT_GETS */
  568.  
  569.  
  570. int skip_lines(count)
  571. int count;
  572. {
  573.     int itemp;
  574.     int ii;
  575.  
  576.     for (ii = 0; ii < count; ii++)
  577.     {
  578.         firstpat = 0;
  579.  
  580.         if ((itemp = pat_gets(delim)) == NOTFOUND || itemp == ERROR)
  581.         {
  582.             typef("\nSKIP_LINES: buffer overflow or unexpected end of file ");
  583.             return (ERROR);
  584.         }
  585.  
  586.         strcpy(&string[1], &string[nextpat]);
  587.  
  588.         if (!((ii + 1) % 10))
  589.             typef("%d ", ii + 1);
  590.     }
  591.  
  592.     typef("\n");
  593.  
  594.     return (ii);
  595. }
  596. /* END OF SKIP_LINES*/
  597.  
  598.  
  599. void summary_output(find_count)
  600. int find_count;
  601. {
  602.     int kk;
  603.  
  604.     printf("%5d finds for search pattern  = \n", find_count);
  605.  
  606.     for (kk = 0; kk < npat; kk++)
  607.     {
  608.         printf("   %c ", pat_array[kk][0]);
  609.  
  610.         outs(&pat_array[kk][1], MAXLINE, TRUE);
  611.  
  612.         if (kk < (npat - 1))
  613.             if (!((kk + 1) % 3))
  614.                 printf("\n");
  615.         else
  616.             if (pat_array[kk][0] != pat_array[kk + 1][0])
  617.             printf("\n");
  618.     }
  619.  
  620.     printf("\n\n");
  621.  
  622.     return;
  623. }
  624. /* END OF SUMMARY_OUTPUT */
  625.  
  626.  
  627. int outs(str, count, ctrl_display)
  628. char *str;
  629. int count, ctrl_display;
  630. {
  631.     int ii, linecount;
  632.     char c;
  633.  
  634.     linecount = 0;
  635.  
  636.     for (ii = 0; ii < count; ii++)
  637.     {
  638.         switch (str[ii] & 0x7f)
  639.         {
  640.         case '\0' :
  641.             return (linecount);
  642.         case '\n' :
  643.             linecount++;
  644.             putchar(str[ii]);
  645.             break;
  646.         default :
  647.             if (ctrl_display)
  648.             {
  649.                 if (str[ii] > 0x80)
  650.                     putchar('~');
  651.                 if ((c = (str[ii] & 0x7f)) < 0x20 || c == 0x7f)
  652.                 {
  653.                     putchar('^');
  654.                     putchar(c + 0x40);
  655.                     if (c != '\r')
  656.                         break;
  657.                 }
  658.             }
  659.             putchar(str[ii]);
  660.         }
  661.     }
  662.  
  663.     return (ERROR);
  664. }
  665. /* END OF OUTS*/
  666.  
  667.  
  668.  
  669. /*page eject*/
  670.  
  671. void pat_decode(pat, str)
  672. char *pat;
  673. char *str;
  674. {
  675.     int c;
  676.  
  677.     j = i = 0;
  678.  
  679.     while (c = pat[i++])
  680.     {
  681.         if (c == '!')
  682.         {
  683.             c = pat[i++];
  684.  
  685.             switch (c)
  686.             {
  687.             case '*' :
  688.             case '?' :
  689.             case '!' :
  690.             case '$' :
  691.             case 0 :
  692.                 error("PAT_DECODE: bad pattern after !.");
  693.             }
  694.  
  695.             decode(c, pat, str, 1);
  696.         }
  697.         else
  698.             decode(c, pat, str, 0);
  699.     }
  700.  
  701.     str[j] = 0;
  702.  
  703.     return;
  704. }
  705. /* END OF PAT_DECODE */
  706.  
  707.  
  708. int decode(c, pat, str, not_flag)
  709. int c, not_flag;
  710. char *pat, *str;
  711. {
  712.     switch (c)
  713.     {
  714.     case '$' :
  715.         str[j++] = SKIPONE;
  716.         break;
  717.     case '*' :
  718.         str[j++] = SKIPANY;
  719.         if (pat[i] == '!' && pat[i + 1] == '}')
  720.             error("DECODE: *!} not allowed.");
  721.         break;
  722.     case '?' :
  723.         str[j++] = SKIPONE;
  724.         break;
  725.     case '}' :
  726.         str[j++] = LINEEND;
  727.         if (pat[i] != 0)
  728.             error("DECODE: } must be last.");
  729.         if (i == 2 && not_flag)
  730.             error("DECODE: no pattern before !}.");
  731.         break;
  732.     case '{' :
  733.         str[j++] = LINESTART;
  734.         if (i != (not_flag + 1))
  735.             error("DECODE: { must be first.");
  736.         if (not_flag)
  737.         {
  738.             if (pat[i] == 0)
  739.                 error("DECODE: no pattern after !{.");
  740.             if (pat[i] == '*')
  741.                 error("DECODE: !{* not allowed.");
  742.             if (pat[i] == '!' && pat[i + 1] == '}')
  743.                 error("DECODE: !{!} not allowed.");
  744.         }
  745.         break;
  746.     case '@' :
  747.         str[j++] = ANYALPHA;
  748.         break;
  749.     case '#' :
  750.         str[j++] = ANYNUMBER;
  751.         break;
  752.     case '_' :
  753.         str[j++] = ' ';
  754.         break;
  755.     case '^' :
  756.         c = pat[i++];
  757.         if (c > 0x7f || c <= 0x40)
  758.             error("DECODE: illegal character follows ^");
  759.         str[j++] = toupper(c) - 0x40;
  760.         break;
  761.     case '\\' :
  762.         c = pat[i++];
  763.         if (c == 0)
  764.             error("DECODE: \\ requires character following.");
  765.         switch (c)
  766.         {
  767.         case 'n' :
  768.         case 'N' :
  769.             c = '\n';
  770.             break;
  771.         case 'f' :
  772.         case 'F' :
  773.             c = '\f';
  774.             break;
  775.         case 'r' :
  776.         case 'R' :
  777.             c = '\r';
  778.             break;
  779.         case 't' :
  780.         case 'T' :
  781.             c = '\t';
  782.             break;
  783.         case 'b' :
  784.         case 'B' :
  785.             c = '\b';
  786.             break;
  787.         }
  788.         str[j++] = c;
  789.         break;
  790.     default :
  791.         str[j++] = c;
  792.     }
  793.     if (not_flag)
  794.         str[j - 1] |= 0x80;
  795.     return;
  796. }
  797. /* END OF DECODE */
  798.  
  799.  
  800. int find()
  801. {
  802.     i = 0;
  803.     j = firstpat;
  804.  
  805.     switch (setjmp(jbuf))
  806.     {
  807.     case NOTFOUND :
  808.         return NOTFOUND;
  809.     case FOUND :
  810.         nextpat = j;
  811.         if (pattern[0] == NOTBEGIN)
  812.             firstpat++;
  813.         if (pattern[strlen(pattern) - 1] == NOTEND)
  814.             nextpat--;
  815.         return FOUND;
  816.     }
  817. loop :
  818.     switch (search())
  819.     {
  820.     case NOTMATCH :
  821.         j = ++firstpat;
  822.         if (!string[j] || (string[j] == 0x1a))
  823.             return NOTFOUND;
  824.         i = 0;
  825.         goto loop;
  826.     case MATCH :
  827.         if (!i++)
  828.             firstpat = j;
  829.         j++;
  830.         if (!pattern[i])
  831.             longjmp(jbuf, FOUND);
  832.         if (!string[j] || (string[j] == 0x1a))
  833.             return NOTFOUND;
  834.         goto loop;
  835.     case FOUND :
  836.         longjmp(jbuf, FOUND);
  837.     case NOTFOUND :
  838.         return NOTFOUND;
  839.     }
  840. }
  841. /* END OF FIND */
  842.  
  843. int search()
  844. {
  845.     int isave;
  846.  
  847.     if (pattern[i] & 0x80)
  848.         switch (pattern[i])
  849.         {
  850.         case ANYALPHA | 0x80 :
  851.             if (!isalpha(string[j]) && j && string[j] != LINEEND)
  852.                 return MATCH;
  853.             else
  854.                 return NOTMATCH;
  855.         case ANYNUMBER | 0x80 :
  856.             if (!isdigit(string[j]) && j && string[j] != LINEEND)
  857.                 return MATCH;
  858.             else
  859.                 return NOTMATCH;
  860.         case SKIPANY :
  861.             if (!pattern[++i])
  862.             {
  863.                 j = strlen(string);
  864.                 longjmp(jbuf, FOUND);
  865.             }
  866.             isave = i;
  867. loop :
  868.             i = isave;
  869. loop2 :
  870.             switch (search())
  871.             {
  872.             case MATCH :
  873.                 if (!pattern[++i])
  874.                 {
  875.                     i--;
  876.                     return MATCH;
  877.                 }
  878.                 if (!string[++j] || (string[j] == 0x1a))
  879.                 {
  880.                     i--;
  881.                     j--;
  882.                     longjmp(jbuf, NOTFOUND);
  883.                 }
  884.                 goto loop2;
  885.             case NOTMATCH :
  886.                 if (!string[++j] || (string[j] == 0x1a))
  887.                 {
  888.                     j--;
  889.                     return NOTMATCH;
  890.                 }
  891.                 goto loop;
  892.             case FOUND :
  893.                 longjmp(jbuf, FOUND);
  894.             case NOTFOUND :
  895.                 longjmp(jbuf, NOTFOUND);
  896.             }
  897.         case SKIPONE :
  898.             if (!j++)
  899.                 return NOTMATCH;
  900.             i++;
  901.             if (!string[j] || (string[j] == 0x1a))
  902.                 longjmp(jbuf, NOTFOUND);
  903.             switch (search())
  904.             {
  905.             case MATCH :
  906.                 return MATCH;
  907.             case NOTMATCH :
  908.                 j--;
  909.                 return NOTMATCH;
  910.             case FOUND :
  911.                 longjmp(jbuf, FOUND);
  912.             case NOTFOUND :
  913.                 longjmp(jbuf, NOTFOUND);
  914.             }
  915.         default :
  916.             if (!inp_pattern && ((string[j] & 0x7f) >= 'a')
  917.                 && ((string[j] & 0x7f) <= 'z'))
  918.                 if ((pattern[i] & 0x7f) != ((string[j] & 0x7f) - 0x20)
  919.                     && j && (string[j] & 0x7f) != LINEEND)
  920.                     return MATCH;
  921.             else
  922.                 return NOTMATCH;
  923.             else
  924.                 if ((pattern[i] & 0x7f) != (string[j] & 0x7f)
  925.                 && j && (string[j] & 0x7f) != LINEEND)
  926.                 return MATCH;
  927.             else
  928.                 return NOTMATCH;
  929.         }
  930.     else
  931.         switch (pattern[i])
  932.     {
  933.     case 0 :
  934.         longjmp(jbuf, FOUND);
  935.     case ANYALPHA :
  936.         if (isalpha(string[j]))
  937.             return MATCH;
  938.         else
  939.             return NOTMATCH;
  940.     case ANYNUMBER :
  941.         if (isdigit(string[j]))
  942.             return MATCH;
  943.         else
  944.             return NOTMATCH;
  945.     default :
  946.         if (!inp_pattern && ((string[j] & 0x7f) >= 'a')
  947.             && ((string[j] & 0x7f) <= 'z'))
  948.             if (pattern[i] == ((string[j] & 0x7f) - 0x20))
  949.                 return MATCH;
  950.         else
  951.             return NOTMATCH;
  952.         else
  953.             if (pattern[i] == (string[j] & 0x7f))
  954.             return MATCH;
  955.         else
  956.             return NOTMATCH;
  957.     }
  958. }
  959. /* END OF SEARCH */
  960.  
  961.  
  962.  
  963. /*page eject*/
  964.  
  965. int string_compare(s, t)
  966. char **s, **t;
  967. {
  968.     char *s1, *t1;
  969.  
  970.     for (s1 = *s, t1 = *t; *s1; s1++, t1++)
  971.         if (*t1 != *s1)
  972.             return (*s1 - *t1);
  973.     return 0;
  974. }
  975. /* END OF STRING_COMPARE */
  976.  
  977.  
  978. int strncpy(str1, str2, n)
  979. char *str1, *str2;
  980. int n;
  981. {
  982.     while (n-- && *str2)
  983.         *str1++ = *str2++;
  984.  
  985.     *str1 = 0;
  986.  
  987.     return (str1);
  988. }
  989. /* END OF STRNCPY*/
  990.  
  991.  
  992. void get_options(argcpntr, argv)
  993. char **argv;
  994. int *argcpntr;
  995. {
  996.     char *ss;
  997.     int jj, ii;
  998.  
  999.     for (ii = *argcpntr - 1; ii > 0; ii--)
  1000.         if (argv[ii][0] == '-')
  1001.         {
  1002.             for (ss = &argv[ii][1]; *ss != '\0';)
  1003.             {
  1004.                 switch (toupper(*ss++))
  1005.                 {
  1006.                 case 'A' :
  1007.                     cas_flag = !cas_flag;
  1008.                     break;
  1009.                 case 'L' :
  1010.                     list_flag = !list_flag;
  1011.                     break;
  1012.                 case 'F' :
  1013.                     no_summary = !no_summary;
  1014.                     break;
  1015.                 case 'N' :
  1016.                     record_numbers = !record_numbers;
  1017.                     break;
  1018.                 case 'P' :
  1019.                     inp_pattern = !inp_pattern;
  1020.                     break;
  1021.                 case 'C' :
  1022.                     disp_ctrl = !disp_ctrl;
  1023.                     break;
  1024.                 case 'S' :
  1025.                     skip = atoi(ss);
  1026.                     break;
  1027.                 case 'H' :
  1028.                     optionerr = TRUE;
  1029.                     break;
  1030.                 default :
  1031.                     typef("sv]: illegal option %c.\n"
  1032.                         , *--ss);
  1033.                     ss++;
  1034.                     optionerr = TRUE;
  1035.                     break;
  1036.                 }
  1037.                 while (isdigit(*ss))
  1038.                     ss++;
  1039.             }
  1040.  
  1041.             for (jj = ii; jj < (*argcpntr - 1); jj++)
  1042.                 argv[jj] = argv[jj + 1];
  1043.             (*argcpntr)--;
  1044.         }
  1045.     return;
  1046. }
  1047. /* END OF GET_OPTIONS */
  1048.  
  1049.  
  1050. voiΣ help_mess()
  1051. {
  1052.     typef("XSHOW: A>xsrch  [pattern]  input_afn and/or <input_ufn_list \n");
  1053.     typef("      [-options (-h = help)]  [>output_ufn (def = crt)]\n");
  1054.     typef("   one input file argument required.\n\n");
  1055.     typef("legal options are:\n");
  1056.     typef("-f=1     toggle list of file name and results summary(def = ON).\n");
  1057.     typef("-n=0     toggle line numbering (def = OFF).\n");
  1058.     typef("-l=1     toggle listing of selected lines (def = ON).\n");
  1059.     typef("-p=0     toggle request for patterns (search, etc) (def = OFF).\n");
  1060.     typef("-c=0     toggle display of control chars (def = OFF).\n");
  1061.     typef("-a=0     toggle filename display before each record (def = OFF).\n");
  1062.     typef("-s#=0    skip -#- records before start search (def = 0).\n");
  1063.     typef("\nmeta characters are:.\n");
  1064.     typef("* - any character string.    ? - any single character.\n");
  1065.     typef("_ - a space.            ^ - a control character follows.\n");
  1066.     typef("{ - beginning of line.        } - end of line.\n");
  1067.     typef("@ - any alphabetic character.    # - any numeric character.\n");
  1068.     typef("! - not the following character.\n");
  1069.     typef("\\ - a literal character or C character constant follows.\n");
  1070.     typef("\nControl C = abort    Control X = next file");
  1071.     exit(0);
  1072. }
  1073. /* END OF HELP_MESS */
  1074.  
  1075.  
  1076.