17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
247c478bd9Sstevel@tonic-gate  * All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include "parser.h"
307c478bd9Sstevel@tonic-gate #include "trace.h"
317c478bd9Sstevel@tonic-gate #include "util.h"
327c478bd9Sstevel@tonic-gate #include "symtab.h"
337c478bd9Sstevel@tonic-gate #include "io.h"
347c478bd9Sstevel@tonic-gate #include "bindings.h"
357c478bd9Sstevel@tonic-gate #include "errlog.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /* File globals. */
397c478bd9Sstevel@tonic-gate static void generate_a_binding(char *, char *);
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate static int strpqcmp(char *, char *, char *);
427c478bd9Sstevel@tonic-gate static void strpqprint(char *, char *, FILE *);
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * Bindings: do three-valued logic, where a binding can be
467c478bd9Sstevel@tonic-gate  *	an expression to evaluate for truthfulness,
477c478bd9Sstevel@tonic-gate  *	true,
487c478bd9Sstevel@tonic-gate  *	false, or
497c478bd9Sstevel@tonic-gate  *	empty.
507c478bd9Sstevel@tonic-gate  *
517c478bd9Sstevel@tonic-gate  *	Exception	Result	Evaluate?	Notes
527c478bd9Sstevel@tonic-gate  *	---------	------	---------	-----
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  *	true		ok	yes		warn[1]
557c478bd9Sstevel@tonic-gate  *	false		ok	no
567c478bd9Sstevel@tonic-gate  *	empty		ok	no		treat as true
577c478bd9Sstevel@tonic-gate  *	expr		ok	yes		s = !e
587c478bd9Sstevel@tonic-gate  *
597c478bd9Sstevel@tonic-gate  * Notes:
607c478bd9Sstevel@tonic-gate  *	[1] Always exceptional, shows errno at run-time
617c478bd9Sstevel@tonic-gate  *
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  * need_bindings -- see if we have to do anything at all. Implements
667c478bd9Sstevel@tonic-gate  *	the following rows from the table above (die and evaluate=no lines)
677c478bd9Sstevel@tonic-gate  *	Returns NO if we don't have to evaluate bindings at all.
687c478bd9Sstevel@tonic-gate  *
697c478bd9Sstevel@tonic-gate  *	Exception	Result	Evaluate?	Notes
707c478bd9Sstevel@tonic-gate  *	---------	------	---------	-----
717c478bd9Sstevel@tonic-gate  *	false		ok	no
727c478bd9Sstevel@tonic-gate  *	empty		ok	no		treat as true
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate int
need_bindings(char * exception)757c478bd9Sstevel@tonic-gate need_bindings(char *exception)
767c478bd9Sstevel@tonic-gate {
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "need_bindings() {");
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	if (exception == NULL)
817c478bd9Sstevel@tonic-gate 		exception = "";
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 	/*	empty		false		ok	no */
847c478bd9Sstevel@tonic-gate 	/*	empty		empty		ok	no, treat as true */
857c478bd9Sstevel@tonic-gate 	if (strcmp(exception, "false") == 0 ||
867c478bd9Sstevel@tonic-gate 	    *exception == '\0') {
877c478bd9Sstevel@tonic-gate 		errlog(END, "}");
887c478bd9Sstevel@tonic-gate 		return (NO);
897c478bd9Sstevel@tonic-gate 	}
907c478bd9Sstevel@tonic-gate 	errlog(END, "}");
917c478bd9Sstevel@tonic-gate 	return (YES);
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate int
need_exception_binding(void)967c478bd9Sstevel@tonic-gate need_exception_binding(void)
977c478bd9Sstevel@tonic-gate {
987c478bd9Sstevel@tonic-gate 	ENTRY	*e;
997c478bd9Sstevel@tonic-gate 	char *exception;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	exception = ((e = symtab_get_exception()) != NULL)?
1027c478bd9Sstevel@tonic-gate 	    (name_of(e)? name_of(e): ""): "";
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	return (need_bindings(exception));
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate  * generate_bindings -- make the code for exception bindings
1107c478bd9Sstevel@tonic-gate  *
1117c478bd9Sstevel@tonic-gate  *	Exception	Result	Evaluate?	Notes
1127c478bd9Sstevel@tonic-gate  *	---------	------	---------	-----
1137c478bd9Sstevel@tonic-gate  *	true		ok	yes		warn[2]
1147c478bd9Sstevel@tonic-gate  *	expr		ok	yes		s::= !e
1157c478bd9Sstevel@tonic-gate  *
1167c478bd9Sstevel@tonic-gate  *	Returns NO if we need both bindings, YES (ANTONYM) if we
1177c478bd9Sstevel@tonic-gate  *	only need to evaluate success.
1187c478bd9Sstevel@tonic-gate  */
1197c478bd9Sstevel@tonic-gate int
generate_bindings(char * exception)1207c478bd9Sstevel@tonic-gate generate_bindings(char *exception)
1217c478bd9Sstevel@tonic-gate {
1227c478bd9Sstevel@tonic-gate 	int ret = NO;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_bindings() {");
1257c478bd9Sstevel@tonic-gate 	errlog(TRACING,  "exception=%s\n", exception ? exception : "NULL");
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	/* Exception	Result	Evaluate?	Notes	*/
1287c478bd9Sstevel@tonic-gate 	/* ---------	------	---------	-----	*/
1297c478bd9Sstevel@tonic-gate 	/* true		ok	yes		warn[2] */
1307c478bd9Sstevel@tonic-gate 	if (exception != NULL) {
1317c478bd9Sstevel@tonic-gate 		generate_a_binding("exception", exception);
1327c478bd9Sstevel@tonic-gate 		errlog(END, "}");
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	return (ret);
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate  * bindings_exist -- make sure we don't use one if they're not there.
1407c478bd9Sstevel@tonic-gate  */
1417c478bd9Sstevel@tonic-gate int
bindings_exist(void)1427c478bd9Sstevel@tonic-gate bindings_exist(void)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate 	int ret;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "bindings_exist() {");
1477c478bd9Sstevel@tonic-gate 	errlog(END, "}");
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	ret = validity_of(symtab_get_exception()) == YES;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	return (ret);
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate /*
1577c478bd9Sstevel@tonic-gate  * generate_a_binding -- generate just one, with a set of transformations
1587c478bd9Sstevel@tonic-gate  *	applied. Eg, return->_return, errno->functions_errvar,
1597c478bd9Sstevel@tonic-gate  *	unchanged(x)->x == 0, etc. Oneof and someof TBD.
1607c478bd9Sstevel@tonic-gate  */
1617c478bd9Sstevel@tonic-gate static void
generate_a_binding(char * name,char * value)1627c478bd9Sstevel@tonic-gate generate_a_binding(char *name, char *value)
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate 	char *p = value;
1657c478bd9Sstevel@tonic-gate 	ENTRY	*e = symtab_get_errval();
1667c478bd9Sstevel@tonic-gate 	char	*errvar = (e == NULL)? NULL: name_of(e);
1677c478bd9Sstevel@tonic-gate 	char	*q;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "generate_a_binding() {");
170*07c94cbfSToomas Soome 	if (*value == '\0') {
1717c478bd9Sstevel@tonic-gate 		errlog(FATAL, "programmer error: asked to generate an "
1727c478bd9Sstevel@tonic-gate 			"empty binding");
1737c478bd9Sstevel@tonic-gate 	}
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	{
1767c478bd9Sstevel@tonic-gate 		/*
1777c478bd9Sstevel@tonic-gate 		 * XXX - friggin spaghetti
1787c478bd9Sstevel@tonic-gate 		 */
1797c478bd9Sstevel@tonic-gate 		ENTRY	*exc = symtab_get_exception();
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 		if (exc != NULL)
1827c478bd9Sstevel@tonic-gate 			(void) fprintf(Bodyfp,
1837c478bd9Sstevel@tonic-gate 			    "#line %d \"%s\"\n",
1847c478bd9Sstevel@tonic-gate 			    line_of(exc), symtab_get_filename());
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	/* Generate prefix. */
1887c478bd9Sstevel@tonic-gate 	(void) fprintf(Bodyfp, "    %s = (", name);
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	/* Walk across line, emitting tokens and transformed tokens */
1917c478bd9Sstevel@tonic-gate 
192*07c94cbfSToomas Soome 	for (; *p != '\0'; p = q) {
1937c478bd9Sstevel@tonic-gate 		p = skipb(p);
1947c478bd9Sstevel@tonic-gate 		q = nextsep(p);
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 		if (p == q) {
1977c478bd9Sstevel@tonic-gate 			/* We're at the end, a "(", ")" or an operator. */
1987c478bd9Sstevel@tonic-gate 			if (*p == '(') {
1997c478bd9Sstevel@tonic-gate 				/* We're at a parenthesized expression */
2007c478bd9Sstevel@tonic-gate 				q++;
2017c478bd9Sstevel@tonic-gate 			} else if (*p == ')') {
2027c478bd9Sstevel@tonic-gate 				/* And the end of an expression. */
2037c478bd9Sstevel@tonic-gate 				q++;
2047c478bd9Sstevel@tonic-gate 			} else if (*p == '!' && *(p+1) != '=') {
2057c478bd9Sstevel@tonic-gate 				/* Or a negated expression */
2067c478bd9Sstevel@tonic-gate 				q++;
2077c478bd9Sstevel@tonic-gate 			} else if ((q = nextb(p)) == p) {
2087c478bd9Sstevel@tonic-gate 				/* Real end! */
2097c478bd9Sstevel@tonic-gate 				break;
2107c478bd9Sstevel@tonic-gate 			}
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 			/* Else it was an operator, boogy onwards. */
2137c478bd9Sstevel@tonic-gate 		}
2147c478bd9Sstevel@tonic-gate 		if (strpqcmp("$return", p, q) == 0) {
2157c478bd9Sstevel@tonic-gate 			(void) fputs("_return", Bodyfp);
2167c478bd9Sstevel@tonic-gate 		} else if (errvar != NULL && strpqcmp(errvar, p, q) == 0) {
2177c478bd9Sstevel@tonic-gate 			(void) fputs("functions_errvar", Bodyfp);
2187c478bd9Sstevel@tonic-gate 		} else if (strpqcmp("unchanged", p, q) == 0) {
2197c478bd9Sstevel@tonic-gate 			/* This will look odd. */
2207c478bd9Sstevel@tonic-gate 			(void) fputs("0 == ", Bodyfp);
2217c478bd9Sstevel@tonic-gate 		} else if (strpqcmp("oneof", p, q) == 0) {
2227c478bd9Sstevel@tonic-gate 			errlog(WARNING,  "Oneof unimplemented in spec2trace"
2237c478bd9Sstevel@tonic-gate 				"It will be treated as the token 'false'");
2247c478bd9Sstevel@tonic-gate 			(void) fputs("false", Bodyfp);
2257c478bd9Sstevel@tonic-gate 			break;
2267c478bd9Sstevel@tonic-gate 		} else if (strpqcmp("someof", p, q) == 0) {
2277c478bd9Sstevel@tonic-gate 			errlog(WARNING, "Someof unimplemented in spec2trace, "
2287c478bd9Sstevel@tonic-gate 				"It will be treated as the token 'false'");
2297c478bd9Sstevel@tonic-gate 			(void) fputs("false", Bodyfp);
2307c478bd9Sstevel@tonic-gate 			break;
2317c478bd9Sstevel@tonic-gate 		} else if (strpqcmp("errno", p, q) == 0) {
2327c478bd9Sstevel@tonic-gate 			(void) fputs("ABI_ERRNO", Bodyfp);
2337c478bd9Sstevel@tonic-gate 		} else {
2347c478bd9Sstevel@tonic-gate 			/* Just copy it. */
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 			strpqprint(p, q, Bodyfp);
2377c478bd9Sstevel@tonic-gate 		}
2387c478bd9Sstevel@tonic-gate 		(void) putc(' ', Bodyfp);
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 	(void) (void) fputs(");\n", Bodyfp);
2417c478bd9Sstevel@tonic-gate 	errlog(END, "}");
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate  * strpqcmp -- compare a null-terminated string with a pq-bracketed string.
2467c478bd9Sstevel@tonic-gate  */
2477c478bd9Sstevel@tonic-gate static int
strpqcmp(char * v1,char * p,char * q)2487c478bd9Sstevel@tonic-gate strpqcmp(char *v1, char *p, char *q)
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate 	int	rc;
2517c478bd9Sstevel@tonic-gate 	char	saved;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "strpqcmp() {");
2547c478bd9Sstevel@tonic-gate 	saved = *q;
255*07c94cbfSToomas Soome 	*q = '\0';
2567c478bd9Sstevel@tonic-gate 	rc = (strcmp(v1, p));
2577c478bd9Sstevel@tonic-gate 	*q = saved;
2587c478bd9Sstevel@tonic-gate 	errlog(END, "}");
2597c478bd9Sstevel@tonic-gate 	return (rc);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate /*
2637c478bd9Sstevel@tonic-gate  * strpqprint -- print a pq-bracketed string
2647c478bd9Sstevel@tonic-gate  */
2657c478bd9Sstevel@tonic-gate static void
strpqprint(char * p,char * q,FILE * fp)2667c478bd9Sstevel@tonic-gate strpqprint(char *p, char *q, FILE *fp)
2677c478bd9Sstevel@tonic-gate {
2687c478bd9Sstevel@tonic-gate 	char	saved;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	errlog(BEGIN, "strpqprint() {");
2717c478bd9Sstevel@tonic-gate 	saved = *q;
272*07c94cbfSToomas Soome 	*q = '\0';
2737c478bd9Sstevel@tonic-gate 	(void) fputs(p, fp);
2747c478bd9Sstevel@tonic-gate 	*q = saved;
2757c478bd9Sstevel@tonic-gate 	errlog(END, "}");
2767c478bd9Sstevel@tonic-gate }
277