⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sgml.c

📁 elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, lynx比elinks早的多, 目前好像停止开发, 这是lynx源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	Handle sgmlatt**	--------------*/PRIVATE void handle_sgmlatt ARGS1(	HTStream *,		context){    CONST char *s = context->string->data;    CTRACE((tfp, "SGML Attribute Declaration:\n<%s>\n", s));    return;}/* *  Convenience macros - tags (elements) are identified sometimes *  by an int or enum value ('TAGNUM'), sometimes *  by a pointer to HTTag ('TAGP'). - kw */#define TAGNUM_OF_TAGP(t) (t - context->dtd->tags)#define TAGP_OF_TAGNUM(e) (context->dtd->tags + e)/* *  The following implement special knowledge about OBJECT. *  As long as HTML_OBJECT is the only tag for which an alternative *  variant exist, they can be simple macros. - kw *//* does 'TAGNUM' e have an alternative (variant) parsing mode? */#define HAS_ALT_TAGNUM(e) (e == HTML_OBJECT)/* return 'TAGNUM' of the alternative mode for 'TAGNUM' e, if any. */#define ALT_TAGNUM(e) ((e == HTML_OBJECT) ? HTML_ALT_OBJECT : e)/* return 'TAGNUM' of the normal mode for 'TAGNUM' e which may be alt. */#define NORMAL_TAGNUM(e) ((e >= HTML_ELEMENTS) ? HTML_OBJECT : e)/* More convenience stuff. - kw */#define ALT_TAGP_OF_TAGNUM(e) TAGP_OF_TAGNUM(ALT_TAGNUM(e))#define NORMAL_TAGP_OF_TAGNUM(e) TAGP_OF_TAGNUM(NORMAL_TAGNUM(e))#define ALT_TAGP(t) ALT_TAGP_OF_TAGNUM(TAGNUM_OF_TAGP(t))#define NORMAL_TAGP(t) NORMAL_TAGP_OF_TAGNUM(TAGNUM_OF_TAGP(t))#ifdef EXTENDED_HTMLDTDPRIVATE BOOL element_valid_within ARGS3(    HTTag *,	new_tag,    HTTag *,	stacked_tag,    BOOL,	direct){    TagClass usecontains, usecontained;    if (!stacked_tag || !new_tag)	return YES;    usecontains = (direct ? stacked_tag->contains : stacked_tag->icontains);    usecontained = (direct ? new_tag->contained : new_tag->icontained);    if (new_tag == stacked_tag)	return (BOOL) ((Tgc_same & usecontains) &&		(Tgc_same & usecontained));    else	return (BOOL) ((new_tag->tagclass & usecontains) &&		(stacked_tag->tagclass & usecontained));}typedef enum {    close_NO	= 0,    close_error = 1,    close_valid = 2} canclose_t;PRIVATE canclose_t can_close ARGS2(    HTTag *,	new_tag,    HTTag *,	stacked_tag){    if (!stacked_tag)	return close_NO;    if (stacked_tag->flags & Tgf_endO)	return close_valid;    else if (new_tag == stacked_tag)	return ((Tgc_same & new_tag->canclose) ? close_error : close_NO);    else	return ((stacked_tag->tagclass & new_tag->canclose) ?		close_error : close_NO);}PRIVATE void do_close_stacked ARGS1(    HTStream *, context){    HTElement * stacked = context->element_stack;    HTMLElement e;    if (!stacked)	return;			/* stack was empty */    if (context->inSELECT && !strcasecomp(stacked->tag->name, "SELECT")) {	context->inSELECT = FALSE;    }    e = NORMAL_TAGNUM(TAGNUM_OF_TAGP(stacked->tag));#ifdef USE_PRETTYSRC    if (!psrc_view) /* Don't actually pass call on if viewing psrc - kw */#endif    (*context->actions->end_element)(	context->target,	e,	(char **)&context->include);    context->element_stack = stacked->next;    pool_free(stacked);    context->no_lynx_specialcodes = context->element_stack ?	(context->element_stack->tag->flags & Tgf_nolyspcl) : NO;}PRIVATE int is_on_stack ARGS2(	HTStream *,	context,	HTTag *,	old_tag){   HTElement * stacked = context->element_stack;    int i = 1;    for (; stacked; stacked = stacked->next, i++) {	if (stacked->tag == old_tag ||	    stacked->tag == ALT_TAGP(old_tag))	    return i;    }    return 0;}#endif /* EXTENDED_HTMLDTD *//*	End element**	-----------*/PRIVATE void end_element ARGS2(	HTStream *,	context,	HTTag *,	old_tag){#ifdef EXTENDED_HTMLDTD    BOOL extra_action_taken = NO;    canclose_t canclose_check = close_valid;    int stackpos = is_on_stack(context, old_tag);    if (!Old_DTD) {	while (canclose_check != close_NO &&	       context->element_stack &&	       (stackpos > 1 || (!extra_action_taken && stackpos == 0))) {	    if (stackpos == 0 && (old_tag->flags & Tgf_startO) &&		element_valid_within(old_tag, context->element_stack->tag, YES)) {		CTRACE((tfp, "SGML: </%s> ignored\n", old_tag->name));		return;	    }	    canclose_check = can_close(old_tag, context->element_stack->tag);	    if (canclose_check != close_NO) {		CTRACE((tfp, "SGML: End </%s> \t<- %s end </%s>\n",			    context->element_stack->tag->name,			    canclose_check == close_valid ? "supplied," : "***forced by",			    old_tag->name));		do_close_stacked(context);		extra_action_taken = YES;		stackpos = is_on_stack(context, old_tag);	    }	}	if (stackpos == 0 && old_tag->contents != SGML_EMPTY) {	    CTRACE((tfp, "SGML: Still open %s, ***no open %s for </%s>\n",			context->element_stack ?			context->element_stack->tag->name : "none",			old_tag->name,			old_tag->name));	    return;	}	if (stackpos > 1) {	    CTRACE((tfp, "SGML: Nesting <%s>...<%s> \t<- ***invalid end </%s>\n",			old_tag->name,			context->element_stack->tag->name,			old_tag->name));	    return;	}    }    /* Now let the non-extended code deal with the rest. - kw */#endif /* EXTENDED_HTMLDTD */    /*    **	If we are in a SELECT block, ignore anything    **	but a SELECT end tag. - FM    */    if (context->inSELECT) {	if (!strcasecomp(old_tag->name, "SELECT")) {	    /*	    **	Turn off the inSELECT flag and fall through. - FM	    */	    context->inSELECT = FALSE;	} else {	    /*	    **	Ignore the end tag. - FM	    */	    CTRACE((tfp, "SGML: ***Ignoring end tag </%s> in SELECT block.\n",			old_tag->name));	    return;	}    }    /*    **	Handle the end tag. - FM    */    CTRACE((tfp, "SGML: End </%s>\n", old_tag->name));    if (old_tag->contents == SGML_EMPTY) {	CTRACE((tfp, "SGML: ***Illegal end tag </%s> found.\n",		    old_tag->name));	return;    }#ifdef WIND_DOWN_STACK    while (context->element_stack) /* Loop is error path only */#else    if (context->element_stack) /* Substitute and remove one stack element */#endif /* WIND_DOWN_STACK */    {	int status = HT_OK;	HTMLElement e;	HTElement * N = context->element_stack;	HTTag * t = (N->tag != old_tag) ? NORMAL_TAGP(N->tag) : N->tag;	if (old_tag != t) {		/* Mismatch: syntax error */	    if (context->element_stack->next) { /* This is not the last level */		CTRACE((tfp, "SGML: Found </%s> when expecting </%s>. </%s> ***assumed.\n",			     old_tag->name, t->name, t->name));	    } else {			/* last level */		CTRACE((tfp, "SGML: Found </%s> when expecting </%s>. </%s> ***Ignored.\n",			    old_tag->name, t->name, old_tag->name));		return;			/* Ignore */	    }	}	e = NORMAL_TAGNUM(TAGNUM_OF_TAGP(t));	CTRACE2(TRACE_SGML, (tfp, "tagnum(%p) = %d\n", t, e));#ifdef USE_PRETTYSRC	if (!psrc_view) /* Don't actually pass call on if viewing psrc - kw */#endif	    status = (*context->actions->end_element)(context->target,						e, (char **)&context->include);	if (status == HT_PARSER_REOPEN_ELT) {	    CTRACE((tfp, "SGML: Restart <%s>\n", t->name));	    (*context->actions->start_element)(		context->target,		e,		NULL,		NULL,		context->current_tag_charset,		(char **)&context->include);	} else if (status == HT_PARSER_OTHER_CONTENT) {	    CTRACE((tfp, "SGML: Continue with other content model for <%s>\n", t->name));	    context->element_stack->tag = ALT_TAGP_OF_TAGNUM(e);	} else {	    context->element_stack = N->next;		/* Remove from stack */	    pool_free(N);	}	context->no_lynx_specialcodes = context->element_stack ?	    (context->element_stack->tag->flags & Tgf_nolyspcl) : NO;#ifdef WIND_DOWN_STACK	if (old_tag == t)	    return;  /* Correct sequence */#else	return;#endif /* WIND_DOWN_STACK */	/* Syntax error path only */    }    CTRACE((tfp, "SGML: Extra end tag </%s> found and ignored.\n",		old_tag->name));}/*	Start a element*/PRIVATE void start_element ARGS1(	HTStream *,	context){    int status;    HTTag * new_tag = context->current_tag;    HTMLElement e = TAGNUM_OF_TAGP(new_tag);    BOOL ok = FALSE;#ifdef EXTENDED_HTMLDTD    BOOL valid = YES;    BOOL direct_container = YES;    BOOL extra_action_taken = NO;    canclose_t canclose_check = close_valid;    if (!Old_DTD) {	while (context->element_stack &&	       (canclose_check == close_valid ||		(canclose_check == close_error &&		 new_tag == context->element_stack->tag)) &&	       !(valid = element_valid_within(new_tag, context->element_stack->tag,					      direct_container))) {	    canclose_check = can_close(new_tag, context->element_stack->tag);	    if (canclose_check != close_NO) {		CTRACE((tfp, "SGML: End </%s> \t<- %s start <%s>\n",			    context->element_stack->tag->name,			    canclose_check == close_valid ? "supplied," : "***forced by",			    new_tag->name));		do_close_stacked(context);		extra_action_taken = YES;		if (canclose_check  == close_error)		    direct_container = NO;	    } else {		CTRACE((tfp, "SGML: Still open %s \t<- ***invalid start <%s>\n",			    context->element_stack->tag->name,			    new_tag->name));	    }	}	if (context->element_stack && !valid &&	    (context->element_stack->tag->flags & Tgf_strict) &&	    !(valid = element_valid_within(new_tag, context->element_stack->tag,					   direct_container))) {	    CTRACE((tfp, "SGML: Still open %s \t<- ***ignoring start <%s>\n",			context->element_stack->tag->name,			new_tag->name));	    return;	}	if (context->element_stack && !extra_action_taken &&	    canclose_check == close_NO && !valid && (new_tag->flags & Tgf_mafse)) {	    BOOL has_attributes = NO;	    int i = 0;	    for (; i< new_tag->number_of_attributes && !has_attributes; i++)		has_attributes = context->present[i];	    if (!has_attributes) {		CTRACE((tfp, "SGML: Still open %s, ***converting invalid <%s> to </%s>\n",			    context->element_stack->tag->name,			    new_tag->name,			    new_tag->name));		end_element(context, new_tag);		return;	    }	}	if (context->element_stack &&	    canclose_check == close_error && !(valid =					       element_valid_within(						   new_tag,						   context->element_stack->tag,						   direct_container))) {	    CTRACE((tfp, "SGML: Still open %s \t<- ***invalid start <%s>\n",			context->element_stack->tag->name,			new_tag->name));	}    }    /* Fall through to the non-extended code - kw */#endif /* EXTENDED_HTMLDTD */    /*    **	If we are not in a SELECT block, check if this is    **	a SELECT start tag.  Otherwise (i.e., we are in a    **	SELECT block) accept only OPTION as valid, terminate    **	the SELECT block if it is any other form-related    **	element, and otherwise ignore it. - FM    */    if (!context->inSELECT) {	/*	**  We are not in a SELECT block, so check if this starts one. - FM	**  (frequent case!)	*/	/* my_casecomp() - optimized by the first character */	if (!my_casecomp(new_tag->name, "SELECT")) {	    /*	    **	Set the inSELECT flag and fall through. - FM	    */	    context->inSELECT = TRUE;	}    } else {	/*	**  We are in a SELECT block. - FM	*/	if (strcasecomp(new_tag->name, "OPTION")) {	    /*	    **	Ugh, it is not an OPTION. - FM	    */	    switch (e) {		case HTML_INPUT:  case HTML_TEXTAREA: case HTML_SELECT:		case HTML_BUTTON: case HTML_FIELDSET: case HTML_LABEL:		case HTML_LEGEND: case HTML_FORM:		    ok = TRUE;		    break;		default:		    break;	    }	    if (ok)	    {		/*		**  It is another form-related start tag, so terminate		**  the current SELECT block and fall through. - FM		*/		CTRACE((tfp, "SGML: ***Faking SELECT end tag before <%s> start tag.\n",			    new_tag->name));		end_element(context, SGMLFindTag(context->dtd, "SELECT"));	    } else {		/*		**  Ignore the start tag. - FM		*/		CTRACE((tfp, "SGML: ***Ignoring start tag <%s> in SELECT block.\n",			    new_tag->name));		return;	    }	}    }    /*    **	Handle the start tag. - FM    */    CTRACE((tfp, "SGML: Start <%s>\n", new_tag->name));    status = (*context->actions->start_element)(	context->target,	TAGNUM_OF_TAGP(new_tag),	context->present,	(CONST char**) context->value,	/* coerce type for think c */	context->current_tag_charset,	(char **)&context->include);    if (status == HT_PARSER_OTHER_CONTENT)	new_tag = ALT_TAGP(new_tag);	/* this is only returned for OBJECT */    if (new_tag->contents != SGML_EMPTY) {		/* i.e., tag not empty */	HTElement * N = pool_alloc();	if (N == NULL)	    outofmem(__FILE__, "start_element");	N->next = context->element_stack;	N->tag = new_tag;	context->element_stack = N;	context->no_lynx_specialcodes = (new_tag->flags & Tgf_nolyspcl);    } else if (e == HTML_META ) {	/*	**  Check for result of META tag. - KW & FM	*/	change_chartrans_handling(context);    }}/*		Find Tag in DTD tag list**		------------------------**** On entry,**	dtd	points to dtd structure including valid tag list**	string	points to name of tag in question**** On exit,**	returns:**		NULL		tag not found**		else		address of tag structure in dtd*/PUBLIC HTTag * SGMLFindTag ARGS2(	CONST SGML_dtd*,	dtd,	CONST char *,		s){    int high, low, i, diff;    static HTTag* last[64] = {NULL};  /*optimize using the previous results*/    HTTag** res = last + (UCH(*s) % 64);     /*pointer arithmetic*/    if (*res && !strcasecomp((*res)->name, s))	return *res;    for (low = 0, high=dtd->number_of_tags;	  high > low;	  diff < 0 ? (low = i+1) : (high = i)) {	/* Binary search */	i = (low + (high-low)/2);	/* my_casecomp() - optimized by the first character, NOT_ASCII ok */	diff = my_casecomp(dtd->tags[i].name, s);	/* Case insensitive */	if (diff == 0) {		/* success: found it */	    *res = &dtd->tags[i];	    return *res;	}    }    if (IsNmStart(*s)) {	/*	**  Unrecognized, but may be valid. - KW

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -