[The following is a code listing from the article "Error Messages and Documentation", by S. L. Sanders]
//============================= qstring ================================
// currline[csi] is the opening quotation mark of a string that is
// assumed to follow the rules for a printf() format string. If
// strnact==SKIP, skip the string. Otherwise, write the string on the
// file to which wrkf points, filtering the format specifiers from it.
// Repeat as long as the quotation mark is followed only by blanks on
// the line, and the next line begins with a string.
// Upon returning, csi indexes the first nonblank after the closing
// quotation mark of the last string processed.
//
// Return: 0=Normal
// 1=Error
//
// 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.
//======================================================================
short qstring(char strnact)
{ //BEGIN qstring
char nltrail; //Boolean: TRUE = 1 or more trailing "\n" inside string
short csiopen=csi; //Hold char-scan index of opening quote
short lctopen=linectr; //Hold line counter of opening quote
short i=-1; //General index (-1 is a first-time signal)
/*--Process all lines that begin with string or continuation--*/
while(TRUE){ //Do all quote lines
csi++; //Skip past opening quote
if(strnact==NOSKIP){ //Write the string, filtering as needed
if(i==-1) //TRUE only first time through
fputs("\n ",wrkf); //Indent
while(currline[csi]!='"'&&!feof(inf)){ //Each char up to closing "
if(currline[csi]=='\\'){ //Escape sequence or line continuation
if(currline[csi+1]=='n'){ //"\n" embedded in string
if(csi==csiopen+1&&linectr==lctopen) //Skip all leading "\n"
for(;currline[csi]=='\\'&&currline[csi+1]=='n';csi+=2);
else{ //Not a leading "\n"; check for trailing
SAVPOS; //Save position in case not a trailing "\n"
nltrail=TRUE;
do{ //Until closing " hit
if(currline[csi]!='\\'||currline[csi+1]!='n'){ //Not "\n"
nltrail=FALSE;
break; //Immediately exit "Until closing " hit" loop
} //END Not "\n"
else
csi+=2; //Skip "\n"
if(currline[csi]=='"'){ //Check for auto concatenation
csi++; //Skip the closing quote
SKIPBLNK(currline,csi) //Skip any blanks after close "
if(EOL){ //Contination or newline follows closing "
i=linectr; //Save line count (to detect skipped lines)
READLINE(return(1))
//return(1) executed by NEXTLINE if read fails.
if(linectr>i+1||currline[beginlin]!='"')
break; //Next line is not a concatenation string
//Immed. exit "Until closing " hit" loop
else
csi++; //Skip next-line concatenation's opening "
} //END Contination or newline follows closing "
else //Non-blank char follows string on same line
if(currline[csi]!='"')
break; //No concatenation string on same line
else
csi++; //Skip same-line concatenation's opening "
} //END Check for auto concatenation
else
if(EOL)
READLINE(return(1))
//return(1) executed by NEXTLINE if read fails
}while(!CLOSEQUO(currline,csi)); //END Until closing " hit
if(nltrail) //Trailing "\n" advanced csi 1 past closing
return(0); //quotation mark, so normal return immediately.
else
RSTPOS //Not trailing "\n", so go back to it
} //END Not a leading "\n"; check for trailing
if(currline[csi]=='\\') //"\n" not leading or trailing
fputs("\n ",wrkf); //Indent
} //END "\n" embedded in string
//ASSERT: If string consisted entirely of one or more "\n"
// pairs, csi indexes the closing quote.
if(CLOSEQUO(currline,csi)) //csi indexes a closing quote
break; //Immed. exit "Each char up to closing " loop
if(currline[csi+1]=='\n') //csi indexes a line-continuation \
csi++; //Skip the line-continuation '\', to get to the '\n'
} //END Escape sequence or line continuation
if(currline[csi]=='\n'){ //Get next line
READLINE(return(1))
//return(1) is executed by NEXTLINE if it can't read the file.
continue; //Immediately iterate "Each char up to closing " loop
} //END Get next line
if(currline[csi]=='\\'){ //Skip past escape sequence inside string
csi++; //Skip the '\'
if(currline[csi]!='\''&&currline[csi]!='"'\
&&currline[csi]!='\\'){ //No-show escape sequence
if(currline[csi]=='x'||currline[csi]=='X'){ //Hex ASCII
csi++; //Skip hexadecimal flag
for(;isxdigit(currline[csi]);csi++); //Skip hex char
}//END Hex ASCII
else //Skip all digits of octal char, if present;
for(i=0;i<7;csi++) //in any case, skip at least one char.
for(i=0;currline[csi]!=octdigit[i]&&i<8;i++);
continue; //Immed. iterate "Each char up to closing " loop
} //END No-show escape sequence
} //END Skip past escape sequence inside string
if(currline[csi]=='%'){ //'%' or printf fmt specifier
csi++; //Skip past '%'
if(currline[csi]!='%'){ //printf format specifier
//Skip to next char in file that is a member of set pfmttype
ISMEMFL(inf,csi,pfmttype,currline,LINESZ,linectr,return(1))
//return(1) is executed by NEXTLINE if it can't read the file.
if(currline[csi]!='"') //Don't skip closing quote
csi++; //Skip past type spec in printf format string
continue; //Immed. iterate "Each char up to closing " loop
} //END printf format specifier
} //END '%' or printf format specifier
fputc(currline[csi],wrkf); // Regular char of string
csi++; //Next char
i=1;
} //END Each char up to closing "
} //END Write the string, filtering as needed
else //Skip to closing quotation mark without writing
while(!CLOSEQUO(currline,csi)&&!feof(inf))
if(EOL)
READLINE(return(1))
//return(1) is executed by NEXTLINE if it can't read the file.
else{ //Increment csi
if(currline[csi]=='\\'&&currline[csi+1]!='\n')
currline[++csi]=' '; //To handle strings that end with \\"
csi++;
} //END Increment csi
/*--Closing quote or unexpected EOF reached--*/
if(feof(inf)){ //Closing quotation mark not found
printf("\nError: EOF looking for closing quotation mark in "
"input file %s.",infnam);
fprintf(wrkf,"\nError: EOF looking for closing quotation mark in "
"input file %s.",infnam);
//This indicates that the input is not an error-free C source file.
err=1; //Indicate bad input file
return(1);
} //END Closing quotation mark not found
csi++; //Skip the closing quote
SKIPBLNK(currline,csi) //Skip any blanks following closing quote
/*--Check for automatic-concatenation string--*/
if(EOL){ //Contination or newline follows closing "
i=linectr; //Save the line count (to detect skipped lines)
READLINE(return(1))
//return(1) is executed by NEXTLINE if it can't read the file.
if(linectr>i+1||currline[beginlin]!='"')
break; //Next line is not a concatenation string
} //END Contination or newline follows closing "
else //Non-blank char follows string on same line
if(currline[csi]!='"') //No concatenation string on same line
break; //Immediately exit "Do all quote lines" loop
} //END Do all quote lines
/*--Normal return--*/
//ASSERT: currline[csi] is the 1st nonblank after the closing quotation
// mark of a string.
return(0);
} //END qstring
//======================================================================
Back to main article.