📄 parser.c
字号:
/*************************************************************************** parser.c - description ------------------- begin : Sat Mar 9 2002 copyright : (C) 2001 by Michael Speck email : kulkanie@gmx.net ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/#include <stdlib.h>#include <string.h>#include "parser.h"/*====================================================================Error string.====================================================================*/static char parser_sub_error[1024];static char parser_error[1024];/*====================================================================This buffer is used to fully load resource files when the compact format is used.====================================================================*/enum { CBUFFER_SIZE = 131072 }; /* 128 KB */static char cbuffer[CBUFFER_SIZE];static char* cbuffer_pos = 0; /* position in cbuffer *//*====================================================================As we need constant strings sometimes we have to define a maximumlength for tokens.====================================================================*/enum { PARSER_MAX_TOKEN_LENGTH = 1024 };/*====================================================================Locals====================================================================*//*====================================================================Macro to shorten the fread call for a single character.====================================================================*/#define FILE_READCHAR( file, c ) fread( &c, sizeof( char ), 1, file )/*====================================================================Copy source to dest and at maximum limit chars. Terminate with 0.====================================================================*/void strcpy_lt( char *dest, char *src, int limit ){ int len = strlen( src ); if ( len > limit ) { strncpy( dest, src, limit ); dest[limit] = 0; } else strcpy( dest, src );}/*====================================================================Find next newline in cbuffer and replace it with \0 and return the pointer to the current line.====================================================================*/static char* parser_get_next_line(){ char *line = cbuffer_pos; char *newpos; if ( cbuffer_pos[0] == 0 ) return 0; /* completely read. no more lines. */ if ( ( newpos = strchr( cbuffer_pos, 10 ) ) == 0 ) cbuffer_pos += strlen( cbuffer_pos ); /* last line */ else { cbuffer_pos = newpos + 1; /* set pointer to next line */ newpos[0] = 0; /* terminate current line */ } return line;}/*====================================================================Set parse error string: "file:line: error"====================================================================*/static void parser_set_parse_error( char *fname, FILE *file, char *error ){ int end, pos; int line_count = 1; char c; end = ftell( file ); pos = 0; fseek( file, 0, SEEK_SET ); while ( pos < end ) { FILE_READCHAR( file, c ); pos++; if ( c == 10 ) line_count++; } sprintf( parser_error, "%s: %i: %s", fname, line_count, error ); }/*====================================================================Check if the given character occurs in the symbol list.If the first symbol is ' ' it is used as wildcard for allwhite-spaces.====================================================================*/static int is_symbol( int c, char *symbols ){ int i = 0; if ( symbols[0] == ' ' && c <= 32 ) return 1; while ( symbols[i] != 0 ) if ( c == symbols[i++] ) return 1; return 0;}/*====================================================================Move file position forward until reading in the given character.If stop is ' ' whitespaces will be ignored.====================================================================*/static void file_skip( FILE *file, char stop ){ char c = 0; FILE_READCHAR( file, c ); while ( ( ( stop == ' ' && c <= 32 ) || ( stop != ' ' && c != stop ) ) && !feof( file ) ) FILE_READCHAR( file, c ); if ( !feof( file ) ) fseek( file, -1, SEEK_CUR );}/*====================================================================Read next token from current file position where symbols is alist of characters used to break up the tokens. The symbols themself are returned as tokens. If ' ' occurs in the symbol listit will be ignored and whitespaces are removed automatically.The token does not exceed PARSER_MAX_TOKEN_LENGTH.Enclosing ".." are kept at the token. Use file_compare_token()to test it's contents.Returns False on EoF.====================================================================*/static int file_read_token_intern( FILE *file, char *symbols, char *token ){ int pos = 0; char c; token[0] = 0; file_skip( file, ' ' ); FILE_READCHAR( file, c ); if ( feof( file ) ) { sprintf( parser_sub_error, "unexpected end of file" ); return 0; } /* string? */ if ( c == '"' ) { token[pos++] = '"'; FILE_READCHAR( file, c ); while ( ( !feof( file ) && c != '"' ) ) { token[pos++] = c; if ( pos == PARSER_MAX_TOKEN_LENGTH - 2 ) { token[pos++] = '"'; token[pos] = 0; sprintf( parser_sub_error, "token exceeds limit" ); return 0; } FILE_READCHAR( file, c ); } token[pos++] = '"'; token[pos] = 0; if ( feof( file ) ) { sprintf( parser_sub_error, "unexpected end of file" ); token[0] = 0; return 0; } return 1; } /* symbol? */ if ( is_symbol( c, symbols ) ) { token[0] = c; token[1] = 0; return 1; } /* other token */ while ( !is_symbol( c, symbols ) && !feof( file ) ) { token[pos++] = c; if ( pos == PARSER_MAX_TOKEN_LENGTH - 1 ) { token[pos] = 0; sprintf( parser_sub_error, "token exceeds limit" ); return 0; } FILE_READCHAR( file, c ); } token[pos] = 0; if ( feof( file ) ) return 1; fseek( file, -1, SEEK_CUR ); return 1;}/*====================================================================Skip all tokens until one begins with character 'stop'. Thistoken is also ignored.====================================================================*/static void file_skip_section( FILE *file, char stop ){ char token[PARSER_MAX_TOKEN_LENGTH]; do { file_read_token_intern( file, PARSER_SYMBOLS, token ); } while ( !feof( file ) && token[0] != stop );}/*====================================================================Read next token and skip comments enclosed in tokensskip[0], skip[1] (if skip is not NULL).Return 0 if EoF.====================================================================*/static int file_read_token( FILE *file, char *symbols, char *skip, char *token ){ while ( 1 ) { if ( !file_read_token_intern( file, symbols, token ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -