mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1180 lines
24 KiB
1180 lines
24 KiB
/*
|
|
docfmt.c - Take the output from extract program and format it.
|
|
|
|
Copyright (c) 1989, Microsoft. All Rights Reserved.
|
|
|
|
...
|
|
10-06-89 Matt Saettler
|
|
...
|
|
10-15-89 Matt Saettler - Autodoc'ed added functions
|
|
|
|
3-26-91 Ported for use with Win32 (NigelT)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <malloc.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <search.h>
|
|
#include <io.h>
|
|
#include <direct.h>
|
|
#include <ctype.h>
|
|
#ifdef MMWIN
|
|
#include <mmsysver.h>
|
|
#endif
|
|
#include "version.h"
|
|
#include "types.h"
|
|
#include "text.h"
|
|
#include "docfmt.h"
|
|
#include "readext.h"
|
|
#include "ventura.h"
|
|
#include "process.h"
|
|
#include "misc.h"
|
|
#include "rtf.h"
|
|
#include "errstr.h"
|
|
|
|
void addexternal(char *pch);
|
|
int levelOK(aBlock *pBlock);
|
|
void parseargfile(char *filename);
|
|
|
|
/* globals */
|
|
char *progName = "docfmt"; // name of our program.
|
|
|
|
char *dirPath = NULL; // path for creation of temporary files
|
|
char *outputFile = NULL; // the final output file name
|
|
|
|
int noOutput = OFF; // if ON then no output is generated.
|
|
int outputType; // type of output to be generated
|
|
int fprocessFiles; // flag: should files be processed?
|
|
int fCleanFiles; // flag: should temporary files be cleaned up?
|
|
|
|
int fMMUserEd=FALSE; // flag: generating for User Ed?
|
|
|
|
logentry *head_log=NULL; // head of list of log files
|
|
aLine *headExternal=NULL; // head of list of external names to process
|
|
|
|
int fprocessOverride=FALSE; // has fprocessFiles been set by user?
|
|
int fCleanOverride=FALSE; // has fCleanFiles been set by user?
|
|
|
|
|
|
char achtmpbuf[128]; // a global temporary buffer
|
|
|
|
int verbose=FALSE;
|
|
|
|
// Definitions for Error Strings
|
|
//
|
|
int warninglevel=2; // warning level
|
|
int prlineno=TRUE; // print line numbers
|
|
int prinfo=TRUE; // print INFO messages ?
|
|
long haderror=0; // count of number of errors
|
|
int therewaserror=FALSE; // flag: TRUE if there was an error
|
|
int dumplevels=FALSE; // flag: TRUE if want to dump doc levels
|
|
int fSortMessage=TRUE; // flag: TRUE if want to sort messages
|
|
// seperately from APIs
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func int | docfmt | Formats the input from the given file and
|
|
* prints it to 'stdout'. If the given filename is NULL, input is
|
|
* taken from 'stdin'.
|
|
*
|
|
* @parm char * | fileName | Specifies the name of the
|
|
* file to be processed.
|
|
*
|
|
* @rdesc A return value of zero indicates success; a non-zero return value
|
|
* indicates an error.
|
|
*/
|
|
int docfmt(fileName, pcur_log)
|
|
char *fileName;
|
|
logentry *pcur_log;
|
|
{
|
|
int nStatus;
|
|
int wtag;
|
|
aBlock *pcurBlock;
|
|
EXTFile *pExt;
|
|
char ach[120];
|
|
|
|
|
|
pExt=(EXTFile *)clear_alloc(sizeof (struct _EXTFile));
|
|
if(!pExt)
|
|
{
|
|
error(ERROR3);
|
|
exit(7);
|
|
}
|
|
/* file from standard input? */
|
|
if( fileName == NULL )
|
|
{
|
|
pExt->EXTFilename=cp_alloc("<stdin>");
|
|
pExt->fp = stdin;
|
|
}
|
|
else
|
|
{
|
|
pExt->EXTFilename=cp_alloc(fileName);
|
|
pExt->fp = fopen( pExt->EXTFilename, "r");
|
|
if(pExt->fp == NULL )
|
|
{
|
|
/* or from user-supplied filename? */
|
|
strcpy( achtmpbuf, dirPath );
|
|
strcat( achtmpbuf, fileName );
|
|
my_free(pExt->EXTFilename);
|
|
pExt->EXTFilename=cp_alloc(achtmpbuf);
|
|
|
|
pExt->fp = fopen( achtmpbuf, "r");
|
|
|
|
|
|
/* can file be opened? */
|
|
if(pExt->fp == NULL)
|
|
{
|
|
error( ERROR1, achtmpbuf);
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
// get header information
|
|
getLine(pExt);
|
|
wtag=HIWORD(getTag(pExt));
|
|
|
|
while(wtag == T2_HEADER)
|
|
{
|
|
wtag=(int)getTag(pExt);
|
|
switch( wtag)
|
|
{
|
|
case TG_BEGINHEAD:
|
|
getLine(pExt);
|
|
break;
|
|
|
|
case TG_EXTRACTID:
|
|
nStatus = processText( pExt, &((pcur_log->pExt)->extractid) );
|
|
if( nStatus)
|
|
return( nStatus );
|
|
getLine(pExt);
|
|
break;
|
|
|
|
case TG_EXTRACTVER:
|
|
nStatus = processText( pExt, &((pcur_log->pExt)->extractver) );
|
|
if( nStatus)
|
|
return( nStatus );
|
|
getLine(pExt);
|
|
break;
|
|
case TG_EXTRACTDATE:
|
|
nStatus = processText( pExt, &((pcur_log->pExt)->extractdate) );
|
|
if( nStatus)
|
|
return( nStatus );
|
|
getLine(pExt);
|
|
break;
|
|
case TG_ENDHEAD:
|
|
break;
|
|
|
|
}
|
|
|
|
wtag=HIWORD(getTag(pExt));
|
|
}
|
|
|
|
#endif
|
|
|
|
if( getLine(pExt) )
|
|
{
|
|
pcurBlock=(aBlock *)1; // a do.. while loop
|
|
while( pcurBlock )
|
|
{
|
|
if(verbose>1)
|
|
fprintf(errfp," Reading: ");
|
|
pcurBlock = getBlock(pExt);
|
|
if(pcurBlock && levelOK(pcurBlock) )
|
|
{
|
|
if(verbose>1)
|
|
fprintf(errfp," Writing.\n");
|
|
putblock(pcurBlock, pcur_log);
|
|
}
|
|
else if(verbose>1)
|
|
if(pcurBlock)
|
|
fprintf(errfp," Skipping\n");
|
|
else
|
|
fprintf(errfp," End of File.\n");
|
|
|
|
if(pcurBlock)
|
|
destroyblock(pcurBlock);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nStatus = ST_EOF;
|
|
}
|
|
|
|
/* close the file */
|
|
fclose(pExt->fp);
|
|
pExt->fp=NULL;
|
|
|
|
if( nStatus == ST_EOF )
|
|
return( 0 );
|
|
else
|
|
return( nStatus );
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func int | levelOK | Returns TRUE if the specified Block is
|
|
* OK to output.
|
|
*
|
|
* @parm aBlock * | pBlock | Specifies the Block to check.
|
|
*
|
|
* @rdesc A return value of TRUE indicates the specified Block is
|
|
* valid to output. If not valid to print, the return value is FALSE.
|
|
*/
|
|
int
|
|
levelOK(aBlock *pBlock)
|
|
{
|
|
aLine *pextern;
|
|
aLine *pLevel;
|
|
|
|
pextern=headExternal;
|
|
while(pextern)
|
|
{
|
|
if(!strcmp(pextern->text,"*")) // '*' means everything
|
|
return TRUE;
|
|
|
|
pLevel=pBlock->doclevel;
|
|
while(pLevel)
|
|
{
|
|
if(!stricmp(pLevel->text,pextern->text))
|
|
return(TRUE); /* we found a match */
|
|
pLevel=pLevel->next;
|
|
}
|
|
pextern=pextern->next;
|
|
|
|
}
|
|
|
|
/* no matches. */
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | Usage | Prints usage information to 'stderr'.
|
|
*
|
|
* @comm This function does not exit.
|
|
*/
|
|
void Usage()
|
|
{
|
|
fprintf(stdout, "usage: \n%s [-x[ ]name] [-r[dh]] [-c[01] [-p[01] \n", progName);
|
|
fprintf(stdout, "\t[-o[ ]filename] [-d[ ]dirpath] [-l[ ]logfile] [-Zs] [-V[level]] [files]\n");
|
|
fprintf(stdout, "\t[@argfile]\n\n");
|
|
fprintf(stdout, "[-x[ ]name\tDefines <name> to be generated from the extracted file.\n");
|
|
fprintf(stdout, "\t\t\t\t(Default is external.)\n");
|
|
fprintf(stdout, "[-X\t\tProcesses all names from extract file.\n");
|
|
fprintf(stdout, "[-Zs]\t\t\tNo output, error check only.\n");
|
|
fprintf(stdout, "[-Ze]\t\t\tEnables extensions: dump doc level in API.\n");
|
|
fprintf(stdout, "[-rd]\t\t\tGenerate RTF output for printing.\n");
|
|
fprintf(stdout, "[-rh]\t\t\tGenerate RTF output for WinHelp.\n");
|
|
fprintf(stdout, "\t\t\t\t(Default is generate for Ventura.)\n");
|
|
fprintf(stdout, "\t\t\t\t(Default RTF is for printing.)\n");
|
|
fprintf(stdout, "[-p[01]] \t\tProcess output files.\n");
|
|
fprintf(stdout, "\t\t\t\t(0 means don't process)\n");
|
|
fprintf(stdout, "[-c[01]] \t\tClean up intermediate files.\n");
|
|
fprintf(stdout, "\t\t\t\t(0 means don't clean)\n");
|
|
fprintf(stdout, "[-m[01]] \t\tSort Messages seperately from APIs.\n");
|
|
fprintf(stdout, "\t\t\t\t(0 means don't sort seperate)\n");
|
|
fprintf(stdout, "[-d dirpath] \t\tSpecify the directory for temporary files.\n");
|
|
fprintf(stdout, "\t\t\t\t(only one tmp path should be specified)\n");
|
|
fprintf(stdout, "[-l logfile] \t\tSpecify the logfile.\n");
|
|
fprintf(stdout, "\t\t\t\t(many logfiles may be specified)\n");
|
|
fprintf(stdout, "\t\t\t\t(the logfile maps functions to files)\n");
|
|
fprintf(stdout, "[-o outputfile] \tSpecify the output file.\n");
|
|
fprintf(stdout, "[-v[level]] \t\tSets the Verbosity level.\n");
|
|
fprintf(stdout, "[-M]] \t\t\tSets processing for MM User Ed.\n");
|
|
fprintf(stdout, "[files] \t\tList of files to be processed.\n");
|
|
fprintf(stdout, "[@argfile]\t\tName of file to get list of arguments from.\n");
|
|
fprintf(stdout, "\nOptions may be placed in any order.\n");
|
|
fprintf(stdout, "example: %s /xinternal /rd dspmgr.ext\n",progName);
|
|
fprintf(stdout, "example: %s dspmgr.ext\n",progName);
|
|
fprintf(stdout, "example: %s /d \\tmp /rh dspmgr.ext\n",progName);
|
|
fprintf(stdout, "example: %s -x internal -x dspmgr -d\\tmp /rh dspmgr.ext /c0 /p0\n",progName);
|
|
fprintf(stdout, "example: %s /rd @args /c0\n",progName);
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func int | main | This function formats documentation information
|
|
* from the given input file and sends it to the standard output.
|
|
* Information is not sorted or formatted.
|
|
*
|
|
* @parm int | argc | Specified the number of arguments.
|
|
*
|
|
* @parm char * | argv[] | Specifies an arrayof points to the arguments.
|
|
*
|
|
* @rdesc The return value is zero if there are no errors, otherwise the
|
|
* return value is a non-zero error code.
|
|
*/
|
|
int main(argc, argv)
|
|
int argc; /* Specifies the number of arguments. */
|
|
char *argv[]; /* Specifies an array of pointers to the arguments */
|
|
{
|
|
int nFiles = 0; /* # of files processed */
|
|
int nStatus;
|
|
int done;
|
|
int temp;
|
|
|
|
if(initerror())
|
|
{
|
|
fprintf(stderr, "%s: Internal Error 01\n",progName);
|
|
exit(765);
|
|
}
|
|
|
|
errfp=stderr; // set error logging file to stderr
|
|
|
|
/* announce our existance */
|
|
|
|
|
|
|
|
|
|
initreadext();
|
|
|
|
noOutput = FALSE;
|
|
done = FALSE;
|
|
|
|
outputType=VENTURA;
|
|
fprocessFiles=TRUE;
|
|
|
|
parsearg(argc,argv, FALSE);
|
|
|
|
#if MMWIN
|
|
sprintf(achtmpbuf," Version %d.%02d.%02d %s %s - %s %s\n",
|
|
rmj, rmm, rup, __DATE__, __TIME__, szVerUser, MMSYSVERSIONSTR);
|
|
|
|
error(LOGON,achtmpbuf);
|
|
#endif
|
|
|
|
if(!head_log)
|
|
{
|
|
Usage();
|
|
exit(1);
|
|
}
|
|
|
|
if(!outputFile)
|
|
{
|
|
if(fprocessFiles)
|
|
{
|
|
if(head_log->inheadFile)
|
|
{
|
|
temp=findlshortname(head_log->inheadFile->filename);
|
|
strncpy(achtmpbuf,head_log->inheadFile->filename,temp);
|
|
}
|
|
else
|
|
{
|
|
temp=findlshortname(head_log->pchlogname);
|
|
strncpy(achtmpbuf,head_log->pchlogname,temp);
|
|
}
|
|
achtmpbuf[temp]='\0';
|
|
switch(outputType)
|
|
{
|
|
case VENTURA:
|
|
strcat(achtmpbuf,".txt");
|
|
break;
|
|
case RTFDOC:
|
|
case RTFHELP:
|
|
strcat(achtmpbuf,".rtf");
|
|
break;
|
|
}
|
|
outputFile=cp_alloc(achtmpbuf);
|
|
error(INFO_OUTFILEDEFAULT, achtmpbuf);
|
|
if(!fCleanOverride)
|
|
fCleanFiles=TRUE;
|
|
}
|
|
|
|
}
|
|
if(!dirPath)
|
|
{
|
|
getcwd(achtmpbuf,128);
|
|
if (achtmpbuf[strlen(achtmpbuf) - 1] != '\\')
|
|
strcat(achtmpbuf,"\\");
|
|
dirPath=cp_alloc(achtmpbuf);
|
|
|
|
}
|
|
if(!headExternal)
|
|
{
|
|
if(verbose>1)
|
|
fprintf(errfp,"Document Level list DEFAULTS to %s\n","external");
|
|
addexternal("external");
|
|
}
|
|
|
|
if(verbose) fprintf(errfp,"Reading input files...\n");
|
|
formatFiles();
|
|
|
|
|
|
if(fprocessFiles)
|
|
{
|
|
if(verbose) fprintf(errfp,"Creating %s...\n",outputFile);
|
|
processLog();
|
|
|
|
}
|
|
|
|
return(FALSE); /* we exit ok */
|
|
}
|
|
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | formatFiles | This function formats the entire list
|
|
* files and sends them to the specified output type.
|
|
*
|
|
* @comm The log files are filled in on exit.
|
|
*/
|
|
void
|
|
formatFiles()
|
|
{
|
|
fileentry *cur_file;
|
|
FILE * fp;
|
|
logentry *cur_log=head_log;
|
|
|
|
while(cur_log)
|
|
{
|
|
fp=fopen(cur_log->pchlogname,"w");
|
|
if(!fp)
|
|
{
|
|
fprintf(errfp,"Can't open %s\n",cur_log->pchlogname);
|
|
error(ERROR3);
|
|
exit(1);
|
|
}
|
|
|
|
/* output per-log header data */
|
|
cur_log->outputType=outputType;
|
|
fprintf(fp,"%d\n",cur_log->outputType);
|
|
|
|
/* close log header */
|
|
fclose(fp);
|
|
if(verbose>1) fprintf(errfp,"Processing log file %s\n",cur_log->pchlogname);
|
|
cur_file=cur_log->inheadFile;
|
|
while(cur_file)
|
|
{
|
|
cur_file->logfile=cur_log;
|
|
|
|
if(verbose>1) fprintf(errfp," Reading file %s\n",cur_file->filename);
|
|
docfmt(cur_file->filename, cur_log);
|
|
cur_file=cur_file->next;
|
|
}
|
|
cur_log=cur_log->next;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | parsearg | This function parses and process the
|
|
* arguments that it is passed.
|
|
*
|
|
* @parm int | argc | Specified the number of arguments.
|
|
*
|
|
* @parm char * | argv[] | Specifies an arrayof points to the arguments.
|
|
*
|
|
* @parm int | flag | Specifies where the arguments came from.
|
|
*
|
|
* @flag TRUE | Arguments came from a file.
|
|
*
|
|
* @flag FALSE | Arguments came from the command line.
|
|
*
|
|
* @rdesc The return value is zero if there are no errors, otherwise the
|
|
* return value is a non-zero error code.
|
|
*/
|
|
void
|
|
parsearg(argc,argv, flag)
|
|
unsigned argc;
|
|
char **argv;
|
|
int flag;
|
|
{
|
|
unsigned i,j;
|
|
char copt;
|
|
int fsamearg;
|
|
|
|
i = 1;
|
|
while( i < argc )
|
|
{
|
|
switch (*argv[i])
|
|
{
|
|
case '@':
|
|
++argv[i];
|
|
if(*argv[i]==':')
|
|
++argv[i];
|
|
if(strlen(argv[i])==0) /* we have @<space><file> */
|
|
i++;
|
|
|
|
if(*argv[i])
|
|
parseargfile(argv[i]);
|
|
else
|
|
{
|
|
error(ERR_FILE_OPTION, '@');
|
|
Usage();
|
|
exit(1);
|
|
}
|
|
|
|
break;
|
|
#ifdef MSDOS
|
|
case '/' :
|
|
#endif
|
|
case '-' :
|
|
++argv[i];
|
|
fsamearg=TRUE;
|
|
while(*argv[i] && fsamearg)
|
|
{
|
|
copt=*argv[i];
|
|
switch( *argv[i] )
|
|
{
|
|
|
|
case 'V':
|
|
case 'v':
|
|
++argv[i];
|
|
fsamearg=FALSE;
|
|
if(*argv[i])
|
|
verbose=atoi( argv[i]);
|
|
else
|
|
verbose=1;
|
|
if(verbose>0)
|
|
prinfo=TRUE;
|
|
else
|
|
prinfo=FALSE;
|
|
break;
|
|
|
|
case 'o':
|
|
case 'O':
|
|
++argv[i];
|
|
fsamearg=FALSE;
|
|
if(*argv[i]==':')
|
|
++argv[i];
|
|
if(strlen(argv[i])==0) /* we have /o<space><file> */
|
|
i++;
|
|
|
|
if(*argv[i])
|
|
setoutputfile(argv[i]);
|
|
else
|
|
{
|
|
if(flag)
|
|
{
|
|
fprintf(errfp,"%s. Line %d\n",argv[0],i);
|
|
}
|
|
error(ERR_FILE_OPTION, copt);
|
|
Usage();
|
|
exit(1);
|
|
}
|
|
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
++argv[i];
|
|
fsamearg=FALSE;
|
|
if(*argv[i]==':')
|
|
++argv[i];
|
|
if(strlen(argv[i])==0) /* we have /d<space><file> */
|
|
i++;
|
|
|
|
if(*argv[i])
|
|
settmppath(argv[i]);
|
|
else
|
|
{
|
|
if(flag)
|
|
{
|
|
fprintf(errfp,"%s. Line %d\n",argv[0],i);
|
|
}
|
|
error(ERR_FILE_OPTION, copt);
|
|
Usage();
|
|
exit(1);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
++argv[i];
|
|
addexternal("*");
|
|
break;
|
|
|
|
case 'x':
|
|
++argv[i];
|
|
fsamearg=FALSE;
|
|
if(*argv[i]==':')
|
|
++argv[i];
|
|
|
|
if(strlen(argv[i])==0) /* we have /l<space><name> */
|
|
i++;
|
|
|
|
if(*argv[i])
|
|
addexternal(argv[i]);
|
|
else
|
|
{
|
|
if(flag)
|
|
{
|
|
fprintf(errfp,"%s. Line %d\n",argv[0],i);
|
|
}
|
|
error(ERR_NAME_OPTION, copt);
|
|
Usage();
|
|
exit(1);
|
|
}
|
|
|
|
break;
|
|
case 'l':
|
|
case 'L':
|
|
++argv[i];
|
|
fsamearg=FALSE;
|
|
if(*argv[i]==':')
|
|
++argv[i];
|
|
|
|
if(strlen(argv[i])==0) /* we have /l<space><file> */
|
|
i++;
|
|
|
|
fprocessFiles=TRUE;
|
|
|
|
if(*argv[i])
|
|
add_logtoprocess(argv[i]);
|
|
else
|
|
{
|
|
if(flag)
|
|
{
|
|
fprintf(errfp,"%s. Line %d\n",argv[0],i);
|
|
}
|
|
error(ERR_FILE_OPTION, copt);
|
|
Usage();
|
|
exit(1);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
case 'C':
|
|
++argv[i];
|
|
fsamearg=FALSE;
|
|
if(*argv[i]==':')
|
|
++argv[i];
|
|
fCleanFiles=atoi( argv[i]);
|
|
fCleanOverride=TRUE;
|
|
break;
|
|
|
|
case 'm':
|
|
++argv[i];
|
|
fsamearg=FALSE;
|
|
if(*argv[i]==':')
|
|
++argv[i];
|
|
fSortMessage=atoi( argv[i]);
|
|
break;
|
|
|
|
case 'p':
|
|
case 'P':
|
|
++argv[i];
|
|
fsamearg=FALSE;
|
|
if(*argv[i]==':')
|
|
++argv[i];
|
|
fprocessFiles=atoi( argv[i]);
|
|
fprocessOverride=TRUE;
|
|
break;
|
|
|
|
|
|
case 'r':
|
|
case 'R':
|
|
++argv[i];
|
|
|
|
if(!argv[i][0]) /* if no parms, default to RTFDOC */
|
|
{
|
|
outputType=RTFDOC;
|
|
break;
|
|
}
|
|
|
|
switch(argv[i][0])
|
|
{
|
|
case 'h':
|
|
case 'H':
|
|
outputType=RTFHELP;
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
outputType=RTFDOC;
|
|
break;
|
|
|
|
default:
|
|
if(flag)
|
|
{
|
|
fprintf(errfp,"%s. Line %d\n",argv[0],i);
|
|
}
|
|
error(ERR_XOPTION, copt, argv[i][0]);
|
|
break;
|
|
}
|
|
++argv[i];
|
|
break;
|
|
|
|
case 'M':
|
|
++argv[i];
|
|
fsamearg=TRUE;
|
|
fMMUserEd=1;
|
|
break;
|
|
|
|
case 'Z':
|
|
++argv[i];
|
|
while(argv[i][0])
|
|
{
|
|
switch(argv[i][0])
|
|
{
|
|
case 'e': // enable extensions
|
|
dumplevels= TRUE;
|
|
break;
|
|
case 's': // syntax check only
|
|
noOutput = YES;
|
|
break;
|
|
default:
|
|
if(flag)
|
|
{
|
|
fprintf(errfp,"%s. Line %d\n",argv[0],i);
|
|
}
|
|
error(ERR_XOPTION,copt, argv[i][0]);
|
|
break;
|
|
}
|
|
++argv[i];
|
|
}
|
|
break;
|
|
|
|
default:
|
|
error(ERR_OPTION, copt);
|
|
Usage();
|
|
exit(1);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
/* let's look to see what kind of file it is */
|
|
j=findlshortname(argv[i]);
|
|
if(j==strlen(argv[i]))
|
|
{
|
|
/* it has no extension */
|
|
if(flag)
|
|
{
|
|
fprintf(errfp,"%s. Line %d\n",argv[0],i);
|
|
}
|
|
error(ERR_UNKNOWN_FILE, argv[i]);
|
|
Usage();
|
|
exit(1);
|
|
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
if(!stricmp(argv[i]+j,".sav"))
|
|
{
|
|
add_infile(argv[i]);
|
|
}
|
|
else if(!stricmp(argv[i]+j,".ind"))
|
|
{ /* it's an input file */
|
|
add_infile(argv[i]);
|
|
}
|
|
else if(!stricmp(argv[i]+j,".db"))
|
|
{ /* it's an input file */
|
|
add_infile(argv[i]);
|
|
}
|
|
else if(!stricmp(argv[i]+j,".xrf"))
|
|
{
|
|
add_xrffile(argv[i]);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
/* default file type */
|
|
/* add it */
|
|
|
|
if(!head_log)
|
|
{
|
|
j=findlshortname(argv[i]);
|
|
strncpy(achtmpbuf,argv[i],j);
|
|
achtmpbuf[j]='\0';
|
|
strcat(achtmpbuf,".log");
|
|
add_logtoprocess(achtmpbuf);
|
|
error(INFO_LOGFILEDEFAULT, achtmpbuf);
|
|
if(!fprocessOverride)
|
|
fprocessFiles=TRUE;
|
|
}
|
|
|
|
add_filetoprocess(argv[i], head_log);
|
|
#if 0
|
|
if(!baseFile)
|
|
{
|
|
argv[i][j]='\0';
|
|
while(j>=0 && (argv[i][j]!='\\' || argv[i][j]!='/') )
|
|
j--;
|
|
j++;
|
|
|
|
baseFile=cp_alloc(argv[i]+j);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
}
|
|
break;
|
|
} /* switch */
|
|
i++;
|
|
} /*while */
|
|
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | parseargfile | This function processes a file as arguments.
|
|
*
|
|
* @parm char * | filename | specifies the filename to process.
|
|
*
|
|
*/
|
|
void
|
|
parseargfile(char *filename)
|
|
{
|
|
static reenter=0;
|
|
|
|
FILE *fp;
|
|
int lineno,i;
|
|
char * * ppch;
|
|
char *pch;
|
|
aLine *pLine=NULL;
|
|
aLine *pHLine=NULL;
|
|
|
|
assert(!reenter);
|
|
reenter++;
|
|
fp=fopen(filename,"r");
|
|
if(!fp)
|
|
{
|
|
fprintf(errfp,"Cannot open argument file %s\n",filename);
|
|
exit(1);
|
|
}
|
|
|
|
lineno=0;
|
|
while(fgets(achtmpbuf,128,fp))
|
|
{
|
|
// comment is # or ; on first significant character
|
|
|
|
pch=achtmpbuf;
|
|
while(*pch && isspace(*pch))
|
|
pch++;
|
|
|
|
if(*pch=='#' || *pch==';')
|
|
continue;
|
|
|
|
pLine=lineMake(pch);
|
|
if(pHLine)
|
|
pLine->next=pHLine;
|
|
pHLine=pLine;
|
|
lineno++;
|
|
}
|
|
fclose(fp);
|
|
|
|
if(lineno>0 && pHLine )
|
|
{
|
|
lineno++; // leave room for arg 0
|
|
ppch=(char * *)clear_alloc( (sizeof (char *)) * (lineno+1));
|
|
assert(ppch);
|
|
|
|
pLine=pHLine;
|
|
sprintf(achtmpbuf,"Arg file: %s",filename);
|
|
ppch[0]=cp_alloc(achtmpbuf);
|
|
for(i=1;i<lineno;i++)
|
|
{
|
|
assert(pLine);
|
|
ppch[i]=pLine->text;
|
|
pLine=pLine->next;
|
|
}
|
|
parsearg(lineno,ppch, TRUE); /* do the dirty work */
|
|
|
|
lineDestroy(pHLine);
|
|
my_free(*ppch);
|
|
my_free(ppch);
|
|
}
|
|
|
|
reenter--;
|
|
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | addexternal | This function adds the specified string
|
|
* to the list of defined externals to extract.
|
|
*
|
|
* @parm char * | pch | Specifies the string to add.
|
|
*
|
|
*/
|
|
void
|
|
addexternal(char *pch)
|
|
{
|
|
aLine *pLine;
|
|
|
|
pLine=lineMake(pch);
|
|
assert(pLine);
|
|
assert(pch);
|
|
|
|
if(headExternal) /* insert at head */
|
|
pLine->next=headExternal;
|
|
|
|
headExternal=pLine;
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | setoutputfile | This sets the output file name.
|
|
*
|
|
* @parm char * | pch | Specifies the filename.
|
|
*
|
|
*/
|
|
void
|
|
setoutputfile(char * pch)
|
|
{
|
|
assert(pch);
|
|
assert(!outputFile);
|
|
|
|
outputFile=cp_alloc(pch);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | settmppath | This sets the path for temporary files.
|
|
*
|
|
* @parm char * | pch | Specifies the path name.
|
|
*
|
|
*/
|
|
void
|
|
settmppath(char *pch)
|
|
{
|
|
int temp;
|
|
char ach[80];
|
|
|
|
assert(pch);
|
|
assert(!dirPath);
|
|
|
|
strcpy( ach, pch );
|
|
temp = strlen( ach );
|
|
if( (temp != 0) && (ach[temp-1] != '\\') )
|
|
{
|
|
ach[temp++] = '\\';
|
|
ach[temp] = '\0';
|
|
}
|
|
dirPath=cp_alloc(ach);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func files | add_outfile | This function adds the specified file to
|
|
* the list of output files for the specified log file.
|
|
*
|
|
* @parm char * | pchfile | Specifies the filename.
|
|
*
|
|
* @parm logentry * | pcur_log | Specifies the log file.
|
|
*
|
|
* @rdesc The return value is the outfile of the specified file.
|
|
*
|
|
*/
|
|
files
|
|
add_outfile(char *pchfile, logentry *pcur_log)
|
|
{
|
|
files pfile;
|
|
files pcurfile;
|
|
|
|
assert(pcur_log);
|
|
|
|
pfile=(files)clear_alloc(sizeof (struct strfile));
|
|
if(!pfile)
|
|
return(NULL);
|
|
|
|
pfile->filename=cp_alloc(pchfile);
|
|
pfile->logfile=pcur_log;
|
|
if(pcur_log->outheadFile)
|
|
{
|
|
pcurfile=pcur_log->outheadFile;
|
|
while(pcurfile->next)
|
|
{
|
|
pcurfile=pcurfile->next;
|
|
}
|
|
pcurfile->next=pfile;
|
|
|
|
}
|
|
else
|
|
pcur_log->outheadFile=pfile;
|
|
|
|
return(pfile);
|
|
}
|
|
|
|
|
|
/**********************************************************/
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func int | putblock | This function outputs a specifed block.
|
|
*
|
|
* @parm aBlock * |pBlock | Specifies the block to output.
|
|
*
|
|
* @parm logentry * | pcur_log | Specifies the log to add the output file.
|
|
*
|
|
* @rdesc The return value is TRUE if no error has occured.
|
|
*
|
|
*/
|
|
int
|
|
putblock( aBlock *pBlock, logentry *pcur_log)
|
|
{
|
|
char achFile[128];
|
|
FILE *tFile;
|
|
files pfile;
|
|
|
|
assert(pBlock);
|
|
assert(pcur_log);
|
|
|
|
/* output function documentation */
|
|
if( !noOutput )
|
|
{
|
|
|
|
mymktemp(dirPath,achFile);
|
|
|
|
pfile=add_outfile(achFile, pcur_log);
|
|
|
|
assert(pfile);
|
|
|
|
/* open the file */
|
|
tFile = fopen( pfile->filename, "w" );
|
|
if( !tFile )
|
|
{
|
|
error(ERROR10, pfile->filename);
|
|
return(FALSE);
|
|
}
|
|
|
|
/* output information */
|
|
switch(outputType)
|
|
{
|
|
case VENTURA:
|
|
VenturaBlockOut(pBlock, tFile);
|
|
break;
|
|
|
|
case RTFDOC:
|
|
case RTFHELP:
|
|
|
|
RTFBlockOut( pBlock, tFile );
|
|
break;
|
|
|
|
default:
|
|
fprintf(errfp, "\nInternal Error: Unknown Output Type. Block name:%s\n",pBlock->name->text);
|
|
break;
|
|
}
|
|
|
|
fclose(tFile);
|
|
|
|
|
|
/* add to the logfile */
|
|
tFile = fopen(pcur_log->pchlogname, "a");
|
|
if( !tFile )
|
|
{
|
|
error(ERROR9, pcur_log->pchlogname );
|
|
}
|
|
else
|
|
{
|
|
fprintf(tFile, "%d ", pBlock->blockType); // output type
|
|
VentextOut( tFile, pBlock->name, FALSE ); // block name
|
|
fprintf( tFile, " \t%s\n", pfile->filename ); // filename
|
|
fclose( tFile );
|
|
}
|
|
|
|
}
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void |destroyblock | This functions deletes all the data structures
|
|
* associated withe a block.
|
|
*
|
|
* @parm aBlock *| pcurblock | Specifies the Block to be destroyed.
|
|
*
|
|
*/
|
|
void
|
|
destroyblock(aBlock *pcurblock)
|
|
{
|
|
aBlock *pcbBlock;
|
|
|
|
if(!pcurblock)
|
|
return;
|
|
|
|
destroyBlockchain(pcurblock->cb);
|
|
pcurblock->cb=NULL;
|
|
|
|
/* free all elements of the aBlock structure */
|
|
my_free( pcurblock->srcfile );
|
|
pcurblock->srcfile=NULL;
|
|
|
|
lineDestroy( pcurblock->doclevel );
|
|
pcurblock->doclevel=NULL;
|
|
|
|
lineDestroy( pcurblock->name );
|
|
pcurblock->name=NULL;
|
|
|
|
lineDestroy( pcurblock->type );
|
|
pcurblock->type=NULL;
|
|
|
|
lineDestroy( pcurblock->desc );
|
|
pcurblock->desc=NULL;
|
|
|
|
parmDestroy( pcurblock->parm );
|
|
pcurblock->parm=NULL;
|
|
|
|
regDestroy( pcurblock->reg );
|
|
pcurblock->reg=NULL;
|
|
|
|
fieldDestroy( pcurblock->field);
|
|
pcurblock->field=NULL;
|
|
|
|
otherDestroy( pcurblock->other);
|
|
pcurblock->other=NULL;
|
|
|
|
lineDestroy( pcurblock->tagname);
|
|
pcurblock->tagname=NULL;
|
|
|
|
lineDestroy( pcurblock->rtndesc );
|
|
pcurblock->rtndesc=NULL;
|
|
|
|
flagDestroy( pcurblock->rtnflag );
|
|
pcurblock->rtnflag=NULL;
|
|
|
|
lineDestroy( pcurblock->comment );
|
|
pcurblock->comment=NULL;
|
|
|
|
lineDestroy( pcurblock->xref );
|
|
pcurblock->xref=NULL;
|
|
|
|
/* now, free the aBlock structure itself */
|
|
my_free( pcurblock );
|
|
}
|
|
|
|
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void |destroyBlockchain | This function deletes a list of Blocks.
|
|
*
|
|
* @parm aBlock * |pcurblock | Specifies the head of the list of Blocks.
|
|
*
|
|
* @comm This function is recursive.
|
|
*/
|
|
void
|
|
destroyBlockchain(aBlock *pcurblock)
|
|
{
|
|
if(!pcurblock)
|
|
return;
|
|
|
|
if(pcurblock->next)
|
|
destroyBlockchain(pcurblock->next);
|
|
|
|
destroyblock(pcurblock);
|
|
}
|