[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] Add %language declaration
From: |
Paolo Bonzini |
Subject: |
Re: [PATCH] Add %language declaration |
Date: |
Mon, 09 Oct 2006 13:01:25 +0200 |
User-agent: |
Thunderbird 1.5.0.7 (Macintosh/20060909) |
No, it turns out I attached the same, wrong patch both times, with the
ChangeLog missing. The mistake however is just that parts of the
bison.texinfo patch were missing.
Sorry.
Paolo
2006-10-09 Paolo Bonzini <address@hidden>
* NEWS: Document %language.
* data/c-skel.m4, data/c++-skel.m4: New.
* data/push.c: Complain on GLR parsers.
* doc/bison.texinfo (C++ Parser Interface): Prefer %language
over %skeleton.
(Directives): Document %language and %skeleton.
(Command line): Document -L.
* src/files.c (compute_exts_from_gc): Look in language structure
for .y extension.
(compute_file_name_parts): Check whether .tab should be added.
* src/getargs.c (valid_languages, skeleton_prio, language_prio,
language, skeleton_arg, language_argmatch): New.
(long_options): Add --language.
(getargs): Use skeleton_arg, add -L/--language.
* src/getargs.h: Include location.h.
(struct bison_language, language, skeleton_arg, language_argmatch): New.
* src/output.c (prepare): Pick default skeleton from struct language.
Don't dispatch C skeletons here.
* src/parse-gram.y (PERCENT_LANGUAGE): New.
(prologue_declaration): Add "%language" rule, use skeleton_arg.
* src/scan-gram.l ("%language"): New rule.
* tests/calc.at: Test %skeleton and %language.
* tests/local.at (AT_SKEL_CC_IF): Look for %language.
(AT_GLR_IF): Look for %skeleton "glr.cc".
(AT_LALR1_CC_IF, AT_GLR_CC_IF): Rewrite.
(AT_YACC_IF): Reject %language.
Index: NEWS
===================================================================
RCS file: /sources/bison/bison/NEWS,v
retrieving revision 1.160
diff -u -p -r1.160 NEWS
--- NEWS 13 Sep 2006 19:42:04 -0000 1.160
+++ NEWS 9 Oct 2006 10:58:55 -0000
@@ -3,6 +3,11 @@ Bison News
Changes in version 2.3a, 2006-09-13:
+* A new directive %language allows to specify the language of the
+ generated parser. Supported languages are C (the default) and
+ C++. Besides the skeleton that is used, the directive affects
+ the names of the generated files if the grammar has extension ".y".
+
* Instead of %union, you can define and use your own union type
YYSTYPE if your grammar contains at least one <type> tag.
Your YYSTYPE need not be a macro; it can be a typedef.
Index: data/c++-skel.m4
===================================================================
RCS file: data/c++-skel.m4
diff -N data/c++-skel.m4
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ data/c++-skel.m4 9 Oct 2006 10:58:55 -0000
@@ -0,0 +1,29 @@
+m4_divert(-1) -*- Autoconf -*-
+
+# C++ skeleton dispatching for Bison.
+# Copyright (C) 2006 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+b4_glr_if( [m4_define([b4_used_skeleton],
[b4_pkgdatadir/[glr.cc]])])
+b4_nondeterministic_if([m4_define([b4_used_skeleton],
[b4_pkgdatadir/[glr.cc]])])
+
+b4_push_if([m4_fatal([%push-parser is not supported by C++])])
+
+m4_define_default([b4_used_skeleton], [b4_pkgdatadir/[lalr1.cc]])
+m4_define_default([b4_skeleton], ["b4_basename(b4_used_skeleton)"])
+
+m4_include(b4_used_skeleton)
Index: data/c-skel.m4
===================================================================
RCS file: data/c-skel.m4
diff -N data/c-skel.m4
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ data/c-skel.m4 9 Oct 2006 10:58:55 -0000
@@ -0,0 +1,28 @@
+m4_divert(-1) -*- Autoconf -*-
+
+# C skeleton dispatching for Bison.
+# Copyright (C) 2006 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+b4_glr_if( [m4_define([b4_used_skeleton],
[b4_pkgdatadir/[glr.c]])])
+b4_nondeterministic_if([m4_define([b4_used_skeleton],
[b4_pkgdatadir/[glr.c]])])
+b4_push_if( [m4_define([b4_used_skeleton],
[b4_pkgdatadir/[push.c]])])
+
+m4_define_default([b4_used_skeleton], [b4_pkgdatadir/[yacc.c]])
+m4_define_default([b4_skeleton], ["b4_basename(b4_used_skeleton)"])
+
+m4_include(b4_used_skeleton)
Index: data/push.c
===================================================================
RCS file: /sources/bison/bison/data/push.c,v
retrieving revision 1.3
diff -u -p -r1.3 push.c
--- data/push.c 21 Sep 2006 17:45:21 -0000 1.3
+++ data/push.c 9 Oct 2006 10:58:56 -0000
@@ -22,6 +22,13 @@ m4_divert(-1)
m4_include(b4_pkgdatadir/[c.m4])
+b4_glr_if([
+m4_fatal([GLR and %push-parser are not yet compatible])])
+
+b4_nondeterministic_if([
+m4_fatal(b4_skeleton[GLR and %push-parser are not yet compatible])])
+
+
## ---------------- ##
## Default values. ##
## ---------------- ##
Index: doc/bison.texinfo
===================================================================
RCS file: /sources/bison/bison/doc/bison.texinfo,v
retrieving revision 1.205
diff -u -p -r1.205 bison.texinfo
--- doc/bison.texinfo 11 Sep 2006 18:56:58 -0000 1.205
+++ doc/bison.texinfo 9 Oct 2006 10:58:58 -0000
@@ -4344,6 +4344,11 @@ Specify a prefix to use for all Bison ou
chosen as if the input file were named @address@hidden
@end deffn
address@hidden {Directive} %language="@var{language}"
+Specify the programming language for the generated parser. Currently
+supported languages include C, C++ and Java.
address@hidden deffn
+
@deffn {Directive} %locations
Generate the code processing the locations (@pxref{Action Features,
,Special Features for Use in Actions}). This mode is enabled as soon as
@@ -4406,6 +4411,11 @@ Require version @var{version} or higher
Require a Version of Bison}.
@end deffn
address@hidden {Directive} %skeleton "@var{file}"
+Specify the skeleton to use. You probably don't need this option unless
+you are developing Bison.
address@hidden deffn
+
@deffn {Directive} %token-table
Generate an array of token names in the parser file. The name of the
array is @code{yytname}; @address@hidden is the name of the
@@ -6997,6 +7007,11 @@ In the parser file, define the macro @co
already defined, so that the debugging facilities are compiled.
@xref{Tracing, ,Tracing Your Parser}.
address@hidden -L @var{language}
address@hidden address@hidden
+Specify the programming language for the generated parser. Currently
+supported languages include C, C++ and Java.
+
@item --locations
Pretend that @code{%locations} was specified. @xref{Decl Summary}.
@@ -7158,14 +7173,24 @@ int yyparse (void);
@node C++ Bison Interface
@subsection C++ Bison Interface
address@hidden - %skeleton "lalr1.cc"
address@hidden - %language "C++"
@c - Always pure
@c - initial action
-The C++ parser @acronym{LALR}(1) skeleton is named @file{lalr1.cc}. To
-select it, you may either pass the option @option{--skeleton=lalr1.cc}
-to Bison, or include the directive @samp{%skeleton "lalr1.cc"} in the
-grammar preamble. When run, @command{bison} will create several
+The C++ parser @acronym{LALR}(1) skeleton is selected using a
+language directive, @samp{%language "C++"}, or the synonymous
+command-line option @address@hidden both
+ the grammar directive and the command-line option, the
+ language name is case-insensitive}. These were introduced
+in Bison 2.4; for compatibility with earlier versions, you
+may also pass the option @option{--skeleton=lalr1.cc} to Bison
+or include the directive @samp{%skeleton "lalr1.cc"} in the
+grammar preamble. Specifying the language is however preferred,
+because it is clearer and because it will automatically choose the
+correct skeleton for GLR parsers (the C++ GLR skeleton is still
+under development).
+
+When run, @command{bison} will create several
entities in the @samp{yy} namespace. Use the @samp{%name-prefix}
directive to change the namespace name, see @ref{Decl Summary}. The
various classes are generated in the following files:
@@ -7553,8 +7578,8 @@ the grammar for.
@comment file: calc++-parser.yy
@example
-%skeleton "lalr1.cc" /* -*- C++ -*- */
-%require "2.1a"
+%language "C++" /* -*- C++ -*- */
+%require "2.3a+"
%defines
%define "parser_class_name" "calcxx_parser"
@end example
Index: src/files.c
===================================================================
RCS file: /sources/bison/bison/src/files.c,v
retrieving revision 1.96
diff -u -p -r1.96 files.c
--- src/files.c 9 Jul 2006 03:44:51 -0000 1.96
+++ src/files.c 9 Oct 2006 10:58:58 -0000
@@ -157,10 +157,18 @@ tr (const char *in, char from, char to)
static void
compute_exts_from_gf (const char *ext)
{
- src_extension = tr (ext, 'y', 'c');
- src_extension = tr (src_extension, 'Y', 'C');
- header_extension = tr (ext, 'y', 'h');
- header_extension = tr (header_extension, 'Y', 'H');
+ if (!strcmp (ext, ".y"))
+ {
+ src_extension = language->src_extension;
+ header_extension = language->header_extension;
+ }
+ else
+ {
+ src_extension = tr (ext, 'y', 'c');
+ src_extension = tr (src_extension, 'Y', 'C');
+ header_extension = tr (ext, 'y', 'h');
+ header_extension = tr (header_extension, 'Y', 'H');
+ }
}
/* Compute extensions from the given c source file extension. */
@@ -282,7 +290,10 @@ compute_file_name_parts (void)
xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
}
- all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
+ if (!language || language->add_tab)
+ all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
+ else
+ all_but_ext = all_but_tab_ext;
/* Compute the extensions from the grammar file name. */
if (ext && !yacc_flag)
Index: src/getargs.c
===================================================================
RCS file: /sources/bison/bison/src/getargs.c,v
retrieving revision 1.80
diff -u -p -r1.80 getargs.c
--- src/getargs.c 20 Sep 2006 20:04:28 -0000 1.80
+++ src/getargs.c 9 Oct 2006 10:58:59 -0000
@@ -66,11 +66,18 @@ int report_flag = report_none;
int trace_flag = trace_none;
int warnings_flag = warnings_none;
+static const struct bison_language valid_languages[] = {
+ { "c", "c-skel.m4", ".c", ".h", true },
+ { "c++", "c++-skel.m4", ".cc", ".hh", true },
+ { NULL, NULL, NULL, NULL, false }
+};
+
+static int skeleton_prio = 2;
const char *skeleton = NULL;
+static int language_prio = 2;
+const struct bison_language *language = &valid_languages[0];
const char *include = NULL;
-extern char *program_name;
-
/** Decode an option's set of keys.
*
@@ -321,12 +328,87 @@ warranty; not even for MERCHANTABILITY o
}
+/*-------------------------------------.
+| --skeleton and --language handling. |
+`--------------------------------------*/
+
+void
+skeleton_arg (char *arg, int prio, location *loc)
+{
+ if (skeleton_prio < prio)
+ return;
+ if (skeleton_prio == prio)
+ {
+ const char *msg =
+ _("multiple skeleton declarations are invalid");
+ if (loc)
+ {
+ complain_at (*loc, msg);
+ return;
+ }
+ else
+ {
+ error (0, 0, msg);
+ usage (EXIT_FAILURE);
+ }
+ }
+
+ skeleton_prio = prio;
+ skeleton = arg;
+}
+
+void
+language_argmatch (char *args, int prio, location *loc)
+{
+ int i;
+ if (language_prio < prio)
+ return;
+ if (language_prio == prio)
+ {
+ const char *msg =
+ _("multiple language declarations are invalid");
+ if (loc)
+ {
+ complain_at (*loc, msg);
+ return;
+ }
+ else
+ {
+ error (0, 0, msg);
+ usage (EXIT_FAILURE);
+ }
+ }
+
+ for (i = 0; valid_languages[i].language; i++)
+ if (!strcasecmp (args, valid_languages[i].language))
+ {
+ language_prio = prio;
+ language = &valid_languages[i];
+ break;
+ }
+
+ if (!language)
+ {
+ const char *msg = _("invalid language `%s'");
+ if (loc)
+ {
+ complain_at (*loc, msg, args);
+ return;
+ }
+ else
+ {
+ error (0, 0, msg, args);
+ usage (EXIT_FAILURE);
+ }
+ }
+}
+
/*----------------------.
| Process the options. |
`----------------------*/
/* Shorts options. */
-static char const short_options[] = "yvegdhr:ltknVo:b:p:S:T::W";
+static char const short_options[] = "yvegdhr:L:ltknVo:b:p:S:T::W";
/* Values for long options that do not have single-letter equivalents. */
enum
@@ -372,6 +454,7 @@ static struct option const long_options[
{ "no-parser", no_argument, 0, 'n' },
{ "raw", no_argument, 0, 0 },
{ "skeleton", required_argument, 0, 'S' },
+ { "language", required_argument, 0, 'L' },
{ "token-table", no_argument, 0, 'k' },
{0, 0, 0, 0}
@@ -412,8 +495,12 @@ getargs (int argc, char *argv[])
case 'h':
usage (EXIT_SUCCESS);
+ case 'L':
+ language_argmatch (optarg, 0, NULL);
+ break;
+
case 'S':
- skeleton = AS_FILE_NAME (optarg);
+ skeleton_arg (AS_FILE_NAME (optarg), 0, NULL);
break;
case 'I':
Index: src/getargs.h
===================================================================
RCS file: /sources/bison/bison/src/getargs.h,v
retrieving revision 1.34
diff -u -p -r1.34 getargs.h
--- src/getargs.h 15 Sep 2006 15:56:26 -0000 1.34
+++ src/getargs.h 9 Oct 2006 10:58:59 -0000
@@ -22,6 +22,10 @@
#ifndef GETARGS_H_
# define GETARGS_H_
+#include "location.h"
+
+extern char *program_name;
+
/* flags set by % directives */
/* for -S */
@@ -65,6 +69,18 @@ extern bool push_parser;
extern bool nondeterministic_parser;
+/* --language. */
+struct bison_language
+{
+ const char *language;
+ const char *skeleton;
+ const char *src_extension;
+ const char *header_extension;
+ bool add_tab;
+};
+
+extern const struct bison_language *language;
+
/*-----------.
| --report. |
`-----------*/
@@ -125,4 +141,8 @@ extern int warnings_flag;
*/
void getargs (int argc, char *argv[]);
+/* Used by parse-gram.y. */
+void language_argmatch (char *arg, int prio, location *loc);
+void skeleton_arg (char *arg, int prio, location *loc);
+
#endif /* !GETARGS_H_ */
Index: src/output.c
===================================================================
RCS file: /sources/bison/bison/src/output.c,v
retrieving revision 1.257
diff -u -p -r1.257 output.c
--- src/output.c 8 Oct 2006 11:07:02 -0000 1.257
+++ src/output.c 9 Oct 2006 10:58:59 -0000
@@ -612,6 +612,7 @@ prepare (void)
DEFINE (spec_name_prefix);
DEFINE (spec_outfile);
DEFINE (spec_verbose_file);
+ DEFINE (program_name);
#undef DEFINE
/* User Code. */
@@ -620,20 +621,16 @@ prepare (void)
muscle_insert ("pre_prologue", obstack_finish (&pre_prologue_obstack));
muscle_insert ("post_prologue", obstack_finish (&post_prologue_obstack));
- /* Find the right skeleton file. */
- if (!skeleton)
- {
- if (glr_parser || nondeterministic_parser)
- skeleton = "glr.c";
- else
- skeleton = "yacc.c";
- }
+ /* Find the right skeleton file, and add muscles about the skeletons */
+ if (skeleton)
+ MUSCLE_INSERT_C_STRING ("skeleton", skeleton);
+ else
+ skeleton = language->skeleton;
- /* About the skeletons. */
+ /* About the skeletons. */
{
char const *pkgdatadir = getenv ("BISON_PKGDATADIR");
MUSCLE_INSERT_STRING ("pkgdatadir", pkgdatadir ? pkgdatadir : PKGDATADIR);
- MUSCLE_INSERT_C_STRING ("skeleton", skeleton);
}
}
Index: src/parse-gram.y
===================================================================
RCS file: /sources/bison/bison/src/parse-gram.y,v
retrieving revision 1.92
diff -u -p -r1.92 parse-gram.y
--- src/parse-gram.y 15 Sep 2006 16:34:48 -0000 1.92
+++ src/parse-gram.y 9 Oct 2006 10:59:00 -0000
@@ -146,6 +146,7 @@ static int current_prec = 0;
PERCENT_FILE_PREFIX "%file-prefix"
PERCENT_GLR_PARSER "%glr-parser"
PERCENT_INITIAL_ACTION "%initial-action"
+ PERCENT_LANGUAGE "%language"
PERCENT_LEX_PARAM "%lex-param"
PERCENT_LOCATIONS "%locations"
PERCENT_NAME_PREFIX "%name-prefix"
@@ -241,6 +242,7 @@ prologue_declaration:
{
muscle_code_grow ("initial_action", translate_symbol_action ($2, @2),
@2);
}
+| "%language" STRING { language_argmatch ($2, 1, &@1); }
| "%lex-param" "{...}" { add_param ("lex_param", $2, @2); }
| "%locations" { locations_flag = true; }
| "%name-prefix" "=" STRING { spec_name_prefix = $3; }
@@ -251,7 +253,7 @@ prologue_declaration:
| "%pure-parser" { pure_parser = true; }
| "%push-parser" { push_parser = true; }
| "%require" STRING { version_check (&@2, $2); }
-| "%skeleton" STRING { skeleton = $2; }
+| "%skeleton" STRING { skeleton_arg ($2, 1, &@1); }
| "%start-header" braceless { muscle_code_grow ("start_header", $2, @2); }
| "%token-table" { token_table_flag = true; }
| "%verbose" { report_flag = report_states; }
Index: src/scan-gram.l
===================================================================
RCS file: /sources/bison/bison/src/scan-gram.l,v
retrieving revision 1.103
diff -u -p -r1.103 scan-gram.l
--- src/scan-gram.l 15 Sep 2006 15:56:26 -0000 1.103
+++ src/scan-gram.l 9 Oct 2006 10:59:00 -0000
@@ -173,6 +173,7 @@ splice (\\[ \f\t\v]*\n)*
"%fixed"[-_]"output"[-_]"files" return PERCENT_YACC;
"%initial-action" return PERCENT_INITIAL_ACTION;
"%glr-parser" return PERCENT_GLR_PARSER;
+ "%language" return PERCENT_LANGUAGE;
"%left" return PERCENT_LEFT;
"%lex-param" return PERCENT_LEX_PARAM;
"%locations" return PERCENT_LOCATIONS;
Index: tests/calc.at
===================================================================
RCS file: /sources/bison/bison/tests/calc.at,v
retrieving revision 1.92
diff -u -p -r1.92 calc.at
--- tests/calc.at 15 Sep 2006 15:56:26 -0000 1.92
+++ tests/calc.at 9 Oct 2006 10:59:00 -0000
@@ -617,12 +617,15 @@ AT_CHECK_CALC_GLR([%pure-parser %error-v
AT_BANNER([[Simple LALR(1) C++ Calculator.]])
+# First let's try using %skeleton
+AT_CHECK_CALC([%skeleton "lalr1.cc" %defines %locations])
+
# AT_CHECK_CALC_LALR1_CC([BISON-OPTIONS])
# ---------------------------------------
# Start a testing chunk which compiles `calc' grammar with
# the C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_LALR1_CC],
-[AT_CHECK_CALC([%skeleton "lalr1.cc" %defines %locations] $@)])
+[AT_CHECK_CALC([%language "C++" %defines %locations] $@)])
AT_CHECK_CALC_LALR1_CC([])
AT_CHECK_CALC_LALR1_CC([%error-verbose %name-prefix="calc" %verbose %yacc])
@@ -641,12 +644,15 @@ AT_CHECK_CALC_LALR1_CC([%pure-parser %er
AT_BANNER([[Simple GLR C++ Calculator.]])
+# Again, we try also using %skeleton.
+AT_CHECK_CALC([%skeleton "glr.cc" %defines %locations])
+
# AT_CHECK_CALC_GLR_CC([BISON-OPTIONS])
# -------------------------------------
# Start a testing chunk which compiles `calc' grammar with
# the GLR C++ skeleton, and performs several tests over the parser.
m4_define([AT_CHECK_CALC_GLR_CC],
-[AT_CHECK_CALC([%skeleton "glr.cc" %defines %locations] $@)])
+[AT_CHECK_CALC([%language "C++" %glr-parser %defines %locations] $@)])
AT_CHECK_CALC_GLR_CC([])
AT_CHECK_CALC_GLR_CC([%error-verbose %name-prefix="calc" %verbose %yacc])
Index: tests/local.at
===================================================================
RCS file: /sources/bison/bison/tests/local.at,v
retrieving revision 1.16
diff -u -p -r1.16 local.at
--- tests/local.at 12 Mar 2006 15:26:05 -0000 1.16
+++ tests/local.at 9 Oct 2006 10:59:00 -0000
@@ -41,17 +41,17 @@ m4_define([AT_BISON_OPTION_PUSHDEFS],
m4_define([_AT_BISON_OPTION_PUSHDEFS],
[m4_if([$1$2], $[1]$[2], [],
[m4_fatal([$0: Invalid arguments: address@hidden)])dnl
-m4_pushdef([AT_LALR1_CC_IF],
-[m4_bmatch([$3], ["lalr1.cc"], [$1], [$2])])
-m4_pushdef([AT_GLR_CC_IF],
-[m4_bmatch([$3], ["glr.cc"], [$1], [$2])])
m4_pushdef([AT_SKEL_CC_IF],
-[m4_bmatch([$3], ["\(glr\|lalr1\).cc"], [$1], [$2])])
+[m4_bmatch([$3], [%language "[Cc]\+\+"\|%skeleton "[a-z0-9]+\.cc"], [$1],
[$2])])
m4_pushdef([AT_GLR_IF],
-[m4_bmatch([$3], [%glr-parser], [$1], [$2])])
+[m4_bmatch([$3], [%glr-parser\|%skeleton "glr\.], [$1], [$2])])
+m4_pushdef([AT_LALR1_CC_IF],
+[AT_SKEL_CC_IF([AT_GLR_IF([$2], [$1])], [$2])])
+m4_pushdef([AT_GLR_CC_IF],
+[AT_SKEL_CC_IF([AT_GLR_IF([$1], [$2])], [$2])])
# Using yacc.c?
m4_pushdef([AT_YACC_IF],
-[m4_bmatch([$3], [%glr-parser\|%skeleton], [$2], [$1])])
+[m4_bmatch([$3], [%language\|%glr-parser\|%skeleton], [$2], [$1])])
m4_pushdef([AT_PARAM_IF],
[m4_bmatch([$3], [%parse-param], [$1], [$2])])
m4_pushdef([AT_LOCATION_IF],
cvs diff: Diffing gnulib
cvs diff: Diffing gnulib/build-aux
cvs diff: Diffing gnulib/config
cvs diff: Diffing gnulib/doc
cvs diff: Diffing gnulib/doc/Copyright
cvs diff: Diffing gnulib/lib
cvs diff: Diffing gnulib/m4
cvs diff: Diffing gnulib/modules
cvs diff: Diffing gnulib/tests