1 %{
2 /*
3  * Turns format specifications into internal list representation.
4 
5  * Formats are lists of items:
6  * format := [count] item | [count] '(' format ')' | format format
7 
8  * where an item is:
9  * item := [count]	insize	outform	[ '>' c ] ...
10  *	 | [count]	insize	[ '>' c ]
11  *	 | [count]	outform	[ '>' c ]
12  *	 | [count]	'['	copyout_string	']'
13  *	 | [count]	!0|!1|!2 or seek0|seek1|seek2 (seeks)
14  *	 | [count]	`n' or `;'		(adds newline)
15  *	 | $c	({+-/*=} number)+		(does math on registers)
16  *	 | $c P					(prints register in %ld fmt)
17 
18  * and a count is:
19  * count := positive decimal number | $c | $$
20  * Here, c is any non-null, non-'$' character; it names a register
21 
22 
23  * insize := C | S | I | L | F | D | Z
24  *           |   |   |   |   |   |   zero-terminated string
25  *           |   |   |   |   |   double
26  *           |   |   |   |   float
27  *           |   |   |   long
28  *           |   |   int
29  *           |   short
30  *           char
31  *	-or-
32  *           char short int integer long float real double string
33 
34  * outform := a | b | c | d | u | o | h | f | g | ~ | "(printf fmt string)"
35  *            |   |   |   |   |   |   |   |   |   ignore (no output)
36  *            |   |   |   |   |   |   |   |   float
37  *            |   |   |   |   |   |   |   float
38  *            |   |   |   |   |   |   hex (unsigned)
39  *            |   |   |   |   |   octal (unsigned)
40  *            |   |   |   |   unsigned decimal
41  *            |   |   |   signed decimal
42  *            |   |   octal for non-printing characters; ascii for printing
43  *            |   binary (unsigned)
44  *            ascii characters
45 
46  * default pairings: C->a, S->o, I->d, L->d, [FD]->g, Z->a
47  *                   a->C, b->C, c->C, [duohx]->I, g->F
48 
49  * illegal pairings: [CSILZ]-fg, [FD]-[abcduohx], [SILFD]-ac
50 
51 
52  * Filters the named files; if there are no files, stdin is used.
53 
54  * Ascii formatting:
55  * null -> \@
56  * percent -> \%
57  * backspace -> \b
58  * formfeed -> \f
59  * newline -> \n
60  * return -> \r
61  * tab -> \t
62  * backslash -> \\
63  * all other printing characters (octal 040 - 177): unchanged
64  * all others -> \nnn
65  * In addition, after transforming newline to \n, a true newline is printed.
66 
67  */
68 
69 
70 #include <stdio.h>
71 #include <ctype.h>
72 #include "string.h"
73 #include <errno.h>
74 #include <stdlib.h>
75 
76 #include "viz.h"
77 
78 extern int do_condense;
79 
80 static mathreg = 0;	/* For handling multiple-term math expressions */
81 
82 %}
83 
84 %token <ival> INCHAR OUTCHAR REG STORE LEXERROR NEWLINE EOF_COUNT SEEK
85 
86 %token <lval> NUMBER
87 
88 %token <sval> COPYOUT PCTSTRING
89 
90 %token <ival> MATHOP U_MATHOP
91 
92 %type <lval> count		/* repetition count */
93 
94 %type <item> copyout		/* An item with the copyout field filled */
95 
96 %type <item> seek		/* Seek on input stream */
97 
98 %type <item> math		/* Math operation on a register */
99 
100 %type <item> iocore		/* An ioformat with the core of the iospec
101 				 * filled: size + ichar + ochar are filled,
102 				 * but fmt ptr & reg_no not filled in.
103 				 */
104 
105 %type <item> iosingle		/* iocore + reg_no info */
106 
107 %type <memp> iounion		/* iosingle | copyout | NEWLINE | math | SEEK;
108 				 * type field filled, but not count field. */
109 
110 %type <memp> iogroup		/* [count] iounion */
111 
112 %type <memp> list member	/* pointers to list and member of list */
113 
114 %type <memp> lexerr		/* For handling lex-found errors */
115 
116 %%
117 
118 list	: member
119 		{
120 		    if (debug)
121 			(void) fprintf(stderr, "list = member; making newlist");
122 		    rootlist = $$ = newlist($1);
123 		    if (debug) {
124 			(void) fprintf(stderr, " ...list is now:\n");
125 			printlist(0, $$);
126 		    }
127 		}
128 	| list member
129 		{
130 		    if (debug)
131 			(void) fprintf(stderr, "list = list member");
132 		    rootlist = $$ = addmember( $1, $2 );
133 		    if (debug) {
134 			(void) fprintf(stderr, " ...list is now:\n");
135 			printlist(0, $$);
136 		    }
137 		}
138 	| lexerr
139 	;
140 
141 member	: iogroup
142 		{
143 		    if (debug)
144 			(void) fprintf(stderr, "member: iogroup\n");
145 		    $$ = $1;
146 		    if ($$ == NIL) {
147 			(void) fprintf(stderr, "%s: malloc failed\n", prog);
148 			YYERROR;
149 		    }
150 		}
151 
152 	| '(' list ')'
153 		{
154 		    if (debug)
155 			(void) fprintf(stderr, "member: ( list )\n");
156 		    $$ = $2;
157 		    $$->count = 1;
158 		}
159 	| count '(' list ')'
160 		{
161 		    if (debug)
162 			(void) fprintf(stderr, "member: %d ( list )\n", $1);
163 		    $3->count = $1 ;
164 		    $$ = $3;
165 		}
166 	;
167 
168 iogroup	: iounion
169 		{
170 		    $$ = $1;
171 		    $$->count = 1;
172 		    $$->next = NIL;
173 		    Fmt.item = Fmt.p;
174 		}
175 	| count iounion
176 		{
177 		    $$ = $2;
178 		    $$->count = $1;
179 		    $$->next = NIL;
180 		    Fmt.item = Fmt.p;
181 		}
182 	;
183 
184 iounion	: iosingle
185 		{
186 		    $$ = (MEMBER *) malloc(sizeof(MEMBER));
187 		    if ($$ == (MEMP) NULL) {
188 			(void) fprintf(stderr, "%s: malloc failed.\n", prog);
189 			YYERROR;
190 		    }
191 		    $$->type = T_IOSPEC;
192 		    $$->u = $1;
193 		    mathreg = 0;
194 		}
195 	| seek
196 		{
197 		    $$ = (MEMBER *) malloc(sizeof(MEMBER));
198 		    if ($$ == (MEMP) NULL) {
199 			(void) fprintf(stderr, "%s: malloc failed.\n", prog);
200 			YYERROR;
201 		    }
202 		    $$->type = T_SEEK;
203 		    $$->u = $1;
204 		}
205 	| copyout
206 		{
207 		    $$ = (MEMBER *) malloc(sizeof(MEMBER));
208 		    if ($$ == (MEMP) NULL) {
209 			(void) fprintf(stderr, "%s: malloc failed.\n", prog);
210 			YYERROR;
211 		    }
212 		    $$->type = T_COPYOUT;
213 		    $$->u = $1;
214 		    mathreg = 0;
215 		}
216 	| NEWLINE
217 		{
218 		    $$ = (MEMBER *) malloc(sizeof(MEMBER));
219 		    if ($$ == (MEMP) NULL) {
220 			(void) fprintf(stderr, "%s: malloc failed.\n", prog);
221 			YYERROR;
222 		    }
223 		    $$->type = T_NEWLINE;
224 		    mathreg = 0;
225 		}
226 	| math
227 		{
228 		    $$ = (MEMBER *) malloc(sizeof(MEMBER));
229 		    if ($$ == (MEMP) NULL) {
230 			(void) fprintf(stderr, "%s: malloc failed.\n", prog);
231 			YYERROR;
232 		    }
233 		    $$->type = T_MATH;
234 		    $$->u = $1;
235 		}
236 	;
237 
238 copyout	: COPYOUT
239 		{
240 		    $$.copyout = malloc((unsigned) (strlen($1) + 1));
241 		    if ($$.copyout == NULL) {
242 			(void) fprintf(stderr, "%s: malloc failed.\n", prog);
243 			YYERROR;
244 		    }
245 		    (void) strcpy($$.copyout, $1);
246 		}
247 	;
248 
249 seek	: count SEEK count
250 		{
251 		    $$.seek.count = $1;
252 		    $$.seek.direction = $3;
253 		}
254 	| MATHOP count SEEK count
255 		{
256 		    if ($1 != '-' && $1 != '+') {
257 			(void) fprintf(stderr,
258 			    "%s: invalid seek offset: %c%d\n",
259 				prog, $1, $2);
260 			YYERROR;
261 		    } else if ($1 == '-') {
262 			$$.seek.count = -$2;
263 		    } else {
264 			$$.seek.count = $2;
265 		    }
266 		    $$.seek.direction = $4;
267 		}
268 	;
269 
270 
271 math : REG MATHOP count
272 		{
273 		    $$.math.reg_no = mathreg = $1;
274 		    $$.math.operator = $2;
275 		    $$.math.operand = $3;
276 		}
277 	| MATHOP count
278 		{
279 		    if (mathreg == 0) {
280 			(void) fprintf(stderr,
281 			    "%s: Math operator outside math expression\n",
282 			    prog);
283 			YYERROR;
284 		    }
285 		    $$.math.reg_no = mathreg;
286 		    $$.math.operator = $1;
287 		    $$.math.operand = $2;
288 		}
289 	| REG U_MATHOP
290 		{
291 		    $$.math.reg_no = mathreg = $1;
292 		    $$.math.operator = $2;
293 		    $$.math.operand = 0;
294 		}
295 	| U_MATHOP
296 		{
297 		    if (mathreg == 0) {
298 			(void) fprintf(stderr,
299 			    "%s: Register print operator w/o register\n",
300 			    prog);
301 			YYERROR;
302 		    }
303 		    $$.math.reg_no = mathreg;
304 		    $$.math.operator = $1;
305 		    $$.math.operand = 0;
306 		}
307 	| REG MATHOP INCHAR
308 		{
309 		    $$.math.reg_no = mathreg = $1;
310 		    $$.math.operator = $2;
311 		    switch ($3) {
312 		    case 'C':
313 			$$.math.operand = sizeof(char);
314 			break;
315 		    case 'S':
316 			$$.math.operand = sizeof(short);
317 			break;
318 		    case 'I':
319 			$$.math.operand = sizeof(int);
320 			break;
321 		    case 'L':
322 			$$.math.operand = sizeof(long);
323 			break;
324 		    case 'F':
325 			$$.math.operand = sizeof(float);
326 			break;
327 		    case 'D':
328 			$$.math.operand = sizeof(double);
329 			break;
330 		    default:
331 			(void) fprintf(stderr,
332 			    "%s: illegal math sizing char %c\n", prog, $3);
333 			YYERROR;
334 		    }
335 		}
336 	| MATHOP INCHAR
337 		{
338 		    if (mathreg == 0) {
339 			(void) fprintf(stderr,
340 			    "%s: Math operator outside math expression\n",
341 			    prog);
342 			YYERROR;
343 		    }
344 		    $$.math.reg_no = mathreg;
345 		    $$.math.operator = $1;
346 		    switch ($2) {
347 		    case 'C':
348 			$$.math.operand = sizeof(char);
349 			break;
350 		    case 'S':
351 			$$.math.operand = sizeof(short);
352 			break;
353 		    case 'I':
354 			$$.math.operand = sizeof(int);
355 			break;
356 		    case 'L':
357 			$$.math.operand = sizeof(long);
358 			break;
359 		    case 'F':
360 			$$.math.operand = sizeof(float);
361 			break;
362 		    case 'D':
363 			$$.math.operand = sizeof(double);
364 			break;
365 		    default:
366 			(void) fprintf(stderr,
367 			    "%s: illegal math sizing char %c\n", prog, $2);
368 			YYERROR;
369 		    }
370 		}
371 	;
372 
373 
374 iosingle : iocore STORE
375 		{
376 		    $$ = $1;
377 		    $$.iospec.reg_no = $2;
378 		    if ( inval4reg($$.iospec.ochar) ) {
379 			(void) fprintf(stderr,
380 		    "%s: Only integer types can be put in a $x register.\n",
381 			    prog);
382 			YYERROR;
383 		    }
384 		}
385 	| iocore
386 		{
387 		    $$ = $1;
388 		    $$.iospec.reg_no = 0;
389 		}
390 	;
391 
392 iocore : INCHAR OUTCHAR
393 		{
394 		    $$.iospec = makecore($1, $2);
395 		    if (badiopair($$.iospec.ichar, $$.iospec.ochar)) {
396 			(void) fprintf(stderr,
397 	    "%s: input size `%c' and output format `%c' cannot go together.\n",
398 			    prog, $$.iospec.ichar, $$.iospec.ochar);
399 			yyerror("");
400 			YYERROR;
401 		    }
402 		}
403 	| INCHAR
404 		{
405 		    $$.iospec = makecore($1, 0);
406 		    if (badiopair($$.iospec.ichar, $$.iospec.ochar)) {
407 			(void) fprintf(stderr,
408 	    "%s: input size `%c' and output format `%c' cannot go together.\n",
409 			    prog, $$.iospec.ichar, $$.iospec.ochar);
410 			yyerror("");
411 			YYERROR;
412 		    }
413 		}
414 	| OUTCHAR
415 		{
416 		    $$.iospec = makecore(0, $1);
417 		    if (badiopair($$.iospec.ichar, $$.iospec.ochar)) {
418 			(void) fprintf(stderr,
419 	    "%s: input size `%c' and output format `%c' cannot go together.\n",
420 			    prog, $$.iospec.ichar, $$.iospec.ochar);
421 			yyerror("");
422 			YYERROR;
423 		    }
424 		}
425 	| INCHAR PCTSTRING
426 		{
427 		    $$.iospec = makecorepct($1, $2);
428 		}
429 	| PCTSTRING
430 		{
431 		    $$.iospec = makecorepct(0, $1);
432 		}
433 	;
434 
435 count	: NUMBER
436 		{ $$ = $1 ; }
437 	| REG
438 		{ $$ = 0 - $1; }
439 	| EOF_COUNT
440 		{ $$ = UPTO_EOF ; }
441 	;
442 
443 lexerr	: LEXERROR
444 		{ YYERROR; }
445 	;
446 %%
447 
yyerror(s)448 yyerror(s)
449 char *s;
450 {
451     if (s && *s)
452 	(void) fprintf(stderr, "%s: %s", prog, s);
453     if (Fmt.p) {
454 	int n0, n1, n2;
455 	char *nl = strchr(Fmt.line, '\n');
456 	if (Fmt.file) {
457 	    n0 = Fmt.item - Fmt.line;
458 	    n1 = ((nl <= Fmt.p) ? nl : Fmt.p + 1) - Fmt.item;
459 	    n2 = nl ? (nl - Fmt.line - n1 - n0) : 0;
460 	    if (Fmt.item && Fmt.line)
461 		fprintf(stderr, " at line %d:\n\t%.*s >>>%.*s<<< %.*s\n",
462 		    Fmt.linenum, n0, Fmt.line, n1, Fmt.item,
463 		    n2, (nl < Fmt.p) ? nl : Fmt.p+1);
464 	    else
465 		fprintf(stderr, " at line %d.\n", Fmt.linenum);
466 	} else {
467 	    if (Fmt.item)
468 		fprintf(stderr, "\n%.*s >>>%.*s<<< %s\n",
469 		    Fmt.item - Fmt.text, Fmt.text,
470 		    Fmt.p + 1 - Fmt.item, Fmt.item,
471 		    Fmt.p+1);
472 	    else
473 		putc('\n', stderr);
474 	}
475     }
476 }
477 /* Save our current location (assumes we are at a newline) */
478 void
mark_line()479 mark_line() {
480     Fmt.linenum++;
481     Fmt.line = Fmt.item = Fmt.p;
482 }
483 
yylex()484 yylex()
485 {
486     static char *tmpbuf;	/* temporary storage for copyout text */
487 
488     char *b;
489     char c;
490 
491     if (Fmt.p == NULL) {
492 	Fmt.p = Fmt.item = Fmt.line = Fmt.text;
493 	Fmt.linenum = 1;
494 	tmpbuf = malloc((unsigned) strlen(Fmt.text));
495 	if (tmpbuf == NULL) {
496 	    (void) fprintf(stderr,
497 		"%s: Can't malloc buffer space in yylex().\n", prog);
498 	    exit(1);
499 	}
500 	/* Eat leading whitespace */
501 eatws1: while (isspace(*Fmt.p)) {
502 	    if (*Fmt.p++ == '\n')
503 		mark_line();
504 	}
505 	if (*Fmt.p == '#') {
506 	    /* Comment embedded in format; discard text through newline */
507 	    while (*Fmt.p  &&  *Fmt.p != '\n')
508 		Fmt.p++;
509 	    goto eatws1;
510 	}
511 	/* If the first non-whitespace character is a digit,
512 	 * then the count is specified; don't process to eof.
513 	 */
514 	if ( isdigit(*Fmt.p) )
515 	    process_to_eof = 0;
516 	else
517 	    process_to_eof = 1;
518     }
519 
520     /* Eat whitespace */
521 eatws2: while (isspace(*Fmt.p)) {
522 	if (*Fmt.p++ == '\n')
523 	    mark_line();
524     }
525 
526     if (*Fmt.p == '#') {
527 	/* Comment embedded in format; discard text through newline */
528 	while (*Fmt.p  &&  *Fmt.p != '\n')
529 	    Fmt.p++;
530 	goto eatws2;
531     }
532 
533 
534     /* Special processing: support {char short int integer long
535      * float real double} for data sizes {C S I I L F F D}, by replacing the
536      * word with the equivalent single-character form.
537 
538      * Likewise map {seek} to {!}.
539 
540      * Likewise allow "print" for P.
541      */
542     {
543 #define ifname(longname, shortname) \
544 	if (strncmp(Fmt.p, longname, sizeof(longname)-1) == 0 && \
545 			!isalpha(*(Fmt.p+sizeof(longname)-1))) { \
546 	    Fmt.p += sizeof(longname) - 2; \
547 	    c = shortname; \
548 	}
549 
550 	ifname("char", 'C')
551 	else ifname("short", 'S')
552 	else ifname("int", 'I')
553 	else ifname("long", 'L')
554 	else ifname("float", 'F')
555 	else ifname("real", 'F')
556 	else ifname("double", 'D')
557 	else ifname("seek", '!')
558 	else ifname("print", 'P')
559 	else
560 	    c = *Fmt.p;
561 
562     }
563     if (debug)
564 	fprintf(stderr, "(dbg) fmt = `%s'\n", Fmt.p);
565 
566     /* Now check for usual forms */
567     switch (c) {
568     case '\0':
569 	return 0;
570 	break;
571     case '0':
572     case '1':
573     case '2':
574     case '3':
575     case '4':
576     case '5':
577     case '6':
578     case '7':
579     case '8':
580     case '9':
581 	/* require count base to be 10; if we allow strtol to interpret
582 	 * hex, we'll have to interpret 10a (10 ascii) as count=266.
583 	 */
584 	yylval.lval = strtol(Fmt.p, &b, 10);
585 	if (b == Fmt.p) {
586 	    fprintf(stderr, "%s: severe error: strtol(\"%s\",...) failed\n");
587 	    exit(1);
588 	}
589 	Fmt.p = b;
590 	return NUMBER;
591 	break;
592     case 'C':
593     case 'S':
594     case 'I':
595     case 'L':
596     case 'F':
597     case 'D':
598     case 'Z':
599 	yylval.ival = c;
600 	*Fmt.p++;
601 	return INCHAR;
602 	break;
603     case '~':
604     case 'a':
605     case 'b':
606     case 'c':
607     case 'd':
608     case 'u':
609     case 'o':
610     case 'x':
611     case 'f':
612     case 'g':
613 	yylval.ival = *Fmt.p++;
614 	return OUTCHAR;
615 	break;
616     case 'h':
617 	yylval.ival = 'x';
618 	Fmt.p++;
619 	return OUTCHAR;
620 	break;
621     case '[':
622 	for (b = tmpbuf, Fmt.p++; *Fmt.p && *Fmt.p != ']'; ) {
623 	    if (*Fmt.p == '\n') {
624 		(void) fprintf(stderr, "%s: Unterminated output comment.\n", prog);
625 		return LEXERROR;
626 	    }
627 	    if (*Fmt.p == '\\' && *(Fmt.p+1) == ']')
628 		{ *b++ = *++Fmt.p; Fmt.p++; }
629 	    else
630 		*b++ = *Fmt.p++;
631 	}
632 	if (*Fmt.p++ != ']') {
633 	    (void) fprintf(stderr, "%s: Unterminated output comment.\n", prog);
634 	    return LEXERROR;
635 	}
636 	*b = '\0';
637 	yylval.sval = tmpbuf;
638 	if (strstr(yylval.sval, "$("))
639 	    do_condense=0;	/* don't condense list, so that $( gives
640 				 * a count correct from user's perspective.
641 				 */
642 	return COPYOUT;
643 	break;
644     case ';':
645 	++Fmt.p;
646 	return NEWLINE;
647 	break;
648     case '\\':
649 	++Fmt.p;
650 	switch (*Fmt.p) {
651 	case 'n':
652 	    ++Fmt.p;
653 	    return NEWLINE;
654 	    break;
655 	default:
656 	    (void) fprintf(stderr, "%s: unrecognized backslash sequence.\n");
657 	}
658     case 'n':
659 	++Fmt.p;
660 	return NEWLINE;
661 	break;
662     case '(':
663     case ')':
664 	return (*Fmt.p++);
665 	break;
666     case '!':
667 	++Fmt.p;
668 	return SEEK;
669 	break;
670     case '$':
671 	yylval.ival = *++Fmt.p;
672 	if (*Fmt.p == '\0') {
673 	    (void) fprintf(stderr,
674 		    "%s: `$' cannot end the format.\n", prog);
675 	    return LEXERROR;
676 	}
677 	Fmt.p++;
678 	if (yylval.ival == '$')
679 	    return EOF_COUNT; /* $$ is special: a count that means up-to-eof */
680 
681 	if (yylval.ival == '(')
682 	    do_condense=0;	/* don't condense list, so that $( gives
683 				 * a count correct from user's perspective.
684 				 */
685 	return REG;
686 	break;
687     case '>':
688 	yylval.ival = *++Fmt.p;
689 	if (*Fmt.p == '\0') {
690 	    (void) fprintf(stderr,
691 		    "%s: `>' must precede a register character.\n", prog);
692 	    return LEXERROR;
693 	}
694 	Fmt.p++;
695 	return STORE;
696 	break;
697     case '+':
698     case '-':
699     case '*':
700     case '/':
701     case '%':
702     case '=':
703 	yylval.ival = *Fmt.p++;
704 	return MATHOP;
705 	break;
706     case '?':
707     case ':':
708 	/* Used to form tests */
709 	return *Fmt.p++;
710 	break;
711     case 'P':
712 	yylval.ival = *Fmt.p++;
713 	return U_MATHOP;
714 	break;
715     case '"':
716 	/* User-entered format.  Terminate it at '"'. */
717 	for (b = tmpbuf, Fmt.p++; *Fmt.p && *Fmt.p != '"'; ) {
718 	    if (*Fmt.p == '\n') {
719 		(void) fprintf(stderr, "%s: Unterminated printf-fmt.\n", prog);
720 		return LEXERROR;
721 	    }
722 	    if (*Fmt.p == '\\' && *(Fmt.p+1) == '"')
723 		{ *b++ = *++Fmt.p; Fmt.p++; }
724 	    else
725 		*b++ = *Fmt.p++;
726 	}
727 	if (*Fmt.p++ != '"') {
728 	    (void) fprintf(stderr, "%s: Unterminated printf-fmt.\n", prog);
729 	    return LEXERROR;
730 	}
731 	*b = '\0';
732 	Fmt.p++;
733 	yylval.sval = tmpbuf;
734 	return PCTSTRING;
735 	break;
736     default:
737 	fprintf(stderr, "%s: Invalid character `%c' in format\n", prog, *Fmt.p);
738 	return LEXERROR;
739     }
740     /* NOTREACHED */
741 }
742 
743 int
defaultichar(ochar)744 defaultichar(ochar)
745 int ochar;	/* Specifies the output character */
746 {
747 
748     switch (ochar) {
749     case 'a':
750     case 'b':
751     case 'c':
752     case '~':
753 	return 'C';
754 	break;
755     case 'd':
756     case 'u':
757     case 'o':
758     case 'h':
759     case 'x':
760 	return 'I';
761 	break;
762     case 'f':
763     case 'g':
764 	return 'F';
765 	break;
766     default:
767 	return '\0';
768 	break;
769     }
770     /* NOTREACHED */
771 }
772 
773 int
defaultochar(ichar)774 defaultochar(ichar)
775 int ichar;	/* Specifies the input character */
776 {
777     switch (ichar) {
778     case 'C':
779 	return 'a';
780 	break;
781     case 'Z':
782 	return 'a';
783 	break;
784     case 'S':
785 	return 'o';
786 	break;
787     case 'I':
788 	return 'd';
789 	break;
790     case 'L':
791 	return 'd';
792 	break;
793     case 'F':
794     case 'D':
795 	return 'g';
796 	break;
797     default:
798 	return '\0';
799 	break;
800     }
801     /* NOTREACHED */
802 }
803 
804 int
getsize(ichar)805 getsize(ichar)
806 int ichar;
807 {
808 
809     switch (ichar) {
810     case ';':
811 	return 0;
812 	break;
813     case 'C':
814     case 'Z':
815 	return sizeof(char);
816 	break;
817     case 'S':
818 	return sizeof(short);
819 	break;
820     case 'I':
821 	return sizeof(int);
822 	break;
823     case 'L':
824 	return sizeof(long);
825 	break;
826     case 'F':
827 	return sizeof(float);
828 	break;
829     case 'D':
830 	return sizeof(double);
831 	break;
832     default:
833 	return 0;
834     }
835     /* NOTREACHED */
836 }
837 
badiopair(ic,oc)838 badiopair(ic, oc)
839 int ic, oc;
840 {
841     /* illegal pairings: [CSILZ]-fg, [FD]-[abduohx], [SILFD]-ac */
842 
843     if (strchr("fg", oc) && strchr("CSILZ", ic))
844 	return 1;
845     else if (strchr("abduohx", oc) && strchr("FD", ic))
846 	return 1;
847     else if (strchr("ac", oc) &&  strchr("SILFD", ic))
848 	return 1;
849     else
850 	return 0;
851 }
852 
853 
inval4reg(oc)854 inval4reg(oc)
855 int oc;
856 {
857     /* Illegal to use ">x" notation if data are float types */
858     if (oc == 'g' || oc == 'f')
859 	return 1;
860     else
861 	return 0;
862 }
863