📄 parser.c
字号:
return 0; if ( skip ) { if ( token[0] == skip[0] ) file_skip_section( file, skip[1] ); else break; } else break; } return 1;}/*====================================================================Remove quotes if any and return result as newly allocated string.====================================================================*/static char* parser_remove_quotes( char *string ){ char *new; if ( string[0] != '"' ) return strdup( string ); new = calloc( strlen( string ) - 1, sizeof( char ) ); strncpy( new, string + 1, strlen( string ) - 2 ); new[strlen( string ) - 2] = 0; return new;}/*====================================================================Proceed in the given string until it ends or non-whitespace occursand return the new position.====================================================================*/static char* string_ignore_whitespace( char *string ){ int i = 0; while ( string[i] != 0 && string[i] <= 32 ) i++; return string + i;}/*====================================================================This function searches file from the current position for the nextpdata entry.====================================================================*/static PData* parser_parse_file( FILE *file ){ char token[PARSER_MAX_TOKEN_LENGTH]; PData *pd = 0, *sub = 0; /* get name */ if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) ) return 0; if ( is_symbol( token[0], PARSER_SYMBOLS ) ) { sprintf( parser_sub_error, "parse error before '%s'", token ); return 0; } pd = calloc( 1, sizeof( PData ) ); pd->name = parser_remove_quotes( token ); /* check type */ if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) ) goto failure; switch ( token[0] ) { case PARSER_SET: /* assign single value or list */ pd->values = list_create( LIST_AUTO_DELETE, LIST_NO_CALLBACK ); if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) ) goto failure; if ( token[0] != PARSER_LIST_BEGIN ) { if ( is_symbol( token[0], PARSER_SYMBOLS ) ) { sprintf( parser_sub_error, "parse error before '%s'", token ); goto failure; } else list_add( pd->values, parser_remove_quotes( token ) ); } else { if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) ) goto failure; while ( token[0] != PARSER_LIST_END ) { if ( is_symbol( token[0], PARSER_SYMBOLS ) ) { sprintf( parser_sub_error, "parse error before '%s'", token ); goto failure; } else list_add( pd->values, parser_remove_quotes( token ) ); if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) ) goto failure; } } break; case PARSER_GROUP_BEGIN: /* check all entries until PARSER_GROUP_END */ pd->entries = list_create( LIST_NO_AUTO_DELETE, LIST_NO_CALLBACK ); while ( 1 ) { if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) ) goto failure; if ( token[0] == PARSER_GROUP_END ) break; fseek( file, -strlen( token ), SEEK_CUR ); sub = parser_parse_file( file ); if ( sub ) list_add( pd->entries, sub ); else goto failure; } break; default: sprintf( parser_sub_error, "parse error before '%s'", token ); goto failure; } return pd;failure: parser_free( &pd ); return 0;}/*====================================================================Publics====================================================================*//*====================================================================This function splits a string into tokens using the charactersfound in symbols as breakpoints. If the first symbol is ' ' allwhitespaces are used as breakpoints though NOT added as a token (thus removed from string).====================================================================*/List* parser_split_string( char *string, char *symbols ){ int pos; char *token = 0; List *list = list_create( LIST_AUTO_DELETE, LIST_NO_CALLBACK ); while ( string[0] != 0 ) { if ( symbols[0] == ' ' ) string = string_ignore_whitespace( string ); if ( string[0] == 0 ) break; pos = 1; /* 'read in' first character */ while ( string[pos - 1] != 0 && !is_symbol( string[pos - 1], symbols ) && string[pos - 1] != '"' ) pos++; if ( pos > 1 ) pos--; else if ( string[pos - 1] == '"' ) { /* read a string */ string = string + 1; pos = 0; while ( string[pos] != 0 && string[pos] != '"' ) pos++; token = calloc( pos + 1, sizeof( char ) ); strncpy( token, string, pos ); token[pos] = 0; list_add( list, token ); string = string + pos + (string[pos] != 0); continue; } token = calloc( pos + 1, sizeof( char ) ); strncpy( token, string, pos); token[pos] = 0; list_add( list, token ); string = string + pos; } return list;}/*====================================================================This is the light version of parser_split_string which checks forjust one character and does not add this glue characters to the list. It's about 2% faster. Wow.====================================================================*/List *parser_explode_string( char *string, char c ){ List *list = list_create( LIST_AUTO_DELETE, LIST_NO_CALLBACK ); char *next_slash = 0; char buffer[64]; while ( string[0] != 0 && ( next_slash = strchr( string, c ) ) != 0 ) { if ( next_slash != string ) { strcpy_lt( buffer, string, (next_slash-string>63)?63:(next_slash-string) ); list_add( list, strdup( buffer ) ); } string += next_slash - string + 1; } if ( string[0] != 0 ) list_add( list, strdup( string ) ); return list;}/*====================================================================This function reads in a whole file and converts it into aPData tree struct. If an error occurs NULL is returned and parser_error is set.====================================================================*/static int parser_read_file_full( FILE *file, PData *top ){ PData *sub = 0; char token[1024]; /* parse file */ while ( !feof( file ) ) { if ( ( sub = parser_parse_file( file ) ) != 0 ) list_add( top->entries, sub ); else return 0; /* skip comments and whitespaces */ if ( !file_read_token( file, PARSER_SYMBOLS, PARSER_SKIP_SYMBOLS, token ) ) { if ( token[0] != 0 ) return 0; break; } else fseek( file, -strlen( token ), SEEK_CUR ); } return 1;}static int parser_read_file_compact( PData *section ){ /* section is the parent pdata that needs some entries */ PData *pd = 0; char *line, *cur; while ( ( line = parser_get_next_line() ) ) { switch ( line[0] ) { case '>': /* this section is finished */ return 1; case '<': /* add a whole subsection */ pd = calloc( 1, sizeof( PData ) ); pd->name = strdup( line + 1 ); pd->entries = list_create( LIST_NO_AUTO_DELETE, LIST_NO_CALLBACK ); parser_read_file_compact( pd ); /* add to section */ list_add( section->entries, pd ); break; default: /* read values as subsection */ pd = calloc( 1, sizeof( PData ) ); /* check name */ if ( ( cur = strchr( line, '
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -