Exemple #1
0
static int read_key (struct cw_KTV_Reader *r, char *key, int max_len)
{
	int c,n;

	do {
		c = skip_chars (r, " \t\n\a\v");
		if (c == '#') {
			c = skip_to_chars (r, "\n\a");
		} else {
			break;
		}
	} while (c != EOF);
	
	unget_char(r,c);
	c=get_char_q(r);

	n=0;
	while(c!=EOF && n<max_len){
		if (!r->quote && !isalnum(c) && !strchr("._/-()@#|{}[]\\",c)){
			unget_char(r,c);
			break;
		}

		key[n]=c;
		c=get_char_q(r);
		n++;

	}
	key[n]=0;
	return n;
}
static int
check_bom(int get_char(struct tok_state *),
          void unget_char(int, struct tok_state *),
          int set_readline(struct tok_state *, const char *),
          struct tok_state *tok)
{
    int ch1, ch2, ch3;
    ch1 = get_char(tok);
    tok->decoding_state = 1;
    if (ch1 == EOF) {
        return 1;
    } else if (ch1 == 0xEF) {
        ch2 = get_char(tok);
        if (ch2 != 0xBB) {
            unget_char(ch2, tok);
            unget_char(ch1, tok);
            return 1;
        }
        ch3 = get_char(tok);
        if (ch3 != 0xBF) {
            unget_char(ch3, tok);
            unget_char(ch2, tok);
            unget_char(ch1, tok);
            return 1;
        }
#if 0
    /* Disable support for UTF-16 BOMs until a decision
       is made whether this needs to be supported.  */
    } else if (ch1 == 0xFE) {
        ch2 = get_char(tok);
        if (ch2 != 0xFF) {
            unget_char(ch2, tok);
            unget_char(ch1, tok);
            return 1;
        }
        if (!set_readline(tok, "utf-16-be"))
            return 0;
        tok->decoding_state = -1;
    } else if (ch1 == 0xFF) {
        ch2 = get_char(tok);
        if (ch2 != 0xFE) {
            unget_char(ch2, tok);
            unget_char(ch1, tok);
            return 1;
        }
        if (!set_readline(tok, "utf-16-le"))
            return 0;
        tok->decoding_state = -1;
#endif
    } else {
        unget_char(ch1, tok);
        return 1;
    }
    if (tok->encoding != NULL)
        PyMem_FREE(tok->encoding);
    tok->encoding = new_string("utf-8", 5);     /* resulting is in utf-8 */
    return 1;
}
Exemple #3
0
/* get token */
static int token(Scheme *sc) {
	int c = skipspace(sc);
	if (c == EOF)
		return (TOK_EOF);
	switch (c = get_char(sc)) {
	case EOF:
		return (TOK_EOF);
	case '(':
		return (TOK_LPAREN);
	case ')':
		return (TOK_RPAREN);
	case '.':
		c = get_char(sc);
		if (find_char_in_string(" \n\t", c)) {
			return (TOK_DOT);
		} else {
			unget_char(sc, c);
			unget_char(sc, '.');
			return TOK_ATOM;
		}
	case '\'': //引用
		return (TOK_QUOTE);
	case ';': //注释
		while ((c = get_char(sc)) != '\n' && c != EOF)
			; //跳过注释
		if (c == EOF)
			return TOK_EOF;
		else
			return token(sc);
	case '"': //双引号
		return (TOK_DQUOTE);
	case '#':
		c = get_char(sc);
		if (c == '(')
			return TOK_VECTOR;
		else if (c == '!') { //#!开头的注释
			while ((c = get_char(sc)) != '\n' && c != EOF)
				;
			if (c == EOF)
				return TOK_EOF;
			return token(sc);
		} else {
			unget_char(sc, c);
			if (find_char_in_string(" tfodxb\\", c))
				return TOK_SHARP_CONST;
			else
				return (TOK_SHARP);
		}
	default:
		unget_char(sc, c);
		return (TOK_ATOM);
	}
}
Exemple #4
0
static int read_type(struct cw_KTV_Reader * r, char *type, int max_len)
{
	int c,n;
	
	c = skip_to_colon(r);
	if (c==-1)
		return -1;
	if (c=='='){
		unget_char(r,c);
		return sprintf(type,"%s","Str");
		
	}

	c = skip_chars (r, " \t");
	
	if (c==':'){
		unget_char(r,c);
		sprintf(type,"%s","Str");
		return 0;
	}
		
	if (!isalpha(c)){
		if (c=='\n'){
			unget_char(r,c);
			/*sprintf(p->error,"Error at line %d, pos %d: Unexpected EOL.", p->line, p->pos);*/
			return -1;
		}
		
		/*sprintf(p->error,"Error at line %d, pos %d: Letter expected.", p->line, p->pos);*/
		return -1;
	}

	n=0;
	while(c!=EOF && n<max_len){
		if (!isalnum(c) && !strchr("_/-.()@#|{}[]",c)/*strchr(": \t\n\a",c)*/){
			unget_char(r,c);
			break;
		}

		type[n]=c;
		c=get_char(r);
		n++;
	}
	type[n]=0;
	return n;
}
Exemple #5
0
static int read_val(struct cw_KTV_Reader *r, char *val, int max_len){
	int c,n,quote;
	c = skip_to_colon(r);
	if (c==-1)
		return -1;
	c = skip_chars (r, " \t");
	if (c=='"'){
		quote=1;
		c=get_char(r);
	}
	else{
		quote=0;
	}
	n=0;
	while(c!=EOF && n<max_len){
		if (quote && c=='"'){
			break;
		}
		if (c=='\n'){
			break;
		}
		if (quote){
			if (c=='\\'){
				c = get_char(r);
				switch(c){
					case 'n':
						c='\n';
						break;
					case '\\':
						break;
					case '"':
						break;
					default:
						unget_char(r,c);
						c='\\';
				}
			}
		}
		val[n++]=c;
		c=get_char(r);
	}
	
	
	if(!quote && n>0){
		while(n>0){
			if (isspace(val[n-1]))
				n--;
			else
				break;
		}
	}
	
	val[n]=0;

	return n;

}
Exemple #6
0
/* skip white characters */
static int skipspace(Scheme *sc) {
	int c = 0;
	do {
		c = get_char(sc);
	} while (isspace(c));
	if (c != EOF) {
		unget_char(sc, c);
		return 1;
	} else
		return EOF;
}
Exemple #7
0
//读取一个字符串直到遇到分隔符
static char *readstr_upto(Scheme *sc, char *delim) {
	String str = init_string();
	while(TRUE) {
		char c = get_char(sc);
		str = append_char(str, c);
		if (*str && !find_char_in_string(delim, c)) ;
		else
			break;
	}
	unget_char(sc, *(str - 1));
	*(str + strlen(str) - 1) = '\0';
	return str;
}
Exemple #8
0
static int
get_number(int *numptr, int low, const char * const names[], int ch, FILE *file,
    const char *terms) {
	char temp[MAX_TEMPSTR], *pc;
	int len, i;

	pc = temp;
	len = 0;

	/* first look for a number */
	while (isdigit((unsigned char)ch)) {
		if (++len >= MAX_TEMPSTR)
			goto bad;
		*pc++ = (char)ch;
		ch = get_char(file);
	}
	*pc = '\0';
	if (len != 0) {
		/* got a number, check for valid terminator */
		if (!strchr(terms, ch))
			goto bad;
		*numptr = atoi(temp);
		return (ch);
	}

	/* no numbers, look for a string if we have any */
	if (names) {
		while (isalpha((unsigned char)ch)) {
			if (++len >= MAX_TEMPSTR)
				goto bad;
			*pc++ = (char)ch;
			ch = get_char(file);
		}
		*pc = '\0';
		if (len != 0 && strchr(terms, ch)) {
			for (i = 0;  names[i] != NULL;  i++) {
				Debug(DPARS|DEXT,
					("get_num, compare(%s,%s)\n", names[i],
					temp));
				if (!strcasecmp(names[i], temp)) {
					*numptr = i+low;
					return (ch);
				}
			}
		}
	}

bad:
	unget_char(ch, file);
	return (EOF);
}
Exemple #9
0
static int
check_bom(int get_char(struct tok_state *),
	  void unget_char(int, struct tok_state *),
	  int set_readline(struct tok_state *, const char *),
	  struct tok_state *tok)
{
	int ch = get_char(tok);
	tok->decoding_state = 1;
	if (ch == EOF) {
		return 1;
	} else if (ch == 0xEF) {
		ch = get_char(tok); if (ch != 0xBB) goto NON_BOM;
		ch = get_char(tok); if (ch != 0xBF) goto NON_BOM;
#if 0
	/* Disable support for UTF-16 BOMs until a decision
	   is made whether this needs to be supported.  */
	} else if (ch == 0xFE) {
		ch = get_char(tok); if (ch != 0xFF) goto NON_BOM;
		if (!set_readline(tok, "utf-16-be")) return 0;
		tok->decoding_state = -1;
	} else if (ch == 0xFF) {
		ch = get_char(tok); if (ch != 0xFE) goto NON_BOM;
		if (!set_readline(tok, "utf-16-le")) return 0;
		tok->decoding_state = -1;
#endif
	} else {
		unget_char(ch, tok);
		return 1;
	}
	if (tok->encoding != NULL)
		PyMem_FREE(tok->encoding);
	tok->encoding = new_string("utf-8", 5);	/* resulting is in utf-8 */
	return 1;
  NON_BOM:
	/* any token beginning with '\xEF', '\xFE', '\xFF' is a bad token */
	unget_char(0xFF, tok);	/* XXX this will cause a syntax error */
	return 1;
}
Exemple #10
0
static int skip_to_colon(struct cw_KTV_Reader * r)
{
	int c;
	c = skip_chars (r, " \t");
	if (c!=':' && c!='='){
		if (c=='\n'){
			unget_char(r,c);
			sprintf(r->error,"Unexpected EOL, colon or equal sign expected.");
			return -1;
		}
		sprintf(r->error,"Colon or equal sign expected.");
		return -1;
	}
	return c;
}
/* skip_comments(file) : read past comment (if any)
 */
void skip_comments(FILE *file)
{
    int ch;

    while (EOF != (ch = get_char(file)))
        {
        /* ch is now the first character of a line.
         */

        while (ch == ' ' || ch == '\t')
            {
            ch = get_char(file);
            }

        if (ch == EOF)
            {
            break;
            }

        /* ch is now the first non-blank character of a line.
         */

        if (ch != '\n' && ch != '#')
            {
            break;
            }

        /* ch must be a newline or comment as first non-blank
         * character on a line.
         */

        while (ch != '\n' && ch != EOF)
            {
            ch = get_char(file);
            }

        /* ch is now the newline of a line which we're going to
         * ignore.
         */
    }

    if (ch != EOF)
        {
        unget_char(ch, file);
        }
}
Exemple #12
0
static int get_char_q(struct cw_KTV_Reader *p)
{
	int c;

	while(1) {
		c = get_char(p);
		if (c==EOF || c=='\n')
			return c;
	
		if(c=='"' && !p->quote){
			p->quote=1;
			continue;
		}
		if(c=='"' && p->quote){
			p->quote=0;
			continue;
		}
		break;
	}
	
	
	if (!p->quote)
		return c;
			
	if (c!='\\')
		return c;
			
	c = get_char(p);
	switch(c){
		case EOF:
			return c;
		case 'n':
			return '\n';
			
		case '\\':
			return '\\';
		case '"':
			return '"';
		default:
			unget_char(p,c);
			return '\\';
	}
			
	/* We will never reach here */
	/* return c;*/
}
Exemple #13
0
static int
get_range(bitstr_t *bits, int low, int high, const char * const names[],
	  int ch, FILE *file)
{
	/* range = number | number "-" number [ "/" number ]
	 */

	int i, num1, num2, num3;
	int	qmark, star;

	qmark = star = FALSE;
	Debug(DPARS|DEXT, ("get_range()...entering, exit won't show\n"));

	if (ch == '*') {
		/* '*' means "first-last" but can still be modified by /step
		 */
		star = TRUE;
		num1 = low;
		num2 = high;
		ch = get_char(file);
		if (ch == EOF)
			return (EOF);
	} else if (ch == '?') {
		qmark = TRUE;
		ch = get_char(file);
		if (ch == EOF)
			return EOF;
		if (!isdigit(ch)) {
			num1 = random_with_range(low, high);
			if (EOF == set_element(bits, low, high, num1))
				return EOF;
			return ch;
		}
	}

	if (!star) {
		ch = get_number(&num1, low, names, ch, file, ",- \t\n");
		if (ch == EOF)
			return (EOF);

		if (ch != '-') {
			/* not a range, it's a single number.
			 * a single number after '?' is bogus.
			 */
			if (qmark)
				return EOF;
			if (EOF == set_element(bits, low, high, num1)) {
				unget_char(ch, file);
				return (EOF);
			}
			return (ch);
		} else {
			/* eat the dash
			 */
			ch = get_char(file);
			if (ch == EOF)
				return (EOF);

			/* get the number following the dash
			 */
			ch = get_number(&num2, low, names, ch, file, "/, \t\n");
			if (ch == EOF || num1 > num2)
				return (EOF);

			/* if we have a random range, it is really
			 * like having a single number.
			 */
			if (qmark) {
				if (num1 > num2)
					return EOF;
				num1 = random_with_range(num1, num2);
				if (EOF == set_element(bits, low, high, num1))
					return EOF;
				return ch;
			}
		}
	}

	/* check for step size
	 */
	if (ch == '/') {
		/* '?' is incompatible with '/'
		 */
		if (qmark)
			return EOF;
		/* eat the slash
		 */
		ch = get_char(file);
		if (ch == EOF)
			return (EOF);

		/* get the step size -- note: we don't pass the
		 * names here, because the number is not an
		 * element id, it's a step size.  'low' is
		 * sent as a 0 since there is no offset either.
		 */
		ch = get_number(&num3, 0, PPC_NULL, ch, file, ", \t\n");
		if (ch == EOF || num3 == 0)
			return (EOF);
	} else {
		/* no step.  default==1.
		 */
		num3 = 1;
	}

	/* range. set all elements from num1 to num2, stepping
	 * by num3.  (the step is a downward-compatible extension
	 * proposed conceptually by bob@acornrc, syntactically
	 * designed then implemented by paul vixie).
	 */
	for (i = num1;  i <= num2;  i += num3)
		if (EOF == set_element(bits, low, high, i)) {
			unget_char(ch, file);
			return (EOF);
		}

	return (ch);
}
Exemple #14
0
Token
Lexer::get_token()
{
  int c;
  while((c = get_char()) != -1)
  {
    if (isspace(c))
    {
      // ignore
    }
    else if (isdigit(c) || c == '.') // number
    {
      bool real = false;

      if (c == '.')
      {
        real = true;
      }

      std::string str;
      str += static_cast<char>(c);
      while((c = get_char()) != -1)
      {
        if (c == '.' && !real)
        {
          real = true;
          str += static_cast<char>(c);
        }
        else if (!isdigit(c))
        {
          unget_char();
          break;
        }
        else
        {
          str += static_cast<char>(c);
        }
      }

      if (real)
      {
        return Token::real(static_cast<float>(atof(str.c_str())));
      }
      else
      {
        return Token::integer(atoi(str.c_str()));
      }
    }
    else if (isalpha(c))
    {
      std::string str;
      str += static_cast<char>(c);
      while((c = get_char()) != -1)
      {
        if (!isalpha(c) && !isdigit(c) && c != '_')
        {
          unget_char();
          break;
        }
        else
        {
          str += static_cast<char>(c);
        }
      }
      return Token::string(str);
    }
    else if (c == '=')
    {
      if ((c = get_char()) != -1 && c == '=')
      {
        return Token::equal();
      }
      else
      {
        throw std::runtime_error("syntax error");
      }
    }
    else if (c == '~')
    {
      return Token::bitwise_not();
    }
    else if (c == '!')
    {
      if ((c = get_char()) != -1 && c == '=')
      {
        return Token::not_equal();
      }
      else
      {
        unget_char();
        return Token::logical_not();
      }
    }
    else if (c == '<')
    {
      if ((c = get_char()) != -1)
      {
        if (c == '=')
          return Token::smaller_or_equal_then();
        else if (c == '<')
          return Token::shift_left();
        else
        {
          unget_char();
          return Token::smaller_then();
        }
      }
      else
      {
        unget_char();
        return Token::smaller_then();
      }
    }
    else if (c == '>')
    {
      if ((c = get_char()) != -1)
      {
        if (c == '=')
        {
          return Token::larger_or_equal_then();
        }
        else if (c == '>')
        {
          return Token::shift_right();
        }
        else
        {
          unget_char();
          return Token::larger_then();
        }
      }
      else
      {
        unget_char();
        return Token::larger_then();
      }
    }
    else if (c == '|')
    {
      if ((c = get_char()) != -1 && c == '|')
      {
        return Token::logical_or();
      }
      else
      {
        unget_char();
        return Token::bitwise_or();
      }
    }
    else if (c == '^')
    {
      return Token::bitwise_xor();
    }
    else if (c == '&')
    {
      if ((c = get_char()) != -1 && c == '&')
      {
        return Token::logical_and();
      }
      else
      {
        unget_char();
        return Token::bitwise_and();
      }
    }
    else if (c == '+')
    {
      return Token::plus();
    }
    else if (c == '%')
    {
      return Token::modulo();
    }
    else if (c == '-')
    {
      return Token::minus();
    }
    else if (c == '*')
    {
      return Token::mult();
    }
    else if (c == '/')
    {
      return Token::div();
    }
    else if (c == '(')
    {
      return Token::parent_left();
    }
    else if (c == ')')
    {
      return Token::parent_right();
    }
    else if (c == ',')
    {
      return Token::comma();
    }
    else if (c == '?')
    {
      return Token::questionmark();
    }
    else if (c == ':')
    {
      return Token::colon();
    }
    else
    {
      throw std::runtime_error("syntax error");
    }
  }

  return Token::eof();
}
Exemple #15
0
parse_real (unsigned char c)
{
  if ((__ctype_ptr[c]&04) && c != '.')
   unget_char ( c);
}
Exemple #16
0
int 
get_token(void)
{
  int type = TOKEN_TYPE_ERR;
  int index = 0;
  int status = SCAN_STATUS_START;
  int save;

  int c;
  while (status != SCAN_STATUS_DONE) {
    c = get_char();
    save = BOOL_YES;

    switch (status) {
    case SCAN_STATUS_START:
      if (' ' == c || '\t' == c) {
        save = BOOL_NO;
      }
      else if ('\n' == c) {
        save = BOOL_NO;
        ++g_line_numer;
      }
      else if (isdigit(c)) {
        status = SCAN_STATUS_IN_CINT;
      }
      else if (isalpha(c) || '_' == c) {
        status = SCAN_STATUS_IN_ID;
      }
      else if ('.' == c) {
        status = SCAN_STATUS_IN_ACCESS;
      }
      else if ('#' == c) {
        save = BOOL_NO;
        status = SCAN_STATUE_IN_COMMENT;
      }
      else {
        status = SCAN_STATUS_DONE;
        switch (c) {
        case EOF:
          save = BOOL_NO;
          type = TOKEN_TYPE_EOF;
          break;
        case '=':
          type = TOKEN_TYPE_ASSIGN;
          break;
        case '<':
          type = TOKEN_TYPE_INHERIT;
          break;
        case '[':
          type = TOKEN_TYPE_LBRACKET;
          break;
        case ']':
          type = TOKEN_TYPE_RBRACKET;
          break;
        case '{':
          type = TOKEN_TYPE_LBRACE;
          break;
        case '}':
          type = TOKEN_TYPE_RBRACE;
          break;
        default:
          save = BOOL_NO;
          type = TOKEN_TYPE_ERR;
          break;
        }
      }
      break;
    case SCAN_STATUS_IN_ACCESS:
      if (isalpha(c) || '_' == c) {
        unget_char();
        save = BOOL_NO;
        status = SCAN_STATUS_DONE;
        type = TOKEN_TYPE_ACCESS;
      }
      else {
        fprintf(stderr, "Lexial error: [%d] after '.' ...\n", g_line_numer);
        exit(1);
      }
      break;
    case SCAN_STATUS_IN_ID:
      if (!isalnum(c) && '_' != c) {
        unget_char();
        save = BOOL_NO;
        status = SCAN_STATUS_DONE;
        type = TOKEN_TYPE_ID;
      }
      break;
    case SCAN_STATUS_IN_CINT:
      if ('.' == c) {
        status = SCAN_STATUS_IN_CREAL;
      }
      else {
        if (!isdigit(c)) {
          unget_char();
          save = BOOL_NO;
          status = SCAN_STATUS_DONE;
          type = TOKEN_TYPE_CINT;
        }
      }
      break;
    case SCAN_STATUS_IN_CREAL:
      if (!isdigit(c)) {
        unget_char();
        save = BOOL_NO;
        status = SCAN_STATUS_DONE;
        type = TOKEN_TYPE_CREAL;
      }
      break;
    case SCAN_STATUE_IN_COMMENT:
      save = BOOL_NO;
      if (EOF == c) {
        status = SCAN_STATUS_DONE;
        type = TOKEN_TYPE_EOF;
      }
      else if ('\n' == c) {
        ++g_line_numer;
        status = SCAN_STATUS_START;
      }
      break;
    case SCAN_STATUS_DONE:
    default:
      fprintf(g_scan_stream, "Scanner bug: status = %d\n", status);
      status = SCAN_STATUS_DONE;
      type = TOKEN_TYPE_ERR;
      break;
    }

    if (save && index < MAX_TOKEN)
      g_token[index++] = (char)c;

    if (SCAN_STATUS_DONE == status) {
      g_token[index] = 0;
      if (TOKEN_TYPE_ID == type)
        type = lookup_reserved(g_token);
    }
  }

  echo_scanner(g_scan_stream, g_line_numer, type, g_token);

  return type;
}
Exemple #17
0
static format_token
format_lex (format_data *fmt)
{
  format_token token;
  int negative_flag;
  int c;
  char delim;

  if (fmt->saved_token != FMT_NONE)
    {
      token = fmt->saved_token;
      fmt->saved_token = FMT_NONE;
      return token;
    }

  negative_flag = 0;
  c = next_char (fmt, 0);

  switch (c)
    {
    case '*':
       token = FMT_STAR;
       break;

    case '(':
      token = FMT_LPAREN;
      break;

    case ')':
      token = FMT_RPAREN;
      break;

    case '-':
      negative_flag = 1;
      /* Fall Through */

    case '+':
      c = next_char (fmt, 0);
      if (!isdigit (c))
	{
	  token = FMT_UNKNOWN;
	  break;
	}

      fmt->value = c - '0';

      for (;;)
	{
	  c = next_char (fmt, 0);
	  if (!isdigit (c))
	    break;

	  fmt->value = 10 * fmt->value + c - '0';
	}

      unget_char (fmt);

      if (negative_flag)
	fmt->value = -fmt->value;
      token = FMT_SIGNED_INT;
      break;

    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      fmt->value = c - '0';

      for (;;)
	{
	  c = next_char (fmt, 0);
	  if (!isdigit (c))
	    break;

	  fmt->value = 10 * fmt->value + c - '0';
	}

      unget_char (fmt);
      token = (fmt->value == 0) ? FMT_ZERO : FMT_POSINT;
      break;

    case '.':
      token = FMT_PERIOD;
      break;

    case ',':
      token = FMT_COMMA;
      break;

    case ':':
      token = FMT_COLON;
      break;

    case '/':
      token = FMT_SLASH;
      break;

    case '$':
      token = FMT_DOLLAR;
      break;

    case 'T':
      switch (next_char (fmt, 0))
	{
	case 'L':
	  token = FMT_TL;
	  break;
	case 'R':
	  token = FMT_TR;
	  break;
	default:
	  token = FMT_T;
	  unget_char (fmt);
	  break;
	}

      break;

    case 'X':
      token = FMT_X;
      break;

    case 'S':
      switch (next_char (fmt, 0))
	{
	case 'S':
	  token = FMT_SS;
	  break;
	case 'P':
	  token = FMT_SP;
	  break;
	default:
	  token = FMT_S;
	  unget_char (fmt);
	  break;
	}

      break;

    case 'B':
      switch (next_char (fmt, 0))
	{
	case 'N':
	  token = FMT_BN;
	  break;
	case 'Z':
	  token = FMT_BZ;
	  break;
	default:
	  token = FMT_B;
	  unget_char (fmt);
	  break;
	}

      break;

    case '\'':
    case '"':
      delim = c;

      fmt->string = fmt->format_string;
      fmt->value = 0;		/* This is the length of the string */

      for (;;)
	{
	  c = next_char (fmt, 1);
	  if (c == -1)
	    {
	      token = FMT_BADSTRING;
	      fmt->error = bad_string;
	      break;
	    }

	  if (c == delim)
	    {
	      c = next_char (fmt, 1);

	      if (c == -1)
		{
		  token = FMT_BADSTRING;
		  fmt->error = bad_string;
		  break;
		}

	      if (c != delim)
		{
		  unget_char (fmt);
		  token = FMT_STRING;
		  break;
		}
	    }

	  fmt->value++;
	}

      break;

    case 'P':
      token = FMT_P;
      break;

    case 'I':
      token = FMT_I;
      break;

    case 'O':
      token = FMT_O;
      break;

    case 'Z':
      token = FMT_Z;
      break;

    case 'F':
      token = FMT_F;
      break;

    case 'E':
      switch (next_char (fmt, 0))
	{
	case 'N':
	  token = FMT_EN;
	  break;
	case 'S':
	  token = FMT_ES;
	  break;
	default:
	  token = FMT_E;
	  unget_char (fmt);
	  break;
	}
      break;

    case 'G':
      token = FMT_G;
      break;

    case 'H':
      token = FMT_H;
      break;

    case 'L':
      token = FMT_L;
      break;

    case 'A':
      token = FMT_A;
      break;

    case 'D':
      switch (next_char (fmt, 0))
	{
	case 'P':
	  token = FMT_DP;
	  break;
	case 'C':
	  token = FMT_DC;
	  break;
	default:
	  token = FMT_D;
	  unget_char (fmt);
	  break;
	}
      break;

    case 'R':
      switch (next_char (fmt, 0))
	{
	case 'C':
	  token = FMT_RC;
	  break;
	case 'D':
	  token = FMT_RD;
	  break;
	case 'N':
	  token = FMT_RN;
	  break;
	case 'P':
	  token = FMT_RP;
	  break;
	case 'U':
	  token = FMT_RU;
	  break;
	case 'Z':
	  token = FMT_RZ;
	  break;
	default:
	  unget_char (fmt);
	  token = FMT_UNKNOWN;
	  break;
	}
      break;

    case -1:
      token = FMT_END;
      break;

    default:
      token = FMT_UNKNOWN;
      break;
    }

  return token;
}
Exemple #18
0
/* return NULL if eof or syntax error occurs;
 * otherwise return a pointer to a new entry.
 */
entry *
load_entry(FILE *file, void (*error_func)(const char *), struct passwd *pw,
    char **envp) {
	/* this function reads one crontab entry -- the next -- from a file.
	 * it skips any leading blank lines, ignores comments, and returns
	 * NULL if for any reason the entry can't be read and parsed.
	 *
	 * the entry is also parsed here.
	 *
	 * syntax:
	 *   user crontab:
	 *	minutes hours doms months dows cmd\n
	 *   system crontab (/etc/crontab):
	 *	minutes hours doms months dows USERNAME cmd\n
	 */

	ecode_e	ecode = e_none;
	entry *e;
	int ch;
	char cmd[MAX_COMMAND];
	char envstr[MAX_ENVSTR];
	char **tenvp;

	Debug(DPARS, ("load_entry()...about to eat comments\n"));

	skip_comments(file);

	ch = get_char(file);
	if (ch == EOF)
		return (NULL);

	/* ch is now the first useful character of a useful line.
	 * it may be an @special or it may be the first character
	 * of a list of minutes.
	 */

	e = calloc(sizeof(*e), sizeof(char));

	if (ch == '@') {
		/* all of these should be flagged and load-limited; i.e.,
		 * instead of @hourly meaning "0 * * * *" it should mean
		 * "close to the front of every hour but not 'til the
		 * system load is low".  Problems are: how do you know
		 * what "low" means? (save me from /etc/cron.conf!) and:
		 * how to guarantee low variance (how low is low?), which
		 * means how to we run roughly every hour -- seems like
		 * we need to keep a history or let the first hour set
		 * the schedule, which means we aren't load-limited
		 * anymore.  too much for my overloaded brain. (vix, jan90)
		 * HINT
		 */
		ch = get_string(cmd, MAX_COMMAND, file, " \t\n");
		if (!strcmp("reboot", cmd)) {
			e->flags |= WHEN_REBOOT;
		} else if (!strcmp("yearly", cmd) || !strcmp("annually", cmd)){
			bit_set(e->minute, 0);
			bit_set(e->hour, 0);
			bit_set(e->dom, 0);
			bit_set(e->month, 0);
			bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
			e->flags |= DOW_STAR;
		} else if (!strcmp("monthly", cmd)) {
			bit_set(e->minute, 0);
			bit_set(e->hour, 0);
			bit_set(e->dom, 0);
			bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
			bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
			e->flags |= DOW_STAR;
		} else if (!strcmp("weekly", cmd)) {
			bit_set(e->minute, 0);
			bit_set(e->hour, 0);
			bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
			bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
			bit_set(e->dow, 0);
			e->flags |= DOM_STAR;
		} else if (!strcmp("daily", cmd) || !strcmp("midnight", cmd)) {
			bit_set(e->minute, 0);
			bit_set(e->hour, 0);
			bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
			bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
			bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
			e->flags |= DOM_STAR | DOW_STAR;
		} else if (!strcmp("hourly", cmd)) {
			bit_set(e->minute, 0);
			bit_nset(e->hour, 0, (LAST_HOUR-FIRST_HOUR+1));
			bit_nset(e->dom, 0, (LAST_DOM-FIRST_DOM+1));
			bit_nset(e->month, 0, (LAST_MONTH-FIRST_MONTH+1));
			bit_nset(e->dow, 0, (LAST_DOW-FIRST_DOW+1));
			e->flags |= DOM_STAR | DOW_STAR;
		} else {
			ecode = e_timespec;
			goto eof;
		}
		/* Advance past whitespace between shortcut and
		 * username/command.
		 */
		Skip_Blanks(ch, file);
		if (ch == EOF || ch == '\n') {
			ecode = e_cmd;
			goto eof;
		}
	} else {
		Debug(DPARS, ("load_entry()...about to parse numerics\n"));

		if (ch == '*')
			e->flags |= MIN_STAR;
		ch = get_list(e->minute, FIRST_MINUTE, LAST_MINUTE,
			      PPC_NULL, ch, file);
		if (ch == EOF) {
			ecode = e_minute;
			goto eof;
		}

		/* hours
		 */

		if (ch == '*')
			e->flags |= HR_STAR;
		ch = get_list(e->hour, FIRST_HOUR, LAST_HOUR,
			      PPC_NULL, ch, file);
		if (ch == EOF) {
			ecode = e_hour;
			goto eof;
		}

		/* DOM (days of month)
		 */

		if (ch == '*')
			e->flags |= DOM_STAR;
		ch = get_list(e->dom, FIRST_DOM, LAST_DOM,
			      PPC_NULL, ch, file);
		if (ch == EOF) {
			ecode = e_dom;
			goto eof;
		}

		/* month
		 */

		ch = get_list(e->month, FIRST_MONTH, LAST_MONTH,
			      MonthNames, ch, file);
		if (ch == EOF) {
			ecode = e_month;
			goto eof;
		}

		/* DOW (days of week)
		 */

		if (ch == '*')
			e->flags |= DOW_STAR;
		ch = get_list(e->dow, FIRST_DOW, LAST_DOW,
			      DowNames, ch, file);
		if (ch == EOF) {
			ecode = e_dow;
			goto eof;
		}
	}

	/* make sundays equivalent */
	if (bit_test(e->dow, 0) || bit_test(e->dow, 7)) {
		bit_set(e->dow, 0);
		bit_set(e->dow, 7);
	}

	/* check for permature EOL and catch a common typo */
	if (ch == '\n' || ch == '*') {
		ecode = e_cmd;
		goto eof;
	}

	/* ch is the first character of a command, or a username */
	unget_char(ch, file);

	if (!pw) {
		char		*username = cmd;	/* temp buffer */

		Debug(DPARS, ("load_entry()...about to parse username\n"));
		ch = get_string(username, MAX_COMMAND, file, " \t\n");

		Debug(DPARS, ("load_entry()...got %s\n",username));
		if (ch == EOF || ch == '\n' || ch == '*') {
			ecode = e_cmd;
			goto eof;
		}

		pw = getpwnam(username);
		if (pw == NULL) {
			ecode = e_username;
			goto eof;
		}
		Debug(DPARS, ("load_entry()...uid %ld, gid %ld\n",
			      (long)pw->pw_uid, (long)pw->pw_gid));
	}

	if ((e->pwd = pw_dup(pw)) == NULL) {
		ecode = e_memory;
		goto eof;
	}
	(void)memset(e->pwd->pw_passwd, 0, strlen(e->pwd->pw_passwd));

	/* copy and fix up environment.  some variables are just defaults and
	 * others are overrides.
	 */
	if ((e->envp = env_copy(envp)) == NULL) {
		ecode = e_memory;
		goto eof;
	}
	if (!env_get("SHELL", e->envp)) {
		if (glue_strings(envstr, sizeof envstr, "SHELL",
				 _PATH_BSHELL, '=')) {
			if ((tenvp = env_set(e->envp, envstr)) == NULL) {
				ecode = e_memory;
				goto eof;
			}
			e->envp = tenvp;
		} else
			log_it("CRON", getpid(), "error", "can't set SHELL");
	}
	if (!env_get("HOME", e->envp)) {
		if (glue_strings(envstr, sizeof envstr, "HOME",
				 pw->pw_dir, '=')) {
			if ((tenvp = env_set(e->envp, envstr)) == NULL) {
				ecode = e_memory;
				goto eof;
			}
			e->envp = tenvp;
		} else
			log_it("CRON", getpid(), "error", "can't set HOME");
	}
	/* If login.conf is in used we will get the default PATH later. */
	if (!env_get("PATH", e->envp)) {
		if (glue_strings(envstr, sizeof envstr, "PATH",
				 _PATH_DEFPATH, '=')) {
			if ((tenvp = env_set(e->envp, envstr)) == NULL) {
				ecode = e_memory;
				goto eof;
			}
			e->envp = tenvp;
		} else
			log_it("CRON", getpid(), "error", "can't set PATH");
	}
	if (glue_strings(envstr, sizeof envstr, "LOGNAME",
			 pw->pw_name, '=')) {
		if ((tenvp = env_set(e->envp, envstr)) == NULL) {
			ecode = e_memory;
			goto eof;
		}
		e->envp = tenvp;
	} else
		log_it("CRON", getpid(), "error", "can't set LOGNAME");
#if defined(BSD) || defined(__linux)
	if (glue_strings(envstr, sizeof envstr, "USER",
			 pw->pw_name, '=')) {
		if ((tenvp = env_set(e->envp, envstr)) == NULL) {
			ecode = e_memory;
			goto eof;
		}
		e->envp = tenvp;
	} else
		log_it("CRON", getpid(), "error", "can't set USER");
#endif

	Debug(DPARS, ("load_entry()...about to parse command\n"));

	/* If the first character of the command is '-' it is a cron option.
	 */
	while ((ch = get_char(file)) == '-') {
		switch (ch = get_char(file)) {
		case 'q':
			e->flags |= DONT_LOG;
			Skip_Nonblanks(ch, file);
			break;
		default:
			ecode = e_option;
			goto eof;
		}
		Skip_Blanks(ch, file);
		if (ch == EOF || ch == '\n') {
			ecode = e_cmd;
			goto eof;
		}
	}
	unget_char(ch, file);

	/* Everything up to the next \n or EOF is part of the command...
	 * too bad we don't know in advance how long it will be, since we
	 * need to malloc a string for it... so, we limit it to MAX_COMMAND.
	 */ 
	ch = get_string(cmd, MAX_COMMAND, file, "\n");

	/* a file without a \n before the EOF is rude, so we'll complain...
	 */
	if (ch == EOF) {
		ecode = e_cmd;
		goto eof;
	}

	/* got the command in the 'cmd' string; save it in *e.
	 */
	if ((e->cmd = strdup(cmd)) == NULL) {
		ecode = e_memory;
		goto eof;
	}

	Debug(DPARS, ("load_entry()...returning successfully\n"));

	/* success, fini, return pointer to the entry we just created...
	 */
	return (e);

 eof:
	if (e->envp)
		env_free(e->envp);
	if (e->pwd)
		free(e->pwd);
	if (e->cmd)
		free(e->cmd);
	free(e);
	while (ch != '\n' && !feof(file))
		ch = get_char(file);
	if (ecode != e_none && error_func)
		(*error_func)(ecodes[(int)ecode]);
	return (NULL);
}
Exemple #19
0
static format_token format_lex(void) {        
format_token token;    
char y, delim;       
       
  if (saved_token != FMT_NONE) {    
    token = saved_token;     
    saved_token = FMT_NONE;    
    return token; 
  }

  if (mode == MODE_FORMAT) where = new_where;     
     
  do {     
    y = next_char(0);   
  } while(g95_is_whitespace(y));

  switch(y) {  
  case '-':          
  case '+':  
    y = next_char(0);  
    if (!isdigit(y)) {      
      token = FMT_UNKNOWN;   
      break;         
    }          
          
    do {      
      y = next_char(0);
    } while(isdigit(y));       
       
    unget_char();         
    token = FMT_SIGNED_INT;   
    break;          
          
  case '0': case '1': case '2': case '3': case '4':         
  case '5': case '6': case '7': case '8': case '9': 
    repeat = y - '0';      
      
    for(;;) {         
      y = next_char(0);      
      if (!isdigit(y)) break;         
         
      repeat = 10*repeat + y - '0';   
    } 
 
    unget_char();     
    token = (repeat == 0) ? FMT_ZERO : FMT_POSINT;   
    break;  
  
  case '.':    
    token = FMT_PERIOD;
    break;    
    
  case ',':          
    token = FMT_COMMA;       
    break;  
  
  case ':':  
    token = FMT_COLON;          
    break;          
          
  case '/':   
    token = FMT_SLASH;    
    break;   
   
  case '$':      
    token = FMT_DOLLAR;    
    break;       
       
  case 'T':   
    y = next_char(0);     
    if (y != 'L' && y != 'R') unget_char();       
       
    token = FMT_POS;  
    break;     
     
  case '(':
    token = FMT_LPAREN;       
    break;

  case ')': 
    token = FMT_RPAREN;        
    break;       
       
  case 'X':  
    token = FMT_X;          
    break;          
          
  case 'S':         
    y = next_char(0);    
    if (y != 'P' && y != 'S') unget_char();          
          
    token = FMT_SIGN;        
    break;  
  
  case 'B':      
    y = next_char(0);
    if (y == 'N' || y == 'Z') 
      token = FMT_BLANK;        
    else {         
      unget_char();      
      token = FMT_IBOZ;     
    }  
  
    break;         
         
  case '\'': case '"':       
    delim = y;       
 
    for(;;) {          
      y = next_char(1);
      if (y == '\0') {
	token = FMT_END;
	break;   
      }        
        
      if (y == delim) {       
	y = next_char(1);      
      
	if (y == '\0') { 
	  token = FMT_END;       
	  break;
	} 
 
	if (y != delim) {         
	  unget_char();     
	  token = FMT_CHAR;       
	  break;          
	}      
      }       
    }          
    break;     
     
  case 'P':          
    token = FMT_P;      
    break;

  case 'I': case 'O': case 'Z':       
    token = FMT_IBOZ;        
    break;  
  
  case 'F':   
    token = FMT_F;         
    break;      
      
  case 'E':          
    y = next_char(0);    
    if (y == 'N' || y == 'S')  
      token = FMT_EXT;        
    else {   
      token = FMT_E;  
      unget_char(); 
    }     
     
    break;

  case 'G':    
    token = FMT_G;      
    break;      
      
  case 'H':          
    token = FMT_H;      
    break;     
     
  case 'L':      
    token = FMT_L;  
    break;      
      
  case 'A':   
    token = FMT_A;  
    break;

  case 'D':        
    token = FMT_D;       
    break;       
       
  case '\0':  
    token = FMT_END;
    break;    
    
  default:  
    token = FMT_UNKNOWN;      
    break;      
  }       
       
  new_where = g95_current_locus;         
  return token;   
}   
Exemple #20
0
static Cell* readstrexp(Scheme *sc) {
	String str = init_string();

	int c1 = 0;
	enum {
		st_ok, st_bsl, st_x1, st_x2, st_oct1, st_oct2
	} state = st_ok;

	while (TRUE) {
		char c = get_char(sc);
		if (c == EOF) {
			return &g_false;
		}
		switch (state) {
		case st_ok:
			switch (c) {
			case '\\':
				state = st_bsl;
				break;
			case '"':
				return make_string_n(sc, str, strlen(str)); //free(str); ?
			default:
				str = append_char(str, c);
				break;
			}
			break;
		case st_bsl:
			switch (c) {
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
				state = st_oct1;
				c1 = c - '0';
				break;
			case 'x':
			case 'X':
				state = st_x1;
				c1 = 0;
				break;
			case 'n':
				str = append_char(str, '\n');
				state = st_ok;
				break;
			case 't':
				str = append_char(str, '\t');
				state = st_ok;
				break;
			case 'r':
				str = append_char(str, '\r');
				state = st_ok;
				break;
			case '"':
				str = append_char(str, '"');
				state = st_ok;
				break;
			default:
				str = append_char(str, c);
				state = st_ok;
				break;
			}
			break;
		case st_x1:
		case st_x2:
			c = toupper(c);
			if (c >= '0' && c <= 'F') {
				if (c <= '9') {
					c1 = (c1 << 4) + c - '0';
				} else {
					c1 = (c1 << 4) + c - 'A' + 10;
				}
				if (state == st_x1) {
					state = st_x2;
				} else {
					str = append_char(str, c1);
					state = st_ok;
				}
			} else {
				return &g_false;
			}
			break;
		case st_oct1:
		case st_oct2:
			if (c < '0' || c > '7') {
				str = append_char(str, c1);
				unget_char(sc, c);
				state = st_ok;
			} else {
				if (state == st_oct2 && c1 >= 32)
					return &g_false;

				c1 = (c1 << 3) + (c - '0');

				if (state == st_oct1)
					state = st_oct2;
				else {
					str = append_char(str, c1);
					state = st_ok;
				}
			}
			break;
		}
	}
}
Exemple #21
0
/*
 * Removes comments (normal and single line) from the file and
 * fixes long lines (lines that are divided to multiple lines with '\')
 * to single line. Carriage returns are added when needed to keep
 * file's line numbers correct.
 * 
 */
void postprocess(FILE *fp_in, FILE *fp_out)
{


        int     c1,c2,c3,fixed,done,i,string;


        fixed = 0;
        string = 0;
        while ((c1 = get_char(fp_in)) != EOF) {  
        
            c2 = get_char(fp_in);
            c3 = get_char(fp_in);
            
            switch (c1) {
                
                case '\\':

                    //
                    //  case: \\n
                    //
                    if (c1 == '\\' && c2 == '\n') {
				    fixed++;
				    unget_char(c3);
            	    
                    //
                    //  case: \\\n  (in a string)
                    //
                    } else if (c1 == '\\' && c2 == '\\' && c3 == '\n' && string) {
            			putc(c1,fp_out);
            			unget_char(c3);
               			unget_char(c2);
            		//
                    //  case: \\ (in a string)
                    //
                    } else if (c1 == '\\' && c2 == '\\' && string) {
           				putc(c1,fp_out);
           				putc(c2,fp_out); 
           				unget_char(c3);
           		
                    //
                    //  case: \ (in a string)
                    //
                    } else if (c1 == '\\' && string) {
            			putc(c1,fp_out);
           				putc(c2,fp_out);
               			unget_char(c3);
           			//
                    //  case: \ 
                    //
                    } else if (c1 == '\\' && !string) {
             			putc(c1, fp_out);
           				unget_char(c3);
           				unget_char(c2);
            		} else { 
            			putc(c1, fp_out);
           				unget_char(c3);
           				unget_char(c2);
           			} 
                   break;
                    
                  
                case '\n':
                        
   	            if (c1 == '\n' && fixed > 0) {
            		    putc(c1,fp_out);
            			unget_char(c3);
               			unget_char(c2);
               			
                        for (i=0; i < fixed; i++) {
                            putc('\n', fp_out); 
                        }
                   	} else {  
                   		putc(c1,fp_out);
            			unget_char(c3);
              			unget_char(c2);
            		} 
            		fixed = 0;
            		break;
                   
                case '/':

                    //
                    // remove C-style comments
                    //
			    if (c1 == '/' && c2 == '*' && !string) {

				    done = 0;
					while (!done) {

				        if (c2 == '*' && c3 == '/') {
						    done = 1;
						} else if (c2 == '\n') {
							putc(c2, fp_out);
							unget_char(c3);
						} else {
							unget_char(c3);
						}
						if (!done) {
							c2 = get_char(fp_in);
							c3 = get_char(fp_in);
						}
					}
                    //
                    // remove C++-style comments
                    //
				} else if (c1 == '/' && c2 == '/' && !string) {
            				
            		    while (c3 != '\n') {
                            c3 = get_char(fp_in);
                        }
				    putc(c3, fp_out);

            		} else { 
            		    putc(c1, fp_out);
            	    	unget_char(c3);
                		unget_char(c2);
            		} 
                    break;
                        
                case '\'':

                    //
                    // case: '"' and '\"'
                    //
             	    if (c1 == '\'' && c2 == '"' && c3 == '\'' && !string ||
                        c1 == '\'' && c2 == '\\' && c3 == '"' && !string) {
                        putc(c1,fp_out);
                        putc(c2,fp_out);
                        putc(c3,fp_out);
                    } else {
                        putc(c1,fp_out);
                        unget_char(c3);
                        unget_char(c2);
                    }

                    break;

                case '"':

                    //
                    // toggle string mode on/off
                    //
                    if (string == 0) {
                        string = 1;
                    } else {
                        string = 0;
                    }
                    putc(c1, fp_out);
                    unget_char(c3);
                   	unget_char(c2);
                        
                    break;

                default:
                    putc(c1, fp_out);
                    unget_char(c3);
                	unget_char(c2);
                    break;
            }
        }
}
Exemple #22
0
/* ARGSUSED */
static int
isearch(int f GCC_UNUSED, int n)
{
    static TBUFF *pat_save = 0;	/* Saved copy of the old pattern str */

    int status;			/* Search status */
    register int cpos;		/* character number in search string */
    register int c;		/* current input character */
    MARK curpos, curp;		/* Current point on entry */
    int init_direction;		/* The initial search direction */

    /* Initialize starting conditions */

    cmd_reexecute = -1;		/* We're not re-executing (yet?) */
    itb_init(&cmd_buff, EOS);	/* Init the command buffer */
    /* Save the old pattern string */
    (void) tb_copy(&pat_save, searchpat);
    curpos = DOT;		/* Save the current pointer */
    init_direction = n;		/* Save the initial search direction */

    ignorecase = window_b_val(curwp, MDIGNCASE);

    scanboundry(FALSE, DOT, FORWARD);	/* keep scanner() finite */

    /* This is a good place to start a re-execution: */

  start_over:

    /* ask the user for the text of a pattern */
    promptpattern("ISearch: ");

    status = TRUE;		/* Assume everything's cool */

    /*
     * Get the first character in the pattern.  If we get an initial
     * Control-S or Control-R, re-use the old search string and find the
     * first occurrence
     */

    c = kcod2key(get_char());	/* Get the first character */
    if ((c == IS_FORWARD) ||
	(c == IS_REVERSE)) {	/* Reuse old search string? */
	for (cpos = 0; cpos < (int) tb_length(searchpat); ++cpos)
	    echochar(tb_values(searchpat)[cpos]);	/* and re-echo the string */
	curp = DOT;
	if (c == IS_REVERSE) {	/* forward search? */
	    n = -1;		/* No, search in reverse */
	    last_srch_direc = REVERSE;
	    backchar(TRUE, 1);	/* Be defensive about EOB */
	} else {
	    n = 1;		/* Yes, search forward */
	    last_srch_direc = FORWARD;
	    forwchar(TRUE, 1);
	}
	unget_char();
	status = scanmore(searchpat, n);	/* Do the search */
	if (status != TRUE)
	    DOT = curp;
	c = kcod2key(get_char());	/* Get another character */
    } else {
	tb_init(&searchpat, EOS);
    }
    /* Top of the per character loop */

    for_ever {			/* ISearch per character loop */
	/* Check for special characters, since they might change the
	 * search to be done
	 */

	if (ABORTED(c) || c == '\r')	/* search aborted? */
	    return (TRUE);	/* end the search */

	if (isbackspace(c))
	    c = '\b';

	if (c == quotec)	/* quote character? */
	    c = kcod2key(get_char());	/* Get the next char */

	switch (c) {		/* dispatch on the input char */
	case IS_REVERSE:	/* If backward search */
	case IS_FORWARD:	/* If forward search */
	    curp = DOT;
	    if (c == IS_REVERSE) {	/* forward search? */
		last_srch_direc = REVERSE;
		n = -1;		/* No, search in reverse */
		backchar(TRUE, 1);	/* Be defensive about
					 * EOB */
	    } else {
		n = 1;		/* Yes, search forward */
		last_srch_direc = FORWARD;
		forwchar(TRUE, 1);
	    }
	    status = scanmore(searchpat, n);	/* Do the search */
	    if (status != TRUE)
		DOT = curp;
	    c = kcod2key(get_char());	/* Get the next char */
	    continue;		/* Go continue with the search */

	case '\t':		/* Generically allowed */
	case '\n':		/* controlled characters */
	    break;		/* Make sure we use it */

	case '\b':		/* or if a Rubout: */
	    if (itb_length(cmd_buff) <= 1)	/* Anything to delete? */
		return (TRUE);	/* No, just exit */
	    unget_char();
	    DOT = curpos;	/* Reset the pointer */
	    n = init_direction;	/* Reset the search direction */
	    (void) tb_copy(&searchpat, pat_save);
	    /* Restore the old search str */
	    cmd_reexecute = 0;	/* Start the whole mess over */
	    goto start_over;	/* Let it take care of itself */

	    /* Presumably a quasi-normal character comes here */

	default:		/* All other chars */
	    if (!isPrint(c)) {	/* Is it printable? */
		/* Nope. */
		unkeystroke(c);	/* Re-eat the char */
		return (TRUE);	/* And return the last status */
	    }
	}			/* Switch */

	/* I guess we got something to search for, so search for it */

	tb_append(&searchpat, c);	/* put the char in the buffer */
	echochar(c);		/* Echo the character */
	if (!status) {		/* If we lost last time */
	    kbd_alarm();	/* Feep again */
	} else			/* Otherwise, we must have won */
	    status = scanmore(searchpat, n);	/* or find the next
						   * match */
	c = kcod2key(get_char());	/* Get the next char */
    }				/* for_ever */
}