From 0d97917cd2c1ff5d76215c80910c9d823c3e62c7 Mon Sep 17 00:00:00 2001 From: Andreas Abel Date: Thu, 26 Dec 2019 11:02:13 +0100 Subject: [PATCH] Make sure ocamlyacc can handle 255 entry points (#9210) The previous promised limit of ocamlyacc was 256 entry points, but on some platforms (x86 at least) the actual limit was 127 due to representation of bucket->entry as char. Switching to unsigned char extends the limit to 255. I introduced a constant MAX_ENTRY_POINT as a synonym of MAXCHAR to handle checks against the limit consistently over the different modules of ocamlyacc. Extensions beyond 255 entry points would require a bit more work (which looks unrewarding) since entry points are currently identified by a single byte at the beginning of the input stream. Fixes: #9207 --- Changes | 4 ++++ yacc/defs.h | 8 +++++++- yacc/error.c | 4 ++-- yacc/reader.c | 6 +++--- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Changes b/Changes index e05ea889c..0b7e742da 100644 --- a/Changes +++ b/Changes @@ -73,6 +73,10 @@ Working version to the toplevel. (Gabriel Scherer, review by Armaël Guéneau) +* #9207: fix ocamlyacc to work correctly with up to 255 entry points + to the grammar. + (Andreas Abel, review by Xavier Leroy) + ### Manual and documentation: - #9141: beginning of the ocamltest reference manual diff --git a/yacc/defs.h b/yacc/defs.h index 91aadc3e6..1fd3dc680 100644 --- a/yacc/defs.h +++ b/yacc/defs.h @@ -145,10 +145,16 @@ struct bucket short prec; char class; char assoc; - char entry; + unsigned char entry; /* 1..MAX_ENTRY_POINT (0 for unassigned) */ char true_token; }; +/* MAX_ENTRY_POINT is the maximal number of entry points into the grammar. */ +/* Entry points are identified by a non-zero byte in the input stream, */ +/* so there are at most 255 entry points. */ + +#define MAX_ENTRY_POINT MAXCHAR + /* TABLE_SIZE is the number of entries in the symbol table. */ /* TABLE_SIZE must be a power of two. */ diff --git a/yacc/error.c b/yacc/error.c index b2750c971..a47bed9fa 100644 --- a/yacc/error.c +++ b/yacc/error.c @@ -177,8 +177,8 @@ token\n", virtual_input_file_name, lineno, s); void too_many_entries(void) { - fprintf(stderr, "File \"%s\", line %d: more than 256 entry points\n", - virtual_input_file_name, lineno); + fprintf(stderr, "File \"%s\", line %d: more than %u entry points\n", + virtual_input_file_name, lineno, MAX_ENTRY_POINT); done(1); } diff --git a/yacc/reader.c b/yacc/reader.c index 1b0a5f6b8..0ac9f340c 100644 --- a/yacc/reader.c +++ b/yacc/reader.c @@ -978,9 +978,9 @@ void declare_start(void) if (bp->class == TERM) terminal_start(bp->name); - bp->entry = ++entry_counter; - if (entry_counter == 256) + if (entry_counter >= MAX_ENTRY_POINT) too_many_entries(); + bp->entry = ++entry_counter; } } @@ -1699,7 +1699,7 @@ void make_goal(void) if (is_polymorphic(bp->tag)) polymorphic_entry_point(bp->name); fprintf(entry_file, - "let %s (lexfun : Lexing.lexbuf -> token) (lexbuf : Lexing.lexbuf) =\n (Parsing.yyparse yytables %d lexfun lexbuf : %s)\n", + "let %s (lexfun : Lexing.lexbuf -> token) (lexbuf : Lexing.lexbuf) =\n (Parsing.yyparse yytables %u lexfun lexbuf : %s)\n", bp->name, bp->entry, bp->tag); fprintf(interface_file, "val %s :\n (Lexing.lexbuf -> token) -> Lexing.lexbuf -> %s\n",