コード例 #1
0
/* parse a compound list
 * 
 * The term compound-list is derived from the grammar in 3.10; it is
 * equivalent to a sequence of lists, separated by <newline>s, that 
 * can be preceded or followed by an arbitrary number of <newline>s.
 * ----------------------------------------------------------------------- */
union node *parse_compound_list(struct parser *p) {
  union node *list;
  union node **nptr;

  tree_init(list, nptr);

  /* skip arbitrary newlines */
  while(parse_gettok(p, P_DEFAULT) & T_NL);
  p->pushback++;

  for(;;) {
    /* try to parse a list */
    *nptr = parse_list(p);

    /* skip arbitrary newlines */
    while(p->tok & T_NL) parse_gettok(p, P_DEFAULT);
    p->pushback++;

    /* no more lists */
    if(*nptr == NULL)
      break;

    /* parse_list already returns a list, so we
       must skip over it to get &lastnode->next */
    while(*nptr)
      tree_next(nptr);
  }

  return list;
}
コード例 #2
0
ファイル: parse_grouping.c プロジェクト: rsenn/shish
/* 3.9.4.1 parse a grouping compound
 * 
 * The format for grouping commands is a s follows:
 * 
 *  (compound-list)       Execute compound-list in a subshell environment;
 *                        Variable assignments and built-in commands that
 *                        affect the environment shall not remain in effect
 *                        after the list finishes.
 * 
 *  { compound-list;}     Execute compound-list in the current process
 *                        environment.
 * 
 * ----------------------------------------------------------------------- */
union node *parse_grouping(struct parser *p) {
  enum tok_flag tok;
  union node  **rptr;
  union node   *grouping;
  union node   *compound_list;

  /* return NULL on empty compound */
  grouping = NULL;
  
  if(!(tok = parse_expect(p, P_DEFAULT, T_BEGIN|T_LP, NULL)))
    return NULL;
  
  /* parse compound content and create a 
     compound node if there are commands */
  if((compound_list = parse_compound_list(p))) {
    grouping = tree_newnode(tok == T_BEGIN ? N_CMDLIST : N_SUBSHELL);
    grouping->ngrp.cmds = compound_list;
  }

  /* expect the appropriate ending token */
  if(!parse_expect(p, P_DEFAULT, tok << 1, grouping))
    return NULL;

  if(grouping) {
    tree_init(grouping->ngrp.rdir, rptr);

    /* now any redirections may follow */
    while(parse_gettok(p, P_DEFAULT) & T_REDIR)
      tree_move(p->tree, rptr);

    p->pushback++;
  }

  return grouping;
}
コード例 #3
0
ファイル: parse_list.c プロジェクト: rsenn/shish
/* A list is a sequence of one or more AND-OR-lists separated by the
 * operators
 *
 *       ;    &
 *
 * and optionally terminated by
 *
 *       ;    &    <newline>
 *
 * ----------------------------------------------------------------------- */
union node *parse_list(struct parser *p) {
    union node   *list;
    union node  **nptr;
    enum tok_flag tok;

    /* keep looking for and-or lists */
    tree_init(list, nptr);

    while((*nptr = parse_and_or(p))) {
        tok = parse_gettok(p, P_DEFAULT);

        /* <newline> terminates the list and eats the token */
        if(tok & T_NL)
            return list;

        /* there must be & or ; after the and-or list,
           otherwise the list will be terminated */
        if(!(tok & (T_SEMI | T_BGND))) {
            p->pushback++;
            break;
        }

        /* & causes async exec of preceding and-or list */
        if(tok & T_BGND)
            (*nptr)->nlist.bgnd = 1;

        /* now check for another and-or list */
        tree_next(nptr);
    }

    return list;
}
コード例 #4
0
ファイル: parser.c プロジェクト: HarryR/sanos
static int parse_expect(struct parser *p, int tempflags, int toks) {
  int n, i, f;
  
  if (parse_gettok(p, tempflags) & toks) return p->tok;

  if (p->tok) {
    for (i = 0, n = p->tok; n > 1; i++, n >>= 1);
    fprintf(stderr, "unexpected token '%s', expecting '", tokens[i].name);
  } else {
コード例 #5
0
ファイル: parse_command.c プロジェクト: rsenn/shish
/* parse a compound- or a simple-command
 * (pipeline and lists are done outside this)
 * ----------------------------------------------------------------------- */
union node *parse_command(struct parser *p, int tempflags) {
  enum tok_flag tok;
  union node *command;
  union node **rptr;
 
  tok = parse_gettok(p, tempflags);

  switch(tok) {
    /* T_FOR begins an iteration statement */
    case T_FOR:
      command = parse_for(p);
      break;

    /* T_IF begins a case match statement */
    case T_CASE:
      command = parse_case(p);
      break;
      
    /* T_IF begins a conditional statement */
    case T_IF:
      command = parse_if(p);
      break;
      
    /* T_WHILE/T_UNTIL begin a for-loop statement */
    case T_WHILE:
    case T_UNTIL:
      command = parse_loop(p);
      break;
      
    /* T_LP/T_BEGIN start a grouping compound */
    case T_LP:
    case T_BEGIN:
      p->pushback++;
      command = parse_grouping(p);
      break;

    /* handle simple commands */
    case T_NAME:
    case T_WORD:
    case T_REDIR:
    case T_ASSIGN:
      p->pushback++;
      command = parse_simple_command(p);
      break;
    
    /* it wasn't a compound command, return now */
    default:
      p->pushback++;
      return NULL;
  }
      
  if(command) {
    /* they all can have redirections, so parse these now */
    rptr = &command->ncmd.rdir;

    /*
     * in the case of a simple command there are maybe already
     * redirections in the list (because in a simple command they
     * can appear between arguments), so skip to the end of the list.
     */
    while(*rptr)
      tree_next(rptr);

    while(parse_gettok(p, P_DEFAULT) & T_REDIR)
      tree_move(p->tree, rptr);
  }
  
  p->pushback++;

  return command;
}
コード例 #6
0
/* main loop, parse lines into trees and execute them
 * ----------------------------------------------------------------------- */
void sh_loop(void) {
  struct parser p;
  union node *list;
  stralloc cmd;

  /* if we're in interactive mode some 
     additional stuff is to be initialized */
  if(source->mode & SOURCE_IACTIVE)
    history_load();
  
  stralloc_init(&cmd);

  parse_init(&p, P_DEFAULT);
  
  while(!(parse_gettok(&p, P_DEFAULT) & T_EOF)) {
    p.pushback++;
    parse_lineno = source->line;

    var_setvint("LINENO", parse_lineno, V_DEFAULT);
    
    /* launch the parser to get a complete command */
    if((list = parse_list(&p)))
    {
      struct eval e;
      
      if(source->mode & SOURCE_IACTIVE)
      {
        tree_printlist(list, &cmd, NULL);
        stralloc_catc(&cmd, '\n');
        stralloc_nul(&cmd);
        history_set(cmd.s);
        cmd.s = NULL;
        history_advance();
      }

#ifdef DEBUG
/*      debug_list(list, 0);
      buffer_putnlflush(fd_err->w);*/
#endif /* DEBUG */
      eval_push(&e, E_JCTL);
      eval_tree(&e, list, E_ROOT|E_LIST);
      sh->exitcode = eval_pop(&e);
      
      stralloc_zero(&cmd);

      tree_free(list);
    } else if(!(p.tok & (T_NL | T_SEMI | T_BGND))) {
      /* we have a parse error */
      if(p.tok != T_EOF)
        parse_error(&p, 0);

      /* exit if not interactive */
      if(!(source->mode & SOURCE_IACTIVE))
        sh_exit(1);

      /* ..otherwise discard the input buffer */
      source_flush();
      p.pushback = 0;
    }
    
    if(p.tok & (T_NL|T_SEMI|T_BGND))
      p.pushback = 0;

    /* reset prompt */
    prompt_number = 0;
  }
}