This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.bin / m4 / serv.c
CommitLineData
0bdacbe1
AM
1/* File : serv.c
2 Author : Ozan Yigit
3 Updated: 4 May 1992
4 Defines: Principal built-in macros for PD M4.
5*/
15637ed4 6
15637ed4 7#include "mdef.h"
0bdacbe1
AM
8#include "extr.h"
9#include "ourlims.h"
10
11#define ucArgv(n) ((unsigned char *)argv[n])
12
13/* 26-Mar-1993 Made m4trim() 8-bit clean.
14*/
15
16/* expand(<DS FN A1 ... An>)
17 0 1 2 n+1 -- initial indices in argv[]
18 -1 0 1 n -- after adjusting argv++, argc--
19 This expands a user-defined macro; FN is the name of the macro, DS
20 is its definition string, and A1 ... An are its arguments.
21*/
22void expand(argv, argc)
23 char **argv;
24 int argc;
25 {
26 register char *t;
27 register char *p;
28 register int n;
29
30#ifdef DEBUG
31 fprintf(stderr, "expand(%s,%d)\n", argv[1], argc);
32#endif
33 argc--; /* discount definition string (-1th arg) */
34 t = *argv++; /* definition string as a whole */
35 for (p = t; *p++; ) ;
36 p -= 2; /* points to last character of definition */
37 while (p > t) { /* if definition is empty, fails at once */
38 if (*--p != ARGFLAG) {
39 putback(p[1]);
40 } else {
41 switch (p[1]) {
42 case '#':
43 pbnum(argc-1);
44 break;
45 case '0': case '1': case '2': case '3': case '4':
46 case '5': case '6': case '7': case '8': case '9':
47 if ((n = p[1]-'0') < argc) pbstr(argv[n]);
48 break;
49 case '*': /* push all arguments back */
50 for (n = argc-1; n > 1; n--) {
51 pbstr(argv[n]);
52 putback(',');
53 }
54 pbstr(argv[1]);
55 break;
56 case '@': /* push arguments back quoted */
57 for (n = argc-1; n > 1; n--) {
58 pbqtd(argv[n]);
59 putback(',');
60 }
61 pbqtd(argv[1]);
62 break;
63 case '$': /* $$ => $ */
64 break;
65 default:
66 putback(p[1]);
67 putback(p[0]);
68 break;
69 }
70 p--;
71 }
72 }
73 if (p == t) putback(*p); /* do last character */
74 }
75
76
77static char nuldefmsg[] = "m4: defining null name.";
78static char recdefmsg[] = "m4: macro defined as itself.";
79
80/* dodefine(Name, Definition)
81 install Definition as the only definition of Name in the hash table.
15637ed4 82 */
0bdacbe1
AM
83void dodefine(name, defn)
84 register char *name;
85 register char *defn;
86 {
87 register ndptr p;
88
89 if (!name || !*name) error(nuldefmsg);
90 if (strcmp(name, defn) == 0) error(recdefmsg);
91#ifdef DEBUG
92 fprintf(stderr, "define(%s,--)\n", name);
93#endif
94 if ((p = lookup(name)) == nil) {
95 p = addent(name);
96 } else
97 if (p->defn != null) { /* what if p->type & STATIC ? */
98 free(p->defn);
99 }
100 p->defn = !defn || !*defn ? null : strsave(defn);
101 p->type = MACRTYPE;
102 }
103
104
105/* dopushdef(Name, Definition)
106 install Definition as the *first* definition of Name in the hash table,
107 but do not remove any existing definitions. The new definition will
108 hide any old ones until a popdef() removes it.
109*/
110void dopushdef(name, defn)
111 register char *name;
112 register char *defn;
113 {
114 register ndptr p;
115
116 if (!name || !*name) error(nuldefmsg);
117 if (strcmp(name, defn) == 0) error(recdefmsg);
118#ifdef DEBUG
119 fprintf(stderr, "pushdef(%s,--)\n", name);
120#endif
121 p = addent(name);
122 p->defn = !defn || !*defn ? null : strsave(defn);
123 p->type = MACRTYPE;
124 }
125
126
127/* dodefn(Name)
128 push back a *quoted* copy of Name's definition.
129*/
130void dodefn(name)
131 char *name;
132 {
133 register ndptr p;
134
135 if ((p = lookup(name)) != nil && p->defn != null) pbqtd(p->defn);
136 }
137
138
139/* dodump(<? dump>) dump all definition in the hash table
140 dodump(<? dump F1 ... Fn>) dump the definitions of F1 ... Fn in that order
141 The requested definitions are written to stderr. What happens to names
142 which have a built-in (numeric) definition?
143*/
144void dodump(argv, argc)
145 register char **argv;
146 register int argc;
147 {
148 register int n;
149 ndptr p;
150 static char dumpfmt[] = "define(`%s',\t`%s')\n";
151
152 if (argc > 2) {
153 for (n = 2; n < argc; n++)
154 if ((p = lookup(argv[n])) != nil)
155 fprintf(stderr, dumpfmt, p->name, p->defn);
156 } else {
157 for (n = 0; n < HASHSIZE; n++)
158 for (p = hashtab[n]; p != nil; p = p->nxtptr)
159 fprintf(stderr, dumpfmt, p->name, p->defn);
160 }
161 }
162
163
164/* doifelse(<? ifelse {x y ifx=y}... [else]>)
165 0 1 2 3 4 [2 when we get to it]
166*/
167void doifelse(argv, argc)
168 register char **argv;
169 register int argc;
170 {
171 for (; argc >= 5; argv += 3, argc -= 3)
172 if (strcmp(argv[2], argv[3]) == 0) {
173 pbstr(argv[4]);
174 return;
175 }
176 if (argc >= 3) pbstr(argv[2]);
177 }
178
179
180/* doinclude(FileName)
181 include a given file.
182*/
183int doincl(FileName)
184 char *FileName;
185 {
186 if (ilevel+1 == MAXINP) error("m4: too many include files.");
187#ifdef DEBUG
188 fprintf(stderr, "include(%s)\n", FileName);
189#endif
190 if ((infile[ilevel+1] = fopen(FileName, "r")) != NULL) {
191#ifndef NO__FILE
192 dopushdef("__FILE__", FileName);
193#endif
194 bbstack[ilevel+1] = bb;
195 bb = bp;
196 ilevel++;
197 return 1;
198 } else {
199 return 0;
200 }
201 }
202
203
15637ed4 204#ifdef EXTENDED
0bdacbe1
AM
205/* dopaste(FileName)
206 copy a given file to the output stream without any macro processing.
207*/
208int dopaste(FileName)
209 char *FileName;
210 {
211 register FILE *pf;
212 register FILE *afil = active;
213 register int c;
214
215 if ((pf = fopen(FileName, "r")) != NULL) {
216 while ((c = getc(pf)) != EOF) putc(c, afil);
217 (void) fclose(pf);
218 return 1;
219 } else {
220 return 0;
221 }
222 }
15637ed4 223#endif
0bdacbe1
AM
224
225
226/* dochq(<? changequote [left [right [verbatim]]]>)
227 0 1 2 3 4
228 change the quote characters; to single characters only.
229 Empty arguments result in no change for that parameter.
230 Missing arguments result in defaults:
231 changequote => ` ' ^V
232 changequote(q) => q q ^V
233 changequote(l,r) => l r ^V
234 changequote(l,r,v) => l r v
235 There isn't any way of switching the verbatim-quote off,
236 but if you make it the same as the right quote it won't
237 be able to do anything (we check for R, L, V in that order).
238*/
239void dochq(argv, argc)
240 register char **argv;
241 register int argc;
242 {
243 if (argc > 2) {
244 if (*argv[2]) lquote = *argv[2];
245 if (argc > 3) {
246 if (*argv[3]) rquote = *argv[3];
247 if (argc > 4 && *argv[4]) vquote = *argv[4];
248 } else {
249 rquote = lquote;
250 }
251 } else {
252 lquote = LQUOTE;
253 rquote = RQUOTE;
254 vquote = VQUOTE;
255 }
256 }
257
258
259/* dochc(<? changecomment [left [right]]>)
260 0 1 2 3
261 change the comment delimiters; to single characters only.
262*/
263void dochc(argv, argc)
264 register char **argv;
265 register int argc;
266 {
267 if (argc > 2) {
268 if (*argv[2]) scommt = *argv[2];
269 if (argc > 3) {
270 if (*argv[3]) ecommt = *argv[3];
271 } else {
272 ecommt = ECOMMT;
273 }
274 } else {
63464f7b
JH
275 scommt = '\0'; /* assuming no nulls in input */
276 ecommt = '\0';
0bdacbe1
AM
277 }
278 }
279
280
281/* dodivert - divert the output to a temporary file
282*/
283void dodiv(n)
284 register int n;
285 {
286 if (n < 0 || n >= MAXOUT) n = 0; /* bitbucket */
287 if (outfile[n] == NULL) {
288 m4temp[UNIQUE] = '0' + n;
289 if ((outfile[n] = fopen(m4temp, "w")) == NULL)
290 error("m4: cannot divert.");
291 }
292 oindex = n;
293 active = outfile[n];
294 }
295
296
297/* doundivert - undivert a specified output, or all
15637ed4 298 * other outputs, in numerical order.
0bdacbe1
AM
299*/
300void doundiv(argv, argc)
301 register char **argv;
302 register int argc;
303 {
304 register int ind;
305 register int n;
306
307 if (argc > 2) {
308 for (ind = 2; ind < argc; ind++) {
309 n = expr(argv[ind]);
310 if (n > 0 && n < MAXOUT && outfile[n] != NULL) getdiv(n);
311 }
312 } else {
313 for (n = 1; n < MAXOUT; n++)
314 if (outfile[n] != NULL) getdiv(n);
315 }
316 }
317
318
319/* dosub(<? substr {offset} [{length}]>)
320 The System V Interface Definition does not say what happens when the
321 offset or length are out of range. I have chosen to force them into
322 range, with the result that unlike the former version of this code,
323 dosub cannot be tricked into SIGSEGV.
324
325 BUG: This is not 8-bit clean yet.
326*/
327void dosub(argv, argc)
328 char **argv;
329 int argc;
330 {
331 register int nc; /* number of characters */
332 register char *ap = argv[2]; /* target string */
333 register int al = strlen(ap); /* its length */
334 register int df = expr(argv[3]);/* offset */
335
336 if (df < 0) df = 0; else /* force df back into the range */
337 if (df > al) df = al; /* 0 <= df <= al */
338 al -= df; /* now al limits nc */
339
340 if (argc >= 5) { /* nc is provided */
341 nc = expr(argv[4]);
342 if (nc < 0) nc = 0; else /* force nc back into the range */
343 if (nc > al) nc = al; /* 0 <= nc <= strlen(ap)-df */
344 } else {
345 nc = al; /* default is all rest of ap */
346 }
347 ap += df + nc;
348 while (--nc >= 0) putback(*--ap);
349 }
350
351
352/* map(dest, src, from, to)
353 map every character of src that is specified in from
354 into "to" and replace in dest. (source "src" remains untouched)
355
356 This is a standard implementation of Icon's map(s,from,to) function.
357 Within mapvec, we replace every character of "from" with the
358 corresponding character in "to". If "to" is shorter than "from",
359 then the corresponding entries are null, which means that those
360 characters disappear altogether. Furthermore, imagine a call like
361 map(dest, "sourcestring", "srtin", "rn..*"). In this case, `s' maps
362 to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s' ultimately
363 maps to `*'. In order to achieve this effect in an efficient manner
364 (i.e. without multiple passes over the destination string), we loop
365 over mapvec, starting with the initial source character. If the
366 character value (dch) in this location is different from the source
367 character (sch), sch becomes dch, once again to index into mapvec,
368 until the character value stabilizes (i.e. sch = dch, in other words
369 mapvec[n] == n). Even if the entry in the mapvec is null for an
370 ordinary character, it will stabilize, since mapvec[0] == 0 at all
371 times. At the end, we restore mapvec* back to normal where
372 mapvec[n] == n for 0 <= n <= 127. This strategy, along with the
373 restoration of mapvec, is about 5 times faster than any algorithm
374 that makes multiple passes over the destination string.
375*/
376
377void map(d, s, f, t)
378 char *d, *s, *f, *t;
379 {
380 register unsigned char *dest = (unsigned char *)d;
381 register unsigned char *src = (unsigned char *)s;
382 unsigned char *from = (unsigned char *)f;
383 register unsigned char *to = (unsigned char *)t;
384 register unsigned char *tmp;
385 register unsigned char sch, dch;
386 static unsigned char mapvec[1+UCHAR_MAX] = {1};
387
388 if (mapvec[0]) {
389 register int i;
390 for (i = 0; i <= UCHAR_MAX; i++) mapvec[i] = i;
391 }
392 if (src && *src) {
393 /* create a mapping between "from" and "to" */
394 if (to && *to)
395 for (tmp = from; sch = *tmp++; ) mapvec[sch] = *to++;
396 else
397 for (tmp = from; sch = *tmp++; ) mapvec[sch] = '\0';
398
399 while (sch = *src++) {
400 while ((dch = mapvec[sch]) != sch) sch = dch;
401 if (*dest = dch) dest++;
402 }
403 /* restore all the changed characters */
404 for (tmp = from; sch = *tmp++; ) mapvec[sch] = sch;
405 }
406 *dest = '\0';
407 }
408
409
410#ifdef EXTENDED
411
412/* m4trim(<? m4trim [string [leading [trailing [middle [rep]]]]]>)
413 0 1 2 3 4 5 6
414
415 (1) Any prefix consisting of characters in the "leading" set is removed.
416 The default is " \t\n".
417 (2) Any suffix consisting of characters in the "trailing" set is removed.
418 The default is to be the same as leading.
419 (3) Any block of consecutive characters in the "middle" set is replaced
420 by the rep string. The default for middle is " \t\n", and the
421 default for rep is the first character of middle.
422*/
423void m4trim(argv, argc)
424 char **argv;
425 int argc;
426 {
427 static unsigned char repbuf[2] = " ";
428 static unsigned char layout[] = " \t\n\r\f";
429 unsigned char *string = argc > 2 ? ucArgv(2) : repbuf+1;
430 unsigned char *leading = argc > 3 ? ucArgv(3) : layout;
431 unsigned char *trailing = argc > 4 ? ucArgv(4) : leading;
432 unsigned char *middle = argc > 5 ? ucArgv(5) : trailing;
433 unsigned char *rep = argc > 6 ? ucArgv(6) :
434 (repbuf[0] = *middle, repbuf);
435 static unsigned char sets[1+UCHAR_MAX];
436# define PREF 1
437# define SUFF 2
438# define MIDL 4
439 register int i, n;
440
441 for (i = UCHAR_MAX; i >= 0; ) sets[i--] = 0;
442 while (*leading) sets[*leading++] |= PREF;
443 while (*trailing) sets[*trailing++] |= SUFF;
444 while (*middle) sets[*middle++] |= MIDL;
445
446 while (*string && sets[*string]&PREF) string++;
447 n = strlen((char *)string);
448 while (n > 0 && sets[string[n-1]]&SUFF) n--;
449 while (n > 0) {
450 i = string[--n];
451 if (sets[i]&MIDL) {
452 pbstr((char*)rep);
453 while (n > 0 && sets[string[n-1]]&MIDL) n--;
454 } else {
455 putback(i);
456 }
457 }
458 }
459
460
461/* defquote(MacroName # The name of the "quoter" macro to be defined.
462 [, Opener # default: "'". The characters to place at the
463 # beginning of the result.
464 [, Separator # default: ",". The characters to place between
465 # successive arguments.
466 [, Closer # default: same as Opener. The characters to
467 # place at the end of the result.
468 [, Escape # default: `' The escape character to put in
469 # front of things that need escaping.
470 [, Default # default: simple. Possible values are
471 # [lL].* = letter, corresponds to PLAIN1.
472 # [dD].* = digit, corresponds to PLAIN2.
473 # [sS].* = simple, corresponds to SIMPLE.
474 # [eE].* = escaped,corresponds to SCAPED.
475 # .*, corresponds to FANCY
476 [, Letters # default: `'. The characters of type "L".
477 [, Digits # default: `'. The characters of type "D".
478 [, Simple # default: `'. The characters of type "S".
479 [, Escaped # default: `'. The characters of type "E".
480 {, Fancy # default: none. Each has the form `C'`Repr'
481 # saying that the character C is to be represented
482 # as Repr. Can be used for trigraphs, \n, &c.
483 }]]]]]]]]])
484
485 Examples:
486 defquote(DOUBLEQT, ")
487 defquote(SINGLEQT, ')
488 After these definitions,
489 DOUBLEQT(a, " b", c) => "a,"" b"",c"
490 SINGLEQT("Don't`, 'he said.") => '"Don''t, he said."'
491 Other examples defining quote styles for several languages will be
492 provided later.
493
494 A quoter is represented in M4 by a special identifying number and a
495 pointer to a Quoter record. I expect that there will be few quoters
496 but that they will need to go fairly fast.
497
498*/
499
500#define PLAIN1 0
501#define PLAIN2 1
502#define SIMPLE 2
503#define SCAPED 3
504#define FANCY 4
505
506struct Quoter
507 {
508 char *opener;
509 char *separator;
510 char *closer;
511 char *escape;
512 char *fancy[1+UCHAR_MAX];
513 char class[1+UCHAR_MAX];
514 };
515
516void freeQuoter(q)
517 struct Quoter *q;
518 {
519 int i;
520
521 free(q->opener);
522 free(q->separator);
523 free(q->closer);
524 free(q->escape);
525 for (i = UCHAR_MAX; i >= 0; i--)
526 if (q->fancy[i]) free(q->fancy[i]);
527 free((char *)q);
528 }
529
530/* dodefqt(<
531 0 ?
532 1 defquote
533 2 MacroName
534 [ 3 Opener
535 [ 4 Separator
536 [ 5 Closer
537 [ 6 Escape
538 [ 7 Default
539 [ 8 Letters
540 [ 9 Digits
541 [10 Simple
542 [11 Escaped
543 [11+i Fancy[i] ]]]]]]]]]]>)
544*/
545
546void dodefqt(argv, argc)
547 char **argv;
548 int argc;
549 {
550 struct Quoter q, *r;
551 register int i;
552 register unsigned char *s;
553 register int c;
554 ndptr p;
555
556 if (!(argc > 2 && *argv[2])) error(nuldefmsg);
557 switch (argc > 7 ? argv[7][0] : '\0') {
558 case 'l': case 'L': c = PLAIN1; break;
559 case 'd': case 'D': c = PLAIN2; break;
560 case 'e': case 'E': c = SCAPED; break;
561 case 'f': case 'F': c = FANCY; break;
562 default: c = SIMPLE;
563 }
564 for (i = UCHAR_MAX; --i >= 0; ) q.class[i] = c;
565 for (i = UCHAR_MAX; --i >= 0; ) q.fancy[i] = 0;
566 q.opener = strsave(argc > 3 ? argv[3] : "");
567 q.separator = strsave(argc > 4 ? argv[4] : ",");
568 q.closer = strsave(argc > 5 ? argv[5] : q.opener);
569 q.escape = strsave(argc > 6 ? argv[6] : "");
570 if (argc > 8)
571 for (s = (unsigned char *)argv[8]; c = *s++; )
572 q.class[c] = PLAIN1;
573 if (argc > 9)
574 for (s = (unsigned char *)argv[9]; c = *s++; )
575 q.class[c] = PLAIN2;
576 if (argc > 10)
577 for (s = (unsigned char *)argv[10]; c = *s++; )
578 q.class[c] = SIMPLE;
579 if (argc > 11)
580 for (s = (unsigned char *)argv[11]; c = *s++; )
581 q.class[c] = SCAPED;
582 for (i = 12; i < argc; i++) {
583 s = (unsigned char *)argv[i];
584 c = *s++;
585 q.fancy[c] = strsave((char *)s);
586 q.class[c] = FANCY;
587 }
588 /* Now we have to make sure that the closing quote works. */
589 if ((c = q.closer[0]) && q.class[c] <= SIMPLE) {
590 if (q.escape[0]) {
591 q.class[c] = SCAPED;
592 } else {
593 char buf[3];
594 buf[0] = c, buf[1] = c, buf[2] = '\0';
595 q.fancy[c] = strsave(buf);
596 q.class[c] = FANCY;
597 }
598 }
599 /* We also have to make sure that the escape (if any) works. */
600 if ((c = q.escape[0]) && q.class[c] <= SIMPLE) {
601 q.class[c] = SCAPED;
602 }
603 r = (struct Quoter *)malloc(sizeof *r);
604 if (r == NULL) error("m4: no more memory");
605 *r = q;
606 p = addent(argv[2]);
607 p->defn = (char *)r;
608 p->type = QUTRTYPE;
609 }
610
611
612/* doqutr(<DB MN A1 ... An>)
613 0 1 2 n+1 argc
614 argv[0] points to the struct Quoter.
615 argv[1] points to the name of this quoting macro
616 argv[2..argc-1] point to the arguments.
617 This applies a user-defined quoting macro. For example, we could
618 define a macro to produce Prolog identifiers:
619 defquote(plid, ', , ', , simple,
620 abcdefghijklmnopqrstuvwxyz,
621 ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789)
622
623 After doing that,
624 plid(foo) => foo
625 plid(*) => '*'
626 plid(Don't) => 'Don''t'
627 plid(foo,) => 'foo'
628*/
629void doqutr(argv, argc)
630 char **argv;
631 int argc;
632 /* DEFINITION-BLOCK MacroName Arg1 ... Argn
633 0 1 2 n-1 argc
634 */
635 {
636 struct Quoter *r = (struct Quoter *)argv[0];
637 char *p;
638 register unsigned char *b, *e;
639 int i;
640 register int c;
641
642 for (;;) { /* does not actually loop */
643 if (argc != 3) break;
644 b = ucArgv(2);
645 e = b + strlen((char*)b);
646 if (e == b) break;
647 if (r->class[*b++] != PLAIN1) break;
648 while (b != e && r->class[*b] <= PLAIN2) b++;
649 if (b != e) break;
650 pbstr(argv[2]);
651 return;
652 }
653
654 p = r->closer;
655 if (argc < 3) {
656 pbstr(p);
657 } else
658 for (i = argc-1; i >= 2; i--) {
659 pbstr(p);
660 b = ucArgv(i);
661 e = b+strlen((char *)b);
662 while (e != b)
663 switch (r->class[c = *--e]) {
664 case FANCY:
665 p = r->fancy[c];
666 if (p) {
667 pbstr(p);
668 } else {
669 pbrad(c, 8, 1);
670 pbstr(r->escape);
671 }
672 break;
673 case SCAPED:
674 putback(c);
675 pbstr(r->escape);
676 break;
677 default:
678 putback(c);
679 break;
680 }
681 p = r->separator;
682 }
683 pbstr(r->opener);
684 }
685
15637ed4 686#endif