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