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