bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Add command line option to map file prefixes


From: Joshua Watt
Subject: Re: [PATCH] Add command line option to map file prefixes
Date: Fri, 8 May 2020 12:26:32 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0


On 5/8/20 2:39 AM, Akim Demaille wrote:
Hi Joshua,

Wow, your patch is very mature, congratulations!  There are even
tests!

Le 7 mai 2020 à 18:25, Joshua Watt<address@hidden>  a écrit :

Teaches bison about a new command line option, --file-prefix-map OLD=NEW
which causes it to replace and file path of OLD in the text of the
output file with NEW, mainly for header guards and comments. The primary
use of this is to make builds reproducible with different input paths,
and in particular the debugging information produced when the source
code is compiled.
This sounds desirable, indeed.  It has always bugged me that the generated
files were so dependent on the user's environment.  In fact Bison itself
is cheating (have a look at the bottom of tests/bison.in).

For example, a distro may know that the bison source
code will be located at "/usr/src/bison" and thus can generate bison
files that are reproducible with the following command:

bison --output=/build/bison/parse.c -d -L C 
--file-prefix-map=/build/bison/=/usr/src/bison parse.y
It seems weird to map "foo/" to "bar".

Yes, you would want to use "bar/". I'll correct the example


Importantly, this will change the header guards from:

#ifndef YY_BUILD_BISON_PARSE_H

to

#ifndef YY_USR_SRC_BISON_PARSE_H

which is reproducible.
It appears that your approach is not sufficient for synclines.  I toyed
with it, and the generated #lines are not adjusted.

I'm somewhat bugged that this relies on a new option, mostly because it
means that it cannot be controlled from within the grammar file itself.
Do you really think we need a list of rules?  Do you have evidence for
that need?

If not, maybe we can find a solution which would rely only on %define/-D.


I think there is a bit of missing background, which I will attempt to provide here (and fix up my commit message to also include):

This option is intended to be use in conjunction with the "-fdebug-prefix-map" [1] option in GCC (and other compilers). When this option is used, you don't necessarily *have* to change the #line directives because the compiler will map them for you when the source code is compiled. However, I can also see the argument that bison should handle the mapping internally, and it doesn't look like it would be too hard to apply the mapping to #line directives also, so I can do that if you would like.

I don't think this is the type of thing you'd want to be able to control from the grammar files themselves; it's entirely an option that needs be specified by the user compiling the source code (since only they know the prefix mapping) and allowing to be set in the grammar file seems like it would only cause confusion and/or broken compiles (at least for the purpose of making builds reproducible).



diff --git a/src/files.c b/src/files.c
index 71c10e34..f685cdaa 100644
--- a/src/files.c
+++ b/src/files.c
/* C source file extension (the parser source).  */
static char *src_extension = NULL;
/* Header file extension (if option '`-d'' is specified).  */
static char *header_extension = NULL;
+
+static struct prefix_map {
+  struct prefix_map *next;
+  char *oldprefix;
+  char *newprefix;
+} *prefix_maps;
Please separate the variable definition from the struct
definition.

We are now getting rid of our hand-written list structures
in favor gnulib's implementation of lists.  Not much of a big deal,
but I'd rather avoid stepping backward at this point.

Ok, I'm not very familiar with gnulib, but I'll look up how to do that and fix it.


+static char *
+map_file_name (char const *filename)
+{
+  struct prefix_map const *p;
+
+  if (!filename)
+    return NULL;
We're in C99, so keep the scopes as small as possible: move if before
the introduction of p.

+  for (p = prefix_maps; p != NULL; p = p->next)
+    if (strncmp(p->oldprefix, filename, strlen(p->oldprefix)) == 0)
We put spaces before parens.

+      break;
+
+  if (!p)
+    return xstrdup (filename);
+
+  size_t oldprefix_len = strlen (p->oldprefix);
+  size_t newprefix_len = strlen (p->newprefix);
+  char *s = xmalloc (1 + newprefix_len + strlen (filename) - oldprefix_len);
I'd prefer the 1 to be last.


+  strcpy (s, p->newprefix);
+  strcat (s, &filename[oldprefix_len]);
We use stpcpy for this kind of things.

Out of curiosity, why do you prefer "&filename[oldprefix_len]" to
"filename + oldprefix_len"?  The latter seems more natural to me.


+
+  return s;
+}
+
+void
+add_prefix_map(char const* oldprefix, char const* newprefix)
+{
+  struct prefix_map *p = xmalloc(sizeof(*p));
+  p->oldprefix = xstrdup(oldprefix);
+  p->newprefix = xstrdup(newprefix);
Many space-before-paren issues.  Elsewhere too.



+  while (prefix_maps) {
Braces alone on their lines please.

+    struct prefix_map *p = prefix_maps;
+    prefix_maps = prefix_maps->next;
+    free(p->oldprefix);
+    free(p->newprefix);
+  }
}
diff --git a/src/files.h b/src/files.h
index 00814ad0..379e6495 100644
--- a/src/files.h
+++ b/src/files.h
@@ -49,9 +49,11 @@ extern char *spec_xml_file;

/* File name specified with --defines.  */
extern char *spec_header_file;
+extern char *spec_mapped_header_file;
Please, document a bit.

@@ -765,6 +769,18 @@ getargs (int argc, char *argv[])
         no_lines_flag = true;
         break;

+      case 'M': // -MOLDPREFIX=NEWPREFIX
I would prefer ":", which is more natural to my eyes to denote a
mapping.

I used the same "old=new" syntax that the compiler option uses as a convenience. For example, using this method, a user could do:

 PREFIX_MAP="/sources/bison/=/usr/src/bison/"

 bison --output=/build/bison/parse.c -d -L C --file-prefix-map=$PREFIX_MAP parse.y

 gcc -o parse.o -fdebug-prefix-map=$PREFIX_MAP -c parse.c


I'm not sold that it has to be done this way if you really want ":". I don't know if bison runs on Windows, but if it does ":" wouldn't be a great option because it's the drive letter separator (e.g. "C:\")


+        {
Useless braces here.

+          if (optarg) {
+            char *newprefix = strchr (optarg, '=');
+            if (newprefix) {
paren and brace issues.

+              *newprefix = 0;
Please use '\0'.  We did use 0 to mean char 0 in many places, but I'm
moving to using '\0' instead.

+              add_prefix_map(optarg, newprefix + 1);
+            }
+          }
+        }
+        break;
+
       case 'o':
         spec_outfile = optarg;
         break;

diff --git a/tests/c++.at b/tests/c++.at
index 490c6c25..cdc2a0d4 100644
--- a/tests/c++.at
+++ b/tests/c++.at
@@ -1489,7 +1489,100 @@ AT_PARSER_CHECK([parser], [0])

AT_CLEANUP

+## --------------------------- ##
+## Header Guard Prefix Mapping ##
+## --------------------------- ##
+
+AT_SETUP([Header Guard Prefix Mapping])
+
+# AT_TEST([PREFIX], [DIRECTIVES])
I wouldn't put this test here, as we should also check the other languages.

Have you seen output.at?  I think it would be more natural.
Maybe we can even reuse easily the existing tests, like AT_CHECK_OUTPUT.

I did originally want to put it in output.at, but it looked like that was all language agnostic. I'll move it there and add the other relevant languages.


I can address this later.


[1]: https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html




reply via email to

[Prev in Thread] Current Thread [Next in Thread]