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