home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / textutil / breakup.c < prev    next >
Internet Message Format  |  1994-03-05  |  6KB

  1. Date: Wed, 23 Apr 86 20:03:28 EST
  2. From: Edward_Vielmetti%UMich-MTS.Mailnet@MIT-MULTICS.ARPA
  3. To: info-ibmpc@USC-ISIB.ARPA
  4. Subject: Breakup.C
  5.  
  6. /*** BREAKUP.  Break up a (presumably large) file into smaller pieces,
  7. /    about a set of breakpoints.  Invoked as:
  8. /       BREAKUP  BigFile.Ext  -C1 A1  -C2 A2  -C3 A2   etc...
  9. /    where the arguments (breakpoints) are:
  10. /       -B  nnn    break after next nnn bytes
  11. /       -L  nnn     "     "     "    "  lines
  12. /       -S  str    break after next occurrence of "str"
  13. /       -LB nnn    break after newline after next nnn bytes
  14. /       -LS str    break after newline after next occurrence of "str"
  15. /       -R         repeat last breakpoint until eof on BigFile
  16. /
  17. /    Written by Charles Roth, December 1983.  This program is in the public
  18. /    domain. */
  19.  
  20. #include <stdio.h>
  21. #define  DASH_B  0
  22. #define  DASH_S  1
  23. #define  DASH_L  2
  24. #define  DASH_LB 3
  25. #define  DASH_LS 4
  26. #define  NONE    5
  27. #define  FUNCTION
  28. #define  NOT       !
  29.  
  30. FUNCTION  main (argc, argv)
  31.    int  argc;   char *argv[];
  32. {
  33.    FILE *in, *out, *fopen();
  34.    int   outnum, c, breaktest, next, ringlen, ringpos, i, r, strfound;
  35.    long  breaknumb, count;
  36.    char  fname[80], fext[80], outfile[80], breakstr[80], ringbuf[80];
  37.  
  38.  
  39.    /*** Mark the end of the argument list so PARSE knows when to stop. */
  40.    argv[argc] = NULL;
  41.  
  42.    if (argc <= 1) {
  43.       printf ("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
  44.       "Usage:  BREAKUP  File.Ext  -C1 A1  -C2 A2  -C3 A3  etc...",
  45.       "  where each -Cn An means break after...",
  46.       "    -B   nnn    next nnn bytes",
  47.       "    -L   nnn    next nnn lines",
  48.       "    -S   str    next occurrence of \"str\"",
  49.       "    -LB  nnn    end-of-line after next nnn bytes",
  50.       "    -LS  str    end-of-line after next occurrence of \"str\"",
  51.       "    -R          repeat last breakpoint indefinitely.");
  52.       exit(1);
  53.    }
  54.  
  55.    /*** Make sure the input file exists, and open it.*/
  56.    if ( (in = fopen (argv[1], "r")) == NULL) {
  57.       printf ("No such file %s\n", argv[1]);
  58.       exit(1);
  59.    }
  60.    xstrbreak (argv[1], fname, fext, ".");
  61.  
  62.    /*** Prepare for main character-by-character loop.  NEXT means "close
  63.    /    file and process next breakpoint."   STRFOUND is used by the -LS
  64.    /    option to remember if the string was found somewhere in the line. */
  65.    next   = 1;
  66.    out    = NULL;
  67.    outnum = 0;
  68.    strfound = 0;
  69.  
  70.    while ( (c = getc (in)) >= 0) {
  71.  
  72.       if (next) {
  73.          /*** Reset the counts, close the old file, open the new one. */
  74.          next  = 0;
  75.          count = 0;
  76.          if (out != NULL)  {fclose (out);    printf  ("%s\n", outfile);}
  77.          sprintf (outfile, "%s.%03d", fname, outnum++);
  78.          out = fopen (outfile, "w");
  79.  
  80.          /*** Parse the next breakpoint and return its type. */
  81.          breaktest = parse (argv, breakstr, &breaknumb);
  82.  
  83.          /*** Initialize the ring buffer for testing -s, -ls strings */
  84.          if (breaktest==DASH_S  ||  breaktest==DASH_LS) {
  85.             ringlen = strlen (breakstr);
  86.             ringpos = 0;
  87.          }
  88.       }
  89.  
  90.       putc (c, out);
  91.  
  92.       /*** For each possible type of breakpoint, test the type and see if
  93.       /    the appropriate condition has happened to break off a new piece. */
  94.       if (breaktest==DASH_B   &&               ++count >= breaknumb)  next = 1;
  95.       if (breaktest==DASH_L   &&  c=='\n'  &&  ++count >= breaknumb)  next = 1;
  96.       if (breaktest==DASH_LB  &&  ++count >= breaknumb  &&  c=='\n')  next = 1;
  97.       if (breaktest==DASH_S  ||  breaktest==DASH_LS) {
  98.          /*** The "str" test is the most difficult.  Keep a ring buffer of
  99.          /    the characters encountered so far, size equal to the size of
  100.          /    the break string.  Each time around the main character loop,
  101.          /    add the new char to the end of the ring buffer, and compare
  102.          /    the ring buffer against the break string.  */
  103.          ringbuf[ringpos] = c;
  104.          ringpos = (ringpos + 1) % ringlen;
  105.          for (i=0, r=ringpos;   breakstr[i];   ++i, r = (r+1) % ringlen)
  106.             if (breakstr[i] != ringbuf[r])  break;
  107.          if (breaktest==DASH_S)    next     = NOT breakstr[i];
  108.          if (breaktest==DASH_LS)   strfound = NOT breakstr[i]  ||  strfound;
  109.       }
  110.  
  111.       if (breaktest==DASH_LS  &&  c=='\n') {
  112.          next     = strfound;
  113.          strfound = 0;
  114.       }
  115.  
  116.    }
  117.    fclose (out);
  118.    printf ("%s\n", outfile);
  119. }
  120.  
  121.  
  122. /*** PARSE breakpoint commands.  On each call, returns 'next' breakpoint
  123. /    type, sets BREAKNUMB to 'nnn' part of -l, -b, -lb breakpoints, and
  124. /    BREAKSTR to string part of -s, -ls breakpoint. */
  125.  
  126. FUNCTION  parse (argv, breakstr, breaknumb)
  127.    char  breakstr[], *argv[];
  128.    long  *breaknumb;
  129. {
  130.    static int a = 1;
  131.    static char realstr[2] = {0, 0};
  132.    char        comstr[80], octalstr[10];
  133.    int         type, p, octalval;
  134.  
  135.    if (argv[++a] == NULL)  {--a;   return(NONE);}
  136.  
  137.    xstrlower  (argv[a]);
  138.    if (xstreq (argv[a], "-r"))  a = a-2;
  139.  
  140.    if      (xstreq (argv[a], "-l"))   type = DASH_L;
  141.    else if (xstreq (argv[a], "-b"))   type = DASH_B;
  142.    else if (xstreq (argv[a], "-s"))   type = DASH_S;
  143.    else if (xstreq (argv[a], "-lb"))  type = DASH_LB;
  144.    else if (xstreq (argv[a], "-ls"))  type = DASH_LS;
  145.  
  146.    ++a;
  147.    if (type==DASH_S  ||  type==DASH_LS) {
  148.       /*** Convert the various \ escape sequences to their proper form. */
  149.       strcpy (breakstr, argv[a]);
  150.       while  (xstralter (breakstr, "\\\"", "\"")) ;
  151.       while  (xstralter (breakstr, "\\n",  "\n")) ;
  152.       while  (xstralter (breakstr, "\\\\", "\\")) ;
  153.  
  154.       /*** Convert \ddd octal strings to the actual characters. */
  155.       for (p=0;  breakstr[p];  ++p) {
  156.          if (breakstr[p] == '\\') {
  157.             xstrsub (octalstr, breakstr, p, 4);
  158.             if (NOT sscanf  (octalstr, "\\%3o", &octalval))  continue;
  159.             realstr[0] = octalval;
  160.             xstralter (breakstr, octalstr, realstr);
  161.          }
  162.       }
  163.    }
  164.  
  165.    if (type==DASH_B  ||  type==DASH_LB  ||  type==DASH_L)
  166.       sscanf (argv[a], "%ld", breaknumb);
  167.  
  168.    return(type);
  169. }
  170.