windows-nt/Source/XPSP1/NT/multimedia/media/tools/docfmt/process.c
2020-09-26 16:20:57 +08:00

910 lines
17 KiB
C

/*
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);
}