[RFC] algol68: Accept -I option and search the include path including files

Pietro Monteiro pietro@sociotechnical.xyz
Thu Mar 20 21:20:50 GMT 2025


This is a first stab at processing `-I' in ga68.

pietro.

gcc/ChangeLog:

	* algol68/a68-lang.cc: Remove unneeded include `ggc.h'.
	(a68_handle_option): Handle `-I'.
	* algol68/a68-parser-scanner.cc (a68_file_read_p): New function.
	(find_include_file): New function.
	(include_files): Use `find_include_file' to find a file to include.
	* algol68/a68-types.h (struct MODULE_T): Add new member `include_paths'.
	(INCLUDE_PATHS): New macro.
	* algol68/lang.opt: Add `I' option.
	* algol68/lang.opt.urls: Regenerate.

gcc/testsuite/ChangeLog:

	* algol68/compile/a68includes/goodbye.a68: New test.
	* algol68/compile/a68includes/hello.a68: New test.
	* algol68/compile/include.a68: New test.

Signed-off-by: Pietro Monteiro <pietro@sociotechnical.xyz>
---
 gcc/algol68/a68-lang.cc                       |   7 +-
 gcc/algol68/a68-parser-scanner.cc             | 123 ++++++++++++++----
 gcc/algol68/a68-types.h                       |   3 +
 gcc/algol68/lang.opt                          |   4 +
 gcc/algol68/lang.opt.urls                     |   3 +
 .../algol68/compile/a68includes/goodbye.a68   |   5 +
 .../algol68/compile/a68includes/hello.a68     |   5 +
 gcc/testsuite/algol68/compile/include.a68     |  19 +++
 8 files changed, 141 insertions(+), 28 deletions(-)
 create mode 100644 gcc/testsuite/algol68/compile/a68includes/goodbye.a68
 create mode 100644 gcc/testsuite/algol68/compile/a68includes/hello.a68
 create mode 100644 gcc/testsuite/algol68/compile/include.a68

diff --git a/gcc/algol68/a68-lang.cc b/gcc/algol68/a68-lang.cc
index 854d01db342..dd76e67cdca 100644
--- a/gcc/algol68/a68-lang.cc
+++ b/gcc/algol68/a68-lang.cc
@@ -25,12 +25,12 @@
 #include "langhooks-def.h"
 #include "target.h"
 #include "stringpool.h"
-#include "ggc.h"
 #include "debug.h"
 #include "diagnostic.h"
 #include "opts.h"
 #include "machmode.h"
 #include "stor-layout.h" /* For layout_type */
+#include "vec.h"
 
 #include "a68.h"
 
@@ -461,7 +461,7 @@ a68_init_options (unsigned int argc ATTRIBUTE_UNUSED,
 
 static bool
 a68_handle_option (size_t scode,
-		   const char *arg ATTRIBUTE_UNUSED,
+		   const char *arg,
 		   HOST_WIDE_INT value ATTRIBUTE_UNUSED,
 		   int kind ATTRIBUTE_UNUSED,
 		   location_t loc ATTRIBUTE_UNUSED,
@@ -486,6 +486,9 @@ a68_handle_option (size_t scode,
     case OPT_fa68_nil_checking:
       OPTION_NIL_CHECKING (&A68_JOB) = flag_a68_nil_checking;
       break;
+    case OPT_I:
+      vec_safe_push (INCLUDE_PATHS (&A68_JOB), arg);
+      break;
     default:
       break;
     }
diff --git a/gcc/algol68/a68-parser-scanner.cc b/gcc/algol68/a68-parser-scanner.cc
index 23457f3a2d2..ea4666e9063 100644
--- a/gcc/algol68/a68-parser-scanner.cc
+++ b/gcc/algol68/a68-parser-scanner.cc
@@ -28,6 +28,7 @@
 #include "coretypes.h"
 #include "diagnostic.h"
 #include "options.h"
+#include "vec.h"
 
 #include "a68.h"
 
@@ -729,6 +730,83 @@ a68_relpath (const char *p1, const char *p2, const char *fn)
   return r;
 }
 
+static bool
+a68_file_read_p (const char *filename)
+{
+  return !access (filename, R_OK);
+}
+
+
+/* Make the name relative to the position of the source file
+   (C preprocessor standard).  */
+
+static char *
+find_include_file(const char *curfile, const char *filename)
+{
+  char *filepath = NO_TEXT;
+  char *tmpfpath = NO_TEXT;
+  char *fnbdir = ldirname (filename);
+  const char *incfile = lbasename (filename);
+
+  if (fnbdir == NULL || incfile == NULL)
+    gcc_unreachable ();
+
+  if (!IS_ABSOLUTE_PATH (filename))
+    {
+      char *sourcedir = ldirname (curfile);
+
+      if (sourcedir == NULL || fnbdir == NULL)
+	gcc_unreachable ();
+
+      if (strlen(sourcedir) == 0 && strlen(fnbdir) == 0)
+	{
+	  free(sourcedir);
+	  sourcedir = (char *) xmalloc (2);
+	  a68_bufcpy (sourcedir, ".", 2);
+	}
+
+      tmpfpath = a68_relpath (sourcedir, fnbdir, incfile);
+      if (a68_file_read_p (tmpfpath))
+	{
+	  filepath = tmpfpath;
+	  goto cleanup;
+	}
+
+      for (unsigned ix = 0; ix != vec_safe_length (INCLUDE_PATHS (&A68_JOB)); ix++)
+	{
+	  const char *include_dir = (*(INCLUDE_PATHS (&A68_JOB)))[ix];
+	  tmpfpath = a68_relpath (include_dir, fnbdir, incfile);
+	  if (!IS_ABSOLUTE_PATH (tmpfpath))
+	    tmpfpath = a68_relpath (sourcedir, fnbdir, incfile);
+	  if (a68_file_read_p (tmpfpath))
+	    {
+	      filepath = tmpfpath;
+	      goto cleanup;
+	    }
+	}
+
+    cleanup:
+      free (sourcedir);
+      goto end;
+    }
+  else
+    {
+      size_t fnwid = (int) strlen (filename) + 1;
+      tmpfpath = (char *) xmalloc ((size_t) fnwid);
+      a68_bufcpy (tmpfpath, filename, fnwid);
+
+      if (a68_file_read_p (tmpfpath))
+	{
+	  filepath = tmpfpath;
+	  goto end;
+	}
+    }
+
+ end:
+  free (fnbdir);
+  return filepath;
+}
+
 /* Include files.
    This function handles the INCLUDE pragmat in the source file.  */
 
@@ -818,35 +896,28 @@ include_files (LINE_T *top)
 	      SCAN_ERROR (n == 0, start_l, start_c,
 			  "incorrect filename");
 
-	      if (!IS_ABSOLUTE_PATH (fnb))
+	      char *sourcefile = NO_TEXT;
+	      if (FILENAME (u) != NO_TEXT)
 		{
-		  /* Make the name relative to the position of the source file
-		     (C preprocessor standard).  */
-		  /* XXX Search in the include_path instead.  */
-		  if (FILENAME (u) != NO_TEXT)
-		    {
-		      char *sourcefile = xstrdup (FILENAME (u));
-		      char *sourcedir = ldirname (sourcefile);
-		      char *fnbdir = ldirname (fnb);
-
-		      if (sourcedir == NULL || fnbdir == NULL)
-			gcc_unreachable ();
-
-		      fn = a68_relpath (sourcedir, fnbdir, lbasename (fnb));
-		      free (sourcefile);
-		      free (fnbdir);
-		      free (sourcedir);
-		    }
-
-		  /* Do not check errno, since errno may be undefined here
-		     after a successful call.  */
-		  if (fn != NO_TEXT)
-		    a68_bufcpy (fnb, fn, BUFFER_SIZE);
-		  else
-		    SCAN_ERROR (true, NO_LINE, NO_TEXT,
-				"error opening include file");
+		  sourcefile = xstrdup (FILENAME (u));
 		}
+	      else
+		{
+		  sourcefile = (char *) xmalloc (2);
+		  a68_bufcpy (sourcefile, ".", 1);
+		}
+	      fn = find_include_file(sourcefile, fnb);
+	      free (sourcefile);
 
+	      /* Do not check errno, since errno may be undefined here
+		 after a successful call.  */
+	      if (fn != NO_TEXT)
+		a68_bufcpy (fnb, fn, BUFFER_SIZE);
+	      else
+		{
+		  SCAN_ERROR (true, start_l, start_c,
+			    "included file not found");
+	      }
 	      size_t fnwid = (int) strlen (fnb) + 1;
 	      fn = (char *) xmalloc ((size_t) fnwid);
 	      a68_bufcpy (fn, fnb, fnwid);
diff --git a/gcc/algol68/a68-types.h b/gcc/algol68/a68-types.h
index eebf00ad92b..0adf411544e 100644
--- a/gcc/algol68/a68-types.h
+++ b/gcc/algol68/a68-types.h
@@ -23,6 +23,7 @@
 #define __A68_TYPES_H__
 
 #include <setjmp.h>
+#include "vec.h"
 
 /* Enumerations.  */
 
@@ -620,6 +621,7 @@ struct MODULE_T
     LINE_T *save_l;
     char *save_s, save_c;
   } scan_state;
+  vec<const char *, va_heap, vl_embed> *include_paths;
 };
 
 struct MODE_CACHE_T
@@ -810,6 +812,7 @@ struct A68_T
 #define IDF(p) ((p)->idf)
 #define IM(z) (VALUE (&(z)[1]))
 #define IN(p) ((p)->in)
+#define INCLUDE_PATHS(p) ((p)->include_paths)
 #define INDEX(p) ((p)->index)
 #define INDICANTS(p) ((p)->indicants)
 #define INFO(p) ((p)->info)
diff --git a/gcc/algol68/lang.opt b/gcc/algol68/lang.opt
index 58a50c34d3f..c40864b8173 100644
--- a/gcc/algol68/lang.opt
+++ b/gcc/algol68/lang.opt
@@ -24,6 +24,10 @@
 Language
 Algol68
 
+I
+Algol68 Joined Separate
+; Documented in c-family/c.opt
+
 Wextensions
 Algol68 Warning Var(warn_algol68_extensions) LangEnabledBy(Algol68, Wextra)
 Warn for usage of non-portable extensions of Algol 68.
diff --git a/gcc/algol68/lang.opt.urls b/gcc/algol68/lang.opt.urls
index ab3296983b8..c6885390c8c 100644
--- a/gcc/algol68/lang.opt.urls
+++ b/gcc/algol68/lang.opt.urls
@@ -1,5 +1,8 @@
 ; Autogenerated by regenerate-opt-urls.py from gcc/algol68/lang.opt and generated HTML
 
+I
+UrlSuffix(gcc/Directory-Options.html#index-I) LangUrlSuffix_D(gdc/Directory-Options.html#index-I)
+
 Wextensions
 LangUrlSuffix_Algol68(ga68/Warnings-options.html#index-Wextensions)
 
diff --git a/gcc/testsuite/algol68/compile/a68includes/goodbye.a68 b/gcc/testsuite/algol68/compile/a68includes/goodbye.a68
new file mode 100644
index 00000000000..45c2ec754a9
--- /dev/null
+++ b/gcc/testsuite/algol68/compile/a68includes/goodbye.a68
@@ -0,0 +1,5 @@
+PROC goodbye = (STRING name) STRING:
+BEGIN
+    STRING msg := "Goodbye " + name;
+    msg
+END;
diff --git a/gcc/testsuite/algol68/compile/a68includes/hello.a68 b/gcc/testsuite/algol68/compile/a68includes/hello.a68
new file mode 100644
index 00000000000..420f6fe6b51
--- /dev/null
+++ b/gcc/testsuite/algol68/compile/a68includes/hello.a68
@@ -0,0 +1,5 @@
+PROC hello = (STRING name) STRING:
+BEGIN
+    STRING msg := "Hello " + name;
+    msg
+END;
diff --git a/gcc/testsuite/algol68/compile/include.a68 b/gcc/testsuite/algol68/compile/include.a68
new file mode 100644
index 00000000000..d85b1d690a8
--- /dev/null
+++ b/gcc/testsuite/algol68/compile/include.a68
@@ -0,0 +1,19 @@
+# { dg-options "-I$srcdir/algol68/compile/a68includes" } #
+# { dg-additional-files "$srcdir/algol68/compile/a68includes/hello.a68 $srcdir/algol68/compile/a68includes/goodbye.a68" } #
+
+PROGRAM
+BEGIN STRING name := "Algol68!";
+      # Both files are in `./a68includes'.
+        The first one will be included because we used `-I'.
+        The second one will be included because of the relative path.
+      #
+      PR include "hello.a68" PR
+      PR include "a68includes/goodbye.a68" PR
+
+      STRING bye := goodbye(name);
+      STRING hi := hello(name);
+
+      puts(hi + "\n");
+      puts(bye  + "\n");
+      0
+END
-- 
2.47.0



More information about the Algol68 mailing list