/* -*-c,save-*- */ /* SDB - expression compiler syntax: ::= ::= { '|' } ::= { '&' } ::= { } ::= | ::= | | '(' ')' ::= | ::= '"' '"' ::= nil | ::= '=' | '<>' | '<' | '>' | '<=' | '>=' ::= '+' | '-' | '~' */ #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); }