Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!samsung!munnari.oz.au!goanna!ok From: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) Newsgroups: comp.lang.c Subject: Re: Is this bad programming? Keywords: #define array definition Message-ID: <3541@goanna.cs.rmit.oz.au> Date: 10 Aug 90 07:57:48 GMT References: <1990Aug8.100614.1223@resam.dk> <1910@tkou02.enet.dec.com> Organization: Comp Sci, RMIT, Melbourne, Australia Lines: 125 In article <1910@tkou02.enet.dec.com>, diamond@tkou02.enet.dec.com (diamond@tkovoa) writes: > In article <1990Aug8.100614.1223@resam.dk> andrew@resam.dk (Leif Andrew Rump) writes: > >char errortext[][40] = { > > "234567890123456789012345678901234567890", > >#define FILE_FOOTER_ERROR 1 > > "File footer error", Instead of all this, suppose you have k separate arrays, k >= 1, that you want to initialise "in parallel". You want to give names to the numbers, and a name to the total number. The obvious method is to construct a miniature language a la Bentley. Take a data file like this: #File: mktable.demo # EntryCt; int whence; int whither; char *name Butcher; 1; 2; "Butcher" Baker; 1; 3; "Baker" Bellman; 2; 3; "Bellman" Boojum; 0; 0; NULL #End: mktable.demo Here the first non-comment line has the form ; ; ... where is the name that will be #defined to the number of elements in each array, is the name of the ith array to be initialised, and is the type of its elements. Subsequent non-comment lines have the form ; ; ... where is the name that will be #defined to the record number, and is a C expression which is to be one of the initial values of array . We feed this through the following AWK script: #File: mktable.awk # BEGIN { # note that no header nor data seen yet k = 0 # number of fields required in each record r = 0 # number of data records processed so far p = 0 # number of data *values* saved in data[] } $0 ~ /^[ \t]*#/ { # ignore comment lines next } k == 0 { # first non-comment line is header if (NF < 2) { print "Error in line " NR ": 2 or more names expected" exit } k = NF # number of fields to be in EACH line for (i = 1; i <= NF; i++) name[i] = $i next # don't treat this as data! } k != 0 { # this must be a data record if (NF != k) { print "Error in line " NR ": wrong number of fields" exit } print "#define", $1, r # define the record number r++ # then save the data away for (i = 2; i <= NF; i++) data[p++] = $i } END { # all records seen if (k == 0) { # never saw a header print "Error; no header record present" exit } if (r == 0) { # never saw any data print "Error; no data records present" exit } # otherwise, data[] is r blocks of (k-1) strings print "#define", name[1], r for (i = 2; i <= k; i++) { print name[i] "[] = {" for (t = i-2; t < p; t += k-1) print "\t" data[t] "," print "};" } } #End: mktable.awk In UNIX it is easy to bolt all this together awk -F\; -f mktable.awk mktable.demo | cb >tables.c ^field separator ^awk program ^data file ^result (Note that using ; as the field separator allows spaces in expressions. If you want "strings" or 'ints' containing ";", use some other character.) The result is #define Butcher 0 #define Baker 1 #define Bellman 2 #define Boojum 3 #define EntryCt 4 int whence[] = { 1, 1, 2, 0, }; int whither[] = { 2, 3, 3, 0, }; char *name[] = { "Butcher", "Baker", "Bellman", NULL, }; In MS-DOS, it's a little harder (you might have to get the MKS awk, for example). On the other hand, it would be pretty easy to translate this awk program to C. In any case, just #include the result into your C program, and Bob's your uncle! -- Taphonomy begins at death.