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