/* * handle_anchor * * handle tag <A>: * - check for HREF set * - update value for attribute HSC.ANCHOR */ BOOL handle_anchor(HSCPRC * hp, HSCTAG * tag) { HSCVAR *vhref = find_varname(tag->attr, "HREF"); HSCVAR *vname = find_varname(tag->attr, "NAME"); HSCVAR *vid = find_varname(tag->attr, "ID"); STRPTR href = NULL; STRPTR name = NULL; STRPTR id = NULL; /* set attribute values */ if (vhref) { href = vhref->text; } if (vname) { name = vname->text; } if (vid) { id = vid->text; } /* tell parser that he is inside an anchor */ if (href) { HSCATTR *anchor_attr = find_varname(hp->defattr, ANCHOR_ATTR); if (anchor_attr) { set_vartext(anchor_attr, href); } else { panic("no anchor-attribute"); } hp->inside_anchor = TRUE; } /* check for both HREF and NAME missing */ if ((!href) && (!name) && (!id)) { hsc_message(hp, MSG_ANCH_NO_NMHR, "%T without HREF, NAME or ID", tag); } return (TRUE); }
/* ** get_vartext_byname: get text value of a var ** ** */ STRPTR get_vartext_byname( DLLIST *varlist, STRPTR name ) { HSCVAR *var = find_varname( varlist, name ); STRPTR vartext = NULL; if ( var ) vartext = var->text; return( vartext ); }
/* ** get_varbool: get value of a boolean var */ BOOL get_varbool( DLLIST *varlist, STRPTR name ) { BOOL set = FALSE; HSCVAR *var = find_varname( varlist, name ); if ( var && var->text ) set = TRUE; return( set ); }
/* * set_local_var * * copies a local attribute to the global attribute list * * NOTE: the VF_MACRO-flag of the set is enabled! */ static HSCATTR *set_local_var(DLLIST * destlist, HSCATTR * locvar, ULONG mci) { HSCATTR *var = find_varname(destlist, locvar->name); if (var) { var->macro_id = mci; var->vartype = locvar->vartype; set_vartext(var, locvar->text); } else panic("set_local_var to UNKNOWN ATTR"); return (var); }
BOOL handle_hsc_content(HSCPRC * hp, HSCTAG * tag) { HSCATTR *content_attr = find_varname(hp->defattr, CONTENT_ATTR); /* attribute that contains content */ HSCTAG *macro = find_end_container_macro(hp); /* use current fileposition as base for including content */ INFILEPOS *fpos = new_infilepos(hp->inpf); if (!macro) { DMC(fprintf(stderr, DHL " no container macro on stack\n")); hsc_msg_no_content(hp); } else if (content_attr) { /* position where content text started */ INFILEPOS *start_content_fpos = macro->end_fpos; /* first node on content stack contains current content text */ DLNODE *first_content_text_node = dll_first(hp->content_stack); if (first_content_text_node) { /* pull first entry from content stack */ STRPTR content = (STRPTR) detach_dlnode(hp->content_stack, first_content_text_node); STRPTR old_content = strclone(get_vartext(content_attr)); DLLIST *old_attribs = init_dllist(del_hscattr); ULONG scope_id = get_current_mci(hp); DMC(fprintf(stderr, DHL " content=`%s'\n", content)); /* update content attribute */ set_vartext(content_attr, content); #ifndef EXPERIMENTAL_CONTAINER /* move local attributes from global list to buffer list */ copy_local_varlist(old_attribs, hp->defattr, scope_id); remove_local_varlist(hp->defattr, scope_id); /* switch back to above scope */ unget_mci(hp); #endif /* now include the macro content */ hsc_base_include_string(hp, SPECIAL_FILE_ID "macro-content", content, IH_NO_STATUS | IH_PARSE_MACRO, start_content_fpos); /* TODO: why IH_PARSE_MACRO? */ /* push entry pulled above back to content stack */ add_dlnode(hp->content_stack, content); #ifndef EXPERIMENTAL_CONTAINER /* restore local attribs and scope from before */ copy_local_varlist(hp->defattr, old_attribs, scope_id); get_mci(hp); #endif /* restore content attribute */ set_vartext(content_attr, old_content); /* free resources */ del_dllist(old_attribs); ufreestr(old_content); } else { DMC(fprintf(stderr, DHL " no content\n")); hsc_msg_no_content(hp); } } else { panic("no content attribute"); } /* cleanup */ del_infilepos(fpos); return (FALSE); }
/* * handle_content_macro * * handle for content macros * (with /CLOSE set at declaration) * * - scan macro content until corresponding end macro * tag is found * - increase scope * - define local HSC.CONTENT * - include macro text (not content!) * - remove HSC.CONTENT * */ static BOOL handle_content_macro(HSCPRC * hp, HSCTAG * tag) { EXPSTR *macro_content = init_estr(1024); /* contains macro contents */ HSCATTR *macro_content_attr = find_varname(hp->defattr, CONTENT_ATTR); /* attribute that contains contents, too */ HSCTAG *end_macro = NULL; STRPTR old_content = NULL; /* to store old value of content attr */ /* position where content starts */ INFILEPOS *start_content_fpos = new_infilepos(hp->inpf); DMC(fprintf(stderr, DHL "--BEGIN content macro <%s>\n", tag->name)); if (!macro_content_attr) { panic("no content attribute") } /* skip macro content until corresponding end macro is found; store * content in macro_content, but without the tag call for the end macro */ skip_until_tag(hp, macro_content, NULL, NULL, tag->name, SKUT_NO_CONTENT_TAGFOUND); /* store current value of content attribute */ { STRPTR old = get_vartext(macro_content_attr); if (old) { old_content = strclone(old); } } /* set content attribute with current macro content */ set_vartext(macro_content_attr, estr2str(macro_content)); /* push content to content stack */ add_strnode(hp->content_stack, estr2str(macro_content)); /* some debuggin info */ DMC(fprintf(stderr, DHL " content=`%s'\n", estr2str(macro_content))); DMC(fprintf(stderr, DHL " text =`%s'\n", estr2str(tag->op_text))); /* push current tag on container stack; this is * only necessary for tag modifiers /MCI and * /NAW, which would not work otherwise */ end_macro = append_end_tag(hp, tag); /* assign position of start of content to macro-tag */ end_macro->end_fpos = start_content_fpos; /* now include the macro text */ include_macro(hp, tag, estr2str(tag->op_text), SPECIAL_FILE_ID "content-macro", tag->start_fpos); /* pull macro tag from container stack */ end_macro->end_fpos = NULL; remove_end_tag(hp, tag); /* restore content attribute to previous value */ set_vartext(macro_content_attr, old_content); /* remove content from stack */ del_dlnode(hp->content_stack, dll_first(hp->content_stack)); /* cleanup */ ufreestr(old_content); del_estr(macro_content); del_infilepos(start_content_fpos); DMC(fprintf(stderr, DHL "--END content macro <%s>\n", tag->name)); return (FALSE); }
int add_model_variable (model *mod, dataset *ds, char *varname, int vartype) { int varidx, ividx; int i; int found = 0; char *intname; /* check for a recognized variable type */ switch (vartype) { case DEPENDENT: printlog(VERBOSE, "%s%s\n", "Adding DEPENDENT variable: ", varname); break; case MAIN: printlog(VERBOSE, "%s%s\n", "Adding MAIN EFFECT variable: ", varname); break; case DIRECT: printlog(VERBOSE, "%s%s\n", "Adding DIRECT EFFECT variable: ", varname); break; case NEW_INTERACTION: printlog(VERBOSE, "%s%s\n", "Adding FIRST INTERACTION variable: ", varname); break; case INTERACTION: printlog(VERBOSE, "%s%s\n", "Adding INTERACTION variable: ", varname); break; default: printlog(INFO, "%s%d%s%s\n", "Error: unrecognized variable type: ", vartype, " for variable: ", varname); return 1; } /* find the variable name and fail if not found */ varidx = find_varname(ds, varname); if (varidx == -1) { return 1; } /* add the DEPENDENT variable to the model */ if (vartype == DEPENDENT) { mod->dv = varidx; mod->dvname = estrdup(varname); return 0; } /* search the array of main effects */ for (i = 0; i < mod->numiv; i++) { if (varidx == mod->iv[i]) { found = 1; ividx = i; break; } } /* warn and return success, if MAIN or DIRECT variable already exists */ if (found && (vartype == MAIN || vartype == DIRECT)) { printlog(INFO, "%s%s\n", "Warning: variable already exists in model: ", varname); return 0; } else if (!found) { /* warn if this is an interaction effect without a main effect */ if (vartype == NEW_INTERACTION || vartype == INTERACTION) { printlog(INFO, "%s%s\n", "Warning: this interaction variable will also be added as a main effect: ", varname); } /* space check */ if (1 + mod->numiv > mod->maxiv) { mod->maxiv *= 2; mod->ivnames = (char **) erealloc(mod->ivnames, mod->maxiv * sizeof(char *)); mod->iv = (int *) erealloc(mod->iv, mod->maxiv * sizeof(int)); mod->direct = (int *) erealloc(mod->direct, mod->maxiv * sizeof(int)); } /* add this variable as a main effect */ mod->iv[mod->numiv] = varidx; mod->ivnames[mod->numiv] = estrdup(varname); mod->direct[mod->numiv] = (vartype == DIRECT) ? 1 : 0; printlog(VERBOSE, "Setting direct array index %d to value %d\n", mod->numiv, mod->direct[mod->numiv]); mod->numiv++; } /* add a new interaction */ if (vartype == NEW_INTERACTION) { /* space check */ if (1 + mod->numints > mod->maxints) { mod->maxints *= 2; mod->inttc = (int *) erealloc(mod->inttc, mod->maxints * sizeof(int)); mod->ints = (int **) erealloc(mod->ints, mod->maxints * sizeof(int *)); mod->intnames = (char **) erealloc(mod->intnames, mod->maxints * sizeof(char *)); } /* add this variable to the newly created interaction */ mod->ints[mod->numints] = (int *) emalloc(1 * sizeof(int)); /* set the index of the interaction variable in the iv array (not the dataset) */ mod->ints[mod->numints][0] = ividx; mod->inttc[mod->numints] = 1; mod->intnames[mod->numints] = estrdup(varname); mod->numints++; } /* append to an existing interaction */ if (vartype == INTERACTION) { /* search the terms in the latest interaction and warn if already found */ for (i = 0, found = 0; i < mod->inttc[mod->numints-1]; i++) { if (ividx == mod->ints[mod->numints-1][i]) { found = 1; break; } } /* warn if found */ if (found) { printlog(INFO, "%s%s\n", "Warning: interaction variable already exists: ", varname); return 0; } /* add this variable to the latest interaction */ mod->ints[mod->numints-1] = (int *) erealloc(mod->ints[mod->numints-1], (1 + mod->inttc[mod->numints-1]) * sizeof(int)); mod->ints[mod->numints-1][mod->inttc[mod->numints-1]] = ividx; intname = (char *) emalloc( strlen(mod->intnames[mod->numints-1]) + strlen(varname) + 2 ); strcpy(intname, mod->intnames[mod->numints-1]); strcat(intname, "*"); strcat(intname, varname); mod->intnames[mod->numints-1] = estrdup(intname); mod->inttc[mod->numints-1] += 1; } return 0; }
/* * init_hsctags * * define hsc tags & attributes; assign tagCBs for them * * NOTE: this ones tricky, but a bit perverted somehow */ BOOL hsc_init_tagsNattr(HSCPRC * hp) { #define INCLUDE_ATTR " PRE:bool SOURCE:bool TEMPORARY:bool" \ " INDENT:num TABSIZE:num=\"4\" " BYTE i = 0; BOOL ok = TRUE; BOOL open_tag; HSCTAG *tag; /* define hsc internal tags */ STRPTR hsc_prefs[] = { /* tags with special chars as name * * IMPORTANT: When adding new tags with names not starting with * HSC_TAGID, make sure to update `tag.c:is_hsc_tag()' */ HSC_COMMENT_STR " /SKIPLF /SPECIAL>", HSC_VERBATIM_STR" /SPECIAL>", HSC_INSEXPR_STR " /SPECIAL>", /* tags starting with HSC_TAGID */ HSC_CONTENT_STR " /SKIPLF>", HSC_DEFENT_STR " /SKIPLF NAME:string RPLC:string NUM:num PREFNUM:bool NONSTD:bool>", HSC_DEFSTYLE_STR " /SKIPLF NAME:string/r VAL:string>", HSC_DEFICON_STR " /SKIPLF NAME:string/r>", HSC_DEFINE_STR " /SKIPLF /SPECIAL>", HSC_DEFTAG_STR " /SKIPLF /SPECIAL>", HSC_DEPEND_STR " /SKIPLF ON:string/r FILE:bool>", HSC_ELSE_STR " /SKIPLF /MBI=\"" HSC_IF_STR "\">", HSC_ELSEIF_STR " /SKIPLF /MBI=\"" HSC_IF_STR "\"" CONDITION_ATTR ":bool>", HSC_MESSAGE_STR " /SKIPLF TEXT:string/r CLASS:enum(\"note|warning|error|fatal\")='note'>", HSC_EXEC_STR " /SKIPLF COMMAND:string/r REMOVE:enum(\"on|off|auto\")=\"auto\" ATTRIBUTE:string INCLUDE:bool FILE:string " INCLUDE_ATTR ">", HSC_EXPORT_STR " /SKIPLF FILE:string/r DATA:string/r APPEND:bool>", HSC_IF_STR " /SKIPLF /CLOSE " CONDITION_ATTR ":bool>", HSC_INSERT_STR " /OBSOLETE TEXT:string TIME:bool FORMAT:string>", HSC_INCLUDE_STR " /SKIPLF FILE:string/r " INCLUDE_ATTR ">", HSC_LAZY_STR " /SKIPLF /SPECIAL>", HSC_LET_STR " /SKIPLF /SPECIAL>", HSC_MACRO_STR " /SKIPLF /SPECIAL>", HSC_SOURCE_STR " /SKIPLF PRE:bool>", HSC_MATCH_STR "/SKIPLF NOCASE:bool RE:string/r S:string/r " "C0:string C1:string C2:string C3:string C4:string " "C5:string C6:string C7:string C8:string C9:string>", HSC_STRIPWS_STR " TYPE:enum(\"" STRIPWS_ENUM "\")=\"" STRIPWS_BOTH "\">", NULL }; STRPTR hsc_attribs[] = { /* * define hsc attributes */ /* name : type : default value */ SYSTEM_ATTR ":string/c" , SYSTEM_ATTR_ID, ANCHOR_ATTR ":string" , "this is a feature, not a bug", CONTENT_ATTR ":string/c" , NULL, RESULT_ATTR ":num=\"0\"", NULL, /* a bit strange */ FILESIZEFORMAT_ATTR ":string" , "%a%u", TIMEFORMAT_ATTR ":string" , "%d-%b-%Y, %H:%M", LINEFEED_ATTR ":string>" , NULL, HSCVERSION_ATTR ":num/c="STRINGIFY(VERSION), NULL, HSCREVISION_ATTR ":num/c="STRINGIFY(REVISION), NULL, NULL, NULL }; /* temporarily disable debugging output */ dbg_disable(hp); /* define hsc-tags */ i = 0; while (!(hp->fatal) && hsc_prefs[i]) { STRARR infname[20]; sprintf(infname, SPECIAL_FILE_ID "init%3d", i); hp->inpf = infopen_str(infname, hsc_prefs[i], 60); if (hp->inpf) { tag = def_tag_name(hp, &open_tag); ok = (tag && def_tag_args(hp, tag)); infclose(hp->inpf); } i++; } /* init hsc-attributes */ i = 0; while (!(hp->fatal) && hsc_attribs[i]) { define_attr_by_text(hp, hsc_attribs[i], hsc_attribs[i+1], 0); i+=2; } /* assign "\n" to linefeed-attribute */ set_vartext(find_varname(hp->defattr, LINEFEED_ATTR), "\n"); /* assign tag-callbacks to hsc-tags */ if (ok) { hsc_set_tagCB(hp, HSC_COMMENT_STR, handle_hsc_comment, NULL); hsc_set_tagCB(hp, HSC_CONTENT_STR, handle_hsc_content, NULL); hsc_set_tagCB(hp, HSC_DEFSTYLE_STR, handle_hsc_defstyle, NULL); hsc_set_tagCB(hp, HSC_DEFENT_STR, handle_hsc_defent, NULL); hsc_set_tagCB(hp, HSC_DEFICON_STR, handle_hsc_deficon, NULL); hsc_set_tagCB(hp, HSC_DEFINE_STR, handle_hsc_define, NULL); hsc_set_tagCB(hp, HSC_DEFTAG_STR, handle_hsc_deftag, NULL); hsc_set_tagCB(hp, HSC_DEPEND_STR, handle_hsc_depend, NULL); hsc_set_tagCB(hp, HSC_ELSE_STR, handle_hsc_else, NULL); hsc_set_tagCB(hp, HSC_ELSEIF_STR, handle_hsc_elseif, NULL); hsc_set_tagCB(hp, HSC_EXEC_STR, handle_hsc_exec, NULL); hsc_set_tagCB(hp, HSC_EXPORT_STR, handle_hsc_export, NULL); hsc_set_tagCB(hp, HSC_IF_STR, handle_hsc_if, handle_hsc_cif); hsc_set_tagCB(hp, HSC_INCLUDE_STR, handle_hsc_include, NULL); hsc_set_tagCB(hp, HSC_INSERT_STR, handle_hsc_insert, NULL); hsc_set_tagCB(hp, HSC_INSEXPR_STR, handle_hsc_insert_expression, NULL); hsc_set_tagCB(hp, HSC_COMMENT_STR, handle_hsc_comment, NULL); hsc_set_tagCB(hp, HSC_LAZY_STR, handle_hsc_lazy, NULL); hsc_set_tagCB(hp, HSC_LET_STR, handle_hsc_let, NULL); hsc_set_tagCB(hp, HSC_MACRO_STR, handle_hsc_macro, NULL); hsc_set_tagCB(hp, HSC_MESSAGE_STR, handle_hsc_message, NULL); hsc_set_tagCB(hp, HSC_VERBATIM_STR, handle_hsc_verbatim, NULL); hsc_set_tagCB(hp, HSC_SOURCE_STR, handle_hsc_source, NULL); hsc_set_tagCB(hp, HSC_MATCH_STR, handle_hsc_match, NULL); hsc_set_tagCB(hp, HSC_STRIPWS_STR, handle_hsc_stripws, NULL); } /* restore debugging output */ dbg_restore(hp); return (ok); }
/* * hsc_parse_amp * * parse ampersand ("&") */ BOOL hsc_parse_amp(HSCPRC * hp) { INFILE *inpf = hp->inpf; EXPSTR *amp_str = init_estr(0); if (!hp->fatal) { BOOL rplc = hp->smart_ent; /* TRUE, if "&" should be replaced */ hp_enable_output(hp, "entity"); if (rplc) { /* * test if char before and * after ">" is white-space */ int ch = infgetc(inpf); inungetc(ch, inpf); if (!(hsc_whtspc(ch) && estrlen(hp->whtspc))) rplc = FALSE; } if (rplc) { /* replace ampersand */ message_rplc(hp, "&", "&"); set_estr(amp_str, "&"); } else { /* * get entity-id, test for unknown entity */ char *nxtwd; DLNODE *nd; BOOL app_entity = TRUE; /* remember "&" */ set_estr(amp_str, infgetcw(inpf)); /* get entity id */ nxtwd = infgetw(inpf); /* TODO: check for white-space */ if (!strcmp(nxtwd, "#")) { /* * process numeric entity */ /* append "#" */ app_estr(amp_str, infgetcw(inpf)); nxtwd = infgetw(inpf); errno = 0; strtoul(nxtwd, NULL, 0); if (errno || strlen(infgetcws(inpf))) { hsc_message(hp, MSG_ILLG_NUM, /* illegal numeric entity */ "illegal numeric value %n for entity", nxtwd); } /* append entity specifier */ app_estr(amp_str, nxtwd); } else { /* * process text entity */ HSCVAR *attr = NULL; /* search for entity in list */ nd = find_dlnode(hp->defent->first, (APTR) nxtwd, cmp_strent); if (hp->jens && (nd == NULL)) { /* asume that entity is an attribute, * try to find it and append it's value */ attr = find_varname(hp->defattr, nxtwd); if (attr) { set_estr(amp_str, get_vartext(attr)); app_entity = FALSE; } } if ((nd == NULL) && (attr == NULL)) { hsc_message(hp, MSG_UNKN_ENTITY, "unknown %e", nxtwd); } else { /* check for icon-entity and warn about */ /* portability peoblem */ HSCENT *entity = dln_data(nd); if (entity->numeric == ICON_ENTITY) if (estrlen(hp->iconbase)) { replace_icon(hp, nxtwd); set_estr(amp_str, ""); app_entity = FALSE; } else { hsc_message(hp, MSG_ICON_ENTITY, "icon %e found", nxtwd); } } if (app_entity) /* append entity specifier */ app_estr(amp_str, nxtwd); } /* TODO: check for whitespace before ";" */ /* check for closing ';' */ parse_wd(hp, ";"); /* append ";" */ if (app_entity) app_estr(amp_str, infgetcw(inpf)); } /* output whole entity */ if (estrlen(amp_str)) hsc_output_text(hp, "", estr2str(amp_str)); del_estr(amp_str); #if (defined MSDOS & (!defined HSC_BILL)) #define WASTE_SIZE (1024*1024) /* waste some time */ { STRPTR mem1 = (STRPTR) umalloc(WASTE_SIZE); STRPTR mem2 = (STRPTR) umalloc(WASTE_SIZE); size_t i = WASTE_SIZE; while (i) { if (mem1[i] && mem2[i]) { mem1[i] = mem2[i]; } else { mem2[i] = mem1[i]; } i--; } ufree(mem2); ufree(mem1); } #endif } return (BOOL) (!hp->fatal); }
/* * define_var * * define a new var with reading its def from input file * (starts parsing after ":", so ":" has to be read before) * * params: varname..name of new var * varlist..list new var should be inserted at the beginning * inpf.....input file where to read def from * flag.....flags: VF_ONLYONCE to avoid re-definition of a var * result: ptr to new var * * definition syntax in input file: * <vartype>[/flag]["="<deftext value>] * legal vartypes: see VT_STR_xx in "vars.h" * legal flags : see VF_STR_xx in "vars.h" */ HSCATTR *define_var(HSCPRC * hp, DLLIST * varlist, ULONG unmasked_flags) { HSCATTR *var = NULL; /* result */ BOOL ok = FALSE; BYTE val_vartype = VT_NONE; /* var-type (numeric) */ BOOL newattr = FALSE; /* next word read from input */ STRPTR nw = NULL; STRPTR varname = NULL; BOOL eof_called = FALSE; /* used at end-of-func, if nw==NULL */ INFILE *inpf = hp->inpf; /* read attribute name */ nw = infget_attrid(hp); if (nw) varname = strclone(nw); /* remember attribute name */ else eof_called = TRUE; /* err_eof() called already */ /* read attribute type */ if (nw) { if (parse_wd(hp, ":")) { nw = infgetw(inpf); if (nw) val_vartype = str2vartype(nw); } else inungetcw(inpf); } if (nw) { /* * look if attr already exist; * if yes, clear old attribute * to redefine the new one */ var = find_varname(varlist, varname); if (var) { DLNODE *nd = find_attrnode(varlist, varname); /* remove old attribute */ if (nd) del_dlnode(varlist, nd); else panic("no node for redefined attribute"); hsc_message(hp, MSG_ATTR_REDEFINED, "redefined %a", varname); } /* * create new attribute */ DDA(fprintf(stderr, DHL "new attr: %s\n", varname)); var = app_var(varlist, varname); /* set type */ var->vartype = val_vartype; if (var->vartype == VT_ENUM) { /* init enum-attribute */ read_enum_str(hp, var); } else if (var->vartype == VT_BOOL) { /* init boolean attr with FALSE */ set_varbool(var, FALSE); } newattr = TRUE; } /* disable "/STRIPEXT" and "/GETSIZE" for non-URI-attributes */ if (nw) { if (var->vartype != VT_URI) unmasked_flags |= VF_GETSIZE | VF_STRIPEXT; nw = infgetw(inpf); /* get net word */ } /* * handle attribute flags */ while (nw && !strcmp(nw, "/")) { nw = infgetw(inpf); /* read flag identifier */ if (nw) { BOOL ok = FALSE; ok |= check_attr_option(hp, nw, var, VF_CONST_STR, VF_CONST_SHT, VF_CONST, unmasked_flags); ok |= check_attr_option(hp, nw, var, VF_GLOBAL_STR, VF_GLOBAL_SHT, VF_GLOBAL, unmasked_flags); ok |= check_attr_option(hp, nw, var, VF_JERK_STR, VF_JERK_SHT, VF_JERK, unmasked_flags); ok |= check_attr_option(hp, nw, var, VF_ONLYONCE_STR, VF_ONLYONCE_SHT, VF_ONLYONCE, unmasked_flags); ok |= check_attr_option(hp, nw, var, VF_REQUIRED_STR, VF_REQUIRED_SHT, VF_REQUIRED, unmasked_flags); ok |= check_attr_option(hp, nw, var, VF_GETSIZE_STR, VF_GETSIZE_SHT, VF_GETSIZE, unmasked_flags); ok |= check_attr_option(hp, nw, var, VF_STRIPEXT_STR, VF_STRIPEXT_SHT, VF_STRIPEXT, unmasked_flags); ok |= check_attr_option(hp, nw, var, VF_OBSOLETE_STR, VF_OBSOLETE_SHT, VF_OBSOLETE, unmasked_flags); ok |= check_attr_option(hp, nw, var, VF_RECOMMENDED_STR, VF_RECOMMENDED_SHT, VF_RECOMMENDED, unmasked_flags); if (!ok) { hsc_message(hp, MSG_UNKN_ATTR_OPTION, "unknown attribute flag %q", nw); } /* read next word (should be "/", "=" or next attr / ">") */ nw = infgetw(inpf); } else hsc_msg_eof(hp, "defining attribute"); } /* * handle default value */ if (nw && !strcmp(nw, "=")) { /* get new deftext value */ STRPTR new_deftext = NULL; LONG old_attrflag = var->varflag; /* disable quotemode-checking */ var->varflag |= VF_KEEP_QUOTES; if (!(var->deftext)) new_deftext = eval_expression(hp, var, NULL); else { STRPTR dummy; hsc_message(hp, MSG_SYMB_2ND_DEFAULT, "default value for %A already set", var); /* skip illegal default value */ dummy = eval_expression(hp, var, NULL); } /* restore quotemode-checking */ var->varflag = old_attrflag; /* store default text value */ if (new_deftext) var->deftext = strclone(new_deftext); /* read next word, only to be ungotten below */ nw = infgetw(inpf); } /* check for unexpected end of file */ if (!nw) { if (!eof_called) hsc_msg_eof(hp, "defining attribute"); } else { /* end of var definition reached */ inungetcw(inpf); ok = TRUE; } /* cleanup */ if (!ok && var) { DLNODE *nd = find_attrnode(varlist, varname); if (nd) del_dlnode(varlist, (APTR) nd); else del_hscattr(var); var = NULL; } ufreestr(varname); return (var); }
/* ** define_var ** ** define a new var with reading its def from input file ** (starts parsing after ":", so ":" has to be read before) ** ** params: varname..name of new var ** varlist..list new var should be inserted at the beginning ** inpf.....input file where to read def from ** flag.....flags: VF_ONLYONCE to avoid re-definition of a var ** result: ptr to new var ** ** definition syntax in input file: ** <vartype>[/flag]["="<deftext value>] ** legal vartypes: see VT_STR_xx in "vars.h" ** legal flags : see VF_STR_xx in "vars.h" */ HSCVAR *define_var( STRPTR varname, DLLIST *varlist, INFILE *inpf, UBYTE flag ) { HSCVAR *var = NULL; /* result */ BOOL ok = FALSE; BYTE val_vartype = VT_NONE; /* var-type (numeric) */ BOOL newattr = FALSE; STRPTR nw = infgetw( inpf ); /* next word read from input */ /* read (optional) var type */ if ( nw ) { if ( !strcmp( nw, ":" ) ) { nw = infgetw( inpf ); if ( nw ) val_vartype = str2vartype( nw ); else err_eof( inpf, "defining attribute" ); } else inungetcw( inpf ); } else err_eof( inpf, "defining attribute" ); /* look if attr already exist, */ var = find_varname( varlist, varname ); if ( !var ) { /* create new attr */ DDA( fprintf( stderr, "** new attr: %s\n", varname ) ); var = app_var( varlist, varname ); if ( val_vartype == VT_NONE ) { /* TODO: error message "attr type expected" */ /* asume generic attribute type "STRING" */ val_vartype = VT_STRING; } /* set type */ var->vartype = val_vartype; /* init enum-attribute */ if ( var->vartype == VT_ENUM ) { var->varflag |= VF_NOQUOTE; read_enum_str( var, inpf ); } newattr = TRUE; } else { /* check for illegal redefinance */ if ( !( flag & VF_UPDATE ) ) { message( MSG_ATTR_REDEFINED, inpf ); errstr( "redefinance of" ); errsym( varname ); errlf(); } /* attr already exists: check for type consistence */ if ( ( val_vartype != VT_NONE ) && ( val_vartype != var->vartype ) ) { /* TODO: error message attr type inconsistent */ } } /* get next word */ nw = infgetw( inpf ); if ( !nw ) err_eof( inpf, "defining attribute" ); /* ** loop: handle flags and deftext value */ while ( nw ) { if ( !strcmp( nw, "=" ) ) { /* get new deftext value */ STRPTR new_deftext; if ( !(var->deftext) ) new_deftext = eval_expression( var, inpf, NULL ); else { STRPTR dummy; message( MSG_SYMB_2ND_DEFAULT, inpf ); errstr( "default value for" ); errsym( var->name ); errstr( "already set\n" ); /* skip illegal default value */ dummy = eval_expression( var, inpf, NULL ); } /* store default text value */ if ( new_deftext ) var->deftext = strclone( new_deftext ); /* check deftext value */ if ( var->vartype == VT_BOOL ) { /* check boolean value */ message( MSG_SYMB_BOOL_DEFAULT, inpf ); errstr( "no default value for boolean" ); errsym( var->name ); errstr( "allowed\n" ); } else if ( var->vartype == VT_NUM ) { /* TODO: test-set value with default value */ /* check numeric value */ LONG num; if ( sscanf( var->text, "%d", &num ) != strlen(var->text) ) { ok = FALSE; message( MSG_ILLEGAL_NUM, inpf ); errstr( "Illegal numeric value: " ); errstr( var->text ); errlf(); } } /* clear boolean var */ /* TODO: why set new bool to ""? */ if ( var->vartype == VT_BOOL ) { var->quote = VQ_NO_QUOTE; var->deftext = strclone( "" ); } } else if ( !strcmp( nw, "/" ) ) { /* set flag */ nw = infgetw( inpf ); if ( flag & VF_UPDATE ) { if ( nw ) { BOOL ok = FALSE; ok |= check_attr_option( nw, var, VF_JERK_STR, VF_JERK_SHT, VF_JERK ); ok |= check_attr_option( nw, var, VF_NOQUOTE_STR, VF_NOQUOTE_SHT, VF_NOQUOTE ); ok |= check_attr_option( nw, var, VF_ONLYONCE_STR, VF_ONLYONCE_SHT, VF_ONLYONCE ); ok |= check_attr_option( nw, var, VF_REQUIRED_STR, VF_REQUIRED_SHT, VF_REQUIRED ); if ( !ok ) { message( MSG_UNKN_ATTR_OPTION, inpf ); errstr( "Unknown attribute option " ); errqstr( nw ); errlf(); } } else err_eof( inpf, "defining attribute" ); } else { /* TODO: error message "no attr flags when updating" */ } } else { /* end of var definition reached */ inungets( nw, inpf ); nw = NULL; ok = TRUE; } /* get next word */ if ( nw ) nw = infgetw( inpf ); } /* while(nw) */ if ( !ok && var ) { del_dlnode( varlist, (APTR) var ); var = NULL; } return (var); }
/* ** get_varbool_byname: get value of a boolean var */ BOOL get_varbool_byname( DLLIST *varlist, STRPTR name ) { HSCVAR *var = find_varname( varlist, name ); return( get_varbool( var ) ); }
/* ** set_tag_arg ** ** parse & set one single tag argument ** */ static BOOL set_tag_arg( HSCPRC *hp, DLLIST *varlist, STRPTR varname ) { HSCATTR *var = find_varname( varlist, varname ); INFILE *inpf = hp->inpf; STRPTR arg = NULL; BOOL ok = FALSE; STRPTR nw; HSCATTR skipvar; /* dummy attribute to skip unkown */ EXPSTR *attr_str = init_estr( 40 ); /* string for attribute name */ EXPSTR *val_str = init_estr( 40 ); /* string for "=" and value */ DAV( fprintf( stderr, DHL " set attr %s\n", varname ) ); /* append attribute name to attr_str */ app_estr( attr_str, infgetcws( inpf ) ); app_estr( attr_str, infgetcw( inpf ) ); if ( !var ) { /* attribute not found */ /* assign to pseudo-attribute */ var = &skipvar; var->name = varname; var->deftext = NULL; var->text = NULL; var->enumstr = NULL; var->vartype = VT_STRING; var->varflag = 0; /* message: unknown attribute */ hsc_msg_unkn_attr( hp, varname ); } /* get argument */ nw = infgetw( inpf ); if ( nw ) if ( !strcmp( nw, "=" ) ) { /* append "=" to log */ app_estr( val_str, infgetcws( inpf ) ); app_estr( val_str, infgetcw( inpf ) ); /* parse expression */ arg = eval_expression( hp, var, NULL ); /* append value to log */ if ( var->quote != VQ_NO_QUOTE ) app_estrch( val_str, var->quote ); if ( get_vartext( var ) ) app_estr( val_str, get_vartext( var ) ); if ( var->quote != VQ_NO_QUOTE ) app_estrch( val_str, var->quote ); if ( arg ) { DAV( fprintf( stderr, DHL " `%s'\n", arg ) ); ok = TRUE; } } else { arg = NULL; inungetcwws( inpf ); ok = TRUE; } else hsc_msg_eof( hp, "read attribute value" ); if ( ok ) if ( arg ) { if ( var->vartype == VT_BOOL ) { /* set boolean attribute depending on expression */ set_vartext_bool( var, get_varbool( var ) ); /* if the expression returned FALSE, remove ** the boolean switch from the call */ if ( !get_varbool( var ) ) clr_estr( attr_str ); } else /* append value to attribute string */ app_estr( attr_str, estr2str( val_str ) ); } else { /* no value has been passed to the attribute */ if ( var->vartype == VT_BOOL ) { /* for boolean attributes, this is legal, ** and enables the attribute */ set_vartext_bool( var, TRUE ); } else { /* for non-boolean attributes, display ** error message */ hsc_message( hp, MSG_NOARG_ATTR, "missing value for %A", var ); } } #if 0 if ( arg ) { if ( var->vartype == VT_BOOL ) { message( MSG_ARG_BOOL_ATTR, inpf ); errstr( "value for boolean" ); errsym( var->name ); errlf(); } } else { if ( var->vartype == VT_BOOL ) { /* set boolean attribute */ DAV( fprintf( stderr, " (bool)\n", var->name ) ); set_vartext( var, var->name ); var->quote = VQ_NO_QUOTE; } else { } } #endif /* cleanup pseudo-attr */ if ( var == &skipvar ) clr_vartext( var ); /* append & cleanup attribute and value string */ app_estr( hp->tag_attr_str, estr2str( attr_str ) ); del_estr( attr_str ); del_estr( val_str ); return( ok ); }
/* ** define_var ** ** define a new var with reading its def from input file ** (starts parsing after ":", so ":" has to be read before) ** ** params: varname..name of new var ** varlist..list new var should be inserted at the beginning ** inpf.....input file where to read def from ** flag.....flags: VF_ONLYONCE to avoid re-definition of a var ** result: ptr to new var ** ** definition syntax in input file: ** <vartype>[/flag]["="<deftext value>] ** legal vartypes: see VT_STR_xx in "vars.h" ** legal flags : see VF_STR_xx in "vars.h" */ HSCVAR *define_var( STRPTR varname, DLLIST *varlist, INFILE *inpf, UBYTE flag ) { HSCVAR *var = NULL; /* result */ BOOL ok = FALSE; STRPTR str_vartype = infgetw( inpf ); /* var-type (string) */ BYTE val_vartype = VT_NONE; /* var-type (numeric) */ /* evaluate var type */ if ( str_vartype ) val_vartype = str2vartype( str_vartype ); else err_eof( inpf, "defining attribute" ); if ( val_vartype == VT_NONE ) { /* illegal var type */ message( MSG_ILLEGAL_SYMB_TYPE, inpf ); errstr( "Illegal variable type \"" ); errstr( str_vartype ); errstr( "\"\n" ); } else { /* look if var already exist, */ /* create new var if neccessary */ var = find_varname( varlist, varname ); if ( !var ) { DDA( fprintf( stderr, "** new var: %s\n", varname ) ); var = app_var( varlist, varname ); } if ( !var ) err_mem( inpf ); else { STRPTR nw; /* next word from input file */ /* set vartype */ var->vartype = val_vartype; /* init enum-attribute */ if ( var->vartype == VT_ENUM ) { var->varflag |= VF_NOQUOTE; read_enum_str( var, inpf ); } /* get next word */ nw = infgetw( inpf ); if ( !nw ) err_eof( inpf, "defining attribute" ); /* ** loop: handle flags and deftext value */ while ( nw ) { if ( !strcmp( nw, "=" ) ) { /* get new deftext value */ STRPTR new_deftext; if ( !(var->deftext) ) new_deftext = parse_vararg( var, inpf ); else { message( MSG_SYMB_2ND_DEFAULT, inpf ); errstr( "Default value for" ); errsym( var->name ); errstr( "already set\n" ); } /* store default text value */ if ( new_deftext ) var->deftext = strclone( new_deftext ); /* check deftext value */ if ( var->deftext && clr_vartext( var ) ) { if ( var->vartype == VT_BOOL ) { /* check boolean value */ message( MSG_SYMB_BOOL_DEFAULT, inpf ); errstr( "No default value for boolean" ); errsym( var->name ); errstr( "allowed\n" ); } else if ( var->vartype == VT_NUM ) { /* check numeric value */ LONG num; if ( sscanf( var->text, "%d", &num ) != strlen(var->text) ) { ok = FALSE; message( MSG_ILLEGAL_NUM, inpf ); errstr( "Illegal numeric value: " ); errstr( var->text ); errlf(); } } } else err_mem( inpf ); /* clear boolean var */ if ( var->vartype == VT_BOOL ) { var->quote = VQ_NO_QUOTE; var->deftext = strclone( "" ); if ( !var->deftext ) err_mem( inpf ); } } else if ( !strcmp( nw, "/" ) ) { /* set flag */ nw = infgetw( inpf ); if ( nw ) { BOOL ok = FALSE; ok |= check_attr_option( nw, var, VF_JERK_STR, VF_JERK_SHT, VF_JERK ); ok |= check_attr_option( nw, var, VF_NOQUOTE_STR, VF_NOQUOTE_SHT, VF_NOQUOTE ); ok |= check_attr_option( nw, var, VF_ONLYONCE_STR, VF_ONLYONCE_SHT, VF_ONLYONCE ); ok |= check_attr_option( nw, var, VF_REQUIRED_STR, VF_REQUIRED_SHT, VF_REQUIRED ); if ( !ok ) { message( MSG_UNKN_ATTR_OPTION, inpf ); errstr( "Unknown attribute option " ); errqstr( nw ); errlf(); } } else err_eof( inpf, "defining attribute" ); } else { /* end of var definition reached */ inungets( nw, inpf ); nw = NULL; ok = TRUE; } /* get next word */ if ( nw ) nw = infgetw( inpf ); } /* while(nw) */ } /* if(!var) */ } /* if(val_vartype..) */ if ( !ok && var ) { del_dlnode( varlist, (APTR) var ); var = NULL; } return (var); }
/* ** parse_vararg: read & check a attribute value */ STRPTR parse_vararg( HSCVAR *var, INFILE *inpf ) { STRPTR str_vararg = NULL; /* return value */ int ch; /* char read from input */ /* TODO: handle "<>" (reset var->text to NULL) */ infskip_ws( inpf ); /* disable log */ inflog_disable( inpf ); /* read var->quote char */ ch = infgetc( inpf ); if ( !strchr( VQ_STR_QUOTE, ch ) ) if ( ch != EOF ) var->quote = VQ_NO_QUOTE; else err_eof( inpf, "reading attribute" ); else var->quote = ch; /* warning if no quote */ if ( ( var->quote == VQ_NO_QUOTE ) && !( var->varflag & VF_NOQUOTE ) ) { message( MSG_ARG_NO_QUOTE, inpf ); errstr( "Argument without quote\n" ); } /* read arg string */ if ( var->quote == '<' ) { /* ** get arg from other var */ STRPTR nw = infgetw( inpf ); if ( nw ) { HSCVAR *refvar = find_varname( vars, nw ); if ( refvar ) { /* TODO: type checking */ var->quote = refvar->quote; str_vararg = refvar->text; /* check empty/circular reference */ if ( !str_vararg ) { message( MSG_EMPTY_SYMB_REF, inpf ); errstr( "Empty reference to" ); errsym( var->name ); errlf(); } /* debugging message */ DDA( fprintf( stderr, "** %s refers to <%s>\n", var->name, refvar->name ) ); } else { /* reference to unknown var */ message( MSG_UNKN_SYMB_REF, inpf ); errstr( "reference to unknown" ); errsym( nw ); errlf(); } if ( (!refvar) || (!str_vararg ) ) { /* return empty var */ var->quote = '"'; str_vararg = ""; } parse_gt( inpf ); } else err_eof( inpf, "reading attribute" ); } else if ( var->quote != EOF ) { /* ** get arg from input file */ BOOL end = FALSE; /* clear vararg or set with first char read */ if ( var->quote == VQ_NO_QUOTE ) end = !set_estr( vararg, ch2str( ch ) ); else end = !clr_estr( vararg ); if ( end ) err_mem( inpf ); /* ** read next char from input file until a ** closing quote if found. ** if the arg had no quote, a white space ** or a '>' is used to detect end of arg. ** if a LF is found, view error message */ while ( !end ) { ch = infgetc( inpf ); end = TRUE; if ( ch == EOF ) err_eof( inpf, "reading attribute" ); else if ( (ch==var->quote) || ( ch==CH_LF ) || ( (var->quote==VQ_NO_QUOTE) && ( inf_isws(ch,inpf) || ( ch=='>' ) ) ) ) { /* end of arg reached */ str_vararg = estr2str( vararg ); if ( var->quote == VQ_NO_QUOTE ) { if ( ch==CH_LF ) err_streol( inpf ); inungetc( ch, inpf ); } } else { /* append next char to vararg */ if ( !app_estrch( vararg, ch ) ) err_mem( inpf ); else end = FALSE; /* continue loop */ } } } if ( str_vararg && var ) /* ** check enum type */ if (var->vartype == VT_ENUM) check_enumstr( var, str_vararg, inpf ); /* ** parse uri (only if no macro-attr) ** (convert abs.uris, check existence) */ else if (var->vartype == VT_URI ) if ( !(var->varflag & VF_MACRO) ) str_vararg = parse_uri( str_vararg, inpf ); else { DDA( fprintf( stderr, "** didn't parse uri \"%s\"\n", str_vararg ) ); } /* update and enable log */ if ( !fatal_error ) { BOOL ok = TRUE; if ( var->quote != VQ_NO_QUOTE ) ok &= inflog_app( inpf, ch2str( var->quote ) );/* append quote */ inflog_app( inpf, str_vararg ); /* append arg */ if ( var->quote != VQ_NO_QUOTE ) ok &= inflog_app( inpf, ch2str( var->quote ) );/* append quote */ inflog_enable( inpf ); /* enable log */ if ( !ok ) err_mem( NULL ); } return ( str_vararg ); }