[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.