From: Matthew Fernandez Date: Tue, 25 Aug 2020 01:31:26 +0000 (-0700) Subject: use Bison's api.prefix and Flex's prefix instead of name mangling in cgraph X-Git-Tag: 2.46.0~20^2^2~99^2~4 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc2cb52756f545d6863d6fd801fa23762a81704c;p=graphviz use Bison's api.prefix and Flex's prefix instead of name mangling in cgraph Related to !1523. Bison's api.prefix was introduced in 2.6, but switched to using this bracing syntax in 3.0. Quoting from the Bison 3.0 release notes: ** Types of values for %define variables Bison used to make no difference between '%define foo bar' and '%define foo "bar"'. The former is now called a 'keyword value', and the latter a 'string value'. A third kind was added: 'code values', such as '%define foo {bar}'. Keyword variables are used for fixed value sets, e.g., %define lr.type lalr Code variables are used for value in the target language, e.g., %define api.value.type {struct semantic_type} String variables are used remaining cases, e.g. file names. The Flex option prefix was introduced in Flex 2.4.1 (November 1993) and then stabilized around 2.5.2 (April 1995). It provides similar functionality: ‘-PPREFIX, --prefix=PREFIX, %option prefix="PREFIX"’ changes the default ‘yy’ prefix used by flex for all globally-visible variable and function names to instead be ‘PREFIX’. For example, ‘--prefix=foo’ changes the name of yytext to footext. It also changes the name of the default output file from lex.yy.c to lex.foo.c. It would have been nicer to split the lexer and parser changes into separate commits. However, the MSBuild build does no name mangling here (see lib/cgraph/cgraph.vcxproj), so changing one of these immediately broke the other one there. On the positive side, this commit has the effect of realigning some MSBuild outputs with the Autotools build, as the cgraph lexer and parser are now aag-prefixed there as well. --- diff --git a/lib/cgraph/Makefile.am b/lib/cgraph/Makefile.am index 2774c54e4..a524ebd4d 100644 --- a/lib/cgraph/Makefile.am +++ b/lib/cgraph/Makefile.am @@ -30,8 +30,8 @@ scan.o scan.lo: scan.c grammar.h scan.c: $(top_srcdir)/lib/cgraph/scan.l @LEX@ -i $(top_srcdir)/lib/cgraph/scan.l - @SED@ "s/yy/aag/g" < @LEX_OUTPUT_ROOT@.c > scan.c - rm @LEX_OUTPUT_ROOT@.c + @SED@ "s/yy/aag/g" < lex.aag.c > scan.c + rm lex.aag.c grammar.c: y.tab.c @SED@ "s/yy/aag/g" < y.tab.c > grammar.c diff --git a/lib/cgraph/grammar.y b/lib/cgraph/grammar.y index 737b147fe..a743419bc 100644 --- a/lib/cgraph/grammar.y +++ b/lib/cgraph/grammar.y @@ -13,11 +13,17 @@ %require "3.0" + /* By default, Bison emits a parser using symbols prefixed with "yy". Graphviz + * contains multiple Bison-generated parsers, so we alter this prefix to avoid + * symbol clashes. + */ +%define api.prefix {aag} + %{ #include /* SAFE */ #include /* SAFE */ -extern void yyerror(char *); /* gets mapped to aagerror, see below */ +extern void aagerror(char *); #ifdef _WIN32 #define gettxt(a,b) (b) @@ -593,15 +599,15 @@ static void freestack() } } -extern FILE *yyin; +extern FILE *aagin; Agraph_t *agconcat(Agraph_t *g, void *chan, Agdisc_t *disc) { - yyin = chan; + aagin = chan; G = g; Ag_G_global = NILgraph; Disc = (disc? disc : &AgDefaultDisc); aglexinit(Disc, chan); - yyparse(); + aagparse(); if (Ag_G_global == NILgraph) aglexbad(); return Ag_G_global; } diff --git a/lib/cgraph/scan.l b/lib/cgraph/scan.l index 5961ee2d3..a80fe683d 100644 --- a/lib/cgraph/scan.l +++ b/lib/cgraph/scan.l @@ -13,6 +13,13 @@ /* requires flex (i.e. not lex) */ + + /* By default, Flex emits a lexer using symbols prefixed with "yy". Graphviz + * contains multiple Flex-generated lexers, so we alter this prefix to avoid + * symbol clashes. + */ +%option prefix="aag" + %{ #include #include @@ -75,12 +82,12 @@ static void addstr(char *src) { } static void endstr(void) { - yylval.str = (char*)agstrdup(Ag_G_global,Sbuf); + aaglval.str = (char*)agstrdup(Ag_G_global,Sbuf); *Sbuf = 0; } static void endstr_html(void) { - yylval.str = (char*)agstrdup_html(Ag_G_global,Sbuf); + aaglval.str = (char*)agstrdup_html(Ag_G_global,Sbuf); *Sbuf = 0; } @@ -101,13 +108,13 @@ storeFileName (char* fname, int len) /* ppDirective: * Process a possible preprocessor line directive. - * yytext = #.* + * aagtext = #.* */ static void ppDirective (void) { int r, cnt, lineno; char buf[2]; - char* s = yytext + 1; /* skip initial # */ + char* s = aagtext + 1; /* skip initial # */ if (strncmp(s, "line", 4) == 0) s += 4; r = sscanf(s, "%d %1[\"]%n", &lineno, buf, &cnt); @@ -132,8 +139,8 @@ static void ppDirective (void) static int twoDots(void) { int i; - for (i = yyleng-2; i >= 0; i--) { - if (((unsigned char)yytext[i]) == '.') + for (i = aagleng-2; i >= 0; i--) { + if (((unsigned char)aagtext[i]) == '.') return 1; } return 0; @@ -145,7 +152,7 @@ static int twoDots(void) * or something like 123.456.78, and report this to the user. */ static int chkNum(void) { - unsigned char c = (unsigned char)yytext[yyleng-1]; /* last character */ + unsigned char c = (unsigned char)aagtext[aagleng-1]; /* last character */ if ((!isdigit(c) && (c != '.')) || ((c == '.') && twoDots())) { /* c is letter */ char* fname; @@ -155,7 +162,7 @@ static int chkNum(void) { fname = "input"; agerr(AGWARN, "syntax ambiguity - badly delimited number '%s' in line %d of " - "%s splits into two tokens\n", yytext, line_num, fname); + "%s splits into two tokens\n", aagtext, line_num, fname); return 1; } @@ -208,23 +215,23 @@ ID ({NAME}|{NUMBER}) "subgraph" return(T_subgraph); "->" 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); } +{NAME} { aaglval.str = (char*)agstrdup(Ag_G_global,aagtext); return(T_atom); } +{NUMBER} { if (chkNum()) yyless(aagleng-1); aaglval.str = (char*)agstrdup(Ag_G_global,aagtext); return(T_atom); } ["] BEGIN(qstring); beginstr(); ["] BEGIN(INITIAL); endstr(); return (T_qatom); [\\]["] addstr ("\""); [\\][\\] addstr ("\\\\"); [\\][\n] line_num++; /* ignore escaped newlines */ -([^"\\]*|[\\]) addstr(yytext); +([^"\\]*|[\\]) addstr(aagtext); [<] BEGIN(hstring); html_nest = 1; beginstr(); -[>] html_nest--; if (html_nest) addstr(yytext); else {BEGIN(INITIAL); endstr_html(); return (T_qatom);} -[<] html_nest++; addstr(yytext); -[\n] addstr(yytext); line_num++; /* add newlines */ -([^><\n]*) addstr(yytext); -. return (yytext[0]); +[>] html_nest--; if (html_nest) addstr(aagtext); else {BEGIN(INITIAL); endstr_html(); return (T_qatom);} +[<] html_nest++; addstr(aagtext); +[\n] addstr(aagtext); line_num++; /* add newlines */ +([^><\n]*) addstr(aagtext); +. return (aagtext[0]); %% -void yyerror(char *str) +void aagerror(char *str) { unsigned char xbuf[BUFSIZ]; char buf[BUFSIZ]; @@ -238,9 +245,9 @@ void yyerror(char *str) agxbput (&xb, str); sprintf(buf," in line %d", line_num); agxbput (&xb, buf); - if (*yytext) { + if (*aagtext) { agxbput(&xb," near '"); - agxbput (&xb, yytext); + agxbput (&xb, aagtext); agxbputc (&xb, '\''); } else switch (YYSTATE) { @@ -285,7 +292,7 @@ void aglexbad() { YY_FLUSH_BUFFER; } # define YY_CALL_ONLY_ARG void #endif -int yywrap(YY_CALL_ONLY_ARG) +int aagwrap(YY_CALL_ONLY_ARG) { return 1; }