[PATCH] algol68: Handle -I option and use the include paths when including files
Jose E. Marchesi
jemarch@gnu.org
Mon Mar 24 23:49:51 GMT 2025
Hi Pietro.
I just installed the patch on your behalf.
Thanks!
> 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
More information about the Algol68
mailing list