]> pd.if.org Git - pdutils/blobdiff - utils/sh/tok.c
rename utils to posix
[pdutils] / utils / sh / tok.c
diff --git a/utils/sh/tok.c b/utils/sh/tok.c
deleted file mode 100644 (file)
index a926343..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-#include <stdio.h>
-#include "gram.h"
-
-/* START HEADER */
-struct token {
-       int type;
-       int rtype; /* a "real type", e.g. In, NAME, etc. */
-       int length;
-       int delimiter;
-       int nondigits;
-       int nonnames;
-       struct token *next;
-       char text[2048];
-};
-
-struct token_state {
-       FILE *input;
-       struct token *tok;
-
-       char *strinput;
-       int is_string;
-       int strlen;
-       int cursor;
-
-       int pc; /* previous char */
-       int cc; /* current char */
-       int nc; /* next char */
-       int push_back; /* true if next char is valid */
-
-       int prev_op; /* previous character was used as part of an operator */
-       int prev_word; /* previous character is part of a word */
-       int quoting; /* type of quoting */
-
-       char buf[2048];
-       int buflen;
-};
-
-struct token_state *ts_init(struct token_state *ts, FILE *f);
-int get_token(struct token_state *ts, struct token *tok);
-
-/* END HEADER */
-
-#if DEBUG_TOKEN
-static void ptoken(struct token_state *ts) {
-       fprintf(stderr, "token %d = %s\n", ts->tok->type, ts->tok->text);
-}
-#endif
-
-static int nextch(struct token_state *ts);
-static int peek(struct token_state *ts);
-static int nextchar(struct token_state *ts); 
-static int process_char(struct token_state *ts);
-
-static int peek(struct token_state *ts) {
-       if (!ts->push_back) {
-               ts->nc = nextchar(ts);
-               ts->push_back = 1;
-       }
-       return ts->nc;
-}
-
-static int nextch(struct token_state *ts) {
-       if (!ts->push_back) {
-               ts->nc = nextchar(ts);
-       }
-       ts->pc = ts->cc;
-       ts->cc = ts->nc;
-       ts->push_back = 0;
-       return ts->cc;
-}
-
-#if 0
-static int pushback(struct token_state *ts) {
-       /* TODO error if already pushed back? */
-       ts->nc = ts->cc;
-       ts->cc = ts->pc;
-       return ts->cc;
-}
-#endif
-
-static int add_to_token(struct token_state *ts, int ch) {
-       ts->tok->text[ts->tok->length++] = (char)ch;
-#if DEBUG_TOKEN
-       ptoken(ts);
-#endif
-       return ts->tok->length;
-}
-
-static int start_token(struct token_state *ts, int type, int ch) {
-       int i;
-       for (i=0;i<sizeof ts->tok->text; i++) {
-               ts->tok->text[i] = 0;
-       }
-       ts->tok->type = type;
-       ts->tok->text[0] = (char)ch;
-       ts->tok->length = 1;
-#if DEBUG_TOKEN
-       fprintf(stderr, "starting ");
-       ptoken(ts);
-#endif
-       return 1;
-}
-
-struct token_state *ts_init(struct token_state *ts, FILE *f) {
-       if (!ts) return NULL;
-       /* TODO malloc one */
-
-       ts->is_string = 0;
-       ts->push_back = 0;
-       ts->prev_op = 0;
-       ts->prev_word = 0;
-       ts->quoting = 0;
-
-       ts->input = f;
-       ts->buf[0] = 0;
-       return ts;
-}
-
-int get_token(struct token_state *ts, struct token *tok) {
-       int i;
-       ts->tok = tok;
-       tok->type = 0;
-       tok->length = 0;
-       ts->prev_op = 0;
-       ts->prev_word = 0;
-       ts->quoting = 0;
-       for (i=0;i<sizeof tok->text; i++) {
-               tok->text[i] = 0;
-       }
-
-       while (!process_char(ts)) {
-       }
-       return tok->type;
-}
-
-/* true if the character could be used with the given token to make
- * an operator
- */
-static int can_op(int type, int ch) {
-       /* TODO */
-       switch (type) {
-               case TOKEN_Ampersand:
-                       if (ch == '&') return TOKEN_AND_IF; break;
-               case TOKEN_Pipe:
-                       if (ch == '|') return TOKEN_OR_IF; break;
-               case TOKEN_Semicolon:
-                       if (ch == ';') return TOKEN_DSEMI; break;
-               case TOKEN_DLESS:
-                       if (ch == '-') return TOKEN_DLESSDASH; break;
-               case TOKEN_Lessthan:
-                       switch (ch) {
-                               case '<': return TOKEN_DLESS; break;
-                               case '&': return TOKEN_LESSAND; break;
-                               case '>': return TOKEN_LESSGREAT; break;
-                               default: break;
-                       }
-                       break;
-               case TOKEN_Greaterthan:
-                       switch (ch) {
-                               case '>': return TOKEN_DGREAT; break;
-                               case '&': return TOKEN_GREATAND; break;
-                               case '|': return TOKEN_CLOBBER; break;
-                               default: break;
-                       }
-                       break;
-               default:
-                       break;
-       }
-       return 0;
-}
-
-static int valid_token(struct token_state *ts) {
-       return ts->tok && ts->tok->length;
-}
-
-static int delimit(struct token_state *ts, int ch) {
-       if (valid_token(ts)) {
-               ts->tok->delimiter = ch;
-               if (ts->tok->length == 1 && ts->tok->text[0] == '\n') {
-                       ts->tok->type = TOKEN_NEWLINE;
-               } else if (!ts->tok->nondigits && (ts->tok->delimiter == '>' || ts->tok->delimiter == '<')) {
-                       ts->tok->type = TOKEN_IO_NUMBER;
-               }
-#if DEBUG_TOKEN
-       fprintf(stderr, "delimited ");
-       ptoken(ts);
-#endif
-               return 1;
-       }
-
-       return 0;
-}
-
-/* return true if delimited */
-static int process_char(struct token_state *ts) {
-       int cc;
-
-       cc = peek(ts);
-#if 1
-       fprintf(stderr, "looking at a '%c'\n", cc);
-#endif
-
-/*
- * If the end of input is recognized, the current token shall be delimited. If
- * there is no current token, the end-of-input indicator shall be returned as
- * the token.
- */
-       if (cc == EOF) {
-               if (delimit(ts,cc)) {
-                       return 1;
-               }
-               fprintf(stderr, "EOF Token\n");
-               ts->tok->type = EOF;
-               return 1;
-       }
-
-/*
- * If the previous character was used as part of an operator and the current
- * character is not quoted and can be used with the current characters to form
- * an operator, it shall be used as part of that (operator) token.
- */
-       if (ts->prev_op && !ts->quoting) {
-               int newop = can_op(ts->tok->type, cc);
-               if (newop) {
-                       ts->tok->type = newop;
-                       add_to_token(ts,cc);
-                       nextch(ts);
-                       return 0;
-               }
-       }
-
-/*
- * If the previous character was used as part of an operator and the current
- * character cannot be used with the current characters to form an
- * operator, the operator containing the previous character shall be
- * delimited.
- */
-       if (ts->prev_op && ! can_op(ts->tok->type, cc)) {
-               if (delimit(ts,cc)) return 1;
-               /* TODO error here, should be impossible */
-       }
-
-       /* match quote */
-/*
- * If the current character is <backslash>, single-quote, or double-quote and
- * it is not quoted, it shall affect quoting for subsequent characters up to
- * the end of the quoted text. The rules for quoting are as described in
- * Quoting . During token recognition no substitutions shall be actually
- * performed, and the result token shall contain exactly the characters that
- * appear in the input (except for <newline> joining), unmodified, including
- * any embedded or enclosing quotes or substitution operators, between the
- * <quotation-mark> and the end of the quoted text. The token shall not be
- * delimited by the end of the quoted field.
- */
-       if (!ts->quoting) {
-               if (cc == '\\' || cc == '\'' || cc == '"') {
-                       ts->quoting = cc;
-               }
-       }
-
-       /* match expansion */
-/*
- * If the current character is an unquoted '$' or '`', the shell shall identify
- * the start of any candidates for parameter expansion (Parameter Expansion),
- * command substitution (Command Substitution), or arithmetic expansion
- * (Arithmetic Expansion) from their introductory unquoted character sequences:
- * '$' or "${", "$(" or '`', and "$((", respectively. The shell shall read
- * sufficient input to determine the end of the unit to be expanded (as
- * explained in the cited sections). While processing the characters, if
- * instances of expansions or quoting are found nested within the substitution,
- * the shell shall recursively process them in the manner specified for the
- * construct that is found. The characters found from the beginning of the
- * substitution to its end, allowing for any recursion necessary to recognize
- * embedded constructs, shall be included unmodified in the result token,
- * including any embedded or enclosing substitution operators or quotes.  The
- * token shall not be delimited by the end of the substitution.
- */
-#if 0
-       if (!ts->quoting) {
-               if (cc == '$' || cc == '`') {
-                       int nc;
-                       nc = peek(ts);
-                       switch (nc) {
-                               case '{':
-                                       ts->expanding = EXP_BRACKET; break;
-                               case '(':
-                                       ts->expanding = EXP_COMMAND; break;
-                               default:
-                                       ts->expanding = EXP_WORDVAR; break;
-                       }
-                       do_expansion(ts, cc);
-               } else if (cc == '`') {
-                       ts->expanding = EXP_COMMAND;
-               }
-       }
-#endif
-
-/*
- * If the current character is not quoted and can be used as the first
- * character of a new operator, the current token (if any) shall be delimited.
- * The current character shall be used as the beginning of the next (operator)
- * token.
- */
-
-/*
- * If the current character is an unquoted <newline>, the current token shall
- * be delimited.
- */
-
-/*
- * If the current character is an unquoted <blank>, any token containing the
- * previous character is delimited and the current character shall be
- * discarded.
- */
-
-/* 
- * The application shall quote the following characters if they are to
- * represent themselves:
- *
- * |  &  ;  <  >  (  )  $  `  \  "  '  <space>  <tab>  <newline>
- */
-
-
-       if (! ts->quoting) {
-               switch (cc) {
-                       case '&':
-                               if (delimit(ts,cc)) return 1;
-                               nextch(ts);
-                               ts->prev_op = 1;
-                               start_token(ts, TOKEN_Ampersand, cc);
-                               return 0; break;
-                       case '|':
-                               if (delimit(ts,cc)) return 1;
-                               nextch(ts);
-                               ts->prev_op = 1;
-                               start_token(ts, TOKEN_Pipe,cc);
-                               return 0; break;
-                       case ';':
-                               if (delimit(ts,cc)) return 1;
-                               nextch(ts);
-                               ts->prev_op = 1;
-                               start_token(ts, TOKEN_Semicolon,cc);
-                               return 0; break;
-                       case '<':
-                               if (delimit(ts,cc)) return 1;
-                               nextch(ts);
-                               ts->prev_op = 1;
-                               start_token(ts, TOKEN_Lessthan,cc);
-                               return 0; break;
-                       case '>':
-                               if (delimit(ts,cc)) return 1;
-                               nextch(ts);
-                               ts->prev_op = 1;
-                               start_token(ts, TOKEN_Greaterthan,cc);
-                               return 0; break;
-                       case '\n':
-                               if (delimit(ts,cc)) return 1;
-                               fprintf(stderr, "newline\n");
-                               nextch(ts);
-                               start_token(ts, TOKEN_NEWLINE,cc);
-                               if (delimit(ts,cc)) return 1;
-                               break;
-                       case '(':
-                               if (delimit(ts,cc)) return 1;
-                               nextch(ts);
-                               start_token(ts, TOKEN_Lparen,cc);
-                               if (delimit(ts,cc)) return 1;
-                               break;
-                       case ')':
-                               if (delimit(ts,cc)) return 1;
-                               nextch(ts);
-                               start_token(ts, TOKEN_Rparen,cc);
-                               if (delimit(ts,cc)) return 1;
-                               break;
-                       case ' ':
-                       case '\t':
-                               if (delimit(ts,cc)) return 1;
-                               nextch(ts);
-                               return 0; break;
-                       default:
-                               break;
-               }
-       }
-
-/*
- * If the previous character was part of a word, the current character shall
- * be appended to that word.
- */
-       if (ts->prev_word) {
-               add_to_token(ts, cc);
-               nextch(ts);
-               return 0;
-       }
-
-/*
- * If the current character is a '#', it and all subsequent characters up
- * to, but excluding, the next <newline> shall be discarded as a comment.
- * The <newline> that ends the line is not considered part of the comment.
- */
-       if (cc == '#') {
-               cc = nextch(ts);
-               cc = peek(ts);
-               while (cc != '\n' && cc != EOF) {
-                       cc = nextch(ts);
-                       cc = peek(ts);
-               }
-               return 0;
-       }
-
-/*
- * The current character is used as the start of a new word.
- */
-       ts->prev_word = 1;
-       start_token(ts, TOKEN_WORD, cc);
-       nextch(ts);
-       return 0;
-}
-
-static int nextchar(struct token_state *ts) {
-       if (ts->is_string) {
-               if (ts->cursor >= ts->strlen) {
-                       return EOF;
-               }
-               return (int)(unsigned char)ts->strinput[ts->cursor++];
-       }
-
-       return fgetc(ts->input);
-}
-