build.c

来自「这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易」· C语言 代码 · 共 2,670 行 · 第 1/5 页

C
2,670
字号
					if(tr->align.halign != ALnone)						c->align.halign = tr->align.halign;					else if(tag == Tth)						c->align.halign = ALcenter;					else						c->align.halign = ALleft;				}				if(c->align.valign == ALnone) {					if(tr->align.valign != ALnone)						c->align.valign = tr->align.valign;					else						c->align.valign = ALmiddle;				}				c->nextinrow = tr->cells;				tr->cells = c;				break;			case Ttd+RBRA:			case Tth+RBRA:				if(curtab == nil || curtab->cells == nil) {					if(warn)						fprint(2, "unexpected %T\n", tok);					continue;				}				ps = finishcell(curtab, ps);				break;			// <!ELEMENT TEXTAREA - - (	//PCDATA)>			case Ttextarea:				if(is->curform == nil) {					if(warn)						fprint(2, "<TEXTAREA> not inside <FORM>\n");					continue;				}				field = newformfield(Ftextarea,					++is->curform->nfields,					is->curform,					aval(tok, Aname),					nil,					0,					0,					is->curform->fields);				is->curform->fields = field;				field->rows = auintval(tok, Arows, 3);				field->cols = auintval(tok, Acols, 50);				field->value = getpcdata(toks, tokslen, &toki);				if(warn && toki < tokslen - 1 && toks[toki + 1].tag != Ttextarea + RBRA)					fprint(2, "warning: <TEXTAREA> data ended by %T\n", &toks[toki + 1]);				ffit = newiformfield(field);				additem(ps, ffit, tok);				if(ffit->genattr != nil)					field->events = ffit->genattr->events;				break;			// <!ELEMENT TITLE - - (	//PCDATA)* -(%head.misc)>			case Ttitle:				di->doctitle = getpcdata(toks, tokslen, &toki);				if(warn && toki < tokslen - 1 && toks[toki + 1].tag != Ttitle + RBRA)					fprint(2, "warning: <TITLE> data ended by %T\n", &toks[toki + 1]);				break;			// <!ELEMENT TR - O (TH|TD)+>			// rows are accumulated in reverse order in curtab->rows			case Ttr:				if(curtab == nil) {					if(warn)						fprint(2, "warning: <TR> outside <TABLE>\n");					continue;				}				if(ps->inpar) {					popjust(ps);					ps->inpar = 0;				}				ps = finishcell(curtab, ps);				if(curtab->rows != nil)					curtab->rows->flags = 0;				curtab->rows = newtablerow(aalign(tok),					makebackground(nil, acolorval(tok, Abgcolor, curtab->background.color)),					TFparsing,					curtab->rows);				break;			case Ttr+RBRA:				if(curtab == nil || curtab->rows == nil) {					if(warn)						fprint(2, "warning: unexpected </TR>\n");					continue;				}				ps = finishcell(curtab, ps);				tr = curtab->rows;				if(tr->cells == nil) {					if(warn)						fprint(2, "warning: empty row\n");					curtab->rows = tr->next;					tr->next = nil;				}				else					tr->flags = 0;				break;			// <!ELEMENT (TT|CODE|KBD|SAMP) - - (%text)*>			case Ttt:			case Tcode:			case Tkbd:			case Tsamp:				pushfontstyle(ps, FntT);				break;			// Tags that have empty action			case Tabbr:			case Tabbr+RBRA:			case Tacronym:			case Tacronym+RBRA:			case Tarea+RBRA:			case Tbase+RBRA:			case Tbasefont+RBRA:			case Tbr+RBRA:			case Tdd+RBRA:			case Tdt+RBRA:			case Tframe+RBRA:			case Thr+RBRA:			case Thtml:			case Thtml+RBRA:			case Timg+RBRA:			case Tinput+RBRA:			case Tisindex+RBRA:			case Tli+RBRA:			case Tlink:			case Tlink+RBRA:			case Tmeta+RBRA:			case Toption+RBRA:			case Tparam+RBRA:			case Ttextarea+RBRA:			case Ttitle+RBRA:				break;			// Tags not implemented			case Tbdo:			case Tbdo+RBRA:			case Tbutton:			case Tbutton+RBRA:			case Tdel:			case Tdel+RBRA:			case Tfieldset:			case Tfieldset+RBRA:			case Tiframe:			case Tiframe+RBRA:			case Tins:			case Tins+RBRA:			case Tlabel:			case Tlabel+RBRA:			case Tlegend:			case Tlegend+RBRA:			case Tobject:			case Tobject+RBRA:			case Toptgroup:			case Toptgroup+RBRA:			case Tspan:			case Tspan+RBRA:				if(warn) {					if(tag > RBRA)						tag -= RBRA;					fprint(2, "warning: unimplemented HTML tag: %S\n", tagnames[tag]);				}				break;			default:				if(warn)					fprint(2, "warning: unknown HTML tag: %S\n", tok->text);				break;			}	}	// some pages omit trailing </table>	while(curtab != nil) {		if(warn)			fprint(2, "warning: <TABLE> not closed\n");		if(curtab->cells != nil) {			ps = finishcell(curtab, ps);			if(curtab->cells == nil) {				if(warn)					fprint(2, "warning: empty table\n");			}			else {				if(curtab->rows != nil)					curtab->rows->flags = 0;				finish_table(curtab);				ps->skipping = 0;				additem(ps, newitable(curtab), curtab->tabletok);				addbrk(ps, 0, 0);			}		}		if(is->tabstk != nil)			is->tabstk = is->tabstk->next;		curtab->next = di->tables;		di->tables = curtab;		curtab = is->tabstk;	}	outerps = lastps(ps);	ans = outerps->items->next;	freeitem(outerps->items);	// note: ans may be nil and di->kids not nil, if there's a frameset!	outerps->items = newispacer(ISPnull);	outerps->lastit = outerps->items;	is->psstk = ps;	if(ans != nil && di->hasscripts) {		// TODO evalscript(nil);		;	}return_ans:	if(dbgbuild) {		assert(validitems(ans));		if(ans == nil)			fprint(2, "getitems returning nil\n");		else			printitems(ans, "getitems returning:");	}	return ans;}// Concatenate together maximal set of Data tokens, starting at toks[toki+1].// Lexer has ensured that there will either be a following non-data token or// we will be at eof.// Return emallocd trimmed concatenation, and update *ptoki to last used tokistatic Rune*getpcdata(Token* toks, int tokslen, int* ptoki){	Rune*	ans;	Rune*	p;	Rune*	trimans;	int	anslen;	int	trimanslen;	int	toki;	Token*	tok;	ans = nil;	anslen = 0;	// first find length of answer	toki = (*ptoki) + 1;	while(toki < tokslen) {		tok = &toks[toki];		if(tok->tag == Data) {			toki++;			anslen += _Strlen(tok->text);		}		else			break;	}	// now make up the initial answer	if(anslen > 0) {		ans = _newstr(anslen);		p = ans;		toki = (*ptoki) + 1;		while(toki < tokslen) {			tok = &toks[toki];			if(tok->tag == Data) {				toki++;				p = _Stradd(p, tok->text, _Strlen(tok->text));			}			else				break;		}		*p = 0;		_trimwhite(ans, anslen, &trimans, &trimanslen);		if(trimanslen != anslen) {			p = ans;			ans = _Strndup(trimans, trimanslen);			free(p);		}	}	*ptoki = toki-1;	return ans;}// If still parsing head of curtab->cells list, finish it off// by transferring the items on the head of psstk to the cell.// Then pop the psstk and return the new psstk.static Pstate*finishcell(Table* curtab, Pstate* psstk){	Tablecell*	c;	Pstate* psstknext;	c = curtab->cells;	if(c != nil) {		if((c->flags&TFparsing)) {			psstknext = psstk->next;			if(psstknext == nil) {				if(warn)					fprint(2, "warning: parse state stack is wrong\n");			}			else {				c->content = psstk->items->next;				c->flags &= ~TFparsing;				freepstate(psstk);				psstk = psstknext;			}		}	}	return psstk;}// Make a new Pstate for a cell, based on the old pstate, oldps.// Also, put the new ps on the head of the oldps stack.static Pstate*cell_pstate(Pstate* oldps, int ishead){	Pstate*	ps;	int	sty;	ps = newpstate(oldps);	ps->skipwhite = 1;	ps->curanchor = oldps->curanchor;	copystack(&ps->fntstylestk, &oldps->fntstylestk);	copystack(&ps->fntsizestk, &oldps->fntsizestk);	ps->curfont = oldps->curfont;	ps->curfg = oldps->curfg;	ps->curbg = oldps->curbg;	copystack(&ps->fgstk, &oldps->fgstk);	ps->adjsize = oldps->adjsize;	if(ishead) {		sty = ps->curfont%NumSize;		ps->curfont = FntB*NumSize + sty;	}	return ps;}// Return a new Pstate with default starting state.// Use link to add it to head of a list, if any.static Pstate*newpstate(Pstate* link){	Pstate*	ps;	ps = (Pstate*)emalloc(sizeof(Pstate));	ps->curfont = DefFnt;	ps->curfg = Black;	ps->curbg.image = nil;	ps->curbg.color = White;	ps->curul = ULnone;	ps->curjust = ALleft;	ps->curstate = IFwrap;	ps->items = newispacer(ISPnull);	ps->lastit = ps->items;	ps->prelastit = nil;	ps->next = link;	return ps;}// Return last Pstate on psl liststatic Pstate*lastps(Pstate* psl){	assert(psl != nil);	while(psl->next != nil)		psl = psl->next;	return psl;}// Add it to end of ps item chain, adding in current state from ps.// Also, if tok is not nil, scan it for generic attributes and assign// the genattr field of the item accordingly.static voidadditem(Pstate* ps, Item* it, Token* tok){	int	aid;	int	any;	Rune*	i;	Rune*	c;	Rune*	s;	Rune*	t;	Attr*	a;	SEvent*	e;	if(ps->skipping) {		if(warn)			fprint(2, "warning: skipping item: %I\n", it);		return;	}	it->anchorid = ps->curanchor;	it->state |= ps->curstate;	if(tok != nil) {		any = 0;		i = nil;		c = nil;		s = nil;		t = nil;		e = nil;		for(a = tok->attr; a != nil; a = a->next) {			aid = a->attid;			if(!attrinfo[aid])				continue;			switch(aid) {			case Aid:				i = a->value;				break;			case Aclass:				c = a->value;				break;			case Astyle:				s = a->value;				break;			case Atitle:				t = a->value;				break;			default:				assert(aid >= Aonblur && aid <= Aonunload);				e = newscriptevent(scriptev[a->attid], a->value, e);				break;			}			a->value = nil;			any = 1;		}		if(any)			it->genattr = newgenattr(i, c, s, t, e);	}	ps->curstate &= ~(IFbrk|IFbrksp|IFnobrk|IFcleft|IFcright);	ps->prelastit = ps->lastit;	ps->lastit->next = it;	ps->lastit = it;}// Make a text item out of s,// using current font, foreground, vertical offset and underline state.static Item*textit(Pstate* ps, Rune* s){	assert(s != nil);	return newitext(s, ps->curfont, ps->curfg, ps->curvoff + Voffbias, ps->curul);}// Add text item or items for s, paying attention to// current font, foreground, baseline offset, underline state,// and literal mode.  Unless we're in literal mode, compress// whitespace to single blank, and, if curstate has a break,// trim any leading whitespace.  Whether in literal mode or not,// turn nonbreaking spaces into spacer items with IFnobrk set.//// In literal mode, break up s at newlines and add breaks instead.// Also replace tabs appropriate number of spaces.// In nonliteral mode, break up the items every 100 or so characters// just to make the layout algorithm not go quadratic.//// addtext assumes ownership of s.static voidaddtext(Pstate* ps, Rune* s){	int	n;	int	i;	int	j;	int	k;	int	col;	int	c;	int	nsp;	Item*	it;	Rune*	ss;	Rune*	p;	Rune	buf[SMALLBUFSIZE];	assert(s != nil);	n = runestrlen(s);	i = 0;	j = 0;	if(ps->literal) {		col = 0;		while(i < n) {			if(s[i] == '\n') {				if(i > j) {					// trim trailing blanks from line					for(k = i; k > j; k--)						if(s[k - 1] != ' ')							break;					if(k > j)						additem(ps, textit(ps, _Strndup(s+j, k-j)), nil);				}				addlinebrk(ps, 0);				j = i + 1;				col = 0;			}			else {				if(s[i] == '\t') {					col += i - j;					nsp = 8 - (col%8);					// make ss = s[j:i] + nsp spaces					ss = _newstr(i-j+nsp);					p = _Stradd(ss, s+j, i-j);					p = _Stradd(p, L"        ", nsp);					*p = 0;					additem(ps, textit(ps, ss), nil);					col += nsp;					j = i + 1;				}				else if(s[i] == NBSP) {					if(i > j)						additem(ps, textit(ps, _Strndup(s+j, i-j)), nil);					addnbsp(ps);					col += (i - j) + 1;					j = i + 1;				}			}			i++;		}		if(i > j) {			if(j == 0 && i == n) {				// just transfer s over				additem(ps, textit(ps, s), nil);			}			else {				additem(ps, textit(ps, _Strndup(s+j, i-j)), nil);				free(s);			}		}	}	else {	// not literal mode		if((ps->curstate&IFbrk) || ps->lastit == ps->items)			while(i < n) {				c = s[i];				if(c >= 256 || !isspace(c))					break;				i++;			}		p = buf;		for(j = i; i < n; i++) {			assert(p+i-j < buf+SMALLBUFSIZE-1);			c = s[i];			if(c == NBSP) {				if(i > j)					p = _Stradd(p, s+j, i-j);				if(p > buf)

⌨️ 快捷键说明

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