Thanks Eric. I think that will do the trick. I'll e-mail the list again if it doesn't work out for me.
As an aside, if y'all are planning a m4 v2.0 release (like I think I've seen in the m4-discuss archive) I'd like to suggest that the ability to ignore duplicate included files be built into the m4 program itself, rather than pushdef/ifdef example. Maybe enabled with a --ignore-duplicate-include option. I'd like the option to also manage the sinclude() lines also at the same time. I'd implement in the C code by keeping track of the files ready by inode number and device mounted on (rather than the path), like I thought about in my icky work-around. Thanks again.... -Roger On Tue, Sep 30, 2008 at 6:19 PM, Eric Blake <[EMAIL PROTECTED]> wrote: > -----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<http://home.comcast.net/%7Eericblake/eblake.gpg> > Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org > > iEYEARECAAYFAkji0A8ACgkQ84KuGfSFAYAywwCgn76hkIQ89pgN2BxkzxnWu3on > Hx8AnROy+XNuVZYcjdgpSWA+tHV56UNX > =NUHy > -----END PGP SIGNATURE----- > >
_______________________________________________ m4-discuss mailing list [email protected] http://lists.gnu.org/mailman/listinfo/m4-discuss
