home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / PRINTING / PSFIX.ZIP / FILEIO.C next >
C/C++ Source or Header  |  1991-03-28  |  32KB  |  960 lines

  1. /*
  2.  *
  3.  *  file i/o routines
  4.  *
  5.  */
  6.  
  7. /*
  8.  * This software may be freely distributed under the following conditions:
  9.  *         1. It is distributed in its current form, without alterations.
  10.  *         2. No monetary profit is made, under any circumstances.
  11.  *
  12.  *             Marc A. Murison
  13.  *             Smithsonian Astrophysical Observatory
  14.  *             60 Garden Street, MS 63
  15.  *             Cambridge, MA  02138
  16.  *
  17.  *             (617) 495-7079      murison@cfacx2.harvard.edu
  18.  */
  19.  
  20.  
  21. #define        global        extern
  22. #define        FILEIO_C
  23. #include    "fileio.h"
  24.  
  25.  
  26.  
  27. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  28. /* Boolean fnext_word( FILE *fp, char *word, int *n, char *cp )            */
  29. /*                                                                         */
  30. /* retrieve next word from a file                                          */
  31. /*                                                                         */
  32. /* A word is assumed to consist of sequential alphanumeric characters.     */
  33. /* Anything else is a word delimiter.                                      */
  34. /*                                                                         */
  35. /* entry:  fp       file pointer                                           */
  36. /*                                                                         */
  37. /* exit:   word     contents of next word                                  */
  38. /*         n        number of characters in word, excluding the NULL       */
  39. /*         fp       points to 2nd char after word                          */
  40. /*         cp       contains the 1st char after word                       */
  41. /*                                                                         */
  42. /* returns:        1    successful                                             */
  43. /*                0    EOF encountered                                        */
  44. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  45. Boolean  fnext_word( FILE *fp, char *word, int *n, char *cp )
  46. {
  47.     char    *wp;
  48.     int        c;
  49.  
  50. /* skip to next word */
  51.     c = getc(fp);
  52.     while( !WORD_CHAR(c)  &&  c != EOF )  c = getc(fp);
  53.     if( c == EOF )  return FALSE;
  54.  
  55. /* transfer a word */
  56.     wp  = word;
  57.     *n  = 0;  
  58.     *wp = NULL;
  59.     while( WORD_CHAR(c) ) {
  60.         *wp++ = c;
  61.         ++(*n);
  62.         c = getc(fp);
  63.     }
  64.     *wp = NULL;
  65.     *cp = c;
  66.     if( c == EOF )
  67.         return FALSE;
  68.     else
  69.         return TRUE;
  70. }
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  81. /* Boolean fnext_line( FILE *file_ptr )                                    */
  82. /*                                                                         */
  83. /* advance file pointer to character after next newline character          */
  84. /*                                                                         */
  85. /* returns:        1    successful                                             */
  86. /*                0    EOF encountered                                        */
  87. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  88. Boolean  fnext_line( FILE *file_ptr )
  89. {
  90.     int        c;
  91.  
  92.     do {
  93.         c = getc( file_ptr );
  94.         if( c == EOF )  return FALSE;
  95.     } while( c != CR  &&  c != LF );
  96.  
  97.     return TRUE;
  98. }
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  108. /* int fget_line( FILE *file_ptr, char *buffer )                           */
  109. /*                                                                         */
  110. /* Read 1 line of text from a file and put it into a buffer.               */
  111. /*                                                                         */
  112. /* Advances file pointer to character after next newline character.        */
  113. /*                                                                         */
  114. /* returns:        number of bytes read (minus newline char) if successful    */
  115. /*                EOF if EOF encountered                                     */
  116. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  117. int  fget_line( FILE *file_ptr, char *buffer )
  118. {
  119.     int        N, c;
  120.     char    *bp;
  121.  
  122.     bp = buffer;  N = 0;
  123.     while( (c=getc(file_ptr)) != NEWLINE  &&  c != EOF ) {
  124.         *bp++ = c;
  125.         ++N;
  126.     }
  127.     *bp = NULL;
  128.  
  129.     if( c == EOF )
  130.         return EOF;
  131.     else
  132.         return N;
  133. }
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141. /*
  142.  *
  143.  * open file function
  144.  *
  145.  */
  146.  
  147. Boolean  openfile( File_Def *file, File_Type ftype, File_Mode mode )
  148. {
  149.     char    *errstr;
  150.  
  151.     if( ftype == FTEXT ) {
  152.         if( mode == FREAD )
  153.             file->fp = fopen( file->name, "r" );
  154.         else if( mode == FWRITE )
  155.             file->fp = fopen( file->name, "w" );
  156.         else if( mode == FAPPEND )
  157.             file->fp = fopen( file->name, "a" );
  158.         else {
  159.             ferrout( ON, stdout, 
  160.                 "\n* * * openfile: Illegal read/write request! * * *\n\n" );
  161.             return FALSE;
  162.         }
  163.     } else if( ftype == FBINARY ) {
  164.         if( mode == FREAD )
  165.             file->fp = fopen( file->name, "rb" );
  166.         else if( mode == FWRITE )
  167.             file->fp = fopen( file->name, "wb" );
  168.         else if( mode == FAPPEND )
  169.             file->fp = fopen( file->name, "ab" );
  170.         else {
  171.             ferrout( ON, stdout, 
  172.                 "\n* * * openfile: Illegal mode request! * * *\n\n" );
  173.             return FALSE;
  174.         }
  175.     } else {
  176.         ferrout( ON, stdout, "\n* * * openfile: Illegal file type! * * *\n\n" );
  177.         return FALSE;
  178.     }
  179.  
  180.     if( file->fp == NULL ) {
  181.         errstr = cvector( 0, 80 );
  182.         strcpy( errstr, "\n* * * openfile: Unable to open " );
  183.         strcat( errstr, file->name );
  184.         strcat( errstr, " * * * \n\n" );
  185.         ferrout( ON, stdout, errstr );
  186.         free_cvector( errstr, 0 );
  187.         return FALSE;
  188.     }
  189.  
  190.     return TRUE;
  191. }
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  202. /* cl_in_out( int min_args, char *usage, char *help, int file_mode,        */
  203. /*              int *argc_ptr, char *argv[], File_Def *infile,               */
  204. /*            File_Def *outfile_ptr )                                      */
  205. /*                                                                         */
  206. /* Function to parse the command line for an input file and an output      */
  207. /* file. Both files will be opened, the input file for read only and       */
  208. /* the output file for write only.                                         */
  209. /*                                                                         */
  210. /*                                                                         */
  211. /* caller must provide                                                     */
  212. /*        argc                command line argument count                    */
  213. /*        *argv[]              command line arguments                         */
  214. /*        min_args            minimum number of command line args needed (in */
  215. /*                           addition to program invocation)               */
  216. /*        usage                usage string printed to screen if usage error  */
  217. /*        help                help string printed to screen if cl arg is "?" */
  218. /*                                                                         */
  219. /* Returns 1 if successful, 0 if error.                                    */
  220. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  221. Boolean cl_in_out( int min_args, char *usage, char *help, File_Mode mode,
  222.                    int argc, char *argv[], File_Def *infile,
  223.                    File_Def *outfile )
  224. {
  225.     int          status;
  226.     File_Def    tmpfile;
  227.  
  228. /* help */
  229.     if( argc == 2 ) {
  230.         if( STREQ( argv[1], "\?" ) ) {
  231. #if __TURBOC__
  232.             if( !browse( help, "*   Help   *" ) )  moreprint( help );
  233. #else
  234.             moreprint( help );
  235. #endif
  236.             return FALSE;
  237.         }
  238.         if( STREQ( argv[1], "\?\?" ) ) {
  239.             print_msg( YES, YES, 1, "Writing file \"help\"..." );
  240.             strcpy( tmpfile.name, "help" );
  241.             status = openfile( &tmpfile, FTEXT, FWRITE );
  242.             if( !status )  return FALSE;
  243.             fprintf( tmpfile.fp, "%s", help );
  244.             fclose( tmpfile.fp );
  245.             print_msg( NO, YES, 1, "Done" );
  246.             return FALSE;
  247.         }
  248.     }
  249.  
  250. /* too few cl args */
  251.     if ( argc <= min_args ) {
  252.         ferrout( ON, stdout, usage );
  253.         return FALSE;
  254.     }
  255.  
  256.  
  257. /* open the input file */
  258.     strcpy( infile->name, argv[1] );
  259.     status = openfile( infile, mode, FREAD );
  260.     if( !status )  return FALSE;
  261.  
  262.  
  263. /* open the output file */
  264.     strcpy( outfile->name, argv[2] );
  265.     status = openfile( outfile, mode, FWRITE );
  266.     if( !status )  return FALSE;
  267.  
  268.     return TRUE;
  269. }
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  279. /* cl_dir_in_out       command line parser                                 */
  280. /*                                                                         */
  281. /* gets input and output file names, opens input and output files, checks  */
  282. /* input file for a directory of files and sets *dirflag_ptr accordingly   */
  283. /*                                                                         */
  284. /* valid cl:   program  infile[.in]  [outfile[.out]]  [more args...]       */
  285. /*             program  infile[.in]  [.out]           [more args...]       */
  286. /*             program  dirfile      [.out]           [more args...]       */
  287. /*             program  dirfile      [.in .out]       [more args...]       */
  288. /*                                                                         */
  289. /* caller must provide                                                     */
  290. /*        nargs               command line argument count                    */
  291. /*        *argv[]              command line arguments                         */
  292. /*        default_in_ext[]    default input file extension (e.g., ".dat")    */
  293. /*        default_out_ext[]    default output file extension (e.g., ".out")   */
  294. /*        min_args            minimum number of command line args needed (in */
  295. /*                           addition to program invocation)               */
  296. /*        usage[]                usage string printed to screen if usage error  */
  297. /*        help                help string printed to screen if cl arg is "?" */
  298. /*        file_mode            must be BINARY or TEXT                         */
  299. /*                                                                         */
  300. /* returns  0  if error,  1 if no error                                    */
  301. /*                                                                         */
  302. /* The pieces of the input and output file names are put into              */
  303. /*        infile->name[]        entire file name                               */
  304. /*        in_name[]            file name root only                            */
  305. /*        in_ext[]            file name extension only                       */
  306. /* and similar for the output file name.                                   */
  307. /*                                                                         */
  308. /* function dependences:    upcase, get_filename, fnext_line               */
  309. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  310. Boolean cl_dir_in_out( int  nargs,            char *argv[],
  311.                        int  min_args,         char *usage,
  312.                        char *help,            File_Mode mode,
  313.                        char default_in_ext[], char default_out_ext[],
  314.                        char in_name[],        char in_ext[],
  315.                        char out_name[],       char out_ext[],
  316.                        File_Def    *infile,      File_Def *outfile,
  317.                        File_Def *dirfile,     int  *dirflag )
  318. {
  319.     int            i, status;
  320.     char        c, *errstr;
  321.     char        def_ext[15];
  322.     char        *name_ptr, *arg_ptr;
  323.     char        *char_ptr, *scratch_ptr;
  324.     char        dirtest[10];
  325.     File_Def    tmpfile;
  326.  
  327.  
  328. /* help */
  329.     if( nargs == 2 ) {
  330.         if( STREQ( argv[1], "\?" ) ) {
  331. #if __TURBOC__
  332.             if( !browse( help, "*   Help   *" ) )  moreprint( help );
  333. #else
  334.             moreprint( help );
  335. #endif
  336.             return FALSE;
  337.         }
  338.         if( STREQ( argv[1], "\?\?" ) ) {
  339.             print_msg( YES, YES, 1, "Writing file \"help\"..." );
  340.             strcpy( tmpfile.name, "help" );
  341.             status = openfile( &tmpfile, FTEXT, FWRITE );
  342.             if( !status )  return FALSE;
  343.             fprintf( tmpfile.fp, "%s", help );
  344.             fclose( tmpfile.fp );
  345.             print_msg( NO, YES, 1, "Done" );
  346.             return FALSE;
  347.         }
  348.     }
  349.  
  350. /* wrong number of command line arguments */
  351.     if( nargs <= min_args ) {
  352.         ferrout( ON, stdout, usage );
  353.         return FALSE;
  354.     }
  355.  
  356.  
  357. /* parse the input file name */
  358.     char_ptr = (char *) strchr( argv[1], DOT );
  359.     if( char_ptr == NULL ) {                    /* name only */
  360.         strcpy( in_name, argv[1] );         
  361.         strcpy( in_ext, default_in_ext );
  362.     } else {                                    /* full file name given */
  363.         arg_ptr  = argv[1];
  364.         name_ptr = in_name;
  365.         while( strcmp( arg_ptr, char_ptr ) != 0 )    /* copy name */
  366.             *name_ptr++ = *arg_ptr++;
  367.         *name_ptr = NULL;
  368.         strcpy( in_ext, char_ptr );                    /* copy ext */
  369.     }
  370.  
  371.  
  372. /* open input file */
  373.     strcpy( infile->name, in_name );            /* form input file name */
  374.     strcat( infile->name, in_ext );
  375.     status = openfile( infile, mode, FREAD );
  376.     if( !status )  return FALSE;
  377.  
  378.  
  379. /* check infile for directory option */
  380.  
  381. dircheck:
  382.     /* skip leading white space */
  383.     do {
  384.         c = getc( infile->fp );
  385.         if( c == EOF ) {
  386.             errstr = cvector( 0, 80 );
  387.             strcpy( errstr, "\nInput file " );
  388.             strcat( errstr, infile->name );
  389.             strcat( errstr, " is empty!\n\n" );
  390.             ferrout( ON, stdout, errstr );
  391.             free_cvector( errstr, 0 );
  392.             fclose( infile->fp );
  393.             return FALSE;
  394.         }
  395.     } while( isspace(c) );
  396.  
  397.     /* now get first 9 characters ... */
  398.     scratch_ptr    = dirtest;
  399.     *scratch_ptr++ = c;                                /* 1st character */
  400.     for( i=1; i < 9; i++ ) {                          /* next 8 */
  401.         c = getc( infile->fp );
  402.         if( c == EOF ) {
  403.             errstr = cvector( 0, 80 );
  404.             strcpy( errstr, "\nInput file " );
  405.             strcat( errstr, infile->name );
  406.             strcat( errstr, " is empty!\n\n" );
  407.             ferrout( ON, stdout, errstr );
  408.             free_cvector( errstr, 0 );
  409.             fclose( infile->fp );
  410.             return FALSE;
  411.         }
  412.         *scratch_ptr++ = c;
  413.     }
  414.     *(++scratch_ptr) = NULL;
  415.  
  416.     /* ...and check for "directory" */
  417.     if( strcmp( upcase(dirtest), "DIRECTORY" ) == 0 ) {
  418.         *dirflag = 1;
  419.         *dirfile = *infile;
  420.  
  421.         /* read past the rest of the "directory" line */
  422.         if( !fnext_line(infile->fp) ) {
  423.             errstr = cvector( 0, 80 );
  424.             strcpy( errstr, "\nInput file " );
  425.             strcat( errstr, infile->name );
  426.             strcat( errstr, " is empty!\n\n" );
  427.             ferrout( ON, stdout, errstr );
  428.             free_cvector( errstr, 0 );
  429.             fclose( infile->fp );
  430.             return FALSE;
  431.         }
  432.  
  433.     /* a result of DOS dir (volume name)--skip to next line */
  434.     } else if( strcmp( dirtest, "VOLUME IN" ) == 0 ) {
  435.         if( !fnext_line(infile->fp) ) {
  436.             errstr = cvector( 0, 80 );
  437.             strcpy( errstr, "\nInput file " );
  438.             strcat( errstr, infile->name );
  439.             strcat( errstr, " is empty!\n\n" );
  440.             ferrout( ON, stdout, errstr );
  441.             free_cvector( errstr, 0 );
  442.             fclose( infile->fp );
  443.             return FALSE;
  444.         }
  445.         goto dircheck;
  446.  
  447.     /* another DOS dir result (file count)--skip it, too */
  448.     } else if( isdigit( dirtest[0] ) ) {
  449.         scratch_ptr = dirtest;
  450.         while( *scratch_ptr  &&  !isspace( *scratch_ptr++ ) );
  451.         if( strcmp( scratch_ptr, "FILE("   ) == 0  ||
  452.             strcmp( scratch_ptr, "FILE(S"  ) == 0  ||
  453.             strcmp( scratch_ptr, "FILE(S)" ) == 0     ) {
  454.  
  455.             if( !fnext_line(infile->fp) ) {
  456.                 errstr = cvector( 0, 80 );
  457.                 strcpy( errstr, "\nInput file " );
  458.                 strcat( errstr, infile->name );
  459.                 strcat( errstr, " is empty!\n\n" );
  460.                 ferrout( ON, stdout, errstr );
  461.                 free_cvector( errstr, 0 );
  462.                 fclose( infile->fp );
  463.                 return FALSE;
  464.             }
  465.             goto dircheck;
  466.         } else {
  467.             *dirflag = 0;            /* not a dirfile */
  468.             rewind( infile->fp );
  469.         }
  470.  
  471.     } else {        /* infile not a directory -- reset infile position */
  472.         *dirflag = 0;
  473.         rewind( infile->fp );
  474.     }
  475.  
  476.  
  477.  
  478. /* set output file name and extension if infile is not a dirfile */
  479.     if( *dirflag == 0 ) {
  480.  
  481.         if( nargs == 2 ) {        /* only infile specified */
  482.             strcpy( out_name, in_name );
  483.             strcpy( out_ext, default_out_ext );
  484.         } else {                /* output file name was specified */
  485.             if( *argv[2] == DOT ) {            /* extension only */
  486.                 strcpy( out_name, in_name );
  487.                 strcpy( out_ext, argv[2] );
  488.             } else {
  489.                 char_ptr = (char *) strchr( argv[2], DOT );
  490.                 if( char_ptr == NULL ) {    /* name only */
  491.                     strcpy( out_name, argv[2] );
  492.                     strcpy( out_ext, default_out_ext );
  493.                 } else {                    /* full file name given */
  494.                     arg_ptr  = argv[2];
  495.                     name_ptr = out_name;
  496.                     while( strcmp( arg_ptr, char_ptr ) != 0 ) /* copy name */
  497.                         *name_ptr++ = *arg_ptr++;
  498.                     *name_ptr = NULL;
  499.                     strcpy( out_ext, char_ptr );              /* copy ext */
  500.                 }
  501.             }
  502.         }
  503.  
  504.         /* form full file name */
  505.         strcpy( outfile->name, out_name );
  506.         strcat( outfile->name, out_ext );
  507.     }
  508.  
  509.  
  510.  
  511. /* get infile and outfile names if infile is a dirfile */
  512.     if( *dirflag ) {
  513.  
  514.         /* set file extensions */
  515.         if( nargs == 2 ) {
  516.             strcpy( def_ext, default_in_ext );
  517.             strcpy( out_ext, default_out_ext );
  518.         } else if( nargs == 3 ) {
  519.             strcpy( def_ext, default_in_ext );
  520.             if( *argv[2] == DOT )
  521.                 strcpy( out_ext, argv[2] );
  522.             else 
  523.                 strcpy( out_ext, default_out_ext );
  524.         } else {    /* 4 or more cl args present */
  525.             if( *argv[2] != DOT ) {
  526.                 strcpy( def_ext, default_in_ext );
  527.                 strcpy( out_ext, default_out_ext );
  528.             } else {
  529.                 if( *argv[3] == DOT ) {
  530.                     strcpy( def_ext, argv[2] );
  531.                     strcpy( default_in_ext, argv[2] );
  532.                     strcpy( out_ext, argv[3] );
  533.                     strcpy( default_out_ext, argv[3] );
  534.                 } else {
  535.                     strcpy( def_ext, default_in_ext );
  536.                     strcpy( out_ext, argv[2] );
  537.                     strcpy( default_out_ext, argv[2] );
  538.                 }
  539.             }
  540.         }
  541.  
  542.  
  543.         /* input file name */
  544.         i = get_filename( dirfile, def_ext, infile->name, in_name, in_ext );
  545.         strcpy( infile->name, in_name );        /* override get_filename */
  546.         strcat( infile->name, def_ext );
  547.  
  548.         /* error--end program now */
  549.         if( ! i ) {
  550.             errstr = cvector( 0, 80 );
  551.             strcpy( errstr, "\nDirectory file " );
  552.             strcat( errstr, infile->name );
  553.             strcat( errstr, " is empty or doesn't contain a valid input " );
  554.             strcat( errstr, "file name!\n\n" );
  555.             ferrout( ON, stdout, errstr );
  556.             free_cvector( errstr, 0 );
  557.             fclose( dirfile->fp );
  558.             return FALSE;
  559.         }
  560.  
  561.         /* output file name */
  562.         strcpy( outfile->name, in_name );
  563.         strcat( outfile->name, out_ext );
  564.  
  565.  
  566.         /* open input file */
  567.         status = openfile( infile, mode, FREAD );
  568.         if( !status )  return FALSE;
  569.  
  570.     }
  571.  
  572.  
  573. /* check for outfile = infile, then open outfile */
  574.     if( *dirflag == 0  &&  strcmp( infile->name, outfile->name ) == 0  ) {
  575.         ferrout( ON, stdout, "\nCannot allow infile = outfile\n\n");
  576.         fclose( infile->fp );
  577.         return FALSE;
  578.     }
  579.  
  580.     status = openfile( outfile, mode, FWRITE );
  581.     if( !status )  return FALSE;
  582.  
  583.     return TRUE;
  584. }
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  595. /*                                                                         */
  596. /* Function to get the next file name from the list in dirfile, parse it,  */
  597. /* and return the parts of the input and output file names. The input and  */
  598. /* output files will be opened for read-only and write-only.               */
  599. /*                                                                         */
  600. /* On exit,                                                                */
  601. /*        *infile            =    File_Def structure pointer for input file      */
  602. /*         *outfile          =    File_Def structure pointer for output file     */
  603. /*        in_name[]        =    character array containing the infile_name     */
  604. /*                             minus the file extension                         */
  605. /*        in_ext[]        =    character array containing the input file      */
  606. /*                             extension                                     */
  607. /*        out_name[]        =    character array containing the outfile_name    */
  608. /*                             minus the file extension                         */
  609. /*        out_ext[]        =    character array containing the output file     */
  610. /*                             extension                                     */
  611. /*        *dirfile        =    closed if encountered EOF, left alone             */
  612. /*                             otherwise                                         */
  613. /*                                                                         */
  614. /*                                                                         */
  615. /* get_next_file returns  0  if error,  1 if no error                      */
  616. /*                                                                         */
  617. /* function dependencies:  get_filename                                    */
  618. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  619. Boolean get_next_file( File_Def *dirfile, File_Def *infile, 
  620.                        File_Def *outfile, File_Mode mode, 
  621.                        char default_in_ext[], char in_name[], 
  622.                        char in_ext[], char out_name[], char out_ext[] )
  623. {
  624.     int        i;
  625.  
  626.  
  627. /* get the next name in the list */
  628.     i = get_filename( dirfile, default_in_ext, infile->name, 
  629.                       in_name, in_ext );
  630.  
  631. /* no more in list */
  632.     if( !i ) {
  633.         fclose( dirfile->fp );
  634.         return FALSE;
  635.     }
  636.  
  637. /* open input file for reading */
  638.     i = openfile( infile, mode, FREAD );
  639.     if( !i )  return FALSE;
  640.  
  641. /* form output file name and open it for writing */
  642.     strcpy( outfile->name, in_name );
  643.     strcpy( out_name, in_name );
  644.     strcat( outfile->name, out_ext );
  645.     i = openfile( outfile, mode, FWRITE );
  646.     if( !i )  return FALSE;
  647.  
  648.     return TRUE;
  649. }
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  663. /*                                                                     */
  664. /* Function to extract next file name from a list of file names.       */
  665. /* The name to be extracted is assumed to be on the current line (i.e.,*/
  666. /* before the next end-of-line character if the line is not blank).    */
  667. /*                                                                     */
  668. /*     on entry:                                                          */
  669. /*        dirfile            =    pointer to directory file, which must      */
  670. /*                             already be opened and waiting to be read  */
  671. /*        default_ext[]     =    character array containing default input   */
  672. /*                             file extension                            */
  673. /*                                                                     */
  674. /*    on exit:                                                           */
  675. /*        infile_name[]    =    character array containing full input      */
  676. /*                             file name                                 */
  677. /*        in_name[]        =    character array containing the infile_name */
  678. /*                             minus the file extension                     */
  679. /*        in_ext[]        =    character array containing the input file  */
  680. /*                             extension                                 */
  681. /*                                                                     */
  682. /*        get_filename returns:                                          */
  683. /*            1 if attempt to read file name from dirfile was successful */
  684. /*          0 if attempt encountered EOF                               */
  685. /*                                                                     */
  686. /* function dependencies:  fnext_line, dncase                          */
  687. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  688. Boolean get_filename( File_Def *dirfile, char default_ext[], 
  689.                       char infile_name[], char in_name[], char in_ext[] )
  690. {
  691.     char    c, *name_ptr, *dot_ptr;
  692.     char    test[MAX_FNAME];
  693.  
  694.  
  695. extract:
  696.  
  697. /* check to make sure we're not already at end of file */
  698.     if( feof( dirfile->fp ) )  return FALSE;
  699.  
  700. /* extract input file name */
  701.     name_ptr = infile_name;
  702.     do {                        /* skip over leading white space */
  703.         c = getc( dirfile->fp );
  704.         if( c == EOF )  return FALSE;
  705.     } while( isspace(c) );
  706.  
  707.     *name_ptr++ = c;            /* put first character to infile_name */
  708.     do {                        /* get the rest of the characters */
  709.         c = getc( dirfile->fp );
  710.         *name_ptr++ = c;
  711.     } while( c == DOT || isalnum(c) || c == '_' || c == '$' && c != EOF );
  712.     *(--name_ptr) = NULL;                    /* put a NULL after last char */
  713.  
  714.  
  715.  
  716. /* check for DOS dir dreck and skip it */
  717.     if( strcmp( infile_name, "Volume" ) == 0 ) {    /* volume name */
  718.         if( !fnext_line(dirfile->fp) )  return FALSE;
  719.         goto extract;
  720.     } else if( isdigit( infile_name[0] ) ) {        /* file count */
  721.         /* skip white */
  722.         while( (c = getc(dirfile->fp)) != EOF  &&  c != '\n'  &&  isspace(c) );
  723.         if( c == EOF )  return FALSE;
  724.  
  725.         /* look for "File(s)" */
  726.         name_ptr    = test;
  727.         *name_ptr++ = c;
  728.         while( (c = getc(dirfile->fp)) != EOF  &&  c != '\n'  &&  !isspace(c) )
  729.             *name_ptr++ = c;
  730.         *name_ptr = NULL;
  731.         if( strcmp( test, "File(s)" ) == 0     ) {
  732.             if( !fnext_line(dirfile->fp) )  return FALSE;
  733.             goto extract;
  734.         }
  735.     }
  736.  
  737.  
  738. /* skip to end of line in preparation for next time */
  739.     fnext_line( dirfile->fp );
  740.  
  741.  
  742. /* parse file name */
  743.     dot_ptr = (char *) strchr( infile_name, DOT );
  744.     if( dot_ptr == NULL ) {                    /* name does not contain a "." */
  745.         strcpy( in_name, infile_name );
  746.         strcpy( in_ext, default_ext );
  747.         strcat( infile_name, in_ext );
  748.     } else {                                /* name contains a "." */
  749.         strcpy( in_ext, dot_ptr );          /* get file extension */
  750.         strcpy( in_name, infile_name );        /* get name */
  751.         dot_ptr  = (char *) strchr( in_name, DOT );
  752.         *dot_ptr = NULL;
  753.     }
  754.  
  755.  
  756. /* lower case */
  757.     infile_name = dncase( infile_name );
  758.     in_name     = dncase( in_name );
  759.     in_ext      = dncase( in_ext );
  760.  
  761.  
  762.     return TRUE;
  763. }
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  773. /* unsigned long fill_file_buff( FILE *infile, File_Type ftype, long Nmax, */
  774. /*                               char *buff_ptr, int *EOF_ptr )            */
  775. /*                                                                         */
  776. /* Function to fill a buffer from infile. Nmax is max number of bytes      */
  777. /* to read. Filling begins at the place pointed to by buff_ptr. If the end */
  778. /* of the file is reached before the buffer is full, the flag pointed to   */
  779. /* by EOF_ptr is set to 1; otherwise, it is set to 0 on entry to this      */
  780. /* routine. ftype must be either TEXT or BINARY.                           */
  781. /*                                                                         */
  782. /* fill_file_buff returns the number of bytes read from infile, not        */
  783. /* counting the EOF if encountered or the NULL placed at the end of the    */
  784. /* buffer.                                                                 */
  785. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  786. unsigned long  fill_file_buff( FILE *infile, File_Type ftype, ulong Nmax, 
  787.                                char *buff_ptr, int *EOF_ptr )
  788. {
  789.     ulong     i;
  790.     int        c;
  791.     char    *p;
  792.  
  793.  
  794.     if( ftype != FTEXT  &&  ftype != FBINARY ) {
  795.         ferrout( ON, stdout, "\nfill_file_buff:  Invalid ftype!\n\n" );
  796.         *EOF_ptr = 1;
  797.         return 0;
  798.     }
  799.  
  800.  
  801.     *EOF_ptr = 0;
  802.     p = buff_ptr;
  803.     for( i = 0;  i < Nmax;  i++ ) {
  804.         c = getc( infile );
  805.         if( c == EOF ) {
  806.             *EOF_ptr = 1;
  807.             break;
  808.         } else if( c == NEWLINE ) 
  809.             if( ftype == FTEXT )  i++;                /* '\n' == cr + lf */
  810.         *p++ = c;
  811.     }
  812.  
  813.     *p = NULL;
  814.  
  815.     return i;
  816. }
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.                                                 
  825. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  826. /* unsigned long append_buff( char *source_buff, unsigned long N,          */
  827. /*                            char *dest_buff )                            */
  828. /*                                                                         */
  829. /* Function to append a destination buffer pointed to by dest_buff         */
  830. /* with N bytes from a source buffer pointed to by source_buff. N is       */
  831. /* the number of bytes to copy. Source buffer must contain a NULL-         */
  832. /* terminated string. Bytes from *source_buff will be transferred starting */
  833. /* from the entry position of source_buff and continuing until either N    */
  834. /* bytes have been copied or the NULL at the end of *source_buff has been  */
  835. /* reached. Copied bytes are placed starting at the entry position pointed */
  836. /* to by dest_buff. *dest_buff will contain a NULL-terminated string upon  */
  837. /* exit.                                                                   */
  838. /*                                                                         */
  839. /* append_buff returns the actual number of bytes copied.                  */
  840. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  841. unsigned long append_buff( char *source_buff, ulong N, char *dest_buff )
  842. {
  843.     ulong    i;
  844.     char    *s, *d;
  845.  
  846.     s = source_buff;
  847.     d = dest_buff;
  848.     for( i = 0;  *s  &&  i < N;  i++ )
  849.         *d++ = *s++;
  850.  
  851.     *d = NULL;
  852.     return i;
  853. }
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  863. /* unsigned int fill_line_buff( FILE *infile, File_Type ftype,             */
  864. /*                              char file_buffer[],                        */
  865. /*                                char **file_buff_ptr_ptr,                  */
  866. /*                                ulong Fbytes, unsigned int Lbytes,         */
  867. /*                                char *line_buff_ptr,                       */
  868. /*                                int msg_flag, int *EOF_ptr )               */
  869. /*                                                                         */
  870. /* Function to fill line buffer from file buffer.                          */
  871. /*                                                                         */
  872. /* Fill line buffer with Lbytes bytes, beginning from the element pointed  */
  873. /* to by line_buff_ptr, from the file buffer, starting from the element    */
  874. /* pointed to by the pointer pointed to by file_buff_ptr_ptr. If the file  */
  875. /* buffer runs out of bytes, read Fbytes more from infile. If the input    */
  876. /* file gets read and runs into the end-of-file marker, or if the EOF has  */
  877. /* already been encountered, *EOF_flag is set to 1; if not, it is set to   */
  878. /* zero. ftype must be either FTEXT or FBINARY.                            */
  879. /*                                                                         */
  880. /* If msg_flag = 1, then if bytes have to be read from the input file a    */
  881. /* "reading..." message is written to (and erased from) the screen.        */
  882. /*                                                                         */
  883. /* fill_line_buff returns the number of bytes actually put into the line   */
  884. /* buffer. The pointer pointed to by file_buff_ptr_ptr is updated to point */
  885. /* to the first unread element of file_buffer.                             */
  886. /*                                                                         */
  887. /* function dependencies:  append_buff,  fill_file_buff                    */
  888. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  889. uint  fill_line_buff( FILE *infile, File_Type ftype, char file_buffer[],
  890.                       char **file_buff_ptr_ptr, ulong Fbytes,  
  891.                       uint Lbytes, char *line_buff_ptr, int msg_flag, 
  892.                       int *EOF_ptr )
  893. {
  894.     uint    n;
  895.     ulong    k;
  896.     char    *file_buff_ptr;
  897.  
  898. /* try to move Lbytes bytes */
  899.     file_buff_ptr = *file_buff_ptr_ptr;
  900.     k = append_buff( file_buff_ptr, (unsigned long) Lbytes, line_buff_ptr );
  901.     n = (unsigned int) k;
  902.     *file_buff_ptr_ptr += n;
  903.  
  904. /* if not enough bytes were copied, get more from the input file */
  905.     if( n != Lbytes ) {
  906.         *file_buffer       = NULL;
  907.         file_buff_ptr      = file_buffer;
  908.         *file_buff_ptr_ptr = file_buff_ptr;
  909.         if( !feof(infile) ) {
  910.             if( msg_flag ) {
  911.                 printf( "\r % % % % % Reading input file " );
  912.                 printf( "% % % % %                    \r" );
  913.             }
  914.             k = fill_file_buff( infile, ftype, Fbytes, file_buff_ptr,
  915.                                 EOF_ptr );
  916.             if( msg_flag ) {
  917.                 printf( "\r                              " );
  918.                 printf( "                             \r" );
  919.             }
  920.             /* finish filling the line buffer */
  921.             line_buff_ptr += n;
  922.             k  = append_buff( file_buff_ptr, (unsigned long) (Lbytes - n), 
  923.                               line_buff_ptr );
  924.             n += (unsigned int) k;
  925.             *file_buff_ptr_ptr += (unsigned int) k;
  926.         } else        /* already at end of file on entry into this routine */
  927.             *EOF_ptr = 1;
  928.     }
  929.  
  930.     return n;
  931. }
  932.  
  933.  
  934.  
  935. /*
  936.  *
  937.  * error output routine
  938.  *
  939.  */
  940.  
  941. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  942. /* void ferrout( int bell, FILE *device, char *errstring )                 */
  943. /*                                                                         */
  944. /* error output                                                            */
  945. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  946. void  ferrout( Boolean bell, FILE *device, char *errstring )
  947. {
  948.     if( bell )  fprintf( device, "\a" );
  949.     fprintf( device, "%s", errstring );
  950.     return;
  951. }
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.