[The following is a code listing from the article "Error Messages and Documentation", by S. L. Sanders]
//============================ exstrng [main] ==========================
// Main program for CUJ article illustrating string extraction.
// Scans a C source file, extracting the first string from each
// function or macro definition. The string is writtten onto an
// output file after removing any printf format specifiers.
//
// Copyright (c) Sanders-Indev, Inc, 1997:
// Commercial use of any kind is prohibited without written consent of
// the owner. Personal and teaching use is permitted.
//======================================================================
#include "exstrng.h" // Includes ctype.h and
// parse2.h, which includes
// stdio.h, stddef.h, and string.h
short main(int argc,char *argv[])
{ //BEGIN main
/*--Initialize for the run--*/
if(argc!=2){ //No filename argument on command line
printf("\a Usage:\nexstrng filenam (filenam is input file.)\n");
return(-1);
} //END No filename argument on command line
if((wrkf=fopen("wrkf.$$$","w"))==NULL) { //Open workfile for output
printf("\nAborted: Can't create work file wrkf.$$$.\a");
/* Can't open the report work file for output. */
return(-1);
} //END Open workfile for output
strcpy(infnam,argv[1]); //Get input file name from command line
if((inf=fopen(infnam,"rt"))==NULL) { //Open input file
printf("\nError: Can't open input file %s.",infnam);
return(-1);
} //END Open input file
/* Can't open an input file for XMan to analyze. */
/*--Process the input file--*/
while(err==0&&!feof(inf)){ //Each char of initialized input file
csisav=csi; //Save char-scan index and line counter, so they
lctsav=linectr; //can be checked for change at end of loop.
if(CIDCHR(currline,csi)){ //Valid C identifier-char (See parse.h)
CIDSTORE //Store currline[csi] as next char in currname array
if(err!=0) //err is set to 1 if name is too long
break; //Name too long-- immediately exit "Each char..." loop
} //END Valid C identifier-char (See parse.h)
else{ //currline[csi] is endname (not a valid C identifier-char)
CKENDRTN //Detect end of function or macro
GETNOJNK(SKIP,err=1) //Skip blanks, empty lines, comments, strings
if(err==1) //GETNOJNK 2nd parameter was executed-- read has failed
break; //Immediately exit the "Each char..." loop
if(morfndx>0){ //currname is not empty
if(tstfmhdr()!=0){ //Test for function or macro header
err=1; //Indicate bad input file
break; //Immediately exit the "Each input file" loop
} //END Test for function or macro header
//ASSERT: If currname is not a function or macro header, csi
// indexes the endname char (or the first non-junk after);
// otherwise, it indexes the first char following the
// opening { of a function's or macro's defining compound
// statement. morfindx has been set to 0, and currname
// contains the name it had prior to the tstfmhdr call,
// but with kNUL appended.
} //END currname is not empty
} //END currline[csi] is endname (not a valid C identifier-char)
/*--Check for newline--*/
if(currline[csi]=='\n')
READLINE(err=1) //READLINE parameter err=1 executed iff fgets()
else //fails to read a line from inf into currline.
//Increment csi only if it indexes the same char of the same line
//it indexed when the main loop started.
if(csi==csisav&&linectr==lctsav)
csi++;
} //END Each char of initialized input file
/*--Normal return--*/
if(fmcount==0){ //Nothing found
printf("\nNo function or macro def found in file %s.",infnam);
fprintf(wrkf,"\nNo function or macro def found in file %s.",infnam);
} //END Nothing found
printf("\n(End %s; %d lines)\n",infnam,linectr);
fprintf(wrkf,"\n(End %s; %d lines)\n",infnam,linectr);
fclose(inf);
return(0);
} //END main
//======================================================================
Back to main article.