From d712967df7374caf71a545020dcb58862c84d677 Mon Sep 17 00:00:00 2001 From: "James K. Lowden" <jklowden@symas.com> Date: Sat, 27 Apr 2024 15:43:54 -0400 Subject: [PATCH] process #line directive --- gcc/cobol/built-gcobol | 7 +++++- gcc/cobol/genapi.cc | 1 + gcc/cobol/parse_ante.h | 2 +- gcc/cobol/scan.l | 3 +++ gcc/cobol/symbols.h | 1 + gcc/cobol/util.cc | 50 +++++++++++++++++++++++++++++++++++++++++- libgcobol/constants.cc | 3 +++ 7 files changed, 64 insertions(+), 3 deletions(-) diff --git a/gcc/cobol/built-gcobol b/gcc/cobol/built-gcobol index 6c0030005d78..f880f4f664fc 100755 --- a/gcc/cobol/built-gcobol +++ b/gcc/cobol/built-gcobol @@ -1,8 +1,13 @@ #!/bin/sh # Run gcobol from the build directory set -e +if [ -z "$build" ] +then + build=build +fi + srcdir=$(cd ${0%/*} && git rev-parse --show-toplevel) -objdir=$srcdir/build +objdir=$srcdir/$build libdir=$(ls $objdir/$(arch)* -d) $objdir/gcc/gcobol \ diff --git a/gcc/cobol/genapi.cc b/gcc/cobol/genapi.cc index 743635170210..0730546ba5c9 100644 --- a/gcc/cobol/genapi.cc +++ b/gcc/cobol/genapi.cc @@ -5376,6 +5376,7 @@ parser_arith_error(cbl_label_t *arithmetic_label) { Analyze(); // We are entering either SIZE ERROR or NOT SIZE ERROR code + RETURN_IF_PARSE_ONLY; set_up_arith_error_label(arithmetic_label); SHOW_PARSE diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h index ae35a37e3e64..d3717b9fe49c 100644 --- a/gcc/cobol/parse_ante.h +++ b/gcc/cobol/parse_ante.h @@ -31,7 +31,7 @@ void next_sentence_label(cbl_label_t* label) { parser_label_label(label); next_sentence = NULL; // release codegen label structure, so it can be reused. - assert(label->structs.goto_trees); + assert(label->structs.goto_trees || mode_syntax_only()); free(label->structs.goto_trees); label->structs.goto_trees = NULL; } diff --git a/gcc/cobol/scan.l b/gcc/cobol/scan.l index 70fe98dd35c6..ed05268c77b3 100644 --- a/gcc/cobol/scan.l +++ b/gcc/cobol/scan.l @@ -163,6 +163,7 @@ NL [[:blank:]]*\r?\n[[:blank:]]* PUSH_FILE \f?[#]FILE{SPC}PUSH{SPC}.+\f POP_FILE \f?[#]FILE{SPC}POP\f +LINE_DIRECTIVE [#]line{SPC}[[:alnum:]]+{SPC}[""''].+\n %x procedure_div ident_state addr_of function classify when_not %x program_id_state comment_entries @@ -1895,6 +1896,8 @@ COPY { auto name = cobol_filename_restore(); if( yy_flex_debug ) warnx("resuming at line %4d of %s", yylineno, name? name : "<none>"); } + + {LINE_DIRECTIVE} { cobol_fileline_set(yytext); } } diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h index 317353ba1949..336f46a41fc2 100644 --- a/gcc/cobol/symbols.h +++ b/gcc/cobol/symbols.h @@ -2116,6 +2116,7 @@ bool cobol_filename( const char *name ); const char * cobol_filename(); const char * cobol_filename_restore(); const char * cobol_lineno_save(); +const char * cobol_fileline_set( const char line[] ); char *cobol_name_mangler(const char *cobol_name); diff --git a/gcc/cobol/util.cc b/gcc/cobol/util.cc index 855e8d5372ca..4399c7d93258 100644 --- a/gcc/cobol/util.cc +++ b/gcc/cobol/util.cc @@ -1910,7 +1910,7 @@ date_time_fmt( const char input[] ) { #include <stack> struct input_file_t { int lineno; const char *name; - input_file_t( const char *name ) : lineno(1), name(name) {} + input_file_t( const char *name, int lineno=1 ) : lineno(lineno), name(name) {} bool operator==( const input_file_t& that ) const { return 0 == strcmp(name, that.name); } @@ -1990,6 +1990,54 @@ cobol_filename_restore() { return input.name; } +const char * +cobol_fileline_set( const char line[] ) { + static const char pattern[] = "#line +([[:alnum:]]+) +([\"'][^\"']+). *\n"; + static const int cflags = REG_EXTENDED | REG_ICASE; + static regex_t re, *preg = NULL; + + int erc; + regmatch_t pmatch[4]; + + if( !preg ) { + if( (erc = regcomp(&re, pattern, cflags)) != 0 ) { + regerror(erc, &re, regexmsg, sizeof(regexmsg)); + warnx( "%s:%d: could not compile regex: %s", __func__, __LINE__, regexmsg ); + return line; + } + preg = &re; + } + if( (erc = regexec(preg, line, COUNT_OF(pmatch), pmatch, 0)) != 0 ) { + if( erc != REG_NOMATCH ) { + regerror(erc, preg, regexmsg, sizeof(regexmsg)); + warnx( "%s:%d: could not compile regex: %s", __func__, __LINE__, regexmsg ); + return line; + } + yyerrorv( "error: invalid #line directive: %s", line ); + return line; + } + + const char + *line_str = xstrndup(line + pmatch[1].rm_so, pmatch[1].rm_eo), + *filename = xstrndup(line + pmatch[2].rm_so, pmatch[2].rm_eo); + int fileline; + + if( 1 != sscanf(line_str, "%d", &fileline) ) + warn("%s:%d: line number %s", __func__, __LINE__, line_str); + + input_file_t input_file( filename, fileline ); + + if( input_filenames.empty() ) { + input_filenames.push(input_file); + } + + input_file_t& file = input_filenames.top(); + file = input_file; + yylineno = file.lineno; + + return file.name; +} + static int parse_file( const char filename[] ) { diff --git a/libgcobol/constants.cc b/libgcobol/constants.cc index c3bcb3007cc0..ed2e06ae0ffb 100644 --- a/libgcobol/constants.cc +++ b/libgcobol/constants.cc @@ -52,6 +52,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" // There are global variables that need to be initialized at the point where // the very first PROGRAM-ID is executed. This flag is used to make sure that @@ -112,6 +113,8 @@ struct cblc_field_t __gg___2_##a = { \ .rdigits = 0 , \ }; + + unsigned char __gg__data_space[1] = {' '}; struct cblc_field_t __gg__space = { .data = __gg__data_space , -- GitLab