[comp.lang.c] Unstylish #defines ??

jrb@petro.UUCP (09/22/87)

I've been toying with ways to make the `HOME' directory for a pile of software
a little more portable and the following sure beats the method where you
effectively get -> sprintf(buf,"%s/afile","/usr/me"); fopen(buf,"r"); <- but
it sure does LOOK wierd!

----- cut here -----
#define FOO "/usr/me

stream = fopen(FOO/afile","r");
----- ereh tuc -----

It works, mostly because file names are "divided" as they are, but is it
stylish?!  Any takers?  Peter?

Thanks!
Jon
-----
Peter and the Wolf?  No! -- Peter da Wolf `-_-'
Gimme a break!           --                'U`
-- 
Jon Boede				...!{gatech,ihnp4,akgua}!petro!jrb
512/599-1847				2555 N.E. Loop 410, #1403, 78217
	"People who are incapable of making decisions are
	 the ones who hit those barrels at freeway exits."

rjchen@phoenix.UUCP (09/24/87)

In article <325@petro.UUCP> jrb@petro.UUCP (Jon Boede) writes:
>I've been toying with ways to make the `HOME' directory for a pile of software
>a little more portable and the following sure beats the method where you
>effectively get -> sprintf(buf,"%s/afile","/usr/me"); fopen(buf,"r"); <- but
>it sure does LOOK wierd!
>
>#define FOO "/usr/me
>stream = fopen(FOO/afile","r");

The official ANSI C way of doing it is as follows:

#define FOO "/usr/me"
stream = fopen(FOO "/afile", "r");

This expands to
stream = fopen("/usr/me" "/afile", "r");

which the preprocessor mushes together to make
stream = fopen("usr/me/afile", "r")

Of course, you need an ANSI-draft-conforming preprocessor first.


-- 
Raymond Chen, BITNET: (preferably) 6101695@pucc, rjchen@pucc
              ARPA: rjchen@pucc.PRINCETON.EDU
              UUCP: {allegra}!princeton!pucc!rjchen
*** DO NOT REPLACE THIS LINE ***

karl@haddock.UUCP (09/25/87)

In article <325@petro.UUCP> jrb@petro.UUCP (Jon Boede) writes:
>#define FOO "/usr/me
>stream = fopen(FOO/afile","r");

It isn't portable, and so it's best to avoid this.  In pre-ANSI, the best you
can do is paste the two pieces together at run-time (with strcat or sprintf),
or #define each such path separately (#define FOO_afile "/usr/me/afile" ,
etc.), but in ANSI C string constants can be pasted at compile-time:
  #define FOO "/usr/me"
  stream = fopen(FOO "/afile", "r")

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

karl@haddock.ISC.COM (Karl Heuer) (09/25/87)

In article <763@phoenix.PRINCETON.EDU> rjchen@phoenix.UUCP (Raymond Juimong Chen) writes:
>This expands to
>stream = fopen("/usr/me" "/afile", "r");
>
>which the preprocessor mushes together to make
>stream = fopen("usr/me/afile", "r")

A minor quibble here.  (No, not the missing slash.)  In compilers that
maintain the traditional separation of cpp from compiler proper, the string
pasting is likely to be done in the lexer, not the preprocessor.  Otherwise
the preprocessor has to avoid situations like ("\12" "3"), for which the naive
answer ("\123") is wrong.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

chris@mimsy.UUCP (Chris Torek) (09/26/87)

In article <1237@haddock.ISC.COM> karl@haddock.ISC.COM (Karl Heuer) writes:
>... In pre-ANSI [C], the best you can do is paste the two pieces
>together at run-time (with strcat or sprintf), or #define each such
>path separately ... but in ANSI C string constants can be pasted at
>compile-time:
>  #define FOO "/usr/me"
>  stream = fopen(FOO "/afile", "r")

Or use the following program, e.g.,
`cc -E foo.c | string > x.c && cc -c x.c && mv x.o foo.o'.

I wrote the original version of string on 30 October 1982.  This
one has been cleaned up a bit.  (This can be done as a tiny lex
program, but until Van sends out his new lex, we get slow scanners.)

static char rcsid[] = "$Header: string.c,v 1.2 87/09/26 01:10:41 chris Exp $";

/* string -- combine adjacent C strings */

#include <stdio.h>

#define	SQUOTE	'\''
#define	DQUOTE	'"'
#define	BACKSLASH '\\'

/*ARGSUSED*/
main(argc, argv)
	int argc;
	char **argv;
{
	register int c;
	register char *p, *q;
	char buf[BUFSIZ];

	/* process charcters, handling 'x' and "string" "s" */
	while ((c = getchar()) != EOF) {
		switch (c) {

		case SQUOTE:	/* char const */
			(void) putchar(c);
			while ((c = getchar()) != EOF) {
				(void) putchar(c);
				if (c == BACKSLASH) {
					if ((c = getchar()) != EOF)
						(void) putchar(c);
				} else if (c == SQUOTE)
					break;
			}
			break;

		case DQUOTE:	/* "string" */
			(void) putchar(DQUOTE);
	more:
			while ((c = getchar()) != EOF) {
				if (c == BACKSLASH) {
					(void) putchar(c);
					if ((c = getchar()) != EOF)
						(void) putchar(c);
				} else if (c == DQUOTE)
					break;
				else
					(void) putchar(c);
			}
			/* found the close quote, but might be another str */
			p = buf;
			while ((c = getchar()) == ' ' || c == '\t' || c == '\n')
				if (p < &buf[sizeof buf])
					*p++ = c;
			if (c == DQUOTE)	/* another string */
				goto more;
			if (c != EOF) {
				/* close previous string and rescan later */
				(void) putchar(DQUOTE);
				ungetc(c, stdin);
			}
			/* write buffered whitespace */
			for (q = buf; q < p;)
				(void) putchar(*q++);
			break;

		default:		/* anything else copied literally */
			(void) putchar(c);
		}
	}
	exit(0);
}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris