diff --git a/gcc/cobol/ChangeLog b/gcc/cobol/ChangeLog
index 8090c57df7422a30fe32a3efb3030be181d3bb7f..316d0d2849aa69571ea90ced20fe6f0698760f81 100644
--- a/gcc/cobol/ChangeLog
+++ b/gcc/cobol/ChangeLog
@@ -54,4 +54,6 @@
 2024-12-25  Robert Dubner <rdubner@symas.com>
 	* Normalize #includes in util.cc
 	* Normalize #includes in symfind.cc
+	* Normalize #includes in cdf-copy.cc and copybook.h
+
 
diff --git a/gcc/cobol/cdf-copy.cc b/gcc/cobol/cdf-copy.cc
index fe0f3a21310302cf1d87a3b935793b564b5aded6..8cde94ec4bd96cb215bc54fa600cef45c12bba84 100644
--- a/gcc/cobol/cdf-copy.cc
+++ b/gcc/cobol/cdf-copy.cc
@@ -34,22 +34,11 @@
 //
 // We regret any confusion engendered.
 
-#include "lexio.h"
-#include "util.h"
+#include "cobol-system.h"
 #include "copybook.h"
 
-#include <deque>
-
-#include <errno.h>
-#include <fcntl.h>
 #include <glob.h>
 #include <libgen.h>
-#include <regex.h>
-#include <unistd.h>
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/uio.h>
 
 #define COUNT_OF(X) (sizeof(X) / sizeof(X[0]))
 
@@ -93,10 +82,10 @@ bool is_reference_format();
 struct line_t {
   char *p, *pend;
   line_t( size_t len, char *data ) : p(data), pend(data + len) {
-    assert(p && p <= pend);
+    gcc_assert(p && p <= pend);
   }
   line_t( char *data, char *eodata ) : p(data), pend(eodata) {
-    assert(p && p <= pend);
+    gcc_assert(p && p <= pend);
   }
   ssize_t size() const { return pend - p; }
 };
@@ -109,7 +98,7 @@ is_separator_space( const char *p) {
     if( p[1] == 0x20 ) return true;
     break;
   }
-  return isspace(*p);
+  return ISSPACE(*p);
 }
 /*
  * Replace any separators in the copybook's REPLACING candidate with
@@ -135,7 +124,7 @@ esc( size_t len, const char input[] ) {
 
   for( const char *s=input; *s && s < eoinput; s++ ) {
     *p = '\0';
-    assert( size_t(p - buffer) < sizeof(buffer) - 4 );
+    gcc_assert( size_t(p - buffer) < sizeof(buffer) - 4 );
     switch(*s) {
     case '^': case '$':
     case '(': case ')':
@@ -160,7 +149,7 @@ esc( size_t len, const char input[] ) {
       }
       __attribute__((fallthrough));
     case 0x20: case '\n':
-      assert(p + sizeof(spacex) < buffer + sizeof(buffer));
+      gcc_assert(p + sizeof(spacex) < buffer + sizeof(buffer));
       p = stpcpy( p, spacex );
       while( s+1 < eoinput && is_separator_space(s+1)) {
         s++;
@@ -176,26 +165,26 @@ esc( size_t len, const char input[] ) {
 #if 0
   cbl_warnx("%s:%d: regex '%s'", __func__, __LINE__, buffer);
 #endif
-  return strdup(buffer);
+  return xstrdup(buffer);
 }
 
 void yyerrorv( const char fmt[], ... );
 
 static int glob_error(const char *epath, int eerrno) {
-  yyerrorv("COPY file search error: '%s': %s", epath, strerror(eerrno));
+  yyerrorv("COPY file search error: '%s': %s", epath, xstrerror(eerrno));
   return 0;
 }
 
 void
 copybook_directory_add( const char gcob_copybook[] ) {
   if( !gcob_copybook ) return;
-  char *directories = strdup(gcob_copybook), *p = directories;
+  char *directories = xstrdup(gcob_copybook), *p = directories;
   if( !directories ) {
     cbl_warn( "OS error: %s", gcob_copybook );
     return;
   }
   char *eodirs = strchr(directories, '\0');
-  assert(eodirs);
+  gcc_assert(eodirs);
 
   do {
     char *pend = std::find(p, eodirs, ':');
@@ -213,8 +202,8 @@ class case_consistent {
 public:
   case_consistent() : lower_upper(0) {}
   bool operator()( char ch ) {
-    if( !isalpha(ch) ) return true;
-    int lu = islower(ch)? -1 : 1;
+    if( !ISALPHA(ch) ) return true;
+    int lu = ISLOWER(ch)? -1 : 1;
     if( !lower_upper ) {
       lower_upper = lu;
       return true;
@@ -228,9 +217,9 @@ copybook_extension_add( const char ext[] ) {
   char *alt = NULL;
   bool one_case = std::all_of( ext, ext + strlen(ext), case_consistent() );
   if( one_case ) {
-    alt = strdup(ext);
-    assert(alt);
-    auto convert = islower(ext[0])? toupper : tolower;
+    alt = xstrdup(ext);
+    gcc_assert(alt);
+    auto convert = ISLOWER(ext[0])? toupper : tolower;
     std::transform( alt, alt+strlen(alt), alt, convert );
   }
   copybook.extensions_add( ext, alt );
@@ -248,11 +237,11 @@ copybook_t::extensions_add( const char ext[], const char alt[] ) {
       cbl_err(EXIT_FAILURE, "could not add copybook extension");
     }
   } else {
-    if( (output = strdup(ext)) == NULL ) {
+    if( (output = xstrdup(ext)) == NULL ) {
       cbl_err(EXIT_FAILURE, "could not add copybook extension");
     }
   }
-  assert(output);
+  gcc_assert(output);
   if( book.extensions ) {
     char *s;
     if( -1 == asprintf(&s, "%s,%s", output, book.extensions) ) {
@@ -278,7 +267,7 @@ inode_of( int fd ) {
 int
 copybook_elem_t::open_file( const char directory[], bool literally ) {
   int erc;
-  char  *pattern, *copier = strdup(cobol_filename());
+  char  *pattern, *copier = xstrdup(cobol_filename());
   if( ! directory ) {
     directory = dirname(copier);
     if( 0 == strcmp(".", directory) ) directory = NULL;
@@ -306,7 +295,7 @@ copybook_elem_t::open_file( const char directory[], bool literally ) {
       if( yydebug ) cbl_warn("error: could not open %s", path);
       return fd;
     } 
-    this->source = strdup(path);
+    this->source = xstrdup(path);
     if( ! cobol_filename(this->source, inode_of(fd)) ) {
       yyerrorv("recursive copybook: '%s' includes itself", path);
       (void)! close(fd);
@@ -314,7 +303,7 @@ copybook_elem_t::open_file( const char directory[], bool literally ) {
     }
     return fd;
   }
-  assert( ! literally );
+  gcc_assert( ! literally );
   
   if( extensions ) {
     if( -1 == asprintf(&pattern, "%s{,.cpy,.CPY,.cbl,.CBL,.cob,.COB,%s}",
@@ -357,10 +346,10 @@ copybook_elem_t::open_file( const char directory[], bool literally ) {
       if( yydebug ) {
         cbl_warnx("found copybook file %s", filename);
       }
-      this->source = strdup(filename);
+      this->source = xstrdup(filename);
       if( ! this->source ) {
         yyerrorv("could not allocate memory for copybook name %s: %s",
-                 filename, strerror(errno));
+                 filename, xstrerror(errno));
         (void)! close(fd);
         fd = -1;
       }
diff --git a/gcc/cobol/cdf.y b/gcc/cobol/cdf.y
index f2feaab59192181af67f52d88c31b629ecd97049..db692e9647e1eda5af2ce8750bd2ab0cb3902695 100644
--- a/gcc/cobol/cdf.y
+++ b/gcc/cobol/cdf.y
@@ -29,7 +29,7 @@
  */
 %{
 #include "util.h"
-#include "copybook.h"
+#include "copybook-old.h"
 #include "ec.h"
 #include "symbols.h"
 #include "exceptl.h"
diff --git a/gcc/cobol/cobol-system.h b/gcc/cobol/cobol-system.h
index 98a62916b77d103f4fd04d9dd7bd6f8eaffd3c19..edbdd43489c70677787c2ef34eb1a322181b7b64 100644
--- a/gcc/cobol/cobol-system.h
+++ b/gcc/cobol/cobol-system.h
@@ -47,13 +47,10 @@
 #define INCLUDE_LIST
 #define INCLUDE_ALGORITHM
 #define INCLUDE_NUMERIC
+#define INCLUDE_STACK
 
-
-
-
-#include <cctype>
-#include <stack>
-
+//#include <cctype>
+#include <deque>
 #include <unordered_map>
 #include <unordered_set>
 
diff --git a/gcc/cobol/copybook-old.h b/gcc/cobol/copybook-old.h
new file mode 100644
index 0000000000000000000000000000000000000000..56bbc36ce08edcfc4aa4ee95d1987fd5b0201234
--- /dev/null
+++ b/gcc/cobol/copybook-old.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2021-2024 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.
+ */
+#include <algorithm>
+#include <deque>
+#include <list>
+#include <stack>
+
+#include <assert.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+FILE * copy_mode_start();
+
+const char * cobol_filename();
+bool cobol_filename( const char *name, ino_t inode );
+
+void scanner_parsing( int token, bool tf );
+void scanner_parsing_toggle();
+void scanner_parsing_pop();
+
+/*
+ * COPY support On encountering a COPY statement, the parser continues
+ * to parse, collecting the replacement values, if any.  At statement
+ * end (at the period), the system rearranges input to apply the
+ * replacements before the input text is read by the lexer.
+ */
+
+enum replace_type_t { string_e, token_e, pseudo_e };
+
+struct copybook_replace_t {
+  replace_type_t type;
+  const char *src, *tgt;
+};
+
+struct copybook_elem_t {
+  bool suppress;
+  const char *source, *library;
+  static const char *extensions;
+  struct { bool source, library; } literally;
+  int  fd;
+  size_t nsubexpr;
+  std::deque<copybook_replace_t> replacements;
+
+  copybook_elem_t()
+    : suppress(false)
+    , source(NULL)
+    , library(NULL)
+    , fd(-1)
+    , nsubexpr(0)
+    , regex_text(NULL)
+  {
+    literally = {};
+  }
+  explicit copybook_elem_t( char src[] )
+    : suppress(false)
+    , source(src)
+    , library(NULL)
+    , fd(-1)
+    , nsubexpr(0)
+    , regex_text(NULL)
+  {
+    literally = {};
+  }
+
+  void clear() {
+    suppress = false;
+    nsubexpr = 0;
+    if( fd ) close(fd);
+    fd = -1;
+    // TODO: free src & tgt
+    replacements.clear();
+  }
+
+  int open_file( const char dir[], bool literally = false );
+  void extensions_add( const char ext[], const char alt[] );
+  
+  static inline bool is_quote( const char ch ) {
+    return ch == '\'' || ch == '"';
+  }
+  static inline bool quoted( const char name[] ) {
+    assert(name);
+    return is_quote(name[0]);
+  }
+  static char * dequote( const char orig[] ) {
+    assert(quoted(orig));
+    auto name = (char*)calloc(1, strlen(orig));
+    assert(name);
+    char *tgt = name;
+
+    // For a literal name, we de-quote it and try to open it in the
+    // current working directory.  The COBOL literal could include
+    // (escaped) doubled quotes, which we reduce to one.
+    for( const char *src = orig; src < orig + strlen(orig); ) {
+      if( is_quote(src[0]) ) {
+        if( src[0] == src[1] ) {
+          *tgt++ = *src++; // copy one of doubled quote
+        }
+        src++; // skip quote
+        continue;
+      }
+      *tgt++ = *src++;
+    }
+    *tgt = '\0';
+
+    return name;
+  }
+
+private:
+  char *regex_text;
+};
+
+class copybook_t {
+  std::list<const char *> directories;
+  copybook_elem_t book;
+
+  static const char * transform_name( const char input[] ) {
+    static char path[PATH_MAX];
+    const char *output = getenv(input);
+    if( !output ) {
+      auto einput = input + std::min(sizeof(path), strlen(input));
+      std::transform( input, einput, path,
+                      []( char ch ) { return toupper(ch); } );
+      output = getenv(path); // try uppercase of envar output
+      if( !output ) output = input; // keep original unmodified
+    }
+    if( false && output != path ) {
+      cbl_warnx("using copybook file '%s' from environment variable ''%s",
+            output, input);
+    }
+    return strdup(output);
+  }
+
+ public:
+  copybook_t() { directories.push_back(NULL); }
+
+  void suppress( bool tf = true  ) { book.suppress = tf; }
+  bool suppressed()                { return book.suppress; }
+  void source( const char name[] ) {
+    book.literally.source = copybook_elem_t::quoted(name);
+    book.source = book.literally.source?
+      copybook_elem_t::dequote(name) : transform_name(name);
+  }
+  void library( const char name[] ) {
+    book.literally.library = copybook_elem_t::quoted(name);
+    book.library = book.literally.library?
+      copybook_elem_t::dequote(name) : transform_name(name);
+  }
+  bool replacement( replace_type_t type, const char src[], const char tgt[] ) {
+    copybook_replace_t elem = { type, src, tgt };
+    book.replacements.push_back(elem);
+    return true;
+  }
+
+  copybook_elem_t *current() { return &book; }
+
+  int open(const char name[]) {
+    int fd = -1;
+    book.clear();
+    this->source(name);
+
+    for( auto dir : directories ) {
+      if( false ) {
+        cbl_warnx("copybook_t::open( '%s' OF '%s' %s",
+              book.source, dir, book.literally.source? ", literally" : "" );
+      }
+      if( (fd = book.open_file(dir, book.literally.source)) != -1 ) break;
+    }
+    return fd;
+  }
+
+  const char * directory_add( const char name[] ) {
+    directories.push_back(name);
+    return name;
+  }
+  void extensions_add( const char ext[], const char alt[] );
+};
+
+extern copybook_t copybook;
+
diff --git a/gcc/cobol/copybook.h b/gcc/cobol/copybook.h
index 56bbc36ce08edcfc4aa4ee95d1987fd5b0201234..897be5707ab9b06349e7d5a1bdce4bee3da4b728 100644
--- a/gcc/cobol/copybook.h
+++ b/gcc/cobol/copybook.h
@@ -27,21 +27,8 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-#include <algorithm>
-#include <deque>
-#include <list>
-#include <stack>
-
-#include <assert.h>
-#include <ctype.h>
-#include <libgen.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
 
+#include "util.h"
 
 FILE * copy_mode_start();
 
@@ -112,13 +99,13 @@ struct copybook_elem_t {
     return ch == '\'' || ch == '"';
   }
   static inline bool quoted( const char name[] ) {
-    assert(name);
+    gcc_assert(name);
     return is_quote(name[0]);
   }
   static char * dequote( const char orig[] ) {
-    assert(quoted(orig));
-    auto name = (char*)calloc(1, strlen(orig));
-    assert(name);
+    gcc_assert(quoted(orig));
+    auto name = (char*)xcalloc(1, strlen(orig));
+    gcc_assert(name);
     char *tgt = name;
 
     // For a literal name, we de-quote it and try to open it in the
@@ -153,7 +140,7 @@ class copybook_t {
     if( !output ) {
       auto einput = input + std::min(sizeof(path), strlen(input));
       std::transform( input, einput, path,
-                      []( char ch ) { return toupper(ch); } );
+                      []( char ch ) { return TOUPPER(ch); } );
       output = getenv(path); // try uppercase of envar output
       if( !output ) output = input; // keep original unmodified
     }
@@ -161,7 +148,7 @@ class copybook_t {
       cbl_warnx("using copybook file '%s' from environment variable ''%s",
             output, input);
     }
-    return strdup(output);
+    return xstrdup(output);
   }
 
  public:
diff --git a/gcc/cobol/lexio.cc b/gcc/cobol/lexio.cc
index d8ebd4f22f573a6941202a1614038d28335e632a..f7725fb4800a857ef03ee3bbb09628583f525649 100644
--- a/gcc/cobol/lexio.cc
+++ b/gcc/cobol/lexio.cc
@@ -103,7 +103,7 @@ bool set_debug( bool tf ) { return debug_mode = tf && is_fixed_format(); }
 static bool nonblank( const char ch ) { return !isblank(ch); }
 
 #include "util.h"
-#include "copybook.h"
+#include "copybook-old.h"
 
 #include <string>
 
diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h
index cb3e277004442473f9d3f38a1ec986bfdc339f02..d50e1aea70b33b6d8254b41883357ce1dfe6bb80 100644
--- a/gcc/cobol/parse_ante.h
+++ b/gcc/cobol/parse_ante.h
@@ -30,7 +30,7 @@
 
 #include "genapi.h"
 #include "util.h"
-#include "copybook.h"
+#include "copybook-old.h"
 #include "io.h"
 #include "ec.h"
 #include "cbldiag.h"
diff --git a/gcc/cobol/scan_ante.h b/gcc/cobol/scan_ante.h
index d8357ef64979773b30f7c13ded9872b74fbc0bf2..60c0fcfaa69399a2998a26c4f6bf80368dade800 100644
--- a/gcc/cobol/scan_ante.h
+++ b/gcc/cobol/scan_ante.h
@@ -41,7 +41,7 @@
 #include "cdf.h"
 #include "symbols.h"
 #include "util.h"
-#include "copybook.h"
+#include "copybook-old.h"
 #include "cbldiag.h"
 
 /*