[comp.lang.c] char *** initialization and compiler problem

hokey@plus5.UUCP (03/13/87)

A while ago I wanted to provide for more comprehensive error message reporting
in some software I was writing.  Since sys_errlist is an array of char *, and
all the libaries I was building had their own, similar, arrays, I thought it
would be "nice" to combine all these tables of messages and pass these messages
from library to library, instead of writing code at the interface between each
library which converted error messages and codes from "them" to "us" format.

This would also give the ability to pass around "multi-line" messages and
handle the logging and printing of all error messages from a single point.
Oh, it also provides me with the ability to tailor the error messages to
different character sets and languages.

I ran in to two instant problems.

First, I have been *unable* to initialize the master table in any way other
than that in the example below.  I tried *lots* of combinations of braces.

Second, the *only* declaration acceptable to the compiler for the given
initialization of the table is the one below.

I am using a SysVr2 C compiler, although a friend was similarly frustrated
with a compiler on his Sun.  He was able to effect a solution using structures,
but I haven't had time to really study that approach.

I have no idea if the example below will work on other C compilers.

Anybody interested in checking out this beastie?

Hokey

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by hokey on Fri Mar 13 12:10:36 CST 1987
# Contents:  emt.c
 
echo x - emt.c
sed 's/^@//' > "emt.c" <<'@//E*O*F emt.c//'
/* Error Message Table test program */


extern char *sys_errlist[];	/* as per perror(3C) */
char *a_list[] = {
	"a0",
	"a1",
	"a2",
	"a3",
	"a4",
	"a5",
	"a6",
	0};
char *b_list[] = {
	"b0",
	"b1",
	"b2",
	"b3",
	0};

/* char ***em_t		/**/
/* char *(*em_t)[]	/**/
/* char *em_t[][]	/**/
char **em_t[]		/**/
	= {
			sys_errlist
		,
			a_list	/* Just try and initialize with strings here! */
		,
			b_list
		,
		0
	};

main() {
	int table, entry;
	int size;

	while(scanf("%d %d", &table, &entry) == 2) {
		printf("table %d, entry %d = %s\n",
		    table,
		    entry,
		    em_t[table][entry]
		    );}
	exit(0);}
@//E*O*F emt.c//
chmod u=rw,g=rw,o=r emt.c
 
exit 0
-- 
Hokey

chris@mimsy.UUCP (03/14/87)

In article <1721@plus5.UUCP> hokey@plus5.UUCP (Hokey) writes:
>First, I have been *unable* to initialize the master table in any way other
>than that in the example below.  I tried *lots* of combinations of braces.

I am not quite sure what you want, but the example is correct.

>Second, the *only* declaration acceptable to the compiler for the given
>initialization of the table is the one below.

Not surprising: it is the correct one.

condensed:
>extern char *sys_errlist[];	/* as per perror(3C) */
>char *a_list[] = { ... };
>char *b_list[] = { ... };

The types of `sys_errlist', `a_list', and `b_list' are each `array
<n> of pointer to char' (<n> varies, being `unknown', 7, and 5, I
think, though I have deleted the actual initialisations).  When
used in ordinary expression contexts, the types are converted to
`pointer to pointer to char'.  Thus:

>char **em_t[] = {
>	sys_errlist,
> 	a_list,		/* Just try and initialize with strings here! */
> 	b_list,
> 	0
>};

`em_t' is `array 4 of pointer to pointer to char'.

Given the comment after `a_list', I guess that you might want, e.g.,
something more like this:

	char **em_t[] = {
		sys_errlist,
	/*
	 * magic unnamed list:
		(char *[] = { "a0", "a1", "a2", ..., 0 }),
	 * and another, `b', list.
	 */
		0
	};

Alas, there is no C construct that creates an unnamed block of
initialised data space (an object of type `array <n> of <type>')
save for anonymous arrays of char, which are created with "string".
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
UUCP:	seismo!mimsy!chris	ARPA/CSNet:	chris@mimsy.umd.edu