source: trunk/essentials/sys-devel/autoconf/bin/autoupdate.in

Last change on this file was 3095, checked in by bird, 18 years ago

unixroot changes.

File size: 32.8 KB
Line 
1#! @PERL@ -w
2# -*- perl -*-
3# @configure_input@
4
5# autoupdate - modernize an Autoconf file.
6# Copyright (C) 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
7# Free Software Foundation, Inc.
8
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2, or (at your option)
12# any later version.
13
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22# 02110-1301, USA.
23
24# Originally written by David MacKenzie <djm@gnu.ai.mit.edu>.
25# Rewritten by Akim Demaille <akim@freefriends.org>.
26
27eval 'case $# in 0) exec @PERL@ -S "$0";; *) exec @PERL@ -S "$0" "$@";; esac'
28 if 0;
29
30BEGIN
31{
32 my $datadir = $ENV{'autom4te_perllibdir'} || '@datadir@';
33 $datadir =~ s/\/\@unixroot/$ENV{'UNIXROOT'}/; # The EMX built perl doesn't know @unixroot.
34 unshift @INC, $datadir;
35
36 # Override SHELL. On DJGPP SHELL may not be set to a shell
37 # that can handle redirection and quote arguments correctly,
38 # e.g.: COMMAND.COM. For DJGPP always use the shell that configure
39 # has detected.
40 $ENV{'SHELL'} = '@SHELL@' if ($^O eq 'dos');
41}
42
43use Autom4te::ChannelDefs;
44use Autom4te::Channels;
45use Autom4te::Configure_ac;
46use Autom4te::FileUtils;
47use Autom4te::General;
48use Autom4te::XFile;
49use File::Basename;
50use strict;
51
52# Lib files.
53my $autom4te = $ENV{'AUTOM4TE'} || '@bindir@/@autom4te-name@';
54$autom4te =~ s/\/\@unixroot/$ENV{'UNIXROOT'}/; # The EMX built perl doesn't know @unixroot.
55my $autoconf = "$autom4te --language=autoconf";
56# We need to find m4sugar.
57my @prepend_include;
58my $first_include = '@datadir@';
59$first_include =~ s/\/\@unixroot/$ENV{'UNIXROOT'}/; # The EMX built perl doesn't know @unixroot.
60my @include = ("$first_include");
61my $force = 0;
62# m4.
63my $m4 = $ENV{"M4"} || '@M4@';
64$m4 =~ s/\/\@unixroot/$ENV{'UNIXROOT'}/; # The EMX built perl doesn't know @unixroot.
65
66
67# $HELP
68# -----
69$help = "Usage: $0 [OPTION] ... [TEMPLATE-FILE...]
70
71Update the TEMPLATE-FILE... if given, or `configure.ac' if present,
72or else `configure.in', to the syntax of the current version of
73Autoconf. The original files are backed up.
74
75Operation modes:
76 -h, --help print this help, then exit
77 -V, --version print version number, then exit
78 -v, --verbose verbosely report processing
79 -d, --debug don't remove temporary files
80 -f, --force consider all files obsolete
81
82Library directories:
83 -B, --prepend-include=DIR prepend directory DIR to search path
84 -I, --include=DIR append directory DIR to search path
85
86Report bugs to <bug-autoconf\@gnu.org>.
87";
88
89# $VERSION
90# --------
91$version = "autoupdate (@PACKAGE_NAME@) @VERSION@
92Copyright (C) 2006 Free Software Foundation, Inc.
93This is free software. You may redistribute copies of it under the terms of
94the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
95There is NO WARRANTY, to the extent permitted by law.
96
97Written by David J. MacKenzie and Akim Demaille.
98";
99
100## ---------- ##
101## Routines. ##
102## ---------- ##
103
104
105# parse_args ()
106# -------------
107# Process any command line arguments.
108sub parse_args ()
109{
110 my $srcdir;
111
112 getopt ('I|include=s' => \@include,
113 'B|prepend-include=s' => \@prepend_include,
114 'f|force' => \$force);
115
116 if (! @ARGV)
117 {
118 my $configure_ac = require_configure_ac;
119 push @ARGV, $configure_ac;
120 }
121}
122
123
124
125# ----------------- #
126# Autoconf macros. #
127# ----------------- #
128
129my (%ac_macros, %au_macros, %m4_builtins);
130
131# HANDLE_AUTOCONF_MACROS ()
132# -------------------------
133# @M4_BUILTINS -- M4 builtins and a useful comment.
134sub handle_autoconf_macros ()
135{
136 # Get the builtins.
137 xsystem ("echo dumpdef | $m4 2>$tmp/m4.defs >/dev/null");
138 my $m4_defs = new Autom4te::XFile "$tmp/m4.defs";
139 while ($_ = $m4_defs->getline)
140 {
141 $m4_builtins{$1} = 1
142 if /^(\w+):/;
143 }
144 $m4_defs->close;
145
146 my $macros = new Autom4te::XFile ("$autoconf"
147 . " --trace AU_DEFINE:'AU:\$f:\$1'"
148 . " --trace define:'AC:\$f:\$1'"
149 . " --melt /dev/null |");
150 while ($_ = $macros->getline)
151 {
152 chomp;
153 my ($domain, $file, $macro) = /^(AC|AU):(.*):([^:]*)$/ or next;
154 if ($domain eq "AU")
155 {
156 $au_macros{$macro} = 1;
157 }
158 elsif ($file =~ /(^|\/)m4sugar\/(m4sugar|version)\.m4$/)
159 {
160 # Add the m4sugar macros to m4_builtins.
161 $m4_builtins{$macro} = 1;
162 }
163 else
164 {
165 # Autoconf, aclocal, and m4sh macros.
166 $ac_macros{$macro} = 1;
167 }
168 }
169 $macros->close;
170
171
172 # Don't keep AU macros in @AC_MACROS.
173 delete $ac_macros{$_}
174 foreach (keys %au_macros);
175 # Don't keep M4sugar macros which are redefined by Autoconf,
176 # such as `builtin', `changequote' etc. See autoconf/autoconf.m4.
177 delete $ac_macros{$_}
178 foreach (keys %m4_builtins);
179 error "no current Autoconf macros found"
180 unless keys %ac_macros;
181 error "no obsolete Autoconf macros found"
182 unless keys %au_macros;
183
184 if ($debug)
185 {
186 print STDERR "Current Autoconf macros:\n";
187 print STDERR join (' ', sort keys %ac_macros) . "\n\n";
188 print STDERR "Obsolete Autoconf macros:\n";
189 print STDERR join (' ', sort keys %au_macros) . "\n\n";
190 }
191
192 # ac.m4 -- autoquoting definitions of the AC macros (M4sugar excluded).
193 # unac.m4 -- undefine the AC macros.
194 my $ac_m4 = new Autom4te::XFile ">$tmp/ac.m4";
195 print $ac_m4 "# ac.m4 -- autoquoting definitions of the AC macros.\n";
196 my $unac_m4 = new Autom4te::XFile ">$tmp/unac.m4";
197 print $unac_m4 "# unac.m4 -- undefine the AC macros.\n";
198 foreach (sort keys %ac_macros)
199 {
200 print $ac_m4 "_au_m4_define([$_], [m4_if(\$#, 0, [[\$0]], [[\$0(\$\@)]])])\n";
201 print $unac_m4 "_au_m4_undefine([$_])\n";
202 }
203
204 # m4save.m4 -- save the m4 builtins.
205 # unm4.m4 -- disable the m4 builtins.
206 # m4.m4 -- enable the m4 builtins.
207 my $m4save_m4 = new Autom4te::XFile ">$tmp/m4save.m4";
208 print $m4save_m4 "# m4save.m4 -- save the m4 builtins.\n";
209 my $unm4_m4 = new Autom4te::XFile ">$tmp/unm4.m4";
210 print $unm4_m4 "# unm4.m4 -- disable the m4 builtins.\n";
211 my $m4_m4 = new Autom4te::XFile ">$tmp/m4.m4";
212 print $m4_m4 "# m4.m4 -- enable the m4 builtins.\n";
213 foreach (sort keys %m4_builtins)
214 {
215 print $m4save_m4 "_au__save([$_])\n";
216 print $unm4_m4 "_au__undefine([$_])\n";
217 print $m4_m4 "_au__restore([$_])\n";
218 }
219}
220
221
222## -------------- ##
223## Main program. ##
224## -------------- ##
225
226parse_args;
227$autoconf .= " --debug" if $debug;
228$autoconf .= " --force" if $force;
229$autoconf .= " --verbose" if $verbose;
230$autoconf .= join (' --include=', '', @include);
231$autoconf .= join (' --prepend-include=', '', @prepend_include);
232
233mktmpdir ('au');
234handle_autoconf_macros;
235
236# $au_changequote -- enable the quote `[', `]' right before any AU macro.
237my $au_changequote =
238 's/\b(' . join ('|', keys %au_macros) . ')\b/_au_m4_changequote([,])$1/g';
239
240# au.m4 -- definitions the AU macros.
241xsystem ("$autoconf --trace AU_DEFINE:'_au_defun(\@<:\@\$1\@:>\@,
242\@<:\@\$2\@:>\@)' --melt /dev/null "
243 . ">$tmp/au.m4");
244
245
246
247## ------------------- ##
248## Process the files. ##
249## ------------------- ##
250
251foreach my $file (@ARGV)
252 {
253 # We need an actual file.
254 if ($file eq '-')
255 {
256 $file = "$tmp/stdin";
257 system "cat >$file";
258 }
259 elsif (! -r "$file")
260 {
261 die "$me: $file: No such file or directory";
262 }
263
264 # input.m4 -- m4 program to produce the updated file.
265 # Load the values, the dispatcher, neutralize m4, and the prepared
266 # input file.
267 my $input_m4 = <<\EOF;
268 divert(-1) -*- Autoconf -*-
269 changequote([,])
270
271 # Define our special macros:
272 define([_au__defn], defn([defn]))
273 define([_au__divert], defn([divert]))
274 define([_au__include], defn([include]))
275 define([_au__undefine], defn([undefine]))
276 define([_au__save], [m4_ifdef([$1], [m4_copy([$1], [_au_$1])])])
277 define([_au__restore],
278 [_au_m4_ifdef([_au_$1],
279 [_au_m4_define([$1], _au__defn([_au_$1]))])])
280
281 # Set up m4sugar.
282 include(m4sugar/m4sugar.m4)
283
284 # Redefine __file__ to make warnings nicer; $file is replaced below.
285 m4_define([__file__], [$file])
286
287 # Redefine m4_location to fix the line number.
288 m4_define([m4_location], [__file__:m4_eval(__line__ - _au__first_line)])
289
290 # Move all the builtins into the `_au_' pseudo namespace
291 m4_include([m4save.m4])
292
293 # _au_defun(NAME, BODY)
294 # ---------------------
295 # Define NAME to BODY, plus AU activation/deactivation.
296 _au_m4_define([_au_defun],
297 [_au_m4_define([$1],
298 [_au_enable()dnl
299 $2[]dnl
300 _au_disable()])])
301
302 # Import the definition of the obsolete macros.
303 _au__include([au.m4])
304
305
306 ## ------------------------ ##
307 ## _au_enable/_au_disable. ##
308 ## ------------------------ ##
309
310 # They work by pair: each time an AU macro is activated, it runs
311 # _au_enable, and at its end its runs _au_disable (see _au_defun
312 # above). AU macros might use AU macros, which should
313 # enable/disable only for the outer AU macros.
314 #
315 # `_au_enabled' is used to this end, determining whether we really
316 # enable/disable.
317
318
319 # __au_enable
320 # -----------
321 # Reenable the builtins, m4sugar, and the autoquoting AC macros.
322 _au_m4_define([__au_enable],
323 [_au__divert(-1)
324 # Enable special characters.
325 _au_m4_changecom([#])
326
327 _au__include([m4.m4])
328 _au__include([ac.m4])
329
330 _au__divert(0)])
331
332 # _au_enable
333 # ----------
334 # Called at the beginning of all the obsolete macros. If this is the
335 # outermost level, call __au_enable.
336 _au_m4_define([_au_enable],
337 [_au_m4_ifdef([_au_enabled],
338 [],
339 [__au_enable()])_au_dnl
340 _au_m4_pushdef([_au_enabled])])
341
342
343 # __au_disable
344 # ------------
345 # Disable the AC autoquoting macros, m4sugar, and m4.
346 _au_m4_define([__au_disable],
347 [_au__divert(-1)
348 _au__include([unac.m4])
349 _au__include([unm4.m4])
350
351 # Disable special characters.
352 _au_m4_changequote()
353 _au_m4_changecom()
354
355 _au__divert(0)])
356
357 # _au_disable
358 # -----------
359 # Called at the end of all the obsolete macros. If we are at the
360 # outermost level, call __au_disable.
361 _au_m4_define([_au_disable],
362 [_au_m4_popdef([_au_enabled])_au_dnl
363 _au_m4_ifdef([_au_enabled],
364 [],
365 [__au_disable()])])
366
367
368 ## ------------------------------- ##
369 ## Disable, and process the file. ##
370 ## ------------------------------- ##
371 # The AC autoquoting macros are not loaded yet, hence invoking
372 # `_au_disable' would be wrong.
373 _au__include([unm4.m4])
374
375 # Disable special characters, and set the first line number.
376 _au_m4_changequote()
377 _au_m4_changecom()
378
379 _au_m4_define(_au__first_line, _au___line__)_au__divert(0)_au_dnl
380EOF
381
382 $input_m4 =~ s/^ //mg;
383 $input_m4 =~ s/\$file/$file/g;
384
385 # prepared input -- input, but reenables the quote before each AU macro.
386 open INPUT_M4, ">$tmp/input.m4"
387 or error "cannot open: $!";
388 open FILE, "<$file"
389 or error "cannot open: $!";
390 print INPUT_M4 "$input_m4";
391 while (<FILE>)
392 {
393 eval $au_changequote;
394 print INPUT_M4;
395 }
396 close FILE
397 or error "cannot close $file: $!";
398 close INPUT_M4
399 or error "cannot close $tmp/input.m4: $!";
400
401 # Now ask m4 to perform the update.
402 xsystem ("$m4 --include=$tmp"
403 . join (' --include=', '', reverse (@prepend_include))
404 . join (' --include=', '', @include)
405 . " $tmp/input.m4 >$tmp/updated");
406 update_file ("$tmp/updated",
407 "$file" eq "$tmp/stdin" ? '-' : "$file");
408 }
409exit 0;
410
411
412# ## ---------------------------- ##
413# ## How `autoupdate' functions. ##
414# ## ---------------------------- ##
415#
416# The task of `autoupdate' is not trivial: the biggest difficulty being
417# that you must limit the changes to the parts that really need to be
418# updated. Finding a satisfying implementation proved to be quite hard,
419# as this is the fifth implementation of `autoupdate'.
420#
421# Below, we will use a simple example of obsolete macro:
422#
423# AU_DEFUN([OLD], [NEW([$1, $2], m4_eval([$1 + $2]))])
424# AC_DEFUN([NEW], [echo "sum($1) = $2"])
425#
426# the input file contains
427#
428# dnl The Unbelievable Truth
429# OLD(1, 2)
430# NEW([0, 0], [0])
431#
432# Of course the expected output is
433#
434# dnl The Unbelievable Truth
435# NEW([1, 2], [3])
436# NEW([0, 0], [0])
437#
438#
439# # First implementation: sed
440# # =========================
441#
442# The first implementation was only able to change the name of obsolete
443# macros.
444#
445# The file `acoldnames.m4' defined the old names based on the new names.
446# It was simple then to produce a sed script such as:
447#
448# s/OLD/NEW/g
449#
450# Updating merely consisted in running this script on the file to
451# update.
452#
453# This scheme suffers an obvious limitation: that `autoupdate' was
454# unable to cope with new macros that just swap some of its arguments
455# compared to the old macro. Fortunately, that was enough to upgrade
456# from Autoconf 1 to Autoconf 2. (But I have no idea whether the
457# changes in Autoconf 2 were precisely limited by this constraint.)
458#
459#
460# # Second implementation: hooks
461# # ============================
462#
463# The version 2.15 of Autoconf brought a vast number of changes compared
464# to 2.13, so a solution was needed. One could think to extend the
465# `sed' scripts with specialized code for complex macros. But this
466# approach is of course full of flaws:
467#
468# a. the Autoconf maintainers have to write these snippets, which we
469# just don't want to,
470#
471# b. I really don't think you'll ever manage to handle the quoting of
472# m4 from sed.
473#
474# To satisfy a., let's remark that the code which implements the old
475# features in term of the new feature is exactly the code which should
476# replace the old code.
477#
478# To answer point b, as usual in the history of Autoconf, the answer, at
479# least on the paper, is simple: m4 is the best tool to parse m4, so
480# let's use m4.
481#
482# Therefore the specification is:
483#
484# I want to be able to tell Autoconf, well, m4, that the macro I
485# am currently defining is an obsolete macro (so that the user is
486# warned), which code is the code to use when running autoconf,
487# but that the very same code has to be used when running
488# autoupdate. To summarize, the interface I want is
489# `AU_DEFUN(OLD-NAME, NEW-CODE)'.
490#
491#
492# Now for the technical details.
493#
494# When running autoconf, except for the warning, AU_DEFUN is basically
495# AC_DEFUN.
496#
497# When running autoupdate, we want *only* OLD-NAMEs to be expanded.
498# This obviously means that acgeneral.m4 and acspecific.m4 must not be
499# loaded. Nonetheless, because we want to use a rich set of m4
500# features, m4sugar.m4 is needed. Please note that the fact that
501# Autoconf's macros are not loaded is positive on two points:
502#
503# - we do get an updated `configure.ac', not a `configure'!
504#
505# - the old macros are replaced by *calls* to the new-macros, not the
506# body of the new macros, since their body is not defined!!!
507# (Whoa, that's really beautiful!).
508#
509# Additionally we need to disable the quotes when reading the input for
510# two reasons: first because otherwise `m4' will swallow the quotes of
511# other macros:
512#
513# NEW([1, 2], 3)
514# => NEW(1, 2, 3)
515#
516# and second, because we want to update the macro calls which are
517# quoted, i.e., we want
518#
519# FOO([OLD(1, 2)])
520# => FOO([NEW([1, 2], [3])])
521#
522# If we don't disable the quotes, only the macros called at the top
523# level would be updated.
524#
525# So, let's disable the quotes.
526#
527# Well, not quite: m4sugar.m4 still needs to use quotes for some macros.
528# Well, in this case, when running in autoupdate code, each macro first
529# reestablishes the quotes, expands itself, and disables the quotes.
530#
531# Thinking a bit more, you realize that in fact, people may use `define'
532# `ifelse' etc. in their files, and you certainly don't want to process
533# them. Another example is `dnl': you don't want to remove the
534# comments. You then realize you don't want exactly to import m4sugar:
535# you want to specify when it is enabled (macros active), and disabled.
536# m4sugar provides m4_disable/m4_enable to this end.
537#
538# You're getting close to it. Now remains one task: how to handle
539# twofold definitions?
540#
541# Remember that the same AU_DEFUN must be understood in two different
542# ways, the AC way, and the AU way.
543#
544# One first solution is to check whether acgeneral.m4 was loaded. But
545# that's definitely not cute. Another is simply to install `hooks',
546# that is to say, to keep in some place m4 knows, late `define' to be
547# triggered *only* in AU mode.
548#
549# You first think to design AU_DEFUN like this:
550#
551# 1. AC_DEFUN(OLD-NAME,
552# [Warn the user OLD-NAME is obsolete.
553# NEW-CODE])
554#
555# 2. Store for late AU binding([define(OLD_NAME,
556# [Reestablish the quotes.
557# NEW-CODE
558# Disable the quotes.])])
559#
560# but this will not work: NEW-CODE has probably $1, $2 etc. and these
561# guys will be replaced with the argument of `Store for late AU binding'
562# when you call it.
563#
564# I don't think there is a means to avoid this using this technology
565# (remember that $1 etc. are *always* expanded in m4). You may also try
566# to replace them with $[1] to preserve them for a later evaluation, but
567# if `Store for late AU binding' is properly written, it will remain
568# quoted till the end...
569#
570# You have to change technology. Since the problem is that `$1'
571# etc. should be `consumed' right away, one solution is to define now a
572# second macro, `AU_OLD-NAME', and to install a hook than binds OLD-NAME
573# to AU_OLD-NAME. Then, autoupdate.m4 just need to run the hooks. By
574# the way, the same method was used in autoheader.
575#
576#
577# # Third implementation: m4 namespaces by m4sugar
578# # ==============================================
579#
580# Actually, this implementation was just a clean up of the previous
581# implementation: instead of defining hooks by hand, m4sugar was equipped
582# with `namespaces'. What are they?
583#
584# Sometimes we want to disable some *set* of macros, and restore them
585# later. We provide support for this via namespaces.
586#
587# There are basically three characters playing this scene: defining a
588# macro in a namespace, disabling a namespace, and restoring a namespace
589# (i.e., all the definitions it holds).
590#
591# Technically, to define a MACRO in NAMESPACE means to define the macro
592# named `NAMESPACE::MACRO' to the VALUE. At the same time, we append
593# `undefine(NAME)' in the macro named `m4_disable(NAMESPACE)', and
594# similarly a binding of NAME to the value of `NAMESPACE::MACRO' in
595# `m4_enable(NAMESPACE)'. These mechanisms allow to bind the macro of
596# NAMESPACE and to unbind them at will.
597#
598# Of course this implementation is really inefficient: m4 has to grow
599# strings which can become quickly huge, which slows it significantly.
600#
601# In particular one should avoid as much as possible to use `define' for
602# temporaries. Now that `define' has quite a complex meaning, it is an
603# expensive operations that should be limited to macros. Use
604# `m4_define' for temporaries.
605#
606# Private copies of the macros we used in entering / exiting the m4sugar
607# namespace. It is much more convenient than fighting with the renamed
608# version of define etc.
609#
610#
611#
612# Those two implementations suffered from serious problems:
613#
614# - namespaces were really expensive, and incurred a major performance
615# loss on `autoconf' itself, not only `autoupdate'. One solution
616# would have been the limit the use of namespaces to `autoupdate', but
617# that's again some complications on m4sugar, which really doesn't need
618# this. So we wanted to get rid of the namespaces.
619#
620# - since the quotes were disabled, autoupdate was sometimes making
621# wrong guesses, for instance on:
622#
623# foo([1, 2])
624#
625# m4 saw 2 arguments: `[1'and `2]'. A simple solution, somewhat
626# fragile, is to reestablish the quotes right before all the obsolete
627# macros, i.e., to use sed so that the previous text becomes
628#
629# changequote([, ])foo([1, 2])
630#
631# To this end, one wants to trace the definition of obsolete macros.
632#
633# It was there that the limitations of the namespace approach became
634# painful: because it was a complex machinery playing a lot with the
635# builtins of m4 (hence, quite fragile), tracing was almost impossible.
636#
637#
638# So this approach was dropped.
639#
640#
641# # The fourth implementation: two steps
642# # ====================================
643#
644# If you drop the uses of namespaces, you no longer can compute the
645# updated value, and replace the old call with it simultaneously.
646#
647# Obviously you will use m4 to compute the updated values, but you may
648# use some other tool to achieve the replacement. Personally, I trust
649# nobody but m4 to parse m4, so below, m4 will perform the two tasks.
650#
651# How can m4 be used to replace *some* macros calls with newer values.
652# Well, that's dead simple: m4 should learn the definitions of obsolete
653# macros, forget its builtins, disable the quotes, and then run on the
654# input file, which amounts to doing this:
655#
656# divert(-1)dnl
657# changequote([, ])
658# define([OLD], [NEW([$1, $2], m4_eval([$1 + $2]))changequote()])
659# undefine([dnl])
660# undefine([m4_eval])
661# # Some more undefines...
662# changequote()
663# divert(0)dnl
664# dnl The Unbelievable Truth
665# changequote([, ])OLD(1, 2)
666# NEW([0, 0],
667# 0)
668#
669# which will result in
670#
671# dnl The Unbelievable Truth
672# NEW(1, 2, m4_eval(1 + 2))
673# NEW([0, 0],
674# 0)
675#
676# Grpmh. Two problems. A minor problem: it would have been much better
677# to have the `m4_eval' computed, and a major problem: you lost the
678# quotation in the result.
679#
680# Let's address the big problem first. One solution is to define any
681# modern macro to rewrite its calls with the proper quotation, thanks to
682# `$@'. Again, tracing the `define's makes it possible to know which
683# are these macros, so you input is:
684#
685# divert(-1)dnl
686# changequote([, ])
687# define([OLD], [NEW([$1, $2], m4_eval([$1 + $2]))changequote()])
688# define([NEW], [[NEW($@)]changequote()])
689# undefine([dnl])
690# undefine([m4_eval])
691# # Some more undefines...
692# changequote()
693# divert(0)dnl
694# dnl The Unbelievable Truth
695# changequote([, ])OLD(1, 2)
696# changequote([, ])NEW([0, 0],
697# 0)
698#
699# which results in
700#
701# dnl The Unbelievable Truth
702# NEW([1, 2],[m4_eval(1 + 2)])
703# NEW([0, 0],[0])
704#
705# Our problem is solved, i.e., the first call to `NEW' is properly
706# quoted, but introduced another problem: we changed the layout of the
707# second calls, which can be a drama in the case of huge macro calls
708# (think of `AC_TRY_RUN' for instance). This example didn't show it,
709# but we also introduced parens to macros which did not have some:
710#
711# AC_INIT
712# => AC_INIT()
713#
714# No big deal for the semantics (unless the macro depends upon $#, which
715# is bad), but the users would not be happy.
716#
717# Additionally, we introduced quotes that were not there before, which is
718# OK in most cases, but could change the semantics of the file.
719#
720# Cruel dilemma: we do want the auto-quoting definition of `NEW' when
721# evaluating `OLD', but we don't when we evaluate the second `NEW'.
722# Back to namespaces?
723#
724# No.
725#
726#
727# # Second step: replacement
728# # ------------------------
729#
730# No, as announced above, we will work in two steps: in a first step we
731# compute the updated values, and in a second step we replace them. Our
732# goal is something like this:
733#
734# divert(-1)dnl
735# changequote([, ])
736# define([OLD], [NEW([1, 2], [3])changequote()])
737# undefine([dnl])
738# undefine([m4_eval])
739# # Some more undefines...
740# changequote()
741# divert(0)dnl
742# dnl The Unbelievable Truth
743# changequote([, ])OLD(1, 2)
744# NEW([0, 0],
745# 0)
746#
747# i.e., the new value of `OLD' is precomputed using the auto-quoting
748# definition of `NEW' and the m4 builtins. We'll see how afterwards,
749# let's finish with the replacement.
750#
751# Of course the solution above is wrong: if there were other calls to
752# `OLD' with different values, we would smash them to the same value.
753# But it is quite easy to generalize the scheme above:
754#
755# divert(-1)dnl
756# changequote([, ])
757# define([OLD([1],[2])], [NEW([1, 2], [3])])
758# define([OLD], [defn([OLD($@)])changequote()])
759# undefine([dnl])
760# undefine([m4_eval])
761# # Some more undefines...
762# changequote()
763# divert(0)dnl
764# dnl The Unbelievable Truth
765# changequote([, ])OLD(1, 2)
766# NEW([0, 0],
767# 0)
768#
769# i.e., for each call to obsolete macros, we build an array `call =>
770# value', and use a macro to dispatch these values. This results in:
771#
772# dnl The Unbelievable Truth
773# NEW([1, 2], [3])
774# NEW([0, 0],
775# 0)
776#
777# In French, we say `Youpi !', which you might roughly translate as
778# `Yippee!'.
779#
780#
781# # First step: computation
782# # -----------------------
783#
784# Let's study the anatomy of the file, and name its sections:
785#
786# prologue
787# divert(-1)dnl
788# changequote([, ])
789# values
790# define([OLD([1],[2])], [NEW([1, 2], [3])])
791# dispatcher
792# define([OLD], [defn([OLD($@)])changequote()])
793# disabler
794# undefine([dnl])
795# undefine([m4_eval])
796# # Some more undefines...
797# changequote()
798# divert(0)dnl
799# input
800# dnl The Unbelievable Truth
801# changequote([, ])OLD(1, 2)
802# NEW([0, 0],
803# 0)
804#
805#
806# # Computing the `values' section
807# # ..............................
808#
809# First we need to get the list of all the AU macro uses. To this end,
810# first get the list of all the AU macros names by tracing `AU_DEFUN' in
811# the initialization of autoconf. This list is computed in the file
812# `au.txt' below.
813#
814# Then use this list to trace all the AU macro uses in the input. The
815# goal is obtain in the case of our example:
816#
817# [define([OLD([1],[2])],]@<<@OLD([1],[2])@>>@[)]
818#
819# This is the file `values.in' below.
820#
821# We want to evaluate this with only the builtins (in fact m4sugar), the
822# auto-quoting definitions of the new macros (`new.m4'), and the
823# definition of the old macros (`old.m4'). Computing these last two
824# files is easy: it's just a matter of using the right `--trace' option.
825#
826# So the content of `values.in' is:
827#
828# include($autoconf_dir/m4sugar.m4)
829# m4_include(new.m4)
830# m4_include(old.m4)
831# divert(0)dnl
832# [define([OLD([1],[2])],]@<<@OLD([1],[2])@>>@[)]
833#
834# We run m4 on it, which yields:
835#
836# define([OLD([1],[2])],@<<@NEW([1, 2], [3])@>>@)
837#
838# Transform `@<<@' and `@>>@' into quotes and we get
839#
840# define([OLD([1],[2])],[NEW([1, 2], [3])])
841#
842# This is `values.m4'.
843#
844#
845# # Computing the `dispatcher' section
846# # ..................................
847#
848# The `prologue', and the `disabler' are simple and need no commenting.
849#
850# To compute the `dispatcher' (`dispatch.m4'), again, it is a simple
851# matter of using the right `--trace'.
852#
853# Finally, the input is not exactly the input file, rather it is the
854# input file with the added `changequote'. To this end, we build
855# `quote.sed'.
856#
857#
858# # Putting it all together
859# # .......................
860#
861# We build the file `input.m4' which contains:
862#
863# divert(-1)dnl
864# changequote([, ])
865# include(values.m4)
866# include(dispatch.m4)
867# undefine([dnl])
868# undefine([eval])
869# # Some more undefines...
870# changequote()
871# divert(0)dnl
872# dnl The Unbelievable Truth
873# changequote([, ])OLD(1, 2)
874# NEW([0, 0],
875# 0)
876#
877# And we just run m4 on it. Et voila`, Monsieur ! Mais oui, mais oui.
878#
879# Well, there are a few additional technicalities. For instance, we
880# rely on `changequote', `ifelse' and `defn', but we don't want to
881# interpret the changequotes of the user, so we simply use another name:
882# `_au_changequote' etc.
883#
884#
885# # Failure of the fourth approach
886# # ------------------------------
887#
888# This approach is heavily based on traces, but then there is an obvious
889# problem: non expanded code will never be seen. In particular, the body
890# of a `define' definition is not seen, so on the input
891#
892# define([idem], [OLD(0, [$1])])
893#
894# autoupdate would never see the `OLD', and wouldn't have updated it.
895# Worse yet, if `idem(0)' was used later, then autoupdate sees that
896# `OLD' is used, computes the result for `OLD(0, 0)' and sets up a
897# dispatcher for `OLD'. Since there was no computed value for `OLD(0,
898# [$1])', the dispatcher would have replaced with... nothing, leading
899# to
900#
901# define([idem], [])
902#
903# With some more thinking, you see that the two step approach is wrong,
904# the namespace approach was much saner.
905#
906# But you learned a lot, in particular you realized that using traces
907# can make it possible to simulate namespaces!
908#
909#
910#
911# # The fifth implementation: m4 namespaces by files
912# # ================================================
913#
914# The fourth implementation demonstrated something unsurprising: you
915# cannot precompute, i.e., the namespace approach was the right one.
916# Still, we no longer want them, they're too expensive. Let's have a
917# look at the way it worked.
918#
919# When updating
920#
921# dnl The Unbelievable Truth
922# OLD(1, 2)
923# NEW([0, 0], [0])
924#
925# you evaluate `input.m4':
926#
927# divert(-1)
928# changequote([, ])
929# define([OLD],
930# [m4_enable()NEW([$1, $2], m4_eval([$1 + $2]))m4_disable()])
931# ...
932# m4_disable()
933# dnl The Unbelievable Truth
934# OLD(1, 2)
935# NEW([0, 0], [0])
936#
937# where `m4_disable' undefines the m4 and m4sugar, and disables the quotes
938# and comments:
939#
940# define([m4_disable],
941# [undefine([__file__])
942# ...
943# changecom(#)
944# changequote()])
945#
946# `m4_enable' does the converse: reestablish quotes and comments
947# --easy--, reestablish m4sugar --easy: just load `m4sugar.m4' again-- and
948# reenable the builtins. This later task requires that you first save
949# the builtins. And BTW, the definition above of `m4_disable' cannot
950# work: you undefined `changequote' before using it! So you need to use
951# your privates copies of the builtins. Let's introduce three files for
952# this:
953#
954# `m4save.m4'
955# moves the m4 builtins into the `_au_' pseudo namespace,
956# `unm4.m4'
957# undefines the builtins,
958# `m4.m4'
959# restores them.
960#
961# So `input.m4' is:
962#
963# divert(-1)
964# changequote([, ])
965#
966# include([m4save.m4])
967#
968# # Import AU.
969# define([OLD],
970# [m4_enable()NEW([$1, $2], m4_eval([$1 + $2]))m4_disable()])
971#
972# define([_au_enable],
973# [_au_changecom([#])
974# _au_include([m4.m4])
975# _au_include(m4sugar.m4)])
976#
977# define([_au_disable],
978# [# Disable m4sugar.
979# # Disable the m4 builtins.
980# _au_include([unm4.m4])
981# # 1. Disable special characters.
982# _au_changequote()
983# _au_changecom()])
984#
985# m4_disable()
986# dnl The Unbelievable Truth
987# OLD(1, 2)
988# NEW([0, 0], [0])
989#
990# Based on what we learned in the fourth implementation we know that we
991# have to enable the quotes *before* any AU macro, and we know we need
992# to build autoquoting versions of the AC macros. But the autoquoting
993# AC definitions must be disabled in the rest of the file, and enabled
994# inside AU macros.
995#
996# Using `autoconf --trace' it is easy to build the files
997#
998# `ac.m4'
999# define the autoquoting AC fake macros
1000# `disable.m4'
1001# undefine the m4sugar and AC autoquoting macros.
1002# `au.m4'
1003# definitions of the AU macros (such as `OLD' above).
1004#
1005# Now, `input.m4' is:
1006#
1007# divert(-1)
1008# changequote([, ])
1009#
1010# include([m4save.m4])
1011# # Import AU.
1012# include([au.m4])
1013#
1014# define([_au_enable],
1015# [_au_changecom([#])
1016# _au_include([m4.m4])
1017# _au_include(m4sugar.m4)
1018# _au_include(ac.m4)])
1019#
1020# define([_au_disable],
1021# [_au_include([disable.m4])
1022# _au_include([unm4.m4])
1023# # 1. Disable special characters.
1024# _au_changequote()
1025# _au_changecom()])
1026#
1027# m4_disable()
1028# dnl The Unbelievable Truth
1029# _au_changequote([, ])OLD(1, 2)
1030# NEW([0, 0], [0])
1031#
1032# Finally, version V is ready.
1033#
1034# Well... almost.
1035#
1036# There is a slight problem that remains: if an AU macro OUTER includes
1037# an AU macro INNER, then _au_enable will be run when entering OUTER
1038# and when entering INNER (not good, but not too bad yet). But when
1039# getting out of INNER, _au_disable will disable everything while we
1040# were still in OUTER. Badaboom.
1041#
1042# Therefore _au_enable and _au_disable have to be written to work by
1043# pairs: each _au_enable pushdef's _au_enabled, and each _au_disable
1044# popdef's _au_enabled. And of course _au_enable and _au_disable are
1045# effective when _au_enabled is *not* defined.
1046#
1047# Finally, version V' is ready. And there is much rejoicing. (And I
1048# have free time again. I think. Yeah, right.)
1049
1050### Setup "GNU" style for perl-mode and cperl-mode.
1051## Local Variables:
1052## perl-indent-level: 2
1053## perl-continued-statement-offset: 2
1054## perl-continued-brace-offset: 0
1055## perl-brace-offset: 0
1056## perl-brace-imaginary-offset: 0
1057## perl-label-offset: -2
1058## cperl-indent-level: 2
1059## cperl-brace-offset: 0
1060## cperl-continued-brace-offset: 0
1061## cperl-label-offset: -2
1062## cperl-extra-newline-before-brace: t
1063## cperl-merge-trailing-else: nil
1064## cperl-continued-statement-offset: 2
1065## End:
Note: See TracBrowser for help on using the repository browser.