• more comment and int→bool cleanup, add and improve some comments

• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment
  variables if setlocale/nl_langinfo(CODESET) doesn’t suffice
• add the ability to call any builtin (some don't make sense or wouldn't
  work) directly by analysing argv[0]
• for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment
  variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set
• when called as builtin, echo behaves POSIXish
• add domainname as alias for true on MirBSD only, to be able to link it
• sync mksh Makefiles with Build.sh output
• adjust manpage wrt release plans
• link some things to mksh now that we have callable builtins:
  bin/echo bin/kill bin/pwd bin/sleep (exact matches)
  bin/test bin/[ (were scripts before)
  bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now)
• drop linked utilities and, except for echo and kill, their manpages
• adjust instbin and link a few more there as well
This commit is contained in:
tg
2011-02-11 01:18:23 +00:00
parent 81b80af47a
commit a796512040
10 changed files with 425 additions and 232 deletions

129
misc.c
View File

@ -29,9 +29,10 @@
#include <grp.h>
#endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.150 2011/01/21 21:04:45 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.151 2011/02/11 01:18:19 tg Exp $");
unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */
/* type bits for unsigned char */
unsigned char chtypes[UCHAR_MAX + 1];
static int do_gmatch(const unsigned char *, const unsigned char *,
const unsigned char *, const unsigned char *);
@ -62,7 +63,8 @@ setctypes(const char *s, int t)
if (t & C_IFS) {
for (i = 0; i < UCHAR_MAX + 1; i++)
chtypes[i] &= ~C_IFS;
chtypes[0] |= C_IFS; /* include \0 in C_IFS */
/* include \0 in C_IFS */
chtypes[0] |= C_IFS;
}
while (*s != 0)
chtypes[(unsigned char)*s++] |= t;
@ -79,7 +81,8 @@ initctypes(void)
chtypes[c] |= C_ALPHA;
chtypes['_'] |= C_ALPHA;
setctypes("0123456789", C_DIGIT);
setctypes(" \t\n|&;<>()", C_LEX1); /* \0 added automatically */
/* \0 added automatically */
setctypes(" \t\n|&;<>()", C_LEX1);
setctypes("*@#!$-?", C_VAR1);
setctypes(" \t\n", C_IFSWS);
setctypes("=-+?", C_SUBOP1);
@ -209,7 +212,8 @@ change_flag(enum sh_flag f, int what, unsigned int newval)
unsigned char oldval;
oldval = Flag(f);
Flag(f) = newval ? 1 : 0; /* needed for tristates */
/* needed for tristates */
Flag(f) = newval ? 1 : 0;
#ifndef MKSH_UNEMPLOYED
if (f == FMONITOR) {
if (what != OF_CMDLINE && newval != oldval)
@ -256,12 +260,14 @@ change_flag(enum sh_flag f, int what, unsigned int newval)
}
}
/* Parse command line & set command arguments. Returns the index of
/*
* Parse command line and set command arguments. Returns the index of
* non-option arguments, -1 if there is an error.
*/
int
parse_args(const char **argv,
int what, /* OF_CMDLINE or OF_SET */
/* OF_CMDLINE or OF_SET */
int what,
bool *setargsp)
{
static char cmd_opts[NELEM(options) + 5]; /* o:T:\0 */
@ -304,7 +310,8 @@ parse_args(const char **argv,
if (what == OF_CMDLINE) {
const char *p = argv[0], *q;
/* Set FLOGIN before parsing options so user can clear
/*
* Set FLOGIN before parsing options so user can clear
* flag using +l.
*/
if (*p != '-')
@ -332,7 +339,8 @@ parse_args(const char **argv,
if (what == OF_FIRSTTIME)
break;
if (go.optarg == NULL) {
/* lone -o: print options
/*
* lone -o: print options
*
* Note that on the command line, -o requires
* an option (ie, can't get here if what is
@ -351,7 +359,8 @@ parse_args(const char **argv,
}
#endif
if ((i != (size_t)-1) && set == Flag(i))
/* Don't check the context if the flag
/*
* Don't check the context if the flag
* isn't changing - makes "set -o interactive"
* work if you're already interactive. Needed
* if the output of "set +o" is to be used.
@ -495,7 +504,8 @@ gmatchx(const char *s, const char *p, bool isfile)
se = s + strlen(s);
pe = p + strlen(p);
/* isfile is false iff no syntax check has been done on
/*
* isfile is false iff no syntax check has been done on
* the pattern. If check fails, just to a strcmp().
*/
if (!isfile && !has_globbing(p, pe)) {
@ -509,7 +519,8 @@ gmatchx(const char *s, const char *p, bool isfile)
(const unsigned char *) p, (const unsigned char *) pe));
}
/* Returns if p is a syntacticly correct globbing pattern, false
/**
* Returns if p is a syntacticly correct globbing pattern, false
* if it contains no pattern characters or if there is a syntax error.
* Syntax errors are:
* - [ with no closing ]
@ -517,14 +528,14 @@ gmatchx(const char *s, const char *p, bool isfile)
* - [...] and *(...) not nested (eg, [a$(b|]c), *(a[b|c]d))
*/
/*XXX
- if no magic,
if dest given, copy to dst
return ?
- if magic && (no globbing || syntax error)
debunk to dst
return ?
- return ?
*/
* - if no magic,
* if dest given, copy to dst
* return ?
* - if magic && (no globbing || syntax error)
* debunk to dst
* return ?
* - return ?
*/
int
has_globbing(const char *xp, const char *xpe)
{
@ -532,42 +543,46 @@ has_globbing(const char *xp, const char *xpe)
const unsigned char *pe = (const unsigned char *) xpe;
int c;
int nest = 0, bnest = 0;
int saw_glob = 0;
int in_bracket = 0; /* inside [...] */
bool saw_glob = false;
/* inside [...] */
bool in_bracket = false;
for (; p < pe; p++) {
if (!ISMAGIC(*p))
continue;
if ((c = *++p) == '*' || c == '?')
saw_glob = 1;
saw_glob = true;
else if (c == '[') {
if (!in_bracket) {
saw_glob = 1;
in_bracket = 1;
saw_glob = true;
in_bracket = true;
if (ISMAGIC(p[1]) && p[2] == NOT)
p += 2;
if (ISMAGIC(p[1]) && p[2] == ']')
p += 2;
}
/* XXX Do we need to check ranges here? POSIX Q */
/*XXX Do we need to check ranges here? POSIX Q */
} else if (c == ']') {
if (in_bracket) {
if (bnest) /* [a*(b]) */
if (bnest)
/* [a*(b]) */
return (0);
in_bracket = 0;
in_bracket = false;
}
} else if ((c & 0x80) && vstrchr("*+?@! ", c & 0x7f)) {
saw_glob = 1;
saw_glob = true;
if (in_bracket)
bnest++;
else
nest++;
} else if (c == '|') {
if (in_bracket && !bnest) /* *(a[foo|bar]) */
if (in_bracket && !bnest)
/* *(a[foo|bar]) */
return (0);
} else if (c == /*(*/ ')') {
if (in_bracket) {
if (!bnest--) /* *(a[b)c] */
if (!bnest--)
/* *(a[b)c] */
return (0);
} else if (nest)
nest--;
@ -629,8 +644,11 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
* [*+?@!](pattern|pattern|..)
* This is also needed for ${..%..}, etc.
*/
case 0x80|'+': /* matches one or more times */
case 0x80|'*': /* matches zero or more times */
/* matches one or more times */
case 0x80|'+':
/* matches zero or more times */
case 0x80|'*':
if (!(prest = pat_scan(p, pe, 0)))
return (0);
s--;
@ -652,9 +670,12 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
}
return (0);
case 0x80|'?': /* matches zero or once */
case 0x80|'@': /* matches one of the patterns */
case 0x80|' ': /* simile for @ */
/* matches zero or once */
case 0x80|'?':
/* matches one of the patterns */
case 0x80|'@':
/* simile for @ */
case 0x80|' ':
if (!(prest = pat_scan(p, pe, 0)))
return (0);
s--;
@ -675,7 +696,8 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
}
return (0);
case 0x80|'!': /* matches none of the patterns */
/* matches none of the patterns */
case 0x80|'!':
if (!(prest = pat_scan(p, pe, 0)))
return (0);
s--;
@ -733,7 +755,8 @@ cclass(const unsigned char *p, int sub)
return (sub == '[' ? orig_p : NULL);
if (ISMAGIC(p[0]) && p[1] == '-' &&
(!ISMAGIC(p[2]) || p[3] != ']')) {
p += 2; /* MAGIC- */
/* MAGIC- */
p += 2;
d = *p++;
if (ISMAGIC(d)) {
d = *p++;
@ -789,7 +812,8 @@ ksh_getopt_reset(Getopt *go, int flags)
}
/* getopt() used for shell built-in commands, the getopts command, and
/**
* getopt() used for shell built-in commands, the getopts command, and
* command line options.
* A leading ':' in options means don't print errors, instead return '?'
* or ':' and set go->optarg to the offending option character.
@ -830,7 +854,8 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
return (-1);
}
if (arg == NULL ||
((flag != '-' ) && /* neither a - nor a + (if + allowed) */
((flag != '-' ) &&
/* neither a - nor a + (if + allowed) */
(!(go->flags & GF_PLUSOPT) || flag != '+')) ||
(c = arg[1]) == '\0') {
go->p = 0;
@ -856,7 +881,8 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
}
return ('?');
}
/* : means argument must be present, may be part of option argument
/**
* : means argument must be present, may be part of option argument
* or the next argument
* ; same as : but argument may be missing
* , means argument is part of option argument, and may be null.
@ -888,7 +914,8 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
go->optarg = argv[go->optind - 1] + go->p;
go->p = 0;
} else if (*o == '#') {
/* argument is optional and may be attached or unattached
/*
* argument is optional and may be attached or unattached
* but must start with a digit. optarg is set to 0 if the
* argument is missing.
*/
@ -909,7 +936,8 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
return (c);
}
/* print variable/alias value using necessary quotes
/*
* print variable/alias value using necessary quotes
* (POSIX says they should be suitable for re-entry...)
* No trailing newline is printed.
*/
@ -1025,8 +1053,9 @@ strip_nuls(char *buf, int nbytes)
{
char *dst;
/* nbytes check because some systems (older FreeBSDs) have a buggy
* memchr()
/*
* nbytes check because some systems (older FreeBSDs) have a
* buggy memchr()
*/
if (nbytes && (dst = memchr(buf, '\0', nbytes))) {
char *end = buf + nbytes;
@ -1116,7 +1145,7 @@ ksh_get_wd(size_t *dlen)
return (ret);
}
/*
/**
* Makes a filename into result using the following algorithm.
* - make result NULL
* - if file starts with '/', append file to result & set cdpathp to NULL
@ -1133,7 +1162,8 @@ ksh_get_wd(size_t *dlen)
*/
int
make_path(const char *cwd, const char *file,
char **cdpathp, /* & of : separated list */
/* & of : separated list */
char **cdpathp,
XString *xsp,
int *phys_pathp)
{
@ -1218,7 +1248,8 @@ simplify_path(char *pathl)
if ((isrooted = pathl[0] == '/'))
very_start++;
/* Before After
/*-
* Before After
* /foo/ /foo
* /foo/../../bar /bar
* /foo/./blah/.. /foo
@ -1571,7 +1602,7 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
/* FALLTHROUGH */
case 'x':
i = cstyle ? -1 : 2;
/*
/**
* x: look for a hexadecimal number with up to
* two (C style: arbitrary) digits; convert
* to raw octet (C style: Unicode if >0xFF)