https://gcc.gnu.org/g:21e2dbfb75aa269f2219e46cb8481e87b96e6615

commit r17-4691-g21e2dbfb75aa269f2219e46cb8481e87b96e6615
Author: James K. Lowden <[email protected]>
Date:   Thu Sep 24 18:36:11 2026 -0400

    cobol: Use automaton to validate PICTURE for edited types.
    
    Validate PICTURE, report errors in the lexer.  In this installment,
    return results in new PICTURE token to parser for alphanumeric-edited
    and numeric-edited types.  Continue to supply the verbatim picture for
    later interpretation during codegen.
    
    gcc/cobol/ChangeLog:
    
            * cbldiag.h (struct cbl_loc_t): Add operators to increment 
first_column.
            (repeat_count): Declare function.
            (parse_error_count): Same.
            (cobol_location): Remove obsolete comment.
            * cdf.y: Update token values.
            * parse.y: Introduce PICTURE token.
            (keyword_tok): Exclude CDF tokens to prevent false positives.
            * parse_ante.h (struct arith_t): Better diagnositic.
            (valid_operands): New function.
            (parser_move_carefully): Reject invalid operands.
            (parser_move2): Whitespace.
            (parser_index): Same.
            * picture.cc (picture_rules): Revise automaton.
            (is_allowed):  Add PICTURE constraints.
            (seek_paren): Add debug messages.
            (is_valid_picture): Rewrote function.
            (class picture_t): Capture PICTURE state to report to lexer.
            * scan.l: Use is_valid_token for complex pictures.
            * scan_ante.h (repeat_count): Use uint32_t, consistent with 
cbl_field_t.
            * semantic_token.h: New file representing lex_picture_t.
            * symbols.cc (parse_error_count): Remove declaration.
            * symbols.h: Use std::array.
            * symfind.cc (struct funcname): Whitespace.
            (symbol_match): Use diagnositic quotes.
            * token_names.h: Regenerate.
            * util.cc (named_constant): Return type of constant.
            (repeat_count): Accept location and return uint32_t.
            (parse_error_count): Remove declaration.
            * util.h (repeat_count): Same.
    
    gcc/
            * config/avr/avr.opt.urls: Regenerate.
            * config/nvptx/nvptx.opt.urls: Regenerate.

Diff:
---
 gcc/cobol/cbldiag.h             |   34 +-
 gcc/cobol/cdf.y                 |  125 ++-
 gcc/cobol/parse.y               |   54 +-
 gcc/cobol/parse_ante.h          |   57 +-
 gcc/cobol/picture.cc            |  511 ++++++++---
 gcc/cobol/scan.l                |   74 +-
 gcc/cobol/scan_ante.h           |  379 +-------
 gcc/cobol/semantic_token.h      |   63 ++
 gcc/cobol/symbols.cc            |    1 -
 gcc/cobol/symbols.h             |   11 +
 gcc/cobol/symfind.cc            |   14 +-
 gcc/cobol/token_names.h         | 1802 +++++++++++++++++++--------------------
 gcc/cobol/util.cc               |   63 +-
 gcc/cobol/util.h                |    2 -
 gcc/config/avr/avr.opt.urls     |    2 +-
 gcc/config/nvptx/nvptx.opt.urls |    2 +-
 16 files changed, 1667 insertions(+), 1527 deletions(-)

diff --git a/gcc/cobol/cbldiag.h b/gcc/cobol/cbldiag.h
index ab5f417e2a03..8a678aa47baf 100644
--- a/gcc/cobol/cbldiag.h
+++ b/gcc/cobol/cbldiag.h
@@ -130,6 +130,23 @@ struct cbl_loc_t : public cbl_loc_base_t {
     first_column = last_column = 1;
     return *this;
   }
+  cbl_loc_t& operator++() {
+    if( first_column + 1 < last_column ) first_column++;
+    return *this;
+  }
+  cbl_loc_t operator++(int) {
+    auto out(*this);
+    if( first_column + 1 < last_column ) first_column++;
+    return out;
+  }
+  cbl_loc_t& operator+=(int n) {
+    if( first_column + n < last_column ) first_column += n;
+    return *this;
+  }
+  cbl_loc_t& operator+(int n) const {
+    auto out(*this);
+    return out += n;
+  }
 
   // Represent a multi-line location as the first line, so "included from"
   // reflects where the COPY statement appears, not where it ends. 
@@ -141,6 +158,11 @@ struct cbl_loc_t : public cbl_loc_base_t {
   }
 };
 
+std::pair<uint32_t, int> repeat_count(const char picture[]);
+std::pair<uint32_t, int> repeat_count(const cbl_loc_t& loc, const char 
picture[]);
+
+size_t parse_error_count();
+
 #include <type_traits>
 /* allow relocate stack */
 static_assert(std::is_trivially_copyable<cbl_loc_t>::value,
@@ -148,18 +170,6 @@ static_assert(std::is_trivially_copyable<cbl_loc_t>::value,
 
 const cbl_loc_t& cobol_location();
 
-/*
- * Naming Convention: Names end with a letter that indicates 
- * their kind:
- * F  fatal, "fatal error: "
- * I  ice, "internal compiler error: "
- * E  error, "error: "
- * S  sorry, "sorry, unimplemented: "
- * W  warning, "warning: "
- * A  anachronism, "anachronism: "
- * N  note, "note: "
- * D  debug, "debug: "
- */
 enum cbl_diag_id_t : uint64_t {
   CdfNotFoundW, 
   CdfParameterW,
diff --git a/gcc/cobol/cdf.y b/gcc/cobol/cdf.y
index abfb7d6e3270..f6ca89f9e048 100644
--- a/gcc/cobol/cdf.y
+++ b/gcc/cobol/cdf.y
@@ -67,9 +67,9 @@ operator<<( std::ostream& os, cbl_loc_t const& loc ) {
   os << "("
      << loc.first_line
      << ","
-     << loc.first_column 
+     << loc.first_column
      << ") to ("
-     << loc.last_line 
+     << loc.last_line
      << ","
      << loc.last_column
      << ")";
@@ -89,7 +89,7 @@ namespace cdf {
     lookahead_token_kind = token;
     return lookahead_token_kind;
   }
-  
+
   bool had_lookahead() {
     int kind = 0;
     std::swap(kind, lookahead_token_kind);
@@ -99,7 +99,7 @@ namespace cdf {
 
 #define SAVE_LOOKAHEAD cdf::lookahead(yyla.kind())
 %}
-                        
+
 %code requires {
     namespace cdf
     {
@@ -107,7 +107,7 @@ namespace cdf {
     }
 }
 
-%code {    
+%code {
     // 
https://learnmoderncpp.com/2020/12/17/generating-c-programs-with-flex-and-bison-2/
     namespace cdf
     {
@@ -128,9 +128,9 @@ namespace cdf {
     }
   }
 }
-                        
+
 %define api.location.type {cbl_loc_t}
-                        
+
 %{
 #define COUNT_OF(X) (sizeof(X) / sizeof(X[0]))
 
@@ -206,7 +206,7 @@ void input_file_status_notify();
               const cdfval_t& value, bool override = false )
   {
     cdf_values_t& dictionary( cdf_dictionary() );
-    
+
     if( scanner_parsing() ) {
       if( ! override ) {
        if( dictionary.find(name) != dictionary.end() ) return false;
@@ -218,7 +218,7 @@ void input_file_status_notify();
   static void
   cdfval_off( const char name[] ) {
     cdf_values_t& dictionary( cdf_dictionary() );
-    
+
     if( scanner_parsing() ) {
       auto p = dictionary.find(name);
       if( p == dictionary.end() ) {
@@ -245,7 +245,7 @@ void input_file_status_notify();
   cdfval_t operator/( const cdfval_base_t& lhs, const cdfval_base_t& rhs );
   cdfval_t negate( cdfval_base_t lhs );
 
-  void cdf_unreachable(); 
+  void cdf_unreachable();
   void cdf_field_add( const cbl_loc_t&, const std::string& name, const 
cdfval_t& value );
   cbl_file_t * cdf_file( size_t program, const cbl_name_t name );
   size_t cdf_file_index( const cbl_file_t *file );
@@ -257,11 +257,11 @@ static char *display_msg;
 const char * keyword_str( int token );
 
 exception_turn_t exception_turn;
-                       
+
 bool
 apply_cdf_turn( const exception_turn_t& turn ) {
   cbl_enabled_exceptions_t& enabled_exceptions( cdf_enabled_exceptions() );
-  
+
   for( auto elem : turn.exception_files() ) {
     std::set<size_t> files(elem.second.begin(), elem.second.end());
     enabled_exceptions.turn_on_off(turn.enabled,
@@ -288,16 +288,16 @@ apply_cdf_turn( const exception_turn_t& turn ) {
 %printer { fprintf(stderr, "%s '%s'",
                   keyword_str($$.token),
                   $$.string? $$.string : "<nil>" ); } <cdfarg>
-// cppcheck-suppress invalidPrintfArgType_sint 
+// cppcheck-suppress invalidPrintfArgType_sint
 %printer { fprintf(stderr, "%ld '%s'",
                   (long)$$.number, $$.string? $$.string : "" ); } <cdfval>
-                        
+
 %type  <string>        NAME NUMSTR LITERAL PSEUDOTEXT
 %type  <string>        LSUB RSUB SUBSCRIPT
 %type  <cdfarg>        namelit name_any name_one
 %type  <string>        name subscript subscripts inof
 %token <boolean>  BOOL
-%token <number>  FEATURE 400  NUMBER 308  EXCEPTION_NAME 284    "EXCEPTION 
NAME"
+%token <number>  FEATURE 401  NUMBER 309  EXCEPTION_NAME 284    "EXCEPTION 
NAME"
 
 %type  <cdfval>        cdf_expr
 %type  <cdfval>        cdf_relexpr cdf_reloper cdf_and cdf_bool_expr
@@ -309,53 +309,53 @@ apply_cdf_turn( const exception_turn_t& turn ) {
 
 %type   <number>        cdf_stackable
 
-%token BY 520
-%token COPY 397
-%token CDF_DISPLAY 418    ">>DISPLAY"
-%token IN 638
+%token BY 521
+%token COPY 398
+%token CDF_DISPLAY 419    ">>DISPLAY"
+%token IN 639
 %token NAME 290
-%token NUMSTR 310    "numeric literal"
-%token OF 721
+%token NUMSTR 311    "numeric literal"
+%token OF 722
 %token PSEUDOTEXT 755
 %token REPLACING 777
-%token READY 405  TRACE 412  RESET 406
-%token LITERAL 303
-%token SUPPRESS 411
-
-%token LSUB 402    "("
-%token SUBSCRIPT 410  RSUB 407    ")"
-
-%token CDF_DEFINE 417    ">>DEFINE"
-%token CDF_IF 419    ">>IF"
-%token CDF_ELSE 420    ">>ELSE"
-%token CDF_END_IF 421    ">>END-IF"
-%token CDF_EVALUATE 422    ">>EVALUATE"
-%token CDF_WHEN 423    ">>WHEN"
-%token CDF_END_EVALUATE 424    ">>END-EVALUATE"
-
-%token ALL 484
-%token CALL_CONVENTION 425    ">>CALL-CONVENTION"
-%token COBOL_WORDS 414    ">>COBOL-WORDS"
-%token CDF_PUSH 428    ">>PUSH"
-%token CDF_POP 429    ">>POP"
-%token SOURCE_FORMAT 430    ">>SOURCE FORMAT"
-
-%token AS 502  CONSTANT 396  DEFINED 398
+%token READY 406  TRACE 413  RESET 407
+%token LITERAL 304
+%token SUPPRESS 412
+
+%token LSUB 403    "("
+%token SUBSCRIPT 411  RSUB 408    ")"
+
+%token CDF_DEFINE 418    ">>DEFINE"
+%token CDF_IF 420    ">>IF"
+%token CDF_ELSE 421    ">>ELSE"
+%token CDF_END_IF 422    ">>END-IF"
+%token CDF_EVALUATE 423    ">>EVALUATE"
+%token CDF_WHEN 424    ">>WHEN"
+%token CDF_END_EVALUATE 425    ">>END-EVALUATE"
+
+%token ALL 485
+%token CALL_CONVENTION 426    ">>CALL-CONVENTION"
+%token COBOL_WORDS 415    ">>COBOL-WORDS"
+%token CDF_PUSH 429    ">>PUSH"
+%token CDF_POP 430    ">>POP"
+%token SOURCE_FORMAT 431    ">>SOURCE FORMAT"
+
+%token AS 503  CONSTANT 397  DEFINED 399
 %type  <boolean>            DEFINED
-%token OTHER 733  PARAMETER_kw 403    "PARAMETER"
-%token OFF 722  OVERRIDE 404
+%token OTHER 734  PARAMETER_kw 404    "PARAMETER"
+%token OFF 723  OVERRIDE 405
 %token THRU 979
 %token TRUE_kw 848    "True"
 
-%token CALL_COBOL 426    "CALL"
-%token CALL_VERBATIM 427    "CALL (as C)"
+%token CALL_COBOL 427    "CALL"
+%token CALL_VERBATIM 428    "CALL (as C)"
 
-%token TURN 850  CHECKING 530  LOCATION 682  ON 724  WITH 877
+%token TURN 850  CHECKING 531  LOCATION 683  ON 725  WITH 877
 
 %left OR 980
 %left AND 982
 %right NOT 983
-%left '<'  '>'  _EQ 302    "EQUAL"  _NE 984  _LE 985  _GE 986
+%left '<'  '>'  _EQ 303    "EQUAL"  _NE 984  _LE 985  _GE 986
 %left '-'  '+'
 %left '*'  '/'
 %right NEG 988
@@ -509,7 +509,7 @@ cdf_define: CDF_DEFINE cdf_constant NAME as cdf_expr[value] 
override
                }
                ;
 cdf_constant:  %empty
-       |       CONSTANT 
+       |       CONSTANT
                 ;
 override:      %empty   { $$ = false; }
        |       OVERRIDE { $$ = true; }
@@ -542,7 +542,7 @@ cdf_push:       CDF_PUSH cdf_stackable {
                   case parser::token::YDF_CDF_DEFINE:  cdf_push_dictionary(); 
break;
                   case parser::token::YDF_COBOL_WORDS:         
cdf_push_current_tokens(); break;
                   case parser::token::YDF_SOURCE_FORMAT:
-                  default: cdf_unreachable(); 
+                  default: cdf_unreachable();
                   }
                 }
                 ;
@@ -553,7 +553,7 @@ cdf_pop:        CDF_POP cdf_stackable {
                   case parser::token::YDF_CDF_DEFINE:  cdf_pop_dictionary(); 
break;
                   case parser::token::YDF_COBOL_WORDS:         
cdf_pop_current_tokens(); break;
                   case parser::token::YDF_SOURCE_FORMAT:
-                  default: cdf_unreachable(); 
+                  default: cdf_unreachable();
                   }
                 }
                 ;
@@ -624,7 +624,7 @@ cdf_if:             CDF_IF cdf_cond_expr {
                ;
 
 cdf_evaluate:   CDF_EVALUATE cdf_expr
-       |       CDF_EVALUATE TRUE_kw 
+       |       CDF_EVALUATE TRUE_kw
                 ;
 
 cdf_eval_when: CDF_WHEN cdf_eval_obj
@@ -632,10 +632,10 @@ cdf_eval_when:    CDF_WHEN cdf_eval_obj
 
 cdf_eval_obj:  cdf_cond_expr
         |       cdf_expr THRU cdf_expr
-        |       OTHER 
+        |       OTHER
         ;
 
-cdf_cond_expr: BOOL 
+cdf_cond_expr: BOOL
        |       NAME DEFINED
                {
                   cdf_values_t& dictionary( cdf_dictionary() );
@@ -868,7 +868,7 @@ namelit:    name
        |       LITERAL { $$ = cdf_arg_t{parser::token::YDF_LITERAL, $1}; }
                ;
 
-name:          NAME                   
+name:          NAME
        |       name inof NAME
                {
                                  char *s = xasprintf( "%s %s %s", $1, $2, $3 );
@@ -895,7 +895,7 @@ subscripts: subscript
                  $$ = s;
                }
                ;
-subscript:     SUBSCRIPT 
+subscript:     SUBSCRIPT
        |       LSUB subscript RSUB
                {
                                  char *s = xasprintf( "%s%s%s", $1, $2, $3 );
@@ -907,15 +907,15 @@ subscript:        SUBSCRIPT
                ;
 
 as:            %empty
-       |       AS 
+       |       AS
                ;
 
 on:             %empty
-        |       ON 
+        |       ON
                 ;
 
 with:           %empty
-        |       WITH 
+        |       WITH
                 ;
 
 %%
@@ -1088,11 +1088,10 @@ cdfval_base_t::operator()( const cbl_loc_t& loc ) {
   // cppcheck-suppress returnTempReference
   return verify_integer(loc, *this) ? *this : zero;
 }
-  
+
 namespace cdf {
   void
   parser::error(cbl_loc_t const& loc, std::string const& msg) {
       error_msg(loc, msg.c_str());
   }
 }
-
diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y
index 2de650c70b85..500cd0f49b16 100644
--- a/gcc/cobol/parse.y
+++ b/gcc/cobol/parse.y
@@ -54,6 +54,9 @@
 
   class ast_op_t;
 
+  struct cbl_field_data_t;
+#include "semantic_token.h"
+
   struct coll_alphanat_t {
     const char *alpha, *national; 
   };
@@ -401,6 +404,7 @@ class locale_tgt_t {
                        NUMED     "NUMERIC-EDITED picture"
                        NUMED_CR  "NUMERIC-EDITED CR picture"
                        NUMED_DB  "NUMERIC-EDITED DB picture"
+%token  <lex_picture>       PICTURE
 %token  <number>        NINEDOT NINES NINEV PIC_P "PICTURE P symbol" ONES
 %token  <string>        SPACES _EQ "EQUAL"
 %token  <literal>       LITERAL
@@ -631,7 +635,7 @@ class locale_tgt_t {
 
                        PACKED_DECIMAL PADDING PAGE
                        PAGE_COUNTER "PAGE-COUNTER"
-                       PF PH PI PIC PICTURE
+                       PF PH PI PIC 
                        PLUS PRESENT_VALUE PRINT_SWITCH
                        PROCEDURES PROCEED PROCESSING
                        PROGRAM_ID "PROGRAM-ID"
@@ -1007,6 +1011,7 @@ class locale_tgt_t {
     struct cbl_field_t *field;
     struct { bool tf; cbl_field_t *field; } bool_field;
     struct { int token; cbl_field_t *cond; } cond_field;
+           lex_picture_t lex_picture;
     struct cbl_refer_t *refer;
            ast_op_t *ast_op;
     struct rel_term_type { bool invert; cbl_refer_t *term; } rel_term_t;
@@ -4459,7 +4464,9 @@ data_descr1:    level_name
                                 "NUMERIC DISPLAY or NUMERIC-EDITED, not %s",
                                 $field->name, cbl_field_type_str($field->type) 
);
                     }
-                    $field->data.picture = original_picture();
+                    if( ! $field->data.picture ) // began as numeric
+                      $field->data.picture = original_picture();
+                    gcc_assert($field->data.picture);
                   }
 
                   // SIGN clause valid only with "S" in picture
@@ -4921,6 +4928,21 @@ picture_clause: PIC signed PIC_P[fore] nines
                   }
                 } 
 
+        |       PICTURE
+                {
+                  cbl_field_t *field = current_field();
+                  const lex_picture_t& picture($1);
+                  field->codeset.set( picture.encoding );
+                  if( !field_type_update(field, picture.type, @PICTURE) ) {
+                   dbgmsg("new picture: %s", field_str(field));
+                    YYERROR;
+                  }
+                  field->set_attr(cbl_field_attr_t($PICTURE.attr));
+                  field->data.apply_picture(*picture.data);
+                  field->blank_initial(picture.data->capacity());
+                }
+        |       NO_CONDITION { YYERROR; }
+
         |       PIC alphanum_pic[nchar]
                 {
                   cbl_field_t *field = current_field();
@@ -13299,9 +13321,33 @@ current_tokens_t::tokenset_t::find( const cbl_name_t 
name, bool include_intrinsi
   return token;
 }
 
+/*
+ * Search the token strings, possibly including intrinsic functions.  Normally
+ * we're not interested in CDF names, unless the CDF is active.
+ */
 int
-keyword_tok( const char * text, bool include_intrinsics ) {
-  return cdf_tokens.find(text, include_intrinsics);
+keyword_tok( const char * name, bool include_intrinsics ) {
+  static const std::vector<tok_name_t> cdf_words
+#include "words/cdf.h"
+  static const std::vector<tok_name_t> intrinsic_words
+#include "words/intrinsic.h"
+  static std::vector<tok_name_t> cdf_only;
+  if( cdf_only.empty() ) {
+    std::set_difference(
+        cdf_words.begin(), cdf_words.end(),
+        intrinsic_words.begin(), intrinsic_words.end(),
+        std::back_inserter(cdf_only)
+    );
+  }
+    
+  std::array<char, 64> uname{};
+  std::transform(name, name + strlen(name) + 1, uname.begin(), ftoupper);
+
+  if( std::binary_search(cdf_only.begin(), cdf_only.end(), uname) ) {
+    return 0;
+  }
+  
+  return cdf_tokens.find(name, include_intrinsics);
 }
 
 static inline size_t
diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h
index 2dbf02eac632..ae056d4fc38a 100644
--- a/gcc/cobol/parse_ante.h
+++ b/gcc/cobol/parse_ante.h
@@ -648,9 +648,11 @@ struct arith_t {
  protected:
   static bool is_numeric( const cbl_loc_t& loc, const cbl_refer_t& r ) {
     if( r.field && ! ::is_numeric(r.field) ) {
-      error_msg(loc, "%qs (%s) is not numeric",
-                nice_name_of(r.field),
-                cbl_field_type_name(r.field->type));
+      if( r.field->type != FldInvalid ) {
+        error_msg(loc, "%qs (%s) is not numeric",
+                  nice_name_of(r.field),
+                  cbl_field_type_name(r.field->type));
+      }
       return false;
     }
     return true;
@@ -3694,6 +3696,11 @@ parser_subtract2(  const cbl_num_result_t& to,
   parser_subtract(to.refer, to.refer, from, to.rounded);
 }
 
+static bool
+valid_operands( const cbl_refer_t& src, const cbl_refer_t& tgt ) {
+  return ! (src.field->type == FldInvalid || tgt.field->type == FldInvalid);
+}
+
 static bool
 parser_move_carefully( const char */*F*/, int /*L*/,
                        tgt_list_t *tgt_list,
@@ -3708,23 +3715,25 @@ parser_move_carefully( const char */*F*/, int /*L*/,
       return false;
     }
 
-    if( is_index ) {
-      if( tgt.field->type != FldIndex && src.field->type != FldIndex) {
-        auto msg = xasprintf("invalid SET %s (%s) TO %s (%s): not a field 
index",
-                             name_of(tgt.field), 
cbl_field_type_name(tgt.field->type),
-                             name_of(src.field), 
cbl_field_type_name(src.field->type));
-        dialect_ok(src.loc, MfSetNumeric, msg);
-        free(msg);
-      }
-    } else {
-      if( ! valid_move( tgt.field, src.field ) ) {
-        if( src.field->type == FldPointer &&
-            tgt.field->type == FldPointer ) {
-          dialect_ok(src.loc, MfMovePointer, "MOVE POINTER");
-        } else {
-          error_msg(src.loc, "cannot MOVE %qs (%s) TO %qs (%s)",
-                    nice_name_of(src.field), 
cbl_field_type_name(src.field->type),
-                    nice_name_of(tgt.field), 
cbl_field_type_name(tgt.field->type));
+    if( valid_operands(src, tgt) ) {
+      if( is_index ) {
+        if( tgt.field->type != FldIndex && src.field->type != FldIndex) {
+          auto msg = xasprintf("invalid SET %s (%s) TO %s (%s): not a field 
index",
+                               name_of(tgt.field), 
cbl_field_type_name(tgt.field->type),
+                               name_of(src.field), 
cbl_field_type_name(src.field->type));
+          dialect_ok(src.loc, MfSetNumeric, msg);
+          free(msg);
+        }
+      } else {
+        if( ! valid_move( tgt.field, src.field ) ) {
+          if( src.field->type == FldPointer &&
+              tgt.field->type == FldPointer ) {
+            dialect_ok(src.loc, MfMovePointer, "MOVE POINTER");
+          } else {
+            error_msg(src.loc, "cannot MOVE %qs (%s) TO %qs (%s)",
+                      nice_name_of(src.field), 
cbl_field_type_name(src.field->type),
+                      nice_name_of(tgt.field), 
cbl_field_type_name(tgt.field->type));
+          }
         }
       }
     }
@@ -3737,10 +3746,10 @@ parser_move_carefully( const char */*F*/, int /*L*/,
   delete tgt_list;
   return true;
 }
-#define parser_move2(P, S) \
-        parser_move_carefully(__func__, __LINE__, (P), (S), false)
-#define parser_index(P, S) \
-        parser_move_carefully(__func__, __LINE__, (P), (S), true)
+#define parser_move2(P, S)                                      \
+  parser_move_carefully(__func__, __LINE__, (P), (S), false)
+#define parser_index(P, S)                                      \
+  parser_move_carefully(__func__, __LINE__, (P), (S), true)
 
 static void
 ast_set_pointers( const list<cbl_num_result_t>& tgts, cbl_refer_t src ) {
diff --git a/gcc/cobol/picture.cc b/gcc/cobol/picture.cc
index 965baa27afc1..dc988edecaa6 100644
--- a/gcc/cobol/picture.cc
+++ b/gcc/cobol/picture.cc
@@ -85,7 +85,6 @@ namespace picture_validation {
     numeric_e,
     numeric_ed_e,
     c_need_r_e,
-    crdb_e, 
     d_need_b_e,
     postdec_e,
     antedec_e,
@@ -102,7 +101,6 @@ namespace picture_validation {
     case antedec_e: return "antedec_e";
     case boolean_e: return "boolean_e";
     case c_need_r_e: return "c_need_r_e";
-    case crdb_e:  return "crdb_e";
     case d_need_b_e: return "d_need_b_e";
     case exponent_e: return "exponent_e";
     case invalid_e: return "invalid_e";
@@ -230,20 +228,21 @@ namespace picture_validation {
     { none_e,          'B',  alpha_ed_e },
     { none_e,          '0',  alpha_ed_e },
     { none_e,          '/',  alpha_ed_e },
-    { none_e,          '9',  antedec_e },   // 9 before V
     { none_e,          'N',  national_e },
-    { none_e,          'P',  none_e },
-    { none_e,          'S',  none_e },
+    { none_e,          '9',  antedec_e },   // 9 before V
+    { none_e,          'P',  antedec_e },
+    { none_e,          'S',  antedec_e },
     { none_e,          'V',  postdec_e, },  // V before 9
                        
-    { none_e,          '1',  antedec_e },
-    { antedec_e,       '1',  antedec_e },
+    { none_e,          '1',  boolean_e },
+    { boolean_e,       '1',  boolean_e },
 
     { alphabetic_e,    'A',  alphabetic_e },
     { alphabetic_e,    'B',  alpha_ed_e },
     { alphabetic_e,    '0',  alpha_ed_e },
     { alphabetic_e,    '/',  alpha_ed_e },
     { alphabetic_e,    'X',  alphanumeric_e },
+    { alphabetic_e,    '9',  alphanumeric_e },
     { alphabetic_e,    '$',  numeric_ed_e },
 
     { alphanumeric_e,  'A',  alphanumeric_e },
@@ -299,11 +298,16 @@ namespace picture_validation {
     { antedec_e,       'P',  numeric_e },
     { antedec_e,       'V',  numeric_e },
     { antedec_e,       'X',  alphanumeric_e },
+    { antedec_e,       '+',  numeric_ed_e },
+    { antedec_e,       '-',  numeric_ed_e },
     { antedec_e,       'C',  c_need_r_e },
     { antedec_e,       'D',  d_need_b_e },
 
     { antedec_e,       'Z',  numeric_ed_e },
     { antedec_e,       '*',  numeric_ed_e },
+    { antedec_e,       'B',  numeric_ed_e },
+    { antedec_e,       '0',  numeric_ed_e },
+    { antedec_e,       '/',  numeric_ed_e },
     { antedec_e,       '$',  numeric_ed_e },
     { antedec_e,       dot,  numeric_ed_e },
     { antedec_e,       com,  numeric_ed_e },
@@ -313,6 +317,7 @@ namespace picture_validation {
                        
     { numeric_e,       '9',  numeric_e },
     { numeric_e,       'P',  numeric_e },
+    { numeric_e,       'V',  numeric_e },
 
     { numeric_e,       'Z',  numeric_ed_e },
     { numeric_e,       '*',  numeric_ed_e },
@@ -416,12 +421,9 @@ namespace picture_validation {
       p_X     = hiword('X'), 
       p_Z     = hiword('Z'), 
 
-      p_boolean_e = p_one, 
-      p_alphabetic_e = p_A, 
       p_alphanumeric_e = (p_A | p_X | p_nine),
       p_b_0_slash_e = (p_B | p_zero | p_slash),
       p_alpha_ed_e = (p_alphanumeric_e | p_b_0_slash_e),
-      p_national_e = p_N,
       p_national_ed_e = (p_N | p_b_0_slash_e),
       p_numeric_e = (p_nine | p_P | p_S | p_V),
       // B P V Z 9 0 / , . + - CR DB * cs (CR/DB not in mask because at end)
@@ -430,60 +432,90 @@ namespace picture_validation {
                        p_comma | p_dot | p_plus | p_minus | p_star | p_cs),
     };
     uint64_t symbol_mask;
-    
-    bool is_boolean() const {
-      return 0 == (symbol_mask & ~p_boolean_e)
-        &&   0 != (symbol_mask &  p_boolean_e);
+
+    bool both( picsym_t a, picsym_t b ) const {
+      return (symbol_mask & (a | b)) == (a | b);
     }
-    bool is_alphabetic() const {
-      return 0 == (symbol_mask & ~p_alphabetic_e)
-        &&   0 != (symbol_mask &  p_alphabetic_e);
+    template <typename T>
+    bool only(T bits) const {
+      return symbol_mask == (symbol_mask & bits);
+    }
+
+    /*
+     * 13.18.40.3 Syntax rules FORMAT 1 
+     */
+    bool is_allowed( char ch ) const {
+      switch( ch ) {
+      case 'P':                       // no P in numeric-edited
+      case 'V':                       // no V in numeric-edited
+      case dot:                       // Neither P nor V with dot.
+        if( both(p_P, p_dot) ) {      // rule 17
+          error_msg(loc,  "%qc and %qc are mutually exclusive", 'P', dot);
+          return false;
+        }
+        if( both(p_V, p_dot) ) {      // rule 20
+          error_msg(loc,  "%qc and %qc are mutually exclusive", 'V', dot);
+          return false;
+        }
+        break;
+      case 'Z': case '*':             // Only blanks or stars
+        if( both(p_Z, p_star) ) {     // rule 21
+          error_msg(loc,  "%qc and %qc are mutually exclusive", 'Z', '*');
+          return false;
+        }
+        break;
+      }
+      return true;
     }
+
+    bool is_boolean() const    { return symbol_mask == p_one; }
+    bool is_alphabetic() const { return symbol_mask == p_A; }
+    bool is_national() const   { return symbol_mask == p_N; }
+    
     bool is_alphanumeric() const {
-      return 0 == (symbol_mask & ~p_alphanumeric_e)
-        &&   0 != (symbol_mask &  p_alphanumeric_e);
+      auto bits = symbol_mask & p_alphanumeric_e;
+      return 0 < bits && symbol_mask == bits;
     }
     bool is_alpha_ed() const {
-      return 0 == (symbol_mask & ~p_alpha_ed_e)
+      return only(p_alpha_ed_e)
         &&   0 != (symbol_mask & p_alphanumeric_e)
         &&   0 != (symbol_mask & p_b_0_slash_e);
     }
-    bool is_national() const {
-      return 0 == (symbol_mask & ~p_national_e)
-        &&   0 != (symbol_mask &  p_national_e);
-    }
     bool is_national_ed() const {
-      return 0 == (symbol_mask & ~p_national_ed_e)
-        &&   0 != (symbol_mask & p_national_e)
+      return only(p_national_ed_e)
+        &&   0 != (symbol_mask & p_N)
         &&   0 != (symbol_mask & p_b_0_slash_e);
     }
     bool is_numeric() const {
-      return 0 == (symbol_mask & ~p_numeric_e)
+      return only(p_numeric_e)
         &&   0 != (symbol_mask &  p_nine)
         &&   0 != (symbol_mask &  p_numeric_e);
     }
     bool is_numeric9_ed() const {
-      return 0 == (symbol_mask & ~p_numeric_ed_e)
+      return only(p_numeric_ed_e)
         &&   0 != (symbol_mask & p_nine)
         &&   0 != (symbol_mask & p_numeric_ed2_e);
     }
     bool is_numeric_ed() const {
-      return 0 == (symbol_mask & ~p_numeric_ed_e)
+      return only(p_numeric_ed_e)
         && ( 0 != (symbol_mask & (p_Z | p_star))
              || two_signs()
              || is_numeric9_ed() );
     }
 
+    bool two_signs() const { return 1 < nplus || 1 < nminus; }
+
     state_t pic_state; // to lookup sequence validity
 
     uint64_t picsym_set( char ch ) {
       switch(ch) {
+      case '$': return symbol_mask |= p_cs;
+      case '*': return symbol_mask |= p_star;
       case '+': return symbol_mask |= p_plus;
+      case ',': return symbol_mask |= p_comma;
       case '-': return symbol_mask |= p_minus;
       case '.': return symbol_mask |= p_dot;
-      case ',': return symbol_mask |= p_comma;
       case '/': return symbol_mask |= p_slash;
-      case '$': return symbol_mask |= p_cs;
       case '0': return symbol_mask |= p_zero;
       case '1': return symbol_mask |= p_one;
       case '9': return symbol_mask |= p_nine;
@@ -505,12 +537,13 @@ namespace picture_validation {
 
     bool picsym_seen( char ch ) const {
       switch(ch) {
+      case '$': return 0 < (symbol_mask & p_cs);
+      case '*': return 0 < (symbol_mask & p_star);
       case '+': return 0 < (symbol_mask & p_plus);
+      case ',': return 0 < (symbol_mask & p_comma);
       case '-': return 0 < (symbol_mask & p_minus);
       case '.': return 0 < (symbol_mask & p_dot);
-      case ',': return 0 < (symbol_mask & p_comma);
       case '/': return 0 < (symbol_mask & p_slash);
-      case '$': return 0 < (symbol_mask & p_cs);
       case '0': return 0 < (symbol_mask & p_zero);
       case '1': return 0 < (symbol_mask & p_one);
       case '9': return 0 < (symbol_mask & p_nine);
@@ -527,33 +560,149 @@ namespace picture_validation {
       case 'X': return 0 < (symbol_mask & p_X);
       case 'Z': return 0 < (symbol_mask & p_Z);
       }
+      return false;
     }
 
+    bool picsym_settable( char ch ) const {
+      switch(ch) {
+      case 'V':
+        return ! picsym_seen(ch);
+      case 'P':
+        return ch == prior_ch || ! picsym_seen(ch);
+      }
+      return true;
+    }
+    
+    cbl_loc_t loc;
     char prior_ch;
     const char decimal_point;
-    int nplus, nminus;
+    int np, nplus, nminus, ndollar;
+    uint64_t field_attr;
     cbl_field_data_t field_data;
+    struct contiguous_t {
+      char ch;
+      int n;
+      explicit contiguous_t( char ch ) : ch(ch),  n(1) {}
+      contiguous_t& operator++() { n++; return *this; }
+    };
+    std::vector<contiguous_t> contiguous;
+
+    // 13.18.40.3 Syntax rules #27 No more than 1 of certain character
+    // sequences.  This function misinterprets the rule.  The rule is not that
+    // e.g. $$,$$ is invalid.  the rule is that the list items are mutually
+    // exclusive, $$Z is invalid.  Keeping the structure for now in case 
needed. 
+#if 0
+    bool contiguous_ok(char ch) const {
+      int n = 0;
+      switch(ch) {
+      case '+': case '-': case '$':
+        n = 2;
+        break;
+      case 'Z': case '*':
+        n = 1;
+        break;
+      }
+      if( n ) {
+        n = std::count_if( contiguous.begin(), contiguous.end(),
+                           [ch, n]( const auto& elem ) {
+                             return ch == elem.ch && n <= elem.n;
+                           } );
+      }
+      return n < 2;
+    }
+#endif
+    bool add_contiguous(char ch) {
+      if( contiguous.empty() ) {
+        contiguous.push_back( contiguous_t(ch) );
+        return true;
+      }
+      auto& last( contiguous.back() );
+      if( ch == last.ch ) {
+        ++last;
+      } else {
+        contiguous.push_back( contiguous_t(ch) );
+      }
+      return true; // contiguous_ok(ch);
+    }
+    
    public:
     const char *bad_repeat;
 
-    constraint_t()
+    constraint_t(const cbl_loc_t& loc, const cbl_name_t picture)
       : symbol_mask(0)
       , pic_state(none_e)
+      , loc(loc)
       , prior_ch('\0')
       , decimal_point(symbol_decimal_point())
-      , nplus(0), nminus(0)
+      , np(0), nplus(0), nminus(0), ndollar(0)
+      , field_attr(0)
       , bad_repeat(nullptr)
-    {}
-    constraint_t& append( char ch, size_t len ) {
+    {
+      // Trim trailing punctuation from picture for later revalidation, because
+      // we do. 
+      auto pic = xstrdup(picture);
+      auto pend = pic + strlen(pic);
+      if( pic < --pend ) {
+        switch( *pend ) {
+        case ';': case ',': case '.':
+          *pend = '\0';
+          break;
+        }
+      }
+
+      field_data.picture = pic;
+    }
+    bool append( char ch, size_t len ) {
+      if( prior_ch == '\0' ) {
+        switch(ch) {
+        case 'S': case '+': case '-': 
+          field_attr |= signable_e;
+        }
+      }
+      if( prior_ch == '.' && ch == '.' ) return false;
+      if( ! add_contiguous(ch) )         return false;
+
+      if( ! picsym_settable(ch) ) { return false; }
       picsym_set(ch);
+      // emits message about invalid combinations
+      if( ! is_allowed(ch) ) { return false; }
+      
       prior_ch = ch;
-      if( ch == '+' ) nplus++;
-      if( ch == '-' ) nminus++;
-      update_capacity(1 + len);
+      add_capacity(len? len : 1);
       observe_the_dot(ch);
-      return *this;
+      loc++;
+      return true;
     }
+    inline void move_caret( int n ) { loc += n; }
+    bool has_s_star() const { return both(p_S, p_star); }
+    
+    void extra_dot( size_t pos ) {
+      if( field_data.picture[pos] != '\0') {
+        assert(field_data.picture[pos+1] == '\0');
+        assert(field_data.picture[pos] == '.');
+        const_cast<char*>(field_data.picture)[pos] = '\0';
+      }
+    }
+
+    bool repeatable() const {
+      switch(prior_ch) {
+      case '1':
+      case 'P':
+      case 'A': case 'X': case '9':
+      case 'N':
+      case 'U':
+      case 'Z': case '*':
+      case 'B': case '0': // B and 0 but not slash
+      case '$': case '+': case '-': 
+        return true;
+      }
+      return false;
+    }
+    
     char prior() const { return prior_ch; }
+    cbl_field_data_t data() const { return field_data; }
+    uint64_t attr() const { return field_attr; }
+    const cbl_loc_t& location() const { return loc; }
 
     state_t picture_state(state_t state) { return pic_state = state; }
     state_t picture_state() const { return pic_state; }
@@ -569,14 +718,34 @@ namespace picture_validation {
       return invalid_e;
     }
 
-    bool two_signs() const { return 1 < nplus || 1 < nminus; }
+    void maybe_signable( char ch ) {
+      switch(TOUPPER(ch)) {
+      case '+': case '-': 
+        field_attr |= signable_e;
+      }
+      dbgmsg("%s: '%c', %ssignable", __func__,
+             ch, (field_attr & signable_e)? "" : "not ");
+    }
 
+    void maybe_signable( state_t state ) {
+      switch(state) {
+      case c_need_r_e:
+      case d_need_b_e:
+        maybe_signable('+');
+      default:
+        break;
+      }
+    }
+    
     /*
      * The followers table is sensitive to whether we've seen decimal point, 
and
      * whether we're in an exponent.  That reflects the duplicate column
      * headings in ISO Table 10.
      */
-    bool day_follows_night( char ch ) {
+    bool day_follows_night( char ch ) const {
+      const static std::string domain("*+,-./019ABENPSVXZCRDB");
+      return std::string::npos != domain.find(ch);
+      
       auto p = followers.find( follow_key_t {pic_state, prior_ch} );
       if( p != followers.end() ) {
         const auto& candidates(p->second);
@@ -586,17 +755,8 @@ namespace picture_validation {
       return false;    
     }
 
-    void prior_repeats( int n ) {
-      if( prior_ch != 'P' ) {
-        update_capacity(n);
-      }
-    }
+    inline bool first_dollar( char ch ) { return ch == '$' && ndollar == 0; }
 
-  protected:
-    void observe_the_dot( char ch ) {
-      if( pic_state == none_e ) pic_state = antedec_e;
-      if( ch == decimal_point || ch == 'V' ) pic_state = postdec_e;
-    }
     /*
      * 1) Every character except V adds to the capacity, with the caveat that
      *    the first CURRENCY PICTURE character adds the length of the CURRENCY
@@ -610,17 +770,47 @@ namespace picture_validation {
      * all of the regression tests assume that V, if there, adds one.  I would
      * really rather attack the V change when everything is working.
      */
-    void update_capacity( int n = 1) {
-      static const std::string nonsize( "PVCRDB" );
-      
-      if( std::string::npos == nonsize.find(prior_ch) ) {
+    void add_capacity(int n) {
+      static const std::string nonsize( "P" );  // do not exclude V from 
capacity for now
+      if( prior_ch == 'P' ) {
+        np += n;
+        field_attr |= scaled_e;
+        // P in front has positive rdigit less one; P aft is negative rdigit.
+        int ndigit = only(p_P | p_S)? (1 < np? n : n - 1) : -n;
+        field_data.rdigits += ndigit;
+      } else {
         field_data.add_capacity(n);
-        if( pic_state == postdec_e ) {
-          field_data.rdigits += n;
-        }
+        if( digital() ) {
+          field_data.digits += n; 
+          if( pic_state == postdec_e ) {
+            field_data.rdigits += n;
+          }
+        } else { n = 0; } // for debug
       }
+      dbgmsg("%s: '%c', added %d: {%u, %u,%d}", __func__, prior_ch, n,
+             field_data.capacity(), field_data.digits, field_data.rdigits);
     }
 
+  protected:
+    void observe_the_dot( char ch ) {
+      if( pic_state == none_e ) pic_state = antedec_e;
+      if( ch == decimal_point || ch == 'V' ) pic_state = postdec_e;
+    }
+    bool digital() {
+      switch(prior_ch) {
+      case '9': case 'Z': case '*':
+        return true;
+      case 'V':
+        return true;
+      case '+':
+        return 0 < nplus++;
+      case '-':
+        return 0 < nminus++;
+      case '$':
+        return 0 < ndollar++;
+      }
+      return false;
+    }
   };
 } // end namespace
 
@@ -646,7 +836,7 @@ seek_paren( const char *p, const char *epicture ) {
   return p;
 }
 
-static bool verbose = false;
+static bool verbose = true;
 
 // Dot as last character is period separator because the lexer defines
 // end-of-picture as a space.
@@ -661,76 +851,187 @@ end_of_picture( const char *p, const char *epicture ) {
   return p == epicture;
 }
 
-std::pair<const char *, state_t>
-is_valid_picture(const char picture[]) {
-  picture_validation::constraint_t constraint;
+#include "semantic_token.h"
+class picture_t : public lex_picture_t {
+  state_t picture_state;
+ public:
+  picture_t()
+    : picture_state(picture_validation::invalid_e)
+  {
+    attr = none_e;
+    pos = 0;
+    blank_when_zero_ok = true; 
+    type = FldInvalid;
+    encoding = current_encoding('A');
+    data = new cbl_field_data_t;
+  }
+
+  void state( state_t state ) {
+    picture_state = state;
+    type = field_type();
+    encoding = field_encoding();
+    if( picture_state == picture_validation::alphabetic_e ) {
+      attr |= uint64_t(all_alpha_e);
+    }
+  }
+
+  picture_t&  update( const picture_validation::constraint_t& constraint )
+  {
+    blank_when_zero_ok = ! constraint.has_s_star();
+    attr = constraint.attr();
+    *data = constraint.data();
+    return *this;
+  }
+
+ protected:
+  cbl_encoding_t field_encoding() const {
+    switch(picture_state) {
+    case picture_validation::unicode_e:
+      cbl_unimplemented("Unicode pictures not implemented");
+      return current_encoding('A');
+    case picture_validation::national_e:
+      return current_encoding('N');
+    default: // alphanumeric by construction
+      return current_encoding('A');
+      break;
+    }
+  }
+  cbl_field_type_t field_type() const  {
+    switch(picture_state) {
+    case picture_validation::alphabetic_e:
+    case picture_validation::unicode_e:
+    case picture_validation::alphanumeric_e:
+    case picture_validation::national_e:
+      return FldAlphanumeric;
+    case picture_validation::alpha_ed_e:
+    case picture_validation::national_ed_e:
+      return FldAlphaEdited;
+    case picture_validation::antedec_e:
+    case picture_validation::numeric_e:
+      return FldNumericDisplay;
+    case picture_validation::numeric_ed_e:
+      return FldNumericEdited;
+
+    case picture_validation::invalid_e:
+    case picture_validation::none_e:
+    case picture_validation::boolean_e:
+    case picture_validation::c_need_r_e:
+    case picture_validation::d_need_b_e:
+    case picture_validation::postdec_e:
+    case picture_validation::exponent_e:
+    case picture_validation::accept_e:
+      break;
+    }
+    return FldInvalid;
+  }
+};
+
+lex_picture_t  
+is_valid_picture(const cbl_loc_t& loc, const char picture[]) {
+  picture_validation::constraint_t constraint(loc, picture);
+  
   const picture_validation::automaton_matrix_t&
     automaton = picture_validation::prepare_automaton();
 
   if( ! picture ) {
-    return {picture, picture_validation::invalid_e};
+    return lex_picture_t();
   }
-  const char *epicture = picture + strlen(picture);
 
   state_t state = picture_validation::none_e;
-  for( auto p=picture; p < epicture; p++ ) {
-    // Advance lookahead past any count, which might be name.
+  const char *p = picture, *epicture = picture + strlen(picture);
+  picture_t output;
+  /*
+   * If a currency has a symbol, width is set to its length until appended,
+   * then becomes 1.
+   */
+  size_t width = 0; 
+
+  for( ; p < epicture; p++, output.pos++ ) {
+    // Advance lookahead past any count, which might be a name.
     // No picture begins with a '('. 
-    if( picture < p && *p == '(' && p+1 < epicture  ) {
-      const char *paren = p;
-      p = seek_paren(p, epicture);
-      if( *p != ')' ) {
-        return {p, picture_validation::invalid_e};
-      }
-      if( p[-1] == '(' ) { // pic 9() is invalid
-        return {p, picture_validation::invalid_e};
-      }
-      p++;
-      auto result = repeat_count(--paren);
-      int len = result.first;
-      if( len == 0 ) {
-        dbgmsg("%s: odd zero repeat_count for '%s'", __func__, paren);
-        constraint.bad_repeat = paren;
-        return {paren, picture_validation::invalid_e};
+    if( *p == '(' && p+1 < epicture  ) {
+      if( constraint.repeatable() ) {
+        const char *paren = p;
+        p = seek_paren(p, epicture);
+        if( *p != ')' ) {
+          output.pos += p - paren;
+          return output;
+        }
+        if( p[-1] == '(' ) { // pic 9() is invalid
+          output.pos += p - paren;
+          return output;
+        }
+        constraint.move_caret(p - paren);
+        p++;
+        auto result = repeat_count(constraint.location(), --paren);
+        int count = result.first;
+        if( count == 0 ) {
+          dbgmsg("%s: odd zero repeat count for '%s'", __func__, paren);
+          constraint.bad_repeat = paren; // pointless, not used
+          return output;
+        }
+        constraint.add_capacity(--count);
+        output.pos = p - picture;
       }
-      constraint.prior_repeats(len);
     }
 
-    if( end_of_picture(p, epicture) ) break;
+    // We may reach end of picture prematurely if it ends with ')'.
+    if( end_of_picture(p, epicture) ) {
+      epicture = p;
+      break;
+    }
 
-    // Now p is fixed, but ch might be a currency symbol
     char ch = TOUPPER(*p);
     
     // Is the current character ever allowed to follow the prior? 
-    size_t currency_len = 0;
-    if( ! constraint.day_follows_night(ch) ) {
+    if( ! constraint.day_follows_night(ch) || constraint.first_dollar(ch)) {
       const char *currency = symbol_currency(ch);
       if( currency ) {
         ch = '$';
-        currency_len = strlen(currency);
+        width = width == 0? strlen(currency) : 1;
       } else {
-        if( verbose ) 
-          fprintf(stderr,  "no %2zu: %c -> %c (%s)\n",
-                  p - picture, constraint.prior(), ch,
-                  picture_validation::state_str(constraint.picture_state()) );
-        return {p, picture_validation::invalid_e};
+        dbgmsg("%s:%d: no %2lu: %c -> %c (%s)\n", __func__, __LINE__, 
+               (unsigned long)(p - picture), constraint.prior(), ch,
+               picture_validation::state_str(constraint.picture_state()));
+        return output;
+      }
+      if( verbose ) {
+        dbgmsg("ok %2lu: %c (next: %s)\n", (unsigned long)(p - picture), ch,
+               picture_validation::state_str(state));
       }
     }
 
     // Update constraint record and advance to the next state.
-    constraint.append(ch, currency_len);
-    state = automaton[state][ch];
-
-    if( verbose ) {
-      fprintf(stderr,  "ok %2zu: %c (next: %s)\n",
-              p - picture, ch, picture_validation::state_str(state));
-    }
+    const auto old_state = picture_validation::state_str(state);
+    if( constraint.append(ch, width) ) {
+      if( 1 < width ) width = 1;
+      state = automaton[state][ch];
+      constraint.maybe_signable(state);
+    } else {
+      state = picture_validation::invalid_e;
+    } 
+      
     if( state == picture_validation::invalid_e ) {
-      return {p, picture_validation::invalid_e};
+      dbgmsg("%s:%d: automaton has no transition for %s '%c'",
+             __func__, __LINE__, old_state, ch);
+      return output;
     }
   }
 
-  return {epicture, constraint.state()};
+  assert( p == epicture );
+
+  if( picture < p ) {
+    char ch = p == epicture? p[-1] : p[0];
+    constraint.maybe_signable(ch);
+  }
+
+  output.state(state);
+  output.update(constraint);
+
+  dbgmsg("%s:%d: decided on %s", __func__, __LINE__,
+         cbl_field_type_str(output.type));
+
+  return output;
 }
 
 #ifdef COBOL_PICTURE
diff --git a/gcc/cobol/scan.l b/gcc/cobol/scan.l
index a295a3fbadc7..470b5d3a8398 100644
--- a/gcc/cobol/scan.l
+++ b/gcc/cobol/scan.l
@@ -75,9 +75,6 @@ namespace picture_validation {
   };
 }
 
-std::pair<const char *, picture_validation::state_t>
-is_valid_picture( const char picture[] );
-
 static const char *
 crdb_maybe( const char *p )  {
   char candidate[3] = { TOUPPER(p[-1]), TOUPPER(p[0]) };
@@ -85,18 +82,24 @@ crdb_maybe( const char *p )  {
   return 1 == endings.count(candidate)? --p : p;
 }
 
+static const char *
+picture_at() {
+  std::reverse_iterator<const char*> end(yytext), beg(yytext + yyleng);
+  auto pos = std::find(beg, end, 0x20);
+  auto picture = pos.base();
+  dbgmsg("%s: picture is '%s'", __func__, picture);
+  return picture;
+}
+
 static size_t
-is_valid_picture() {
-    std::reverse_iterator<const char*> end(yytext), beg(yytext + yyleng);
-    auto pos = std::find(beg, end, 0x20);
-    auto picture = pos.base();
+old_valid_picture(){
+    auto picture = picture_at();
     dbgmsg("%s: picture is '%s'", __func__, picture);
     
-    auto result = is_valid_picture(picture);
+    auto result = is_valid_picture(yylloc, picture);
 
-    if( 0 != (result.second & picture_validation::invalid_e) ) {
-      assert(yytext < result.first);
-      auto p = crdb_maybe(result.first);
+    if( result.valid() ) {
+      auto p = crdb_maybe( yytext + result.pos );
       auto loc(yylloc);
       if( loc.first_line == loc.last_line ) {
         auto error_col = p - yytext;
@@ -1297,9 +1300,51 @@ USE({SPC}FOR)?           { return USE; }
                        }
 
   PIC(TURE)?({SPC}IS)?{SPC}{PICTURE} {
-                                 auto pos = is_valid_picture();
-                                 myless(pos);
-                                 yy_push_state(picture); return PIC;
+                                 const auto nerror = parse_error_count();
+                                  auto end_dot = yyleng - 1;
+                                 auto p = picture_at();
+                                  auto loc(yylloc);
+                                  loc.first_column += (p - yytext);
+                                 const auto& pic = is_valid_picture(loc, p);
+                                  switch( pic.type ) {
+                                  case FldAlphaEdited:
+                                  case FldNumericEdited:
+                                    ////pic.dump();
+                                    yylval.lex_picture = pic;
+                                    if( yytext[end_dot] == '.' )  {
+                                      myless(end_dot);
+                                    }
+                                    return PICTURE;
+                                  case FldInvalid:
+                                    if( nerror == parse_error_count() ) {
+                                      if( *p == '1' ) {
+                                        cbl_unimplemented_at(loc, "BOOLEAN 
PICTURE %qs", p);
+                                      } else {
+                                        loc += pic.pos;
+                                        error_msg(loc, "invalid %qc at %u in 
PICTURE %qs",
+                                                  p[pic.pos], 
unsigned(pic.pos), p);
+                                      }
+                                    }
+                                    if( yytext[end_dot] == '.' )  {
+                                      myless(end_dot);
+                                    }
+                                    return NO_CONDITION;
+                                    break;
+                                  default:
+                                    if( nerror < parse_error_count() ) {
+                                      if( yytext[end_dot] == '.' )  {
+                                        myless(end_dot);
+                                        dbgmsg("picture is %s, %u error",
+                                               cbl_field_type_str(pic.type),
+                                               unsigned(nerror));
+                                        return NO_CONDITION;
+                                      }
+                                    }
+                                    break;
+                                  }
+                                 myless(p - yytext);
+                                 yy_push_state(picture);
+                                  return PIC;
                                 }
 
   ANY                          { return ANY; }
@@ -1622,6 +1667,7 @@ USE({SPC}FOR)?            { return USE; }
                         tmpstring = NULL; pop_return LITERAL; }
 }
 
+
   /* These appear only in ISO list of CDF reserved words */
   /* DE-EDITING                { return DE_EDITING; } */
   /* EXTERNAL-FILE-FILE-STATUS         { return EXTERNAL_FILE_FILE_STATUS; } */
diff --git a/gcc/cobol/scan_ante.h b/gcc/cobol/scan_ante.h
index f87db5657035..99387eae60c9 100644
--- a/gcc/cobol/scan_ante.h
+++ b/gcc/cobol/scan_ante.h
@@ -727,7 +727,7 @@ ndigit(int len, const char **pleft = nullptr) {
     n++;
     if( p[1] == model ) continue;
 
-    std::pair<int,int> result = repeat_count(p);
+    std::pair<uint32_t, int> result = repeat_count(p);
     int count = result.first, pos = result.second;
     
     if( pos == -1 ) {
@@ -758,383 +758,6 @@ picset( int token, int leng = yyleng ) {
   return token;
 }
 
-/**
-## Script and data to produce picture_t::followers.
-## Based on ISO Table 10. 
-#! /usr/bin/awk -f
-
-BEGIN  {
-  str = "B0/ , . + +- +- CR/DB cs cs Z* Z* + + cs cs 9 AX S V P P 1 N E"
-  split(str, cols)
-}
-
-$1 ~ /CR|DB|cs/ { next }
-
-0 && !nlines++ {
-  for( i=0; i < length(cols); i++ ) {
-    print i, cols[i], "'" $i "'"
-  }
-}
-
-$field == "x" {
-  if( ! nout++ ) {
-    printf "%2d: %5s: \"", field, cols[field - 1]
-  }
-
-  gsub(/^ +| +$/, "", $1) 
-  printf "%s", $1
-}
-
-END {
-  if( ! nout++ ) {
-    printf "%2d: %5s: \"", field, cols[field - 1]
-  }
-  print "\""
-}
-
-B  x x x - x - - x - x x x x x x x x - x - x - x
-0  x x x - x - - x - x x x x x x x x - x - x - x
-/  x x x - x - - x - x x x x x x x x - x - x - x
-,  x x x - x - - x - x x x x x x x - - x - x
-.  x x - - x - - x - x - x - x - x
-+  - - - - - - - - - - - - - - - - - - - - - - - x
-+
-–
-+  x x x - - - - x x x x - - x x x - - x x x
-CR x x x - - - - x x x x - - x x x - - x x x
-DB x x x - - - - x x x x - - x x x - - x x x
-cs - - - - x
-cs x x x - x - - - - x x - - - - x - - x x x
-
-Z  x x - - x - - x - x
-*  x x - - x - - x - x
-Z  x x x - x - - x - x x - - - - - - - x - x
-*  x x x - x - - x - x x - - - - - - - x - x
-+  x x - - - - - x - - - x
-–  x x - - - - - x - - - x
-+  x x x - - - - x - - - x x - - - - - x
-–  x x x - - - - x - - - x x - - - - - x
-cs x x - - x - - - - - - - - x
-cs x x x - x - - - - - - - - x x - - - x
-
-9  x x x x x - - x - x - x - x - x x x x - x - - x
-A  x - - - - - - - - - - - - - - x x
-X  x - - - - - - - - - - - - - - x x
-S 
-V  x x - - x - - x - x - x - x - x - x - x
-P  x x - - x - - x - x - x - x - x - x - x
-P  - - - - x - - x - - - - - - - - - x x - x
-1  - - - - - - - - - - - - - - - - - - - - - x
-N  x - - - - - - - - - - - - - - - - - - - - - x
-E  x x x - x - - - - - - - - - - x
-**/
-
-class picture_t {
-  static const char dot = '.', comma = ',';
-
-  typedef std::vector<std::string> followings_t;
-  static const std::map <char, followings_t> followers;
-  
-  const char * const begin;
-  const char *p, *pend; 
-  size_t pos;
-  struct exclusions_t { // Nonzero if set, > 1 is false.
-    // crdb means CR/DB or +/-.
-    // pluses means 2 or more consecutive '+'.
-    // minuses means 2 or more consecutive '-'.
-    // "21) The symbol 'Z' and the symbol '*' are mutually exclusive "
-    // stars means '*' or Z.
-    unsigned short int crdb, currency, dot, pluses, minuses, stars, zzz;
-    exclusions_t()
-      : crdb(0), currency(0), dot(0), pluses(0), minuses(0), stars(0)
-    {}
-  } exclusions;
-  cbl_loc_t loc;
-  
-  bool is_crdb() const { // input must be uppercase for CR/DB
-    if( p[0] == 'C' || p[0] == 'D' ) {
-      char input[3] = { p[0], p[1] };
-      return ( 0 == strcmp(input, "CR") || 0 == strcmp(input, "DB") );
-    }
-    return false;
-  }
-
-  const char * match_paren( const char *paren ) const {
-    gcc_assert(paren[0] == '(');  // start with opening paren
-    paren = std::find_if( paren, pend,
-                          []( char ch ) {
-                            return ch == '(' || ch == ')';
-                          } );
-    if( *paren == '(' ) return nullptr; // no nesting
-    if( paren == pend ) return nullptr;
-    return ++paren;
-  }
-
-  const char * next_not( char ch ) const {
-    return std::find_if( p, pend,
-                         [ch = TOUPPER(ch)]( char next ) {
-                           return ch != next;
-                         } );
-  }
-
-  const char * valid_next( const char *p, const std::string& valid ) const {
-    if( p == pend || p + 1 == pend ) return pend;
-    if( p[1] == '(' ) {
-      return match_paren(++p);
-    }
-    auto pv = std::find(valid.begin(), valid.end(), TOUPPER(p[1]));
-    return pv != valid.end()? ++p : nullptr;
-  }
-  const char * valid_next( const char *p,
-                           bool first = true, char ch = '\0' ) const {
-    if( p == pend || p + 1 == pend ) return pend;
-    if( p[0] == '(' ) {
-      if( (p = match_paren(p)) == nullptr ) return nullptr;
-    }
-    if( p[0] == '(' ) return nullptr;  // consecutive parentheses
-    
-    int index = first? 0 : 1;
-    if( !ch ) ch = *p;   // use current character unless overridden
-    auto valid = followers.find(TOUPPER(ch));
-    if( valid == followers.end() ) {
-      cbl_loc_t loc(yylloc);
-      loc.first_column += int(p - begin);
-      error_msg( loc, "PICTURE: strange character %qc, giving up", ch );
-      return nullptr;
-    }
-    return valid_next(p, valid->second[index]);
-  }
-
-  const char * start() { // start modifies exclusions, but not p
-    auto pnext = p;
-
-    switch(TOUPPER(p[0])) {
-    case comma: case dot:
-      // use decimal_is_comma()
-      //  4:     .: "B0/,+Z*+-9E"
-      exclusions.dot++;
-      pnext = valid_next(p, "B0/,+Z*+-9E");
-      break;
-    case '+': case '-':
-      //  6:    +-: "B0/,.Z*Z*9VPPE"
-      exclusions.crdb++;
-      pnext = next_not(p[0]);
-      if( p + 1 < pnext ) {
-        exclusions.pluses++;
-      }
-      pnext = valid_next(--pnext, "B0/,.Z*Z*9VPPE");
-      break;
-    case 'Z': case '*': 
-      exclusions.stars++;
-      pnext = next_not(p[0]);
-      break;
-    case 'S':
-      // 19:     S: "9VP"
-      pnext = valid_next(p, "9VP");
-      break;
-    }
-
-    /*
-     * "For fixed editing sign control, the currency symbol, when used, shall
-     * be either the leftmost symbol in character-string-1, optionally preceded
-     * by one of the symbols '+' or '-' "
-     */
-    if( pnext ) {
-      if( p == pnext || p[0] == '+' || p[0] == '-' ) {
-        if( symbol_currency(*pnext) ) {
-          exclusions.currency++;
-          pnext = next_not(*pnext);
-          pnext = valid_next(--pnext, true, '$');
-        }
-      }
-    }
-    
-    return pnext;
-  }
-
-  const char * next() { // modify state; do not modify position
-    auto pnext = p;
-    auto loc(picture_t::loc);
-    loc.first_column += int(p - begin);
-
-    if( is_crdb() ) {
-      if( exclusions.crdb++ ) {
-        error_msg( loc, "PICTURE: CR/DB and %c/%c may appear only once", '+', 
'-' );
-        return nullptr;
-      }
-      if( p + 2 != pend ) { 
-        error_msg( loc, "PICTURE: CR/DB must appear at the end" );
-        return nullptr;
-      }
-      return pend;
-    }
-
-    if( symbol_currency(p[0]) ) {
-      if( false && exclusions.currency++ ) { // not enforced
-        error_msg( loc, "PICTURE: CURRENCY SYMBOL sequence may appear at most 
once" );
-        return nullptr;
-      }
-      return valid_next(p, ! exclusions.dot, '$');
-    }
-
-    switch(TOUPPER(p[0])) {
-    case '(':
-      return match_paren(p);
-      break;
-    case 'B': case '0': case '/':
-      pnext = valid_next(p);
-      break;
-    case comma: 
-      if( decimal_is_comma() ) {
-        if( exclusions.dot++ ) {
-          error_msg( loc, "PICTURE: %qc: may appear at most once", p[0] );
-          return nullptr;
-        }
-        pnext = valid_next(p, true, dot);
-      } else {
-        pnext = valid_next(p);
-      }
-      break;
-    case dot: 
-      if( p + 1 == pend ) {
-        pnext = pend;
-      } else {
-        if( decimal_is_comma() ) {
-          pnext = valid_next(p, true, comma );
-        } else {
-          if( exclusions.dot++ ) {
-            error_msg( loc, "PICTURE: %qc: may appear at most once", p[0] );
-            return nullptr;
-          }
-          pnext = valid_next(p);
-        }
-      }
-      break;
-
-    case '+': case '-':
-      // 7 is trailing sign; 13 & 14 are numeric.  Leading sign handled by 
start(). 
-      if( p + 1 == pend ) {
-        if( exclusions.crdb++ ) {
-          error_msg( loc, "PICTURE: %c/%c may appear at most once as a sign", 
'+', '-' );
-          return nullptr;
-        }
-        pnext = pend;
-      } else {
-        pnext = next_not(p[0]);
-        if( p + 1 < pnext ) {
-          if( false && exclusions.pluses++ )  { // not enforced
-            error_msg( loc, "PICTURE: %qc: sequence may appear at most once", 
p[0] );
-            return nullptr;
-          }
-        }
-        pnext = valid_next(pnext, ! exclusions.dot);
-      }
-      break;
-
-    case 'Z': case '*':
-      if( false && exclusions.stars++ ) { // not enforced 
-        error_msg( loc, "PICTURE: %qc: sequence may appear at most once", p[0] 
);
-        return nullptr;
-      }
-      if( (pnext = next_not(p[0])) == nullptr ) return pnext;
-      pnext = valid_next(pnext, ! exclusions.dot);
-      break;
-    case 'P':
-      pnext = valid_next(pnext, ! exclusions.dot);
-      break;
-    case '9':
-    case 'A': case 'X':
-    case 'V':
-    case '1':
-    case 'N':
-      pnext = valid_next(p);
-      break;
-    case 'E':
-      pnext = valid_next(p, "+9");
-      if( pnext && *pnext == '+' ) {
-        pnext = valid_next(p, "9");
-      }
-      break;
-    default:
-      error_msg( loc, "PICTURE: %qc: invalid character", p[0] );
-      return nullptr;
-    }
-    return pnext;
-  }
-  
- public:
-  picture_t( const char *p, int len )
-    : begin(p)
-    , p(p), pend(p + len)
-    , loc(yylloc)
-  { 
-    assert(TOUPPER(*p) == 'P'); // as in PICTURE (or PICTURE IS)
-    // move p to start of picture string
-    while( (p = std::find_if(p, pend, fisspace)) != pend ) {
-      this->p = p = std::find_if(p, pend,
-                                 []( char ch ) { return ! fisspace(ch); } );
-    }
-    assert(this->p != pend);
-    pos = this->p - begin;
-  }
-
-  bool is_valid() {
-    if( !p ) return false;
-    if( (p = start()) == nullptr ) {
-      return false;
-    }
-
-    while( p && p < pend) {
-      p = next();
-    }
-    return p == pend;
-  }
-
-  int starts_at() const { return pos; }
-};
-
-/*
- * The Followers map gives 1 or 2 lists of valid characters following a
- * character, the one in the key. If there are two lists, the correct one is
- * determined by the caller based on the state of the picture string, i.e.,
- * what has been seen before.
- */
-const std::map <char, picture_t::followings_t> picture_t::followers {
-  /*   B0/ */ { 'B', {"B0/,.Z*+-9AXVPNE" } },
-  /*   B0/ */ { '0', {"B0/,.Z*+-9AXVPNE" } },
-  /*   B0/ */ { '/', {"B0/,.Z*+-9AXVPNE" } },
-  /*     , */ { ',', {"B0/,.Z*+-9VPE"} },
-  /*     . */ { '.', {"B0/,Z*+-9E"} },
-  /*    +- */ { '+', {"B0/,.Z*9VPE", "" } },
-  /*    +- */ { '-', {"B0/,.Z*9VPE", "" } },
-  /*    Z* */ { 'Z', {"B0/,.+Z*9VP", "B0/,+Z*"} },
-  /*    Z* */ { '*', {"B0/,.+Z*9VP", "B0/,+Z*"} },
-  /*     + */ { '+', {"B0/,.+-9VP",  "B0/,+-"} },
-  /*    cs */ { '$', {"B0/,.+9VP",   "B0/,+"} },
-  /*     9 */ { '9', {"B0/,.+9AXVPE"} },
-  /*    AX */ { 'A', {"B0/9AX"} },
-  /*    AX */ { 'X', {"B0/9AX"} },
-  /*     S */ { 'S', {"9VP"} },
-  /*     V */ { 'V', {"B0/,+Z*+-9P"} },
-  /*     P */ { 'P', {"+VP", "B0/,+Z*9P"} },
-  /*     1 */ { '1', {"1"} },
-  /*     N */ { 'N', {"B0/N"} },
-  /*     E */ { 'E', {"+9"} },
-};
-
-/*
- * Although picture_t::is_valid return a bool, it's not used. The validation
- * routines emit messages where the error is detected. The entire string is
- * subsequently parsed by the parser, which might otherwise accept an invalid
- * string, but will usually emit a message of its own.
- */
-static int 
-validate_picture() {
-  picture_t picture(yytext, yyleng);
-  picture.is_valid();
-  return  picture.starts_at();
-}
-
 static inline bool
 is_integer_token( int *pvalue = NULL ) {
   int v, n = 0;
diff --git a/gcc/cobol/semantic_token.h b/gcc/cobol/semantic_token.h
new file mode 100644
index 000000000000..0fead8c3d35b
--- /dev/null
+++ b/gcc/cobol/semantic_token.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021-2026 Symas Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following disclaimer
+ *   in the documentation and/or other materials provided with the
+ *   distribution.
+ * * Neither the name of the Symas Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SEMANTIC_TOKEN_H_
+#define _SEMANTIC_TOKEN_H_
+
+struct lex_picture_t {
+  size_t pos;
+  uint64_t attr;
+  bool blank_when_zero_ok;
+  cbl_field_type_t type;
+  cbl_encoding_t encoding;
+  cbl_field_data_t *data; // NULL if error
+
+  bool valid() const { return type != FldInvalid; }
+  void dump( cbl_name_t input ) const {
+    auto len = strlen(input);
+    int pad = len < 20? 20 - len : 0;
+    fprintf( stderr, "%-20s %s: '%s'%*s @ %u of %u (%s)",
+             cbl_field_type_str(type),
+             (attr & all_alpha_e)? "A" : " ",
+             input,
+             pad, "",
+             unsigned(pos), unsigned(strlen(input)),
+             __gg__encoding_iconv_name(encoding) );
+    if( data ) {
+      fprintf( stderr, "%2u{%3u,%u,%d}",
+               data->memsize, data->capacity(), data->digits, data->rdigits );
+    }
+    fprintf(stderr, "\n");
+  }
+};
+
+lex_picture_t is_valid_picture(const cbl_loc_t& lock, const char picture[]);
+
+#endif
diff --git a/gcc/cobol/symbols.cc b/gcc/cobol/symbols.cc
index c41e0b8ff2a3..db64208fabfc 100644
--- a/gcc/cobol/symbols.cc
+++ b/gcc/cobol/symbols.cc
@@ -1828,7 +1828,6 @@ operator<<( std::ostream& os, const cbl_field_t& field ) {
 #pragma GCC diagnostic pop
 
 static std::map<size_t, std::set<size_t>> same_record_areas;
-size_t parse_error_count();
 
 /*
  * This function produces a zero-filled level number, so 1 becomes "01".  It's
diff --git a/gcc/cobol/symbols.h b/gcc/cobol/symbols.h
index d1864b1fdde6..a14d2e13c43d 100644
--- a/gcc/cobol/symbols.h
+++ b/gcc/cobol/symbols.h
@@ -39,6 +39,7 @@
 #include <cstring>
 
 #include <algorithm>
+#include <array>
 #include <list>
 #include <map>
 #include <set>
@@ -51,6 +52,8 @@
 
 extern const char *numed_message;
 
+typedef std::array<char, 64> tok_name_t;
+
 static inline const char *
 cbl_dialect_str(cbl_dialect_t dialect)  {
   switch(dialect) {
@@ -551,6 +554,14 @@ public:
   void original( REAL_VALUE_TYPE value ) {
     orig = orig_t(value);
   }
+
+  void apply_picture( const cbl_field_data_t& that ) {
+    nbyte = that.nbyte;
+    digits = that.digits;
+    rdigits = that.rdigits;
+    picture = that.picture;
+  }
+
  protected:
   cbl_field_data_t& copy_self( const cbl_field_data_t& that ) {
     memsize = that.memsize;
diff --git a/gcc/cobol/symfind.cc b/gcc/cobol/symfind.cc
index ebf7f5317b4b..c7e76a43682b 100644
--- a/gcc/cobol/symfind.cc
+++ b/gcc/cobol/symfind.cc
@@ -61,7 +61,7 @@ struct funcname {
     std::reverse_iterator<const char *> rbeg(pend), rend(p);
     // Find the last character that could not by part of the function name.
     const std::string stop(" *&");
-    auto rp = std::find_if( rbeg, rend, 
+    auto rp = std::find_if( rbeg, rend,
                             [stop]( char ch ) {
                               return stop.find(ch) != std::string::npos;
                             } );
@@ -136,7 +136,7 @@ static class symbol_file_names_t : protected symbol_map_t {
     std::vector<size_t> ids( 1, file.default_record );
     sym_name_t key(program, file.name, 0);
     (*this)[key] = ids;
-    // Keep track of symbols we added, so the parser can ask. 
+    // Keep track of symbols we added, so the parser can ask.
     auto f = cbl_field_of(symbol_at(ids.front()));
     assert('_' == f->name[0]); // not a COBOL name
     named_defaults.insert(ids.front());
@@ -144,16 +144,16 @@ static class symbol_file_names_t : protected symbol_map_t 
{
   symbol_map_t find( size_t program, const char name[] ) const {
     symbol_map_t output;
     std::copy_if( cbegin(), cend(),
-                  std::inserter(output, output.begin()), 
+                  std::inserter(output, output.begin()),
                   [program, name]( const auto& elem ) {
                     return match(program, name, elem);
                   } );
-    
+
     dbgmsg("%s:%d: found %lu #%lu for %s", __funcsig__, __LINE__,
            (unsigned long)output.size(),
            output.empty()? 0ul : (unsigned long)output.begin()->second.front(),
            name);
-           
+
     return output;
   }
   bool exists( const cbl_field_t * field ) const {
@@ -596,12 +596,12 @@ symbol_match( size_t program, const std::list<const char 
*>& names, bool diagnos
     symbol_map_t::key_type key( e->program, f->name, f->parent );
     auto p = symbol_map.find(key);
     if( p == symbol_map.end() ) {
-      yyerror("%s is not defined", key.name);
+      yyerror("%qs is not defined", key.name);
       continue;
     }
     auto inserted = output.insert(*p);
     if( diagnose && ! inserted.second ) {
-      error_msg_direct("%s is not a unique reference", key.name);
+      error_msg_direct("%qs is not a unique reference", key.name);
     }
   }
   return output;
diff --git a/gcc/cobol/token_names.h b/gcc/cobol/token_names.h
index 407050fbde14..43eca0c613f7 100644
--- a/gcc/cobol/token_names.h
+++ b/gcc/cobol/token_names.h
@@ -38,459 +38,459 @@ tokens = {
        { "numed", NUMED }, // 293
        { "numed-cr", NUMED_CR }, // 294
        { "numed-db", NUMED_DB }, // 295
-       { "ninedot", NINEDOT }, // 296
-       { "nines", NINES }, // 297
-       { "ninev", NINEV }, // 298
-       { "pic-p", PIC_P }, // 299
-       { "ones", ONES }, // 300
-       { "spaces", SPACES }, // 301
-       { "space", SPACES }, // 301
-       { "-eq", _EQ }, // 302
-       { "literal", LITERAL }, // 303
-       { "end", END }, // 304
-       { "eop", EOP }, // 305
-       { "-filename", _FILENAME }, // 306
-       { "invalid", INVALID }, // 307
-       { "number", NUMBER }, // 308
-       { "negative", NEGATIVE }, // 309
-       { "numstr", NUMSTR }, // 310
-       { "overflow", OVERFLOW_kw }, // 311
-       { "-binary-integer", _BINARY_INTEGER }, // 312
-       { "computational", COMPUTATIONAL }, // 313
-       { "perform", PERFORM }, // 314
-       { "backward", BACKWARD }, // 315
-       { "positive", POSITIVE }, // 316
-       { "pointer", POINTER }, // 317
-       { "process", PROCESS }, // 318
-       { "section", SECTION }, // 319
-       { "standard-alphabet", STANDARD_ALPHABET }, // 320
-       { "switch", SWITCH }, // 321
-       { "upsi", UPSI }, // 322
-       { "zero", ZERO }, // 323
-       { "zeros", ZERO }, // 323
-       { "zeroes", ZERO }, // 323
-       { "sysin", SYSIN }, // 324
-       { "sysipt", SYSIPT }, // 325
-       { "sysout", SYSOUT }, // 326
-       { "syslist", SYSLIST }, // 327
-       { "syslst", SYSLST }, // 328
-       { "syspunch", SYSPUNCH }, // 329
-       { "syspch", SYSPCH }, // 330
-       { "console", CONSOLE }, // 331
-       { "c01", C01 }, // 332
-       { "c02", C02 }, // 333
-       { "c03", C03 }, // 334
-       { "c04", C04 }, // 335
-       { "c05", C05 }, // 336
-       { "c06", C06 }, // 337
-       { "c07", C07 }, // 338
-       { "c08", C08 }, // 339
-       { "c09", C09 }, // 340
-       { "c10", C10 }, // 341
-       { "c11", C11 }, // 342
-       { "c12", C12 }, // 343
-       { "csp", CSP }, // 344
-       { "s01", S01 }, // 345
-       { "s02", S02 }, // 346
-       { "s03", S03 }, // 347
-       { "s04", S04 }, // 348
-       { "s05", S05 }, // 349
-       { "afp-5a", AFP_5A }, // 350
-       { "stdin", STDIN }, // 351
-       { "stdout", STDOUT }, // 352
-       { "stderr", STDERR }, // 353
-       { "list", LIST }, // 354
-       { "map", MAP }, // 355
-       { "nolist", NOLIST }, // 356
-       { "nomap", NOMAP }, // 357
-       { "nosource", NOSOURCE }, // 358
-       { "might-be", MIGHT_BE }, // 359
-       { "function-udf", FUNCTION_UDF }, // 360
-       { "function-udf-0", FUNCTION_UDF_0 }, // 361
-       { "default", DEFAULT }, // 362
-       { "date-fmt", DATE_FMT }, // 363
-       { "time-fmt", TIME_FMT }, // 364
-       { "datetime-fmt", DATETIME_FMT }, // 365
-       { "flag-02", FLAG_02 }, // 366
-       { "move-to-same-name", MOVE_TO_SAME_NAME }, // 367
-       { "range-exception-for-index", RANGE_EXCEPTION_FOR_INDEX }, // 368
-       { "terminate-with-varying", TERMINATE_WITH_VARYING }, // 369
-       { "flag-14", FLAG_14 }, // 370
-       { "compile-time-arithmetic-expressions", 
COMPILE_TIME_ARITHMETIC_EXPRESSIONS }, // 371
-       { "i-o-declarative", I_O_DECLARATIVE }, // 372
-       { "i-o-status-04", I_O_STATUS_04 }, // 373
-       { "i-o-status-07", I_O_STATUS_07 }, // 374
-       { "num-ed-zero-figconst", NUM_ED_ZERO_FIGCONST }, // 375
-       { "read-previous", READ_PREVIOUS }, // 376
-       { "ref-mod-zero-length", REF_MOD_ZERO_LENGTH }, // 377
-       { "value-editing", VALUE_EDITING }, // 378
-       { "value-fig-con-length", VALUE_FIG_CON_LENGTH }, // 379
-       { "value-zero", VALUE_ZERO }, // 380
-       { "write-end-of-page", WRITE_END_OF_PAGE }, // 381
-       { "leap-second", LEAP_SECOND }, // 382
-       { "listing", LISTING }, // 383
-       { "propagate", PROPAGATE }, // 384
-       { "zero-length", ZERO_LENGTH }, // 385
-       { "b-and", B_AND }, // 386
-       { "b-not", B_NOT }, // 387
-       { "b-or", B_OR }, // 388
-       { "b-shift-l", B_SHIFT_L }, // 389
-       { "b-shift-lc", B_SHIFT_LC }, // 390
-       { "b-shift-r", B_SHIFT_R }, // 391
-       { "b-shift-rc", B_SHIFT_RC }, // 392
-       { "b-xor", B_XOR }, // 393
-       { "basis", BASIS }, // 394
-       { "cbl", CBL }, // 395
-       { "constant", CONSTANT }, // 396
-       { "copy", COPY }, // 397
-       { "defined", DEFINED }, // 398
-       { "enter", ENTER }, // 399
-       { "feature", FEATURE }, // 400
-       { "insertt", INSERTT }, // 401
-       { "lsub", LSUB }, // 402
-       { "parameter", PARAMETER_kw }, // 403
-       { "override", OVERRIDE }, // 404
-       { "ready", READY }, // 405
-       { "reset", RESET }, // 406
-       { "rsub", RSUB }, // 407
-       { "service-reload", SERVICE_RELOAD }, // 408
-       { "star-cbl", STAR_CBL }, // 409
-       { "subscript", SUBSCRIPT }, // 410
-       { "suppress", SUPPRESS }, // 411
-       { "trace", TRACE }, // 412
-       { "use", USE }, // 413
-       { "cobol-words", COBOL_WORDS }, // 414
-       { "equate", EQUATE }, // 415
-       { "undefine", UNDEFINE }, // 416
-       { "cdf-define", CDF_DEFINE }, // 417
-       { "cdf-display", CDF_DISPLAY }, // 418
-       { "cdf-if", CDF_IF }, // 419
-       { "cdf-else", CDF_ELSE }, // 420
-       { "cdf-end-if", CDF_END_IF }, // 421
-       { "cdf-evaluate", CDF_EVALUATE }, // 422
-       { "cdf-when", CDF_WHEN }, // 423
-       { "cdf-end-evaluate", CDF_END_EVALUATE }, // 424
-       { "call-convention", CALL_CONVENTION }, // 425
-       { "call-cobol", CALL_COBOL }, // 426
-       { "call-verbatim", CALL_VERBATIM }, // 427
-       { "cdf-push", CDF_PUSH }, // 428
-       { "cdf-pop", CDF_POP }, // 429
-       { "source-format", SOURCE_FORMAT }, // 430
-       { "if", IF }, // 431
-       { "then", THEN }, // 432
-       { "else", ELSE }, // 433
-       { "sentence", SENTENCE }, // 434
-       { "accept", ACCEPT }, // 435
-       { "add", ADD }, // 436
-       { "alter", ALTER }, // 437
-       { "call", CALL }, // 438
-       { "cancel", CANCEL }, // 439
-       { "close", CLOSE }, // 440
-       { "compute", COMPUTE }, // 441
-       { "continue", CONTINUE }, // 442
-       { "delete", DELETE }, // 443
-       { "display", DISPLAY }, // 444
-       { "divide", DIVIDE }, // 445
-       { "evaluate", EVALUATE }, // 446
-       { "exit", EXIT }, // 447
-       { "filler", FILLER_kw }, // 448
-       { "goback", GOBACK }, // 449
-       { "goto", GOTO }, // 450
-       { "initialize", INITIALIZE }, // 451
-       { "inspect", INSPECT }, // 452
-       { "merge", MERGE }, // 453
-       { "move", MOVE }, // 454
-       { "multiply", MULTIPLY }, // 455
-       { "open", OPEN }, // 456
-       { "paragraph", PARAGRAPH }, // 457
-       { "read", READ }, // 458
-       { "release", RELEASE }, // 459
-       { "return", RETURN }, // 460
-       { "rewrite", REWRITE }, // 461
-       { "search", SEARCH }, // 462
-       { "set", SET }, // 463
-       { "select", SELECT }, // 464
-       { "sort", SORT }, // 465
-       { "sort-merge", SORT_MERGE }, // 466
-       { "string", STRING_kw }, // 467
-       { "stop", STOP }, // 468
-       { "subtract", SUBTRACT }, // 469
-       { "start", START }, // 470
-       { "unstring", UNSTRING }, // 471
-       { "write", WRITE }, // 472
-       { "when", WHEN }, // 473
-       { "argument-number", ARGUMENT_NUMBER }, // 474
-       { "argument-value", ARGUMENT_VALUE }, // 475
-       { "environment-name", ENVIRONMENT_NAME }, // 476
-       { "environment-value", ENVIRONMENT_VALUE }, // 477
-       { "abs", ABS }, // 478
-       { "access", ACCESS }, // 479
-       { "acos", ACOS }, // 480
-       { "actual", ACTUAL }, // 481
-       { "advancing", ADVANCING }, // 482
-       { "after", AFTER }, // 483
-       { "all", ALL }, // 484
-       { "allocate", ALLOCATE }, // 485
-       { "alphabet", ALPHABET }, // 486
-       { "alphabetic", ALPHABETIC }, // 487
-       { "alphabetic-lower", ALPHABETIC_LOWER }, // 488
-       { "alphabetic-upper", ALPHABETIC_UPPER }, // 489
-       { "alphanumeric", ALPHANUMERIC }, // 490
-       { "alphanumeric-edited", ALPHANUMERIC_EDITED }, // 491
-       { "also", ALSO }, // 492
-       { "alternate", ALTERNATE }, // 493
-       { "annuity", ANNUITY }, // 494
-       { "anum", ANUM }, // 495
-       { "any", ANY }, // 496
-       { "anycase", ANYCASE }, // 497
-       { "apply", APPLY }, // 498
-       { "are", ARE }, // 499
-       { "area", AREA }, // 500
-       { "areas", AREAS }, // 501
-       { "as", AS }, // 502
-       { "ascending", ASCENDING }, // 503
-       { "activating", ACTIVATING }, // 504
-       { "asin", ASIN }, // 505
-       { "assign", ASSIGN }, // 506
-       { "at", AT }, // 507
-       { "atan", ATAN }, // 508
-       { "based", BASED }, // 509
-       { "baseconvert", BASECONVERT }, // 510
-       { "before", BEFORE }, // 511
-       { "binary", BINARY }, // 512
-       { "bit", BIT }, // 513
-       { "bit-of", BIT_OF }, // 514
-       { "bit-to-char", BIT_TO_CHAR }, // 515
-       { "blank", BLANK }, // 516
-       { "block", BLOCK_kw }, // 517
-       { "boolean-of-integer", BOOLEAN_OF_INTEGER }, // 518
-       { "bottom", BOTTOM }, // 519
-       { "by", BY }, // 520
-       { "byte", BYTE }, // 521
-       { "byte-length", BYTE_LENGTH }, // 522
-       { "cf", CF }, // 523
-       { "ch", CH }, // 524
-       { "changed", CHANGED }, // 525
-       { "char", CHAR }, // 526
-       { "char-national", CHAR_NATIONAL }, // 527
-       { "character", CHARACTER }, // 528
-       { "characters", CHARACTERS }, // 529
-       { "checking", CHECKING }, // 530
-       { "class", CLASS }, // 531
-       { "cobol", COBOL }, // 532
-       { "code", CODE }, // 533
-       { "code-set", CODESET }, // 534
-       { "collating", COLLATING }, // 535
-       { "column", COLUMN }, // 536
-       { "combined-datetime", COMBINED_DATETIME }, // 537
-       { "comma", COMMA }, // 538
-       { "command-line", COMMAND_LINE }, // 539
-       { "command-line-count", COMMAND_LINE_COUNT }, // 540
-       { "commit", COMMIT }, // 541
-       { "common", COMMON }, // 542
-       { "concat", CONCAT }, // 543
-       { "condition", CONDITION }, // 544
-       { "configuration", CONFIGURATION }, // 545
-       { "configuration section", CONFIGURATION_SECT }, // 546
-       { "contains", CONTAINS }, // 547
-       { "content", CONTENT }, // 548
-       { "control", CONTROL }, // 549
-       { "controls", CONTROLS }, // 550
-       { "convert", CONVERT }, // 551
-       { "converting", CONVERTING }, // 552
-       { "corresponding", CORRESPONDING }, // 553
-       { "cos", COS }, // 554
-       { "count", COUNT }, // 555
-       { "currency", CURRENCY }, // 556
-       { "current", CURRENT }, // 557
-       { "current-date", CURRENT_DATE }, // 558
-       { "date", DATE }, // 559
-       { "date-compiled", DATE_COMPILED }, // 560
-       { "date-of-integer", DATE_OF_INTEGER }, // 561
-       { "date-to-yyyymmdd", DATE_TO_YYYYMMDD }, // 562
-       { "date-written", DATE_WRITTEN }, // 563
-       { "day", DAY }, // 564
-       { "day-of-integer", DAY_OF_INTEGER }, // 565
-       { "day-of-week", DAY_OF_WEEK }, // 566
-       { "day-to-yyyyddd", DAY_TO_YYYYDDD }, // 567
-       { "dbcs", DBCS }, // 568
-       { "de", DE }, // 569
-       { "debugging", DEBUGGING }, // 570
-       { "decimal-point", DECIMAL_POINT }, // 571
-       { "declaratives", DECLARATIVES }, // 572
-       { "delimited", DELIMITED }, // 573
-       { "delimiter", DELIMITER }, // 574
-       { "depending", DEPENDING }, // 575
-       { "descending", DESCENDING }, // 576
-       { "detail", DETAIL }, // 577
-       { "direct", DIRECT }, // 578
-       { "direct-access", DIRECT_ACCESS }, // 579
-       { "division", DIVISION }, // 580
-       { "down", DOWN }, // 581
-       { "duplicates", DUPLICATES }, // 582
-       { "dynamic", DYNAMIC }, // 583
-       { "e", E }, // 584
-       { "ebcdic", EBCDIC }, // 585
-       { "ec", EC }, // 586
-       { "egcs", EGCS }, // 587
-       { "encoding", ENCODING }, // 588
-       { "entry", ENTRY }, // 589
-       { "every", EVERY }, // 590
-       { "examine", EXAMINE }, // 591
-       { "exhibit", EXHIBIT }, // 592
-       { "exp", EXP }, // 593
-       { "exp10", EXP10 }, // 594
-       { "extend", EXTEND }, // 595
-       { "external", EXTERNAL }, // 596
-       { "exception-file", EXCEPTION_FILE }, // 597
-       { "exception-file-n", EXCEPTION_FILE_N }, // 598
-       { "exception-location", EXCEPTION_LOCATION }, // 599
-       { "exception-location-n", EXCEPTION_LOCATION_N }, // 600
-       { "exception-statement", EXCEPTION_STATEMENT }, // 601
-       { "exception-status", EXCEPTION_STATUS }, // 602
-       { "factorial", FACTORIAL }, // 603
-       { "false", FALSE_kw }, // 604
-       { "fd", FD }, // 605
-       { "file-control", FILE_CONTROL }, // 606
-       { "file", FILE_KW }, // 607
-       { "file-limit", FILE_LIMIT }, // 608
-       { "final", FINAL }, // 609
-       { "finally", FINALLY }, // 610
-       { "find-string", FIND_STRING }, // 611
-       { "first", FIRST }, // 612
-       { "fixed", FIXED }, // 613
-       { "footing", FOOTING }, // 614
-       { "for", FOR }, // 615
-       { "formatted-current-date", FORMATTED_CURRENT_DATE }, // 616
-       { "formatted-date", FORMATTED_DATE }, // 617
-       { "formatted-datetime", FORMATTED_DATETIME }, // 618
-       { "formatted-time", FORMATTED_TIME }, // 619
-       { "form-overflow", FORM_OVERFLOW }, // 620
-       { "free", FREE }, // 621
-       { "fraction-part", FRACTION_PART }, // 622
-       { "from", FROM }, // 623
-       { "function", FUNCTION }, // 624
-       { "generate", GENERATE }, // 625
-       { "giving", GIVING }, // 626
-       { "global", GLOBAL }, // 627
-       { "go", GO }, // 628
-       { "group", GROUP }, // 629
-       { "heading", HEADING }, // 630
-       { "hex", HEX }, // 631
-       { "hex-of", HEX_OF }, // 632
-       { "hex-to-char", HEX_TO_CHAR }, // 633
-       { "high-values", HIGH_VALUES }, // 634
-       { "highest-algebraic", HIGHEST_ALGEBRAIC }, // 635
-       { "hold", HOLD }, // 636
-       { "ibm-360", IBM_360 }, // 637
-       { "in", IN }, // 638
-       { "include", INCLUDE }, // 639
-       { "index", INDEX }, // 640
-       { "indexed", INDEXED }, // 641
-       { "indicate", INDICATE }, // 642
-       { "initial", INITIAL_kw }, // 643
-       { "initiate", INITIATE }, // 644
-       { "input", INPUT }, // 645
-       { "installation", INSTALLATION }, // 646
-       { "interface", INTERFACE }, // 647
-       { "integer", INTEGER }, // 648
-       { "integer-of-boolean", INTEGER_OF_BOOLEAN }, // 649
-       { "integer-of-date", INTEGER_OF_DATE }, // 650
-       { "integer-of-day", INTEGER_OF_DAY }, // 651
-       { "integer-of-formatted-date", INTEGER_OF_FORMATTED_DATE }, // 652
-       { "integer-part", INTEGER_PART }, // 653
-       { "into", INTO }, // 654
-       { "intrinsic", INTRINSIC }, // 655
-       { "invoke", INVOKE }, // 656
-       { "i-o", IO }, // 657
-       { "i-o-control", IO_CONTROL }, // 658
-       { "is", IS }, // 659
-       { "isnt", ISNT }, // 660
-       { "kanji", KANJI }, // 661
-       { "key", KEY }, // 662
-       { "label", LABEL }, // 663
-       { "last", LAST }, // 664
-       { "leading", LEADING }, // 665
-       { "left", LEFT }, // 666
-       { "length", LENGTH }, // 667
-       { "length-of", LENGTH_OF }, // 668
-       { "limit", LIMIT }, // 669
-       { "limits", LIMITS }, // 670
-       { "line", LINE }, // 671
-       { "lines", LINES }, // 672
-       { "line-counter", LINE_COUNTER }, // 673
-       { "linage", LINAGE }, // 674
-       { "linkage", LINKAGE }, // 675
-       { "locale", LOCALE }, // 676
-       { "locale-compare", LOCALE_COMPARE }, // 677
-       { "locale-date", LOCALE_DATE }, // 678
-       { "locale-time", LOCALE_TIME }, // 679
-       { "locale-time-from-seconds", LOCALE_TIME_FROM_SECONDS }, // 680
-       { "local-storage", LOCAL_STORAGE }, // 681
-       { "location", LOCATION }, // 682
-       { "lock", LOCK }, // 683
-       { "lock-on", LOCK_ON }, // 684
-       { "log", LOG }, // 685
-       { "log10", LOG10 }, // 686
-       { "lower-case", LOWER_CASE }, // 687
-       { "low-values", LOW_VALUES }, // 688
-       { "lowest-algebraic", LOWEST_ALGEBRAIC }, // 689
-       { "lparen", LPAREN }, // 690
-       { "manual", MANUAL }, // 691
-       { "maxx", MAXX }, // 692
-       { "mean", MEAN }, // 693
-       { "median", MEDIAN }, // 694
-       { "midrange", MIDRANGE }, // 695
-       { "minn", MINN }, // 696
-       { "multiple", MULTIPLE }, // 697
-       { "mod", MOD }, // 698
-       { "mode", MODE }, // 699
-       { "module-name", MODULE_NAME }, // 700
-       { "named", NAMED }, // 701
-       { "namespace", NAMESPACE }, // 702
-       { "namespace-prefix", NAMESPACE_PREFIX }, // 703
-       { "nat", NAT }, // 704
-       { "national", NATIONAL }, // 705
-       { "national-edited", NATIONAL_EDITED }, // 706
-       { "national-of", NATIONAL_OF }, // 707
-       { "native", NATIVE }, // 708
-       { "nested", NESTED }, // 709
-       { "next", NEXT }, // 710
-       { "no", NO }, // 711
-       { "note", NOTE }, // 712
-       { "nulls", NULLS }, // 713
-       { "null", NULLS }, // 713
-       { "nullptr", NULLPTR }, // 714
-       { "numeric", NUMERIC }, // 715
-       { "numeric-edited", NUMERIC_EDITED }, // 716
-       { "numval", NUMVAL }, // 717
-       { "numval-c", NUMVAL_C }, // 718
-       { "numval-f", NUMVAL_F }, // 719
-       { "occurs", OCCURS }, // 720
-       { "of", OF }, // 721
-       { "off", OFF }, // 722
-       { "omitted", OMITTED }, // 723
-       { "on", ON }, // 724
-       { "only", ONLY }, // 725
-       { "optional", OPTIONAL }, // 726
-       { "options", OPTIONS }, // 727
-       { "ord", ORD }, // 728
-       { "order", ORDER }, // 729
-       { "ord-max", ORD_MAX }, // 730
-       { "ord-min", ORD_MIN }, // 731
-       { "organization", ORGANIZATION }, // 732
-       { "other", OTHER }, // 733
-       { "otherwise", OTHERWISE }, // 734
-       { "output", OUTPUT }, // 735
-       { "packed-decimal", PACKED_DECIMAL }, // 736
-       { "padding", PADDING }, // 737
-       { "page", PAGE }, // 738
-       { "page-counter", PAGE_COUNTER }, // 739
-       { "pf", PF }, // 740
-       { "ph", PH }, // 741
-       { "pi", PI }, // 742
-       { "pic", PIC }, // 743
-       { "picture", PICTURE }, // 744
+       { "picture", PICTURE }, // 296
+       { "ninedot", NINEDOT }, // 297
+       { "nines", NINES }, // 298
+       { "ninev", NINEV }, // 299
+       { "pic-p", PIC_P }, // 300
+       { "ones", ONES }, // 301
+       { "spaces", SPACES }, // 302
+       { "space", SPACES }, // 302
+       { "-eq", _EQ }, // 303
+       { "literal", LITERAL }, // 304
+       { "end", END }, // 305
+       { "eop", EOP }, // 306
+       { "-filename", _FILENAME }, // 307
+       { "invalid", INVALID }, // 308
+       { "number", NUMBER }, // 309
+       { "negative", NEGATIVE }, // 310
+       { "numstr", NUMSTR }, // 311
+       { "overflow", OVERFLOW_kw }, // 312
+       { "-binary-integer", _BINARY_INTEGER }, // 313
+       { "computational", COMPUTATIONAL }, // 314
+       { "perform", PERFORM }, // 315
+       { "backward", BACKWARD }, // 316
+       { "positive", POSITIVE }, // 317
+       { "pointer", POINTER }, // 318
+       { "process", PROCESS }, // 319
+       { "section", SECTION }, // 320
+       { "standard-alphabet", STANDARD_ALPHABET }, // 321
+       { "switch", SWITCH }, // 322
+       { "upsi", UPSI }, // 323
+       { "zero", ZERO }, // 324
+       { "zeros", ZERO }, // 324
+       { "zeroes", ZERO }, // 324
+       { "sysin", SYSIN }, // 325
+       { "sysipt", SYSIPT }, // 326
+       { "sysout", SYSOUT }, // 327
+       { "syslist", SYSLIST }, // 328
+       { "syslst", SYSLST }, // 329
+       { "syspunch", SYSPUNCH }, // 330
+       { "syspch", SYSPCH }, // 331
+       { "console", CONSOLE }, // 332
+       { "c01", C01 }, // 333
+       { "c02", C02 }, // 334
+       { "c03", C03 }, // 335
+       { "c04", C04 }, // 336
+       { "c05", C05 }, // 337
+       { "c06", C06 }, // 338
+       { "c07", C07 }, // 339
+       { "c08", C08 }, // 340
+       { "c09", C09 }, // 341
+       { "c10", C10 }, // 342
+       { "c11", C11 }, // 343
+       { "c12", C12 }, // 344
+       { "csp", CSP }, // 345
+       { "s01", S01 }, // 346
+       { "s02", S02 }, // 347
+       { "s03", S03 }, // 348
+       { "s04", S04 }, // 349
+       { "s05", S05 }, // 350
+       { "afp-5a", AFP_5A }, // 351
+       { "stdin", STDIN }, // 352
+       { "stdout", STDOUT }, // 353
+       { "stderr", STDERR }, // 354
+       { "list", LIST }, // 355
+       { "map", MAP }, // 356
+       { "nolist", NOLIST }, // 357
+       { "nomap", NOMAP }, // 358
+       { "nosource", NOSOURCE }, // 359
+       { "might-be", MIGHT_BE }, // 360
+       { "function-udf", FUNCTION_UDF }, // 361
+       { "function-udf-0", FUNCTION_UDF_0 }, // 362
+       { "default", DEFAULT }, // 363
+       { "date-fmt", DATE_FMT }, // 364
+       { "time-fmt", TIME_FMT }, // 365
+       { "datetime-fmt", DATETIME_FMT }, // 366
+       { "flag-02", FLAG_02 }, // 367
+       { "move-to-same-name", MOVE_TO_SAME_NAME }, // 368
+       { "range-exception-for-index", RANGE_EXCEPTION_FOR_INDEX }, // 369
+       { "terminate-with-varying", TERMINATE_WITH_VARYING }, // 370
+       { "flag-14", FLAG_14 }, // 371
+       { "compile-time-arithmetic-expressions", 
COMPILE_TIME_ARITHMETIC_EXPRESSIONS }, // 372
+       { "i-o-declarative", I_O_DECLARATIVE }, // 373
+       { "i-o-status-04", I_O_STATUS_04 }, // 374
+       { "i-o-status-07", I_O_STATUS_07 }, // 375
+       { "num-ed-zero-figconst", NUM_ED_ZERO_FIGCONST }, // 376
+       { "read-previous", READ_PREVIOUS }, // 377
+       { "ref-mod-zero-length", REF_MOD_ZERO_LENGTH }, // 378
+       { "value-editing", VALUE_EDITING }, // 379
+       { "value-fig-con-length", VALUE_FIG_CON_LENGTH }, // 380
+       { "value-zero", VALUE_ZERO }, // 381
+       { "write-end-of-page", WRITE_END_OF_PAGE }, // 382
+       { "leap-second", LEAP_SECOND }, // 383
+       { "listing", LISTING }, // 384
+       { "propagate", PROPAGATE }, // 385
+       { "zero-length", ZERO_LENGTH }, // 386
+       { "b-and", B_AND }, // 387
+       { "b-not", B_NOT }, // 388
+       { "b-or", B_OR }, // 389
+       { "b-shift-l", B_SHIFT_L }, // 390
+       { "b-shift-lc", B_SHIFT_LC }, // 391
+       { "b-shift-r", B_SHIFT_R }, // 392
+       { "b-shift-rc", B_SHIFT_RC }, // 393
+       { "b-xor", B_XOR }, // 394
+       { "basis", BASIS }, // 395
+       { "cbl", CBL }, // 396
+       { "constant", CONSTANT }, // 397
+       { "copy", COPY }, // 398
+       { "defined", DEFINED }, // 399
+       { "enter", ENTER }, // 400
+       { "feature", FEATURE }, // 401
+       { "insertt", INSERTT }, // 402
+       { "lsub", LSUB }, // 403
+       { "parameter", PARAMETER_kw }, // 404
+       { "override", OVERRIDE }, // 405
+       { "ready", READY }, // 406
+       { "reset", RESET }, // 407
+       { "rsub", RSUB }, // 408
+       { "service-reload", SERVICE_RELOAD }, // 409
+       { "star-cbl", STAR_CBL }, // 410
+       { "subscript", SUBSCRIPT }, // 411
+       { "suppress", SUPPRESS }, // 412
+       { "trace", TRACE }, // 413
+       { "use", USE }, // 414
+       { "cobol-words", COBOL_WORDS }, // 415
+       { "equate", EQUATE }, // 416
+       { "undefine", UNDEFINE }, // 417
+       { "cdf-define", CDF_DEFINE }, // 418
+       { "cdf-display", CDF_DISPLAY }, // 419
+       { "cdf-if", CDF_IF }, // 420
+       { "cdf-else", CDF_ELSE }, // 421
+       { "cdf-end-if", CDF_END_IF }, // 422
+       { "cdf-evaluate", CDF_EVALUATE }, // 423
+       { "cdf-when", CDF_WHEN }, // 424
+       { "cdf-end-evaluate", CDF_END_EVALUATE }, // 425
+       { "call-convention", CALL_CONVENTION }, // 426
+       { "call-cobol", CALL_COBOL }, // 427
+       { "call-verbatim", CALL_VERBATIM }, // 428
+       { "cdf-push", CDF_PUSH }, // 429
+       { "cdf-pop", CDF_POP }, // 430
+       { "source-format", SOURCE_FORMAT }, // 431
+       { "if", IF }, // 432
+       { "then", THEN }, // 433
+       { "else", ELSE }, // 434
+       { "sentence", SENTENCE }, // 435
+       { "accept", ACCEPT }, // 436
+       { "add", ADD }, // 437
+       { "alter", ALTER }, // 438
+       { "call", CALL }, // 439
+       { "cancel", CANCEL }, // 440
+       { "close", CLOSE }, // 441
+       { "compute", COMPUTE }, // 442
+       { "continue", CONTINUE }, // 443
+       { "delete", DELETE }, // 444
+       { "display", DISPLAY }, // 445
+       { "divide", DIVIDE }, // 446
+       { "evaluate", EVALUATE }, // 447
+       { "exit", EXIT }, // 448
+       { "filler", FILLER_kw }, // 449
+       { "goback", GOBACK }, // 450
+       { "goto", GOTO }, // 451
+       { "initialize", INITIALIZE }, // 452
+       { "inspect", INSPECT }, // 453
+       { "merge", MERGE }, // 454
+       { "move", MOVE }, // 455
+       { "multiply", MULTIPLY }, // 456
+       { "open", OPEN }, // 457
+       { "paragraph", PARAGRAPH }, // 458
+       { "read", READ }, // 459
+       { "release", RELEASE }, // 460
+       { "return", RETURN }, // 461
+       { "rewrite", REWRITE }, // 462
+       { "search", SEARCH }, // 463
+       { "set", SET }, // 464
+       { "select", SELECT }, // 465
+       { "sort", SORT }, // 466
+       { "sort-merge", SORT_MERGE }, // 467
+       { "string", STRING_kw }, // 468
+       { "stop", STOP }, // 469
+       { "subtract", SUBTRACT }, // 470
+       { "start", START }, // 471
+       { "unstring", UNSTRING }, // 472
+       { "write", WRITE }, // 473
+       { "when", WHEN }, // 474
+       { "argument-number", ARGUMENT_NUMBER }, // 475
+       { "argument-value", ARGUMENT_VALUE }, // 476
+       { "environment-name", ENVIRONMENT_NAME }, // 477
+       { "environment-value", ENVIRONMENT_VALUE }, // 478
+       { "abs", ABS }, // 479
+       { "access", ACCESS }, // 480
+       { "acos", ACOS }, // 481
+       { "actual", ACTUAL }, // 482
+       { "advancing", ADVANCING }, // 483
+       { "after", AFTER }, // 484
+       { "all", ALL }, // 485
+       { "allocate", ALLOCATE }, // 486
+       { "alphabet", ALPHABET }, // 487
+       { "alphabetic", ALPHABETIC }, // 488
+       { "alphabetic-lower", ALPHABETIC_LOWER }, // 489
+       { "alphabetic-upper", ALPHABETIC_UPPER }, // 490
+       { "alphanumeric", ALPHANUMERIC }, // 491
+       { "alphanumeric-edited", ALPHANUMERIC_EDITED }, // 492
+       { "also", ALSO }, // 493
+       { "alternate", ALTERNATE }, // 494
+       { "annuity", ANNUITY }, // 495
+       { "anum", ANUM }, // 496
+       { "any", ANY }, // 497
+       { "anycase", ANYCASE }, // 498
+       { "apply", APPLY }, // 499
+       { "are", ARE }, // 500
+       { "area", AREA }, // 501
+       { "areas", AREAS }, // 502
+       { "as", AS }, // 503
+       { "ascending", ASCENDING }, // 504
+       { "activating", ACTIVATING }, // 505
+       { "asin", ASIN }, // 506
+       { "assign", ASSIGN }, // 507
+       { "at", AT }, // 508
+       { "atan", ATAN }, // 509
+       { "based", BASED }, // 510
+       { "baseconvert", BASECONVERT }, // 511
+       { "before", BEFORE }, // 512
+       { "binary", BINARY }, // 513
+       { "bit", BIT }, // 514
+       { "bit-of", BIT_OF }, // 515
+       { "bit-to-char", BIT_TO_CHAR }, // 516
+       { "blank", BLANK }, // 517
+       { "block", BLOCK_kw }, // 518
+       { "boolean-of-integer", BOOLEAN_OF_INTEGER }, // 519
+       { "bottom", BOTTOM }, // 520
+       { "by", BY }, // 521
+       { "byte", BYTE }, // 522
+       { "byte-length", BYTE_LENGTH }, // 523
+       { "cf", CF }, // 524
+       { "ch", CH }, // 525
+       { "changed", CHANGED }, // 526
+       { "char", CHAR }, // 527
+       { "char-national", CHAR_NATIONAL }, // 528
+       { "character", CHARACTER }, // 529
+       { "characters", CHARACTERS }, // 530
+       { "checking", CHECKING }, // 531
+       { "class", CLASS }, // 532
+       { "cobol", COBOL }, // 533
+       { "code", CODE }, // 534
+       { "code-set", CODESET }, // 535
+       { "collating", COLLATING }, // 536
+       { "column", COLUMN }, // 537
+       { "combined-datetime", COMBINED_DATETIME }, // 538
+       { "comma", COMMA }, // 539
+       { "command-line", COMMAND_LINE }, // 540
+       { "command-line-count", COMMAND_LINE_COUNT }, // 541
+       { "commit", COMMIT }, // 542
+       { "common", COMMON }, // 543
+       { "concat", CONCAT }, // 544
+       { "condition", CONDITION }, // 545
+       { "configuration", CONFIGURATION }, // 546
+       { "configuration section", CONFIGURATION_SECT }, // 547
+       { "contains", CONTAINS }, // 548
+       { "content", CONTENT }, // 549
+       { "control", CONTROL }, // 550
+       { "controls", CONTROLS }, // 551
+       { "convert", CONVERT }, // 552
+       { "converting", CONVERTING }, // 553
+       { "corresponding", CORRESPONDING }, // 554
+       { "cos", COS }, // 555
+       { "count", COUNT }, // 556
+       { "currency", CURRENCY }, // 557
+       { "current", CURRENT }, // 558
+       { "current-date", CURRENT_DATE }, // 559
+       { "date", DATE }, // 560
+       { "date-compiled", DATE_COMPILED }, // 561
+       { "date-of-integer", DATE_OF_INTEGER }, // 562
+       { "date-to-yyyymmdd", DATE_TO_YYYYMMDD }, // 563
+       { "date-written", DATE_WRITTEN }, // 564
+       { "day", DAY }, // 565
+       { "day-of-integer", DAY_OF_INTEGER }, // 566
+       { "day-of-week", DAY_OF_WEEK }, // 567
+       { "day-to-yyyyddd", DAY_TO_YYYYDDD }, // 568
+       { "dbcs", DBCS }, // 569
+       { "de", DE }, // 570
+       { "debugging", DEBUGGING }, // 571
+       { "decimal-point", DECIMAL_POINT }, // 572
+       { "declaratives", DECLARATIVES }, // 573
+       { "delimited", DELIMITED }, // 574
+       { "delimiter", DELIMITER }, // 575
+       { "depending", DEPENDING }, // 576
+       { "descending", DESCENDING }, // 577
+       { "detail", DETAIL }, // 578
+       { "direct", DIRECT }, // 579
+       { "direct-access", DIRECT_ACCESS }, // 580
+       { "division", DIVISION }, // 581
+       { "down", DOWN }, // 582
+       { "duplicates", DUPLICATES }, // 583
+       { "dynamic", DYNAMIC }, // 584
+       { "e", E }, // 585
+       { "ebcdic", EBCDIC }, // 586
+       { "ec", EC }, // 587
+       { "egcs", EGCS }, // 588
+       { "encoding", ENCODING }, // 589
+       { "entry", ENTRY }, // 590
+       { "every", EVERY }, // 591
+       { "examine", EXAMINE }, // 592
+       { "exhibit", EXHIBIT }, // 593
+       { "exp", EXP }, // 594
+       { "exp10", EXP10 }, // 595
+       { "extend", EXTEND }, // 596
+       { "external", EXTERNAL }, // 597
+       { "exception-file", EXCEPTION_FILE }, // 598
+       { "exception-file-n", EXCEPTION_FILE_N }, // 599
+       { "exception-location", EXCEPTION_LOCATION }, // 600
+       { "exception-location-n", EXCEPTION_LOCATION_N }, // 601
+       { "exception-statement", EXCEPTION_STATEMENT }, // 602
+       { "exception-status", EXCEPTION_STATUS }, // 603
+       { "factorial", FACTORIAL }, // 604
+       { "false", FALSE_kw }, // 605
+       { "fd", FD }, // 606
+       { "file-control", FILE_CONTROL }, // 607
+       { "file", FILE_KW }, // 608
+       { "file-limit", FILE_LIMIT }, // 609
+       { "final", FINAL }, // 610
+       { "finally", FINALLY }, // 611
+       { "find-string", FIND_STRING }, // 612
+       { "first", FIRST }, // 613
+       { "fixed", FIXED }, // 614
+       { "footing", FOOTING }, // 615
+       { "for", FOR }, // 616
+       { "formatted-current-date", FORMATTED_CURRENT_DATE }, // 617
+       { "formatted-date", FORMATTED_DATE }, // 618
+       { "formatted-datetime", FORMATTED_DATETIME }, // 619
+       { "formatted-time", FORMATTED_TIME }, // 620
+       { "form-overflow", FORM_OVERFLOW }, // 621
+       { "free", FREE }, // 622
+       { "fraction-part", FRACTION_PART }, // 623
+       { "from", FROM }, // 624
+       { "function", FUNCTION }, // 625
+       { "generate", GENERATE }, // 626
+       { "giving", GIVING }, // 627
+       { "global", GLOBAL }, // 628
+       { "go", GO }, // 629
+       { "group", GROUP }, // 630
+       { "heading", HEADING }, // 631
+       { "hex", HEX }, // 632
+       { "hex-of", HEX_OF }, // 633
+       { "hex-to-char", HEX_TO_CHAR }, // 634
+       { "high-values", HIGH_VALUES }, // 635
+       { "highest-algebraic", HIGHEST_ALGEBRAIC }, // 636
+       { "hold", HOLD }, // 637
+       { "ibm-360", IBM_360 }, // 638
+       { "in", IN }, // 639
+       { "include", INCLUDE }, // 640
+       { "index", INDEX }, // 641
+       { "indexed", INDEXED }, // 642
+       { "indicate", INDICATE }, // 643
+       { "initial", INITIAL_kw }, // 644
+       { "initiate", INITIATE }, // 645
+       { "input", INPUT }, // 646
+       { "installation", INSTALLATION }, // 647
+       { "interface", INTERFACE }, // 648
+       { "integer", INTEGER }, // 649
+       { "integer-of-boolean", INTEGER_OF_BOOLEAN }, // 650
+       { "integer-of-date", INTEGER_OF_DATE }, // 651
+       { "integer-of-day", INTEGER_OF_DAY }, // 652
+       { "integer-of-formatted-date", INTEGER_OF_FORMATTED_DATE }, // 653
+       { "integer-part", INTEGER_PART }, // 654
+       { "into", INTO }, // 655
+       { "intrinsic", INTRINSIC }, // 656
+       { "invoke", INVOKE }, // 657
+       { "i-o", IO }, // 658
+       { "i-o-control", IO_CONTROL }, // 659
+       { "is", IS }, // 660
+       { "isnt", ISNT }, // 661
+       { "kanji", KANJI }, // 662
+       { "key", KEY }, // 663
+       { "label", LABEL }, // 664
+       { "last", LAST }, // 665
+       { "leading", LEADING }, // 666
+       { "left", LEFT }, // 667
+       { "length", LENGTH }, // 668
+       { "length-of", LENGTH_OF }, // 669
+       { "limit", LIMIT }, // 670
+       { "limits", LIMITS }, // 671
+       { "line", LINE }, // 672
+       { "lines", LINES }, // 673
+       { "line-counter", LINE_COUNTER }, // 674
+       { "linage", LINAGE }, // 675
+       { "linkage", LINKAGE }, // 676
+       { "locale", LOCALE }, // 677
+       { "locale-compare", LOCALE_COMPARE }, // 678
+       { "locale-date", LOCALE_DATE }, // 679
+       { "locale-time", LOCALE_TIME }, // 680
+       { "locale-time-from-seconds", LOCALE_TIME_FROM_SECONDS }, // 681
+       { "local-storage", LOCAL_STORAGE }, // 682
+       { "location", LOCATION }, // 683
+       { "lock", LOCK }, // 684
+       { "lock-on", LOCK_ON }, // 685
+       { "log", LOG }, // 686
+       { "log10", LOG10 }, // 687
+       { "lower-case", LOWER_CASE }, // 688
+       { "low-values", LOW_VALUES }, // 689
+       { "lowest-algebraic", LOWEST_ALGEBRAIC }, // 690
+       { "lparen", LPAREN }, // 691
+       { "manual", MANUAL }, // 692
+       { "maxx", MAXX }, // 693
+       { "mean", MEAN }, // 694
+       { "median", MEDIAN }, // 695
+       { "midrange", MIDRANGE }, // 696
+       { "minn", MINN }, // 697
+       { "multiple", MULTIPLE }, // 698
+       { "mod", MOD }, // 699
+       { "mode", MODE }, // 700
+       { "module-name", MODULE_NAME }, // 701
+       { "named", NAMED }, // 702
+       { "namespace", NAMESPACE }, // 703
+       { "namespace-prefix", NAMESPACE_PREFIX }, // 704
+       { "nat", NAT }, // 705
+       { "national", NATIONAL }, // 706
+       { "national-edited", NATIONAL_EDITED }, // 707
+       { "national-of", NATIONAL_OF }, // 708
+       { "native", NATIVE }, // 709
+       { "nested", NESTED }, // 710
+       { "next", NEXT }, // 711
+       { "no", NO }, // 712
+       { "note", NOTE }, // 713
+       { "nulls", NULLS }, // 714
+       { "null", NULLS }, // 714
+       { "nullptr", NULLPTR }, // 715
+       { "numeric", NUMERIC }, // 716
+       { "numeric-edited", NUMERIC_EDITED }, // 717
+       { "numval", NUMVAL }, // 718
+       { "numval-c", NUMVAL_C }, // 719
+       { "numval-f", NUMVAL_F }, // 720
+       { "occurs", OCCURS }, // 721
+       { "of", OF }, // 722
+       { "off", OFF }, // 723
+       { "omitted", OMITTED }, // 724
+       { "on", ON }, // 725
+       { "only", ONLY }, // 726
+       { "optional", OPTIONAL }, // 727
+       { "options", OPTIONS }, // 728
+       { "ord", ORD }, // 729
+       { "order", ORDER }, // 730
+       { "ord-max", ORD_MAX }, // 731
+       { "ord-min", ORD_MIN }, // 732
+       { "organization", ORGANIZATION }, // 733
+       { "other", OTHER }, // 734
+       { "otherwise", OTHERWISE }, // 735
+       { "output", OUTPUT }, // 736
+       { "packed-decimal", PACKED_DECIMAL }, // 737
+       { "padding", PADDING }, // 738
+       { "page", PAGE }, // 739
+       { "page-counter", PAGE_COUNTER }, // 740
+       { "pf", PF }, // 741
+       { "ph", PH }, // 742
+       { "pi", PI }, // 743
+       { "pic", PIC }, // 744
        { "plus", PLUS }, // 745
        { "present-value", PRESENT_VALUE }, // 746
        { "print-switch", PRINT_SWITCH }, // 747
@@ -779,455 +779,455 @@ token_names = {
        "NUMED", // 35 (293)
        "NUMED-CR", // 36 (294)
        "NUMED-DB", // 37 (295)
-       "NINEDOT", // 38 (296)
-       "NINES", // 39 (297)
-       "NINEV", // 40 (298)
-       "PIC-P", // 41 (299)
-       "ONES", // 42 (300)
-       "SPACES", // 43 (301)
-       "-EQ", // 44 (302)
-       "LITERAL", // 45 (303)
-       "END", // 46 (304)
-       "EOP", // 47 (305)
-       "-FILENAME", // 48 (306)
-       "INVALID", // 49 (307)
-       "NUMBER", // 50 (308)
-       "NEGATIVE", // 51 (309)
-       "NUMSTR", // 52 (310)
-       "OVERFLOW", // 53 (311)
-       "-BINARY-INTEGER", // 54 (312)
-       "COMPUTATIONAL", // 55 (313)
-       "PERFORM", // 56 (314)
-       "BACKWARD", // 57 (315)
-       "POSITIVE", // 58 (316)
-       "POINTER", // 59 (317)
-       "PROCESS", // 60 (318)
-       "SECTION", // 61 (319)
-       "STANDARD-ALPHABET", // 62 (320)
-       "SWITCH", // 63 (321)
-       "UPSI", // 64 (322)
-       "ZERO", // 65 (323)
-       "SYSIN", // 66 (324)
-       "SYSIPT", // 67 (325)
-       "SYSOUT", // 68 (326)
-       "SYSLIST", // 69 (327)
-       "SYSLST", // 70 (328)
-       "SYSPUNCH", // 71 (329)
-       "SYSPCH", // 72 (330)
-       "CONSOLE", // 73 (331)
-       "C01", // 74 (332)
-       "C02", // 75 (333)
-       "C03", // 76 (334)
-       "C04", // 77 (335)
-       "C05", // 78 (336)
-       "C06", // 79 (337)
-       "C07", // 80 (338)
-       "C08", // 81 (339)
-       "C09", // 82 (340)
-       "C10", // 83 (341)
-       "C11", // 84 (342)
-       "C12", // 85 (343)
-       "CSP", // 86 (344)
-       "S01", // 87 (345)
-       "S02", // 88 (346)
-       "S03", // 89 (347)
-       "S04", // 90 (348)
-       "S05", // 91 (349)
-       "AFP-5A", // 92 (350)
-       "STDIN", // 93 (351)
-       "STDOUT", // 94 (352)
-       "STDERR", // 95 (353)
-       "LIST", // 96 (354)
-       "MAP", // 97 (355)
-       "NOLIST", // 98 (356)
-       "NOMAP", // 99 (357)
-       "NOSOURCE", // 100 (358)
-       "MIGHT-BE", // 101 (359)
-       "FUNCTION-UDF", // 102 (360)
-       "FUNCTION-UDF-0", // 103 (361)
-       "DEFAULT", // 104 (362)
-       "DATE-FMT", // 105 (363)
-       "TIME-FMT", // 106 (364)
-       "DATETIME-FMT", // 107 (365)
-       "FLAG-02", // 108 (366)
-       "MOVE-TO-SAME-NAME", // 109 (367)
-       "RANGE-EXCEPTION-FOR-INDEX", // 110 (368)
-       "TERMINATE-WITH-VARYING", // 111 (369)
-       "FLAG-14", // 112 (370)
-       "COMPILE-TIME-ARITHMETIC-EXPRESSIONS", // 113 (371)
-       "I-O-DECLARATIVE", // 114 (372)
-       "I-O-STATUS-04", // 115 (373)
-       "I-O-STATUS-07", // 116 (374)
-       "NUM-ED-ZERO-FIGCONST", // 117 (375)
-       "READ-PREVIOUS", // 118 (376)
-       "REF-MOD-ZERO-LENGTH", // 119 (377)
-       "VALUE-EDITING", // 120 (378)
-       "VALUE-FIG-CON-LENGTH", // 121 (379)
-       "VALUE-ZERO", // 122 (380)
-       "WRITE-END-OF-PAGE", // 123 (381)
-       "LEAP-SECOND", // 124 (382)
-       "LISTING", // 125 (383)
-       "PROPAGATE", // 126 (384)
-       "ZERO-LENGTH", // 127 (385)
-       "B-AND", // 128 (386)
-       "B-NOT", // 129 (387)
-       "B-OR", // 130 (388)
-       "B-SHIFT-L", // 131 (389)
-       "B-SHIFT-LC", // 132 (390)
-       "B-SHIFT-R", // 133 (391)
-       "B-SHIFT-RC", // 134 (392)
-       "B-XOR", // 135 (393)
-       "BASIS", // 136 (394)
-       "CBL", // 137 (395)
-       "CONSTANT", // 138 (396)
-       "COPY", // 139 (397)
-       "DEFINED", // 140 (398)
-       "ENTER", // 141 (399)
-       "FEATURE", // 142 (400)
-       "INSERTT", // 143 (401)
-       "LSUB", // 144 (402)
-       "PARAMETER", // 145 (403)
-       "OVERRIDE", // 146 (404)
-       "READY", // 147 (405)
-       "RESET", // 148 (406)
-       "RSUB", // 149 (407)
-       "SERVICE-RELOAD", // 150 (408)
-       "STAR-CBL", // 151 (409)
-       "SUBSCRIPT", // 152 (410)
-       "SUPPRESS", // 153 (411)
-       "TRACE", // 154 (412)
-       "USE", // 155 (413)
-       "COBOL-WORDS", // 156 (414)
-       "EQUATE", // 157 (415)
-       "UNDEFINE", // 158 (416)
-       "CDF-DEFINE", // 159 (417)
-       "CDF-DISPLAY", // 160 (418)
-       "CDF-IF", // 161 (419)
-       "CDF-ELSE", // 162 (420)
-       "CDF-END-IF", // 163 (421)
-       "CDF-EVALUATE", // 164 (422)
-       "CDF-WHEN", // 165 (423)
-       "CDF-END-EVALUATE", // 166 (424)
-       "CALL-CONVENTION", // 167 (425)
-       "CALL-COBOL", // 168 (426)
-       "CALL-VERBATIM", // 169 (427)
-       "CDF-PUSH", // 170 (428)
-       "CDF-POP", // 171 (429)
-       "SOURCE-FORMAT", // 172 (430)
-       "IF", // 173 (431)
-       "THEN", // 174 (432)
-       "ELSE", // 175 (433)
-       "SENTENCE", // 176 (434)
-       "ACCEPT", // 177 (435)
-       "ADD", // 178 (436)
-       "ALTER", // 179 (437)
-       "CALL", // 180 (438)
-       "CANCEL", // 181 (439)
-       "CLOSE", // 182 (440)
-       "COMPUTE", // 183 (441)
-       "CONTINUE", // 184 (442)
-       "DELETE", // 185 (443)
-       "DISPLAY", // 186 (444)
-       "DIVIDE", // 187 (445)
-       "EVALUATE", // 188 (446)
-       "EXIT", // 189 (447)
-       "FILLER", // 190 (448)
-       "GOBACK", // 191 (449)
-       "GOTO", // 192 (450)
-       "INITIALIZE", // 193 (451)
-       "INSPECT", // 194 (452)
-       "MERGE", // 195 (453)
-       "MOVE", // 196 (454)
-       "MULTIPLY", // 197 (455)
-       "OPEN", // 198 (456)
-       "PARAGRAPH", // 199 (457)
-       "READ", // 200 (458)
-       "RELEASE", // 201 (459)
-       "RETURN", // 202 (460)
-       "REWRITE", // 203 (461)
-       "SEARCH", // 204 (462)
-       "SET", // 205 (463)
-       "SELECT", // 206 (464)
-       "SORT", // 207 (465)
-       "SORT-MERGE", // 208 (466)
-       "STRING", // 209 (467)
-       "STOP", // 210 (468)
-       "SUBTRACT", // 211 (469)
-       "START", // 212 (470)
-       "UNSTRING", // 213 (471)
-       "WRITE", // 214 (472)
-       "WHEN", // 215 (473)
-       "ARGUMENT-NUMBER", // 216 (474)
-       "ARGUMENT-VALUE", // 217 (475)
-       "ENVIRONMENT-NAME", // 218 (476)
-       "ENVIRONMENT-VALUE", // 219 (477)
-       "ABS", // 220 (478)
-       "ACCESS", // 221 (479)
-       "ACOS", // 222 (480)
-       "ACTUAL", // 223 (481)
-       "ADVANCING", // 224 (482)
-       "AFTER", // 225 (483)
-       "ALL", // 226 (484)
-       "ALLOCATE", // 227 (485)
-       "ALPHABET", // 228 (486)
-       "ALPHABETIC", // 229 (487)
-       "ALPHABETIC-LOWER", // 230 (488)
-       "ALPHABETIC-UPPER", // 231 (489)
-       "ALPHANUMERIC", // 232 (490)
-       "ALPHANUMERIC-EDITED", // 233 (491)
-       "ALSO", // 234 (492)
-       "ALTERNATE", // 235 (493)
-       "ANNUITY", // 236 (494)
-       "ANUM", // 237 (495)
-       "ANY", // 238 (496)
-       "ANYCASE", // 239 (497)
-       "APPLY", // 240 (498)
-       "ARE", // 241 (499)
-       "AREA", // 242 (500)
-       "AREAS", // 243 (501)
-       "AS", // 244 (502)
-       "ASCENDING", // 245 (503)
-       "ACTIVATING", // 246 (504)
-       "ASIN", // 247 (505)
-       "ASSIGN", // 248 (506)
-       "AT", // 249 (507)
-       "ATAN", // 250 (508)
-       "BASED", // 251 (509)
-       "BASECONVERT", // 252 (510)
-       "BEFORE", // 253 (511)
-       "BINARY", // 254 (512)
-       "BIT", // 255 (513)
-       "BIT-OF", // 256 (514)
-       "BIT-TO-CHAR", // 257 (515)
-       "BLANK", // 258 (516)
-       "BLOCK", // 259 (517)
-       "BOOLEAN-OF-INTEGER", // 260 (518)
-       "BOTTOM", // 261 (519)
-       "BY", // 262 (520)
-       "BYTE", // 263 (521)
-       "BYTE-LENGTH", // 264 (522)
-       "CF", // 265 (523)
-       "CH", // 266 (524)
-       "CHANGED", // 267 (525)
-       "CHAR", // 268 (526)
-       "CHAR-NATIONAL", // 269 (527)
-       "CHARACTER", // 270 (528)
-       "CHARACTERS", // 271 (529)
-       "CHECKING", // 272 (530)
-       "CLASS", // 273 (531)
-       "COBOL", // 274 (532)
-       "CODE", // 275 (533)
-       "CODE-SET", // 276 (534)
-       "COLLATING", // 277 (535)
-       "COLUMN", // 278 (536)
-       "COMBINED-DATETIME", // 279 (537)
-       "COMMA", // 280 (538)
-       "COMMAND-LINE", // 281 (539)
-       "COMMAND-LINE-COUNT", // 282 (540)
-       "COMMIT", // 283 (541)
-       "COMMON", // 284 (542)
-       "CONCAT", // 285 (543)
-       "CONDITION", // 286 (544)
-       "CONFIGURATION", // 287 (545)
+       "PICTURE", // 38 (296)
+       "NINEDOT", // 39 (297)
+       "NINES", // 40 (298)
+       "NINEV", // 41 (299)
+       "PIC-P", // 42 (300)
+       "ONES", // 43 (301)
+       "SPACES", // 44 (302)
+       "-EQ", // 45 (303)
+       "LITERAL", // 46 (304)
+       "END", // 47 (305)
+       "EOP", // 48 (306)
+       "-FILENAME", // 49 (307)
+       "INVALID", // 50 (308)
+       "NUMBER", // 51 (309)
+       "NEGATIVE", // 52 (310)
+       "NUMSTR", // 53 (311)
+       "OVERFLOW", // 54 (312)
+       "-BINARY-INTEGER", // 55 (313)
+       "COMPUTATIONAL", // 56 (314)
+       "PERFORM", // 57 (315)
+       "BACKWARD", // 58 (316)
+       "POSITIVE", // 59 (317)
+       "POINTER", // 60 (318)
+       "PROCESS", // 61 (319)
+       "SECTION", // 62 (320)
+       "STANDARD-ALPHABET", // 63 (321)
+       "SWITCH", // 64 (322)
+       "UPSI", // 65 (323)
+       "ZERO", // 66 (324)
+       "SYSIN", // 67 (325)
+       "SYSIPT", // 68 (326)
+       "SYSOUT", // 69 (327)
+       "SYSLIST", // 70 (328)
+       "SYSLST", // 71 (329)
+       "SYSPUNCH", // 72 (330)
+       "SYSPCH", // 73 (331)
+       "CONSOLE", // 74 (332)
+       "C01", // 75 (333)
+       "C02", // 76 (334)
+       "C03", // 77 (335)
+       "C04", // 78 (336)
+       "C05", // 79 (337)
+       "C06", // 80 (338)
+       "C07", // 81 (339)
+       "C08", // 82 (340)
+       "C09", // 83 (341)
+       "C10", // 84 (342)
+       "C11", // 85 (343)
+       "C12", // 86 (344)
+       "CSP", // 87 (345)
+       "S01", // 88 (346)
+       "S02", // 89 (347)
+       "S03", // 90 (348)
+       "S04", // 91 (349)
+       "S05", // 92 (350)
+       "AFP-5A", // 93 (351)
+       "STDIN", // 94 (352)
+       "STDOUT", // 95 (353)
+       "STDERR", // 96 (354)
+       "LIST", // 97 (355)
+       "MAP", // 98 (356)
+       "NOLIST", // 99 (357)
+       "NOMAP", // 100 (358)
+       "NOSOURCE", // 101 (359)
+       "MIGHT-BE", // 102 (360)
+       "FUNCTION-UDF", // 103 (361)
+       "FUNCTION-UDF-0", // 104 (362)
+       "DEFAULT", // 105 (363)
+       "DATE-FMT", // 106 (364)
+       "TIME-FMT", // 107 (365)
+       "DATETIME-FMT", // 108 (366)
+       "FLAG-02", // 109 (367)
+       "MOVE-TO-SAME-NAME", // 110 (368)
+       "RANGE-EXCEPTION-FOR-INDEX", // 111 (369)
+       "TERMINATE-WITH-VARYING", // 112 (370)
+       "FLAG-14", // 113 (371)
+       "COMPILE-TIME-ARITHMETIC-EXPRESSIONS", // 114 (372)
+       "I-O-DECLARATIVE", // 115 (373)
+       "I-O-STATUS-04", // 116 (374)
+       "I-O-STATUS-07", // 117 (375)
+       "NUM-ED-ZERO-FIGCONST", // 118 (376)
+       "READ-PREVIOUS", // 119 (377)
+       "REF-MOD-ZERO-LENGTH", // 120 (378)
+       "VALUE-EDITING", // 121 (379)
+       "VALUE-FIG-CON-LENGTH", // 122 (380)
+       "VALUE-ZERO", // 123 (381)
+       "WRITE-END-OF-PAGE", // 124 (382)
+       "LEAP-SECOND", // 125 (383)
+       "LISTING", // 126 (384)
+       "PROPAGATE", // 127 (385)
+       "ZERO-LENGTH", // 128 (386)
+       "B-AND", // 129 (387)
+       "B-NOT", // 130 (388)
+       "B-OR", // 131 (389)
+       "B-SHIFT-L", // 132 (390)
+       "B-SHIFT-LC", // 133 (391)
+       "B-SHIFT-R", // 134 (392)
+       "B-SHIFT-RC", // 135 (393)
+       "B-XOR", // 136 (394)
+       "BASIS", // 137 (395)
+       "CBL", // 138 (396)
+       "CONSTANT", // 139 (397)
+       "COPY", // 140 (398)
+       "DEFINED", // 141 (399)
+       "ENTER", // 142 (400)
+       "FEATURE", // 143 (401)
+       "INSERTT", // 144 (402)
+       "LSUB", // 145 (403)
+       "PARAMETER", // 146 (404)
+       "OVERRIDE", // 147 (405)
+       "READY", // 148 (406)
+       "RESET", // 149 (407)
+       "RSUB", // 150 (408)
+       "SERVICE-RELOAD", // 151 (409)
+       "STAR-CBL", // 152 (410)
+       "SUBSCRIPT", // 153 (411)
+       "SUPPRESS", // 154 (412)
+       "TRACE", // 155 (413)
+       "USE", // 156 (414)
+       "COBOL-WORDS", // 157 (415)
+       "EQUATE", // 158 (416)
+       "UNDEFINE", // 159 (417)
+       "CDF-DEFINE", // 160 (418)
+       "CDF-DISPLAY", // 161 (419)
+       "CDF-IF", // 162 (420)
+       "CDF-ELSE", // 163 (421)
+       "CDF-END-IF", // 164 (422)
+       "CDF-EVALUATE", // 165 (423)
+       "CDF-WHEN", // 166 (424)
+       "CDF-END-EVALUATE", // 167 (425)
+       "CALL-CONVENTION", // 168 (426)
+       "CALL-COBOL", // 169 (427)
+       "CALL-VERBATIM", // 170 (428)
+       "CDF-PUSH", // 171 (429)
+       "CDF-POP", // 172 (430)
+       "SOURCE-FORMAT", // 173 (431)
+       "IF", // 174 (432)
+       "THEN", // 175 (433)
+       "ELSE", // 176 (434)
+       "SENTENCE", // 177 (435)
+       "ACCEPT", // 178 (436)
+       "ADD", // 179 (437)
+       "ALTER", // 180 (438)
+       "CALL", // 181 (439)
+       "CANCEL", // 182 (440)
+       "CLOSE", // 183 (441)
+       "COMPUTE", // 184 (442)
+       "CONTINUE", // 185 (443)
+       "DELETE", // 186 (444)
+       "DISPLAY", // 187 (445)
+       "DIVIDE", // 188 (446)
+       "EVALUATE", // 189 (447)
+       "EXIT", // 190 (448)
+       "FILLER", // 191 (449)
+       "GOBACK", // 192 (450)
+       "GOTO", // 193 (451)
+       "INITIALIZE", // 194 (452)
+       "INSPECT", // 195 (453)
+       "MERGE", // 196 (454)
+       "MOVE", // 197 (455)
+       "MULTIPLY", // 198 (456)
+       "OPEN", // 199 (457)
+       "PARAGRAPH", // 200 (458)
+       "READ", // 201 (459)
+       "RELEASE", // 202 (460)
+       "RETURN", // 203 (461)
+       "REWRITE", // 204 (462)
+       "SEARCH", // 205 (463)
+       "SET", // 206 (464)
+       "SELECT", // 207 (465)
+       "SORT", // 208 (466)
+       "SORT-MERGE", // 209 (467)
+       "STRING", // 210 (468)
+       "STOP", // 211 (469)
+       "SUBTRACT", // 212 (470)
+       "START", // 213 (471)
+       "UNSTRING", // 214 (472)
+       "WRITE", // 215 (473)
+       "WHEN", // 216 (474)
+       "ARGUMENT-NUMBER", // 217 (475)
+       "ARGUMENT-VALUE", // 218 (476)
+       "ENVIRONMENT-NAME", // 219 (477)
+       "ENVIRONMENT-VALUE", // 220 (478)
+       "ABS", // 221 (479)
+       "ACCESS", // 222 (480)
+       "ACOS", // 223 (481)
+       "ACTUAL", // 224 (482)
+       "ADVANCING", // 225 (483)
+       "AFTER", // 226 (484)
+       "ALL", // 227 (485)
+       "ALLOCATE", // 228 (486)
+       "ALPHABET", // 229 (487)
+       "ALPHABETIC", // 230 (488)
+       "ALPHABETIC-LOWER", // 231 (489)
+       "ALPHABETIC-UPPER", // 232 (490)
+       "ALPHANUMERIC", // 233 (491)
+       "ALPHANUMERIC-EDITED", // 234 (492)
+       "ALSO", // 235 (493)
+       "ALTERNATE", // 236 (494)
+       "ANNUITY", // 237 (495)
+       "ANUM", // 238 (496)
+       "ANY", // 239 (497)
+       "ANYCASE", // 240 (498)
+       "APPLY", // 241 (499)
+       "ARE", // 242 (500)
+       "AREA", // 243 (501)
+       "AREAS", // 244 (502)
+       "AS", // 245 (503)
+       "ASCENDING", // 246 (504)
+       "ACTIVATING", // 247 (505)
+       "ASIN", // 248 (506)
+       "ASSIGN", // 249 (507)
+       "AT", // 250 (508)
+       "ATAN", // 251 (509)
+       "BASED", // 252 (510)
+       "BASECONVERT", // 253 (511)
+       "BEFORE", // 254 (512)
+       "BINARY", // 255 (513)
+       "BIT", // 256 (514)
+       "BIT-OF", // 257 (515)
+       "BIT-TO-CHAR", // 258 (516)
+       "BLANK", // 259 (517)
+       "BLOCK", // 260 (518)
+       "BOOLEAN-OF-INTEGER", // 261 (519)
+       "BOTTOM", // 262 (520)
+       "BY", // 263 (521)
+       "BYTE", // 264 (522)
+       "BYTE-LENGTH", // 265 (523)
+       "CF", // 266 (524)
+       "CH", // 267 (525)
+       "CHANGED", // 268 (526)
+       "CHAR", // 269 (527)
+       "CHAR-NATIONAL", // 270 (528)
+       "CHARACTER", // 271 (529)
+       "CHARACTERS", // 272 (530)
+       "CHECKING", // 273 (531)
+       "CLASS", // 274 (532)
+       "COBOL", // 275 (533)
+       "CODE", // 276 (534)
+       "CODE-SET", // 277 (535)
+       "COLLATING", // 278 (536)
+       "COLUMN", // 279 (537)
+       "COMBINED-DATETIME", // 280 (538)
+       "COMMA", // 281 (539)
+       "COMMAND-LINE", // 282 (540)
+       "COMMAND-LINE-COUNT", // 283 (541)
+       "COMMIT", // 284 (542)
+       "COMMON", // 285 (543)
+       "CONCAT", // 286 (544)
+       "CONDITION", // 287 (545)
        "CONFIGURATION", // 288 (546)
-       "CONTAINS", // 289 (547)
-       "CONTENT", // 290 (548)
-       "CONTROL", // 291 (549)
-       "CONTROLS", // 292 (550)
-       "CONVERT", // 293 (551)
-       "CONVERTING", // 294 (552)
-       "CORRESPONDING", // 295 (553)
-       "COS", // 296 (554)
-       "COUNT", // 297 (555)
-       "CURRENCY", // 298 (556)
-       "CURRENT", // 299 (557)
-       "CURRENT-DATE", // 300 (558)
-       "DATE", // 301 (559)
-       "DATE-COMPILED", // 302 (560)
-       "DATE-OF-INTEGER", // 303 (561)
-       "DATE-TO-YYYYMMDD", // 304 (562)
-       "DATE-WRITTEN", // 305 (563)
-       "DAY", // 306 (564)
-       "DAY-OF-INTEGER", // 307 (565)
-       "DAY-OF-WEEK", // 308 (566)
-       "DAY-TO-YYYYDDD", // 309 (567)
-       "DBCS", // 310 (568)
-       "DE", // 311 (569)
-       "DEBUGGING", // 312 (570)
-       "DECIMAL-POINT", // 313 (571)
-       "DECLARATIVES", // 314 (572)
-       "DELIMITED", // 315 (573)
-       "DELIMITER", // 316 (574)
-       "DEPENDING", // 317 (575)
-       "DESCENDING", // 318 (576)
-       "DETAIL", // 319 (577)
-       "DIRECT", // 320 (578)
-       "DIRECT-ACCESS", // 321 (579)
-       "DIVISION", // 322 (580)
-       "DOWN", // 323 (581)
-       "DUPLICATES", // 324 (582)
-       "DYNAMIC", // 325 (583)
-       "E", // 326 (584)
-       "EBCDIC", // 327 (585)
-       "EC", // 328 (586)
-       "EGCS", // 329 (587)
-       "ENCODING", // 330 (588)
-       "ENTRY", // 331 (589)
-       "EVERY", // 332 (590)
-       "EXAMINE", // 333 (591)
-       "EXHIBIT", // 334 (592)
-       "EXP", // 335 (593)
-       "EXP10", // 336 (594)
-       "EXTEND", // 337 (595)
-       "EXTERNAL", // 338 (596)
-       "EXCEPTION-FILE", // 339 (597)
-       "EXCEPTION-FILE-N", // 340 (598)
-       "EXCEPTION-LOCATION", // 341 (599)
-       "EXCEPTION-LOCATION-N", // 342 (600)
-       "EXCEPTION-STATEMENT", // 343 (601)
-       "EXCEPTION-STATUS", // 344 (602)
-       "FACTORIAL", // 345 (603)
-       "FALSE", // 346 (604)
-       "FD", // 347 (605)
-       "FILE-CONTROL", // 348 (606)
-       "FILE", // 349 (607)
-       "FILE-LIMIT", // 350 (608)
-       "FINAL", // 351 (609)
-       "FINALLY", // 352 (610)
-       "FIND-STRING", // 353 (611)
-       "FIRST", // 354 (612)
-       "FIXED", // 355 (613)
-       "FOOTING", // 356 (614)
-       "FOR", // 357 (615)
-       "FORMATTED-CURRENT-DATE", // 358 (616)
-       "FORMATTED-DATE", // 359 (617)
-       "FORMATTED-DATETIME", // 360 (618)
-       "FORMATTED-TIME", // 361 (619)
-       "FORM-OVERFLOW", // 362 (620)
-       "FREE", // 363 (621)
-       "FRACTION-PART", // 364 (622)
-       "FROM", // 365 (623)
-       "FUNCTION", // 366 (624)
-       "GENERATE", // 367 (625)
-       "GIVING", // 368 (626)
-       "GLOBAL", // 369 (627)
-       "GO", // 370 (628)
-       "GROUP", // 371 (629)
-       "HEADING", // 372 (630)
-       "HEX", // 373 (631)
-       "HEX-OF", // 374 (632)
-       "HEX-TO-CHAR", // 375 (633)
-       "HIGH-VALUES", // 376 (634)
-       "HIGHEST-ALGEBRAIC", // 377 (635)
-       "HOLD", // 378 (636)
-       "IBM-360", // 379 (637)
-       "IN", // 380 (638)
-       "INCLUDE", // 381 (639)
-       "INDEX", // 382 (640)
-       "INDEXED", // 383 (641)
-       "INDICATE", // 384 (642)
-       "INITIAL", // 385 (643)
-       "INITIATE", // 386 (644)
-       "INPUT", // 387 (645)
-       "INSTALLATION", // 388 (646)
-       "INTERFACE", // 389 (647)
-       "INTEGER", // 390 (648)
-       "INTEGER-OF-BOOLEAN", // 391 (649)
-       "INTEGER-OF-DATE", // 392 (650)
-       "INTEGER-OF-DAY", // 393 (651)
-       "INTEGER-OF-FORMATTED-DATE", // 394 (652)
-       "INTEGER-PART", // 395 (653)
-       "INTO", // 396 (654)
-       "INTRINSIC", // 397 (655)
-       "INVOKE", // 398 (656)
-       "I-O", // 399 (657)
-       "I-O-CONTROL", // 400 (658)
-       "IS", // 401 (659)
-       "ISNT", // 402 (660)
-       "KANJI", // 403 (661)
-       "KEY", // 404 (662)
-       "LABEL", // 405 (663)
-       "LAST", // 406 (664)
-       "LEADING", // 407 (665)
-       "LEFT", // 408 (666)
-       "LENGTH", // 409 (667)
-       "LENGTH-OF", // 410 (668)
-       "LIMIT", // 411 (669)
-       "LIMITS", // 412 (670)
-       "LINE", // 413 (671)
-       "LINES", // 414 (672)
-       "LINE-COUNTER", // 415 (673)
-       "LINAGE", // 416 (674)
-       "LINKAGE", // 417 (675)
-       "LOCALE", // 418 (676)
-       "LOCALE-COMPARE", // 419 (677)
-       "LOCALE-DATE", // 420 (678)
-       "LOCALE-TIME", // 421 (679)
-       "LOCALE-TIME-FROM-SECONDS", // 422 (680)
-       "LOCAL-STORAGE", // 423 (681)
-       "LOCATION", // 424 (682)
-       "LOCK", // 425 (683)
-       "LOCK-ON", // 426 (684)
-       "LOG", // 427 (685)
-       "LOG10", // 428 (686)
-       "LOWER-CASE", // 429 (687)
-       "LOW-VALUES", // 430 (688)
-       "LOWEST-ALGEBRAIC", // 431 (689)
-       "LPAREN", // 432 (690)
-       "MANUAL", // 433 (691)
-       "MAXX", // 434 (692)
-       "MEAN", // 435 (693)
-       "MEDIAN", // 436 (694)
-       "MIDRANGE", // 437 (695)
-       "MINN", // 438 (696)
-       "MULTIPLE", // 439 (697)
-       "MOD", // 440 (698)
-       "MODE", // 441 (699)
-       "MODULE-NAME", // 442 (700)
-       "NAMED", // 443 (701)
-       "NAMESPACE", // 444 (702)
-       "NAMESPACE-PREFIX", // 445 (703)
-       "NAT", // 446 (704)
-       "NATIONAL", // 447 (705)
-       "NATIONAL-EDITED", // 448 (706)
-       "NATIONAL-OF", // 449 (707)
-       "NATIVE", // 450 (708)
-       "NESTED", // 451 (709)
-       "NEXT", // 452 (710)
-       "NO", // 453 (711)
-       "NOTE", // 454 (712)
-       "NULLS", // 455 (713)
-       "NULLPTR", // 456 (714)
-       "NUMERIC", // 457 (715)
-       "NUMERIC-EDITED", // 458 (716)
-       "NUMVAL", // 459 (717)
-       "NUMVAL-C", // 460 (718)
-       "NUMVAL-F", // 461 (719)
-       "OCCURS", // 462 (720)
-       "OF", // 463 (721)
-       "OFF", // 464 (722)
-       "OMITTED", // 465 (723)
-       "ON", // 466 (724)
-       "ONLY", // 467 (725)
-       "OPTIONAL", // 468 (726)
-       "OPTIONS", // 469 (727)
-       "ORD", // 470 (728)
-       "ORDER", // 471 (729)
-       "ORD-MAX", // 472 (730)
-       "ORD-MIN", // 473 (731)
-       "ORGANIZATION", // 474 (732)
-       "OTHER", // 475 (733)
-       "OTHERWISE", // 476 (734)
-       "OUTPUT", // 477 (735)
-       "PACKED-DECIMAL", // 478 (736)
-       "PADDING", // 479 (737)
-       "PAGE", // 480 (738)
-       "PAGE-COUNTER", // 481 (739)
-       "PF", // 482 (740)
-       "PH", // 483 (741)
-       "PI", // 484 (742)
-       "PIC", // 485 (743)
-       "PICTURE", // 486 (744)
+       "CONFIGURATION", // 289 (547)
+       "CONTAINS", // 290 (548)
+       "CONTENT", // 291 (549)
+       "CONTROL", // 292 (550)
+       "CONTROLS", // 293 (551)
+       "CONVERT", // 294 (552)
+       "CONVERTING", // 295 (553)
+       "CORRESPONDING", // 296 (554)
+       "COS", // 297 (555)
+       "COUNT", // 298 (556)
+       "CURRENCY", // 299 (557)
+       "CURRENT", // 300 (558)
+       "CURRENT-DATE", // 301 (559)
+       "DATE", // 302 (560)
+       "DATE-COMPILED", // 303 (561)
+       "DATE-OF-INTEGER", // 304 (562)
+       "DATE-TO-YYYYMMDD", // 305 (563)
+       "DATE-WRITTEN", // 306 (564)
+       "DAY", // 307 (565)
+       "DAY-OF-INTEGER", // 308 (566)
+       "DAY-OF-WEEK", // 309 (567)
+       "DAY-TO-YYYYDDD", // 310 (568)
+       "DBCS", // 311 (569)
+       "DE", // 312 (570)
+       "DEBUGGING", // 313 (571)
+       "DECIMAL-POINT", // 314 (572)
+       "DECLARATIVES", // 315 (573)
+       "DELIMITED", // 316 (574)
+       "DELIMITER", // 317 (575)
+       "DEPENDING", // 318 (576)
+       "DESCENDING", // 319 (577)
+       "DETAIL", // 320 (578)
+       "DIRECT", // 321 (579)
+       "DIRECT-ACCESS", // 322 (580)
+       "DIVISION", // 323 (581)
+       "DOWN", // 324 (582)
+       "DUPLICATES", // 325 (583)
+       "DYNAMIC", // 326 (584)
+       "E", // 327 (585)
+       "EBCDIC", // 328 (586)
+       "EC", // 329 (587)
+       "EGCS", // 330 (588)
+       "ENCODING", // 331 (589)
+       "ENTRY", // 332 (590)
+       "EVERY", // 333 (591)
+       "EXAMINE", // 334 (592)
+       "EXHIBIT", // 335 (593)
+       "EXP", // 336 (594)
+       "EXP10", // 337 (595)
+       "EXTEND", // 338 (596)
+       "EXTERNAL", // 339 (597)
+       "EXCEPTION-FILE", // 340 (598)
+       "EXCEPTION-FILE-N", // 341 (599)
+       "EXCEPTION-LOCATION", // 342 (600)
+       "EXCEPTION-LOCATION-N", // 343 (601)
+       "EXCEPTION-STATEMENT", // 344 (602)
+       "EXCEPTION-STATUS", // 345 (603)
+       "FACTORIAL", // 346 (604)
+       "FALSE", // 347 (605)
+       "FD", // 348 (606)
+       "FILE-CONTROL", // 349 (607)
+       "FILE", // 350 (608)
+       "FILE-LIMIT", // 351 (609)
+       "FINAL", // 352 (610)
+       "FINALLY", // 353 (611)
+       "FIND-STRING", // 354 (612)
+       "FIRST", // 355 (613)
+       "FIXED", // 356 (614)
+       "FOOTING", // 357 (615)
+       "FOR", // 358 (616)
+       "FORMATTED-CURRENT-DATE", // 359 (617)
+       "FORMATTED-DATE", // 360 (618)
+       "FORMATTED-DATETIME", // 361 (619)
+       "FORMATTED-TIME", // 362 (620)
+       "FORM-OVERFLOW", // 363 (621)
+       "FREE", // 364 (622)
+       "FRACTION-PART", // 365 (623)
+       "FROM", // 366 (624)
+       "FUNCTION", // 367 (625)
+       "GENERATE", // 368 (626)
+       "GIVING", // 369 (627)
+       "GLOBAL", // 370 (628)
+       "GO", // 371 (629)
+       "GROUP", // 372 (630)
+       "HEADING", // 373 (631)
+       "HEX", // 374 (632)
+       "HEX-OF", // 375 (633)
+       "HEX-TO-CHAR", // 376 (634)
+       "HIGH-VALUES", // 377 (635)
+       "HIGHEST-ALGEBRAIC", // 378 (636)
+       "HOLD", // 379 (637)
+       "IBM-360", // 380 (638)
+       "IN", // 381 (639)
+       "INCLUDE", // 382 (640)
+       "INDEX", // 383 (641)
+       "INDEXED", // 384 (642)
+       "INDICATE", // 385 (643)
+       "INITIAL", // 386 (644)
+       "INITIATE", // 387 (645)
+       "INPUT", // 388 (646)
+       "INSTALLATION", // 389 (647)
+       "INTERFACE", // 390 (648)
+       "INTEGER", // 391 (649)
+       "INTEGER-OF-BOOLEAN", // 392 (650)
+       "INTEGER-OF-DATE", // 393 (651)
+       "INTEGER-OF-DAY", // 394 (652)
+       "INTEGER-OF-FORMATTED-DATE", // 395 (653)
+       "INTEGER-PART", // 396 (654)
+       "INTO", // 397 (655)
+       "INTRINSIC", // 398 (656)
+       "INVOKE", // 399 (657)
+       "I-O", // 400 (658)
+       "I-O-CONTROL", // 401 (659)
+       "IS", // 402 (660)
+       "ISNT", // 403 (661)
+       "KANJI", // 404 (662)
+       "KEY", // 405 (663)
+       "LABEL", // 406 (664)
+       "LAST", // 407 (665)
+       "LEADING", // 408 (666)
+       "LEFT", // 409 (667)
+       "LENGTH", // 410 (668)
+       "LENGTH-OF", // 411 (669)
+       "LIMIT", // 412 (670)
+       "LIMITS", // 413 (671)
+       "LINE", // 414 (672)
+       "LINES", // 415 (673)
+       "LINE-COUNTER", // 416 (674)
+       "LINAGE", // 417 (675)
+       "LINKAGE", // 418 (676)
+       "LOCALE", // 419 (677)
+       "LOCALE-COMPARE", // 420 (678)
+       "LOCALE-DATE", // 421 (679)
+       "LOCALE-TIME", // 422 (680)
+       "LOCALE-TIME-FROM-SECONDS", // 423 (681)
+       "LOCAL-STORAGE", // 424 (682)
+       "LOCATION", // 425 (683)
+       "LOCK", // 426 (684)
+       "LOCK-ON", // 427 (685)
+       "LOG", // 428 (686)
+       "LOG10", // 429 (687)
+       "LOWER-CASE", // 430 (688)
+       "LOW-VALUES", // 431 (689)
+       "LOWEST-ALGEBRAIC", // 432 (690)
+       "LPAREN", // 433 (691)
+       "MANUAL", // 434 (692)
+       "MAXX", // 435 (693)
+       "MEAN", // 436 (694)
+       "MEDIAN", // 437 (695)
+       "MIDRANGE", // 438 (696)
+       "MINN", // 439 (697)
+       "MULTIPLE", // 440 (698)
+       "MOD", // 441 (699)
+       "MODE", // 442 (700)
+       "MODULE-NAME", // 443 (701)
+       "NAMED", // 444 (702)
+       "NAMESPACE", // 445 (703)
+       "NAMESPACE-PREFIX", // 446 (704)
+       "NAT", // 447 (705)
+       "NATIONAL", // 448 (706)
+       "NATIONAL-EDITED", // 449 (707)
+       "NATIONAL-OF", // 450 (708)
+       "NATIVE", // 451 (709)
+       "NESTED", // 452 (710)
+       "NEXT", // 453 (711)
+       "NO", // 454 (712)
+       "NOTE", // 455 (713)
+       "NULLS", // 456 (714)
+       "NULLPTR", // 457 (715)
+       "NUMERIC", // 458 (716)
+       "NUMERIC-EDITED", // 459 (717)
+       "NUMVAL", // 460 (718)
+       "NUMVAL-C", // 461 (719)
+       "NUMVAL-F", // 462 (720)
+       "OCCURS", // 463 (721)
+       "OF", // 464 (722)
+       "OFF", // 465 (723)
+       "OMITTED", // 466 (724)
+       "ON", // 467 (725)
+       "ONLY", // 468 (726)
+       "OPTIONAL", // 469 (727)
+       "OPTIONS", // 470 (728)
+       "ORD", // 471 (729)
+       "ORDER", // 472 (730)
+       "ORD-MAX", // 473 (731)
+       "ORD-MIN", // 474 (732)
+       "ORGANIZATION", // 475 (733)
+       "OTHER", // 476 (734)
+       "OTHERWISE", // 477 (735)
+       "OUTPUT", // 478 (736)
+       "PACKED-DECIMAL", // 479 (737)
+       "PADDING", // 480 (738)
+       "PAGE", // 481 (739)
+       "PAGE-COUNTER", // 482 (740)
+       "PF", // 483 (741)
+       "PH", // 484 (742)
+       "PI", // 485 (743)
+       "PIC", // 486 (744)
        "PLUS", // 487 (745)
        "PRESENT-VALUE", // 488 (746)
        "PRINT-SWITCH", // 489 (747)
diff --git a/gcc/cobol/util.cc b/gcc/cobol/util.cc
index 3085b01bec70..44fb1f794fea 100644
--- a/gcc/cobol/util.cc
+++ b/gcc/cobol/util.cc
@@ -537,15 +537,19 @@ determine_intermediate_type( const cbl_refer_t& aref,
 static char regexmsg[80];
 
 static int
-named_constant( const cbl_name_t name ) {
+named_constant( const cbl_name_t name, cbl_field_type_t *type_out ) {
   int output = -1;
 
   auto e = symbol_field( current_program_index(), 0, name );
   if( e && e->type == SymField ) {
     auto f = cbl_field_of(e);
-    if( f->has_attr(constant_e) && is_numeric(f->type) ) {
-      auto result = f->data.int64_of();
-      if( result.second) output = result.first;
+    if( is_numeric(f->type) ) {
+      if( f->has_attr(constant_e) && is_numeric(f->type) ) {
+        auto result = f->data.int64_of();
+        if( result.second) output = result.first;
+      }
+    } else {
+      *type_out = f->type;
     }
   }
   return output;
@@ -558,35 +562,67 @@ named_constant( const cbl_name_t name ) {
  */
 extern cbl_loc_t yylloc;
 
-std::pair<int, int>
-repeat_count(const char picture[])
+std::pair<uint32_t, int>
+repeat_count(const cbl_loc_t& loc, const char picture[])
 {
   char ch;
-  int count = 0, pos = -1;
+  long count = 0;
+  int pos = -1;
 
-  int n = sscanf(picture, "%c(%d)%n", &ch, &count, &pos);
+  int n = sscanf(picture, "%c(%ld)%n", &ch, &count, &pos);
 
   if( n == 2 ) {
-    if( count < 0 ) {
-      error_msg(yylloc, "not a positive integer constant: %d", count);
+    if( count == 0 ) {
+      error_msg(loc, "%<(0)%> invalid in PICTURE (ISO 2023 13.18.40.3)");
+    } else if( count < 0 ) {
+      error_msg(loc, "not a positive integer constant: %ld", count);
+    } else {
+      uint32_t n = count;
+      if( n != count ) {
+        error_msg(loc, "count exceeds 4 GB: %ld", count);
+      }
     }
   } else {
     cbl_name_t name;
+    cbl_field_type_t type = FldInvalid;
     n = sscanf(picture, "%c(%s)%n", &ch, name, &pos);
+
     if( n == 2 ) {
-      if( (count = named_constant(name)) < 0 ) {
-        error_msg(yylloc, "not a positive integer constant: %qs: %d", name, 
count);
+      auto ename = name + sizeof(name);
+      auto p = std::find(name, ename, ')');
+      if( p < ename ) *p = '\0';
+      if( (count = named_constant(name, &type)) <= 0 ) {
+        if( is_numeric(type) ) {
+          if( count == 0 ) {
+            error_msg(loc, "%qs is 0, invalid in PICTURE (ISO 2023 
13.18.40.3)", name);
+          } else {
+            error_msg(loc, "not a positive integer constant: %qs: %ld", name, 
count);
+          }
+        } else {
+          error_msg(loc, "not an integer constant: %qs", name);
+        }
+      } else {
+        uint32_t n = count;
+        if( n != count ) {
+          error_msg(loc, "count exceeds 4 GB: %qs: %ld", name, count);
+        }
       }
     }
   }
 
   if( n == 2 && 0 <= count ) {
-  return {count, pos};
+    return {count, pos};
   }
 
   return {0, -1};
 }
 
+std::pair<uint32_t, int>
+repeat_count(const char picture[])
+{
+  return repeat_count(yylloc, picture);
+}
+
 const char *numed_message;
 
 extern int yydebug, yy_flex_debug;
@@ -1963,7 +1999,6 @@ cbl_field_t::encode_numeric( const char input[], 
cbl_loc_t loc ) {
 }
 
 size_t parse_error_inc();
-size_t parse_error_count();
 
 bool // true if error reported
 cbl_field_t::report_invalid_initial_value(const cbl_loc_t& loc) const {
diff --git a/gcc/cobol/util.h b/gcc/cobol/util.h
index 2cf91dcd2b27..b99533944376 100644
--- a/gcc/cobol/util.h
+++ b/gcc/cobol/util.h
@@ -45,8 +45,6 @@ void cobol_filename_restore();
 const char * cobol_lineno( int );
 int cobol_lineno(void);
 
-std::pair<int, int> repeat_count(const char picture[]);
-
 unsigned long gb4( size_t input );
 
 template <typename P>
diff --git a/gcc/config/avr/avr.opt.urls b/gcc/config/avr/avr.opt.urls
index e0c725e8d1a8..a7d2d295f89e 100644
--- a/gcc/config/avr/avr.opt.urls
+++ b/gcc/config/avr/avr.opt.urls
@@ -112,7 +112,7 @@ mfuse-move2
 UrlSuffix(gcc/AVR-Options.html#index-mfuse-move2)
 
 moptimize
-UrlSuffix(gcc/AVR-Options.html#index-moptimize-1)
+UrlSuffix(gcc/AVR-Options.html#index-moptimize)
 
 mabsdata
 UrlSuffix(gcc/AVR-Options.html#index-mabsdata)
diff --git a/gcc/config/nvptx/nvptx.opt.urls b/gcc/config/nvptx/nvptx.opt.urls
index 931b329204fd..ced5d34eaeb7 100644
--- a/gcc/config/nvptx/nvptx.opt.urls
+++ b/gcc/config/nvptx/nvptx.opt.urls
@@ -7,7 +7,7 @@ mmainkernel
 UrlSuffix(gcc/Nvidia-PTX-Options.html#index-mmainkernel)
 
 moptimize
-UrlSuffix(gcc/Nvidia-PTX-Options.html#index-moptimize)
+UrlSuffix(gcc/Nvidia-PTX-Options.html#index-moptimize-1)
 
 msoft-stack
 UrlSuffix(gcc/Nvidia-PTX-Options.html#index-msoft-stack)

Reply via email to