Macros with multi-line results?

Dave Corcoran dave at aspect.UUCP
Wed Jan 23 08:35:21 AEST 1991


In article <16101 at burdvax.PRC.Unisys.COM>, fritzson at PRC.Unisys.COM (Richard Fritzson) writes:
> I am trying to write a macro which generates more than one line of
> output.
> 
> as output from the C preprocessor. I would very much like to get
> 
> 	body
> 	more body
> 	still more
> 
> somehow. Is this possible? 
> 

Here is an m4 solution, named perldef (in perlmac.m) using perl.


The macro which follows will define another macro which can be invoked
inline (via m4 (SunOS users use /usr/5bin/m4)) and can use any perl script.

Quoted constructs:

	'\''		to insert tics	
	\\n			to insert \n
	%%			to insert %

so the string

	" '\''%%s'\''\\n "

yields

	" '%s'\n "

in the output perl *script*.


Options to perl can be passed as $3 of the definition.

The contents of perlmac.m follows
---------------------8<--------------------------
define(perldef,
	`syscmd((echo ' '$2' | sed 's/^(//;s/^)//' `>/tmp/pm_$1))'
	`define($1,`syscmd(perl $3 /tmp/pm_$1 $'`1 ifelse($'`2,,,<<@@
$'`2
@@))')'
)
---------------------8<--------------------------

Two forms of invocation can be used: (where xx is the macro definition)


1.
	xx([arg1 ... argN])

This form places arg1 -> argN in arg list (i.e. @ARGV).
Note the *absence* of *any* commas in the arg list.


2.
	xx(,arg1.1 arg1.2
	arg2
	arg3
	arg4 arg4.1) 

This presents the arg list as the "here-is" form.

	i.e.
	perl scriptfilename <<@@
	arg1 arg1.1 arg1.2
	arg2
	arg3
	arg4 arg4.1
	@@

Note the usage of the leading comma and absence of any commas in
the balence of the list.


An example of how to use follows: (tst.c.m)
                                     (^^^^ -- is this an ok convention?)

Note that the placement of the 2nd inner parens, which allows commas to
be used in the script, must be the first and last characters in the
macro; the perldef macro strips them out using:

	sed 's/^(/^)/' 

so all lines with leading parens column 1 will be deleted. This is a
bug(feature).


tst.c.m
---------------------8<--------------------------
include(perlmac.m)

perldef(xx,(
	for $i (@ARGV) {
		printf qq/#define %s %d\n/,$i,++$j;
	}
))

perldef(yy,( 
	for $i (@ARGV) {
		@l=split(/ */,$i);
		@l[0]=~y/a-z/A-Z/;
		$m=join("", at l);
		$i=~y/a-z/A-Z/;
		printf qq/#define %s "%s"\n/,$i,$m;
	}
))

perldef(zz,(
	for $i (@ARGV) {
		$j=$i;
		$i=~y/a-z/A-Z/;
		printf qq/	printf("-- %%d -- %%s\\n",$j,$i);\n/;
	}
	print qq/	printf("'\''this is in single quotes'\''\\n");\n/;
	## note that $HOME contains "/" so qq/ will not work
	print qq@	printf("this is my current dir - ' $HOME '\\n");\n@;
))


define(`vars',one two three four five six)
define(`vars',vars seven eight nine ten eleven)

xx(vars)
yy(vars)

main()
{
	zz(vars)
}
---------------------8<--------------------------

m4 tst.c.m >tst.c

Invocation given the above yields: (leading blank lines deleted)

#define one 1
#define two 2
#define three 3
#define four 4
#define five 5
#define six 6
#define seven 7
#define eight 8
#define nine 9
#define ten 10
#define eleven 11

#define ONE "One"
#define TWO "Two"
#define THREE "Three"
#define FOUR "Four"
#define FIVE "Five"
#define SIX "Six"
#define SEVEN "Seven"
#define EIGHT "Eight"
#define NINE "Nine"
#define TEN "Ten"
#define ELEVEN "Eleven"


main()
{
		printf("-- %d -- %s\n",one,ONE);
	printf("-- %d -- %s\n",two,TWO);
	printf("-- %d -- %s\n",three,THREE);
	printf("-- %d -- %s\n",four,FOUR);
	printf("-- %d -- %s\n",five,FIVE);
	printf("-- %d -- %s\n",six,SIX);
	printf("-- %d -- %s\n",seven,SEVEN);
	printf("-- %d -- %s\n",eight,EIGHT);
	printf("-- %d -- %s\n",nine,NINE);
	printf("-- %d -- %s\n",ten,TEN);
	printf("-- %d -- %s\n",eleven,ELEVEN);
	printf("'this is in single quotes'\n");
	printf("this is my current dir -  /home/dave \n");

}
-- 
David Corcoran		      -@@
uunet!aspect!dave	        ~
In a society where anything goes eventually everything will.



More information about the Comp.lang.c mailing list