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.
static char* InputFile;
static Agdisc_t *Disc;
static void *Ifile;
+static int graphType;
/* Reset line number */
void agreadline(int n) { line_num = n; }
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
<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();
{
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 */
static char* InputFile;
static Agdisc_t *Disc;
static void *Ifile;
+static int graphType;
/* Reset line number */
void agreadline(int n) { line_num = n; }
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
<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();
{
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 */
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.
*/
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++;