Re: Question about m4 include/sinclude
Eric Blake <[email protected]>
| Newsgroups | gmane.comp.gnu.m4.general |
|---|---|
| Message-ID | <[email protected]> |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 According to [email protected] on 9/30/2008 4:49 PM: > Without using ifdef or something similar, is there a way to prevent m4 from > entering an infinite recursion with a file like: > > % cat foo > include(`foo') No. But WITH ifdef, there is a way, and in fact, autoconf uses it to prohibit including a file more than once (not because of the fear of infinite recursion, but because of the surprising number of .m4 include files out there that define a macro with the first argument underquoted - re-including the file would define a new macro, named by the definition of the original macro, rather than being a no-op). > I realize I can probably do something like define a macro in the file, > and then not include > the file if the macro is defined... HOWEVER, in my particular > application, I cannot control all > of the m4 files... The trick is not doing it in the file, but before the file. In other words, redefine include to do additional work. In other words, the act of calling include defines a witness macro, such that if the witness macro is defined, you are recursively (or repeatedly) trying to re-include the file. pushdef(`include', `ifelse(`$#', `0', ``$0'', `ifdef(`include($1)', `ifelse(`$1 has been seen; replace this no-op comment with m4exit if desired')', `define(`include($1)')builtin(`$0', $@)')')') pushdef(`sinclude', defn(`include')) The ifelse comment there can be turned into a warning (via errprint) or error (via m4exit) if desired. And this works independently of the file contents (so you can protect yourself against malicious include files, as appears to be your goal). > And my m4 go off into an infinite loop. I can control command line > options, but > when I tried --nesting-limit=1, that didn't seem to help. - --nesting-limit only controls textual nesting (such as "include(include(foo))"), not recursive invocation. In the case of recursive invocation, each macro is expanded at the outermost level of textual nesting. > > About all I could think of is to have my Perl script I'm calling m4 from > pre-process the > files looking for include or sinclude lines, taking into account the > M4PATH environment > files, and making sure I don't repeat files (using something like stat() > and the inode and > device to make sure I handle symlinks). I agree - that seems gross. And as autoconf developers have already noted, m4 is the best language for parsing m4 - it is almost impossible to write robust perl scripts that still handle all cases of m4 input reliably. - -- Don't work too hard, make some time for fun as well! Eric Blake [email protected] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkji0A8ACgkQ84KuGfSFAYAywwCgn76hkIQ89pgN2BxkzxnWu3on Hx8AnROy+XNuVZYcjdgpSWA+tHV56UNX =NUHy -----END PGP SIGNATURE-----