|
|
1.1 root 1: /*
2: * Quick and dirty screen builder.
3: * by Charles Fiterman on 2-6-90
4: *
5: * pass 1 count lines with data and field start chars.
6: * allocate tables.
7: * pass 2 build data.
8: * pass 3 output data to .c file.
9: */
10: #include <misc.h>
11: #include <scn.h>
12: #include <ctype.h>
13:
14: extern char *strrchr();
15: extern char *strchr();
16: extern char *strcpy();
17:
18: static char *fileName = NULL;
19: static char *outFile;
20: static char fieldDesig = '!';
21: static int errCt = 0, line = 1;
22: static int backCnt, locCnt;
23: static loc *locTab;
24: static long filePos;
25:
26: static FILE *ifp, *ofp, *hfp;
27:
28: static char *buf;
29:
30: #define MAXTOKEN 5
31:
32: /*
33: * Usage message documents program usage.
34: */
35: void
36: Usage()
37: {
38: fprintf(stderr, "Usage: scn [-fc] filename\n");
39: fprintf(stderr, "\t-fc sets field designator to c\n");
40: exit(1);
41: }
42:
43: /*
44: * Read into buff.
45: */
46: qread()
47: {
48: return (NULL != (buf = getline(ifp, &line)));
49: }
50:
51: /*
52: * this routine breaks command_string into individual tokens, putting
53: * pointers to these tokens into the array tokenlist.
54: * no more than maxtoken tokens will be found.
55: * Note that the string is modified to place '\0' over
56: * token separators. The tokenlist points into the string.
57: * Tokens are separated by spaces, tabs and commas.
58: */
59: void
60: tokenize(s, tokenlist, maxtoken)
61: register char *s;
62: char *tokenlist[];
63: int maxtoken;
64: {
65: register int state, i;
66:
67: for (i = 0; i < maxtoken; i++)
68: tokenlist[i] = NULL;
69:
70: for (i = state = 0; ; s++) {
71: switch (*s) {
72: case ' ':
73: case '\t':
74: *s = state = 0;
75: continue;
76: case ',':
77: *s = state = 0;
78: if (maxtoken > ++i)
79: continue;
80: fprintf(stderr, "Too many tokens in line %d\n", line);
81: errCt++;
82: case 0:
83: return;
84: }
85: if (!state) { /* was in whitespace */
86: tokenlist[i] = s;
87: state = 1; /* in token */
88: }
89: }
90: }
91:
92: /*
93: * Count lines and fields allocate space.
94: */
95: void
96: pass1()
97: {
98: register char *p, c;
99: int sw, pos, nameCt, nlines, repits;
100:
101: fprintf(ofp, "/*\n");
102: fprintf(ofp, " * This file generated by scn from %s\n", fileName);
103: fprintf(ofp, " */\n");
104:
105: for (nlines = repits = nameCt = 0; qread(); ) {
106: char *token[MAXTOKEN]; /* name len default verifyProc */
107: int len;
108:
109: if ('%' == buf[0]) { /* control statemnet */
110: switch (buf[1]) {
111: case '%': /* done with preface */
112: filePos = ftell(ifp);
113: break;
114: case 'h': /* help line */
115: continue;
116: case ' ': /* group line */
117: case 'g':
118: if (2 == sscanf(buf + 2, "%d %d",
119: &nlines, &repits))
120: continue;
121: default:
122: fatal("Improper control line line %d", line);
123: }
124: break;
125: }
126: tokenize(buf, token, MAXTOKEN);
127: if (token[0] != NULL) {
128: if (!(len = abs(atoi(token[1]))))
129: len = abs(atoi(token[2]));
130: len++;
131: if (nlines) {
132: nlines--;
133: nameCt += repits;
134: fprintf(hfp,
135: "extern char %s[%d][%d];\n",
136: token[0],
137: repits,
138: len);
139: fprintf(ofp,
140: "char %s[%d][%d];\n",
141: token[0],
142: repits,
143: len);
144: }
145: else {
146: nameCt++;
147: fprintf(hfp, "extern char %s[%d];\n",
148: token[0], len);
149: fprintf(ofp, "char %s[%d];\n",
150: token[0], len);
151: }
152: }
153: else {
154: errCt++;
155: fprintf(stderr, "No field in line %d\n", line);
156: }
157: if (NULL != token[3])
158: fprintf(ofp, "extern int (*%s)();\n", token[3]);
159: if ((NULL != token[2]) && (NULL != token[1]) &&
160: ((len = atoi(token[1])) > 0) &&
161: (strlen(token[2]) > len)) {
162: errCt++;
163: fprintf(stderr, "default %s greater then %d line %d\n",
164: token[2], len, line);
165: }
166: }
167:
168: fprintf(ofp, "/* C tables for the screen:\n");
169: while (qread()) {
170: pos = sw = 0;
171: for (p = buf; c = *p; p++, pos++) {
172: if (c == fieldDesig)
173: locCnt++;
174: else if (!isspace(c))
175: sw = 1;
176: else if ('\t' == c)
177: pos |= 7;
178: }
179: backCnt += sw;
180: if (pos > 80) {
181: errCt++;
182: fprintf(stderr, "Line %d too long", line);
183: continue;
184: }
185: for (p = buf; c = *p++; sw = c) {
186: if ((('/' == c) && ('*' == sw)) ||
187: (('/' == sw) && ('*' == c)))
188: c = '?';
189: fputc(c, ofp);
190: }
191: fputc('\n', ofp);
192: }
193: fprintf(ofp, " */\n\n");
194: if (nameCt != locCnt)
195: fatal("%d field names but %d fileds", nameCt, locCnt);
196: if (errCt)
197: exit(1);
198: if (locCnt)
199: locTab = alloc(locCnt * sizeof(loc));
200: }
201:
202: /*
203: * Put together tables.
204: */
205: void
206: pass2()
207: {
208: int dataLine, row, lc;
209:
210: fseek(ifp, filePos, 0); /* pass %% */
211:
212: fprintf(ofp, "/*\n");
213: fprintf(ofp, " * Screen background data.\n");
214: fprintf(ofp, " */\n");
215: fprintf(ofp, "#include <scn.h>\n\n");
216: fprintf(ofp, "struct backGrnd %s_data[] = {\n", fileName);
217:
218: for (lc = row = dataLine = 0; qread(); row++) {
219: register char *p, c, *p1;
220: int spos, pos;
221:
222: for ((p1 = NULL), (p = buf), (pos = 0); c = *p; pos++, p++) {
223: if (c == fieldDesig) {
224: locTab[lc].row = row;
225: locTab[lc].col = pos;
226: *p = ' ';
227: lc++;
228: continue;
229: }
230: switch (c) {
231: case '\t':
232: pos |= 7;
233: case ' ':
234: continue;
235: }
236: if (NULL == p1) { /* mark start of line */
237: spos = pos;
238: p1 = p;
239: }
240: }
241: if (NULL == p1) /* no printable data on line */
242: continue;
243:
244: for (p--; isspace(*p); p--) /* trim line */
245: *p = '\0';
246:
247: fputc('"', ofp);
248: for (pos = spos; c = *p1; p1++) {
249: switch (c) {
250: case '\t': /* raw mode ignores tabs */
251: do { /* make them spaces */
252: fputc(' ', ofp);
253: } while (++pos & 7);
254: continue;
255: case '\\':
256: case '"':
257: fputc('\\', ofp);
258: default:
259: fputc(c, ofp);
260: }
261: pos++;
262: }
263: fprintf(ofp, "\",\n\t %d, %d,\n", row, spos);
264: }
265: fprintf(ofp, "NULL\n");
266: fprintf(ofp, "};\n\n");
267: }
268:
269: #define nc(t, x) ((NULL != t) ? t : x)
270: void
271: pass3()
272: {
273: register int i;
274: int nlines, skipout;
275:
276: rewind(ifp);
277:
278: fprintf(ofp, "/*\n");
279: fprintf(ofp, " * Screen data location table.\n");
280: fprintf(ofp, " */\n");
281: fprintf(ofp, "struct loc %s_locs[] = {\n", fileName);
282: for (skipout = nlines = i = 0; i < locCnt; i++) {
283: char *token[MAXTOKEN]; /* name len default verifyProc */
284: char helpMsg[80];
285: int skip, len, slines, j, repits;
286:
287: helpMsg[0] = 0;
288: for (qread(); '%' == buf[0]; qread()) {
289: switch (buf[1]) {
290: case ' ':
291: case 'g':
292: sscanf(buf + 2, "%d %d", &nlines, &repits);
293: j = 0;
294: slines = nlines;
295: skipout = nlines * repits;
296: filePos = ftell(ifp);
297: break;
298: case 'h':
299: strcpy(helpMsg, buf + 3);
300: }
301: }
302: tokenize(buf, token, MAXTOKEN);
303: if (NULL == token[1]) /* no length given */
304: len = 79 - locTab[i].col;
305: else
306: len = atoi(token[1]);
307:
308: if (skipout)
309: skipout--;
310: skip = 0;
311: if (NULL != token[4]) {
312: if (strcmp(token[4], "group"))
313: skip = atoi(token[4]);
314: else
315: skip = skipout;
316: }
317: else if (!len)
318: skip = atoi(token[2]);
319:
320: if (nlines) {
321: if (len <= 0)
322: fprintf(ofp, /* field is default */
323: "\t%s[%d], %d, %s[%d], %s, %d, %d, %d,",
324: token[0], j,
325: -len,
326: ((len && NULL != token[2]) ?
327: token[2] : token[0]),
328: j,
329: nc(token[3], "NULL"),
330: locTab[i].row,
331: locTab[i].col,
332: skip);
333: else
334: fprintf(ofp,
335: "\t%s[%d], %d, \"%s\", %s, %d, %d, %d,",
336: token[0], j,
337: len,
338: nc(token[2], ""),
339: nc(token[3], "NULL"),
340: locTab[i].row,
341: locTab[i].col,
342: skip);
343:
344: if (!--nlines && (++j != repits)) {
345: fseek(ifp, filePos, 0);
346: nlines = slines;
347: }
348: }
349: else {
350: if (len <= 0)
351: fprintf(ofp,
352: "\t%s, %d, %s, %s, %d, %d, %d,",
353: token[0],
354: -len,
355: ((len && NULL != token[2]) ?
356: token[2] : token[0]),
357: nc(token[3], "NULL"),
358: locTab[i].row,
359: locTab[i].col,
360: skip);
361: else
362: fprintf(ofp,
363: "\t%s, %d, \"%s\", %s, %d, %d, %d,",
364: token[0],
365: len,
366: nc(token[2], ""),
367: nc(token[3], "NULL"),
368: locTab[i].row,
369: locTab[i].col,
370: skip);
371: }
372: if (helpMsg[0])
373: fprintf(ofp, "\n\t\"%s\",\n", helpMsg);
374: else
375: fprintf(ofp, " NULL,\n");
376: }
377: fprintf(ofp, "\tNULL\n};\n");
378: }
379:
380: /*
381: * Process args and call phases.
382: */
383: main(argc, argv)
384: char **argv;
385: {
386: register char *arg;
387:
388: while (NULL != (arg = *++argv)) {
389: if ('-' == *arg) {
390: switch (*++arg) {
391: case 'f':
392: fieldDesig = *++arg;
393: break;
394: default:
395: Usage();
396: }
397: continue;
398: }
399: fileName = arg;
400: }
401: if (NULL == fileName)
402: Usage();
403:
404: ifp = xopen(fileName, "r");
405: if (NULL != (arg = strrchr(fileName, '/')))
406: fileName = arg + 1;
407: if (NULL != (arg = strrchr(fileName, '.')))
408: *arg = '\0';
409: outFile = alloc(strlen(fileName) + 3);
410: sprintf(outFile, "%s.c", fileName);
411: ofp = xopen(outFile, "w");
412: sprintf(outFile, "%s.h", fileName);
413: hfp = xopen(outFile, "w");
414: fprintf(hfp, "/*\n");
415: fprintf(hfp, " * This file generated by scn from %s\n", fileName);
416: fprintf(hfp, " */\n");
417: fprintf(hfp, "#include <scn.h>\n\n");
418: fprintf(hfp, "extern loc %s_locs[];\n", fileName);
419: fprintf(hfp, "extern backGrnd %s_data[];\n", fileName);
420: pass1();
421: pass2();
422: pass3();
423: exit(0);
424: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.