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 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 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 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 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 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 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 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