]> granicus.if.org Git - graphviz/commitdiff
Fix scanners to work correctly with preprocessor line directives,
authorerg <devnull@localhost>
Wed, 30 Jan 2008 20:52:35 +0000 (20:52 +0000)
committererg <devnull@localhost>
Wed, 30 Jan 2008 20:52:35 +0000 (20:52 +0000)
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.

lib/agraph/scan.l
lib/cgraph/scan.l
lib/graph/lexer.c

index 2e3f59480d4c4c13de16626daeddf7d8a0d38279..bd462f9fce26455cbd2d1dc1c27df1363aa08137 100644 (file)
@@ -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})
 <comment>"*"+[^*/\n]*  /* eat up '*'s not followed by '/'s */
 <comment>"*"+"/"       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 */
index aa13e945781060915f91cf1acfa15addfc733d4d..a9cf107e1ca30c65626ffc532011af591a286b70 100644 (file)
@@ -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})
 <comment>"*"+[^*/\n]*  /* eat up '*'s not followed by '/'s */
 <comment>"*"+"/"               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 */
index 2e3c76a097d470c1065f0c9d972422af605d0c06..f1ba84e14de5d52ec181a04fe572ec57359a9233 100644 (file)
@@ -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++;