From bcaee645462812b4d855d041434e933944db9888 Mon Sep 17 00:00:00 2001
From: "James K. Lowden" <jklowden@symas.com>
Date: Wed, 15 Jan 2025 13:58:37 -0500
Subject: [PATCH] WIP: converting messages in parse.y

---
 gcc/cobol/UAT/testsuite.src/run_functions.at  |  86 ++--
 gcc/cobol/UAT/testsuite.src/syn_definition.at |   4 +-
 gcc/cobol/parse.y                             | 454 +++++++++---------
 gcc/cobol/parse_ante.h                        |   3 +-
 gcc/cobol/scan.l                              | 347 ++++++++++++-
 gcc/cobol/scan_ante.h                         |  43 +-
 gcc/cobol/util.cc                             |   9 +-
 7 files changed, 642 insertions(+), 304 deletions(-)

diff --git a/gcc/cobol/UAT/testsuite.src/run_functions.at b/gcc/cobol/UAT/testsuite.src/run_functions.at
index a5de5daeeb37..afb0f3bca8b5 100644
--- a/gcc/cobol/UAT/testsuite.src/run_functions.at
+++ b/gcc/cobol/UAT/testsuite.src/run_functions.at
@@ -5266,43 +5266,43 @@ AT_DATA([prog.cob], [
 ])
 
 AT_CHECK([$COMPILE prog.cob], [1], [], 
-[prog.cob:12:29: error: syntax error, unexpected NAME, expecting DATETIME_FMT
+[prog.cob:12:29: error: syntax error, unexpected NAME, expecting datetime format
    12 |                            (invalid-date-format) <> SPACES
       |                             ^
 prog.cob:16:12: error: syntax error, unexpected END_IF
    16 |            END-IF
       |            ^
-prog.cob:18:40: error: syntax error, unexpected NAME, expecting DATE_FMT
+prog.cob:18:40: error: syntax error, unexpected NAME, expecting date format
    18 |            IF FUNCTION FORMATTED-DATE (invalid-date-format, 1) <> SPACES
       |                                        ^
 prog.cob:22:12: error: syntax error, unexpected END_IF
    22 |            END-IF
       |            ^
-prog.cob:25:29: error: syntax error, unexpected NAME, expecting DATETIME_FMT
+prog.cob:25:29: error: syntax error, unexpected NAME, expecting datetime format
    25 |                            (invalid-datetime-format, 1, 1) <> SPACES
       |                             ^
 prog.cob:29:12: error: syntax error, unexpected END_IF
    29 |            END-IF
       |            ^
-prog.cob:31:40: error: syntax error, unexpected NAME, expecting TIME_FMT
+prog.cob:31:40: error: syntax error, unexpected NAME, expecting time format
    31 |            IF FUNCTION FORMATTED-TIME (invalid-time-format, 1) <> SPACES
       |                                        ^
 prog.cob:35:12: error: syntax error, unexpected END_IF
    35 |            END-IF
       |            ^
-prog.cob:38:29: error: syntax error, unexpected NAME, expecting DATE_FMT or DATETIME_FMT
+prog.cob:38:29: error: syntax error, unexpected NAME, expecting date format or datetime format
    38 |                            (invalid-date-format, 1) <> ZERO
       |                             ^
 prog.cob:42:12: error: syntax error, unexpected END_IF
    42 |            END-IF
       |            ^
-prog.cob:45:29: error: syntax error, unexpected NAME, expecting TIME_FMT or DATETIME_FMT
+prog.cob:45:29: error: syntax error, unexpected NAME, expecting time format or datetime format
    45 |                            (invalid-time-format, 1) <> ZERO
       |                             ^
 prog.cob:49:12: error: syntax error, unexpected END_IF
    49 |            END-IF
       |            ^
-prog.cob:52:29: error: syntax error, unexpected NAME, expecting DATE_FMT or TIME_FMT or DATETIME_FMT
+prog.cob:52:29: error: syntax error, unexpected NAME, expecting date format or time format or datetime format
    52 |                            (invalid-datetime-format, 1) <> ZERO
       |                             ^
 prog.cob:56:12: error: syntax error, unexpected END_IF
@@ -5450,112 +5450,112 @@ AT_DATA([prog.cob], [
         END PROGRAM datetime.
 ])
 AT_CHECK([$COMPILE prog.cob], [1], [],
-[prog.cob:7:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+[prog.cob:7:46: error: syntax error, unexpected LITERAL, expecting datetime format
     7 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-DDDThhmmss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:8:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:8:46: error: syntax error, unexpected LITERAL, expecting datetime format
     8 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-DDDThhmmss+hhmm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:9:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:9:46: error: syntax error, unexpected LITERAL, expecting datetime format
     9 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-DDDThhmmss.ssss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:10:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:10:46: error: syntax error, unexpected LITERAL, expecting datetime format
    10 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-DDDThhmmss.ssss+hhmm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:11:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:11:46: error: syntax error, unexpected LITERAL, expecting datetime format
    11 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-DDDThhmmss.ssssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:12:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:12:46: error: syntax error, unexpected LITERAL, expecting datetime format
    12 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-DDDThhmmssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:13:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:13:46: error: syntax error, unexpected LITERAL, expecting datetime format
    13 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-MM-DDThhmmss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:14:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:14:46: error: syntax error, unexpected LITERAL, expecting datetime format
    14 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-MM-DDThhmmss+hhmm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:15:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:15:46: error: syntax error, unexpected LITERAL, expecting datetime format
    15 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-MM-DDThhmmss.ssss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:16:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:16:46: error: syntax error, unexpected LITERAL, expecting datetime format
    16 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-MM-DDThhmmss.ssss+hhmm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:17:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:17:46: error: syntax error, unexpected LITERAL, expecting datetime format
    17 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-MM-DDThhmmss.ssssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:18:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:18:46: error: syntax error, unexpected LITERAL, expecting datetime format
    18 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-MM-DDThhmmssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:19:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:19:46: error: syntax error, unexpected LITERAL, expecting datetime format
    19 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-Www-DThhmmss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:20:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:20:46: error: syntax error, unexpected LITERAL, expecting datetime format
    20 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-Www-DThhmmss+hhmm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:21:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:21:46: error: syntax error, unexpected LITERAL, expecting datetime format
    21 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-Www-DThhmmss.ssss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:22:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:22:46: error: syntax error, unexpected LITERAL, expecting datetime format
    22 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-Www-DThhmmss.ssss+hhmm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:23:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:23:46: error: syntax error, unexpected LITERAL, expecting datetime format
    23 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-Www-DThhmmss.ssssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:24:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:24:46: error: syntax error, unexpected LITERAL, expecting datetime format
    24 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYY-Www-DThhmmssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:25:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:25:46: error: syntax error, unexpected LITERAL, expecting datetime format
    25 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYDDDThh:mm:ss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:26:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:26:46: error: syntax error, unexpected LITERAL, expecting datetime format
    26 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYDDDThh:mm:ss+hh:mm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:27:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:27:46: error: syntax error, unexpected LITERAL, expecting datetime format
    27 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYDDDThh:mm:ss.ssss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:28:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:28:46: error: syntax error, unexpected LITERAL, expecting datetime format
    28 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYDDDThh:mm:ss.ssss+hh:mm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:29:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:29:46: error: syntax error, unexpected LITERAL, expecting datetime format
    29 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYDDDThh:mm:ss.ssssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:30:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:30:46: error: syntax error, unexpected LITERAL, expecting datetime format
    30 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYDDDThh:mm:ssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:31:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:31:46: error: syntax error, unexpected LITERAL, expecting datetime format
    31 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYMMDDThh:mm:ss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:32:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:32:46: error: syntax error, unexpected LITERAL, expecting datetime format
    32 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYMMDDThh:mm:ss+hh:mm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:33:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:33:46: error: syntax error, unexpected LITERAL, expecting datetime format
    33 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYMMDDThh:mm:ss.ssss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:34:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:34:46: error: syntax error, unexpected LITERAL, expecting datetime format
    34 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYMMDDThh:mm:ss.ssss+hh:mm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:35:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:35:46: error: syntax error, unexpected LITERAL, expecting datetime format
    35 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYMMDDThh:mm:ss.ssssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:36:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:36:46: error: syntax error, unexpected LITERAL, expecting datetime format
    36 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYMMDDThh:mm:ssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:37:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:37:46: error: syntax error, unexpected LITERAL, expecting datetime format
    37 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYWwwDThh:mm:ss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:38:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:38:46: error: syntax error, unexpected LITERAL, expecting datetime format
    38 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYWwwDThh:mm:ss+hh:mm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:39:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:39:46: error: syntax error, unexpected LITERAL, expecting datetime format
    39 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYWwwDThh:mm:ss.ssss" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:40:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:40:46: error: syntax error, unexpected LITERAL, expecting datetime format
    40 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYWwwDThh:mm:ss.ssss+hh:mm" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:41:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:41:46: error: syntax error, unexpected LITERAL, expecting datetime format
    41 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYWwwDThh:mm:ss.ssssZ" 128623 45296.987654321 -300).
       |                                              ^
-prog.cob:42:46: error: syntax error, unexpected LITERAL, expecting DATETIME_FMT
+prog.cob:42:46: error: syntax error, unexpected LITERAL, expecting datetime format
    42 |         DISPLAY FUNCTION FORMATTED-DATETIME("YYYYWwwDThh:mm:ssZ" 128623 45296.987654321 -300).
       |                                              ^
 cobol1: error: failed compiling prog.cob
diff --git a/gcc/cobol/UAT/testsuite.src/syn_definition.at b/gcc/cobol/UAT/testsuite.src/syn_definition.at
index 4a4329903e90..e42d7a3f370f 100644
--- a/gcc/cobol/UAT/testsuite.src/syn_definition.at
+++ b/gcc/cobol/UAT/testsuite.src/syn_definition.at
@@ -345,7 +345,9 @@ AT_DATA([prog.cob], [
        END PROGRAM prog.
 ])
 AT_CHECK([$COMPILE_ONLY prog.cob], [1], [],
-[prog.cob:13: syntax error at 'END'
+[prog.cob:13:8: error: syntax error, unexpected END, expecting end of file or END PROGRAM <contained program>
+   13 |        END PROGRAM prog.
+      |        ^
 cobol1: error: failed compiling prog.cob
 ])
 AT_CLEANUP
diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y
index 2fb7efffe10a..3ecf1187bec8 100644
--- a/gcc/cobol/parse.y
+++ b/gcc/cobol/parse.y
@@ -285,21 +285,39 @@
 #include "parse_ante.h"
 %}
 
-%token                  IDENTIFICATION_DIV ENVIRONMENT_DIV PROCEDURE_DIV
-                        DATA_DIV FILE_SECT INPUT_OUTPUT_SECT LINKAGE_SECT
-                        LOCAL_STORAGE_SECT WORKING_STORAGE_SECT
-
-%token                  OBJECT_COMPUTER
-
-%token                  DISPLAY_OF
-                        END_FUNCTION END_PROGRAM END_SUBPROGRAM
-                        JUSTIFIED RETURNING
+%token                  IDENTIFICATION_DIV   _("IDENTIFICATION DIVISION")
+			ENVIRONMENT_DIV      _("ENVIRONMENT DIVISION")
+			PROCEDURE_DIV        _("PROCEDURE DIVISION")
+                        DATA_DIV             _("DATA DIVISION")
+			FILE_SECT            _("FILE SECTION")
+			INPUT_OUTPUT_SECT    _("INPUT-OUTPUT SECTION")
+			LINKAGE_SECT         _("LINKAGE SECTION")
+                        LOCAL_STORAGE_SECT   _("LOCAL-STORAGE SECTION")
+			WORKING_STORAGE_SECT _("WORKING-STORAGE SECTION")
+
+%token                  OBJECT_COMPUTER _("OBJECT COMPUTER")
+
+%token                  DISPLAY_OF     _("DISPLAY OF")
+                        END_FUNCTION   _("END FUNCTION")
+			END_PROGRAM    _("END PROGRAM")
+			END_SUBPROGRAM _("END PROGRAM <contained program>")
+
+%token			HIGH_ORDER_LEFT  _("HIGH-ORDER-LEFT")
+			HIGH_ORDER_RIGHT _("HIGH-ORDER-RIGHT")
+			
+%token			JUSTIFIED RETURNING NO_CONDITION _("invalid token")
 
 %token  <string>        ALNUM ALPHED
 %token  <number>        ERROR EXCEPTION SIZE_ERROR
 %token	<ec_type>	EXCEPTION_NAME
 %token  <number>        LEVEL LEVEL66 LEVEL78 LEVEL88
-%token  <string>        CLASS_NAME NAME NAME88 NUME NUMED NUMED_CR NUMED_DB
+%token  <string>        CLASS_NAME _("class name")
+			NAME
+			NAME88    _("Level 88 NAME")
+			NUME      _("NAME")
+			NUMED     _("NUMERIC-EDITED picture")
+			NUMED_CR  _("NUMERIC-EDITED CR picture")
+			NUMED_DB  _("NUMERIC-EDITED DB picture")
 %token  <number>        NINEDOT NINES NINEV PIC_P
 %token  <string>        SPACES
 %token  <literal>       LITERAL
@@ -315,7 +333,7 @@
 %token  <number>        POSITIVE
 %token  <field_attr>	POINTER
 %token  <string>        SECTION
-%token  <number>        STANDARD_ALPHABET 
+%token  <number>        STANDARD_ALPHABET _("STANDARD ALPHABET") 
 %token  <string>        SWITCH
 %token  <string>        UPSI
 %token  <number>        ZERO
@@ -323,14 +341,18 @@
                          /* environment names */
 %token  <number>        SYSIN SYSIPT SYSOUT SYSLIST SYSLST SYSPUNCH SYSPCH CONSOLE
 %token  <number>        C01 C02 C03 C04 C05 C06 C07 C08 C09 C10 C11 C12 CSP
-%token  <number>        S01 S02 S03 S04 S05 AFP_5A
+%token  <number>        S01 S02 S03 S04 S05 AFP_5A _("AFP 5A")
 %token  <number>        STDIN STDOUT STDERR
 
                          /* intrinsics */
 %token  <string>        LIST MAP NOLIST NOMAP NOSOURCE
-%token  <number>        MIGHT_BE FUNCTION_UDF FUNCTION_UDF_0
+%token  <number>        MIGHT_BE _("IS or IS NOT")
+			FUNCTION_UDF   _("UDF name")
+			FUNCTION_UDF_0 _("UDF")
 
-%token  <string>        DATE_FMT TIME_FMT DATETIME_FMT
+%token  <string>        DATE_FMT _("date format")
+			TIME_FMT _("time format")
+			DATETIME_FMT _("datetime format")
 
     // YYEOF added for compatibility with Bison 3.5
     // https://savannah.gnu.org/forum/forum.php?forum_id=9735
@@ -754,8 +776,8 @@
 
                         NAMED NAT NATIONAL NATIONAL_EDITED NATIONAL_OF
                         NATIVE NEGATIVE NESTED NEXT
-			NINEDOT NINES NINEV NO NOTE
-                        NO_CONDITION NULLS NULLPTR NUMBER
+			NINEDOT NINES NINEV NO NOTE NO_CONDITION 
+			NULLS NULLPTR NUMBER
                         NUME NUMED NUMED_CR NUMED_DB NUMERIC
                         NUMERIC_EDITED NUMSTR NUMVAL NUMVAL_C NUMVAL_F
 
@@ -1088,7 +1110,7 @@ opt_clause:     opt_arith
 
 opt_arith:      ARITHMETIC is opt_arith_type {
 		  if( ! current.option($opt_arith_type) ) {
-		    yyerror("unable to set ARITHMETIC option");
+		    error_msg(@3, "unable to set ARITHMETIC option");
 		  }
 		}
                 ;
@@ -1109,46 +1131,46 @@ opt_binary:     FLOAT_BINARY default_kw is HIGH_ORDER_LEFT
 		{
 		  cbl_unimplementedw("HIGH-ORDER-LEFT was ignored");
 		  if( ! current.option_binary(cbl_options_t::high_order_left_e) ) {
-		    yyerror("unable to set HIGH_ORDER_LEFT");
+		    error_msg(@3, "unable to set HIGH_ORDER_LEFT");
 		  }
 		}
-        |       FLOAT_BINARY default_kw is HIGH_ORDER_RIGHT
+        |       FLOAT_BINARY default_kw is HIGH_ORDER_RIGHT[opt]
 		{
 		  cbl_unimplementedw("HIGH-ORDER-RIGHT was ignored");
 		  if( ! current.option_binary(cbl_options_t::high_order_right_e) ) {
-		    yyerror("unable to set HIGH_ORDER_RIGHT");
+		    error_msg(@opt, "unable to set HIGH-ORDER-RIGHT");
 		  }
 		}
                 ;
 default_kw:     %empty
         |       DEFAULT
                 ;
-opt_decimal:    FLOAT_DECIMAL default_kw is HIGH_ORDER_LEFT
+opt_decimal:    FLOAT_DECIMAL default_kw is HIGH_ORDER_LEFT[opt]
 		{
 		  cbl_unimplementedw("HIGH-ORDER-LEFT was ignored");
 		  if( ! current.option_decimal(cbl_options_t::high_order_left_e) ) {
-		    yyerror("unable to set HIGH_ORDER_LEFT");
+		    error_msg(@opt, "unable to set HIGH-ORDER-LEFT");
 		  }
 		}
-        |       FLOAT_DECIMAL default_kw is HIGH_ORDER_RIGHT
+        |       FLOAT_DECIMAL default_kw is HIGH_ORDER_RIGHT[opt]
 		{
 		  cbl_unimplementedw("HIGH-ORDER-RIGHT was ignored");
 		  if( ! current.option_decimal(cbl_options_t::high_order_right_e) ) {
-		    yyerror("unable to set HIGH_ORDER_RIGHT");
+		    error_msg(@opt, "unable to set HIGH-ORDER-RIGHT");
 		  }
 		}
-        |       FLOAT_DECIMAL default_kw is BINARY_ENCODING
+        |       FLOAT_DECIMAL default_kw is BINARY_ENCODING[opt]
 		{
 		  cbl_unimplementedw("BINARY-ENCODING was ignored");
 		  if( ! current.option(cbl_options_t::binary_encoding_e) ) {
-		    yyerror("unable to set BINARY-ENCODING option");
+		    error_msg(@opt, "unable to set BINARY-ENCODING option");
 		  }
 		}
-        |       FLOAT_DECIMAL default_kw is DECIMAL_ENCODING
+        |       FLOAT_DECIMAL default_kw is DECIMAL_ENCODING[opt]
 		{
 		  cbl_unimplementedw("DECIMAL-ENCODING was ignored");
 		  if( ! current.option(cbl_options_t::decimal_encoding_e) ) {
-		    yyerror("unable to set DECIMAL-ENCODING option");
+		    error_msg(@opt, "unable to set DECIMAL-ENCODING option");
 		  }
 		}
                 ;
@@ -1208,10 +1230,10 @@ opt_init_value: BINARY ZERO { $$ = constant_index(NULLS); }
 	|       LITERAL
 		{
 		  if( $1.prefix[0] != 'X' ) {
-		    yyerror("hexadecimal literal required");
+		    error_msg(@1, "hexadecimal literal required");
 		  } 
 		  if( $1.len != 1 ) {
-		    yyerror("1-byte hexadecimal literal required");
+		    error_msg(@1, "1-byte hexadecimal literal required");
 		  } 
       char ach[16];
       sprintf(ach, "%d", (int)($1.data[0]));
@@ -1251,24 +1273,25 @@ comminits:      comminit
         |       comminits comminit {
                   if( ($1.initial && $2.recursive) ||
                       ($2.initial && $1.recursive) ) {
-                    yyerror("INITIAL cannot be used with RECURSIVE");
+		    auto loc = $1.initial? @1 : @2;
+                    error_msg(loc, "INITIAL cannot be used with RECURSIVE");
                   }
                   $$ = $1;
                   if( $2.common ) {
                     if( $1.common ) {
-                      yyerror("COMMON repeated");
+                      error_msg(@2, "COMMON repeated");
                     }
                     $$.common = $2.common;
                   }
                   if( $2.initial ) {
                     if( $1.initial ) {
-                      yyerror("INITIAL repeated");
+                      error_msg(@2, "INITIAL repeated");
                     }
                     $$.initial = $2.initial;
                   }
                   if( $2.recursive ) {
                     if( $1.recursive ) {
-                      yyerror("RECURSIVE repeated");
+                      error_msg(@2, "RECURSIVE repeated");
                     }
                     $$.recursive = $2.recursive;
                   }
@@ -1276,7 +1299,7 @@ comminits:      comminit
                 ;
 comminit:       COMMON     {
                   if( program_level() == 0 ) { // PROGRAM-ID being parsed not added yet.
-                    yyerror("COMMON may be used only in a contained program");
+                    error_msg(@1, "COMMON may be used only in a contained program");
                   }
                   $$.common = true;
                   $$.initial = $$.recursive = false;
@@ -1355,7 +1378,7 @@ select:         SELECT optional NAME[name] select_clauses[clauses] '.'
                   if( !namcpy(file->name, $name) ) YYERROR;
 
                   if( ! ($clauses.clauses & assign_clause_e) ) {
-                    yyerror("ASSIGN clause missing for %s", file->name);
+                    error_msg(@name, "ASSIGN clause missing for %s", file->name);
                   }
 
                   // key check
@@ -1367,13 +1390,13 @@ select:         SELECT optional NAME[name] select_clauses[clauses] '.'
                       auto ikey = file->nkey - 1;
                       assert(file->keys[ikey].fields);
                       auto f = cbl_field_of(symbol_at(file->keys[ikey].fields[0]));
-                      yyerror("INDEXED file %s cannot have RELATIVE key %s",
-                             file->name, f->name);
+                      error_msg(@name, "INDEXED file %s cannot have RELATIVE key %s",
+				file->name, f->name);
                       break; // because next message would be redundant
                     }
                     if( ($clauses.clauses & record_key_clause_e) == 0 ) {
-                      yyerror("INDEXED file %s has no RECORD KEY",
-                               file->name);
+                      error_msg(@name, "INDEXED file %s has no RECORD KEY",
+				file->name);
                     }
                     break;
                   case file_disorganized_e:
@@ -1385,8 +1408,8 @@ select:         SELECT optional NAME[name] select_clauses[clauses] '.'
                       auto ikey = file->nkey - 1;
                       assert(file->keys[ikey].fields);
                       auto f = cbl_field_of(symbol_at(file->keys[ikey].fields[0]));
-                      yyerror("%s file %s cannot have RECORD key %s",
-                               file_org_str(file->org), file->name, f->name);
+                      error_msg(@name, "%s file %s cannot have RECORD key %s",
+				file_org_str(file->org), file->name, f->name);
                     }
                     break;
                   }
@@ -1396,9 +1419,9 @@ select:         SELECT optional NAME[name] select_clauses[clauses] '.'
                   case file_access_rnd_e:
                   case file_access_dyn_e:
                       if( is_sequential(file) ) {
-                          yyerror("%s file %s cannot have ACCESS %s",
-                                 file_org_str(file->org), file->name,
-                                 file_access_str(file->access));
+                          error_msg(@name, "%s file %s cannot have ACCESS %s",
+				    file_org_str(file->org), file->name,
+				    file_access_str(file->access));
                       }
                       break;
                   default:
@@ -1435,7 +1458,7 @@ selected_name:  external scalar { $$ = $2; }
                 {
                   const char *name = string_of($name);
                   if( ! name ) {
-                    yyerror("'%s' has embedded NUL", $name.data);
+                    error_msg(@name, "'%s' has embedded NUL", $name.data);
                     YYERROR;
                   }
                   uint32_t len = $name.len;
@@ -1486,27 +1509,27 @@ select_clauses: select_clause { $$.clauses = $1.clause; $$.file = $1.file; }
                     break;
                   case assign_clause_e:
                     if( exists ) {
-                      yyerror("clause is repeated");
+                      error_msg(@part, "clause is repeated");
                       YYERROR;
                     }
                     $$.file->filename = $part.file->filename;
                     break;
                   case collating_clause_e:
                     if( exists ) {
-                      yyerror("clause is repeated");
+                      error_msg(@part, "clause is repeated");
                       YYERROR;
                     }
                     break;
                   case lock_mode_clause_e:
                     if( exists ) {
-                      yyerror("clause is repeated");
+                      error_msg(@part, "clause is repeated");
                       YYERROR;
                     }
                     $$.file->lock = $part.file->lock;
                     break;
                   case organization_clause_e:
                     if( exists ) {
-                      yyerror("clause is repeated");
+                      error_msg(@part, "clause is repeated");
                       YYERROR;
                     }
                     $$.file->org = $part.file->org;
@@ -1516,36 +1539,36 @@ select_clauses: select_clause { $$.clauses = $1.clause; $$.file = $1.file; }
                   case sharing_clause_e:
                   case record_delim_clause_e:
                     if( exists ) {
-                      yyerror("clause is repeated");
+                      error_msg(@part, "clause is repeated");
                       YYERROR;
                     }
                     break;
                   case access_clause_e:
                     if( exists ) {
-                      yyerror("clause is repeated");
+                      error_msg(@part, "clause is repeated");
                       YYERROR;
                     }
                     $$.file->access = $part.file->access;
                     break;
                   case relative_key_clause_e:
                     if( exists ) {
-                      yyerror("clause is repeated");
+                      error_msg(@part, "clause is repeated");
                       YYERROR;
                     }
                     if( $$.clauses & record_key_clause_e ) {
-                      yyerror("FILE %s is INDEXED, has no RELATIVE key",
+                      error_msg(@part, "FILE %s is INDEXED, has no RELATIVE key",
                                $$.file->name);
                       YYERROR;
                     }
                     // fall thru
                   case record_key_clause_e:
                     if( exists ) {
-                      yyerror("clause is repeated");
+                      error_msg(@part, "clause is repeated");
                       YYERROR;
                     }
                     if( ($$.clauses & relative_key_clause_e) &&
                          $part.clause == record_key_clause_e ) {
-                      yyerror("FILE %s is RELATIVE, has no RECORD key",
+                      error_msg(@part, "FILE %s is RELATIVE, has no RECORD key",
                                $$.file->name);
                       YYERROR;
                     }
@@ -1559,7 +1582,7 @@ select_clauses: select_clause { $$.clauses = $1.clause; $$.file = $1.file; }
                   /* case password_clause_e: */
                   case file_status_clause_e:
                     if( exists ) {
-                      yyerror("clause is repeated");
+                      error_msg(@part, "clause is repeated");
                       YYERROR;
                     }
                     $$.file->user_status = $part.file->user_status;
@@ -1569,7 +1592,7 @@ select_clauses: select_clause { $$.clauses = $1.clause; $$.file = $1.file; }
                   if( $$.file->lock.locked() ) {
                     if( $$.file->org == file_sequential_e &&
                         $$.file->lock.multiple ) {
-                      yyerror("SEQUENTIAL file cannot lock MULTIPLE records");
+                      error_msg(@part, "SEQUENTIAL file cannot lock MULTIPLE records");
                     }
                   }
 
@@ -1807,8 +1830,8 @@ config_paragraph:
                 {
                   if( $name ) {
                     if( !current.collating_sequence($name) ) {
-                      yyerror( "collating sequence already defined as '%s'",
-                                current.collating_sequence() );
+                      error_msg(@name, "collating sequence already defined as '%s'",
+                                current.collating_sequence());
                       YYERROR;
                     }
                   }
@@ -1863,8 +1886,8 @@ repo_func_name: NAME {
                   if( ! current.repository_add($NAME) ) { // add intrinsic by name
                     auto token = current.udf_in($NAME);
                     if( !token ) {
-                      yyerror("%s is not defined here as a user-defined function",
-                             $NAME);
+                      error_msg(@NAME, "%s is not defined here as a user-defined function",
+                                $NAME);
                       current.udf_dump();
                       YYERROR;
                     }
@@ -1881,14 +1904,14 @@ repo_program:   PROGRAM_kw NAME repo_as
                   auto program = symbol_label( PROGRAM, LblProgram, 0, $NAME );
                   if( ! program ) {
                     if( $repo_as.empty() ) {
-                      yyerror("'%s' does not name an earlier program", $NAME);
+                      error_msg(@repo_as, "'%s' does not name an earlier program", $NAME);
                       YYERROR;
                     }
                     program = symbol_label( PROGRAM, LblProgram, 0,
                                             "", $repo_as.data );
                   }
                   if( ! program ) {
-                    yyerror("'%s' does not name an earlier program",
+                    error_msg(@repo_as, "'%s' does not name an earlier program",
                              $repo_as.data);
                     YYERROR;
                   }
@@ -1914,7 +1937,7 @@ repo_property:  PROPERTY NAME repo_as
 with_debug:     %empty
         |       with DEBUGGING MODE {
                   if( ! set_debug(true) ) {
-                    yyerror("DEBUGGING MODE valid only in fixed format");
+                    error_msg(@2, "DEBUGGING MODE valid only in fixed format");
                   }
                 }
                 ;
@@ -1970,7 +1993,7 @@ special_name:   dev_mnemonic
                 // character in the PICTURE string, and 'sign' is the substitution
                 // that gets made in memory.
                   if( ! string_of($lit) ) {
-                    yyerror("'%s' has embedded NUL", $lit.data);
+                    error_msg(@lit, "'%s' has embedded NUL", $lit.data);
                     YYERROR;
                   }
                 symbol_currency_add( $picture_sym, $lit.data );
@@ -2046,7 +2069,7 @@ dev_mnemonic:	device_name is NAME
 		                 device, toupper);
 		  auto p = fujitsus.find(device);
 		  if( p == fujitsus.end() ) {
-		    yyerror("%s is not a device name");
+		    error_msg(@device, "%s is not a device name");
 		  }
 
                   cbl_special_name_t special = { .id = p->second };
@@ -2097,8 +2120,8 @@ alphabet_name:  STANDARD_ALPHABET  { $$ = alphabet_add(ASCII_e); }
                 }
         |       error
                 {
-                  yyerror("code-name-1 may be STANDARD-1, STANDARD-2, "
-                          "NATIVE, OR EBCDIC");
+                  error_msg(@1, "code-name-1 may be STANDARD-1, STANDARD-2, "
+                            "NATIVE, OR EBCDIC");
                   $$ = NULL;
                 }
                 ;
@@ -2113,7 +2136,7 @@ alphabet_seqs:  alphabet_seq[seq]
                   $$ = new cbl_alphabet_t(custom_encoding_e);
 
                   if( !$seq.low || $seq.also ) {
-                    yyerror( "syntax error at ALSO");
+                    error_msg(@1, "syntax error at ALSO");
                     YYERROR;
                   }
                   $$->add_sequence($seq.low);
@@ -2170,7 +2193,7 @@ alphabet_seq:   alphabet_lit[low]
 alphabet_etc:   alphabet_lit
                 {
                   if( $1.len > 1 ) {
-                    yyerror("'%c' can be only a single letter", $1.data);
+                    error_msg(@1, "'%c' can be only a single letter", $1.data);
                     YYERROR;
                   }
                   $$ = (unsigned char)$1.data[0];
@@ -2240,14 +2263,6 @@ upsi:           UPSI is NAME
                     off->data.upsi_mask = new cbl_upsi_mask_t(false, value);
                   }
                 }
-        /* |    error */
-        /*      { */
-        /*        yyerror("Switch names are UPSI-0 through UPSI-7"); */
-        /*        if( max_errors_exceeded(nparse_error) ) { */
-        /*          yyerror("max errors %d reached", nparse_error); */
-        /*          YYABORT; */
-        /*        } */
-        /*      } */
                 ;
 upsi_entry:     ON  status is NAME
                 {
@@ -2274,7 +2289,7 @@ upsi_entry:     ON  status is NAME
 picture_sym:    %empty                { $$ = NULL; }
         |       PICTURE SYMBOL LITERAL[lit] {
                   if( ! string_of($lit) ) {
-                    yyerror("'%s' has embedded NUL", $lit.data);
+                    error_msg(@lit, "'%s' has embedded NUL", $lit.data);
                     YYERROR;
                   }
                   $$ = string_of($lit);
@@ -2437,7 +2452,7 @@ fd_clause:      record_desc
                   f->varying_size.explicitly = f->varies();
                   if( f->varying_size.max != 0 ) {
                     if( !(f->varying_size.min <= f->varying_size.max) ) {
-                      yyerror("%zu must be <= %zu",
+                      error_msg(@1, "%zu must be <= %zu",
                                 f->varying_size.min, f->varying_size.max);
                       YYERROR;
                     }
@@ -2455,11 +2470,10 @@ fd_clause:      record_desc
                   case 'S':
                     break;
                   default:
-                    yyerror( "syntax error: invalid RECORDING MODE '%s'",
-                              $NAME);
+                    error_msg(@NAME, "invalid RECORDING MODE '%s'", $NAME);
                     YYERROR;
                   }
-                  yywarn("RECORDING MODE was ignored, not defined by ISO 2023");
+                  cbl_unimplementedw("RECORDING MODE was ignored, not defined by ISO 2023");
                 }
         |       VALUE OF fd_values
         |       CODESET is NAME
@@ -2491,7 +2505,7 @@ block_desc:     BLOCK contains rec_contains chars_recs
 rec_contains:   NUMSTR[min] {
                   ssize_t n;
                   if( (n = numstr2i($min.string, $min.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $min.string);
+                    error_msg(@min, "size %s cannot be negative", $min.string);
                     YYERROR;
                   }
                   $$.min = $$.max = n; // fixed length
@@ -2499,18 +2513,18 @@ rec_contains:   NUMSTR[min] {
         |       NUMSTR[min] TO NUMSTR[max] {
                   ssize_t n;
                   if( (n = numstr2i($min.string, $min.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $min.string);
+                    error_msg(@min, "size %s cannot be negative", $min.string);
                     YYERROR;
                   }
                   $$.min = n;
 
                   if( (n = numstr2i($max.string, $max.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $max.string);
+                    error_msg(@max, "size %s cannot be negative", $max.string);
                     YYERROR;
                   }
                   $$.max = n;
                   if( !($$.min < $$.max) ) {
-                    yyerror("FROM (%xz) must be less than TO (%zu)",
+                    error_msg(@max, "FROM (%xz) must be less than TO (%zu)",
                               $$.min, $$.max);
                     YYERROR;
                   }
@@ -2565,12 +2579,12 @@ in_size:        IN SIZE
 from_to:        FROM NUMSTR[min] TO NUMSTR[max] characters {
                   ssize_t n;
                   if( (n = numstr2i($min.string, $min.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $min.string);
+                    error_msg(@min, "size %s cannot be negative", $min.string);
                     YYERROR;
                   }
                   $$.min = n;
                   if( (n = numstr2i($max.string, $max.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $max.string);
+                    error_msg(@min, "size %s cannot be negative", $max.string);
                     YYERROR;
                   }
                   $$.max = n;
@@ -2578,12 +2592,12 @@ from_to:        FROM NUMSTR[min] TO NUMSTR[max] characters {
         |       NUMSTR[min] TO NUMSTR[max] characters {
                   ssize_t n;
                   if( (n = numstr2i($min.string, $min.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $min.string);
+                    error_msg(@min, "size %s cannot be negative", $min.string);
                     YYERROR;
                   }
                   $$.min = n;
                   if( (n = numstr2i($max.string, $max.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $max.string);
+                    error_msg(@max, "size %s cannot be negative", $max.string);
                     YYERROR;
                   }
                   $$.max = n;
@@ -2592,7 +2606,7 @@ from_to:        FROM NUMSTR[min] TO NUMSTR[max] characters {
         |       TO NUMSTR[max] characters {
                   ssize_t n;
                   if( (n = numstr2i($max.string, $max.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $max.string);
+                    error_msg(@max, "size %s cannot be negative", $max.string);
                     YYERROR;
                   }
                   $$.min = 0;
@@ -2602,7 +2616,7 @@ from_to:        FROM NUMSTR[min] TO NUMSTR[max] characters {
         |       FROM NUMSTR[min] characters {
                   ssize_t n;
                   if( (n = numstr2i($min.string, $min.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $min.string);
+                    error_msg(@min, "size %s cannot be negative", $min.string);
                     YYERROR;
                   }
                   $$.min = n;
@@ -2611,7 +2625,7 @@ from_to:        FROM NUMSTR[min] TO NUMSTR[max] characters {
         |       NUMSTR[min] characters {
                   ssize_t n;
                   if( (n = numstr2i($min.string, $min.radix)) < 0 ) {
-                    yyerror("size %s cannot be negative", $min.string);
+                    error_msg(@min, "size %s cannot be negative", $min.string);
                     YYERROR;
                   }
                   $$.min = n;
@@ -2693,8 +2707,8 @@ field:          cdf
                           prior.type == FldInvalid &&
                           prior.level == field.level  )
                       {
-                        yyerror("%s %s requires PICTURE",
-				prior.level_str(), prior.name);
+                        error_msg(@1, "%s %s requires PICTURE",
+				  prior.level_str(), prior.name);
                         dbgmsg(field_str($data_descr));
                         YYERROR;
                       }
@@ -2719,7 +2733,7 @@ field:          cdf
                       }
                       initial = string_of(field.data.value);
                       if( !initial ) {
-                        yyerror(xstrerror(errno));
+                        error_msg(@1, xstrerror(errno));
                         YYERROR;
                       }
                       char decimal = symbol_decimal_point();
@@ -2729,11 +2743,11 @@ field:          cdf
                       if( yydebug ) {
                         const char *value_str = string_of(field.data.value);
                         dbgmsg("%s::data.initial is (%%%d.%d) %s ==> '%s'",
-                            field.name,
-                              field.data.digits,
-                              rdigits,
-                            value_str? value_str : "",
-                            field.data.initial);
+			       field.name,
+			       field.data.digits,
+			       rdigits,
+			       value_str? value_str : "",
+			       field.data.initial);
                       }
                     }
                   }
@@ -2747,7 +2761,7 @@ occurs_clause:  OCCURS cardinal_lb             indexed
         |       OCCURS name                    indexed
 		{
 		  if( ! (is_constant($name) && $name->type == FldLiteralN) ) {
-		    yyerror("%s is not CONSTANT", $name->name);
+		    error_msg(@name, "%s is not CONSTANT", $name->name);
 		    YYERROR;
 		  }
                   cbl_occurs_t *occurs = &current_field()->occurs;
@@ -2826,7 +2840,7 @@ index_field1:   ctx_name[name]
                   auto symbol = symbol_field(PROGRAM, 0, $name);
                   if( symbol ) {
                     auto field( cbl_field_of(symbol) );
-                    yyerror( "'%s' already defined on line %d",
+                    error_msg(@name,  "'%s' already defined on line %d",
                               field->name, field->line );
                     YYERROR;
                   }
@@ -2849,7 +2863,7 @@ level_name:     LEVEL ctx_name
                   case 88:
                     break;
                   default:
-                    yyerror("LEVEL %d not supported", $LEVEL);
+                    error_msg(@LEVEL, "LEVEL %d not supported", $LEVEL);
                     YYERROR;
                   }
                   struct cbl_field_t field = { 0,
@@ -2874,7 +2888,7 @@ level_name:     LEVEL ctx_name
                   case 88:
                     break;
                   default:
-                    yyerror("LEVEL %d not supported", $LEVEL);
+                    error_msg(@LEVEL, "LEVEL %d not supported", $LEVEL);
                     YYERROR;
                   }
                   struct cbl_field_t field = { 0,
@@ -2941,7 +2955,7 @@ data_descr1:    level_name
                 {
                   cbl_field_t& field = *$1;
                   if( field.level != 1 ) {
-                    yyerror("%s must be an 01-level data item", field.name);
+                    error_msg(@1, "%s must be an 01-level data item", field.name);
                     YYERROR;
                   }
 
@@ -2952,7 +2966,7 @@ data_descr1:    level_name
                   field.data.initial = string_of($const_value);
 
                   if( !cdf_value(field.name, static_cast<int64_t>($const_value)) ) {
-                    yywarn("%s was defined by CDF", field.name);
+                    error_msg(@1, "%s was defined by CDF", field.name);
                   }
                 }
         |       level_name CONSTANT is_global as literalism[lit]
@@ -2965,7 +2979,7 @@ data_descr1:    level_name
                   field.data.initial  = $lit.data;
                   field.attr |= literal_attr($lit.prefix);
                   if( field.level != 1 ) {
-                    yyerror("%s must be an 01-level data item", field.name);
+                    error_msg(@1, "%s must be an 01-level data item", field.name);
                     YYERROR;
                   }
                   if( !cdf_value(field.name, $lit.data) ) {
@@ -2978,7 +2992,7 @@ data_descr1:    level_name
                   assert($1 == current_field());
                   const cdfval_t *cdfval = cdf_value($NAME);
                   if( !cdfval ) {
-                    yyerror("%s is not was defined by CDF", $NAME);
+                    error_msg(@1, "%s was defined by CDF", $NAME);
                     YYERROR;
                   }
                   cbl_field_t& field = *$1;
@@ -2988,7 +3002,7 @@ data_descr1:    level_name
                   field.data.initial  = cdfval->string;
                   field.data.value = cdfval->number;
                   if( !cdf_value(field.name, *cdfval) ) {
-                    yywarn("%s was defined by CDF", field.name);
+                    error_msg(@1, "%s was defined by CDF", field.name);
                   }
                 }
 
@@ -3016,7 +3030,7 @@ data_descr1:    level_name
                     }
                   }
                   if( ($$ = field_add(&field)) == NULL ) {
-                    yyerror("failed level 78");
+                    error_msg(@name, "failed level 78");
                     YYERROR;
                   }
                 }
@@ -3037,12 +3051,12 @@ data_descr1:    level_name
                   field.data.domain = domain;
 
                   if( ($$ = field_add(&field)) == NULL ) {
-                    yyerror("failed level 88");
+                    error_msg(@NAME, "failed level 88");
                     YYERROR;
                   }
                   auto parent = cbl_field_of(symbol_at($$->parent));
                   if( parent->type != FldPointer ) {
-                    yyerror("LEVEL 88 %s VALUE NULLS invalid for "
+                    error_msg(@NAME, "LEVEL 88 %s VALUE NULLS invalid for "
                              "%s %s, which is not a POINTER",
 			    $$->name, parent->level_str(), parent->name);
                   }
@@ -3065,7 +3079,7 @@ data_descr1:    level_name
                   domains.clear();
 
                   if( ($$ = field_add(&field)) == NULL ) {
-                    yyerror("failed level 88");
+                    error_msg(@NAME, "failed level 88");
                     YYERROR;
                   }
                 }
@@ -3074,27 +3088,27 @@ data_descr1:    level_name
                 {
 		  symbol_field_alias_end();
                   if( is_literal($orig) ) {
-                    yyerror("cannot RENAME '%s'", name_of($orig));
+                    error_msg(@orig, "cannot RENAME '%s'", name_of($orig));
                     YYERROR;
                   }
                   if( !immediately_follows($orig) ) {
-                    yyerror("%s must immediately follow %s to RENAME it",
+                    error_msg(@orig, "%s must immediately follow %s to RENAME it",
                              $alias, name_of($orig));
                     YYERROR;
                   }
                   if( $orig->occurs.ntimes() ) {
-                    yyerror("cannot RENAME table %02u %s",
+                    error_msg(@orig, "cannot RENAME table %02u %s",
                              $orig->level, name_of($orig));
                     YYERROR;
                   }
                   auto table = occurs_in($orig);
                   if( table ) {
-                    yyerror("cannot RENAME '%s' OF %s",
+                    error_msg(@orig, "cannot RENAME '%s' OF %s",
                              name_of($orig), table->name);
                     YYERROR;
                   }
                   if( ! $orig->rename_level_ok() ) {
-                    yyerror("cannot RENAME %02u %s",
+                    error_msg(@orig, "cannot RENAME %02u %s",
                              $orig->level, name_of($orig));
                     YYERROR;
                   }
@@ -3106,37 +3120,37 @@ data_descr1:    level_name
                 {
 		  symbol_field_alias_end();
                   if( !immediately_follows($orig) ) {
-                    yyerror("RENAMES: %s must immediately follow %s",
+                    error_msg(@orig, "RENAMES: %s must immediately follow %s",
                              $alias, name_of($orig));
                     YYERROR;
                   }
                   if( is_literal($orig) ) {
-                    yyerror("cannot RENAME '%s'", name_of($orig));
+                    error_msg(@orig, "cannot RENAME '%s'", name_of($orig));
                     YYERROR;
                   }
                   if( is_literal($thru) ) {
-                    yyerror("cannot RENAME '%s'", name_of($thru));
+                    error_msg(@thru, "cannot RENAME '%s'", name_of($thru));
                     YYERROR;
                   }
                   auto table = occurs_in($orig);
                   if( table ) {
-                    yyerror("cannot RENAME '%s' OF %s",
+                    error_msg(@orig, "cannot RENAME '%s' OF %s",
                              name_of($orig), table->name);
                     YYERROR;
                   }
                   table = occurs_in($thru);
                   if( table ) {
-                    yyerror("cannot RENAME '%s' OF %s",
+                    error_msg(@thru, "cannot RENAME '%s' OF %s",
                              name_of($thru), table->name);
                     YYERROR;
                   }
                   if( ! $orig->rename_level_ok() ) {
-                    yyerror("cannot RENAME %02u %s",
+                    error_msg(@orig, "cannot RENAME %02u %s",
                              $orig->level, name_of($orig));
                     YYERROR;
                   }
                   if( $orig->has_subordinate($thru) ) {
-                    yyerror("cannot RENAME %02u %s THRU %02u %s "
+                    error_msg(@orig, "cannot RENAME %02u %s THRU %02u %s "
                              "because %s is subordinate to %s",
                              $orig->level, name_of($orig),
                              $thru->level, name_of($thru),
@@ -3145,7 +3159,7 @@ data_descr1:    level_name
                   }
                   auto not_ok = rename_not_ok($orig, $thru);
                   if( not_ok ) {
-                    yyerror("cannot RENAME %02u %s THRU %02u %s "
+                    error_msg(@orig, "cannot RENAME %02u %s THRU %02u %s "
                              "because %02u %s cannot be renamed",
                              $orig->level, name_of($orig),
                              $thru->level, name_of($thru),
@@ -3153,7 +3167,7 @@ data_descr1:    level_name
                     YYERROR;
                   }
                   if( field_index($thru) <= field_index($orig) ) {
-                    yyerror("cannot RENAME %02u %s THRU %02u %s "
+                    error_msg(@orig, "cannot RENAME %02u %s THRU %02u %s "
                              "because they're in the wrong order",
                              $orig->level, name_of($orig),
                              $thru->level, name_of($thru));
@@ -3176,7 +3190,7 @@ data_descr1:    level_name
                         ! $field->has_attr(quoted_e) &&
                         normal_value_e == cbl_figconst_of($field->data.initial) )
                     {
-                      yyerror("%s numeric VALUE %s requires PICTURE",
+                      error_msg(@field, "%s numeric VALUE %s requires PICTURE",
                                $field->name, $field->data.initial);
                     }
                     if( null_value_e == cbl_figconst_of($field->data.initial) ) {
@@ -3197,12 +3211,12 @@ data_descr1:    level_name
                     switch($field->type) {
                     case FldNumericEdited:
                       if( $field->has_attr(signable_e) ) {
-                        yyerror( "%s has 'S' in PICTURE, cannot be BLANK WHEN ZERO",
+                        error_msg(@2,  "%s has 'S' in PICTURE, cannot be BLANK WHEN ZERO",
                                   $field->name, cbl_field_type_str($field->type) );
                       }
                       break;
                     default:
-                      yyerror( "%s must be "
+                      error_msg(@2,  "%s must be "
                                 "NUMERIC DISPLAY or NUMERIC-EDITED, not %s",
                                 $field->name, cbl_field_type_str($field->type) );
                     }
@@ -3221,7 +3235,7 @@ data_descr1:    level_name
 
                     if( $field->attr & sign_attrs ) {
                       dbgmsg("%s:%d: %s", __func__, __LINE__, field_str($field));
-                      yyerror("%s must be signed for SIGN IS",
+                      error_msg(@field, "%s must be signed for SIGN IS",
                                 $field->name );
                       YYERROR;
                     }
@@ -3263,7 +3277,7 @@ data_descr1:    level_name
                     switch( $field->data.initial[0] ) {
                     case '-': 
                       if( !$field->has_attr(signable_e) ) {
-                        yyerror("%s is unsigned but has signed VALUE '%s'",
+                        error_msg(@field, "%s is unsigned but has signed VALUE '%s'",
                                  $field->name, $field->data.initial);
                       }
                     }
@@ -3304,7 +3318,7 @@ name66:         LEVEL66 NAME[alias]
                 {
                   build_symbol_map();
 		  if( ! symbol_field_alias_begin() ) {
-		     yyerror("no Level 01 record exists "
+		     error_msg(@alias, "no Level 01 record exists "
 		              "for %s to redefine", $alias);
 		  }
                   $$ = $alias;
@@ -3316,12 +3330,12 @@ data_clauses:   data_clause
                   if( $data_clause == redefines_clause_e ) {
                     auto parent = parent_of(current_field());
                     if( !parent ) {
-                      yyerror("%s invalid REDEFINES",
+                      error_msg(@1, "%s invalid REDEFINES",
                                current_field()->name);
                       YYERROR;
                     }
                     if( parent->occurs.ntimes() > 0 ) {
-                      yyerror("%s cannot REDEFINE table %s",
+                      error_msg(@1, "%s cannot REDEFINE table %s",
                                current_field()->name,
                                parent->name);
                       YYERROR;
@@ -3349,19 +3363,19 @@ data_clauses:   data_clause
                   case typedef_clause_e:    clause = "TYPEDEF";   break;
                   }
                   if( ($$ & $2) == $2 ) {
-                    yyerror("%s clause repeated", clause);
+                    error_msg(@2, "%s clause repeated", clause);
                     YYERROR;
                   }
 
                   if( $data_clause == redefines_clause_e ) {
-                    yyerror("REDEFINES must appear "
+                    error_msg(@2, "REDEFINES must appear "
                              "immediately after LEVEL and NAME");
                     YYERROR;
                   }
                   cbl_field_t *field = current_field();
                   const int globex = (global_e | external_e);
                   if( (($$ | $2) & globex) == globex ) {
-                    yyerror("GLOBAL and EXTERNAL specified");
+                    error_msg(@2, "GLOBAL and EXTERNAL specified");
                     YYERROR;
                   }
 
@@ -3376,18 +3390,18 @@ data_clauses:   data_clause
 
                   if( type_clause_e < ($$ & (type_clause_e | type_implies)) ) {
                     if( $2 == type_clause_e ) {
-                      yyerror("TYPE TO incompatible with ALIGNED, "
+                      error_msg(@2, "TYPE TO incompatible with ALIGNED, "
                               "BLANK WHEN ZERO, JUSTIFIED, PICTURE, SIGN, "
                               "SYNCHRONIZED, and USAGE");
                     } else {
-                      yyerror("%s incompatible with TYPE TO", clause);
+                      error_msg(@2, "%s incompatible with TYPE TO", clause);
                     }
                     YYERROR;
                   }
 
                   if( ($$ & same_clause_e) == same_clause_e ) {
                     if( 0 < ($$ & ~same_clause_e) ) {
-                      yyerror("%s %s SAME AS "
+                      error_msg(@2, "%s %s SAME AS "
 			      "precludes other DATA DIVISION clauses",
 			      field->level_str(), field->name);
                       YYERROR;
@@ -3396,7 +3410,7 @@ data_clauses:   data_clause
 
                   if( is_numeric(field->type) && field->type != FldNumericDisplay ) {
                     if( $$ & sign_clause_e ) {
-                      yyerror("%s is binary NUMERIC type, "
+                      error_msg(@2, "%s is binary NUMERIC type, "
                                "incompatible with SIGN IS", field->name);
                     }
                   }
@@ -3419,7 +3433,7 @@ data_clauses:   data_clause
                   switch( field->type ) {
                   case FldFloat:
                     if( ($$ & picture_clause_e) == picture_clause_e ) {
-		      yyerror("%s: FLOAT types do not allow PICTURE",
+		      error_msg(@2, "%s: FLOAT types do not allow PICTURE",
 			       field->name);
                     }
                     break;
@@ -3428,7 +3442,7 @@ data_clauses:   data_clause
                   }
 
 		  if( ! field->is_justifiable() ) {
-		    yyerror("%s: %s is incompatible with JUSTIFIED",
+		    error_msg(@2, "%s: %s is incompatible with JUSTIFIED",
 			     field->name, 3 + cbl_field_type_str(field->type));
 		  }
                 }
@@ -3481,8 +3495,8 @@ data_clause:    any_length        { $$ = any_length_e; }
                   }
 		  const cbl_field_t *parent;
 		  if( (parent = parent_has_value(field)) != NULL ) {
-		    yyerror("VALUE invalid because group %s has VALUE clause",
-		             parent->name);
+		    error_msg(@1, "VALUE invalid because group %s has VALUE clause",
+		              parent->name);
 		  }
                 }
         |       volatile_clause      { $$ = volatile_clause_e; }
@@ -3499,13 +3513,13 @@ picture_clause: PIC signed nps[fore] nines nps[aft]
                   field->data.capacity = type_capacity(field->type, $4);
                   field->data.digits = $4;
                   if( long(field->data.digits) != $4 ) {
-                    yyerror("indicated size would be %ld bytes, "
+                    error_msg(@2, "indicated size would be %ld bytes, "
                              "maximum data item size is %u",
                              $4, UINT32_MAX);
                   }
 
                   if( $fore && $aft ) { // leading and trailing P's
-                    yyerror("PIC cannot have both leading and trailing P");
+                    error_msg(@2, "PIC cannot have both leading and trailing P");
                     YYERROR;
                   }
                   if( $fore || $aft ) {
@@ -3513,7 +3527,7 @@ picture_clause: PIC signed nps[fore] nines nps[aft]
                     field->data.rdigits = $fore? $fore : -$aft;
                   }
                   if( ! field->reasonable_capacity() ) {
-                    yyerror("%s limited to capacity of %d (would need %u)",
+                    error_msg(@2, "%s limited to capacity of %d (would need %u)",
 			     field->name, MAX_FIXED_POINT_DIGITS, field->data.capacity);
                   }
                 }
@@ -3536,7 +3550,7 @@ picture_clause: PIC signed nps[fore] nines nps[aft]
                     field->data.rdigits = $rdigits;
                   }
                   if( ! field->reasonable_capacity() ) {
-                    yyerror("%s limited to capacity of %d (would need %u)",
+                    error_msg(@2, "%s limited to capacity of %d (would need %u)",
 			     field->name, MAX_FIXED_POINT_DIGITS, field->data.capacity);
                   }
                 }
@@ -3555,7 +3569,7 @@ picture_clause: PIC signed nps[fore] nines nps[aft]
                   field->data.rdigits = $rdigits;
 
                   if( ! field->reasonable_capacity() ) {
-                    yyerror("%s limited to capacity of %d (would need %u)",
+                    error_msg(@2, "%s limited to capacity of %d (would need %u)",
 			     field->name, MAX_FIXED_POINT_DIGITS, field->data.capacity);
                   }
                 }
@@ -3569,7 +3583,7 @@ picture_clause: PIC signed nps[fore] nines nps[aft]
 		      dialect_mf() )
 		  { // PIC X COMP-X or COMP-9
 		    if( ! field->has_attr(all_x_e) ) {
-		      yyerror("COMP PICTURE requires all X's or all 9's"); 
+		      error_msg(@2, "COMP PICTURE requires all X's or all 9's"); 
                       YYERROR;
 		    }
 		  } else {
@@ -3603,7 +3617,7 @@ picture_clause: PIC signed nps[fore] nines nps[aft]
                   }
                   ERROR_IF_CAPACITY(field);
                   if( !is_numeric_edited($picture) ) {
-                    yyerror(numed_message);
+                    error_msg(@picture, numed_message);
                     YYERROR;
                   }
                   field->data.picture = $picture;
@@ -3637,7 +3651,7 @@ picture_clause: PIC signed nps[fore] nines nps[aft]
                     break;
                   case FldAlphaEdited:
                     if( !is_alpha_edited(field->data.picture) ) {
-                      yyerror("invalid picture for Alphanumeric-edited");
+                      error_msg(@picture, "invalid picture for Alphanumeric-edited");
                       YYERROR;
                     }
                     break;
@@ -3654,19 +3668,16 @@ alphanum_pic:   alphanum_part {
         |       alphanum_pic alphanum_part
                 {
 		  auto field = current_field();
-		  if( yydebug ) 
-		    yywarn("%s has %s against %s",
-			  field->name, field_attr_str(field),
-			  cbl_field_attr_str($2.attr));
+		  dbgmsg("%s has %s against %s",
+			 field->name, field_attr_str(field),
+			 cbl_field_attr_str($2.attr));
 		  
 		  if( ! field->has_attr($2.attr) ) {
                     field->clear_attr(all_ax_e); // clears 2 bits
                   }
                   $$ += $2.nbyte;
 
-		  if( yydebug ) 
-		    yywarn("%s attrs: %s",
-			  field->name, field_attr_str(field));
+		  dbgmsg("%s attrs: %s", field->name, field_attr_str(field));
                 }
                 ;
 alphanum_part:  ALNUM[picture] count
@@ -3679,7 +3690,7 @@ alphanum_part:  ALNUM[picture] count
                     $$.nbyte += count; // AX9(3) has count 5
                   }
 		  if( count < 0 ) {
-		    yyerror("PICTURE count '(%d)' is negative", count );
+		    error_msg(@2, "PICTURE count '(%d)' is negative", count );
 		    YYERROR;
 		  }
                 }
@@ -3698,7 +3709,7 @@ nine:           %empty           { $$ = 0; }
                 {
                   $$ = $1;
 		  if( $$ == 0 ) {
-		    yyerror("'(0)' invalid in PICTURE (ISO 2023 13.18.40.3)");
+		    error_msg(@1, "'(0)' invalid in PICTURE (ISO 2023 13.18.40.3)");
 		  }
                 }
                 ;
@@ -3711,28 +3722,30 @@ count:          %empty           { $$ = 0; }
                 {
                   $$ = numstr2i( $NUMSTR.string, $NUMSTR.radix );
 		  if( $$ == 0 ) {
-		    yyerror("'(0)' invalid in PICTURE (ISO 2023 13.18.40.3)");
+		    error_msg(@2, "'(0)' invalid in PICTURE (ISO 2023 13.18.40.3)");
 		  }
                 }
 	|	'(' NAME ')'
                 {
 		  auto value = cdf_value($NAME);
 		  if( ! (value && value->is_numeric()) ) {
-		    yyerror("PICTURE '(%s)' requires a CONSTANT value", $NAME );
+		    error_msg(@NAME, "PICTURE '(%s)' requires a CONSTANT value", $NAME );
 		    YYERROR;
 		  }
+		  int nmsg = 0;
 		  auto e = symbol_field(PROGRAM, 0, $NAME);
 		  if( e ) { // verify not floating point with nonzero fraction
 		    auto field = cbl_field_of(e);
 		    assert(is_literal(field)); 
 		    if( field->data.value != size_t(field->data.value) ) {
-		          yyerror("invalid PICTURE count '(%s)'",
-		                   field->data.initial );
+		      nmsg++;
+		      error_msg(@NAME, "invalid PICTURE count '(%s)'",
+				field->data.initial );
 		    }
 		  }
 		  $$ = value->as_number();
-		  if( $$ <= 0 ) {
-		    yyerror("invalid PICTURE count '(%s)'", $NAME );
+		  if( $$ <= 0 && !nmsg) {
+		    error_msg(@NAME, "invalid PICTURE count '(%s)'", $NAME );
 		  }
                 }
                 ;
@@ -3775,7 +3788,7 @@ usage_clause1:  usage COMPUTATIONAL[comp]   native
                           field->type = $comp.type;
 		      	  field->clear_attr(signable_e);
 		        } else {
-		      	  yyerror("numeric USAGE invalid "
+		      	  error_msg(@comp, "numeric USAGE invalid "
 				   "with Alpnanumeric PICTURE");
 		      	  YYERROR;
 		        }
@@ -3816,7 +3829,7 @@ usage_clause1:  usage COMPUTATIONAL[comp]   native
                   if( infer ) {
                     if( $comp.capacity > 0 ) {
                       if( field->data.capacity > 0 ) {
-                        yyerror("%s is BINARY type, incompatible with PICTURE",
+                        error_msg(@comp, "%s is BINARY type, incompatible with PICTURE",
                                field->name);
                         YYERROR;
                       }
@@ -3836,7 +3849,7 @@ usage_clause1:  usage COMPUTATIONAL[comp]   native
                   cbl_field_t *field = current_field();
 		  if( field->data.capacity > 0 &&
 		      field->type != FldNumericDisplay) {
-		    yyerror("%s PICTURE is incompatible with USAGE PACKED DECIMAL",
+		    error_msg(@2, "%s PICTURE is incompatible with USAGE PACKED DECIMAL",
 			     field->name);
 		    YYERROR;
 		  }
@@ -3877,7 +3890,7 @@ usage_clause1:  usage COMPUTATIONAL[comp]   native
                     if( redefined->data.initial ) {
                       char *s = new char[1 + redefined->data.capacity];
                       if( !s ) {
-                        yyerror("could not expand initial value of %s", field->name);
+                        error_msg(@2, "could not expand initial value of %s", field->name);
                         YYERROR;
                       }
                       (void)! snprintf(s, 1 + redefined->data.capacity,
@@ -3906,10 +3919,7 @@ value_clause:   VALUE all LITERAL[lit] {
                     field->data.capacity = $lit.len;
                   } else {
                     if( $all ) {
-                      if( ! field_value_all(field) ) {
-                        yyerror("could not allocate field %s", field->name);
-                        YYERROR;
-                      }
+                      field_value_all(field);
                     } else {
                       if( $lit.len < field->data.capacity ) {
                         auto p = blank_pad_initial( $lit.data, $lit.len,
@@ -3932,10 +3942,7 @@ value_clause:   VALUE all LITERAL[lit] {
                     pristine_values.insert(initial);
                   } else {
                     initial = string_of($value);
-                    if( !initial ) {
-                      yyerror("could not allocate field %s", field->name);
-                      YYERROR;
-                    }
+                    gcc_assert(initial);
                   }
 
                   char decimal = symbol_decimal_point();
@@ -3944,10 +3951,7 @@ value_clause:   VALUE all LITERAL[lit] {
                   field->data.initial = initial;
                   field->data.value = $value;
 
-                  if( $all && ! field_value_all(field) ) {
-                    yyerror("could not allocate ALL field %s", field->name);
-                    YYERROR;
-                  }
+                  if( $all ) field_value_all(field);
                 }
         |       VALUE all reserved_value[value]
                 {
@@ -3963,7 +3967,7 @@ value_clause:   VALUE all LITERAL[lit] {
                 }
         |       VALUE error
                 {
-                  yyerror("no valid VALUE supplied");
+                  error_msg(@2, "no valid VALUE supplied");
                 }
                 ;
 
@@ -3991,23 +3995,23 @@ redefines_clause: REDEFINES NAME[orig]
                 {
                   struct symbol_elem_t *e = field_of($orig);
                   if( !e ) {
-                    yyerror("REDEFINES target not defined");
+                    error_msg(@2, "REDEFINES target not defined");
                     YYERROR;
                   }
                   cbl_field_t *field = current_field();
                   cbl_field_t *orig = cbl_field_of(e);
 		  if( orig->has_attr(filler_e) ) {
-                    yyerror("%s may not REDEFINE %s",
+                    error_msg(@2, "%s may not REDEFINE %s",
                             field->name, orig->name);
 		  }
                   cbl_field_t *super = symbol_redefines(orig);
                   if( super ) {
-                    yyerror("%s may not REDEFINE %s, "
+                    error_msg(@2, "%s may not REDEFINE %s, "
                             "which redefines %s",
                             field->name, orig->name, super->name);
                   }
                   if( field->level != orig->level ) {
-                    yyerror("cannot redefine %s %s as %s %s "
+                    error_msg(@2, "cannot redefine %s %s as %s %s "
                              "because they have different levels",
 			    orig->level_str(), name_of(orig),
 			    field->level_str(), name_of(field));
@@ -4027,7 +4031,7 @@ redefines_clause: REDEFINES NAME[orig]
 					 } );
 		  if( p != symbol_elem_of(field) ) {
 		    auto mid( cbl_field_of(p) );
-                    yyerror("cannot redefine %s %s as %s %s "
+                    error_msg(@2, "cannot redefine %s %s as %s %s "
 			    "because %s %s intervenes",
 			    orig->level_str(), name_of(orig),
 			    field->level_str(), name_of(field), 
@@ -4047,13 +4051,13 @@ redefines_clause: REDEFINES NAME[orig]
 any_length:     ANY LENGTH
                 { cbl_field_t *field = current_field();
                   if( field->attr & any_length_e ) {
-                    yyerror("ANY LENGTH already set");
+                    error_msg(@1, "ANY LENGTH already set");
                   }
                   if( ! (field->level == 1 &&
                          current_data_section == linkage_datasect_e &&
                          (1 < current.program_level() ||
 			      current.program()->is_function())) ) {
-                    yyerror("ANY LENGTH valid only for 01 "
+                    error_msg(@1, "ANY LENGTH valid only for 01 "
                             "in LINKAGE SECTION of a function or contained program");
                     YYERROR;
                   }
@@ -4064,7 +4068,7 @@ any_length:     ANY LENGTH
 based_clause:   BASED
                 { cbl_field_t *field = current_field();
                   if( field->attr & based_e ) {
-                    yyerror("BASED already set");
+                    error_msg(@1, "BASED already set");
                   }
                   field->attr |= based_e;
                 }
@@ -4093,34 +4097,34 @@ same_clause:    SAME AS name
                 {
                   cbl_field_t *field = current_field(), *other = $name;
                   if( other->occurs.ntimes() > 0 ) {
-                    yyerror("SAME AS %s: cannot have OCCURS",
+                    error_msg(@name, "SAME AS %s: cannot have OCCURS",
                              other->name); // 13.18.49.2,P5
                     YYERROR;
                   }
                   if( field->level == 77 and !is_elementary(other->type) ) {
 		    // ISO 2023 13.18.49.2,P8
-                    yyerror("%s %s SAME AS %s: must be elementary",
+                    error_msg(@name, "%s %s SAME AS %s: must be elementary",
 			    field->level_str(), field->name, other->name); 
                     YYERROR;
                   }
 
                   if( (other->attr & (sign_clause_e | usage_clause_e)) > 0 ) {
-                    yyerror("%s: source of SAME AS cannot have "
+                    error_msg(@name, "%s: source of SAME AS cannot have "
                                "SIGN or USAGE clause", other->name);
                     YYERROR;
                   }
                   if( other->usage == FldGroup ) {
-                    yyerror("%s: source of SAME AS cannot have "
+                    error_msg(@name, "%s: source of SAME AS cannot have "
                                "GROUP-USAGE clause", other->name);
                     YYERROR;
                   }
                   if( other->has_attr(constant_e ) ) {
-                    yyerror("%s: source of SAME AS cannot "
+                    error_msg(@name, "%s: source of SAME AS cannot "
                                "be constant", other->name);
                     YYERROR;
                   }
                   if( field->parent == field_index(other) ) {
-                    yyerror("%s: SAME AS uses "
+                    error_msg(@name, "%s: SAME AS uses "
                              "its own parent %s", field->name, other->name);
                     YYERROR;
                   }
@@ -4195,7 +4199,7 @@ typedef_clause: is TYPEDEF strong
                   switch( field->level ) {
                   case 1: case 77: break;
                   default:
-                    yyerror("%s %s IS TYPEDEF must be level 01",
+                    error_msg(@2, "%s %s IS TYPEDEF must be level 01",
 			    field->level_str(), field->name);
                   }
                   field->attr |= typedef_e;
@@ -4203,7 +4207,7 @@ typedef_clause: is TYPEDEF strong
                   if( ! current.typedef_add(field) ) {
                     auto prior = current.has_typedef(field);
                     assert(prior);
-                    yyerror("%s %s IS TYPEDEF is not unique "
+                    error_msg(@2, "%s %s IS TYPEDEF is not unique "
                              "(see %s, line %d)",
 			    field->level_str(), field->name,
 			    prior->name, prior->line);
@@ -4240,14 +4244,16 @@ procedure_args: USING procedure_uses[args]
                 {
                   if( !procedure_division_ready($ret, $args) ) YYABORT;
                   if( ! $ret->has_attr(linkage_e) ) {
-                    yyerror("RETURNING %s is not defined in LINKAGE SECTION", $ret->name);
+                    error_msg(@ret, "RETURNING %s is not defined in LINKAGE SECTION",
+			      $ret->name);
                   }
                 }
         |                                  RETURNING name[ret]
                 {
                   if( !procedure_division_ready($ret, NULL) ) YYABORT;
                   if( ! $ret->has_attr(linkage_e) ) {
-                    yyerror("RETURNING %s is not defined in LINKAGE SECTION", $ret->name);
+                    error_msg(@ret, "RETURNING %s is not defined in LINKAGE SECTION",
+			      $ret->name);
                   }
                 }
                 ;
@@ -4367,7 +4373,7 @@ sentence:       statements  '.'
                   assert(prog);
                   const char *name = string_of($name);
                   if( !name || 0 != strcasecmp(prog->name, name) ) {
-                    yyerror( "END PROGRAM '%s' does not match PROGRAM-ID '%s'",
+                    error_msg(@name,  "END PROGRAM '%s' does not match PROGRAM-ID '%s'",
                               name? name : $name.data, prog->name);
                     YYERROR;
                   }
@@ -4399,11 +4405,11 @@ statements:                statement { $$ = $1; }
 
 statement:      error {
                   if( current.declarative_section_name() ) {
-                    yyerror("missing END DECLARATIVES or SECTION name", nparse_error);
+                    error_msg(@1, "missing END DECLARATIVES or SECTION name", nparse_error);
                     YYABORT;
                   }
                   if( max_errors_exceeded(nparse_error) ) {
-                    yyerror("max errors %d reached", nparse_error);
+                    error_msg(@1, "max errors %d reached", nparse_error);
                     YYABORT;
                   }
                 }
@@ -4488,7 +4494,7 @@ accept:         accept_body end_accept {
 		  cbl_field_t *argi = register_find("_ARGI");
 		  switch( $accept_body.func ) {
 		  case accept_done_e:
-		    yyerror("ON EXCEPTION valid only "
+		    error_msg(@ec, "ON EXCEPTION valid only "
 			    "with ENVIRONMENT or COMAMND-LINE(n)");
 		    break;
 		  case accept_command_line_e:
@@ -4500,7 +4506,7 @@ accept:         accept_body end_accept {
 		    } else if( $1.from->field == argi ) {
 		      parser_move(*$1.into, *$1.from);
 		      if( $ec.on_error || $ec.not_error ) {
-			yyerror("ON EXCEPTION valid only "
+			error_msg(@ec, "ON EXCEPTION valid only "
 				"with ENVIRONMENT or COMAMND-LINE(n)");
 		      }
 		    } else {
@@ -4528,7 +4534,7 @@ accept_body:    accept_refer
                 {
 		  $$.func = accept_done_e;
                   if( $1->is_reference() ) {
-                    yyerror("subscripts are unsupported here");
+                    error_msg(@1, "subscripts are unsupported here");
                     YYERROR;
                   }
                   parser_accept_date_yymmdd($1->field);
@@ -4537,7 +4543,7 @@ accept_body:    accept_refer
                 {
 		  $$.func = accept_done_e;
                   if( $1->is_reference() ) {
-                    yyerror("subscripts are unsupported here");
+                    error_msg(@1, "subscripts are unsupported here");
                     YYERROR;
                   }
                   parser_accept_date_yyyymmdd($1->field);
@@ -4546,7 +4552,7 @@ accept_body:    accept_refer
                 {
 		  $$.func = accept_done_e;
                   if( $1->is_reference() ) {
-                    yyerror("subscripts are unsupported here");
+                    error_msg(@1, "subscripts are unsupported here");
                     YYERROR;
                   }
                   parser_accept_date_yyddd($1->field);
@@ -4555,7 +4561,7 @@ accept_body:    accept_refer
                 {
 		  $$.func = accept_done_e;
                   if( $1->is_reference() ) {
-                    yyerror("subscripts are unsupported here");
+                    error_msg(@1, "subscripts are unsupported here");
                     YYERROR;
                   }
                   parser_accept_date_yyyyddd($1->field);
@@ -4564,7 +4570,7 @@ accept_body:    accept_refer
                 {
 		  $$.func = accept_done_e;
                   if( $1->is_reference() ) {
-                    yyerror("subscripts are unsupported here");
+                    error_msg(@1, "subscripts are unsupported here");
                     YYERROR;
                   }
                   parser_accept_date_dow($1->field);
@@ -4574,7 +4580,7 @@ accept_body:    accept_refer
                 {
 		  $$.func = accept_done_e;
                   if( $1->is_reference() ) {
-                    yyerror("subscripts are unsupported here");
+                    error_msg(@1, "subscripts are unsupported here");
                     YYERROR;
                   }
                   parser_accept_date_hhmmssff($1->field);
@@ -4629,16 +4635,16 @@ accept_refer:   ACCEPT scalar { statement_begin(@1, ACCEPT); $$ = $2; }
 accept_excepts:	accept_excepts[a] accept_except[b] statements %prec ACCEPT
                 {
                   if( $a.on_error && $a.not_error ) {
-                    yyerror("too many ON EXCEPTION clauses");
+                    error_msg(@b, "too many ON EXCEPTION clauses");
                     YYERROR;
                   }
                   // "ON" and "NOT ON" could be reversed, but not duplicated.
                   if( $a.on_error && $b.on_error ) {
-                    yyerror("duplicate ON EXCEPTION clauses");
+                    error_msg(@b, "duplicate ON EXCEPTION clauses");
                     YYERROR;
                   }
                   if( $a.not_error && $b.not_error ) {
-                    yyerror("duplicate NOT ON EXCEPTION clauses");
+                    error_msg(@b, "duplicate NOT ON EXCEPTION clauses");
                     YYERROR;
                   }
                   $$ = $a;
@@ -5948,7 +5954,7 @@ typename:       NAME
                 {
                   auto e = symbol_typedef(PROGRAM, $NAME);
                   if( ! e ) {
-		    error_msg(@1, "symbol '%s' not found", $NAME );
+		    error_msg(@1, "DATA-ITEM '%s' not found", $NAME );
                     YYERROR;
                   }
                   $$ = cbl_field_of(e);
@@ -5962,7 +5968,7 @@ name:           qname
 
                   if( ($$ = field_find(names)) == NULL ) {
                     if( procedure_div_e == current_division  ) {
-		      error_msg(@1, "symbol '%s' not found", names.back() );
+		      error_msg(@1, "DATA-ITEM '%s' not found", names.back() );
                       YYERROR;
                     }
                     /*
@@ -8636,7 +8642,7 @@ nume:           qnume {
                   for( ; !names.empty(); names.pop_front() ) {
                     if( (e = symbol_field(PROGRAM,
                                           index, names.front())) == NULL ) {
-                      yyerror("symbol '%s' not found", names.front() );
+                      error_msg(@1, "DATA-ITEM '%s' not found", names.front() );
                       YYERROR;
                     }
                     $$ = cbl_field_of(e);
diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h
index 65fe4fc2675c..0f55fdcec326 100644
--- a/gcc/cobol/parse_ante.h
+++ b/gcc/cobol/parse_ante.h
@@ -2747,7 +2747,7 @@ valid_redefine( const cbl_field_t *field, const cbl_field_t *orig ) {
   return true;
 }
 
-static struct cbl_field_t *
+static void
 field_value_all(struct cbl_field_t * field ) {
   // Expand initial by repeating its contents until it is of length capacity:
   assert(field->data.initial != NULL);
@@ -2761,7 +2761,6 @@ field_value_all(struct cbl_field_t * field ) {
   new_initial[field->data.capacity] = '\0';
   free(const_cast<char *>(field->data.initial));
   field->data.initial = new_initial;
-  return field;
 }
 
 static cbl_field_t *
diff --git a/gcc/cobol/scan.l b/gcc/cobol/scan.l
index 6b3103eddd9b..c936894bc153 100644
--- a/gcc/cobol/scan.l
+++ b/gcc/cobol/scan.l
@@ -252,7 +252,7 @@ PROGRAM-ID/{DOTEOL}	{ yy_push_state(ident_state);
 PROCEDURE{SPC}DIVISION	{ yy_push_state(procedure_div);
                                   return PROCEDURE_DIV; }
 <comment_entries>{
-  (ENVIRONMENT|DATA|PROCEDURE){SPC}DIVISION  { yyless(0); yy_pop_state(); }
+  (ENVIRONMENT|DATA|PROCEDURE){SPC}DIVISION  { myless(0); yy_pop_state(); }
   {BLANK_EOL}
   [^[:space:]]{1,512}{BLANK_OEOL}  // about 1/2 KB at a time
 }
@@ -262,9 +262,9 @@ PROCEDURE{SPC}DIVISION	{ yy_push_state(procedure_div);
   AS{SPC}[''] 	{ yy_push_state(quoted1); return AS; }
   IS		{ pop_return IS; }
 
-  OPTIONS		{ yy_pop_state(); yyless(0); }
+  OPTIONS		{ yy_pop_state(); myless(0); }
   [[:blank:]]*(ENVIRONMENT|DATA|PROCEDURE)[[:blank:]]+DIVISION/.+\n {
-                                  yy_pop_state(); yyless(0); }
+                                  yy_pop_state(); myless(0); }
   [[:blank:]]*AUTHOR[[:blank:].]+{EOL}? {
 				  // Might not have an EOL, but stop on one. 
                                   yy_push_state(author_state); }
@@ -291,7 +291,7 @@ PROCEDURE{SPC}DIVISION	{ yy_push_state(procedure_div);
   ^[[:blank:]]*0?1/[[:space:]] { /* If in File Section parse record */
                             yy_push_state(field_state);
                             yy_set_bol(1);
-                            yyless(0); }
+                            myless(0); }
 }
 
 <INITIAL,procedure_div,cdf_state>{
@@ -427,7 +427,7 @@ CONTINUE	{ return CONTINUE; }
 
 COPY		{
                   yy_push_state(copy_state);
-                  yyless(0);
+                  myless(0);
                 }
 
 EXTEND		{ return EXTEND;}
@@ -571,7 +571,7 @@ RELATIVE{SPC}(KEY{SPC})?(IS{SPC})?{NAME} {
 		  assert(ISALNUM(name[0]));
 		  assert(ISSPACE(name[-1]));
 		  int token = keyword_tok(name)? RELATIVE : KEY;
-		  yyless( name - yytext );
+		  myless( name - yytext );
 		  return token;
 		}
 RELATIVE	{ return RELATIVE; }
@@ -937,7 +937,7 @@ USE({SPC}FOR)?		{ return USE; }
                               assert(len);
                               if( s[--len] == '.' ) {
                                 s[len] = '\0';
-                                yyless(len);
+                                myless(len);
                               }
                               numstr_of(s); free(s);
                               return NUMSTR;
@@ -1049,7 +1049,7 @@ USE({SPC}FOR)?		{ return USE; }
 		    dialect_error("EJECT is not ISO syntax,", "ibm");
 		  }
                   auto len = yyleng - 1;
-                  if( yytext[len] == '\f' ) yyless(--len);
+                  if( yytext[len] == '\f' ) myless(--len);
 		}
   EXTERNAL		{ return EXTERNAL; }
   FALSE			{ return FALSE_kw; }
@@ -1098,7 +1098,7 @@ USE({SPC}FOR)?		{ return USE; }
 
   COPY			{
                 	  yy_push_state(copy_state);
-                	  yyless(0);
+                	  myless(0);
                 	}
 
   FD/[[:blank:]]+       { parsing.need_level(false); return FD; }
@@ -1344,7 +1344,7 @@ USE({SPC}FOR)?		{ return USE; }
 			  return FEATURE; }
   [[:blank:]]+
   {BLANK_EOL}
-  . 			{ yyless(0); yy_pop_state(); } // not a CDF token
+  . 			{ myless(0); yy_pop_state(); } // not a CDF token
 }
 
 <program_id_state>{
@@ -1361,7 +1361,7 @@ USE({SPC}FOR)?		{ return USE; }
   COMMON	{ pop_return COMMON; }
   PROGRAM 	{ pop_return PROGRAM; }
 
-  AS/{SPC} 	{ yyless(0); yy_pop_state(); } /* => ident_state */
+  AS/{SPC} 	{ myless(0); yy_pop_state(); } /* => ident_state */
   [[:blank:]]*{DOTSEP}[[:blank:].]+{EOL} { pop_return '.'; }
   {DOTEOL}		 		 { pop_return '.'; }
 }
@@ -1382,8 +1382,8 @@ USE({SPC}FOR)?		{ return USE; }
   [.]/[[:blank:]]+.     { return *yytext; }
 
   [[:blank:]]*{DOTSEP}[[:blank:].]+{EOL} {
-			  yy_pop_state(); yyless(0); }
-  {DOTEOL}             	{ yy_pop_state(); yyless(0); }
+			  yy_pop_state(); myless(0); }
+  {DOTEOL}             	{ yy_pop_state(); myless(0); }
 }
 <dot_state>{
   [[:blank:]]*[.][[:blank:].]+{EOL} 	{ pop_return '.'; }
@@ -1431,7 +1431,7 @@ USE({SPC}FOR)?		{ return USE; }
 
   [+-]?({dfc}|{dseq})([.,][[:digit:]])* { auto eotext = yytext + yyleng - 1;
 				       if( *eotext == '.' ) {
-				         yyless(yyleng - 1);
+				         myless(yyleng - 1);
 				         *eotext = '\0';
 				       }
 				       return numstr_of(yytext); }
@@ -1455,7 +1455,7 @@ USE({SPC}FOR)?		{ return USE; }
                                char *p = strchr(s, '.');
                                if( p && strlen(p) == 1 ) {
                                  *p = '\0';
-                                 yyless(p - s);
+                                 myless(p - s);
                                }
                                numstr_of(s); free(s);
                                pop_return NUMSTR;
@@ -1494,7 +1494,7 @@ USE({SPC}FOR)?		{ return USE; }
 
 <procedure_div>{
   (ID|IDENTIFICATION|ENVIRONMENT|DATA|PROCEDURE){SPC}DIVISION  {
-			    yyless(0); yy_pop_state(); }
+			    myless(0); yy_pop_state(); }
 
   EXIT{SPC}/(PROGRAM|SECTION|PARAGRAPH|PERFORM) {
 			  return EXIT; }
@@ -1572,12 +1572,12 @@ USE({SPC}FOR)?		{ return USE; }
 
   {ISNT}{SPC}{VARTYPE}   { yylval.number = NOT;
                                   yy_push_state(classify);
-                                  yyless(0);
+                                  myless(0);
                                   return MIGHT_BE;
                                 }
   IS{SPC}{VARTYPE}       { yylval.number = IS;
                                   yy_push_state(classify);
-                                  yyless(0);
+                                  myless(0);
                                   return MIGHT_BE;
                                 }
 
@@ -1619,7 +1619,7 @@ USE({SPC}FOR)?		{ return USE; }
                     int token = keyword_tok(yytext);
                     if( token ) return token;
                     if( is_integer_token() ) return numstr_of(yytext);
-		    yyless(0);
+		    myless(0);
 	            yy_push_state(partial_name);
 		    tee_up_empty();
 		}
@@ -1659,7 +1659,7 @@ USE({SPC}FOR)?		{ return USE; }
 		        return NAME;
 		      }
 		    }
-		    yyless(0);
+		    myless(0);
 	            yy_push_state(partial_name);
 		    tee_up_empty();
 		}
@@ -1766,7 +1766,7 @@ USE({SPC}FOR)?		{ return USE; }
 				  pop_return token;
 				}
 
-  . 				{ yyless(0); yy_pop_state(); }
+  . 				{ myless(0); yy_pop_state(); }
 }
 
 <function>{
@@ -2019,10 +2019,10 @@ BASIS		{ yy_push_state(basis); return BASIS; }
 <*>{
   ^[ ]{6}D.*\n 	{
 		  if( !is_fixed_format() ) {
-		    yyless(6);
+		    myless(6);
 		  } else {
 		    // If WITH DEBUGGING MODE, drop the D, else drop the line.
-		    if( include_debug() ) yyless(7);
+		    if( include_debug() ) myless(7);
 		  }
 		}
   ^[ ]*>>{OSPC}IF		{ yy_push_state(cdf_state); return CDF_IF; }
@@ -2124,6 +2124,301 @@ BASIS		{ yy_push_state(basis); return BASIS; }
   ^{TITLE}
 }
 
+<*>{
+  ACCEPT	{ return ACCEPT; }
+  ACCESS	{ return ACCESS; }
+  ADD	{ return ADD; }
+  ADDRESS	{ return ADDRESS; }
+  ADVANCING	{ return ADVANCING; }
+  AFTER	{ return AFTER; }
+  ALL	{ return ALL; }
+  ALLOCATE	{ return ALLOCATE; }
+  ALPHABET	{ return ALPHABET; }
+  ALPHABETIC	{ return ALPHABETIC; }
+  ALPHABETIC-LOWER	{ return ALPHABETIC_LOWER; }
+  ALPHABETIC-UPPER	{ return ALPHABETIC_UPPER; }
+  ALPHANUMERIC	{ return ALPHANUMERIC; }
+  ALPHANUMERIC-EDITED	{ return ALPHANUMERIC_EDITED; }
+  ALSO	{ return ALSO; }
+  ALTERNATE	{ return ALTERNATE; }
+  AND	{ return AND; }
+  ANY	{ return ANY; }
+  ANYCASE	{ return ANYCASE; }
+  ARE	{ return ARE; }
+  AREA	{ return AREA; }
+  AREAS	{ return AREAS; }
+  AS	{ return AS; }
+  ASCENDING	{ return ASCENDING; }
+  ASSIGN	{ return ASSIGN; }
+  AT	{ return AT; }
+  BASED	{ return BASED; }
+  BEFORE	{ return BEFORE; }
+  BINARY	{ return BINARY; }
+  BIT	{ return BIT; }
+  BLANK	{ return BLANK; }
+  BLOCK	{ return BLOCK; }
+  BOTTOM	{ return BOTTOM; }
+  BY	{ return BY; }
+  CALL	{ return CALL; }
+  CANCEL	{ return CANCEL; }
+  CF	{ return CF; }
+  CH	{ return CH; }
+  CHARACTER	{ return CHARACTER; }
+  CHARACTERS	{ return CHARACTERS; }
+  CLASS	{ return CLASS; }
+  CLOSE	{ return CLOSE; }
+  CODE	{ return CODE; }
+  COMMA	{ return COMMA; }
+  COMMIT	{ return COMMIT; }
+  COMMON	{ return COMMON; }
+  CONDITION	{ return CONDITION; }
+  CONSTANT	{ return CONSTANT; }
+  CONTAINS	{ return CONTAINS; }
+  CONTENT	{ return CONTENT; }
+  CONTINUE	{ return CONTINUE; }
+  CONTROL	{ return CONTROL; }
+  CONTROLS	{ return CONTROLS; }
+  CONVERTING	{ return CONVERTING; }
+  COPY	{ return COPY; }
+  COUNT	{ return COUNT; }
+  CURRENCY	{ return CURRENCY; }
+  DATA	{ return DATA; }
+  DATE	{ return DATE; }
+  DAY	{ return DAY; }
+  DAY-OF-WEEK	{ return DAY_OF_WEEK; }
+  DE	{ return DE; }
+  DECIMAL-POINT	{ return DECIMAL_POINT; }
+  DECLARATIVES	{ return DECLARATIVES; }
+  DEFAULT	{ return DEFAULT; }
+  DELETE	{ return DELETE; }
+  DELIMITED	{ return DELIMITED; }
+  DELIMITER	{ return DELIMITER; }
+  DEPENDING	{ return DEPENDING; }
+  DESCENDING	{ return DESCENDING; }
+  DETAIL	{ return DETAIL; }
+  DISPLAY	{ return DISPLAY; }
+  DIVIDE	{ return DIVIDE; }
+  DOWN	{ return DOWN; }
+  DUPLICATES	{ return DUPLICATES; }
+  DYNAMIC	{ return DYNAMIC; }
+  EC	{ return EC; }
+  ELSE	{ return ELSE; }
+  END	{ return END; }
+  END-ACCEPT	{ return END_ACCEPT; }
+  END-ADD	{ return END_ADD; }
+  END-CALL	{ return END_CALL; }
+  END-DELETE	{ return END_DELETE; }
+  END-DISPLAY	{ return END_DISPLAY; }
+  END-DIVIDE	{ return END_DIVIDE; }
+  END-EVALUATE	{ return END_EVALUATE; }
+  END-IF	{ return END_IF; }
+  END-MULTIPLY	{ return END_MULTIPLY; }
+  END-PERFORM	{ return END_PERFORM; }
+  END-READ	{ return END_READ; }
+  END-RETURN	{ return END_RETURN; }
+  END-REWRITE	{ return END_REWRITE; }
+  END-SEARCH	{ return END_SEARCH; }
+  END-SUBTRACT	{ return END_SUBTRACT; }
+  END-WRITE	{ return END_WRITE; }
+  ENVIRONMENT	{ return ENVIRONMENT; }
+  EQUAL	{ return EQUAL; }
+  ERROR	{ return ERROR; }
+  EVALUATE	{ return EVALUATE; }
+  EXCEPTION	{ return EXCEPTION; }
+  EXIT	{ return EXIT; }
+  EXTEND	{ return EXTEND; }
+  EXTERNAL	{ return EXTERNAL; }
+  FALSE	{ return FALSE; }
+  FD	{ return FD; }
+  FINAL	{ return FINAL; }
+  FINALLY	{ return FINALLY; }
+  FIRST	{ return FIRST; }
+  FOOTING	{ return FOOTING; }
+  FOR	{ return FOR; }
+  FREE	{ return FREE; }
+  FROM	{ return FROM; }
+  FUNCTION	{ return FUNCTION; }
+  GENERATE	{ return GENERATE; }
+  GIVING	{ return GIVING; }
+  GLOBAL	{ return GLOBAL; }
+  GO	{ return GO; }
+  GOBACK	{ return GOBACK; }
+  GROUP	{ return GROUP; }
+  HEADING	{ return HEADING; }
+  IDENTIFICATION	{ return IDENTIFICATION_DIV; }
+  IF	{ return IF; }
+  IN	{ return IN; }
+  INDEX	{ return INDEX; }
+  INDEXED	{ return INDEXED; }
+  INDICATE	{ return INDICATE; }
+  INITIAL	{ return INITIAL; }
+  INITIALIZE	{ return INITIALIZE; }
+  INITIATE	{ return INITIATE; }
+  INPUT	{ return INPUT; }
+  INSPECT	{ return INSPECT; }
+  INTERFACE	{ return INTERFACE; }
+  INTO	{ return INTO; }
+  INVOKE	{ return INVOKE; }
+  IS	{ return IS; }
+  KEY	{ return KEY; }
+  LAST	{ return LAST; }
+  LEADING	{ return LEADING; }
+  LEFT	{ return LEFT; }
+  LENGTH	{ return LENGTH; }
+  LIMIT	{ return LIMIT; }
+  LIMITS	{ return LIMITS; }
+  LINAGE	{ return LINAGE; }
+  LINE	{ return LINE; }
+  LINE-COUNTER	{ return LINE_COUNTER; }
+  LINES	{ return LINES; }
+  LINKAGE	{ return LINKAGE; }
+  LOCAL-STORAGE	{ return LOCAL_STORAGE; }
+  LOCALE	{ return LOCALE; }
+  LOCATION	{ return LOCATION; }
+  LOCK	{ return LOCK; }
+  MERGE	{ return MERGE; }
+  MODE	{ return MODE; }
+  MOVE	{ return MOVE; }
+  MULTIPLY	{ return MULTIPLY; }
+  NATIONAL	{ return NATIONAL; }
+  NATIONAL-EDITED	{ return NATIONAL_EDITED; }
+  NATIVE	{ return NATIVE; }
+  NEGATIVE	{ return NEGATIVE; }
+  NESTED	{ return NESTED; }
+  NEXT	{ return NEXT; }
+  NO	{ return NO; }
+  NOT	{ return NOT; }
+  NUMBER	{ return NUMBER; }
+  NUMERIC	{ return NUMERIC; }
+  NUMERIC-EDITED	{ return NUMERIC_EDITED; }
+  OCCURS	{ return OCCURS; }
+  OF	{ return OF; }
+  OFF	{ return OFF; }
+  OMITTED	{ return OMITTED; }
+  ON	{ return ON; }
+  OPEN	{ return OPEN; }
+  OPTIONAL	{ return OPTIONAL; }
+  OPTIONS	{ return OPTIONS; }
+  OR	{ return OR; }
+  ORDER	{ return ORDER; }
+  ORGANIZATION	{ return ORGANIZATION; }
+  OTHER	{ return OTHER; }
+  OUTPUT	{ return OUTPUT; }
+  OVERFLOW	{ return OVERFLOW; }
+  OVERRIDE	{ return OVERRIDE; }
+  PACKED-DECIMAL	{ return PACKED_DECIMAL; }
+  PAGE	{ return PAGE; }
+  PAGE-COUNTER	{ return PAGE_COUNTER; }
+  PERFORM	{ return PERFORM; }
+  PF	{ return PF; }
+  PH	{ return PH; }
+  PIC	{ return PIC; }
+  PICTURE	{ return PICTURE; }
+  PLUS	{ return PLUS; }
+  POINTER	{ return POINTER; }
+  POSITIVE	{ return POSITIVE; }
+  PROCEDURE	{ return PROCEDURE; }
+  PROGRAM	{ return PROGRAM; }
+  PROGRAM-ID	{ return PROGRAM_ID; }
+  PROPERTY	{ return PROPERTY; }
+  PROTOTYPE	{ return PROTOTYPE; }
+  QUOTE	{ return QUOTE; }
+  QUOTES	{ return QUOTES; }
+  RAISE	{ return RAISE; }
+  RAISING	{ return RAISING; }
+  RANDOM	{ return RANDOM; }
+  RD	{ return RD; }
+  READ	{ return READ; }
+  RECORD	{ return RECORD; }
+  RECORDS	{ return RECORDS; }
+  REDEFINES	{ return REDEFINES; }
+  REEL	{ return REEL; }
+  REFERENCE	{ return REFERENCE; }
+  RELATIVE	{ return RELATIVE; }
+  RELEASE	{ return RELEASE; }
+  REMAINDER	{ return REMAINDER; }
+  REMOVAL	{ return REMOVAL; }
+  RENAMES	{ return RENAMES; }
+  REPLACE	{ return REPLACE; }
+  REPLACING	{ return REPLACING; }
+  REPORT	{ return REPORT; }
+  REPORTING	{ return REPORTING; }
+  REPORTS	{ return REPORTS; }
+  REPOSITORY	{ return REPOSITORY; }
+  RESERVE	{ return RESERVE; }
+  RESET	{ return RESET; }
+  RESUME	{ return RESUME; }
+  RETURN	{ return RETURN; }
+  RETURNING	{ return RETURNING; }
+  REWIND	{ return REWIND; }
+  REWRITE	{ return REWRITE; }
+  RF	{ return RF; }
+  RH	{ return RH; }
+  RIGHT	{ return RIGHT; }
+  ROUNDED	{ return ROUNDED; }
+  RUN	{ return RUN; }
+  SAME	{ return SAME; }
+  SCREEN	{ return SCREEN; }
+  SD	{ return SD; }
+  SEARCH	{ return SEARCH; }
+  SECTION	{ return SECTION; }
+  SELECT	{ return SELECT; }
+  SENTENCE	{ return SENTENCE; }
+  SEPARATE	{ return SEPARATE; }
+  SEQUENCE	{ return SEQUENCE; }
+  SEQUENTIAL	{ return SEQUENTIAL; }
+  SET	{ return SET; }
+  SHARING	{ return SHARING; }
+  SIGN	{ return SIGN; }
+  SIZE	{ return SIZE; }
+  SORT	{ return SORT; }
+  SORT-MERGE	{ return SORT_MERGE; }
+  SOURCE	{ return SOURCE; }
+  SPACE	{ return SPACE; }
+  SPACES	{ return SPACES; }
+  SPECIAL-NAMES	{ return SPECIAL_NAMES; }
+  STANDARD	{ return STANDARD; }
+  STANDARD-1	{ return STANDARD_1; }
+  START	{ return START; }
+  STATUS	{ return STATUS; }
+  STOP	{ return STOP; }
+  SUBTRACT	{ return SUBTRACT; }
+  SUM	{ return SUM; }
+  SUPPRESS	{ return SUPPRESS; }
+  SYMBOLIC	{ return SYMBOLIC; }
+  TALLYING	{ return TALLYING; }
+  TERMINATE	{ return TERMINATE; }
+  TEST	{ return TEST; }
+  THAN	{ return THAN; }
+  THEN	{ return THEN; }
+  THRU	{ return THRU; }
+  TIME	{ return TIME; }
+  TIMES	{ return TIMES; }
+  TO	{ return TO; }
+  TOP	{ return TOP; }
+  TRAILING	{ return TRAILING; }
+  TRUE	{ return TRUE; }
+  TYPE	{ return TYPE; }
+  TYPEDEF	{ return TYPEDEF; }
+  UNIT	{ return UNIT; }
+  UNTIL	{ return UNTIL; }
+  UP	{ return UP; }
+  UPON	{ return UPON; }
+  USAGE	{ return USAGE; }
+  USE	{ return USE; }
+  USING	{ return USING; }
+  VALUE	{ return VALUE; }
+  VARYING	{ return VARYING; }
+  WHEN	{ return WHEN; }
+  WITH	{ return WITH; }
+  WORKING-STORAGE	{ return WORKING_STORAGE; }
+  WRITE	{ return WRITE; }
+  
+  ZERO	|
+  ZEROES	|
+  ZEROS	{ return ZERO; }
+}
+
 <*>{
   %EBCDIC-MODE		{ ydflval.number = feature_internal_ebcdic_e;
 			  return FEATURE; }
@@ -2135,9 +2430,9 @@ BASIS		{ yy_push_state(basis); return BASIS; }
    {NAME}       {
                   int token = keyword_tok(yytext);
                   if( token ) {
-		    if(yydebug && YY_START) {
-                       yywarn("missed token %s in start condition %d",
-			     yytext, YY_START);
+		    if(yy_flex_debug && YY_START) {
+                       dbgmsg("missed token %s in start condition %d",
+			      yytext, YY_START);
 		    }
 		    // Do not return "token" because it may have been excluded
 		    // by a start condition.  For example, REM might be a name,
diff --git a/gcc/cobol/scan_ante.h b/gcc/cobol/scan_ante.h
index eeaf78129040..15f95813ce9d 100644
--- a/gcc/cobol/scan_ante.h
+++ b/gcc/cobol/scan_ante.h
@@ -357,6 +357,13 @@ static void level_found() {
   if( scanner_normal() ) parsing.need_level(false);
 }
 
+#define myless(N)				\
+  do {						\
+    auto n(N);					\
+    trim_location(n);				\
+    yyless(n);					\
+  } while(0)
+
 static void
 update_location() {
   auto nline = std::count(yytext, yytext + yyleng, '\n');
@@ -380,6 +387,38 @@ update_location() {
   }
 }
 
+static void
+trim_location( int nkeep) {
+  gcc_assert( 0 <= nkeep && nkeep <= yyleng );
+  struct { char *p, *pend;
+    size_t size() const { return pend - p; }
+  } rescan = { yytext + nkeep, yytext + yyleng };
+  
+  auto nline = std::count(rescan.p, rescan.pend, '\n');
+  dbgmsg("%s:%d: yyless(%d), rescan '%.*s' (%zu lines, %d bytes)",
+	 __func__, __LINE__,
+	 nkeep,
+	 int(rescan.size()), rescan.p,
+	 nline, rescan.size());
+  if( nline ) {
+    gcc_assert( yylloc.first_line + nline <= yylloc.last_line );
+    yylloc.last_line =- int(nline);
+    char *p = static_cast<char*>(memrchr(rescan.p, '\n', rescan.size()));
+    yylloc.last_column = rescan.pend - ++p;
+    return;
+  }
+
+  gcc_assert( int(rescan.size()) < yylloc.last_column );
+  yylloc.last_column -= rescan.size();
+  if( yylloc.last_column < yylloc.first_column ) {
+    yylloc.first_column = 1;
+  }
+
+  if( getenv("update_location") ) {
+    location_dump(__func__, __LINE__, "yylloc", yylloc);
+  }
+}
+
 static void
 update_location_col( const char str[], int correction = 0) {
   auto col = yylloc.last_column - strlen(str) + correction;
@@ -456,7 +495,7 @@ picset( int token ) {
   char *p = orig_picture + strlen(orig_picture);
 
   if( eop < p + yyleng ) {
-    yyerror("PICTURE exceeds maximum size of %zu bytes",
+    error_msg(yylloc, "PICTURE exceeds maximum size of %zu bytes",
              sizeof(orig_picture) - 1);
   }
   snprintf( p, eop - p, "%s", yytext );
@@ -472,7 +511,7 @@ is_integer_token( int *pvalue = NULL ) {
 
 static bool need_nume = false;
 bool need_nume_set( bool tf ) {
-  if( yydebug ) yywarn( "need_nume now %s", tf? "true" : "false" );
+  dbgmsg( "need_nume now %s", tf? "true" : "false" );
   return need_nume = tf;
 }
 
diff --git a/gcc/cobol/util.cc b/gcc/cobol/util.cc
index 984f74e9e235..edd2eb4cd374 100644
--- a/gcc/cobol/util.cc
+++ b/gcc/cobol/util.cc
@@ -239,7 +239,6 @@ is_alpha_edited( const char picture[] ) {
 bool
 is_numeric_edited( const char picture[] ) {
   static const char valid[] = "BbPpVvZz90/(),.+-*"; // and CR DB
-  char *s;
   const char *p;
   assert(picture);
 
@@ -295,10 +294,9 @@ is_numeric_edited( const char picture[] ) {
       numed_message = "expected DB in PICTURE";
       break;
     default:
-      asprintf(&s, "invalid PICTURE  character "
-               "'%c' at offset %zu in '%s'",
-               *p, p - picture, picture);
-      numed_message = s;
+      numed_message = xasprintf("invalid PICTURE character "
+				"'%c' at offset %zu in '%s'",
+				*p, p - picture, picture);
       break;
     }
 
@@ -2417,7 +2415,6 @@ cbl_unimplemented(const char *gmsgid, ...) {
   va_list ap;
   va_start(ap, gmsgid);
   emit_diagnostic_valist( DK_SORRY, token_location, option_id, gmsgid, &ap );
-  yyerror("Program requires unimplemented syntax.");
   va_end(ap);
 }
 
-- 
GitLab