diff --git a/gcc/cobol/built-gcobol b/gcc/cobol/built-gcobol index 6c0030005d78619870125a6af785808e97ff3a07..f880f4f664fcb85caf0e9979a71e1cba3e259d1b 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 7436351702105a5f06ca026b4f1e5c9fbcbc0088..0730546ba5c97756250f67fa5fc9afc2c4b3c891 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 ae35a37e3e647bd9dc08791fe064fb5cd69e41aa..d3717b9fe49c2e39db7c03139089030f0c93da24 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 70fe98dd35c67e06ba88fe7895e658e7c0e182f7..ed05268c77b35fa864a21fcfa30fdb0ed051a446 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 317353ba19496778b5512bbc49d7cf217c9e03e3..336f46a41fc266fbb9bd4347e1f4636210ffef03 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 855e8d5372ca82bf5fdf787219b56e964b008d8a..4399c7d93258bb5bd37b69d390b427a961a1cecc 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 c3bcb3007cc024eb9e4ffeb99f15bbc5c893df1d..ed2e06ae0ffbde533e136e3fb1338721e7457f14 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 ,