Beispiel #1
0
/**
 * Create a TestBaseCli object.
 */
TestBaseCli::TestBaseCli(YangModel& model, bool debug)
  : BaseCli(model),
    editline_(NULL),
    debug_(debug)
{
  ModeState::ptr_t new_root_mode(new ModeState(*this,*root_parse_node_));
  mode_stack_root(std::move(new_root_mode));

  add_builtins();
  setprompt();
}
Beispiel #2
0
union node *
parsecmd(int interact)
{
	int t;
	extern int exitstatus;

	tokpushback = 0;
	doprompt = interact;
	if (doprompt)
		setprompt(exitstatus == 0 || (vpse.flags & VUNSET)
					? 1 : -1);
	else
		setprompt(0);
	needprompt = 0;
	t = readtoken();
	if (t == TEOF)
		return NEOF;
	if (t == TNL)
		return NULL;
	tokpushback++;
	return list(1);
}
Beispiel #3
0
int openvdem(char *mgmt,char *progname, struct netif **nif,char *nodename)
{
	struct sockaddr_un sun;
	int fd,n;
	char buf[BUFSIZE+1],*line2,*ctrl;
	sun.sun_family=PF_UNIX;
	snprintf(sun.sun_path,UNIX_PATH_MAX,"%s",mgmt);
	fd=socket(PF_UNIX,SOCK_STREAM,0);
	if (connect(fd,(struct sockaddr *)(&sun),sizeof(sun)) < 0) {
		printlog(LOG_ERR,"Error connecting to the management socket '%s': %s", mgmt, strerror(errno));
		exit(-1);
	}
	if ((n=read(fd,buf,BUFSIZE))<=0) {
		printlog(LOG_ERR,"Error reading banner from VDE switch: %s",strerror(errno));
		exit(-1);
	}
	buf[n]=0;
	if ((ctrl=rindex(buf,'\n')) != NULL)
		*ctrl=0;
	banner=strdup(buf);
	write(fd,"ds/showinfo\n",12);
	if ((n=read(fd,buf,BUFSIZE))<=0) {
		printlog(LOG_ERR,"Error reading ctl socket from VDE switch: %s",strerror(errno));
		exit(-1);
	}
	buf[n]=0;
	if ((line2=index(buf,'\n')) == NULL) {
		printlog(LOG_ERR,"Error parsing first line of ctl socket information");
		exit(-1);
	}
	line2++;
	if (strncmp(line2,"ctl dir ",8) != 0) {
		printlog(LOG_ERR,"Error parsing ctl socket information");
		exit(-1);
	}
	for(ctrl=line2+8;*ctrl!='\n' && ctrl<buf+n;ctrl++)
		;
	*ctrl=0;
	ctrl=line2+8;
	setprompt(ctrl,nodename);
	strcat(ctrl,"[0]");
	*nif=lwip_vdeif_add(lwipstack,ctrl);
	if (*nif == NULL) {
		printlog(LOG_ERR,"Cannot connect to the VDE switch");
		exit(-1);
	}
	lwip_ifup(*nif);

	return fd;
}
Beispiel #4
0
STATIC void
parseheredoc(void)
{
	struct heredoc *here;
	union node *n;

	while (heredoclist) {
		here = heredoclist;
		heredoclist = here->next;
		if (needprompt) {
			setprompt(2);
			needprompt = 0;
		}
		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
				here->eofmark, here->striptabs);
		n = (union node *)stalloc(sizeof (struct narg));
		n->narg.type = NARG;
		n->narg.next = NULL;
		n->narg.text = wordtext;
		n->narg.backquote = backquotelist;
		here->here->nhere.doc = n;
	}
}
Beispiel #5
0
// 																		<<<<<<<<<<-------------- TODO: Check this out...dose some intresting things
static void
skip_percent_comment(void)
{

#ifndef TTYEDEN
    Script     *script;
    extern Script *st_script, *dd_script;
    extern int  run(short, void *, char *);
    extern void dd_lex(int), st_lex(int);
#ifdef WANT_SASAMI
    extern Script *sa_script;
    extern void sa_input(char);
#endif /* WANT_SASAMI */
#ifdef DISTRIB
    extern void lsd_lex(int);
#endif /* DISTRIB */
#endif /* not TTYEDEN */

    /* skip_percent_comment is called when we are starting a new line
       and nextc=='%' [Ash] */

    char       *s;
    int         start = yyleng;

    safe_input();		/* read in the initial '%' */

    for (;;) {

	s = yytext + start;

	/* safe_input until we have an end-of-line or EOF */
	if ((nextc != '\n') && (nextc != '\r') && (nextc != 0)) {
	  safe_input();
	  continue;
	} else {
	  /* now we've found the end of the line, terminate it correctly */
	  end_text1();
	}

	if ((nextc == '\n') || (nextc == '\r')) {
	  if (notationSwitch(s)) {
	    char execstr[100];
	    int c;
	    
	    changeNotation(NEWOTHER);

	    /* Notation now changed to a non-default one.  Slurp in
	       the rest of the text until (just before) the next
	       change of notation and parse it.  [Ash] */
	    for (nextc = peek();
		 (nextc != '\0') && (nextc != EOF);
		 nextc = peek()) {
	      
	      if (Inp_Dev->newline && nextc == '%') {
		/* Trying to fix sqleddi "prepare to eat and then eat"
		   bug [Ash, 23rd October 2002] */
		/*
		  strcpy(execstr, "notationChar('\\\n');");
		  run(STRING_DEV, execstr, 0);
		*/
		
		nextc = '\n';
		return;
	      } else if (Inp_Dev->newline && nextc == '#') {
		c = keyin();
		if (nextc == '#') {
		  /* "##" comment input: ignore to end of line */
		  do {c = keyin();} while (!Inp_Dev->newline);
		  
		} else {
		  /* input line starts with #, but second character is
		     not #.  Pass the first # to the Eden parser, and
		     parse the second character the next time round
		     the loop. */
		  strcpy(execstr, "notationChar('#');");
		  run(STRING_DEV, execstr, 0);
		}
	      } else {
		/* Something in the sqleddi model causes C's idea
                   about the status of the current notation to get
                   confused.  As this piece of code is executing, we
                   must be in a NEWOTHER notation, so set it
                   explicitly.  [Ash, 24th October 2002] */
#ifdef TTYEDEN
		changeNotation(NEWOTHER);
#endif
		c = keyin();
		/* fprintf(stderr, "KEYIN %d\n", c); */
		
		if (c == '\'')
		  strcpy(execstr, "notationChar('\\\'');");
		else if (c == '\\')
		  strcpy(execstr, "notationChar('\\\\');");
		else
		  sprintf(execstr, "notationChar('%c');", c);
		
		run(STRING_DEV, execstr, 0);
	      }
	      
	    } /* end for */
	    
#ifdef TTYEDEN
	    /* ttyeden does not currently keep track of the current
	       notation properly.  It should still be %eddi after an
	       included file has changed to that notation and not back
	       again, but this would require some work on the lexer.
	       At least we can ensure that the prompt is correct here.
	       [Ash] */
	    /*
	      if ((nextc == EOF) || (nextc == '\0')) {
	      fprintf(stderr, "EOF FUDGE\n");
	      notationSwitch("%eden");
	      currentNotation = EDEN;
	      }
	    */

	    currentNotation = EDEN;
	    /* peek() does not seem to manage to successfully push
	       back the EOF character in TTYEDEN and so keyin() would
	       cause another character to be read.  Stop immediately
	       instead.  [Ash] */
	    return;
#else
	    keyin();	/* read the null character */
	    /* treat end-of-file as end-of-line */
	    /* the code feeding the parser with \n below is a
	       reinterpretation of something Chris Brown put in, but
	       it doesn't seem to be required any more */
	    /*
	     * strcpy(execstr, "notationChar('\\n');");
	     * run(STRING_DEV, execstr, 0);
	     */
	    setprompt();
#endif
	    
	  } /* end if notationSwitch(s) */


#ifndef TTYEDEN
	  /* DoNaLD -------------------------------------------- */
	  /* %donald0 is an alternative alias for %donald, so that we
	     can replace %donald with a new translator but still
	     access this builtin as %donald0 */
	  else if ((strncmp(s, "%donald0", 8) == 0) ||
		   (strncmp(s, "%donald", 7) == 0)) {
	    changeNotation(DONALD);
	    dd_script = script = newScript();
	    for (nextc = peek(); nextc != '\0'; nextc = peek()) {
	      if (Inp_Dev->newline && (nextc == '%' || nextc == '>'
				       || nextc == '<')) {
		if (nextc == '>' || nextc == '<') {
		  input();
		  getAgentName();
		}
		else {
		  nextc = '\n';
		  if (script->text[0] != '\0') {
		    appAgentName--;
		    /* printf("from donald 1"); */
		    pushEntryStack(DONALD);
		    run(STRING_DEV, script->text, 0);
		    popEntryStack();
		    appAgentName++;
		  }
		  deleteScript(script);
		  return;
		} /* end if (nextc == '>' || nextc == '<') */
	      } /* end if (Inp_Dev->newline...) */
	      else {
		dd_lex(keyin());
		if (script->ready) {
		  if (script->text[0] != '\0') {
		    appAgentName--;
		    /* printf("from donald 2"); */
		    pushEntryStack(DONALD);
		    run(STRING_DEV, script->text, 0);
		    dd_script = script;
		    popEntryStack();
		    /* printf("from donald 3"); */
		    appAgentName++;
		  }
		  resetScript(script);
		} /* end if (script->ready) */
	      } /* end if (Inp_Dev->newline...) (two versions) */
	    } /* end for (nextc = peek()...) */


	    keyin();	/* read the null character */
	    dd_lex('\n');	/* treat end-of-file as end-of-line */

	    if (script->text[0] != '\0') {
	      appAgentName--;
	      pushEntryStack(DONALD);
	      run(STRING_DEV, script->text, 0);
	      popEntryStack();
	      /* printf("from donald 4"); */
	      appAgentName++;
	    }
	    deleteScript(script);
	  } /* end if (strncmp(s, "%donald", 7) == 0) */


	  /* SCOUT -------------------------------------------- */
	  else if (strncmp(s, "%scout", 6) == 0) {	/* is SCOUT */
	    scoutScreenInitOpen();
	    changeNotation(SCOUT);
	    st_script = script = newScript();
	    for (nextc = peek(); nextc != '\0'; nextc = peek()) {
	      if (Inp_Dev->newline && (nextc == '%' || nextc == '>'
				       || nextc == '<')) {
		if (nextc == '>' || nextc == '<') {
		  input();
		  getAgentName();
		} else {
		  nextc = '\n';
		  if (script->text[0] != '\0') {
		    appAgentName--;
		    /* printf("from scout 1"); */
		    pushEntryStack(SCOUT);
		    run(STRING_DEV, script->text, 0);
		    popEntryStack();
		    appAgentName++;
		  }
		  deleteScript(script);
		  return;
		}
	      } /* end if (Inp_Dev->newline...) */
	      else {
		st_lex(keyin());
		if (script->ready) {
		  if (script->text[0] != '\0') {
		    appAgentName--;
		    /* printf("from scout 2 %s\n", script->text); */
		    pushEntryStack(SCOUT);
		    run(STRING_DEV, script->text, 0);
		    st_script = script;
		    popEntryStack();
		    appAgentName++;
		  }
		  resetScript(script);
		}
	      }
	    } /* end for (nextc = peek();... */

	    keyin();	/* read the null character */
	    st_lex('\n');	/* treat end-of-file as end-of-line */
	    if (script->text[0] != '\0') {
	      appAgentName--;
	      pushEntryStack(SCOUT);
	      run(STRING_DEV, script->text, 0);
	      popEntryStack();
	      appAgentName++;
	    }
	    deleteScript(script);
	  } /* end if (strncmp(s, "%scout", 6)... */

#ifdef WANT_SASAMI

	  /* Sasami -------------------------------------------- */

	  else if (strncmp(s, "%sasami", 7) == 0) {
	    changeNotation(SASAMI);
	    sa_script = script = newScript();
	    for (nextc = peek(); nextc != '\0'; nextc = peek())	{
	      if (Inp_Dev->newline && (nextc == '%' || nextc == '>' ||
				       nextc == '<')) {
		/* This is a %, > or < statement and shouldn't be
                   passed to Sasami */
		if (nextc == '>' || nextc == '<') {
		  input();
		  getAgentName();
		} else {
		  nextc = '\n';
		  if (script->text[0] != '\0') {
		    appAgentName--;
		    /* printf("from sasami 1"); */
		    pushEntryStack(SASAMI);
		    run(STRING_DEV, script->text, 0);
		    popEntryStack();
		    appAgentName++;
		  }
		  deleteScript(script);
		  return;
		}
	      } else {
		/* This must be something worth sending to Sasami */
		sa_input(keyin());
		/* Now run the EDEN script that Sasami's produced (if
                   there is one) */
		if (script->ready) {
		  if (script->text[0] != '\0') {
		    appAgentName--;
		    /* printf("from sasami 2"); */
		    pushEntryStack(SASAMI);
		    run(STRING_DEV, script->text, 0);
		    sa_script = script;
		    popEntryStack();
		    /* printf("from sasami 3"); */
		    appAgentName++;
		  }
		  resetScript(script);
		}
	      }
	    }

	    /* OK - finished with the input, so send an EOL to make
	       sure that the parser runs the last input line, and
	       exit. */

	    keyin();	/* read the null character */

	    sa_input('\n');	/* treat end-of-file as end-of-line */

	    if (script->text[0] != '\0') {
	      appAgentName--;
	      pushEntryStack(SASAMI);
	      run(STRING_DEV, script->text, 0);
	      popEntryStack();
	      /* printf("from sasami 4"); */
	      appAgentName++;
	    }
	    deleteScript(script);
	  } /* end if (strncmp(s, "%sasami", 7) == 0) */
#endif /* WANT_SASAMI */

#ifdef DISTRIB
	  /* LSD -------------------------------------------- */
	  else if (strncmp(s, "%lsd", 4) == 0) {
	    changeNotation(LSD);
	    for (nextc = peek(); nextc != '\0'; nextc = peek()) {
	      if (Inp_Dev->newline && (nextc == '%' || nextc == '>'
				       || nextc == '<')) {
		if (nextc == '>' || nextc == '<') {
		  input();
		  getAgentName();
		} else {
		  nextc = '\n';
		  return;
		}
	      } else {
		lsd_lex(keyin());
	      }
	    }
	    keyin();	/* read the null character */
	    lsd_lex('\n');	/* treat end-of-file as end-of-line */
	  } /* end if (strncmp(s, "%lsd", 4)... */
#endif /* DISTRIB */

	  /* This push and pop facility ("%+eden") appears be used
             only in Donald [Ash] */

	  /* Push entry -------------------------------------------- */
	  else if (s[1] == '+') {
	    /*  appAgentName=0; */
	    if ((strncmp(s + 2, "donald0", 7) == 0) ||
		(strncmp(s + 2, "donald", 6) == 0)) {	/* is DoNaLD */
	      pushEntryStack(DONALD);
	    } else if (strncmp(s + 2, "scout", 5) == 0) {	/* is SCOUT */
	      pushEntryStack(SCOUT);
	    } else if (strncmp(s + 2, "eden", 4) == 0) {	/* is EDEN */
	      pushEntryStack(EDEN);
#ifdef WANT_SASAMI
	    } else if (strncmp(s + 2, "sasami", 6) == 0) {	/* is Sasami */
	      pushEntryStack(SASAMI);
#endif /* WANT_SASAMI */
	    }
	  } /* end if (s[1] == '+') */


	  /* Pop entry -------------------------------------------- */
	  else if (s[1] == '-') {
	    if ((strncmp(s + 2, "donald0", 7) == 0)
		|| strncmp(s + 2, "donald", 6) == 0
		|| strncmp(s + 2, "scout", 5) == 0	/* is SCOUT */
#ifdef WANT_SASAMI
		|| strncmp(s + 2, "sasami", 6) == 0	/* is Sasami */
#endif
		|| strncmp(s + 2, "eden", 4) == 0) {	/* is EDEN */
	      popEntryStack();
	      /*  appAgentName=1; */
	    }
	  } /* end if (s[1] == '-') */

#endif /* not TTYEDEN */

	  /* Eden -------------------------------------------- */
	  else {
	    changeNotation(EDEN);
	  }

	  return;

	} else if (nextc == 0) {
	  /* EOF */
#ifdef TTYEDEN
	  /* Dummy if start to make the else's below work... [Ash] */
	  if (0) {}
#else
	  if ((strncmp(s, "%donald0", 8) == 0) ||
	      (strncmp(s, "%donald", 7) == 0)) {	/* is DoNaLD */
	    changeNotation(DONALD);
	  }
	  else if (strncmp(s, "%scout", 6) == 0) {	/* is SCOUT */
	    changeNotation(SCOUT);
	  }
#ifdef WANT_SASAMI
	  else if (strncmp(s, "%sasami", 7) == 0) {	/* is Sasami */
	    changeNotation(SASAMI);
	  }
#endif /* WANT_SASAMI */
#endif /* not TTYEDEN */
          else if (notationSwitch(s)) {
	    changeNotation(NEWOTHER);
	  } else {		/* is EDEN */
	    changeNotation(EDEN);
	  }
	  return;
	} /* end if nextc==0 */
    } /* end for ;; */
} /* end skip_percent_comment */
Beispiel #6
0
STATIC int
readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
{
	int c = firstc;
	char *out;
	int len;
	char line[EOFMARKLEN + 1];
	struct nodelist *bqlist;
	int quotef;
	int dblquote;
	int varnest;	/* levels of variables expansion */
	int arinest;	/* levels of arithmetic expansion */
	int parenlevel;	/* levels of parens in arithmetic */
	int oldstyle;
	char const *prevsyntax;	/* syntax before arithmetic */
	int synentry;
#if __GNUC__
	/* Avoid longjmp clobbering */
	(void) &out;
	(void) &quotef;
	(void) &dblquote;
	(void) &varnest;
	(void) &arinest;
	(void) &parenlevel;
	(void) &oldstyle;
	(void) &prevsyntax;
	(void) &syntax;
	(void) &synentry;
#endif

	startlinno = plinno;
	dblquote = 0;
	if (syntax == DQSYNTAX)
		dblquote = 1;
	quotef = 0;
	bqlist = NULL;
	varnest = 0;
	arinest = 0;
	parenlevel = 0;

	STARTSTACKSTR(out);
	loop: {	/* for each line, until end of word */
		CHECKEND();	/* set c to PEOF if at end of here document */
		for (;;) {	/* until end of line or end of word */
			CHECKSTRSPACE(3, out);	/* permit 3 calls to USTPUTC */

			synentry = syntax[c];

			switch(synentry) {
			case CNL:	/* '\n' */
				if (syntax == BASESYNTAX)
					goto endword;	/* exit outer loop */
				USTPUTC(c, out);
				plinno++;
				if (doprompt)
					setprompt(2);
				else
					setprompt(0);
				c = pgetc();
				goto loop;		/* continue outer loop */
			case CWORD:
				USTPUTC(c, out);
				break;
			case CCTL:
				if (eofmark == NULL || dblquote)
					USTPUTC(CTLESC, out);
				USTPUTC(c, out);
				break;
			case CBACK:	/* backslash */
				c = pgetc();
				if (c == PEOF) {
					USTPUTC('\\', out);
					pungetc();
				} else if (c == '\n') {
					if (doprompt)
						setprompt(2);
					else
						setprompt(0);
				} else {
					if (dblquote && c != '\\' &&
					    c != '`' && c != '$' &&
					    (c != '"' || eofmark != NULL))
						USTPUTC('\\', out);
					if (SQSYNTAX[c] == CCTL)
						USTPUTC(CTLESC, out);
					else if (eofmark == NULL)
						USTPUTC(CTLQUOTEMARK, out);
					USTPUTC(c, out);
					quotef++;
				}
				break;
			case CSQUOTE:
				if (eofmark == NULL)
					USTPUTC(CTLQUOTEMARK, out);
				syntax = SQSYNTAX;
				break;
			case CDQUOTE:
				if (eofmark == NULL)
					USTPUTC(CTLQUOTEMARK, out);
				syntax = DQSYNTAX;
				dblquote = 1;
				break;
			case CENDQUOTE:
				if (eofmark != NULL && arinest == 0 &&
				    varnest == 0) {
					USTPUTC(c, out);
				} else {
					if (arinest) {
						syntax = ARISYNTAX;
						dblquote = 0;
					} else if (eofmark == NULL) {
						syntax = BASESYNTAX;
						dblquote = 0;
					}
					quotef++;
				}
				break;
			case CVAR:	/* '$' */
				PARSESUB();		/* parse substitution */
				break;
			case CENDVAR:	/* '}' */
				if (varnest > 0) {
					varnest--;
					USTPUTC(CTLENDVAR, out);
				} else {
					USTPUTC(c, out);
				}
				break;
			case CLP:	/* '(' in arithmetic */
				parenlevel++;
				USTPUTC(c, out);
				break;
			case CRP:	/* ')' in arithmetic */
				if (parenlevel > 0) {
					USTPUTC(c, out);
					--parenlevel;
				} else {
					if (pgetc() == ')') {
						if (--arinest == 0) {
							USTPUTC(CTLENDARI, out);
							syntax = prevsyntax;
							if (syntax == DQSYNTAX)
								dblquote = 1;
							else
								dblquote = 0;
						} else
							USTPUTC(')', out);
					} else {
						/*
						 * unbalanced parens
						 *  (don't 2nd guess - no error)
						 */
						pungetc();
						USTPUTC(')', out);
					}
				}
				break;
			case CBQUOTE:	/* '`' */
				PARSEBACKQOLD();
				break;
			case CEOF:
				goto endword;		/* exit outer loop */
			default:
				if (varnest == 0)
					goto endword;	/* exit outer loop */
				USTPUTC(c, out);
			}
			c = pgetc_macro();
		}
	}
endword:
	if (syntax == ARISYNTAX)
		synerror("Missing '))'");
	if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
		synerror("Unterminated quoted string");
	if (varnest != 0) {
		startlinno = plinno;
		synerror("Missing '}'");
	}
	USTPUTC('\0', out);
	len = out - stackblock();
	out = stackblock();
	if (eofmark == NULL) {
		if ((c == '>' || c == '<')
		 && quotef == 0
		 && len <= 2
		 && (*out == '\0' || is_digit(*out))) {
			PARSEREDIR();
			return lasttoken = TREDIR;
		} else {
			pungetc();
		}
	}
	quoteflag = quotef;
	backquotelist = bqlist;
	grabstackblock(len);
	wordtext = out;
	return lasttoken = TWORD;
/* end of readtoken routine */



/*
 * Check to see whether we are at the end of the here document.  When this
 * is called, c is set to the first character of the next input line.  If
 * we are at the end of the here document, this routine sets the c to PEOF.
 */

checkend: {
	if (eofmark) {
		if (striptabs) {
			while (c == '\t')
				c = pgetc();
		}
		if (c == *eofmark) {
			if (pfgets(line, sizeof line) != NULL) {
				char *p, *q;

				p = line;
				for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
				if (*p == '\n' && *q == '\0') {
					c = PEOF;
					plinno++;
					needprompt = doprompt;
				} else {
					pushstring(line, strlen(line), NULL);
				}
			}
		}
	}
	goto checkend_return;
}


/*
 * Parse a redirection operator.  The variable "out" points to a string
 * specifying the fd to be redirected.  The variable "c" contains the
 * first character of the redirection operator.
 */

parseredir: {
	char fd = *out;
	union node *np;

	np = (union node *)stalloc(sizeof (struct nfile));
	if (c == '>') {
		np->nfile.fd = 1;
		c = pgetc();
		if (c == '>')
			np->type = NAPPEND;
		else if (c == '&')
			np->type = NTOFD;
		else if (c == '|')
			np->type = NCLOBBER;
		else {
			np->type = NTO;
			pungetc();
		}
	} else {	/* c == '<' */
		np->nfile.fd = 0;
		c = pgetc();
		if (c == '<') {
			if (sizeof (struct nfile) != sizeof (struct nhere)) {
				np = (union node *)stalloc(sizeof (struct nhere));
				np->nfile.fd = 0;
			}
			np->type = NHERE;
			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
			heredoc->here = np;
			if ((c = pgetc()) == '-') {
				heredoc->striptabs = 1;
			} else {
				heredoc->striptabs = 0;
				pungetc();
			}
		} else if (c == '&')
			np->type = NFROMFD;
		else if (c == '>')
			np->type = NFROMTO;
		else {
			np->type = NFROM;
			pungetc();
		}
	}
	if (fd != '\0')
		np->nfile.fd = digit_val(fd);
	redirnode = np;
	goto parseredir_return;
}


/*
 * Parse a substitution.  At this point, we have read the dollar sign
 * and nothing else.
 */

parsesub: {
	int subtype;
	int typeloc;
	int flags;
	char *p;
#ifndef GDB_HACK
	static const char types[] = "}-+?=";
#endif
       int bracketed_name = 0; /* used to handle ${[0-9]*} variables */

	c = pgetc();
	if (c != '(' && c != '{' && !is_name(c) && !is_special(c)) {
		USTPUTC('$', out);
		pungetc();
	} else if (c == '(') {	/* $(command) or $((arith)) */
		if (pgetc() == '(') {
			PARSEARITH();
		} else {
			pungetc();
			PARSEBACKQNEW();
		}
	} else {
		USTPUTC(CTLVAR, out);
		typeloc = out - stackblock();
		USTPUTC(VSNORMAL, out);
		subtype = VSNORMAL;
		if (c == '{') {
			bracketed_name = 1;
			c = pgetc();
			if (c == '#') {
				if ((c = pgetc()) == '}')
					c = '#';
				else
					subtype = VSLENGTH;
			}
			else
				subtype = 0;
		}
		if (is_name(c)) {
			do {
				STPUTC(c, out);
				c = pgetc();
			} while (is_in_name(c));
		} else if (is_digit(c)) {
			if (bracketed_name) {
				do {
					STPUTC(c, out);
					c = pgetc();
				} while (is_digit(c));
			} else {
				STPUTC(c, out);
				c = pgetc();
			}
		} else {
			if (! is_special(c))
badsub:				synerror("Bad substitution");
			USTPUTC(c, out);
			c = pgetc();
		}
		STPUTC('=', out);
		flags = 0;
		if (subtype == 0) {
			switch (c) {
			case ':':
				flags = VSNUL;
				c = pgetc();
				/*FALLTHROUGH*/
			default:
				p = strchr(types, c);
				if (p == NULL)
					goto badsub;
				subtype = p - types + VSNORMAL;
				break;
			case '%':
			case '#':
				{
					int cc = c;
					subtype = c == '#' ? VSTRIMLEFT :
							     VSTRIMRIGHT;
					c = pgetc();
					if (c == cc)
						subtype++;
					else
						pungetc();
					break;
				}
			}
		} else {
			pungetc();
		}
		if (subtype != VSLENGTH && (dblquote || arinest))
			flags |= VSQUOTE;
		*(stackblock() + typeloc) = subtype | flags;
		if (subtype != VSNORMAL)
			varnest++;
	}
	goto parsesub_return;
}


/*
 * Called to parse command substitutions.  Newstyle is set if the command
 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
 * list of commands (passed by reference), and savelen is the number of
 * characters on the top of the stack which must be preserved.
 */

parsebackq: {
	struct nodelist **nlpp;
	int savepbq;
	union node *n;
	char *volatile str;
	struct jmploc jmploc;
	struct jmploc *volatile savehandler;
	int savelen;
	int saveprompt;
#if __GNUC__
	/* Avoid longjmp clobbering */
	(void) &saveprompt;
#endif

	savepbq = parsebackquote;
	if (setjmp(jmploc.loc)) {
		if (str)
			ckfree(str);
		parsebackquote = 0;
		handler = savehandler;
		longjmp(handler->loc, 1);
	}
	INTOFF;
	str = NULL;
	savelen = out - stackblock();
	if (savelen > 0) {
		str = ckmalloc(savelen);
		memcpy(str, stackblock(), savelen);
	}
	savehandler = handler;
	handler = &jmploc;
	INTON;
        if (oldstyle) {
                /* We must read until the closing backquote, giving special
                   treatment to some slashes, and then push the string and
                   reread it as input, interpreting it normally.  */
                char *out;
                int c;
                int savelen;
                char *str;


                STARTSTACKSTR(out);
		for (;;) {
			if (needprompt) {
				setprompt(2);
				needprompt = 0;
			}
			switch (c = pgetc()) {
			case '`':
				goto done;

			case '\\':
                                if ((c = pgetc()) == '\n') {
					plinno++;
					if (doprompt)
						setprompt(2);
					else
						setprompt(0);
					/*
					 * If eating a newline, avoid putting
					 * the newline into the new character
					 * stream (via the STPUTC after the
					 * switch).
					 */
					continue;
				}
                                if (c != '\\' && c != '`' && c != '$'
                                    && (!dblquote || c != '"'))
                                        STPUTC('\\', out);
				break;

			case '\n':
				plinno++;
				needprompt = doprompt;
				break;

			case PEOF:
			        startlinno = plinno;
				synerror("EOF in backquote substitution");
 				break;

			default:
				break;
			}
			STPUTC(c, out);
                }
done:
                STPUTC('\0', out);
                savelen = out - stackblock();
                if (savelen > 0) {
                        str = ckmalloc(savelen);
                        memcpy(str, stackblock(), savelen);
			setinputstring(str, 1);
                }
        }
	nlpp = &bqlist;
	while (*nlpp)
		nlpp = &(*nlpp)->next;
	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
	(*nlpp)->next = NULL;
	parsebackquote = oldstyle;

	if (oldstyle) {
		saveprompt = doprompt;
		doprompt = 0;
	}

	n = list(0);

	if (oldstyle)
		doprompt = saveprompt;
	else {
		if (readtoken() != TRP)
			synexpect(TRP);
	}

	(*nlpp)->n = n;
        if (oldstyle) {
		/*
		 * Start reading from old file again, ignoring any pushed back
		 * tokens left from the backquote parsing
		 */
                popfile();
		tokpushback = 0;
	}
	while (stackblocksize() <= savelen)
		growstackblock();
	STARTSTACKSTR(out);
	if (str) {
		memcpy(out, str, savelen);
		STADJUST(savelen, out);
		INTOFF;
		ckfree(str);
		str = NULL;
		INTON;
	}
	parsebackquote = savepbq;
	handler = savehandler;
	if (arinest || dblquote)
		USTPUTC(CTLBACKQ | CTLQUOTE, out);
	else
		USTPUTC(CTLBACKQ, out);
	if (oldstyle)
		goto parsebackq_oldreturn;
	else
		goto parsebackq_newreturn;
}

/*
 * Parse an arithmetic expansion (indicate start of one and set state)
 */
parsearith: {

	if (++arinest == 1) {
		prevsyntax = syntax;
		syntax = ARISYNTAX;
		USTPUTC(CTLARI, out);
		if (dblquote)
			USTPUTC('"',out);
		else
			USTPUTC(' ',out);
	} else {
		/*
		 * we collapse embedded arithmetic expansion to
		 * parenthesis, which should be equivalent
		 */
		USTPUTC('(', out);
	}
	goto parsearith_return;
}

} /* end of readtoken */
Beispiel #7
0
STATIC int
xxreadtoken(void)
{
	int c;

	if (tokpushback) {
		tokpushback = 0;
		return lasttoken;
	}
	if (needprompt) {
		setprompt(2);
		needprompt = 0;
	}
	startlinno = plinno;
	for (;;) {	/* until token or start of word found */
		c = pgetc_macro();
		if (c == ' ' || c == '\t')
			continue;		/* quick check for white space first */
		switch (c) {
		case ' ': case '\t':
			continue;
		case '#':
			while ((c = pgetc()) != '\n' && c != PEOF);
			pungetc();
			continue;
		case '\\':
			if (pgetc() == '\n') {
				startlinno = ++plinno;
				if (doprompt)
					setprompt(2);
				else
					setprompt(0);
				continue;
			}
			pungetc();
			goto breakloop;
		case '\n':
			plinno++;
			needprompt = doprompt;
			RETURN(TNL);
		case PEOF:
			RETURN(TEOF);
		case '&':
			if (pgetc() == '&')
				RETURN(TAND);
			pungetc();
			RETURN(TBACKGND);
		case '|':
			if (pgetc() == '|')
				RETURN(TOR);
			pungetc();
			RETURN(TPIPE);
		case ';':
			if (pgetc() == ';')
				RETURN(TENDCASE);
			pungetc();
			RETURN(TSEMI);
		case '(':
			RETURN(TLP);
		case ')':
			RETURN(TRP);
		default:
			goto breakloop;
		}
	}
breakloop:
	return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
#undef RETURN
}