From: erg Date: Wed, 30 Jan 2008 20:52:35 +0000 (+0000) Subject: Fix scanners to work correctly with preprocessor line directives, X-Git-Tag: LAST_LIBGRAPH~32^2~4800 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=656ef593aeeb0d7600cb44ae211418710750da3d;p=graphviz Fix scanners to work correctly with preprocessor line directives, storing file names if necessary. Fix the cgraph and agraph scanners to check for the correct edgeop depending on whether the graph is directed or not. --- diff --git a/lib/agraph/scan.l b/lib/agraph/scan.l index 2e3f59480..bd462f9fc 100644 --- a/lib/agraph/scan.l +++ b/lib/agraph/scan.l @@ -31,6 +31,7 @@ static int html_nest = 0; /* nesting level for html strings */ static char* InputFile; static Agdisc_t *Disc; static void *Ifile; +static int graphType; /* Reset line number */ void agreadline(int n) { line_num = n; } @@ -86,6 +87,45 @@ static void endstr_html(void) { yylval.str = (char*)agstrdup_html(Ag_G_global,Sbuf); } +static void +storeFileName (char* fname, int len) +{ + static int cnt; + static char* buf; + + if (len > cnt) { + if (cnt) buf = (char*)realloc (buf, len+1); + else buf = (char*)malloc (len+1); + cnt = len; + } + strcpy (buf, fname); + InputFile = buf; +} + +/* ppDirective: + * Process a possible preprocessor line directive. + * yytext = #.* + */ +static void ppDirective () +{ + int cnt, lineno; + char buf[2]; + int r = sscanf(yytext + 1, "%d %1[\"]%n", &lineno, buf, &cnt); + + if (r > 0) { /* got line number */ + line_num = lineno - 1; + if (r > 1) { /* saw quote */ + char* p = yytext + 1 + cnt; + char* e = p; + while (*e && (*e != '"')) e++; + if (e != p) { + *e = '\0'; + storeFileName (p, e-p); + } + } + } +} + /* chkNum: * The regexp for NUMBER allows a terminating letter. * This way we can catch a number immediately followed by a name @@ -128,15 +168,17 @@ ID ({NAME}|{NUMBER}) "*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ "*"+"/" BEGIN(INITIAL); "//".* /* ignore C++-style comments */ +^"#".* ppDirective (); "#".* /* ignore shell-like comments */ [\000-\040\177] /* ignore whitespace */ "node" return(T_node); /* see tokens in agcanonstr */ "edge" return(T_edge); -"graph" return(T_graph); -"digraph" return(T_digraph); +"graph" graphType = T_graph; return(T_graph); +"digraph" graphType = T_digraph; return(T_digraph); "strict" return(T_strict); "subgraph" return(T_subgraph); -"->"|"--" return(T_edgeop); +"->" if (graphType == T_digraph) return(T_edgeop); else return ('-'); +"--" if (graphType == T_graph) return(T_edgeop); else return ('-'); {NAME} { yylval.str = (char*)agstrdup(Ag_G_global,yytext); return(T_atom); } {NUMBER} { if (chkNum()) yyless(yyleng-1); yylval.str = (char*)agstrdup(Ag_G_global,yytext); return(T_atom); } ["] BEGIN(qstring); beginstr(); @@ -155,10 +197,10 @@ void yyerror(char *str) { char buf[BUFSIZ]; if (InputFile) - sprintf(buf,"%s:%d: %s in line %d near '%s'",InputFile, line_num, + sprintf(buf,"%s:%d: %s in line %d near '%s'\n",InputFile, line_num, str,line_num,yytext); else - sprintf(buf," %s in line %d near '%s'", str,line_num,yytext); + sprintf(buf," %s in line %d near '%s'\n", str,line_num,yytext); agerror(AGERROR_SYNTAX,buf); } /* must be here to see flex's macro defns */ diff --git a/lib/cgraph/scan.l b/lib/cgraph/scan.l index aa13e9457..a9cf107e1 100644 --- a/lib/cgraph/scan.l +++ b/lib/cgraph/scan.l @@ -27,6 +27,7 @@ static int html_nest = 0; /* nesting level for html strings */ static char* InputFile; static Agdisc_t *Disc; static void *Ifile; +static int graphType; /* Reset line number */ void agreadline(int n) { line_num = n; } @@ -82,6 +83,45 @@ static void endstr_html(void) { yylval.str = (char*)agstrdup_html(Ag_G_global,Sbuf); } +static void +storeFileName (char* fname, int len) +{ + static int cnt; + static char* buf; + + if (len > cnt) { + if (cnt) buf = (char*)realloc (buf, len+1); + else buf = (char*)malloc (len+1); + cnt = len; + } + strcpy (buf, fname); + InputFile = buf; +} + +/* ppDirective: + * Process a possible preprocessor line directive. + * yytext = #.* + */ +static void ppDirective () +{ + int cnt, lineno; + char buf[2]; + int r = sscanf(yytext + 1, "%d %1[\"]%n", &lineno, buf, &cnt); + + if (r > 0) { /* got line number */ + line_num = lineno - 1; + if (r > 1) { /* saw quote */ + char* p = yytext + 1 + cnt; + char* e = p; + while (*e && (*e != '"')) e++; + if (e != p) { + *e = '\0'; + storeFileName (p, e-p); + } + } + } +} + /* chkNum: * The regexp for NUMBER allows a terminating letter. * This way we can catch a number immediately followed by a name @@ -124,15 +164,17 @@ ID ({NAME}|{NUMBER}) "*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ "*"+"/" BEGIN(INITIAL); "//".* /* ignore C++-style comments */ +^"#".* ppDirective (); "#".* /* ignore shell-like comments */ [ \t\r] /* ignore whitespace */ "node" return(T_node); /* see tokens in agcanonstr */ "edge" return(T_edge); -"graph" return(T_graph); -"digraph" return(T_digraph); +"graph" graphType = T_graph; return(T_graph); +"digraph" graphType = T_digraph; return(T_digraph); "strict" return(T_strict); "subgraph" return(T_subgraph); -"->"|"--" return(T_edgeop); +"->" if (graphType == T_digraph) return(T_edgeop); else return('-'); +"--" if (graphType == T_graph) return(T_edgeop); else return('-'); {NAME} { yylval.str = (char*)agstrdup(Ag_G_global,yytext); return(T_atom); } {NUMBER} { if (chkNum()) yyless(yyleng-1); yylval.str = (char*)agstrdup(Ag_G_global,yytext); return(T_atom); } ["] BEGIN(qstring); beginstr(); @@ -151,10 +193,10 @@ void yyerror(char *str) { char buf[BUFSIZ]; if (InputFile) - sprintf(buf,"%s:%d: %s in line %d near '%s'",InputFile, line_num, + sprintf(buf,"%s:%d: %s in line %d near '%s'\n",InputFile, line_num, str,line_num,yytext); else - sprintf(buf," %s in line %d near '%s'", str,line_num,yytext); + sprintf(buf," %s in line %d near '%s'\n", str,line_num,yytext); agerr(AGWARN,buf); } /* must be here to see flex's macro defns */ diff --git a/lib/graph/lexer.c b/lib/graph/lexer.c index 2e3c76a09..f1ba84e14 100644 --- a/lib/graph/lexer.c +++ b/lib/graph/lexer.c @@ -37,6 +37,21 @@ int Line_number; static char *InputFile; static gets_f Lexer_gets; +static void +storeFileName (char* fname, int len) +{ + static int cnt; + static char* buf; + + if (len > cnt) { + if (cnt) buf = (char*)realloc (buf, len+1); + else buf = (char*)malloc (len+1); + cnt = len; + } + strcpy (buf, fname); + InputFile = buf; +} + /* Reset line number. * Argument n is indexed from 1, so we decrement it. */ @@ -247,10 +262,24 @@ static char *lex_gets(void) if (clp[len - 1] == '\n') { /* have physical line */ if ((clp[0] == '#') && (curlen == 0)) { /* comment line or cpp line sync */ - if (sscanf(clp + 1, "%d", &Line_number) == 0) - Line_number++; + int cnt; + char buf[2]; + int r = sscanf(clp + 1, "%d %1[\"]%n", &Line_number, buf, &cnt); + if (r <= 0) Line_number++; + else { /* got line number */ + Line_number--; + if (r > 1) { /* saw quote */ + char* p = clp + 1 + cnt; + char* e = p; + while (*e && (*e != '"')) e++; + if (e != p) { + *e = '\0'; + storeFileName (p, e-p); + } + } + } clp[0] = 0; - len = 1; /* this will make the while test below succeed */ + len = 1; /* this will make the while test below succeed */ continue; } Line_number++;