• merge printf from OpenBSD

• deactivate %a and %A since our libc doesn’t have it
• rewrite the mksh integration code to use shf instead of stdio, removing
  floating point support always in the process, as shf doesn’t support it
  ⇒ saves 11114 (6706 text, 168 data, 4240 bss) with dietlibc on Debian
• fix -Wall -Wextra -Wformat -Wstrict-aliasing=2 for gcc (Debian 4.4.4-7)
• fix these and -Wc++-compat for gcc version 4.6.0 20100711 (experimental)
  [trunk revision 162057] (Debian 20100711-1) except:
  – a few enum warnings that relate to eglibc’s {g,s}etrlimit() functions
    taking an enum instead of an int because they’re too stupid to adhere
    to POSIX interfaces they design by themselves
  – all “request for implicit conversion” involving a "void *" on one side
• tweak the manual page somewhat more
This commit is contained in:
tg 2010-07-17 22:09:40 +00:00
parent 1e113b416b
commit 7c91e018f4
13 changed files with 189 additions and 182 deletions

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.381 2010/07/13 13:12:28 tg Exp $
# $MirOS: src/bin/mksh/check.t,v 1.382 2010/07/17 22:09:30 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@ -25,7 +25,7 @@
# http://www.research.att.com/~gsf/public/ifs.sh
expected-stdout:
@(#)MIRBSD KSH R39 2010/07/13
@(#)MIRBSD KSH R39 2010/07/17
description:
Check version of shell.
stdin:

40
edit.c
View File

@ -25,7 +25,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.194 2010/07/04 18:52:52 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.195 2010/07/17 22:09:32 tg Exp $");
/*
* in later versions we might use libtermcap for this, but since external
@ -2258,13 +2258,13 @@ x_vt_hack(int c)
static char *
x_mapin(const char *cp, Area *ap)
{
char *new, *op;
char *news, *op;
/* for clang's static analyser, the nonnull attribute isn't enough */
mkssert(cp != NULL);
strdupx(new, cp, ap);
op = new;
strdupx(news, cp, ap);
op = news;
while (*cp) {
/* XXX -- should handle \^ escape? */
if (*cp == '^') {
@ -2281,7 +2281,7 @@ x_mapin(const char *cp, Area *ap)
}
*op = '\0';
return (new);
return (news);
}
static void
@ -3311,7 +3311,7 @@ static const unsigned char classify[128] = {
static char undocbuf[LINE];
static struct edstate *save_edstate(struct edstate *old);
static void restore_edstate(struct edstate *old, struct edstate *new);
static void restore_edstate(struct edstate *old, struct edstate *news);
static void free_edstate(struct edstate *old);
static struct edstate ebuf;
@ -4573,25 +4573,25 @@ restore_cbuf(void)
static struct edstate *
save_edstate(struct edstate *old)
{
struct edstate *new;
struct edstate *news;
new = alloc(sizeof(struct edstate), APERM);
new->cbuf = alloc(old->cbufsize, APERM);
memcpy(new->cbuf, old->cbuf, old->linelen);
new->cbufsize = old->cbufsize;
new->linelen = old->linelen;
new->cursor = old->cursor;
new->winleft = old->winleft;
return (new);
news = alloc(sizeof(struct edstate), APERM);
news->cbuf = alloc(old->cbufsize, APERM);
memcpy(news->cbuf, old->cbuf, old->linelen);
news->cbufsize = old->cbufsize;
news->linelen = old->linelen;
news->cursor = old->cursor;
news->winleft = old->winleft;
return (news);
}
static void
restore_edstate(struct edstate *new, struct edstate *old)
restore_edstate(struct edstate *news, struct edstate *old)
{
memcpy(new->cbuf, old->cbuf, old->linelen);
new->linelen = old->linelen;
new->cursor = old->cursor;
new->winleft = old->winleft;
memcpy(news->cbuf, old->cbuf, old->linelen);
news->linelen = old->linelen;
news->cursor = old->cursor;
news->winleft = old->winleft;
free_edstate(old);
}

122
emacsfn.h
View File

@ -1,86 +1,86 @@
#if defined(EMACSFN_DEFNS)
__RCSID("$MirOS: src/bin/mksh/emacsfn.h,v 1.4 2009/09/23 18:04:55 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/emacsfn.h,v 1.5 2010/07/17 22:09:33 tg Exp $");
#define FN(cname,sname,flags) static int x_##cname(int);
#elif defined(EMACSFN_ENUMS)
#define FN(cname,sname,flags) XFUNC_##cname,
#define F0(cname,sname,flags) XFUNC_##cname = 0,
#elif defined(EMACSFN_ITEMS)
#define FN(cname,sname,flags) { x_##cname, #sname, flags },
#define FN(cname,sname,flags) { x_##cname, sname, flags },
#endif
#ifndef F0
#define F0 FN
#endif
F0(abort, abort, 0)
FN(beg_hist, beginning-of-history, 0)
FN(cls, clear-screen, 0)
FN(comment, comment, 0)
FN(comp_comm, complete-command, 0)
FN(comp_file, complete-file, 0)
FN(comp_list, complete-list, 0)
FN(complete, complete, 0)
FN(del_back, delete-char-backward, XF_ARG)
FN(del_bword, delete-word-backward, XF_ARG)
FN(del_char, delete-char-forward, XF_ARG)
FN(del_fword, delete-word-forward, XF_ARG)
FN(del_line, kill-line, 0)
FN(draw_line, redraw, 0)
F0(abort, "abort", 0)
FN(beg_hist, "beginning-of-history", 0)
FN(cls, "clear-screen", 0)
FN(comment, "comment", 0)
FN(comp_comm, "complete-command", 0)
FN(comp_file, "complete-file", 0)
FN(comp_list, "complete-list", 0)
FN(complete, "complete", 0)
FN(del_back, "delete-char-backward", XF_ARG)
FN(del_bword, "delete-word-backward", XF_ARG)
FN(del_char, "delete-char-forward", XF_ARG)
FN(del_fword, "delete-word-forward", XF_ARG)
FN(del_line, "kill-line", 0)
FN(draw_line, "redraw", 0)
#ifndef MKSH_SMALL
FN(edit_line, edit-line, XF_ARG)
FN(edit_line, "edit-line", XF_ARG)
#endif
FN(end_hist, end-of-history, 0)
FN(end_of_text, eot, 0)
FN(enumerate, list, 0)
FN(eot_del, eot-or-delete, XF_ARG)
FN(error, error, 0)
FN(expand, expand-file, 0)
FN(end_hist, "end-of-history", 0)
FN(end_of_text, "eot", 0)
FN(enumerate, "list", 0)
FN(eot_del, "eot-or-delete", XF_ARG)
FN(error, "error", 0)
FN(expand, "expand-file", 0)
#ifndef MKSH_SMALL
FN(fold_capitalise, capitalize-word, XF_ARG)
FN(fold_lower, downcase-word, XF_ARG)
FN(fold_upper, upcase-word, XF_ARG)
FN(fold_capitalise, "capitalize-word", XF_ARG)
FN(fold_lower, "downcase-word", XF_ARG)
FN(fold_upper, "upcase-word", XF_ARG)
#endif
FN(goto_hist, goto-history, XF_ARG)
FN(goto_hist, "goto-history", XF_ARG)
#ifndef MKSH_SMALL
FN(ins_string, macro-string, XF_NOBIND)
FN(ins_string, "macro-string", XF_NOBIND)
#endif
FN(insert, auto-insert, XF_ARG)
FN(kill, kill-to-eol, XF_ARG)
FN(kill_region, kill-region, 0)
FN(list_comm, list-command, 0)
FN(list_file, list-file, 0)
FN(literal, quote, 0)
FN(meta1, prefix-1, XF_PREFIX)
FN(meta2, prefix-2, XF_PREFIX)
FN(meta_yank, yank-pop, 0)
FN(mv_back, backward-char, XF_ARG)
FN(mv_begin, beginning-of-line, 0)
FN(mv_bword, backward-word, XF_ARG)
FN(mv_end, end-of-line, 0)
FN(mv_forw, forward-char, XF_ARG)
FN(mv_fword, forward-word, XF_ARG)
FN(newline, newline, 0)
FN(next_com, down-history, XF_ARG)
FN(nl_next_com, newline-and-next, 0)
FN(noop, no-op, 0)
FN(prev_com, up-history, XF_ARG)
FN(prev_histword, prev-hist-word, XF_ARG)
FN(search_char_back, search-character-backward, XF_ARG)
FN(search_char_forw, search-character-forward, XF_ARG)
FN(search_hist, search-history, 0)
FN(insert, "auto-insert", XF_ARG)
FN(kill, "kill-to-eol", XF_ARG)
FN(kill_region, "kill-region", 0)
FN(list_comm, "list-command", 0)
FN(list_file, "list-file", 0)
FN(literal, "quote", 0)
FN(meta1, "prefix-1", XF_PREFIX)
FN(meta2, "prefix-2", XF_PREFIX)
FN(meta_yank, "yank-pop", 0)
FN(mv_back, "backward-char", XF_ARG)
FN(mv_begin, "beginning-of-line", 0)
FN(mv_bword, "backward-word", XF_ARG)
FN(mv_end, "end-of-line", 0)
FN(mv_forw, "forward-char", XF_ARG)
FN(mv_fword, "forward-word", XF_ARG)
FN(newline, "newline", 0)
FN(next_com, "down-history", XF_ARG)
FN(nl_next_com, "newline-and-next", 0)
FN(noop, "no-op", 0)
FN(prev_com, "up-history", XF_ARG)
FN(prev_histword, "prev-hist-word", XF_ARG)
FN(search_char_back, "search-character-backward", XF_ARG)
FN(search_char_forw, "search-character-forward", XF_ARG)
FN(search_hist, "search-history", 0)
#ifndef MKSH_SMALL
FN(search_hist_dn, search-history-down, 0)
FN(search_hist_up, search-history-up, 0)
FN(search_hist_dn, "search-history-down", 0)
FN(search_hist_up, "search-history-up", 0)
#endif
FN(set_arg, set-arg, XF_NOBIND)
FN(set_mark, set-mark-command, 0)
FN(transpose, transpose-chars, 0)
FN(version, version, 0)
FN(set_arg, "set-arg", XF_NOBIND)
FN(set_mark, "set-mark-command", 0)
FN(transpose, "transpose-chars", 0)
FN(version, "version", 0)
#ifndef MKSH_SMALL
FN(vt_hack, vt100-hack, XF_ARG)
FN(vt_hack, "vt100-hack", XF_ARG)
#endif
FN(xchg_point_mark, exchange-point-and-mark, 0)
FN(yank, yank, 0)
FN(xchg_point_mark, "exchange-point-and-mark", 0)
FN(yank, "yank", 0)
#undef FN
#undef F0

18
eval.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.89 2010/05/16 19:17:42 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.90 2010/07/17 22:09:33 tg Exp $");
/*
* string expansion
@ -1559,19 +1559,19 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
count++;
else if ((*p == CBRACE && --count == 0) ||
(*p == ',' && count == 1)) {
char *new;
char *news;
int l1, l2, l3;
l1 = brace_start - start;
l2 = (p - 1) - field_start;
l3 = end - brace_end;
new = alloc(l1 + l2 + l3 + 1, ATEMP);
memcpy(new, start, l1);
memcpy(new + l1, field_start, l2);
memcpy(new + l1 + l2, brace_end, l3);
new[l1 + l2 + l3] = '\0';
alt_expand(wp, new, new + l1,
new + l1 + l2 + l3, fdo);
news = alloc(l1 + l2 + l3 + 1, ATEMP);
memcpy(news, start, l1);
memcpy(news + l1, field_start, l2);
memcpy(news + l1 + l2, brace_end, l3);
news[l1 + l2 + l3] = '\0';
alt_expand(wp, news, news + l1,
news + l1 + l2 + l3, fdo);
field_start = p + 1;
}
}

21
exec.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.74 2010/04/08 13:21:05 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.75 2010/07/17 22:09:34 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
@ -35,7 +35,7 @@ static int call_builtin(struct tbl *, const char **);
static int iosetup(struct ioword *, struct tbl *);
static int herein(const char *, int);
static const char *do_selectargs(const char **, bool);
static int dbteste_isa(Test_env *, Test_meta);
static Test_op dbteste_isa(Test_env *, Test_meta);
static const char *dbteste_getopnd(Test_env *, Test_op, bool);
static void dbteste_error(Test_env *, int, const char *);
@ -1446,19 +1446,20 @@ pr_list(char * const *ap)
* [[ ... ]] evaluation routines
*/
/* Test if the current token is a whatever. Accepts the current token if
/*
* Test if the current token is a whatever. Accepts the current token if
* it is. Returns 0 if it is not, non-zero if it is (in the case of
* TM_UNOP and TM_BINOP, the returned value is a Test_op).
*/
static int
static Test_op
dbteste_isa(Test_env *te, Test_meta meta)
{
int ret = 0;
Test_op ret = TO_NONOP;
int uqword;
const char *p;
if (!*te->pos.wp)
return (meta == TM_END);
return (meta == TM_END ? TO_NONNULL : TO_NONOP);
/* unquoted word? */
for (p = *te->pos.wp; *p == CHAR; p += 2)
@ -1476,13 +1477,13 @@ dbteste_isa(Test_env *te, Test_meta meta)
ret = test_isop(meta, buf);
}
} else if (meta == TM_END)
ret = 0;
ret = TO_NONOP;
else
ret = uqword &&
strcmp(*te->pos.wp, dbtest_tokens[(int) meta]) == 0;
ret = (uqword && !strcmp(*te->pos.wp,
dbtest_tokens[(int)meta])) ? TO_NONNULL : TO_NONOP;
/* Accept the token? */
if (ret)
if (ret != TO_NONOP)
te->pos.wp++;
return (ret);

32
funcs.c
View File

@ -25,7 +25,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.155 2010/04/27 21:39:08 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.156 2010/07/17 22:09:34 tg Exp $");
#if HAVE_KILLPG
/*
@ -168,7 +168,7 @@ static int test_oexpr(Test_env *, bool);
static int test_aexpr(Test_env *, bool);
static int test_nexpr(Test_env *, bool);
static int test_primary(Test_env *, bool);
static int ptest_isa(Test_env *, Test_meta);
static Test_op ptest_isa(Test_env *, Test_meta);
static const char *ptest_getopnd(Test_env *, Test_op, bool);
static void ptest_error(Test_env *, int, const char *);
static char *kill_fmt_entry(char *, int, int, const void *);
@ -336,7 +336,7 @@ c_cd(const char **wp)
bool printpath = false; /* print where we cd'd? */
struct tbl *pwd_s, *oldpwd_s;
XString xs;
char *dir, *allocd = NULL, *try, *pwd, *cdpath;
char *dir, *allocd = NULL, *tryp, *pwd, *cdpath;
while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != -1)
switch (optc) {
@ -421,10 +421,10 @@ c_cd(const char **wp)
do {
cdnode = make_path(current_wd, dir, &cdpath, &xs, &phys_path);
if (physical)
rv = chdir(try = Xstring(xs, xp) + phys_path);
rv = chdir(tryp = Xstring(xs, xp) + phys_path);
else {
simplify_path(Xstring(xs, xp));
rv = chdir(try = Xstring(xs, xp));
rv = chdir(tryp = Xstring(xs, xp));
}
} while (rv < 0 && cdpath != NULL);
@ -432,7 +432,7 @@ c_cd(const char **wp)
if (cdnode)
bi_errorf("%s: bad directory", dir);
else
bi_errorf("%s - %s", try, strerror(errno));
bi_errorf("%s - %s", tryp, strerror(errno));
afree(allocd, ATEMP);
return (1);
}
@ -2633,11 +2633,11 @@ c_mknod(const char **wp)
goto c_mknod_err;
}
dv = makedev(majnum, minnum);
if ((unsigned long)major(dv) != majnum) {
if ((unsigned long)(major(dv)) != majnum) {
bi_errorf("device major too large: %lu", majnum);
goto c_mknod_err;
}
if ((unsigned long)minor(dv) != minnum) {
if ((unsigned long)(minor(dv)) != minnum) {
bi_errorf("device minor too large: %lu", minnum);
goto c_mknod_err;
}
@ -3048,31 +3048,33 @@ test_primary(Test_env *te, bool do_eval)
* Plain test (test and [ .. ]) specific routines.
*/
/* Test if the current token is a whatever. Accepts the current token if
/*
* Test if the current token is a whatever. Accepts the current token if
* it is. Returns 0 if it is not, non-zero if it is (in the case of
* TM_UNOP and TM_BINOP, the returned value is a Test_op).
*/
static int
static Test_op
ptest_isa(Test_env *te, Test_meta meta)
{
/* Order important - indexed by Test_meta values */
static const char *const tokens[] = {
"-o", "-a", "!", "(", ")"
};
int rv;
Test_op rv;
if (te->pos.wp >= te->wp_end)
return (meta == TM_END);
return (meta == TM_END ? TO_NONNULL : TO_NONOP);
if (meta == TM_UNOP || meta == TM_BINOP)
rv = test_isop(meta, *te->pos.wp);
else if (meta == TM_END)
rv = 0;
rv = TO_NONOP;
else
rv = strcmp(*te->pos.wp, tokens[(int) meta]) == 0;
rv = !strcmp(*te->pos.wp, tokens[(int)meta]) ?
TO_NONNULL : TO_NONOP;
/* Accept the token? */
if (rv)
if (rv != TO_NONOP)
te->pos.wp++;
return (rv);

View File

@ -26,7 +26,7 @@
#include <sys/file.h>
#endif
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.96 2010/07/04 17:45:14 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.97 2010/07/17 22:09:35 tg Exp $");
/*-
* MirOS: This is the default mapping type, and need not be specified.
@ -956,7 +956,7 @@ writehistfile(int lno, char *cmd)
{
int sizenow;
unsigned char *base;
unsigned char *new;
unsigned char *news;
int bytes;
unsigned char hdr[5];
@ -973,13 +973,13 @@ writehistfile(int lno, char *cmd)
MAP_FILE | MAP_PRIVATE, histfd, (off_t)0);
if (base == (unsigned char *)MAP_FAILED)
goto bad;
new = base + hsize;
if (*new != COMMAND) {
news = base + hsize;
if (*news != COMMAND) {
munmap((caddr_t)base, sizenow);
goto bad;
}
hist_source->line--;
histload(hist_source, new, bytes);
histload(hist_source, news, bytes);
hist_source->line++;
lno = hist_source->line;
munmap((caddr_t)base, sizenow);

12
lex.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.115 2010/07/04 18:29:40 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.116 2010/07/17 22:09:36 tg Exp $");
/*
* states while lexing word
@ -1748,12 +1748,12 @@ getsc_bn(void)
static Lex_state *
push_state_(State_info *si, Lex_state *old_end)
{
Lex_state *new = alloc(STATE_BSIZE * sizeof(Lex_state), ATEMP);
Lex_state *news = alloc(STATE_BSIZE * sizeof(Lex_state), ATEMP);
new[0].ls_info.base = old_end;
si->base = &new[0];
si->end = &new[STATE_BSIZE];
return (&new[1]);
news[0].ls_info.base = old_end;
si->base = &news[0];
si->end = &news[STATE_BSIZE];
return (&news[1]);
}
static Lex_state *

8
misc.c
View File

@ -29,7 +29,7 @@
#include <grp.h>
#endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.140 2010/07/13 13:07:56 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.141 2010/07/17 22:09:36 tg Exp $");
unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */
@ -695,10 +695,10 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
static const unsigned char *
cclass(const unsigned char *p, int sub)
{
int c, d, not, found = 0;
int c, d, notp, found = 0;
const unsigned char *orig_p = p;
if ((not = (ISMAGIC(*p) && *++p == NOT)))
if ((notp = (ISMAGIC(*p) && *++p == NOT)))
p++;
do {
c = *p++;
@ -732,7 +732,7 @@ cclass(const unsigned char *p, int sub)
found = 1;
} while (!(ISMAGIC(p[0]) && p[1] == ']'));
return ((found != not) ? p+2 : NULL);
return ((found != notp) ? p+2 : NULL);
}
/* Look for next ) or | (if match_sep) in *(foo|bar) pattern */

10
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.231 2010/07/17 20:21:18 tg Exp $
.\" $MirOS: src/bin/mksh/mksh.1,v 1.232 2010/07/17 22:09:37 tg Exp $
.\" $OpenBSD: ksh.1,v 1.136 2010/07/15 20:04:35 schwarze Exp $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
@ -3509,14 +3509,14 @@ option suppresses the trailing newline.
.Pp
.It Ic printf Ar format Op Ar arguments ...
Formatted output.
The same as the utility
Approximately the same as the utility
.Xr printf 1 ,
except that it may use the same
except that it uses the same
.Sx Backslash expansion
code as the rest of
and I/O code as the rest of
.Nm mksh .
This is not normally part of
.Nm mksh ,
.Nm mksh ;
however, distributors may have added this as builtin as a speed hack.
.Pp
.It Ic pwd Op Fl LP

25
sh.h
View File

@ -150,9 +150,9 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.397 2010/07/13 13:12:32 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.398 2010/07/17 22:09:38 tg Exp $");
#endif
#define MKSH_VERSION "R39 2010/07/13"
#define MKSH_VERSION "R39 2010/07/17"
#ifndef MKSH_INCLUDES_ONLY
@ -548,7 +548,7 @@ extern struct env {
* some kind of global shell state, for change_random() mostly
*/
EXTERN struct {
EXTERN struct mksh_kshstate_v {
/* for change_random */
struct timeval cr_tv; /* timestamp */
const void *cr_dp; /* argument address */
@ -561,7 +561,7 @@ EXTERN struct {
struct env env_; /* top-level parsing & execution env. */
uint8_t shell_flags_[FNFLAGS];
} kshstate_v;
EXTERN struct {
EXTERN struct mksh_kshstate_f {
const char *kshname_; /* $0 */
pid_t kshpid_; /* $$, shell PID */
pid_t kshpgrp_; /* process group of shell */
@ -1666,7 +1666,9 @@ enum Test_op {
TO_FILRD, TO_FILGZ, TO_FILTT, TO_FILSETU, TO_FILWR, TO_FILEX,
/* binary operators */
TO_STEQL, TO_STNEQ, TO_STLT, TO_STGT, TO_INTEQ, TO_INTNE, TO_INTGT,
TO_INTGE, TO_INTLT, TO_INTLE, TO_FILEQ, TO_FILNT, TO_FILOT
TO_INTGE, TO_INTLT, TO_INTLE, TO_FILEQ, TO_FILNT, TO_FILOT,
/* not an operator */
TO_NONNULL /* !TO_NONOP */
};
typedef enum Test_op Test_op;
@ -1686,19 +1688,18 @@ typedef enum Test_meta Test_meta;
#define TEF_ERROR BIT(0) /* set if we've hit an error */
#define TEF_DBRACKET BIT(1) /* set if [[ .. ]] test */
typedef struct test_env Test_env;
struct test_env {
typedef struct test_env {
union {
const char **wp;/* used by ptest_* */
XPtrV *av; /* used by dbtestp_* */
} pos;
const char **wp_end; /* used by ptest_* */
int (*isa)(Test_env *, Test_meta);
const char *(*getopnd) (Test_env *, Test_op, bool);
int (*eval)(Test_env *, Test_op, const char *, const char *, bool);
void (*error)(Test_env *, int, const char *);
Test_op (*isa)(struct test_env *, Test_meta);
const char *(*getopnd) (struct test_env *, Test_op, bool);
int (*eval)(struct test_env *, Test_op, const char *, const char *, bool);
void (*error)(struct test_env *, int, const char *);
int flags; /* TEF_* */
};
} Test_env;
extern const char *const dbtest_tokens[];

29
syn.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.48 2009/12/12 22:27:10 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.49 2010/07/17 22:09:39 tg Exp $");
struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */
@ -50,7 +50,7 @@ static void nesting_push(struct nesting_state *, int);
static void nesting_pop(struct nesting_state *);
static int assign_command(char *);
static int inalias(struct source *);
static int dbtestp_isa(Test_env *, Test_meta);
static Test_op dbtestp_isa(Test_env *, Test_meta);
static const char *dbtestp_getopnd(Test_env *, Test_op, bool);
static int dbtestp_eval(Test_env *, Test_op, const char *,
const char *, bool);
@ -917,42 +917,45 @@ const char db_close[] = { CHAR, ']', CHAR, ']', EOS };
const char db_lthan[] = { CHAR, '<', EOS };
const char db_gthan[] = { CHAR, '>', EOS };
/* Test if the current token is a whatever. Accepts the current token if
/*
* Test if the current token is a whatever. Accepts the current token if
* it is. Returns 0 if it is not, non-zero if it is (in the case of
* TM_UNOP and TM_BINOP, the returned value is a Test_op).
*/
static int
static Test_op
dbtestp_isa(Test_env *te, Test_meta meta)
{
int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN));
int uqword;
char *save = NULL;
int ret = 0;
Test_op ret = TO_NONOP;
/* unquoted word? */
uqword = c == LWORD && *ident;
if (meta == TM_OR)
ret = c == LOGOR;
ret = c == LOGOR ? TO_NONNULL : TO_NONOP;
else if (meta == TM_AND)
ret = c == LOGAND;
ret = c == LOGAND ? TO_NONNULL : TO_NONOP;
else if (meta == TM_NOT)
ret = uqword && strcmp(yylval.cp, dbtest_tokens[(int) TM_NOT]) == 0;
ret = (uqword && !strcmp(yylval.cp,
dbtest_tokens[(int)TM_NOT])) ? TO_NONNULL : TO_NONOP;
else if (meta == TM_OPAREN)
ret = c == '(' /*)*/;
ret = c == '(' /*)*/ ? TO_NONNULL : TO_NONOP;
else if (meta == TM_CPAREN)
ret = c == /*(*/ ')';
ret = c == /*(*/ ')' ? TO_NONNULL : TO_NONOP;
else if (meta == TM_UNOP || meta == TM_BINOP) {
if (meta == TM_BINOP && c == REDIR &&
(yylval.iop->flag == IOREAD || yylval.iop->flag == IOWRITE)) {
ret = 1;
ret = TO_NONNULL;
save = wdcopy(yylval.iop->flag == IOREAD ?
db_lthan : db_gthan, ATEMP);
} else if (uqword && (ret = test_isop(meta, ident)))
save = yylval.cp;
} else /* meta == TM_END */
ret = uqword && strcmp(yylval.cp, db_close) == 0;
if (ret) {
ret = (uqword && !strcmp(yylval.cp,
db_close)) ? TO_NONNULL : TO_NONOP;
if (ret != TO_NONOP) {
ACCEPT;
if (meta < NELEM(dbtest_tokens))
save = wdcopy(dbtest_tokens[(int)meta], ATEMP);

40
var.c
View File

@ -26,7 +26,7 @@
#include <sys/sysctl.h>
#endif
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.107 2010/07/11 11:17:33 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.108 2010/07/17 22:09:40 tg Exp $");
/*
* Variables
@ -40,7 +40,7 @@ __RCSID("$MirOS: src/bin/mksh/var.c,v 1.107 2010/07/11 11:17:33 tg Exp $");
static struct tbl vtemp;
static struct table specials;
static char *formatstr(struct tbl *, const char *);
static void export(struct tbl *, const char *);
static void exportprep(struct tbl *, const char *);
static int special(const char *);
static void unspecial(const char *);
static void getspec(struct tbl *);
@ -426,7 +426,7 @@ setstr(struct tbl *vq, const char *s, int error_ok)
if (s && (vq->flag & (UCASEV_AL|LCASEV|LJUST|RJUST)))
s = salloc = formatstr(vq, s);
if ((vq->flag&EXPORT))
export(vq, s);
exportprep(vq, s);
else {
strdupx(vq->val.s, s, vq->areap);
vq->flag |= ALLOC;
@ -645,7 +645,7 @@ formatstr(struct tbl *vp, const char *s)
* make vp->val.s be "name=value" for quick exporting.
*/
static void
export(struct tbl *vp, const char *val)
exportprep(struct tbl *vp, const char *val)
{
char *xp;
char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
@ -837,7 +837,7 @@ typeset(const char *var, Tflag set, Tflag clr, int field, int base)
/* only x[0] is ever exported, so use vpbase */
if ((vpbase->flag&EXPORT) && !(vpbase->flag&INTEGER) &&
vpbase->type == 0)
export(vpbase, (vpbase->flag&ISSET) ? vpbase->val.s : null);
exportprep(vpbase, (vpbase->flag&ISSET) ? vpbase->val.s : null);
return (vp);
}
@ -1288,7 +1288,7 @@ unsetspec(struct tbl *vp)
static struct tbl *
arraysearch(struct tbl *vp, uint32_t val)
{
struct tbl *prev, *curr, *new;
struct tbl *prev, *curr, *news;
size_t len;
vp->flag = (vp->flag | (ARRAY|DEFINED)) & ~ASSOC;
@ -1304,25 +1304,25 @@ arraysearch(struct tbl *vp, uint32_t val)
if (curr && curr->ua.index == val) {
if (curr->flag&ISSET)
return (curr);
new = curr;
news = curr;
} else
new = NULL;
news = NULL;
len = strlen(vp->name) + 1;
if (!new) {
new = alloc(offsetof(struct tbl, name[0]) + len, vp->areap);
memcpy(new->name, vp->name, len);
if (!news) {
news = alloc(offsetof(struct tbl, name[0]) + len, vp->areap);
memcpy(news->name, vp->name, len);
}
new->flag = (vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL)) | AINDEX;
new->type = vp->type;
new->areap = vp->areap;
new->u2.field = vp->u2.field;
new->ua.index = val;
news->flag = (vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL)) | AINDEX;
news->type = vp->type;
news->areap = vp->areap;
news->u2.field = vp->u2.field;
news->ua.index = val;
if (curr != new) { /* not reusing old array entry */
prev->u.array = new;
new->u.array = curr;
if (curr != news) { /* not reusing old array entry */
prev->u.array = news;
news->u.array = curr;
}
return (new);
return (news);
}
/* Return the length of an array reference (eg, [1+2]) - cp is assumed