FreeBSD/contrib/mdocml/roff.c
/*
 * In the current line, expand escape sequences that tend to get
 * used in numerical expressions and conditional requests.
 * Also check the syntax of the remaining escape sequences.
 */
In the current line, expand escape sequences that tend to get
used in numerical expressions and conditional requests.
Also check the syntax of the remaining escape sequences.
In the current line expand escape sequences that tend to get used in numerical expressions and conditional requests . Also check the syntax of the remaining escape sequences .
static enum rofferr
roff_res(struct roff *r, struct buf *buf, int ln, int pos)
{
	char		 ubuf[24]; 
	const char	*start;	
	char		*stesc;	
	const char	*stnam;	
	const char	*cp;	
	const char	*res;	
	char		*nbuf;	
	size_t		 maxl;  
	size_t		 naml;	
	enum mandoc_esc	 esc;	
	int		 inaml;	
	int		 expand_count;	
	int		 npos;	
	int		 arg_complete; 
	char		 term;	
	expand_count = 0;
	start = buf->buf + pos;
	stesc = strchr(start, '\0') - 1;
	while (stesc-- > start) {
		if (*stesc != '\\')
			continue;
		for (cp = stesc - 1; cp >= start; cp--)
			if (*cp != '\\')
				break;
		if ((stesc - cp) % 2 == 0) {
			stesc = (char *)cp;
			continue;
		}
		term = '\0';
		cp = stesc + 1;
		switch (*cp) {
		case '*':
			res = NULL;
			break;
		case 'B':
		case 'w':
			term = cp[1];
		case 'n':
			res = ubuf;
			break;
		default:
			esc = mandoc_escape(&cp, &stnam, &inaml);
			if (esc == ESCAPE_ERROR ||
			    (esc == ESCAPE_SPECIAL &&
			     mchars_spec2cp(stnam, inaml) < 0))
				mandoc_vmsg(MANDOCERR_ESC_BAD,
				    r->parse, ln, (int)(stesc - buf->buf),
				    "%.*s", (int)(cp - stesc), stesc);
			continue;
		}
		if (EXPAND_LIMIT < ++expand_count) {
			mandoc_msg(MANDOCERR_ROFFLOOP, r->parse,
			    ln, (int)(stesc - buf->buf), NULL);
			return ROFF_IGN;
		}
		if (term == '\0') {
			switch (*++cp) {
			case '\0':
				maxl = 0;
				break;
			case '(':
				cp++;
				maxl = 2;
				break;
			case '[':
				cp++;
				term = ']';
				maxl = 0;
				break;
			default:
				maxl = 1;
				break;
			}
		} else {
			cp += 2;
			maxl = 0;
		}
		stnam = cp;
		naml = 0;
		arg_complete = 1;
		while (maxl == 0 || naml < maxl) {
			if (*cp == '\0') {
				mandoc_msg(MANDOCERR_ESC_BAD, r->parse,
				    ln, (int)(stesc - buf->buf), stesc);
				arg_complete = 0;
				break;
			}
			if (maxl == 0 && *cp == term) {
				cp++;
				break;
			}
			if (*cp++ != '\\' || stesc[1] != 'w') {
				naml++;
				continue;
			}
			switch (mandoc_escape(&cp, NULL, NULL)) {
			case ESCAPE_SPECIAL:
			case ESCAPE_UNICODE:
			case ESCAPE_NUMBERED:
			case ESCAPE_OVERSTRIKE:
				naml++;
				break;
			default:
				break;
			}
		}
		switch (stesc[1]) {
		case '*':
			if (arg_complete)
				res = roff_getstrn(r, stnam, naml);
			break;
		case 'B':
			npos = 0;
			ubuf[0] = arg_complete &&
			    roff_evalnum(r, ln, stnam, &npos,
			      NULL, ROFFNUM_SCALE) &&
			    stnam + npos + 1 == cp ? '1' : '0';
			ubuf[1] = '\0';
			break;
		case 'n':
			if (arg_complete)
				(void)snprintf(ubuf, sizeof(ubuf), "%d",
				    roff_getregn(r, stnam, naml));
			else
				ubuf[0] = '\0';
			break;
		case 'w':
			(void)snprintf(ubuf, sizeof(ubuf), "%d",
			    24 * (int)naml);
			break;
		}
		if (res == NULL) {
			mandoc_vmsg(MANDOCERR_STR_UNDEF,
			    r->parse, ln, (int)(stesc - buf->buf),
			    "%.*s", (int)naml, stnam);
			res = "";
		} else if (buf->sz + strlen(res) > SHRT_MAX) {
			mandoc_msg(MANDOCERR_ROFFLOOP, r->parse,
			    ln, (int)(stesc - buf->buf), NULL);
			return ROFF_IGN;
		}
		*stesc = '\0';
		buf->sz = mandoc_asprintf(&nbuf, "%s%s%s",
		    buf->buf, res, cp) + 1;
		start = nbuf + pos;
		stesc = nbuf + (stesc - buf->buf) + strlen(res);
		free(buf->buf);
		buf->buf = nbuf;
	}
	return ROFF_CONT;
}
static enum rofferr roff_res ( struct roff * r , struct buf * buf , int ln , int pos ) { char ubuf [ 24 ] ; const char * start ; char * stesc ; const char * stnam ; const char * cp ; const char * res ; char * nbuf ; size_t maxl ; size_t naml ; enum mandoc_esc esc ; int inaml ; int expand_count ; int npos ; int arg_complete ; char term ; expand_count = 0 ; start = buf -> buf + pos ; stesc = strchr ( start , ' \0 ' ) - 1 ; while ( stesc -- > start ) { if ( * stesc != ' \\ ' ) continue ; for ( cp = stesc - 1 ; cp >= start ; cp -- ) if ( * cp != ' \\ ' ) break ; if ( ( stesc - cp ) % 2 == 0 ) { stesc = ( char * ) cp ; continue ; } term = ' \0 ' ; cp = stesc + 1 ; switch ( * cp ) { case ' ' : res = NULL ; break ; case ' ' : case ' ' : term = cp [ 1 ] ; case ' ' : res = ubuf ; break ; default : esc = mandoc_escape ( & cp , & stnam , & inaml ) ; if ( esc == ESCAPE_ERROR || ( esc == ESCAPE_SPECIAL && mchars_spec2cp ( stnam , inaml ) < 0 ) ) mandoc_vmsg ( MANDOCERR_ESC_BAD , r -> parse , ln , ( int ) ( stesc - buf -> buf ) , " " , ( int ) ( cp - stesc ) , stesc ) ; continue ; } if ( EXPAND_LIMIT < ++ expand_count ) { mandoc_msg ( MANDOCERR_ROFFLOOP , r -> parse , ln , ( int ) ( stesc - buf -> buf ) , NULL ) ; return ROFF_IGN ; } if ( term == ' \0 ' ) { switch ( * ++ cp ) { case ' \0 ' : maxl = 0 ; break ; case ' ' : cp ++ ; maxl = 2 ; break ; case ' ' : cp ++ ; term = ' ' ; maxl = 0 ; break ; default : maxl = 1 ; break ; } } else { cp += 2 ; maxl = 0 ; } stnam = cp ; naml = 0 ; arg_complete = 1 ; while ( maxl == 0 || naml < maxl ) { if ( * cp == ' \0 ' ) { mandoc_msg ( MANDOCERR_ESC_BAD , r -> parse , ln , ( int ) ( stesc - buf -> buf ) , stesc ) ; arg_complete = 0 ; break ; } if ( maxl == 0 && * cp == term ) { cp ++ ; break ; } if ( * cp ++ != ' \\ ' || stesc [ 1 ] != ' ' ) { naml ++ ; continue ; } switch ( mandoc_escape ( & cp , NULL , NULL ) ) { case ESCAPE_SPECIAL : case ESCAPE_UNICODE : case ESCAPE_NUMBERED : case ESCAPE_OVERSTRIKE : naml ++ ; break ; default : break ; } } switch ( stesc [ 1 ] ) { case ' ' : if ( arg_complete ) res = roff_getstrn ( r , stnam , naml ) ; break ; case ' ' : npos = 0 ; ubuf [ 0 ] = arg_complete && roff_evalnum ( r , ln , stnam , & npos , NULL , ROFFNUM_SCALE ) && stnam + npos + 1 == cp ? ' ' : ' ' ; ubuf [ 1 ] = ' \0 ' ; break ; case ' ' : if ( arg_complete ) ( void ) snprintf ( ubuf , sizeof ( ubuf ) , " " , roff_getregn ( r , stnam , naml ) ) ; else ubuf [ 0 ] = ' \0 ' ; break ; case ' ' : ( void ) snprintf ( ubuf , sizeof ( ubuf ) , " " , 24 * ( int ) naml ) ; break ; } if ( res == NULL ) { mandoc_vmsg ( MANDOCERR_STR_UNDEF , r -> parse , ln , ( int ) ( stesc - buf -> buf ) , " " , ( int ) naml , stnam ) ; res = " " ; } else if ( buf -> sz + strlen ( res ) > SHRT_MAX ) { mandoc_msg ( MANDOCERR_ROFFLOOP , r -> parse , ln , ( int ) ( stesc - buf -> buf ) , NULL ) ; return ROFF_IGN ; } * stesc = ' \0 ' ; buf -> sz = mandoc_asprintf ( & nbuf , " " , buf -> buf , res , cp ) + 1 ; start = nbuf + pos ; stesc = nbuf + ( stesc - buf -> buf ) + strlen ( res ) ; free ( buf -> buf ) ; buf -> buf = nbuf ; } return ROFF_CONT ; }
In the current line, expand escape sequences that tend to get
 used in numerical expressions and conditional requests.
In the current line expand escape sequences that tend to get used in numerical expressions and conditional requests .
/* buffer to print the number */ /* start of the string to process */ /* start of an escape sequence ('\\') */ /* start of the name, after "[(*" */ /* end of the name, e.g. before ']' */ /* the string to be substituted */ /* new buffer to copy buf->buf to */ /* expected length of the escape name */ /* actual length of the escape name */ /* type of the escape sequence */ /* length returned from mandoc_escape() */ /* to avoid infinite loops */ /* position in numeric expression */ /* argument not interrupted by eol */ /* character terminating the escape */ /* Search backwards for the next backslash. */ /* If it is escaped, skip it. */ /* Decide whether to expand or to check only. */ /* FALLTHROUGH */ /*
		 * The third character decides the length
		 * of the name of the string or register.
		 * Save a pointer to the name.
		 */ /* Advance to the end of the name. */ /*
		 * Retrieve the replacement string; if it is
		 * undefined, resume searching for escapes.
		 */ /* use even incomplete args */ /* Replace the escape sequence by the string. */ /* Prepare for the next replacement. */