mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 16:34:07 +00:00
1 line
10 KiB
C
1 line
10 KiB
C
/* -*-c,save-*- */
|
||
|
||
/* SDB - expression compiler
|
||
|
||
syntax:
|
||
|
||
<expr> ::= <lor> <EOS>
|
||
|
||
<lor> ::= <land> { '|' <land> }
|
||
|
||
<land> ::= <relat> { '&' <relat> }
|
||
|
||
<relat> ::= <primary> { <relop> <primary> }
|
||
|
||
<primary> ::= <factor> | <unop> <unary>
|
||
|
||
<factor> ::= <number> | <string> | '(' <query> ')'
|
||
|
||
<number> ::= <digit> | <number> <digit>
|
||
|
||
<string> ::= '"' <chars> '"'
|
||
|
||
<chars> ::= nil | <chars> <character>
|
||
|
||
<relop> ::= '=' | '<>' | '<' | '>' | '<=' | '>='
|
||
|
||
<unop> ::= '+' | '-' | '~'
|
||
|
||
*/
|
||
|
||
|
||
|
||
#include "sdbio.h"
|
||
|
||
|
||
|
||
/* #define DEBUG 1 /* debug hackery */
|
||
|
||
#ifdef DEBUG
|
||
|
||
#define LOCAL
|
||
|
||
#else
|
||
|
||
#define LOCAL static
|
||
|
||
#endif
|
||
|
||
|
||
|
||
extern int dbv_token;
|
||
|
||
extern char dbv_tstring[];
|
||
|
||
extern int dbv_tvalue;
|
||
|
||
|
||
|
||
extern int db_xand();
|
||
|
||
extern int db_xor();
|
||
|
||
extern int db_xnot();
|
||
|
||
extern int db_xlss();
|
||
|
||
extern int db_xleq();
|
||
|
||
extern int db_xeql();
|
||
|
||
extern int db_xgeq();
|
||
|
||
extern int db_xgtr();
|
||
|
||
extern int db_xneq();
|
||
|
||
extern int db_xpush();
|
||
|
||
extern int db_xstop();
|
||
|
||
|
||
|
||
LOCAL union codecell code[CODEMAX+1];
|
||
|
||
LOCAL int cndx;
|
||
|
||
LOCAL struct sel *selptr;
|
||
|
||
|
||
|
||
/* compile - compile a boolean expression */
|
||
|
||
int db_compile(slptr)
|
||
|
||
struct sel *slptr;
|
||
|
||
{
|
||
|
||
int result,i;
|
||
|
||
union codecell *cptr;
|
||
|
||
#ifdef Lattice
|
||
|
||
int (*dns)(); /*dns*/
|
||
|
||
#endif
|
||
|
||
|
||
|
||
/* save the selection structure pointer */
|
||
|
||
selptr = slptr;
|
||
|
||
|
||
|
||
/* initialize the code array index */
|
||
|
||
cndx = 0;
|
||
|
||
|
||
|
||
/* parse the boolean expression */
|
||
|
||
if (!expr(&result)) {
|
||
|
||
code[cndx++].c_operator = db_xstop;
|
||
|
||
freelit(code);
|
||
|
||
return (FALSE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* terminate the code */
|
||
|
||
code[cndx++].c_operator = db_xstop;
|
||
|
||
|
||
|
||
/* allocate space for the code array */
|
||
|
||
if ((cptr = malloc(sizeof(union codecell) * cndx)) == NULL) {
|
||
|
||
freelit(code);
|
||
|
||
return (FALSE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* store the code into the code array */
|
||
|
||
slptr->sl_where = cptr;
|
||
|
||
for (i = 0; i < cndx; i++) {
|
||
|
||
(*cptr++).c_operator = code[i].c_operator;
|
||
|
||
#ifndef Lattice
|
||
|
||
if (code[i].c_operator == db_xpush)
|
||
|
||
#else
|
||
|
||
if ( code[i].c_operator == (dns=db_xpush) ) /*dns*/
|
||
|
||
#endif
|
||
|
||
(*cptr++).c_operand = code[++i].c_operand;
|
||
|
||
}
|
||
|
||
|
||
|
||
/* return successfully */
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* db_fcode - free a code array */
|
||
|
||
db_fcode(slptr)
|
||
|
||
struct sel *slptr;
|
||
|
||
{
|
||
|
||
/* make sure there is a where clause */
|
||
|
||
if (slptr->sl_where == NULL)
|
||
|
||
return;
|
||
|
||
|
||
|
||
/* free the literals */
|
||
|
||
freelit(slptr->sl_where);
|
||
|
||
|
||
|
||
/* free the code array */
|
||
|
||
free(slptr->sl_where);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* operator - insert an operator into the code array */
|
||
|
||
LOCAL int operator(opr)
|
||
|
||
int (*opr)();
|
||
|
||
{
|
||
|
||
/* insert the operator */
|
||
|
||
if (cndx < CODEMAX)
|
||
|
||
code[cndx++].c_operator = opr;
|
||
|
||
else
|
||
|
||
return (db_ferror(CDSIZE));
|
||
|
||
|
||
|
||
/* return successfully */
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* operand - insert an operand into the code array */
|
||
|
||
LOCAL int operand(opr)
|
||
|
||
struct operand *opr;
|
||
|
||
{
|
||
|
||
/* insert the push operator */
|
||
|
||
if (!operator(db_xpush))
|
||
|
||
return (FALSE);
|
||
|
||
|
||
|
||
/* insert the operand */
|
||
|
||
if (cndx < CODEMAX)
|
||
|
||
code[cndx++].c_operand = opr;
|
||
|
||
else
|
||
|
||
return (db_ferror(CDSIZE));
|
||
|
||
|
||
|
||
/* return successfully */
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* expr - compile an expression */
|
||
|
||
LOCAL int expr(result)
|
||
|
||
int *result;
|
||
|
||
{
|
||
|
||
int lval,rval;
|
||
|
||
|
||
|
||
if (!land(&lval))
|
||
|
||
return (FALSE);
|
||
|
||
while (db_token() == '|') {
|
||
|
||
db_ntoken();
|
||
|
||
if (!land(&rval))
|
||
|
||
return (FALSE);
|
||
|
||
if (!operator(db_xor))
|
||
|
||
return (FALSE);
|
||
|
||
}
|
||
|
||
*result = lval;
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
LOCAL int land(result)
|
||
|
||
int *result;
|
||
|
||
{
|
||
|
||
int lval,rval;
|
||
|
||
|
||
|
||
if (!relat(&lval))
|
||
|
||
return (FALSE);
|
||
|
||
while (db_token() == '&') {
|
||
|
||
db_ntoken();
|
||
|
||
if (!relat(&rval))
|
||
|
||
return (FALSE);
|
||
|
||
if (!operator(db_xand))
|
||
|
||
return (FALSE);
|
||
|
||
}
|
||
|
||
*result = lval;
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
LOCAL int relat(result)
|
||
|
||
int *result;
|
||
|
||
{
|
||
|
||
int lval,rval;
|
||
|
||
int tkn;
|
||
|
||
|
||
|
||
if (!primary(&lval))
|
||
|
||
return (FALSE);
|
||
|
||
while (db_token() <= LSS && dbv_token >= GTR) {
|
||
|
||
tkn = db_ntoken();
|
||
|
||
if (!primary(&rval))
|
||
|
||
return (FALSE);
|
||
|
||
switch (tkn) {
|
||
|
||
case LSS:
|
||
|
||
if (!operator(db_xlss))
|
||
|
||
return (FALSE);
|
||
|
||
break;
|
||
|
||
case LEQ:
|
||
|
||
if (!operator(db_xleq))
|
||
|
||
return (FALSE);
|
||
|
||
break;
|
||
|
||
case EQL:
|
||
|
||
if (!operator(db_xeql))
|
||
|
||
return (FALSE);
|
||
|
||
break;
|
||
|
||
case NEQ:
|
||
|
||
if (!operator(db_xneq))
|
||
|
||
return (FALSE);
|
||
|
||
break;
|
||
|
||
case GEQ:
|
||
|
||
if (!operator(db_xgeq))
|
||
|
||
return (FALSE);
|
||
|
||
break;
|
||
|
||
case GTR:
|
||
|
||
if (!operator(db_xgtr))
|
||
|
||
return (FALSE);
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
*result = lval;
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
LOCAL int primary(result)
|
||
|
||
int *result;
|
||
|
||
{
|
||
|
||
int val;
|
||
|
||
int tkn;
|
||
|
||
|
||
|
||
if (db_token() == '~') {
|
||
|
||
tkn = db_ntoken();
|
||
|
||
if (!primary(&val))
|
||
|
||
return (FALSE);
|
||
|
||
switch (tkn) {
|
||
|
||
case '~':
|
||
|
||
if (!operator(db_xnot))
|
||
|
||
return (FALSE);
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
else
|
||
|
||
if (!factor(&val))
|
||
|
||
return (FALSE);
|
||
|
||
*result = val;
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
LOCAL int factor(result)
|
||
|
||
int *result;
|
||
|
||
{
|
||
|
||
int val;
|
||
|
||
|
||
|
||
if (db_token() == '(') {
|
||
|
||
db_ntoken();
|
||
|
||
if (!expr(&val))
|
||
|
||
return (FALSE);
|
||
|
||
if (db_token() != ')')
|
||
|
||
return (db_ferror(SYNTAX));
|
||
|
||
db_ntoken();
|
||
|
||
}
|
||
|
||
else
|
||
|
||
if (!get_operand(&val))
|
||
|
||
return (FALSE);
|
||
|
||
*result = val;
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* get_operand - get an operand (number, string, or attribute) */
|
||
|
||
LOCAL int get_operand(result)
|
||
|
||
int *result;
|
||
|
||
{
|
||
|
||
/* determine operand type */
|
||
|
||
if (db_ntoken() == NUMBER)
|
||
|
||
return (get_number(result));
|
||
|
||
else if (dbv_token == ID)
|
||
|
||
return (get_attr(result));
|
||
|
||
else if (dbv_token == STRING)
|
||
|
||
return (get_string(result));
|
||
|
||
else
|
||
|
||
return (db_ferror(SYNTAX));
|
||
|
||
}
|
||
|
||
|
||
|
||
/* get_attr - get an attribute argument */
|
||
|
||
LOCAL int get_attr(result)
|
||
|
||
int *result;
|
||
|
||
{
|
||
|
||
struct operand *opr;
|
||
|
||
char rname[RNSIZE+1],aname[ANSIZE+1];
|
||
|
||
char *aptr; int atype,alen;
|
||
|
||
|
||
|
||
#ifdef DEBUG
|
||
|
||
printf("*** get_attr(): dbv_tstring = %s\n", dbv_tstring);
|
||
|
||
#endif
|
||
|
||
/* save the attribute name */
|
||
|
||
strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;
|
||
|
||
|
||
|
||
/* check for a "." indicating a qualified attribute name */
|
||
|
||
if (db_token() == '.') {
|
||
|
||
db_ntoken();
|
||
|
||
|
||
|
||
/* the previous ID was really a relation name */
|
||
|
||
strcpy(rname,aname);
|
||
|
||
|
||
|
||
/* check for the real attribute name */
|
||
|
||
if (db_ntoken() != ID)
|
||
|
||
return (db_ferror(SYNTAX));
|
||
|
||
|
||
|
||
#ifdef DEBUG
|
||
|
||
printf("*** : dbv_tstring = %s\n", dbv_tstring);
|
||
|
||
#endif
|
||
|
||
/* save the attribute name */
|
||
|
||
strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;
|
||
|
||
|
||
|
||
/* lookup the attribute name */
|
||
|
||
if (!db_sattr(selptr,rname,aname,&atype,&aptr,&alen))
|
||
|
||
return (FALSE);
|
||
|
||
}
|
||
|
||
else
|
||
|
||
if (!db_sattr(selptr,NULL,aname,&atype,&aptr,&alen))
|
||
|
||
return (FALSE);
|
||
|
||
|
||
|
||
/* get a new operand structure */
|
||
|
||
if ((opr = malloc(sizeof(struct operand))) == NULL)
|
||
|
||
return (db_ferror(INSMEM));
|
||
|
||
|
||
|
||
/* initialize the new operand structure */
|
||
|
||
opr->o_type = ATTR;
|
||
|
||
opr->o_value.ov_char.ovc_type = atype;
|
||
|
||
opr->o_value.ov_char.ovc_string = aptr;
|
||
|
||
opr->o_value.ov_char.ovc_length = alen;
|
||
|
||
|
||
|
||
/* insert the operand into the code array */
|
||
|
||
if (!operand(opr)) {
|
||
|
||
free(opr);
|
||
|
||
return (FALSE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* store operand type */
|
||
|
||
*result = atype;
|
||
|
||
|
||
|
||
/* return successfully */
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* get_number - get a numeric operand */
|
||
|
||
LOCAL int get_number(result)
|
||
|
||
int *result;
|
||
|
||
{
|
||
|
||
struct operand *opr;
|
||
|
||
|
||
|
||
/* get a new operand structure */
|
||
|
||
if ((opr = malloc(sizeof(struct operand))) == NULL)
|
||
|
||
return (db_ferror(INSMEM));
|
||
|
||
|
||
|
||
/* initialize the new operand structure */
|
||
|
||
opr->o_type = LITERAL;
|
||
|
||
if ((opr->o_value.ov_char.ovc_string =
|
||
|
||
malloc(strlen(dbv_tstring)+1)) == NULL) {
|
||
|
||
free(opr);
|
||
|
||
return (db_ferror(INSMEM));
|
||
|
||
}
|
||
|
||
opr->o_value.ov_char.ovc_type = TNUM;
|
||
|
||
strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
|
||
|
||
opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);
|
||
|
||
|
||
|
||
/* insert the operand into the code array */
|
||
|
||
if (!operand(opr)) {
|
||
|
||
free(opr->o_value.ov_char.ovc_string); free(opr);
|
||
|
||
return (FALSE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* operand type is number */
|
||
|
||
*result = TNUM;
|
||
|
||
|
||
|
||
/* return successfully */
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* get_string - get a string operand */
|
||
|
||
LOCAL int get_string(result)
|
||
|
||
int *result;
|
||
|
||
{
|
||
|
||
struct operand *opr;
|
||
|
||
|
||
|
||
/* get a new operand structure */
|
||
|
||
if ((opr = malloc(sizeof(struct operand))) == NULL)
|
||
|
||
return (db_ferror(INSMEM));
|
||
|
||
|
||
|
||
/* initialize the new operand structure */
|
||
|
||
opr->o_type = LITERAL;
|
||
|
||
if ((opr->o_value.ov_char.ovc_string =
|
||
|
||
malloc(strlen(dbv_tstring)+1)) == NULL) {
|
||
|
||
free(opr);
|
||
|
||
return (db_ferror(INSMEM));
|
||
|
||
}
|
||
|
||
opr->o_value.ov_char.ovc_type = TCHAR;
|
||
|
||
strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
|
||
|
||
opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);
|
||
|
||
|
||
|
||
/* insert the operand into the code array */
|
||
|
||
if (!operand(opr)) {
|
||
|
||
free(opr->o_value.ov_char.ovc_string); free(opr);
|
||
|
||
return (FALSE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* operand type is character */
|
||
|
||
*result = TCHAR;
|
||
|
||
|
||
|
||
/* return successfully */
|
||
|
||
return (TRUE);
|
||
|
||
}
|
||
|
||
|
||
|
||
/* freelit - free the literals in a code array */
|
||
|
||
LOCAL freelit(cptr)
|
||
|
||
union codecell *cptr;
|
||
|
||
{
|
||
|
||
#ifdef Lattice
|
||
|
||
int (*dns)(); /*dns*/
|
||
|
||
for (; (*cptr).c_operator != (dns=db_xstop); cptr++) /*dns*/
|
||
|
||
if ((*cptr).c_operator == (dns=db_xpush) ) /*dns*/
|
||
|
||
#else
|
||
|
||
for (; (*cptr).c_operator != db_xstop; cptr++)
|
||
|
||
if ((*cptr).c_operator == db_xpush )
|
||
|
||
#endif
|
||
|
||
if ((*++cptr).c_operand->o_type == LITERAL)
|
||
|
||
free((*cptr).c_operand->o_value.ov_char.ovc_string);
|
||
|
||
}
|
||
|
||
|