1 /*
2 * Copyright (C) 1992,1993 NEC Corporation.
3 */
4 #ifndef lint
5 static char rcsid[] =
6 "$Id: macro.c,v 2.10 1994/04/19 10:16:48 uchida Exp $ (NEC)";
7 #endif
8
9 #include <stdio.h>
10 #include <ctype.h>
11 #include <stdarg.h>
12 #include "plain2.h"
13 #include "macro.h"
14
15 #define MACRO_SUFFIX ".p2"
16
17 struct macNames macNames[] = {
18 "DOC_BEGIN", M_DOC_BEGIN, "#$$",
19 "DOC_END", M_DOC_END, "",
20 "PLAIN_BEGIN", M_PLAIN_BEGIN, "",
21 "PLAIN_END", M_PLAIN_END, "",
22 "EXAM_BEGIN", M_EXAM_BEGIN, "#",
23 "EXAM_END", M_EXAM_END, "",
24 "JEXAM_BEGIN", M_JEXAM_BEGIN, "#",
25 "JEXAM_END", M_JEXAM_END, "",
26 "SET_SEC", M_SET_SEC, "#$",
27 "APPENDIX", M_APPENDIX, "$",
28 "APDX_BEGIN", M_APDX_BEGIN, "",
29 "BLANK", M_BLANK, "",
30 "PAGE", M_PAGE, "",
31 "NEWLINE", M_NEWLINE, "",
32 "CENTER_BEGIN", M_CENTER_BEGIN, "",
33 "CENTER_END", M_CENTER_END, "",
34 "RIGHT_BEGIN", M_RIGHT_BEGIN, "",
35 "RIGHT_END", M_RIGHT_END, "",
36 "INDENT", M_INDENT, "#",
37 "INDENT0", M_INDENT0, "",
38 "TITLE", M_TITLE, "&&&&&&&&&",
39 "FOOTN_BEGIN", M_FOOTN_BEGIN, "",
40 "FOOTN_END", M_FOOTN_END, "",
41 "REFER_BEGIN", M_REFER_BEGIN, "",
42 "REFER_END", M_REFER_END, "",
43 "BOLD_BEGIN", M_BOLD_BEGIN, "",
44 "BOLD_END", M_BOLD_END, "",
45 "INDEX_BEGIN", M_INDEX_BEGIN, "",
46 "INDEX_END", M_INDEX_END, "",
47 "SECTION_END", M_SECTION_END, "",
48 "SECTION_1", M_SECTION_1, "$",
49 "SECTION_2", M_SECTION_2, "$",
50 "SECTION_3", M_SECTION_3, "$",
51 "SECTION_4", M_SECTION_4, "$",
52 "SECTION_5", M_SECTION_5, "$",
53 "SECTION", M_SECTION, "#$",
54 "SETSEC_1", M_SETSEC_1, "#",
55 "SETSEC_2", M_SETSEC_2, "#",
56 "SETSEC_3", M_SETSEC_3, "#",
57 "SETSEC_4", M_SETSEC_4, "#",
58 "SETSEC_5", M_SETSEC_5, "#",
59 "SETSEC", M_SETSEC, "##",
60 };
61
62 struct cmpMac *outMacro[M_MAXNUM];
63
64 #define ATYPE_VOID 0
65 #define ATYPE_INT 1
66 #define ATYPE_STR 2
67 #define ATYPE_PSTR 3
68
69 static int
atype(c)70 atype(c)
71 char c;
72 {
73 if (c == '#')
74 return ATYPE_INT;
75 if (c == '$' || c == '@')
76 return ATYPE_STR;
77 if (c == '&')
78 return ATYPE_PSTR;
79 return ATYPE_VOID;
80 }
81
82 struct cmpMac *
macroParse(s,macroNum,orig)83 macroParse(s, macroNum, orig)
84 int macroNum;
85 char *s;
86 char *orig;
87 {
88 struct cmpMac *mip, *new_mip;
89 int def_type;
90 mip = (struct cmpMac *)malloc(sizeof(struct cmpMac));
91 if(mip == NULL){ /* Add Nide */
92 malloc_error:
93 fprintf(stderr, "PANIC(malloc in macroParse)\n");
94 exit (2);
95 }
96 mip->cmac_next = NULL;
97 mip->cmac_argnum = -1;
98 mip->cmac_str = s;
99 while (*s) {
100 if (isdigit(*(s+1)) && (def_type = atype(*s)) != ATYPE_VOID) {
101 new_mip=(struct cmpMac *)malloc(sizeof(struct cmpMac));
102 if(new_mip == NULL) goto malloc_error; /* Add Nide */
103 mip->cmac_next = new_mip;
104 new_mip->cmac_next = NULL;
105 new_mip->cmac_argtype = *s;
106 new_mip->cmac_argnum = *(s + 1) - '0';
107 if (new_mip->cmac_argnum >
108 strlen(macNames[macroNum].mname_argattr)) {
109 fprintf(stderr,"Argnum too big %d in \"%s %s\"\n",
110 new_mip->cmac_argnum,
111 macNames[macroNum].mname_name, orig);
112 exit(1);
113 }
114 else if (atype(macNames[macroNum].
115 mname_argattr[new_mip->cmac_argnum - 1])
116 != def_type) {
117 fprintf(stderr,"Improper argtype in \"%s %s\"\n",
118 macNames[macroNum].mname_name, orig);
119 exit(1);
120 }
121 *s = '\0';
122 if (*(s + 2) == '\0')
123 return mip;;
124 new_mip->cmac_next = macroParse(s + 2, macroNum, orig);
125 break;
126 }
127 s++;
128 }
129 return mip;
130 }
131 char *
getMacroNum(buf,macroNump)132 getMacroNum(buf, macroNump)
133 char *buf;
134 int *macroNump;
135 {
136 char *rval = NULL;
137 char *s = buf;
138 int i;
139 *macroNump = -1;
140 while (!isspace(*s))
141 s++;
142 if (*s != '\n')
143 rval = s + 1;
144 *s = '\0';
145 for (i = 0; i < sizeof(macNames)/sizeof(struct macNames); i++) {
146 if (strcmp(macNames[i].mname_name, buf) == 0) {
147 *macroNump = i;
148 return rval;
149 }
150 }
151 return rval;
152 }
getMacroDef(buf,rstr)153 getMacroDef(buf, rstr)
154 char *buf;
155 char *rstr;
156 {
157 int in_escape = 0;
158 rstr[0] = '\0';
159 while (1) {
160 if (!in_escape && *buf == '"') {
161 *rstr = '\0';
162 return 0;
163 }
164 if (in_escape) {
165 in_escape = 0;
166 switch(*buf) {
167 case '\n':
168 *rstr++ = '\0';
169 return -2;
170 case 'n':
171 *rstr++ = '\n';
172 break;
173 case 't':
174 *rstr++ = '\t';
175 break;
176 default:
177 *rstr++ = *buf;
178 break;
179 }
180 }
181 else if (*buf == '\n')
182 return 1;
183 else if (*buf == '\\')
184 in_escape = 1;
185 else {
186 in_escape = 0;
187 *rstr++ = *buf;
188 }
189 buf++;
190 }
191 }
putMacro(int macroNum,char * fmt,...)192 putMacro(int macroNum, char *fmt, ...)
193 {
194 va_list ap;
195 union macroArg {
196 int ma_num;
197 char *ma_str;
198 char **ma_pstr;
199 } margs[MACRO_MAXARG];
200 int argtype[MACRO_MAXARG];
201 struct cmpMac *mip = outMacro[macroNum];
202 int i, maxarg = 0;
203
204 for (i = 1; i < MACRO_MAXARG; i++)
205 argtype[i] = ATYPE_VOID;
206 if (mip == NULL)
207 return -1;
208 while(mip) {
209 if (mip->cmac_argnum > 0) {
210 if (maxarg < mip->cmac_argnum)
211 maxarg = mip->cmac_argnum;
212 switch(mip->cmac_argtype) {
213 case '#':
214 argtype[mip->cmac_argnum] = ATYPE_INT;
215 break;
216 case '$':
217 case '@':
218 argtype[mip->cmac_argnum] = ATYPE_STR;
219 break;
220 case '&':
221 argtype[mip->cmac_argnum] = ATYPE_PSTR;
222 break;
223 }
224 }
225 mip = mip->cmac_next;
226 }
227 va_start(ap, fmt);
228 for (i = 1; i <= maxarg; i++) {
229 switch(argtype[i]) {
230 case ATYPE_VOID:
231 va_arg(ap, char *);
232 break;
233 case ATYPE_INT:
234 margs[i].ma_num = (int)va_arg(ap, int *);
235 break;
236 case ATYPE_STR:
237 margs[i].ma_str = va_arg(ap, char *);
238 break;
239 case ATYPE_PSTR:
240 margs[i].ma_pstr = (char **)va_arg(ap, char **);
241 break;
242 }
243 }
244 mip = outMacro[macroNum];
245 while(mip) {
246 if (mip->cmac_argnum > 0) {
247 switch(mip->cmac_argtype) {
248 case '#':
249 printf ("%d", margs[mip->cmac_argnum].ma_num);
250 break;
251 case '$':
252 printf ("%s", codeCvt((*put->quote1)(margs[mip->cmac_argnum].ma_str)));
253 break;
254 case '@':
255 printf ("%s", codeCvt((*put->quote2)(margs[mip->cmac_argnum].ma_str)));
256 break;
257 case '&':
258 {
259 char **argp;
260 argp = margs[mip->cmac_argnum].ma_pstr;
261 while (*argp) {
262 printf("%s", codeCvt((*put->quote1)(*argp)));
263 if (*++argp) {
264 if (put == &texPut) {
265 printf("~\\\\");
266 }
267 putchar('\n');
268 }
269 }
270 break;
271 }
272 }
273 }
274 else
275 printf ("%s", codeCvt(mip->cmac_str));
276 mip = mip->cmac_next;
277 }
278 va_end(ap);
279 return 0;
280 }
clearMacro()281 clearMacro()
282 {
283 int i;
284 for (i = 0; i < M_MAXNUM; i++)
285 outMacro[i] = NULL;
286 }
287 initMacroDefs(mcp)
288 struct macDefs *mcp;
289 {
290 while(mcp->mdef_number >= 0) {
291 if (outMacro[mcp->mdef_number] == NULL)
292 outMacro[mcp->mdef_number] =
293 macroParse(mcp->mdef_def, mcp->mdef_number,
294 mcp->mdef_def);
295 mcp++;
296 }
297 }
298
299 FILE *
macroFopen(fname)300 macroFopen(fname)
301 char *fname;
302 {
303 FILE *fd;
304 char buf[1024];
305 if ((fd = fopen(fname, "r")) != NULL)
306 return fd;
307 strcpy(buf, fname);
308 strcat(buf, MACRO_SUFFIX);
309 return fopen(buf, "r");
310 }
311
macroFile(fname)312 macroFile(fname)
313 char *fname;
314 {
315 char defstr[1024];
316 char buf[1024];
317 char path[1024];
318 FILE *fd;
319 int macroNum;
320 char *s;
321 fd = macroFopen(fname);
322 if (fd == NULL && plain2Lib != NULL && fname[0] != '/') {
323 char *colon;
324 fd = NULL;
325
326 colon = index(plain2Lib, ':');
327 while (colon && colon != NULL) {
328 *colon = '\0';
329 sprintf(path, "%s/%s", plain2Lib, fname);
330 if ((fd = macroFopen(path)) != NULL)
331 break;
332 plain2Lib = colon+1;
333 colon = index(plain2Lib, ':');
334 }
335 if (fd == NULL && *plain2Lib != '\0') {
336 sprintf(path, "%s/%s", plain2Lib, fname);
337 fd = macroFopen(path);
338 }
339 }
340 if (fd == NULL) {
341 #ifdef MACRO_LIB
342 sprintf(path, "%s/%s", MACRO_LIB, fname);
343 if ((fd = macroFopen(path)) == NULL) {
344 fprintf(stderr, "Can't open %s\n", fname);
345 exit(1);
346 }
347 #else
348 fprintf(stderr, "Can't open %s\n", fname);
349 exit(1);
350 #endif
351 }
352 while(fgets(buf, sizeof(buf), fd) != NULL) {
353 char *macro_body;
354 int ret;
355 if (buf[0] == '#')
356 continue;
357 macro_body = getMacroNum(buf, ¯oNum);
358 if (macroNum < 0 || macro_body == NULL)
359 continue;
360 while (isspace(*macro_body))
361 macro_body++;
362 if (*macro_body != '"') {
363 fprintf(stderr,"Macro body must start with \" in \"%s\"\n",
364 macNames[macroNum].mname_name);
365 fclose(fd);
366 exit(1);
367 }
368 macro_body++;
369 ret = getMacroDef(macro_body, defstr);
370 while(ret == -2) {
371 for (s = defstr; *s; s++);
372 if (fgets(buf, sizeof(buf), fd) == NULL)
373 break;
374 ret = getMacroDef(buf, s);
375 }
376 if (ret == -1)
377 continue;
378 s = strsave(defstr); /* Changed Nide (but don't we need free?)*/
379 outMacro[macroNum] = macroParse(s, macroNum, s);
380 }
381 fclose(fd);
382 return 0;
383 }
384