コード例 #1
0
ファイル: extoken.c プロジェクト: aosm/graphviz
int
extoken_fn(register Expr_t* ex)
{
	register int	c;
	register char*	s;
	register int	q;
	char*		e;

	if (ex->eof || ex->errors)
		return 0;
 again:
	for (;;) switch (c = lex(ex))
	{
	case 0:
		goto eof;
	case '/':
		switch (q = lex(ex))
		{
		case '*':
			for (;;) switch (lex(ex))
			{
			case '\n':
				BUMP (error_info.line);
				continue;
			case '*':
				switch (lex(ex))
				{
				case 0:
					goto eof;
				case '\n':
					BUMP (error_info.line);
					break;
				case '*':
					exunlex(ex, '*');
					break;
				case '/':
					goto again;
				}
				break;
			}
			break;
		case '/':
			while ((c = lex(ex)) != '\n')
				if (!c)
					goto eof;
			break;
		default:
			goto opeq;
		}
		/*FALLTHROUGH*/
	case '\n':
		BUMP (error_info.line);
		/*FALLTHROUGH*/
	case ' ':
	case '\t':
		break;
	case '(':
	case '{':
	case '[':
		ex->input->nesting++;
		return exlval.op = c;
	case ')':
	case '}':
	case ']':
		ex->input->nesting--;
		return exlval.op = c;
	case '+':
	case '-':
		if ((q = lex(ex)) == c)
			return exlval.op = c == '+' ? INC : DEC;
		goto opeq;
	case '*':
	case '%':
	case '^':
		q = lex(ex);
	opeq:
		exlval.op = c;
		if (q == '=')
			c = '=';
		else if (q == '%' && c == '%')
		{
			if (ex->input->fp)
				ex->more = (const char*)ex->input->fp;
			else ex->more = ex->input->sp;
			goto eof;
		}
		else exunlex(ex, q);
		return c;
	case '&':
	case '|':
		if ((q = lex(ex)) == '=')
		{
			exlval.op = c;
			return '=';
		}
		if (q == c)
			c = c == '&' ? AND : OR;
		else exunlex(ex, q);
		return exlval.op = c;
	case '<':
	case '>':
		if ((q = lex(ex)) == c)
		{
			exlval.op = c = c == '<' ? LS : RS;
			if ((q = lex(ex)) == '=')
				c = '=';
			else exunlex(ex, q);
			return c;
		}
		goto relational;
	case '=':
	case '!':
		q = lex(ex);
	relational:
		if (q == '=') switch (c)
		{
		case '<':
			c = LE;
			break;
		case '>':
			c = GE;
			break;
		case '=':
			c = EQ;
			break;
		case '!':
			c = NE;
			break;
		}
		else exunlex(ex, q);
		return exlval.op = c;
	case '#':
		if (!ex->linewrap && !(ex->disc->flags & EX_PURE))
		{
			s = ex->linep - 1;
			while (s > ex->line && isspace(*(s - 1)))
				s--;
			if (s == ex->line)
			{
				switch (extoken_fn(ex))
				{
				case DYNAMIC:
				case ID:
				case NAME:
					s = exlval.id->name;
					break;
				default:
					s = "";
					break;
				}
				if (streq(s, "include"))
				{
					if (extoken_fn(ex) != STRING)
						exerror("#%s: string argument expected", s);
					else if (!expush(ex, exlval.string, 1, NiL, NiL))
					{
						setcontext(ex);
						goto again;
					}
				}
				else exerror("unknown directive");
			}
		}
		return exlval.op = c;
	case '\'':
	case '"':
		q = c;
		sfstrset(ex->tmp, 0);
		ex->input->nesting++;
		while ((c = lex(ex)) != q)
		{
			if (c == '\\')
			{
				sfputc(ex->tmp, c);
				c = lex(ex);
			}
			if (!c)
			{
				exerror("unterminated %c string", q);
				goto eof;
			}
			if (c == '\n')
			{
				BUMP (error_info.line);
			}
			sfputc(ex->tmp, c);
		}
		ex->input->nesting--;
		s = sfstruse(ex->tmp);
		if (q == '"' || (ex->disc->flags & EX_CHARSTRING))
		{
			if (!(exlval.string = vmstrdup(ex->vm, s)))
				goto eof;
			stresc(exlval.string);
			return STRING;
		}
		exlval.integer = chrtoi(s);
		return INTEGER;
	case '.':
		if (isdigit(c = lex(ex)))
		{
			sfstrset(ex->tmp, 0);
			sfputc(ex->tmp, '0');
			sfputc(ex->tmp, '.');
			goto floating;
		}
		exunlex(ex, c);
		return exlval.op = '.';
	case '0': case '1': case '2': case '3': case '4':
	case '5': case '6': case '7': case '8': case '9':
		sfstrset(ex->tmp, 0);
		sfputc(ex->tmp, c);
		q = INTEGER;
		if ((c = lex(ex)) == 'x' || c == 'X')
		{
			sfputc(ex->tmp, c);
			for (;;)
			{
				switch (c = lex(ex))
				{
				case '0': case '1': case '2': case '3': case '4':
				case '5': case '6': case '7': case '8': case '9':
				case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 
				case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 
					sfputc(ex->tmp, c);
					continue;
				}
				break;
			}
		}
		else
		{
			while (isdigit(c))
			{
				sfputc(ex->tmp, c);
				c = lex(ex);
			}
			if (c == '#')
			{
				sfputc(ex->tmp, c);
				/* s = sfstruse(ex->tmp); */
				/* b = strtol(s, NiL, 10); */
				do
				{
					sfputc(ex->tmp, c);
				} while (isalnum(c = lex(ex)));
			}
			else
			{
				if (c == '.')
				{
				floating:
					q = FLOATING;
					sfputc(ex->tmp, c);
					while (isdigit(c = lex(ex)))
						sfputc(ex->tmp, c);
				}
				if (c == 'e' || c == 'E')
				{
					q = FLOATING;
					sfputc(ex->tmp, c);
					if ((c = lex(ex)) == '-' || c == '+')
					{
						sfputc(ex->tmp, c);
						c = lex(ex);
					}
					while (isdigit(c))
					{
						sfputc(ex->tmp, c);
						c = lex(ex);
					}
				}
			}
		}
		s = sfstruse(ex->tmp);
		if (q == FLOATING)
			exlval.floating = strtod(s, &e);
		else
		{
			if (c == 'u' || c == 'U')
			{
				q = UNSIGNED;
				c = lex(ex);
				exlval.integer = strToL(s, &e);
			}
			else
				exlval.integer = strToL(s, &e);
			if (*e)
			{
				*--e = 1;
				exlval.integer *= strton(e, &e, NiL, 0);
			}
		}
		exunlex(ex, c);
		if (*e || isalpha(c) || c == '_' || c == '$')
		{
			exerror("%s: invalid numeric constant", s);
			goto eof;
		}
		return q;
	default:
		if (isalpha(c) || c == '_' || c == '$')
		{
			sfstrset(ex->tmp, 0);
			sfputc(ex->tmp, c);
			while (isalnum(c = lex(ex)) || c == '_' || c == '$')
				sfputc(ex->tmp, c);
			exunlex(ex, c);
			s = sfstruse(ex->tmp);
			if (!(exlval.id = (Exid_t*)dtmatch(ex->symbols, s)))
			{
				if (!(exlval.id = newof(0, Exid_t, 1, strlen(s) - EX_NAMELEN + 1)))
				{
					exerror("out of space");
					goto eof;
				}
				strcpy(exlval.id->name, s);
				exlval.id->lex = NAME;
				dtinsert((ex->formals || !ex->symbols->view) ? ex->symbols : ex->symbols->view, exlval.id);
			}

			/*
			 * lexical analyzer state controlled by the grammar
			 */

			switch (exlval.id->lex)
			{
			case DECLARE:
				if (exlval.id->index == CHAR)
				{
					/*
					 * `char*' === `string'
					 * the * must immediately follow char
					 */

					if (c == '*')
					{
						lex(ex);
						exlval.id = id_string;
					}
				}
				break;
			case NAME:
				/*
				 * action labels are disambiguated from ?:
				 * through the expr.nolabel grammar hook
				 * the : must immediately follow labels
				 */

				if (c == ':' && !expr.nolabel)
					return LABEL;
				break;
			case PRAGMA:
				/*
				 * user specific statement stripped and
				 * passed as string
				 */

				{
					int	b;
					int	n;
					int	pc = 0;
					int	po;
					int	t;

					/*UNDENT...*/
	sfstrset(ex->tmp, 0);
	b = 1;
	n = 0;
	po = 0;
	t = 0;
	for (c = t = lex(ex);; c = lex(ex))
	{
		switch (c)
		{
		case 0:
			goto eof;
		case '/':
			switch (q = lex(ex))
			{
			case '*':
				for (;;)
				{
					switch (lex(ex))
					{
					case '\n':
						BUMP (error_info.line);
						continue;
					case '*':
						switch (lex(ex))
						{
						case 0:
							goto eof;
						case '\n':
							BUMP (error_info.line);
							continue;
						case '*':
							exunlex(ex, '*');
							continue;
						case '/':
							break;
						default:
							continue;
						}
						break;
					}
					if (!b++)
						goto eof;
					sfputc(ex->tmp, ' ');
					break;
				}
				break;
			case '/':
				while ((c = lex(ex)) != '\n')
					if (!c)
						goto eof;
				BUMP (error_info.line);
				b = 1;
				sfputc(ex->tmp, '\n');
				break;
			default:
				b = 0;
				sfputc(ex->tmp, c);
				sfputc(ex->tmp, q);
				break;
			}
			continue;
		case '\n':
			BUMP (error_info.line);
			b = 1;
			sfputc(ex->tmp, '\n');
			continue;
		case ' ':
		case '\t':
			if (!b++)
				goto eof;
			sfputc(ex->tmp, ' ');
			continue;
		case '(':
		case '{':
		case '[':
			b = 0;
			if (!po)
			{
				switch (po = c)
				{
				case '(':
					pc = ')';
					break;
				case '{':
					pc = '}';
					break;
				case '[':
					pc = ']';
					break;
				}
				n++;
			}
			else if (c == po)
				n++;
			sfputc(ex->tmp, c);
			continue;
		case ')':
		case '}':
		case ']':
			b = 0;
			if (!po)
			{
				exunlex(ex, c);
				break;
			}
			sfputc(ex->tmp, c);
			if (c == pc && --n <= 0)
			{
				if (t == po)
					break;
				po = 0;
			}
			continue;
		case ';':
			b = 0;
			if (!n)
				break;
			sfputc(ex->tmp, c);
			continue;
		case '\'':
		case '"':
			b = 0;
			sfputc(ex->tmp, c);
			ex->input->nesting++;
			q = c;
			while ((c = lex(ex)) != q)
			{
				if (c == '\\')
				{
					sfputc(ex->tmp, c);
					c = lex(ex);
				}
				if (!c)
				{
					exerror("unterminated %c string", q);
					goto eof;
				}
				if (c == '\n')
				{
					BUMP (error_info.line);
				}
				sfputc(ex->tmp, c);
			}
			ex->input->nesting--;
			continue;
		default:
			b = 0;
			sfputc(ex->tmp, c);
			continue;
		}
		break;
	}
	(*ex->disc->reff)(ex, NiL, exlval.id, NiL, sfstruse(ex->tmp), 0, ex->disc);

					/*..INDENT*/
				}
				goto again;
			}
			return exlval.id->lex;
		}
		return exlval.op = c;
	}
 eof:
	ex->eof = 1;
	return exlval.op = ';';
}
コード例 #2
0
ファイル: ppexpr.c プロジェクト: ISLEcode/kornshell
static long
subexpr(register int precedence, int* pun)
{
	register int		c;
	register long		n;
	register long		x;
	register int		operand = 1;
	int			un = 0;
	int			xn;

	switch (lex(c))
	{
	case 0:
	case '\n':
		unlex(c);
		if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "more tokens expected";
		return 0;
	case '-':
		n = -subexpr(13, &un);
		break;
	case '+':
		n = subexpr(13, &un);
		break;
	case '!':
		n = !subexpr(13, &un);
		break;
	case '~':
		n = ~subexpr(13, &un);
		break;
	default:
		unlex(c);
		n = 0;
		operand = 0;
		break;
	}
	un <<= 1;
	for (;;)
	{
		switch (lex(c))
		{
		case 0:
		case '\n':
			goto done;
		case ')':
			if (!precedence)
			{
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "too many )'s";
				return 0;
			}
			goto done;
		case '(':
			n = subexpr(1, &un);
			if (lex(c) != ')')
			{
				unlex(c);
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "closing ) expected";
				return 0;
			}
		gotoperand:
			if (operand)
			{
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operator expected";
				return 0;
			}
			operand = 1;
			un <<= 1;
			continue;
		case '?':
			if (precedence > 1) goto done;
			un = 0;
			if (lex(c) == ':')
			{
				if (!n) n = subexpr(2, &un);
				else
				{
					x = pp.mode;
					pp.mode |= INACTIVE;
					subexpr(2, &xn);
					pp.mode = x;
				}
			}
			else
			{
				unlex(c);
				x = subexpr(2, &xn);
				if (lex(c) != ':')
				{
					unlex(c);
					if (!errmsg && !(pp.mode & INACTIVE)) errmsg = ": expected for ? operator";
					return 0;
				}
				if (n)
				{
					n = x;
					un = xn;
					subexpr(2, &xn);
				}
				else n = subexpr(2, &un);
			}
			break;
		case ':':
			goto done;
		case T_ANDAND:
		case T_OROR:
			xn = (c == T_ANDAND) ? 4 : 3;
			if (precedence >= xn) goto done;
			if ((n != 0) == (c == T_ANDAND)) n = subexpr(xn, &un) != 0;
			else
			{
				x = pp.mode;
				pp.mode |= INACTIVE;
				subexpr(xn, &un);
				pp.mode = x;
			}
			un = 0;
			break;
		case '|':
			if (precedence > 4) goto done;
			n |= subexpr(5, &un);
			break;
		case '^':
			if (precedence > 5) goto done;
			n ^= subexpr(6, &un);
			break;
		case '&':
			if (precedence > 6) goto done;
			n &= subexpr(7, &un);
			break;
		case T_EQ:
		case T_NE:
			if (precedence > 7) goto done;
			n = (n == subexpr(8, &un)) == (c == T_EQ);
			un = 0;
			break;
		case '<':
		case T_LE:
		case T_GE:
		case '>':
			if (precedence > 8) goto done;
			x = subexpr(9, &un);
			switch (c)
			{
			case '<':
				switch (un)
				{
				case 01:
					n = n < (unsigned long)x;
					break;
				case 02:
					n = (unsigned long)n < x;
					break;
				case 03:
					n = (unsigned long)n < (unsigned long)x;
					break;
				default:
					n = n < x;
					break;
				}
				break;
			case T_LE:
				switch (un)
				{
				case 01:
					n = n <= (unsigned long)x;
					break;
				case 02:
					n = (unsigned long)n <= x;
					break;
				case 03:
					n = (unsigned long)n <= (unsigned long)x;
					break;
				default:
					n = n <= x;
					break;
				}
				break;
			case T_GE:
				switch (un)
				{
				case 01:
					n = n >= (unsigned long)x;
					break;
				case 02:
					n = (unsigned long)n >= x;
					break;
				case 03:
					n = (unsigned long)n >= (unsigned long)x;
					break;
				default:
					n = n >= x;
					break;
				}
				break;
			case '>':
				switch (un)
				{
				case 01:
					n = n > (unsigned long)x;
					break;
				case 02:
					n = (unsigned long)n > x;
					break;
				case 03:
					n = (unsigned long)n > (unsigned long)x;
					break;
				default:
					n = n > x;
					break;
				}
				break;
			}
			un = 0;
			break;
		case T_LSHIFT:
		case T_RSHIFT:
			if (precedence > 9) goto done;
			x = subexpr(10, &un);
			if (c == T_LSHIFT) n <<= x;
			else n >>= x;
			un >>= 1;
			break;
		case '+':
		case '-':
			if (precedence > 10) goto done;
			x = subexpr(11, &un);
			if (c == '+') n += x;
			else n -= x;
			break;
		case '*':
		case '/':
		case '%':
			if (precedence > 11) goto done;
			x = subexpr(12, &un);
			if (c == '*') n *= x;
			else if (x == 0)
			{
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "divide by zero";
				return 0;
			}
			else if (c == '/') n /= x;
			else n %= x;
			break;
		case '#':
			pp.state |= DISABLE;
			c = pplex();
			pp.state &= ~DISABLE;
			if (c != T_ID)
			{
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "# must precede a predicate identifier";
				return 0;
			}
			n = predicate(0);
			goto gotoperand;
		case T_ID:
			n = predicate(1);
			goto gotoperand;
		case T_CHARCONST:
			c = *(pp.toknxt - 1);
			*(pp.toknxt - 1) = 0;
			n = chrtoi(pp.token + 1);
			*(pp.toknxt - 1) = c;
			if (n & ~((1<<CHAR_BIT)-1))
			{
				if (!(pp.mode & HOSTED))
					error(1, "'%s': multi-character character constants are not portable", pp.token);
			}
#if CHAR_MIN < 0
			else n = (char)n;
#endif
			goto gotoperand;
		case T_DECIMAL_U:
		case T_DECIMAL_UL:
		case T_OCTAL_U:
		case T_OCTAL_UL:
		case T_HEXADECIMAL_U:
		case T_HEXADECIMAL_UL:
			un |= 01;
			/*FALLTHROUGH*/
		case T_DECIMAL:
		case T_DECIMAL_L:
		case T_OCTAL:
		case T_OCTAL_L:
		case T_HEXADECIMAL:
		case T_HEXADECIMAL_L:
			n = strtoul(pp.token, NiL, 0);
			if ((unsigned long)n > LONG_MAX) un |= 01;
			goto gotoperand;
		case T_WCHARCONST:
			n = chrtoi(pp.token);
			goto gotoperand;
		default:
			if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid token";
			return 0;
		}
		if (errmsg) return 0;
		if (!operand) goto nooperand;
	}
 done:
	unlex(c);
	if (!operand)
	{
	nooperand:
		if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operand expected";
		return 0;
	}
	if (un) *pun |= 01;
	return n;
}