[PATCH] algol68: Handle -I option and use the include paths when including files
Pietro Monteiro
pietro@sociotechnical.xyz
Mon Mar 24 21:31:56 GMT 2025
This patch implements handling the `-I' option in the `ga68' driver.
Now when handling the include pragmat:
- If file name in the pragmat is an absolute path use the name as-is.
If file name in the pragmat is not an absolute path:
- Use the filename to look for a file relative to the source being parsed.
- If a file was not found then use the search paths provided by the -I option to
look for a file to include.
Other front-ends that also accept `-I' need to have their `lang.opt.urls'
regenerated too. I didn't include those files in this patch to try to minimize
conflicts when this front-end gets merged into trunk.
gcc/ChangeLog:
* algol68/a68-lang.cc: Remove unneeded include `ggc.h'.
(a68_handle_option): Handle `-I'.
* algol68/a68-parser-scanner.cc (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 A68_T): Add new member `include_paths'.
* algol68/a68.h (A68_INCLUDE_PATHS): New macro.
* algol68/ga68.texi: Add `Directory options' section and document `-I'
option.
* 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>
---
Changes from the RFC patch:
- Add the `include_paths' vector to struct A68_T instead of struct MODULE_T.
- Rename the static function `a68_file_read_p' to `file_read_p' [Jose E. Marchesi].
- Document the option in the compiler manual [Jose E. Marchesi].
- Link to RFC: https://gcc.gnu.org/pipermail/algol68/2025-March/000063.html
---
gcc/algol68/a68-lang.cc | 7 +-
gcc/algol68/a68-parser-scanner.cc | 129 ++++++++++++++----
gcc/algol68/a68-types.h | 10 ++
gcc/algol68/a68.h | 9 +-
gcc/algol68/ga68.texi | 21 +++
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 +++
10 files changed, 180 insertions(+), 32 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..2bf852e7b13 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 (A68_INCLUDE_PATHS, arg);
+ break;
default:
break;
}
diff --git a/gcc/algol68/a68-parser-scanner.cc b/gcc/algol68/a68-parser-scanner.cc
index 23457f3a2d2..1f37cdaac60 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,89 @@ a68_relpath (const char *p1, const char *p2, const char *fn)
return r;
}
+/* Return true if we can open the file for reading. False otherwise. */
+
+static bool
+file_read_p (const char *filename)
+{
+ return access (filename, R_OK) == 0 ? true : false;
+}
+
+/* Find a file to include into the current source being parsed. Search the file
+ system for FILENAME and return a string with the file path. If the file is
+ not found, return NULL.
+
+ When FILENAME is not an absolute path we first try to find it relative to the
+ current file being parsed (CURFILE). Failing to do that we use the search
+ paths provided by the -I option. */
+
+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 (file_read_p (tmpfpath))
+ {
+ filepath = tmpfpath;
+ goto cleanup;
+ }
+
+ for (unsigned ix = 0; ix != vec_safe_length (A68_INCLUDE_PATHS); ix++)
+ {
+ const char *include_dir = (*(A68_INCLUDE_PATHS))[ix];
+ tmpfpath = a68_relpath (include_dir, fnbdir, incfile);
+ if (!IS_ABSOLUTE_PATH (tmpfpath))
+ tmpfpath = a68_relpath (sourcedir, fnbdir, incfile);
+ if (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 (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 +902,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..ca4952cb8ca 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. */
@@ -734,6 +735,14 @@ struct PARSER_T
POSTULATES is a collection of postulates used by the moid pretty printer.
TOP_SOID_LIST is used by the moid machinery.
+
+ STANDENV XXX.
+
+ TOP_TOKEN XXX.
+
+ INCLUDE_PATHS is the list of paths where we search for files to include.
+ Directories are added to the list at the option handling language hook.
+ The list is searched in FIFO order.
*/
struct A68_T
@@ -757,6 +766,7 @@ struct A68_T
SOID_T *top_soid_list;
TABLE_T *standenv;
TOKEN_T *top_token;
+ vec<const char *, va_heap, vl_embed> *include_paths;
};
/*
diff --git a/gcc/algol68/a68.h b/gcc/algol68/a68.h
index 1b0fd18d0db..5f1973055e5 100644
--- a/gcc/algol68/a68.h
+++ b/gcc/algol68/a68.h
@@ -54,10 +54,11 @@ enum
/* Front-end global state. */
extern A68_T a68_common;
-#define A68(z) (a68_common.z)
-#define A68_JOB A68 (job)
-#define A68_STANDENV A68 (standenv)
-#define A68_MCACHE(z) A68 (mode_cache.z)
+#define A68(z) (a68_common.z)
+#define A68_JOB A68 (job)
+#define A68_STANDENV A68 (standenv)
+#define A68_MCACHE(z) A68 (mode_cache.z)
+#define A68_INCLUDE_PATHS A68 (include_paths)
/* Particular pre-defined modes. */
diff --git a/gcc/algol68/ga68.texi b/gcc/algol68/ga68.texi
index 8ed75f1d459..85e27071abb 100644
--- a/gcc/algol68/ga68.texi
+++ b/gcc/algol68/ga68.texi
@@ -139,6 +139,7 @@ This manual only documents the options specific to @command{ga68}.
@menu
* Dialect options:: Options controlling the accepted language.
+* Directory options:: Options influencing where to find source files.
* Warnings options:: Options controlling warnings specific to ga68
* Runtime options:: Options controlling runtime behavior
* Linking options:: Options influencing the linking step
@@ -170,6 +171,26 @@ blessed by the Revised Report and is still strict Algol 68.
This option is disabled by default.
@end table
+@node Directory options
+@section Options for Directory Search
+@cindex directory options
+@cindex options, directory search
+@cindex search path
+
+These options specify directories to search for files, libraries, and
+other parts of the compiler:
+
+@table @gcctabopt
+
+@opindex I
+@item -I@var{dir}
+Add the directory @var{dir} to the list of directories to be searched
+for files when processing the @ref{pragmat include}. Multiple
+@option{-I} options can be used, and the directories specified are
+scanned in left-to-right order, as with @command{gcc}.
+
+@end table
+
@node Warnings options
@section Warnings options
@cindex options, warnings
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..3eb2fd0cc61 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) LangUrlSuffix_Algol68(ga68/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