static BOOL Parse( myFILE *InFile, BOOL (*sfunc)(char *), BOOL (*pfunc)(char *, char *) ) /* ------------------------------------------------------------------------ ** * Scan & parse the input. * * Input: InFile - Input source. * sfunc - Function to be called when a section name is scanned. * See Section(). * pfunc - Function to be called when a parameter is scanned. * See Parameter(). * * Output: True if the file was successfully scanned, else False. * * Notes: The input can be viewed in terms of 'lines'. There are four * types of lines: * Blank - May contain whitespace, otherwise empty. * Comment - First non-whitespace character is a ';' or '#'. * The remainder of the line is ignored. * Section - First non-whitespace character is a '['. * Parameter - The default case. * * ------------------------------------------------------------------------ ** */ { int c; c = EatWhitespace( InFile ); while( (EOF != c) && (c > 0) ) { switch( c ) { case '\n': /* Blank line. */ c = EatWhitespace( InFile ); break; case ';': /* Comment line. */ case '#': c = EatComment( InFile ); break; case '[': /* Section Header. */ if( !Section( InFile, sfunc ) ) return( False ); c = EatWhitespace( InFile ); break; case '\\': /* Bogus backslash. */ c = EatWhitespace( InFile ); break; default: /* Parameter line. */ if( !Parameter( InFile, pfunc, c ) ) return( False ); c = EatWhitespace( InFile ); break; } } return( True ); } /* Parse */
void JSONReader::EatWhitespaceAndComments() { while('\0' != *json_pos_) { switch(*json_pos_) { case ' ': case '\n': case '\r': case '\t': ++json_pos_; break; case '/': // TODO: RFC中没定义, 所以可作为解析器标记. if(!EatComment()) { return; } break; default: // 不是空白, 退出. return; } } }
static bool Parse( DATA_BLOB *buf, myFILE *InFile, bool (*sfunc)(const char *, void *), bool (*pfunc)(const char *, const char *, void *), void *userdata) { int c; c = EatWhitespace( InFile ); while( (EOF != c) && (c > 0) ) { switch( c ) { case '\n': /* Blank line. */ c = EatWhitespace( InFile ); break; case ';': /* Comment line. */ case '#': c = EatComment( InFile ); break; case '[': /* Section Header. */ if( !Section( buf, InFile, sfunc, userdata ) ) return False; c = EatWhitespace( InFile ); break; case '\\': /* Bogus backslash. */ c = EatWhitespace( InFile ); break; default: /* Parameter line. */ if( !Parameter( buf, InFile, pfunc, c, userdata ) ) return False; c = EatWhitespace( InFile ); break; } } return True; }
static BOOL Section( myFILE *InFile, BOOL (*sfunc)(char *) ) /* ------------------------------------------------------------------------ ** * Scan a section name, and pass the name to function sfunc(). * * Input: InFile - Input source. * sfunc - Pointer to the function to be called if the section * name is successfully read. * * Output: True if the section name was read and True was returned from * <sfunc>. False if <sfunc> failed or if a lexical error was * encountered. * * ------------------------------------------------------------------------ ** */ { int c; int i; int end; char *func = "params.c:Section() -"; i = 0; /* <i> is the offset of the next free byte in bufr[] and */ end = 0; /* <end> is the current "end of string" offset. In most */ /* cases these will be the same, but if the last */ /* character written to bufr[] is a space, then <end> */ /* will be one less than <i>. */ c = EatWhitespace( InFile ); /* We've already got the '['. Scan */ /* past initial white space. */ while( (EOF != c) && (c > 0) ) { /* Check that the buffer is big enough for the next character. */ if( i > (bSize - 2) ) { bSize += BUFR_INC; bufr = Realloc( bufr, bSize ); if( NULL == bufr ) { DEBUG(0, ("%s Memory re-allocation failure.", func) ); return( False ); } } /* Handle a single character. */ switch( c ) { case ']': /* Found the closing bracket. */ bufr[end] = '\0'; if( 0 == end ) /* Don't allow an empty name. */ { DEBUG(0, ("%s Empty section name in configuration file.\n", func )); return( False ); } if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */ return( False ); (void)EatComment( InFile ); /* Finish off the line. */ return( True ); case '\n': /* Got newline before closing ']'. */ i = Continuation( bufr, i ); /* Check for line continuation. */ if( i < 0 ) { bufr[end] = '\0'; DEBUG(0, ("%s Badly formed line in configuration file: %s\n", func, bufr )); return( False ); } end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i); c = mygetc( InFile ); /* Continue with next line. */ break; default: /* All else are a valid name chars. */ if( isspace( c ) ) /* One space per whitespace region. */ { bufr[end] = ' '; i = end + 1; c = EatWhitespace( InFile ); } else /* All others copy verbatim. */ { bufr[i++] = c; end = i; c = mygetc( InFile ); } } } /* We arrive here if we've met the EOF before the closing bracket. */ DEBUG(0, ("%s Unexpected EOF in the configuration file: %s\n", func, bufr )); return( False ); } /* Section */
static bool Section( DATA_BLOB *buf, myFILE *InFile, bool (*sfunc)(const char *, void *), void *userdata ) { int c; int i; int end; const char *func = "params.c:Section() -"; i = 0; /* <i> is the offset of the next free byte in bufr[] and */ end = 0; /* <end> is the current "end of string" offset. In most */ /* cases these will be the same, but if the last */ /* character written to bufr[] is a space, then <end> */ /* will be one less than <i>. */ /* Find the end of the section. We must use mb functions for this. */ if (!FindSectionEnd(InFile)) { DEBUG(0, ("%s No terminating ']' character in section.\n", func) ); return False; } c = EatWhitespace( InFile ); /* We've already got the '['. Scan */ /* past initial white space. */ while( (EOF != c) && (c > 0) ) { /* Check that the buffer is big enough for the next character. */ if( i > (buf->length - 2) ) { uint8_t *tb = (uint8_t *)SMB_REALLOC_KEEP_OLD_ON_ERROR(buf->data, buf->length+BUFR_INC ); if(!tb) { DEBUG(0, ("%s Memory re-allocation failure.", func) ); return False; } buf->data = tb; buf->length += BUFR_INC; } /* Handle a single character other than section end. */ switch( c ) { case '\n': /* Got newline before closing ']'. */ i = Continuation( buf->data, i ); /* Check for line continuation. */ if( i < 0 ) { buf->data[end] = '\0'; DEBUG(0, ("%s Badly formed line in configuration file: %s\n", func, buf->data )); return False; } end = ( (i > 0) && (' ' == buf->data[i - 1]) ) ? (i - 1) : (i); c = mygetc( InFile ); /* Continue with next line. */ break; default: /* All else are a valid name chars. */ if(isspace( c )) { /* One space per whitespace region. */ buf->data[end] = ' '; i = end + 1; c = EatWhitespace( InFile ); } else { buf->data[i++] = c; end = i; c = mygetc( InFile ); } } if (AtSectionEnd(InFile)) { /* Got to the closing bracket. */ buf->data[end] = '\0'; if( 0 == end ) { /* Don't allow an empty name. */ DEBUG(0, ("%s Empty section name in configuration file.\n", func )); return False; } if( !sfunc((char *)buf->data, userdata) ) /* Got a valid name. Deal with it. */ return False; EatComment( InFile ); /* Finish off the line. */ return True; } } /* We arrive here if we've met the EOF before the closing bracket. */ DEBUG(0, ("%s Unexpected EOF in the configuration file: %s\n", func, buf->data )); return False; }