diff --git a/gcc/cobol/cdf_text.h b/gcc/cobol/cdf_text.h
index 4f2c281f23c51a20d86aaa2ffce07ae9e8d7d1f1..8c86bc770db7d034d01462523099a9d0904850dc 100644
--- a/gcc/cobol/cdf_text.h
+++ b/gcc/cobol/cdf_text.h
@@ -28,7 +28,51 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+static const char *
+find_filter( const char filter[] ) {
+
+  if( 0 == access(filter, X_OK) ) {
+    return filter;
+  }
+  
+  const char *path = getenv("PATH");
+  if( ! path ) return NULL;
+  char *p = strdup(path), *eopath = p + strlen(p);
+  
+  while( *p != '\0' ) {
+    auto pend = std::find( p, eopath, ':' );
+    if( *pend == ':' ) *pend++ = '\0';
+
+    static char name[PATH_MAX];
+
+    snprintf( name, sizeof(name), "%s/%s", p, filter );
+    
+    if( 0 == access(name, X_OK) ) {
+      return name;
+    }
+    p = pend;
+  }
+  return NULL;
+}
+
+bool verbose_file_reader = false;
+static std::list<char *> preprocessor_filters;
+
 #include "lexio.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+bool preprocess_filter_add( const char filter[] ) {
+  auto filename = find_filter(filter);
+  if( !filename ) {
+    warnx("error: preprocessor '%s/%s' not found", getcwd(NULL, 0), filter);
+    return false;
+  }
+  preprocessor_filters.push_back( strdup(filename) );
+  return true;
+}
+
 FILE *
 cdftext::lex_open( const char filename[] ) {
   int input = open_input( filename );
@@ -39,6 +83,29 @@ cdftext::lex_open( const char filename[] ) {
   cobol_filename(filename);
   process_file( mfile, output );
 
+  for( auto filter : preprocessor_filters ) {
+    input  = output;
+    output = open_output();
+
+    pid_t pid = fork();
+
+    switch(pid){
+    case -1: err(EXIT_FAILURE, "%s", __func__);
+    case 0: // child
+      if( -1 == dup2(input, STDIN_FILENO) ) {
+        errx(EXIT_FAILURE, "%s: could not dup input", __func__);
+      }
+      if( -1 == dup2(output, STDOUT_FILENO) ) {
+        errx(EXIT_FAILURE, "%s: could not dup output", __func__);
+      }
+      _exit( execl( filter, filter, "/dev/stdin", NULL ) );
+    }
+    int status;
+    if( pid != wait(&status) ) {
+      err(EXIT_FAILURE, "error: %s failed with exit status %d", filter, status);
+    }
+  }
+
   return fdopen( output, "r");
 }
 
@@ -49,6 +116,12 @@ cdftext::open_input( const char filename[] ) {
   if( fd == -1 ) {
     if( yydebug ) warn( "error: could not open '%s'", filename );
   }
+
+  verbose_file_reader = NULL != getenv("GCOBOL_TEMPDIR");
+
+  if( verbose_file_reader ) {
+    warnx("verbose: opening %s for input", filename);
+  }
   return fd;
 }
 
@@ -58,7 +131,7 @@ cdftext::open_output() {
   char *name = getenv("GCOBOL_TEMPDIR");
   int fd;
   
-  if( name ) {
+  if( name && 0 != strcmp(name, "/") ) {
     sprintf(stem, "%sXXXXXX", name);
     if( -1 == (fd = mkstemp(stem)) ) {
       err(EXIT_FAILURE,
diff --git a/gcc/cobol/cobol1.cc b/gcc/cobol/cobol1.cc
index 3eaa25a32e4809298bf29e375068079b92f163ca..4cc4f3c9e7e4253c549526b0e056063d5b79babc 100644
--- a/gcc/cobol/cobol1.cc
+++ b/gcc/cobol/cobol1.cc
@@ -155,6 +155,8 @@ void parser_internal_is_ebcdic(bool is_ebcdic);
 bool use_static_call( bool yn );
 void add_cobol_exception( int );
 
+bool preprocess_filter_add( const char filter[] );
+
 bool max_errors_exceeded( int nerr ) {
   return flag_max_errors != 0 && flag_max_errors <= nerr;
 }
@@ -252,7 +254,7 @@ cobol_langhook_handle_option (size_t scode,
           return true;
           
         case OPT_preprocess:
-          ////preprocess_filter_add(arg);
+          preprocess_filter_add(arg);
           return true;
 
         case OPT_main:
diff --git a/gcc/cobol/gcobol.1 b/gcc/cobol/gcobol.1
index ed930fc5e0362493314a88f61af7e60d6b4c7e69..b7ec1cef5010a67be7629efe8c2d3113f4578909 100644
--- a/gcc/cobol/gcobol.1
+++ b/gcc/cobol/gcobol.1
@@ -19,6 +19,7 @@
 .Op Fl findicator-column
 .Op Fl finternal-ebcdic
 .Op Fl dialect Ar dialect-name
+.Op Fl preprocess Ar preprocess-filter
 .Op Fl fflex-debug 
 .Op Fl fyacc-debug
 .Ar filename Op ...
@@ -228,6 +229,25 @@ Only a few such non-standard constructs are accepted, and
 makes no claim or aspiration to emulate other compilers.  But to the
 extent that a feature is popular but nonstandard, this
 option provides a way to support it, or add it.
+.
+.It Fl preprocess Ar preprocess-filter
+After all CDF text-manipulation has been applied, and before the
+prepared \*[lang] is sent to the cobol1 compiler, the input may be
+further altered by one or more filters.  In the tradition of
+.Xr sed 1 ,
+each
+.Ar preprocess-filter
+reads from standard input and writes to standard output.
+No options or arguments are supported for
+.Ar preprocess-filter .
+.Nm
+searches the current working directory and the PATH environment
+variable directories for the existence of an executable file whose
+name matches
+.Ar preprocess-filter .
+The first one found is used.  If none is found, an error is reported
+and the compiler is not invoked.
+.
 .It Fl fflex-debug Ns Li , Fl fyacc-debug
 produce messages useful for compiler development.  The
 .Fl fflex-debug
@@ -875,7 +895,8 @@ through
 where 0-7 indicates a bit position.  The value of the UPSI switches is
 taken from the
 .Ev UPSI
-environment variable, whose value is a string of up to eight 1's and 0's.  The first character represents the value of
+environment variable, whose value is a string of up to eight 1's and
+0's.  The first character represents the value of
 .Sy UPSI-0 ,
 and missing values are assigned 0.  For example,
 .Sy UPSI=1000011
@@ -885,6 +906,15 @@ in the environment sets bits 0, 5, and 6 on, which means that
 and
 .Sy UPSI-6
 are on.
+.It Ev GCOBOL_TEMPDIR
+causes any temporary files created during CDF processing to be written
+to a file whose name is specified in the value of
+.Ev GCOBOL_TEMPDIR .
+If the value is just
+.Dq / ,
+the effect is different: each copybook read is reported on standard
+error.  This feature is meant to help diagnose mysterious copybook
+errors.
 .El
 .
 .Sh FILES
diff --git a/gcc/cobol/lexio.h b/gcc/cobol/lexio.h
index e619d853abfd4e80ae6ba0ced714b356c4870e45..2deca53c15c92f6bfc077f87c119111e6a45ac3d 100644
--- a/gcc/cobol/lexio.h
+++ b/gcc/cobol/lexio.h
@@ -230,13 +230,6 @@ struct replace_t {
 #include <list>
 
 class cdftext {
-  ////std::stack< std::list<replace_t> > replace_directives;
-  
-  //// bool parse_copy_directive( filespan_t& mfile );
-  //// bool parse_replace_last_off( filespan_t& mfile );
-  //// bool parse_replace_text( filespan_t& mfile, size_t current_lineno );
-  //// parse_replace_directive( filespan_t& mfile, size_t current_lineno );
-  
   static filespan_t  free_form_reference_format( int fd ); 
   static void process_file( filespan_t, int output, bool second_pass = false );
   
diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y
index a8d00f6408a01dfa8fecfd829fbad065b61d0306..67cbd6fea55f78d5356bbfdba87305be350868df 100644
--- a/gcc/cobol/parse.y
+++ b/gcc/cobol/parse.y
@@ -2938,11 +2938,11 @@ data_descr1:    level_name
                   assert($field == current_field());
                   if( $data_clauses == value_clause_e ) { // only VALUE, no PIC
 		    // Error unless VALUE is a figurative constant or (quoted) string.
-		    if( !has_field_attr($field->attr, quoted_e) &&
+		    if( $field->type != FldPointer &&
+		        ! has_field_attr($field->attr, quoted_e) &&
 			normal_value_e == cbl_figconst_of($field->data.initial) )
 		    {
-		      yyerrorv("syntax error: "
-			       "%s numeric VALUE %s requires PICTURE",
+		      yyerrorv("error: %s numeric VALUE %s requires PICTURE",
 			       $field->name, $field->data.initial);
 		    }
                     $field->type = FldAlphanumeric;
@@ -3172,10 +3172,11 @@ data_clauses:   data_clause
                     YYERROR;
                   }
                   cbl_field_t *field = current_field();
+#if 0
                   if( symbol_redefines(field) ) {
                     redefine_field(field);
                   }
-
+#endif
                   const int globex = (global_e | external_e);
                   if( (($$ | $2) & globex) == globex ) {
                     yyerror("GLOBAL and EXTERNAL specified");
@@ -3513,7 +3514,25 @@ usage_clause1:  usage COMPUTATIONAL[comp]   native
                   $$ = symbol_field_index_set( current_field() )->type;
 		}
 		// We should enforce data/code pointers with a different type. 
-        |       usage POINTER                { $$ = FldPointer; }
+        |       usage POINTER
+		{
+		  $$ = FldPointer;
+		  auto field = current_field();
+		  auto redefined = symbol_redefines(field);
+		  
+		  field->data.capacity = sizeof(void *);
+
+		  if( dialect_ibm() && redefined &&
+		      is_numeric(redefined->type) && redefined->size() == 4) {
+		    // For now, we allow POINTER to expand a 32-bit item to 64 bits.
+		    if( yydebug ) {
+		      warnx("%s: expanding #%zu %s capacity %u => %u", __func__, 
+		  	  field_index(redefined), redefined->name,
+		  	  redefined->data.capacity, field->data.capacity);
+		    }
+		    redefined->data.capacity = field->data.capacity;
+		  }
+		}
         |       usage POINTER TO error
 		{
 		  yyerror("error: unimplemented: TYPEDEF");
@@ -3626,6 +3645,7 @@ redefines_clause: REDEFINES NAME[orig]
 		             orig->level, name_of(orig), 
 		             field->level, name_of(field));
 		  }
+		
 		  if( valid_redefine(field, orig) ) {
                     /*
                      * Defer "inheriting" the parent's description until the
diff --git a/gcc/cobol/parse_ante.h b/gcc/cobol/parse_ante.h
index 865dd1c11b0d4da8ee4945f43c60c513bf95539c..b04c1cbe08e75731c92aa5dd7b8b83b22a1e4ab1 100644
--- a/gcc/cobol/parse_ante.h
+++ b/gcc/cobol/parse_ante.h
@@ -2166,12 +2166,17 @@ valid_redefine( const cbl_field_t *field, const cbl_field_t *orig ) {
    */
   if( field->type != FldGroup && orig->type != FldGroup ) {
     if( orig->size() < field->size() ) {
-      if( orig->level > 1 || has_field_attr(orig->attr, external_e) ) 
+      if( orig->level > 1 || has_field_attr(orig->attr, external_e) ) {
+        if( yydebug ) {
+          yyerrorv( "size error orig:  %s", field_str(orig) );
+          yyerrorv( "size error redef: %s", field_str(field) );
+        }
         yyerrorv( "error: %s (%s size %u) larger than REDEFINES %s (%s size %u)",
                   field->name,
                   3 + cbl_field_type_str(field->type), field->size(),
                   orig->name,
                   3 + cbl_field_type_str(orig->type), orig->size() );
+      }
     }
   }
   
diff --git a/gcc/cobol/symbols.cc b/gcc/cobol/symbols.cc
index 110c3f038255721950cb5d98adf463a29c3e9550..98644f11b586d48aee6fa8fa254db1fc073e5736 100644
--- a/gcc/cobol/symbols.cc
+++ b/gcc/cobol/symbols.cc
@@ -1266,31 +1266,35 @@ static struct symbol_elem_t *
      * referenced by data- name-2 has been specified with level
      * number 1 and without the EXTERNAL clause.
      */
-    if( redefined && redefined->type == FldGroup && redefined->level > 1 ) {
-      if( field->type != FldGroup && redefined->type != FldGroup ) {
-        if( field_memsize(redefined) < field_memsize(field) ) {
-          yyerrorv("error: line %d: %s (size %u) larger than REDEFINES %s (size %u)",
-                   field->line,
-                   field->name, field_memsize(field),
-                   redefined->name, field_memsize(redefined));
+    if( redefined ) {
+      if( redefined->type == FldGroup && redefined->level > 1 ) {
+        if( field->type != FldGroup && redefined->type != FldGroup ) {
+          assert(false);
+          // don't know what this intended, but redefined->type can't be FldGroup and not.
+          if( field_memsize(redefined) < field_memsize(field) ) {
+            yyerrorv("error: line %d: %s (size %u) larger than REDEFINES %s (size %u)",
+                     field->line,
+                     field->name, field_memsize(field),
+                     redefined->name, field_memsize(redefined));
+          }
         }
       }
-    }
+      
+      if( redefined != group) {
+        if( group->our_index != redefined->parent ) {
+          if( yydebug ) yyerrorv("%s:%d: our index %zu != redefined parent %zu",
+                                 __func__, __LINE__, group->our_index, redefined->parent);
+          continue;
+        }
 
-    if( redefined && redefined != group) {
-      if( group->our_index != redefined->parent ) {
-        if( yydebug ) yyerrorv("%s:%d: our index %zu != redefined parent %zu",
-                               __func__, __LINE__, group->our_index, redefined->parent);
+        redefined->data.memsize = std::max(field_memsize(redefined), 
+                                           field_memsize(field));
+        field->data.memsize = 0;
+        if( redefined->data.memsize == redefined->data.capacity ) {
+          redefined->data.memsize = 0;
+        }
         continue;
       }
-
-      redefined->data.memsize = std::max(field_memsize(redefined), 
-                                         field_memsize(field));
-      field->data.memsize = 0;
-      if( redefined->data.memsize == redefined->data.capacity ) {
-        redefined->data.memsize = 0;
-      }
-      continue;
     }
     
     members.push_back(field);
@@ -1312,7 +1316,9 @@ static struct symbol_elem_t *
     if( redefined ) {
       assert( group == redefined );
       max_memsize = std::max(max_memsize, field_memsize(field));
-      field->data.memsize = 0;
+      if( redefined->data.memsize == redefined->data.capacity ) {
+        redefined->data.memsize = 0;
+      }
       continue;
     }
     group->data.capacity += field_size(field);
@@ -1328,7 +1334,9 @@ static struct symbol_elem_t *
   if( group->data.memsize == group->data.capacity ) group->data.memsize = 0;
 
   if( 0 < group->data.memsize && group->data.memsize < group->data.capacity ) {
-    warnx( "%s:%d: small capacity?\n\t%s", __func__, __LINE__, field_str(group) );
+    if( yydebug ) {
+      warnx( "%s:%d: small capacity?\n\t%s", __func__, __LINE__, field_str(group) );
+    }
     group->data.memsize = group->data.capacity;
   }
 
diff --git a/gcc/cobol/util.cc b/gcc/cobol/util.cc
index bbc3e7824c9d56824e10f4e149eed1800de043c0..7f94c2e8d9ccc425e8f3afc7b20b89443cf51917 100644
--- a/gcc/cobol/util.cc
+++ b/gcc/cobol/util.cc
@@ -752,7 +752,7 @@ redefine_field( cbl_field_t *field ) {
   }
 
   if( field->data.capacity == 0 ) field->data = primary->data;
-  
+
   if( is_numeric(field->type) && field->usage == FldDisplay ) {
     fOK = symbol_field_type_update(field, FldNumericDisplay, false);
   }