home *** CD-ROM | disk | FTP | other *** search
/ MPEG Toolkit / MPEG Toolkit.iso / os2 / mpegenc / src / param.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-01  |  20.4 KB  |  746 lines

  1. /*===========================================================================*
  2.  * param.c                                     *
  3.  *                                         *
  4.  *    Procedures to read in parameter file                     *
  5.  *                                         *
  6.  * EXPORTED PROCEDURES:                                 *
  7.  *    ReadParamFile                                 *
  8.  *    GetNthInputFileName                             *
  9.  *                                         *
  10.  *===========================================================================*/
  11.  
  12. /*
  13.  * Copyright (c) 1993 The Regents of the University of California.
  14.  * All rights reserved.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software and its
  17.  * documentation for any purpose, without fee, and without written agreement is
  18.  * hereby granted, provided that the above copyright notice and the following
  19.  * two paragraphs appear in all copies of this software.
  20.  *
  21.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  22.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  23.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  24.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  *
  26.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  27.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  28.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  29.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  30.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  31.  */
  32.  
  33. /*  
  34.  *  $Header: /n/picasso/users/keving/encode/src/RCS/param.c,v 1.2 1993/07/22 22:23:43 keving Exp keving $
  35.  *  $Log: param.c,v $
  36.  * Revision 1.2  1993/07/22  22:23:43  keving
  37.  * nothing
  38.  *
  39.  * Revision 1.1  1993/06/30  20:06:09  keving
  40.  * nothing
  41.  *
  42.  */
  43.  
  44.  
  45. /*==============*
  46.  * HEADER FILES *
  47.  *==============*/
  48.  
  49. #include "all.h"
  50. #include "mtypes.h"
  51. #include "mpeg.h"
  52. #include "search.h"
  53. #ifdef OS2
  54. /* @@@ FAT 8.3 convention */
  55. #include "prototyp.h"
  56. #else
  57. #include "prototypes.h"
  58. #endif
  59. #include "parallel.h"
  60. #include "param.h"
  61. #ifdef OS2
  62. /* @@@ FAT 8.3 convention */
  63. #include "readfram.h"
  64. #else
  65. #include "readframe.h"
  66. #endif
  67. #include "fsize.h"
  68.  
  69.  
  70. /*===========*
  71.  * CONSTANTS *
  72.  *===========*/
  73.  
  74. #define INPUT_ENTRY_BLOCK_SIZE   128
  75.  
  76. #define FIRST_OPTION 0
  77. #define OPTION_GOP  0
  78. #define OPTION_PATTERN 1
  79. #define OPTION_PIXEL 2
  80. #define OPTION_PQSCALE 3
  81. #define OPTION_OUTPUT 4
  82. #define OPTION_RANGE 5
  83. #define OPTION_PSEARCH_ALG 6
  84. #define OPTION_IQSCALE 7
  85. #define OPTION_INPUT_DIR 8
  86. #define OPTION_INPUT_CONVERT 9
  87. #define OPTION_INPUT 10
  88. #define OPTION_BQSCALE 11
  89. #define OPTION_BASE_FORMAT 12
  90. #define OPTION_SPF 13
  91. #define OPTION_BSEARCH_ALG 14
  92. #define OPTION_REF_FRAME    15
  93. #define LAST_OPTION 15
  94. /* YUV_SIZE not required, so put after LAST_OPTION */
  95. #define OPTION_IO_CONVERT   16
  96. #define OPTION_SLAVE_CONVERT    17
  97. #define OPTION_YUV_SIZE    18
  98.  
  99.  
  100. /*=======================*
  101.  * STRUCTURE DEFINITIONS *
  102.  *=======================*/
  103.  
  104. typedef struct InputFileEntryStruct {
  105.     char    left[256];
  106.     char    right[256];
  107.     boolean glob;        /* if FALSE, left is complete name */
  108.     int        startID;
  109.     int        endID;
  110.     int        skip;
  111.     int        numPadding;        /* -1 if there is none */
  112.     int        numFiles;
  113. } InputFileEntry;
  114.  
  115.  
  116. /*==================*
  117.  * STATIC VARIABLES *
  118.  *==================*/
  119.  
  120. static InputFileEntry **inputFileEntries;
  121. static int numInputFileEntries = 0;
  122. static int  maxInputFileEntries;
  123.  
  124.  
  125. /*==================*
  126.  * GLOBAL VARIABLES *
  127.  *==================*/
  128.  
  129. extern char currentPath[MAXPATHLEN];
  130. extern char currentGOPPath[MAXPATHLEN];
  131. extern char currentFramePath[MAXPATHLEN];
  132. char    outputFileName[256];
  133. int numInputFiles = 0;
  134. char inputConversion[1024];
  135. char ioConversion[1024];
  136. char slaveConversion[1024];
  137. boolean optionSeen[OPTION_YUV_SIZE+1];
  138. int numMachines;
  139. char    machineName[MAX_MACHINES][256];
  140. char    userName[MAX_MACHINES][256];
  141. char    executable[MAX_MACHINES][1024];
  142. char    remoteParamFile[MAX_MACHINES][1024];
  143. boolean    remote[MAX_MACHINES];
  144.  
  145.  
  146. /*===============================*
  147.  * INTERNAL PROCEDURE prototypes *
  148.  *===============================*/
  149.  
  150. static void    ReadInputFileNames _ANSI_ARGS_((FILE *fpointer,
  151.                         char *endInput));
  152. static char    *SkipSpacesTabs _ANSI_ARGS_((char *start));
  153. static void    ReadMachineNames _ANSI_ARGS_((FILE *fpointer));
  154.  
  155.  
  156. /*=====================*
  157.  * EXPORTED PROCEDURES *
  158.  *=====================*/
  159.  
  160.  
  161. /*===========================================================================*
  162.  *
  163.  * ReadParamFile
  164.  *
  165.  *    read the parameter file
  166.  *    function is ENCODE_FRAMES, COMBINE_GOPS, or COMBINE_FRAMES, and
  167.  *        will slightly modify the procedure's behavior as to what it
  168.  *        is looking for in the parameter file
  169.  *
  170.  * RETURNS:    TRUE if the parameter file was read correctly; FALSE if not
  171.  *
  172.  * SIDE EFFECTS:    sets parameters accordingly, as well as machine info for
  173.  *            parallel execution and input file names
  174.  *
  175.  *===========================================================================*/
  176. boolean
  177. ReadParamFile(fileName, function)
  178.     char *fileName;
  179.     int function;
  180. {
  181.     FILE *fpointer;
  182.     char    input[256];
  183.     char    *charPtr;
  184.     boolean yuvUsed = FALSE;
  185.     static char *optionText[LAST_OPTION+1] = { "GOP", "PATTERN", "PIXEL", "PQSCALE",
  186.     "OUTPUT", "RANGE", "PSEARCH_ALG", "IQSCALE", "INPUT_DIR",
  187.     "INPUT_CONVERT", "INPUT", "BQSCALE", "BASE_FILE_FORMAT",
  188.     "SLICES_PER_FRAME", "BSEARCH_ALG", "REFERENCE_FRAME" };
  189.     register int index;
  190.  
  191.     if ( (fpointer = fopen(fileName, "r")) == NULL ) {
  192.     fprintf(stderr, "Error:  Cannot open parameter file:  %s\n", fileName);
  193.     return FALSE;
  194.     }
  195.  
  196.     /* should set defaults */
  197.     numInputFiles = 0;
  198.     numMachines = 0;
  199.     sprintf(currentPath, ".");
  200.     sprintf(currentGOPPath, ".");
  201.     sprintf(currentFramePath, ".");
  202.     SetRemoteShell("rsh");
  203.  
  204.     switch(function) {
  205.     case ENCODE_FRAMES:
  206.         for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) {
  207.         optionSeen[index] = FALSE;
  208.         }
  209.         optionSeen[OPTION_YUV_SIZE] = FALSE;
  210.         optionSeen[OPTION_IO_CONVERT] = FALSE;
  211.         optionSeen[OPTION_SLAVE_CONVERT] = FALSE;
  212.         break;
  213.     case COMBINE_GOPS:
  214.         for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) {
  215.         optionSeen[index] = TRUE;
  216.         }
  217.  
  218.         optionSeen[OPTION_YUV_SIZE] = FALSE;
  219.         optionSeen[OPTION_OUTPUT] = FALSE;
  220.         break;
  221.     case COMBINE_FRAMES:
  222.         for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) {
  223.         optionSeen[index] = TRUE;
  224.         }
  225.  
  226.         optionSeen[OPTION_GOP] = FALSE;
  227.         optionSeen[OPTION_OUTPUT] = FALSE;
  228.         optionSeen[OPTION_YUV_SIZE] = FALSE;
  229.         break;
  230.     }
  231.  
  232.     while ( fgets(input, 256, fpointer) != NULL ) {
  233.     if ( input[0] == '#' ) {        /* skip comments */
  234.         continue;
  235.     }
  236.  
  237.     input[strlen(input)-1] = '\0';    /* get rid of newline */
  238.  
  239.     switch(input[0]) {
  240.         case 'G':
  241.         if ( strncmp(input, "GOP_SIZE", 8) == 0 ) {
  242.             charPtr = SkipSpacesTabs(&input[8]);
  243.             SetGOPSize(atoi(charPtr));
  244.             optionSeen[OPTION_GOP] = TRUE;
  245.         } else if ( strncmp(input, "GOP_INPUT_DIR", 13) == 0 ) {
  246.             charPtr = SkipSpacesTabs(&input[13]);
  247.             strcpy(currentGOPPath, charPtr);
  248.         } else if ( strncmp(input, "GOP_INPUT", 9) == 0 ) {
  249.             if ( function == COMBINE_GOPS ) {
  250.             ReadInputFileNames(fpointer, "GOP_END_INPUT");
  251.             }
  252.         }
  253.         break;
  254.  
  255.         case 'F':
  256.         if ( strncmp(input, "FRAME_INPUT_DIR", 15) == 0 ) {
  257.             charPtr = SkipSpacesTabs(&input[15]);
  258.             strcpy(currentFramePath, charPtr);
  259.         } else if ( strncmp(input, "FRAME_INPUT", 11) == 0 ) {
  260.             if ( function == COMBINE_FRAMES ) {
  261.             ReadInputFileNames(fpointer, "FRAME_END_INPUT");
  262.             }
  263.         } else if ( strncmp(input, "FORCE_I_ALIGN", 13) == 0 ) {
  264.             forceIalign = TRUE;
  265.         }
  266.         break;
  267.  
  268.         case 'P':
  269.         if ( strncmp(input, "PATTERN", 7) == 0 ) {
  270.             charPtr = SkipSpacesTabs(&input[7]);
  271.             SetFramePattern(charPtr);
  272.             optionSeen[OPTION_PATTERN] = TRUE;
  273.         } else if ( strncmp(input, "PIXEL", 5) == 0 ) {
  274.             charPtr = SkipSpacesTabs(&input[5]);
  275.             SetPixelSearch(charPtr);
  276.             optionSeen[OPTION_PIXEL] = TRUE;
  277.         } else if ( strncmp(input, "PQSCALE", 7) == 0 ) {
  278.             charPtr = SkipSpacesTabs(&input[7]);
  279.             SetPQScale(atoi(charPtr));
  280.             optionSeen[OPTION_PQSCALE] = TRUE;
  281.         } else if ( strncmp(input, "PSEARCH_ALG", 11) == 0 ) {
  282.             charPtr = SkipSpacesTabs(&input[11]);
  283.             SetPSearchAlg(charPtr);
  284.             optionSeen[OPTION_PSEARCH_ALG] = TRUE;
  285.         } else if ( strncmp(input, "PARALLEL_TEST_FRAMES", 20) == 0 ) {
  286.             charPtr = SkipSpacesTabs(&input[20]);
  287.             parallelTestFrames = atoi(charPtr);
  288.         } else if ( strncmp(input, "PARALLEL_TIME_CHUNKS", 20) == 0 ) {
  289.             charPtr = SkipSpacesTabs(&input[20]);
  290.             parallelTimeChunks = atoi(charPtr);
  291.         } else if ( strncmp(input, "PARALLEL_PERFECT", 16) == 0 ) {
  292.             SetParallelPerfect();
  293.         } else if ( strncmp(input, "PARALLEL", 8) == 0 ) {
  294.             ReadMachineNames(fpointer);
  295.         }
  296.         break;
  297.  
  298.         case 'O':
  299.         if ( strncmp(input, "OUTPUT", 6) == 0 ) {
  300.             charPtr = SkipSpacesTabs(&input[6]);
  301.             if ( whichGOP == -1 ) {
  302.             strcpy(outputFileName, charPtr);
  303.             } else {
  304.             sprintf(outputFileName, "%s.gop.%d",
  305.                 charPtr, whichGOP);
  306.             }
  307.  
  308.             optionSeen[OPTION_OUTPUT] = TRUE;
  309.         }
  310.         break;
  311.  
  312.         case 'R':
  313.         if ( strncmp(input, "RANGE", 5) == 0 ) {
  314.             charPtr = SkipSpacesTabs(&input[5]);
  315.             SetSearchRange(atoi(charPtr));
  316.             optionSeen[OPTION_RANGE] = TRUE;
  317.         } else if ( strncmp(input, "REFERENCE_FRAME", 15) == 0 ) {
  318.             charPtr = SkipSpacesTabs(&input[15]);
  319.             SetReferenceFrameType(charPtr);
  320.             optionSeen[OPTION_REF_FRAME] = TRUE;
  321.         } else if ( strncmp(input, "RSH", 3) == 0 ) {
  322.             charPtr = SkipSpacesTabs(&input[3]);
  323.             SetRemoteShell(charPtr);
  324.         }
  325.  
  326.         break;
  327.  
  328.         case 'S':
  329.         if ( strncmp(input, "SLICES_PER_FRAME", 16) == 0 ) {
  330.             charPtr = SkipSpacesTabs(&input[16]);
  331.             SetSlicesPerFrame(atoi(charPtr));
  332.             optionSeen[OPTION_SPF] = TRUE;
  333.         } else if ( strncmp(input, "SLAVE_CONVERT", 13) == 0 ) {
  334.             charPtr = SkipSpacesTabs(&input[13]);
  335.             strcpy(slaveConversion, charPtr);
  336.             optionSeen[OPTION_SLAVE_CONVERT] = TRUE;
  337.         }
  338.  
  339.         break;
  340.  
  341.         case 'I':
  342.         if ( strncmp(input, "IQSCALE", 7) == 0 ) {
  343.             charPtr = SkipSpacesTabs(&input[7]);
  344.             SetIQScale(atoi(charPtr));
  345.             optionSeen[OPTION_IQSCALE] = TRUE;
  346.         } else if ( strncmp(input, "INPUT_DIR", 9) == 0 ) {
  347.             charPtr = SkipSpacesTabs(&input[9]);
  348.             strcpy(currentPath, charPtr);
  349.             optionSeen[OPTION_INPUT_DIR] = TRUE;
  350.         } else if ( strncmp(input, "INPUT_CONVERT", 13) == 0 ) {
  351.             charPtr = SkipSpacesTabs(&input[13]);
  352.             strcpy(inputConversion, charPtr);
  353.             optionSeen[OPTION_INPUT_CONVERT] = TRUE;
  354.         } else if ( strcmp(input, "INPUT") == 0 ) {   /* yes, strcmp */
  355.             if ( function == ENCODE_FRAMES ) {
  356.             ReadInputFileNames(fpointer, "END_INPUT");
  357.             optionSeen[OPTION_INPUT] = TRUE;
  358.             }
  359.         } else if ( strncmp(input, "IO_SERVER_CONVERT", 17) == 0 ) {
  360.             charPtr = SkipSpacesTabs(&input[17]);
  361.             strcpy(ioConversion, charPtr);
  362.             optionSeen[OPTION_IO_CONVERT] = TRUE;
  363.         }
  364.  
  365.         break;
  366.  
  367.         case 'B':
  368.         if ( strncmp(input, "BQSCALE", 7) == 0 ) {
  369.             charPtr = SkipSpacesTabs(&input[7]);
  370.             SetBQScale(atoi(charPtr));
  371.             optionSeen[OPTION_BQSCALE] = TRUE;
  372.         } else if ( strncmp(input, "BASE_FILE_FORMAT", 16) == 0 ) {
  373.             charPtr = SkipSpacesTabs(&input[16]);
  374.             SetFileFormat(charPtr);
  375.             if ( strcmp(charPtr, "YUV") == 0 ) {
  376.                 yuvUsed = TRUE;
  377.             }
  378.             optionSeen[OPTION_BASE_FORMAT] = TRUE;
  379.         } else if ( strncmp(input, "BSEARCH_ALG", 11) == 0 ) {
  380.             charPtr = SkipSpacesTabs(&input[11]);
  381.             SetBSearchAlg(charPtr);
  382.             optionSeen[OPTION_BSEARCH_ALG] = TRUE;
  383.         }
  384.         break;
  385.  
  386.         case 'Y':
  387.         if ( strncmp(input, "YUV_SIZE", 8) == 0 ) {
  388.             charPtr = SkipSpacesTabs(&input[8]);
  389.             sscanf(charPtr, "%dx%d", &yuvWidth, &yuvHeight);
  390.             realWidth = yuvWidth;
  391.             realHeight = yuvHeight;
  392.             Fsize_Validate(&yuvWidth, &yuvHeight);
  393.             optionSeen[OPTION_YUV_SIZE] = TRUE;
  394.         }
  395.         break;
  396.         default:
  397.         break;
  398.     }
  399.     }
  400.  
  401.     fclose(fpointer);
  402.  
  403.     for ( index = FIRST_OPTION; index <= LAST_OPTION; index++ ) {
  404.     if ( ! optionSeen[index] ) {
  405.         fprintf(stdout, "ERROR:  Missing option '%s'\n", optionText[index]);
  406.         exit(1);
  407.     }
  408.     }
  409.  
  410.     /* error checking */
  411.     if ( yuvUsed && (! optionSeen[OPTION_YUV_SIZE]) ) {
  412.         fprintf(stderr, "ERROR:  YUV format used but YUV_SIZE not given\n");
  413.     exit(1);
  414.     }
  415.  
  416.     if ( optionSeen[OPTION_IO_CONVERT] != optionSeen[OPTION_SLAVE_CONVERT] ) {
  417.         fprintf(stderr, "ERROR:  must have either both IO_SERVER_CONVERT and SLAVE_CONVERT\n");
  418.         fprintf(stderr, "        or neither\n");
  419.     exit(1);
  420.     }
  421.  
  422.     SetIOConvert(optionSeen[OPTION_IO_CONVERT]);
  423.  
  424.     SetFCode();
  425.  
  426.     if ( psearchAlg == PSEARCH_TWOLEVEL )
  427.     SetPixelSearch("HALF");
  428.  
  429.     return TRUE;
  430. }
  431.  
  432.  
  433. /*===========================================================================*
  434.  *
  435.  * GetNthInputFileName
  436.  *
  437.  *    finds the nth input file name
  438.  *
  439.  * RETURNS:    name is placed in already allocated fileName string
  440.  *
  441.  * SIDE EFFECTS:    none
  442.  *
  443.  *===========================================================================*/
  444. void
  445. GetNthInputFileName(fileName, n)
  446.     char *fileName;
  447.     int n;
  448. {
  449.     static int    lastN = 0, lastMapN = 0, lastSoFar = 0;
  450.     int        mapN;
  451.     register int index;
  452.     int        soFar;
  453.     int        loop;
  454.     int        numPadding;
  455.     char    numBuffer[33];
  456.  
  457.     /* assumes n is within bounds 0...numInputFiles-1 */
  458.  
  459.     if ( n >= lastN ) {
  460.     soFar = lastSoFar;
  461.     index = lastMapN;
  462.     } else {
  463.     soFar = 0;
  464.     index = 0;
  465.     }
  466.  
  467.     while ( soFar + inputFileEntries[index]->numFiles <= n ) {
  468.     soFar +=  inputFileEntries[index]->numFiles;
  469.     index++;
  470.     }
  471.  
  472.     mapN = index;
  473.  
  474.     index = inputFileEntries[mapN]->startID +
  475.         inputFileEntries[mapN]->skip*(n-soFar);
  476.  
  477.     numPadding = inputFileEntries[mapN]->numPadding;
  478.  
  479.     if ( numPadding != -1 ) {
  480.     sprintf(numBuffer, "%32d", index);
  481.     for ( loop = 32-numPadding; loop < 32; loop++ ) {
  482.         if ( numBuffer[loop] != ' ' ) {
  483.         break;
  484.         } else {
  485.         numBuffer[loop] = '0';
  486.         }
  487.     }
  488.  
  489.     sprintf(fileName, "%s%s%s",
  490.         inputFileEntries[mapN]->left,
  491.         &numBuffer[32-numPadding],
  492.         inputFileEntries[mapN]->right);
  493.     } else {
  494.     sprintf(fileName, "%s%d%s",
  495.         inputFileEntries[mapN]->left,
  496.         index,
  497.         inputFileEntries[mapN]->right);
  498.     }
  499.  
  500.     lastN = n;
  501.     lastMapN = mapN;
  502.     lastSoFar = soFar;
  503. }
  504.  
  505.  
  506. /*=====================*
  507.  * INTERNAL PROCEDURES *
  508.  *=====================*/
  509.  
  510. /*===========================================================================*
  511.  *
  512.  * ReadMachineNames
  513.  *
  514.  *    read a list of machine names for parallel execution
  515.  *
  516.  * RETURNS:    nothing
  517.  *
  518.  * SIDE EFFECTS:    machine info updated
  519.  *
  520.  *===========================================================================*/
  521. static void
  522. ReadMachineNames(fpointer)
  523.     FILE *fpointer;
  524. {
  525.     char    input[256];
  526.     char    *charPtr;
  527.  
  528.     while ( (fgets(input, 256, fpointer) != NULL) &&
  529.         (strncmp(input, "END_PARALLEL", 12) != 0) ) {
  530.     if ( input[0] == '#' ) {
  531.         continue;
  532.     }
  533.  
  534.     if ( strncmp(input, "REMOTE", 6) == 0 ) {
  535.         charPtr = SkipSpacesTabs(&input[6]);
  536.         remote[numMachines] = TRUE;
  537.  
  538.         sscanf(charPtr, "%s %s %s %s", machineName[numMachines],
  539.            userName[numMachines], executable[numMachines],
  540.            remoteParamFile[numMachines]);
  541.     } else {
  542.         remote[numMachines] = FALSE;
  543.  
  544.         sscanf(input, "%s %s %s", machineName[numMachines],
  545.            userName[numMachines], executable[numMachines]);
  546.     }
  547.  
  548.     numMachines++;
  549.     }
  550. }
  551.  
  552.  
  553. /*===========================================================================*
  554.  *
  555.  * ReadInputFileNames
  556.  *
  557.  *    read a list of input file names
  558.  *
  559.  * RETURNS:    nothing
  560.  *
  561.  * SIDE EFFECTS:    info stored for retrieval using GetNthInputFileName
  562.  *
  563.  *===========================================================================*/
  564. static void
  565. ReadInputFileNames(fpointer, endInput)
  566.     FILE *fpointer;
  567.     char *endInput;
  568. {
  569.     char    input[256];
  570.     char left[256], right[256];
  571.     char *globPtr, *charPtr;
  572.     char leftNumText[256], rightNumText[256];
  573.     char    skipNumText[256];
  574.     int    leftNum, rightNum;
  575.     int        skipNum;
  576.     boolean padding;
  577.     int        numPadding = 0;
  578.     int        length;
  579.  
  580.     inputFileEntries = (InputFileEntry **) malloc(INPUT_ENTRY_BLOCK_SIZE*
  581.                           sizeof(InputFileEntry *));
  582.     maxInputFileEntries = INPUT_ENTRY_BLOCK_SIZE;
  583.  
  584.     length = strlen(endInput);
  585.  
  586.     /* read input files up until endInput */
  587.     while ( (fgets(input, 256, fpointer) != NULL) &&
  588.         (strncmp(input, endInput, length) != 0) ) {
  589.     if ( input[0] == '#' ) {
  590.         continue;
  591.     }
  592.  
  593.     input[strlen(input)-1] = '\0';    /* get rid of newline */
  594.  
  595.     if ( numInputFileEntries == maxInputFileEntries ) {    /* more space! */
  596.         maxInputFileEntries += INPUT_ENTRY_BLOCK_SIZE;
  597.         inputFileEntries = realloc(inputFileEntries,
  598.                        maxInputFileEntries*
  599.                        sizeof(InputFileEntry *));
  600.     }
  601.  
  602.     inputFileEntries[numInputFileEntries] = (InputFileEntry *)
  603.                         malloc(sizeof(InputFileEntry));
  604.  
  605.     if ( input[strlen(input)-1] == ']' ) {
  606.         inputFileEntries[numInputFileEntries]->glob = TRUE;
  607.  
  608.         /* star expand */
  609.  
  610.         globPtr = input;
  611.         charPtr = left;
  612.         /* copy left of '*' */
  613.         while ( (*globPtr != '\0') && (*globPtr != '*') ) {
  614.         *charPtr = *globPtr;
  615.         charPtr++;
  616.         globPtr++;
  617.         }
  618.         *charPtr = '\0';
  619.  
  620.         globPtr++;
  621.         charPtr = right;
  622.         /* copy right of '*' */
  623.         while ( (*globPtr != '\0') && (*globPtr != ' ') &&
  624.             (*globPtr != '\t') ) {
  625.         *charPtr = *globPtr;
  626.         charPtr++;
  627.         globPtr++;
  628.         }
  629.         *charPtr = '\0';
  630.  
  631.         globPtr = SkipSpacesTabs(globPtr);
  632.  
  633.         if ( *globPtr != '[' ) {
  634.         fprintf(stderr, "ERROR:  Invalid input file expansion expression (no '[')\n");
  635.         exit(1);
  636.         }
  637.  
  638.         globPtr++;
  639.         charPtr = leftNumText;
  640.         /* copy left number */
  641.         while ( isdigit(*globPtr) ) {
  642.         *charPtr = *globPtr;
  643.         charPtr++;
  644.         globPtr++;
  645.         }
  646.         *charPtr = '\0';
  647.  
  648.         if ( *globPtr != '-' ) {
  649.         fprintf(stderr, "ERROR:  Invalid input file expansion expression (no '-')\n");
  650.         exit(1);
  651.         }
  652.  
  653.         globPtr++;
  654.         charPtr = rightNumText;
  655.         /* copy right number */
  656.         while ( isdigit(*globPtr) ) {
  657.         *charPtr = *globPtr;
  658.         charPtr++;
  659.         globPtr++;
  660.         }
  661.         *charPtr = '\0';
  662.  
  663.  
  664.         if ( *globPtr != ']' ) {
  665.         if ( *globPtr != '+' ) {
  666.             fprintf(stderr, "ERROR:  Invalid input file expansion expression (no ']')\n");
  667.             exit(1);
  668.         }
  669.  
  670.         globPtr++;
  671.         charPtr = skipNumText;
  672.         /* copy skip number */
  673.         while ( isdigit(*globPtr) ) {
  674.             *charPtr = *globPtr;
  675.             charPtr++;
  676.             globPtr++;
  677.         }
  678.         *charPtr = '\0';
  679.  
  680.         if ( *globPtr != ']' ) {
  681.             fprintf(stderr, "ERROR:  Invalid input file expansion expression (no ']')\n");
  682.             exit(1);
  683.         }
  684.  
  685.         skipNum = atoi(skipNumText);
  686.         } else {
  687.         skipNum = 1;
  688.         }
  689.  
  690.         leftNum = atoi(leftNumText);
  691.         rightNum = atoi(rightNumText);
  692.  
  693.         if ( (leftNumText[0] == '0') && (leftNumText[1] != '\0') ) {
  694.         padding = TRUE;
  695.         numPadding = strlen(leftNumText);
  696.         } else {
  697.         padding = FALSE;
  698.         }
  699.  
  700.         inputFileEntries[numInputFileEntries]->startID = leftNum;
  701.         inputFileEntries[numInputFileEntries]->endID = rightNum;
  702.         inputFileEntries[numInputFileEntries]->skip = skipNum;
  703.         inputFileEntries[numInputFileEntries]->numFiles = (rightNum-leftNum+1)/skipNum;
  704.         strcpy(inputFileEntries[numInputFileEntries]->left, left);
  705.         strcpy(inputFileEntries[numInputFileEntries]->right, right);
  706.         if ( padding ) {
  707.         inputFileEntries[numInputFileEntries]->numPadding = numPadding;
  708.         } else {
  709.         inputFileEntries[numInputFileEntries]->numPadding = -1;
  710.         }
  711.     } else {
  712.         strcpy(inputFileEntries[numInputFileEntries]->left, input);
  713.         inputFileEntries[numInputFileEntries]->glob = FALSE;
  714.         inputFileEntries[numInputFileEntries]->numFiles = 1;
  715.     }
  716.  
  717.     numInputFiles += inputFileEntries[numInputFileEntries]->numFiles;
  718.     numInputFileEntries++;
  719.     }
  720. }
  721.  
  722.  
  723. /*===========================================================================*
  724.  *
  725.  * SkipSpacesTabs
  726.  *
  727.  *    skip all spaces and tabs
  728.  *
  729.  * RETURNS:    point to next character not a space or tab
  730.  *
  731.  * SIDE EFFECTS:    none
  732.  *
  733.  *===========================================================================*/
  734. static char *
  735. SkipSpacesTabs(start)
  736.     char *start;
  737. {
  738.     while ( (*start == ' ') || (*start == '\t') ) {
  739.     start++;
  740.     }
  741.  
  742.     return start;
  743. }
  744.  
  745.  
  746.