more KNF, mostly whitespace, this time more manual labour applying style(9)
This commit is contained in:
parent
39bb71fc54
commit
0432f97ffe
118
check.pl
118
check.pl
@ -1,4 +1,4 @@
|
|||||||
# $MirOS: src/bin/mksh/check.pl,v 1.22 2009/05/16 16:59:32 tg Rel $
|
# $MirOS: src/bin/mksh/check.pl,v 1.23 2009/06/10 18:12:43 tg Rel $
|
||||||
# $OpenBSD: th,v 1.13 2006/05/18 21:27:23 miod Exp $
|
# $OpenBSD: th,v 1.13 2006/05/18 21:27:23 miod Exp $
|
||||||
#-
|
#-
|
||||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
@ -35,40 +35,40 @@
|
|||||||
# expected-exit: 1
|
# expected-exit: 1
|
||||||
# ---
|
# ---
|
||||||
# This runs the test-program (eg, mksh) with the arguments -x and -f,
|
# This runs the test-program (eg, mksh) with the arguments -x and -f,
|
||||||
# standard input is a file containing "echo hi*\nfalse\n". The program
|
# standard input is a file containing "echo hi*\nfalse\n". The program
|
||||||
# is expected to produce "hi*" (no trailing newline) on standard output,
|
# is expected to produce "hi*" (no trailing newline) on standard output,
|
||||||
# "+ echo hi*\n+false\n" on standard error, and an exit code of 1.
|
# "+ echo hi*\n+false\n" on standard error, and an exit code of 1.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Format of test files:
|
# Format of test files:
|
||||||
# - blank lines and lines starting with # are ignored
|
# - blank lines and lines starting with # are ignored
|
||||||
# - a test file contains a series of tests
|
# - a test file contains a series of tests
|
||||||
# - a test is a series of tag:value pairs ended with a "---" line
|
# - a test is a series of tag:value pairs ended with a "---" line
|
||||||
# (leading/trailing spaces are stripped from the first line of value)
|
# (leading/trailing spaces are stripped from the first line of value)
|
||||||
# - test tags are:
|
# - test tags are:
|
||||||
# Tag Flag Description
|
# Tag Flag Description
|
||||||
# ----- ---- -----------
|
# ----- ---- -----------
|
||||||
# name r The name of the test; should be unique
|
# name r The name of the test; should be unique
|
||||||
# description m What test does
|
# description m What test does
|
||||||
# arguments M Arguments to pass to the program;
|
# arguments M Arguments to pass to the program;
|
||||||
# default is no arguments.
|
# default is no arguments.
|
||||||
# script m Value is written to a file which
|
# script m Value is written to a file which
|
||||||
# is passed as an argument to the program
|
# is passed as an argument to the program
|
||||||
# (after the arguments arguments)
|
# (after the arguments arguments)
|
||||||
# stdin m Value is written to a file which is
|
# stdin m Value is written to a file which is
|
||||||
# used as standard-input for the program;
|
# used as standard-input for the program;
|
||||||
# default is to use /dev/null.
|
# default is to use /dev/null.
|
||||||
# perl-setup m Value is a perl script which is executed
|
# perl-setup m Value is a perl script which is executed
|
||||||
# just before the test is run. Try to
|
# just before the test is run. Try to
|
||||||
# avoid using this...
|
# avoid using this...
|
||||||
# perl-cleanup m Value is a perl script which is executed
|
# perl-cleanup m Value is a perl script which is executed
|
||||||
# just after the test is run. Try to
|
# just after the test is run. Try to
|
||||||
# avoid using this...
|
# avoid using this...
|
||||||
# env-setup M Value is a list of NAME=VALUE elements
|
# env-setup M Value is a list of NAME=VALUE elements
|
||||||
# which are put in the environment before
|
# which are put in the environment before
|
||||||
# the test is run. If the =VALUE is
|
# the test is run. If the =VALUE is
|
||||||
# missing, NAME is removed from the
|
# missing, NAME is removed from the
|
||||||
# environment. Programs are run with
|
# environment. Programs are run with
|
||||||
# the following minimal environment:
|
# the following minimal environment:
|
||||||
# HOME, LD_LIBRARY_PATH, LOCPATH,
|
# HOME, LD_LIBRARY_PATH, LOCPATH,
|
||||||
# LOGNAME, PATH, SHELL, USER
|
# LOGNAME, PATH, SHELL, USER
|
||||||
@ -77,17 +77,17 @@
|
|||||||
# ENV is set to /nonexistant.
|
# ENV is set to /nonexistant.
|
||||||
# __progname is set to the -p argument.
|
# __progname is set to the -p argument.
|
||||||
# __perlname is set to $^X (perlexe).
|
# __perlname is set to $^X (perlexe).
|
||||||
# file-setup mps Used to create files, directories
|
# file-setup mps Used to create files, directories
|
||||||
# and symlinks. First word is either
|
# and symlinks. First word is either
|
||||||
# file, dir or symlink; second word is
|
# file, dir or symlink; second word is
|
||||||
# permissions; this is followed by a
|
# permissions; this is followed by a
|
||||||
# quoted word that is the name of the
|
# quoted word that is the name of the
|
||||||
# file; the end-quote should be followed
|
# file; the end-quote should be followed
|
||||||
# by a newline, then the file data
|
# by a newline, then the file data
|
||||||
# (if any). The first word may be
|
# (if any). The first word may be
|
||||||
# preceded by a ! to strip the trailing
|
# preceded by a ! to strip the trailing
|
||||||
# newline in a symlink.
|
# newline in a symlink.
|
||||||
# file-result mps Used to verify a file, symlink or
|
# file-result mps Used to verify a file, symlink or
|
||||||
# directory is created correctly.
|
# directory is created correctly.
|
||||||
# The first word is either
|
# The first word is either
|
||||||
# file, dir or symlink; second word is
|
# file, dir or symlink; second word is
|
||||||
@ -101,35 +101,35 @@
|
|||||||
# of the file that should be created.
|
# of the file that should be created.
|
||||||
# The end-quote should be followed
|
# The end-quote should be followed
|
||||||
# by a newline, then the file data
|
# by a newline, then the file data
|
||||||
# (if any). The first word may be
|
# (if any). The first word may be
|
||||||
# preceded by a ! to strip the trailing
|
# preceded by a ! to strip the trailing
|
||||||
# newline in the file contents.
|
# newline in the file contents.
|
||||||
# The permissions, user and group fields
|
# The permissions, user and group fields
|
||||||
# may be * meaning accept any value.
|
# may be * meaning accept any value.
|
||||||
# time-limit Time limit - the program is sent a
|
# time-limit Time limit - the program is sent a
|
||||||
# SIGKILL N seconds. Default is no
|
# SIGKILL N seconds. Default is no
|
||||||
# limit.
|
# limit.
|
||||||
# expected-fail 'yes' if the test is expected to fail.
|
# expected-fail 'yes' if the test is expected to fail.
|
||||||
# expected-exit expected exit code. Can be a number,
|
# expected-exit expected exit code. Can be a number,
|
||||||
# or a C expression using the variables
|
# or a C expression using the variables
|
||||||
# e, s and w (exit code, termination
|
# e, s and w (exit code, termination
|
||||||
# signal, and status code).
|
# signal, and status code).
|
||||||
# expected-stdout m What the test should generate on stdout;
|
# expected-stdout m What the test should generate on stdout;
|
||||||
# default is to expect no output.
|
# default is to expect no output.
|
||||||
# expected-stdout-pattern m A perl pattern which matches the
|
# expected-stdout-pattern m A perl pattern which matches the
|
||||||
# expected output.
|
# expected output.
|
||||||
# expected-stderr m What the test should generate on stderr;
|
# expected-stderr m What the test should generate on stderr;
|
||||||
# default is to expect no output.
|
# default is to expect no output.
|
||||||
# expected-stderr-pattern m A perl pattern which matches the
|
# expected-stderr-pattern m A perl pattern which matches the
|
||||||
# expected standard error.
|
# expected standard error.
|
||||||
# category m Specify a comma separated list of
|
# category m Specify a comma separated list of
|
||||||
# 'categories' of program that the test
|
# 'categories' of program that the test
|
||||||
# is to be run for. A category can be
|
# is to be run for. A category can be
|
||||||
# negated by prefixing the name with a !.
|
# negated by prefixing the name with a !.
|
||||||
# The idea is that some tests in a
|
# The idea is that some tests in a
|
||||||
# test suite may apply to a particular
|
# test suite may apply to a particular
|
||||||
# program version and shouldn't be run
|
# program version and shouldn't be run
|
||||||
# on other versions. The category(s) of
|
# on other versions. The category(s) of
|
||||||
# the program being tested can be
|
# the program being tested can be
|
||||||
# specified on the command line.
|
# specified on the command line.
|
||||||
# One category os:XXX is predefined
|
# One category os:XXX is predefined
|
||||||
@ -137,8 +137,8 @@
|
|||||||
# eg, linux, dec_osf).
|
# eg, linux, dec_osf).
|
||||||
# Flag meanings:
|
# Flag meanings:
|
||||||
# r tag is required (eg, a test must have a name tag).
|
# r tag is required (eg, a test must have a name tag).
|
||||||
# m value can be multiple lines. Lines must be prefixed with
|
# m value can be multiple lines. Lines must be prefixed with
|
||||||
# a tab. If the value part of the initial tag:value line is
|
# a tab. If the value part of the initial tag:value line is
|
||||||
# - empty: the initial blank line is stripped.
|
# - empty: the initial blank line is stripped.
|
||||||
# - a lone !: the last newline in the value is stripped;
|
# - a lone !: the last newline in the value is stripped;
|
||||||
# M value can be multiple lines (prefixed by a tab) and consists
|
# M value can be multiple lines (prefixed by a tab) and consists
|
||||||
@ -175,35 +175,35 @@ EOF
|
|||||||
|
|
||||||
# See comment above for flag meanings
|
# See comment above for flag meanings
|
||||||
%test_fields = (
|
%test_fields = (
|
||||||
'name', 'r',
|
'name', 'r',
|
||||||
'description', 'm',
|
'description', 'm',
|
||||||
'arguments', 'M',
|
'arguments', 'M',
|
||||||
'script', 'm',
|
'script', 'm',
|
||||||
'stdin', 'm',
|
'stdin', 'm',
|
||||||
'perl-setup', 'm',
|
'perl-setup', 'm',
|
||||||
'perl-cleanup', 'm',
|
'perl-cleanup', 'm',
|
||||||
'env-setup', 'M',
|
'env-setup', 'M',
|
||||||
'file-setup', 'mps',
|
'file-setup', 'mps',
|
||||||
'file-result', 'mps',
|
'file-result', 'mps',
|
||||||
'time-limit', '',
|
'time-limit', '',
|
||||||
'expected-fail', '',
|
'expected-fail', '',
|
||||||
'expected-exit', '',
|
'expected-exit', '',
|
||||||
'expected-stdout', 'm',
|
'expected-stdout', 'm',
|
||||||
'expected-stdout-pattern', 'm',
|
'expected-stdout-pattern', 'm',
|
||||||
'expected-stderr', 'm',
|
'expected-stderr', 'm',
|
||||||
'expected-stderr-pattern', 'm',
|
'expected-stderr-pattern', 'm',
|
||||||
'category', 'm',
|
'category', 'm',
|
||||||
);
|
);
|
||||||
# Filled in by read_test()
|
# Filled in by read_test()
|
||||||
%internal_test_fields = (
|
%internal_test_fields = (
|
||||||
':full-name', 1, # file:name
|
':full-name', 1, # file:name
|
||||||
':long-name', 1, # dir/file:lineno:name
|
':long-name', 1, # dir/file:lineno:name
|
||||||
);
|
);
|
||||||
|
|
||||||
# Categories of the program under test. Provide the current
|
# Categories of the program under test. Provide the current
|
||||||
# os by default.
|
# os by default.
|
||||||
%categories = (
|
%categories = (
|
||||||
"os:$os", '1'
|
"os:$os", '1'
|
||||||
);
|
);
|
||||||
|
|
||||||
$temps = "/tmp/rts$$";
|
$temps = "/tmp/rts$$";
|
||||||
|
320
edit.c
320
edit.c
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.167 2009/06/08 20:22:19 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.168 2009/06/10 18:12:44 tg Exp $");
|
||||||
|
|
||||||
/* tty driver characters we are interested in */
|
/* tty driver characters we are interested in */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -141,15 +141,16 @@ x_putcf(int c)
|
|||||||
shf_putc(c, shl_out);
|
shf_putc(c, shl_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/*********************************
|
||||||
/* Misc common code for vi/emacs */
|
* Misc common code for vi/emacs *
|
||||||
|
*********************************/
|
||||||
|
|
||||||
/* Handle the commenting/uncommenting of a line.
|
/* Handle the commenting/uncommenting of a line.
|
||||||
* Returns:
|
* Returns:
|
||||||
* 1 if a carriage return is indicated (comment added)
|
* 1 if a carriage return is indicated (comment added)
|
||||||
* 0 if no return (comment removed)
|
* 0 if no return (comment removed)
|
||||||
* -1 if there is an error (not enough room for comment chars)
|
* -1 if there is an error (not enough room for comment chars)
|
||||||
* If successful, *lenp contains the new length. Note: cursor should be
|
* If successful, *lenp contains the new length. Note: cursor should be
|
||||||
* moved to the start of the line after (un)commenting.
|
* moved to the start of the line after (un)commenting.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -192,8 +193,9 @@ x_do_comment(char *buf, int bsize, int *lenp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/****************************************************
|
||||||
/* Common file/command completion code for vi/emacs */
|
* Common file/command completion code for vi/emacs *
|
||||||
|
****************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
x_print_expansions(int nwords, char * const *words, bool is_command)
|
x_print_expansions(int nwords, char * const *words, bool is_command)
|
||||||
@ -239,8 +241,8 @@ x_print_expansions(int nwords, char * const *words, bool is_command)
|
|||||||
XPfree(l); /* not x_free_words() */
|
XPfree(l); /* not x_free_words() */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Do file globbing:
|
* Do file globbing:
|
||||||
* - appends * to (copy of) str if no globbing chars found
|
* - appends * to (copy of) str if no globbing chars found
|
||||||
* - does expansion, checks for no match, etc.
|
* - does expansion, checks for no match, etc.
|
||||||
* - sets *wordsp to array of matching strings
|
* - sets *wordsp to array of matching strings
|
||||||
@ -434,7 +436,7 @@ x_locate_word(const char *buf, int buflen, int pos, int *startp,
|
|||||||
{
|
{
|
||||||
int start, end;
|
int start, end;
|
||||||
|
|
||||||
/* Bad call? Probably should report error */
|
/* Bad call? Probably should report error */
|
||||||
if (pos < 0 || pos > buflen) {
|
if (pos < 0 || pos > buflen) {
|
||||||
*startp = pos;
|
*startp = pos;
|
||||||
*is_commandp = false;
|
*is_commandp = false;
|
||||||
@ -492,7 +494,7 @@ x_cf_glob(int flags, const char *buf, int buflen, int pos, int *startp,
|
|||||||
if (!(flags & XCF_COMMAND))
|
if (!(flags & XCF_COMMAND))
|
||||||
is_command = false;
|
is_command = false;
|
||||||
/* Don't do command globing on zero length strings - it takes too
|
/* Don't do command globing on zero length strings - it takes too
|
||||||
* long and isn't very useful. File globs are more likely to be
|
* long and isn't very useful. File globs are more likely to be
|
||||||
* useful, so allow these.
|
* useful, so allow these.
|
||||||
*/
|
*/
|
||||||
if (len == 0 && is_command)
|
if (len == 0 && is_command)
|
||||||
@ -513,8 +515,8 @@ x_cf_glob(int flags, const char *buf, int buflen, int pos, int *startp,
|
|||||||
return (nwords);
|
return (nwords);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a string, copy it and possibly add a '*' to the end. The
|
/* Given a string, copy it and possibly add a '*' to the end.
|
||||||
* new string is returned.
|
* The new string is returned.
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
add_glob(const char *str, int slen)
|
add_glob(const char *str, int slen)
|
||||||
@ -537,8 +539,8 @@ add_glob(const char *str, int slen)
|
|||||||
for (s = toglob; *s; s++) {
|
for (s = toglob; *s; s++) {
|
||||||
if (*s == '\\' && s[1])
|
if (*s == '\\' && s[1])
|
||||||
s++;
|
s++;
|
||||||
else if (*s == '*' || *s == '[' || *s == '?' || *s == '$'
|
else if (*s == '*' || *s == '[' || *s == '?' || *s == '$' ||
|
||||||
|| (s[1] == '(' && vstrchr("*+?@!", *s)))
|
(s[1] == '(' && vstrchr("*+?@!", *s)))
|
||||||
break;
|
break;
|
||||||
else if (*s == '/')
|
else if (*s == '/')
|
||||||
saw_slash = true;
|
saw_slash = true;
|
||||||
@ -581,7 +583,7 @@ x_free_words(int nwords, char **words)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the offset of the basename of string s (which ends at se - need not
|
/* Return the offset of the basename of string s (which ends at se - need not
|
||||||
* be null terminated). Trailing slashes are ignored. If s is just a slash,
|
* be null terminated). Trailing slashes are ignored. If s is just a slash,
|
||||||
* then the offset is 0 (actually, length - 1).
|
* then the offset is 0 (actually, length - 1).
|
||||||
* s Return
|
* s Return
|
||||||
* /etc 1
|
* /etc 1
|
||||||
@ -614,7 +616,7 @@ x_basename(const char *s, const char *se)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Apply pattern matching to a table: all table entries that match a pattern
|
* Apply pattern matching to a table: all table entries that match a pattern
|
||||||
* are added to wp.
|
* are added to wp.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
@ -962,7 +964,7 @@ utf_wctomb(char *dst, unsigned int wc)
|
|||||||
static Area aedit;
|
static Area aedit;
|
||||||
#define AEDIT &aedit /* area for kill ring and macro defns */
|
#define AEDIT &aedit /* area for kill ring and macro defns */
|
||||||
|
|
||||||
#define MKCTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
|
#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */
|
||||||
#define UNCTRL(x) ((x) ^ 0x40) /* ASCII */
|
#define UNCTRL(x) ((x) ^ 0x40) /* ASCII */
|
||||||
|
|
||||||
/* values returned by keyboard functions */
|
/* values returned by keyboard functions */
|
||||||
@ -995,9 +997,9 @@ struct x_defbindings {
|
|||||||
#define X_TABSZ 256 /* size of keydef tables etc */
|
#define X_TABSZ 256 /* size of keydef tables etc */
|
||||||
|
|
||||||
/* Arguments for do_complete()
|
/* Arguments for do_complete()
|
||||||
* 0 = enumerate M-= complete as much as possible and then list
|
* 0 = enumerate M-= complete as much as possible and then list
|
||||||
* 1 = complete M-Esc
|
* 1 = complete M-Esc
|
||||||
* 2 = list M-?
|
* 2 = list M-?
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CT_LIST, /* list the possible completions */
|
CT_LIST, /* list the possible completions */
|
||||||
@ -1274,95 +1276,95 @@ static const struct x_ftab x_ftab[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct x_defbindings const x_defbindings[] = {
|
static struct x_defbindings const x_defbindings[] = {
|
||||||
{ XFUNC_del_back, 0, MKCTRL('?') },
|
{ XFUNC_del_back, 0, CTRL('?') },
|
||||||
{ XFUNC_del_bword, 1, MKCTRL('?') },
|
{ XFUNC_del_bword, 1, CTRL('?') },
|
||||||
{ XFUNC_eot_del, 0, MKCTRL('D') },
|
{ XFUNC_eot_del, 0, CTRL('D') },
|
||||||
{ XFUNC_del_back, 0, MKCTRL('H') },
|
{ XFUNC_del_back, 0, CTRL('H') },
|
||||||
{ XFUNC_del_bword, 1, MKCTRL('H') },
|
{ XFUNC_del_bword, 1, CTRL('H') },
|
||||||
{ XFUNC_del_bword, 1, 'h' },
|
{ XFUNC_del_bword, 1, 'h' },
|
||||||
{ XFUNC_mv_bword, 1, 'b' },
|
{ XFUNC_mv_bword, 1, 'b' },
|
||||||
{ XFUNC_mv_fword, 1, 'f' },
|
{ XFUNC_mv_fword, 1, 'f' },
|
||||||
{ XFUNC_del_fword, 1, 'd' },
|
{ XFUNC_del_fword, 1, 'd' },
|
||||||
{ XFUNC_mv_back, 0, MKCTRL('B') },
|
{ XFUNC_mv_back, 0, CTRL('B') },
|
||||||
{ XFUNC_mv_forw, 0, MKCTRL('F') },
|
{ XFUNC_mv_forw, 0, CTRL('F') },
|
||||||
{ XFUNC_search_char_forw, 0, MKCTRL(']') },
|
{ XFUNC_search_char_forw, 0, CTRL(']') },
|
||||||
{ XFUNC_search_char_back, 1, MKCTRL(']') },
|
{ XFUNC_search_char_back, 1, CTRL(']') },
|
||||||
{ XFUNC_newline, 0, MKCTRL('M') },
|
{ XFUNC_newline, 0, CTRL('M') },
|
||||||
{ XFUNC_newline, 0, MKCTRL('J') },
|
{ XFUNC_newline, 0, CTRL('J') },
|
||||||
{ XFUNC_end_of_text, 0, MKCTRL('_') },
|
{ XFUNC_end_of_text, 0, CTRL('_') },
|
||||||
{ XFUNC_abort, 0, MKCTRL('G') },
|
{ XFUNC_abort, 0, CTRL('G') },
|
||||||
{ XFUNC_prev_com, 0, MKCTRL('P') },
|
{ XFUNC_prev_com, 0, CTRL('P') },
|
||||||
{ XFUNC_next_com, 0, MKCTRL('N') },
|
{ XFUNC_next_com, 0, CTRL('N') },
|
||||||
{ XFUNC_nl_next_com, 0, MKCTRL('O') },
|
{ XFUNC_nl_next_com, 0, CTRL('O') },
|
||||||
{ XFUNC_search_hist, 0, MKCTRL('R') },
|
{ XFUNC_search_hist, 0, CTRL('R') },
|
||||||
{ XFUNC_beg_hist, 1, '<' },
|
{ XFUNC_beg_hist, 1, '<' },
|
||||||
{ XFUNC_end_hist, 1, '>' },
|
{ XFUNC_end_hist, 1, '>' },
|
||||||
{ XFUNC_goto_hist, 1, 'g' },
|
{ XFUNC_goto_hist, 1, 'g' },
|
||||||
{ XFUNC_mv_end, 0, MKCTRL('E') },
|
{ XFUNC_mv_end, 0, CTRL('E') },
|
||||||
{ XFUNC_mv_begin, 0, MKCTRL('A') },
|
{ XFUNC_mv_begin, 0, CTRL('A') },
|
||||||
{ XFUNC_draw_line, 0, MKCTRL('L') },
|
{ XFUNC_draw_line, 0, CTRL('L') },
|
||||||
{ XFUNC_cls, 1, MKCTRL('L') },
|
{ XFUNC_cls, 1, CTRL('L') },
|
||||||
{ XFUNC_meta1, 0, MKCTRL('[') },
|
{ XFUNC_meta1, 0, CTRL('[') },
|
||||||
{ XFUNC_meta2, 0, MKCTRL('X') },
|
{ XFUNC_meta2, 0, CTRL('X') },
|
||||||
{ XFUNC_kill, 0, MKCTRL('K') },
|
{ XFUNC_kill, 0, CTRL('K') },
|
||||||
{ XFUNC_yank, 0, MKCTRL('Y') },
|
{ XFUNC_yank, 0, CTRL('Y') },
|
||||||
{ XFUNC_meta_yank, 1, 'y' },
|
{ XFUNC_meta_yank, 1, 'y' },
|
||||||
{ XFUNC_literal, 0, MKCTRL('^') },
|
{ XFUNC_literal, 0, CTRL('^') },
|
||||||
{ XFUNC_comment, 1, '#' },
|
{ XFUNC_comment, 1, '#' },
|
||||||
{ XFUNC_transpose, 0, MKCTRL('T') },
|
{ XFUNC_transpose, 0, CTRL('T') },
|
||||||
{ XFUNC_complete, 1, MKCTRL('[') },
|
{ XFUNC_complete, 1, CTRL('[') },
|
||||||
{ XFUNC_comp_list, 0, MKCTRL('I') },
|
{ XFUNC_comp_list, 0, CTRL('I') },
|
||||||
{ XFUNC_comp_list, 1, '=' },
|
{ XFUNC_comp_list, 1, '=' },
|
||||||
{ XFUNC_enumerate, 1, '?' },
|
{ XFUNC_enumerate, 1, '?' },
|
||||||
{ XFUNC_expand, 1, '*' },
|
{ XFUNC_expand, 1, '*' },
|
||||||
{ XFUNC_comp_file, 1, MKCTRL('X') },
|
{ XFUNC_comp_file, 1, CTRL('X') },
|
||||||
{ XFUNC_comp_comm, 2, MKCTRL('[') },
|
{ XFUNC_comp_comm, 2, CTRL('[') },
|
||||||
{ XFUNC_list_comm, 2, '?' },
|
{ XFUNC_list_comm, 2, '?' },
|
||||||
{ XFUNC_list_file, 2, MKCTRL('Y') },
|
{ XFUNC_list_file, 2, CTRL('Y') },
|
||||||
{ XFUNC_set_mark, 1, ' ' },
|
{ XFUNC_set_mark, 1, ' ' },
|
||||||
{ XFUNC_kill_region, 0, MKCTRL('W') },
|
{ XFUNC_kill_region, 0, CTRL('W') },
|
||||||
{ XFUNC_xchg_point_mark, 2, MKCTRL('X') },
|
{ XFUNC_xchg_point_mark, 2, CTRL('X') },
|
||||||
{ XFUNC_literal, 0, MKCTRL('V') },
|
{ XFUNC_literal, 0, CTRL('V') },
|
||||||
{ XFUNC_version, 1, MKCTRL('V') },
|
{ XFUNC_version, 1, CTRL('V') },
|
||||||
{ XFUNC_prev_histword, 1, '.' },
|
{ XFUNC_prev_histword, 1, '.' },
|
||||||
{ XFUNC_prev_histword, 1, '_' },
|
{ XFUNC_prev_histword, 1, '_' },
|
||||||
{ XFUNC_set_arg, 1, '0' },
|
{ XFUNC_set_arg, 1, '0' },
|
||||||
{ XFUNC_set_arg, 1, '1' },
|
{ XFUNC_set_arg, 1, '1' },
|
||||||
{ XFUNC_set_arg, 1, '2' },
|
{ XFUNC_set_arg, 1, '2' },
|
||||||
{ XFUNC_set_arg, 1, '3' },
|
{ XFUNC_set_arg, 1, '3' },
|
||||||
{ XFUNC_set_arg, 1, '4' },
|
{ XFUNC_set_arg, 1, '4' },
|
||||||
{ XFUNC_set_arg, 1, '5' },
|
{ XFUNC_set_arg, 1, '5' },
|
||||||
{ XFUNC_set_arg, 1, '6' },
|
{ XFUNC_set_arg, 1, '6' },
|
||||||
{ XFUNC_set_arg, 1, '7' },
|
{ XFUNC_set_arg, 1, '7' },
|
||||||
{ XFUNC_set_arg, 1, '8' },
|
{ XFUNC_set_arg, 1, '8' },
|
||||||
{ XFUNC_set_arg, 1, '9' },
|
{ XFUNC_set_arg, 1, '9' },
|
||||||
{ XFUNC_fold_upper, 1, 'U' },
|
{ XFUNC_fold_upper, 1, 'U' },
|
||||||
{ XFUNC_fold_upper, 1, 'u' },
|
{ XFUNC_fold_upper, 1, 'u' },
|
||||||
{ XFUNC_fold_lower, 1, 'L' },
|
{ XFUNC_fold_lower, 1, 'L' },
|
||||||
{ XFUNC_fold_lower, 1, 'l' },
|
{ XFUNC_fold_lower, 1, 'l' },
|
||||||
{ XFUNC_fold_capitalise, 1, 'C' },
|
{ XFUNC_fold_capitalise, 1, 'C' },
|
||||||
{ XFUNC_fold_capitalise, 1, 'c' },
|
{ XFUNC_fold_capitalise, 1, 'c' },
|
||||||
/* These for ansi arrow keys: arguablely shouldn't be here by
|
/* These for ansi arrow keys: arguablely shouldn't be here by
|
||||||
* default, but its simpler/faster/smaller than using termcap
|
* default, but its simpler/faster/smaller than using termcap
|
||||||
* entries.
|
* entries.
|
||||||
*/
|
*/
|
||||||
{ XFUNC_meta2, 1, '[' },
|
{ XFUNC_meta2, 1, '[' },
|
||||||
{ XFUNC_meta2, 1, 'O' },
|
{ XFUNC_meta2, 1, 'O' },
|
||||||
{ XFUNC_prev_com, 2, 'A' },
|
{ XFUNC_prev_com, 2, 'A' },
|
||||||
{ XFUNC_next_com, 2, 'B' },
|
{ XFUNC_next_com, 2, 'B' },
|
||||||
{ XFUNC_mv_forw, 2, 'C' },
|
{ XFUNC_mv_forw, 2, 'C' },
|
||||||
{ XFUNC_mv_back, 2, 'D' },
|
{ XFUNC_mv_back, 2, 'D' },
|
||||||
{ XFUNC_mv_begin | 0x80, 2, '1' },
|
{ XFUNC_mv_begin | 0x80, 2, '1' },
|
||||||
{ XFUNC_mv_begin | 0x80, 2, '7' },
|
{ XFUNC_mv_begin | 0x80, 2, '7' },
|
||||||
{ XFUNC_mv_begin, 2, 'H' },
|
{ XFUNC_mv_begin, 2, 'H' },
|
||||||
{ XFUNC_mv_end | 0x80, 2, '4' },
|
{ XFUNC_mv_end | 0x80, 2, '4' },
|
||||||
{ XFUNC_mv_end | 0x80, 2, '8' },
|
{ XFUNC_mv_end | 0x80, 2, '8' },
|
||||||
{ XFUNC_mv_end, 2, 'F' },
|
{ XFUNC_mv_end, 2, 'F' },
|
||||||
{ XFUNC_del_char | 0x80, 2, '3' },
|
{ XFUNC_del_char | 0x80, 2, '3' },
|
||||||
{ XFUNC_search_hist_up | 0x80, 2, '5' },
|
{ XFUNC_search_hist_up | 0x80, 2, '5' },
|
||||||
{ XFUNC_search_hist_dn | 0x80, 2, '6' },
|
{ XFUNC_search_hist_dn | 0x80, 2, '6' },
|
||||||
/* more non-standard ones */
|
/* more non-standard ones */
|
||||||
{ XFUNC_edit_line, 2, 'e' }
|
{ XFUNC_edit_line, 2, 'e' }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef MKSH_SMALL
|
#ifdef MKSH_SMALL
|
||||||
@ -1508,7 +1510,7 @@ x_insert(int c)
|
|||||||
static char str[4];
|
static char str[4];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Should allow tab and control chars.
|
* Should allow tab and control chars.
|
||||||
*/
|
*/
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
invmbs:
|
invmbs:
|
||||||
@ -2114,13 +2116,13 @@ x_search_hist(int c)
|
|||||||
if ((c = x_e_getc()) < 0)
|
if ((c = x_e_getc()) < 0)
|
||||||
return (KSTD);
|
return (KSTD);
|
||||||
f = x_tab[0][c];
|
f = x_tab[0][c];
|
||||||
if (c == MKCTRL('[')) {
|
if (c == CTRL('[')) {
|
||||||
if ((f & 0x7F) == XFUNC_meta1) {
|
if ((f & 0x7F) == XFUNC_meta1) {
|
||||||
if ((c = x_e_getc()) < 0)
|
if ((c = x_e_getc()) < 0)
|
||||||
return (KSTD);
|
return (KSTD);
|
||||||
f = x_tab[1][c] & 0x7F;
|
f = x_tab[1][c] & 0x7F;
|
||||||
if (f == XFUNC_meta1 || f == XFUNC_meta2)
|
if (f == XFUNC_meta1 || f == XFUNC_meta2)
|
||||||
x_meta1(MKCTRL('['));
|
x_meta1(CTRL('['));
|
||||||
x_e_ungetc(c);
|
x_e_ungetc(c);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2296,7 +2298,7 @@ x_cls(int c __unused)
|
|||||||
return (KSTD);
|
return (KSTD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Redraw (part of) the line. If limit is < 0, the everything is redrawn
|
/* Redraw (part of) the line. If limit is < 0, the everything is redrawn
|
||||||
* on a NEW line, otherwise limit is the screen column up to which needs
|
* on a NEW line, otherwise limit is the screen column up to which needs
|
||||||
* redrawing.
|
* redrawing.
|
||||||
*/
|
*/
|
||||||
@ -2377,10 +2379,10 @@ x_transpose(int c __unused)
|
|||||||
/* What transpose is meant to do seems to be up for debate. This
|
/* What transpose is meant to do seems to be up for debate. This
|
||||||
* is a general summary of the options; the text is abcd with the
|
* is a general summary of the options; the text is abcd with the
|
||||||
* upper case character or underscore indicating the cursor position:
|
* upper case character or underscore indicating the cursor position:
|
||||||
* Who Before After Before After
|
* Who Before After Before After
|
||||||
* at&t ksh in emacs mode: abCd abdC abcd_ (bell)
|
* at&t ksh in emacs mode: abCd abdC abcd_ (bell)
|
||||||
* at&t ksh in gmacs mode: abCd baCd abcd_ abdc_
|
* at&t ksh in gmacs mode: abCd baCd abcd_ abdc_
|
||||||
* gnu emacs: abCd acbD abcd_ abdc_
|
* gnu emacs: abCd acbD abcd_ abdc_
|
||||||
* Pdksh currently goes with GNU behavior since I believe this is the
|
* Pdksh currently goes with GNU behavior since I believe this is the
|
||||||
* most common version of emacs, unless in gmacs mode, in which case
|
* most common version of emacs, unless in gmacs mode, in which case
|
||||||
* it does the at&t ksh gmacs mode.
|
* it does the at&t ksh gmacs mode.
|
||||||
@ -2560,7 +2562,7 @@ x_mapin(const char *cp, Area *ap)
|
|||||||
if (*cp == '^') {
|
if (*cp == '^') {
|
||||||
cp++;
|
cp++;
|
||||||
if (*cp >= '?') /* includes '?'; ASCII */
|
if (*cp >= '?') /* includes '?'; ASCII */
|
||||||
*op++ = MKCTRL(*cp);
|
*op++ = CTRL(*cp);
|
||||||
else {
|
else {
|
||||||
*op++ = '^';
|
*op++ = '^';
|
||||||
cp--;
|
cp--;
|
||||||
@ -2606,7 +2608,7 @@ x_print(int prefix, int key)
|
|||||||
if (prefix)
|
if (prefix)
|
||||||
/* prefix == 1 || prefix == 2 */
|
/* prefix == 1 || prefix == 2 */
|
||||||
shf_puts(x_mapout(prefix == 1 ?
|
shf_puts(x_mapout(prefix == 1 ?
|
||||||
MKCTRL('[') : MKCTRL('X')), shl_stdout);
|
CTRL('[') : CTRL('X')), shl_stdout);
|
||||||
shprintf("%s%s = ", x_mapout(key), (f & 0x80) ? "~" : "");
|
shprintf("%s%s = ", x_mapout(key), (f & 0x80) ? "~" : "");
|
||||||
if ((f & 0x7F) != XFUNC_ins_string)
|
if ((f & 0x7F) != XFUNC_ins_string)
|
||||||
shprintf("%s\n", x_ftab[f & 0x7F].xf_name);
|
shprintf("%s\n", x_ftab[f & 0x7F].xf_name);
|
||||||
@ -2735,7 +2737,7 @@ x_init_emacs(void)
|
|||||||
static void
|
static void
|
||||||
bind_if_not_bound(int p, int k, int func)
|
bind_if_not_bound(int p, int k, int func)
|
||||||
{
|
{
|
||||||
/* Has user already bound this key? If so, don't override it */
|
/* Has user already bound this key? If so, don't override it */
|
||||||
if (x_bound[((p) * X_TABSZ + (k)) / 8] &
|
if (x_bound[((p) * X_TABSZ + (k)) / 8] &
|
||||||
(1 << (((p) * X_TABSZ + (k)) % 8)))
|
(1 << (((p) * X_TABSZ + (k)) % 8)))
|
||||||
return;
|
return;
|
||||||
@ -2926,7 +2928,7 @@ do_complete(int flags, /* XCF_{COMMAND,FILE,COMMAND_FILE} */
|
|||||||
*
|
*
|
||||||
* DESCRIPTION:
|
* DESCRIPTION:
|
||||||
* This function is called when we have exceeded the bounds
|
* This function is called when we have exceeded the bounds
|
||||||
* of the edit window. It increments x_adj_done so that
|
* of the edit window. It increments x_adj_done so that
|
||||||
* functions like x_ins and x_delete know that we have been
|
* functions like x_ins and x_delete know that we have been
|
||||||
* called and can skip the x_bs() stuff which has already
|
* called and can skip the x_bs() stuff which has already
|
||||||
* been done by x_redraw.
|
* been done by x_redraw.
|
||||||
@ -3139,7 +3141,7 @@ x_version(int c __unused)
|
|||||||
|
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return (KSTD);
|
return (KSTD);
|
||||||
/* This is what at&t ksh seems to do... Very bizarre */
|
/* This is what at&t ksh seems to do... Very bizarre */
|
||||||
if (c != ' ')
|
if (c != ' ')
|
||||||
x_e_ungetc(c);
|
x_e_ungetc(c);
|
||||||
|
|
||||||
@ -3176,7 +3178,7 @@ x_edit_line(int c __unused)
|
|||||||
*
|
*
|
||||||
* DESCRIPTION:
|
* DESCRIPTION:
|
||||||
* This function recovers the last word from the previous
|
* This function recovers the last word from the previous
|
||||||
* command and inserts it into the current edit line. If a
|
* command and inserts it into the current edit line. If a
|
||||||
* numeric arg is supplied then the n'th word from the
|
* numeric arg is supplied then the n'th word from the
|
||||||
* start of the previous command is used.
|
* start of the previous command is used.
|
||||||
* As a side effect, trashes the mark in order to achieve
|
* As a side effect, trashes the mark in order to achieve
|
||||||
@ -3323,9 +3325,9 @@ x_fold_case(int c)
|
|||||||
* x_lastcp()
|
* x_lastcp()
|
||||||
*
|
*
|
||||||
* DESCRIPTION:
|
* DESCRIPTION:
|
||||||
* This function returns a pointer to that char in the
|
* This function returns a pointer to that char in the
|
||||||
* edit buffer that will be the last displayed on the
|
* edit buffer that will be the last displayed on the
|
||||||
* screen. The sequence:
|
* screen. The sequence:
|
||||||
*
|
*
|
||||||
* cp = x_lastcp();
|
* cp = x_lastcp();
|
||||||
* while (cp > xcp)
|
* while (cp > xcp)
|
||||||
@ -3498,39 +3500,39 @@ static int x_vi_putbuf(const char *, size_t);
|
|||||||
#define is_zerocount(c) (classify[(c)&0x7f]&Z_)
|
#define is_zerocount(c) (classify[(c)&0x7f]&Z_)
|
||||||
|
|
||||||
static const unsigned char classify[128] = {
|
static const unsigned char classify[128] = {
|
||||||
/* 0 1 2 3 4 5 6 7 */
|
/* 0 1 2 3 4 5 6 7 */
|
||||||
/* 0 ^@ ^A ^B ^C ^D ^E ^F ^G */
|
/* 0 ^@ ^A ^B ^C ^D ^E ^F ^G */
|
||||||
B_, 0, 0, 0, 0, C_|U_, C_|Z_, 0,
|
B_, 0, 0, 0, 0, C_|U_, C_|Z_, 0,
|
||||||
/* 01 ^H ^I ^J ^K ^L ^M ^N ^O */
|
/* 1 ^H ^I ^J ^K ^L ^M ^N ^O */
|
||||||
M_, C_|Z_, 0, 0, C_|U_, 0, C_, 0,
|
M_, C_|Z_, 0, 0, C_|U_, 0, C_, 0,
|
||||||
/* 02 ^P ^Q ^R ^S ^T ^U ^V ^W */
|
/* 2 ^P ^Q ^R ^S ^T ^U ^V ^W */
|
||||||
C_, 0, C_|U_, 0, 0, 0, C_, 0,
|
C_, 0, C_|U_, 0, 0, 0, C_, 0,
|
||||||
/* 03 ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
|
/* 3 ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
|
||||||
C_, 0, 0, C_|Z_, 0, 0, 0, 0,
|
C_, 0, 0, C_|Z_, 0, 0, 0, 0,
|
||||||
/* 04 <space> ! " # $ % & ' */
|
/* 4 <space> ! " # $ % & ' */
|
||||||
M_, 0, 0, C_, M_, M_, 0, 0,
|
M_, 0, 0, C_, M_, M_, 0, 0,
|
||||||
/* 05 ( ) * + , - . / */
|
/* 5 ( ) * + , - . / */
|
||||||
0, 0, C_, C_, M_, C_, 0, C_|S_,
|
0, 0, C_, C_, M_, C_, 0, C_|S_,
|
||||||
/* 06 0 1 2 3 4 5 6 7 */
|
/* 6 0 1 2 3 4 5 6 7 */
|
||||||
M_, 0, 0, 0, 0, 0, 0, 0,
|
M_, 0, 0, 0, 0, 0, 0, 0,
|
||||||
/* 07 8 9 : ; < = > ? */
|
/* 7 8 9 : ; < = > ? */
|
||||||
0, 0, 0, M_, 0, C_, 0, C_|S_,
|
0, 0, 0, M_, 0, C_, 0, C_|S_,
|
||||||
/* 010 @ A B C D E F G */
|
/* 8 @ A B C D E F G */
|
||||||
C_|X_, C_, M_, C_, C_, M_, M_|X_, C_|U_|Z_,
|
C_|X_, C_, M_, C_, C_, M_, M_|X_, C_|U_|Z_,
|
||||||
/* 011 H I J K L M N O */
|
/* 9 H I J K L M N O */
|
||||||
0, C_, 0, 0, 0, 0, C_|U_, 0,
|
0, C_, 0, 0, 0, 0, C_|U_, 0,
|
||||||
/* 012 P Q R S T U V W */
|
/* A P Q R S T U V W */
|
||||||
C_, 0, C_, C_, M_|X_, C_, 0, M_,
|
C_, 0, C_, C_, M_|X_, C_, 0, M_,
|
||||||
/* 013 X Y Z [ \ ] ^ _ */
|
/* B X Y Z [ \ ] ^ _ */
|
||||||
C_, C_|U_, 0, 0, C_|Z_, 0, M_, C_|Z_,
|
C_, C_|U_, 0, 0, C_|Z_, 0, M_, C_|Z_,
|
||||||
/* 014 ` a b c d e f g */
|
/* C ` a b c d e f g */
|
||||||
0, C_, M_, E_, E_, M_, M_|X_, C_|Z_,
|
0, C_, M_, E_, E_, M_, M_|X_, C_|Z_,
|
||||||
/* 015 h i j k l m n o */
|
/* D h i j k l m n o */
|
||||||
M_, C_, C_|U_, C_|U_, M_, 0, C_|U_, 0,
|
M_, C_, C_|U_, C_|U_, M_, 0, C_|U_, 0,
|
||||||
/* 016 p q r s t u v w */
|
/* E p q r s t u v w */
|
||||||
C_, 0, X_, C_, M_|X_, C_|U_, C_|U_|Z_,M_,
|
C_, 0, X_, C_, M_|X_, C_|U_, C_|U_|Z_, M_,
|
||||||
/* 017 x y z { | } ~ ^? */
|
/* F x y z { | } ~ ^? */
|
||||||
C_, E_|U_, 0, 0, M_|Z_, 0, C_, 0
|
C_, E_|U_, 0, 0, M_|Z_, 0, C_, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAXVICMD 3
|
#define MAXVICMD 3
|
||||||
@ -3584,8 +3586,8 @@ static int state;
|
|||||||
|
|
||||||
/* Information for keeping track of macros that are being expanded.
|
/* Information for keeping track of macros that are being expanded.
|
||||||
* The format of buf is the alias contents followed by a NUL byte followed
|
* The format of buf is the alias contents followed by a NUL byte followed
|
||||||
* by the name (letter) of the alias. The end of the buffer is marked by
|
* by the name (letter) of the alias. The end of the buffer is marked by
|
||||||
* a double NUL. The name of the alias is stored so recursive macros can
|
* a double NUL. The name of the alias is stored so recursive macros can
|
||||||
* be detected.
|
* be detected.
|
||||||
*/
|
*/
|
||||||
struct macro_state {
|
struct macro_state {
|
||||||
@ -3758,7 +3760,7 @@ vi_hook(int ch)
|
|||||||
es->cursor = 0;
|
es->cursor = 0;
|
||||||
es->linelen = 0;
|
es->linelen = 0;
|
||||||
putbuf(KSH_VERSION,
|
putbuf(KSH_VERSION,
|
||||||
strlen(KSH_VERSION), 0);
|
strlen(KSH_VERSION), 0);
|
||||||
refresh(0);
|
refresh(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4386,8 +4388,8 @@ vi_cmd(int argcnt, const char *cmd)
|
|||||||
histsave(&source->line, es->cbuf, true,
|
histsave(&source->line, es->cbuf, true,
|
||||||
true);
|
true);
|
||||||
} else
|
} else
|
||||||
argcnt = source->line + 1
|
argcnt = source->line + 1 -
|
||||||
- (hlast - hnum);
|
(hlast - hnum);
|
||||||
}
|
}
|
||||||
if (argcnt)
|
if (argcnt)
|
||||||
shf_snprintf(es->cbuf, es->cbufsize, "%s %d",
|
shf_snprintf(es->cbuf, es->cbufsize, "%s %d",
|
||||||
@ -5417,7 +5419,7 @@ complete_word(int cmd, int count)
|
|||||||
rval = x_escape(match, match_len, x_vi_putbuf);
|
rval = x_escape(match, match_len, x_vi_putbuf);
|
||||||
|
|
||||||
if (rval == 0 && is_unique) {
|
if (rval == 0 && is_unique) {
|
||||||
/* If exact match, don't undo. Allows directory completions
|
/* If exact match, don't undo. Allows directory completions
|
||||||
* to be used (ie, complete the next portion of the path).
|
* to be used (ie, complete the next portion of the path).
|
||||||
*/
|
*/
|
||||||
expanded = NONE;
|
expanded = NONE;
|
||||||
|
63
eval.c
63
eval.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.58 2009/06/08 20:06:45 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.59 2009/06/10 18:12:45 tg Exp $");
|
||||||
|
|
||||||
#ifdef MKSH_SMALL
|
#ifdef MKSH_SMALL
|
||||||
#define MKSH_NOPWNAM
|
#define MKSH_NOPWNAM
|
||||||
@ -37,14 +37,14 @@ __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.58 2009/06/08 20:06:45 tg Exp $");
|
|||||||
|
|
||||||
/* expansion generator state */
|
/* expansion generator state */
|
||||||
typedef struct Expand {
|
typedef struct Expand {
|
||||||
/* int type; */ /* see expand() */
|
/* int type; */ /* see expand() */
|
||||||
const char *str; /* string */
|
const char *str; /* string */
|
||||||
union {
|
union {
|
||||||
const char **strv;/* string[] */
|
const char **strv; /* string[] */
|
||||||
struct shf *shf; /* file */
|
struct shf *shf; /* file */
|
||||||
} u; /* source */
|
} u; /* source */
|
||||||
struct tbl *var; /* variable in ${var..} */
|
struct tbl *var; /* variable in ${var..} */
|
||||||
short split; /* split "$@" / call waitlast $() */
|
short split; /* split "$@" / call waitlast $() */
|
||||||
} Expand;
|
} Expand;
|
||||||
|
|
||||||
#define XBASE 0 /* scanning original */
|
#define XBASE 0 /* scanning original */
|
||||||
@ -312,13 +312,12 @@ expand(const char *cp, /* input word */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
case OSUBST: /* ${{#}var{:}[=+-?#%]word} */
|
case OSUBST: { /* ${{#}var{:}[=+-?#%]word} */
|
||||||
/* format is:
|
/* format is:
|
||||||
* OSUBST [{x] plain-variable-part \0
|
* OSUBST [{x] plain-variable-part \0
|
||||||
* compiled-word-part CSUBST [}x]
|
* compiled-word-part CSUBST [}x]
|
||||||
* This is where all syntax checking gets done...
|
* This is where all syntax checking gets done...
|
||||||
*/
|
*/
|
||||||
{
|
|
||||||
const char *varname = ++sp; /* skip the { or x (}) */
|
const char *varname = ++sp; /* skip the { or x (}) */
|
||||||
int stype;
|
int stype;
|
||||||
int slen = 0;
|
int slen = 0;
|
||||||
@ -543,7 +542,7 @@ expand(const char *cp, /* input word */
|
|||||||
* after :s here is
|
* after :s here is
|
||||||
* non-standard ksh, but is
|
* non-standard ksh, but is
|
||||||
* consistent with rules for
|
* consistent with rules for
|
||||||
* other assignments. Not
|
* other assignments. Not
|
||||||
* sure what POSIX thinks of
|
* sure what POSIX thinks of
|
||||||
* this.
|
* this.
|
||||||
* Not doing tilde expansion
|
* Not doing tilde expansion
|
||||||
@ -574,7 +573,7 @@ expand(const char *cp, /* input word */
|
|||||||
/* skip word */
|
/* skip word */
|
||||||
sp += wdscan(sp, CSUBST) - sp;
|
sp += wdscan(sp, CSUBST) - sp;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case CSUBST: /* only get here if expanding word */
|
case CSUBST: /* only get here if expanding word */
|
||||||
do_CSUBST:
|
do_CSUBST:
|
||||||
sp++; /* ({) skip the } or x */
|
sp++; /* ({) skip the } or x */
|
||||||
@ -629,15 +628,14 @@ expand(const char *cp, /* input word */
|
|||||||
doblank++;
|
doblank++;
|
||||||
st = st->prev;
|
st = st->prev;
|
||||||
continue;
|
continue;
|
||||||
case '?':
|
case '?': {
|
||||||
{
|
|
||||||
char *s = Xrestpos(ds, dp, st->base);
|
char *s = Xrestpos(ds, dp, st->base);
|
||||||
|
|
||||||
errorf("%s: %s", st->var->name,
|
errorf("%s: %s", st->var->name,
|
||||||
dp == s ?
|
dp == s ?
|
||||||
"parameter null or not set" :
|
"parameter null or not set" :
|
||||||
(debunk(s, s, strlen(s) + 1), s));
|
(debunk(s, s, strlen(s) + 1), s));
|
||||||
}
|
}
|
||||||
case '0':
|
case '0':
|
||||||
case '/':
|
case '/':
|
||||||
dp = Xrestpos(ds, dp, st->base);
|
dp = Xrestpos(ds, dp, st->base);
|
||||||
@ -733,8 +731,9 @@ expand(const char *cp, /* input word */
|
|||||||
--newlines;
|
--newlines;
|
||||||
} else {
|
} else {
|
||||||
while ((c = shf_getc(x.u.shf)) == 0 || c == '\n')
|
while ((c = shf_getc(x.u.shf)) == 0 || c == '\n')
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
newlines++; /* Save newlines */
|
/* Save newlines */
|
||||||
|
newlines++;
|
||||||
if (newlines && c != EOF) {
|
if (newlines && c != EOF) {
|
||||||
shf_ungetc(c, x.u.shf);
|
shf_ungetc(c, x.u.shf);
|
||||||
c = '\n';
|
c = '\n';
|
||||||
@ -758,13 +757,13 @@ expand(const char *cp, /* input word */
|
|||||||
if (c == 0 || (!quote && (f & DOBLANK) && doblank &&
|
if (c == 0 || (!quote && (f & DOBLANK) && doblank &&
|
||||||
!make_magic && ctype(c, C_IFS))) {
|
!make_magic && ctype(c, C_IFS))) {
|
||||||
/* How words are broken up:
|
/* How words are broken up:
|
||||||
* | value of c
|
* | value of c
|
||||||
* word | ws nws 0
|
* word | ws nws 0
|
||||||
* -----------------------------------
|
* -----------------------------------
|
||||||
* IFS_WORD w/WS w/NWS w
|
* IFS_WORD w/WS w/NWS w
|
||||||
* IFS_WS -/WS w/NWS -
|
* IFS_WS -/WS w/NWS -
|
||||||
* IFS_NWS -/NWS w/NWS w
|
* IFS_NWS -/NWS w/NWS w
|
||||||
* (w means generate a word)
|
* (w means generate a word)
|
||||||
* Note that IFS_NWS/0 generates a word (at&t ksh
|
* Note that IFS_NWS/0 generates a word (at&t ksh
|
||||||
* doesn't do this, but POSIX does).
|
* doesn't do this, but POSIX does).
|
||||||
*/
|
*/
|
||||||
@ -1183,7 +1182,7 @@ glob(char *cp, XPtrV *wp, int markdirs)
|
|||||||
#define GF_GLOBBED BIT(1) /* some globbing has been done */
|
#define GF_GLOBBED BIT(1) /* some globbing has been done */
|
||||||
#define GF_MARKDIR BIT(2) /* add trailing / to directories */
|
#define GF_MARKDIR BIT(2) /* add trailing / to directories */
|
||||||
|
|
||||||
/* Apply file globbing to cp and store the matching files in wp. Returns
|
/* Apply file globbing to cp and store the matching files in wp. Returns
|
||||||
* the number of matches found.
|
* the number of matches found.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -1295,7 +1294,7 @@ globit(XString *xs, /* dest string */
|
|||||||
int len;
|
int len;
|
||||||
int prefix_len;
|
int prefix_len;
|
||||||
|
|
||||||
/* xp = *xpp; copy_non_glob() may have re-alloc'd xs */
|
/* xp = *xpp; copy_non_glob() may have re-alloc'd xs */
|
||||||
*xp = '\0';
|
*xp = '\0';
|
||||||
prefix_len = Xlength(*xs, xp);
|
prefix_len = Xlength(*xs, xp);
|
||||||
dirp = opendir(prefix_len ? Xstring(*xs, xp) : ".");
|
dirp = opendir(prefix_len ? Xstring(*xs, xp) : ".");
|
||||||
@ -1356,7 +1355,7 @@ debunk(char *dp, const char *sp, size_t dlen)
|
|||||||
return (dp);
|
return (dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if p is an unquoted name, possibly followed by a / or :. If so
|
/* Check if p is an unquoted name, possibly followed by a / or :. If so
|
||||||
* puts the expanded version in *dcp,dp and returns a pointer in p just
|
* puts the expanded version in *dcp,dp and returns a pointer in p just
|
||||||
* past the name, otherwise returns 0.
|
* past the name, otherwise returns 0.
|
||||||
*/
|
*/
|
||||||
@ -1475,7 +1474,7 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
|
|||||||
/* no valid expansions... */
|
/* no valid expansions... */
|
||||||
if (!p || count != 0) {
|
if (!p || count != 0) {
|
||||||
/* Note that given a{{b,c} we do not expand anything (this is
|
/* Note that given a{{b,c} we do not expand anything (this is
|
||||||
* what at&t ksh does. This may be changed to do the {b,c}
|
* what at&t ksh does. This may be changed to do the {b,c}
|
||||||
* expansion. }
|
* expansion. }
|
||||||
*/
|
*/
|
||||||
if (fdo & DOGLOB)
|
if (fdo & DOGLOB)
|
||||||
|
74
exec.c
74
exec.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.57 2009/06/08 20:06:45 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.58 2009/06/10 18:12:45 tg Exp $");
|
||||||
|
|
||||||
static int comexec(struct op *, struct tbl *volatile, const char **,
|
static int comexec(struct op *, struct tbl *volatile, const char **,
|
||||||
int volatile, volatile int *);
|
int volatile, volatile int *);
|
||||||
@ -69,7 +69,7 @@ execute(struct op *volatile t,
|
|||||||
runtraps(0);
|
runtraps(0);
|
||||||
|
|
||||||
if (t->type == TCOM) {
|
if (t->type == TCOM) {
|
||||||
/* Clear subst_exstat before argument expansion. Used by
|
/* Clear subst_exstat before argument expansion. Used by
|
||||||
* null commands (see comexec() and c_eval()) and by c_set().
|
* null commands (see comexec() and c_eval()) and by c_set().
|
||||||
*/
|
*/
|
||||||
subst_exstat = 0;
|
subst_exstat = 0;
|
||||||
@ -136,10 +136,11 @@ execute(struct op *volatile t,
|
|||||||
while (t->type == TPIPE) {
|
while (t->type == TPIPE) {
|
||||||
openpipe(pv);
|
openpipe(pv);
|
||||||
ksh_dup2(pv[1], 1, false); /* stdout of curr */
|
ksh_dup2(pv[1], 1, false); /* stdout of curr */
|
||||||
/* Let exchild() close pv[0] in child
|
/**
|
||||||
|
* Let exchild() close pv[0] in child
|
||||||
* (if this isn't done, commands like
|
* (if this isn't done, commands like
|
||||||
* (: ; cat /etc/termcap) | sleep 1
|
* (: ; cat /etc/termcap) | sleep 1
|
||||||
* will hang forever).
|
* will hang forever).
|
||||||
*/
|
*/
|
||||||
exchild(t->left, flags | XPIPEO | XCCLOSE,
|
exchild(t->left, flags | XPIPEO | XCCLOSE,
|
||||||
NULL, pv[0]);
|
NULL, pv[0]);
|
||||||
@ -164,9 +165,8 @@ execute(struct op *volatile t,
|
|||||||
rv = execute(t, flags & XERROK, xerrok);
|
rv = execute(t, flags & XERROK, xerrok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TCOPROC:
|
case TCOPROC: {
|
||||||
{
|
sigset_t omask;
|
||||||
sigset_t omask;
|
|
||||||
|
|
||||||
/* Block sigchild as we are using things changed in the
|
/* Block sigchild as we are using things changed in the
|
||||||
* signal handler
|
* signal handler
|
||||||
@ -221,11 +221,11 @@ execute(struct op *volatile t,
|
|||||||
exchild(t->left, flags | XBGND | XFORK | XCOPROC | XCCLOSE,
|
exchild(t->left, flags | XBGND | XFORK | XCOPROC | XCCLOSE,
|
||||||
NULL, coproc.readw);
|
NULL, coproc.readw);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TASYNC:
|
case TASYNC:
|
||||||
/* XXX non-optimal, I think - "(foo &)", forks for (),
|
/* XXX non-optimal, I think - "(foo &)", forks for (),
|
||||||
* forks again for async... parent should optimise
|
* forks again for async... parent should optimise
|
||||||
* this to "foo &"...
|
* this to "foo &"...
|
||||||
*/
|
*/
|
||||||
rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK, xerrok);
|
rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK, xerrok);
|
||||||
@ -248,8 +248,7 @@ execute(struct op *volatile t,
|
|||||||
*xerrok = 1;
|
*xerrok = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TDBRACKET:
|
case TDBRACKET: {
|
||||||
{
|
|
||||||
Test_env te;
|
Test_env te;
|
||||||
|
|
||||||
te.flags = TEF_DBRACKET;
|
te.flags = TEF_DBRACKET;
|
||||||
@ -261,11 +260,10 @@ execute(struct op *volatile t,
|
|||||||
|
|
||||||
rv = test_parse(&te);
|
rv = test_parse(&te);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TFOR:
|
case TFOR:
|
||||||
case TSELECT:
|
case TSELECT: {
|
||||||
{
|
|
||||||
volatile bool is_first = true;
|
volatile bool is_first = true;
|
||||||
ap = (t->vars == NULL) ? e->loc->argv + 1 :
|
ap = (t->vars == NULL) ? e->loc->argv + 1 :
|
||||||
(const char **)eval((const char **)t->vars,
|
(const char **)eval((const char **)t->vars,
|
||||||
@ -301,8 +299,8 @@ execute(struct op *volatile t,
|
|||||||
rv = execute(t->left, flags & XERROK, xerrok);
|
rv = execute(t->left, flags & XERROK, xerrok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case TWHILE:
|
case TWHILE:
|
||||||
case TUNTIL:
|
case TUNTIL:
|
||||||
@ -426,16 +424,16 @@ comexec(struct op *t, struct tbl *volatile tp, const char **ap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Deal with the shell builtins builtin, exec and command since
|
/* Deal with the shell builtins builtin, exec and command since
|
||||||
* they can be followed by other commands. This must be done before
|
* they can be followed by other commands. This must be done before
|
||||||
* we know if we should create a local block which must be done
|
* we know if we should create a local block which must be done
|
||||||
* before we can do a path search (in case the assignments change
|
* before we can do a path search (in case the assignments change
|
||||||
* PATH).
|
* PATH).
|
||||||
* Odd cases:
|
* Odd cases:
|
||||||
* FOO=bar exec >/dev/null FOO is kept but not exported
|
* FOO=bar exec >/dev/null FOO is kept but not exported
|
||||||
* FOO=bar exec foobar FOO is exported
|
* FOO=bar exec foobar FOO is exported
|
||||||
* FOO=bar command exec >/dev/null FOO is neither kept nor exported
|
* FOO=bar command exec >/dev/null FOO is neither kept nor exported
|
||||||
* FOO=bar command FOO is neither kept nor exported
|
* FOO=bar command FOO is neither kept nor exported
|
||||||
* PATH=... foobar use new PATH in foobar search
|
* PATH=... foobar use new PATH in foobar search
|
||||||
*/
|
*/
|
||||||
keepasn_ok = 1;
|
keepasn_ok = 1;
|
||||||
while (tp && tp->type == CSHELL) {
|
while (tp && tp->type == CSHELL) {
|
||||||
@ -538,8 +536,7 @@ comexec(struct op *t, struct tbl *volatile tp, const char **ap,
|
|||||||
rv = call_builtin(tp, (const char **)ap);
|
rv = call_builtin(tp, (const char **)ap);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CFUNC: /* function call */
|
case CFUNC: { /* function call */
|
||||||
{
|
|
||||||
volatile char old_xflag;
|
volatile char old_xflag;
|
||||||
volatile Tflag old_inuse;
|
volatile Tflag old_inuse;
|
||||||
const char *volatile old_kshname;
|
const char *volatile old_kshname;
|
||||||
@ -618,8 +615,8 @@ comexec(struct op *t, struct tbl *volatile tp, const char **ap,
|
|||||||
kshname = old_kshname;
|
kshname = old_kshname;
|
||||||
Flag(FXTRACE) = old_xflag;
|
Flag(FXTRACE) = old_xflag;
|
||||||
tp->flag = (tp->flag & ~FINUSE) | old_inuse;
|
tp->flag = (tp->flag & ~FINUSE) | old_inuse;
|
||||||
/* Were we deleted while executing? If so, free the execution
|
/* Were we deleted while executing? If so, free the execution
|
||||||
* tree. todo: Unfortunately, the table entry is never re-used
|
* tree. todo: Unfortunately, the table entry is never re-used
|
||||||
* until the lookup table is expanded.
|
* until the lookup table is expanded.
|
||||||
*/
|
*/
|
||||||
if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) {
|
if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) {
|
||||||
@ -646,14 +643,14 @@ comexec(struct op *t, struct tbl *volatile tp, const char **ap,
|
|||||||
internal_errorf("CFUNC %d", i);
|
internal_errorf("CFUNC %d", i);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CEXEC: /* executable command */
|
case CEXEC: /* executable command */
|
||||||
case CTALIAS: /* tracked alias */
|
case CTALIAS: /* tracked alias */
|
||||||
if (!(tp->flag&ISSET)) {
|
if (!(tp->flag&ISSET)) {
|
||||||
/* errno_ will be set if the named command was found
|
/* errno_ will be set if the named command was found
|
||||||
* but could not be executed (permissions, no execute
|
* but could not be executed (permissions, no execute
|
||||||
* bit, directory, etc). Print out a (hopefully)
|
* bit, directory, etc). Print out a (hopefully)
|
||||||
* useful error message and set the exit status to 126.
|
* useful error message and set the exit status to 126.
|
||||||
*/
|
*/
|
||||||
if (tp->u2.errno_) {
|
if (tp->u2.errno_) {
|
||||||
@ -799,7 +796,7 @@ shcomexec(const char **wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Search function tables for a function. If create set, a table entry
|
* Search function tables for a function. If create set, a table entry
|
||||||
* is created if none is found.
|
* is created if none is found.
|
||||||
*/
|
*/
|
||||||
struct tbl *
|
struct tbl *
|
||||||
@ -824,7 +821,7 @@ findfunc(const char *name, unsigned int h, int create)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* define function. Returns 1 if function is being undefined (t == 0) and
|
* define function. Returns 1 if function is being undefined (t == 0) and
|
||||||
* function did not exist, returns 0 otherwise.
|
* function did not exist, returns 0 otherwise.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -1003,7 +1000,7 @@ flushcom(int all) /* just relative or all */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if path is something we want to find. Returns -1 for failure. */
|
/* Check if path is something we want to find. Returns -1 for failure. */
|
||||||
int
|
int
|
||||||
search_access(const char *lpath, int mode,
|
search_access(const char *lpath, int mode,
|
||||||
int *errnop) /* set if candidate found, but not suitable */
|
int *errnop) /* set if candidate found, but not suitable */
|
||||||
@ -1018,7 +1015,7 @@ search_access(const char *lpath, int mode,
|
|||||||
err = errno; /* File exists, but we can't access it */
|
err = errno; /* File exists, but we can't access it */
|
||||||
else if (mode == X_OK && (!S_ISREG(statb.st_mode) ||
|
else if (mode == X_OK && (!S_ISREG(statb.st_mode) ||
|
||||||
!(statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))) {
|
!(statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))) {
|
||||||
/* This 'cause access() says root can execute everything */
|
/* This 'cause access() says root can execute everything */
|
||||||
ret = -1;
|
ret = -1;
|
||||||
err = S_ISDIR(statb.st_mode) ? EISDIR : EACCES;
|
err = S_ISDIR(statb.st_mode) ? EISDIR : EACCES;
|
||||||
}
|
}
|
||||||
@ -1148,8 +1145,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
/* cp may have wrong name */
|
/* cp may have wrong name */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IODUP:
|
case IODUP: {
|
||||||
{
|
|
||||||
const char *emsg;
|
const char *emsg;
|
||||||
|
|
||||||
do_open = 0;
|
do_open = 0;
|
||||||
@ -1166,7 +1162,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
if (u == iop->unit)
|
if (u == iop->unit)
|
||||||
return (0); /* "dup from" == "dup to" */
|
return (0); /* "dup from" == "dup to" */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_open) {
|
if (do_open) {
|
||||||
@ -1194,7 +1190,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
e->savefd[iop->unit] = -1;
|
e->savefd[iop->unit] = -1;
|
||||||
else
|
else
|
||||||
/* c_exec() assumes e->savefd[fd] set for any
|
/* c_exec() assumes e->savefd[fd] set for any
|
||||||
* redirections. Ask savefd() not to close iop->unit;
|
* redirections. Ask savefd() not to close iop->unit;
|
||||||
* this allows error messages to be seen if iop->unit
|
* this allows error messages to be seen if iop->unit
|
||||||
* is 2; also means we can't lose the fd (eg, both
|
* is 2; also means we can't lose the fd (eg, both
|
||||||
* dup2 below and dup2 in restfd() failing).
|
* dup2 below and dup2 in restfd() failing).
|
||||||
@ -1296,7 +1292,7 @@ herein(const char *content, int sub)
|
|||||||
fd = errno;
|
fd = errno;
|
||||||
warningf(true, "error writing %s: %s, %s", h->name,
|
warningf(true, "error writing %s: %s, %s", h->name,
|
||||||
strerror(i), strerror(fd));
|
strerror(i), strerror(fd));
|
||||||
return (-2); /* special to iosetup(): don't print error */
|
return (-2); /* special to iosetup(): don't print error */
|
||||||
}
|
}
|
||||||
|
|
||||||
return (fd);
|
return (fd);
|
||||||
@ -1429,8 +1425,8 @@ pr_list(char *const *ap)
|
|||||||
* [[ ... ]] evaluation routines
|
* [[ ... ]] 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
|
* 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).
|
* TM_UNOP and TM_BINOP, the returned value is a Test_op).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
10
expr.c
10
expr.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.28 2009/06/08 20:13:07 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.29 2009/06/10 18:12:45 tg Exp $");
|
||||||
|
|
||||||
/* The order of these enums is constrained by the order of opinfo[] */
|
/* The order of these enums is constrained by the order of opinfo[] */
|
||||||
enum token {
|
enum token {
|
||||||
@ -79,7 +79,7 @@ struct opinfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Tokens in this table must be ordered so the longest are first
|
/* Tokens in this table must be ordered so the longest are first
|
||||||
* (eg, += before +). If you change something, change the order
|
* (eg, += before +). If you change something, change the order
|
||||||
* of enum token too.
|
* of enum token too.
|
||||||
*/
|
*/
|
||||||
static const struct opinfo opinfo[] = {
|
static const struct opinfo opinfo[] = {
|
||||||
@ -138,9 +138,9 @@ struct expr_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define bivui(x, op, y) (es->natural ? \
|
#define bivui(x, op, y) (es->natural ? \
|
||||||
(mksh_ari_t)((x)->val.u op (y)->val.u) : \
|
(mksh_ari_t)((x)->val.u op (y)->val.u) : \
|
||||||
(mksh_ari_t)((x)->val.i op (y)->val.i) \
|
(mksh_ari_t)((x)->val.i op (y)->val.i) \
|
||||||
)
|
)
|
||||||
#define chvui(x, op) do { \
|
#define chvui(x, op) do { \
|
||||||
if (es->natural) \
|
if (es->natural) \
|
||||||
(x)->val.u = op (x)->val.u; \
|
(x)->val.u = op (x)->val.u; \
|
||||||
|
79
funcs.c
79
funcs.c
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.113 2009/06/10 18:11:26 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.114 2009/06/10 18:12:46 tg Exp $");
|
||||||
|
|
||||||
#if HAVE_KILLPG
|
#if HAVE_KILLPG
|
||||||
/*
|
/*
|
||||||
@ -168,8 +168,7 @@ static const char *ptest_getopnd(Test_env *, Test_op, bool);
|
|||||||
static void ptest_error(Test_env *, int, const char *);
|
static void ptest_error(Test_env *, int, const char *);
|
||||||
static char *kill_fmt_entry(const void *, int, char *, int);
|
static char *kill_fmt_entry(const void *, int, char *, int);
|
||||||
static void p_time(struct shf *, bool, long, int, int,
|
static void p_time(struct shf *, bool, long, int, int,
|
||||||
const char *, const char *)
|
const char *, const char *) __attribute__((nonnull (6, 7)));
|
||||||
__attribute__((nonnull (6, 7)));
|
|
||||||
|
|
||||||
int
|
int
|
||||||
c_cd(const char **wp)
|
c_cd(const char **wp)
|
||||||
@ -465,8 +464,10 @@ c_print(const char **wp)
|
|||||||
*/
|
*/
|
||||||
case 'a': c = '\007'; break;
|
case 'a': c = '\007'; break;
|
||||||
case 'b': c = '\b'; break;
|
case 'b': c = '\b'; break;
|
||||||
case 'c': flags &= ~PO_NL;
|
case 'c':
|
||||||
continue; /* AT&T brain damage */
|
flags &= ~PO_NL;
|
||||||
|
/* AT&T brain damage */
|
||||||
|
continue;
|
||||||
case 'f': c = '\f'; break;
|
case 'f': c = '\f'; break;
|
||||||
case 'n': c = '\n'; break;
|
case 'n': c = '\n'; break;
|
||||||
case 'r': c = '\r'; break;
|
case 'r': c = '\r'; break;
|
||||||
@ -475,7 +476,7 @@ c_print(const char **wp)
|
|||||||
case '0':
|
case '0':
|
||||||
/* Look for an octal number: can have
|
/* Look for an octal number: can have
|
||||||
* three digits (not counting the
|
* three digits (not counting the
|
||||||
* leading 0). Truly burnt.
|
* leading 0). Truly burnt.
|
||||||
*/
|
*/
|
||||||
c = 0;
|
c = 0;
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
@ -559,7 +560,7 @@ c_print(const char **wp)
|
|||||||
int opipe = 0;
|
int opipe = 0;
|
||||||
|
|
||||||
/* Ensure we aren't killed by a SIGPIPE while writing to
|
/* Ensure we aren't killed by a SIGPIPE while writing to
|
||||||
* a coprocess. at&t ksh doesn't seem to do this (seems
|
* a coprocess. AT&T ksh doesn't seem to do this (seems
|
||||||
* to just check that the co-process is alive which is
|
* to just check that the co-process is alive which is
|
||||||
* not enough).
|
* not enough).
|
||||||
*/
|
*/
|
||||||
@ -624,7 +625,7 @@ c_whence(const char **wp)
|
|||||||
fcflags |= FC_DEFPATH;
|
fcflags |= FC_DEFPATH;
|
||||||
/* Convert command options to whence options - note that
|
/* Convert command options to whence options - note that
|
||||||
* command -pV uses a different path search than whence -v
|
* command -pV uses a different path search than whence -v
|
||||||
* or whence -pv. This should be considered a feature.
|
* or whence -pv. This should be considered a feature.
|
||||||
*/
|
*/
|
||||||
vflag = Vflag;
|
vflag = Vflag;
|
||||||
}
|
}
|
||||||
@ -710,7 +711,7 @@ c_whence(const char **wp)
|
|||||||
int
|
int
|
||||||
c_command(const char **wp)
|
c_command(const char **wp)
|
||||||
{
|
{
|
||||||
/* Let c_whence do the work. Note that c_command() must be
|
/* Let c_whence do the work. Note that c_command() must be
|
||||||
* a distinct function from c_whence() (tested in comexec()).
|
* a distinct function from c_whence() (tested in comexec()).
|
||||||
*/
|
*/
|
||||||
return (c_whence(wp));
|
return (c_whence(wp));
|
||||||
@ -752,7 +753,7 @@ c_typeset(const char **wp)
|
|||||||
builtin_opt.flags |= GF_PLUSOPT;
|
builtin_opt.flags |= GF_PLUSOPT;
|
||||||
/* at&t ksh seems to have 0-9 as options which are multiplied
|
/* at&t ksh seems to have 0-9 as options which are multiplied
|
||||||
* to get a number that is used with -L, -R, -Z or -i (eg, -1R2
|
* to get a number that is used with -L, -R, -Z or -i (eg, -1R2
|
||||||
* sets right justify in a field of 12). This allows options
|
* sets right justify in a field of 12). This allows options
|
||||||
* to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and
|
* to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and
|
||||||
* does not allow the number to be specified as a separate argument
|
* does not allow the number to be specified as a separate argument
|
||||||
* Here, the number must follow the RLZi option, but is optional
|
* Here, the number must follow the RLZi option, but is optional
|
||||||
@ -771,7 +772,7 @@ c_typeset(const char **wp)
|
|||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
/* at&t ksh uses u, but this conflicts with
|
/* at&t ksh uses u, but this conflicts with
|
||||||
* upper/lower case. If this option is changed,
|
* upper/lower case. If this option is changed,
|
||||||
* need to change the -U below as well
|
* need to change the -U below as well
|
||||||
*/
|
*/
|
||||||
flag = INT_U;
|
flag = INT_U;
|
||||||
@ -845,7 +846,7 @@ c_typeset(const char **wp)
|
|||||||
if (wp[builtin_opt.optind]) {
|
if (wp[builtin_opt.optind]) {
|
||||||
/* Take care of exclusions.
|
/* Take care of exclusions.
|
||||||
* At this point, flags in fset are cleared in fclr and vise
|
* At this point, flags in fset are cleared in fclr and vise
|
||||||
* versa. This property should be preserved.
|
* versa. This property should be preserved.
|
||||||
*/
|
*/
|
||||||
if (fset & LCASEV) /* LCASEV has priority over UCASEV_AL */
|
if (fset & LCASEV) /* LCASEV has priority over UCASEV_AL */
|
||||||
fset &= ~UCASEV_AL;
|
fset &= ~UCASEV_AL;
|
||||||
@ -1683,17 +1684,22 @@ c_umask(const char **wp)
|
|||||||
case 'r': new_val |= 04; break;
|
case 'r': new_val |= 04; break;
|
||||||
case 'w': new_val |= 02; break;
|
case 'w': new_val |= 02; break;
|
||||||
case 'x': new_val |= 01; break;
|
case 'x': new_val |= 01; break;
|
||||||
case 'u': new_val |= old_umask >> 6;
|
case 'u':
|
||||||
break;
|
new_val |= old_umask >> 6;
|
||||||
case 'g': new_val |= old_umask >> 3;
|
break;
|
||||||
break;
|
case 'g':
|
||||||
case 'o': new_val |= old_umask >> 0;
|
new_val |= old_umask >> 3;
|
||||||
break;
|
break;
|
||||||
case 'X': if (old_umask & 0111)
|
case 'o':
|
||||||
|
new_val |= old_umask >> 0;
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
if (old_umask & 0111)
|
||||||
new_val |= 01;
|
new_val |= 01;
|
||||||
break;
|
break;
|
||||||
case 's': /* ignored */
|
case 's':
|
||||||
break;
|
/* ignored */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
new_val = (new_val & 07) * positions;
|
new_val = (new_val & 07) * positions;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@ -1844,12 +1850,12 @@ c_read(const char **wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If we are reading from the co-process for the first time,
|
/* If we are reading from the co-process for the first time,
|
||||||
* make sure the other side of the pipe is closed first. This allows
|
* make sure the other side of the pipe is closed first. This allows
|
||||||
* the detection of eof.
|
* the detection of eof.
|
||||||
*
|
*
|
||||||
* This is not compatible with at&t ksh... the fd is kept so another
|
* This is not compatible with at&t ksh... the fd is kept so another
|
||||||
* coproc can be started with same output, however, this means eof
|
* coproc can be started with same output, however, this means eof
|
||||||
* can't be detected... This is why it is closed here.
|
* can't be detected... This is why it is closed here.
|
||||||
* If this call is removed, remove the eof check below, too.
|
* If this call is removed, remove the eof check below, too.
|
||||||
* coproc_readw_close(fd);
|
* coproc_readw_close(fd);
|
||||||
*/
|
*/
|
||||||
@ -1978,13 +1984,14 @@ c_eval(const char **wp)
|
|||||||
*
|
*
|
||||||
* A strict reading of POSIX says we don't do this (though
|
* A strict reading of POSIX says we don't do this (though
|
||||||
* it is traditionally done). [from 1003.2-1992]
|
* it is traditionally done). [from 1003.2-1992]
|
||||||
* 3.9.1: Simple Commands
|
*
|
||||||
|
* 3.9.1: Simple Commands
|
||||||
* ... If there is a command name, execution shall
|
* ... If there is a command name, execution shall
|
||||||
* continue as described in 3.9.1.1. If there
|
* continue as described in 3.9.1.1. If there
|
||||||
* is no command name, but the command contained a command
|
* is no command name, but the command contained a command
|
||||||
* substitution, the command shall complete with the exit
|
* substitution, the command shall complete with the exit
|
||||||
* status of the last command substitution
|
* status of the last command substitution
|
||||||
* 3.9.1.1: Command Search and Execution
|
* 3.9.1.1: Command Search and Execution
|
||||||
* ...(1)...(a) If the command name matches the name of
|
* ...(1)...(a) If the command name matches the name of
|
||||||
* a special built-in utility, that special built-in
|
* a special built-in utility, that special built-in
|
||||||
* utility shall be invoked.
|
* utility shall be invoked.
|
||||||
@ -2118,7 +2125,7 @@ c_brkcont(const char **wp)
|
|||||||
|
|
||||||
if (quit) {
|
if (quit) {
|
||||||
/* at&t ksh doesn't print a message - just does what it
|
/* at&t ksh doesn't print a message - just does what it
|
||||||
* can. We print a message 'cause it helps in debugging
|
* can. We print a message 'cause it helps in debugging
|
||||||
* scripts, but don't generate an error (ie, keep going).
|
* scripts, but don't generate an error (ie, keep going).
|
||||||
*/
|
*/
|
||||||
if (n == quit) {
|
if (n == quit) {
|
||||||
@ -2126,7 +2133,7 @@ c_brkcont(const char **wp)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
/* POSIX says if n is too big, the last enclosing loop
|
/* POSIX says if n is too big, the last enclosing loop
|
||||||
* shall be used. Doesn't say to print an error but we
|
* shall be used. Doesn't say to print an error but we
|
||||||
* do anyway 'cause the user messed up.
|
* do anyway 'cause the user messed up.
|
||||||
*/
|
*/
|
||||||
if (last_ep)
|
if (last_ep)
|
||||||
@ -2848,8 +2855,8 @@ test_primary(Test_env *te, bool do_eval)
|
|||||||
* Plain test (test and [ .. ]) specific routines.
|
* 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
|
* 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).
|
* TM_UNOP and TM_BINOP, the returned value is a Test_op).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -3084,11 +3091,11 @@ c_rename(const char **wp)
|
|||||||
{
|
{
|
||||||
int rv = 1;
|
int rv = 1;
|
||||||
|
|
||||||
if (wp == NULL /* argv */ ||
|
if (wp == NULL /* argv */ ||
|
||||||
wp[0] == NULL /* name of builtin */ ||
|
wp[0] == NULL /* name of builtin */ ||
|
||||||
wp[1] == NULL /* first argument */ ||
|
wp[1] == NULL /* first argument */ ||
|
||||||
wp[2] == NULL /* second argument */ ||
|
wp[2] == NULL /* second argument */ ||
|
||||||
wp[3] != NULL /* no further args please */)
|
wp[3] != NULL /* no further args please */)
|
||||||
bi_errorf(T_synerr);
|
bi_errorf(T_synerr);
|
||||||
else if ((rv = rename(wp[1], wp[2])) != 0) {
|
else if ((rv = rename(wp[1], wp[2])) != 0) {
|
||||||
rv = errno;
|
rv = errno;
|
||||||
|
17
histrap.c
17
histrap.c
@ -26,7 +26,7 @@
|
|||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.83 2009/06/08 20:06:46 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.84 2009/06/10 18:12:46 tg Exp $");
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* MirOS: This is the default mapping type, and need not be specified.
|
* MirOS: This is the default mapping type, and need not be specified.
|
||||||
@ -111,7 +111,7 @@ c_fc(const char **wp)
|
|||||||
case 's': /* posix version of -e - */
|
case 's': /* posix version of -e - */
|
||||||
sflag++;
|
sflag++;
|
||||||
break;
|
break;
|
||||||
/* kludge city - accept -num as -- -num (kind of) */
|
/* kludge city - accept -num as -- -num (kind of) */
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
p = shf_smprintf("-%c%s",
|
p = shf_smprintf("-%c%s",
|
||||||
@ -642,8 +642,9 @@ histsave(int *lnp, const char *cmd, bool dowrite __unused, bool ignoredups)
|
|||||||
/*
|
/*
|
||||||
* Open a history file
|
* Open a history file
|
||||||
* Format is:
|
* Format is:
|
||||||
* Bytes 1, 2: HMAGIC - just to check that we are dealing with
|
* Bytes 1, 2:
|
||||||
* the correct object
|
* HMAGIC - just to check that we are dealing with
|
||||||
|
* the correct object
|
||||||
* Then follows a number of stored commands
|
* Then follows a number of stored commands
|
||||||
* Each command is
|
* Each command is
|
||||||
* <command byte><command number(4 bytes)><bytes><null>
|
* <command byte><command number(4 bytes)><bytes><null>
|
||||||
@ -1196,7 +1197,7 @@ trap_pending(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* run any pending traps. If intr is set, only run traps that
|
* run any pending traps. If intr is set, only run traps that
|
||||||
* can interrupt commands.
|
* can interrupt commands.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -1363,7 +1364,7 @@ restore_pipe(int restore_dfl)
|
|||||||
setsig(&sigtraps[SIGPIPE], SIG_DFL, SS_RESTORE_CURR);
|
setsig(&sigtraps[SIGPIPE], SIG_DFL, SS_RESTORE_CURR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set action for a signal. Action may not be set if original
|
/* Set action for a signal. Action may not be set if original
|
||||||
* action was SIG_IGN, depending on the value of flags and FTALKING.
|
* action was SIG_IGN, depending on the value of flags and FTALKING.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -1374,7 +1375,7 @@ setsig(Trap *p, sig_t f, int flags)
|
|||||||
if (p->signal == SIGEXIT_ || p->signal == SIGERR_)
|
if (p->signal == SIGEXIT_ || p->signal == SIGERR_)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
/* First time setting this signal? If so, get and note the current
|
/* First time setting this signal? If so, get and note the current
|
||||||
* setting.
|
* setting.
|
||||||
*/
|
*/
|
||||||
if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) {
|
if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) {
|
||||||
@ -1395,7 +1396,7 @@ setsig(Trap *p, sig_t f, int flags)
|
|||||||
setexecsig(p, flags & SS_RESTORE_MASK);
|
setexecsig(p, flags & SS_RESTORE_MASK);
|
||||||
|
|
||||||
/* This is here 'cause there should be a way of clearing shtraps, but
|
/* This is here 'cause there should be a way of clearing shtraps, but
|
||||||
* don't know if this is a sane way of doing it. At the moment,
|
* don't know if this is a sane way of doing it. At the moment,
|
||||||
* all users of shtrap are lifetime users (SIGCHLD, SIGALRM, SIGWINCH).
|
* all users of shtrap are lifetime users (SIGCHLD, SIGALRM, SIGWINCH).
|
||||||
*/
|
*/
|
||||||
if (!(flags & SS_USER))
|
if (!(flags & SS_USER))
|
||||||
|
20
jobs.c
20
jobs.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.55 2009/06/08 20:34:40 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.56 2009/06/10 18:12:47 tg Exp $");
|
||||||
|
|
||||||
#if HAVE_KILLPG
|
#if HAVE_KILLPG
|
||||||
#define mksh_killpg killpg
|
#define mksh_killpg killpg
|
||||||
@ -720,7 +720,7 @@ j_resume(const char *cp, int bg)
|
|||||||
NULL);
|
NULL);
|
||||||
bi_errorf("1st tcsetpgrp(%d, %d) failed: %s",
|
bi_errorf("1st tcsetpgrp(%d, %d) failed: %s",
|
||||||
tty_fd,
|
tty_fd,
|
||||||
(int) ((j->flags & JF_SAVEDTTYPGRP) ?
|
(int)((j->flags & JF_SAVEDTTYPGRP) ?
|
||||||
j->saved_ttypgrp : j->pgrp),
|
j->saved_ttypgrp : j->pgrp),
|
||||||
strerror(rv));
|
strerror(rv));
|
||||||
return (1);
|
return (1);
|
||||||
@ -995,7 +995,7 @@ j_waitj(Job *j,
|
|||||||
if (Flag(FMONITOR) && ttypgrp_ok && j->pgrp) {
|
if (Flag(FMONITOR) && ttypgrp_ok && j->pgrp) {
|
||||||
/*
|
/*
|
||||||
* Save the tty's current pgrp so it can be restored
|
* Save the tty's current pgrp so it can be restored
|
||||||
* when the job is foregrounded. This is to
|
* when the job is foregrounded. This is to
|
||||||
* deal with things like the GNU su which does
|
* deal with things like the GNU su which does
|
||||||
* a fork/exec instead of an exec (the fork means
|
* a fork/exec instead of an exec (the fork means
|
||||||
* the execed shell gets a different pid from its
|
* the execed shell gets a different pid from its
|
||||||
@ -1019,7 +1019,7 @@ j_waitj(Job *j,
|
|||||||
#endif
|
#endif
|
||||||
if (tty_fd >= 0) {
|
if (tty_fd >= 0) {
|
||||||
/* Only restore tty settings if job was originally
|
/* Only restore tty settings if job was originally
|
||||||
* started in the foreground. Problems can be
|
* started in the foreground. Problems can be
|
||||||
* caused by things like 'more foobar &' which will
|
* caused by things like 'more foobar &' which will
|
||||||
* typically get and save the shell's vi/emacs tty
|
* typically get and save the shell's vi/emacs tty
|
||||||
* settings before setting up the tty for itself;
|
* settings before setting up the tty for itself;
|
||||||
@ -1032,7 +1032,7 @@ j_waitj(Job *j,
|
|||||||
} else {
|
} else {
|
||||||
tcsetattr(tty_fd, TCSADRAIN, &tty_state);
|
tcsetattr(tty_fd, TCSADRAIN, &tty_state);
|
||||||
/* Don't use tty mode if job is stopped and
|
/* Don't use tty mode if job is stopped and
|
||||||
* later restarted and exits. Consider
|
* later restarted and exits. Consider
|
||||||
* the sequence:
|
* the sequence:
|
||||||
* vi foo (stopped)
|
* vi foo (stopped)
|
||||||
* ...
|
* ...
|
||||||
@ -1048,7 +1048,7 @@ j_waitj(Job *j,
|
|||||||
}
|
}
|
||||||
#ifndef MKSH_UNEMPLOYED
|
#ifndef MKSH_UNEMPLOYED
|
||||||
/* If it looks like user hit ^C to kill a job, pretend we got
|
/* If it looks like user hit ^C to kill a job, pretend we got
|
||||||
* one too to break out of for loops, etc. (at&t ksh does this
|
* one too to break out of for loops, etc. (at&t ksh does this
|
||||||
* even when not monitoring, but this doesn't make sense since
|
* even when not monitoring, but this doesn't make sense since
|
||||||
* a tty generated ^C goes to the whole process group)
|
* a tty generated ^C goes to the whole process group)
|
||||||
*/
|
*/
|
||||||
@ -1155,7 +1155,7 @@ j_sigchld(int sig __unused)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Called only when a process in j has exited/stopped (ie, called only
|
* Called only when a process in j has exited/stopped (ie, called only
|
||||||
* from j_sigchld()). If no processes are running, the job status
|
* from j_sigchld()). If no processes are running, the job status
|
||||||
* and state are updated, asynchronous job notification is done and,
|
* and state are updated, asynchronous job notification is done and,
|
||||||
* if unneeded, the job is removed.
|
* if unneeded, the job is removed.
|
||||||
*
|
*
|
||||||
@ -1238,7 +1238,7 @@ check_job(Job *j)
|
|||||||
fd = ep->savefd[2];
|
fd = ep->savefd[2];
|
||||||
shf_reopen(fd, SHF_WR, shl_j);
|
shf_reopen(fd, SHF_WR, shl_j);
|
||||||
}
|
}
|
||||||
/* Can't call j_notify() as it removes jobs. The job
|
/* Can't call j_notify() as it removes jobs. The job
|
||||||
* must stay in the job list as j_waitj() may be
|
* must stay in the job list as j_waitj() may be
|
||||||
* running with this job.
|
* running with this job.
|
||||||
*/
|
*/
|
||||||
@ -1279,7 +1279,7 @@ j_print(Job *j, int how, struct shf *shf)
|
|||||||
|
|
||||||
if (how == JP_PGRP) {
|
if (how == JP_PGRP) {
|
||||||
/* POSIX doesn't say what to do it there is no process
|
/* POSIX doesn't say what to do it there is no process
|
||||||
* group leader (ie, !FMONITOR). We arbitrarily return
|
* group leader (ie, !FMONITOR). We arbitrarily return
|
||||||
* last pid (which is what $! returns).
|
* last pid (which is what $! returns).
|
||||||
*/
|
*/
|
||||||
shf_fprintf(shf, "%d\n", (int)(j->pgrp ? j->pgrp :
|
shf_fprintf(shf, "%d\n", (int)(j->pgrp ? j->pgrp :
|
||||||
@ -1287,7 +1287,7 @@ j_print(Job *j, int how, struct shf *shf)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
j->flags &= ~JF_CHANGED;
|
j->flags &= ~JF_CHANGED;
|
||||||
filler = j->job > 10 ? "\n " : "\n ";
|
filler = j->job > 10 ? "\n " : "\n ";
|
||||||
if (j == job_list)
|
if (j == job_list)
|
||||||
jobchar = '+';
|
jobchar = '+';
|
||||||
else if (j == job_list->next)
|
else if (j == job_list->next)
|
||||||
|
55
lex.c
55
lex.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.86 2009/06/08 20:06:47 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.87 2009/06/10 18:12:47 tg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* states while lexing word
|
* states while lexing word
|
||||||
@ -129,19 +129,19 @@ static int ignore_backslash_newline;
|
|||||||
|
|
||||||
#define STATE_BSIZE 32
|
#define STATE_BSIZE 32
|
||||||
|
|
||||||
#define PUSH_STATE(s) do { \
|
#define PUSH_STATE(s) do { \
|
||||||
if (++statep == state_info.end) \
|
if (++statep == state_info.end) \
|
||||||
statep = push_state_(&state_info, statep); \
|
statep = push_state_(&state_info, statep); \
|
||||||
state = statep->ls_state = (s); \
|
state = statep->ls_state = (s); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define POP_STATE() do { \
|
#define POP_STATE() do { \
|
||||||
if (--statep == state_info.base) \
|
if (--statep == state_info.base) \
|
||||||
statep = pop_state_(&state_info, statep); \
|
statep = pop_state_(&state_info, statep); \
|
||||||
state = statep->ls_state; \
|
state = statep->ls_state; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Lexical analyser
|
* Lexical analyser
|
||||||
*
|
*
|
||||||
* tokens are not regular expressions, they are LL(1).
|
* tokens are not regular expressions, they are LL(1).
|
||||||
@ -259,9 +259,9 @@ yylex(int cf)
|
|||||||
Source *s;
|
Source *s;
|
||||||
|
|
||||||
s = pushs(SREREAD,
|
s = pushs(SREREAD,
|
||||||
source->areap);
|
source->areap);
|
||||||
s->start = s->str
|
s->start = s->str =
|
||||||
= s->u.freeme = tmp;
|
s->u.freeme = tmp;
|
||||||
s->next = source;
|
s->next = source;
|
||||||
source = s;
|
source = s;
|
||||||
}
|
}
|
||||||
@ -655,7 +655,7 @@ yylex(int cf)
|
|||||||
/*(*/
|
/*(*/
|
||||||
if (c == ')') {
|
if (c == ')') {
|
||||||
if (statep->ls_sletparen.nparen > 0)
|
if (statep->ls_sletparen.nparen > 0)
|
||||||
--statep->ls_sletparen.nparen;
|
--statep->ls_sletparen.nparen;
|
||||||
/*(*/
|
/*(*/
|
||||||
else if ((c2 = getsc()) == ')') {
|
else if ((c2 = getsc()) == ')') {
|
||||||
c = 0;
|
c = 0;
|
||||||
@ -855,11 +855,11 @@ yylex(int cf)
|
|||||||
c = (c == ';') ? BREAK :
|
c = (c == ';') ? BREAK :
|
||||||
(c == '|') ? LOGOR :
|
(c == '|') ? LOGOR :
|
||||||
(c == '&') ? LOGAND :
|
(c == '&') ? LOGAND :
|
||||||
/*
|
/*
|
||||||
* this is the place where
|
* this is the place where
|
||||||
* ((...); (...))
|
* ((...); (...))
|
||||||
* and similar is broken
|
* and similar is broken
|
||||||
*/
|
*/
|
||||||
/* c == '(' ) */ MDPAREN;
|
/* c == '(' ) */ MDPAREN;
|
||||||
else if (c == '|' && c2 == '&')
|
else if (c == '|' && c2 == '&')
|
||||||
c = COPROC;
|
c = COPROC;
|
||||||
@ -1132,7 +1132,7 @@ getsc__(void)
|
|||||||
/* At this point, we need to keep the current
|
/* At this point, we need to keep the current
|
||||||
* alias in the source list so recursive
|
* alias in the source list so recursive
|
||||||
* aliases can be detected and we also need
|
* aliases can be detected and we also need
|
||||||
* to return the next character. Do this
|
* to return the next character. Do this
|
||||||
* by temporarily popping the alias to get
|
* by temporarily popping the alias to get
|
||||||
* the next character and then put it back
|
* the next character and then put it back
|
||||||
* in the source list with the SF_ALIASEND
|
* in the source list with the SF_ALIASEND
|
||||||
@ -1238,7 +1238,7 @@ getsc_line(Source *s)
|
|||||||
xp--; /* ...and move back again */
|
xp--; /* ...and move back again */
|
||||||
}
|
}
|
||||||
/* flush any unwanted input so other programs/builtins
|
/* flush any unwanted input so other programs/builtins
|
||||||
* can read it. Not very optimal, but less error prone
|
* can read it. Not very optimal, but less error prone
|
||||||
* than flushing else where, dealing with redirections,
|
* than flushing else where, dealing with redirections,
|
||||||
* etc..
|
* etc..
|
||||||
* todo: reduce size of shf buffer (~128?) if SSTDIN
|
* todo: reduce size of shf buffer (~128?) if SSTDIN
|
||||||
@ -1318,7 +1318,7 @@ set_prompt(int to, Source *s)
|
|||||||
if (sigsetjmp(e->jbuf, 0)) {
|
if (sigsetjmp(e->jbuf, 0)) {
|
||||||
prompt = safe_prompt;
|
prompt = safe_prompt;
|
||||||
/* Don't print an error - assume it has already
|
/* Don't print an error - assume it has already
|
||||||
* been printed. Reason is we may have forked
|
* been printed. Reason is we may have forked
|
||||||
* to run a command and the child may be
|
* to run a command and the child may be
|
||||||
* unwinding its stack through this code as it
|
* unwinding its stack through this code as it
|
||||||
* exits.
|
* exits.
|
||||||
@ -1404,10 +1404,9 @@ static char *
|
|||||||
get_brace_var(XString *wsp, char *wp)
|
get_brace_var(XString *wsp, char *wp)
|
||||||
{
|
{
|
||||||
enum parse_state {
|
enum parse_state {
|
||||||
PS_INITIAL, PS_SAW_HASH, PS_IDENT,
|
PS_INITIAL, PS_SAW_HASH, PS_IDENT,
|
||||||
PS_NUMBER, PS_VAR1, PS_END
|
PS_NUMBER, PS_VAR1, PS_END
|
||||||
}
|
} state;
|
||||||
state;
|
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
state = PS_INITIAL;
|
state = PS_INITIAL;
|
||||||
|
10
main.c
10
main.c
@ -33,7 +33,7 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.131 2009/06/08 20:06:47 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.132 2009/06/10 18:12:47 tg Exp $");
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
@ -189,13 +189,13 @@ main(int argc, const char *argv[])
|
|||||||
*/
|
*/
|
||||||
Flag(FNOHUP) = 1;
|
Flag(FNOHUP) = 1;
|
||||||
|
|
||||||
/* Turn on brace expansion by default. AT&T kshs that have
|
/* Turn on brace expansion by default. AT&T kshs that have
|
||||||
* alternation always have it on.
|
* alternation always have it on.
|
||||||
*/
|
*/
|
||||||
Flag(FBRACEEXPAND) = 1;
|
Flag(FBRACEEXPAND) = 1;
|
||||||
|
|
||||||
/* Set edit mode to emacs by default, may be overridden
|
/* Set edit mode to emacs by default, may be overridden
|
||||||
* by the environment or the user. Also, we want tab completion
|
* by the environment or the user. Also, we want tab completion
|
||||||
* on in vi by default. */
|
* on in vi by default. */
|
||||||
change_flag(FEMACS, OF_SPECIAL, 1);
|
change_flag(FEMACS, OF_SPECIAL, 1);
|
||||||
#ifndef MKSH_NOVI
|
#ifndef MKSH_NOVI
|
||||||
@ -535,7 +535,7 @@ shell(Source * volatile s, volatile int toplevel)
|
|||||||
wastty)
|
wastty)
|
||||||
s->type = SSTDIN;
|
s->type = SSTDIN;
|
||||||
/* Used by exit command to get back to
|
/* Used by exit command to get back to
|
||||||
* top level shell. Kind of strange since
|
* top level shell. Kind of strange since
|
||||||
* interactive is set if we are reading from
|
* interactive is set if we are reading from
|
||||||
* a tty, but to have stopped jobs, one only
|
* a tty, but to have stopped jobs, one only
|
||||||
* needs FMONITOR set (not FTALKING/SF_TTY)...
|
* needs FMONITOR set (not FTALKING/SF_TTY)...
|
||||||
@ -773,7 +773,7 @@ remove_temps(struct temp *tp)
|
|||||||
unlink(tp->name);
|
unlink(tp->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise tty_fd. Used for saving/reseting tty modes upon
|
/* Initialise tty_fd. Used for saving/reseting tty modes upon
|
||||||
* foreground job completion and for setting up tty process group.
|
* foreground job completion and for setting up tty process group.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
112
misc.c
112
misc.c
@ -29,7 +29,7 @@
|
|||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.109 2009/06/08 20:06:48 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.110 2009/06/10 18:12:48 tg Exp $");
|
||||||
|
|
||||||
#undef USE_CHVT
|
#undef USE_CHVT
|
||||||
#if defined(TIOCSCTTY) && !defined(MKSH_SMALL)
|
#if defined(TIOCSCTTY) && !defined(MKSH_SMALL)
|
||||||
@ -103,56 +103,56 @@ const struct shoption options[] = {
|
|||||||
* Options are sorted by their longnames - the order of these
|
* Options are sorted by their longnames - the order of these
|
||||||
* entries MUST match the order of sh_flag F* enumerations in sh.h.
|
* entries MUST match the order of sh_flag F* enumerations in sh.h.
|
||||||
*/
|
*/
|
||||||
{ "allexport", 'a', OF_ANY },
|
{ "allexport", 'a', OF_ANY },
|
||||||
#if HAVE_ARC4RANDOM
|
#if HAVE_ARC4RANDOM
|
||||||
{ "arc4random", 0, OF_ANY },
|
{ "arc4random", 0, OF_ANY },
|
||||||
#endif
|
#endif
|
||||||
{ "braceexpand", 0, OF_ANY }, /* non-standard */
|
{ "braceexpand", 0, OF_ANY }, /* non-standard */
|
||||||
#if HAVE_NICE
|
#if HAVE_NICE
|
||||||
{ "bgnice", 0, OF_ANY },
|
{ "bgnice", 0, OF_ANY },
|
||||||
#endif
|
#endif
|
||||||
{ NULL, 'c', OF_CMDLINE },
|
{ NULL, 'c', OF_CMDLINE },
|
||||||
{ "emacs", 0, OF_ANY },
|
{ "emacs", 0, OF_ANY },
|
||||||
{ "errexit", 'e', OF_ANY },
|
{ "errexit", 'e', OF_ANY },
|
||||||
{ "gmacs", 0, OF_ANY },
|
{ "gmacs", 0, OF_ANY },
|
||||||
{ "ignoreeof", 0, OF_ANY },
|
{ "ignoreeof", 0, OF_ANY },
|
||||||
{ "interactive",'i', OF_CMDLINE },
|
{ "interactive", 'i', OF_CMDLINE },
|
||||||
{ "keyword", 'k', OF_ANY },
|
{ "keyword", 'k', OF_ANY },
|
||||||
{ "login", 'l', OF_CMDLINE },
|
{ "login", 'l', OF_CMDLINE },
|
||||||
{ "markdirs", 'X', OF_ANY },
|
{ "markdirs", 'X', OF_ANY },
|
||||||
#ifndef MKSH_UNEMPLOYED
|
#ifndef MKSH_UNEMPLOYED
|
||||||
{ "monitor", 'm', OF_ANY },
|
{ "monitor", 'm', OF_ANY },
|
||||||
#else
|
#else
|
||||||
{ NULL, 'm', 0 }, /* needed */
|
{ NULL, 'm', 0 }, /* needed */
|
||||||
#endif
|
#endif
|
||||||
{ "noclobber", 'C', OF_ANY },
|
{ "noclobber", 'C', OF_ANY },
|
||||||
{ "noexec", 'n', OF_ANY },
|
{ "noexec", 'n', OF_ANY },
|
||||||
{ "noglob", 'f', OF_ANY },
|
{ "noglob", 'f', OF_ANY },
|
||||||
{ "nohup", 0, OF_ANY },
|
{ "nohup", 0, OF_ANY },
|
||||||
{ "nolog", 0, OF_ANY }, /* no effect */
|
{ "nolog", 0, OF_ANY }, /* no effect */
|
||||||
#ifndef MKSH_UNEMPLOYED
|
#ifndef MKSH_UNEMPLOYED
|
||||||
{ "notify", 'b', OF_ANY },
|
{ "notify", 'b', OF_ANY },
|
||||||
#endif
|
#endif
|
||||||
{ "nounset", 'u', OF_ANY },
|
{ "nounset", 'u', OF_ANY },
|
||||||
{ "physical", 0, OF_ANY }, /* non-standard */
|
{ "physical", 0, OF_ANY }, /* non-standard */
|
||||||
{ "posix", 0, OF_ANY }, /* non-standard */
|
{ "posix", 0, OF_ANY }, /* non-standard */
|
||||||
{ "privileged", 'p', OF_ANY },
|
{ "privileged", 'p', OF_ANY },
|
||||||
{ "restricted", 'r', OF_CMDLINE },
|
{ "restricted", 'r', OF_CMDLINE },
|
||||||
{ "stdin", 's', OF_CMDLINE }, /* pseudo non-standard */
|
{ "stdin", 's', OF_CMDLINE }, /* pseudo non-st.. */
|
||||||
{ "trackall", 'h', OF_ANY },
|
{ "trackall", 'h', OF_ANY },
|
||||||
{ "utf8-mode", 'U', OF_ANY }, /* non-standard */
|
{ "utf8-mode", 'U', OF_ANY }, /* non-standard */
|
||||||
{ "verbose", 'v', OF_ANY },
|
{ "verbose", 'v', OF_ANY },
|
||||||
#ifndef MKSH_NOVI
|
#ifndef MKSH_NOVI
|
||||||
{ "vi", 0, OF_ANY },
|
{ "vi", 0, OF_ANY },
|
||||||
{ "viraw", 0, OF_ANY }, /* no effect */
|
{ "viraw", 0, OF_ANY }, /* no effect */
|
||||||
{ "vi-tabcomplete", 0, OF_ANY }, /* non-standard */
|
{ "vi-tabcomplete", 0, OF_ANY }, /* non-standard */
|
||||||
{ "vi-esccomplete", 0, OF_ANY }, /* non-standard */
|
{ "vi-esccomplete", 0, OF_ANY }, /* non-standard */
|
||||||
#endif
|
#endif
|
||||||
{ "xtrace", 'x', OF_ANY },
|
{ "xtrace", 'x', OF_ANY },
|
||||||
/* Anonymous flags: used internally by shell only
|
/* Anonymous flags: used internally by shell only
|
||||||
* (not visible to user)
|
* (not visible to user)
|
||||||
*/
|
*/
|
||||||
{ NULL, 0, OF_INTERNAL }, /* FTALKING_I */
|
{ NULL, 0, OF_INTERNAL }, /* FTALKING_I */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -287,7 +287,7 @@ change_flag(enum sh_flag f,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse command line & set command arguments. returns the index of
|
/* Parse command line & set command arguments. Returns the index of
|
||||||
* non-option arguments, -1 if there is an error.
|
* non-option arguments, -1 if there is an error.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -303,7 +303,7 @@ parse_args(const char **argv,
|
|||||||
size_t i;
|
size_t i;
|
||||||
int optc, sortargs = 0, arrayset = 0;
|
int optc, sortargs = 0, arrayset = 0;
|
||||||
|
|
||||||
/* First call? Build option strings... */
|
/* First call? Build option strings... */
|
||||||
if (cmd_opts[0] == '\0') {
|
if (cmd_opts[0] == '\0') {
|
||||||
char *p = cmd_opts, *q = set_opts;
|
char *p = cmd_opts, *q = set_opts;
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ parse_args(const char **argv,
|
|||||||
if ((i != (size_t)-1) && set == Flag(i))
|
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"
|
* isn't changing - makes "set -o interactive"
|
||||||
* work if you're already interactive. Needed
|
* work if you're already interactive. Needed
|
||||||
* if the output of "set +o" is to be used.
|
* if the output of "set +o" is to be used.
|
||||||
*/
|
*/
|
||||||
;
|
;
|
||||||
@ -521,7 +521,7 @@ gmatchx(const char *s, const char *p, bool isfile)
|
|||||||
se = s + strlen(s);
|
se = s + strlen(s);
|
||||||
pe = p + strlen(p);
|
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().
|
* the pattern. If check fails, just to a strcmp().
|
||||||
*/
|
*/
|
||||||
if (!isfile && !has_globbing(p, pe)) {
|
if (!isfile && !has_globbing(p, pe)) {
|
||||||
size_t len = pe - p + 1;
|
size_t len = pe - p + 1;
|
||||||
@ -644,10 +644,10 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
|
|||||||
} while (s++ < se);
|
} while (s++ < se);
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* [*+?@!](pattern|pattern|..)
|
* [*+?@!](pattern|pattern|..)
|
||||||
* This is also needed for ${..%..}, etc.
|
* This is also needed for ${..%..}, etc.
|
||||||
*/
|
*/
|
||||||
case 0x80|'+': /* matches one or more times */
|
case 0x80|'+': /* matches one or more times */
|
||||||
case 0x80|'*': /* matches zero or more times */
|
case 0x80|'*': /* matches zero or more times */
|
||||||
if (!(prest = pat_scan(p, pe, 0)))
|
if (!(prest = pat_scan(p, pe, 0)))
|
||||||
@ -822,11 +822,11 @@ ksh_getopt_reset(Getopt *go, int flags)
|
|||||||
* the option is missing).
|
* the option is missing).
|
||||||
* Used for 'read -u2', 'print -u2' and fc -40.
|
* Used for 'read -u2', 'print -u2' and fc -40.
|
||||||
* - '#' is like ':' in options, expect that the argument is optional
|
* - '#' is like ':' in options, expect that the argument is optional
|
||||||
* and must start with a digit. If the argument doesn't start with a
|
* and must start with a digit. If the argument doesn't start with a
|
||||||
* digit, it is assumed to be missing and normal option processing
|
* digit, it is assumed to be missing and normal option processing
|
||||||
* continues (optarg is set to 0 if the option is missing).
|
* continues (optarg is set to 0 if the option is missing).
|
||||||
* Used for 'typeset -LZ4'.
|
* Used for 'typeset -LZ4'.
|
||||||
* - accepts +c as well as -c IF the GF_PLUSOPT flag is present. If an
|
* - accepts +c as well as -c IF the GF_PLUSOPT flag is present. If an
|
||||||
* option starting with + is accepted, the GI_PLUS flag will be set
|
* option starting with + is accepted, the GI_PLUS flag will be set
|
||||||
* in go->info.
|
* in go->info.
|
||||||
*/
|
*/
|
||||||
@ -904,7 +904,7 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
|
|||||||
go->p = 0;
|
go->p = 0;
|
||||||
} else if (*o == '#') {
|
} 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
|
* but must start with a digit. optarg is set to 0 if the
|
||||||
* argument is missing.
|
* argument is missing.
|
||||||
*/
|
*/
|
||||||
if (argv[go->optind - 1][go->p]) {
|
if (argv[go->optind - 1][go->p]) {
|
||||||
@ -973,7 +973,7 @@ print_columns(struct shf *shf, int n,
|
|||||||
if (x_cols < MIN_COLS)
|
if (x_cols < MIN_COLS)
|
||||||
change_winsz();
|
change_winsz();
|
||||||
|
|
||||||
/* max_width + 1 for the space. Note that no space
|
/* max_width + 1 for the space. Note that no space
|
||||||
* is printed after the last column to avoid problems
|
* is printed after the last column to avoid problems
|
||||||
* with terminals that have auto-wrap.
|
* with terminals that have auto-wrap.
|
||||||
*/
|
*/
|
||||||
@ -1204,13 +1204,13 @@ simplify_path(char *pathl)
|
|||||||
very_start++;
|
very_start++;
|
||||||
|
|
||||||
/* Before After
|
/* Before After
|
||||||
* /foo/ /foo
|
* /foo/ /foo
|
||||||
* /foo/../../bar /bar
|
* /foo/../../bar /bar
|
||||||
* /foo/./blah/.. /foo
|
* /foo/./blah/.. /foo
|
||||||
* . .
|
* . .
|
||||||
* .. ..
|
* .. ..
|
||||||
* ./foo foo
|
* ./foo foo
|
||||||
* foo/../../../bar ../../bar
|
* foo/../../../bar ../../bar
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (cur = t = start = very_start; ; ) {
|
for (cur = t = start = very_start; ; ) {
|
||||||
|
15
setmode.c
15
setmode.c
@ -1,4 +1,3 @@
|
|||||||
/** $MirOS: src/bin/mksh/setmode.c,v 1.12 2009/04/07 18:41:37 tg Rel $ */
|
|
||||||
/* $OpenBSD: setmode.c,v 1.17 2005/08/08 08:05:34 espie Exp $ */
|
/* $OpenBSD: setmode.c,v 1.17 2005/08/08 08:05:34 espie Exp $ */
|
||||||
/* $NetBSD: setmode.c,v 1.15 1997/02/07 22:21:06 christos Exp $ */
|
/* $NetBSD: setmode.c,v 1.15 1997/02/07 22:21:06 christos Exp $ */
|
||||||
|
|
||||||
@ -57,13 +56,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
__SCCSID("@(#)setmode.c 8.2 (Berkeley) 3/25/94");
|
__SCCSID("@(#)setmode.c 8.2 (Berkeley) 3/25/94");
|
||||||
__RCSID("$MirOS: src/bin/mksh/setmode.c,v 1.12 2009/04/07 18:41:37 tg Rel $");
|
__RCSID("$MirOS: src/bin/mksh/setmode.c,v 1.14 2009/06/10 18:12:48 tg Rel $");
|
||||||
__RCSID("$miros: src/lib/libc/gen/setmode.c,v 1.12 2009/06/10 18:12:42 tg Exp $");
|
__RCSID("$miros: src/lib/libc/gen/setmode.c,v 1.12 2009/06/10 18:12:42 tg Exp $");
|
||||||
|
|
||||||
/* for mksh */
|
/* for mksh */
|
||||||
#ifdef ksh_isdigit
|
#ifdef ksh_isdigit
|
||||||
#undef isdigit
|
#undef isdigit
|
||||||
#define isdigit ksh_isdigit
|
#define isdigit ksh_isdigit
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef S_ISTXT
|
#ifndef S_ISTXT
|
||||||
@ -110,7 +109,7 @@ getmode(const void *bbox, mode_t omode)
|
|||||||
/*
|
/*
|
||||||
* When copying the user, group or other bits around, we "know"
|
* When copying the user, group or other bits around, we "know"
|
||||||
* where the bits are in the mode so that we can do shifts to
|
* where the bits are in the mode so that we can do shifts to
|
||||||
* copy them around. If we don't use shifts, it gets real
|
* copy them around. If we don't use shifts, it gets real
|
||||||
* grundgy with lots of single bit checks and bit sets.
|
* grundgy with lots of single bit checks and bit sets.
|
||||||
*/
|
*/
|
||||||
case 'u':
|
case 'u':
|
||||||
@ -126,7 +125,7 @@ getmode(const void *bbox, mode_t omode)
|
|||||||
common:
|
common:
|
||||||
if (set->cmd2 & CMD2_CLR) {
|
if (set->cmd2 & CMD2_CLR) {
|
||||||
clrval =
|
clrval =
|
||||||
(set->cmd2 & CMD2_SET) ? S_IRWXO : value;
|
(set->cmd2 & CMD2_SET) ? S_IRWXO : value;
|
||||||
if (set->cmd2 & CMD2_UBITS)
|
if (set->cmd2 & CMD2_UBITS)
|
||||||
newmode &= ~((clrval<<6) & set->bits);
|
newmode &= ~((clrval<<6) & set->bits);
|
||||||
if (set->cmd2 & CMD2_GBITS)
|
if (set->cmd2 & CMD2_GBITS)
|
||||||
@ -199,7 +198,7 @@ setmode(const char *p)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a copy of the mask for the permissions that are mask relative.
|
* Get a copy of the mask for the permissions that are mask relative.
|
||||||
* Flip the bits, we want what's not set. Since it's possible that
|
* Flip the bits, we want what's not set. Since it's possible that
|
||||||
* the caller is opening files inside a signal handler, protect them
|
* the caller is opening files inside a signal handler, protect them
|
||||||
* as best we can.
|
* as best we can.
|
||||||
*/
|
*/
|
||||||
@ -420,8 +419,8 @@ dumpmode(BITCMD *set)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Given an array of bitcmd structures, compress by compacting consecutive
|
* Given an array of bitcmd structures, compress by compacting consecutive
|
||||||
* '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
|
* '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
|
||||||
* 'g' and 'o' commands continue to be separate. They could probably be
|
* 'g' and 'o' commands continue to be separate. They could probably be
|
||||||
* compacted, but it's not worth the effort.
|
* compacted, but it's not worth the effort.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
|
18
sh.h
18
sh.h
@ -122,7 +122,7 @@
|
|||||||
#define __SCCSID(x) __IDSTRING(sccsid,x)
|
#define __SCCSID(x) __IDSTRING(sccsid,x)
|
||||||
|
|
||||||
#ifdef EXTERN
|
#ifdef EXTERN
|
||||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.309 2009/06/10 18:11:27 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.310 2009/06/10 18:12:48 tg Rel $");
|
||||||
#endif
|
#endif
|
||||||
#define MKSH_VERSION "R38 2009/06/10"
|
#define MKSH_VERSION "R38 2009/06/10"
|
||||||
|
|
||||||
@ -667,11 +667,11 @@ EXTERN int really_exit;
|
|||||||
*/
|
*/
|
||||||
#define C_ALPHA BIT(0) /* a-z_A-Z */
|
#define C_ALPHA BIT(0) /* a-z_A-Z */
|
||||||
#define C_DIGIT BIT(1) /* 0-9 */
|
#define C_DIGIT BIT(1) /* 0-9 */
|
||||||
#define C_LEX1 BIT(2) /* \0 \t\n|&;<>() */
|
#define C_LEX1 BIT(2) /* \t \n\0|&;<>() */
|
||||||
#define C_VAR1 BIT(3) /* *@#!$-? */
|
#define C_VAR1 BIT(3) /* *@#!$-? */
|
||||||
#define C_IFSWS BIT(4) /* \t \n (IFS white space) */
|
#define C_IFSWS BIT(4) /* \t \n (IFS white space) */
|
||||||
#define C_SUBOP1 BIT(5) /* "=-+?" */
|
#define C_SUBOP1 BIT(5) /* "=-+?" */
|
||||||
#define C_QUOTE BIT(6) /* \n\t"#$&'()*;<>?[]\`| (needing quoting) */
|
#define C_QUOTE BIT(6) /* \t \n"#$&'()*;<>?[]\`| (needing quoting) */
|
||||||
#define C_IFS BIT(7) /* $IFS */
|
#define C_IFS BIT(7) /* $IFS */
|
||||||
#define C_SUBOP2 BIT(8) /* "#%" (magic, see below) */
|
#define C_SUBOP2 BIT(8) /* "#%" (magic, see below) */
|
||||||
|
|
||||||
@ -885,8 +885,8 @@ struct tbl { /* table item */
|
|||||||
/* Attributes that can be set by the user (used to decide if an unset param
|
/* Attributes that can be set by the user (used to decide if an unset param
|
||||||
* should be repoted by set/typeset). Does not include ARRAY or LOCAL.
|
* should be repoted by set/typeset). Does not include ARRAY or LOCAL.
|
||||||
*/
|
*/
|
||||||
#define USERATTRIB (EXPORT|INTEGER|RDONLY|LJUST|RJUST|ZEROFIL\
|
#define USERATTRIB (EXPORT|INTEGER|RDONLY|LJUST|RJUST|ZEROFIL|\
|
||||||
|LCASEV|UCASEV_AL|INT_U|INT_L)
|
LCASEV|UCASEV_AL|INT_U|INT_L)
|
||||||
|
|
||||||
/* command types */
|
/* command types */
|
||||||
#define CNONE 0 /* undefined */
|
#define CNONE 0 /* undefined */
|
||||||
@ -1215,10 +1215,10 @@ struct source {
|
|||||||
const char *str; /* input pointer */
|
const char *str; /* input pointer */
|
||||||
const char *start; /* start of current buffer */
|
const char *start; /* start of current buffer */
|
||||||
union {
|
union {
|
||||||
const char **strv; /* string [] */
|
const char **strv; /* string [] */
|
||||||
struct shf *shf; /* shell file */
|
struct shf *shf; /* shell file */
|
||||||
struct tbl *tblp; /* alias (SF_HASALIAS) */
|
struct tbl *tblp; /* alias (SF_HASALIAS) */
|
||||||
char *freeme; /* also for SREREAD */
|
char *freeme; /* also for SREREAD */
|
||||||
} u;
|
} u;
|
||||||
const char *file; /* input file name */
|
const char *file; /* input file name */
|
||||||
int type; /* input type */
|
int type; /* input type */
|
||||||
|
61
shf.c
61
shf.c
@ -22,14 +22,14 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.29 2009/06/08 20:06:49 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.30 2009/06/10 18:12:49 tg Exp $");
|
||||||
|
|
||||||
/* flags to shf_emptybuf() */
|
/* flags to shf_emptybuf() */
|
||||||
#define EB_READSW 0x01 /* about to switch to reading */
|
#define EB_READSW 0x01 /* about to switch to reading */
|
||||||
#define EB_GROW 0x02 /* grow buffer if necessary (STRING+DYNAMIC) */
|
#define EB_GROW 0x02 /* grow buffer if necessary (STRING+DYNAMIC) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replacement stdio routines. Stdio is too flakey on too many machines
|
* Replacement stdio routines. Stdio is too flakey on too many machines
|
||||||
* to be useful when you have multiple processes using the same underlying
|
* to be useful when you have multiple processes using the same underlying
|
||||||
* file descriptors.
|
* file descriptors.
|
||||||
*/
|
*/
|
||||||
@ -37,8 +37,8 @@ __RCSID("$MirOS: src/bin/mksh/shf.c,v 1.29 2009/06/08 20:06:49 tg Exp $");
|
|||||||
static int shf_fillbuf(struct shf *);
|
static int shf_fillbuf(struct shf *);
|
||||||
static int shf_emptybuf(struct shf *, int);
|
static int shf_emptybuf(struct shf *, int);
|
||||||
|
|
||||||
/* Open a file. First three args are for open(), last arg is flags for
|
/* Open a file. First three args are for open(), last arg is flags for
|
||||||
* this package. Returns NULL if file could not be opened, or if a dup
|
* this package. Returns NULL if file could not be opened, or if a dup
|
||||||
* fails.
|
* fails.
|
||||||
*/
|
*/
|
||||||
struct shf *
|
struct shf *
|
||||||
@ -79,7 +79,7 @@ shf_open(const char *name, int oflags, int mode, int sflags)
|
|||||||
return (shf_reopen(fd, sflags, shf));
|
return (shf_reopen(fd, sflags, shf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the shf structure for a file descriptor. Doesn't fail. */
|
/* Set up the shf structure for a file descriptor. Doesn't fail. */
|
||||||
struct shf *
|
struct shf *
|
||||||
shf_fdopen(int fd, int sflags, struct shf *shf)
|
shf_fdopen(int fd, int sflags, struct shf *shf)
|
||||||
{
|
{
|
||||||
@ -183,12 +183,12 @@ shf_reopen(int fd, int sflags, struct shf *shf)
|
|||||||
return (shf);
|
return (shf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a string for reading or writing. If reading, bsize is the number
|
/* Open a string for reading or writing. If reading, bsize is the number
|
||||||
* of bytes that can be read. If writing, bsize is the maximum number of
|
* of bytes that can be read. If writing, bsize is the maximum number of
|
||||||
* bytes that can be written. If shf is not null, it is filled in and
|
* bytes that can be written. If shf is not null, it is filled in and
|
||||||
* returned, if it is null, shf is allocated. If writing and buf is null
|
* returned, if it is null, shf is allocated. If writing and buf is null
|
||||||
* and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is
|
* and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is
|
||||||
* used for the initial size). Doesn't fail.
|
* used for the initial size). Doesn't fail.
|
||||||
* When writing, a byte is reserved for a trailing null - see shf_sclose().
|
* When writing, a byte is reserved for a trailing null - see shf_sclose().
|
||||||
*/
|
*/
|
||||||
struct shf *
|
struct shf *
|
||||||
@ -280,7 +280,7 @@ shf_sclose(struct shf *shf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Un-read what has been read but not examined, or write what has been
|
/* Un-read what has been read but not examined, or write what has been
|
||||||
* buffered. Returns 0 for success, EOF for (write) error.
|
* buffered. Returns 0 for success, EOF for (write) error.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
shf_flush(struct shf *shf)
|
shf_flush(struct shf *shf)
|
||||||
@ -310,8 +310,8 @@ shf_flush(struct shf *shf)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write out any buffered data. If currently reading, flushes the read
|
/* Write out any buffered data. If currently reading, flushes the read
|
||||||
* buffer. Returns 0 for success, EOF for (write) error.
|
* buffer. Returns 0 for success, EOF for (write) error.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
shf_emptybuf(struct shf *shf, int flags)
|
shf_emptybuf(struct shf *shf, int flags)
|
||||||
@ -391,7 +391,7 @@ shf_emptybuf(struct shf *shf, int flags)
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill up a read buffer. Returns EOF for a read error, 0 otherwise. */
|
/* Fill up a read buffer. Returns EOF for a read error, 0 otherwise. */
|
||||||
static int
|
static int
|
||||||
shf_fillbuf(struct shf *shf)
|
shf_fillbuf(struct shf *shf)
|
||||||
{
|
{
|
||||||
@ -434,7 +434,7 @@ shf_fillbuf(struct shf *shf)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read a buffer from shf. Returns the number of bytes read into buf,
|
/* Read a buffer from shf. Returns the number of bytes read into buf,
|
||||||
* if no bytes were read, returns 0 if end of file was seen, EOF if
|
* if no bytes were read, returns 0 if end of file was seen, EOF if
|
||||||
* a read error occurred.
|
* a read error occurred.
|
||||||
*/
|
*/
|
||||||
@ -468,8 +468,8 @@ shf_read(char *buf, int bsize, struct shf *shf)
|
|||||||
orig_bsize - bsize);
|
orig_bsize - bsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read up to a newline or EOF. The newline is put in buf; buf is always
|
/* Read up to a newline or EOF. The newline is put in buf; buf is always
|
||||||
* null terminated. Returns NULL on read error or if nothing was read before
|
* null terminated. Returns NULL on read error or if nothing was read before
|
||||||
* end of file, returns a pointer to the null byte in buf otherwise.
|
* end of file, returns a pointer to the null byte in buf otherwise.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
@ -510,7 +510,7 @@ shf_getse(char *buf, int bsize, struct shf *shf)
|
|||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the char read. Returns EOF for error and end of file. */
|
/* Returns the char read. Returns EOF for error and end of file. */
|
||||||
int
|
int
|
||||||
shf_getchar(struct shf *shf)
|
shf_getchar(struct shf *shf)
|
||||||
{
|
{
|
||||||
@ -523,7 +523,7 @@ shf_getchar(struct shf *shf)
|
|||||||
return (*shf->rp++);
|
return (*shf->rp++);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put a character back in the input stream. Returns the character if
|
/* Put a character back in the input stream. Returns the character if
|
||||||
* successful, EOF if there is no room.
|
* successful, EOF if there is no room.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -558,7 +558,7 @@ shf_ungetc(int c, struct shf *shf)
|
|||||||
return (c);
|
return (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a character. Returns the character if successful, EOF if
|
/* Write a character. Returns the character if successful, EOF if
|
||||||
* the char could not be written.
|
* the char could not be written.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -600,7 +600,7 @@ shf_putchar(int c, struct shf *shf)
|
|||||||
return (c);
|
return (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a string. Returns the length of the string if successful, EOF if
|
/* Write a string. Returns the length of the string if successful, EOF if
|
||||||
* the string could not be written.
|
* the string could not be written.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -612,7 +612,7 @@ shf_puts(const char *s, struct shf *shf)
|
|||||||
return (shf_write(s, strlen(s), shf));
|
return (shf_write(s, strlen(s), shf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a buffer. Returns nbytes if successful, EOF if there is an error. */
|
/* Write a buffer. Returns nbytes if successful, EOF if there is an error. */
|
||||||
int
|
int
|
||||||
shf_write(const char *buf, int nbytes, struct shf *shf)
|
shf_write(const char *buf, int nbytes, struct shf *shf)
|
||||||
{
|
{
|
||||||
@ -761,11 +761,11 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* This will accept flags/fields in any order - not
|
* This will accept flags/fields in any order - not
|
||||||
* just the order specified in printf(3), but this is
|
* just the order specified in printf(3), but this is
|
||||||
* the way _doprnt() seems to work (on bsd and sysV).
|
* the way _doprnt() seems to work (on bsd and sysV).
|
||||||
* The only restriction is that the format character must
|
* The only restriction is that the format character must
|
||||||
* come last :-).
|
* come last :-).
|
||||||
*/
|
*/
|
||||||
flags = field = precision = 0;
|
flags = field = precision = 0;
|
||||||
for ( ; (c = *fmt++) ; ) {
|
for ( ; (c = *fmt++) ; ) {
|
||||||
@ -861,7 +861,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
|
|||||||
* For shorts, we want sign extend for %d but not
|
* For shorts, we want sign extend for %d but not
|
||||||
* for %[oxu] - on 16 bit machines it doesn't matter.
|
* for %[oxu] - on 16 bit machines it doesn't matter.
|
||||||
* Assumes C compiler has converted shorts to ints
|
* Assumes C compiler has converted shorts to ints
|
||||||
* before pushing them. XXX optimise this -tg
|
* before pushing them. XXX optimise this -tg
|
||||||
*/
|
*/
|
||||||
if (flags & FL_LONG)
|
if (flags & FL_LONG)
|
||||||
lnum = va_arg(args, unsigned long);
|
lnum = va_arg(args, unsigned long);
|
||||||
@ -905,8 +905,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'x':
|
case 'x': {
|
||||||
{
|
|
||||||
const char *digits = (flags & FL_UPPER) ?
|
const char *digits = (flags & FL_UPPER) ?
|
||||||
"0123456789ABCDEF" :
|
"0123456789ABCDEF" :
|
||||||
"0123456789abcdef";
|
"0123456789abcdef";
|
||||||
@ -919,7 +918,7 @@ shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
|
|||||||
*--cp = (flags & FL_UPPER) ? 'X' : 'x';
|
*--cp = (flags & FL_UPPER) ? 'X' : 'x';
|
||||||
*--cp = '0';
|
*--cp = '0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
len = numbuf + sizeof(numbuf) - (s = cp);
|
len = numbuf + sizeof(numbuf) - (s = cp);
|
||||||
if (flags & FL_DOT) {
|
if (flags & FL_DOT) {
|
||||||
|
@ -18,11 +18,11 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/strlcpy.c,v 1.6 2009/05/27 09:58:24 tg Rel $");
|
__RCSID("$MirOS: src/bin/mksh/strlcpy.c,v 1.7 2009/06/10 18:12:50 tg Rel $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy src to string dst of size siz. At most siz-1 characters
|
* Copy src to string dst of size siz. At most siz-1 characters
|
||||||
* will be copied. Always NUL terminates (unless siz == 0).
|
* will be copied. Always NUL terminates (unless siz == 0).
|
||||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||||
*/
|
*/
|
||||||
size_t
|
size_t
|
||||||
|
23
syn.c
23
syn.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.36 2009/06/08 20:06:49 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.37 2009/06/10 18:12:50 tg Exp $");
|
||||||
|
|
||||||
struct nesting_state {
|
struct nesting_state {
|
||||||
int start_token; /* token than began nesting (eg, FOR) */
|
int start_token; /* token than began nesting (eg, FOR) */
|
||||||
@ -143,7 +143,7 @@ c_list(int multi)
|
|||||||
break;
|
break;
|
||||||
else if (c == '&' || c == COPROC)
|
else if (c == '&' || c == COPROC)
|
||||||
p = block(c == '&' ? TASYNC : TCOPROC,
|
p = block(c == '&' ? TASYNC : TCOPROC,
|
||||||
p, NOBLOCK, NOWORDS);
|
p, NOBLOCK, NOWORDS);
|
||||||
else if (c != ';')
|
else if (c != ';')
|
||||||
have_sep = 0;
|
have_sep = 0;
|
||||||
if (!t)
|
if (!t)
|
||||||
@ -302,7 +302,7 @@ get_command(int cf)
|
|||||||
t = function_body(XPptrv(args)[0], false);
|
t = function_body(XPptrv(args)[0], false);
|
||||||
goto Leave;
|
goto Leave;
|
||||||
is_wdarrassign:
|
is_wdarrassign:
|
||||||
{
|
{
|
||||||
static const char set_cmd0[] = {
|
static const char set_cmd0[] = {
|
||||||
CHAR, 'e', CHAR, 'v',
|
CHAR, 'e', CHAR, 'v',
|
||||||
CHAR, 'a', CHAR, 'l', EOS
|
CHAR, 'a', CHAR, 'l', EOS
|
||||||
@ -335,7 +335,7 @@ get_command(int cf)
|
|||||||
musthave(LWORD,LETARRAY);
|
musthave(LWORD,LETARRAY);
|
||||||
XPput(args, yylval.cp);
|
XPput(args, yylval.cp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
goto Leave;
|
goto Leave;
|
||||||
@ -353,8 +353,7 @@ get_command(int cf)
|
|||||||
t = nested(TBRACE, '{', '}');
|
t = nested(TBRACE, '{', '}');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MDPAREN:
|
case MDPAREN: {
|
||||||
{
|
|
||||||
static const char let_cmd[] = {
|
static const char let_cmd[] = {
|
||||||
CHAR, 'l', CHAR, 'e',
|
CHAR, 'l', CHAR, 'e',
|
||||||
CHAR, 't', EOS
|
CHAR, 't', EOS
|
||||||
@ -367,7 +366,7 @@ get_command(int cf)
|
|||||||
musthave(LWORD,LETEXPR);
|
musthave(LWORD,LETEXPR);
|
||||||
XPput(args, yylval.cp);
|
XPput(args, yylval.cp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DBRACKET: /* [[ .. ]] */
|
case DBRACKET: /* [[ .. ]] */
|
||||||
/* Leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */
|
/* Leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */
|
||||||
@ -603,11 +602,11 @@ function_body(char *name,
|
|||||||
bool old_func_parse;
|
bool old_func_parse;
|
||||||
|
|
||||||
sname = wdstrip(name, false, false);
|
sname = wdstrip(name, false, false);
|
||||||
/* Check for valid characters in name. posix and ksh93 say only
|
/* Check for valid characters in name. posix and ksh93 say only
|
||||||
* allow [a-zA-Z_0-9] but this allows more as old pdkshs have
|
* allow [a-zA-Z_0-9] but this allows more as old pdkshs have
|
||||||
* allowed more (the following were never allowed:
|
* allowed more (the following were never allowed:
|
||||||
* nul space nl tab $ ' " \ ` ( ) & | ; = < >
|
* nul space nl tab $ ' " \ ` ( ) & | ; = < >
|
||||||
* C_QUOTE covers all but = and adds # [ ] ? *)
|
* C_QUOTE covers all but = and adds # [ ] ? *)
|
||||||
*/
|
*/
|
||||||
for (p = sname; *p; p++)
|
for (p = sname; *p; p++)
|
||||||
if (ctype(*p, C_QUOTE) || *p == '=')
|
if (ctype(*p, C_QUOTE) || *p == '=')
|
||||||
@ -620,7 +619,7 @@ function_body(char *name,
|
|||||||
|
|
||||||
/* Note that POSIX allows only compound statements after foo(), sh and
|
/* Note that POSIX allows only compound statements after foo(), sh and
|
||||||
* at&t ksh allow any command, go with the later since it shouldn't
|
* at&t ksh allow any command, go with the later since it shouldn't
|
||||||
* break anything. However, for function foo, at&t ksh only accepts
|
* break anything. However, for function foo, at&t ksh only accepts
|
||||||
* an open-brace.
|
* an open-brace.
|
||||||
*/
|
*/
|
||||||
if (ksh_func) {
|
if (ksh_func) {
|
||||||
@ -894,8 +893,8 @@ const char db_close[] = { CHAR, ']', CHAR, ']', EOS };
|
|||||||
const char db_lthan[] = { CHAR, '<', EOS };
|
const char db_lthan[] = { CHAR, '<', EOS };
|
||||||
const char db_gthan[] = { 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
|
* 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).
|
* TM_UNOP and TM_BINOP, the returned value is a Test_op).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
7
tree.c
7
tree.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.27 2009/06/08 20:06:49 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.28 2009/06/10 18:12:50 tg Exp $");
|
||||||
|
|
||||||
#define INDENT 4
|
#define INDENT 4
|
||||||
|
|
||||||
@ -84,8 +84,7 @@ ptree(struct op *t, int indent, struct shf *shf)
|
|||||||
shf_puts("! ", shf);
|
shf_puts("! ", shf);
|
||||||
t = t->right;
|
t = t->right;
|
||||||
goto Chain;
|
goto Chain;
|
||||||
case TDBRACKET:
|
case TDBRACKET: {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
shf_puts("[[", shf);
|
shf_puts("[[", shf);
|
||||||
@ -93,7 +92,7 @@ ptree(struct op *t, int indent, struct shf *shf)
|
|||||||
fptreef(shf, indent, " %S", t->args[i]);
|
fptreef(shf, indent, " %S", t->args[i]);
|
||||||
shf_puts(" ]] ", shf);
|
shf_puts(" ]] ", shf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TSELECT:
|
case TSELECT:
|
||||||
fptreef(shf, indent, "select %s ", t->str);
|
fptreef(shf, indent, "select %s ", t->str);
|
||||||
/* FALLTHRU */
|
/* FALLTHRU */
|
||||||
|
39
var.c
39
var.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.73 2009/06/08 20:06:50 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.74 2009/06/10 18:12:51 tg Exp $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Variables
|
* Variables
|
||||||
@ -133,7 +133,7 @@ initvar(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Used to calculate an array index for global()/local(). Sets *arrayp to
|
/* Used to calculate an array index for global()/local(). Sets *arrayp to
|
||||||
* non-zero if this is an array, sets *valp to the array index, returns
|
* non-zero if this is an array, sets *valp to the array index, returns
|
||||||
* the basename of the array.
|
* the basename of the array.
|
||||||
*/
|
*/
|
||||||
@ -303,8 +303,9 @@ str_val(struct tbl *vp)
|
|||||||
else if (!(vp->flag&INTEGER)) /* string source */
|
else if (!(vp->flag&INTEGER)) /* string source */
|
||||||
s = vp->val.s + vp->type;
|
s = vp->val.s + vp->type;
|
||||||
else { /* integer source */
|
else { /* integer source */
|
||||||
/* worst case number length is when base=2, so use BITS(long) */
|
/* worst case number length is when base=2 */
|
||||||
/* minus base # number NUL */
|
/* 1 (minus) + 2 (base, up to 36) + 1 ('#') + number of bits
|
||||||
|
* in the mksh_uari_t + 1 (NUL) */
|
||||||
char strbuf[1 + 2 + 1 + 8 * sizeof(mksh_uari_t) + 1];
|
char strbuf[1 + 2 + 1 + 8 * sizeof(mksh_uari_t) + 1];
|
||||||
const char *digits = (vp->flag & UCASEV_AL) ?
|
const char *digits = (vp->flag & UCASEV_AL) ?
|
||||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" :
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" :
|
||||||
@ -650,7 +651,7 @@ typeset(const char *var, Tflag set, Tflag clr, int field, int base)
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
/* IMPORT is only used when the shell starts up and is
|
/* IMPORT is only used when the shell starts up and is
|
||||||
* setting up its environment. Allow only simple array
|
* setting up its environment. Allow only simple array
|
||||||
* references at this time since parameter/command substitution
|
* references at this time since parameter/command substitution
|
||||||
* is preformed on the [expression] which would be a major
|
* is preformed on the [expression] which would be a major
|
||||||
* security hole.
|
* security hole.
|
||||||
@ -684,7 +685,7 @@ typeset(const char *var, Tflag set, Tflag clr, int field, int base)
|
|||||||
|
|
||||||
vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp;
|
vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp;
|
||||||
|
|
||||||
/* only allow export flag to be set. at&t ksh allows any attribute to
|
/* only allow export flag to be set. at&t ksh allows any attribute to
|
||||||
* be changed which means it can be truncated or modified (-L/-R/-Z/-i)
|
* be changed which means it can be truncated or modified (-L/-R/-Z/-i)
|
||||||
*/
|
*/
|
||||||
if ((vpbase->flag&RDONLY) &&
|
if ((vpbase->flag&RDONLY) &&
|
||||||
@ -775,7 +776,7 @@ typeset(const char *var, Tflag set, Tflag clr, int field, int base)
|
|||||||
return (vp);
|
return (vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unset a variable. array_ref is set if there was an array reference in
|
/* Unset a variable. array_ref is set if there was an array reference in
|
||||||
* the name lookup (eg, x[2]).
|
* the name lookup (eg, x[2]).
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -820,7 +821,7 @@ skip_varname(const char *s, int aok)
|
|||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a pointer to the first character past any legal variable name. */
|
/* Return a pointer to the first character past any legal variable name */
|
||||||
const char *
|
const char *
|
||||||
skip_wdvarname(const char *s,
|
skip_wdvarname(const char *s,
|
||||||
int aok) /* skip array de-reference? */
|
int aok) /* skip array de-reference? */
|
||||||
@ -1086,7 +1087,7 @@ getspec(struct tbl *vp)
|
|||||||
break;
|
break;
|
||||||
case V_COLUMNS:
|
case V_COLUMNS:
|
||||||
case V_LINES:
|
case V_LINES:
|
||||||
/* Do NOT export COLUMNS/LINES. Many applications
|
/* Do NOT export COLUMNS/LINES. Many applications
|
||||||
* check COLUMNS/LINES before checking ws.ws_col/row,
|
* check COLUMNS/LINES before checking ws.ws_col/row,
|
||||||
* so if the app is started with C/L in the environ
|
* so if the app is started with C/L in the environ
|
||||||
* and the window is then resized, the app won't
|
* and the window is then resized, the app won't
|
||||||
@ -1219,14 +1220,14 @@ unsetspec(struct tbl *vp)
|
|||||||
unspecial(vp->name);
|
unspecial(vp->name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* at&t ksh man page says OPTIND, OPTARG and _ lose special meaning,
|
/* at&t ksh man page says OPTIND, OPTARG and _ lose special meaning,
|
||||||
* but OPTARG does not (still set by getopts) and _ is also still
|
* but OPTARG does not (still set by getopts) and _ is also still
|
||||||
* set in various places.
|
* set in various places.
|
||||||
* Don't know what at&t does for:
|
* Don't know what at&t does for:
|
||||||
* HISTSIZE, HISTFILE,
|
* HISTSIZE, HISTFILE,
|
||||||
* Unsetting these in at&t ksh does not loose the 'specialness':
|
* Unsetting these in at&t ksh does not loose the 'specialness':
|
||||||
* no effect: IFS, COLUMNS, PATH, TMPDIR
|
* no effect: IFS, COLUMNS, PATH, TMPDIR
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1272,7 +1273,7 @@ arraysearch(struct tbl *vp, uint32_t val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Return the length of an array reference (eg, [1+2]) - cp is assumed
|
/* Return the length of an array reference (eg, [1+2]) - cp is assumed
|
||||||
* to point to the open bracket. Returns 0 if there is no matching closing
|
* to point to the open bracket. Returns 0 if there is no matching closing
|
||||||
* bracket.
|
* bracket.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@ -1327,7 +1328,7 @@ set_array(const char *var, int reset, const char **vals)
|
|||||||
/* trash existing values and attributes */
|
/* trash existing values and attributes */
|
||||||
unset(vp, 0);
|
unset(vp, 0);
|
||||||
/* todo: would be nice for assignment to completely succeed or
|
/* todo: would be nice for assignment to completely succeed or
|
||||||
* completely fail. Only really effects integer arrays:
|
* completely fail. Only really effects integer arrays:
|
||||||
* evaluation of some of vals[] may fail...
|
* evaluation of some of vals[] may fail...
|
||||||
*/
|
*/
|
||||||
for (i = 0; vals[i]; i++) {
|
for (i = 0; vals[i]; i++) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user