From 65521437b7bde22500eb63de2adf6a4beb4f545f Mon Sep 17 00:00:00 2001
From: "James K. Lowden" <jklowden@symas.com>
Date: Tue, 2 Jan 2024 15:44:58 -0500
Subject: [PATCH] introduce -preprocess option

---
 gcc/cobol/cdf_text.h | 75 +++++++++++++++++++++++++++++++++++++++++++-
 gcc/cobol/cobol1.cc  |  4 ++-
 gcc/cobol/lexio.h    |  7 -----
 3 files changed, 77 insertions(+), 9 deletions(-)

diff --git a/gcc/cobol/cdf_text.h b/gcc/cobol/cdf_text.h
index 4f2c281f23c5..8c86bc770db7 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 3eaa25a32e48..4cc4f3c9e7e4 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/lexio.h b/gcc/cobol/lexio.h
index e619d853abfd..2deca53c15c9 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 );
   
-- 
GitLab