コード例 #1
0
ファイル: unifdef.c プロジェクト: ganwell/chirp
/*
 * Parse a line and determine its type. We keep the preprocessor line
 * parser state between calls in the global variable linestate, with
 * help from skipcomment().
 */
static Linetype
parseline(void)
{
	const char *cp;
	int cursym;
	Linetype retval;
	Comment_state wascomment;

	wascomment = incomment;
	cp = skiphash();
	if (cp == NULL)
		return (LT_EOF);
	if (newline == NULL) {
		if (strrchr(tline, '\n') == strrchr(tline, '\r') + 1)
			newline = newline_crlf;
		else
			newline = newline_unix;
	}
	if (*cp == '\0') {
		retval = LT_PLAIN;
		goto done;
	}
	keyword = tline + (cp - tline);
	if ((cp = matchsym("ifdef", keyword)) != NULL ||
	    (cp = matchsym("ifndef", keyword)) != NULL) {
		cp = skipcomment(cp);
		if ((cursym = findsym(&cp)) < 0)
			retval = LT_IF;
		else {
			retval = (keyword[2] == 'n')
			    ? LT_FALSE : LT_TRUE;
			if (value[cursym] == NULL)
				retval = (retval == LT_TRUE)
				    ? LT_FALSE : LT_TRUE;
			if (ignore[cursym])
				retval = (retval == LT_TRUE)
				    ? LT_TRUEI : LT_FALSEI;
		}
	} else if ((cp = matchsym("if", keyword)) != NULL)
		retval = ifeval(&cp);
	else if ((cp = matchsym("elif", keyword)) != NULL)
		retval = linetype_if2elif(ifeval(&cp));
	else if ((cp = matchsym("else", keyword)) != NULL)
		retval = LT_ELSE;
	else if ((cp = matchsym("endif", keyword)) != NULL)
		retval = LT_ENDIF;
	else {
		cp = skipsym(keyword);
		/* no way can we deal with a continuation inside a keyword */
		if (strncmp(cp, "\\\r\n", 3) == 0 ||
		    strncmp(cp, "\\\n", 2) == 0)
			Eioccc();
		cp = skipline(cp);
		retval = LT_PLAIN;
		goto done;
	}
	cp = skipcomment(cp);
	if (*cp != '\0') {
		cp = skipline(cp);
		if (retval == LT_TRUE || retval == LT_FALSE ||
		    retval == LT_TRUEI || retval == LT_FALSEI)
			retval = LT_IF;
		if (retval == LT_ELTRUE || retval == LT_ELFALSE)
			retval = LT_ELIF;
	}
	/* the following can happen if the last line of the file lacks a
	   newline or if there is too much whitespace in a directive */
	if (linestate == LS_HASH) {
		long len = cp - tline;
		if (fgets(tline + len, MAXLINE - len, input) == NULL) {
			if (ferror(input))
				err(2, "can't read %s", filename);
			/* append the missing newline at eof */
			strcpy(tline + len, newline);
			cp += strlen(newline);
			linestate = LS_START;
		} else {
			linestate = LS_DIRTY;
		}
	}
	if (retval != LT_PLAIN && (wascomment || linestate != LS_START)) {
		retval = linetype_2dodgy(retval);
		linestate = LS_DIRTY;
	}
done:
	debug("parser line %d state %s comment %s line", linenum,
	    comment_name[incomment], linestate_name[linestate]);
	return (retval);
}
コード例 #2
0
/*
 * Parse a line and determine its type. We keep the preprocessor line
 * parser state between calls in the global variable linestate, with
 * help from skipcomment().
 */
static Linetype
parseline(void)
{
	const char *cp;
	int cursym;
	int kwlen;
	Linetype retval;
	Comment_state wascomment;

	linenum++;
	if (fgets(tline, MAXLINE, input) == NULL) {
		if (ferror(input))
			err(2, "can't read %s", filename);
		else
			return (LT_EOF);
	}
	if (newline == NULL) {
		if (strrchr(tline, '\n') == strrchr(tline, '\r') + 1)
			newline = newline_crlf;
		else
			newline = newline_unix;
	}
	retval = LT_PLAIN;
	wascomment = incomment;
	cp = skipcomment(tline);
	if (linestate == LS_START) {
		if (*cp == '#') {
			linestate = LS_HASH;
			firstsym = true;
			cp = skipcomment(cp + 1);
		} else if (*cp != '\0')
			linestate = LS_DIRTY;
	}
	if (!incomment && linestate == LS_HASH) {
		keyword = tline + (cp - tline);
		cp = skipsym(cp);
		kwlen = cp - keyword;
		/* no way can we deal with a continuation inside a keyword */
		if (strncmp(cp, "\\\r\n", 3) == 0 ||
		    strncmp(cp, "\\\n", 2) == 0)
			Eioccc();
		if (strlcmp("ifdef", keyword, kwlen) == 0 ||
		    strlcmp("ifndef", keyword, kwlen) == 0) {
			cp = skipcomment(cp);
			if ((cursym = findsym(cp)) < 0)
				retval = LT_IF;
			else {
				retval = (keyword[2] == 'n')
				    ? LT_FALSE : LT_TRUE;
				if (value[cursym] == NULL)
					retval = (retval == LT_TRUE)
					    ? LT_FALSE : LT_TRUE;
				if (ignore[cursym])
					retval = (retval == LT_TRUE)
					    ? LT_TRUEI : LT_FALSEI;
			}
			cp = skipsym(cp);
		} else if (strlcmp("if", keyword, kwlen) == 0)
			retval = ifeval(&cp);
		else if (strlcmp("elif", keyword, kwlen) == 0)
			retval = linetype_if2elif(ifeval(&cp));
		else if (strlcmp("else", keyword, kwlen) == 0)
			retval = LT_ELSE;
		else if (strlcmp("endif", keyword, kwlen) == 0)
			retval = LT_ENDIF;
		else {
			linestate = LS_DIRTY;
			retval = LT_PLAIN;
		}
		cp = skipcomment(cp);
		if (*cp != '\0') {
			linestate = LS_DIRTY;
			if (retval == LT_TRUE || retval == LT_FALSE ||
			    retval == LT_TRUEI || retval == LT_FALSEI)
				retval = LT_IF;
			if (retval == LT_ELTRUE || retval == LT_ELFALSE)
				retval = LT_ELIF;
		}
		if (retval != LT_PLAIN && (wascomment || incomment)) {
			retval = linetype_2dodgy(retval);
			if (incomment)
				linestate = LS_DIRTY;
		}
		/* skipcomment normally changes the state, except
		   if the last line of the file lacks a newline, or
		   if there is too much whitespace in a directive */
		if (linestate == LS_HASH) {
			size_t len = cp - tline;
			if (fgets(tline + len, MAXLINE - len, input) == NULL) {
				if (ferror(input))
					err(2, "can't read %s", filename);
				/* append the missing newline at eof */
				strcpy(tline + len, newline);
				cp += strlen(newline);
				linestate = LS_START;
			} else {
				linestate = LS_DIRTY;
			}
		}
	}
	if (linestate == LS_DIRTY) {
		while (*cp != '\0')
			cp = skipcomment(cp + 1);
	}
	debug("parser line %d state %s comment %s line", linenum,
	    comment_name[incomment], linestate_name[linestate]);
	return (retval);
}