bindings.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1997-1999 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <string.h>
#include "parser.h"
#include "trace.h"
#include "util.h"
#include "symtab.h"
#include "io.h"
#include "bindings.h"
#include "errlog.h"
/* File globals. */
static void generate_a_binding(char *, char *);
static int strpqcmp(char *, char *, char *);
static void strpqprint(char *, char *, FILE *);
/*
* Bindings: do three-valued logic, where a binding can be
* an expression to evaluate for truthfulness,
* true,
* false, or
* empty.
*
* Exception Result Evaluate? Notes
* --------- ------ --------- -----
*
* true ok yes warn[1]
* false ok no
* empty ok no treat as true
* expr ok yes s = !e
*
* Notes:
* [1] Always exceptional, shows errno at run-time
*
*/
/*
* need_bindings -- see if we have to do anything at all. Implements
* the following rows from the table above (die and evaluate=no lines)
* Returns NO if we don't have to evaluate bindings at all.
*
* Exception Result Evaluate? Notes
* --------- ------ --------- -----
* false ok no
* empty ok no treat as true
*/
int
need_bindings(char *exception)
{
errlog(BEGIN, "need_bindings() {");
if (exception == NULL)
exception = "";
/* empty false ok no */
/* empty empty ok no, treat as true */
if (strcmp(exception, "false") == 0 ||
*exception == '\0') {
errlog(END, "}");
return (NO);
}
errlog(END, "}");
return (YES);
}
int
need_exception_binding(void)
{
ENTRY *e;
char *exception;
exception = ((e = symtab_get_exception()) != NULL)?
(name_of(e)? name_of(e): ""): "";
return (need_bindings(exception));
}
/*
* generate_bindings -- make the code for exception bindings
*
* Exception Result Evaluate? Notes
* --------- ------ --------- -----
* true ok yes warn[2]
* expr ok yes s::= !e
*
* Returns NO if we need both bindings, YES (ANTONYM) if we
* only need to evaluate success.
*/
int
generate_bindings(char *exception)
{
int ret = NO;
errlog(BEGIN, "generate_bindings() {");
errlog(TRACING, "exception=%s\n", exception ? exception : "NULL");
/* Exception Result Evaluate? Notes */
/* --------- ------ --------- ----- */
/* true ok yes warn[2] */
if (exception != NULL) {
generate_a_binding("exception", exception);
errlog(END, "}");
}
return (ret);
}
/*
* bindings_exist -- make sure we don't use one if they're not there.
*/
int
bindings_exist(void)
{
int ret;
errlog(BEGIN, "bindings_exist() {");
errlog(END, "}");
ret = validity_of(symtab_get_exception()) == YES;
return (ret);
}
/*
* generate_a_binding -- generate just one, with a set of transformations
* applied. Eg, return->_return, errno->functions_errvar,
* unchanged(x)->x == 0, etc. Oneof and someof TBD.
*/
static void
generate_a_binding(char *name, char *value)
{
char *p = value;
ENTRY *e = symtab_get_errval();
char *errvar = (e == NULL)? NULL: name_of(e);
char *q;
errlog(BEGIN, "generate_a_binding() {");
if (*value == NULL) {
errlog(FATAL, "programmer error: asked to generate an "
"empty binding");
}
{
/*
* XXX - friggin spaghetti
*/
ENTRY *exc = symtab_get_exception();
if (exc != NULL)
(void) fprintf(Bodyfp,
"#line %d \"%s\"\n",
line_of(exc), symtab_get_filename());
}
/* Generate prefix. */
(void) fprintf(Bodyfp, " %s = (", name);
/* Walk across line, emitting tokens and transformed tokens */
for (; *p != NULL; p = q) {
p = skipb(p);
q = nextsep(p);
if (p == q) {
/* We're at the end, a "(", ")" or an operator. */
if (*p == '(') {
/* We're at a parenthesized expression */
q++;
} else if (*p == ')') {
/* And the end of an expression. */
q++;
} else if (*p == '!' && *(p+1) != '=') {
/* Or a negated expression */
q++;
} else if ((q = nextb(p)) == p) {
/* Real end! */
break;
}
/* Else it was an operator, boogy onwards. */
}
if (strpqcmp("$return", p, q) == 0) {
(void) fputs("_return", Bodyfp);
} else if (errvar != NULL && strpqcmp(errvar, p, q) == 0) {
(void) fputs("functions_errvar", Bodyfp);
} else if (strpqcmp("unchanged", p, q) == 0) {
/* This will look odd. */
(void) fputs("0 == ", Bodyfp);
} else if (strpqcmp("oneof", p, q) == 0) {
errlog(WARNING, "Oneof unimplemented in spec2trace"
"It will be treated as the token 'false'");
(void) fputs("false", Bodyfp);
break;
} else if (strpqcmp("someof", p, q) == 0) {
errlog(WARNING, "Someof unimplemented in spec2trace, "
"It will be treated as the token 'false'");
(void) fputs("false", Bodyfp);
break;
} else if (strpqcmp("errno", p, q) == 0) {
(void) fputs("ABI_ERRNO", Bodyfp);
} else {
/* Just copy it. */
strpqprint(p, q, Bodyfp);
}
(void) putc(' ', Bodyfp);
}
(void) (void) fputs(");\n", Bodyfp);
errlog(END, "}");
}
/*
* strpqcmp -- compare a null-terminated string with a pq-bracketed string.
*/
static int
strpqcmp(char *v1, char *p, char *q)
{
int rc;
char saved;
errlog(BEGIN, "strpqcmp() {");
saved = *q;
*q = NULL;
rc = (strcmp(v1, p));
*q = saved;
errlog(END, "}");
return (rc);
}
/*
* strpqprint -- print a pq-bracketed string
*/
static void
strpqprint(char *p, char *q, FILE *fp)
{
char saved;
errlog(BEGIN, "strpqprint() {");
saved = *q;
*q = NULL;
(void) fputs(p, fp);
*q = saved;
errlog(END, "}");
}