1*753d2d2eSraf /*
2*753d2d2eSraf * CDDL HEADER START
3*753d2d2eSraf *
4*753d2d2eSraf * The contents of this file are subject to the terms of the
5*753d2d2eSraf * Common Development and Distribution License, Version 1.0 only
6*753d2d2eSraf * (the "License"). You may not use this file except in compliance
7*753d2d2eSraf * with the License.
8*753d2d2eSraf *
9*753d2d2eSraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*753d2d2eSraf * or http://www.opensolaris.org/os/licensing.
11*753d2d2eSraf * See the License for the specific language governing permissions
12*753d2d2eSraf * and limitations under the License.
13*753d2d2eSraf *
14*753d2d2eSraf * When distributing Covered Code, include this CDDL HEADER in each
15*753d2d2eSraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*753d2d2eSraf * If applicable, add the following below this CDDL HEADER, with the
17*753d2d2eSraf * fields enclosed by brackets "[]" replaced with your own identifying
18*753d2d2eSraf * information: Portions Copyright [yyyy] [name of copyright owner]
19*753d2d2eSraf *
20*753d2d2eSraf * CDDL HEADER END
21*753d2d2eSraf */
22*753d2d2eSraf /*
23*753d2d2eSraf * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
24*753d2d2eSraf * All rights reserved.
25*753d2d2eSraf */
26*753d2d2eSraf
27*753d2d2eSraf #pragma ident "%Z%%M% %I% %E% SMI"
28*753d2d2eSraf
29*753d2d2eSraf #include <stdio.h>
30*753d2d2eSraf #include <string.h>
31*753d2d2eSraf #include "parser.h"
32*753d2d2eSraf #include "trace.h"
33*753d2d2eSraf #include "util.h"
34*753d2d2eSraf #include "symtab.h"
35*753d2d2eSraf #include "io.h"
36*753d2d2eSraf #include "bindings.h"
37*753d2d2eSraf #include "errlog.h"
38*753d2d2eSraf
39*753d2d2eSraf
40*753d2d2eSraf /* File globals. */
41*753d2d2eSraf static void generate_a_binding(char *, char *);
42*753d2d2eSraf
43*753d2d2eSraf static int strpqcmp(char *, char *, char *);
44*753d2d2eSraf static void strpqprint(char *, char *, FILE *);
45*753d2d2eSraf
46*753d2d2eSraf /*
47*753d2d2eSraf * Bindings: do three-valued logic, where a binding can be
48*753d2d2eSraf * an expression to evaluate for truthfulness,
49*753d2d2eSraf * true,
50*753d2d2eSraf * false, or
51*753d2d2eSraf * empty.
52*753d2d2eSraf *
53*753d2d2eSraf * Exception Result Evaluate? Notes
54*753d2d2eSraf * --------- ------ --------- -----
55*753d2d2eSraf *
56*753d2d2eSraf * true ok yes warn[1]
57*753d2d2eSraf * false ok no
58*753d2d2eSraf * empty ok no treat as true
59*753d2d2eSraf * expr ok yes s = !e
60*753d2d2eSraf *
61*753d2d2eSraf * Notes:
62*753d2d2eSraf * [1] Always exceptional, shows errno at run-time
63*753d2d2eSraf *
64*753d2d2eSraf */
65*753d2d2eSraf
66*753d2d2eSraf /*
67*753d2d2eSraf * need_bindings -- see if we have to do anything at all. Implements
68*753d2d2eSraf * the following rows from the table above (die and evaluate=no lines)
69*753d2d2eSraf * Returns NO if we don't have to evaluate bindings at all.
70*753d2d2eSraf *
71*753d2d2eSraf * Exception Result Evaluate? Notes
72*753d2d2eSraf * --------- ------ --------- -----
73*753d2d2eSraf * false ok no
74*753d2d2eSraf * empty ok no treat as true
75*753d2d2eSraf */
76*753d2d2eSraf int
need_bindings(char * exception)77*753d2d2eSraf need_bindings(char *exception)
78*753d2d2eSraf {
79*753d2d2eSraf
80*753d2d2eSraf errlog(BEGIN, "need_bindings() {");
81*753d2d2eSraf
82*753d2d2eSraf if (exception == NULL)
83*753d2d2eSraf exception = "";
84*753d2d2eSraf
85*753d2d2eSraf /* empty false ok no */
86*753d2d2eSraf /* empty empty ok no, treat as true */
87*753d2d2eSraf if (strcmp(exception, "false") == 0 ||
88*753d2d2eSraf *exception == '\0') {
89*753d2d2eSraf errlog(END, "}");
90*753d2d2eSraf return (NO);
91*753d2d2eSraf }
92*753d2d2eSraf errlog(END, "}");
93*753d2d2eSraf return (YES);
94*753d2d2eSraf }
95*753d2d2eSraf
96*753d2d2eSraf
97*753d2d2eSraf int
need_exception_binding(void)98*753d2d2eSraf need_exception_binding(void)
99*753d2d2eSraf {
100*753d2d2eSraf ENTRY *e;
101*753d2d2eSraf char *exception;
102*753d2d2eSraf
103*753d2d2eSraf exception = ((e = symtab_get_exception()) != NULL)?
104*753d2d2eSraf (name_of(e)? name_of(e): ""): "";
105*753d2d2eSraf
106*753d2d2eSraf return (need_bindings(exception));
107*753d2d2eSraf
108*753d2d2eSraf }
109*753d2d2eSraf
110*753d2d2eSraf /*
111*753d2d2eSraf * generate_bindings -- make the code for exception bindings
112*753d2d2eSraf *
113*753d2d2eSraf * Exception Result Evaluate? Notes
114*753d2d2eSraf * --------- ------ --------- -----
115*753d2d2eSraf * true ok yes warn[2]
116*753d2d2eSraf * expr ok yes s::= !e
117*753d2d2eSraf *
118*753d2d2eSraf * Returns NO if we need both bindings, YES (ANTONYM) if we
119*753d2d2eSraf * only need to evaluate success.
120*753d2d2eSraf */
121*753d2d2eSraf int
generate_bindings(char * exception)122*753d2d2eSraf generate_bindings(char *exception)
123*753d2d2eSraf {
124*753d2d2eSraf int ret = NO;
125*753d2d2eSraf
126*753d2d2eSraf errlog(BEGIN, "generate_bindings() {");
127*753d2d2eSraf errlog(TRACING, "exception=%s\n", exception ? exception : "NULL");
128*753d2d2eSraf
129*753d2d2eSraf /* Exception Result Evaluate? Notes */
130*753d2d2eSraf /* --------- ------ --------- ----- */
131*753d2d2eSraf /* true ok yes warn[2] */
132*753d2d2eSraf if (exception != NULL) {
133*753d2d2eSraf generate_a_binding("exception", exception);
134*753d2d2eSraf errlog(END, "}");
135*753d2d2eSraf }
136*753d2d2eSraf
137*753d2d2eSraf return (ret);
138*753d2d2eSraf }
139*753d2d2eSraf
140*753d2d2eSraf /*
141*753d2d2eSraf * bindings_exist -- make sure we don't use one if they're not there.
142*753d2d2eSraf */
143*753d2d2eSraf int
bindings_exist(void)144*753d2d2eSraf bindings_exist(void)
145*753d2d2eSraf {
146*753d2d2eSraf int ret;
147*753d2d2eSraf
148*753d2d2eSraf errlog(BEGIN, "bindings_exist() {");
149*753d2d2eSraf errlog(END, "}");
150*753d2d2eSraf
151*753d2d2eSraf ret = validity_of(symtab_get_exception()) == YES;
152*753d2d2eSraf
153*753d2d2eSraf return (ret);
154*753d2d2eSraf }
155*753d2d2eSraf
156*753d2d2eSraf
157*753d2d2eSraf
158*753d2d2eSraf /*
159*753d2d2eSraf * generate_a_binding -- generate just one, with a set of transformations
160*753d2d2eSraf * applied. Eg, return->_return, errno->functions_errvar,
161*753d2d2eSraf * unchanged(x)->x == 0, etc. Oneof and someof TBD.
162*753d2d2eSraf */
163*753d2d2eSraf static void
generate_a_binding(char * name,char * value)164*753d2d2eSraf generate_a_binding(char *name, char *value)
165*753d2d2eSraf {
166*753d2d2eSraf char *p = value;
167*753d2d2eSraf ENTRY *e = symtab_get_errval();
168*753d2d2eSraf char *errvar = (e == NULL)? NULL: name_of(e);
169*753d2d2eSraf char *q;
170*753d2d2eSraf
171*753d2d2eSraf errlog(BEGIN, "generate_a_binding() {");
172*753d2d2eSraf if (*value == NULL) {
173*753d2d2eSraf errlog(FATAL, "programmer error: asked to generate an "
174*753d2d2eSraf "empty binding");
175*753d2d2eSraf }
176*753d2d2eSraf
177*753d2d2eSraf {
178*753d2d2eSraf /*
179*753d2d2eSraf * XXX - friggin spaghetti
180*753d2d2eSraf */
181*753d2d2eSraf ENTRY *exc = symtab_get_exception();
182*753d2d2eSraf
183*753d2d2eSraf if (exc != NULL)
184*753d2d2eSraf (void) fprintf(Bodyfp,
185*753d2d2eSraf "#line %d \"%s\"\n",
186*753d2d2eSraf line_of(exc), symtab_get_filename());
187*753d2d2eSraf }
188*753d2d2eSraf
189*753d2d2eSraf /* Generate prefix. */
190*753d2d2eSraf (void) fprintf(Bodyfp, " %s = (", name);
191*753d2d2eSraf
192*753d2d2eSraf /* Walk across line, emitting tokens and transformed tokens */
193*753d2d2eSraf
194*753d2d2eSraf for (; *p != NULL; p = q) {
195*753d2d2eSraf p = skipb(p);
196*753d2d2eSraf q = nextsep(p);
197*753d2d2eSraf
198*753d2d2eSraf if (p == q) {
199*753d2d2eSraf /* We're at the end, a "(", ")" or an operator. */
200*753d2d2eSraf if (*p == '(') {
201*753d2d2eSraf /* We're at a parenthesized expression */
202*753d2d2eSraf q++;
203*753d2d2eSraf } else if (*p == ')') {
204*753d2d2eSraf /* And the end of an expression. */
205*753d2d2eSraf q++;
206*753d2d2eSraf } else if (*p == '!' && *(p+1) != '=') {
207*753d2d2eSraf /* Or a negated expression */
208*753d2d2eSraf q++;
209*753d2d2eSraf } else if ((q = nextb(p)) == p) {
210*753d2d2eSraf /* Real end! */
211*753d2d2eSraf break;
212*753d2d2eSraf }
213*753d2d2eSraf
214*753d2d2eSraf /* Else it was an operator, boogy onwards. */
215*753d2d2eSraf }
216*753d2d2eSraf if (strpqcmp("$return", p, q) == 0) {
217*753d2d2eSraf (void) fputs("_return", Bodyfp);
218*753d2d2eSraf } else if (errvar != NULL && strpqcmp(errvar, p, q) == 0) {
219*753d2d2eSraf (void) fputs("functions_errvar", Bodyfp);
220*753d2d2eSraf } else if (strpqcmp("unchanged", p, q) == 0) {
221*753d2d2eSraf /* This will look odd. */
222*753d2d2eSraf (void) fputs("0 == ", Bodyfp);
223*753d2d2eSraf } else if (strpqcmp("oneof", p, q) == 0) {
224*753d2d2eSraf errlog(WARNING, "Oneof unimplemented in spec2trace"
225*753d2d2eSraf "It will be treated as the token 'false'");
226*753d2d2eSraf (void) fputs("false", Bodyfp);
227*753d2d2eSraf break;
228*753d2d2eSraf } else if (strpqcmp("someof", p, q) == 0) {
229*753d2d2eSraf errlog(WARNING, "Someof unimplemented in spec2trace, "
230*753d2d2eSraf "It will be treated as the token 'false'");
231*753d2d2eSraf (void) fputs("false", Bodyfp);
232*753d2d2eSraf break;
233*753d2d2eSraf } else if (strpqcmp("errno", p, q) == 0) {
234*753d2d2eSraf (void) fputs("ABI_ERRNO", Bodyfp);
235*753d2d2eSraf } else {
236*753d2d2eSraf /* Just copy it. */
237*753d2d2eSraf
238*753d2d2eSraf strpqprint(p, q, Bodyfp);
239*753d2d2eSraf }
240*753d2d2eSraf (void) putc(' ', Bodyfp);
241*753d2d2eSraf }
242*753d2d2eSraf (void) (void) fputs(");\n", Bodyfp);
243*753d2d2eSraf errlog(END, "}");
244*753d2d2eSraf }
245*753d2d2eSraf
246*753d2d2eSraf /*
247*753d2d2eSraf * strpqcmp -- compare a null-terminated string with a pq-bracketed string.
248*753d2d2eSraf */
249*753d2d2eSraf static int
strpqcmp(char * v1,char * p,char * q)250*753d2d2eSraf strpqcmp(char *v1, char *p, char *q)
251*753d2d2eSraf {
252*753d2d2eSraf int rc;
253*753d2d2eSraf char saved;
254*753d2d2eSraf
255*753d2d2eSraf errlog(BEGIN, "strpqcmp() {");
256*753d2d2eSraf saved = *q;
257*753d2d2eSraf *q = NULL;
258*753d2d2eSraf rc = (strcmp(v1, p));
259*753d2d2eSraf *q = saved;
260*753d2d2eSraf errlog(END, "}");
261*753d2d2eSraf return (rc);
262*753d2d2eSraf }
263*753d2d2eSraf
264*753d2d2eSraf /*
265*753d2d2eSraf * strpqprint -- print a pq-bracketed string
266*753d2d2eSraf */
267*753d2d2eSraf static void
strpqprint(char * p,char * q,FILE * fp)268*753d2d2eSraf strpqprint(char *p, char *q, FILE *fp)
269*753d2d2eSraf {
270*753d2d2eSraf char saved;
271*753d2d2eSraf
272*753d2d2eSraf errlog(BEGIN, "strpqprint() {");
273*753d2d2eSraf saved = *q;
274*753d2d2eSraf *q = NULL;
275*753d2d2eSraf (void) fputs(p, fp);
276*753d2d2eSraf *q = saved;
277*753d2d2eSraf errlog(END, "}");
278*753d2d2eSraf }
279