|
|
/*
process.c - Process the log files.
Copyright (c) 1989, Microsoft. All Rights Reserved.
10-07-89 Matt Saettler 10-10-89 Update for log,aBlock,EXTFile,files structures */
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <assert.h>
#include <search.h>
#include "types.h"
#include "docfmt.h"
#include "ventura.h"
#include "rtf.h"
#include "process.h"
#include "misc.h"
#include "errstr.h"
void dumptable(int numfiles, files * ptable);
/*
* @doc INTERNAL * * @func void | processLog | This function processes all the Log files. * * @xref readLog, initLogs, processLogs, doneLogs */ void processLog(void) { logentry *cur_log; FILE *fpout;
if(!head_log) return;
cur_log=head_log; while(cur_log) { readLog(cur_log); cur_log=cur_log->next; }
fpout=fopen(outputFile,"w"); if(!fpout) return;
cur_log=head_log;
initLogs(fpout, &head_log);
while(cur_log) { if(verbose>1) fprintf(errfp," Processing Log file: %s\n",cur_log->pchlogname); processLogs(fpout, cur_log); cur_log=cur_log->next; } doneLogs(fpout, head_log);
fclose(fpout); if(verbose) fprintf(errfp,"%s is complete.\n",outputFile);
}
/*
* * @doc INTERNAL * * @func void | processLogs | This functions processes all the files within * the specified log file structure. * * @parm FILE * | fpout | This is the output file to process the files * to. * * @parm logentry * | cur_log | This is the current log file to process. * * @xref initFiles, processFiles, doneFiles */ void processLogs(FILE *fpout, logentry * cur_log) { initFiles(fpout, cur_log);
if(cur_log->outheadMFile) processFiles(fpout, cur_log->outheadMFile); processFiles(fpout, cur_log->outheadFile);
if(cur_log->outheadSUFile) processFiles(fpout, cur_log->outheadSUFile); doneFiles(fpout, cur_log->outheadFile);
}
/*
* @doc INTERNAL * * @func void | cleanLogs | This function removes the log files structure * from memory and removes any files if the fCleanFiles flag is TRUE. * * @parm logentry * | cur_log | This specifies the log file structure to remove. * * @xref cleanFile, cleanLogs */ void cleanLogs(logentry *cur_log) { if(!cur_log) return;
cleanFile(cur_log->outheadFile); cleanFile(cur_log->outheadMFile); cleanFile(cur_log->outheadSUFile); // structs go here...
cleanLogs(cur_log->next); /* recursive !! */
if(fCleanFiles) unlink(cur_log->pchlogname);
my_free(cur_log->pchlogname);
my_free(cur_log); return; }
/*
* @doc INTERNAL PROCESS * * @func void | readLog | This function reads the logfile and creates * the logfile structure. * * @parm logentry * | cur_log | This specifies the logfile structure to * fill. The filename has been filled in. * * @xref parseFile */ void readLog(logentry *cur_log) { FILE * tFile; files curFile; files curMFile; files curSUFile; files curTFile;
tFile = fopen(cur_log->pchlogname, "r"); if(tFile == NULL) { error(ERROR9, "xxx", cur_log->pchlogname ); Usage(); return; }
cur_log->outheadFile=NULL; cur_log->outheadMFile=NULL; cur_log->outheadSUFile=NULL; fscanf(tFile, "%d\n",&cur_log->outputType);
curTFile=(files)clear_alloc(sizeof (struct strfile) ); curMFile=NULL; curSUFile=NULL; curFile=NULL; curFile=cur_log->outheadFile; while(parseFile(tFile, curTFile)) { if(curTFile->blockType==MESSAGE && fSortMessage) { if(curMFile==NULL) { cur_log->outheadMFile=curTFile; } else { curMFile->next=curTFile; } curMFile=curTFile; } else if( (curTFile->blockType==STRUCTBLOCK) || (curTFile->blockType==STRUCTBLOCK)) { if(curSUFile==NULL) { cur_log->outheadSUFile=curTFile; } else { curSUFile->next=curTFile; } curSUFile=curTFile; } else { if(curFile==NULL) { cur_log->outheadFile=curTFile; } else { curFile->next=curTFile; } curFile=curTFile; } curTFile=(files)clear_alloc(sizeof (struct strfile) ); } my_free(curTFile); curFile->next=NULL;
#ifdef MMWIN // This causes GP fault
curMFile->next=NULL; // just to be sure.
curSUFile->next=NULL; // just to be sure.
#endif
fclose( tFile );
}
/*
* @doc INTERNAL PROCESS * * @func int | initLogs | This function is called at the beginning of * processing the list of logs. * * @parm FILE * | phoutfile | This functions specifies the output file handle. * * @parm logentry **| phead_log | This specifies the pointer to the list of * log files to be processed. The head value may be modified due to sorting, * etc., by the output LogInit routine <f VenLogInit> or <f RTFLogInit>. * * @rdesc The return value is TRUE if the operation succeds. * * @xref VenLogInit, RTFLogInit * */ int initLogs(FILE *phoutfile, logentry **phead_log) { switch(head_log->outputType) { case VENTURA: VenLogInit(phoutfile, phead_log); break; case RTFDOC: case RTFHELP: RTFLogInit(phoutfile, phead_log); break;
default: fprintf(stderr, "Unknown Output Type"); break;
} return(TRUE); }
/*
* @doc INTERNAL PROCESS * * @func int |initFiles| This function is called before processing each * log file. * * @parm FILE *|phoutfile| This parmameter specifies the output file. * * @parm logentry * | curlog | This is the log file containing the files * to be processed. * * @rdesc The return value is TRUE if the initialization was successful. * * @comm The files are sorted by function name * * @xref VenFileInit, RTFFileInit * */ int initFiles(FILE *phoutfile, logentry *curlog) { files curFile; int i; files *ptable; int numFiles;
numFiles=0; curFile=curlog->outheadFile; if(!curFile) goto nofiles; while(curFile) { numFiles++; curFile=curFile->next; } /* sort the list */
ptable=(files *)clear_alloc( sizeof (struct s_log) * (numFiles + 1) );
curFile=curlog->outheadFile; for(i=0;i<numFiles; i++) { ptable[i]=curFile; curFile=curFile->next; }
/* dumptable(numFiles, ptable); */
qsort( ptable, numFiles, sizeof (files *), filecmp);
/* dumptable(numFiles, ptable); */
curlog->outheadFile=ptable[0]; curFile=curlog->outheadFile;
for(i=0;i<numFiles; i++) { curFile->next=ptable[i]; curFile=curFile->next; } curFile->next=NULL;
my_free(ptable);
nofiles:
////////////////////////////////////////////////////////////////
// sort messages
numFiles=0; curFile=curlog->outheadMFile; if(!curFile) goto nomessages; while(curFile) { numFiles++; curFile=curFile->next; } /* sort the list */
ptable=(files *)clear_alloc( sizeof (struct s_log) * (numFiles + 1) );
curFile=curlog->outheadMFile; for(i=0;i<numFiles; i++) { ptable[i]=curFile; curFile=curFile->next; }
/* dumptable(numFiles, ptable); */
qsort( ptable, numFiles, sizeof (files *), filecmp);
/* dumptable(numFiles, ptable); */
curlog->outheadMFile=ptable[0]; curFile=curlog->outheadMFile;
for(i=0;i<numFiles; i++) { curFile->next=ptable[i]; curFile=curFile->next; } curFile->next=NULL;
my_free(ptable);
nomessages:
////////////////////////////////////////////////////////////////
// sort structs/unions
numFiles=0; curFile=curlog->outheadSUFile; if(!curFile) goto nosu; while(curFile) { numFiles++; curFile=curFile->next; } /* sort the list */
ptable=(files *)clear_alloc( sizeof (struct s_log) * (numFiles + 1) );
curFile=curlog->outheadSUFile; for(i=0;i<numFiles; i++) { ptable[i]=curFile; curFile=curFile->next; }
/* dumptable(numFiles, ptable); */
qsort( ptable, numFiles, sizeof (files *), filecmp);
/* dumptable(numFiles, ptable); */
curlog->outheadSUFile=ptable[0]; curFile=curlog->outheadSUFile;
for(i=0;i<numFiles; i++) { curFile->next=ptable[i]; curFile=curFile->next; } curFile->next=NULL;
my_free(ptable);
nosu:
//////////////////////////////////////////////////////////////
// Init file/section output
// this is a little out of design because we now have multiple
// files (text and messages and soon structs...
switch(outputType) { case VENTURA: VenFileInit(phoutfile, curlog); break; case RTFDOC: case RTFHELP: RTFFileInit(phoutfile, curlog); break;
default: fprintf(stderr, "Unknown Output Type"); break;
} return(TRUE); }
/*
* @doc INTERNAL PROCESS * * @func void|dumptable| This is a debug function to dump the list of * files. * * @parm int| numfiles | Specifies the nmber of entries in the table. * * @parm files * | ptable | Specifies the table to dump. * * @xref initFiles * */ void dumptable(int numfiles, files * ptable) { int i; for(i=0;i<numfiles;i++) fprintf(stderr, "%s\t\t%s\n",ptable[i]->name,ptable[i]->filename); }
/*
* @doc INTERNAL PROCESS * * @func int | filecmp | This routine is used in the qsort. It does a * case insensitive compare of the names. * * @parm files * | f1 | This is the first file to compare. * * @parm files * | f2 | This is the second file to compare. * * @rdesc The return is the same as <f strcmp>. See <f qsort>. * * @xref qsort, strcmp, initFiles */ int filecmp(files * f1, files * f2) { int order;
order=stricmp((*f1)->name,(*f2)->name);
return(order);
}
/*
* @doc INTERNAL PROCESS * * @func int | processFiles | This routine processes all the files in * a log file structure by calling the appropriate file output routine. * * @parm FILE * | phoutfile | This is the output file handle. * * @parm files |headFile| This is the head of the list of files to process. * * @xref VenFileProcess, RTFFileProcess */ int processFiles(FILE * phoutfile, files headFile) {
files curFile;
curFile=headFile; while(curFile && curFile->name) { if(verbose>1) fprintf(errfp," Copying Block %s\n",curFile->name);
switch(outputType) { case VENTURA: VenFileProcess(phoutfile, curFile); break; case RTFDOC: case RTFHELP: RTFFileProcess(phoutfile, curFile); break;
default: fprintf(stderr, "Unknown Output Type"); break;
} curFile=curFile->next; }
return TRUE; }
/*
* @doc INTERNAL PROCESS * * @func int | parseFile | This routine parses a file structure from a log file. * * @parm FILE * | pfh | The input file handle of the log file. * * @parm files | curFile| The file structure to place the data from the file. * */ int parseFile(FILE * pfh, files curFile) { char achbuf[80];
if(fscanf(pfh,"%d ",&(curFile->blockType)) == EOF) return(FALSE);
if(fscanf(pfh, "%s",achbuf) == EOF) return(FALSE);
curFile->name=cp_alloc(achbuf);
if(fscanf(pfh, " %s\n",achbuf) == EOF) return(FALSE);
curFile->filename=cp_alloc(achbuf);
return(TRUE); }
/*
* @doc INTERNAL PROCESS * * @func void | doneLogs | This function is called after all the logs * in the list have been processed. * * @parm FILE *|phoutfile| Specifies the output file. * * @parm logentry * | headLog | Specifies the head of the list of log structure. * * @xref VenLogDone, RTFLogDone, cleanLogs * * @comm If the fCleanFiles flag is set, then the log files are cleaned. * */ void doneLogs(FILE *phoutfile, logentry *headLog) { switch(outputType) { case VENTURA: VenLogDone(phoutfile, headLog); break; case RTFDOC: case RTFHELP: RTFLogDone(phoutfile, headLog); break;
default: fprintf(stderr, "Unknown Output Type"); break;
}
if(fCleanFiles) cleanLogs(headLog);
return; }
/*
* @doc INTERNAL PROCESS * * @func void | doneFiles | This function is called when all the files * in the current log have been processed. * * @parm FILE *|phoutfile| Specifies the output file. * * @parm files | headFile| Specifies the list of files that have been processed. * * @xref VenFileDone, RTFFileDone */ void doneFiles(FILE *phoutfile, files headFile) { switch(outputType) { case VENTURA: VenFileDone(phoutfile, headFile); break; case RTFDOC: case RTFHELP: RTFFileDone(phoutfile, headFile); break;
default: fprintf(stderr, "Unknown Output Type"); break;
}
return; }
/*
* @doc INTERNAL PROCESS * * @func int | cleanFile | This function removes all the memory and * DOS files associated with the files data structure. * * @parm files | headFile| Specifies the list of files to be cleaned. * */ int cleanFile(files headFile) { files curFile; files tcurFile;
curFile=headFile;
while(curFile && curFile->name) { unlink(curFile->filename); my_free(curFile->filename); my_free(curFile->name);
tcurFile=curFile->next; my_free(curFile);
curFile=tcurFile; }
return TRUE;
}
/*
* @doc INTERNAL PROCESS * * @func void | copyfile | This function appends the specified file name * to the specified output file. * * @parm FILE *|phoutfile| Specifies the output file. * * @parm char *| pchfilename| Specifies the input file. * */ void copyfile(FILE *phoutfile, char *pchfilename) { FILE *fpin; int i; char *pch;
pch=findfile(pchfilename); if(!pch) return; fpin=fopen(pch,"r"); if(!fpin) return;
while((i=fgetc(fpin))!=EOF) fputc(i,phoutfile);
fclose(fpin);
return;
}
/*
* @doc INTERNAL PROCESS * * @func char * | findfile | This function tries to find the specified * file. It searches directories in this order: current, PATH, INIT * and finally INCLUDE. * * @parm char * |pch| Specifies the filename to find. * * @rdesc This function returns a pointer to the complete file/path * of the specified file. Just the file name is returned if it is * found in the current directory. NULL is returned if the file cannot * be found. * */ char * findfile(char * pch) { FILE *fp; static char ach[128]; static char *pchmode="r";
strcpy(ach,pch); fp=fopen(ach, pchmode); if(fp) { fclose(fp); return(ach); }
_searchenv(pch,"PATH",ach); fp=fopen(ach, pchmode); if(fp) { fclose(fp); return(ach); }
_searchenv(pch,"INIT",ach); fp=fopen(ach, pchmode); if(fp) { fclose(fp); return(ach); }
_searchenv(pch,"INCLUDE",ach); fp=fopen(ach, pchmode); if(fp) { fclose(fp); return(ach); }
return(NULL); }
/*
* @doc INTERNAL PROCESS * * @func logentry * | add_logtoprocess | This function adds the specified * log file name to the list of logs to be processed. * * @parm char * | pch| Specifies log file name to bo added. * * @rdesc The return value specifies the logentry that was created * for the specified log file. * * @xref newlog */ logentry * add_logtoprocess(char *pch) { logentry *cur_log; cur_log=newlog(&head_log); cur_log->pchlogname=cp_alloc(pch); return(cur_log);
}
/*
* @doc INTERNAL PROCESS * * @func logentry * | newlog | This function creates a new log entry * in the specified list of logs. * * @parm logentry ** | start_log| Specifies the head of head of the list * of logs. * * @rdesc The return value specifies the logentry that was added. * * @comm The new log structure is added at the head of the list. * */ logentry * newlog(logentry **start_log) { logentry * cur_log; logentry * tmp_log;
cur_log=(logentry *)clear_alloc(sizeof(struct s_log));
if(!*start_log) { *start_log=cur_log; } else { tmp_log=*start_log; while(tmp_log->next) tmp_log=tmp_log->next;
tmp_log->next=cur_log; } return(cur_log);
}
/*
* @doc INTERNAL PROCESS * * @func fileentry * | add_filetoprocess | This function adds an input * file to process to a log structure. * * @parm char * |pch| Specifies the filename to be added. * * @parm logentry *|curlog| Specifies the log structure. * * @rdesc The return value is the new file structure that is created * to hold the file entry in the log structure. * * @xref newfile */ fileentry * add_filetoprocess(char *pch, logentry *curlog) { fileentry *cur_file; cur_file=newfile(&(curlog->inheadFile)); cur_file->filename=cp_alloc(pch); cur_file->logfile=curlog; return(cur_file);
}
/*
* @doc INTERNAL PROCESS * * @func fileentry * | newfile | This function creates a new file entry * in a list of files. It is similar to <f newlog>. * * @parm fileentry **|start_file| Specifies the head of the list of files. * * @rdesc The return value specifies the new file structure that was created * to hold the new file entry. * * @comm This routine inserts at the head of the list. * */ fileentry * newfile(fileentry **start_file) { fileentry * cur_file; fileentry * tmp_file;
cur_file=(fileentry *)clear_alloc(sizeof(struct strfile));
if(!*start_file) { *start_file=cur_file; } else { tmp_file=*start_file; while(tmp_file->next) tmp_file=tmp_file->next;
tmp_file->next=cur_file; } return(cur_file);
}
|