/* ======================================================================== bisl_front.c - front-end routines for BISL Copyright 1996 Micah Beck / Simon D. Levy University of Tennessee All distributions of this product must include source code. Source code is not to be distributed in any modified form. Global routines: compile_file - compile named file constrain_node - constrain node using Boolean expression make_back - make a new background node make_image - make a new image node make_pane - make a pane node make_sound - make a new sound node make_text - make a new text node make_url - make a new URL node make_cstr - make a new out-only constraint make_point - make a new Cartesian coordinate point make_place - make a new placement-tuple make_string - make a new string-tuple add_place - add a named placement to specified region tuple make_infix - make infixed Boolean expression make_prefix - make prefixed Boolean expression make_terminal - make terminal Boolean expression ======================================================================== */ #include "bisl.h" static Dlist m_cstr_list, /* list of constraints in graph */ m_node_list; /* list of nodes in graph */ #define new_dlist(x) nilchk((x) = make_dl()) /* ------------------------------------------------------------------------ check_tuple - look up named tuple in table; return pointer to it if no problems ------------------------------------------------------------------------ */ static TUPL *check_tuple(char *name) { TUPL *tupl; char msg[80]; if (!(tupl = find_tupl(name))) { sprintf(msg, "symbol %s not found", name); fatal_error(msg); } return tupl; } /* check_tuple */ /* ------------------------------------------------------------------------ verify_tuple - look up named tuple in table; check its type; return pointer to it if no problems ------------------------------------------------------------------------ */ static TUPL *verify_tuple(char *name, TTAG what, char *callstr, char *whatstr) { TUPL *tupl; char msg[80]; tupl = check_tuple(name); if (tupl->what != what) { sprintf(msg, "%s works only with %s", callstr, whatstr); fatal_error(msg); } return tupl; } /* verify_tuple */ /* ------------------------------------------------------------------------ new_cstr - return pointer to new constraint of specified type ------------------------------------------------------------------------ */ static CSTR *new_cstr(CTAG what) { CSTR *cstr; new (cstr, CSTR); cstr->what = what; new_dlist(cstr->nodes_to); dl_insert_b(m_cstr_list, (void *)cstr); return cstr; } /* new_cstr */ /* ------------------------------------------------------------------------ new_node - return pointer to new node of specified type ------------------------------------------------------------------------ */ static NODE *new_node(NTAG what) { NODE *node; new(node, NODE); node->what = what; return node; } /* new_node */ /* ------------------------------------------------------------------------ new_tupl - return a pointer to a newly-allocated tuple of specified type ------------------------------------------------------------------------ */ static TUPL *new_tupl(TTAG what) { TUPL *tupl; new(tupl, TUPL); tupl->what = what; return tupl; } /* new_tupl */ /* ------------------------------------------------------------------------ new_region - make a region of specified type ------------------------------------------------------------------------ */ static TUPL *new_region(RTAG tag, char *rname) { REGSTRUCT *regptr; TUPL *tupl, *platupl=NULL; new(regptr, REGSTRUCT); regptr->what = tag; tupl = new_tupl(t_Region); tupl->uval.regptr = regptr; return tupl; } /* new_region */ /* ------------------------------------------------------------------------ new_visual - make a visual of specified type ------------------------------------------------------------------------ */ static TUPL *new_visual(VTAG tag) { VISSTRUCT *visptr; TUPL *tupl; new(visptr, VISSTRUCT); visptr->what = tag; tupl = new_tupl(t_Visual); tupl->uval.visptr = visptr; return tupl; } /* new_visual */ /* ------------------------------------------------------------------------ insert_visual_node - insert visual node into node list based on non-ascending depth ------------------------------------------------------------------------ */ static void insert_visual_node(NODE *node) { Dlist dp; PLASTRUCT *plaptr; NODE *np; int depth; plaptr = node->uval.plaptr; depth = plaptr->depth; dl_traverse(dp, m_node_list) { NODE *np = (NODE *)dp->val; if (np->what != n_Image && np->what != n_Text) continue; plaptr = np->uval.plaptr; if (plaptr->depth <= depth) { dl_insert_b(dp, node); /* insert inside list */ return; } } dl_insert_b(m_node_list, node); /* insert at end */ } /* insert_visual_node */ /* ------------------------------------------------------------------------ compile_file - compile named file ------------------------------------------------------------------------ */ void compile_file(char *fname) { FILE *fp; char errstr[80]; if (!(fp=fopen(fname, "r"))) /* attempt open; exit on failure */ { sprintf(errstr, "Error opening %s for input", fname); handle_error(errstr); } init_syms(); /* initialize symbol tables */ new_dlist(m_cstr_list); /* initialize constraint list */ new_dlist(m_node_list); /* initialize node list */ set_input(fp); /* make parser read from input file */ if (yyparse()) /* yyparse() is non-zero if had extra text */ { yyerror(); /* so we flag a syntax error */ exit(1); /* and quit */ } fclose(fp); /* done parsing */ gen_code(fname, m_node_list, /* generate code */ m_cstr_list); } /* compile_file */ /* ------------------------------------------------------------------------ constrain_node - constrain node using Boolean expression over constraints Local routine : r_add_node_to_cstr - recursively search to leaves of Boolean expression tree, adding node to each leaf's list of pointed-to nodes ------------------------------------------------------------------------ */ static void r_add_node_to_cstr(NODE *node, BEXP *bexp) { switch(bexp->oper) { case b_And: /* & */ case b_Or: /* | */ r_add_node_to_cstr(node, bexp->left); r_add_node_to_cstr(node, bexp->right); break; case b_Not: /* ~ */ r_add_node_to_cstr(node, bexp->left); break; default: /* terminal */ dl_insert_b(bexp->cstr->nodes_to, (void *)node); } /* switch(bexp->oper) */ } /* r_add_node_to_cstr */ void constrain_node(NODE *node, BEXP *bexp) { node->constraint = bexp; r_add_node_to_cstr(node, bexp); } /* constrain_node */ /* ------------------------------------------------------------------------ make_back - make a background-image node using specified visual ------------------------------------------------------------------------ */ NODE *make_back(char *vname) { BAKSTRUCT *bakptr; NODE *node; TUPL *vistupl; vistupl = verify_tuple(vname, t_Visual, "BACK", "visual"); new(bakptr, BAKSTRUCT); bakptr->visptr = vistupl->uval.visptr; node = new_node(n_Back); node->uval.bakptr = bakptr; dl_insert_b(m_node_list, (void *)node); return node; } /* make_back */ /* ------------------------------------------------------------------------ make_image - make an image node using specified placement ------------------------------------------------------------------------ */ NODE *make_image(char *pname) { NODE *node; TUPL *platupl; PLASTRUCT *plaptr; platupl = verify_tuple(pname, t_Place, "IMAGE", "PLACE"); plaptr = platupl->uval.plaptr; node = new_node(n_Image); node->uval.plaptr = plaptr; plaptr->node = node; insert_visual_node(node); return node; } /* make_image */ /* ------------------------------------------------------------------------ make_sound - make a sound-node using specified file name ------------------------------------------------------------------------ */ NODE *make_sound(char *fname) { SNDSTRUCT *sndptr; NODE *node; new(sndptr, SNDSTRUCT); sndptr->fname = fname; node = new_node(n_Sound); node->uval.sndptr = sndptr; dl_insert_b(m_node_list, (void *)node); return node; } /* make_sound */ /* ------------------------------------------------------------------------ make_text - make a text node using specified placement ------------------------------------------------------------------------ */ NODE *make_text(char *pname) { NODE *node; TUPL *platupl; PLASTRUCT *plaptr; platupl = verify_tuple(pname, t_Place, "TEXT", "PLACE"); plaptr = platupl->uval.plaptr; node = new_node(n_Text); node->uval.plaptr = plaptr; plaptr->node = node; insert_visual_node(node); return node; } /* make_text */ /* ------------------------------------------------------------------------ make_url - make a URL node using specified URL string ------------------------------------------------------------------------ */ NODE *make_url(char *uname) { URLSTRUCT *urlptr; NODE *node; new(urlptr, URLSTRUCT); urlptr->uname = uname; node = new_node(n_URL); node->uval.urlptr = urlptr; dl_insert_b(m_node_list, (void *)node); return node; } /* make_url */ /* ------------------------------------------------------------------------ make_cstr1 - add an output-only constraint of specified type to the graph, coming out of named tuple. Returns a pointer to the constraint. ------------------------------------------------------------------------ */ CSTR *make_cstr1(CTAG what, char *tname) { CSTR *cstr; TUPL *tupl; tupl = check_tuple(tname); if (tupl->what != t_Place && tupl->what != t_Region) fatal_error("Constraints allowed only from placements and regions"); cstr = new_cstr(what); cstr->tupl_from = tupl; return cstr; } /* make_cstr1 */ /* ------------------------------------------------------------------------ make_cstr2 - add an input-output constraint of specified type to the graph, coming out of named constraint. Returns a pointer to the new constraint. ------------------------------------------------------------------------ */ CSTR *make_cstr2(CTAG what, char *cname) { CSTR *cstr, *cstr_in; if (!(cstr_in=find_cstr(cname))) { char msg[100]; sprintf(msg, "Constraint %s not found", cname); fatal_error(msg); } cstr = new_cstr(what); cstr_in->cstr_to = cstr; return cstr; } /* make_cstr2 */ /* ------------------------------------------------------------------------ make_point - make a Cartesian coordinate point using specified coordinates). Returns a pointer to the point. ------------------------------------------------------------------------ */ POINT *make_point(int x, int y) { POINT *point; new(point, POINT); point->x = x; point->y = y; return point; } /* make_point */ /* ------------------------------------------------------------------------ make_circ - make a circle-tuple using upper-left coordinate point and lower-right coordinate point, and optional image-placement name ------------------------------------------------------------------------ */ TUPL *make_circ(POINT *center, int radius) { CIRSTRUCT *cirptr; TUPL *tupl; new(cirptr, CIRSTRUCT); cirptr->center = center; cirptr->radius = radius; tupl = new_region(r_Circ, "CIRC"); tupl->uval.regptr->uval.cirptr = cirptr; return tupl;; } /* make_circ */ /* ------------------------------------------------------------------------ make_giff - make a giff-tuple using specified file name ------------------------------------------------------------------------ */ TUPL *make_giff(char *fname) { GIFSTRUCT *gifptr; TUPL *tupl; new(gifptr, GIFSTRUCT); gifptr->fname = fname; tupl = new_visual(v_Giff); tupl->uval.visptr->uval.gifptr = gifptr; return tupl; } /* make_giff */ /* ------------------------------------------------------------------------ make_place - make an image placement using specified visual name, upper-left coordinate point, and depth ------------------------------------------------------------------------ */ TUPL *make_place(char *vname, POINT *ul_point, int depth) { PLASTRUCT *plaptr; TUPL *tupl, *vistupl; vistupl = verify_tuple(vname, t_Visual, "PLACE", "visual"); new(plaptr, PLASTRUCT); plaptr->ul_point = ul_point; plaptr->visptr = vistupl->uval.visptr; plaptr->depth = depth; tupl = new_tupl(t_Place); tupl->uval.plaptr = plaptr; return tupl; } /* make_place */ /* ------------------------------------------------------------------------ make_rect - make a rectangle-tuple using upper-left coordinate point, and lower-right coordinate point ------------------------------------------------------------------------ */ TUPL *make_rect(POINT *ul_point, POINT *lr_point) { RECSTRUCT *recptr; TUPL *tupl; new(recptr, RECSTRUCT); recptr->ul_point = ul_point; recptr->lr_point = lr_point; tupl = new_region(r_Rect, "RECT"); tupl->uval.regptr->uval.recptr = recptr; return tupl; } /* make_rect */ /* ------------------------------------------------------------------------ make_string - make a string tuple using specified string and optional font, style, size, and color specifications ------------------------------------------------------------------------ */ TUPL *make_string(char *string, char *font, char *style, int size, char *color) { STRSTRUCT *strptr; TUPL *tupl; new(strptr, STRSTRUCT); string[strlen(string)-1] = 0; /* cut off trailing ' */ strptr->string = &string[1]; /* cut off leading ' */ strptr->font = font ? font : DEFAULT_FONT; strptr->style = style ? style : DEFAULT_STYLE; strptr->size = size ? size : DEFAULT_SIZE; strptr->color = color ? color : DEFAULT_COLOR; tupl = new_visual(v_String); tupl->uval.visptr->uval.strptr = strptr; return tupl; } /* make_string */ /* ------------------------------------------------------------------------ add_place - add a named placement to specified region-tuple ------------------------------------------------------------------------ */ TUPL *add_place(TUPL *tupl, char *pname) { TUPL *platupl; platupl = verify_tuple(pname, t_Place, "region", "placements"); tupl->uval.regptr->plaptr = platupl->uval.plaptr; return tupl; } /* add_place */ /* ------------------------------------------------------------------------ make_infix - make infixed Boolean expression ------------------------------------------------------------------------ */ BEXP *make_infix(BEXP *lexp, BEXP *rexp, OPER oper) { BEXP *bexp; new(bexp, BEXP); bexp->left = lexp; bexp->right = rexp; bexp->oper = oper; return bexp; } /* make_infix */ /* ------------------------------------------------------------------------ make_prefix - make prefixed Boolean expression ------------------------------------------------------------------------ */ BEXP *make_prefix(BEXP *exp, OPER oper) { BEXP *bexp; new(bexp, BEXP); bexp->left = exp; bexp->oper = oper; return bexp; } /* make_prefix */ /* ------------------------------------------------------------------------ make_terminal - make terminal Boolean expression ------------------------------------------------------------------------ */ BEXP *make_terminal(char *ename) { BEXP *bexp; CSTR *cstr; char msg[256]; if (!ename) return; /* no cstr */ if (!(cstr = find_cstr(ename))) { char msg[80]; sprintf(msg, "cstr %s not found", ename); fatal_error(msg); } new(bexp, BEXP); bexp->cstr = cstr; return bexp; } /* make_terminal */