我使用flex创建了一个使用bison和scanner的解析器来解析windows中的setupapi.log文件。我尝试通过获取文件的一小部分来执行解析器并完成。它适用于大约20行的文件。但是当我在身体的最后一行添加两个单词时,它终止了那里,因为.exe已经停止工作而给出了错误。
我怎样摆脱这个。
我在我的bison文件中使用%union,只要遇到标识符,就会使用flexoc文件中的malloc分配内存。
我的flex文件是:
%{
#include <stdio.h>
#include "check.tab.h"
#include <string.h>
#include<malloc.h>
int yyline=1;
int i;
%}
identifier [_a-zA-Z\.0-9:=&\\{}()\'\-]+
time ([0-9]+\:[0-9]+\:[0-9]+\.[0-9]+)
%%
"/" {
return(SLASH_TOK);
}
"[" {
return(OPEN_TOK);
}
"]" {
return(CLOSE_TOK);
}
">>>" {
return (START_TOK);
}
"<<<" {
return (END_TOK);
}
"!!!" {
return(ERROR_TOK);
}
"!" {
return(WARN_TOK);
}
"...:" {
return(VEND_INFO);
}
"bak:" {
return(BAK_TOK);
}
"cci:" {
return(CCI_TOK);
}
//SOME MORE TOKENS ARE HERE....
"\n" {
yyline++;
}
{time} {
yylval.sval = malloc(strlen(yytext)+1);
printf("FRM LEXER TIME= %s %s\n",yytext,yylval.sval);
strncpy(yylval.sval,yytext,strlen(yytext)+1);
for(i=0;yylval.sval[i]!='\0';i++)
{
if(!(i<strlen(yytext)))
{
yylval.sval[i]='\0';
}
}
printf("FRM LEXER TIME= %s %s\n",yytext,yylval.sval);
return(TIME);
}
[a-zA-Z_0-9:\\]+(\.)+[\.a-zA-Z_0-9:\\]* {printf("REACHED EXTRA\n");return(DATA);}
[a-zA-Z]+(\:)+[\.a-zA-Z_0-9:\\]* {yylval.sval = malloc(strlen(yytext)+1);
strncpy(yylval.sval,yytext,strlen(yytext)+1);
printf("REACHED EXTRA\n");
for(i=0;yylval.sval[i]!='\0';i++)
{
if(!(i<strlen(yytext)))
{
yylval.sval[i]='\0';
}
}
return(DATA);
}
{identifier} {
yylval.sval = malloc(strlen(yytext)+1);
strncpy(yylval.sval,yytext,strlen(yytext)+1);
//printf("YYTEXT=%s %d\n",yytext,strlen(yytext));
for(i=0;yylval.sval[i]!='\0';i++)
{
if(!(i<strlen(yytext)))
{
yylval.sval[i]='\0';
}
}
printf("FRM LEXER ID = %s %s\n",yytext,yylval.sval);
return(IDENTIFIER);
}
%%
int yywrap(void)
{
return 1;
}
我的野牛文件是:
%{
#include <stdio.h>
#include <string.h>
extern int yyline;
extern char* yytext;
FILE *fp;
%}
%union
{
char *sval;
};
%token SLASH_TOK
%token OPEN_TOK
%token CLOSE_TOK
%token START_TOK
//ALL TOKENS ARE HERE
%type <sval> boot_data description statements word date section_title time_stamp section_body log_entry evt_catgry evt_time
%start session
%%
session : boot_data section
{
printf("SESSION\n");
fprintf(fp,"NO.OF LINES PARSED = %d\n",yyline);
}
;
boot_data : description statements description boot_time
{
printf("BOOT DATA\n");
fprintf(fp,"DESCRIPTION:%s\n",$1);
}
;
description : OPEN_TOK statements CLOSE_TOK
{
$$=$2;
printf("DESCRIPTION\n");
}
;
boot_time: OPEN_TOK statements date TIME CLOSE_TOK
{
printf("BOOT TIME\n");
fprintf(fp,"DATE:%s\n",$3);
fprintf(fp,"TIME:%s\n",$4);
}
;
date : IDENTIFIER SLASH_TOK IDENTIFIER SLASH_TOK IDENTIFIER
{
printf("DATE\n");
$$=$1;
strcat($$,"/");
strcat($$,$3);
strcat($$,"/");
strcat($$,$5);
}
;
statements : word
{
$$=$1;
printf("STAETEMENT 1\n");
}
|statements word
{
$$=$1;
strcat($$," ");
strcat($$,$2);
printf("statements 2\n");
}
;
word : IDENTIFIER
{
printf("WORD=%s %s\n",yytext, $$);
}
|TIME
{
printf("TIME=%s %s\n",yytext, $$);
fprintf(fp,"%s",$$);
}
|DATA
;
section : section_head section_body section_tail
{
printf("Compilation_start\n");
}
;
section_head : section_title time_stamp
{
printf("Compilation_start111\n");
}
;
section_title :START_TOK OPEN_TOK statements CLOSE_TOK
{
printf("Compilation_start222\n");
fprintf(fp,"%s\n",$3);
}
;
time_stamp :START_TOK statements date TIME
{
printf("Compilation_start444\n");
fprintf(fp,"%s Date: %s\n",$2,$3);
fprintf(fp,"%s Time: %s\n\n",$2,$4);
}
;
section_body :log_entry
{
printf("single entry\n");
}
|section_body log_entry
{
printf("MULTIPLE ENTRIES\n");
}
;
log_entry :entry_prefix evt_time evt_catgry statements
{
printf("no time stamp\n");
// fprintf(fp,"====%s====\n",$3);
}
;
section_tail :section_foot exit_status
{
printf("Compilation_start666\n");
}
;
section_foot: END_TOK statements date TIME
{
printf("Compilation_start777\n");
fprintf(fp,"\n\n%s Date: %s\n",$2,$3);
fprintf(fp,"%s Time: %s\n",$2,$4);
}
;
exit_status : END_TOK OPEN_TOK statements CLOSE_TOK
{
printf("Compilation_start888\n");
fprintf(fp,"\n%s\n",$3);
}
;
%%
yyerror(char *str)
{
printf("Parse error: %s at line %d ,",str,yyline);
yywhere();
}
yywhere()
{
int colon=0;
int i;
if(yytext)
{
for(i=0;i<50;i++) if(!yytext[i] || yytext[i] == '\n') break;
if(i)
{
if(!colon)
{
printf(" near: \"%s\"\n", yytext);
colon = 1;
}
}
printf("\n");
}
}
int main(void)
{
int i =remove("output.txt");
fp=fopen("output.txt","a+");
yyparse();
fclose(fp);
}
答案 0 :(得分:2)
(对Windows也应该有效):
strcat()函数将src字符串追加到dest字符串, 在dest的末尾覆盖空字节(&#39; \ 0&#39;)然后 添加一个终止空字节。字符串 可能不会重叠,并且dest字符串必须有足够的空间用于结果。
现在你正在做:
statements : word
{
$$=$1;
printf("STAETEMENT 1\n");
}
|statements word
{
$$=$1;
strcat($$," ");
strcat($$,$2);
printf("statements 2\n");
}
;
因此,如果我假设您输入了两个单词,则会发生以下情况:
在第一个单词之后,语句指向此单词,因为您执行$$ = $1
。
然后你的扫描仪会读取下一个单词,然后将空白和下一个单词连接到第一个单词。但是你没有采取有关可用内存的预防措施。
你用C编程,这意味着你必须自己做所有事情。
您可以将第二个操作更改为:
statements : statements word
{
int lgth1 = strlen($$);
int lgth2 = strlen($2);
/* instead of malloc you could also realloc */
char *tmp = (char *) malloc((lgth1 + lgth2 + 1 + 1) * sizeof(char));
/* no error handling for clarity */
sprintf(tmp, "%s %s", $$, $2); /* alternative: strcpy(); strcat(); strcat(); */
free($$); free($2); /* freeing the memory not used any more */
$$ = tmp;
}
这当然不是防弹代码,你也必须修理其他地方。 希望这会有所帮助。