"Fossies" - the Fresh Open Source Software Archive

Member "cpost.c" (9 May 1995, 31573 Bytes) of package /linux/misc/old/cpost.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "cpost.c" see the Fossies "Dox" file reference documentation.

    1 /*------------------------------------------------------------------
    2  * cPost.c  : c language formatter
    3  *------------------------------------------------------------------
    4  * 10-10-91 originally by Patrick J. Mueller
    5  * 12-03-92 converted from cBook to cPost
    6  *------------------------------------------------------------------*/
    7 
    8 #define PROGRAM_VERS  "1.4"
    9 #define PROGRAM_NAME  "cPost"
   10 #define PROGRAM_YEAR  "1994"
   11 #define PROGRAM_AUTH  "Patrick J. Mueller"
   12 #define PROGRAM_ADDR  "(pmuellr@vnet.ibm.com)"
   13 #define PROGRAM_ENVV  "CPOST"
   14 
   15 #include <stdio.h>
   16 #include <stdlib.h>
   17 #include <string.h>
   18 #include <stdarg.h>
   19 #include <signal.h>
   20 #include <time.h>
   21 
   22 #include "parsearg.h"
   23 
   24 #include "ctok.h"
   25 #define DEFINE_GLOBALS
   26 #include "cpost.h"
   27 #include "tokfile.h"
   28 
   29 #include "cposthdr.h"
   30 
   31 /*---------------------------------------------------------------
   32  * global variables
   33  *---------------------------------------------------------------*/
   34 int  AllDone = 0;
   35 
   36 static char *ReservedTokens[] =
   37    {
   38    /*---------------------------------------------------------------
   39     * data types
   40     *---------------------------------------------------------------*/
   41    "auto", "char", "const", "double", "enum", "extern", "float", "int",
   42    "long", "register", "short", "signed", "static", "struct", "union",
   43    "unsigned", "void", "volatile",
   44 
   45    /*---------------------------------------------------------------
   46     * other keywords
   47     *---------------------------------------------------------------*/
   48    "break", "case", "continue", "default", "do", "else", "for", "goto",
   49    "if", "return", "sizeof", "switch", "typedef", "while",
   50 
   51    /*---------------------------------------------------------------
   52     * saa c extensions
   53     *---------------------------------------------------------------*/
   54    "_Packed","_System","_Optlink", "_Far16", "_Cdecl", "_Pascal"
   55    };
   56 
   57 /*------------------------------------------------------------------
   58  * c++ reserved words
   59  *------------------------------------------------------------------*/
   60 static char *CppReservedTokens[] =
   61    {
   62    "catch", "class", "delete", "friend", "inline", "new", "operator",
   63    "private", "protected", "public", "template", "this", "throw", "try",
   64    "virtual"
   65    };
   66 
   67 
   68 /*------------------------------------------------------------------
   69  * generate an error message and exit
   70  *------------------------------------------------------------------*/
   71 void cPostError(
   72    int   exitCode,
   73    char *format,
   74    ...
   75    )
   76    {
   77    va_list vlist;
   78 
   79    fprintf(stderr,"%s : ",PROGRAM_NAME);
   80 
   81    va_start(vlist,format);
   82    vfprintf(stderr,format,vlist);
   83    va_end(vlist);
   84 
   85    fprintf(stderr,"\n");
   86 
   87    if (exitCode)
   88       exit(exitCode);
   89    }
   90 
   91 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
   92 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
   93 
   94 /*------------------------------------------------------------------
   95  * print some help, assuming me is argv[0]
   96  *------------------------------------------------------------------*/
   97 static void Usage(void)
   98    {
   99    fprintf(stderr,"%s %s by %s %s\n",PROGRAM_NAME,PROGRAM_VERS,PROGRAM_AUTH,PROGRAM_ADDR);
  100    fprintf(stderr,"\n");
  101    fprintf(stderr,"usage:\n");
  102    fprintf(stderr,"   %s <options> <filespec> <filespec> ...\n",PROGRAM_NAME);
  103    fprintf(stderr,"is used to produce a listing of C language files in PostScript\n");
  104    fprintf(stderr,"format.  The PostScript output is written to stdout.\n\n");
  105    fprintf(stderr,"where:\n");
  106    fprintf(stderr,"   <filespec> is a filespec matching C language files.\n\n");
  107    fprintf(stderr,"Valid options are:\n");
  108    fprintf(stderr,"   -b[+|-]             - enable/disable bracketing around braces\n");
  109    fprintf(stderr,"   -cext1,ext2,...     - treat files with extention ext1 and ext2 as C files\n");
  110    fprintf(stderr,"   -d[+|-]             - enable/disable duplex\n");
  111    fprintf(stderr,"   -hext1,ext2,...     - treat files with extention ext1 and ext2 as H files\n");
  112    fprintf(stderr,"   -ifile1;file2;...   - imbed files into output\n");
  113    fprintf(stderr,"   -kk1,k2,...         - treat k1, k2 as reserved (key=c++ adds c++ keywords)\n");
  114    fprintf(stderr,"   -n#                 - separate line numbers from lines with # spaces\n");
  115    fprintf(stderr,"   -n0                 - do not generate line numbers\n");
  116    fprintf(stderr,"   -ofile              - output written to file (instead of stdout)\n");
  117    fprintf(stderr,"   -p[+|-]             - enable/disable page break at functions\n");
  118    fprintf(stderr,"   -rfile1;file2,...   - replace default PS procs with contents of files\n");
  119    fprintf(stderr,"   -snt or -stn        - sort files by name/type or type/name\n");
  120    fprintf(stderr,"   -t#                 - expand tabs to # columns\n");
  121    fprintf(stderr,"   -wf1,f2;f3,f4       - prepend files f1, f2 to output, append files f3, f4\n");
  122    fprintf(stderr,"   -xx,y               - coordinates for page adjustment\n");
  123    fprintf(stderr,"   -ypath              - path to use for temporary files\n");
  124    fprintf(stderr,"   -?                  - display this help\n\n");
  125    fprintf(stderr,"Default options are:\n");
  126    fprintf(stderr,"   -b+ -d- -cc -hh -n2 -p+ -stn -t4 -x0,0\n");
  127    fprintf(stderr,"Options may also be set in the environment variable %s.\n",PROGRAM_ENVV);
  128 
  129    exit(1);
  130    }
  131 
  132 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  133 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  134 
  135 /*------------------------------------------------------------------
  136  * add default key words to reserved hash
  137  *------------------------------------------------------------------*/
  138 void InitializeReservedHash(
  139    Info *info,
  140    char *keyList
  141    )
  142    {
  143    int   i;
  144    char *part;
  145 
  146    /*---------------------------------------------------------------
  147     * create hash table
  148     *---------------------------------------------------------------*/
  149    info->reservedHash = HashCreate(sizeof(char *),
  150                                   30,
  151                                   (HashFunc *)IdentHash,
  152                                   (ListCompareFunc *)IdentCompare,
  153                                   cPostNoMem);
  154 
  155    if (!info->reservedHash)
  156       cPostError(1,"error creating reserved word hash table");
  157 
  158    for (i=0; i<sizeof(ReservedTokens)/sizeof(char *); i++)
  159       if (!HashAdd(info->reservedHash,&(ReservedTokens[i])))
  160          cPostError(1,"error adding reserved word '%s' to hash table",
  161                     ReservedTokens[i]);
  162 
  163    /*---------------------------------------------------------------
  164     * loop through the comma separated keys ...
  165     *---------------------------------------------------------------*/
  166    part = strtok(keyList,",");
  167    while (part)
  168       {
  169       /*------------------------------------------------------------
  170        * special c++ token
  171        *------------------------------------------------------------*/
  172       if (!Stricmp("c++",part))
  173          {
  174          for (i=0; i<sizeof(CppReservedTokens)/sizeof(char *); i++)
  175             if (!HashAdd(info->reservedHash,&(CppReservedTokens[i])))
  176                cPostError(1,"error adding reserved word '%s' to hash table",
  177                           CppReservedTokens[i]);
  178 
  179          }
  180 
  181       /*------------------------------------------------------------
  182        * file name
  183        *------------------------------------------------------------*/
  184       else if (('@' == part[0]) && (1 != strlen(part)))
  185          {
  186          TokFileInfo  tfi;
  187          char        *key;
  188 
  189          part++;
  190 
  191          tfi = TokFileOpen(part);
  192 
  193          if (!tfi)
  194             cPostError(0,"error opening file '%s' for reading",part);
  195 
  196          else
  197             {
  198             while (NULL != (part = TokFileNext(tfi)))
  199                {
  200                key = malloc(1 + strlen(part));
  201                if (!key)
  202                   cPostError(1,"out of memory!!");
  203 
  204                strcpy(key,part);
  205 
  206                if (!HashAdd(info->reservedHash,&key))
  207                   cPostError(0,"error adding reserved word '%s' to hash table; word ignored",
  208                                 key);
  209                }
  210             }
  211          }
  212 
  213       /*------------------------------------------------------------
  214        * plain old token
  215        *------------------------------------------------------------*/
  216       else if (!HashAdd(info->reservedHash,&part))
  217          {
  218          cPostError(0,"error adding reserved word '%s' to hash table; word ignored",part);
  219          }
  220 
  221       part = strtok(NULL,",");
  222       }
  223    }
  224 
  225 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  226 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  227 
  228 /*------------------------------------------------------------------
  229  * clean up file list
  230  *------------------------------------------------------------------*/
  231 static int CleanUpFileList(
  232    File     *file,
  233    Info     *info
  234    )
  235    {
  236    PageEject *pe;
  237 
  238    if (!(info->oDebug & 1) && (file->tempName))
  239       remove(file->tempName);
  240 
  241    /*---------------------------------------------------------------
  242     * free up file fields
  243     *---------------------------------------------------------------*/
  244    free(file->name);
  245    free(file->pathName);
  246 
  247    if (*(file->ext))
  248       free(file->ext);
  249 
  250    if (file->tempName)
  251       free(file->tempName);
  252 
  253    /*---------------------------------------------------------------
  254     * free function lists
  255     *---------------------------------------------------------------*/
  256    ListDestroy(file->funcDefList);
  257    ListDestroy(file->funcProList);
  258 
  259    /*---------------------------------------------------------------
  260     * free page eject list
  261     *---------------------------------------------------------------*/
  262    pe = file->breakList;
  263    while (pe)
  264       {
  265       PageEject *next;
  266 
  267       next = pe->next;
  268       free(pe);
  269       pe   = next;
  270       }
  271 
  272    return 0;
  273    }
  274 
  275 /*------------------------------------------------------------------
  276  * clean up function list
  277  *------------------------------------------------------------------*/
  278 static int CleanUpFuncList(
  279    Function *func,
  280    Info     *info
  281    )
  282    {
  283    ListDestroy(func->callsList);
  284    ListDestroy(func->calledByList);
  285 
  286    free(func->name);
  287 
  288    return 0;
  289    }
  290 
  291 /*------------------------------------------------------------------
  292  * atexit processing
  293  *------------------------------------------------------------------*/
  294 static void RunAtExit(void)
  295    {
  296 
  297    if (!AllDone)
  298       fprintf(stderr,"%s : Program terminated.\n",PROGRAM_NAME);
  299 
  300    /*---------------------------------------------------------------
  301     * erase any temporary files we might have open
  302     *---------------------------------------------------------------*/
  303    if (!AllDone)
  304       fprintf(stderr,"%s : Cleaning up temporary files.\n",PROGRAM_NAME);
  305 
  306    ListIterate(info.fileList,(ListIterateFunc *)CleanUpFileList,&info);
  307 
  308    /*---------------------------------------------------------------
  309     * destroy file list
  310     *---------------------------------------------------------------*/
  311    ListDestroy(info.fileList);
  312 
  313    /*---------------------------------------------------------------
  314     * destroy hash tables
  315     *---------------------------------------------------------------*/
  316    HashDestroy(info.identHash);
  317    HashDestroy(info.reservedHash);
  318 
  319    /*---------------------------------------------------------------
  320     * destroy function list
  321     *---------------------------------------------------------------*/
  322    ListIterate(info.funcTree,(ListIterateFunc *)CleanUpFuncList,&info);
  323    ListDestroy(info.funcTree);
  324 
  325    /*---------------------------------------------------------------
  326     * dump memory (if debug enabled
  327     *---------------------------------------------------------------*/
  328 #if defined(__DEBUG_ALLOC__)
  329    _dump_allocated(0);
  330 #endif
  331    }
  332 
  333 /*------------------------------------------------------------------
  334  * signal handler for program interruption
  335  *------------------------------------------------------------------*/
  336 #if defined(OPSYS_LINUX)
  337 void SigHandler(int sig)
  338 #else 
  339 void SignalHandler(int sig)
  340 #endif
  341    {
  342    exit(1);
  343    }
  344 
  345 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  346 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  347 
  348 /*------------------------------------------------------------------
  349  * print function name symbol defintions
  350  *------------------------------------------------------------------*/
  351 static int PrintFunctionDefinition(
  352    Function *func,
  353    Info     *info
  354    )
  355    {
  356    fprintf(info->oFile,
  357            ".nameit symbol=fn%4.4d gmltype=hp%c size='+%d' text='%s'\n",
  358            func->id, '2', 3, func->name);
  359 
  360    return 0;
  361    }
  362 
  363 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  364 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  365 
  366 /*------------------------------------------------------------------
  367  * compute calls and called bys, replace if > than max
  368  *------------------------------------------------------------------*/
  369 static int CountFunctionRefs(
  370    Function *func,
  371    Info     *info
  372    )
  373    {
  374    int count;
  375 
  376    count  = ListCount(func->callsList);
  377    count += ListCount(func->calledByList);
  378 
  379    if (count > info->count1)
  380       info->count1 = count;
  381 
  382    return 0;
  383    }
  384 
  385 /*------------------------------------------------------------------
  386  * get maximum number of calls and called bys for all the functions
  387  * so figure out which table to use
  388  *------------------------------------------------------------------*/
  389 int GetMaxFuncTableEntries(
  390    Info      *info
  391    )
  392    {
  393 
  394    info->count1 = 0;
  395 
  396    ListIterate(info->funcTree,
  397                (ListIterateFunc *)CountFunctionRefs,
  398                info);
  399 
  400    return info->count1;
  401    }
  402 
  403 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  404 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  405 
  406 /*------------------------------------------------------------------
  407  * parse command line for options
  408  *------------------------------------------------------------------*/
  409 static void GetOptions(
  410    int   *argc,
  411    char  *argv[],
  412    Info  *info
  413    )
  414    {
  415    int            oHelp;
  416    char          *oBrack;
  417    char          *oTabs;
  418    char          *oCtype;
  419    char          *oHtype;
  420 #if defined(OPSYS_LINUX)
  421    char          oSort[10];
  422 #else
  423    char          *oSort;
  424 #endif
  425    char          *oFile;
  426    char          *oSpace;
  427    char          *oKeys;
  428    char          *oBreak;
  429    char          *oTemp;
  430    char          *oImbed;
  431    char          *oDuplex;
  432 #if defined(OPSYS_LINUX)
  433    char          oXlate[80];
  434 #else
  435    char          *oXlate;
  436 #endif
  437    char          *numLeft;
  438    char          *s1;
  439    char          *s2;
  440    char          *oWrap;
  441    char          *oRepHdr;
  442 
  443    /*---------------------------------------------------------------
  444     * parse arguments
  445     *---------------------------------------------------------------*/
  446    parsearg(argc,argv,0,PROGRAM_ENVV,"-",
  447             "? b@ c@ d@ h@ k@ i@ n@ o@ p@ r@ s@ t@ w@ x@ y@",
  448             &oHelp,&oBrack,&oCtype,&oDuplex,&oHtype,&oKeys,&oImbed,
  449             &oSpace,&oFile,&oBreak,&oRepHdr,&oSort,&oTabs,&oWrap,
  450             &oXlate,&oTemp);
  451 
  452    /*---------------------------------------------------------------
  453     * check parms
  454     *---------------------------------------------------------------*/
  455    if (oHelp || (*argc < 2))
  456       Usage();
  457 
  458    if ('?' == *argv[1])
  459       Usage();
  460 
  461    /*---------------------------------------------------------------
  462     * apply option defaults
  463     *---------------------------------------------------------------*/
  464    if ((NULL == oBrack ) || ('\0' == *oBrack ))  oBrack  = "+";
  465    if ((NULL == oCtype ) || ('\0' == *oCtype ))  oCtype  = "c";
  466    if ((NULL == oDuplex) || ('\0' == *oDuplex))  oDuplex = "-";
  467    if ((NULL == oHtype ) || ('\0' == *oHtype ))  oHtype  = "h";
  468    if ((NULL == oKeys  ) || ('\0' == *oKeys  ))  oKeys   = "";
  469    if ((NULL == oImbed ) || ('\0' == *oImbed ))  oImbed  = "";
  470    if ((NULL == oSpace ) || ('\0' == *oSpace ))  oSpace  = "2";
  471    if ((NULL == oFile  ) || ('\0' == *oFile  ))  oFile   = NULL;
  472    if ((NULL == oBreak ) || ('\0' == *oBreak ))  oBreak  = "+";
  473    if ((NULL == oRepHdr) || ('\0' == *oRepHdr))  oRepHdr = "";
  474 #if defined(OPSYS_LINUX)
  475    if ((NULL == oSort  ) || ('\0' == *oSort  ))  strcpy(oSort,"tn");
  476 #else
  477    if ((NULL == oSort  ) || ('\0' == *oSort  ))  oSort   = "tn";
  478 #endif
  479    if ((NULL == oTabs  ) || ('\0' == *oTabs  ))  oTabs   = "4";
  480    if ((NULL == oWrap  ) || ('\0' == *oWrap  ))  oWrap   = "";
  481 #if defined(OPSYS_LINUX)
  482    if ((NULL == oXlate ) || ('\0' == *oXlate ))  strcpy(oXlate, "0,0");
  483 #else
  484    if ((NULL == oXlate ) || ('\0' == *oXlate ))  oXlate  = "0,0";
  485 #endif
  486    if ((NULL == oTemp  ) || ('\0' == *oTemp  ))  oTemp   = "";
  487 
  488    /*---------------------------------------------------------------
  489     * bracketing option
  490     *---------------------------------------------------------------*/
  491    info->oBrack = (int) strtol(oBrack,NULL,10);
  492    if (0 == info->oBrack)
  493       {
  494       if ((1 != strlen(oBrack)) || (NULL == strchr("-+",*oBrack)))
  495          cPostError(1,"invalid value on -b option");
  496 
  497       if ('+' == *oBrack)
  498          info->oBrack = 1000;
  499       else
  500          info->oBrack = 0;
  501       }
  502 
  503    /*---------------------------------------------------------------
  504     * extensions for C files
  505     *---------------------------------------------------------------*/
  506    info->oCtype = oCtype;
  507 
  508    /*---------------------------------------------------------------
  509     * duplex
  510     *---------------------------------------------------------------*/
  511    if ((1 != strlen(oDuplex)) || (NULL == strchr("-+",*oDuplex)))
  512       cPostError(1,"invalid value on -d option");
  513 
  514    info->oDuplex  = ('+' == *oDuplex);
  515 
  516    /*---------------------------------------------------------------
  517     * extensions for H files
  518     *---------------------------------------------------------------*/
  519    info->oHtype = oHtype;
  520 
  521    /*---------------------------------------------------------------
  522     * reserved words
  523     *---------------------------------------------------------------*/
  524    InitializeReservedHash(info,oKeys);
  525 
  526    /*---------------------------------------------------------------
  527     * imbed option
  528     *---------------------------------------------------------------*/
  529    info->oImbed  = oImbed;
  530 
  531    /*---------------------------------------------------------------
  532     * space option
  533     *---------------------------------------------------------------*/
  534    info->oSpace = (int) strtol(oSpace,&numLeft,10);
  535    if (*numLeft || (info->oSpace < 0))
  536       cPostError(1,"invalid value on -n option");
  537 
  538    /*---------------------------------------------------------------
  539     * output file option
  540     *---------------------------------------------------------------*/
  541    if (NULL == oFile)
  542       info->oFile = stdout;
  543    else
  544       {
  545       info->oFile = fopen(oFile,"w");
  546       if (NULL == info->oFile)
  547          cPostError(1,"error opening output file %s for writing",oFile);
  548       }
  549 
  550    /*---------------------------------------------------------------
  551     * page break option
  552     *---------------------------------------------------------------*/
  553    if ((1 != strlen(oBreak)) || (NULL == strchr("-+",*oBreak)))
  554       cPostError(1,"invalid value on -p option");
  555 
  556    info->oBreak  = ('+' == *oBreak);
  557 
  558    /*---------------------------------------------------------------
  559     * replace PS header
  560     *---------------------------------------------------------------*/
  561    info->oRepHdr = oRepHdr;
  562 
  563    /*---------------------------------------------------------------
  564     * sort option
  565     *---------------------------------------------------------------*/
  566    if ((0 != Stricmp("nt",oSort)) && (0 != Stricmp("tn",oSort)))
  567       cPostError(1,"invalid value on -s option");
  568 
  569    info->oSort  = Strupr(oSort);
  570 
  571 
  572    /*---------------------------------------------------------------
  573     * tabs option
  574     *---------------------------------------------------------------*/
  575    info->oTabs = (int) strtol(oTabs,NULL,10);
  576    if (0 == info->oTabs)
  577       cPostError(1,"invalid value on -t option");
  578 
  579    /*---------------------------------------------------------------
  580     * wrap PS around output
  581     *---------------------------------------------------------------*/
  582    info->oWrapB = strtok(oWrap,";");
  583    info->oWrapA = strtok(NULL,"");
  584 
  585    /*---------------------------------------------------------------
  586     * translate option
  587     *---------------------------------------------------------------*/
  588    s1 = strtok(oXlate,",");
  589    s2 = strtok(NULL,"");
  590 
  591    if (!s1 || !s2)
  592       cPostError(1,"invalid value on -x option");
  593 
  594    info->oXlateX = (int) strtol(s1,NULL,10);
  595    info->oXlateY = (int) strtol(s2,NULL,10);
  596 
  597 
  598    /*---------------------------------------------------------------
  599     * temp path
  600     *---------------------------------------------------------------*/
  601    if (!strlen(oTemp))
  602       info->oTemp = "";
  603 
  604    else
  605       {
  606       char c;
  607 
  608       c = oTemp[strlen(oTemp) - 1];
  609       if (('\\' == c) || ('/' == c))
  610          info->oTemp = oTemp;
  611       else
  612          {
  613          info->oTemp = malloc(2+strlen(oTemp));
  614          strcpy(info->oTemp,oTemp);
  615          strcat(info->oTemp,"/");
  616          }
  617       }
  618 
  619    }
  620 
  621 /*------------------------------------------------------------------
  622  * copy one file stream to another
  623  *------------------------------------------------------------------*/
  624 void copyFile(
  625    FILE *fileFrom,
  626    FILE *fileTo
  627    )
  628    {
  629 #define BUFFER_SIZE 8192
  630    char *buffer;
  631 
  632    /*---------------------------------------------------------------
  633     * allocate buffer
  634     *---------------------------------------------------------------*/
  635    buffer = malloc(BUFFER_SIZE);
  636    if (!buffer)
  637       cPostError(1,"out of memory!!");
  638 
  639    /*---------------------------------------------------------------
  640     * copy file buffer at a time
  641     *---------------------------------------------------------------*/
  642    while (!feof(fileFrom))
  643       {
  644       int count;
  645       count = fread(buffer,1,BUFFER_SIZE,fileFrom);
  646       fwrite(buffer,1,count,fileTo);
  647       }
  648 
  649    /*---------------------------------------------------------------
  650     * free the buffer
  651     *---------------------------------------------------------------*/
  652    free(buffer);
  653    }
  654 
  655 /*------------------------------------------------------------------
  656  * process the imbed file option
  657  *------------------------------------------------------------------*/
  658 void processImbedFile(
  659    char *imbedFileName
  660    )
  661    {
  662    FILE *file;
  663 
  664    /*---------------------------------------------------------------
  665     * while we have imbedFileNames
  666     *---------------------------------------------------------------*/
  667    imbedFileName = strtok(imbedFileName,";,");
  668    while (imbedFileName)
  669       {
  670       /*------------------------------------------------------------
  671        * open the imbed file
  672        *------------------------------------------------------------*/
  673       file = fopen(imbedFileName,"r");
  674 
  675       /*------------------------------------------------------------
  676        * print error if not found, or copy it in if found
  677        *------------------------------------------------------------*/
  678       if (!file)
  679          cPostError(0,"unable to open file '%s' for reading",imbedFileName);
  680       else
  681          {
  682          copyFile(file,info.oFile);
  683          fclose(file);
  684          }
  685 
  686       /*------------------------------------------------------------
  687        * get next imbed file name
  688        *------------------------------------------------------------*/
  689       imbedFileName = strtok(NULL,";,");
  690       }
  691    }
  692 
  693 /*-/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\-*/
  694 /*-\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/-*/
  695 
  696 /*------------------------------------------------------------------
  697  * main program
  698  *------------------------------------------------------------------*/
  699 int main(
  700    int   argc,
  701    char *argv[]
  702    )
  703    {
  704    int        i;
  705    char       dateStr[30];
  706    struct tm *tm;
  707    time_t     t;
  708    char      *origParms;
  709 
  710    /*---------------------------------------------------------------
  711     * check for help
  712     *---------------------------------------------------------------*/
  713    if ((1 == argc) || ('?' == *(argv[1])))
  714       Usage();
  715 
  716    /*---------------------------------------------------------------
  717     * get original parms
  718     *---------------------------------------------------------------*/
  719    origParms  = malloc(1);
  720    *origParms = 0;
  721 
  722    for (i=0; i<argc; i++)
  723       {
  724       origParms = realloc(origParms,2 + strlen(origParms) + strlen(argv[i]));
  725       strcat(origParms," ");
  726       strcat(origParms,argv[i]);
  727       }
  728    /*---------------------------------------------------------------
  729     * zero out info
  730     *---------------------------------------------------------------*/
  731    memset(&info,0,sizeof(info));
  732 
  733    /*---------------------------------------------------------------
  734     * get options
  735     *---------------------------------------------------------------*/
  736    GetOptions(&argc,argv,&info);
  737    /*---------------------------------------------------------------
  738     * buffer output
  739     *---------------------------------------------------------------*/
  740 /* setvbuf(info.oFile,NULL,_IOFBF,32000); */
  741 
  742    /*---------------------------------------------------------------
  743     * put filenames in a list
  744     *---------------------------------------------------------------*/
  745    info.fileList = ListCreate(sizeof(File),
  746                               (ListCompareFunc *)FileNameCompare,
  747                               cPostNoMem);
  748    if (!info.fileList)
  749       cPostError(1,"error creating list of files");
  750 
  751    for (i=1; i<argc; i++)
  752       FileSpecAdd(&info,info.fileList,argv[i]);
  753 
  754    /*---------------------------------------------------------------
  755     * check for no files to process
  756     *---------------------------------------------------------------*/
  757    if (!ListCount(info.fileList))
  758       cPostError(1,"no files to process");
  759 
  760    /*---------------------------------------------------------------
  761     * intialize rest of info structure
  762     *---------------------------------------------------------------*/
  763    info.funcTree  = ListCreate(sizeof(Function),
  764                                (ListCompareFunc *)FunctionNameCompare,
  765                                cPostNoMem);
  766    if (!info.fileList)
  767       cPostError(1,"error creating list of functions");
  768 
  769    info.identHash   = HashCreate(sizeof(char *),
  770                                  1000,
  771                                  (HashFunc *)IdentHash,
  772                                  (ListCompareFunc *)IdentCompare,
  773                                  cPostNoMem);
  774 
  775 
  776    if (!info.identHash)
  777       cPostError(1,"error creating global hash table");
  778 
  779    /*---------------------------------------------------------------
  780     * setup error termination processing
  781     *---------------------------------------------------------------*/
  782    atexit(RunAtExit);
  783 #if defined(OPSYS_LINUX)
  784    signal(SIGINT,  SigHandler);
  785    signal(SIGTERM, SigHandler);
  786 #else    
  787    signal(SIGINT,  SignalHandler);
  788    signal(SIGTERM, SignalHandler);
  789 #endif   
  790 
  791 #if defined(OPSYS_OS2) || defined(OPSYS_OS2V2)
  792    signal(SIGBREAK,SignalHandler);
  793 #endif
  794 
  795    /*---------------------------------------------------------------
  796     * print header
  797     *---------------------------------------------------------------*/
  798    fprintf(info.oFile,"%%! PostScript file generated by %s %s\n\n",
  799            PROGRAM_NAME,PROGRAM_VERS);
  800 
  801 /*------------------------------------------------------------------
  802  * a macro to write a line to the output file
  803  *------------------------------------------------------------------*/
  804 #define p(x) fprintf(info.oFile,"%s\n",x);
  805 
  806 
  807    /*---------------------------------------------------------------
  808     * write command line and environment variable setting
  809     *---------------------------------------------------------------*/
  810 #if defined(ECHO_COMMAND_LINE)
  811       {
  812       p("%%-----------------------------------------------------------------")
  813 
  814       fprintf(info.oFile,"%%%% this file created with the command:\n");
  815       fprintf(info.oFile,"%%%%   %s\n",origParms);
  816       fprintf(info.oFile,"%%%% the CPOST environment variable ");
  817       if (!getenv(PROGRAM_ENVV))
  818          fprintf(info.oFile,"is not set.\n");
  819       else
  820          {
  821          fprintf(info.oFile,"is set to:\n");
  822          fprintf(info.oFile,"%%%%   %s\n",getenv(PROGRAM_ENVV));
  823          }
  824 
  825       p("%%-----------------------------------------------------------------")
  826       p("");
  827       }
  828 #endif
  829 
  830    /*---------------------------------------------------------------
  831     * write wrapper prefix
  832     *---------------------------------------------------------------*/
  833    if (info.oWrapB && strlen(info.oWrapB))
  834       processImbedFile(info.oWrapB);
  835 
  836    /*---------------------------------------------------------------
  837     * get the time
  838     *---------------------------------------------------------------*/
  839    t  = time(NULL);
  840    tm = localtime(&t);
  841    strftime(dateStr,sizeof(dateStr)-1,"%m/%d/%y   %H:%M:%S",tm);
  842 
  843    p("%%-----------------------------------------------------------------")
  844    p("%% runtime options and values")
  845    p("%%-----------------------------------------------------------------")
  846    p("")
  847    fprintf(info.oFile,"/printDate (%s) def\n",dateStr);
  848    fprintf(info.oFile,"/oSpace %d def\n",info.oSpace);
  849    fprintf(info.oFile,"/oXlate { %d %d translate } def\n",info.oXlateX,info.oXlateY);
  850    fprintf(info.oFile,"/oDuplex 1 %d eq def\n",info.oDuplex);
  851    fprintf(info.oFile,"/oNumber 0 %d ne def\n",info.oSpace);
  852    p("")
  853 
  854    /*---------------------------------------------------------------
  855     * write replaced header ...
  856     *---------------------------------------------------------------*/
  857    if (info.oRepHdr && strlen(info.oRepHdr))
  858       {
  859       processImbedFile(info.oImbed);
  860       p("");
  861       processImbedFile(info.oRepHdr);
  862       p("");
  863       }
  864 
  865    /*---------------------------------------------------------------
  866     * or default stuff
  867     *---------------------------------------------------------------*/
  868    else
  869       {
  870       for (i=0; i< sizeof(Header_1)/sizeof(char *); i++)
  871          p(Header_1[i]);
  872 
  873       p("");
  874       processImbedFile(info.oImbed);
  875       p("");
  876 
  877       for (i=0; i< sizeof(Header_2)/sizeof(char *); i++)
  878          p(Header_2[i]);
  879 
  880       p("");
  881       }
  882 
  883    /*---------------------------------------------------------------
  884     * read the files. make copies
  885     *---------------------------------------------------------------*/
  886    fprintf(stderr,"Pass 1\n");
  887    ListIterate(info.fileList,(ListIterateFunc *)Pass1,&info);
  888 
  889    /*---------------------------------------------------------------
  890     * read the copies. write the output file
  891     *---------------------------------------------------------------*/
  892    fprintf(stderr,"Pass 2\n");
  893    ListIterate(info.fileList,(ListIterateFunc *)Pass2,&info);
  894 
  895    /*---------------------------------------------------------------*
  896     * print trailing line feed
  897     *---------------------------------------------------------------*/
  898    fprintf(info.oFile,"\n");
  899 
  900    /*---------------------------------------------------------------
  901     * write wrapper suffix
  902     *---------------------------------------------------------------*/
  903    if (info.oWrapA && strlen(info.oWrapA))
  904       processImbedFile(info.oWrapA);
  905 
  906    /*---------------------------------------------------------------
  907     * close file (another line feed for luck!)
  908     *---------------------------------------------------------------*/
  909    fprintf(info.oFile,"\n");
  910    fclose(info.oFile);
  911 
  912    AllDone = 1;
  913    return 0;
  914    }