[PATCH] kconfig: improve error handling in the parser
Add a few error tokens to the parser to catch common errors and print more descriptive error messages. Signed-off-by: Roman Zippel <zippel@linux-m68k.org> Cc: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
3370f9f0d9
Коммит
a02f0570ae
|
@ -323,7 +323,7 @@ void zconffree (void * );
|
|||
|
||||
/* Begin user sect3 */
|
||||
|
||||
#define zconfwrap(n) 1
|
||||
#define zconfwrap() 1
|
||||
#define YY_SKIP_YYWRAP
|
||||
|
||||
typedef unsigned char YY_CHAR;
|
||||
|
@ -686,10 +686,10 @@ struct yy_trans_info
|
|||
static yyconst flex_int16_t yy_accept[61] =
|
||||
{ 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
34, 5, 4, 3, 2, 7, 8, 6, 32, 29,
|
||||
34, 5, 4, 2, 3, 7, 8, 6, 32, 29,
|
||||
31, 24, 28, 27, 26, 22, 17, 13, 16, 20,
|
||||
22, 11, 12, 19, 19, 14, 22, 22, 4, 3,
|
||||
2, 2, 1, 6, 32, 29, 31, 30, 24, 23,
|
||||
22, 11, 12, 19, 19, 14, 22, 22, 4, 2,
|
||||
3, 3, 1, 6, 32, 29, 31, 30, 24, 23,
|
||||
26, 25, 15, 20, 9, 19, 19, 21, 10, 18
|
||||
} ;
|
||||
|
||||
|
@ -753,6 +753,11 @@ char *zconftext;
|
|||
|
||||
#define START_STRSIZE 16
|
||||
|
||||
static struct {
|
||||
struct file *file;
|
||||
int lineno;
|
||||
} current_pos;
|
||||
|
||||
static char *text;
|
||||
static int text_size, text_asize;
|
||||
|
||||
|
@ -766,7 +771,7 @@ struct buffer *current_buf;
|
|||
static int last_ts, first_ts;
|
||||
|
||||
static void zconf_endhelp(void);
|
||||
static struct buffer *zconf_endfile(void);
|
||||
static void zconf_endfile(void);
|
||||
|
||||
void new_string(void)
|
||||
{
|
||||
|
@ -993,17 +998,17 @@ do_action: /* This label is used only to access EOF actions. */
|
|||
{ /* beginning of action switch */
|
||||
case 1:
|
||||
/* rule 1 can match eol */
|
||||
YY_RULE_SETUP
|
||||
current_file->lineno++;
|
||||
YY_BREAK
|
||||
case 2:
|
||||
/* rule 2 can match eol */
|
||||
YY_RULE_SETUP
|
||||
|
||||
{
|
||||
current_file->lineno++;
|
||||
return T_EOL;
|
||||
}
|
||||
YY_BREAK
|
||||
case 3:
|
||||
/* rule 3 can match eol */
|
||||
YY_RULE_SETUP
|
||||
current_file->lineno++; return T_EOL;
|
||||
|
||||
YY_BREAK
|
||||
case 4:
|
||||
YY_RULE_SETUP
|
||||
|
@ -1023,8 +1028,10 @@ case 6:
|
|||
YY_RULE_SETUP
|
||||
{
|
||||
struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng);
|
||||
BEGIN(PARAM);
|
||||
current_pos.file = current_file;
|
||||
current_pos.lineno = current_file->lineno;
|
||||
if (id && id->flags & TF_COMMAND) {
|
||||
BEGIN(PARAM);
|
||||
zconflval.id = id;
|
||||
return id->token;
|
||||
}
|
||||
|
@ -1040,7 +1047,11 @@ YY_RULE_SETUP
|
|||
case 8:
|
||||
/* rule 8 can match eol */
|
||||
YY_RULE_SETUP
|
||||
current_file->lineno++; BEGIN(INITIAL);
|
||||
{
|
||||
BEGIN(INITIAL);
|
||||
current_file->lineno++;
|
||||
return T_EOL;
|
||||
}
|
||||
YY_BREAK
|
||||
|
||||
case 9:
|
||||
|
@ -1246,9 +1257,9 @@ case YY_STATE_EOF(HELP):
|
|||
case YY_STATE_EOF(INITIAL):
|
||||
case YY_STATE_EOF(COMMAND):
|
||||
{
|
||||
if (current_buf) {
|
||||
if (current_file) {
|
||||
zconf_endfile();
|
||||
return T_EOF;
|
||||
return T_EOL;
|
||||
}
|
||||
fclose(zconfin);
|
||||
yyterminate();
|
||||
|
@ -1958,7 +1969,7 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size )
|
|||
|
||||
/** Setup the input buffer state to scan a string. The next call to zconflex() will
|
||||
* scan from a @e copy of @a str.
|
||||
* @param str a NUL-terminated string to scan
|
||||
* @param yy_str a NUL-terminated string to scan
|
||||
*
|
||||
* @return the newly allocated buffer state object.
|
||||
* @note If you want to scan bytes that may contain NUL values, then use
|
||||
|
@ -2276,7 +2287,7 @@ void zconf_nextfile(const char *name)
|
|||
current_file = file;
|
||||
}
|
||||
|
||||
static struct buffer *zconf_endfile(void)
|
||||
static void zconf_endfile(void)
|
||||
{
|
||||
struct buffer *parent;
|
||||
|
||||
|
@ -2292,23 +2303,15 @@ static struct buffer *zconf_endfile(void)
|
|||
}
|
||||
free(current_buf);
|
||||
current_buf = parent;
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
int zconf_lineno(void)
|
||||
{
|
||||
if (current_buf)
|
||||
return current_file->lineno - 1;
|
||||
else
|
||||
return 0;
|
||||
return current_pos.lineno;
|
||||
}
|
||||
|
||||
char *zconf_curname(void)
|
||||
{
|
||||
if (current_buf)
|
||||
return current_file->name;
|
||||
else
|
||||
return "<none>";
|
||||
return current_pos.file ? current_pos.file->name : "<none>";
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ void kconfig_load(void);
|
|||
|
||||
/* menu.c */
|
||||
void menu_init(void);
|
||||
void menu_add_menu(void);
|
||||
struct menu *menu_add_menu(void);
|
||||
void menu_end_menu(void);
|
||||
void menu_add_entry(struct symbol *sym);
|
||||
void menu_end_entry(void);
|
||||
|
|
|
@ -61,10 +61,11 @@ void menu_end_entry(void)
|
|||
{
|
||||
}
|
||||
|
||||
void menu_add_menu(void)
|
||||
struct menu *menu_add_menu(void)
|
||||
{
|
||||
current_menu = current_entry;
|
||||
menu_end_entry();
|
||||
last_entry_ptr = ¤t_entry->list;
|
||||
return current_menu = current_entry;
|
||||
}
|
||||
|
||||
void menu_end_menu(void)
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
|
||||
#define START_STRSIZE 16
|
||||
|
||||
static struct {
|
||||
struct file *file;
|
||||
int lineno;
|
||||
} current_pos;
|
||||
|
||||
static char *text;
|
||||
static int text_size, text_asize;
|
||||
|
||||
|
@ -31,7 +36,7 @@ struct buffer *current_buf;
|
|||
static int last_ts, first_ts;
|
||||
|
||||
static void zconf_endhelp(void);
|
||||
static struct buffer *zconf_endfile(void);
|
||||
static void zconf_endfile(void);
|
||||
|
||||
void new_string(void)
|
||||
{
|
||||
|
@ -70,10 +75,13 @@ n [A-Za-z0-9_]
|
|||
int str = 0;
|
||||
int ts, i;
|
||||
|
||||
[ \t]*#.*\n current_file->lineno++;
|
||||
[ \t]*#.*\n |
|
||||
[ \t]*\n {
|
||||
current_file->lineno++;
|
||||
return T_EOL;
|
||||
}
|
||||
[ \t]*#.*
|
||||
|
||||
[ \t]*\n current_file->lineno++; return T_EOL;
|
||||
|
||||
[ \t]+ {
|
||||
BEGIN(COMMAND);
|
||||
|
@ -88,8 +96,10 @@ n [A-Za-z0-9_]
|
|||
<COMMAND>{
|
||||
{n}+ {
|
||||
struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
|
||||
BEGIN(PARAM);
|
||||
current_pos.file = current_file;
|
||||
current_pos.lineno = current_file->lineno;
|
||||
if (id && id->flags & TF_COMMAND) {
|
||||
BEGIN(PARAM);
|
||||
zconflval.id = id;
|
||||
return id->token;
|
||||
}
|
||||
|
@ -98,7 +108,11 @@ n [A-Za-z0-9_]
|
|||
return T_WORD;
|
||||
}
|
||||
.
|
||||
\n current_file->lineno++; BEGIN(INITIAL);
|
||||
\n {
|
||||
BEGIN(INITIAL);
|
||||
current_file->lineno++;
|
||||
return T_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
<PARAM>{
|
||||
|
@ -214,9 +228,9 @@ n [A-Za-z0-9_]
|
|||
}
|
||||
|
||||
<<EOF>> {
|
||||
if (current_buf) {
|
||||
if (current_file) {
|
||||
zconf_endfile();
|
||||
return T_EOF;
|
||||
return T_EOL;
|
||||
}
|
||||
fclose(yyin);
|
||||
yyterminate();
|
||||
|
@ -307,7 +321,7 @@ void zconf_nextfile(const char *name)
|
|||
current_file = file;
|
||||
}
|
||||
|
||||
static struct buffer *zconf_endfile(void)
|
||||
static void zconf_endfile(void)
|
||||
{
|
||||
struct buffer *parent;
|
||||
|
||||
|
@ -323,22 +337,14 @@ static struct buffer *zconf_endfile(void)
|
|||
}
|
||||
free(current_buf);
|
||||
current_buf = parent;
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
int zconf_lineno(void)
|
||||
{
|
||||
if (current_buf)
|
||||
return current_file->lineno - 1;
|
||||
else
|
||||
return 0;
|
||||
return current_pos.lineno;
|
||||
}
|
||||
|
||||
char *zconf_curname(void)
|
||||
{
|
||||
if (current_buf)
|
||||
return current_file->name;
|
||||
else
|
||||
return "<none>";
|
||||
return current_pos.file ? current_pos.file->name : "<none>";
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -25,21 +25,25 @@ int cdebug = PRINTD;
|
|||
|
||||
extern int zconflex(void);
|
||||
static void zconfprint(const char *err, ...);
|
||||
static void zconf_error(const char *err, ...);
|
||||
static void zconferror(const char *err);
|
||||
static bool zconf_endtoken(int token, int starttoken, int endtoken);
|
||||
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken);
|
||||
|
||||
struct symbol *symbol_hash[257];
|
||||
|
||||
static struct menu *current_menu, *current_entry;
|
||||
|
||||
#define YYDEBUG 0
|
||||
#if YYDEBUG
|
||||
#define YYERROR_VERBOSE
|
||||
#endif
|
||||
%}
|
||||
%expect 40
|
||||
%expect 26
|
||||
|
||||
%union
|
||||
{
|
||||
int token;
|
||||
char *string;
|
||||
struct file *file;
|
||||
struct symbol *symbol;
|
||||
struct expr *expr;
|
||||
struct menu *menu;
|
||||
|
@ -74,7 +78,6 @@ static struct menu *current_menu, *current_entry;
|
|||
%token T_CLOSE_PAREN
|
||||
%token T_OPEN_PAREN
|
||||
%token T_EOL
|
||||
%token T_EOF
|
||||
|
||||
%left T_OR
|
||||
%left T_AND
|
||||
|
@ -82,34 +85,54 @@ static struct menu *current_menu, *current_entry;
|
|||
%nonassoc T_NOT
|
||||
|
||||
%type <string> prompt
|
||||
%type <string> source
|
||||
%type <symbol> symbol
|
||||
%type <expr> expr
|
||||
%type <expr> if_expr
|
||||
%type <token> end
|
||||
%type <id> end
|
||||
%type <id> option_name
|
||||
%type <menu> if_entry menu_entry choice_entry
|
||||
|
||||
%destructor {
|
||||
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
|
||||
$$->file->name, $$->lineno);
|
||||
if (current_menu == $$)
|
||||
menu_end_menu();
|
||||
} if_entry menu_entry choice_entry
|
||||
|
||||
%%
|
||||
input: /* empty */
|
||||
| input block
|
||||
input: stmt_list;
|
||||
|
||||
stmt_list:
|
||||
/* empty */
|
||||
| stmt_list common_stmt
|
||||
| stmt_list choice_stmt
|
||||
| stmt_list menu_stmt
|
||||
| stmt_list T_MAINMENU prompt nl
|
||||
| stmt_list end { zconf_error("unexpected end statement"); }
|
||||
| stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
|
||||
| stmt_list option_name error T_EOL
|
||||
{
|
||||
zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name);
|
||||
}
|
||||
| stmt_list error T_EOL { zconf_error("invalid statement"); }
|
||||
;
|
||||
|
||||
block: common_block
|
||||
| choice_stmt
|
||||
| menu_stmt
|
||||
| T_MAINMENU prompt nl_or_eof
|
||||
| T_ENDMENU { zconfprint("unexpected 'endmenu' statement"); }
|
||||
| T_ENDIF { zconfprint("unexpected 'endif' statement"); }
|
||||
| T_ENDCHOICE { zconfprint("unexpected 'endchoice' statement"); }
|
||||
| error nl_or_eof { zconfprint("syntax error"); yyerrok; }
|
||||
option_name:
|
||||
T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT
|
||||
;
|
||||
|
||||
common_block:
|
||||
if_stmt
|
||||
common_stmt:
|
||||
T_EOL
|
||||
| if_stmt
|
||||
| comment_stmt
|
||||
| config_stmt
|
||||
| menuconfig_stmt
|
||||
| source_stmt
|
||||
| nl_or_eof
|
||||
;
|
||||
|
||||
option_error:
|
||||
T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
|
||||
| error T_EOL { zconf_error("invalid option"); }
|
||||
;
|
||||
|
||||
|
||||
|
@ -152,6 +175,7 @@ config_option_list:
|
|||
| config_option_list config_option
|
||||
| config_option_list depends
|
||||
| config_option_list help
|
||||
| config_option_list option_error
|
||||
| config_option_list T_EOL
|
||||
;
|
||||
|
||||
|
@ -204,8 +228,7 @@ choice: T_CHOICE T_EOL
|
|||
|
||||
choice_entry: choice choice_option_list
|
||||
{
|
||||
menu_end_entry();
|
||||
menu_add_menu();
|
||||
$$ = menu_add_menu();
|
||||
};
|
||||
|
||||
choice_end: end
|
||||
|
@ -216,13 +239,8 @@ choice_end: end
|
|||
}
|
||||
};
|
||||
|
||||
choice_stmt:
|
||||
choice_entry choice_block choice_end
|
||||
| choice_entry choice_block
|
||||
{
|
||||
printf("%s:%d: missing 'endchoice' for this 'choice' statement\n", current_menu->file->name, current_menu->lineno);
|
||||
zconfnerrs++;
|
||||
};
|
||||
choice_stmt: choice_entry choice_block choice_end
|
||||
;
|
||||
|
||||
choice_option_list:
|
||||
/* empty */
|
||||
|
@ -230,6 +248,7 @@ choice_option_list:
|
|||
| choice_option_list depends
|
||||
| choice_option_list help
|
||||
| choice_option_list T_EOL
|
||||
| choice_option_list option_error
|
||||
;
|
||||
|
||||
choice_option: T_PROMPT prompt if_expr T_EOL
|
||||
|
@ -267,18 +286,17 @@ choice_option: T_DEFAULT T_WORD if_expr T_EOL
|
|||
|
||||
choice_block:
|
||||
/* empty */
|
||||
| choice_block common_block
|
||||
| choice_block common_stmt
|
||||
;
|
||||
|
||||
/* if entry */
|
||||
|
||||
if: T_IF expr T_EOL
|
||||
if_entry: T_IF expr nl
|
||||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
|
||||
menu_add_entry(NULL);
|
||||
menu_add_dep($2);
|
||||
menu_end_entry();
|
||||
menu_add_menu();
|
||||
$$ = menu_add_menu();
|
||||
};
|
||||
|
||||
if_end: end
|
||||
|
@ -289,17 +307,12 @@ if_end: end
|
|||
}
|
||||
};
|
||||
|
||||
if_stmt:
|
||||
if if_block if_end
|
||||
| if if_block
|
||||
{
|
||||
printf("%s:%d: missing 'endif' for this 'if' statement\n", current_menu->file->name, current_menu->lineno);
|
||||
zconfnerrs++;
|
||||
};
|
||||
if_stmt: if_entry if_block if_end
|
||||
;
|
||||
|
||||
if_block:
|
||||
/* empty */
|
||||
| if_block common_block
|
||||
| if_block common_stmt
|
||||
| if_block menu_stmt
|
||||
| if_block choice_stmt
|
||||
;
|
||||
|
@ -315,8 +328,7 @@ menu: T_MENU prompt T_EOL
|
|||
|
||||
menu_entry: menu depends_list
|
||||
{
|
||||
menu_end_entry();
|
||||
menu_add_menu();
|
||||
$$ = menu_add_menu();
|
||||
};
|
||||
|
||||
menu_end: end
|
||||
|
@ -327,31 +339,20 @@ menu_end: end
|
|||
}
|
||||
};
|
||||
|
||||
menu_stmt:
|
||||
menu_entry menu_block menu_end
|
||||
| menu_entry menu_block
|
||||
{
|
||||
printf("%s:%d: missing 'endmenu' for this 'menu' statement\n", current_menu->file->name, current_menu->lineno);
|
||||
zconfnerrs++;
|
||||
};
|
||||
menu_stmt: menu_entry menu_block menu_end
|
||||
;
|
||||
|
||||
menu_block:
|
||||
/* empty */
|
||||
| menu_block common_block
|
||||
| menu_block common_stmt
|
||||
| menu_block menu_stmt
|
||||
| menu_block choice_stmt
|
||||
| menu_block error T_EOL { zconfprint("invalid menu option"); yyerrok; }
|
||||
;
|
||||
|
||||
source: T_SOURCE prompt T_EOL
|
||||
source_stmt: T_SOURCE prompt T_EOL
|
||||
{
|
||||
$$ = $2;
|
||||
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
|
||||
};
|
||||
|
||||
source_stmt: source
|
||||
{
|
||||
zconf_nextfile($1);
|
||||
zconf_nextfile($2);
|
||||
};
|
||||
|
||||
/* comment entry */
|
||||
|
@ -383,9 +384,11 @@ help: help_start T_HELPTEXT
|
|||
|
||||
/* depends option */
|
||||
|
||||
depends_list: /* empty */
|
||||
| depends_list depends
|
||||
| depends_list T_EOL
|
||||
depends_list:
|
||||
/* empty */
|
||||
| depends_list depends
|
||||
| depends_list T_EOL
|
||||
| depends_list option_error
|
||||
;
|
||||
|
||||
depends: T_DEPENDS T_ON expr T_EOL
|
||||
|
@ -417,13 +420,15 @@ prompt: T_WORD
|
|||
| T_WORD_QUOTE
|
||||
;
|
||||
|
||||
end: T_ENDMENU nl_or_eof { $$ = T_ENDMENU; }
|
||||
| T_ENDCHOICE nl_or_eof { $$ = T_ENDCHOICE; }
|
||||
| T_ENDIF nl_or_eof { $$ = T_ENDIF; }
|
||||
end: T_ENDMENU T_EOL { $$ = $1; }
|
||||
| T_ENDCHOICE T_EOL { $$ = $1; }
|
||||
| T_ENDIF T_EOL { $$ = $1; }
|
||||
;
|
||||
|
||||
nl_or_eof:
|
||||
T_EOL | T_EOF;
|
||||
nl:
|
||||
T_EOL
|
||||
| nl T_EOL
|
||||
;
|
||||
|
||||
if_expr: /* empty */ { $$ = NULL; }
|
||||
| T_IF expr { $$ = $2; }
|
||||
|
@ -456,7 +461,10 @@ void conf_parse(const char *name)
|
|||
modules_sym = sym_lookup("MODULES", 0);
|
||||
rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
|
||||
|
||||
//zconfdebug = 1;
|
||||
#if YYDEBUG
|
||||
if (getenv("ZCONF_DEBUG"))
|
||||
zconfdebug = 1;
|
||||
#endif
|
||||
zconfparse();
|
||||
if (zconfnerrs)
|
||||
exit(1);
|
||||
|
@ -477,20 +485,25 @@ const char *zconf_tokenname(int token)
|
|||
case T_ENDCHOICE: return "endchoice";
|
||||
case T_IF: return "if";
|
||||
case T_ENDIF: return "endif";
|
||||
case T_DEPENDS: return "depends";
|
||||
}
|
||||
return "<token>";
|
||||
}
|
||||
|
||||
static bool zconf_endtoken(int token, int starttoken, int endtoken)
|
||||
static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken)
|
||||
{
|
||||
if (token != endtoken) {
|
||||
zconfprint("unexpected '%s' within %s block", zconf_tokenname(token), zconf_tokenname(starttoken));
|
||||
if (id->token != endtoken) {
|
||||
zconf_error("unexpected '%s' within %s block",
|
||||
kconf_id_strings + id->name, zconf_tokenname(starttoken));
|
||||
zconfnerrs++;
|
||||
return false;
|
||||
}
|
||||
if (current_menu->file != current_file) {
|
||||
zconfprint("'%s' in different file than '%s'", zconf_tokenname(token), zconf_tokenname(starttoken));
|
||||
zconfprint("location of the '%s'", zconf_tokenname(starttoken));
|
||||
zconf_error("'%s' in different file than '%s'",
|
||||
kconf_id_strings + id->name, zconf_tokenname(starttoken));
|
||||
fprintf(stderr, "%s:%d: location of the '%s'\n",
|
||||
current_menu->file->name, current_menu->lineno,
|
||||
zconf_tokenname(starttoken));
|
||||
zconfnerrs++;
|
||||
return false;
|
||||
}
|
||||
|
@ -501,7 +514,19 @@ static void zconfprint(const char *err, ...)
|
|||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno() + 1);
|
||||
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
|
||||
va_start(ap, err);
|
||||
vfprintf(stderr, err, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void zconf_error(const char *err, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
zconfnerrs++;
|
||||
fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
|
||||
va_start(ap, err);
|
||||
vfprintf(stderr, err, ap);
|
||||
va_end(ap);
|
||||
|
@ -510,7 +535,9 @@ static void zconfprint(const char *err, ...)
|
|||
|
||||
static void zconferror(const char *err)
|
||||
{
|
||||
#if YYDEBUG
|
||||
fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_quoted_string(FILE *out, const char *str)
|
||||
|
|
Загрузка…
Ссылка в новой задаче