struct alias *ap; /* if push was associated with an alias */
#endif
char *string; /* remember the string since it may change */
+
+ /* Remember last two characters for pungetc. */
+ int lastc[2];
+
+ /* Number of outstanding calls to pungetc. */
+ int unget;
};
struct parsefile {
char *buf; /* input buffer */
struct strpush *strpush; /* for pushing strings at this level */
struct strpush basestrpush; /* so pushing one is fast */
+
+ /* Remember last two characters for pungetc. */
+ int lastc[2];
+
+ /* Number of outstanding calls to pungetc. */
+ int unget;
};
static struct parsefile basepf; /* top level input file */
g_parsefile->strpush = sp;
sp->prev_string = g_parsefile->next_to_pgetc;
sp->prev_left_in_line = g_parsefile->left_in_line;
+ sp->unget = g_parsefile->unget;
+ memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
#if ENABLE_ASH_ALIAS
sp->ap = ap;
if (ap) {
#endif
g_parsefile->next_to_pgetc = s;
g_parsefile->left_in_line = len;
+ g_parsefile->unget = 0;
INT_ON;
}
#endif
g_parsefile->next_to_pgetc = sp->prev_string;
g_parsefile->left_in_line = sp->prev_left_in_line;
+ g_parsefile->unget = sp->unget;
+ memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
g_parsefile->strpush = sp->prev;
if (sp != &(g_parsefile->basestrpush))
free(sp);
*/
//#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
#define pgetc_debug(...) ((void)0)
+static int pgetc(void);
static int
preadbuffer(void)
{
char *q;
int more;
- while (g_parsefile->strpush) {
+ if (g_parsefile->strpush) {
#if ENABLE_ASH_ALIAS
if (g_parsefile->left_in_line == -1
&& g_parsefile->strpush->ap
}
#endif
popstring();
- /* try "pgetc" now: */
- pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
- g_parsefile->left_in_line,
- g_parsefile->next_to_pgetc,
- g_parsefile->next_to_pgetc);
- if (--g_parsefile->left_in_line >= 0)
- return (unsigned char)(*g_parsefile->next_to_pgetc++);
+ return pgetc();
}
/* on both branches above g_parsefile->left_in_line < 0.
* "pgetc" needs refilling.
return (unsigned char)*g_parsefile->next_to_pgetc++;
}
-#define pgetc_as_macro() \
- (--g_parsefile->left_in_line >= 0 \
- ? (unsigned char)*g_parsefile->next_to_pgetc++ \
- : preadbuffer() \
- )
-
static int
pgetc(void)
{
- pgetc_debug("pgetc_fast at %d:%p'%s'",
+ int c;
+
+ pgetc_debug("pgetc at %d:%p'%s'",
g_parsefile->left_in_line,
g_parsefile->next_to_pgetc,
g_parsefile->next_to_pgetc);
- return pgetc_as_macro();
-}
+ if (g_parsefile->unget)
+ return g_parsefile->lastc[--g_parsefile->unget];
-#if ENABLE_ASH_OPTIMIZE_FOR_SIZE
-# define pgetc_fast() pgetc()
-#else
-# define pgetc_fast() pgetc_as_macro()
-#endif
+ if (--g_parsefile->left_in_line >= 0)
+ c = (signed char)*g_parsefile->next_to_pgetc++;
+ else
+ c = preadbuffer();
+
+ g_parsefile->lastc[1] = g_parsefile->lastc[0];
+ g_parsefile->lastc[0] = c;
+
+ return c;
+}
#if ENABLE_ASH_ALIAS
static int
{
int c;
do {
- pgetc_debug("pgetc_fast at %d:%p'%s'",
+ pgetc_debug("pgetc at %d:%p'%s'",
g_parsefile->left_in_line,
g_parsefile->next_to_pgetc,
g_parsefile->next_to_pgetc);
- c = pgetc_fast();
+ c = pgetc();
} while (c == PEOA);
return c;
}
}
/*
- * Undo the last call to pgetc. Only one character may be pushed back.
+ * Undo a call to pgetc. Only two characters may be pushed back.
* PEOF may be pushed back.
*/
static void
pungetc(void)
{
- g_parsefile->left_in_line++;
- g_parsefile->next_to_pgetc--;
- pgetc_debug("pushed back to %d:%p'%s'",
- g_parsefile->left_in_line,
- g_parsefile->next_to_pgetc,
- g_parsefile->next_to_pgetc);
+ g_parsefile->unget++;
}
/*
pf->pf_fd = -1;
/*pf->strpush = NULL; - ckzalloc did it */
/*pf->basestrpush.prev = NULL;*/
+ /*pf->unget = 0;*/
g_parsefile = pf;
}
IF_ASH_ALIAS(if (c != PEOA))
USTPUTC(c, out);
}
- c = pgetc_fast();
+ c = pgetc();
} /* for (;;) */
endword:
setprompt_if(needprompt, 2);
startlinno = g_parsefile->linno;
for (;;) { /* until token or start of word found */
- c = pgetc_fast();
+ c = pgetc();
if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
continue;
setprompt_if(needprompt, 2);
startlinno = g_parsefile->linno;
for (;;) { /* until token or start of word found */
- c = pgetc_fast();
+ c = pgetc();
switch (c) {
case ' ': case '\t':
IF_ASH_ALIAS(case PEOA:)