NT4/private/windows/media/tools/docfmt/docfmt.c
2020-09-30 17:12:29 +02:00

1181 lines
24 KiB
C

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