Ejemplo n.º 1
0
static char *
eat_string(int starting_line)
{
    int c;
    char buffer[500];
    char *ptr = buffer;

    for (;;) {
	/*
	 * Get the next input character, handling EOF:
	 */
	c = input();
	if (!c) {
	    unput(c);
	    report_parse_error("unterminated string found beginning",
			    starting_line);
	    return(0);
	}

	/*
	 * Deal with special characters ('\\', '"', and '\n'):
	 */
	if (c=='\\') {
	    c = eat_escape_code();
	    if (!c)
	      continue;
	} else if (c == '"') {
	    *ptr = 0;
	    return(string_Copy(buffer));
	} else if (c == '\n') {
	    unput(c);        /* fix line # reference to right line # */
	    report_parse_error("carriage return found in string", yylineno);
	    return(0);
	}

	/*
	 * Add the character c to the current string:
	 */
	*ptr = c;
	ptr++;

	/*
	 * If out of buffer space, do a recursive call then
	 * concatanate the result to the string read in so far to get the
	 * entire string and return that:
	 */
	if (ptr>buffer+sizeof(buffer)-20) {
	    string rest_of_string, result;

	    rest_of_string = eat_string(starting_line);
	    if (!rest_of_string)
	      return(0);
	    
	    *ptr = 0;
	    result = string_Concat(buffer, rest_of_string);
	    free(rest_of_string);
	    return(result);
	}
    }
}
Ejemplo n.º 2
0
int regexpr(void)
{
	int c;
	static char *buf = 0;
	static int bufsz = 500;
	char *bp;

	if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
		FATAL("out of space for rex expr");
	bp = buf;
	for ( ; (c = input()) != '/' && c != 0; ) {
		if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, 0))
			FATAL("out of space for reg expr %.10s...", buf);
		if (c == '\n') {
			SYNTAX( "newline in regular expression %.10s...", buf ); 
			unput('\n');
			break;
		} else if (c == '\\') {
			*bp++ = '\\'; 
			*bp++ = input();
		} else {
			*bp++ = c;
		}
	}
	*bp = 0;
	if (c == 0)
		SYNTAX("non-terminated regular expression %.10s...", buf);
	yylval.s = tostring(buf);
	unput('/');
	RET(REGEXPR);
}
Ejemplo n.º 3
0
int gettok(char **pbuf, int *psz)	/* get next input token */
{
	int c;
	char *buf = *pbuf;
	int sz = *psz;
	char *bp = buf;

	c = input();
	if (c == 0)
		return 0;
	buf[0] = c;
	buf[1] = 0;
	if (!isalnum(c) && c != '.' && c != '_')
		return c;

	*bp++ = c;
	if (isalpha(c) || c == '_') {	/* it's a varname */
		for ( ; (c = input()) != 0; ) {
			if (bp-buf >= sz)
				if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
					FATAL( "out of space for name %.10s...", buf );
			if (isalnum(c) || c == '_')
				*bp++ = c;
			else {
				*bp = 0;
				unput(c);
				break;
			}
		}
		*bp = 0;
	} else {	/* it's a number */
		char *rem;
		/* read input until can't be a number */
		for ( ; (c = input()) != 0; ) {
			if (bp-buf >= sz)
				if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
					FATAL( "out of space for number %.10s...", buf );
			if (isdigit(c) || c == 'e' || c == 'E' 
			  || c == '.' || c == '+' || c == '-')
				*bp++ = c;
			else {
				unput(c);
				break;
			}
		}
		*bp = 0;
		strtod(buf, &rem);	/* parse the number */
		unputstr(rem);		/* put rest back for later */
		rem[0] = 0;
	}
	*pbuf = buf;
	*psz = sz;
	return buf[0];
}
Ejemplo n.º 4
0
static char *
eat_show_line(int test_for_endshow)
{
    int c;
    int saw_escape_code = 0;
    int starting_line = yylineno;
    char buffer[200];      /* This must be large enough to hold "endshow" */
    char *ptr = buffer;

    while (yylineno == starting_line) {
	c = input();
	if (!c) {
	    unput(c);
	    *ptr = '\0';
	    return(string_Copy(buffer));
	} else if (c == '\\') {
	    saw_escape_code = 1;
	    c = eat_escape_code();
	    if (!c)
	      continue;
	}

	*ptr = c;
	ptr++;

	if ((ptr==buffer+strlen("endshow")) && test_for_endshow)
	  if (!strncmp(buffer, "endshow", strlen("endshow"))
	      && !saw_escape_code) {
	      c = input();
	      unput(c);
	      if (!is_identifier_char(c))
		return(0);
	  }

	if (ptr>buffer+sizeof(buffer)-2) {
	    string the_line;
	    string rest_of_line = eat_show_line(0);

	    *ptr = '\0';
	    the_line = string_Concat(buffer, rest_of_line);
	    free(rest_of_line);
	    return(the_line);
	}
    }

    *ptr = '\0';
    return(string_Copy(buffer));
}
Ejemplo n.º 5
0
getarg(char *p)	/* pick up single argument, store in p, return length */
{
	int n, c, npar;

	n = npar = 0;
	for ( ;; ) {
		c = input9();
		if (c == EOF)
			ERROR "end of file in getarg!" FATAL;
		if (npar == 0 && (c == ',' || c == ')'))
			break;
		if (c == '"')	/* copy quoted stuff intact */
			do {
				*p++ = c;
				n++;
			} while ((c = input9()) != '"' && c != EOF);
		else if (c == '(')
			npar++;
		else if (c == ')')
			npar--;
		n++;
		*p++ = c;
	}
	*p = 0;
	unput(c);
	return(n + 1);
}
Ejemplo n.º 6
0
Archivo: lex.c Proyecto: 99years/plan9
void getstr(char *s, int n)
{
	register int c;
	register char *p;

	p = s;
	while ((c = input()) == ' ' || c == '\n')
		;
	if (c == EOF) {
		*s = 0;
		return;
	}
	while (c != ' ' && c != '\t' && c != '\n' && c != '{' && c != '}'
	    && c != '"' && c != '~' && c != '^') {
		if (!display && c == righteq)
			break;
		if (c == '(' && p > s) {	/* might be defined(...) */
			*p = '\0';
			if (lookup(deftbl, s) != NULL)
				break;
		}
		if (c == '\\')
			if ((c = input()) != '"')
				*p++ = '\\';
		*p++ = c;
		if (--n <= 0)
			ERROR "token %.20s... too long", s FATAL;
		c = input();
	}
	unput(c);
	*p = '\0';
	yylval = (int) s;
}
Ejemplo n.º 7
0
void unputstr(const char *s)	/* put a string back on input */
{
	int i;

	for (i = strlen(s)-1; i >= 0; i--)
		unput(s[i]);
}
Ejemplo n.º 8
0
Archivo: hex.c Proyecto: mrahn/hex
int main()
{
  Pvoid_t PJArray = (Pvoid_t) NULL;
  PPosition_type pos = new_position();
  PState_DFS state = new_state();

  load_pjarray (&PJArray);

  for (int f = 0; f < LEN * LEN; ++f)
  {
    if (pos->taken[f] == N)
    {
      put (pos, state, f);
      if (_winning (pos, state, &PJArray))
      {
        show (pos);
      }
      unput (pos, f);
    }
  }

  save_pjarray (PJArray);

  Word_t Rc_word;

  JLFA (Rc_word, PJArray);

  printf ( "put %lu ins %lu hit %lu Judy-bytes %lu\n"
         , _cnt_put, _cnt_ins, _cnt_hit, Rc_word
         );

  release_position (pos);
  release_state (state);
}
Ejemplo n.º 9
0
    void unputString(const char* textp, size_t length) {
	// Add characters to input stream in back-to-front order
	const char* cp = textp;
	for (cp += length - 1; length--; cp--) {
	    unput(*cp);
	}
    }
Ejemplo n.º 10
0
char *
ifstat(double expr, char *thenpart, char *elsepart) {
	if (expr) {
		unput('\n');
		pushsrc(Free, thenpart);
		pushsrc(pString, thenpart);
		unput('\n');
  		if (elsepart)
			free(elsepart);
		return thenpart;	/* to be freed later */
	} else {
		free(thenpart);
		if (elsepart) {
			unput('\n');
			pushsrc(Free, elsepart);
			pushsrc(pString, elsepart);
			unput('\n');
		}
		return elsepart;
	}
}
Ejemplo n.º 11
0
/* Flex != lex
#undef input
#define input s_input
#undef unput
#define unput(c) s_unput(c)

char s_input(void)
{
  int c;

  if (g_buf_index <=0)
    c = getc(g_fd);
  else
    c = g_buf[--g_buf_index];
  if (c==EOF) {return '~';}
  printf("%d :%c\n",c,c);
  return c;
}
*/
int yywrap()
{
  char c;

  return 1;
  c = input();
  if (c == '~')
    return 1;
  else {
    unput(c);
    return 0;
  }
}
Ejemplo n.º 12
0
Archivo: for.c Proyecto: 99years/plan9
char *ifstat(double expr, char *thenpart, char *elsepart)
{
	dprintf("if %g then <%s> else <%s>\n", expr, thenpart, elsepart? elsepart : "");
	if (expr) {
		unput('\n');
		pushsrc(Free, thenpart);
		pushsrc(String, thenpart);
		unput('\n');
  		if (elsepart)
			free(elsepart);
		return thenpart;	/* to be freed later */
	} else {
		free(thenpart);
		if (elsepart) {
			unput('\n');
			pushsrc(Free, elsepart);
			pushsrc(String, elsepart);
			unput('\n');
		}
		return elsepart;
	}
}
Ejemplo n.º 13
0
static char
eat_escape_code(void)
{
    int c, coded_char;

    c = input();

    switch (c) {
      case 0:  /* i.e., EOF */
	unput(c);
	return(c);
      case '\n':
	return(0);
      case 'n':
	return('\n');
      case 't':
	return('\t');
      case 'b':
	return('\b');
      case '0':   case '1':   case '2':   case '3':
      case '4':   case '5':   case '6':   case '7':
	coded_char = c - '0';
	c = input();
	if (!is_octal_digit(c)) {
	    unput(c);
	    return(coded_char);
	}
	coded_char = coded_char*8 + c-'0';
	c = input();
	if (!is_octal_digit(c)) {
	    unput(c);
	    return(coded_char);
	}
	return(coded_char*8 + c-'0');
      default:
	return(c);
    }
}
Ejemplo n.º 14
0
Archivo: for.c Proyecto: 99years/plan9
void forloop(char *var, double from, double to, int op,
	double by, char *str)	/* set up a for loop */
{
	dprintf("# for %s from %g to %g by %c %g \n",
		var, from, to, op, by);
	if (++forp >= forstk+10)
		ERROR "for loop nested too deep" FATAL;
	forp->var = var;
	forp->to = to;
	forp->op = op;
	forp->by = by;
	forp->str = str;
	setfval(var, from);
	nextfor();
	unput('\n');
}
Ejemplo n.º 15
0
get_comment()
{
    char c;
    int n;
    char  txt[80];

    n = 0;
    while( (c = input()) != '\n' )
    {
	txt[n] = c;
	n++;       
    }
    txt[n] = 0;
    if (displ_sw) printf("#%s\n",txt);
    unput('\n');
    return(NUL_TKN);
}
Ejemplo n.º 16
0
void
forloop(char *var, double from, double to, int op, double by, char *str)
{
	if (++forp >= forstk+10)
		fatal("for loop nested too deep");

/* note: actually we here want to take a vector variable and construct its   */
/*	 values directly, then access them one at a time below; the current  */
/*	 version is a temporary concession to old pic's version of the 'for' */

	forp->sym = findvar(var, VARNAME);
	if (forp->sym->s_dim && forp->sym->s_val.a)
		free(forp->sym->s_val.a);
	forp->sym->s_dim = 0;
	forp->sym->s_val.f = from;
	forp->to = to;
	if (by == 0.)
		fatal("step size of 0 not allowed");

	/*  For additive or subtractive step, make sure step is positive.
	    Otherwise, make sure step is greater than 1 in absolute value. */
	if ((op == ' ' || op == '+') && by < 0.) {
		op = '-';
		by = -by;
	}
	else if (op == '-' && by < 0.) {
		op = '+';
		by = -by;
	}
	else if (op == '*' && fabs(by) < 1.) {
		op = '/';
		by = 1 / by;
	}
	else if (op == '/' && fabs(by) < 1.) {
		op = '*';
		by = 1 / by;
	}
	forp->op = op;
	forp->by = by;
	forp->str = str;
	nextfor();
	unput('\n');
}
Ejemplo n.º 17
0
Archivo: hex.c Proyecto: mrahn/hex
static uint8_t _winning (PPosition_type pos, PState_DFS state, Pvoid_t* PJArray)
{
  if (pos->winner != N)
  {
    return 1;
  }

  Word_t const Index = encode (pos);

  {
    PWord_t PValue;

    JLG (PValue, *PJArray, Index);

    if (PValue)
    {
      ++_cnt_hit;

      return *PValue != pos->player;
    }
  }

  for (int f = 0; f < LEN * LEN; ++f)
  {
    if (pos->taken[f] == N)
    {
      put (pos, state, f);
      const uint8_t w = _winning (pos, state, PJArray);
      unput (pos, f);

      if (w)
      {
        insert (PJArray, Index, pos->player);

        return 0;
      }
    }
  }

  insert (PJArray, Index, 1 - pos->player);

  return 1;
}
Ejemplo n.º 18
0
static int
handle_show(void)
{
    int c;
    int start_line_no = yylineno;

    /*
     * Eat up ' ' and '\t's after show.  If the next character is a newline,
     * eat it.  This is so we don't get an extra newline when we call
     * eat_til_endshow:
     */
    while (c=input(), c==' ' || c=='\t') ;
    if (c!='\n')
      unput(c);

    yylval.text = eat_til_endshow(start_line_no);
    if (yylval.text)
      return(SHOW);
    else
      return(ERROR);
}
Ejemplo n.º 19
0
Archivo: lex.c Proyecto: 99years/plan9
void include(void)
{
	char name[100];
	FILE *fin;
	int c;
	extern int errno;

	while ((c = input()) == ' ')
		;
	unput(c);
	cstr(name, c == '"', sizeof(name));	/* gets it quoted or not */
	if ((fin = fopen(name, "r")) == NULL)
		ERROR "can't open file %s", name FATAL;
	errno = 0;
	curfile++;
	curfile->fin = fin;
	curfile->fname = strsave(name);
	curfile->lineno = 0;
	printf(".lf 1 %s\n", curfile->fname);
	pushsrc(File, curfile->fname);
}
Ejemplo n.º 20
0
comment()
{
    char c, c1;
#ifdef AST
    printf("<COMMENT>");
#endif
loop:
    while ((c = input()) != '*' && c != 0)
#ifdef AST
        putchar(c)
#endif
	;
    if ((c1 = input()) != '/' && c != 0)
    {
        unput(c1);
        goto loop;
    }
#ifdef AST
    printf("</COMMENT>\n");
#endif
}
Ejemplo n.º 21
0
void comment()
{
	char c, c1;

	output('/');
	output('*');

loop:
	while ((c = input()) != '*' && c != 0)
		output(c);

	if ((c1 = input()) != '/' && c != 0)
	{
		unput(c1);
		goto loop;
	}

	if (c != 0) {
		output('*');
		output(c1);
	}
}
Ejemplo n.º 22
0
static char *
eat_til_endshow(int start_line_no)
{
    register int c;
    string text_so_far = string_Copy("");
    string next_line;

    for (;;) {
	/*
	 * Skip the spaces & tabs at the start of the current line:
	 */
	while ((c=input()), c==' ' || c=='\t') ;
	unput(c);

	/*
	 * Handle unterminated shows:
	 */
	if (!c) {
	    report_parse_error("unterminated show beginning", start_line_no);
	    free(text_so_far);
	    return(0);
	}

	/*
	 * Read in rest of the line (including the <cr> at end), allowing
	 * for escape codes and checking for "endshow{nonalpha}" at the
	 * start of the line.  (Note: \<newline> is considered the
	 * end of a line here!)
	 */
	next_line = eat_show_line(1);

	if (!next_line)  /* i.e., is this the endshow line? */
	  return(text_so_far);

	text_so_far = string_Concat2(text_so_far, next_line);
	free(next_line);
    }
}
Ejemplo n.º 23
0
int string(void)
{
	int c, n;
	char *s, *bp;
	static char *buf = 0;
	static int bufsz = 500;

	if (buf == 0 && (buf = (char *) malloc(bufsz)) == NULL)
		FATAL("out of space for strings");
	for (bp = buf; (c = input()) != '"'; ) {
		if (!adjbuf(&buf, &bufsz, bp-buf+2, 500, &bp, 0))
			FATAL("out of space for string %.10s...", buf);
		switch (c) {
		case '\n':
		case '\r':
		case 0:
			SYNTAX( "non-terminated string %.10s...", buf );
			lineno++;
			if (c == 0)	/* hopeless */
				FATAL( "giving up" );
			break;
		case '\\':
			c = input();
			switch (c) {
			case '"': *bp++ = '"'; break;
			case 'n': *bp++ = '\n'; break;	
			case 't': *bp++ = '\t'; break;
			case 'f': *bp++ = '\f'; break;
			case 'r': *bp++ = '\r'; break;
			case 'b': *bp++ = '\b'; break;
			case 'v': *bp++ = '\v'; break;
			case 'a': *bp++ = '\007'; break;
			case '\\': *bp++ = '\\'; break;

			case '0': case '1': case '2': /* octal: \d \dd \ddd */
			case '3': case '4': case '5': case '6': case '7':
				n = c - '0';
				if ((c = peek()) >= '0' && c < '8') {
					n = 8 * n + input() - '0';
					if ((c = peek()) >= '0' && c < '8')
						n = 8 * n + input() - '0';
				}
				*bp++ = n;
				break;

			case 'x':	/* hex  \x0-9a-fA-F + */
			    {	char xbuf[100], *px;
				for (px = xbuf; (c = input()) != 0 && px-xbuf < 100-2; ) {
					if (isdigit(c)
					 || (c >= 'a' && c <= 'f')
					 || (c >= 'A' && c <= 'F'))
						*px++ = c;
					else
						break;
				}
				*px = 0;
				unput(c);
	  			sscanf(xbuf, "%x", &n);
				*bp++ = n;
				break;
			    }

			default: 
				*bp++ = c;
				break;
			}
			break;
		default:
			*bp++ = c;
			break;
		}
	}
	*bp = 0; 
	s = tostring(buf);
	*bp++ = ' '; *bp++ = 0;
	yylval.cp = setsymtab(buf, s, 0.0, CON|STR|DONTFREE, symtab);
	RET(STRING);
}
Ejemplo n.º 24
0
int yylex(void)
{
	int c;
	static char *buf = 0;
	static int bufsize = 500;

	if (buf == 0 && (buf = (char *) malloc(bufsize)) == NULL)
		FATAL( "out of space in yylex" );
	if (sc) {
		sc = 0;
		RET('}');
	}
	if (reg) {
		reg = 0;
		return regexpr();
	}
/* printf("top\n"); */
	for (;;) {
		c = gettok(&buf, &bufsize);
/* printf("gettok [%s]\n", buf); */
		if (c == 0)
			return 0;
		if (isalpha(c) || c == '_')
			return word(buf);
		if (isdigit(c)) {
			yylval.cp = setsymtab(buf, tostring(buf), atof(buf), CON|NUM, symtab);
			/* should this also have STR set? */
			RET(NUMBER);
		}
	
		yylval.i = c;
		switch (c) {
		case '\n':	/* {EOL} */
			RET(NL);
		case '\r':	/* assume \n is coming */
		case ' ':	/* {WS}+ */
		case '\t':
			break;
		case '#':	/* #.* strip comments */
			while ((c = input()) != '\n' && c != 0)
				;
			unput(c);
			break;
		case ';':
			RET(';');
		case '\\':
			if (peek() == '\n') {
				input();
			} else if (peek() == '\r') {
				input(); input();	/* \n */
				lineno++;
			} else {
				RET(c);
			}
			break;
		case '&':
			if (peek() == '&') {
				input(); RET(AND);
			} else 
				RET('&');
		case '|':
			if (peek() == '|') {
				input(); RET(BOR);
			} else
				RET('|');
		case '!':
			if (peek() == '=') {
				input(); yylval.i = NE; RET(NE);
			} else if (peek() == '~') {
				input(); yylval.i = NOTMATCH; RET(MATCHOP);
			} else
				RET(NOT);
		case '~':
			yylval.i = MATCH;
			RET(MATCHOP);
		case '<':
			if (peek() == '=') {
				input(); yylval.i = LE; RET(LE);
			} else {
				yylval.i = LT; RET(LT);
			}
		case '=':
			if (peek() == '=') {
				input(); yylval.i = EQ; RET(EQ);
			} else {
				yylval.i = ASSIGN; RET(ASGNOP);
			}
		case '>':
			if (peek() == '=') {
				input(); yylval.i = GE; RET(GE);
			} else if (peek() == '>') {
				input(); yylval.i = APPEND; RET(APPEND);
			} else {
				yylval.i = GT; RET(GT);
			}
		case '+':
			if (peek() == '+') {
				input(); yylval.i = INCR; RET(INCR);
			} else if (peek() == '=') {
				input(); yylval.i = ADDEQ; RET(ASGNOP);
			} else
				RET('+');
		case '-':
			if (peek() == '-') {
				input(); yylval.i = DECR; RET(DECR);
			} else if (peek() == '=') {
				input(); yylval.i = SUBEQ; RET(ASGNOP);
			} else
				RET('-');
		case '*':
			if (peek() == '=') {	/* *= */
				input(); yylval.i = MULTEQ; RET(ASGNOP);
			} else if (peek() == '*') {	/* ** or **= */
				input();	/* eat 2nd * */
				if (peek() == '=') {
					input(); yylval.i = POWEQ; RET(ASGNOP);
				} else {
					RET(POWER);
				}
			} else
				RET('*');
		case '/':
			RET('/');
		case '%':
			if (peek() == '=') {
				input(); yylval.i = MODEQ; RET(ASGNOP);
			} else
				RET('%');
		case '^':
			if (peek() == '=') {
				input(); yylval.i = POWEQ; RET(ASGNOP);
			} else
				RET(POWER);

		case '$':
			/* BUG: awkward, if not wrong */
			c = gettok(&buf, &bufsize);
			if (isalpha(c)) {
				if (strcmp(buf, "NF") == 0) {	/* very special */
					unputstr("(NF)");
					RET(INDIRECT);
				}
				c = peek();
				if (c == '(' || c == '[' || (infunc && isarg(buf) >= 0)) {
					unputstr(buf);
					RET(INDIRECT);
				}
				yylval.cp = setsymtab(buf, "", 0.0, STR|NUM, symtab);
				RET(IVAR);
			} else if (c == 0) {	/*  */
				SYNTAX( "unexpected end of input after $" );
				RET(';');
			} else {
				unputstr(buf);
				RET(INDIRECT);
			}
	
		case '}':
			if (--bracecnt < 0)
				SYNTAX( "extra }" );
			sc = 1;
			RET(';');
		case ']':
			if (--brackcnt < 0)
				SYNTAX( "extra ]" );
			RET(']');
		case ')':
			if (--parencnt < 0)
				SYNTAX( "extra )" );
			RET(')');
		case '{':
			bracecnt++;
			RET('{');
		case '[':
			brackcnt++;
			RET('[');
		case '(':
			parencnt++;
			RET('(');
	
		case '"':
			return string();	/* BUG: should be like tran.c ? */
	
		default:
			RET(c);
		}
	}
}
Ejemplo n.º 25
0
int gettok(char **pbuf, int *psz)	/* get next input token */
{
	int c, retc;
	char *buf = *pbuf;
	int sz = *psz;
	char *bp = buf;

	c = input();
	if (c == 0)
		return 0;
	buf[0] = c;
	buf[1] = 0;
	if (!isalnum(c) && c != '.' && c != '_')
		return c;

	*bp++ = c;
	if (isalpha(c) || c == '_') {	/* it's a varname */
		for ( ; (c = input()) != 0; ) {
			if (bp-buf >= sz)
				if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
					FATAL( "out of space for name %.10s...", buf );
			if (isalnum(c) || c == '_')
				*bp++ = c;
			else {
				*bp = 0;
				unput(c);
				break;
			}
		}
		*bp = 0;
		retc = 'a';	/* alphanumeric */
	} else {	/* maybe it's a number, but could be . */
		char *rem;
		/* read input until can't be a number */
		for ( ; (c = input()) != 0; ) {
			if (bp-buf >= sz)
				if (!adjbuf(&buf, &sz, bp-buf+2, 100, &bp, 0))
					FATAL( "out of space for number %.10s...", buf );
			if (isdigit(c) || c == 'e' || c == 'E' 
			  || c == '.' || c == '+' || c == '-')
				*bp++ = c;
			else {
				unput(c);
				break;
			}
		}
		*bp = 0;
		strtod(buf, &rem);	/* parse the number */
		if (rem == buf) {	/* it wasn't a valid number at all */
			buf[1] = 0;	/* return one character as token */
			retc = buf[0];	/* character is its own type */
			unputstr(rem+1); /* put rest back for later */
		} else {	/* some prefix was a number */
			unputstr(rem);	/* put rest back for later */
			rem[0] = 0;	/* truncate buf after number part */
			retc = '0';	/* type is number */
		}
	}
	*pbuf = buf;
	*psz = sz;
	return retc;
}
Ejemplo n.º 26
0
int peek(void)
{
	int c = input();
	unput(c);
	return c;
}
Ejemplo n.º 27
0
yylook()
{
	register struct yysvf *yystate, **lsp;
	register struct yywork *yyt;
	struct yysvf *yyz;
	int yych;
	struct yywork *yyr;
/*
# ifdef LEXDEBUG
	int debug;
# endif
*/
	
	char *yylastch;
	
	/* start off machines */

/*
# ifdef LEXDEBUG
	debug = 1;
# else
	debug = 0;
# endif
*/

# ifdef LEXDEBUG
#define debug 1
# else
#define debug 0
#endif
	
#ifdef YYDEBUG
	fprintf(yyout,"yylook()\n");
# endif
	
	if (!yymorfg)
		yylastch = yytext;
	else
	{
		yymorfg=0;
		yylastch = yytext+yyleng;
	}

#ifdef YYDEBUG
	fprintf(yyout,"yylook: yymorfg=%d\n",yymorfg);
# endif
		
	for(;;)
	{
#ifdef YYDEBUG
		fprintf(yyout,"yylook:  (outer loop)");
		printchar("yyprevious",yyprevious);
# endif
		lsp = yylstate;
		yyestate = yystate = yybgin;
		if (yyprevious==YYNEWLINE) yystate++;

		testbreak=0;
		
		for (;;)
		{
# ifdef LEXDEBUG
			fprintf(yyout,"yylook:   (inner loop) state %d\n",yystate-yysvec-1);
# endif
			if(testbreak==5)
			{
				fprintf(yyout,"yylook:   error, aborted after 5 loops\n");
				exit(0);
			}
			testbreak++;
			
			yyt = yystate->yystoff;

/*			fprintf(yyout,"yylook:   yyt offs: %02x\n",yyt-yycrank); */

			
			if(yyt == yycrank)
			{		/* may not be any transitions */
				yyz = yystate->yyother;
				if(yyz == 0)break;
				if(yyz->yystoff == yycrank)break;
			}
			*yylastch++ = yych = input();

# ifdef LEXDEBUG
			fprintf(yyout,"yylook:   input ");
			printchar("yych",yych);
# endif
			
		tryagain:

# ifdef LEXDEBUG
/*			fprintf(yyout,"yylook:   yych=%02x yymatch[yych]=%02x\n",yych,yymatch[yych]); */
			fprintf(yyout,"yylook:   tryagain\n");
# endif
			yyr = yyt;

/*			fprintf(yyout,"yylook:   yyr offs: %02x\n",yyr-yycrank); */
			
			if ( yyt > yycrank)
			{
				yyt = yyr + yych;
				if (yyt <= yytop && yyt->verify+yysvec == yystate)
				{
					if(yyt->advance+yysvec == YYLERR)	/* error transitions */
					{
# ifdef LEXDEBUG
						fprintf(yyout,"yylook:   unput (1) ");
						printchar("*yylastch",*yylastch);
# endif
						unput(*--yylastch);
						break;
					}
					*lsp++ = yystate = yyt->advance+yysvec;
# ifdef LEXDEBUG
					fprintf(yyout,"yylook:   continue (1)\n");
# endif
					goto contin;
				}
# ifdef LEXDEBUG
				fprintf(yyout,"yylook:   ( yyt > yycrank)\n");
# endif
			}
# ifdef YYOPTIM
			else if(yyt < yycrank) /* r < yycrank */
			{		
				yyt = yyr = yycrank+(yycrank-yyt);
# ifdef LEXDEBUG
				fprintf(yyout,"yylook:   compressed state\n");
# endif
				yyt = yyt + yych;
				if(yyt <= yytop && yyt->verify+yysvec == yystate)
				{
# ifdef LEXDEBUG
					fprintf(yyout,"yylook:   (1)\n");
# endif
					if(yyt->advance+yysvec == YYLERR)	/* error transitions */
					{
# ifdef LEXDEBUG
						fprintf(yyout,"yylook:   unput (2) ");
						printchar("*yylastch",*yylastch);
# endif
						unput(*--yylastch);
						break;
					}
					*lsp++ = yystate = yyt->advance+yysvec;
# ifdef LEXDEBUG
					fprintf(yyout,"yylook:   continue (2)\n");
# endif
					goto contin;
					
				}
# ifdef LEXDEBUG
/*
				fprintf(yyout,"yylook:   yych=%02x yymatch[yych]=%02x\n",yych,yymatch[yych]);
				fprintf(yyout,"yylook:   yyt offs: %02x\n",yyt-yycrank);
				fprintf(yyout,"yylook:   yyr offs: %02x\n",yyr-yycrank);
*/
# endif
				yyt = yyr + YYU(yymatch[yych]);
# ifdef LEXDEBUG
/*
				fprintf(yyout,"yylook:   yyt offs: %02x <= yytop offs: %02x\n",yyt-yycrank,yytop-yycrank);
				fprintf(yyout,"yylook:   yyt->verify=%04x yysvec=%04x (yyt->verify+yysvec)=%04x == yystate=%04x\n",yyt->verify,yysvec,(yyt->verify+yysvec),yystate);
*/
				fprintf(yyout,"yylook:   try fall back character\n");
# endif
				if(yyt <= yytop && yyt->verify+yysvec == yystate) 
				{
# ifdef LEXDEBUG
					fprintf(yyout,"yylook:   (2a)\n");
# endif
					
					if(yyt->advance+yysvec == YYLERR)	/* error transition */
					{
# ifdef LEXDEBUG
/* cc65 compiles this ?!						fprintf(yyout,"yylook:   unput (3) ",); */
						fprintf(yyout,"yylook:   unput (3) ");
						printchar("*yylastch",*yylastch);
# endif
						unput(*--yylastch);
						break;
					}
					*lsp++ = yystate = yyt->advance+yysvec;
# ifdef LEXDEBUG
/*					fprintf(yyout,"yylook:   yyt offs: %02x yyt->advance=%d\n",yyt-yycrank,yyt->advance); */
					fprintf(yyout,"yylook:   continue (3)\n");
# endif
					goto contin;
					
				}
# ifdef LEXDEBUG
				fprintf(yyout,"yylook:   (2)\n");
# endif
			}
			if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank)
			{
# ifdef LEXDEBUG
				fprintf(yyout,"yylook:   fall back to state %d\n",yystate-yysvec-1);
# endif
				goto tryagain;
			}
# endif
			else
			{
# ifdef LEXDEBUG
				fprintf(yyout,"yylook:   unput (4) ");
				printchar("*yylastch",*yylastch);
# endif
				unput(*--yylastch);
				break;
			}
		contin:
# ifdef LEXDEBUG
			fprintf(yyout,"yylook:   contin state=%d\n",yystate-yysvec-1);
# endif
			;
		}

# ifdef LEXDEBUG
		if((*(lsp-1)-yysvec-1)<0)
		{
			fprintf(yyout,"yylook:  stopped (end)\n");
		}
		else
		{
			fprintf(yyout,"yylook:  stopped at %d with\n",*(lsp-1)-yysvec-1);
		}
# endif
		while (lsp-- > yylstate)
		{
			*yylastch-- = 0;
			if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0)
			{
				yyolsp = lsp;
				if(yyextra[*yyfnd]) /* must backup */
				{		
					while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate)
					{
						lsp--;
# ifdef LEXDEBUG
						fprintf(yyout,"yylook:   unput (5) ");
						printchar("*yylastch",*yylastch);
# endif
						unput(*yylastch--);
					}
				}
				yyprevious = YYU(*yylastch);
				yylsp = lsp;
				yyleng = yylastch-yytext+1;
				yytext[yyleng] = 0;
# ifdef LEXDEBUG
				fprintf(yyout,"\nyylook:  match action %d\n",*yyfnd);
				fprintf(yyout,"yylook:  done loops: %d\n",testbreak);
# endif
				return(*yyfnd++);
			}
			unput(*yylastch);
		}
		if (yytext[0] == 0  /* && feof(yyin) */)
		{
			yysptr=yysbuf;
# ifdef LEXDEBUG
			fprintf(yyout,"yylook:  done loops: %d\n",testbreak);
# endif
			return(0);
		}
		yyprevious = yytext[0] = input();

# ifdef LEXDEBUG
		fprintf(yyout,"yylook:   input ");
		printchar("yyprevious",yyprevious);
# endif

		if (yyprevious>0)
			output(yyprevious);
		yylastch=yytext;
# ifdef LEXDEBUG
/*		if(debug)putchar('\n'); */
# endif
	}

# ifdef LEXDEBUG
	fprintf(yyout,"yylook: done loops: %d\n",testbreak);
	fprintf(yyout,"yylook: return <void>\n");
# endif
}
Ejemplo n.º 28
0
int yylex(void)
{
    register int c, last_char;
    register char *ptr;
    int start_line_no;
    int_dictionary_binding *binding;
    char varname[MAX_IDENTIFIER_LENGTH+1];

    for (;;) {
	switch (c = input()) {

	    /*
	     * Skip whitespace:
	     */
	  case ' ':   case '\t':   case '\n':
	    continue;

	    /*
	     * '#' comments out everything up to the and including
	     * the next <cr>:
	     */
	  case '#':
	    while ( (c=input()) && (c!='\n') ) ;
	    if (!c)
	      unput(c);
	    continue;

	    /*
	     * Handle c-style comments.  Note that "/[^*]" is not the start
	     * of any valid token.
	     */
	  case '/':
	    start_line_no = yylineno;

	    /* verify that next character is a '*': */
	    if ((c=input()) != '*')
	      return(ERROR);

	    /* Scan until "*\/" or <EOF>: */
	    for (last_char=0; ; last_char=c) {
		c = input();
		if (c == '/' && (last_char=='*'))
		  break;
		if (!c) {
		    unput(c);
		    report_parse_error("unterminated c style comment found beginning", start_line_no);
		    return(ERROR);
		}
	    }
	    continue;

	    /*
	     * The following characters lex as themselves:
	     *   '+', '|', '&', '(', ')', '.', ',' and <EOF>:
	     */
	  case   0:   case '+':   case '|':   case '&':   case '(':
	  case ')':   case '.':	  case ',':
	    return(c);

	    /*
	     * Handle "=[^~=]", "=~", and "==":
	     */
	  case '=':
	    switch (c = input()) {
	      case '~':
		return(REGEQ);
	      case '=':
		return(EQ);
	      default:
		unput(c);
		return('=');
	    }

	    /*
	     * Handle "![^~=]", "!~", and "!=":
	     */
	  case '!':
	    switch (c = input()) {
	      case '~':
		return(REGNEQ);
	      case '=':
		return(NEQ);
	      default:
		unput(c);
		return('!');
	    }

	    /*
	     * Handle identifiers and keywords:
	     *
	     * Note that the below set of characters is hard coded from
	     * is_identifier_char from parser.h.
	     */
	  case 'a':   case 'b':   case 'c':   case 'd':   case 'e':
	  case 'f':   case 'g':   case 'h':   case 'i':   case 'j':
	  case 'k':   case 'l':   case 'm':   case 'n':   case 'o':
	  case 'p':   case 'q':   case 'r':   case 's':   case 't':
	  case 'u':   case 'v':   case 'w':   case 'x':   case 'y':
	  case 'z':
	  case 'A':   case 'B':   case 'C':   case 'D':   case 'E':
	  case 'F':   case 'G':   case 'H':   case 'I':   case 'J':
	  case 'K':   case 'L':   case 'M':   case 'N':   case 'O':
	  case 'P':   case 'Q':   case 'R':   case 'S':   case 'T':
	  case 'U':   case 'V':   case 'W':   case 'X':   case 'Y':
	  case 'Z':
	  case '0':   case '1':   case '2':   case '3':   case '4':
	  case '5':   case '6':   case '7':   case '8':   case '9':
	  case '_':
	    /*
	     * Read in the first MAX_IDENTIFIER_LENGTH characters of the
	     * identifier into varname null terminated.  Eat
	     * the rest of the characters of the identifier:
	     */
	    for (ptr = varname;;) {
		if (ptr<varname+MAX_IDENTIFIER_LENGTH)
		  *(ptr++) = c;
		c = input();
		if (!is_identifier_char(c))
		  break;
	    }
	    unput(c);
	    *ptr = '\0';

	    /*
	     * Look up the identifier in the keyword dictionary.
	     * If its a match, return the keyword's #.  In the case
	     * of show, call handle_show to do more processing.
	     * If not a match, treat as a variable name.
	     */
	    binding = int_dictionary_Lookup(keyword_dict, varname);
	    if (!binding) {
		yylval.text = string_Copy(varname);
		return(VARNAME);
	    }
	    if (binding->value == SHOW)
	      return(handle_show());
	    else
	      return(binding->value);

	    /*
	     * Handle "${identifier}".  Note that $ followed by a
	     * non-identifier character is not the start of any valid token.
	     */
	  case '$':
	    c = input();
	    if (!is_identifier_char(c))
	      return(ERROR);
    
	    /*
	     * Read in the first MAX_IDENTIFIER_LENGTH characters of the
	     * identifier into varname null terminated.  Eat
	     * the rest of the characters of the identifier:
	     */
	    for (ptr = varname;;) {
		if (ptr<varname+MAX_IDENTIFIER_LENGTH)
		  *(ptr++) = c;
		c = input();
		if (!is_identifier_char(c))
		  break;
	    }
	    unput(c);
	    *ptr = '\0';

	    yylval.text = string_Copy(varname);
	    return(VARREF);

	    /*
	     * Handle constant strings:
	     */
	  case '"':
	    yylval.text = eat_string(yylineno);
	    if (yylval.text)
	      return(STRING);
	    else
	      return(ERROR);

	    /*
	     * All other characters do not start valid tokens:
	     */
	  default:
	    return(ERROR);
	}
    }
}
Ejemplo n.º 29
0
Archivo: proplex.c Proyecto: ombt/ombt
yylook()
#endif
{
	register struct yysvf *yystate, **lsp;
	register struct yywork *yyt;
	struct yysvf *yyz;
	int yych, yyfirst;
	struct yywork *yyr;
# ifdef LEXDEBUG
	int debug;
# endif
	char *yylastch;
	/* start off machines */
# ifdef LEXDEBUG
	debug = 0;
# endif
	yyfirst=1;
	if (!yymorfg)
		yylastch = yytext;
	else {
		yymorfg=0;
		yylastch = yytext+yyleng;
		}
	for(;;){
		lsp = yylstate;
		yyestate = yystate = yybgin;
		if (yyprevious==YYNEWLINE) yystate++;
		for (;;){
# ifdef LEXDEBUG
			if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1);
# endif
			yyt = yystate->yystoff;
			if(yyt == yycrank && !yyfirst){  /* may not be any transitions */
				yyz = yystate->yyother;
				if(yyz == 0)break;
				if(yyz->yystoff == yycrank)break;
				}
#ifndef __cplusplus
			*yylastch++ = yych = input();
#else
			*yylastch++ = yych = lex_input();
#endif
			if(yylastch > &yytext[YYLMAX]) {
				fprintf(yyout,"Input string too long, limit %d\n",YYLMAX);
				exit(1);
			}
			yyfirst=0;
		tryagain:
# ifdef LEXDEBUG
			if(debug){
				fprintf(yyout,"char ");
				allprint(yych);
				putchar('\n');
				}
# endif
			yyr = yyt;
			if ( (int)yyt > (int)yycrank){
				yyt = yyr + yych;
				if (yyt <= yytop && yyt->verify+yysvec == yystate){
					if(yyt->advance+yysvec == YYLERR)	/* error transitions */
						{unput(*--yylastch);break;}
					*lsp++ = yystate = yyt->advance+yysvec;
					if(lsp > &yylstate[YYLMAX]) {
						fprintf(yyout,"Input string too long, limit %d\n",YYLMAX);
						exit(1);
					}
					goto contin;
					}
				}
# ifdef YYOPTIM
			else if((int)yyt < (int)yycrank) {		/* r < yycrank */
				yyt = yyr = yycrank+(yycrank-yyt);
# ifdef LEXDEBUG
				if(debug)fprintf(yyout,"compressed state\n");
# endif
				yyt = yyt + yych;
				if(yyt <= yytop && yyt->verify+yysvec == yystate){
					if(yyt->advance+yysvec == YYLERR)	/* error transitions */
						{unput(*--yylastch);break;}
					*lsp++ = yystate = yyt->advance+yysvec;
					if(lsp > &yylstate[YYLMAX]) {
						fprintf(yyout,"Input string too long, limit %d\n",YYLMAX);
						exit(1);
					}
					goto contin;
					}
				yyt = yyr + YYU(yymatch[yych]);
# ifdef LEXDEBUG
				if(debug){
					fprintf(yyout,"try fall back character ");
					allprint(YYU(yymatch[yych]));
					putchar('\n');
					}
# endif
				if(yyt <= yytop && yyt->verify+yysvec == yystate){
					if(yyt->advance+yysvec == YYLERR)	/* error transition */
						{unput(*--yylastch);break;}
					*lsp++ = yystate = yyt->advance+yysvec;
					if(lsp > &yylstate[YYLMAX]) {
						fprintf(yyout,"Input string too long, limit %d\n",YYLMAX);
						exit(1);
					}
					goto contin;
					}
				}
			if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){
# ifdef LEXDEBUG
				if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1);
# endif
				goto tryagain;
				}
# endif
			else
				{unput(*--yylastch);break;}
		contin:
# ifdef LEXDEBUG
			if(debug){
				fprintf(yyout,"state %d char ",yystate-yysvec-1);
				allprint(yych);
				putchar('\n');
				}
# endif
			;
			}
# ifdef LEXDEBUG
		if(debug){
			fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1);
			allprint(yych);
			putchar('\n');
			}
# endif
		while (lsp-- > yylstate){
			*yylastch-- = 0;
			if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){
				yyolsp = lsp;
				if(yyextra[*yyfnd]){		/* must backup */
					while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){
						lsp--;
						unput(*yylastch--);
						}
					}
				yyprevious = YYU(*yylastch);
				yylsp = lsp;
				yyleng = yylastch-yytext+1;
				yytext[yyleng] = 0;
# ifdef LEXDEBUG
				if(debug){
					fprintf(yyout,"\nmatch ");
					sprint(yytext);
					fprintf(yyout," action %d\n",*yyfnd);
					}
# endif
				return(*yyfnd++);
				}
			unput(*yylastch);
			}
		if (yytext[0] == 0  /* && feof(yyin) */)
			{
			yysptr=yysbuf;
			return(0);
			}
#ifndef __cplusplus
		yyprevious = yytext[0] = input();
		if (yyprevious>0)
			output(yyprevious);
#else
		yyprevious = yytext[0] = lex_input();
		if (yyprevious>0)
			lex_output(yyprevious);
#endif
		yylastch=yytext;
# ifdef LEXDEBUG
		if(debug)putchar('\n');
# endif
		}
	}
Ejemplo n.º 30
0
/* LEXICON -- Simple "conversational mode" lexical analyser.  Lexical analysis
 * in the CL is carried out by a dual mode lexical analyser.  In conversational
 * mode there are few tokens and few special characters; arguments are
 * delimited by whitespace and may contain nonalphanumeric characters.  Few
 * strings have to be quoted.  In computational mode the arithmetic operators
 * are recognized and arguments must be delimited by commas.  Computational
 * mode is in effect whenever the parenlevel is nonzero.
 *
 * The two modes are implemented with two separate lexical analyzers.  Gettok
 * implements conversational mode, while computational mode is implemented with
 * a LEX finite state automaton.  Gettok recognizes the following special chars:
 *
 *	[ \t]				argument delimiter
 *	["']				string
 *	\n				newline
 *	\				single character escape
 *	!				os escape
 *	#				comment
 *	&				spawn background job
 *	(				lparen
 *	+				plus (switch)
 *	-				minus (switch)
 *	;				eost
 *	=				equals
 *	+=				add and set
 *	-=				subtract and set
 *	*=				multiply and set
 *	/=				divide and set
 *	<				redirin
 *	>				redir
 *	>&				allredir
 *	>>				append
 *	>>&				allappend
 *	>(G|I|P|)+			graphics stream redirection
 *	{				lbrace
 *	|				pipe
 *	|&				allpipe
 *	}				rbrace
 *	[				beginning of index list
 *	]				end of index list
 *
 * The history metacharacter ^ is processed before input is passed to the
 * lexical analyser.  Any sequence of nonwhite characters that does not form
 * one of the recognized tokens is returned as a string.
 */
int 
lexicon (void)
{
	char	*bkgerr = "ERROR: cannot submit background job inside {}\n";
	register int	ch, cch;
	register int	token;
	int	stringtok, identifier, setlevel;
	int	clswitch;
	char	*op, *index();

	/* Return pushed back token if any.
	 */
	if (pbtoken) {
	    token = pbtoken;
	    pbtoken = 0;
	    return (token);
	}

	/* Skip leading whitespace.  If whitespace is seen and we are in an
	 * argument list (according to the parser) set flag to output the
	 * comma argument delimiter if the next token begins an argument.
	 * If whitespace or = is seen (except whitespace at the beginning of
	 * a command) then set LHS to false, turning [] off as conversational
	 * mode metacharacters (they will be automatically turned on when
	 * compute mode is entered in an expression).
	 */
	while (ch = input())
	    if (ch == ' ' || ch == '\t') {
space:		if (lexcol > 0)
		    lhs = 0;
		if (inarglist)
		    newarg++;
	    } else if (ch == '\\') {
		if ((ch = input()) != '\n') {
		    unput (ch);
		    break;
		} else
		    goto space;
	    } else
		break;
	

	/* Start new token.
	 */
	if (ch) {
	    unput (ch);
	    yyleng = 0;
	    if (!inarglist)
		newarg = 0;
	} else
	    return (0);


	/* Identify and accumulate next token.  Simple tokens are returned as
	 * integer constants, more complex tokens as operand structures in
	 * yylval.
	 */
	while (ch = input()) {
	    lexcol++;

	    switch (ch) {
	    case '&':
		/* An ampersand triggers bkg execution in command mode, unless
		 * it occurs in a token such as >& or >>&, in which case we
		 * never get here.
		 */
		if (!newtoken) {
		    unput (ch);
		    goto tokout_;
		} else {
		    while (ch = input()) {
			if (ch == ' ' || ch == '\t')
			    continue;
			else {
			    char   bkgmsg[SZ_LINE+1];
			    int    n = SZ_LINE;

			    op = bkgmsg;
			    unput (ch);
			    if (bracelevel) {
				eprintf (bkgerr);
				return ('#');
			    }

			    while (--n >= 0 && (*op = input()) != '\n')
				op++;
			    *op = EOS;
			    bkg_init (bkgmsg);
			    return (Y_NEWLINE);
			}
		    }
		    return (0);
		}

	    case ';':
	    case '\n':
		lexcol = 0;
		lhs = 1;
		goto etok_;

	    case '\t':
	    case ' ':
		if (lexcol > 0)
		    lhs = 0;
		goto etok_;

	    case '[':
	    case ']':
		/* [] are recognized as command mode metacharacters only
		 * on the left hand side of an assignment statement.
		 */
		if (!lhs)
		    goto deposit_;
		/* Fall through */

	    case '{':
	    case '}':
		/* We want to distinguish here between the use of {} for
		 * the set selection operator in template strings, and the
		 * conventional compound statement operator.  The distinction
		 * is that { is recognized as a token only if occurs at the
		 * beginning of a token, and } is recognized as a separate
		 * token when inside a token only if it matches a { in the
		 * same token.  Hence, alpha{xxx} is a single token in command
		 * mode, whereas {xxx} is 3 tokens, the same as { xxx },
		 * and xxx} is the same as xxx }.  Usage is completely
		 * unambiguous if the { or } is preceded by a space.
		 */
		if (newtoken)
		    return (ch);
		if (stringtok) {
		    if (ch == '{')
			setlevel++;
		    else if (setlevel == 0)
			goto etok_;		/* } does not match { */
		    else
			--setlevel;
		    goto deposit_;
		}
		/* fall through */

	    case '=':
etok_:		if (!newtoken) {
		    unput (ch);
		    goto tokout_;
		} else if (ch == '\n') {
		    return (Y_NEWLINE);
		} else if (ch == '=') {
		    token = ch;
		    lhs = 0;
		    goto eatwhite_;
		} else
		    return (ch);

	    case '?':
		/* ?, ?? menu commands, recognized only at beginning of stmt */
		if (lexcol > 1) {
		    goto deposit_;
		} else if (ch = input()) {
		    if (ch == '?')
			return (crackident ("??"));
		    else {
			unput (ch);
			return (crackident ("?"));
		    }
		} else
		    return (0);

	    case '+':
	    case '-':
		/* Plus and minus are recognized as the switch operators for
		 * boolean parameters only if encountered while accumulating
		 * a token and if followed by an argument delimiter, i.e.,
		 * space, tab, newline, or semicolon.  If found at the beginning
		 * of a token they are returned as a separate token and will be
		 * interpreted by the parser as unary plus or minus.
		 */
		if (newtoken) {
		    if (newarg) {
			cch = input();
			if (cch == 0)
			    return (0);
			unput (cch);

			if (ch == '-' && isdigit (cch)) {
			    unput (ch);
			    newarg = 0;
			    return (',');
			} else {
			    /* Not number; treat +- as a string char.
			     */
			    goto deposit_;
			}

		    } else {
			cch = input();
			if (cch == 0)
			    return (0);

			if (cch == '=') {
			    if (ch == '+')
				return (YOP_AOADD);
			    else
				return (YOP_AOSUB);
			} else if (isdigit (cch)) {
			    unput (cch);
			    return (ch);
			} else {
			    unput (cch);
			    goto deposit_;
			}
		    }

		} else if (cch = input()) {
		    clswitch = (isspace (cch) || cch == ';');
		    if (cch == '=') {
			unput(cch);
			unput (ch);
			goto tokout_;
		    }
		    unput (cch);
		    if (clswitch) {
			pbtoken = ch;
			goto tokout_;
		    } else
			goto deposit_;
		} else
		    return (0);

	    case '"':
	    case '\'':
		if (!newtoken) {
		    unput (ch);
		    goto tokout_;
		} else if (newarg) {
		    unput (ch);
		    newarg = 0;
		    return (',');
		} else {
		    traverse (ch);
		    yylval = addconst (yytext, OT_STRING);
		    return (Y_CONSTANT);
		}

	    case '\\':
		if (ch = input()) {
		    if (ch == '\n')
			continue;
		    else if (index ("&;=+-\"'\\#><()|", ch) != NULL)
			goto deposit_;		/* put ch in string */
		    else
			goto escape_;		/* put \ch in string */
		} else
		    return (0);

	    case '!':
		/* OS escape is only recognized when the ! occurs as the first
		 * token in a statement.
		 */
		if (lexcol > 1)
		    goto deposit_;

		/* Accumulate command.  Newline may be escaped to enter a long
		 * command, but all other escapes are passed on unmodified.
		 */
		while ((ch = input()) && ch != '\n') {
		    if (ch == '\\')
			if (ch = input()) {
			    if (ch == '\n')
				continue;
			    else
				yytext[yyleng++] = '\\';
			} else
			    break;
		    yytext[yyleng++] = ch;
		}
		if (ch)
		    unput (ch);

		yytext[yyleng] = '\0';
		yylval = addconst (yytext, OT_STRING);
		return (Y_OSESC);

	    case '#':
		/* Discard the comment line. */
		while ((ch = input()) && ch != '\n')
		    ;
		if (ch) {
		    unput (ch);
		    continue;
		} else
		    return (0);

	    case '>':
	    case '<':
	    case '(':
		/* These characters are alike in that they all begin a new
		 * argument when found in an argument list.
		 */
		if (!newtoken) {
		    unput (ch);
		    goto tokout_;
		} else if (newarg) {
		    unput (ch);
		    newarg = 0;
		    return (',');
		} else if (ch == '<') {
		    token = ch;
		    goto eatwhite_;

		} else if (ch == '>') {
		    ch = input();
		    if (ch == 0) {
			return ('>');

		    } else if (ch == '>') {
			ch = input();
			if (ch == 0) {
			    return (Y_APPEND);
			} else if (ch == 'G' || ch == 'I' || ch == 'P') {
			    op = yytext;
			    *op++ = '>';
			    *op++ = '>';
			    *op++ = ch;
			    goto gsredir_;
			} else if (ch == '&') {
			    token = Y_ALLAPPEND;
			    goto eatwhite_;
			} else {
			    unput (ch);
			    token = Y_APPEND;
			    goto eatwhite_;
			}

		    } else if (ch == 'G' || ch == 'I' || ch == 'P') {
			/* Graphics stream redirection.
			 */
			op = yytext;
			*op++ = '>';
			*op++ = ch;
gsredir_:
			ch = input();
			while (ch == 'G' || ch == 'I' || ch == 'P') {
			    *op++ = ch;
			    ch = input();
			}
			unput (ch);
			*op = EOS;

			yylval = addconst (yytext, OT_STRING);
			token = Y_GSREDIR;
			goto eatwhite_;

		    } else if (ch == '&') {
			token = Y_ALLREDIR;
			goto eatwhite_;
		    } else {
			unput (ch);
			token = '>';
			goto eatwhite_;
		    }

		} else
		    return ('(');

	    case '|':
		if (!newtoken) {
		    unput (ch);
		    goto tokout_;
		} else if (ch = input()) {
		    if (ch == '&')
			return (Y_ALLPIPE);
		    else {
			unput (ch);
			return ('|');
		    }
		} else
		    return (0);

	    case '*':
	    case '/':
		cch = input();
		if (cch == 0)
		    return (0);

		if (newtoken) {
		    if (cch == '=')
			return ((ch=='*') ? YOP_AOMUL:YOP_AODIV);
		    else {
			unput (cch);
			goto deposit_;
		    }
		} else {
		    if (cch == '=') {
			unput (cch);
			unput (ch);
			goto tokout_;
		    } else {
			unput (cch);
			goto deposit_;
		    }
		}

	    /* The following cases are included to force the compiler
	     * to compile the case as an ASCII jump table.
	     */
	    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
	    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
	    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
	    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
	    case 'y': case 'z':
	    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
	    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
	    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
	    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
	    case 'Y': case 'Z':
		/* fall through to default */

	    default:
		goto deposit_;
escape_:	
		/* Deposit a character preceded by the escape character.
		 */
		if (!newarg) {
		    unput (ch);
		    ch = '\\';
		}
deposit_:
		/* If the last token returned was a string argument and we
		 * are starting a second, a delimiter token must be returned
		 * to delimit the two arguments.  Check for chars not legal
		 * in an identifier so that we can know whether to return
		 * CONSTANT or call crackident() which returns IDENT if not
		 * a reserved keyword.
		 */
		if (newtoken) {
		    identifier = 1;
		    stringtok  = 1;
		    setlevel   = 0;
		    if (newarg) {
			unput (ch);
			newarg = 0;
			return (',');
		    }
		}

		yytext[yyleng++] = ch;
		if (ch == '[') {
		    while ((ch = input()) != ']')
		        yytext[yyleng++] = ch;
		    yytext[yyleng++] = ch;
		} else if (ch == '\\')
		    yytext[yyleng++] = ch = input();
		else if (!(isalnum(ch) || ch == '_' || ch == '$' || ch == '.'))
		    identifier = 0;
	    }
	}

tokout_:
	yytext[yyleng] = '\0';

	if (isdigit (yytext[0]) || yytext[0] == '.' && isdigit (yytext[1])) {
	    int	token, toklen;

	    token = c_lexnum (yytext, &toklen);
	    if (token != LEX_NONNUM && toklen == yyleng) {
		switch (token) {
		case LEX_REAL:
		    yylval = addconst (yytext, OT_REAL);
		    break;
		default:
		    yylval = addconst (yytext, OT_INT);
		    break;
		}
		return (Y_CONSTANT);
	    }
	}

	if (identifier)
	    return (crackident (yytext));
	else {
	    yylval = addconst (yytext, OT_STRING);
	    return (Y_CONSTANT);
	}

eatwhite_:
	/* Control transfers here after a token has been identified which is
	 * followed by an associated argument (e.g. > file or < file).  Our
	 * function is to discard any whitespace following the current token
	 * in order to make whitespace optional in the input at this point.
	 * This makes "> file" (for example) equivalent to ">file".
	 */
	newarg = 0;
        while ((ch = input()) && (ch == ' ' || ch == '\t'))
	    ;
	if (ch) {
	    unput (ch);
	    return (token);
	} else
	    return (0);
}