home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-386-Vol-2of3.iso / c / chop1292.zip / CHOP.C < prev    next >
C/C++ Source or Header  |  1992-12-19  |  19KB  |  555 lines

  1. /* This program splits the input file into smaller files.
  2.  
  3.    USAGE: CHOP FILENAME SIZE [OUTPATH] -SWITCHES
  4.    Version 1.23.  Written by W. J. Kennamer and released into the public domain.
  5.                   Enhanced by Edgar Swank         "           "         "
  6.      Enhancements/Changes:
  7.       1)Performance improvement by reading/writing in large blocks.
  8.       2)Support for non-ASCII files with -b option.
  9.       3)Add optional disk/path for output files.
  10.       4)Add -w option to wait after each output file (except last).
  11.       Note: this source is now for IBM/MS C Compiler.
  12.             Compile with HUGE memory model /AH.
  13.      FILENAME is any valid MS-DOS filename.  Wildcards are not supported.
  14.      Output file names will be FILENAME.1, FILENAME.2, etc.
  15.      Output files are always terminated with a carriage return and
  16.      a <ctrl>Z, UNLESS -b is specified.
  17.      SIZE is the desired file size for each new file.
  18.      OUTPATH is an optional disk/pathname (A: or \path\ or a:\path\)
  19.      to put output files on a different disk and/or directory from input file.
  20.      If using -p with OUTPATH, enter some dummy argument for SIZE.
  21.      SWITCHES must follow the FILENAME,SIZE and OUTPATH parameters,
  22.        and may be entered in any order.  Switches may be combined.
  23.      Valid SWITCHES are:
  24.        -b  binary    ║ do not add cr/lf/^z to output files.
  25.                      ║   forces -s.
  26.        -s  strict    ║ chop file at exact SIZE boundary.
  27.        -w  wait      ║ wait after closing each output file.
  28.                      ║  can change output diskette if separate from input.
  29.        -r  return    ║ chop file at first carriage return
  30.                      ║   following SIZE characters (default).
  31.        -px partition ║ partition file into x equal units.
  32.                      ║   SIZE is ignored (and may be omitted) if
  33.                      ║   you choose this option.
  34.  
  35. File pointer fp1 is the input file.  fp2 is always the output
  36.    file, though its name changes as new output files are
  37.    opened.
  38.  
  39. */
  40.  
  41. #include  <fcntl.h>
  42. #include  <dos.h>
  43. #include  <stdio.h>
  44. #include  <ctype.h>
  45. #include  <string.h>
  46. #include  <malloc.h>
  47. #include  <stdlib.h>
  48.  
  49. #define VERSION "1.23"
  50. #define PROGNAME "CHOP"
  51. #define CTRL_Z   0x1a
  52. #define VOID     int
  53. #define CR       0x0d
  54. #define LF       0x0a
  55. #define OFF   0
  56. #define ON   1
  57.  
  58. int binary = OFF;                   /* do not add CR,LF,EOF             */
  59. int wait   = OFF;                   /* Wait after each output file close*/
  60. int count;                          /* no. of digits in size            */
  61. int c;                              /* current character                */
  62. int j;                              /* index                            */
  63. long inpleft;                       /* Bytes input left to read         */
  64. long inplimit;                      /* Bytes input left to read low lim */
  65. long bfsiz;                         /* I/O buffer size                  */
  66. long bread;                         /* Bytes read into buffer           */
  67. long pbread;                        /* Bytes read this partition        */
  68. long bwrit;                         /* Bytes written from buffer        */
  69. long pbwrit;                        /* Bytes written this partition     */
  70.  
  71. long size = 0;                      /* partition value -- file size     */
  72. long byte_count = 0;                /* total bytes in original file     */
  73. long inpfz = 0;                     /* total bytes in original file     */
  74. long out_file_size = 0;             /* total bytes in output file       */
  75.  
  76. char *bfpa[20];                     /* I/O buffer pointer array         */
  77.  
  78. FILE *fp1,*fp2;                     /* fp1=input, fp2=output            */
  79. int derno,erno;
  80.  
  81.  int bfx;                           /* buffer array index               */
  82.  int num_output_files = 0;          /* no of files successfully created */
  83.  int length;                        /* length of matching string        */
  84.  int normal = ON;                   /* normal CR breaks                 */
  85.  int strict = OFF;                  /* break exactly at boundary        */
  86.  int partition = OFF;               /* strict or normal                 */
  87.  int num_part;                      /* number of partitions             */
  88.  int int_size;                      /* integer for file size            */
  89.  int nmb;                           /* number of 16k blocks IO          */
  90.  unsigned int  w;
  91.  
  92.  char *p;                           /* pointer to switch string         */
  93.  char *period_p;                    /* location of period in filename   */
  94.  char *output_file;                 /* output file name                 */
  95.  char filename[80];                 /* original file name               */
  96.  char fnwork[80];                   /* workarea for file name           */
  97.  
  98.  char outpath[64];                  /* optional output disk/path        */
  99.  char line1[80];                    /* data buffer                      */
  100.  char line2[30];                    /* data buffer                      */
  101.  char *switches;                    /* string to hold switches          */
  102.  char infile[80];                   /* input filename                   */
  103.  
  104.  VOID help();
  105.  VOID close_out();
  106.  VOID block_read();
  107.  VOID block_write();
  108.  VOID copy_to_eol();
  109.  VOID construct_output_filename();
  110.  VOID delete_file();
  111.  
  112. main(argc,argv)
  113. int argc;
  114. char *argv[];
  115.    {
  116.  
  117.  
  118.    /* test code to prints args **********
  119.    printf("ARGC=%d\n",argc);
  120.    for (j=0;j<argc ;j++ )
  121.    {
  122.    printf("ARGV[%d]=%s\n",j,argv[j]);
  123.    }
  124.    ***************************************/
  125.    bfsiz=0;
  126.    for (nmb=1;nmb<=20 ;nmb++ )
  127.    {
  128.    bfpa[nmb-1]=malloc(16384);
  129.    if (bfpa[nmb-1]==NULL)
  130.     {
  131.    break;
  132.     }
  133.     else
  134.     {
  135.    bfsiz=(long)nmb*16384;
  136.     }
  137.    } /*for (nmb=1;nmb<=10 ;nmb++ )*/
  138.    nmb--;
  139.    if (nmb==0)
  140.    {
  141.     printf ("Insufficient Memory for I/O Buffer.\n");
  142.     exit(8);
  143.    }
  144.    else
  145.     printf ("%ld (%u*16384) bytes allocated for I/O Buffers.\n",bfsiz,nmb);
  146.  
  147.  
  148.    if( argc > 5 || argc < 3 || strcmp(argv[2],"-?")==0
  149.                             || strcmp(argv[3],"-?")==0
  150.                             || strcmp(argv[4],"-?")==0 )
  151.       {
  152.       help();
  153.       exit(1);
  154.       }
  155.  
  156.    /* see which argument is the switch */
  157.    switches = line2;
  158.    strcpy(switches,"");
  159.    for (j=2;j<argc;j++)
  160.    {
  161.    if( argv[j][0]=='-')
  162.       {
  163.       strcpy(switches,argv[j]);
  164.       break;
  165.       }
  166.     } /*for*/
  167.     if (j>3)
  168.      strcpy(outpath,argv[3]);
  169.     else
  170.      outpath[0]=0;
  171.  
  172.      set_switches();
  173.  
  174.    if( (fp1 = fopen(argv[1],"rb") ) == NULL)
  175.       {
  176.       printf("Cannot open %s for input.\n",argv[1]);
  177.       exit(1);
  178.       }
  179.  
  180.       if( fseek(fp1,0L,2) == -1)            /* position at EOF */
  181.          {
  182.          printf("Error seeking end of input file.\n");
  183.          exit(1);
  184.          }
  185.  
  186.       inpfz = ftell(fp1);                   /* tell EOF  */
  187.       rewind(fp1);                          /* back to beginning of file */
  188.       printf("  Input file size = %ld bytes\n",inpfz);
  189.  
  190.    /* determine file size */
  191.    if(partition == ON)
  192.       {
  193.  
  194.       /* each partition requires 3 extra bytes -- CTRL_Z, newline */
  195.       size = ((inpfz + 3*(long)num_part) / (long)num_part ) + 1 ;
  196.  
  197.       printf("   Partition size = %ld bytes\n",size);
  198.       printf("No. of partitions = %ld\n\n",(long)num_part);
  199.  
  200.       }
  201.    else                                 /* partition is not ON */
  202.       {                                 /* read SIZE from command line */
  203.  
  204.       count = sscanf(argv[2],"%D",&size); /* convert string to long integer */
  205.       if(count == 0)
  206.          {
  207.          printf("Invalid size\n");
  208.          exit(1);
  209.          }
  210.       } /*else*/
  211.       if (size>inpfz)
  212.         {
  213.         printf("Requested Size > Input File Size.\n");
  214.         exit(1);
  215.         }
  216.  
  217.    strcpy(filename,argv[1]);
  218.    strcpy(infile,argv[1]);
  219.  
  220.    period_p = strchr(filename,'.');         /* locate the period, if any */
  221.  
  222.    if( period_p != NULL )
  223.       *period_p = '\0';                     /* chop off the period  */
  224.  
  225.    if (outpath[0]!=0)                       /* if outpath specified */
  226.      construct_output_filename();
  227.  
  228.    inpleft=inpfz;
  229.    if (binary==ON)
  230.     inplimit=0;
  231.    else
  232.     inplimit=3;
  233.    bread=0;pbread=0;w=16384;
  234.    bwrit=0;pbwrit=0;bfx=0;
  235.    while (inpleft>inplimit)
  236.     {
  237.       block_read();
  238.  
  239.       if (pbwrit==0)
  240.       {
  241.       (num_output_files)++;
  242.       if(num_output_files > 127)
  243.          {
  244.          printf("Too many files--%d.\nExiting program\n.",num_output_files);
  245.          exit(1);
  246.          }
  247.  
  248.       output_file = line1;                /* initialize output_file pointer */
  249.  
  250.       /* create the next filename */
  251.       sprintf(output_file,"%s.%-d",filename,num_output_files);
  252.  
  253.       fp2 = fopen(output_file,"wb");
  254.       if (fp2 == NULL)
  255.          {
  256.          printf("Cannot open %s for output\n",output_file);
  257.          printf("Exiting the program.\n");
  258.          printf("%d files created.\n",(num_output_files) - 1 );
  259.          printf("Actual original filesize = %u bytes.\n",byte_count);
  260.          exit(1);
  261.          }
  262.        } /*pbwrit==0 */
  263.  
  264.       block_write();
  265.  
  266.          if( inpleft == 0 )
  267.             {
  268.             close_out(fp2,output_file);
  269.             delete_file();
  270.             exit(0);
  271.             }
  272.       if (pbwrit>=size)
  273.        {
  274.         if( normal == ON )
  275.          copy_to_eol();
  276.  
  277.         close_out(fp2,output_file);
  278.         pbwrit=0;pbread=0;
  279.        } /*if (pbwrit>=size)*/
  280.    bfx=0;bread=0;w=16384;
  281.    bwrit=0;
  282.       } /*while (inpleft>inplimit)*/
  283.    while(1)
  284.       {
  285.       c = getc(fp1);
  286.       if( c == EOF )
  287.          {
  288.          close_out(fp2,output_file);
  289.          delete_file();
  290.          exit(0);
  291.          }
  292.      inpleft--;
  293.      if (binary==ON || (c != CR && c !=LF && c != CTRL_Z))
  294.      {
  295.       putc(c,fp2);
  296.      }
  297.     } /*while(1)*/
  298.    } /*main(argc,argv)*/
  299. /***************************************************************************/
  300.  VOID set_switches()
  301.   {
  302.    for( p = switches ; (p - switches) < strlen(switches)  ; p++ )
  303.       {
  304.       if( *p == 's' )
  305.          {
  306.          strict = ON;
  307.          normal = OFF;
  308.          }
  309.       else if( *p == 'b' )
  310.          {
  311.          strict = ON;
  312.          normal = OFF;
  313.          binary = ON;
  314.          }
  315.       else if ( *p == 'r' || *p == 'n')
  316.          {
  317.          normal = ON;
  318.          strict = OFF;
  319.          binary = OFF;
  320.          }
  321.       else if ( *p == 'p')
  322.          {
  323.          partition = ON;
  324.          if(sscanf((p+1),"%d",&num_part) == 0 || num_part<=0)
  325.             {
  326.             printf("Invalid number of partitions.\n");
  327.             exit(1);
  328.             }
  329.          }
  330.       else if ( *p == 'w')
  331.          {
  332.          wait = ON;
  333.          }
  334.       } /*for( p = switches ...*/
  335.   } /*VOID set_switches()*/
  336. /***************************************************************************/
  337.  VOID construct_output_filename()
  338.     {
  339.      p=outpath+strlen(outpath)-1;           /* ensure outpath properly terminated*/
  340.      if (*p!='\\' && *p!=':')
  341.       {
  342.        *(p+1)='\\';
  343.        *(p+2)=0;
  344.       }
  345.  
  346.      if (filename[1]==':')                  /* strip disk/path from input filename*/
  347.       {
  348.       strcpy(fnwork,(filename+2));
  349.       strcpy(filename,fnwork);
  350.       }
  351.     for (p=filename+strlen(filename);p>=filename;p--)
  352.      {
  353.       if (*p=='\\')
  354.        {
  355.        strcpy(fnwork,p+1);
  356.        strcpy(filename,fnwork);
  357.        break;
  358.        } /*if*/
  359.      } /* for (p=filename+strlen(filename),p>=filename,p--)*/
  360.      if (strlen(outpath)+strlen(filename)<75)
  361.      {
  362.      strcpy(fnwork,outpath);
  363.      strcat(fnwork,filename);
  364.      strcpy(filename,fnwork);
  365.      }
  366.      else
  367.       {
  368.       printf("Syntax Error generating output filename\n");
  369.       exit(8);
  370.       }
  371.     } /*VOID construct_output_filename()*/
  372. /***************************************************************************/
  373. VOID block_read()
  374.    {
  375.       while (pbread<size && bread<bfsiz && inpleft>inplimit && w==16384)
  376.       {
  377.        if (bfsiz>=bread+16384 && size>=pbread+16384 && inpleft>inplimit+16384)
  378.         {
  379.         w=fread(bfpa[bfx],1,16384,fp1);
  380.         }
  381.        else
  382.        if (size-pbread>bfsiz-bread && inpleft-inplimit>bfsiz-bread)
  383.        {
  384.         w=fread(bfpa[bfx],1,(int)(bfsiz-bread),fp1);
  385.        }
  386.        else
  387.        if (inpleft-inplimit>size-pbread)
  388.        {
  389.         w=fread(bfpa[bfx],1,(int)(size-pbread),fp1);
  390.        }
  391.        else
  392.        {
  393.         w=fread(bfpa[bfx],1,(int)(inpleft-inplimit),fp1);
  394.        }
  395.        if (ferror(fp1))
  396.         {
  397.          printf("File read error.\n");
  398.          exit(8);
  399.         }
  400.        bfx++;
  401.        bread+=(long)w;
  402.        pbread+=(long)w;
  403.        inpleft-=(long)w;
  404.       } /* while (pbread<size && bread<bfsiz && inpleft>inplimit && w==16384)*/
  405.    }/* VOID block_read()*/
  406. /***************************************************************************/
  407.  VOID block_write()
  408.   {
  409.       bfx=0;w=16384;
  410.       bwrit=0;
  411.       while (pbwrit<size && bwrit<bread && w==16384)
  412.       {
  413.        if (bread>=bwrit+16384 && size>=pbwrit+16384)
  414.        {
  415.         w=fwrite(bfpa[bfx],1,16384,fp2);
  416.        }
  417.        else
  418.        if ((size-pbwrit)>(bread-bwrit))
  419.         {
  420.         w=fwrite(bfpa[bfx],1,(int)(bread-bwrit),fp2);
  421.         }
  422.        else
  423.         {
  424.         w=fwrite(bfpa[bfx],1,(int)(size-pbwrit),fp2);
  425.         }
  426.        if (ferror(fp2))
  427.         {
  428.          printf("File write error.\n");
  429.          exit(8);
  430.         } /*ferror(fp2)*/
  431.        bfx++;
  432.        bwrit+=(long)w;
  433.        pbwrit+=(long)w;
  434.  
  435.       } /*while (pbwrit<size && bwrit<bread && w==16384)*/
  436.   } /*VOID block_write()*/
  437. /***************************************************************************/
  438.  VOID copy_to_eol()
  439.          {
  440.          while(1)
  441.           {
  442.             c = getc(fp1);
  443.             if( c == EOF )
  444.                {
  445.                close_out(fp2,output_file);
  446.                exit(0);
  447.                }
  448.            inpleft--;
  449.            if (c == LF) break;
  450.            if (c != CR)
  451.            {
  452.             putc(c,fp2);
  453.             pbwrit++;
  454.            }
  455.           } /*while(1)*/
  456.          } /*VOID copy_to_eol()*/
  457. /***************************************************************************/
  458. VOID help()
  459.    {
  460.    printf("Version %s -- 12/19/92\n",VERSION);
  461.    printf("USAGE: %s FILENAME SIZE [OUTPATH] -SWITCHES\n\n",PROGNAME);
  462.    printf("Written by W. J. Kennamer (74025,514) and released into the public domain.\n");
  463.    printf("Enhanced by Edgar Swank <edgar@spectrx.saigon.com>.\n");
  464.    printf("  FILENAME is any valid MS-DOS filename.  Wildcards are not supported.\n");
  465.    printf("  Output file names will be FILENAME.1, FILENAME.2, etc.\n");
  466.    printf("  Output files are always terminated with a carriage return and\n");
  467.    printf("  a <ctrl>Z, UNLESS -b is specified.\n");
  468.    printf("  SIZE is the desired file size for each new file.\n");
  469.    printf("  OUTPATH is an optional disk/pathname (A: or \\path\\ or a:\\path\\)\n");
  470.    printf("  to put output files on a different disk and/or directory from input file.\n");
  471.    printf("  If using -p with OUTPATH, enter some dummy argument for SIZE.\n");
  472.    printf("  SWITCHES must follow the FILENAME,SIZE and OUTPATH parameters,\n");
  473.    printf("    and may be entered in any order.  Switches may be combined.\n");
  474.    printf("Press any key to continue:\n");
  475.     getchar();
  476.    printf("  Valid SWITCHES are:\n");
  477.    printf("╔═════════════════╤═══════════════════════════════════════════════╗\n");
  478.    printf("║   -b  binary    │ do not add cr/lf/^z to output files.          ║\n");
  479.    printf("║                 │   forces -s.                                  ║\n");
  480.    printf("╟─────────────────┼───────────────────────────────────────────────╢\n");
  481.    printf("║   -s  strict    │ chop file at exact SIZE boundary.             ║\n");
  482.    printf("╟─────────────────┼───────────────────────────────────────────────╢\n");
  483.    printf("║   -w  wait      │ wait after closing each output file.          ║\n");
  484.    printf("║                 │ can change output diskette if separate        ║\n");
  485.    printf("║                 │ from input.                                   ║\n");
  486.    printf("╟─────────────────┼───────────────────────────────────────────────╢\n");
  487.    printf("║   -r  return    │ chop file at first carriage return            ║\n");
  488.    printf("║                 │   following SIZE characters (default).        ║\n");
  489.    printf("╟─────────────────┼───────────────────────────────────────────────╢\n");
  490.    printf("║   -px partition │ partition file into x equal units.            ║\n");
  491.    printf("║                 │   SIZE is ignored (and may be omitted) if     ║\n");
  492.    printf("║                 │   you choose this option.                     ║\n");
  493.    printf("╚═════════════════╧═══════════════════════════════════════════════╝\n");
  494.    }
  495.  
  496. /***************************************************************************/
  497.  
  498. VOID close_out(fp,filename)
  499.  
  500. FILE *fp;
  501. char *filename;                    /* output file name                 */
  502.  
  503.    {
  504.    long file_size;
  505.  
  506.    if (binary==OFF)
  507.    {
  508.    putc(CR,fp);                    /* terminating CR */
  509.    putc(LF,fp);                    /* terminating LF */
  510.    putc(CTRL_Z,fp);                /* terminate file with EOF mark    */
  511.    }
  512.  
  513.    if( fseek(fp,0L,2) == -1 )         /* position at EOF                 */
  514.                 {
  515.                 printf("Error seeking end of output file.\n");
  516.                 exit(1);
  517.                 }
  518.    file_size = ftell(fp);          /* report EOF position             */
  519.    fclose(fp);
  520.    printf("Created %s -- %ld bytes\n" , filename , file_size);
  521.    if (wait==ON && inpleft>0)
  522.     {
  523.      printf("Press any key to continue.\n");
  524.      getchar();
  525.     }
  526.    }
  527.  
  528. /***************************************************************************/
  529. VOID delete_file()
  530.  {
  531.     int u;
  532.  
  533.     Printf("Delete Input File?(y/n)\n");
  534.     c=getche();
  535.     printf("\n");
  536.     if (c=='y' || c=='Y')
  537.      {
  538.         u=unlink(infile);
  539.         if (u==0)
  540.          {
  541.           printf("%s Deleted.\n",infile);
  542.          }
  543.         else
  544.          {
  545.           derno=_doserrno;erno=errno;
  546.           printf("Error Deleting %s.\n",infile);
  547.           printf ("DOS ERROR %4X errno %d %s\n",derno,erno,sys_errlist[erno]);
  548.          } /* endif */
  549.      }
  550.     else
  551.      {
  552.      } /* endif */
  553.  
  554.  }
  555.