Add a if-exists-then-else built-in spec function
authorDouglas Rupp <rupp@adacore.com>
Tue, 7 Apr 2020 21:05:57 +0000 (14:05 -0700)
committerOlivier Hainque <hainque@adacore.com>
Fri, 23 Oct 2020 15:21:38 +0000 (15:21 +0000)
This patch adds an if-exists-then-else
builtin spec function, which tests for the existence of
a file and returns one or the other of the following
arguments depending on the result of the test.

This differs from the existing if-exists or
if-exists-else function which return the name of the
tested file if it exists.

This new function is of help to a forthcoming change for
VxWorks where we check for the presence of a specific header
file to decide the name of a library to include in the link
closure.

2020-10-23  Douglas Rupp  <rupp@adacore.com>

gcc/
* gcc.c (if-exists-then-else): New built-in spec function.
* doc/invoke.texi: Document it.

gcc/doc/invoke.texi
gcc/gcc.c

index 0b87822..3c3c51c 100644 (file)
@@ -31685,6 +31685,19 @@ crt0%O%s %:if-exists(crti%O%s) \
 %:if-exists-else(crtbeginT%O%s crtbegin%O%s)
 @end smallexample
 
+@item @code{if-exists-then-else}
+The @code{if-exists-then-else} spec function takes at least two arguments
+and an optional third one. The first argument is an absolute pathname to a
+file.  If the file exists, the function returns the second argument.
+If the file does not exist, the function returns the third argument if there
+is one, or NULL otherwise. This can be used to expand one text, or optionally
+another, based on the existence of a file.  Here is a small example of its
+usage:
+
+@smallexample
+-l%:if-exists-then-else(%:getenv(VSB_DIR rtnet.h) rtnet net)
+@end smallexample
+
 @item @code{replace-outfile}
 The @code{replace-outfile} spec function takes two arguments.  It looks for the
 first argument in the outfiles array and replaces it with the second argument.  Here
index ff7b6c4..337c274 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -416,6 +416,7 @@ static void try_generate_repro (const char **argv);
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
+static const char *if_exists_then_else_spec_function (int, const char **);
 static const char *sanitize_spec_function (int, const char **);
 static const char *replace_outfile_spec_function (int, const char **);
 static const char *remove_outfile_spec_function (int, const char **);
@@ -1723,6 +1724,7 @@ static const struct spec_function static_spec_functions[] =
   { "getenv",                   getenv_spec_function },
   { "if-exists",               if_exists_spec_function },
   { "if-exists-else",          if_exists_else_spec_function },
+  { "if-exists-then-else",     if_exists_then_else_spec_function },
   { "sanitize",                        sanitize_spec_function },
   { "replace-outfile",         replace_outfile_spec_function },
   { "remove-outfile",          remove_outfile_spec_function },
@@ -10087,6 +10089,29 @@ if_exists_else_spec_function (int argc, const char **argv)
   return argv[1];
 }
 
+/* if-exists-then-else built-in spec function.
+
+   Checks to see if the file specified by the absolute pathname in
+   the first arg exists.  Returns the second arg if so, otherwise returns
+   the third arg if it is present.  */
+
+static const char *
+if_exists_then_else_spec_function (int argc, const char **argv)
+{
+
+  /* Must have two or three arguments.  */
+  if (argc != 2 && argc != 3)
+    return NULL;
+
+  if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
+    return argv[1];
+
+  if (argc == 3)
+    return argv[2];
+
+  return NULL;
+}
+
 /* sanitize built-in spec function.
 
    This returns non-NULL, if sanitizing address, thread or