/* * handle_heading: tag handle for <H1>..<H6> * * compute number of haeding, * compare it with previous heading, * check first heading to be <H1> * */ BOOL handle_heading(HSCPRC * hp, HSCTAG * tag) { BYTE num = (tag->name[1] - '0'); /* num of heading (1..6) */ D(fprintf(stderr, DHL " heading %d\n", num)); /* check for <Hx> inside <A> */ if (find_strtag(hp->container_stack, "A")) { hsc_message(hp, MSG_ANCHOR_HEADING, "heading inside anchor"); } if ((hp->prev_heading_num - num) < (-1)) { char hstr[4]; sprintf(hstr, "H%ld", hp->prev_heading_num + 1); hsc_message(hp, MSG_WRONG_HEADING, "expected heading %t", hstr); } hp->prev_heading_num = num; return (TRUE); }
/* hsc_msg_unknown_id: warning about unknown id-refrence */ VOID hsc_msg_unknown_id(HSCPRC * hp, STRPTR filename, STRPTR id) { if (filename) hsc_message(hp, MSG_UNKN_ID, "unknown id `%s#%s'", filename, id); else hsc_message(hp, MSG_UNKN_ID, "unknown id %q", id); }
/* * hsc_parse_end * * check for all tags closed and required * tags occured */ BOOL hsc_parse_end(HSCPRC * hp) { if (!hp->fatal) { /* remember current file position */ INFILEPOS *infpos = new_infilepos(hp->inpf); DLNODE *nd = NULL; /* check for unclosed containers: * for every container tag still on stack launch a message, * exept for autoclose tags */ nd = hp->container_stack->last; while (nd) { HSCTAG *endtag = (HSCTAG *) dln_data(nd); if (!(endtag->option & HT_AUTOCLOSE)) { set_infilepos(hp->inpf, endtag->start_fpos); hsc_message(hp, MSG_MISS_CTAG, "%c missing", endtag->name); } nd = dln_prev(nd); } /* restore file position */ set_infilepos(hp->inpf, infpos); del_infilepos(infpos); /* check for required and recommended tags missing */ nd = dll_first(hp->deftag); while (nd) { HSCTAG *tag = (HSCTAG *) dln_data(nd); if ((tag->option & HT_REQUIRED && (tag->occured == FALSE))) { hsc_message(hp, MSG_MISS_REQTAG, "required %T missing", tag); } else if ((tag->option & HT_RECOMMENDED && (tag->occured == FALSE))) { hsc_message(hp, MSG_MISS_RCMDTAG, "recommended %T missing", tag); } nd = dln_next(nd); } /* output last white spaces at eof */ hsc_output_text(hp, "", ""); } return (BOOL) (!hp->fatal); }
/* * check_mbinaw * * check if tag occures in allowed context with other tags */ static BOOL check_mbinaw(HSCPRC * hp, HSCTAG * tag) { BOOL ok = TRUE; /* check for tags that must be called before */ if (tag->mbi) { DLNODE *nd = hp->container_stack->first; LONG found = 0; while (nd && !found) { HSCTAG *ctag = (HSCTAG *) nd->data; found = strenum(ctag->name, tag->mbi, '|', STEN_NOCASE); nd = nd->next; } if (!found) { hsc_message(hp, MSG_MBI, "%T must be inside %t", tag, tag->mbi); ok = FALSE; } } /* check for tags that are not to be called before */ if (tag->naw) { DLNODE *nd = hp->container_stack->last; LONG found = 0; while (nd) { HSCTAG *ctag = (HSCTAG *) nd->data; found = strenum(ctag->name, tag->naw, '|', STEN_NOCASE); if (found) { hsc_message(hp, MSG_NAW, "%T not allowed within %T", tag, ctag); ok = FALSE; } nd = dln_prev(nd); } } return ok; }
/* replace icon-entity by image */ static VOID replace_icon(HSCPRC * hp, STRPTR icon) { INFILEPOS *base = new_infilepos(hp->inpf); EXPSTR *image = init_estr(0); STRPTR s = estr2str(hp->iconbase); /* create string like <IMG SRC=":icons/back.gif" ALT="back"> */ set_estr(image, "<IMG SRC=\""); /* use iconbase with "*" replaced by iconname as uri */ while (s[0]) { if (s[0] == '*') app_estr(image, icon); else app_estrch(image, s[0]); s++; } /* set ALT attribute to iconname */ app_estr(image, "\" ALT=\""); app_estr(image, icon); app_estr(image, "\">"); hsc_message(hp, MSG_RPLC_ICON, "replacing icon-%e", icon); hsc_include_string(hp, SPECIAL_FILE_ID "include icon", estr2str(image), IH_PARSE_HSC | IH_NO_STATUS | IH_POS_PARENT); del_estr(image); del_infilepos(base); }
/* ** hsc_include_file ** ** open input file and include it */ BOOL hsc_base_include_file( HSCPRC *hp, STRPTR filename, ULONG optn, INFILEPOS *base_pos ) { BOOL ok = FALSE; STRARR msg[ 200 ]; /* TODO: use expstr */ INFILE *inpf = NULL; /* status message: reading input */ if ( !(optn & (IH_PARSE_MACRO | IH_PARSE_HSC)) ) { sprintf( msg, "reading `%s'", filename ); hsc_status_misc( hp, msg ); } /* open & read input file */ inpf = infopen( filename, ES_STEP_INFILE ); if ( inpf ) /* include opened file */ ok = hsc_include( hp, inpf, optn, base_pos ); else { /* couldn't open file */ hsc_message( hp, MSG_NO_INPUT, "can not open %q for input: %s", filename, strerror( errno ) ); } return( ok ); }
/* * hsc_read_prefs * * try to open (any) config file and read preferences * from it */ static BOOL hsc_read_prefs(HSCPRC * hp, STRPTR prefs_fname) { BOOL ok = FALSE; EXPSTR *prefs_name_buffer = init_estr(32); /* find prefs file */ if (!prefs_fname) prefs_fname = find_prefs_fname(hp, prefs_name_buffer); /* status message */ if (prefs_fname) { dbg_disable(hp); hsc_status_file_begin(hp, prefs_fname); ok = hsc_include_file(hp, prefs_fname, IH_PARSE_HSC | IH_NO_STATUS); dbg_restore(hp); if (ok) { EXPSTR *msg = init_estr(32); set_estr(msg, prefs_fname); app_estr(msg, ": preferences read"); hsc_status_misc(hp, estr2str(msg)); del_estr(msg); } } else hsc_message(hp, MSG_NO_CONFIG, "can not open preferences file"); del_estr(prefs_name_buffer); return (ok); }
/* * check_varlist: check for required attributes missing * * result: TRUE, if all attributes ok */ static BOOL check_reqvar(HSCPRC * hp, HSCATTR * var) { BOOL ok = TRUE; if ((var->varflag & VF_RECOMMENDED) && (!var->text)) hsc_message(hp, MSG_MISS_RCMD_ATTR, "recommended %A missing", var); if ((var->varflag & VF_REQUIRED) && (!var->text)) { hsc_message(hp, MSG_MISS_REQ_ATTR, "required %A missing", var); ok = FALSE; } return (ok); }
/* * parse_wd * * check if a expected word really occured and * display error message if neccessary * * params: inpf.....input file to read char from * expstr...expected word * result: TRUE if successful, FALSE if wrong char found */ BOOL parse_wd(HSCPRC * hp, STRPTR expstr) { INFILE *inpf = hp->inpf; BOOL value = TRUE; if (expstr) { STRPTR nw = infgetw(inpf); /* check for expeted word */ if (!nw || upstrcmp(nw, expstr)) { if (!nw) nw = "<EOF>"; hsc_message(hp, MSG_UNEXPT_CH, "expected %q, found %q", expstr, nw); value = FALSE; } } else { panic("no data to expect"); } return (value); }
/* * remove_end_tag * * remove tag from container stack, check for legal nesting, * show up message if necessary. * * params: hp....hsc process * tag...tag to be removed */ VOID remove_end_tag(HSCPRC * hp, HSCTAG * tag) { /* search for tag on stack of occured tags */ DLNODE *nd = find_dlnode_bw(hp->container_stack->last, (APTR) tag->name, cmp_strtag); if (nd == NULL) { /* closing tag not found on stack */ /* ->unmatched closing tag without previous opening tag */ hsc_message(hp, MSG_UNMA_CTAG, "unmatched %C", tag); } else { /* closing tag found on stack */ HSCTAG *end_tag = (HSCTAG *) dln_data(nd); STRPTR foundnm = (STRPTR) end_tag->name; STRPTR lastnm = (STRPTR) dln_data(dll_last(hp->container_stack)); /* check if name of closing tag is -not- equal * to the name of the last tag last on stack * ->illegal tag nesting */ if (upstrcmp(lastnm, foundnm) && !(tag->option | HT_MACRO) && !(is_hsc_tag(tag))) { hsc_message(hp, MSG_CTAG_NESTING, "illegal end tag nesting (expected %c, found %C)", lastnm, tag); } /* if closing tag has any attributes defined, * it must be a closing macto tag. so copy * the attributes of the closing tag to the * attributes of the macro tag. therefor, * the closing macro tag inherits the * attributes of his opening macro */ if (end_tag->attr) { set_local_varlist(tag->attr, end_tag->attr, MCI_APPCTAG); } /* remove node for closing tag from container_stack */ del_dlnode(hp->container_stack, nd); } }
/* * output text function * * output text to host process * * params: hp....hsc process to perform ouput with * wspc..white spaces * text..other text * result: true, if text has been outputted */ BOOL hsc_output_text(HSCPRC * hp, STRPTR wspc, STRPTR text) { BOOL written = FALSE; if ((hp)->CB_text && !((hp)->suppress_output)) { /* add current white spaces to white space * buffer; if hp->compact is enabled, reduce * white spaces */ if (wspc) app_estr(hp->whtspc, wspc); if (hp->compact && (!hp->inside_pre)) /* reduce white spaces */ wspc = compactWs(hp, estr2str(hp->whtspc)); else wspc = estr2str(hp->whtspc); /* strip white spaces if requested */ if (hp->strip_next_whtspc) { D(fprintf(stderr, DHL "bad white spaces stripped\n")); hp->strip_next_whtspc = FALSE; wspc = ""; } else if (hp->strip_next2_whtspc) { hp->strip_next2_whtspc = FALSE; hp->strip_next_whtspc = TRUE; } else if ((hp->tag_next_whtspc) && strlen(wspc)) { hsc_message(hp, MSG_SUCC_WHTSPC, "succeeding white-space for %T", hp->tag_next_whtspc); } hp->tag_next_whtspc = NULL; #if DEBUG_HSCLIB_OUTPUT if (hp->debug) if (text) if (strcmp(text, "\n")) fprintf(stderr, DHL "ouput: `%s', `%s'\n", wspc, text); else fprintf(stderr, DHL "ouput: `%s', `\\n'\n", wspc); #endif if ((wspc && wspc[0]) || (text && text[0])) { /* convert NULL values to empty strings */ if (!wspc) wspc = ""; if (!text) text = ""; /* output text */ (*((hp)->CB_text)) ((hp), wspc, text); written = TRUE; } /* reset white space buffer */ clr_estr(hp->whtspc); } return (written); }
/* * hsc_parse_end * * check for all tags closed and required * tags occured */ BOOL hsc_parse_end(HSCPRC * hp) { if (!hp->fatal) { INFILEPOS *infpos = new_infilepos(hp->inpf); /* check for unclosed containers */ DLNODE *nd = hp->container_stack->first; while (nd) { HSCTAG *endtag = (HSCTAG *) dln_data(nd); set_infilepos(hp->inpf, endtag->start_fpos); hsc_message(hp, MSG_MISS_CTAG, "%c missing", endtag->name); nd = dln_next(nd); } set_infilepos(hp->inpf, infpos); del_infilepos(infpos); /* check for required tags missing */ nd = hp->deftag->first; while (nd) { HSCTAG *tag = (HSCTAG *) nd->data; if ((tag->option & HT_REQUIRED && (tag->occured == FALSE))) { hsc_message(hp, MSG_MISS_REQTAG, "required %T missing", tag); } nd = nd->next; } } return (BOOL) (!hp->fatal); }
/* * add_local_iddef * * define a new local ID that can be refered to */ BOOL add_local_iddef(HSCPRC * hp, STRPTR id) { INFILEPOS *fpos = new_infilepos(hp->inpf); HSCIDD *iddef = find_iddef(hp->project->document, id); DIHP(fprintf(stderr, DHL "add ref to id `%s' at `%s' (%lu,%lu)\n", id, ifp_get_fname(fpos), ifp_get_y(fpos), ifp_get_x(fpos))); /* check for duplicate definition */ if (iddef) { /* duplicate definition */ DIHP(fprintf(stderr, DHL " duplicate definition\n")); hsc_message(hp, MSG_REDEFINE_ID, "local id %q already declared", id); set_infilepos(hp->inpf, iddef->fpos); hsc_message(hp, MSG_REDEFINE_ID, "(location of previous declaration)"); set_infilepos(hp->inpf, fpos); del_infilepos(fpos); } else { /* remember new local id */ iddef = app_iddef(hp->project->document, id); iddef->caller = fpos2caller(fpos); iddef->fpos = fpos; DIHP(fprintf(stderr, DHL " append to local iddefs\n")); } return (TRUE); }
/* * 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); }
static BOOL parse_lazy_option( HSCPRC *hp, HSCTAG *tag, STRPTR lazy ) { BOOL ok = TRUE; while( lazy[0] ) { switch ( lazy[0] ) { case 'c': def_lazy_attr( hp, tag, "CLASS", VT_STRING ); break; case 'h': def_lazy_attr( hp, tag, "HREF", VT_URI ); break; case 'i': def_lazy_attr( hp, tag, "ID", VT_ID ); break; case 'k': { HSCATTR *clear_attr = def_lazy_attr( hp, tag, "CLEAR", VT_ENUM ); clear_attr->enumstr = strclone( "left|right|all|*" ); } break; case 'l': def_lazy_attr( hp, tag, "LANG", VT_STRING ); break; case 'm': def_lazy_attr( hp, tag, "MD", VT_STRING ); break; case 's': def_lazy_attr( hp, tag, "SRC", VT_URI ); break; case 'w': def_lazy_attr( hp, tag, "NOWRAP", VT_BOOL ); break; default: hsc_message( hp, MSG_UNKN_TAG_OPTION, "unknown tag option %q (arg %q)", "LAZY", ch2str( lazy[0] ) ); break; } lazy++; } return( ok ); }
/* * try_set_attr * * if attribute exists and it's value is empty, set * new value and update tag-attribute-string */ static VOID try_setattr(HSCPRC * hp, HSCVAR * attr, ULONG value) { if (attr) { STRPTR old_value = get_vartext(attr); STRPTR new_value = long2str(value); if (!old_value) { /* set new value */ set_vartext(attr, new_value); /* append attribute name and "=" */ app_estr(hp->tag_attr_str, " "); app_estr(hp->tag_attr_str, attr->name); app_estr(hp->tag_attr_str, "="); /* append quotes and value */ if ((hp->quotemode == QMODE_KEEP) || (hp->quotemode == QMODE_DOUBLE)) app_estrch(hp->tag_attr_str, '\"'); else if (hp->quotemode == QMODE_SINGLE) app_estrch(hp->tag_attr_str, '\''); app_estr(hp->tag_attr_str, long2str(value)); /* append value */ if ((hp->quotemode == QMODE_KEEP) || (hp->quotemode == QMODE_DOUBLE)) app_estrch(hp->tag_attr_str, '\"'); else if (hp->quotemode == QMODE_SINGLE) app_estrch(hp->tag_attr_str, '\''); } else { /* validate old value */ if (strcmp(old_value, new_value)) { hsc_message(hp, MSG_UNEX_ATTR_VALUE, "unexpected value for %A: expected %q, found %q", attr, new_value, old_value); } } } }
/* * check_attr_option * * check if a attribute-option-string is equal to an id/short id. * if so, set the corresponding option value within the attribute. * * params: option..option string to check for (read from input) * attr....attribute to update option value for * id......id string of option (eg "REQUIRED") * sid.....short id string (eg "R") * value...option value to OR with old tag's option value * result: TRUE, if tag's option value updated */ static BOOL check_attr_option(HSCPRC * hp, STRPTR option, HSCATTR * attr, STRPTR id, STRPTR sid, ULONG value, ULONG unmasked_flags) { BOOL found = FALSE; if (!((upstrcmp(option, id)) && (upstrcmp(option, sid)))) { DDA(fprintf(stderr, DHL " option %s\n", id)); if (value & unmasked_flags) { hsc_message(hp, MSG_ILLG_ATTR_FLAG, "attribute option %q not allowed in this context", id); } else attr->varflag |= value; found = TRUE; } return (found); }
/* * handle_blink: tag handle for <BLINK> * * just tell the user that frames are disgusting */ BOOL handle_frame(HSCPRC * hp, HSCTAG * tag) { hsc_message(hp, MSG_FRAME_SUX, "frames are disgusting"); return (TRUE); }
/* * handle_blink: tag handle for <BLINK> * * just tell the user that blink sucks */ BOOL handle_blink(HSCPRC * hp, HSCTAG * tag) { hsc_message(hp, MSG_BLINK_SUX, "%t sucks", "BLINK"); return (TRUE); }
/* * handle_sgml_comment: tag handle for <!..> * * */ BOOL handle_sgml_comment(HSCPRC * hp, HSCTAG * tag) { BOOL not_stripped = TRUE; #if 1 EXPSTR *content = hp->tag_attr_str; /* do not maintain content, if comment should be stripped * lateron anyway */ if (hp->strip_cmt) { content = NULL; } /* skip data */ skip_sgml_special(hp,content); /* check if comment should be stripped */ if (hp->strip_cmt) { hsc_msg_stripped_tag(hp, tag, "sgml-comment"); not_stripped = FALSE; } #else STRPTR nw = infgetw(inpf); INFILE *inpf = hp->inpf; if (nw) { BOOL comment = FALSE; BOOL oneword = FALSE; BOOL end_min = FALSE; /* append to attribute string */ app_estr(hp->tag_attr_str, infgetcws(inpf)); app_estr(hp->tag_attr_str, infgetcw(inpf)); if (!strncmp(nw, "--", 2)) { size_t slen = strlen(nw); /* length of current word */ comment = TRUE; /* check for "--" */ if (slen >= 4) { /* word starts with "--" and ends with "--" */ end_min = ((nw[slen - 1] == '-') && (nw[slen - 1] == '-')); oneword = TRUE; } } /* check for whitespace after "!" */ if (strlen(infgetcws(inpf))) hsc_msg_illg_whtspc(hp); if (!strcmp(nw, ">")) /* zero-comment */ hsc_message(hp, MSG_ONEW_COMMENT, "empty sgml comment"); else if (!comment) skip_until_eot(hp, hp->tag_attr_str); /* unknown "!"-command: skip */ else { /* handle comment */ BOOL end_gt = FALSE; BOOL in_quote = FALSE; while (!(hp->fatal) && !end_gt) { /* read next word */ nw = infgetw(inpf); if (nw) { size_t slen = strlen(nw); /* append word to attribute string */ app_estr(hp->tag_attr_str, infgetcws(inpf)); app_estr(hp->tag_attr_str, infgetcw(inpf)); /* *check for "--" */ if (slen >= 2) end_min = ((nw[slen - 1] == '-') && (nw[slen - 1] == '-')); /* * check for end-of-comment */ if (!strcmp(nw, ">")) if (end_min) end_gt = TRUE; else { hsc_message(hp, MSG_GT_IN_COMMENT, "%q inside sgml-comment", ">"); } else { if (oneword) { oneword = FALSE; end_min = FALSE; } /* check for LF */ if (!strcmp(nw, "\n")) { in_quote = FALSE; hsc_message(hp, MSG_LF_IN_COMMENT, "line feed inside sgml-comment"); } /* check for quote */ else if (!strcmp(nw, "\"") || !strcmp(nw, "'")) in_quote = !in_quote; } } else hsc_msg_eof(hp, "reading sgml-comment"); if (end_gt && in_quote) { hsc_message(hp, MSG_CMTEND_QUOTE, "sgml-comment ends inside quotes"); } if (end_gt && oneword) hsc_message(hp, MSG_ONEW_COMMENT, "sgml-comment consists of a single word"); } } /* check if comment should be stripped */ if (hp->strip_cmt) { hsc_msg_stripped_tag(hp, tag, "sgml-comment"); not_stripped = FALSE; } } else hsc_msg_eof(hp, "reading sgml-comment"); #endif return (not_stripped); }
/* * err_op: unknown binary operator */ static void err_op(HSCPRC * hp, STRPTR opstr) { hsc_message(hp, MSG_UNKN_BINOP, "unknown binary operator %q", opstr); }
/* * 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); }
/* * hsc_parse_text */ BOOL hsc_parse_text(HSCPRC * hp) { INFILE *inpf = hp->inpf; STRPTR nw = infgetcw(inpf); if (nw && hp->suppress_output) hp_enable_output(hp, "some text"); if (nw) { /* do test below only if not end-of-file */ /* * check unmatched ">" */ if (!strcmp(nw, ">")) { BOOL rplc = hp->smart_ent; /* TRUE, if ">" should be replaced */ 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 gt */ message_rplc(hp, nw, ">"); nw = ">"; } else { hsc_message(hp, MSG_UNMA_GT, "unmatched %q", ">"); } } /* * check for quote */ else if (!strcmp(nw, "\"")) { if (hp->rplc_quote) { /* replace quote */ message_rplc(hp, nw, """); nw = """; } } /* * check for entities to replace */ else { DLNODE *nd = NULL; /* entity search result */ if (hp->rplc_ent && (strlen(nw) == 1) && (nw[0] >= 127)) { nd = find_dlnode(hp->defent->first, (APTR) nw, cmp_rplcent); if (nd) { BOOL ok = TRUE; /* copy replaced entity to buffer */ ok &= set_estr(hp->tmpstr, "&"); ok &= app_estr(hp->tmpstr, ((HSCENT *) nd->data)->name); ok &= app_estr(hp->tmpstr, ";"); if (ok) { /* replace-message */ message_rplc(hp, nw, estr2str(hp->tmpstr)); nw = estr2str(hp->tmpstr); } } } /* * check for "click here" syndrome */ if (hp->inside_anchor && hp->click_here_str) { ULONG found = strenum(nw, hp->click_here_str, '|', STEN_NOCASE); if (found) { hsc_message(hp, MSG_CLICK_HERE, "%q-syndrome detected", "click here"); } } #if (defined MSDOS & (!defined HSC_PLEASE)) /* replace certain keywords */ if (!upstrcmp(nw, "Netscape")) { nw = "Nutscape"; } else if (!upstrcmp(nw, "Microsoft")) { nw = "Mircosoft"; } else if (!upstrcmp(nw, "Intel")) { nw = "Wintel"; } /* to be continued.. */ #endif } } if (nw) hsc_output_text(hp, "", nw); /* output word */ return (BOOL) (!hp->fatal); }
/* * 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); }
/* display message "linefeed inside sgml-comment" */ static VOID msg_lf_in_comment(HSCPRC * hp) { hsc_message(hp, MSG_LF_IN_COMMENT, "line feed inside sgml-comment"); }
/* * message_rplc * * message that tells user that a special char * was replaced by its entity */ static VOID message_rplc(HSCPRC * hp, STRPTR what, STRPTR by) { hsc_message(hp, MSG_RPLC_ENT, "replaced %q by %q", what, by); }
/* * hsc_parse_tag * * parse tag (after "<") */ BOOL hsc_parse_tag(HSCPRC * hp) { INFILE *inpf = hp->inpf; STRPTR nxtwd = NULL; DLNODE *nd = NULL; HSCTAG *tag = NULL; ULONG tci = 0; /* tag_call_id returned by set_tag_args() */ BOOL(*hnd) (HSCPRC * hp, HSCTAG * tag) = NULL; BOOL open_tag; DLLIST *taglist = hp->deftag; BOOL rplc_lt = FALSE; /* TRUE, if replace spc. char "<" */ BOOL hnd_result = TRUE; /* result returned by handle */ BOOL unknown_tag = FALSE; /* TRUE, if tag has not been defined before */ BOOL preceeding_whtspc = estrlen(hp->whtspc); /* init strings used inside tag-handles */ set_estr(hp->tag_name_str, infgetcw(inpf)); clr_estr(hp->tag_attr_str); clr_estr(hp->tag_close_str); if (hp->smart_ent && preceeding_whtspc) { /* * check for special char "<" */ int ch = infgetc(inpf); /* check if next char is a white space */ if (hsc_whtspc(ch)) { rplc_lt = TRUE; /* write "<" and white spaces */ message_rplc(hp, "<", "<"); hsc_output_text(hp, "", "<"); } inungetc(ch, inpf); } if (!rplc_lt) { /* get tag id */ nxtwd = infget_tagid(hp); if (!hp->fatal) { /* append tag-name to tag_name_str */ app_estr(hp->tag_name_str, infgetcw(inpf)); /* check for hsctag; if not, enable output */ if (hp->suppress_output && upstrncmp(nxtwd, HSC_TAGID, strlen(HSC_TAGID)) && strcmp(nxtwd, HSC_COMMENT_STR) && strcmp(nxtwd, HSC_ONLYCOPY_STR) ) { hp_enable_output(hp, "non-hsctag occured"); } if (!hp->suppress_output) { D(fprintf(stderr, DHL "tag <")); } } } if (!hp->fatal && !rplc_lt) { BOOL write_tag = FALSE; /* flag: write tag text & attrs to output? */ if (strcmp("/", nxtwd)) /* is it a closing tag? */ { /* * * process start-tag * */ open_tag = TRUE; if (!hp->suppress_output) { D(fprintf(stderr, "%s>\n", nxtwd)); } /* search for tag in list */ nd = find_dlnode(taglist->first, (APTR) nxtwd, cmp_strtag); if (nd == NULL) { hsc_message(hp, MSG_UNKN_TAG, /* tag not found */ "unknown %t", nxtwd); tag = new_hsctag(nxtwd); tag->option |= HT_UNKNOWN; unknown_tag = TRUE; #if 0 /* TODO: remove */ /* NOTE: This one's a bit perverted, because * the closing ">" is appended to the * attribute string, and the closing string * is left empty; as there is nearly no code * between setting and writing the strings, * I think this is more reasonable than doing * some tricky string-manipulation... */ skip_until_eot(hp, hp->tag_attr_str); clr_estr(hp->tag_close_str); #endif } else { tag = (HSCTAG *) nd->data; } /* set handle-function */ hnd = tag->o_handle; /* * handle options */ /* check for obsolete tag */ if (tag->option & HT_OBSOLETE) { hsc_message(hp, MSG_TAG_OBSOLETE, "%T is obsolete", tag); } /* check for jerk-tag */ if (tag->option & HT_JERK) { hsc_message(hp, MSG_TAG_JERK, "%T is only used by %j", tag); } /* only-once-tag occured twice? */ if ((tag->option & HT_ONLYONCE) && (tag->occured)) { hsc_message(hp, MSG_TAG_TOO_OFTEN, "%T occured too often", tag); } /* set occured-flag */ if (tag->option & (HT_ONLYONCE | HT_REQUIRED)) tag->occured = TRUE; /* check for "must be inside"/"not allowed within"-tags */ if (!check_mbinaw(hp, tag)) hnd = NULL; /* clear (reset to default) attribute values of tag */ clr_varlist(tag->attr); /* set attributes or check for ">" */ if (!(tag->option & HT_SPECIAL)) { tci = set_tag_args(hp, tag); if (tci == MCI_ERROR) { skip_until_eot(hp, NULL); hnd = NULL; } if (!hp->fatal) { /* set ">" in string that contains closing text */ if (!hp->compact) { set_estr(hp->tag_close_str, infgetcws(inpf)); } else { clr_estr(hp->tag_close_str); } app_estr(hp->tag_close_str, infgetcw(inpf)); /* check for succeeding white-space */ if ((tag->option & HT_WHTSPC) && !infeof(inpf)) { int ch = infgetc(inpf); if (hsc_whtspc(ch)) { if (hp->strip_badws) { hp->strip_next2_whtspc = TRUE; } else { hsc_message(hp, MSG_SUCC_WHTSPC, "succeeding white-space for %T", tag); } } inungetc(ch, inpf); } } } /* end-tag required? */ if (tag->option & HT_CLOSE) app_ctag(hp, tag); } else { /* * * process end-tag * */ /* get tag id */ nxtwd = infget_tagid(hp); /* get tag id */ open_tag = FALSE; /* append tag-name to tag_name_str */ if (!hp->compact) { app_estr(hp->tag_name_str, infgetcws(inpf)); } app_estr(hp->tag_name_str, infgetcw(inpf)); if (!hp->suppress_output) { D(fprintf(stderr, "/%s>\n", nxtwd)); } /* search for tag in taglist */ /* (see if it exists at all) */ nd = find_dlnode(taglist->first, (APTR) nxtwd, cmp_strtag); if (nd == NULL) { /* closing tag is absolutely unknown */ hsc_message(hp, MSG_UNKN_TAG, /* tag not found */ "unknown %c", nxtwd); skip_until_eot(hp, hp->tag_attr_str); } else { tag = (HSCTAG *) nd->data; /* fitting tag in taglist */ /* check for preceding white-spaces */ if ((tag->option & HT_WHTSPC) && anyWhtspc(hp)) { if (hp->strip_badws) { hp->strip_next_whtspc = TRUE; } else { hsc_message(hp, MSG_PREC_WHTSPC, "preceding white space for %C", tag); } } if (tag->option & (HT_CLOSE | HT_AUTOCLOSE)) { /* set closing handle */ hnd = tag->c_handle; /* check for no args */ if (!parse_wd(hp, ">")) { hsc_message(hp, MSG_CL_TAG_ARG, "no attributes allowed for end-tags"); } else { /* set ">" in string that contains closing text */ if (!hp->compact) { set_estr(hp->tag_close_str, infgetcws(inpf)); } app_estr(hp->tag_close_str, infgetcw(inpf)); } /* set values of attributes stored * in end-tag, * remove end-tag from stack */ remove_ctag(hp, tag); } else { /* illegal closing tag */ hsc_message(hp, MSG_ILLG_CTAG, /* tag not found */ "illegal %c", nxtwd); parse_gt(hp); tag = NULL; } } } /* * processed for opening AND closing tag */ write_tag = (!(tag) || !(tag->option & HT_NOCOPY)); if (tag) { /* * check if tag should be stripped */ if (!postprocess_tagattr(hp, tag, open_tag)) { /* stripped tag with external reference */ if (open_tag) hsc_msg_stripped_tag(hp, tag, "external reference"); hnd = NULL; /* don't call handle */ write_tag = FALSE; /* don't output tag */ } else if (hp->strip_tags && strenum(tag->name, hp->strip_tags, '|', STEN_NOCASE)) { /* strip tag requested by user */ if (!(tag->option & HT_SPECIAL)) { if (open_tag) hsc_msg_stripped_tag(hp, tag, "as requested"); hnd = NULL; /* don't call handle */ write_tag = FALSE; /* don't output tag */ } else { hsc_message(hp, MSG_TAG_CANT_STRIP, "can not strip special tag %T", tag); } /* * get values for size from reference */ } else if (tag->uri_size && get_vartext(tag->uri_size)) get_attr_size(hp, tag); } /* call handle if available */ if (hnd && !hp->fatal) hnd_result = (*hnd) (hp, tag); /* write whole tag out */ if (write_tag && hnd_result) { VOID(*tag_callback) (struct hscprocess * hp, HSCTAG * tag, STRPTR tag_name, STRPTR tag_attr, STRPTR tag_close) = NULL; if (open_tag) tag_callback = hp->CB_start_tag; else tag_callback = hp->CB_end_tag; /* write white spaces */ hsc_output_text(hp, "", ""); if (tag_callback) { (*tag_callback) (hp, tag, estr2str(hp->tag_name_str), estr2str(hp->tag_attr_str), estr2str(hp->tag_close_str)); } } /* skip LF if requested */ if (tag && (tag->option & HT_SKIPLF)) { skip_next_lf(hp); /* TODO: really skip single lf */ } /* remove temporary created tag */ if (unknown_tag) del_hsctag(tag); #if (defined MSDOS && (!defined HSC_TRIGGER)) #define UNLIKELY (10*1024) /* crash randomly */ if ((rand() % UNLIKELY) == (UNLIKELY / 2)) { enforcerHit(); } #endif } return (BOOL) (!hp->fatal); }
BOOL skip_sgml_special(HSCPRC * hp, EXPSTR * content) { INFILE *inpf = hp->inpf; int ch = infgetc(inpf); /* read next char */ int ch_prev = EOF; BOOL end = FALSE; /* flag: end of comment reached? */ if (ch == '>') { hsc_message(hp, MSG_ZERO_COMMENT, "empty sgml comment"); end = TRUE; } else if (ch == '-') { ch_prev = ch; ch = infgetc(inpf); if (ch == '-') { BOOL inside_comment = TRUE; BOOL warned_text = FALSE; DS(fprintf(stderr, DHLS "skip sgml comment\n")); APP_CONTENT_CH(ch_prev); APP_CONTENT_CH(ch); ch_prev = EOF; ch = infgetc(inpf); while (!end && (ch != EOF)) { /* append current char to content */ APP_CONTENT_CH(ch); if ((ch == '-') && (ch_prev == '-')) { inside_comment = !inside_comment; warned_text = FALSE; ch_prev = EOF; } else if (ch == '-') { ch_prev = '-'; } else if (ch == '\r') { ch_prev = '\r'; msg_lf_in_comment(hp); } else { if (ch == '\n') { if (ch_prev != '\r') { msg_lf_in_comment(hp); } } ch_prev = EOF; if (ch == '>') { if (inside_comment) { hsc_message(hp, MSG_GT_IN_COMMENT, "%q inside sgml-comment", ">"); } else { end = TRUE; } } else { if (!inside_comment && !warned_text) { hsc_message(hp, MSG_TEXT_IN_COMMENT, "text outside sgml-comment context"); } warned_text = TRUE; } } if (!end) { /* read next char */ ch = infgetc(inpf); } } /* push back last char */ if (!end && (ch != EOF)) { inungetc(ch, inpf); } } else { /* push back chars read until yet */ inungetc(ch, inpf); inungetc(ch_prev, inpf); ch_prev = EOF; } } /* skip other "!"-tags (SSI and that bullshit) */ if (!end) { DS(fprintf(stderr, DHLS "skip sgml special\n")); APP_CONTENT_CH(ch); do { ch = infgetc(inpf); if (ch != EOF) { APP_CONTENT_CH(ch); DS( { fprintf(stderr, DHLS " word starting with: "); dbg_printc(ch); fprintf(stderr, "\n"); } ); if (ch == '>') { end = TRUE; } else { skip_expression(hp, content, ch); } }
/* * handle_hsc_content * * handle content inside a content macro * (insert text of attribute HSC.CONTENT) */ static VOID hsc_msg_no_content(HSCPRC *hp) { hsc_message(hp, MSG_NO_CONTENT, "no content within current context"); }
/* ** def_tag_name ** */ HSCTAG *def_tag_name( HSCPRC *hp, BOOL *open_tag ) { STRPTR nw = NULL; HSCTAG *tag = NULL; DLLIST *taglist = hp->deftag; /* get tag name */ nw = infget_tagid( hp ); /* create new tag */ if ( nw ) { *open_tag = (BOOL)(strcmp( nw, "/" )); if ( !(*open_tag) ) { /* add closing tag */ nw = infget_tagid( hp ); if ( nw ) { tag = find_strtag( taglist, nw ); if ( tag ) /* set closing flag */ tag->option |= HT_CLOSE; else { hsc_message( hp, MSG_DEFTAG_NO_OPEN, "no start tag for %c", nw ); } } /* err_eof already called in infget_tagid() */ } else { tag = find_strtag( taglist, nw ); if ( tag ) { /* find tag-node in list */ /* NOTE: this is rather stupid, 'cause the list */ /* has to be searched twice this way; but who cares? */ DLNODE *nd = find_dlnode( hp->deftag->first, (APTR) nw, cmp_strtag ); /* new tag/macro replaces old tag/macro */ if ( (tag->option) & HT_MACRO ) { tag->occured = FALSE; hsc_message( hp, MSG_REDEFINE_MACRO, "redefined %T", tag ); } else { hsc_message( hp, MSG_REDEFINE_TAG, "can not redefine %T", tag ); } del_dlnode( hp->deftag, nd ); } /* create a new opening tag */ tag = app_tag( taglist, nw ); } } /* err_eof already called in infget_tagid() */ /* convert tag name to upper case */ if ( tag ) upstr( tag->name ); return( tag ); }