aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Config.in23
-rw-r--r--Makefile12
-rw-r--r--Makefile.flags9
-rw-r--r--README1
-rw-r--r--README.win3232
-rw-r--r--archival/Config.src1
-rw-r--r--archival/bbunzip.c2
-rw-r--r--archival/libarchive/open_transformer.c2
-rw-r--r--archival/rpm2cpio.c2
-rw-r--r--archival/tar.c4
-rw-r--r--configs/mingw32_defconfig1010
-rw-r--r--console-tools/clear.c9
-rw-r--r--coreutils/Config.src3
-rw-r--r--coreutils/date.c13
-rw-r--r--coreutils/dd.c20
-rw-r--r--coreutils/dos2unix.c2
-rw-r--r--coreutils/ls.c5
-rw-r--r--coreutils/od_bloaty.c7
-rw-r--r--coreutils/test.c27
-rw-r--r--coreutils/uname.c10
-rw-r--r--coreutils/whoami.c10
-rw-r--r--debianutils/which.c49
-rw-r--r--editors/vi.c9
-rw-r--r--findutils/grep.c8
-rw-r--r--include/libbb.h25
-rw-r--r--include/mingw.h381
-rw-r--r--include/platform.h39
-rw-r--r--libbb/Kbuild.src22
-rw-r--r--libbb/appletlib.c16
-rw-r--r--libbb/copy_file.c9
-rw-r--r--libbb/execable.c53
-rw-r--r--libbb/find_pid_by_name.c4
-rw-r--r--libbb/get_last_path_component.c5
-rw-r--r--libbb/get_line_from_file.c4
-rw-r--r--libbb/get_shell_name.c2
-rw-r--r--libbb/getopt32.c2
-rw-r--r--libbb/lineedit.c15
-rw-r--r--libbb/make_directory.c15
-rw-r--r--libbb/messages.c2
-rw-r--r--libbb/procps.c3
-rw-r--r--libbb/vfork_daemon_rexec.c5
-rw-r--r--libbb/xreadlink.c2
-rw-r--r--networking/wget.c1
-rw-r--r--procps/ps.c10
-rw-r--r--scripts/basic/fixdep.c51
-rw-r--r--shell/ash.c1170
-rw-r--r--shell/shell_common.c10
-rw-r--r--win32/Kbuild18
-rw-r--r--win32/env.c130
-rw-r--r--win32/fnmatch.c488
-rw-r--r--win32/fnmatch.h84
-rw-r--r--win32/grp.h0
-rw-r--r--win32/ioctl.c24
-rw-r--r--win32/mingw.c731
-rw-r--r--win32/net.c54
-rw-r--r--win32/net/if.h0
-rw-r--r--win32/netdb.h0
-rw-r--r--win32/netinet/in.h0
-rw-r--r--win32/poll.c606
-rw-r--r--win32/popen.c220
-rw-r--r--win32/process.c373
-rw-r--r--win32/pwd.h0
-rw-r--r--win32/regex.c4929
-rw-r--r--win32/regex.h490
-rw-r--r--win32/sched.h1
-rw-r--r--win32/sys/ioctl.h0
-rw-r--r--win32/sys/mman.h0
-rw-r--r--win32/sys/poll.h53
-rw-r--r--win32/sys/socket.h0
-rw-r--r--win32/sys/sysmacros.h0
-rw-r--r--win32/sys/times.h0
-rw-r--r--win32/sys/un.h0
-rw-r--r--win32/sys/utsname.h66
-rw-r--r--win32/sys/wait.h0
-rw-r--r--win32/termios.c83
-rw-r--r--win32/termios.h129
-rw-r--r--win32/uname.c50
-rw-r--r--win32/winansi.c436
79 files changed, 12035 insertions, 47 deletions
diff --git a/.gitignore b/.gitignore
index 0a0c65bc3..54369de10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ Config.in
18# Normal output 18# Normal output
19# 19#
20/busybox 20/busybox
21/busybox.exe
21/busybox_old 22/busybox_old
22/busybox_unstripped* 23/busybox_unstripped*
23 24
diff --git a/Config.in b/Config.in
index 17bdc895a..cd51e2b45 100644
--- a/Config.in
+++ b/Config.in
@@ -9,6 +9,29 @@ config HAVE_DOT_CONFIG
9 bool 9 bool
10 default y 10 default y
11 11
12choice
13 prompt "Target platform"
14 default PLATFORM_POSIX
15 help
16 Target platform you are building busybox for
17
18config PLATFORM_POSIX
19 bool "POSIX"
20
21config PLATFORM_MINGW32
22 bool "MS Windows (MinGW port)"
23
24endchoice
25
26config WIN32_NET
27 bool "Support networking"
28 default n
29 depends on PLATFORM_MINGW32
30 help
31 Enable network applets. Some other applets can also be
32 enabled because they use htonl/htons, which are provided
33 by ws2_32.dll
34
12menu "Busybox Settings" 35menu "Busybox Settings"
13 36
14menu "General Configuration" 37menu "General Configuration"
diff --git a/Makefile b/Makefile
index d5beb0459..cfe4d5219 100644
--- a/Makefile
+++ b/Makefile
@@ -311,6 +311,7 @@ AFLAGS_MODULE = $(MODFLAGS)
311LDFLAGS_MODULE = -r 311LDFLAGS_MODULE = -r
312CFLAGS_KERNEL = 312CFLAGS_KERNEL =
313AFLAGS_KERNEL = 313AFLAGS_KERNEL =
314EXEEXT =
314 315
315 316
316# Use LINUXINCLUDE when you must reference the include/ directory. 317# Use LINUXINCLUDE when you must reference the include/ directory.
@@ -490,6 +491,7 @@ libs-y := \
490 sysklogd/ \ 491 sysklogd/ \
491 util-linux/ \ 492 util-linux/ \
492 util-linux/volume_id/ \ 493 util-linux/volume_id/ \
494 win32/ \
493 495
494endif # KBUILD_EXTMOD 496endif # KBUILD_EXTMOD
495 497
@@ -528,7 +530,7 @@ endif
528# command line. 530# command line.
529# This allow a user to issue only 'make' to build a kernel including modules 531# This allow a user to issue only 'make' to build a kernel including modules
530# Defaults busybox but it is usually overridden in the arch makefile 532# Defaults busybox but it is usually overridden in the arch makefile
531all: busybox doc 533all: busybox$(EXEEXT) doc
532 534
533-include $(srctree)/arch/$(ARCH)/Makefile 535-include $(srctree)/arch/$(ARCH)/Makefile
534 536
@@ -711,16 +713,16 @@ debug_kallsyms: .tmp_map$(last_kallsyms)
711endif # ifdef CONFIG_KALLSYMS 713endif # ifdef CONFIG_KALLSYMS
712 714
713# busybox image - including updated kernel symbols 715# busybox image - including updated kernel symbols
714busybox_unstripped: $(busybox-all) FORCE 716busybox_unstripped$(EXEEXT): $(busybox-all) FORCE
715 $(call if_changed_rule,busybox__) 717 $(call if_changed_rule,busybox__)
716 $(Q)rm -f .old_version 718 $(Q)rm -f .old_version
717 719
718busybox: busybox_unstripped 720busybox$(EXEEXT): busybox_unstripped$(EXEEXT)
719ifeq ($(SKIP_STRIP),y) 721ifeq ($(SKIP_STRIP),y)
720 $(Q)cp $< $@ 722 $(Q)cp $< $@
721else 723else
722 $(Q)$(STRIP) -s --remove-section=.note --remove-section=.comment \ 724 $(Q)$(STRIP) -s --remove-section=.note --remove-section=.comment \
723 busybox_unstripped -o $@ 725 busybox_unstripped$(EXEEXT) -o $@
724# strip is confused by PIE executable and does not set exec bits 726# strip is confused by PIE executable and does not set exec bits
725 $(Q)chmod a+x $@ 727 $(Q)chmod a+x $@
726endif 728endif
@@ -956,7 +958,7 @@ endif # CONFIG_MODULES
956 958
957# Directories & files removed with 'make clean' 959# Directories & files removed with 'make clean'
958CLEAN_DIRS += $(MODVERDIR) _install 0_lib 960CLEAN_DIRS += $(MODVERDIR) _install 0_lib
959CLEAN_FILES += busybox busybox_unstripped* busybox.links \ 961CLEAN_FILES += busybox$(EXEEXT) busybox_unstripped* busybox.links \
960 System.map .kernelrelease \ 962 System.map .kernelrelease \
961 .tmp_kallsyms* .tmp_version .tmp_busybox* .tmp_System.map 963 .tmp_kallsyms* .tmp_version .tmp_busybox* .tmp_System.map
962 964
diff --git a/Makefile.flags b/Makefile.flags
index c43c8dca8..0eb495c60 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -104,6 +104,15 @@ CFLAGS += --sysroot=$(CONFIG_SYSROOT)
104export SYSROOT=$(CONFIG_SYSROOT) 104export SYSROOT=$(CONFIG_SYSROOT)
105endif 105endif
106 106
107ifeq ($(CONFIG_PLATFORM_MINGW32),y)
108# These defintions are not strictly needed, but they help shut up fnmatch.c warnings
109CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 -fno-builtin-stpcpy
110EXEEXT = .exe
111ifeq ($(CONFIG_WIN32_NET),y)
112LDLIBS += ws2_32
113endif
114endif
115
107# Android has no separate crypt library 116# Android has no separate crypt library
108# gcc-4.2.1 fails if we try to feed C source on stdin: 117# gcc-4.2.1 fails if we try to feed C source on stdin:
109# echo 'int main(void){return 0;}' | $(CC) $(CFLAGS) -lcrypt -o /dev/null -xc - 118# echo 'int main(void){return 0;}' | $(CC) $(CFLAGS) -lcrypt -o /dev/null -xc -
diff --git a/README b/README
index b940e357a..9b1774a7f 100644
--- a/README
+++ b/README
@@ -1,3 +1,4 @@
1Please see README.win32 for Windows-specific info.
1Please see the LICENSE file for details on copying and usage. 2Please see the LICENSE file for details on copying and usage.
2Please refer to the INSTALL file for instructions on how to build. 3Please refer to the INSTALL file for instructions on how to build.
3 4
diff --git a/README.win32 b/README.win32
new file mode 100644
index 000000000..9e9c8f39f
--- /dev/null
+++ b/README.win32
@@ -0,0 +1,32 @@
1Status
2======
3
4I would consider this port experimental. Things may work, or may not.
5Things may never work because of huge differences between Linux and
6Windows. Or things may work in future, if you report the faults to
7https://github.com/rmyorston/busybox-w32, especially with patches.
8
9Building
10========
11
12You need MinGW compiler and a POSIX environment (so that "make
13menuconfig" works). I cross compile from Linux, but MSYS or Cygwin
14should be OK.
15
16To start, run "make mingw32_defconfig". You can then customize your
17build with "make menuconfig".
18
19In particular you may need to adjust the compiler by going to Busybox
20Settings -> Build Options -> Cross Compiler Prefix
21
22Then just "make".
23
24Attempts to make it work with MS Visual Studio are appreciated. You
25can start with porting kconfig ;-)
26
27Limitation
28==========
29
30 - Use forward slashes. Backslash support is very limited.
31 - Do not do wild things with Windows drive notation, like archiving a
32 whole drive. If you want it, tell us, preferably with patches.
diff --git a/archival/Config.src b/archival/Config.src
index ae1afc594..13c33c795 100644
--- a/archival/Config.src
+++ b/archival/Config.src
@@ -202,6 +202,7 @@ config GZIP_FAST
202config LZOP 202config LZOP
203 bool "lzop" 203 bool "lzop"
204 default y 204 default y
205 depends on PLATFORM_POSIX || WIN32_NET
205 help 206 help
206 Lzop compression/decompresion. 207 Lzop compression/decompresion.
207 208
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index 94d8a81c9..66a046052 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -129,6 +129,8 @@ int FAST_FUNC bbunpack(char **argv,
129 if (new_name == filename) 129 if (new_name == filename)
130 filename[strlen(filename)] = '.'; 130 filename[strlen(filename)] = '.';
131 } 131 }
132 if (ENABLE_PLATFORM_MINGW32)
133 xclose(STDIN_FILENO);
132 xunlink(del); 134 xunlink(del);
133 135
134#if 0 /* Currently buggy - wrong name: "a.gz: 261% - replaced with a.gz" */ 136#if 0 /* Currently buggy - wrong name: "a.gz: 261% - replaced with a.gz" */
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c
index dae04aa57..f2edc2a2b 100644
--- a/archival/libarchive/open_transformer.c
+++ b/archival/libarchive/open_transformer.c
@@ -27,6 +27,7 @@ int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigne
27 return 0; 27 return 0;
28} 28}
29 29
30#if !ENABLE_PLATFORM_MINGW32
30void check_errors_in_children(int signo) 31void check_errors_in_children(int signo)
31{ 32{
32 int status; 33 int status;
@@ -52,6 +53,7 @@ void check_errors_in_children(int signo)
52 bb_got_signal = 1; 53 bb_got_signal = 1;
53 } 54 }
54} 55}
56#endif
55 57
56/* transformer(), more than meets the eye */ 58/* transformer(), more than meets the eye */
57#if BB_MMU 59#if BB_MMU
diff --git a/archival/rpm2cpio.c b/archival/rpm2cpio.c
index f3dfa5159..898d4aca4 100644
--- a/archival/rpm2cpio.c
+++ b/archival/rpm2cpio.c
@@ -79,9 +79,11 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv)
79 close(rpm_fd); 79 close(rpm_fd);
80 } 80 }
81 81
82#if !ENABLE_PLATFORM_MINGW32
82 if (SEAMLESS_COMPRESSION) { 83 if (SEAMLESS_COMPRESSION) {
83 check_errors_in_children(0); 84 check_errors_in_children(0);
84 return bb_got_signal; 85 return bb_got_signal;
85 } 86 }
87#endif
86 return EXIT_SUCCESS; 88 return EXIT_SUCCESS;
87} 89}
diff --git a/archival/tar.c b/archival/tar.c
index cf972c24c..fcd128a91 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -454,6 +454,7 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb
454 } 454 }
455 } 455 }
456 456
457#if !ENABLE_PLATFORM_MINGW32
457 /* It is a bad idea to store the archive we are in the process of creating, 458 /* It is a bad idea to store the archive we are in the process of creating,
458 * so check the device and inode to be sure that this particular file isn't 459 * so check the device and inode to be sure that this particular file isn't
459 * the new tarball */ 460 * the new tarball */
@@ -463,6 +464,7 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb
463 bb_error_msg("%s: file is the archive; skipping", fileName); 464 bb_error_msg("%s: file is the archive; skipping", fileName);
464 return TRUE; 465 return TRUE;
465 } 466 }
467#endif
466 468
467 if (exclude_file(tbInfo->excludeList, header_name)) 469 if (exclude_file(tbInfo->excludeList, header_name))
468 return SKIP; 470 return SKIP;
@@ -1094,9 +1096,11 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
1094 if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */) 1096 if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */)
1095 close(tar_handle->src_fd); 1097 close(tar_handle->src_fd);
1096 1098
1099#if !ENABLE_PLATFORM_MINGW32
1097 if (SEAMLESS_COMPRESSION || OPT_COMPRESS) { 1100 if (SEAMLESS_COMPRESSION || OPT_COMPRESS) {
1098 check_errors_in_children(0); 1101 check_errors_in_children(0);
1099 return bb_got_signal; 1102 return bb_got_signal;
1100 } 1103 }
1104#endif
1101 return EXIT_SUCCESS; 1105 return EXIT_SUCCESS;
1102} 1106}
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig
new file mode 100644
index 000000000..7e19586e5
--- /dev/null
+++ b/configs/mingw32_defconfig
@@ -0,0 +1,1010 @@
1#
2# Automatically generated make config: don't edit
3# Busybox version: 1.20.0.git
4# Sat Mar 31 15:38:08 2012
5#
6CONFIG_HAVE_DOT_CONFIG=y
7# CONFIG_PLATFORM_POSIX is not set
8CONFIG_PLATFORM_MINGW32=y
9CONFIG_WIN32_NET=y
10
11#
12# Busybox Settings
13#
14
15#
16# General Configuration
17#
18CONFIG_DESKTOP=y
19CONFIG_EXTRA_COMPAT=y
20# CONFIG_INCLUDE_SUSv2 is not set
21CONFIG_USE_PORTABLE_CODE=y
22# CONFIG_PLATFORM_LINUX is not set
23CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
24# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
25# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
26CONFIG_SHOW_USAGE=y
27CONFIG_FEATURE_VERBOSE_USAGE=y
28CONFIG_FEATURE_COMPRESS_USAGE=y
29# CONFIG_FEATURE_INSTALLER is not set
30# CONFIG_INSTALL_NO_USR is not set
31# CONFIG_LOCALE_SUPPORT is not set
32# CONFIG_UNICODE_SUPPORT is not set
33# CONFIG_UNICODE_USING_LOCALE is not set
34# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set
35CONFIG_SUBST_WCHAR=0
36CONFIG_LAST_SUPPORTED_WCHAR=0
37# CONFIG_UNICODE_COMBINING_WCHARS is not set
38# CONFIG_UNICODE_WIDE_WCHARS is not set
39# CONFIG_UNICODE_BIDI_SUPPORT is not set
40# CONFIG_UNICODE_NEUTRAL_TABLE is not set
41# CONFIG_UNICODE_PRESERVE_BROKEN is not set
42CONFIG_LONG_OPTS=y
43# CONFIG_FEATURE_DEVPTS is not set
44# CONFIG_FEATURE_CLEAN_UP is not set
45# CONFIG_FEATURE_UTMP is not set
46# CONFIG_FEATURE_WTMP is not set
47# CONFIG_FEATURE_PIDFILE is not set
48# CONFIG_FEATURE_SUID is not set
49# CONFIG_FEATURE_SUID_CONFIG is not set
50# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
51# CONFIG_SELINUX is not set
52CONFIG_FEATURE_PREFER_APPLETS=y
53CONFIG_BUSYBOX_EXEC_PATH=""
54# CONFIG_FEATURE_SYSLOG is not set
55# CONFIG_FEATURE_HAVE_RPC is not set
56
57#
58# Build Options
59#
60# CONFIG_STATIC is not set
61# CONFIG_PIE is not set
62# CONFIG_NOMMU is not set
63# CONFIG_BUILD_LIBBUSYBOX is not set
64# CONFIG_FEATURE_INDIVIDUAL is not set
65# CONFIG_FEATURE_SHARED_BUSYBOX is not set
66# CONFIG_LFS is not set
67CONFIG_CROSS_COMPILER_PREFIX="i686-pc-mingw32-"
68CONFIG_SYSROOT=""
69CONFIG_EXTRA_CFLAGS="-g -O0"
70CONFIG_EXTRA_LDFLAGS=""
71CONFIG_EXTRA_LDLIBS=""
72
73#
74# Debugging Options
75#
76CONFIG_DEBUG=y
77# CONFIG_DEBUG_PESSIMIZE is not set
78# CONFIG_WERROR is not set
79CONFIG_NO_DEBUG_LIB=y
80# CONFIG_DMALLOC is not set
81# CONFIG_EFENCE is not set
82
83#
84# Installation Options ("make install" behavior)
85#
86CONFIG_INSTALL_APPLET_SYMLINKS=y
87# CONFIG_INSTALL_APPLET_HARDLINKS is not set
88# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
89# CONFIG_INSTALL_APPLET_DONT is not set
90# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
91# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
92# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
93CONFIG_PREFIX=""
94
95#
96# Busybox Library Tuning
97#
98# CONFIG_FEATURE_SYSTEMD is not set
99CONFIG_FEATURE_RTMINMAX=y
100CONFIG_PASSWORD_MINLEN=6
101CONFIG_MD5_SMALL=1
102# CONFIG_FEATURE_FAST_TOP is not set
103# CONFIG_FEATURE_ETC_NETWORKS is not set
104# CONFIG_FEATURE_USE_TERMIOS is not set
105CONFIG_FEATURE_EDITING=y
106CONFIG_FEATURE_EDITING_MAX_LEN=1024
107# CONFIG_FEATURE_EDITING_VI is not set
108CONFIG_FEATURE_EDITING_HISTORY=255
109# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set
110# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set
111# CONFIG_FEATURE_REVERSE_SEARCH is not set
112CONFIG_FEATURE_TAB_COMPLETION=y
113# CONFIG_FEATURE_USERNAME_COMPLETION is not set
114# CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set
115# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set
116CONFIG_FEATURE_NON_POSIX_CP=y
117# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
118CONFIG_FEATURE_COPYBUF_KB=4
119CONFIG_FEATURE_SKIP_ROOTFS=y
120# CONFIG_MONOTONIC_SYSCALL is not set
121CONFIG_IOCTL_HEX2STR_ERROR=y
122# CONFIG_FEATURE_HWIB is not set
123
124#
125# Applets
126#
127
128#
129# Archival Utilities
130#
131CONFIG_FEATURE_SEAMLESS_XZ=y
132CONFIG_FEATURE_SEAMLESS_LZMA=y
133CONFIG_FEATURE_SEAMLESS_BZ2=y
134CONFIG_FEATURE_SEAMLESS_GZ=y
135CONFIG_FEATURE_SEAMLESS_Z=y
136CONFIG_AR=y
137CONFIG_FEATURE_AR_LONG_FILENAMES=y
138CONFIG_FEATURE_AR_CREATE=y
139CONFIG_BUNZIP2=y
140CONFIG_BZIP2=y
141CONFIG_CPIO=y
142CONFIG_FEATURE_CPIO_O=y
143CONFIG_FEATURE_CPIO_P=y
144# CONFIG_DPKG is not set
145# CONFIG_DPKG_DEB is not set
146# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
147CONFIG_GUNZIP=y
148CONFIG_GZIP=y
149CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
150CONFIG_GZIP_FAST=2
151CONFIG_LZOP=y
152# CONFIG_LZOP_COMPR_HIGH is not set
153CONFIG_RPM2CPIO=y
154# CONFIG_RPM is not set
155CONFIG_TAR=y
156CONFIG_FEATURE_TAR_CREATE=y
157CONFIG_FEATURE_TAR_AUTODETECT=y
158# CONFIG_FEATURE_TAR_FROM is not set
159CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y
160# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set
161CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
162CONFIG_FEATURE_TAR_LONG_OPTIONS=y
163# CONFIG_FEATURE_TAR_TO_COMMAND is not set
164# CONFIG_FEATURE_TAR_UNAME_GNAME is not set
165# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set
166# CONFIG_FEATURE_TAR_SELINUX is not set
167CONFIG_UNCOMPRESS=y
168CONFIG_UNLZMA=y
169CONFIG_FEATURE_LZMA_FAST=y
170CONFIG_LZMA=y
171CONFIG_UNXZ=y
172CONFIG_XZ=y
173CONFIG_UNZIP=y
174
175#
176# Coreutils
177#
178CONFIG_BASENAME=y
179CONFIG_CAT=y
180CONFIG_DATE=y
181CONFIG_FEATURE_DATE_ISOFMT=y
182# CONFIG_FEATURE_DATE_NANO is not set
183CONFIG_FEATURE_DATE_COMPAT=y
184# CONFIG_HOSTID is not set
185# CONFIG_ID is not set
186# CONFIG_GROUPS is not set
187CONFIG_TEST=y
188CONFIG_FEATURE_TEST_64=y
189CONFIG_TOUCH=y
190CONFIG_FEATURE_TOUCH_SUSV3=y
191CONFIG_TR=y
192CONFIG_FEATURE_TR_CLASSES=y
193CONFIG_FEATURE_TR_EQUIV=y
194CONFIG_BASE64=y
195# CONFIG_WHO is not set
196# CONFIG_USERS is not set
197CONFIG_CAL=y
198CONFIG_CATV=y
199# CONFIG_CHGRP is not set
200CONFIG_CHMOD=y
201# CONFIG_CHOWN is not set
202# CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set
203# CONFIG_CHROOT is not set
204CONFIG_CKSUM=y
205CONFIG_COMM=y
206CONFIG_CP=y
207CONFIG_FEATURE_CP_LONG_OPTIONS=y
208CONFIG_CUT=y
209CONFIG_DD=y
210# CONFIG_FEATURE_DD_SIGNAL_HANDLING is not set
211# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set
212CONFIG_FEATURE_DD_IBS_OBS=y
213# CONFIG_DF is not set
214# CONFIG_FEATURE_DF_FANCY is not set
215CONFIG_DIRNAME=y
216CONFIG_DOS2UNIX=y
217CONFIG_UNIX2DOS=y
218# CONFIG_DU is not set
219# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set
220CONFIG_ECHO=y
221CONFIG_FEATURE_FANCY_ECHO=y
222CONFIG_ENV=y
223CONFIG_FEATURE_ENV_LONG_OPTIONS=y
224CONFIG_EXPAND=y
225CONFIG_FEATURE_EXPAND_LONG_OPTIONS=y
226CONFIG_EXPR=y
227CONFIG_EXPR_MATH_SUPPORT_64=y
228CONFIG_FALSE=y
229CONFIG_FOLD=y
230# CONFIG_FSYNC is not set
231CONFIG_HEAD=y
232CONFIG_FEATURE_FANCY_HEAD=y
233# CONFIG_INSTALL is not set
234# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set
235# CONFIG_LN is not set
236# CONFIG_LOGNAME is not set
237CONFIG_LS=y
238CONFIG_FEATURE_LS_FILETYPES=y
239CONFIG_FEATURE_LS_FOLLOWLINKS=y
240CONFIG_FEATURE_LS_RECURSIVE=y
241CONFIG_FEATURE_LS_SORTFILES=y
242CONFIG_FEATURE_LS_TIMESTAMPS=y
243CONFIG_FEATURE_LS_USERNAME=y
244CONFIG_FEATURE_LS_COLOR=y
245CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
246CONFIG_MD5SUM=y
247CONFIG_MKDIR=y
248CONFIG_FEATURE_MKDIR_LONG_OPTIONS=y
249# CONFIG_MKFIFO is not set
250# CONFIG_MKNOD is not set
251CONFIG_MV=y
252CONFIG_FEATURE_MV_LONG_OPTIONS=y
253# CONFIG_NICE is not set
254# CONFIG_NOHUP is not set
255CONFIG_OD=y
256CONFIG_PRINTENV=y
257CONFIG_PRINTF=y
258CONFIG_PWD=y
259# CONFIG_READLINK is not set
260# CONFIG_FEATURE_READLINK_FOLLOW is not set
261# CONFIG_REALPATH is not set
262CONFIG_RM=y
263CONFIG_RMDIR=y
264CONFIG_FEATURE_RMDIR_LONG_OPTIONS=y
265CONFIG_SEQ=y
266CONFIG_SHA1SUM=y
267CONFIG_SHA256SUM=y
268CONFIG_SHA512SUM=y
269CONFIG_SLEEP=y
270CONFIG_FEATURE_FANCY_SLEEP=y
271# CONFIG_FEATURE_FLOAT_SLEEP is not set
272CONFIG_SORT=y
273CONFIG_FEATURE_SORT_BIG=y
274CONFIG_SPLIT=y
275CONFIG_FEATURE_SPLIT_FANCY=y
276# CONFIG_STAT is not set
277# CONFIG_FEATURE_STAT_FORMAT is not set
278# CONFIG_STTY is not set
279CONFIG_SUM=y
280# CONFIG_SYNC is not set
281CONFIG_TAC=y
282CONFIG_TAIL=y
283CONFIG_FEATURE_FANCY_TAIL=y
284CONFIG_TEE=y
285CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
286CONFIG_TRUE=y
287# CONFIG_TTY is not set
288CONFIG_UNAME=y
289CONFIG_UNEXPAND=y
290CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS=y
291CONFIG_UNIQ=y
292CONFIG_USLEEP=y
293CONFIG_UUDECODE=y
294CONFIG_UUENCODE=y
295CONFIG_WC=y
296CONFIG_FEATURE_WC_LARGE=y
297CONFIG_WHOAMI=y
298CONFIG_YES=y
299
300#
301# Common options for cp and mv
302#
303# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set
304
305#
306# Common options for ls, more and telnet
307#
308CONFIG_FEATURE_AUTOWIDTH=y
309
310#
311# Common options for df, du, ls
312#
313CONFIG_FEATURE_HUMAN_READABLE=y
314
315#
316# Common options for md5sum, sha1sum, sha256sum, sha512sum
317#
318CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
319
320#
321# Console Utilities
322#
323# CONFIG_CHVT is not set
324# CONFIG_FGCONSOLE is not set
325CONFIG_CLEAR=y
326# CONFIG_DEALLOCVT is not set
327# CONFIG_DUMPKMAP is not set
328# CONFIG_KBD_MODE is not set
329# CONFIG_LOADFONT is not set
330# CONFIG_LOADKMAP is not set
331# CONFIG_OPENVT is not set
332# CONFIG_RESET is not set
333# CONFIG_RESIZE is not set
334# CONFIG_FEATURE_RESIZE_PRINT is not set
335# CONFIG_SETCONSOLE is not set
336# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
337# CONFIG_SETFONT is not set
338# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set
339CONFIG_DEFAULT_SETFONT_DIR=""
340# CONFIG_SETKEYCODES is not set
341# CONFIG_SETLOGCONS is not set
342# CONFIG_SHOWKEY is not set
343# CONFIG_FEATURE_LOADFONT_PSF2 is not set
344# CONFIG_FEATURE_LOADFONT_RAW is not set
345
346#
347# Debian Utilities
348#
349# CONFIG_MKTEMP is not set
350# CONFIG_PIPE_PROGRESS is not set
351# CONFIG_RUN_PARTS is not set
352# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
353# CONFIG_FEATURE_RUN_PARTS_FANCY is not set
354# CONFIG_START_STOP_DAEMON is not set
355# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
356# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
357CONFIG_WHICH=y
358
359#
360# Editors
361#
362# CONFIG_PATCH is not set
363CONFIG_VI=y
364CONFIG_FEATURE_VI_MAX_LEN=4096
365# CONFIG_FEATURE_VI_8BIT is not set
366CONFIG_FEATURE_VI_COLON=y
367CONFIG_FEATURE_VI_YANKMARK=y
368CONFIG_FEATURE_VI_SEARCH=y
369# CONFIG_FEATURE_VI_REGEX_SEARCH is not set
370# CONFIG_FEATURE_VI_USE_SIGNALS is not set
371CONFIG_FEATURE_VI_DOT_CMD=y
372CONFIG_FEATURE_VI_READONLY=y
373CONFIG_FEATURE_VI_SETOPTS=y
374CONFIG_FEATURE_VI_SET=y
375CONFIG_FEATURE_VI_WIN_RESIZE=y
376CONFIG_FEATURE_VI_ASK_TERMINAL=y
377# CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set
378CONFIG_AWK=y
379# CONFIG_FEATURE_AWK_LIBM is not set
380CONFIG_CMP=y
381CONFIG_DIFF=y
382CONFIG_FEATURE_DIFF_LONG_OPTIONS=y
383CONFIG_FEATURE_DIFF_DIR=y
384CONFIG_ED=y
385CONFIG_SED=y
386CONFIG_FEATURE_ALLOW_EXEC=y
387
388#
389# Finding Utilities
390#
391CONFIG_FIND=y
392CONFIG_FEATURE_FIND_PRINT0=y
393CONFIG_FEATURE_FIND_MTIME=y
394CONFIG_FEATURE_FIND_MMIN=y
395# CONFIG_FEATURE_FIND_PERM is not set
396CONFIG_FEATURE_FIND_TYPE=y
397# CONFIG_FEATURE_FIND_XDEV is not set
398CONFIG_FEATURE_FIND_MAXDEPTH=y
399CONFIG_FEATURE_FIND_NEWER=y
400# CONFIG_FEATURE_FIND_INUM is not set
401# CONFIG_FEATURE_FIND_EXEC is not set
402# CONFIG_FEATURE_FIND_USER is not set
403# CONFIG_FEATURE_FIND_GROUP is not set
404CONFIG_FEATURE_FIND_NOT=y
405CONFIG_FEATURE_FIND_DEPTH=y
406CONFIG_FEATURE_FIND_PAREN=y
407CONFIG_FEATURE_FIND_SIZE=y
408CONFIG_FEATURE_FIND_PRUNE=y
409CONFIG_FEATURE_FIND_DELETE=y
410CONFIG_FEATURE_FIND_PATH=y
411CONFIG_FEATURE_FIND_REGEX=y
412# CONFIG_FEATURE_FIND_CONTEXT is not set
413# CONFIG_FEATURE_FIND_LINKS is not set
414CONFIG_GREP=y
415CONFIG_FEATURE_GREP_EGREP_ALIAS=y
416CONFIG_FEATURE_GREP_FGREP_ALIAS=y
417CONFIG_FEATURE_GREP_CONTEXT=y
418CONFIG_XARGS=y
419CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
420CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
421CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
422CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
423
424#
425# Init Utilities
426#
427# CONFIG_BOOTCHARTD is not set
428# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set
429# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set
430# CONFIG_HALT is not set
431# CONFIG_FEATURE_CALL_TELINIT is not set
432CONFIG_TELINIT_PATH=""
433# CONFIG_INIT is not set
434# CONFIG_FEATURE_USE_INITTAB is not set
435# CONFIG_FEATURE_KILL_REMOVED is not set
436CONFIG_FEATURE_KILL_DELAY=0
437# CONFIG_FEATURE_INIT_SCTTY is not set
438# CONFIG_FEATURE_INIT_SYSLOG is not set
439# CONFIG_FEATURE_EXTRA_QUIET is not set
440# CONFIG_FEATURE_INIT_COREDUMPS is not set
441# CONFIG_FEATURE_INITRD is not set
442CONFIG_INIT_TERMINAL_TYPE=""
443# CONFIG_MESG is not set
444# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set
445
446#
447# Login/Password Management Utilities
448#
449# CONFIG_ADD_SHELL is not set
450# CONFIG_REMOVE_SHELL is not set
451# CONFIG_FEATURE_SHADOWPASSWDS is not set
452# CONFIG_USE_BB_PWD_GRP is not set
453# CONFIG_USE_BB_SHADOW is not set
454# CONFIG_USE_BB_CRYPT is not set
455# CONFIG_USE_BB_CRYPT_SHA is not set
456# CONFIG_ADDUSER is not set
457# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
458# CONFIG_FEATURE_CHECK_NAMES is not set
459CONFIG_FIRST_SYSTEM_ID=0
460CONFIG_LAST_SYSTEM_ID=0
461# CONFIG_ADDGROUP is not set
462# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set
463# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set
464# CONFIG_DELUSER is not set
465# CONFIG_DELGROUP is not set
466# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set
467# CONFIG_GETTY is not set
468# CONFIG_LOGIN is not set
469# CONFIG_LOGIN_SESSION_AS_CHILD is not set
470# CONFIG_PAM is not set
471# CONFIG_LOGIN_SCRIPTS is not set
472# CONFIG_FEATURE_NOLOGIN is not set
473# CONFIG_FEATURE_SECURETTY is not set
474# CONFIG_PASSWD is not set
475# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set
476# CONFIG_CRYPTPW is not set
477# CONFIG_CHPASSWD is not set
478CONFIG_FEATURE_DEFAULT_PASSWD_ALGO=""
479# CONFIG_SU is not set
480# CONFIG_FEATURE_SU_SYSLOG is not set
481# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set
482# CONFIG_SULOGIN is not set
483# CONFIG_VLOCK is not set
484
485#
486# Linux Ext2 FS Progs
487#
488# CONFIG_CHATTR is not set
489# CONFIG_FSCK is not set
490# CONFIG_LSATTR is not set
491# CONFIG_TUNE2FS is not set
492
493#
494# Linux Module Utilities
495#
496# CONFIG_MODINFO is not set
497# CONFIG_MODPROBE_SMALL is not set
498# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set
499# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set
500# CONFIG_INSMOD is not set
501# CONFIG_RMMOD is not set
502# CONFIG_LSMOD is not set
503# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
504# CONFIG_MODPROBE is not set
505# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
506# CONFIG_DEPMOD is not set
507
508#
509# Options common to multiple modutils
510#
511# CONFIG_FEATURE_2_4_MODULES is not set
512# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
513# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
514# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
515# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
516# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
517# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
518# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
519# CONFIG_FEATURE_MODUTILS_ALIAS is not set
520# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
521CONFIG_DEFAULT_MODULES_DIR=""
522CONFIG_DEFAULT_DEPMOD_FILE=""
523
524#
525# Linux System Utilities
526#
527# CONFIG_BLOCKDEV is not set
528# CONFIG_MDEV is not set
529# CONFIG_FEATURE_MDEV_CONF is not set
530# CONFIG_FEATURE_MDEV_RENAME is not set
531# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set
532# CONFIG_FEATURE_MDEV_EXEC is not set
533# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set
534# CONFIG_REV is not set
535# CONFIG_ACPID is not set
536# CONFIG_FEATURE_ACPID_COMPAT is not set
537# CONFIG_BLKID is not set
538# CONFIG_FEATURE_BLKID_TYPE is not set
539# CONFIG_DMESG is not set
540# CONFIG_FEATURE_DMESG_PRETTY is not set
541# CONFIG_FBSET is not set
542# CONFIG_FEATURE_FBSET_FANCY is not set
543# CONFIG_FEATURE_FBSET_READMODE is not set
544# CONFIG_FDFLUSH is not set
545# CONFIG_FDFORMAT is not set
546# CONFIG_FDISK is not set
547# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set
548# CONFIG_FEATURE_FDISK_WRITABLE is not set
549# CONFIG_FEATURE_AIX_LABEL is not set
550# CONFIG_FEATURE_SGI_LABEL is not set
551# CONFIG_FEATURE_SUN_LABEL is not set
552# CONFIG_FEATURE_OSF_LABEL is not set
553# CONFIG_FEATURE_GPT_LABEL is not set
554# CONFIG_FEATURE_FDISK_ADVANCED is not set
555# CONFIG_FINDFS is not set
556# CONFIG_FLOCK is not set
557# CONFIG_FREERAMDISK is not set
558# CONFIG_FSCK_MINIX is not set
559# CONFIG_MKFS_EXT2 is not set
560# CONFIG_MKFS_MINIX is not set
561# CONFIG_FEATURE_MINIX2 is not set
562# CONFIG_MKFS_REISER is not set
563# CONFIG_MKFS_VFAT is not set
564CONFIG_GETOPT=y
565CONFIG_FEATURE_GETOPT_LONG=y
566CONFIG_HEXDUMP=y
567CONFIG_FEATURE_HEXDUMP_REVERSE=y
568CONFIG_HD=y
569# CONFIG_HWCLOCK is not set
570# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set
571# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
572# CONFIG_IPCRM is not set
573# CONFIG_IPCS is not set
574# CONFIG_LOSETUP is not set
575# CONFIG_LSPCI is not set
576# CONFIG_LSUSB is not set
577# CONFIG_MKSWAP is not set
578# CONFIG_FEATURE_MKSWAP_UUID is not set
579# CONFIG_MORE is not set
580# CONFIG_MOUNT is not set
581# CONFIG_FEATURE_MOUNT_FAKE is not set
582# CONFIG_FEATURE_MOUNT_VERBOSE is not set
583# CONFIG_FEATURE_MOUNT_HELPERS is not set
584# CONFIG_FEATURE_MOUNT_LABEL is not set
585# CONFIG_FEATURE_MOUNT_NFS is not set
586# CONFIG_FEATURE_MOUNT_CIFS is not set
587# CONFIG_FEATURE_MOUNT_FLAGS is not set
588# CONFIG_FEATURE_MOUNT_FSTAB is not set
589# CONFIG_PIVOT_ROOT is not set
590# CONFIG_RDATE is not set
591# CONFIG_RDEV is not set
592# CONFIG_READPROFILE is not set
593# CONFIG_RTCWAKE is not set
594# CONFIG_SCRIPT is not set
595# CONFIG_SCRIPTREPLAY is not set
596# CONFIG_SETARCH is not set
597# CONFIG_SWAPONOFF is not set
598# CONFIG_FEATURE_SWAPON_PRI is not set
599# CONFIG_SWITCH_ROOT is not set
600# CONFIG_UMOUNT is not set
601# CONFIG_FEATURE_UMOUNT_ALL is not set
602# CONFIG_FEATURE_MOUNT_LOOP is not set
603# CONFIG_FEATURE_MOUNT_LOOP_CREATE is not set
604# CONFIG_FEATURE_MTAB_SUPPORT is not set
605# CONFIG_VOLUMEID is not set
606# CONFIG_FEATURE_VOLUMEID_EXT is not set
607# CONFIG_FEATURE_VOLUMEID_BTRFS is not set
608# CONFIG_FEATURE_VOLUMEID_REISERFS is not set
609# CONFIG_FEATURE_VOLUMEID_FAT is not set
610# CONFIG_FEATURE_VOLUMEID_HFS is not set
611# CONFIG_FEATURE_VOLUMEID_JFS is not set
612# CONFIG_FEATURE_VOLUMEID_XFS is not set
613# CONFIG_FEATURE_VOLUMEID_NTFS is not set
614# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set
615# CONFIG_FEATURE_VOLUMEID_UDF is not set
616# CONFIG_FEATURE_VOLUMEID_LUKS is not set
617# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set
618# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set
619# CONFIG_FEATURE_VOLUMEID_ROMFS is not set
620# CONFIG_FEATURE_VOLUMEID_SYSV is not set
621# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set
622# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set
623
624#
625# Miscellaneous Utilities
626#
627# CONFIG_CONSPY is not set
628# CONFIG_LESS is not set
629CONFIG_FEATURE_LESS_MAXLINES=0
630# CONFIG_FEATURE_LESS_BRACKETS is not set
631# CONFIG_FEATURE_LESS_FLAGS is not set
632# CONFIG_FEATURE_LESS_MARKS is not set
633# CONFIG_FEATURE_LESS_REGEXP is not set
634# CONFIG_FEATURE_LESS_WINCH is not set
635# CONFIG_FEATURE_LESS_ASK_TERMINAL is not set
636# CONFIG_FEATURE_LESS_DASHCMD is not set
637# CONFIG_FEATURE_LESS_LINENUMS is not set
638# CONFIG_NANDWRITE is not set
639# CONFIG_NANDDUMP is not set
640# CONFIG_SETSERIAL is not set
641# CONFIG_UBIATTACH is not set
642# CONFIG_UBIDETACH is not set
643# CONFIG_UBIMKVOL is not set
644# CONFIG_UBIRMVOL is not set
645# CONFIG_UBIRSVOL is not set
646# CONFIG_UBIUPDATEVOL is not set
647# CONFIG_ADJTIMEX is not set
648CONFIG_BBCONFIG=y
649CONFIG_FEATURE_COMPRESS_BBCONFIG=y
650# CONFIG_BEEP is not set
651CONFIG_FEATURE_BEEP_FREQ=0
652CONFIG_FEATURE_BEEP_LENGTH_MS=0
653# CONFIG_CHAT is not set
654# CONFIG_FEATURE_CHAT_NOFAIL is not set
655# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
656# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set
657# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set
658# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set
659# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set
660# CONFIG_FEATURE_CHAT_CLR_ABORT is not set
661# CONFIG_CHRT is not set
662# CONFIG_CROND is not set
663# CONFIG_FEATURE_CROND_D is not set
664# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
665CONFIG_FEATURE_CROND_DIR=""
666# CONFIG_CRONTAB is not set
667CONFIG_DC=y
668# CONFIG_FEATURE_DC_LIBM is not set
669# CONFIG_DEVFSD is not set
670# CONFIG_DEVFSD_MODLOAD is not set
671# CONFIG_DEVFSD_FG_NP is not set
672# CONFIG_DEVFSD_VERBOSE is not set
673# CONFIG_FEATURE_DEVFS is not set
674# CONFIG_DEVMEM is not set
675# CONFIG_EJECT is not set
676# CONFIG_FEATURE_EJECT_SCSI is not set
677# CONFIG_FBSPLASH is not set
678# CONFIG_FLASHCP is not set
679# CONFIG_FLASH_LOCK is not set
680# CONFIG_FLASH_UNLOCK is not set
681# CONFIG_FLASH_ERASEALL is not set
682# CONFIG_IONICE is not set
683# CONFIG_INOTIFYD is not set
684# CONFIG_LAST is not set
685# CONFIG_FEATURE_LAST_SMALL is not set
686# CONFIG_FEATURE_LAST_FANCY is not set
687# CONFIG_HDPARM is not set
688# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
689# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
690# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
691# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
692# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
693# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
694# CONFIG_MAKEDEVS is not set
695# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
696# CONFIG_FEATURE_MAKEDEVS_TABLE is not set
697# CONFIG_MAN is not set
698# CONFIG_MICROCOM is not set
699# CONFIG_MOUNTPOINT is not set
700# CONFIG_MT is not set
701# CONFIG_RAIDAUTORUN is not set
702# CONFIG_READAHEAD is not set
703# CONFIG_RFKILL is not set
704# CONFIG_RUNLEVEL is not set
705# CONFIG_RX is not set
706# CONFIG_SETSID is not set
707CONFIG_STRINGS=y
708# CONFIG_TASKSET is not set
709# CONFIG_FEATURE_TASKSET_FANCY is not set
710# CONFIG_TIME is not set
711# CONFIG_TIMEOUT is not set
712# CONFIG_TTYSIZE is not set
713# CONFIG_VOLNAME is not set
714# CONFIG_WALL is not set
715# CONFIG_WATCHDOG is not set
716
717#
718# Networking Utilities
719#
720# CONFIG_NAMEIF is not set
721# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
722# CONFIG_NBDCLIENT is not set
723# CONFIG_NC is not set
724# CONFIG_NC_SERVER is not set
725# CONFIG_NC_EXTRA is not set
726# CONFIG_NC_110_COMPAT is not set
727# CONFIG_PING is not set
728# CONFIG_PING6 is not set
729# CONFIG_FEATURE_FANCY_PING is not set
730# CONFIG_WHOIS is not set
731# CONFIG_FEATURE_IPV6 is not set
732# CONFIG_FEATURE_UNIX_LOCAL is not set
733# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set
734# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set
735# CONFIG_ARP is not set
736# CONFIG_ARPING is not set
737# CONFIG_BRCTL is not set
738# CONFIG_FEATURE_BRCTL_FANCY is not set
739# CONFIG_FEATURE_BRCTL_SHOW is not set
740# CONFIG_DNSD is not set
741# CONFIG_ETHER_WAKE is not set
742# CONFIG_FAKEIDENTD is not set
743# CONFIG_FTPD is not set
744# CONFIG_FEATURE_FTP_WRITE is not set
745# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set
746# CONFIG_FTPGET is not set
747# CONFIG_FTPPUT is not set
748# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
749# CONFIG_HOSTNAME is not set
750# CONFIG_HTTPD is not set
751# CONFIG_FEATURE_HTTPD_RANGES is not set
752# CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set
753# CONFIG_FEATURE_HTTPD_SETUID is not set
754# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set
755# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
756# CONFIG_FEATURE_HTTPD_CGI is not set
757# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set
758# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set
759# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set
760# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set
761# CONFIG_FEATURE_HTTPD_PROXY is not set
762# CONFIG_FEATURE_HTTPD_GZIP is not set
763# CONFIG_IFCONFIG is not set
764# CONFIG_FEATURE_IFCONFIG_STATUS is not set
765# CONFIG_FEATURE_IFCONFIG_SLIP is not set
766# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
767# CONFIG_FEATURE_IFCONFIG_HW is not set
768# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set
769# CONFIG_IFENSLAVE is not set
770# CONFIG_IFPLUGD is not set
771# CONFIG_IFUPDOWN is not set
772CONFIG_IFUPDOWN_IFSTATE_PATH=""
773# CONFIG_FEATURE_IFUPDOWN_IP is not set
774# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set
775# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
776# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
777# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
778# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
779# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
780# CONFIG_INETD is not set
781# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
782# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
783# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
784# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
785# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
786# CONFIG_FEATURE_INETD_RPC is not set
787# CONFIG_IP is not set
788# CONFIG_FEATURE_IP_ADDRESS is not set
789# CONFIG_FEATURE_IP_LINK is not set
790# CONFIG_FEATURE_IP_ROUTE is not set
791# CONFIG_FEATURE_IP_TUNNEL is not set
792# CONFIG_FEATURE_IP_RULE is not set
793# CONFIG_FEATURE_IP_SHORT_FORMS is not set
794# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
795# CONFIG_IPADDR is not set
796# CONFIG_IPLINK is not set
797# CONFIG_IPROUTE is not set
798# CONFIG_IPTUNNEL is not set
799# CONFIG_IPRULE is not set
800# CONFIG_IPCALC is not set
801# CONFIG_FEATURE_IPCALC_FANCY is not set
802# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
803# CONFIG_NETSTAT is not set
804# CONFIG_FEATURE_NETSTAT_WIDE is not set
805# CONFIG_FEATURE_NETSTAT_PRG is not set
806# CONFIG_NSLOOKUP is not set
807# CONFIG_NTPD is not set
808# CONFIG_FEATURE_NTPD_SERVER is not set
809# CONFIG_PSCAN is not set
810# CONFIG_ROUTE is not set
811# CONFIG_SLATTACH is not set
812# CONFIG_TCPSVD is not set
813# CONFIG_TELNET is not set
814# CONFIG_FEATURE_TELNET_TTYPE is not set
815# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
816# CONFIG_TELNETD is not set
817# CONFIG_FEATURE_TELNETD_STANDALONE is not set
818# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set
819# CONFIG_TFTP is not set
820# CONFIG_TFTPD is not set
821# CONFIG_FEATURE_TFTP_GET is not set
822# CONFIG_FEATURE_TFTP_PUT is not set
823# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set
824# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set
825# CONFIG_TFTP_DEBUG is not set
826# CONFIG_TRACEROUTE is not set
827# CONFIG_TRACEROUTE6 is not set
828# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set
829# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set
830# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
831# CONFIG_TUNCTL is not set
832# CONFIG_FEATURE_TUNCTL_UG is not set
833# CONFIG_UDHCPC6 is not set
834# CONFIG_UDHCPD is not set
835# CONFIG_DHCPRELAY is not set
836# CONFIG_DUMPLEASES is not set
837# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set
838# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set
839CONFIG_DHCPD_LEASES_FILE=""
840# CONFIG_UDHCPC is not set
841# CONFIG_FEATURE_UDHCPC_ARPING is not set
842# CONFIG_FEATURE_UDHCP_PORT is not set
843CONFIG_UDHCP_DEBUG=0
844# CONFIG_FEATURE_UDHCP_RFC3397 is not set
845# CONFIG_FEATURE_UDHCP_8021Q is not set
846CONFIG_UDHCPC_DEFAULT_SCRIPT=""
847CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0
848CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS=""
849# CONFIG_UDPSVD is not set
850# CONFIG_VCONFIG is not set
851CONFIG_WGET=y
852# CONFIG_FEATURE_WGET_STATUSBAR is not set
853# CONFIG_FEATURE_WGET_AUTHENTICATION is not set
854CONFIG_FEATURE_WGET_LONG_OPTIONS=y
855# CONFIG_FEATURE_WGET_TIMEOUT is not set
856# CONFIG_ZCIP is not set
857
858#
859# Print Utilities
860#
861# CONFIG_LPD is not set
862# CONFIG_LPR is not set
863# CONFIG_LPQ is not set
864
865#
866# Mail Utilities
867#
868# CONFIG_MAKEMIME is not set
869CONFIG_FEATURE_MIME_CHARSET=""
870# CONFIG_POPMAILDIR is not set
871# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set
872# CONFIG_REFORMIME is not set
873# CONFIG_FEATURE_REFORMIME_COMPAT is not set
874# CONFIG_SENDMAIL is not set
875
876#
877# Process Utilities
878#
879# CONFIG_IOSTAT is not set
880# CONFIG_MPSTAT is not set
881# CONFIG_NMETER is not set
882# CONFIG_PMAP is not set
883# CONFIG_POWERTOP is not set
884# CONFIG_PSTREE is not set
885# CONFIG_PWDX is not set
886# CONFIG_SMEMCAP is not set
887# CONFIG_UPTIME is not set
888# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set
889# CONFIG_FREE is not set
890# CONFIG_FUSER is not set
891CONFIG_KILL=y
892CONFIG_KILLALL=y
893# CONFIG_KILLALL5 is not set
894CONFIG_PGREP=y
895CONFIG_PIDOF=y
896CONFIG_FEATURE_PIDOF_SINGLE=y
897CONFIG_FEATURE_PIDOF_OMIT=y
898# CONFIG_PKILL is not set
899CONFIG_PS=y
900# CONFIG_FEATURE_PS_WIDE is not set
901# CONFIG_FEATURE_PS_LONG is not set
902# CONFIG_FEATURE_PS_TIME is not set
903# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set
904# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
905# CONFIG_RENICE is not set
906# CONFIG_BB_SYSCTL is not set
907# CONFIG_TOP is not set
908# CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set
909# CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set
910# CONFIG_FEATURE_TOP_SMP_CPU is not set
911# CONFIG_FEATURE_TOP_DECIMALS is not set
912# CONFIG_FEATURE_TOP_SMP_PROCESS is not set
913# CONFIG_FEATURE_TOPMEM is not set
914# CONFIG_FEATURE_SHOW_THREADS is not set
915# CONFIG_WATCH is not set
916
917#
918# Runit Utilities
919#
920# CONFIG_RUNSV is not set
921# CONFIG_RUNSVDIR is not set
922# CONFIG_FEATURE_RUNSVDIR_LOG is not set
923# CONFIG_SV is not set
924CONFIG_SV_DEFAULT_SERVICE_DIR=""
925# CONFIG_SVLOGD is not set
926# CONFIG_CHPST is not set
927# CONFIG_SETUIDGID is not set
928# CONFIG_ENVUIDGID is not set
929# CONFIG_ENVDIR is not set
930# CONFIG_SOFTLIMIT is not set
931# CONFIG_CHCON is not set
932# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
933# CONFIG_GETENFORCE is not set
934# CONFIG_GETSEBOOL is not set
935# CONFIG_LOAD_POLICY is not set
936# CONFIG_MATCHPATHCON is not set
937# CONFIG_RESTORECON is not set
938# CONFIG_RUNCON is not set
939# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set
940# CONFIG_SELINUXENABLED is not set
941# CONFIG_SETENFORCE is not set
942# CONFIG_SETFILES is not set
943# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
944# CONFIG_SETSEBOOL is not set
945# CONFIG_SESTATUS is not set
946
947#
948# Shells
949#
950CONFIG_ASH=y
951CONFIG_ASH_BASH_COMPAT=y
952# CONFIG_ASH_IDLE_TIMEOUT is not set
953# CONFIG_ASH_JOB_CONTROL is not set
954CONFIG_ASH_ALIAS=y
955CONFIG_ASH_GETOPTS=y
956CONFIG_ASH_BUILTIN_ECHO=y
957CONFIG_ASH_BUILTIN_PRINTF=y
958CONFIG_ASH_BUILTIN_TEST=y
959CONFIG_ASH_CMDCMD=y
960# CONFIG_ASH_MAIL is not set
961CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
962CONFIG_ASH_RANDOM_SUPPORT=y
963CONFIG_ASH_EXPAND_PRMT=y
964# CONFIG_CTTYHACK is not set
965# CONFIG_HUSH is not set
966# CONFIG_HUSH_BASH_COMPAT is not set
967# CONFIG_HUSH_BRACE_EXPANSION is not set
968# CONFIG_HUSH_HELP is not set
969# CONFIG_HUSH_INTERACTIVE is not set
970# CONFIG_HUSH_SAVEHISTORY is not set
971# CONFIG_HUSH_JOB is not set
972# CONFIG_HUSH_TICK is not set
973# CONFIG_HUSH_IF is not set
974# CONFIG_HUSH_LOOPS is not set
975# CONFIG_HUSH_CASE is not set
976# CONFIG_HUSH_FUNCTIONS is not set
977# CONFIG_HUSH_LOCAL is not set
978# CONFIG_HUSH_RANDOM_SUPPORT is not set
979# CONFIG_HUSH_EXPORT_N is not set
980# CONFIG_HUSH_MODE_X is not set
981# CONFIG_MSH is not set
982CONFIG_FEATURE_SH_IS_ASH=y
983# CONFIG_FEATURE_SH_IS_HUSH is not set
984# CONFIG_FEATURE_SH_IS_NONE is not set
985CONFIG_FEATURE_BASH_IS_ASH=y
986# CONFIG_FEATURE_BASH_IS_HUSH is not set
987# CONFIG_FEATURE_BASH_IS_NONE is not set
988CONFIG_SH_MATH_SUPPORT=y
989CONFIG_SH_MATH_SUPPORT_64=y
990CONFIG_FEATURE_SH_EXTRA_QUIET=y
991CONFIG_FEATURE_SH_STANDALONE=y
992CONFIG_FEATURE_SH_NOFORK=y
993# CONFIG_FEATURE_SH_HISTFILESIZE is not set
994
995#
996# System Logging Utilities
997#
998# CONFIG_SYSLOGD is not set
999# CONFIG_FEATURE_ROTATE_LOGFILE is not set
1000# CONFIG_FEATURE_REMOTE_LOG is not set
1001# CONFIG_FEATURE_SYSLOGD_DUP is not set
1002# CONFIG_FEATURE_SYSLOGD_CFG is not set
1003CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0
1004# CONFIG_FEATURE_IPC_SYSLOG is not set
1005CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0
1006# CONFIG_LOGREAD is not set
1007# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
1008# CONFIG_KLOGD is not set
1009# CONFIG_FEATURE_KLOGD_KLOGCTL is not set
1010# CONFIG_LOGGER is not set
diff --git a/console-tools/clear.c b/console-tools/clear.c
index ac22b787e..232d500b5 100644
--- a/console-tools/clear.c
+++ b/console-tools/clear.c
@@ -18,5 +18,14 @@ int clear_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
18int clear_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 18int clear_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
19{ 19{
20 /* home; clear to the end of screen */ 20 /* home; clear to the end of screen */
21#if !ENABLE_PLATFORM_MINGW32
21 return full_write1_str("\033[H""\033[J") != 6; 22 return full_write1_str("\033[H""\033[J") != 6;
23#else
24 int ret;
25
26 ret = printf("\033[H\033[J");
27 fflush(stdout);
28
29 return ret != 6;
30#endif
22} 31}
diff --git a/coreutils/Config.src b/coreutils/Config.src
index a28449b11..81be71993 100644
--- a/coreutils/Config.src
+++ b/coreutils/Config.src
@@ -499,18 +499,21 @@ config SEQ
499config SHA1SUM 499config SHA1SUM
500 bool "sha1sum" 500 bool "sha1sum"
501 default y 501 default y
502 depends on PLATFORM_POSIX || WIN32_NET
502 help 503 help
503 Compute and check SHA1 message digest 504 Compute and check SHA1 message digest
504 505
505config SHA256SUM 506config SHA256SUM
506 bool "sha256sum" 507 bool "sha256sum"
507 default y 508 default y
509 depends on PLATFORM_POSIX || WIN32_NET
508 help 510 help
509 Compute and check SHA256 message digest 511 Compute and check SHA256 message digest
510 512
511config SHA512SUM 513config SHA512SUM
512 bool "sha512sum" 514 bool "sha512sum"
513 default y 515 default y
516 depends on PLATFORM_POSIX || WIN32_NET
514 help 517 help
515 Compute and check SHA512 message digest 518 Compute and check SHA512 message digest
516 519
diff --git a/coreutils/date.c b/coreutils/date.c
index 767e0d4a2..62cceff9c 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -293,9 +293,14 @@ int date_main(int argc UNUSED_PARAM, char **argv)
293 maybe_set_utc(opt); 293 maybe_set_utc(opt);
294 294
295 /* if setting time, set it */ 295 /* if setting time, set it */
296#if ENABLE_PLATFORM_MINGW32
297 if (opt & OPT_SET)
298 bb_error_msg_and_die("Setting date is not supported");
299#else
296 if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) { 300 if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) {
297 bb_perror_msg("can't set date"); 301 bb_perror_msg("can't set date");
298 } 302 }
303#endif
299 } 304 }
300 305
301 /* Display output */ 306 /* Display output */
@@ -323,7 +328,11 @@ int date_main(int argc UNUSED_PARAM, char **argv)
323 i = sizeof("%a, %d %b %Y %H:%M:%S ")-1; 328 i = sizeof("%a, %d %b %Y %H:%M:%S ")-1;
324 goto format_utc; 329 goto format_utc;
325 } else { /* default case */ 330 } else { /* default case */
331#if ENABLE_PLATFORM_MINGW32
332 fmt_dt2str = (char*)"%a %b %d %H:%M:%S %Z %Y";
333#else
326 fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; 334 fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y";
335#endif
327 } 336 }
328 } 337 }
329#if ENABLE_FEATURE_DATE_NANO 338#if ENABLE_FEATURE_DATE_NANO
@@ -376,6 +385,10 @@ int date_main(int argc UNUSED_PARAM, char **argv)
376 if (strncmp(fmt_dt2str, "%f", 2) == 0) { 385 if (strncmp(fmt_dt2str, "%f", 2) == 0) {
377 fmt_dt2str = (char*)"%Y.%m.%d-%H:%M:%S"; 386 fmt_dt2str = (char*)"%Y.%m.%d-%H:%M:%S";
378 } 387 }
388#if ENABLE_PLATFORM_MINGW32
389 if (strstr(fmt_dt2str, "%e"))
390 bb_error_msg_and_die("%%e is not supported by Windows strftime");
391#endif
379 /* Generate output string */ 392 /* Generate output string */
380 strftime(date_buf, sizeof(date_buf), fmt_dt2str, &tm_time); 393 strftime(date_buf, sizeof(date_buf), fmt_dt2str, &tm_time);
381 } 394 }
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 96602ebdd..f6869cb26 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -200,6 +200,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
200#endif 200#endif
201 }; 201 };
202 int exitcode = EXIT_FAILURE; 202 int exitcode = EXIT_FAILURE;
203 int devzero = 0;
203 size_t ibs = 512, obs = 512; 204 size_t ibs = 512, obs = 512;
204 ssize_t n, w; 205 ssize_t n, w;
205 char *ibuf, *obuf; 206 char *ibuf, *obuf;
@@ -317,7 +318,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
317#endif 318#endif
318 319
319 if (infile != NULL) 320 if (infile != NULL)
320 xmove_fd(xopen(infile, O_RDONLY), ifd); 321 if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) {
322 flags |= FLAG_NOERROR;
323 devzero = 1;
324 }
325 else
326 xmove_fd(xopen(infile, O_RDONLY), ifd);
321 else { 327 else {
322 infile = bb_msg_standard_input; 328 infile = bb_msg_standard_input;
323 } 329 }
@@ -344,7 +350,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
344 } else { 350 } else {
345 outfile = bb_msg_standard_output; 351 outfile = bb_msg_standard_output;
346 } 352 }
347 if (skip) { 353 if (skip && !devzero) {
348 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { 354 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) {
349 while (skip-- > 0) { 355 while (skip-- > 0) {
350 n = safe_read(ifd, ibuf, ibs); 356 n = safe_read(ifd, ibuf, ibs);
@@ -361,7 +367,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
361 } 367 }
362 368
363 while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { 369 while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
364 n = safe_read(ifd, ibuf, ibs); 370 if (devzero) {
371 memset(ibuf, 0, ibs);
372 n = ibs;
373 }
374 else
375 n = safe_read(ifd, ibuf, ibs);
365 if (n == 0) 376 if (n == 0)
366 break; 377 break;
367 if (n < 0) { 378 if (n < 0) {
@@ -415,7 +426,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
415 if (w < 0) goto out_status; 426 if (w < 0) goto out_status;
416 if (w > 0) G.out_part++; 427 if (w > 0) G.out_part++;
417 } 428 }
418 if (close(ifd) < 0) { 429
430 if (!devzero && close(ifd) < 0) {
419 die_infile: 431 die_infile:
420 bb_simple_perror_msg_and_die(infile); 432 bb_simple_perror_msg_and_die(infile);
421 } 433 }
diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c
index 07398bdfa..e1fbe8538 100644
--- a/coreutils/dos2unix.c
+++ b/coreutils/dos2unix.c
@@ -58,7 +58,7 @@ static void convert(char *fn, int conv_type)
58 58
59 temp_fn = xasprintf("%sXXXXXX", resolved_fn); 59 temp_fn = xasprintf("%sXXXXXX", resolved_fn);
60 i = xmkstemp(temp_fn); 60 i = xmkstemp(temp_fn);
61 if (fchmod(i, st.st_mode) == -1) 61 if (!ENABLE_PLATFORM_MINGW32 && fchmod(i, st.st_mode) == -1)
62 bb_simple_perror_msg_and_die(temp_fn); 62 bb_simple_perror_msg_and_die(temp_fn);
63 63
64 out = xfdopen_for_write(i); 64 out = xfdopen_for_write(i);
diff --git a/coreutils/ls.c b/coreutils/ls.c
index d5b25ee70..4fe291d17 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -754,7 +754,12 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
754 cur->dn_ctime = statbuf.st_ctime ; 754 cur->dn_ctime = statbuf.st_ctime ;
755#endif 755#endif
756 cur->dn_ino = statbuf.st_ino ; 756 cur->dn_ino = statbuf.st_ino ;
757#if !ENABLE_PLATFORM_MINGW32
757 cur->dn_blocks = statbuf.st_blocks; 758 cur->dn_blocks = statbuf.st_blocks;
759#else
760 /* MinGW does not have st_blocks */
761 cur->dn_blocks = 0;
762#endif
758 cur->dn_nlink = statbuf.st_nlink ; 763 cur->dn_nlink = statbuf.st_nlink ;
759 cur->dn_uid = statbuf.st_uid ; 764 cur->dn_uid = statbuf.st_uid ;
760 cur->dn_gid = statbuf.st_gid ; 765 cur->dn_gid = statbuf.st_gid ;
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c
index 347f879d7..8497722ba 100644
--- a/coreutils/od_bloaty.c
+++ b/coreutils/od_bloaty.c
@@ -100,6 +100,13 @@ typedef long long llong;
100# define LDBL_DIG DBL_DIG 100# define LDBL_DIG DBL_DIG
101#endif 101#endif
102 102
103#if ENABLE_PLATFORM_MINGW32
104/* symbol conflict */
105#define CHAR SIZE_CHAR
106#define SHORT SIZE_SHORT
107#define LONG SIZE_LONG
108#define INT SIZE_INT
109#endif
103enum size_spec { 110enum size_spec {
104 NO_SIZE, 111 NO_SIZE,
105 CHAR, 112 CHAR,
diff --git a/coreutils/test.c b/coreutils/test.c
index 0bc008e7c..ccfa923da 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -642,6 +642,33 @@ static int filstat(char *nm, enum token mode)
642 return 0; 642 return 0;
643 } 643 }
644 644
645#if ENABLE_PLATFORM_MINGW32
646#undef R_OK
647#define R_OK S_IREAD
648#undef W_OK
649#define W_OK S_IWRITE
650 if (mode == FILEX) {
651 int len = strlen(nm), ret;
652 if (len >= 4 &&
653 (!strcmp(nm+len-4,".exe") ||
654 !strcmp(nm+len-4,".com")))
655 ret = stat(nm, &s);
656 else {
657 char *exepath;
658 exepath = malloc(len+5);
659 memcpy(exepath, nm, len);
660 memcpy(exepath+len, ".exe", 5);
661 ret = stat(exepath, &s);
662 if (ret < 0) {
663 memcpy(exepath+len, ".exe", 5);
664 ret = stat(exepath, &s);
665 }
666 free(exepath);
667 }
668 return ret >= 0;
669 }
670#endif
671
645 if (stat(nm, &s) != 0) 672 if (stat(nm, &s) != 0)
646 return 0; 673 return 0;
647 if (mode == FILEXIST) 674 if (mode == FILEXIST)
diff --git a/coreutils/uname.c b/coreutils/uname.c
index b96d76b6c..b4827de25 100644
--- a/coreutils/uname.c
+++ b/coreutils/uname.c
@@ -68,11 +68,17 @@
68/* After libbb.h, since it needs sys/types.h on some systems */ 68/* After libbb.h, since it needs sys/types.h on some systems */
69#include <sys/utsname.h> 69#include <sys/utsname.h>
70 70
71#if ENABLE_PLATFORM_MINGW32
72# define OSNAME "MS/Windows"
73#else
74# define OSNAME "GNU/Linux"
75#endif
76
71typedef struct { 77typedef struct {
72 struct utsname name; 78 struct utsname name;
73 char processor[sizeof(((struct utsname*)NULL)->machine)]; 79 char processor[sizeof(((struct utsname*)NULL)->machine)];
74 char platform[sizeof(((struct utsname*)NULL)->machine)]; 80 char platform[sizeof(((struct utsname*)NULL)->machine)];
75 char os[sizeof("GNU/Linux")]; 81 char os[sizeof(OSNAME)];
76} uname_info_t; 82} uname_info_t;
77 83
78static const char options[] ALIGN1 = "snrvmpioa"; 84static const char options[] ALIGN1 = "snrvmpioa";
@@ -139,7 +145,7 @@ int uname_main(int argc UNUSED_PARAM, char **argv)
139#endif 145#endif
140 strcpy(uname_info.processor, unknown_str); 146 strcpy(uname_info.processor, unknown_str);
141 strcpy(uname_info.platform, unknown_str); 147 strcpy(uname_info.platform, unknown_str);
142 strcpy(uname_info.os, "GNU/Linux"); 148 strcpy(uname_info.os, OSNAME);
143#if 0 149#if 0
144 /* Fedora does something like this */ 150 /* Fedora does something like this */
145 strcpy(uname_info.processor, uname_info.name.machine); 151 strcpy(uname_info.processor, uname_info.name.machine);
diff --git a/coreutils/whoami.c b/coreutils/whoami.c
index 30b17cab3..500e07166 100644
--- a/coreutils/whoami.c
+++ b/coreutils/whoami.c
@@ -21,11 +21,21 @@
21int whoami_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 21int whoami_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
22int whoami_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 22int whoami_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
23{ 23{
24#if ENABLE_PLATFORM_MINGW32
25 char buf[64];
26 DWORD len = 64;
27#endif
28
24 if (argv[1]) 29 if (argv[1])
25 bb_show_usage(); 30 bb_show_usage();
26 31
32#if ENABLE_PLATFORM_MINGW32
33 GetUserName(buf, &len);
34 puts(buf);
35#else
27 /* Will complain and die if username not found */ 36 /* Will complain and die if username not found */
28 puts(xuid2uname(geteuid())); 37 puts(xuid2uname(geteuid()));
38#endif
29 39
30 return fflush_all(); 40 return fflush_all();
31} 41}
diff --git a/debianutils/which.c b/debianutils/which.c
index 15fd598b7..2b5804e00 100644
--- a/debianutils/which.c
+++ b/debianutils/which.c
@@ -21,6 +21,29 @@
21 21
22#include "libbb.h" 22#include "libbb.h"
23 23
24#if ENABLE_PLATFORM_MINGW32
25static char *win32_execable_file(const char *p)
26{
27 char *path;
28 int len = strlen(p) + 5;
29
30 if ( (path=malloc(len)) != NULL ) {
31 memcpy(path, p, len);
32 memcpy(path+len, ".exe", 5);
33 if (execable_file(path)) {
34 return path;
35 }
36 memcpy(path+len, ".com", 5);
37 if (execable_file(path)) {
38 return path;
39 }
40 free(path);
41 }
42
43 return NULL;
44}
45#endif
46
24int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 47int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
25int which_main(int argc UNUSED_PARAM, char **argv) 48int which_main(int argc UNUSED_PARAM, char **argv)
26{ 49{
@@ -43,13 +66,28 @@ int which_main(int argc UNUSED_PARAM, char **argv)
43 } 66 }
44 67
45 do { 68 do {
69#if ENABLE_FEATURE_PREFER_APPLETS
70 if ( find_applet_by_name(*argv) >= 0 ) {
71 puts(*argv);
72 IF_DESKTOP(if ( !opt ))
73 continue;
74 }
75#endif
76
46#if ENABLE_DESKTOP 77#if ENABLE_DESKTOP
47/* Much bloat just to support -a */ 78/* Much bloat just to support -a */
48 if (strchr(*argv, '/')) { 79 if (strchr(*argv, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(*argv, '\\'))) {
49 if (execable_file(*argv)) { 80 if (execable_file(*argv)) {
50 puts(*argv); 81 puts(*argv);
51 continue; 82 continue;
52 } 83 }
84#if ENABLE_PLATFORM_MINGW32
85 else if ((p=win32_execable_file(*argv)) != NULL) {
86 puts(p);
87 free(p);
88 continue;
89 }
90#endif
53 status = EXIT_FAILURE; 91 status = EXIT_FAILURE;
54 } else { 92 } else {
55 char *path2 = xstrdup(path); 93 char *path2 = xstrdup(path);
@@ -75,11 +113,18 @@ int which_main(int argc UNUSED_PARAM, char **argv)
75 } 113 }
76#else 114#else
77/* Just ignoring -a */ 115/* Just ignoring -a */
78 if (strchr(*argv, '/')) { 116 if (strchr(*argv, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(*argv, '\\'))) {
79 if (execable_file(*argv)) { 117 if (execable_file(*argv)) {
80 puts(*argv); 118 puts(*argv);
81 continue; 119 continue;
82 } 120 }
121#if ENABLE_PLATFORM_MINGW32
122 else if ((p=win32_execable_file(*argv)) != NULL) {
123 puts(p);
124 free(p);
125 continue;
126 }
127#endif
83 } else { 128 } else {
84 char *path2 = xstrdup(path); 129 char *path2 = xstrdup(path);
85 char *tmp = path2; 130 char *tmp = path2;
diff --git a/editors/vi.c b/editors/vi.c
index b4ad12e5c..6fae221ac 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2386,11 +2386,20 @@ static void catch_sig(int sig)
2386 2386
2387static int mysleep(int hund) // sleep for 'hund' 1/100 seconds or stdin ready 2387static int mysleep(int hund) // sleep for 'hund' 1/100 seconds or stdin ready
2388{ 2388{
2389#if ENABLE_PLATFORM_MINGW32
2390 HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
2391 DWORD ret;
2392
2393 fflush(stdout);
2394 ret = WaitForSingleObject(h, hund*10);
2395 return ret != WAIT_TIMEOUT;
2396#else
2389 struct pollfd pfd[1]; 2397 struct pollfd pfd[1];
2390 2398
2391 pfd[0].fd = STDIN_FILENO; 2399 pfd[0].fd = STDIN_FILENO;
2392 pfd[0].events = POLLIN; 2400 pfd[0].events = POLLIN;
2393 return safe_poll(pfd, 1, hund*10) > 0; 2401 return safe_poll(pfd, 1, hund*10) > 0;
2402#endif
2394} 2403}
2395 2404
2396//----- IO Routines -------------------------------------------- 2405//----- IO Routines --------------------------------------------
diff --git a/findutils/grep.c b/findutils/grep.c
index f14d6e6c1..5b8ae3bff 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -179,6 +179,14 @@ enum {
179#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L) 179#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L)
180#define NUL_DELIMITED (option_mask32 & OPT_z) 180#define NUL_DELIMITED (option_mask32 & OPT_z)
181 181
182#if ENABLE_PLATFORM_MINGW32
183# define RE_TRANSLATE_TYPE unsigned char*
184# undef ENABLE_EXTRA_COMPAT
185# define ENABLE_EXTRA_COMPAT 0
186# undef IF_EXTRA_COMPAT
187# define IF_EXTRA_COMPAT(x)
188#endif
189
182struct globals { 190struct globals {
183 int max_matches; 191 int max_matches;
184#if !ENABLE_EXTRA_COMPAT 192#if !ENABLE_EXTRA_COMPAT
diff --git a/include/libbb.h b/include/libbb.h
index 2cc146631..e776951f0 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -112,6 +112,13 @@
112# include <arpa/inet.h> 112# include <arpa/inet.h>
113#elif defined __APPLE__ 113#elif defined __APPLE__
114# include <netinet/in.h> 114# include <netinet/in.h>
115#elif ENABLE_PLATFORM_MINGW32
116# ifndef WINVER
117# define WINVER 0x0501
118# endif
119# include <winsock2.h>
120# include <ws2tcpip.h>
121# undef s_addr
115#else 122#else
116# include <arpa/inet.h> 123# include <arpa/inet.h>
117# if !defined(__socklen_t_defined) && !defined(_SOCKLEN_T_DECLARED) 124# if !defined(__socklen_t_defined) && !defined(_SOCKLEN_T_DECLARED)
@@ -136,7 +143,9 @@
136 143
137/* Some libc's forget to declare these, do it ourself */ 144/* Some libc's forget to declare these, do it ourself */
138 145
146#if !ENABLE_PLATFORM_MINGW32
139extern char **environ; 147extern char **environ;
148#endif
140#if defined(__GLIBC__) && __GLIBC__ < 2 149#if defined(__GLIBC__) && __GLIBC__ < 2
141int vdprintf(int d, const char *format, va_list ap); 150int vdprintf(int d, const char *format, va_list ap);
142#endif 151#endif
@@ -149,6 +158,10 @@ int klogctl(int type, char *b, int len);
149# define BUFSIZ 4096 158# define BUFSIZ 4096
150#endif 159#endif
151 160
161/* Can't use ENABLE_PLATFORM_MINGW32 because it's also called by host compiler */
162#if ENABLE_PLATFORM_MINGW32
163# include "mingw.h"
164#endif
152 165
153/* Busybox does not use threads, we can speed up stdio. */ 166/* Busybox does not use threads, we can speed up stdio. */
154#ifdef HAVE_UNLOCKED_STDIO 167#ifdef HAVE_UNLOCKED_STDIO
@@ -801,6 +814,9 @@ char *safe_getdomainname(void) FAST_FUNC;
801char* str_tolower(char *str) FAST_FUNC; 814char* str_tolower(char *str) FAST_FUNC;
802 815
803char *utoa(unsigned n) FAST_FUNC; 816char *utoa(unsigned n) FAST_FUNC;
817#if ENABLE_PLATFORM_MINGW32
818# define itoa bb_itoa
819#endif
804char *itoa(int n) FAST_FUNC; 820char *itoa(int n) FAST_FUNC;
805/* Returns a pointer past the formatted number, does NOT null-terminate */ 821/* Returns a pointer past the formatted number, does NOT null-terminate */
806char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) FAST_FUNC; 822char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) FAST_FUNC;
@@ -1557,6 +1573,9 @@ typedef struct procps_status_t {
1557#if ENABLE_FEATURE_TOP_SMP_PROCESS 1573#if ENABLE_FEATURE_TOP_SMP_PROCESS
1558 int last_seen_on_cpu; 1574 int last_seen_on_cpu;
1559#endif 1575#endif
1576#if ENABLE_PLATFORM_MINGW32
1577 HANDLE snapshot;
1578#endif
1560} procps_status_t; 1579} procps_status_t;
1561/* flag bits for procps_scan(xx, flags) calls */ 1580/* flag bits for procps_scan(xx, flags) calls */
1562enum { 1581enum {
@@ -1711,6 +1730,11 @@ extern const char bb_msg_standard_output[];
1711extern const char bb_hexdigits_upcase[]; 1730extern const char bb_hexdigits_upcase[];
1712 1731
1713extern const char bb_path_wtmp_file[]; 1732extern const char bb_path_wtmp_file[];
1733#if ENABLE_PLATFORM_MINGW32
1734#define bb_busybox_exec_path get_busybox_exec_path()
1735#else
1736extern const char bb_busybox_exec_path[];
1737#endif
1714 1738
1715/* Busybox mount uses either /proc/mounts or /etc/mtab to 1739/* Busybox mount uses either /proc/mounts or /etc/mtab to
1716 * get the list of currently mounted filesystems */ 1740 * get the list of currently mounted filesystems */
@@ -1724,7 +1748,6 @@ extern const char bb_path_wtmp_file[];
1724#define bb_path_motd_file "/etc/motd" 1748#define bb_path_motd_file "/etc/motd"
1725 1749
1726#define bb_dev_null "/dev/null" 1750#define bb_dev_null "/dev/null"
1727extern const char bb_busybox_exec_path[];
1728/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, 1751/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
1729 * but I want to save a few bytes here */ 1752 * but I want to save a few bytes here */
1730extern const char bb_PATH_root_path[]; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */ 1753extern const char bb_PATH_root_path[]; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */
diff --git a/include/mingw.h b/include/mingw.h
new file mode 100644
index 000000000..2cae375a6
--- /dev/null
+++ b/include/mingw.h
@@ -0,0 +1,381 @@
1#include <sys/utime.h>
2
3/*
4 * MS Windows has broken versions of snprintf/vsnprintf that return -1 if
5 * the string is too large for the buffer and don't null terminate the
6 * string if it fills the buffer. However, if we're using a sufficiently
7 * modern version of MinGW and have an appropriate source code qualifier
8 * (such as _GNU_SOURCE) MinGW will use its own standards-compliant
9 * implementation. Check for this.
10 */
11#if !defined(__USE_MINGW_ANSI_STDIO)
12#error "Must use MinGW stdio for snprintf/vsnprintf"
13#endif
14
15#define NOIMPL(name,...) static inline int name(__VA_ARGS__) { errno = ENOSYS; return -1; }
16#define IMPL(name,ret,retval,...) static inline ret name(__VA_ARGS__) { return retval; }
17
18/*
19 * sys/types.h
20 */
21typedef int gid_t;
22typedef int uid_t;
23typedef int pid_t;
24
25/*
26 * arpa/inet.h
27 */
28static inline unsigned int git_ntohl(unsigned int x) { return (unsigned int)ntohl(x); }
29#define ntohl git_ntohl
30int inet_aton(const char *cp, struct in_addr *inp);
31
32/*
33 * fcntl.h
34 */
35#define F_DUPFD 0
36#define F_GETFD 1
37#define F_SETFD 2
38#define F_GETFL 3
39#define F_SETFL 3
40#define FD_CLOEXEC 0x1
41#define O_NONBLOCK 04000
42
43/*
44 * grp.h
45 */
46
47struct group {
48 char *gr_name;
49 char *gr_passwd;
50 gid_t gr_gid;
51 char **gr_mem;
52};
53IMPL(getgrnam,struct group *,NULL,const char *name UNUSED_PARAM);
54IMPL(getgrgid,struct group *,NULL,gid_t gid UNUSED_PARAM);
55NOIMPL(initgroups,const char *group UNUSED_PARAM,gid_t gid UNUSED_PARAM);
56static inline void endgrent(void) {}
57
58/*
59 * limits.h
60 */
61#define NAME_MAX 255
62#define MAXSYMLINKS 20
63
64/*
65 * netdb.h
66 */
67
68typedef int sa_family_t;
69
70/*
71 * linux/un.h
72 */
73struct sockaddr_un {
74 sa_family_t sun_family;
75 char sun_path[1]; /* to make compiler happy, don't bother */
76};
77
78/*
79 * pwd.h
80 */
81struct passwd {
82 char *pw_name;
83 char *pw_gecos;
84 char *pw_dir;
85 uid_t pw_uid;
86 gid_t pw_gid;
87};
88
89IMPL(getpwnam,struct passwd *,NULL,const char *name UNUSED_PARAM);
90struct passwd *getpwuid(int uid);
91
92/*
93 * signal.h
94 */
95#define SIGHUP 1
96#define SIGQUIT 3
97#define SIGKILL 9
98#define SIGUSR1 10
99#define SIGUSR2 12
100#define SIGPIPE 13
101#define SIGALRM 14
102#define SIGCHLD 17
103#define SIGCONT 18
104#define SIGSTOP 19
105#define SIGTSTP 20
106#define SIGTTIN 21
107#define SIGTTOU 22
108#define SIGXCPU 24
109#define SIGXFSZ 25
110#define SIGVTALRM 26
111#define SIGWINCH 28
112
113#define SIG_UNBLOCK 1
114
115typedef void (__cdecl *sighandler_t)(int);
116struct sigaction {
117 sighandler_t sa_handler;
118 unsigned sa_flags;
119 int sa_mask;
120};
121#define sigemptyset(x) (void)0
122#define SA_RESTART 0
123
124int sigaction(int sig, struct sigaction *in, struct sigaction *out);
125sighandler_t mingw_signal(int sig, sighandler_t handler);
126NOIMPL(sigfillset,int *mask UNUSED_PARAM);
127NOIMPL(FAST_FUNC sigprocmask_allsigs, int how UNUSED_PARAM);
128NOIMPL(FAST_FUNC sigaction_set,int signo UNUSED_PARAM, const struct sigaction *sa UNUSED_PARAM);
129
130#define signal mingw_signal
131/*
132 * stdio.h
133 */
134#define fseeko(f,o,w) fseek(f,o,w)
135
136int fdprintf(int fd, const char *format, ...);
137FILE* mingw_fopen(const char *filename, const char *mode);
138int mingw_rename(const char*, const char*);
139#define fopen mingw_fopen
140#define rename mingw_rename
141
142FILE *mingw_popen(const char *cmd, const char *mode);
143int mingw_pclose(FILE *fd);
144#define popen mingw_popen
145#define pclose mingw_pclose
146
147#define setlinebuf(fd) setvbuf(fd, (char *) NULL, _IOLBF, 0)
148
149/*
150 * ANSI emulation wrappers
151 */
152
153int winansi_fputs(const char *str, FILE *stream);
154int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2)));
155int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3)));
156#define fputs winansi_fputs
157#define printf(...) winansi_printf(__VA_ARGS__)
158#define fprintf(...) winansi_fprintf(__VA_ARGS__)
159
160int winansi_get_terminal_width_height(struct winsize *win);
161
162/*
163 * stdlib.h
164 */
165#define WIFEXITED(x) ((unsigned)(x) < 259) /* STILL_ACTIVE */
166#define WEXITSTATUS(x) ((x) & 0xff)
167#define WIFSIGNALED(x) ((unsigned)(x) > 259)
168#define WTERMSIG(x) ((x) & 0x7f)
169#define WCOREDUMP(x) 0
170
171int clearenv(void);
172char *mingw_getenv(const char *name);
173int mkstemp(char *template);
174char *realpath(const char *path, char *resolved_path);
175int setenv(const char *name, const char *value, int replace);
176void unsetenv(const char *env);
177
178#define getenv mingw_getenv
179
180/*
181 * sys/ioctl.h
182 */
183
184#define TIOCGWINSZ 0x5413
185
186int ioctl(int fd, int code, ...);
187
188/*
189 * sys/socket.h
190 */
191#define hstrerror strerror
192
193#ifdef CONFIG_WIN32_NET
194int mingw_socket(int domain, int type, int protocol);
195int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);
196
197# define socket mingw_socket
198# define connect mingw_connect
199#endif
200NOIMPL(mingw_sendto,SOCKET s UNUSED_PARAM, const char *buf UNUSED_PARAM, int len UNUSED_PARAM, int flags UNUSED_PARAM, const struct sockaddr *sa UNUSED_PARAM, int salen UNUSED_PARAM);
201NOIMPL(mingw_listen,SOCKET s UNUSED_PARAM,int backlog UNUSED_PARAM);
202NOIMPL(mingw_bind,SOCKET s UNUSED_PARAM,const struct sockaddr* sa UNUSED_PARAM,int salen UNUSED_PARAM);
203
204/* Windows declaration is different */
205#define socket mingw_socket
206#define sendto mingw_sendto
207#define listen mingw_listen
208#define bind mingw_bind
209
210/*
211 * sys/stat.h
212 */
213typedef int blkcnt_t;
214typedef int nlink_t;
215
216#define S_ISUID 04000
217#define S_ISGID 02000
218#define S_ISVTX 01000
219#ifndef S_IRWXU
220#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
221#endif
222#define S_IRWXG (S_IRWXU >> 3)
223#define S_IRWXO (S_IRWXG >> 3)
224
225#define S_IFSOCK 0140000
226#define S_IFLNK 0120000 /* Symbolic link */
227#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
228#define S_ISSOCK(x) 0
229
230#define S_IRGRP (S_IRUSR >> 3)
231#define S_IWGRP (S_IWUSR >> 3)
232#define S_IXGRP (S_IXUSR >> 3)
233#define S_IROTH (S_IRGRP >> 3)
234#define S_IWOTH (S_IWGRP >> 3)
235#define S_IXOTH (S_IXGRP >> 3)
236
237NOIMPL(fchmod,int fildes UNUSED_PARAM, mode_t mode UNUSED_PARAM);
238NOIMPL(fchown,int fd UNUSED_PARAM, uid_t uid UNUSED_PARAM, gid_t gid UNUSED_PARAM);
239int mingw_mkdir(const char *path, int mode);
240#define mkdir mingw_mkdir
241
242/* Use mingw_lstat()/mingw_stat() instead of lstat()/stat() and
243 * mingw_fstat() instead of fstat() on Windows.
244 */
245#if ENABLE_LFS
246# define off_t off64_t
247#endif
248#define lseek _lseeki64
249#define stat _stati64
250int mingw_lstat(const char *file_name, struct stat *buf);
251int mingw_stat(const char *file_name, struct stat *buf);
252int mingw_fstat(int fd, struct stat *buf);
253#define fstat mingw_fstat
254#define lstat mingw_lstat
255#define _stati64(x,y) mingw_stat(x,y)
256
257/*
258 * sys/sysmacros.h
259 */
260#define makedev(a,b) 0*(a)*(b) /* avoid unused warning */
261#define minor(x) 0
262#define major(x) 0
263
264/*
265 * sys/time.h
266 */
267struct timespec {
268 time_t tv_sec;
269 long int tv_nsec;
270};
271struct itimerval {
272 struct timeval it_value, it_interval;
273};
274#define ITIMER_REAL 0
275
276int setitimer(int type, struct itimerval *in, struct itimerval *out);
277
278/*
279 * sys/wait.h
280 */
281#define WNOHANG 1
282#define WUNTRACED 2
283int waitpid(pid_t pid, int *status, unsigned options);
284
285/*
286 * time.h
287 */
288struct tm *gmtime_r(const time_t *timep, struct tm *result);
289struct tm *localtime_r(const time_t *timep, struct tm *result);
290char *strptime(const char *s, const char *format, struct tm *tm);
291
292/*
293 * unistd.h
294 */
295#define PIPE_BUF 8192
296
297IMPL(alarm,unsigned int,0,unsigned int seconds UNUSED_PARAM);
298NOIMPL(chown,const char *path UNUSED_PARAM, uid_t uid UNUSED_PARAM, gid_t gid UNUSED_PARAM);
299NOIMPL(chroot,const char *root UNUSED_PARAM);
300int mingw_dup2 (int fd, int fdto);
301char *mingw_getcwd(char *pointer, int len);
302
303
304#ifdef USE_WIN32_MMAP
305int mingw_getpagesize(void);
306#define getpagesize mingw_getpagesize
307#else
308int getpagesize(void); /* defined in MinGW's libgcc.a */
309#endif
310
311IMPL(getgid,int,1,void);
312NOIMPL(getgroups,int n UNUSED_PARAM,gid_t *groups UNUSED_PARAM);
313IMPL(getppid,int,1,void);
314IMPL(getegid,int,1,void);
315IMPL(geteuid,int,1,void);
316NOIMPL(getsid,pid_t pid UNUSED_PARAM);
317IMPL(getuid,int,1,void);
318int fcntl(int fd, int cmd, ...);
319#define fork() -1
320IMPL(fsync,int,0,int fd UNUSED_PARAM);
321int kill(pid_t pid, int sig);
322int link(const char *oldpath, const char *newpath);
323NOIMPL(mknod,const char *name UNUSED_PARAM, mode_t mode UNUSED_PARAM, dev_t device UNUSED_PARAM);
324int mingw_open (const char *filename, int oflags, ...);
325int pipe(int filedes[2]);
326NOIMPL(readlink,const char *path UNUSED_PARAM, char *buf UNUSED_PARAM, size_t bufsiz UNUSED_PARAM);
327NOIMPL(setgid,gid_t gid UNUSED_PARAM);
328NOIMPL(setsid,void);
329NOIMPL(setuid,uid_t gid UNUSED_PARAM);
330unsigned int sleep(unsigned int seconds);
331NOIMPL(symlink,const char *oldpath UNUSED_PARAM, const char *newpath UNUSED_PARAM);
332static inline void sync(void) {}
333NOIMPL(ttyname_r,int fd UNUSED_PARAM, char *buf UNUSED_PARAM, int sz UNUSED_PARAM);
334int mingw_unlink(const char *pathname);
335NOIMPL(vfork,void);
336NOIMPL(getdomainname, char *name UNUSED_PARAM, size_t len UNUSED_PARAM);
337
338#define dup2 mingw_dup2
339#define getcwd mingw_getcwd
340#define lchown chown
341#define open mingw_open
342#define unlink mingw_unlink
343
344/*
345 * utime.h
346 */
347int mingw_utime(const char *file_name, const struct utimbuf *times);
348int utimes(const char *file_name, const struct timeval times[2]);
349
350#define utime mingw_utime
351
352/*
353 * MinGW specific
354 */
355#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
356#define PRIuMAX "I64u"
357
358pid_t mingw_spawn(char **argv);
359int mingw_execv(const char *cmd, const char *const *argv);
360int mingw_execvp(const char *cmd, const char *const *argv);
361int mingw_execve(const char *cmd, const char *const *argv, const char *const *envp);
362pid_t mingw_spawn_applet(int mode, const char *applet, const char *const *argv, const char *const *envp);
363pid_t mingw_spawn_1(int mode, const char *cmd, const char *const *argv, const char *const *envp);
364#define execvp mingw_execvp
365#define execve mingw_execve
366#define execv mingw_execv
367
368const char * next_path_sep(const char *path);
369#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
370#define is_absolute_path(path) ((path)[0] == '/' || has_dos_drive_prefix(path))
371
372/*
373 * helpers
374 */
375
376char **copy_environ(const char *const *env);
377void free_environ(char **env);
378char **env_setenv(char **env, const char *name);
379
380const char *get_busybox_exec_path(void);
381void init_winsock(void);
diff --git a/include/platform.h b/include/platform.h
index d79cc97e5..b3c4eaf5d 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -7,6 +7,15 @@
7#ifndef BB_PLATFORM_H 7#ifndef BB_PLATFORM_H
8#define BB_PLATFORM_H 1 8#define BB_PLATFORM_H 1
9 9
10#if ENABLE_PLATFORM_MINGW32
11# if !defined(__MINGW32__) /* HOSTCC is called */
12# undef ENABLE_PLATFORM_MINGW32
13# endif
14#else
15# if defined(__MINGW32__)
16# error "You must select target platform MS Windows, or it won't build"
17# endif
18#endif
10 19
11/* Convenience macros to test the version of gcc. */ 20/* Convenience macros to test the version of gcc. */
12#undef __GNUC_PREREQ 21#undef __GNUC_PREREQ
@@ -116,7 +125,7 @@
116 125
117/* Make all declarations hidden (-fvisibility flag only affects definitions) */ 126/* Make all declarations hidden (-fvisibility flag only affects definitions) */
118/* (don't include system headers after this until corresponding pop!) */ 127/* (don't include system headers after this until corresponding pop!) */
119#if __GNUC_PREREQ(4,1) && !defined(__CYGWIN__) 128#if __GNUC_PREREQ(4,1) && !defined(__CYGWIN__) && !ENABLE_PLATFORM_MINGW32
120# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN _Pragma("GCC visibility push(hidden)") 129# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN _Pragma("GCC visibility push(hidden)")
121# define POP_SAVED_FUNCTION_VISIBILITY _Pragma("GCC visibility pop") 130# define POP_SAVED_FUNCTION_VISIBILITY _Pragma("GCC visibility pop")
122#else 131#else
@@ -145,6 +154,14 @@
145# define bswap_64 __bswap64 154# define bswap_64 __bswap64
146# define bswap_32 __bswap32 155# define bswap_32 __bswap32
147# define bswap_16 __bswap16 156# define bswap_16 __bswap16
157# define __BIG_ENDIAN__ (_BYTE_ORDER == _BIG_ENDIAN)
158#elif ENABLE_PLATFORM_MINGW32
159# define __BIG_ENDIAN 0
160# define __LITTLE_ENDIAN 1
161# define __BYTE_ORDER __LITTLE_ENDIAN
162# define bswap_16(x) ((((x) & 0xFF00) >> 8) | (((x) & 0xFF) << 8))
163# define bswap_32(x) ((bswap_16(((x) & 0xFFFF0000L) >> 16)) | (bswap_16((x) & 0xFFFFL) << 16))
164# define bswap_64(x) ((bswap_32(((x) & 0xFFFFFFFF00000000LL) >> 32)) | (bswap_32((x) & 0xFFFFFFFFLL) << 32))
148#else 165#else
149# include <byteswap.h> 166# include <byteswap.h>
150# include <endian.h> 167# include <endian.h>
@@ -376,6 +393,24 @@ typedef unsigned smalluint;
376# undef HAVE_STRCHRNUL 393# undef HAVE_STRCHRNUL
377#endif 394#endif
378 395
396#if ENABLE_PLATFORM_MINGW32
397# undef HAVE_DPRINTF
398# undef HAVE_MEMRCHR
399# undef HAVE_MKDTEMP
400# undef HAVE_SETBIT
401# undef HAVE_STPCPY
402# undef HAVE_STRCASESTR
403# undef HAVE_STRCHRNUL
404# undef HAVE_STRSEP
405# undef HAVE_STRSIGNAL
406# undef HAVE_STRVERSCMP
407# undef HAVE_VASPRINTF
408# undef HAVE_UNLOCKED_STDIO
409# undef HAVE_UNLOCKED_LINE_OPS
410# undef HAVE_MNTENT_H
411# undef HAVE_SYS_STATFS_H
412#endif
413
379#if defined(__WATCOMC__) 414#if defined(__WATCOMC__)
380# undef HAVE_DPRINTF 415# undef HAVE_DPRINTF
381# undef HAVE_GETLINE 416# undef HAVE_GETLINE
@@ -453,6 +488,7 @@ extern int dprintf(int fd, const char *format, ...);
453#endif 488#endif
454 489
455#ifndef HAVE_MEMRCHR 490#ifndef HAVE_MEMRCHR
491#include <stddef.h>
456extern void *memrchr(const void *s, int c, size_t n) FAST_FUNC; 492extern void *memrchr(const void *s, int c, size_t n) FAST_FUNC;
457#endif 493#endif
458 494
@@ -491,6 +527,7 @@ extern char *strsep(char **stringp, const char *delim) FAST_FUNC;
491#endif 527#endif
492 528
493#ifndef HAVE_VASPRINTF 529#ifndef HAVE_VASPRINTF
530# include <stdarg.h>
494extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC; 531extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC;
495#endif 532#endif
496 533
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 61eec26f7..ad81ce46b 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -39,25 +39,19 @@ lib-y += fgets_str.o
39lib-y += find_pid_by_name.o 39lib-y += find_pid_by_name.o
40lib-y += find_root_device.o 40lib-y += find_root_device.o
41lib-y += full_write.o 41lib-y += full_write.o
42lib-y += get_console.o
43lib-y += get_last_path_component.o 42lib-y += get_last_path_component.o
44lib-y += get_line_from_file.o 43lib-y += get_line_from_file.o
45lib-y += getopt32.o 44lib-y += getopt32.o
46lib-y += getpty.o
47lib-y += get_volsize.o 45lib-y += get_volsize.o
48lib-y += herror_msg.o 46lib-y += herror_msg.o
49lib-y += human_readable.o 47lib-y += human_readable.o
50lib-y += inet_common.o
51lib-y += info_msg.o 48lib-y += info_msg.o
52lib-y += inode_hash.o 49lib-y += inode_hash.o
53lib-y += isdirectory.o 50lib-y += isdirectory.o
54lib-y += kernel_version.o
55lib-y += last_char_is.o 51lib-y += last_char_is.o
56lib-y += lineedit.o lineedit_ptr_hack.o 52lib-y += lineedit.o lineedit_ptr_hack.o
57lib-y += llist.o 53lib-y += llist.o
58lib-y += login.o
59lib-y += make_directory.o 54lib-y += make_directory.o
60lib-y += makedev.o
61lib-y += hash_md5_sha.o 55lib-y += hash_md5_sha.o
62# Alternative (disabled) MD5 implementation 56# Alternative (disabled) MD5 implementation
63#lib-y += hash_md5prime.o 57#lib-y += hash_md5prime.o
@@ -78,7 +72,6 @@ lib-y += progress.o
78lib-y += ptr_to_globals.o 72lib-y += ptr_to_globals.o
79lib-y += read.o 73lib-y += read.o
80lib-y += read_printf.o 74lib-y += read_printf.o
81lib-y += read_key.o
82lib-y += recursive_action.o 75lib-y += recursive_action.o
83lib-y += remove_file.o 76lib-y += remove_file.o
84lib-y += run_shell.o 77lib-y += run_shell.o
@@ -87,7 +80,6 @@ lib-y += safe_poll.o
87lib-y += safe_strncpy.o 80lib-y += safe_strncpy.o
88lib-y += safe_write.o 81lib-y += safe_write.o
89lib-y += setup_environment.o 82lib-y += setup_environment.o
90lib-y += signals.o
91lib-y += simplify_path.o 83lib-y += simplify_path.o
92lib-y += single_argv.o 84lib-y += single_argv.o
93lib-y += skip_whitespace.o 85lib-y += skip_whitespace.o
@@ -107,14 +99,24 @@ lib-y += wfopen_input.o
107lib-y += write.o 99lib-y += write.o
108lib-y += xatonum.o 100lib-y += xatonum.o
109lib-y += xconnect.o 101lib-y += xconnect.o
102lib-y += xfunc_die.o
110lib-y += xfuncs.o 103lib-y += xfuncs.o
111lib-y += xfuncs_printf.o 104lib-y += xfuncs_printf.o
112lib-y += xfunc_die.o
113lib-y += xgetcwd.o 105lib-y += xgetcwd.o
114lib-y += xgethostbyname.o
115lib-y += xreadlink.o 106lib-y += xreadlink.o
116lib-y += xrealloc_vector.o 107lib-y += xrealloc_vector.o
117 108
109lib-$(CONFIG_PLATFORM_POSIX) += get_console.o
110lib-$(CONFIG_PLATFORM_POSIX) += getpty.o
111lib-$(CONFIG_PLATFORM_POSIX) += inet_common.o
112lib-$(CONFIG_PLATFORM_POSIX) += kernel_version.o
113lib-$(CONFIG_PLATFORM_POSIX) += login.o
114lib-$(CONFIG_PLATFORM_POSIX) += makedev.o
115lib-$(CONFIG_PLATFORM_POSIX) += read_key.o
116lib-$(CONFIG_PLATFORM_POSIX) += signals.o
117lib-$(CONFIG_PLATFORM_POSIX) += udp_io.o
118lib-$(CONFIG_PLATFORM_POSIX) += xgethostbyname.o
119
118lib-$(CONFIG_PLATFORM_LINUX) += match_fstype.o 120lib-$(CONFIG_PLATFORM_LINUX) += match_fstype.o
119 121
120lib-$(CONFIG_FEATURE_UTMP) += utmp.o 122lib-$(CONFIG_FEATURE_UTMP) += utmp.o
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 73f71f1d0..116e275be 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -812,6 +812,22 @@ int main(int argc UNUSED_PARAM, char **argv)
812 applet_name = argv[0]; 812 applet_name = argv[0];
813 if (applet_name[0] == '-') 813 if (applet_name[0] == '-')
814 applet_name++; 814 applet_name++;
815 if (ENABLE_PLATFORM_MINGW32) {
816 const char *applet_name_env = getenv("BUSYBOX_APPLET_NAME");
817 if (applet_name_env && *applet_name_env) {
818 applet_name = applet_name_env;
819 unsetenv("BUSYBOX_APPLET_NAME");
820 }
821 else {
822 int i, len = strlen(applet_name);
823 if (len > 4 && !strcmp(applet_name+len-4, ".exe")) {
824 len -= 4;
825 argv[0][applet_name-argv[0]+len] = '\0';
826 }
827 for (i = 0; i < len; i++)
828 argv[0][applet_name-argv[0]+i] = tolower(applet_name[i]);
829 }
830 }
815 applet_name = bb_basename(applet_name); 831 applet_name = bb_basename(applet_name);
816 832
817 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ 833 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index 9333a8d49..be65c4b47 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -100,12 +100,15 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
100 return -1; 100 return -1;
101 } 101 }
102 } else { 102 } else {
103#if !ENABLE_PLATFORM_MINGW32
104 /* MinGW does not have inode, and does not use device */
103 if (source_stat.st_dev == dest_stat.st_dev 105 if (source_stat.st_dev == dest_stat.st_dev
104 && source_stat.st_ino == dest_stat.st_ino 106 && source_stat.st_ino == dest_stat.st_ino
105 ) { 107 ) {
106 bb_error_msg("'%s' and '%s' are the same file", source, dest); 108 bb_error_msg("'%s' and '%s' are the same file", source, dest);
107 return -1; 109 return -1;
108 } 110 }
111#endif
109 dest_exists = 1; 112 dest_exists = 1;
110 } 113 }
111 114
@@ -139,6 +142,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
139 } 142 }
140 143
141 /* Did we ever create source ourself before? */ 144 /* Did we ever create source ourself before? */
145#if !ENABLE_PLATFORM_MINGW32
142 tp = is_in_ino_dev_hashtable(&source_stat); 146 tp = is_in_ino_dev_hashtable(&source_stat);
143 if (tp) { 147 if (tp) {
144 /* We did! it's a recursion! man the lifeboats... */ 148 /* We did! it's a recursion! man the lifeboats... */
@@ -146,6 +150,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
146 source); 150 source);
147 return -1; 151 return -1;
148 } 152 }
153#endif
149 154
150 if (dest_exists) { 155 if (dest_exists) {
151 if (!S_ISDIR(dest_stat.st_mode)) { 156 if (!S_ISDIR(dest_stat.st_mode)) {
@@ -176,9 +181,11 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
176 return -1; 181 return -1;
177 } 182 }
178 } 183 }
184#if !ENABLE_PLATFORM_MINGW32
179 /* remember (dev,inode) of each created dir. 185 /* remember (dev,inode) of each created dir.
180 * NULL: name is not remembered */ 186 * NULL: name is not remembered */
181 add_to_ino_dev_hashtable(&dest_stat, NULL); 187 add_to_ino_dev_hashtable(&dest_stat, NULL);
188#endif
182 189
183 /* Recursively copy files in SOURCE */ 190 /* Recursively copy files in SOURCE */
184 dp = opendir(source); 191 dp = opendir(source);
@@ -248,6 +255,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
248 goto dont_cat; 255 goto dont_cat;
249 } 256 }
250 257
258#if !ENABLE_PLATFORM_MINGW32
251 if (ENABLE_FEATURE_PRESERVE_HARDLINKS && !FLAGS_DEREF) { 259 if (ENABLE_FEATURE_PRESERVE_HARDLINKS && !FLAGS_DEREF) {
252 const char *link_target; 260 const char *link_target;
253 link_target = is_in_ino_dev_hashtable(&source_stat); 261 link_target = is_in_ino_dev_hashtable(&source_stat);
@@ -265,6 +273,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
265 } 273 }
266 add_to_ino_dev_hashtable(&source_stat, dest); 274 add_to_ino_dev_hashtable(&source_stat, dest);
267 } 275 }
276#endif
268 277
269 src_fd = open_or_warn(source, O_RDONLY); 278 src_fd = open_or_warn(source, O_RDONLY);
270 if (src_fd < 0) 279 if (src_fd < 0)
diff --git a/libbb/execable.c b/libbb/execable.c
index 178a00a5f..afb957e43 100644
--- a/libbb/execable.c
+++ b/libbb/execable.c
@@ -16,7 +16,31 @@
16int FAST_FUNC execable_file(const char *name) 16int FAST_FUNC execable_file(const char *name)
17{ 17{
18 struct stat s; 18 struct stat s;
19#if ENABLE_PLATFORM_MINGW32
20 if (!stat(name, &s) && S_ISREG(s.st_mode)) {
21 int len, fd, n;
22 char buf[100];
23
24 if ((len=strlen(name)) > 4 &&
25 (!strcasecmp(name+len-4, ".exe") ||
26 !strcasecmp(name+len-4, ".com"))) {
27 return 1;
28 }
29
30 fd = open(name, O_RDONLY);
31 if (fd < 0)
32 return 0;
33 n = read(fd, buf, sizeof(buf)-1);
34 close(fd);
35 if (n < 4) /* at least '#!/x' and not error */
36 return 0;
37
38 return (buf[0] == '#' && buf[1] == '!');
39 }
40 return 0;
41#else
19 return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); 42 return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode));
43#endif
20} 44}
21 45
22/* search (*PATHp) for an executable file; 46/* search (*PATHp) for an executable file;
@@ -28,13 +52,17 @@ int FAST_FUNC execable_file(const char *name)
28 * return NULL otherwise; (PATHp is undefined) 52 * return NULL otherwise; (PATHp is undefined)
29 * in all cases (*PATHp) contents will be trashed (s/:/NUL/). 53 * in all cases (*PATHp) contents will be trashed (s/:/NUL/).
30 */ 54 */
55#if !ENABLE_PLATFORM_MINGW32
56#define next_path_sep(s) strchr(s, ':')
57#endif
58
31char* FAST_FUNC find_execable(const char *filename, char **PATHp) 59char* FAST_FUNC find_execable(const char *filename, char **PATHp)
32{ 60{
33 char *p, *n; 61 char *p, *n;
34 62
35 p = *PATHp; 63 p = *PATHp;
36 while (p) { 64 while (p) {
37 n = strchr(p, ':'); 65 n = (char*)next_path_sep(p);
38 if (n) 66 if (n)
39 *n++ = '\0'; 67 *n++ = '\0';
40 if (*p != '\0') { /* it's not a PATH="foo::bar" situation */ 68 if (*p != '\0') { /* it's not a PATH="foo::bar" situation */
@@ -43,6 +71,29 @@ char* FAST_FUNC find_execable(const char *filename, char **PATHp)
43 *PATHp = n; 71 *PATHp = n;
44 return p; 72 return p;
45 } 73 }
74 if (ENABLE_PLATFORM_MINGW32) {
75 int len = strlen(p);
76 if (len > 4 &&
77 (!strcasecmp(p+len-4, ".exe") ||
78 !strcasecmp(p+len-4, ".com")))
79 ; /* nothing, already tested by find_execable() */
80 else {
81 char *np = xmalloc(len+4+1);
82 memcpy(np, p, len);
83 memcpy(np+len, ".exe", 5);
84 if (execable_file(np)) {
85 *PATHp = n;
86 free(p);
87 return np;
88 }
89 memcpy(np+len, ".com", 5);
90 if (execable_file(np)) {
91 *PATHp = n;
92 free(p);
93 return np;
94 }
95 }
96 }
46 free(p); 97 free(p);
47 } 98 }
48 p = n; 99 p = n;
diff --git a/libbb/find_pid_by_name.c b/libbb/find_pid_by_name.c
index db823d05b..d4bea8ab5 100644
--- a/libbb/find_pid_by_name.c
+++ b/libbb/find_pid_by_name.c
@@ -56,6 +56,7 @@ static int comm_match(procps_status_t *p, const char *procName)
56 * This can be crazily_long_script_name.sh! 56 * This can be crazily_long_script_name.sh!
57 * The telltale sign is basename(argv[1]) == procName */ 57 * The telltale sign is basename(argv[1]) == procName */
58 58
59#if !ENABLE_PLATFORM_MINGW32
59 if (!p->argv0) 60 if (!p->argv0)
60 return 0; 61 return 0;
61 62
@@ -66,6 +67,7 @@ static int comm_match(procps_status_t *p, const char *procName)
66 67
67 if (strcmp(bb_basename(argv1), procName) != 0) 68 if (strcmp(bb_basename(argv1), procName) != 0)
68 return 0; 69 return 0;
70#endif
69 71
70 return 1; 72 return 1;
71} 73}
@@ -88,10 +90,12 @@ pid_t* FAST_FUNC find_pid_by_name(const char *procName)
88 pidList = xzalloc(sizeof(*pidList)); 90 pidList = xzalloc(sizeof(*pidList));
89 while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN|PSSCAN_EXE))) { 91 while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN|PSSCAN_EXE))) {
90 if (comm_match(p, procName) 92 if (comm_match(p, procName)
93#if !ENABLE_PLATFORM_MINGW32
91 /* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/ 94 /* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/
92 || (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0) 95 || (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0)
93 /* or we require /proc/PID/exe link to match */ 96 /* or we require /proc/PID/exe link to match */
94 || (p->exe && strcmp(bb_basename(p->exe), procName) == 0) 97 || (p->exe && strcmp(bb_basename(p->exe), procName) == 0)
98#endif
95 ) { 99 ) {
96 pidList = xrealloc_vector(pidList, 2, i); 100 pidList = xrealloc_vector(pidList, 2, i);
97 pidList[i++] = p->pid; 101 pidList[i++] = p->pid;
diff --git a/libbb/get_last_path_component.c b/libbb/get_last_path_component.c
index 04fdf2a3e..db4be68ad 100644
--- a/libbb/get_last_path_component.c
+++ b/libbb/get_last_path_component.c
@@ -13,6 +13,11 @@ const char* FAST_FUNC bb_basename(const char *name)
13 const char *cp = strrchr(name, '/'); 13 const char *cp = strrchr(name, '/');
14 if (cp) 14 if (cp)
15 return cp + 1; 15 return cp + 1;
16#if ENABLE_PLATFORM_MINGW32
17 cp = strrchr(name, '\\');
18 if (cp)
19 return cp + 1;
20#endif
16 return name; 21 return name;
17} 22}
18 23
diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c
index a98dd35eb..2038fac7d 100644
--- a/libbb/get_line_from_file.c
+++ b/libbb/get_line_from_file.c
@@ -57,6 +57,10 @@ char* FAST_FUNC xmalloc_fgetline(FILE *file)
57 57
58 if (i && c[--i] == '\n') 58 if (i && c[--i] == '\n')
59 c[i] = '\0'; 59 c[i] = '\0';
60#if ENABLE_PLATFORM_MINGW32
61 if (i && c[--i] == '\r')
62 c[i] = '\0';
63#endif
60 64
61 return c; 65 return c;
62} 66}
diff --git a/libbb/get_shell_name.c b/libbb/get_shell_name.c
index c930afd94..d196d293d 100644
--- a/libbb/get_shell_name.c
+++ b/libbb/get_shell_name.c
@@ -17,9 +17,11 @@ const char *get_shell_name(void)
17 if (shell && shell[0]) 17 if (shell && shell[0])
18 return shell; 18 return shell;
19 19
20#if !ENABLE_PLATFORM_MINGW32
20 pw = getpwuid(getuid()); 21 pw = getpwuid(getuid());
21 if (pw && pw->pw_shell && pw->pw_shell[0]) 22 if (pw && pw->pw_shell && pw->pw_shell[0])
22 return pw->pw_shell; 23 return pw->pw_shell;
24#endif
23 25
24 return DEFAULT_SHELL; 26 return DEFAULT_SHELL;
25} 27}
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index d0e83d88e..ae019b26b 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -540,7 +540,7 @@ getopt32(char **argv, const char *applet_opts, ...)
540 * run_nofork_applet() does this, but we might end up here 540 * run_nofork_applet() does this, but we might end up here
541 * also via gunzip_main() -> gzip_main(). Play safe. 541 * also via gunzip_main() -> gzip_main(). Play safe.
542 */ 542 */
543#ifdef __GLIBC__ 543#if defined(__GLIBC__) || ENABLE_PLATFORM_MINGW32
544 optind = 0; 544 optind = 0;
545#else /* BSD style */ 545#else /* BSD style */
546 optind = 1; 546 optind = 1;
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index db8416712..77dc1c607 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -715,7 +715,11 @@ static int path_parse(char ***p)
715 tmp = (char*)pth; 715 tmp = (char*)pth;
716 npth = 1; /* path component count */ 716 npth = 1; /* path component count */
717 while (1) { 717 while (1) {
718#if ENABLE_PLATFORM_MINGW32
719 tmp = next_path_sep(tmp);
720#else
718 tmp = strchr(tmp, ':'); 721 tmp = strchr(tmp, ':');
722#endif
719 if (!tmp) 723 if (!tmp)
720 break; 724 break;
721 tmp++; 725 tmp++;
@@ -728,7 +732,11 @@ static int path_parse(char ***p)
728 res[0] = tmp = xstrdup(pth); 732 res[0] = tmp = xstrdup(pth);
729 npth = 1; 733 npth = 1;
730 while (1) { 734 while (1) {
735#if ENABLE_PLATFORM_MINGW32
736 tmp = next_path_sep(tmp);
737#else
731 tmp = strchr(tmp, ':'); 738 tmp = strchr(tmp, ':');
739#endif
732 if (!tmp) 740 if (!tmp)
733 break; 741 break;
734 *tmp++ = '\0'; /* ':' -> '\0' */ 742 *tmp++ = '\0'; /* ':' -> '\0' */
@@ -2161,9 +2169,16 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2161 2169
2162 INIT_S(); 2170 INIT_S();
2163 2171
2172#if ENABLE_PLATFORM_MINGW32
2173 memset(initial_settings.c_cc, sizeof(initial_settings.c_cc), 0);
2174 initial_settings.c_cc[VINTR] = CTRL('C');
2175 initial_settings.c_cc[VEOF] = CTRL('D');
2176 if (!isatty(0) || !isatty(1)) {
2177#else
2164 if (tcgetattr(STDIN_FILENO, &initial_settings) < 0 2178 if (tcgetattr(STDIN_FILENO, &initial_settings) < 0
2165 || !(initial_settings.c_lflag & ECHO) 2179 || !(initial_settings.c_lflag & ECHO)
2166 ) { 2180 ) {
2181#endif
2167 /* Happens when e.g. stty -echo was run before */ 2182 /* Happens when e.g. stty -echo was run before */
2168 parse_and_put_prompt(prompt); 2183 parse_and_put_prompt(prompt);
2169 /* fflush_all(); - done by parse_and_put_prompt */ 2184 /* fflush_all(); - done by parse_and_put_prompt */
diff --git a/libbb/make_directory.c b/libbb/make_directory.c
index 72303e7a3..8057f2cec 100644
--- a/libbb/make_directory.c
+++ b/libbb/make_directory.c
@@ -31,7 +31,7 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
31 mode_t cur_mask; 31 mode_t cur_mask;
32 mode_t org_mask; 32 mode_t org_mask;
33 const char *fail_msg; 33 const char *fail_msg;
34 char *s; 34 char *s, *s2;
35 char c; 35 char c;
36 struct stat st; 36 struct stat st;
37 37
@@ -45,14 +45,21 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
45 c = '\0'; 45 c = '\0';
46 46
47 if (flags & FILEUTILS_RECUR) { /* Get the parent */ 47 if (flags & FILEUTILS_RECUR) { /* Get the parent */
48 /* skip drive letter and initial slashes */
49 if (ENABLE_PLATFORM_MINGW32 && s == path && *s && s[1] == ':') {
50 s += 2;
51 while (*s == '/')
52 s++;
53 }
48 /* Bypass leading non-'/'s and then subsequent '/'s */ 54 /* Bypass leading non-'/'s and then subsequent '/'s */
49 while (*s) { 55 while (*s) {
50 if (*s == '/') { 56 if (*s == '/') {
57 s2 = s;
58 c = *s2; /* Save the current char */
59 *s2 = 0; /* and replace it with nul. */
51 do { 60 do {
52 ++s; 61 ++s;
53 } while (*s == '/'); 62 } while (*s == '/');
54 c = *s; /* Save the current char */
55 *s = '\0'; /* and replace it with nul */
56 break; 63 break;
57 } 64 }
58 ++s; 65 ++s;
@@ -113,7 +120,7 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
113 } 120 }
114 121
115 /* Remove any inserted nul from the path (recursive mode) */ 122 /* Remove any inserted nul from the path (recursive mode) */
116 *s = c; 123 *s2 = c;
117 } /* while (1) */ 124 } /* while (1) */
118 125
119 bb_perror_msg("can't %s directory '%s'", fail_msg, path); 126 bb_perror_msg("can't %s directory '%s'", fail_msg, path);
diff --git a/libbb/messages.c b/libbb/messages.c
index fad82c9da..ef42b30d7 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -35,7 +35,9 @@ const char bb_msg_standard_output[] ALIGN1 = "standard output";
35 35
36const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF"; 36const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF";
37 37
38#if !ENABLE_PLATFORM_MINGW32
38const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH; 39const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH;
40#endif
39const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL; 41const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL;
40/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, 42/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
41 * but I want to save a few bytes here. Check libbb.h before changing! */ 43 * but I want to save a few bytes here. Check libbb.h before changing! */
diff --git a/libbb/procps.c b/libbb/procps.c
index 40587db82..dbae46e33 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -75,6 +75,7 @@ const char* FAST_FUNC get_cached_groupname(gid_t gid)
75 return get_cached(&groupname, gid, gid2group_utoa); 75 return get_cached(&groupname, gid, gid2group_utoa);
76} 76}
77 77
78#if !ENABLE_PLATFORM_MINGW32
78 79
79#define PROCPS_BUFSIZE 1024 80#define PROCPS_BUFSIZE 1024
80 81
@@ -569,6 +570,8 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
569 return sp; 570 return sp;
570} 571}
571 572
573#endif /* ENABLE_PLATFORM_MINGW32 */
574
572void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) 575void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
573{ 576{
574 int sz; 577 int sz;
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index ed1f86f0c..6611dabfa 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -25,6 +25,9 @@ pid_t FAST_FUNC spawn(char **argv)
25 volatile int failed; 25 volatile int failed;
26 pid_t pid; 26 pid_t pid;
27 27
28 if (ENABLE_PLATFORM_MINGW32)
29 return mingw_spawn(argv);
30
28 fflush_all(); 31 fflush_all();
29 32
30 /* Be nice to nommu machines. */ 33 /* Be nice to nommu machines. */
@@ -183,7 +186,7 @@ int FAST_FUNC spawn_and_wait(char **argv)
183 { 186 {
184 return run_nofork_applet(a, argv); 187 return run_nofork_applet(a, argv);
185 } 188 }
186# if BB_MMU 189# if BB_MMU && !ENABLE_PLATFORM_MINGW32
187 /* MMU only */ 190 /* MMU only */
188 /* a->noexec is true */ 191 /* a->noexec is true */
189 rc = fork(); 192 rc = fork();
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index ec95af222..f2faa6d7a 100644
--- a/libbb/xreadlink.c
+++ b/libbb/xreadlink.c
@@ -59,7 +59,7 @@ char* FAST_FUNC xmalloc_follow_symlinks(const char *path)
59 linkpath = xmalloc_readlink(buf); 59 linkpath = xmalloc_readlink(buf);
60 if (!linkpath) { 60 if (!linkpath) {
61 /* not a symlink, or doesn't exist */ 61 /* not a symlink, or doesn't exist */
62 if (errno == EINVAL || errno == ENOENT) 62 if (errno == EINVAL || errno == ENOENT || (ENABLE_PLATFORM_MINGW32 && errno == ENOSYS))
63 return buf; 63 return buf;
64 goto free_buf_ret_null; 64 goto free_buf_ret_null;
65 } 65 }
diff --git a/networking/wget.c b/networking/wget.c
index 1991a1072..ea46d1795 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -886,6 +886,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
886#endif 886#endif
887 887
888 INIT_G(); 888 INIT_G();
889 IF_WIN32_NET(init_winsock();)
889 890
890 IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) 891 IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;)
891 G.proxy_flag = "on"; /* use proxies if env vars are set */ 892 G.proxy_flag = "on"; /* use proxies if env vars are set */
diff --git a/procps/ps.c b/procps/ps.c
index 4727b218b..aa004aa22 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -372,13 +372,19 @@ static void func_pcpu(char *buf, int size, const procps_status_t *ps)
372 372
373static const ps_out_t out_spec[] = { 373static const ps_out_t out_spec[] = {
374/* Mandated by http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html: */ 374/* Mandated by http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html: */
375#if !ENABLE_PLATFORM_MINGW32
375 { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, 376 { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID },
376 { 8 , "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, 377 { 8 , "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID },
378#endif
377 { 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM }, 379 { 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM },
380#if !ENABLE_PLATFORM_MINGW32
378 { MAX_WIDTH , "args" ,"COMMAND",func_args ,PSSCAN_COMM }, 381 { MAX_WIDTH , "args" ,"COMMAND",func_args ,PSSCAN_COMM },
382#endif
379 { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID }, 383 { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID },
384#if !ENABLE_PLATFORM_MINGW32
380 { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID }, 385 { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID },
381 { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID }, 386 { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID },
387#endif
382#if ENABLE_FEATURE_PS_TIME 388#if ENABLE_FEATURE_PS_TIME
383 { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME }, 389 { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME },
384#endif 390#endif
@@ -391,11 +397,13 @@ static const ps_out_t out_spec[] = {
391#if ENABLE_FEATURE_PS_TIME 397#if ENABLE_FEATURE_PS_TIME
392 { 6 , "time" ,"TIME" ,func_time ,PSSCAN_STIME | PSSCAN_UTIME }, 398 { 6 , "time" ,"TIME" ,func_time ,PSSCAN_STIME | PSSCAN_UTIME },
393#endif 399#endif
400#if !ENABLE_PLATFORM_MINGW32
394 { 6 , "tty" ,"TT" ,func_tty ,PSSCAN_TTY }, 401 { 6 , "tty" ,"TT" ,func_tty ,PSSCAN_TTY },
395 { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ }, 402 { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ },
396/* Not mandated, but useful: */ 403/* Not mandated, but useful: */
397 { 4 , "stat" ,"STAT" ,func_state ,PSSCAN_STATE }, 404 { 4 , "stat" ,"STAT" ,func_state ,PSSCAN_STATE },
398 { 4 , "rss" ,"RSS" ,func_rss ,PSSCAN_RSS }, 405 { 4 , "rss" ,"RSS" ,func_rss ,PSSCAN_RSS },
406#endif
399#if ENABLE_SELINUX 407#if ENABLE_SELINUX
400 { 35 , "label" ,"LABEL" ,func_label ,PSSCAN_CONTEXT }, 408 { 35 , "label" ,"LABEL" ,func_label ,PSSCAN_CONTEXT },
401#endif 409#endif
@@ -534,6 +542,8 @@ static void format_process(const procps_status_t *ps)
534#if ENABLE_SELINUX 542#if ENABLE_SELINUX
535# define SELINUX_O_PREFIX "label," 543# define SELINUX_O_PREFIX "label,"
536# define DEFAULT_O_STR (SELINUX_O_PREFIX "pid,user" IF_FEATURE_PS_TIME(",time") ",args") 544# define DEFAULT_O_STR (SELINUX_O_PREFIX "pid,user" IF_FEATURE_PS_TIME(",time") ",args")
545#elif ENABLE_PLATFORM_MINGW32
546# define DEFAULT_O_STR ("pid,comm")
537#else 547#else
538# define DEFAULT_O_STR ("pid,user" IF_FEATURE_PS_TIME(",time") ",args") 548# define DEFAULT_O_STR ("pid,user" IF_FEATURE_PS_TIME(",time") ",args")
539#endif 549#endif
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 165a8c39d..b7f9e0c2f 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -104,7 +104,9 @@
104 104
105#include <sys/types.h> 105#include <sys/types.h>
106#include <sys/stat.h> 106#include <sys/stat.h>
107#ifndef __MINGW32__
107#include <sys/mman.h> 108#include <sys/mman.h>
109#endif
108#include <unistd.h> 110#include <unistd.h>
109#include <fcntl.h> 111#include <fcntl.h>
110#include <string.h> 112#include <string.h>
@@ -112,7 +114,9 @@
112#include <stdio.h> 114#include <stdio.h>
113#include <limits.h> 115#include <limits.h>
114#include <ctype.h> 116#include <ctype.h>
117#ifndef __MINGW32__
115#include <arpa/inet.h> 118#include <arpa/inet.h>
119#endif
116#include <alloca.h> 120#include <alloca.h>
117 121
118/* bbox: not needed 122/* bbox: not needed
@@ -122,6 +126,53 @@
122#define INT_FIG_ ntohl(0x4649475f) 126#define INT_FIG_ ntohl(0x4649475f)
123*/ 127*/
124 128
129#ifdef __MINGW32__
130#define UNUSED __attribute__ ((__unused__))
131
132/* Workaround specifically for fixdep */
133#define PROT_READ 0
134#define MAP_PRIVATE 0
135void *mmap(void *start UNUSED, size_t size, int prot UNUSED,
136 int flags UNUSED, int fd, off_t offset UNUSED)
137{
138 void *p;
139 void *curP;
140 ssize_t readB;
141
142 p = malloc(size);
143 if (!p)
144 return (void*)((long)-1);
145
146 curP = p;
147
148 while (size > 0)
149 {
150 readB = read(fd, curP, size);
151
152 if (readB == 0)
153 {
154 /* EOF reached */
155 break;
156 }
157 else if (readB < 0)
158 {
159 perror("fixdep: read config");
160 free(p);
161 return (void*)((long)-1);
162 }
163
164 size -= readB;
165 curP += readB;
166 }
167
168 return p;
169}
170void munmap(void *p, size_t size UNUSED)
171{
172 free(p);
173}
174#endif
175
125char *target; 176char *target;
126char *depfile; 177char *depfile;
127char *cmdline; 178char *cmdline;
diff --git a/shell/ash.c b/shell/ash.c
index d197fa19a..3719066b9 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -17,6 +17,20 @@
17 */ 17 */
18 18
19/* 19/*
20 * MinGW notes
21 *
22 * - Environment variables from Windows will all be turned to uppercase.
23 * - PATH accepts both ; and : as separator, but can't be mixed
24 * - command without ".exe" extension is still understood as executable
25 * - shell scripts on the path are detected by the presence of '#!';
26 * the path to the interpreter is ignored, PATH is searched to find it
27 * - both / and \ are supported in PATH. Usually you must use /
28 * - trap/job does not work
29 * - /dev/null is supported for redirection
30 * - no $PPID
31 */
32
33/*
20 * The following should be set to reflect the type of system you have: 34 * The following should be set to reflect the type of system you have:
21 * JOBS -> 1 if you have Berkeley job control, 0 otherwise. 35 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
22 * define SYSV if you are running under System V. 36 * define SYSV if you are running under System V.
@@ -36,7 +50,10 @@
36 50
37#define JOBS ENABLE_ASH_JOB_CONTROL 51#define JOBS ENABLE_ASH_JOB_CONTROL
38 52
53#include "busybox.h" /* for applet_names */
54#if !ENABLE_PLATFORM_MINGW32
39#include <paths.h> 55#include <paths.h>
56#endif
40#include <setjmp.h> 57#include <setjmp.h>
41#include <fnmatch.h> 58#include <fnmatch.h>
42#include <sys/times.h> 59#include <sys/times.h>
@@ -70,6 +87,10 @@
70# define PIPE_BUF 4096 /* amount of buffering in a pipe */ 87# define PIPE_BUF 4096 /* amount of buffering in a pipe */
71#endif 88#endif
72 89
90#if !ENABLE_PLATFORM_MINGW32
91# define is_absolute_path(path) ((path)[0] == '/')
92#endif
93
73#if !BB_MMU 94#if !BB_MMU
74# error "Do not even bother, ash will not run on NOMMU machine" 95# error "Do not even bother, ash will not run on NOMMU machine"
75#endif 96#endif
@@ -192,6 +213,41 @@
192//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o 213//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
193//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o 214//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
194 215
216#if ENABLE_PLATFORM_MINGW32
217struct forkshell;
218union node;
219struct strlist;
220struct job;
221
222typedef void (*forkpoint_fn)(struct forkshell *fs);
223struct forkshell {
224 /* filled by forkshell_copy() */
225 struct globals_var *gvp;
226 struct globals_misc *gmp;
227 struct tblentry **cmdtable;
228 struct localvar *localvars;
229 /* struct alias **atab; */
230 /* struct parsefile *g_parsefile; */
231 int fpid;
232 HANDLE hMapFile;
233 void *old_base;
234 int nodeptr_offset;
235 int size;
236
237 forkpoint_fn fp;
238 /* optional data, used by forkpoint_fn */
239 int flags;
240 int fd[10];
241 union node *n;
242 char **argv;
243 char *string;
244 struct strlist *strlist;
245 pid_t pid;
246};
247static void sticky_free(void *p);
248#define free(p) sticky_free(p)
249static int spawn_forkshell(struct job *jp, struct forkshell *fs, int mode);
250#endif
195 251
196/* ============ Hash table sizes. Configurable. */ 252/* ============ Hash table sizes. Configurable. */
197 253
@@ -2382,10 +2438,22 @@ path_advance(const char **path, const char *name)
2382 if (*path == NULL) 2438 if (*path == NULL)
2383 return NULL; 2439 return NULL;
2384 start = *path; 2440 start = *path;
2441#if ENABLE_PLATFORM_MINGW32
2442 p = next_path_sep(start);
2443 q = strchr(start, '%');
2444 if ((p && q && q < p) || (!p && q))
2445 p = q;
2446 if (!p)
2447 for (p = start; *p; p++)
2448 continue;
2449#else
2385 for (p = start; *p && *p != ':' && *p != '%'; p++) 2450 for (p = start; *p && *p != ':' && *p != '%'; p++)
2386 continue; 2451 continue;
2452#endif
2387 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ 2453 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2388 while (stackblocksize() < len) 2454
2455 /* preserve space for .exe too */
2456 while (stackblocksize() < (ENABLE_PLATFORM_MINGW32 ? len+4 : len))
2389 growstackblock(); 2457 growstackblock();
2390 q = stackblock(); 2458 q = stackblock();
2391 if (p != start) { 2459 if (p != start) {
@@ -2397,10 +2465,19 @@ path_advance(const char **path, const char *name)
2397 pathopt = NULL; 2465 pathopt = NULL;
2398 if (*p == '%') { 2466 if (*p == '%') {
2399 pathopt = ++p; 2467 pathopt = ++p;
2468#if ENABLE_PLATFORM_MINGW32
2469 p = next_path_sep(start);
2470
2471 /* *p != ':' and '*' would suffice */
2472 if (!p)
2473 p = pathopt - 1;
2474#else
2400 while (*p && *p != ':') 2475 while (*p && *p != ':')
2401 p++; 2476 p++;
2477#endif
2402 } 2478 }
2403 if (*p == ':') 2479 if (*p == ':' ||
2480 (ENABLE_PLATFORM_MINGW32 && *p == ';'))
2404 *path = p + 1; 2481 *path = p + 1;
2405 else 2482 else
2406 *path = NULL; 2483 *path = NULL;
@@ -2502,6 +2579,99 @@ cdopt(void)
2502static const char * 2579static const char *
2503updatepwd(const char *dir) 2580updatepwd(const char *dir)
2504{ 2581{
2582#if ENABLE_PLATFORM_MINGW32
2583#define is_path_sep(x) ((x) == '/' || (x) == '\\')
2584 /*
2585 * Due to Windows drive notion, getting pwd is a completely
2586 * different thing. Handle it in a separate routine
2587 */
2588
2589 char *new;
2590 char *p;
2591 char *cdcomppath;
2592 const char *lim;
2593 /*
2594 * There are four cases
2595 * absdrive + abspath: c:/path
2596 * absdrive + !abspath: c:path
2597 * !absdrive + abspath: /path
2598 * !absdrive + !abspath: path
2599 *
2600 * Damn DOS!
2601 * c:path behaviour is "undefined"
2602 * To properly handle this case, I have to keep track of cwd
2603 * of every drive, which is too painful to do.
2604 * So when c:path is given, I assume it's c:${curdir}path
2605 * with ${curdir} comes from the current drive
2606 */
2607 int absdrive = *dir && dir[1] == ':';
2608 int abspath = absdrive ? is_path_sep(dir[2]) : is_path_sep(*dir);
2609 char *drive;
2610
2611 cdcomppath = ststrdup(dir);
2612 STARTSTACKSTR(new);
2613 if (!absdrive && curdir == nullstr)
2614 return 0;
2615 if (!abspath) {
2616 if (curdir == nullstr)
2617 return 0;
2618 new = stack_putstr(curdir, new);
2619 }
2620 new = makestrspace(strlen(dir) + 2, new);
2621
2622 drive = stackblock();
2623 if (absdrive) {
2624 *drive = *dir;
2625 cdcomppath += 2;
2626 dir += 2;
2627 } else {
2628 *drive = *curdir;
2629 }
2630 drive[1] = ':'; /* in case of absolute drive+path */
2631
2632 if (abspath)
2633 new = drive + 2;
2634 lim = drive + 3;
2635 if (!abspath) {
2636 if (!is_path_sep(new[-1]))
2637 USTPUTC('/', new);
2638 if (new > lim && is_path_sep(*lim))
2639 lim++;
2640 } else {
2641 USTPUTC('/', new);
2642 cdcomppath ++;
2643 if (is_path_sep(dir[1]) && !is_path_sep(dir[2])) {
2644 USTPUTC('/', new);
2645 cdcomppath++;
2646 lim++;
2647 }
2648 }
2649 p = strtok(cdcomppath, "/\\");
2650 while (p) {
2651 switch (*p) {
2652 case '.':
2653 if (p[1] == '.' && p[2] == '\0') {
2654 while (new > lim) {
2655 STUNPUTC(new);
2656 if (is_path_sep(new[-1]))
2657 break;
2658 }
2659 break;
2660 }
2661 if (p[1] == '\0')
2662 break;
2663 /* fall through */
2664 default:
2665 new = stack_putstr(p, new);
2666 USTPUTC('/', new);
2667 }
2668 p = strtok(0, "/\\");
2669 }
2670 if (new > lim)
2671 STUNPUTC(new);
2672 *new = 0;
2673 return stackblock();
2674#else
2505 char *new; 2675 char *new;
2506 char *p; 2676 char *p;
2507 char *cdcomppath; 2677 char *cdcomppath;
@@ -2555,6 +2725,7 @@ updatepwd(const char *dir)
2555 STUNPUTC(new); 2725 STUNPUTC(new);
2556 *new = 0; 2726 *new = 0;
2557 return stackblock(); 2727 return stackblock();
2728#endif
2558} 2729}
2559 2730
2560/* 2731/*
@@ -2649,7 +2820,7 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2649 } 2820 }
2650 if (!dest) 2821 if (!dest)
2651 dest = nullstr; 2822 dest = nullstr;
2652 if (*dest == '/') 2823 if (is_absolute_path(dest))
2653 goto step7; 2824 goto step7;
2654 if (*dest == '.') { 2825 if (*dest == '.') {
2655 c = dest[1]; 2826 c = dest[1];
@@ -3421,6 +3592,8 @@ setsignal(int signo)
3421 char cur_act, new_act; 3592 char cur_act, new_act;
3422 struct sigaction act; 3593 struct sigaction act;
3423 3594
3595 if (ENABLE_PLATFORM_MINGW32)
3596 return;
3424 t = trap[signo]; 3597 t = trap[signo];
3425 new_act = S_DFL; 3598 new_act = S_DFL;
3426 if (t != NULL) { /* trap for this sig is set */ 3599 if (t != NULL) { /* trap for this sig is set */
@@ -3941,6 +4114,79 @@ sprint_status(char *s, int status, int sigonly)
3941 return col; 4114 return col;
3942} 4115}
3943 4116
4117#if ENABLE_PLATFORM_MINGW32
4118
4119HANDLE hSIGINT; /* Ctrl-C is pressed */
4120
4121static BOOL WINAPI ctrl_handler(DWORD dwCtrlType)
4122{
4123 if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) {
4124 SetEvent(hSIGINT);
4125 return TRUE;
4126 }
4127 return FALSE;
4128}
4129
4130/*
4131 * Windows does not know about parent-child relationship
4132 * They don't support waitpid(-1)
4133 */
4134static pid_t
4135waitpid_child(int *status, int wait_flags)
4136{
4137 HANDLE *pidlist, *pidp;
4138 int pid_nr = 0;
4139 pid_t pid;
4140 DWORD win_status, idx;
4141 struct job *jb;
4142
4143 #define LOOP(stmt) \
4144 for (jb = curjob; jb; jb = jb->prev_job) { \
4145 struct procstat *ps, *psend; \
4146 if (jb->state == JOBDONE) \
4147 continue; \
4148 ps = jb->ps; \
4149 psend = ps + jb->nprocs; \
4150 while (ps < psend) { \
4151 if (ps->ps_pid != -1) { \
4152 stmt; \
4153 } \
4154 ps++; \
4155 } \
4156 }
4157
4158 LOOP(pid_nr++);
4159 if (!pid_nr)
4160 return -1;
4161 pid_nr++;
4162 pidp = pidlist = ckmalloc(sizeof(*pidlist)*pid_nr);
4163 *pidp++ = hSIGINT;
4164 LOOP(*pidp++ = (HANDLE)ps->ps_pid);
4165 #undef LOOP
4166
4167 idx = WaitForMultipleObjects(pid_nr, pidlist, FALSE,
4168 wait_flags|WNOHANG ? 0 : INFINITE);
4169 if (idx >= pid_nr) {
4170 free(pidlist);
4171 return -1;
4172 }
4173 if (!idx) { /* hSIGINT */
4174 int i;
4175 ResetEvent(hSIGINT);
4176 for (i = 1; i < pid_nr; i++)
4177 TerminateProcess(pidlist[i], 1);
4178 free(pidlist);
4179 *status = 260; /* terminated by a signal */
4180 return pidlist[1];
4181 }
4182 GetExitCodeProcess(pidlist[idx], &win_status);
4183 pid = (int)pidlist[idx];
4184 free(pidlist);
4185 *status = (int)win_status;
4186 return pid;
4187}
4188#endif
4189
3944static int 4190static int
3945dowait(int wait_flags, struct job *job) 4191dowait(int wait_flags, struct job *job)
3946{ 4192{
@@ -3957,7 +4203,11 @@ dowait(int wait_flags, struct job *job)
3957 * NB: _not_ safe_waitpid, we need to detect EINTR */ 4203 * NB: _not_ safe_waitpid, we need to detect EINTR */
3958 if (doing_jobctl) 4204 if (doing_jobctl)
3959 wait_flags |= WUNTRACED; 4205 wait_flags |= WUNTRACED;
4206#if ENABLE_PLATFORM_MINGW32
4207 pid = waitpid_child(&status, wait_flags);
4208#else
3960 pid = waitpid(-1, &status, wait_flags); 4209 pid = waitpid(-1, &status, wait_flags);
4210#endif
3961 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", 4211 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
3962 pid, status, errno, strerror(errno))); 4212 pid, status, errno, strerror(errno)));
3963 if (pid <= 0) 4213 if (pid <= 0)
@@ -3980,6 +4230,8 @@ dowait(int wait_flags, struct job *job)
3980 jobno(jp), pid, ps->ps_status, status)); 4230 jobno(jp), pid, ps->ps_status, status));
3981 ps->ps_status = status; 4231 ps->ps_status = status;
3982 thisjob = jp; 4232 thisjob = jp;
4233 if (ENABLE_PLATFORM_MINGW32)
4234 ps->ps_pid = -1;
3983 } 4235 }
3984 if (ps->ps_status == -1) 4236 if (ps->ps_status == -1)
3985 state = JOBRUNNING; 4237 state = JOBRUNNING;
@@ -4211,6 +4463,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4211 int retval; 4463 int retval;
4212 struct job *jp; 4464 struct job *jp;
4213 4465
4466 if (ENABLE_PLATFORM_MINGW32)
4467 return 0;
4468
4214 if (pending_sig) 4469 if (pending_sig)
4215 raise_exception(EXSIG); 4470 raise_exception(EXSIG);
4216 4471
@@ -4823,7 +5078,7 @@ static void
4823forkparent(struct job *jp, union node *n, int mode, pid_t pid) 5078forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4824{ 5079{
4825 TRACE(("In parent shell: child = %d\n", pid)); 5080 TRACE(("In parent shell: child = %d\n", pid));
4826 if (!jp) { 5081 if (!jp && !ENABLE_PLATFORM_MINGW32) { /* FIXME not quite understand this */
4827 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) 5082 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4828 continue; 5083 continue;
4829 jobless++; 5084 jobless++;
@@ -4863,6 +5118,9 @@ forkshell(struct job *jp, union node *n, int mode)
4863 int pid; 5118 int pid;
4864 5119
4865 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode)); 5120 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5121 if (ENABLE_PLATFORM_MINGW32)
5122 return -1;
5123
4866 pid = fork(); 5124 pid = fork();
4867 if (pid < 0) { 5125 if (pid < 0) {
4868 TRACE(("Fork failed, errno=%d", errno)); 5126 TRACE(("Fork failed, errno=%d", errno));
@@ -5065,11 +5323,39 @@ noclobberopen(const char *fname)
5065 */ 5323 */
5066/* openhere needs this forward reference */ 5324/* openhere needs this forward reference */
5067static void expandhere(union node *arg, int fd); 5325static void expandhere(union node *arg, int fd);
5326#if ENABLE_PLATFORM_MINGW32
5327static void
5328forkshell_openhere(struct forkshell *fs)
5329{
5330 union node *redir = fs->n;
5331 int pip[2];
5332
5333 pip[0] = fs->fd[0];
5334 pip[1] = fs->fd[1];
5335
5336 TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__));
5337
5338 close(pip[0]);
5339 ignoresig(SIGINT); //signal(SIGINT, SIG_IGN);
5340 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5341 ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN);
5342 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5343 signal(SIGPIPE, SIG_DFL);
5344 if (redir->type == NHERE) {
5345 size_t len = strlen(redir->nhere.doc->narg.text);
5346 full_write(pip[1], redir->nhere.doc->narg.text, len);
5347 } else /* NXHERE */
5348 expandhere(redir->nhere.doc, pip[1]);
5349 _exit(EXIT_SUCCESS);
5350}
5351#endif
5352
5068static int 5353static int
5069openhere(union node *redir) 5354openhere(union node *redir)
5070{ 5355{
5071 int pip[2]; 5356 int pip[2];
5072 size_t len = 0; 5357 size_t len = 0;
5358 IF_PLATFORM_MINGW32(struct forkshell fs);
5073 5359
5074 if (pipe(pip) < 0) 5360 if (pipe(pip) < 0)
5075 ash_msg_and_raise_error("pipe call failed"); 5361 ash_msg_and_raise_error("pipe call failed");
@@ -5080,6 +5366,16 @@ openhere(union node *redir)
5080 goto out; 5366 goto out;
5081 } 5367 }
5082 } 5368 }
5369#if ENABLE_PLATFORM_MINGW32
5370 memset(&fs, 0, sizeof(fs));
5371 fs.fp = forkshell_openhere;
5372 fs.flags = 0;
5373 fs.n = redir;
5374 fs.fd[0] = pip[0];
5375 fs.fd[1] = pip[1];
5376 if (spawn_forkshell(NULL, &fs, FORK_NOJOB) < 0)
5377 ash_msg_and_raise_error("unable to spawn shell");
5378#endif
5083 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { 5379 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5084 /* child */ 5380 /* child */
5085 close(pip[0]); 5381 close(pip[0]);
@@ -5105,6 +5401,31 @@ openredirect(union node *redir)
5105 char *fname; 5401 char *fname;
5106 int f; 5402 int f;
5107 5403
5404#if ENABLE_PLATFORM_MINGW32
5405 /* Support for /dev/null */
5406 switch (redir->nfile.type) {
5407 case NFROM:
5408 if (!strcmp(redir->nfile.expfname, "/dev/null"))
5409 return open("nul",O_RDWR);
5410 if (!strncmp(redir->nfile.expfname, "/dev/", 5)) {
5411 ash_msg("Unhandled device %s\n", redir->nfile.expfname);
5412 return -1;
5413 }
5414 break;
5415
5416 case NFROMTO:
5417 case NTO:
5418 case NCLOBBER:
5419 case NAPPEND:
5420 if (!strcmp(redir->nfile.expfname, "/dev/null"))
5421 return open("nul",O_RDWR);
5422 if (!strncmp(redir->nfile.expfname, "/dev/", 5)) {
5423 ash_msg("Unhandled device %s\n", redir->nfile.expfname);
5424 return -1;
5425 }
5426 break;
5427 }
5428#endif
5108 switch (redir->nfile.type) { 5429 switch (redir->nfile.type) {
5109 case NFROM: 5430 case NFROM:
5110 fname = redir->nfile.expfname; 5431 fname = redir->nfile.expfname;
@@ -5807,6 +6128,8 @@ exptilde(char *startp, char *p, int flags)
5807 if (*name == '\0') { 6128 if (*name == '\0') {
5808 home = lookupvar("HOME"); 6129 home = lookupvar("HOME");
5809 } else { 6130 } else {
6131 if (ENABLE_PLATFORM_MINGW32)
6132 goto lose;
5810 pw = getpwnam(name); 6133 pw = getpwnam(name);
5811 if (pw == NULL) 6134 if (pw == NULL)
5812 goto lose; 6135 goto lose;
@@ -5834,6 +6157,7 @@ struct backcmd { /* result of evalbackcmd */
5834 int fd; /* file descriptor to read from */ 6157 int fd; /* file descriptor to read from */
5835 int nleft; /* number of chars in buffer */ 6158 int nleft; /* number of chars in buffer */
5836 char *buf; /* buffer */ 6159 char *buf; /* buffer */
6160 IF_PLATFORM_MINGW32(struct forkshell fs);
5837 struct job *jp; /* job structure for command */ 6161 struct job *jp; /* job structure for command */
5838}; 6162};
5839 6163
@@ -5842,6 +6166,25 @@ static uint8_t back_exitstatus; /* exit status of backquoted command */
5842#define EV_EXIT 01 /* exit after evaluating tree */ 6166#define EV_EXIT 01 /* exit after evaluating tree */
5843static void evaltree(union node *, int); 6167static void evaltree(union node *, int);
5844 6168
6169#if ENABLE_PLATFORM_MINGW32
6170static void
6171forkshell_evalbackcmd(struct forkshell *fs)
6172{
6173 union node *n = fs->n;
6174 int pip[2] = {fs->fd[0], fs->fd[1]};
6175
6176 FORCE_INT_ON;
6177 close(pip[0]);
6178 if (pip[1] != 1) {
6179 /*close(1);*/
6180 copyfd(pip[1], 1 | COPYFD_EXACT);
6181 close(pip[1]);
6182 }
6183 eflag = 0;
6184 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6185 /* NOTREACHED */
6186}
6187#endif
5845static void FAST_FUNC 6188static void FAST_FUNC
5846evalbackcmd(union node *n, struct backcmd *result) 6189evalbackcmd(union node *n, struct backcmd *result)
5847{ 6190{
@@ -5850,6 +6193,7 @@ evalbackcmd(union node *n, struct backcmd *result)
5850 result->fd = -1; 6193 result->fd = -1;
5851 result->buf = NULL; 6194 result->buf = NULL;
5852 result->nleft = 0; 6195 result->nleft = 0;
6196 IF_PLATFORM_MINGW32(memset(&result->fs, 0, sizeof(result->fs)));
5853 result->jp = NULL; 6197 result->jp = NULL;
5854 if (n == NULL) 6198 if (n == NULL)
5855 goto out; 6199 goto out;
@@ -5864,6 +6208,14 @@ evalbackcmd(union node *n, struct backcmd *result)
5864 if (pipe(pip) < 0) 6208 if (pipe(pip) < 0)
5865 ash_msg_and_raise_error("pipe call failed"); 6209 ash_msg_and_raise_error("pipe call failed");
5866 jp = makejob(/*n,*/ 1); 6210 jp = makejob(/*n,*/ 1);
6211#if ENABLE_PLATFORM_MINGW32
6212 result->fs.fp = forkshell_evalbackcmd;
6213 result->fs.n = n;
6214 result->fs.fd[0] = pip[0];
6215 result->fs.fd[1] = pip[1];
6216 if (spawn_forkshell(jp, &result->fs, FORK_NOJOB) < 0)
6217 ash_msg_and_raise_error("unable to spawn shell");
6218#endif
5867 if (forkshell(jp, n, FORK_NOJOB) == 0) { 6219 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5868 FORCE_INT_ON; 6220 FORCE_INT_ON;
5869 close(pip[0]); 6221 close(pip[0]);
@@ -5934,7 +6286,8 @@ expbackq(union node *cmd, int quoted, int quotes)
5934 6286
5935 /* Eat all trailing newlines */ 6287 /* Eat all trailing newlines */
5936 dest = expdest; 6288 dest = expdest;
5937 for (; dest > (char *)stackblock() && dest[-1] == '\n';) 6289 for (; dest > (char *)stackblock() && (dest[-1] == '\n' ||
6290 (ENABLE_PLATFORM_MINGW32 && dest[-1] == '\r'));)
5938 STUNPUTC(dest); 6291 STUNPUTC(dest);
5939 expdest = dest; 6292 expdest = dest;
5940 6293
@@ -7475,7 +7828,7 @@ shellexec(char **argv, const char *path, int idx)
7475 7828
7476 clearredir(/*drop:*/ 1); 7829 clearredir(/*drop:*/ 1);
7477 envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL); 7830 envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7478 if (strchr(argv[0], '/') != NULL 7831 if ((strchr(argv[0], '/') || (ENABLE_PLATFORM_MINGW32 && strchr(argv[0], '\\')))
7479#if ENABLE_FEATURE_SH_STANDALONE 7832#if ENABLE_FEATURE_SH_STANDALONE
7480 || (applet_no = find_applet_by_name(argv[0])) >= 0 7833 || (applet_no = find_applet_by_name(argv[0])) >= 0
7481#endif 7834#endif
@@ -7986,6 +8339,10 @@ static int funcblocksize; /* size of structures in function */
7986static int funcstringsize; /* size of strings in node */ 8339static int funcstringsize; /* size of strings in node */
7987static void *funcblock; /* block to allocate function from */ 8340static void *funcblock; /* block to allocate function from */
7988static char *funcstring; /* block to allocate strings from */ 8341static char *funcstring; /* block to allocate strings from */
8342#if ENABLE_PLATFORM_MINGW32
8343static int nodeptrsize;
8344static int *nodeptr;
8345#endif
7989 8346
7990/* flags in argument to evaltree */ 8347/* flags in argument to evaltree */
7991#define EV_EXIT 01 /* exit after evaluating tree */ 8348#define EV_EXIT 01 /* exit after evaluating tree */
@@ -8031,6 +8388,7 @@ sizenodelist(struct nodelist *lp)
8031{ 8388{
8032 while (lp) { 8389 while (lp) {
8033 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); 8390 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8391 IF_PLATFORM_MINGW32(nodeptrsize += 2);
8034 calcsize(lp->n); 8392 calcsize(lp->n);
8035 lp = lp->next; 8393 lp = lp->next;
8036 } 8394 }
@@ -8047,15 +8405,18 @@ calcsize(union node *n)
8047 calcsize(n->ncmd.redirect); 8405 calcsize(n->ncmd.redirect);
8048 calcsize(n->ncmd.args); 8406 calcsize(n->ncmd.args);
8049 calcsize(n->ncmd.assign); 8407 calcsize(n->ncmd.assign);
8408 IF_PLATFORM_MINGW32(nodeptrsize += 3);
8050 break; 8409 break;
8051 case NPIPE: 8410 case NPIPE:
8052 sizenodelist(n->npipe.cmdlist); 8411 sizenodelist(n->npipe.cmdlist);
8412 IF_PLATFORM_MINGW32(nodeptrsize++);
8053 break; 8413 break;
8054 case NREDIR: 8414 case NREDIR:
8055 case NBACKGND: 8415 case NBACKGND:
8056 case NSUBSHELL: 8416 case NSUBSHELL:
8057 calcsize(n->nredir.redirect); 8417 calcsize(n->nredir.redirect);
8058 calcsize(n->nredir.n); 8418 calcsize(n->nredir.n);
8419 IF_PLATFORM_MINGW32(nodeptrsize += 2);
8059 break; 8420 break;
8060 case NAND: 8421 case NAND:
8061 case NOR: 8422 case NOR:
@@ -8064,31 +8425,37 @@ calcsize(union node *n)
8064 case NUNTIL: 8425 case NUNTIL:
8065 calcsize(n->nbinary.ch2); 8426 calcsize(n->nbinary.ch2);
8066 calcsize(n->nbinary.ch1); 8427 calcsize(n->nbinary.ch1);
8428 IF_PLATFORM_MINGW32(nodeptrsize += 2);
8067 break; 8429 break;
8068 case NIF: 8430 case NIF:
8069 calcsize(n->nif.elsepart); 8431 calcsize(n->nif.elsepart);
8070 calcsize(n->nif.ifpart); 8432 calcsize(n->nif.ifpart);
8071 calcsize(n->nif.test); 8433 calcsize(n->nif.test);
8434 IF_PLATFORM_MINGW32(nodeptrsize += 3);
8072 break; 8435 break;
8073 case NFOR: 8436 case NFOR:
8074 funcstringsize += strlen(n->nfor.var) + 1; 8437 funcstringsize += strlen(n->nfor.var) + 1;
8075 calcsize(n->nfor.body); 8438 calcsize(n->nfor.body);
8076 calcsize(n->nfor.args); 8439 calcsize(n->nfor.args);
8440 IF_PLATFORM_MINGW32(nodeptrsize += 3);
8077 break; 8441 break;
8078 case NCASE: 8442 case NCASE:
8079 calcsize(n->ncase.cases); 8443 calcsize(n->ncase.cases);
8080 calcsize(n->ncase.expr); 8444 calcsize(n->ncase.expr);
8445 IF_PLATFORM_MINGW32(nodeptrsize += 2);
8081 break; 8446 break;
8082 case NCLIST: 8447 case NCLIST:
8083 calcsize(n->nclist.body); 8448 calcsize(n->nclist.body);
8084 calcsize(n->nclist.pattern); 8449 calcsize(n->nclist.pattern);
8085 calcsize(n->nclist.next); 8450 calcsize(n->nclist.next);
8451 IF_PLATFORM_MINGW32(nodeptrsize += 3);
8086 break; 8452 break;
8087 case NDEFUN: 8453 case NDEFUN:
8088 case NARG: 8454 case NARG:
8089 sizenodelist(n->narg.backquote); 8455 sizenodelist(n->narg.backquote);
8090 funcstringsize += strlen(n->narg.text) + 1; 8456 funcstringsize += strlen(n->narg.text) + 1;
8091 calcsize(n->narg.next); 8457 calcsize(n->narg.next);
8458 IF_PLATFORM_MINGW32(nodeptrsize += 3);
8092 break; 8459 break;
8093 case NTO: 8460 case NTO:
8094#if ENABLE_ASH_BASH_COMPAT 8461#if ENABLE_ASH_BASH_COMPAT
@@ -8100,28 +8467,34 @@ calcsize(union node *n)
8100 case NAPPEND: 8467 case NAPPEND:
8101 calcsize(n->nfile.fname); 8468 calcsize(n->nfile.fname);
8102 calcsize(n->nfile.next); 8469 calcsize(n->nfile.next);
8470 IF_PLATFORM_MINGW32(nodeptrsize += 2);
8103 break; 8471 break;
8104 case NTOFD: 8472 case NTOFD:
8105 case NFROMFD: 8473 case NFROMFD:
8106 calcsize(n->ndup.vname); 8474 calcsize(n->ndup.vname);
8107 calcsize(n->ndup.next); 8475 calcsize(n->ndup.next);
8476 IF_PLATFORM_MINGW32(nodeptrsize += 2);
8108 break; 8477 break;
8109 case NHERE: 8478 case NHERE:
8110 case NXHERE: 8479 case NXHERE:
8111 calcsize(n->nhere.doc); 8480 calcsize(n->nhere.doc);
8112 calcsize(n->nhere.next); 8481 calcsize(n->nhere.next);
8482 IF_PLATFORM_MINGW32(nodeptrsize += 2);
8113 break; 8483 break;
8114 case NNOT: 8484 case NNOT:
8115 calcsize(n->nnot.com); 8485 calcsize(n->nnot.com);
8486 IF_PLATFORM_MINGW32(nodeptrsize++);
8116 break; 8487 break;
8117 }; 8488 };
8118} 8489}
8119 8490
8120static char * 8491static char *
8121nodeckstrdup(char *s) 8492nodeckstrdup(const char *s)
8122{ 8493{
8123 char *rtn = funcstring; 8494 char *rtn = funcstring;
8124 8495
8496 if (!s)
8497 return NULL;
8125 strcpy(funcstring, s); 8498 strcpy(funcstring, s);
8126 funcstring += strlen(s) + 1; 8499 funcstring += strlen(s) + 1;
8127 return rtn; 8500 return rtn;
@@ -8129,6 +8502,18 @@ nodeckstrdup(char *s)
8129 8502
8130static union node *copynode(union node *); 8503static union node *copynode(union node *);
8131 8504
8505#if ENABLE_PLATFORM_MINGW32
8506# define SAVE_PTR(dst) {if (nodeptr) *nodeptr++ = (int)&(dst);}
8507# define SAVE_PTR2(dst1,dst2) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);}}
8508# define SAVE_PTR3(dst1,dst2,dst3) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);*nodeptr++ = (int)&(dst3);}}
8509# define SAVE_PTR4(dst1,dst2,dst3,dst4) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);*nodeptr++ = (int)&(dst3);*nodeptr++ = (int)&(dst4);}}
8510#else
8511# define SAVE_PTR(dst)
8512# define SAVE_PTR2(dst,dst2)
8513# define SAVE_PTR3(dst,dst2,dst3)
8514# define SAVE_PTR4(dst,dst2,dst3,dst4)
8515#endif
8516
8132static struct nodelist * 8517static struct nodelist *
8133copynodelist(struct nodelist *lp) 8518copynodelist(struct nodelist *lp)
8134{ 8519{
@@ -8140,6 +8525,7 @@ copynodelist(struct nodelist *lp)
8140 *lpp = funcblock; 8525 *lpp = funcblock;
8141 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist)); 8526 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8142 (*lpp)->n = copynode(lp->n); 8527 (*lpp)->n = copynode(lp->n);
8528 SAVE_PTR2((*lpp)->n, (*lpp)->next);
8143 lp = lp->next; 8529 lp = lp->next;
8144 lpp = &(*lpp)->next; 8530 lpp = &(*lpp)->next;
8145 } 8531 }
@@ -8162,16 +8548,19 @@ copynode(union node *n)
8162 new->ncmd.redirect = copynode(n->ncmd.redirect); 8548 new->ncmd.redirect = copynode(n->ncmd.redirect);
8163 new->ncmd.args = copynode(n->ncmd.args); 8549 new->ncmd.args = copynode(n->ncmd.args);
8164 new->ncmd.assign = copynode(n->ncmd.assign); 8550 new->ncmd.assign = copynode(n->ncmd.assign);
8551 SAVE_PTR3(new->ncmd.redirect,new->ncmd.args, new->ncmd.assign);
8165 break; 8552 break;
8166 case NPIPE: 8553 case NPIPE:
8167 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); 8554 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8168 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd; 8555 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8556 SAVE_PTR(new->npipe.cmdlist);
8169 break; 8557 break;
8170 case NREDIR: 8558 case NREDIR:
8171 case NBACKGND: 8559 case NBACKGND:
8172 case NSUBSHELL: 8560 case NSUBSHELL:
8173 new->nredir.redirect = copynode(n->nredir.redirect); 8561 new->nredir.redirect = copynode(n->nredir.redirect);
8174 new->nredir.n = copynode(n->nredir.n); 8562 new->nredir.n = copynode(n->nredir.n);
8563 SAVE_PTR2(new->nredir.redirect,new->nredir.n);
8175 break; 8564 break;
8176 case NAND: 8565 case NAND:
8177 case NOR: 8566 case NOR:
@@ -8180,31 +8569,37 @@ copynode(union node *n)
8180 case NUNTIL: 8569 case NUNTIL:
8181 new->nbinary.ch2 = copynode(n->nbinary.ch2); 8570 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8182 new->nbinary.ch1 = copynode(n->nbinary.ch1); 8571 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8572 SAVE_PTR2(new->nbinary.ch1,new->nbinary.ch2);
8183 break; 8573 break;
8184 case NIF: 8574 case NIF:
8185 new->nif.elsepart = copynode(n->nif.elsepart); 8575 new->nif.elsepart = copynode(n->nif.elsepart);
8186 new->nif.ifpart = copynode(n->nif.ifpart); 8576 new->nif.ifpart = copynode(n->nif.ifpart);
8187 new->nif.test = copynode(n->nif.test); 8577 new->nif.test = copynode(n->nif.test);
8578 SAVE_PTR3(new->nif.elsepart,new->nif.ifpart,new->nif.test);
8188 break; 8579 break;
8189 case NFOR: 8580 case NFOR:
8190 new->nfor.var = nodeckstrdup(n->nfor.var); 8581 new->nfor.var = nodeckstrdup(n->nfor.var);
8191 new->nfor.body = copynode(n->nfor.body); 8582 new->nfor.body = copynode(n->nfor.body);
8192 new->nfor.args = copynode(n->nfor.args); 8583 new->nfor.args = copynode(n->nfor.args);
8584 SAVE_PTR3(new->nfor.var,new->nfor.body,new->nfor.args);
8193 break; 8585 break;
8194 case NCASE: 8586 case NCASE:
8195 new->ncase.cases = copynode(n->ncase.cases); 8587 new->ncase.cases = copynode(n->ncase.cases);
8196 new->ncase.expr = copynode(n->ncase.expr); 8588 new->ncase.expr = copynode(n->ncase.expr);
8589 SAVE_PTR2(new->ncase.cases,new->ncase.expr);
8197 break; 8590 break;
8198 case NCLIST: 8591 case NCLIST:
8199 new->nclist.body = copynode(n->nclist.body); 8592 new->nclist.body = copynode(n->nclist.body);
8200 new->nclist.pattern = copynode(n->nclist.pattern); 8593 new->nclist.pattern = copynode(n->nclist.pattern);
8201 new->nclist.next = copynode(n->nclist.next); 8594 new->nclist.next = copynode(n->nclist.next);
8595 SAVE_PTR3(new->nclist.body,new->nclist.pattern,new->nclist.next);
8202 break; 8596 break;
8203 case NDEFUN: 8597 case NDEFUN:
8204 case NARG: 8598 case NARG:
8205 new->narg.backquote = copynodelist(n->narg.backquote); 8599 new->narg.backquote = copynodelist(n->narg.backquote);
8206 new->narg.text = nodeckstrdup(n->narg.text); 8600 new->narg.text = nodeckstrdup(n->narg.text);
8207 new->narg.next = copynode(n->narg.next); 8601 new->narg.next = copynode(n->narg.next);
8602 SAVE_PTR3(new->narg.backquote,new->narg.text,new->narg.next);
8208 break; 8603 break;
8209 case NTO: 8604 case NTO:
8210#if ENABLE_ASH_BASH_COMPAT 8605#if ENABLE_ASH_BASH_COMPAT
@@ -8217,6 +8612,7 @@ copynode(union node *n)
8217 new->nfile.fname = copynode(n->nfile.fname); 8612 new->nfile.fname = copynode(n->nfile.fname);
8218 new->nfile.fd = n->nfile.fd; 8613 new->nfile.fd = n->nfile.fd;
8219 new->nfile.next = copynode(n->nfile.next); 8614 new->nfile.next = copynode(n->nfile.next);
8615 SAVE_PTR2(new->nfile.fname,new->nfile.next);
8220 break; 8616 break;
8221 case NTOFD: 8617 case NTOFD:
8222 case NFROMFD: 8618 case NFROMFD:
@@ -8224,15 +8620,18 @@ copynode(union node *n)
8224 new->ndup.dupfd = n->ndup.dupfd; 8620 new->ndup.dupfd = n->ndup.dupfd;
8225 new->ndup.fd = n->ndup.fd; 8621 new->ndup.fd = n->ndup.fd;
8226 new->ndup.next = copynode(n->ndup.next); 8622 new->ndup.next = copynode(n->ndup.next);
8623 SAVE_PTR2(new->ndup.vname,new->ndup.next);
8227 break; 8624 break;
8228 case NHERE: 8625 case NHERE:
8229 case NXHERE: 8626 case NXHERE:
8230 new->nhere.doc = copynode(n->nhere.doc); 8627 new->nhere.doc = copynode(n->nhere.doc);
8231 new->nhere.fd = n->nhere.fd; 8628 new->nhere.fd = n->nhere.fd;
8232 new->nhere.next = copynode(n->nhere.next); 8629 new->nhere.next = copynode(n->nhere.next);
8630 SAVE_PTR2(new->nhere.doc,new->nhere.next);
8233 break; 8631 break;
8234 case NNOT: 8632 case NNOT:
8235 new->nnot.com = copynode(n->nnot.com); 8633 new->nnot.com = copynode(n->nnot.com);
8634 SAVE_PTR(new->nnot.com);
8236 break; 8635 break;
8237 }; 8636 };
8238 new->type = n->type; 8637 new->type = n->type;
@@ -8255,6 +8654,7 @@ copyfunc(union node *n)
8255 f = ckmalloc(blocksize + funcstringsize); 8654 f = ckmalloc(blocksize + funcstringsize);
8256 funcblock = (char *) f + offsetof(struct funcnode, n); 8655 funcblock = (char *) f + offsetof(struct funcnode, n);
8257 funcstring = (char *) f + blocksize; 8656 funcstring = (char *) f + blocksize;
8657 IF_PLATFORM_MINGW32(nodeptr = NULL);
8258 copynode(n); 8658 copynode(n);
8259 f->count = 0; 8659 f->count = 0;
8260 return f; 8660 return f;
@@ -8611,9 +9011,26 @@ evalcase(union node *n, int flags)
8611/* 9011/*
8612 * Kick off a subshell to evaluate a tree. 9012 * Kick off a subshell to evaluate a tree.
8613 */ 9013 */
9014#if ENABLE_PLATFORM_MINGW32
9015static void
9016forkshell_evalsubshell(struct forkshell *fs)
9017{
9018 union node *n = fs->n;
9019 int flags = fs->flags;
9020
9021 TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__));
9022 INT_ON;
9023 flags |= EV_EXIT;
9024 expredir(n->nredir.redirect);
9025 redirect(n->nredir.redirect, 0);
9026 evaltreenr(n->nredir.n, flags);
9027 /* never returns */
9028}
9029#endif
8614static void 9030static void
8615evalsubshell(union node *n, int flags) 9031evalsubshell(union node *n, int flags)
8616{ 9032{
9033 IF_PLATFORM_MINGW32(struct forkshell fs;)
8617 struct job *jp; 9034 struct job *jp;
8618 int backgnd = (n->type == NBACKGND); 9035 int backgnd = (n->type == NBACKGND);
8619 int status; 9036 int status;
@@ -8623,6 +9040,14 @@ evalsubshell(union node *n, int flags)
8623 goto nofork; 9040 goto nofork;
8624 INT_OFF; 9041 INT_OFF;
8625 jp = makejob(/*n,*/ 1); 9042 jp = makejob(/*n,*/ 1);
9043#if ENABLE_PLATFORM_MINGW32
9044 memset(&fs, 0, sizeof(fs));
9045 fs.fp = forkshell_evalsubshell;
9046 fs.n = n;
9047 fs.flags = flags;
9048 if (spawn_forkshell(jp, &fs, backgnd) < 0)
9049 ash_msg_and_raise_error("unable to spawn shell");
9050#endif
8626 if (forkshell(jp, n, backgnd) == 0) { 9051 if (forkshell(jp, n, backgnd) == 0) {
8627 /* child */ 9052 /* child */
8628 INT_ON; 9053 INT_ON;
@@ -8699,9 +9124,35 @@ expredir(union node *n)
8699 * of the shell, which make the last process in a pipeline the parent 9124 * of the shell, which make the last process in a pipeline the parent
8700 * of all the rest.) 9125 * of all the rest.)
8701 */ 9126 */
9127#if ENABLE_PLATFORM_MINGW32
9128static void
9129forkshell_evalpipe(struct forkshell *fs)
9130{
9131 union node *n = fs->n;
9132 int flags = fs->flags;
9133 int prevfd = fs->fd[2];
9134 int pip[2] = {fs->fd[0], fs->fd[1]};
9135
9136 TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__));
9137 INT_ON;
9138 if (pip[1] >= 0) {
9139 close(pip[0]);
9140 }
9141 if (prevfd > 0) {
9142 dup2(prevfd, 0);
9143 close(prevfd);
9144 }
9145 if (pip[1] > 1) {
9146 dup2(pip[1], 1);
9147 close(pip[1]);
9148 }
9149 evaltreenr(n, flags);
9150}
9151#endif
8702static void 9152static void
8703evalpipe(union node *n, int flags) 9153evalpipe(union node *n, int flags)
8704{ 9154{
9155 IF_PLATFORM_MINGW32(struct forkshell fs;)
8705 struct job *jp; 9156 struct job *jp;
8706 struct nodelist *lp; 9157 struct nodelist *lp;
8707 int pipelen; 9158 int pipelen;
@@ -8725,6 +9176,17 @@ evalpipe(union node *n, int flags)
8725 ash_msg_and_raise_error("pipe call failed"); 9176 ash_msg_and_raise_error("pipe call failed");
8726 } 9177 }
8727 } 9178 }
9179#if ENABLE_PLATFORM_MINGW32
9180 memset(&fs, 0, sizeof(fs));
9181 fs.fp = forkshell_evalpipe;
9182 fs.flags = flags;
9183 fs.n = lp->n;
9184 fs.fd[0] = pip[0];
9185 fs.fd[1] = pip[1];
9186 fs.fd[2] = prevfd;
9187 if (spawn_forkshell(jp, &fs, n->npipe.pipe_backgnd) < 0)
9188 ash_msg_and_raise_error("unable to spawn shell");
9189#endif
8728 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { 9190 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8729 INT_ON; 9191 INT_ON;
8730 if (pip[1] >= 0) { 9192 if (pip[1] >= 0) {
@@ -9193,6 +9655,20 @@ bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9193 * as POSIX mandates */ 9655 * as POSIX mandates */
9194 return back_exitstatus; 9656 return back_exitstatus;
9195} 9657}
9658
9659#if ENABLE_PLATFORM_MINGW32
9660static void
9661forkshell_shellexec(struct forkshell *fs)
9662{
9663 int idx = fs->fd[0];
9664 struct strlist *varlist = fs->strlist;
9665 char **argv = fs->argv;
9666 char *path = fs->string;
9667
9668 listsetvar(varlist, VEXPORT|VSTACK);
9669 shellexec(argv, path, idx);
9670}
9671#endif
9196static void 9672static void
9197evalcommand(union node *cmd, int flags) 9673evalcommand(union node *cmd, int flags)
9198{ 9674{
@@ -9370,6 +9846,27 @@ evalcommand(union node *cmd, int flags)
9370 * in a script or a subshell does not need forking, 9846 * in a script or a subshell does not need forking,
9371 * we can just exec it. 9847 * we can just exec it.
9372 */ 9848 */
9849#if ENABLE_PLATFORM_MINGW32
9850 if (!(flags & EV_EXIT) || trap[0]) {
9851 /* No, forking off a child is necessary */
9852 struct forkshell fs;
9853
9854 memset(&fs, 0, sizeof(fs));
9855 fs.fp = forkshell_shellexec;
9856 fs.argv = argv;
9857 fs.string = (char*)path;
9858 fs.fd[0] = cmdentry.u.index;
9859 fs.strlist = varlist.list;
9860 jp = makejob(/*cmd,*/ 1);
9861 if (spawn_forkshell(jp, &fs, FORK_FG) < 0)
9862 ash_msg_and_raise_error("unable to spawn shell");
9863 exitstatus = waitforjob(jp);
9864 INT_ON;
9865 TRACE(("forked child exited with %d\n", exitstatus));
9866 break;
9867 }
9868 /* goes through to shellexec() */
9869#else
9373 if (!(flags & EV_EXIT) || may_have_traps) { 9870 if (!(flags & EV_EXIT) || may_have_traps) {
9374 /* No, forking off a child is necessary */ 9871 /* No, forking off a child is necessary */
9375 INT_OFF; 9872 INT_OFF;
@@ -9385,6 +9882,7 @@ evalcommand(union node *cmd, int flags)
9385 FORCE_INT_ON; 9882 FORCE_INT_ON;
9386 /* fall through to exec'ing external program */ 9883 /* fall through to exec'ing external program */
9387 } 9884 }
9885#endif
9388 listsetvar(varlist.list, VEXPORT|VSTACK); 9886 listsetvar(varlist.list, VEXPORT|VSTACK);
9389 shellexec(argv, path, cmdentry.u.index); 9887 shellexec(argv, path, cmdentry.u.index);
9390 /* NOTREACHED */ 9888 /* NOTREACHED */
@@ -9777,7 +10275,7 @@ preadbuffer(void)
9777 more--; 10275 more--;
9778 10276
9779 c = *q; 10277 c = *q;
9780 if (c == '\0') { 10278 if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) {
9781 memmove(q, q + 1, more); 10279 memmove(q, q + 1, more);
9782 } else { 10280 } else {
9783 q++; 10281 q++;
@@ -12208,7 +12706,7 @@ find_dot_file(char *name)
12208 struct stat statb; 12706 struct stat statb;
12209 12707
12210 /* don't try this for absolute or relative paths */ 12708 /* don't try this for absolute or relative paths */
12211 if (strchr(name, '/')) 12709 if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\')))
12212 return name; 12710 return name;
12213 12711
12214 /* IIRC standards do not say whether . is to be searched. 12712 /* IIRC standards do not say whether . is to be searched.
@@ -12318,10 +12816,11 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
12318 struct stat statb; 12816 struct stat statb;
12319 int e; 12817 int e;
12320 int updatetbl; 12818 int updatetbl;
12819 IF_PLATFORM_MINGW32(int len;)
12321 struct builtincmd *bcmd; 12820 struct builtincmd *bcmd;
12322 12821
12323 /* If name contains a slash, don't use PATH or hash table */ 12822 /* If name contains a slash, don't use PATH or hash table */
12324 if (strchr(name, '/') != NULL) { 12823 if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) {
12325 entry->u.index = -1; 12824 entry->u.index = -1;
12326 if (act & DO_ABS) { 12825 if (act & DO_ABS) {
12327 while (stat(name, &statb) < 0) { 12826 while (stat(name, &statb) < 0) {
@@ -12428,12 +12927,48 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
12428 } 12927 }
12429 } 12928 }
12430 /* if rehash, don't redo absolute path names */ 12929 /* if rehash, don't redo absolute path names */
12431 if (fullname[0] == '/' && idx <= prev) { 12930 if (is_absolute_path(fullname) && idx <= prev) {
12432 if (idx < prev) 12931 if (idx < prev)
12433 continue; 12932 continue;
12434 TRACE(("searchexec \"%s\": no change\n", name)); 12933 TRACE(("searchexec \"%s\": no change\n", name));
12435 goto success; 12934 goto success;
12436 } 12935 }
12936#if ENABLE_PLATFORM_MINGW32
12937 len = strlen(fullname);
12938 if (len > 4 &&
12939 (!strcasecmp(fullname+len-4, ".exe") ||
12940 !strcasecmp(fullname+len-4, ".com"))) {
12941 if (stat(fullname, &statb) < 0) {
12942 if (errno != ENOENT && errno != ENOTDIR)
12943 e = errno;
12944 goto loop;
12945 }
12946 }
12947 else {
12948 /* path_advance() has reserved space for .exe */
12949 memcpy(fullname+len, ".exe", 5);
12950 if (stat(fullname, &statb) < 0) {
12951 if (errno != ENOENT && errno != ENOTDIR)
12952 e = errno;
12953 memcpy(fullname+len, ".com", 5);
12954 if (stat(fullname, &statb) < 0) {
12955 if (errno != ENOENT && errno != ENOTDIR)
12956 e = errno;
12957 fullname[len] = '\0';
12958 if (stat(fullname, &statb) < 0) {
12959 if (errno != ENOENT && errno != ENOTDIR)
12960 e = errno;
12961 goto loop;
12962 }
12963 if (!execable_file(fullname)) {
12964 e = ENOEXEC;
12965 goto loop;
12966 }
12967 }
12968 }
12969 fullname[len] = '\0';
12970 }
12971#else
12437 while (stat(fullname, &statb) < 0) { 12972 while (stat(fullname, &statb) < 0) {
12438#ifdef SYSV 12973#ifdef SYSV
12439 if (errno == EINTR) 12974 if (errno == EINTR)
@@ -12443,6 +12978,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
12443 e = errno; 12978 e = errno;
12444 goto loop; 12979 goto loop;
12445 } 12980 }
12981#endif
12446 e = EACCES; /* if we fail, this will be the error */ 12982 e = EACCES; /* if we fail, this will be the error */
12447 if (!S_ISREG(statb.st_mode)) 12983 if (!S_ISREG(statb.st_mode))
12448 continue; 12984 continue;
@@ -12691,6 +13227,10 @@ unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12691 return ret & 1; 13227 return ret & 1;
12692} 13228}
12693 13229
13230/* setmode.c */
13231
13232#if !ENABLE_PLATFORM_MINGW32
13233
12694static const unsigned char timescmd_str[] ALIGN1 = { 13234static const unsigned char timescmd_str[] ALIGN1 = {
12695 ' ', offsetof(struct tms, tms_utime), 13235 ' ', offsetof(struct tms, tms_utime),
12696 '\n', offsetof(struct tms, tms_stime), 13236 '\n', offsetof(struct tms, tms_stime),
@@ -12722,6 +13262,13 @@ timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12722 13262
12723 return 0; 13263 return 0;
12724} 13264}
13265#else
13266static int FAST_FUNC
13267timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13268{
13269 return 0;
13270}
13271#endif
12725 13272
12726#if ENABLE_SH_MATH_SUPPORT 13273#if ENABLE_SH_MATH_SUPPORT
12727/* 13274/*
@@ -12950,13 +13497,67 @@ init(void)
12950 struct stat st1, st2; 13497 struct stat st1, st2;
12951 13498
12952 initvar(); 13499 initvar();
13500
13501#if ENABLE_PLATFORM_MINGW32
13502 /*
13503 * case insensitive env names from Windows world
13504 *
13505 * Some standard env names such as PATH is named Path and so on
13506 * ash itself is case sensitive, so "Path" will confuse it, as
13507 * MSVC getenv() is case insensitive.
13508 *
13509 * We may end up having both Path and PATH. Then Path will be chosen
13510 * because it appears first.
13511 */
13512 for (envp = environ; envp && *envp; envp++)
13513 if (!strncasecmp(*envp, "PATH=", 5) &&
13514 strncmp(*envp, "PATH=", 5))
13515 break;
13516 if (envp && *envp) {
13517 char *start, *end;
13518 for (envp = environ; envp && *envp; envp++) {
13519 end = strchr(*envp, '=');
13520 if (!end)
13521 continue;
13522 for (start = *envp;start < end;start++)
13523 *start = toupper(*start);
13524 }
13525 }
13526#endif
12953 for (envp = environ; envp && *envp; envp++) { 13527 for (envp = environ; envp && *envp; envp++) {
13528#if ENABLE_PLATFORM_MINGW32
13529 char *s;
13530
13531 while ((s=strchr(*envp, '\\'))) {
13532 *s = '/';
13533 }
13534#endif
12954 if (strchr(*envp, '=')) { 13535 if (strchr(*envp, '=')) {
12955 setvareq(*envp, VEXPORT|VTEXTFIXED); 13536 setvareq(*envp, VEXPORT|VTEXTFIXED);
12956 } 13537 }
12957 } 13538 }
12958 13539
12959 setvar("PPID", utoa(getppid()), 0); 13540#if ENABLE_PLATFORM_MINGW32
13541 p = lookupvar("HOME");
13542 if (!p) {
13543 const char *hd, *hp;
13544
13545 hd = lookupvar("HOMEDRIVE");
13546 hp = lookupvar("HOMEPATH");
13547 if (hd && hp) {
13548 char *s;
13549
13550 if ((s=malloc(strlen(hd) + strlen(hp) + 1)) != NULL) {
13551 strcat(strcpy(s, hd), hp);
13552 setvar("HOME", s, VEXPORT);
13553 free(s);
13554 }
13555 }
13556 }
13557#endif
13558
13559 if (!ENABLE_PLATFORM_MINGW32)
13560 setvar("PPID", utoa(getppid()), 0);
12960 13561
12961 p = lookupvar("PWD"); 13562 p = lookupvar("PWD");
12962 if (p) { 13563 if (p) {
@@ -13090,6 +13691,20 @@ static short profile_buf[16384];
13090extern int etext(); 13691extern int etext();
13091#endif 13692#endif
13092 13693
13694#if ENABLE_PLATFORM_MINGW32
13695static const forkpoint_fn forkpoints[] = {
13696 forkshell_openhere,
13697 forkshell_evalbackcmd,
13698 forkshell_evalsubshell,
13699 forkshell_evalpipe,
13700 forkshell_shellexec,
13701 NULL
13702};
13703
13704static struct forkshell* forkshell_prepare(struct forkshell *fs);
13705static void forkshell_init(const char *idstr);
13706#endif
13707
13093/* 13708/*
13094 * Main routine. We initialize things, parse the arguments, execute 13709 * Main routine. We initialize things, parse the arguments, execute
13095 * profiles if we're a login shell, and then call cmdloop to execute 13710 * profiles if we're a login shell, and then call cmdloop to execute
@@ -13159,6 +13774,17 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
13159 13774
13160 init(); 13775 init();
13161 setstackmark(&smark); 13776 setstackmark(&smark);
13777
13778#if ENABLE_PLATFORM_MINGW32
13779 hSIGINT = CreateEvent(NULL, TRUE, FALSE, NULL);
13780 SetConsoleCtrlHandler(ctrl_handler, TRUE);
13781 if (argc == 3 && !strcmp(argv[1], "--forkshell")) {
13782 forkshell_init(argv[2]);
13783
13784 /* NOTREACHED */
13785 bb_error_msg_and_die("subshell ended unexpectedly");
13786 }
13787#endif
13162 procargs(argv); 13788 procargs(argv);
13163 13789
13164#if ENABLE_FEATURE_EDITING_SAVEHISTORY 13790#if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -13238,6 +13864,526 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
13238 /* NOTREACHED */ 13864 /* NOTREACHED */
13239} 13865}
13240 13866
13867#if ENABLE_PLATFORM_MINGW32
13868/* FIXME: should consider running forkparent() and forkchild() */
13869static int
13870spawn_forkshell(struct job *jp, struct forkshell *fs, int mode)
13871{
13872 const char *argv[] = { "sh", "--forkshell", NULL, NULL };
13873 char buf[16];
13874
13875 struct forkshell *new;
13876 new = forkshell_prepare(fs);
13877 sprintf(buf, "%x", (unsigned int)new->hMapFile);
13878 argv[2] = buf;
13879 fs->pid = mingw_spawn_applet(P_NOWAIT, "sh", argv,
13880 (const char *const *)environ);
13881 CloseHandle(new->hMapFile);
13882 UnmapViewOfFile(new);
13883 if (fs->pid == -1) {
13884 free(jp);
13885 return -1;
13886 }
13887 forkparent(jp, fs->node, mode, fs->pid);
13888 return fs->pid;
13889}
13890
13891/*
13892 * forkshell_prepare() and friends
13893 *
13894 * The sequence is as follows:
13895 * - funcblocksize, funcstringsize, nodeptrsize are initialized
13896 * - forkshell_size(fs) is called to calculate the exact memory needed
13897 * - a new struct is allocated
13898 * - funcblock, funcstring, nodeptr are initialized from the new block
13899 * - forkshell_copy(fs) is called to copy recursively everything over
13900 * it will record all pointers along the way, to nodeptr
13901 *
13902 * When this memory is mapped elsewhere, pointer fixup will be needed
13903 */
13904#define SLIST_SIZE_BEGIN(name,type) \
13905static void \
13906name(type *p) \
13907{ \
13908 while (p) { \
13909 funcblocksize += sizeof(type);
13910 /* do something here with p */
13911#define SLIST_SIZE_END() \
13912 nodeptrsize++; \
13913 p = p->next; \
13914 } \
13915}
13916
13917#define SLIST_COPY_BEGIN(name,type) \
13918static type * \
13919name(type *vp) \
13920{ \
13921 type *start; \
13922 type **vpp; \
13923 vpp = &start; \
13924 while (vp) { \
13925 *vpp = funcblock; \
13926 funcblock = (char *) funcblock + sizeof(type);
13927 /* do something here with vpp and vp */
13928#define SLIST_COPY_END() \
13929 SAVE_PTR((*vpp)->next); \
13930 vp = vp->next; \
13931 vpp = &(*vpp)->next; \
13932 } \
13933 *vpp = NULL; \
13934 return start; \
13935}
13936
13937/*
13938 * struct var
13939 */
13940SLIST_SIZE_BEGIN(var_size,struct var)
13941funcstringsize += strlen(p->var_text) + 1;
13942nodeptrsize++; /* p->text */
13943SLIST_SIZE_END()
13944
13945SLIST_COPY_BEGIN(var_copy,struct var)
13946(*vpp)->var_text = nodeckstrdup(vp->var_text);
13947(*vpp)->flags = vp->flags;
13948/*
13949 * The only place that can set struct var#func is varinit[],
13950 * which will be fixed by forkshell_init()
13951 */
13952(*vpp)->var_func = NULL;
13953SAVE_PTR((*vpp)->var_text);
13954SLIST_COPY_END()
13955
13956/*
13957 * struct localvar
13958 */
13959SLIST_SIZE_BEGIN(localvar_size,struct localvar)
13960var_size(p->vp);
13961funcstringsize += strlen(p->text) + 1;
13962nodeptrsize += 2; /* p->vp, p->text */
13963SLIST_SIZE_END()
13964
13965SLIST_COPY_BEGIN(localvar_copy,struct localvar)
13966(*vpp)->text = nodeckstrdup(vp->text);
13967(*vpp)->flags = vp->flags;
13968(*vpp)->vp = var_copy(vp->vp);
13969SAVE_PTR2((*vpp)->vp, (*vpp)->text);
13970SLIST_COPY_END()
13971
13972/*
13973 * struct strlist
13974 */
13975SLIST_SIZE_BEGIN(strlist_size,struct strlist)
13976funcstringsize += strlen(p->text) + 1;
13977nodeptrsize++; /* p->text */
13978SLIST_SIZE_END()
13979
13980SLIST_COPY_BEGIN(strlist_copy,struct strlist)
13981(*vpp)->text = nodeckstrdup(vp->text);
13982SAVE_PTR((*vpp)->text);
13983SLIST_COPY_END()
13984
13985/*
13986 * struct tblentry
13987 */
13988static void
13989tblentry_size(struct tblentry *tep)
13990{
13991 while (tep) {
13992 funcblocksize += sizeof(struct tblentry) + strlen(tep->cmdname) + 1;
13993 /* CMDBUILTIN, e->param.cmd needs no pointer relocation */
13994 if (tep->cmdtype == CMDFUNCTION) {
13995 funcblocksize += offsetof(struct funcnode, n);
13996 calcsize(&tep->param.func->n);
13997 nodeptrsize++; /* tep->param.func */
13998 }
13999 nodeptrsize++; /* tep->next */
14000 tep = tep->next;
14001 }
14002}
14003
14004static struct tblentry *
14005tblentry_copy(struct tblentry *tep)
14006{
14007 struct tblentry *start;
14008 struct tblentry **newp;
14009 int size;
14010
14011 newp = &start;
14012 while (tep) {
14013 *newp = funcblock;
14014 size = sizeof(struct tblentry) + strlen(tep->cmdname) + 1;
14015
14016 funcblock = (char *) funcblock + size;
14017 memcpy(*newp, tep, size);
14018 switch (tep->cmdtype) {
14019 case CMDBUILTIN:
14020 /* No pointer saving, this field must be fixed by forkshell_init() */
14021 (*newp)->param.cmd = (const struct builtincmd *)(tep->param.cmd - builtintab);
14022 break;
14023 case CMDFUNCTION:
14024 (*newp)->param.func = funcblock;
14025 funcblock = (char *) funcblock + offsetof(struct funcnode, n);
14026 copynode(&tep->param.func->n);
14027 SAVE_PTR((*newp)->param.func);
14028 break;
14029 default:
14030 break;
14031 }
14032 SAVE_PTR((*newp)->next);
14033 tep = tep->next;
14034 newp = &(*newp)->next;
14035 }
14036 *newp = NULL;
14037 return start;
14038}
14039
14040static void
14041cmdtable_size(struct tblentry **cmdtablep)
14042{
14043 int i;
14044 nodeptrsize += CMDTABLESIZE;
14045 funcblocksize += sizeof(struct tblentry *)*CMDTABLESIZE;
14046 for (i = 0; i < CMDTABLESIZE; i++)
14047 tblentry_size(cmdtablep[i]);
14048}
14049
14050static struct tblentry **
14051cmdtable_copy(struct tblentry **cmdtablep)
14052{
14053 struct tblentry **new = funcblock;
14054 int i;
14055
14056 funcblock = (char *) funcblock + sizeof(struct tblentry *)*CMDTABLESIZE;
14057 for (i = 0; i < CMDTABLESIZE; i++) {
14058 new[i] = tblentry_copy(cmdtablep[i]);
14059 SAVE_PTR(new[i]);
14060 }
14061 return new;
14062}
14063
14064/*
14065 * char **
14066 */
14067static void
14068argv_size(char **p)
14069{
14070 while (p && *p) {
14071 funcblocksize += sizeof(char *);
14072 funcstringsize += strlen(*p)+1;
14073 nodeptrsize++;
14074 p++;
14075 }
14076 funcblocksize += sizeof(char *);
14077}
14078
14079static char **
14080argv_copy(char **p)
14081{
14082 char **new, **start = funcblock;
14083
14084 while (p && *p) {
14085 new = funcblock;
14086 funcblock = (char *) funcblock + sizeof(char *);
14087 *new = nodeckstrdup(*p);
14088 SAVE_PTR(*new);
14089 p++;
14090 new++;
14091 }
14092 new = funcblock;
14093 funcblock = (char *) funcblock + sizeof(char *);
14094 *new = NULL;
14095 return start;
14096}
14097
14098/*
14099 * struct redirtab
14100 */
14101static void
14102redirtab_size(struct redirtab *rdtp)
14103{
14104 while (rdtp) {
14105 funcblocksize += sizeof(*rdtp)+sizeof(rdtp->two_fd[0])*rdtp->pair_count;
14106 rdtp = rdtp->next;
14107 nodeptrsize++; /* rdtp->next */
14108 }
14109}
14110
14111static struct redirtab *
14112redirtab_copy(struct redirtab *rdtp)
14113{
14114 struct redirtab *start;
14115 struct redirtab **vpp;
14116
14117 vpp = &start;
14118 while (rdtp) {
14119 int size = sizeof(*rdtp)+sizeof(rdtp->two_fd[0])*rdtp->pair_count;
14120 *vpp = funcblock;
14121 funcblock = (char *) funcblock + size;
14122 memcpy(*vpp, rdtp, size);
14123 SAVE_PTR((*vpp)->next);
14124 rdtp = rdtp->next;
14125 vpp = &(*vpp)->next;
14126 }
14127 *vpp = NULL;
14128 return start;
14129}
14130
14131#undef shellparam
14132#undef redirlist
14133#undef varinit
14134#undef vartab
14135static void
14136globals_var_size(struct globals_var *gvp)
14137{
14138 int i;
14139
14140 funcblocksize += sizeof(struct globals_var);
14141 argv_size(gvp->shellparam.p);
14142 redirtab_size(gvp->redirlist);
14143 for (i = 0; i < VTABSIZE; i++)
14144 var_size(gvp->vartab[i]);
14145 for (i = 0; i < ARRAY_SIZE(varinit_data); i++)
14146 var_size(gvp->varinit+i);
14147 nodeptrsize += 2 + VTABSIZE; /* gvp->redirlist, gvp->shellparam.p, vartab */
14148}
14149
14150#undef g_nullredirs
14151#undef preverrout_fd
14152static struct globals_var *
14153globals_var_copy(struct globals_var *gvp)
14154{
14155 int i;
14156 struct globals_var *new;
14157
14158 new = funcblock;
14159 funcblock = (char *) funcblock + sizeof(struct globals_var);
14160
14161 /* shparam */
14162 memcpy(&new->shellparam, &gvp->shellparam, sizeof(struct shparam));
14163 new->shellparam.malloced = 0;
14164 new->shellparam.p = argv_copy(gvp->shellparam.p);
14165 SAVE_PTR(new->shellparam.p);
14166
14167 new->redirlist = redirtab_copy(gvp->redirlist);
14168 SAVE_PTR(new->redirlist);
14169
14170 new->g_nullredirs = gvp->g_nullredirs;
14171 new->preverrout_fd = gvp->preverrout_fd;
14172 for (i = 0; i < VTABSIZE; i++) {
14173 new->vartab[i] = var_copy(gvp->vartab[i]);
14174 SAVE_PTR(new->vartab[i]);
14175 }
14176
14177 /* Can't use var_copy because varinit is already allocated */
14178 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) {
14179 new->varinit[i].next = NULL;
14180 new->varinit[i].var_text = nodeckstrdup(gvp->varinit[i].var_text);
14181 SAVE_PTR(new->varinit[i].var_text);
14182 new->varinit[i].flags = gvp->varinit[i].flags;
14183 new->varinit[i].var_func = gvp->varinit[i].var_func;
14184 }
14185 return new;
14186}
14187
14188#undef minusc
14189#undef curdir
14190#undef physdir
14191#undef arg0
14192#undef nullstr
14193static void
14194globals_misc_size(struct globals_misc *p)
14195{
14196 funcblocksize += sizeof(struct globals_misc);
14197 funcstringsize += p->minusc ? strlen(p->minusc) + 1 : 1;
14198 if (p->curdir != p->nullstr)
14199 funcstringsize += strlen(p->curdir) + 1;
14200 if (p->physdir != p->nullstr)
14201 funcstringsize += strlen(p->physdir) + 1;
14202 funcstringsize += strlen(p->arg0) + 1;
14203 nodeptrsize += 4; /* minusc, curdir, physdir, arg0 */
14204}
14205
14206static struct globals_misc *
14207globals_misc_copy(struct globals_misc *p)
14208{
14209 struct globals_misc *new = funcblock;
14210
14211 funcblock = (char *) funcblock + sizeof(struct globals_misc);
14212 memcpy(new, p, sizeof(struct globals_misc));
14213
14214 new->minusc = nodeckstrdup(p->minusc);
14215 new->curdir = p->curdir != p->nullstr ? nodeckstrdup(p->curdir) : new->nullstr;
14216 new->physdir = p->physdir != p->nullstr ? nodeckstrdup(p->physdir) : new->nullstr;
14217 new->arg0 = nodeckstrdup(p->arg0);
14218 SAVE_PTR4(new->minusc, new->curdir, new->physdir, new->arg0);
14219 return new;
14220}
14221
14222static void
14223forkshell_size(struct forkshell *fs)
14224{
14225 funcblocksize += sizeof(struct forkshell);
14226 globals_var_size(fs->gvp);
14227 globals_misc_size(fs->gmp);
14228 cmdtable_size(fs->cmdtable);
14229 localvar_size(fs->localvars);
14230 /* optlist_transfer(sending, fd); */
14231 /* misc_transfer(sending, fd); */
14232
14233 calcsize(fs->n);
14234 argv_size(fs->argv);
14235 funcstringsize += (fs->string ? strlen(fs->string) : 0) + 1;
14236 strlist_size(fs->strlist);
14237
14238 nodeptrsize += 8; /* gvp, gmp, cmdtable, localvars, n, argv, string, strlist */
14239}
14240
14241static struct forkshell *
14242forkshell_copy(struct forkshell *fs)
14243{
14244 struct forkshell *new;
14245
14246 new = funcblock;
14247 funcblock = (char *) funcblock + sizeof(struct forkshell);
14248
14249 memcpy(new, fs, sizeof(struct forkshell)); /* non-pointer stuff */
14250 new->gvp = globals_var_copy(fs->gvp);
14251 new->gmp = globals_misc_copy(fs->gmp);
14252 new->cmdtable = cmdtable_copy(fs->cmdtable);
14253 new->localvars = localvar_copy(fs->localvars);
14254 SAVE_PTR4(new->gvp, new->gmp, new->cmdtable, new->localvars);
14255
14256 /* new->fs will be reconstructed from new->fpid */
14257 new->n = copynode(fs->n);
14258 new->argv = argv_copy(fs->argv);
14259 new->string = nodeckstrdup(fs->string);
14260 new->strlist = strlist_copy(fs->strlist);
14261 SAVE_PTR4(new->n, new->argv, new->string, new->strlist);
14262 return new;
14263}
14264
14265static struct forkshell *
14266forkshell_prepare(struct forkshell *fs)
14267{
14268 struct forkshell *new;
14269 int size, fp, nodeptr_offset;
14270 HANDLE h;
14271 SECURITY_ATTRIBUTES sa;
14272
14273 for (fp = 0; forkpoints[fp] && forkpoints[fp] != fs->fp; fp++)
14274 ;
14275
14276 if (!forkpoints[fp])
14277 bb_error_msg_and_die("invalid forkpoint %08x", (int)fs->fp);
14278 fs->fpid = fp;
14279
14280 /* Calculate size of "new" */
14281 fs->gvp = ash_ptr_to_globals_var;
14282 fs->gmp = ash_ptr_to_globals_misc;
14283 fs->cmdtable = cmdtable;
14284 fs->localvars = localvars;
14285
14286 nodeptrsize = 1; /* NULL terminated */
14287 funcblocksize = 0;
14288 funcstringsize = 0;
14289 forkshell_size(fs);
14290 size = funcblocksize + funcstringsize + nodeptrsize*sizeof(int);
14291
14292 /* Allocate, initialize pointers */
14293 memset(&sa, 0, sizeof(sa));
14294 sa.nLength = sizeof(sa);
14295 sa.lpSecurityDescriptor = NULL;
14296 sa.bInheritHandle = TRUE;
14297 h = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, size, NULL);
14298 new = (struct forkshell *)MapViewOfFile(h, FILE_MAP_WRITE, 0,0, 0);
14299 /* new = ckmalloc(size); */
14300 funcblock = new;
14301 funcstring = (char *) funcblock + funcblocksize;
14302 nodeptr = (int*)((char *) funcstring + funcstringsize);
14303 nodeptr_offset = (int) nodeptr - (int) new;
14304
14305 /* Now pack them all */
14306 forkshell_copy(fs);
14307
14308 /* Finish it up */
14309 *nodeptr = 0;
14310 new->size = size;
14311 new->nodeptr_offset = nodeptr_offset;
14312 new->old_base = new;
14313 new->hMapFile = h;
14314 return new;
14315}
14316
14317#undef exception_handler
14318#undef trap
14319#undef trap_ptr
14320static void *sticky_mem_start, *sticky_mem_end;
14321static void
14322forkshell_init(const char *idstr)
14323{
14324 struct forkshell *fs;
14325 int map_handle;
14326 HANDLE h;
14327 struct globals_var **gvpp;
14328 struct globals_misc **gmpp;
14329 int i;
14330
14331 if (sscanf(idstr, "%x", &map_handle) != 1)
14332 bb_error_msg_and_die("invalid forkshell ID");
14333
14334 h = (HANDLE)map_handle;
14335 fs = (struct forkshell *)MapViewOfFile(h, FILE_MAP_WRITE, 0,0, 0);
14336 if (!fs)
14337 bb_error_msg_and_die("Invalid forkshell memory");
14338
14339 /* this memory can't be freed */
14340 sticky_mem_start = fs;
14341 sticky_mem_end = (char *) fs + fs->size;
14342 /* pointer fixup */
14343 nodeptr = (int*)((char*)fs + fs->nodeptr_offset);
14344 while (*nodeptr) {
14345 int *ptr = (int*)((char*)fs + (*nodeptr - (int)fs->old_base));
14346 if (*ptr)
14347 *ptr -= ((int)fs->old_base - (int)fs);
14348 nodeptr++;
14349 }
14350 /* Now fix up stuff that can't be transferred */
14351 fs->fp = forkpoints[fs->fpid];
14352 for (i = 0; i < ARRAY_SIZE(varinit_data); i++)
14353 fs->gvp->varinit[i].var_func = varinit_data[i].var_func;
14354 for (i = 0; i < CMDTABLESIZE; i++) {
14355 struct tblentry *e = fs->cmdtable[i];
14356 while (e) {
14357 if (e->cmdtype == CMDBUILTIN)
14358 e->param.cmd = builtintab + (int)e->param.cmd;
14359 e = e->next;
14360 }
14361 }
14362 fs->gmp->exception_handler = ash_ptr_to_globals_misc->exception_handler;
14363 for (i = 0; i < NSIG; i++)
14364 fs->gmp->trap[i] = ash_ptr_to_globals_misc->trap[i];
14365 fs->gmp->trap_ptr = ash_ptr_to_globals_misc->trap_ptr;
14366
14367 /* Switch global variables */
14368 gvpp = (struct globals_var **)&ash_ptr_to_globals_var;
14369 *gvpp = fs->gvp;
14370 gmpp = (struct globals_misc **)&ash_ptr_to_globals_misc;
14371 *gmpp = fs->gmp;
14372 localvars = fs->localvars;
14373 cmdtable = fs->cmdtable;
14374
14375 fs->fp(fs);
14376}
14377
14378#undef free
14379static void
14380sticky_free(void *base)
14381{
14382 if (base >= sticky_mem_start && base < sticky_mem_end)
14383 return;
14384 free(base);
14385}
14386#endif
13241 14387
13242/*- 14388/*-
13243 * Copyright (c) 1989, 1991, 1993, 1994 14389 * Copyright (c) 1989, 1991, 1993, 1994
diff --git a/shell/shell_common.c b/shell/shell_common.c
index 51c92d60e..0ffe21e0b 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -200,7 +200,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
200 } 200 }
201 201
202 c = buffer[bufpos]; 202 c = buffer[bufpos];
203 if (c == '\0') 203 if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r'))
204 continue; 204 continue;
205 if (backslash) { 205 if (backslash) {
206 backslash = 0; 206 backslash = 0;
@@ -369,6 +369,13 @@ static const char ulimit_opt_string[] = "-HSa"
369#endif 369#endif
370 ; 370 ;
371 371
372#if ENABLE_PLATFORM_MINGW32
373int FAST_FUNC
374shell_builtin_ulimit(char **argv)
375{
376 return 1;
377}
378#else
372static void printlim(unsigned opts, const struct rlimit *limit, 379static void printlim(unsigned opts, const struct rlimit *limit,
373 const struct limits *l) 380 const struct limits *l)
374{ 381{
@@ -497,3 +504,4 @@ shell_builtin_ulimit(char **argv)
497 504
498 return 0; 505 return 0;
499} 506}
507#endif
diff --git a/win32/Kbuild b/win32/Kbuild
new file mode 100644
index 000000000..ceede0c67
--- /dev/null
+++ b/win32/Kbuild
@@ -0,0 +1,18 @@
1# Makefile for busybox
2#
3# Licensed under the GPL v2, see the file LICENSE in this tarball.
4
5lib-y:=
6
7lib-$(CONFIG_PLATFORM_MINGW32) += env.o
8lib-$(CONFIG_PLATFORM_MINGW32) += fnmatch.o
9lib-$(CONFIG_PLATFORM_MINGW32) += ioctl.o
10lib-$(CONFIG_PLATFORM_MINGW32) += mingw.o
11lib-$(CONFIG_PLATFORM_MINGW32) += process.o
12lib-$(CONFIG_PLATFORM_MINGW32) += regex.o
13lib-$(CONFIG_WIN32_NET) += net.o
14lib-$(CONFIG_PLATFORM_MINGW32) += poll.o
15lib-$(CONFIG_PLATFORM_MINGW32) += popen.o
16lib-$(CONFIG_PLATFORM_MINGW32) += termios.o
17lib-$(CONFIG_PLATFORM_MINGW32) += uname.o
18lib-$(CONFIG_PLATFORM_MINGW32) += winansi.o
diff --git a/win32/env.c b/win32/env.c
new file mode 100644
index 000000000..f8d231a8f
--- /dev/null
+++ b/win32/env.c
@@ -0,0 +1,130 @@
1#include "libbb.h"
2
3char **copy_environ(const char *const *envp)
4{
5 char **env;
6 int i = 0;
7 while (envp[i])
8 i++;
9 env = xmalloc((i+1)*sizeof(*env));
10 for (i = 0; envp[i]; i++)
11 env[i] = xstrdup(envp[i]);
12 env[i] = NULL;
13 return env;
14}
15
16void free_environ(char **env)
17{
18 int i;
19 for (i = 0; env[i]; i++)
20 free(env[i]);
21 free(env);
22}
23
24static int lookup_env(char **env, const char *name, size_t nmln)
25{
26 int i;
27
28 for (i = 0; env[i]; i++) {
29 if (0 == strncmp(env[i], name, nmln)
30 && '=' == env[i][nmln])
31 /* matches */
32 return i;
33 }
34 return -1;
35}
36
37#undef getenv
38char *mingw_getenv(const char *name)
39{
40 char *result = getenv(name);
41 if (!result && !strcmp(name, "TMPDIR")) {
42 /* on Windows it is TMP and TEMP */
43 result = getenv("TMP");
44 if (!result)
45 result = getenv("TEMP");
46 }
47 return result;
48}
49
50int setenv(const char *name, const char *value, int replace)
51{
52 int out;
53 size_t namelen, valuelen;
54 char *envstr;
55
56 if (!name || !value) return -1;
57 if (!replace) {
58 char *oldval = NULL;
59 oldval = getenv(name);
60 if (oldval) return 0;
61 }
62
63 namelen = strlen(name);
64 valuelen = strlen(value);
65 envstr = malloc((namelen + valuelen + 2));
66 if (!envstr) return -1;
67
68 memcpy(envstr, name, namelen);
69 envstr[namelen] = '=';
70 memcpy(envstr + namelen + 1, value, valuelen);
71 envstr[namelen + valuelen + 1] = 0;
72
73 out = putenv(envstr);
74 /* putenv(3) makes the argument string part of the environment,
75 * and changing that string modifies the environment --- which
76 * means we do not own that storage anymore. Do not free
77 * envstr.
78 */
79
80 return out;
81}
82
83/*
84 * If name contains '=', then sets the variable, otherwise it unsets it
85 */
86char **env_setenv(char **env, const char *name)
87{
88 char *eq = strchrnul(name, '=');
89 int i = lookup_env(env, name, eq-name);
90
91 if (i < 0) {
92 if (*eq) {
93 for (i = 0; env[i]; i++)
94 ;
95 env = xrealloc(env, (i+2)*sizeof(*env));
96 env[i] = xstrdup(name);
97 env[i+1] = NULL;
98 }
99 }
100 else {
101 free(env[i]);
102 if (*eq)
103 env[i] = xstrdup(name);
104 else {
105 for (; env[i]; i++)
106 env[i] = env[i+1];
107 SetEnvironmentVariable(name, NULL);
108 }
109 }
110 return env;
111}
112
113void unsetenv(const char *env)
114{
115 env_setenv(environ, env);
116}
117
118int clearenv(void)
119{
120 char **env = environ;
121 if (!env)
122 return 0;
123 while (*env) {
124 free(*env);
125 env++;
126 }
127 free(env);
128 environ = NULL;
129 return 0;
130}
diff --git a/win32/fnmatch.c b/win32/fnmatch.c
new file mode 100644
index 000000000..1f4ead5f9
--- /dev/null
+++ b/win32/fnmatch.c
@@ -0,0 +1,488 @@
1/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with this library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
18
19#if HAVE_CONFIG_H
20# include <config.h>
21#endif
22
23/* Enable GNU extensions in fnmatch.h. */
24#ifndef _GNU_SOURCE
25# define _GNU_SOURCE 1
26#endif
27
28#include <errno.h>
29#include <fnmatch.h>
30#include <ctype.h>
31
32#if HAVE_STRING_H || defined _LIBC
33# include <string.h>
34#else
35# include <strings.h>
36#endif
37
38#if defined STDC_HEADERS || defined _LIBC
39# include <stdlib.h>
40#endif
41
42/* For platform which support the ISO C amendement 1 functionality we
43 support user defined character classes. */
44#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
45/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */
46# include <wchar.h>
47# include <wctype.h>
48#endif
49
50/* Comment out all this code if we are using the GNU C Library, and are not
51 actually compiling the library itself. This code is part of the GNU C
52 Library, but also included in many other GNU distributions. Compiling
53 and linking in this code is a waste when using the GNU C library
54 (especially if it is a shared library). Rather than having every GNU
55 program understand `configure --with-gnu-libc' and omit the object files,
56 it is simpler to just do this in the source for each such file. */
57
58#if defined _LIBC || !defined __GNU_LIBRARY__
59
60
61# if defined STDC_HEADERS || !defined isascii
62# define ISASCII(c) 1
63# else
64# define ISASCII(c) isascii(c)
65# endif
66
67# ifdef isblank
68# define ISBLANK(c) (ISASCII (c) && isblank (c))
69# else
70# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
71# endif
72# ifdef isgraph
73# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
74# else
75# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
76# endif
77
78# define ISPRINT(c) (ISASCII (c) && isprint (c))
79# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
80# define ISALNUM(c) (ISASCII (c) && isalnum (c))
81# define ISALPHA(c) (ISASCII (c) && isalpha (c))
82# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
83# define ISLOWER(c) (ISASCII (c) && islower (c))
84# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
85# define ISSPACE(c) (ISASCII (c) && isspace (c))
86# define ISUPPER(c) (ISASCII (c) && isupper (c))
87# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
88
89# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
90
91# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
92/* The GNU C library provides support for user-defined character classes
93 and the functions from ISO C amendement 1. */
94# ifdef CHARCLASS_NAME_MAX
95# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
96# else
97/* This shouldn't happen but some implementation might still have this
98 problem. Use a reasonable default value. */
99# define CHAR_CLASS_MAX_LENGTH 256
100# endif
101
102# ifdef _LIBC
103# define IS_CHAR_CLASS(string) __wctype (string)
104# else
105# define IS_CHAR_CLASS(string) wctype (string)
106# endif
107# else
108# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
109
110# define IS_CHAR_CLASS(string) \
111 (STREQ (string, "alpha") || STREQ (string, "upper") \
112 || STREQ (string, "lower") || STREQ (string, "digit") \
113 || STREQ (string, "alnum") || STREQ (string, "xdigit") \
114 || STREQ (string, "space") || STREQ (string, "print") \
115 || STREQ (string, "punct") || STREQ (string, "graph") \
116 || STREQ (string, "cntrl") || STREQ (string, "blank"))
117# endif
118
119/* Avoid depending on library functions or files
120 whose names are inconsistent. */
121
122# if !defined _LIBC && !defined getenv
123extern char *getenv ();
124# endif
125
126# ifndef errno
127extern int errno;
128# endif
129
130/* This function doesn't exist on most systems. */
131
132# if !defined HAVE___STRCHRNUL && !defined _LIBC
133static char *
134__strchrnul (s, c)
135 const char *s;
136 int c;
137{
138 char *result = strchr (s, c);
139 if (result == NULL)
140 result = strchr (s, '\0');
141 return result;
142}
143# endif
144
145# ifndef internal_function
146/* Inside GNU libc we mark some function in a special way. In other
147 environments simply ignore the marking. */
148# define internal_function
149# endif
150
151/* Match STRING against the filename pattern PATTERN, returning zero if
152 it matches, nonzero if not. */
153static int internal_fnmatch __P ((const char *pattern, const char *string,
154 int no_leading_period, int flags))
155 internal_function;
156static int
157internal_function
158internal_fnmatch (pattern, string, no_leading_period, flags)
159 const char *pattern;
160 const char *string;
161 int no_leading_period;
162 int flags;
163{
164 register const char *p = pattern, *n = string;
165 register unsigned char c;
166
167/* Note that this evaluates C many times. */
168# ifdef _LIBC
169# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
170# else
171# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
172# endif
173
174 while ((c = *p++) != '\0')
175 {
176 c = FOLD (c);
177
178 switch (c)
179 {
180 case '?':
181 if (*n == '\0')
182 return FNM_NOMATCH;
183 else if (*n == '/' && (flags & FNM_FILE_NAME))
184 return FNM_NOMATCH;
185 else if (*n == '.' && no_leading_period
186 && (n == string
187 || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
188 return FNM_NOMATCH;
189 break;
190
191 case '\\':
192 if (!(flags & FNM_NOESCAPE))
193 {
194 c = *p++;
195 if (c == '\0')
196 /* Trailing \ loses. */
197 return FNM_NOMATCH;
198 c = FOLD (c);
199 }
200 if (FOLD ((unsigned char) *n) != c)
201 return FNM_NOMATCH;
202 break;
203
204 case '*':
205 if (*n == '.' && no_leading_period
206 && (n == string
207 || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
208 return FNM_NOMATCH;
209
210 for (c = *p++; c == '?' || c == '*'; c = *p++)
211 {
212 if (*n == '/' && (flags & FNM_FILE_NAME))
213 /* A slash does not match a wildcard under FNM_FILE_NAME. */
214 return FNM_NOMATCH;
215 else if (c == '?')
216 {
217 /* A ? needs to match one character. */
218 if (*n == '\0')
219 /* There isn't another character; no match. */
220 return FNM_NOMATCH;
221 else
222 /* One character of the string is consumed in matching
223 this ? wildcard, so *??? won't match if there are
224 less than three characters. */
225 ++n;
226 }
227 }
228
229 if (c == '\0')
230 /* The wildcard(s) is/are the last element of the pattern.
231 If the name is a file name and contains another slash
232 this does mean it cannot match. */
233 return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
234 ? FNM_NOMATCH : 0);
235 else
236 {
237 const char *endp;
238
239 endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
240
241 if (c == '[')
242 {
243 int flags2 = ((flags & FNM_FILE_NAME)
244 ? flags : (flags & ~FNM_PERIOD));
245
246 for (--p; n < endp; ++n)
247 if (internal_fnmatch (p, n,
248 (no_leading_period
249 && (n == string
250 || (n[-1] == '/'
251 && (flags
252 & FNM_FILE_NAME)))),
253 flags2)
254 == 0)
255 return 0;
256 }
257 else if (c == '/' && (flags & FNM_FILE_NAME))
258 {
259 while (*n != '\0' && *n != '/')
260 ++n;
261 if (*n == '/'
262 && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
263 flags) == 0))
264 return 0;
265 }
266 else
267 {
268 int flags2 = ((flags & FNM_FILE_NAME)
269 ? flags : (flags & ~FNM_PERIOD));
270
271 if (c == '\\' && !(flags & FNM_NOESCAPE))
272 c = *p;
273 c = FOLD (c);
274 for (--p; n < endp; ++n)
275 if (FOLD ((unsigned char) *n) == c
276 && (internal_fnmatch (p, n,
277 (no_leading_period
278 && (n == string
279 || (n[-1] == '/'
280 && (flags
281 & FNM_FILE_NAME)))),
282 flags2) == 0))
283 return 0;
284 }
285 }
286
287 /* If we come here no match is possible with the wildcard. */
288 return FNM_NOMATCH;
289
290 case '[':
291 {
292 /* Nonzero if the sense of the character class is inverted. */
293 static int posixly_correct;
294 register int not;
295 char cold;
296
297 if (posixly_correct == 0)
298 posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
299
300 if (*n == '\0')
301 return FNM_NOMATCH;
302
303 if (*n == '.' && no_leading_period && (n == string
304 || (n[-1] == '/'
305 && (flags
306 & FNM_FILE_NAME))))
307 return FNM_NOMATCH;
308
309 if (*n == '/' && (flags & FNM_FILE_NAME))
310 /* `/' cannot be matched. */
311 return FNM_NOMATCH;
312
313 not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
314 if (not)
315 ++p;
316
317 c = *p++;
318 for (;;)
319 {
320 unsigned char fn = FOLD ((unsigned char) *n);
321
322 if (!(flags & FNM_NOESCAPE) && c == '\\')
323 {
324 if (*p == '\0')
325 return FNM_NOMATCH;
326 c = FOLD ((unsigned char) *p);
327 ++p;
328
329 if (c == fn)
330 goto matched;
331 }
332 else if (c == '[' && *p == ':')
333 {
334 /* Leave room for the null. */
335 char str[CHAR_CLASS_MAX_LENGTH + 1];
336 size_t c1 = 0;
337# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
338 wctype_t wt;
339# endif
340 const char *startp = p;
341
342 for (;;)
343 {
344 if (c1 == CHAR_CLASS_MAX_LENGTH)
345 /* The name is too long and therefore the pattern
346 is ill-formed. */
347 return FNM_NOMATCH;
348
349 c = *++p;
350 if (c == ':' && p[1] == ']')
351 {
352 p += 2;
353 break;
354 }
355 if (c < 'a' || c >= 'z')
356 {
357 /* This cannot possibly be a character class name.
358 Match it as a normal range. */
359 p = startp;
360 c = '[';
361 goto normal_bracket;
362 }
363 str[c1++] = c;
364 }
365 str[c1] = '\0';
366
367# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
368 wt = IS_CHAR_CLASS (str);
369 if (wt == 0)
370 /* Invalid character class name. */
371 return FNM_NOMATCH;
372
373 if (__iswctype (__btowc ((unsigned char) *n), wt))
374 goto matched;
375# else
376 if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
377 || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
378 || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
379 || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
380 || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
381 || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
382 || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
383 || (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
384 || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
385 || (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
386 || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
387 || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
388 goto matched;
389# endif
390 }
391 else if (c == '\0')
392 /* [ (unterminated) loses. */
393 return FNM_NOMATCH;
394 else
395 {
396 normal_bracket:
397 if (FOLD (c) == fn)
398 goto matched;
399
400 cold = c;
401 c = *p++;
402
403 if (c == '-' && *p != ']')
404 {
405 /* It is a range. */
406 unsigned char cend = *p++;
407 if (!(flags & FNM_NOESCAPE) && cend == '\\')
408 cend = *p++;
409 if (cend == '\0')
410 return FNM_NOMATCH;
411
412 if (cold <= fn && fn <= FOLD (cend))
413 goto matched;
414
415 c = *p++;
416 }
417 }
418
419 if (c == ']')
420 break;
421 }
422
423 if (!not)
424 return FNM_NOMATCH;
425 break;
426
427 matched:
428 /* Skip the rest of the [...] that already matched. */
429 while (c != ']')
430 {
431 if (c == '\0')
432 /* [... (unterminated) loses. */
433 return FNM_NOMATCH;
434
435 c = *p++;
436 if (!(flags & FNM_NOESCAPE) && c == '\\')
437 {
438 if (*p == '\0')
439 return FNM_NOMATCH;
440 /* XXX 1003.2d11 is unclear if this is right. */
441 ++p;
442 }
443 else if (c == '[' && *p == ':')
444 {
445 do
446 if (*++p == '\0')
447 return FNM_NOMATCH;
448 while (*p != ':' || p[1] == ']');
449 p += 2;
450 c = *p;
451 }
452 }
453 if (not)
454 return FNM_NOMATCH;
455 }
456 break;
457
458 default:
459 if (c != FOLD ((unsigned char) *n))
460 return FNM_NOMATCH;
461 }
462
463 ++n;
464 }
465
466 if (*n == '\0')
467 return 0;
468
469 if ((flags & FNM_LEADING_DIR) && *n == '/')
470 /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
471 return 0;
472
473 return FNM_NOMATCH;
474
475# undef FOLD
476}
477
478
479int
480fnmatch (pattern, string, flags)
481 const char *pattern;
482 const char *string;
483 int flags;
484{
485 return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
486}
487
488#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/win32/fnmatch.h b/win32/fnmatch.h
new file mode 100644
index 000000000..cc3ec3794
--- /dev/null
+++ b/win32/fnmatch.h
@@ -0,0 +1,84 @@
1/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
18
19#ifndef _FNMATCH_H
20#define _FNMATCH_H 1
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
27# if !defined __GLIBC__ || !defined __P
28# undef __P
29# define __P(protos) protos
30# endif
31#else /* Not C++ or ANSI C. */
32# undef __P
33# define __P(protos) ()
34/* We can get away without defining `const' here only because in this file
35 it is used only inside the prototype for `fnmatch', which is elided in
36 non-ANSI C where `const' is problematical. */
37#endif /* C++ or ANSI C. */
38
39#ifndef const
40# if (defined __STDC__ && __STDC__) || defined __cplusplus
41# define __const const
42# else
43# define __const
44# endif
45#endif
46
47/* We #undef these before defining them because some losing systems
48 (HP-UX A.08.07 for example) define these in <unistd.h>. */
49#undef FNM_PATHNAME
50#undef FNM_NOESCAPE
51#undef FNM_PERIOD
52
53/* Bits set in the FLAGS argument to `fnmatch'. */
54#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
55#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
56#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
57
58#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
59# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
60# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
61# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
62#endif
63
64/* Value returned by `fnmatch' if STRING does not match PATTERN. */
65#define FNM_NOMATCH 1
66
67/* This value is returned if the implementation does not support
68 `fnmatch'. Since this is not the case here it will never be
69 returned but the conformance test suites still require the symbol
70 to be defined. */
71#ifdef _XOPEN_SOURCE
72# define FNM_NOSYS (-1)
73#endif
74
75/* Match NAME against the filename pattern PATTERN,
76 returning zero if it matches, FNM_NOMATCH if not. */
77extern int fnmatch __P ((__const char *__pattern, __const char *__name,
78 int __flags));
79
80#ifdef __cplusplus
81}
82#endif
83
84#endif /* fnmatch.h */
diff --git a/win32/grp.h b/win32/grp.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/grp.h
diff --git a/win32/ioctl.c b/win32/ioctl.c
new file mode 100644
index 000000000..73ceeedec
--- /dev/null
+++ b/win32/ioctl.c
@@ -0,0 +1,24 @@
1#include "libbb.h"
2
3int ioctl(int fd UNUSED_PARAM, int code, ...)
4{
5 va_list ap;
6 void *arg;
7 int ret = -1;
8
9 va_start(ap, code);
10
11 switch (code) {
12 case TIOCGWINSZ:
13 arg = va_arg(ap, void *);
14 ret = winansi_get_terminal_width_height((struct winsize *)arg);
15 break;
16 default:
17 ret = -1;
18 errno = EINVAL;
19 break;
20 }
21
22 va_end(ap);
23 return ret;
24}
diff --git a/win32/mingw.c b/win32/mingw.c
new file mode 100644
index 000000000..b99c88444
--- /dev/null
+++ b/win32/mingw.c
@@ -0,0 +1,731 @@
1#include "libbb.h"
2
3unsigned int _CRT_fmode = _O_BINARY;
4
5static int err_win_to_posix(DWORD winerr)
6{
7 int error = ENOSYS;
8 switch(winerr) {
9 case ERROR_ACCESS_DENIED: error = EACCES; break;
10 case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
11 case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
12 case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
13 case ERROR_ALREADY_EXISTS: error = EEXIST; break;
14 case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
15 case ERROR_BAD_COMMAND: error = EIO; break;
16 case ERROR_BAD_DEVICE: error = ENODEV; break;
17 case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
18 case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
19 case ERROR_BAD_FORMAT: error = ENOEXEC; break;
20 case ERROR_BAD_LENGTH: error = EINVAL; break;
21 case ERROR_BAD_PATHNAME: error = ENOENT; break;
22 case ERROR_BAD_PIPE: error = EPIPE; break;
23 case ERROR_BAD_UNIT: error = ENODEV; break;
24 case ERROR_BAD_USERNAME: error = EINVAL; break;
25 case ERROR_BROKEN_PIPE: error = EPIPE; break;
26 case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
27 case ERROR_BUSY: error = EBUSY; break;
28 case ERROR_BUSY_DRIVE: error = EBUSY; break;
29 case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
30 case ERROR_CANNOT_MAKE: error = EACCES; break;
31 case ERROR_CANTOPEN: error = EIO; break;
32 case ERROR_CANTREAD: error = EIO; break;
33 case ERROR_CANTWRITE: error = EIO; break;
34 case ERROR_CRC: error = EIO; break;
35 case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
36 case ERROR_DEVICE_IN_USE: error = EBUSY; break;
37 case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
38 case ERROR_DIRECTORY: error = EINVAL; break;
39 case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
40 case ERROR_DISK_CHANGE: error = EIO; break;
41 case ERROR_DISK_FULL: error = ENOSPC; break;
42 case ERROR_DRIVE_LOCKED: error = EBUSY; break;
43 case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
44 case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
45 case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
46 case ERROR_FILE_EXISTS: error = EEXIST; break;
47 case ERROR_FILE_INVALID: error = ENODEV; break;
48 case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
49 case ERROR_GEN_FAILURE: error = EIO; break;
50 case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
51 case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
52 case ERROR_INVALID_ACCESS: error = EACCES; break;
53 case ERROR_INVALID_ADDRESS: error = EFAULT; break;
54 case ERROR_INVALID_BLOCK: error = EFAULT; break;
55 case ERROR_INVALID_DATA: error = EINVAL; break;
56 case ERROR_INVALID_DRIVE: error = ENODEV; break;
57 case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
58 case ERROR_INVALID_FLAGS: error = EINVAL; break;
59 case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
60 case ERROR_INVALID_HANDLE: error = EBADF; break;
61 case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
62 case ERROR_INVALID_NAME: error = EINVAL; break;
63 case ERROR_INVALID_OWNER: error = EINVAL; break;
64 case ERROR_INVALID_PARAMETER: error = EINVAL; break;
65 case ERROR_INVALID_PASSWORD: error = EPERM; break;
66 case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
67 case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
68 case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
69 case ERROR_INVALID_WORKSTATION: error = EACCES; break;
70 case ERROR_IO_DEVICE: error = EIO; break;
71 case ERROR_IO_INCOMPLETE: error = EINTR; break;
72 case ERROR_LOCKED: error = EBUSY; break;
73 case ERROR_LOCK_VIOLATION: error = EACCES; break;
74 case ERROR_LOGON_FAILURE: error = EACCES; break;
75 case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
76 case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
77 case ERROR_MORE_DATA: error = EPIPE; break;
78 case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
79 case ERROR_NOACCESS: error = EFAULT; break;
80 case ERROR_NONE_MAPPED: error = EINVAL; break;
81 case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
82 case ERROR_NOT_READY: error = EAGAIN; break;
83 case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
84 case ERROR_NO_DATA: error = EPIPE; break;
85 case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
86 case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
87 case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
88 case ERROR_OPEN_FAILED: error = EIO; break;
89 case ERROR_OPEN_FILES: error = EBUSY; break;
90 case ERROR_OPERATION_ABORTED: error = EINTR; break;
91 case ERROR_OUTOFMEMORY: error = ENOMEM; break;
92 case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
93 case ERROR_PATH_BUSY: error = EBUSY; break;
94 case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
95 case ERROR_PIPE_BUSY: error = EBUSY; break;
96 case ERROR_PIPE_CONNECTED: error = EPIPE; break;
97 case ERROR_PIPE_LISTENING: error = EPIPE; break;
98 case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
99 case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
100 case ERROR_READ_FAULT: error = EIO; break;
101 case ERROR_SEEK: error = EIO; break;
102 case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
103 case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
104 case ERROR_SHARING_VIOLATION: error = EACCES; break;
105 case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
106 case ERROR_SWAPERROR: error = ENOENT; break;
107 case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
108 case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
109 case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
110 case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
111 case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
112 case ERROR_WRITE_FAULT: error = EIO; break;
113 case ERROR_WRITE_PROTECT: error = EROFS; break;
114 }
115 return error;
116}
117
118#undef open
119int mingw_open (const char *filename, int oflags, ...)
120{
121 va_list args;
122 unsigned mode;
123 int fd;
124
125 va_start(args, oflags);
126 mode = va_arg(args, int);
127 va_end(args);
128
129 if (oflags & O_NONBLOCK) {
130 errno = ENOSYS;
131 return -1;
132 }
133 if (filename && !strcmp(filename, "/dev/null"))
134 filename = "nul";
135 fd = open(filename, oflags, mode);
136 if (fd < 0 && (oflags & O_CREAT) && errno == EACCES) {
137 DWORD attrs = GetFileAttributes(filename);
138 if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
139 errno = EISDIR;
140 }
141 return fd;
142}
143
144#undef fopen
145FILE *mingw_fopen (const char *filename, const char *otype)
146{
147 if (filename && !strcmp(filename, "/dev/null"))
148 filename = "nul";
149 return fopen(filename, otype);
150}
151
152#undef dup2
153int mingw_dup2 (int fd, int fdto)
154{
155 int ret = dup2(fd, fdto);
156 return ret != -1 ? fdto : -1;
157}
158
159/*
160 * The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
161 * Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
162 */
163static inline long long filetime_to_hnsec(const FILETIME *ft)
164{
165 long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
166 /* Windows to Unix Epoch conversion */
167 return winTime - 116444736000000000LL;
168}
169
170static inline time_t filetime_to_time_t(const FILETIME *ft)
171{
172 return (time_t)(filetime_to_hnsec(ft) / 10000000);
173}
174
175static inline int file_attr_to_st_mode (DWORD attr)
176{
177 int fMode = S_IREAD;
178 if (attr & FILE_ATTRIBUTE_DIRECTORY)
179 fMode |= S_IFDIR;
180 else
181 fMode |= S_IFREG;
182 if (!(attr & FILE_ATTRIBUTE_READONLY))
183 fMode |= S_IWRITE;
184 return fMode;
185}
186
187static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fdata)
188{
189 if (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata))
190 return 0;
191
192 switch (GetLastError()) {
193 case ERROR_ACCESS_DENIED:
194 case ERROR_SHARING_VIOLATION:
195 case ERROR_LOCK_VIOLATION:
196 case ERROR_SHARING_BUFFER_EXCEEDED:
197 return EACCES;
198 case ERROR_BUFFER_OVERFLOW:
199 return ENAMETOOLONG;
200 case ERROR_NOT_ENOUGH_MEMORY:
201 return ENOMEM;
202 default:
203 return ENOENT;
204 }
205}
206
207/* We keep the do_lstat code in a separate function to avoid recursion.
208 * When a path ends with a slash, the stat will fail with ENOENT. In
209 * this case, we strip the trailing slashes and stat again.
210 *
211 * If follow is true then act like stat() and report on the link
212 * target. Otherwise report on the link itself.
213 */
214static int do_lstat(int follow, const char *file_name, struct stat *buf)
215{
216 int err;
217 WIN32_FILE_ATTRIBUTE_DATA fdata;
218
219 if (!(err = get_file_attr(file_name, &fdata))) {
220 int len = strlen(file_name);
221
222 buf->st_ino = 0;
223 buf->st_gid = 0;
224 buf->st_uid = 0;
225 buf->st_nlink = 1;
226 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
227 if (len > 4 && !strcmp(file_name+len-4, ".exe"))
228 buf->st_mode |= S_IEXEC;
229 buf->st_size = fdata.nFileSizeLow |
230 (((off64_t)fdata.nFileSizeHigh)<<32);
231 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
232 buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
233 buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
234 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
235 if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
236 WIN32_FIND_DATAA findbuf;
237 HANDLE handle = FindFirstFileA(file_name, &findbuf);
238 if (handle != INVALID_HANDLE_VALUE) {
239 if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
240 (findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
241 if (follow) {
242 char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
243 buf->st_size = readlink(file_name, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
244 } else {
245 buf->st_mode = S_IFLNK;
246 }
247 buf->st_mode |= S_IREAD;
248 if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
249 buf->st_mode |= S_IWRITE;
250 }
251 FindClose(handle);
252 }
253 }
254 return 0;
255 }
256 errno = err;
257 return -1;
258}
259
260/* We provide our own lstat/fstat functions, since the provided
261 * lstat/fstat functions are so slow. These stat functions are
262 * tailored for Git's usage (read: fast), and are not meant to be
263 * complete. Note that Git stat()s are redirected to mingw_lstat()
264 * too, since Windows doesn't really handle symlinks that well.
265 */
266static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
267{
268 int namelen;
269 static char alt_name[PATH_MAX];
270
271 if (!do_lstat(follow, file_name, buf))
272 return 0;
273
274 /* if file_name ended in a '/', Windows returned ENOENT;
275 * try again without trailing slashes
276 */
277 if (errno != ENOENT)
278 return -1;
279
280 namelen = strlen(file_name);
281 if (namelen && file_name[namelen-1] != '/')
282 return -1;
283 while (namelen && file_name[namelen-1] == '/')
284 --namelen;
285 if (!namelen || namelen >= PATH_MAX)
286 return -1;
287
288 memcpy(alt_name, file_name, namelen);
289 alt_name[namelen] = 0;
290 return do_lstat(follow, alt_name, buf);
291}
292
293int mingw_lstat(const char *file_name, struct stat *buf)
294{
295 return do_stat_internal(0, file_name, buf);
296}
297int mingw_stat(const char *file_name, struct stat *buf)
298{
299 return do_stat_internal(1, file_name, buf);
300}
301
302#undef fstat
303int mingw_fstat(int fd, struct stat *buf)
304{
305 HANDLE fh = (HANDLE)_get_osfhandle(fd);
306 BY_HANDLE_FILE_INFORMATION fdata;
307
308 if (fh == INVALID_HANDLE_VALUE) {
309 errno = EBADF;
310 return -1;
311 }
312 /* direct non-file handles to MS's fstat() */
313 if (GetFileType(fh) != FILE_TYPE_DISK)
314 return _fstati64(fd, buf);
315
316 if (GetFileInformationByHandle(fh, &fdata)) {
317 buf->st_ino = 0;
318 buf->st_gid = 0;
319 buf->st_uid = 0;
320 buf->st_nlink = 1;
321 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
322 buf->st_size = fdata.nFileSizeLow |
323 (((off64_t)fdata.nFileSizeHigh)<<32);
324 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
325 buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
326 buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
327 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
328 return 0;
329 }
330 errno = EBADF;
331 return -1;
332}
333
334static inline void time_t_to_filetime(time_t t, FILETIME *ft)
335{
336 long long winTime = t * 10000000LL + 116444736000000000LL;
337 ft->dwLowDateTime = winTime;
338 ft->dwHighDateTime = winTime >> 32;
339}
340
341int mingw_utime (const char *file_name, const struct utimbuf *times)
342{
343 FILETIME mft, aft;
344 int fh, rc;
345
346 /* must have write permission */
347 if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0)
348 return -1;
349
350 if (times) {
351 time_t_to_filetime(times->modtime, &mft);
352 time_t_to_filetime(times->actime, &aft);
353 }
354 else {
355 SYSTEMTIME st;
356 GetSystemTime(&st);
357 SystemTimeToFileTime(&st, &aft);
358 mft = aft;
359 }
360 if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
361 errno = EINVAL;
362 rc = -1;
363 } else
364 rc = 0;
365 close(fh);
366 return rc;
367}
368
369static inline void timeval_to_filetime(const struct timeval tv, FILETIME *ft)
370{
371 long long winTime = ((tv.tv_sec * 1000000LL) + tv.tv_usec) * 10LL + 116444736000000000LL;
372 ft->dwLowDateTime = winTime;
373 ft->dwHighDateTime = winTime >> 32;
374}
375
376int utimes(const char *file_name, const struct timeval times[2])
377{
378 FILETIME mft, aft;
379 int fh, rc;
380
381 /* must have write permission */
382 if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0)
383 return -1;
384
385 if (times) {
386 timeval_to_filetime(times[0], &aft);
387 timeval_to_filetime(times[1], &mft);
388 }
389 else {
390 SYSTEMTIME st;
391 GetSystemTime(&st);
392 SystemTimeToFileTime(&st, &aft);
393 mft = aft;
394 }
395 if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
396 errno = EINVAL;
397 rc = -1;
398 } else
399 rc = 0;
400 close(fh);
401 return rc;
402}
403
404unsigned int sleep (unsigned int seconds)
405{
406 Sleep(seconds*1000);
407 return 0;
408}
409
410int mkstemp(char *template)
411{
412 char *filename = mktemp(template);
413 if (filename == NULL)
414 return -1;
415 return open(filename, O_RDWR | O_CREAT, 0600);
416}
417
418int gettimeofday(struct timeval *tv, void *tz UNUSED_PARAM)
419{
420 FILETIME ft;
421 long long hnsec;
422
423 GetSystemTimeAsFileTime(&ft);
424 hnsec = filetime_to_hnsec(&ft);
425 tv->tv_sec = hnsec / 10000000;
426 tv->tv_usec = (hnsec % 10000000) / 10;
427 return 0;
428}
429
430int pipe(int filedes[2])
431{
432 if (_pipe(filedes, PIPE_BUF, 0) < 0)
433 return -1;
434 return 0;
435}
436
437struct tm *gmtime_r(const time_t *timep, struct tm *result)
438{
439 /* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */
440 memcpy(result, gmtime(timep), sizeof(struct tm));
441 return result;
442}
443
444struct tm *localtime_r(const time_t *timep, struct tm *result)
445{
446 /* localtime() in MSVCRT.DLL is thread-safe, but not reentrant */
447 memcpy(result, localtime(timep), sizeof(struct tm));
448 return result;
449}
450
451#undef getcwd
452char *mingw_getcwd(char *pointer, int len)
453{
454 int i;
455 char *ret = getcwd(pointer, len);
456 if (!ret)
457 return ret;
458 for (i = 0; ret[i]; i++)
459 if (ret[i] == '\\')
460 ret[i] = '/';
461 return ret;
462}
463
464#undef rename
465int mingw_rename(const char *pold, const char *pnew)
466{
467 DWORD attrs;
468
469 /*
470 * Try native rename() first to get errno right.
471 * It is based on MoveFile(), which cannot overwrite existing files.
472 */
473 if (!rename(pold, pnew))
474 return 0;
475 if (errno != EEXIST)
476 return -1;
477 if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
478 return 0;
479 /* TODO: translate more errors */
480 if (GetLastError() == ERROR_ACCESS_DENIED &&
481 (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
482 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
483 errno = EISDIR;
484 return -1;
485 }
486 if ((attrs & FILE_ATTRIBUTE_READONLY) &&
487 SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
488 if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
489 return 0;
490 /* revert file attributes on failure */
491 SetFileAttributes(pnew, attrs);
492 }
493 }
494 errno = EACCES;
495 return -1;
496}
497
498struct passwd *getpwuid(int uid UNUSED_PARAM)
499{
500 static char user_name[100];
501 static struct passwd p;
502
503 DWORD len = sizeof(user_name);
504 if (!GetUserName(user_name, &len))
505 return NULL;
506 p.pw_name = user_name;
507 p.pw_gecos = "unknown";
508 p.pw_dir = NULL;
509 return &p;
510}
511
512static HANDLE timer_event;
513static HANDLE timer_thread;
514static int timer_interval;
515static int one_shot;
516static sighandler_t timer_fn = SIG_DFL;
517
518/* The timer works like this:
519 * The thread, ticktack(), is a trivial routine that most of the time
520 * only waits to receive the signal to terminate. The main thread tells
521 * the thread to terminate by setting the timer_event to the signalled
522 * state.
523 * But ticktack() interrupts the wait state after the timer's interval
524 * length to call the signal handler.
525 */
526
527static __stdcall unsigned ticktack(void *dummy UNUSED_PARAM)
528{
529 while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
530 if (timer_fn == SIG_DFL)
531 bb_error_msg_and_die("Alarm");
532 if (timer_fn != SIG_IGN)
533 timer_fn(SIGALRM);
534 if (one_shot)
535 break;
536 }
537 return 0;
538}
539
540static int start_timer_thread(void)
541{
542 timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
543 if (timer_event) {
544 timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
545 if (!timer_thread ) {
546 errno = ENOMEM;
547 return -1;
548 }
549 } else {
550 errno = ENOMEM;
551 return -1;
552 }
553 return 0;
554}
555
556static void stop_timer_thread(void)
557{
558 if (timer_event)
559 SetEvent(timer_event); /* tell thread to terminate */
560 if (timer_thread) {
561 int rc = WaitForSingleObject(timer_thread, 1000);
562 if (rc == WAIT_TIMEOUT)
563 fprintf(stderr, "timer thread did not terminate timely");
564 else if (rc != WAIT_OBJECT_0)
565 fprintf(stderr, "waiting for timer thread failed: %lu",
566 GetLastError());
567 CloseHandle(timer_thread);
568 }
569 if (timer_event)
570 CloseHandle(timer_event);
571 timer_event = NULL;
572 timer_thread = NULL;
573}
574
575static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)
576{
577 return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
578}
579
580int setitimer(int type UNUSED_PARAM, struct itimerval *in, struct itimerval *out)
581{
582 static const struct timeval zero;
583 static int atexit_done;
584
585 if (out != NULL) {
586 errno = EINVAL;
587 return -1;
588 }
589 if (!is_timeval_eq(&in->it_interval, &zero) &&
590 !is_timeval_eq(&in->it_interval, &in->it_value)) {
591 errno = EINVAL;
592 return -1;
593 }
594
595 if (timer_thread)
596 stop_timer_thread();
597
598 if (is_timeval_eq(&in->it_value, &zero) &&
599 is_timeval_eq(&in->it_interval, &zero))
600 return 0;
601
602 timer_interval = in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000;
603 one_shot = is_timeval_eq(&in->it_interval, &zero);
604 if (!atexit_done) {
605 atexit(stop_timer_thread);
606 atexit_done = 1;
607 }
608 return start_timer_thread();
609}
610
611int sigaction(int sig, struct sigaction *in, struct sigaction *out)
612{
613 if (sig != SIGALRM) {
614 errno = EINVAL;
615 return -1;
616 }
617 if (out != NULL) {
618 errno = EINVAL;
619 return -1;
620 }
621
622 timer_fn = in->sa_handler;
623 return 0;
624}
625
626#undef signal
627sighandler_t mingw_signal(int sig, sighandler_t handler)
628{
629 sighandler_t old = timer_fn;
630 if (sig != SIGALRM)
631 return signal(sig, handler);
632 timer_fn = handler;
633 return old;
634}
635
636int link(const char *oldpath, const char *newpath)
637{
638 typedef BOOL (WINAPI *T)(const char*, const char*, LPSECURITY_ATTRIBUTES);
639 static T create_hard_link = NULL;
640 if (!create_hard_link) {
641 create_hard_link = (T) GetProcAddress(
642 GetModuleHandle("kernel32.dll"), "CreateHardLinkA");
643 if (!create_hard_link)
644 create_hard_link = (T)-1;
645 }
646 if (create_hard_link == (T)-1) {
647 errno = ENOSYS;
648 return -1;
649 }
650 if (!create_hard_link(newpath, oldpath, NULL)) {
651 errno = err_win_to_posix(GetLastError());
652 return -1;
653 }
654 return 0;
655}
656
657char *realpath(const char *path, char *resolved_path)
658{
659 /* FIXME: need normalization */
660 return strcpy(resolved_path, path);
661}
662
663const char *get_busybox_exec_path(void)
664{
665 static char path[PATH_MAX] = "";
666
667 if (!*path)
668 GetModuleFileName(NULL, path, PATH_MAX);
669 return path;
670}
671
672#undef mkdir
673int mingw_mkdir(const char *path, int mode UNUSED_PARAM)
674{
675 return mkdir(path);
676}
677
678int fcntl(int fd, int cmd, ...)
679{
680 va_list arg;
681 int result = -1;
682 char *fds;
683 int target, i, newfd;
684
685 va_start(arg, cmd);
686
687 switch (cmd) {
688 case F_GETFD:
689 case F_SETFD:
690 case F_GETFL:
691 /*
692 * Our fake F_GETFL won't matter if the return value is used as
693 * fcntl(fd, F_SETFL, ret|something);
694 * because F_SETFL isn't supported either.
695 */
696 result = 0;
697 break;
698 case F_DUPFD:
699 target = va_arg(arg, int);
700 fds = xzalloc(target);
701 while ((newfd = dup(fd)) < target && newfd >= 0) {
702 fds[newfd] = 1;
703 }
704 for (i = 0; i < target; ++i) {
705 if (fds[i]) {
706 close(i);
707 }
708 }
709 free(fds);
710 result = newfd;
711 default:
712 errno = ENOSYS;
713 break;
714 }
715
716 va_end(arg);
717 return result;
718}
719
720#undef unlink
721int mingw_unlink(const char *pathname)
722{
723 /* read-only files cannot be removed */
724 chmod(pathname, 0666);
725 return unlink(pathname);
726}
727
728char *strptime(const char *s UNUSED_PARAM, const char *format UNUSED_PARAM, struct tm *tm UNUSED_PARAM)
729{
730 return NULL;
731}
diff --git a/win32/net.c b/win32/net.c
new file mode 100644
index 000000000..eadda6b69
--- /dev/null
+++ b/win32/net.c
@@ -0,0 +1,54 @@
1#include "libbb.h"
2
3int inet_aton(const char *cp, struct in_addr *inp)
4{
5 unsigned long val = inet_addr(cp);
6
7 if (val == INADDR_NONE)
8 return 0;
9 inp->S_un.S_addr = val;
10 return 1;
11}
12
13void init_winsock(void)
14{
15 WSADATA wsa;
16 if (WSAStartup(MAKEWORD(2,2), &wsa))
17 bb_error_msg_and_die("unable to initialize winsock subsystem, error %d",
18 WSAGetLastError());
19 atexit((void(*)(void)) WSACleanup); /* may conflict with other atexit? */
20}
21
22int mingw_socket(int domain, int type, int protocol)
23{
24 int sockfd;
25 SOCKET s = WSASocket(domain, type, protocol, NULL, 0, 0);
26 if (s == INVALID_SOCKET) {
27 /*
28 * WSAGetLastError() values are regular BSD error codes
29 * biased by WSABASEERR.
30 * However, strerror() does not know about networking
31 * specific errors, which are values beginning at 38 or so.
32 * Therefore, we choose to leave the biased error code
33 * in errno so that _if_ someone looks up the code somewhere,
34 * then it is at least the number that are usually listed.
35 */
36 errno = WSAGetLastError();
37 return -1;
38 }
39 /* convert into a file descriptor */
40 if ((sockfd = _open_osfhandle(s, O_RDWR|O_BINARY)) < 0) {
41 closesocket(s);
42 bb_error_msg("unable to make a socket file descriptor: %s",
43 strerror(errno));
44 return -1;
45 }
46 return sockfd;
47}
48
49#undef connect
50int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
51{
52 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
53 return connect(s, sa, sz);
54}
diff --git a/win32/net/if.h b/win32/net/if.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/net/if.h
diff --git a/win32/netdb.h b/win32/netdb.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/netdb.h
diff --git a/win32/netinet/in.h b/win32/netinet/in.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/netinet/in.h
diff --git a/win32/poll.c b/win32/poll.c
new file mode 100644
index 000000000..4438305ce
--- /dev/null
+++ b/win32/poll.c
@@ -0,0 +1,606 @@
1/* Emulation for poll(2)
2 Contributed by Paolo Bonzini.
3
4 Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc.
5
6 This file is part of gnulib.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
21
22/* Tell gcc not to warn about the (nfd < 0) tests, below. */
23#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
24# pragma GCC diagnostic ignored "-Wtype-limits"
25#endif
26
27#include <malloc.h>
28
29#include <sys/types.h>
30
31/* Specification. */
32#include <sys/poll.h>
33
34#include <errno.h>
35#include <limits.h>
36#include <assert.h>
37
38#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
39# define WIN32_NATIVE
40# if defined (_MSC_VER)
41# define _WIN32_WINNT 0x0502
42# endif
43# include <winsock2.h>
44# include <windows.h>
45# include <io.h>
46# include <stdio.h>
47# include <conio.h>
48#else
49# include <sys/time.h>
50# include <sys/socket.h>
51# include <sys/select.h>
52# include <unistd.h>
53#endif
54
55#ifdef HAVE_SYS_IOCTL_H
56# include <sys/ioctl.h>
57#endif
58#ifdef HAVE_SYS_FILIO_H
59# include <sys/filio.h>
60#endif
61
62#include <time.h>
63
64#ifndef INFTIM
65# define INFTIM (-1)
66#endif
67
68/* BeOS does not have MSG_PEEK. */
69#ifndef MSG_PEEK
70# define MSG_PEEK 0
71#endif
72
73#ifdef WIN32_NATIVE
74
75#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
76
77static BOOL
78IsSocketHandle (HANDLE h)
79{
80 WSANETWORKEVENTS ev;
81
82 if (IsConsoleHandle (h))
83 return FALSE;
84
85 /* Under Wine, it seems that getsockopt returns 0 for pipes too.
86 WSAEnumNetworkEvents instead distinguishes the two correctly. */
87 ev.lNetworkEvents = 0xDEADBEEF;
88 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
89 return ev.lNetworkEvents != 0xDEADBEEF;
90}
91
92/* Declare data structures for ntdll functions. */
93typedef struct _FILE_PIPE_LOCAL_INFORMATION {
94 ULONG NamedPipeType;
95 ULONG NamedPipeConfiguration;
96 ULONG MaximumInstances;
97 ULONG CurrentInstances;
98 ULONG InboundQuota;
99 ULONG ReadDataAvailable;
100 ULONG OutboundQuota;
101 ULONG WriteQuotaAvailable;
102 ULONG NamedPipeState;
103 ULONG NamedPipeEnd;
104} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
105
106typedef struct _IO_STATUS_BLOCK
107{
108 union {
109 DWORD Status;
110 PVOID Pointer;
111 } u;
112 ULONG_PTR Information;
113} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
114
115typedef enum _FILE_INFORMATION_CLASS {
116 FilePipeLocalInformation = 24
117} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
118
119typedef DWORD (WINAPI *PNtQueryInformationFile)
120 (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
121
122# ifndef PIPE_BUF
123# define PIPE_BUF 512
124# endif
125
126/* Compute revents values for file handle H. If some events cannot happen
127 for the handle, eliminate them from *P_SOUGHT. */
128
129static int
130win32_compute_revents (HANDLE h, int *p_sought)
131{
132 int i, ret, happened;
133 INPUT_RECORD *irbuffer;
134 DWORD avail, nbuffer;
135 BOOL bRet;
136 IO_STATUS_BLOCK iosb;
137 FILE_PIPE_LOCAL_INFORMATION fpli;
138 static PNtQueryInformationFile NtQueryInformationFile;
139 static BOOL once_only;
140
141 switch (GetFileType (h))
142 {
143 case FILE_TYPE_PIPE:
144 if (!once_only)
145 {
146 NtQueryInformationFile = (PNtQueryInformationFile)
147 GetProcAddress (GetModuleHandle ("ntdll.dll"),
148 "NtQueryInformationFile");
149 once_only = TRUE;
150 }
151
152 happened = 0;
153 if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
154 {
155 if (avail)
156 happened |= *p_sought & (POLLIN | POLLRDNORM);
157 }
158 else if (GetLastError () == ERROR_BROKEN_PIPE)
159 happened |= POLLHUP;
160
161 else
162 {
163 /* It was the write-end of the pipe. Check if it is writable.
164 If NtQueryInformationFile fails, optimistically assume the pipe is
165 writable. This could happen on Win9x, where NtQueryInformationFile
166 is not available, or if we inherit a pipe that doesn't permit
167 FILE_READ_ATTRIBUTES access on the write end (I think this should
168 not happen since WinXP SP2; WINE seems fine too). Otherwise,
169 ensure that enough space is available for atomic writes. */
170 memset (&iosb, 0, sizeof (iosb));
171 memset (&fpli, 0, sizeof (fpli));
172
173 if (!NtQueryInformationFile
174 || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
175 FilePipeLocalInformation)
176 || fpli.WriteQuotaAvailable >= PIPE_BUF
177 || (fpli.OutboundQuota < PIPE_BUF &&
178 fpli.WriteQuotaAvailable == fpli.OutboundQuota))
179 happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
180 }
181 return happened;
182
183 case FILE_TYPE_CHAR:
184 ret = WaitForSingleObject (h, 0);
185 if (!IsConsoleHandle (h))
186 return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;
187
188 nbuffer = avail = 0;
189 bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
190 if (bRet)
191 {
192 /* Input buffer. */
193 *p_sought &= POLLIN | POLLRDNORM;
194 if (nbuffer == 0)
195 return POLLHUP;
196 if (!*p_sought)
197 return 0;
198
199 irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
200 bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
201 if (!bRet || avail == 0)
202 return POLLHUP;
203
204 for (i = 0; i < avail; i++)
205 if (irbuffer[i].EventType == KEY_EVENT)
206 return *p_sought;
207 return 0;
208 }
209 else
210 {
211 /* Screen buffer. */
212 *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
213 return *p_sought;
214 }
215
216 default:
217 ret = WaitForSingleObject (h, 0);
218 if (ret == WAIT_OBJECT_0)
219 return *p_sought & ~(POLLPRI | POLLRDBAND);
220
221 return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
222 }
223}
224
225/* Convert fd_sets returned by select into revents values. */
226
227static int
228win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)
229{
230 int happened = 0;
231
232 if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)
233 happened |= (POLLIN | POLLRDNORM) & sought;
234
235 else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
236 {
237 int r, error;
238
239 char data[64];
240 WSASetLastError (0);
241 r = recv (h, data, sizeof (data), MSG_PEEK);
242 error = WSAGetLastError ();
243 WSASetLastError (0);
244
245 if (r > 0 || error == WSAENOTCONN)
246 happened |= (POLLIN | POLLRDNORM) & sought;
247
248 /* Distinguish hung-up sockets from other errors. */
249 else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET
250 || error == WSAECONNABORTED || error == WSAENETRESET)
251 happened |= POLLHUP;
252
253 else
254 happened |= POLLERR;
255 }
256
257 if (lNetworkEvents & (FD_WRITE | FD_CONNECT))
258 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
259
260 if (lNetworkEvents & FD_OOB)
261 happened |= (POLLPRI | POLLRDBAND) & sought;
262
263 return happened;
264}
265
266#else /* !MinGW */
267
268/* Convert select(2) returned fd_sets into poll(2) revents values. */
269static int
270compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)
271{
272 int happened = 0;
273 if (FD_ISSET (fd, rfds))
274 {
275 int r;
276 int socket_errno;
277
278# if defined __MACH__ && defined __APPLE__
279 /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
280 for some kinds of descriptors. Detect if this descriptor is a
281 connected socket, a server socket, or something else using a
282 0-byte recv, and use ioctl(2) to detect POLLHUP. */
283 r = recv (fd, NULL, 0, MSG_PEEK);
284 socket_errno = (r < 0) ? errno : 0;
285 if (r == 0 || socket_errno == ENOTSOCK)
286 ioctl (fd, FIONREAD, &r);
287# else
288 char data[64];
289 r = recv (fd, data, sizeof (data), MSG_PEEK);
290 socket_errno = (r < 0) ? errno : 0;
291# endif
292 if (r == 0)
293 happened |= POLLHUP;
294
295 /* If the event happened on an unconnected server socket,
296 that's fine. */
297 else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))
298 happened |= (POLLIN | POLLRDNORM) & sought;
299
300 /* Distinguish hung-up sockets from other errors. */
301 else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET
302 || socket_errno == ECONNABORTED || socket_errno == ENETRESET)
303 happened |= POLLHUP;
304
305 else
306 happened |= POLLERR;
307 }
308
309 if (FD_ISSET (fd, wfds))
310 happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;
311
312 if (FD_ISSET (fd, efds))
313 happened |= (POLLPRI | POLLRDBAND) & sought;
314
315 return happened;
316}
317#endif /* !MinGW */
318
319int
320poll (struct pollfd *pfd, nfds_t nfd, int timeout)
321{
322#ifndef WIN32_NATIVE
323 fd_set rfds, wfds, efds;
324 struct timeval tv;
325 struct timeval *ptv;
326 int maxfd, rc;
327 nfds_t i;
328
329# ifdef _SC_OPEN_MAX
330 static int sc_open_max = -1;
331
332 if (nfd < 0
333 || (nfd > sc_open_max
334 && (sc_open_max != -1
335 || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))
336 {
337 errno = EINVAL;
338 return -1;
339 }
340# else /* !_SC_OPEN_MAX */
341# ifdef OPEN_MAX
342 if (nfd < 0 || nfd > OPEN_MAX)
343 {
344 errno = EINVAL;
345 return -1;
346 }
347# endif /* OPEN_MAX -- else, no check is needed */
348# endif /* !_SC_OPEN_MAX */
349
350 /* EFAULT is not necessary to implement, but let's do it in the
351 simplest case. */
352 if (!pfd)
353 {
354 errno = EFAULT;
355 return -1;
356 }
357
358 /* convert timeout number into a timeval structure */
359 if (timeout == 0)
360 {
361 ptv = &tv;
362 ptv->tv_sec = 0;
363 ptv->tv_usec = 0;
364 }
365 else if (timeout > 0)
366 {
367 ptv = &tv;
368 ptv->tv_sec = timeout / 1000;
369 ptv->tv_usec = (timeout % 1000) * 1000;
370 }
371 else if (timeout == INFTIM)
372 /* wait forever */
373 ptv = NULL;
374 else
375 {
376 errno = EINVAL;
377 return -1;
378 }
379
380 /* create fd sets and determine max fd */
381 maxfd = -1;
382 FD_ZERO (&rfds);
383 FD_ZERO (&wfds);
384 FD_ZERO (&efds);
385 for (i = 0; i < nfd; i++)
386 {
387 if (pfd[i].fd < 0)
388 continue;
389
390 if (pfd[i].events & (POLLIN | POLLRDNORM))
391 FD_SET (pfd[i].fd, &rfds);
392
393 /* see select(2): "the only exceptional condition detectable
394 is out-of-band data received on a socket", hence we push
395 POLLWRBAND events onto wfds instead of efds. */
396 if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))
397 FD_SET (pfd[i].fd, &wfds);
398 if (pfd[i].events & (POLLPRI | POLLRDBAND))
399 FD_SET (pfd[i].fd, &efds);
400 if (pfd[i].fd >= maxfd
401 && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI
402 | POLLRDNORM | POLLRDBAND
403 | POLLWRNORM | POLLWRBAND)))
404 {
405 maxfd = pfd[i].fd;
406 if (maxfd > FD_SETSIZE)
407 {
408 errno = EOVERFLOW;
409 return -1;
410 }
411 }
412 }
413
414 /* examine fd sets */
415 rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);
416 if (rc < 0)
417 return rc;
418
419 /* establish results */
420 rc = 0;
421 for (i = 0; i < nfd; i++)
422 if (pfd[i].fd < 0)
423 pfd[i].revents = 0;
424 else
425 {
426 int happened = compute_revents (pfd[i].fd, pfd[i].events,
427 &rfds, &wfds, &efds);
428 if (happened)
429 {
430 pfd[i].revents = happened;
431 rc++;
432 }
433 }
434
435 return rc;
436#else
437 static struct timeval tv0;
438 static HANDLE hEvent;
439 WSANETWORKEVENTS ev;
440 HANDLE h, handle_array[FD_SETSIZE + 2];
441 DWORD ret, wait_timeout, nhandles;
442 fd_set rfds, wfds, xfds;
443 BOOL poll_again;
444 MSG msg;
445 int rc = 0;
446 nfds_t i;
447
448 if (nfd < 0 || timeout < -1)
449 {
450 errno = EINVAL;
451 return -1;
452 }
453
454 if (!hEvent)
455 hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
456
457restart:
458 handle_array[0] = hEvent;
459 nhandles = 1;
460 FD_ZERO (&rfds);
461 FD_ZERO (&wfds);
462 FD_ZERO (&xfds);
463
464 /* Classify socket handles and create fd sets. */
465 for (i = 0; i < nfd; i++)
466 {
467 int sought = pfd[i].events;
468 pfd[i].revents = 0;
469 if (pfd[i].fd < 0)
470 continue;
471 if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND
472 | POLLPRI | POLLRDBAND)))
473 continue;
474
475 h = (HANDLE) _get_osfhandle (pfd[i].fd);
476 assert (h != NULL);
477 if (IsSocketHandle (h))
478 {
479 int requested = FD_CLOSE;
480
481 /* see above; socket handles are mapped onto select. */
482 if (sought & (POLLIN | POLLRDNORM))
483 {
484 requested |= FD_READ | FD_ACCEPT;
485 FD_SET ((SOCKET) h, &rfds);
486 }
487 if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))
488 {
489 requested |= FD_WRITE | FD_CONNECT;
490 FD_SET ((SOCKET) h, &wfds);
491 }
492 if (sought & (POLLPRI | POLLRDBAND))
493 {
494 requested |= FD_OOB;
495 FD_SET ((SOCKET) h, &xfds);
496 }
497
498 if (requested)
499 WSAEventSelect ((SOCKET) h, hEvent, requested);
500 }
501 else
502 {
503 /* Poll now. If we get an event, do not poll again. Also,
504 screen buffer handles are waitable, and they'll block until
505 a character is available. win32_compute_revents eliminates
506 bits for the "wrong" direction. */
507 pfd[i].revents = win32_compute_revents (h, &sought);
508 if (sought)
509 handle_array[nhandles++] = h;
510 if (pfd[i].revents)
511 timeout = 0;
512 }
513 }
514
515 if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)
516 {
517 /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but
518 no need to call select again. */
519 poll_again = FALSE;
520 wait_timeout = 0;
521 }
522 else
523 {
524 poll_again = TRUE;
525 if (timeout == INFTIM)
526 wait_timeout = INFINITE;
527 else
528 wait_timeout = timeout;
529 }
530
531 for (;;)
532 {
533 ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
534 wait_timeout, QS_ALLINPUT);
535
536 if (ret == WAIT_OBJECT_0 + nhandles)
537 {
538 /* new input of some other kind */
539 BOOL bRet;
540 while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
541 {
542 TranslateMessage (&msg);
543 DispatchMessage (&msg);
544 }
545 }
546 else
547 break;
548 }
549
550 if (poll_again)
551 select (0, &rfds, &wfds, &xfds, &tv0);
552
553 /* Place a sentinel at the end of the array. */
554 handle_array[nhandles] = NULL;
555 nhandles = 1;
556 for (i = 0; i < nfd; i++)
557 {
558 int happened;
559
560 if (pfd[i].fd < 0)
561 continue;
562 if (!(pfd[i].events & (POLLIN | POLLRDNORM |
563 POLLOUT | POLLWRNORM | POLLWRBAND)))
564 continue;
565
566 h = (HANDLE) _get_osfhandle (pfd[i].fd);
567 if (h != handle_array[nhandles])
568 {
569 /* It's a socket. */
570 WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
571 WSAEventSelect ((SOCKET) h, 0, 0);
572
573 /* If we're lucky, WSAEnumNetworkEvents already provided a way
574 to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
575 if (FD_ISSET ((SOCKET) h, &rfds)
576 && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))
577 ev.lNetworkEvents |= FD_READ | FD_ACCEPT;
578 if (FD_ISSET ((SOCKET) h, &wfds))
579 ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;
580 if (FD_ISSET ((SOCKET) h, &xfds))
581 ev.lNetworkEvents |= FD_OOB;
582
583 happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,
584 ev.lNetworkEvents);
585 }
586 else
587 {
588 /* Not a socket. */
589 int sought = pfd[i].events;
590 happened = win32_compute_revents (h, &sought);
591 nhandles++;
592 }
593
594 if ((pfd[i].revents |= happened) != 0)
595 rc++;
596 }
597
598 if (!rc && timeout == INFTIM)
599 {
600 SwitchToThread();
601 goto restart;
602 }
603
604 return rc;
605#endif
606}
diff --git a/win32/popen.c b/win32/popen.c
new file mode 100644
index 000000000..b75ddbcb6
--- /dev/null
+++ b/win32/popen.c
@@ -0,0 +1,220 @@
1#include <fcntl.h>
2#include "libbb.h"
3
4typedef struct {
5 PROCESS_INFORMATION piProcInfo;
6 HANDLE in[2], out[2], err[2];
7 char mode;
8 FILE *fd;
9} pipe_data;
10
11static pipe_data *pipes = NULL;
12static int num_pipes = 0;
13
14static int mingw_pipe(HANDLE *readwrite)
15{
16 SECURITY_ATTRIBUTES sa;
17
18 sa.nLength = sizeof(sa); /* Length in bytes */
19 sa.bInheritHandle = 1; /* the child must inherit these handles */
20 sa.lpSecurityDescriptor = NULL;
21
22 if ( !CreatePipe (&readwrite[0], &readwrite[1], &sa, 1 << 13) ) {
23 return -1;
24 }
25
26 return 0;
27}
28
29FILE *mingw_popen(const char *cmd, const char *mode)
30{
31 int i;
32 pipe_data *p = NULL;
33 FILE *fptr = NULL;
34 STARTUPINFO siStartInfo;
35 int success;
36 int fd;
37 int len, count;
38 char *cmd_buff = NULL;
39 const char *s;
40 char *t;
41
42 if ( cmd == NULL || *cmd == '\0' || mode == NULL ||
43 (*mode != 'r' && *mode != 'w') ) {
44 return NULL;
45 }
46
47 /* find an unused pipe structure */
48 for ( i=0; i<num_pipes; ++i ) {
49 if ( pipes[i].mode == '\0' ) {
50 p = pipes+i;
51 break;
52 }
53 }
54
55 if ( p == NULL ) {
56 /* need to extend array */
57 if ( (p=realloc(pipes, sizeof(pipe_data)*(num_pipes+10))) == NULL ) {
58 return NULL;
59 }
60
61 pipes = p;
62 for ( i=0; i<10; ++i ) {
63 memset(pipes+num_pipes+i, 0, sizeof(pipe_data));
64 }
65 p = pipes + num_pipes;
66 num_pipes += 10;
67 }
68
69 /* count double quotes */
70 count = 0;
71 for ( s=cmd; *s; ++s ) {
72 if ( *s == '"' ) {
73 ++count;
74 }
75 }
76
77 len = strlen(cmd) + 10 + count;
78 if ( (cmd_buff=malloc(len)) == NULL ) {
79 return NULL;
80 }
81
82 /* escape double quotes */
83 strcpy(cmd_buff, "sh -c \"");
84 for ( s=cmd,t=cmd_buff+strlen(cmd_buff); *s; ++s ) {
85 if ( *s == '"' ) {
86 *t++ = '\\';
87 }
88 *t++ = *s;
89 }
90 *t++ = '"';
91 *t = '\0';
92
93 p->in[0] = INVALID_HANDLE_VALUE;
94 p->in[1] = INVALID_HANDLE_VALUE;
95 p->out[0] = INVALID_HANDLE_VALUE;
96 p->out[1] = INVALID_HANDLE_VALUE;
97 p->err[0] = INVALID_HANDLE_VALUE;
98 p->err[1] = INVALID_HANDLE_VALUE;
99
100 /* Create the Pipes... */
101 if ( mingw_pipe(p->in) == -1 ||
102 mingw_pipe(p->out) == -1 ||
103 mingw_pipe(p->err) == -1) {
104 goto finito;
105 }
106
107 /* Make the parent ends of the pipes non-inheritable */
108 SetHandleInformation(p->in[1], HANDLE_FLAG_INHERIT, 0);
109 SetHandleInformation(p->out[0], HANDLE_FLAG_INHERIT, 0);
110 SetHandleInformation(p->err[0], HANDLE_FLAG_INHERIT, 0);
111
112 /* Now create the child process */
113 ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
114 siStartInfo.cb = sizeof(STARTUPINFO);
115 siStartInfo.hStdInput = p->in[0];
116 siStartInfo.hStdOutput = p->out[1];
117 siStartInfo.hStdError = p->err[1];
118 siStartInfo.dwFlags = STARTF_USESTDHANDLES;
119
120 success = CreateProcess(NULL,
121 (LPTSTR)cmd_buff, /* command line */
122 NULL, /* process security attributes */
123 NULL, /* primary thread security attributes */
124 TRUE, /* handles are inherited */
125 CREATE_NO_WINDOW, /* creation flags */
126 NULL, /* use parent's environment */
127 NULL, /* use parent's current directory */
128 &siStartInfo, /* STARTUPINFO pointer */
129 &p->piProcInfo); /* receives PROCESS_INFORMATION */
130
131 if ( !success ) {
132 goto finito;
133 }
134
135 /* Close the child ends of the pipes */
136 CloseHandle(p->in[0]); p->in[0] = INVALID_HANDLE_VALUE;
137 CloseHandle(p->out[1]); p->out[1] = INVALID_HANDLE_VALUE;
138 CloseHandle(p->err[1]); p->err[1] = INVALID_HANDLE_VALUE;
139
140 if ( *mode == 'r' ) {
141 fd = _open_osfhandle((long)p->out[0], _O_RDONLY|_O_BINARY);
142 fptr = _fdopen(fd, "rb");
143 }
144 else {
145 fd = _open_osfhandle((long)p->in[1], _O_WRONLY|_O_BINARY);
146 fptr = _fdopen(fd, "wb");
147 }
148
149finito:
150 if ( !fptr ) {
151 if ( p->in[0] != INVALID_HANDLE_VALUE ) {
152 CloseHandle(p->in[0]);
153 }
154 if ( p->in[1] != INVALID_HANDLE_VALUE ) {
155 CloseHandle(p->in[1]);
156 }
157 if ( p->out[0] != INVALID_HANDLE_VALUE ) {
158 CloseHandle(p->out[0]);
159 }
160 if ( p->out[1] != INVALID_HANDLE_VALUE ) {
161 CloseHandle(p->out[1]);
162 }
163 if ( p->err[0] != INVALID_HANDLE_VALUE ) {
164 CloseHandle(p->err[0]);
165 }
166 if ( p->err[1] != INVALID_HANDLE_VALUE ) {
167 CloseHandle(p->err[1]);
168 }
169 }
170 else {
171 p->mode = *mode;
172 }
173 free(cmd_buff);
174
175 p->fd = fptr;
176 return fptr;
177}
178
179int mingw_pclose(FILE *fd)
180{
181 int i;
182 pipe_data *p = NULL;
183 DWORD ret;
184
185 if ( fd == NULL ) {
186 return -1;
187 }
188
189 /* find struct containing fd */
190 for ( i=0; i<num_pipes; ++i ) {
191 if ( pipes[i].fd == fd ) {
192 p = pipes+i;
193 break;
194 }
195 }
196
197 if ( p == NULL ) {
198 /* no pipe data, maybe fd isn't a pipe? */
199 return -1;
200 }
201
202 fclose(fd);
203
204 CloseHandle(p->err[0]);
205 if ( p->mode == 'r' ) {
206 CloseHandle(p->in[1]);
207 }
208 else {
209 CloseHandle(p->out[0]);
210 }
211
212 ret = WaitForSingleObject(p->piProcInfo.hProcess, INFINITE);
213
214 CloseHandle(p->piProcInfo.hProcess);
215 CloseHandle(p->piProcInfo.hThread);
216
217 p->mode = '\0';
218
219 return (ret == WAIT_OBJECT_0) ? 0 : -1;
220}
diff --git a/win32/process.c b/win32/process.c
new file mode 100644
index 000000000..b95e173e1
--- /dev/null
+++ b/win32/process.c
@@ -0,0 +1,373 @@
1#include "libbb.h"
2#include <tlhelp32.h>
3
4int waitpid(pid_t pid, int *status, unsigned options)
5{
6 /* Windows does not understand parent-child */
7 if (options == 0 && pid != -1)
8 return _cwait(status, pid, 0);
9 errno = EINVAL;
10 return -1;
11}
12
13const char *
14next_path_sep(const char *path)
15{
16 static const char *from = NULL, *to;
17 static int has_semicolon;
18 int len = strlen(path);
19
20 if (!from || !(path >= from && path+len <= to)) {
21 from = path;
22 to = from+len;
23 has_semicolon = strchr(path, ';') != NULL;
24 }
25
26 /* Semicolons take precedence, it's Windows PATH */
27 if (has_semicolon)
28 return strchr(path, ';');
29 /* PATH=C:, not really a separator */
30 return strchr(has_dos_drive_prefix(path) ? path+2 : path, ':');
31}
32
33#define MAX_OPT 10
34
35static const char *
36parse_interpreter(const char *cmd, char ***opts, int *nopts)
37{
38 static char buf[100], *opt[MAX_OPT];
39 char *p, *s, *t;
40 int n, fd;
41
42 *nopts = 0;
43 *opts = opt;
44
45 /* don't even try a .exe */
46 n = strlen(cmd);
47 if (n >= 4 &&
48 (!strcasecmp(cmd+n-4, ".exe") ||
49 !strcasecmp(cmd+n-4, ".com")))
50 return NULL;
51
52 fd = open(cmd, O_RDONLY);
53 if (fd < 0)
54 return NULL;
55 n = read(fd, buf, sizeof(buf)-1);
56 close(fd);
57 if (n < 4) /* at least '#!/x' and not error */
58 return NULL;
59
60 if (buf[0] != '#' || buf[1] != '!')
61 return NULL;
62 buf[n] = '\0';
63 p = strchr(buf, '\n');
64 if (!p)
65 return NULL;
66 *p = '\0';
67
68 /* remove trailing whitespace */
69 while ( isspace(*--p) ) {
70 *p = '\0';
71 }
72
73 /* move to end of interpreter path (which may not contain spaces) */
74 for ( s=buf+2; *s && !isspace(*s); ++s ) {
75 }
76
77 n = 0;
78 if ( *s != '\0' ) {
79 /* there are options */
80 *s++ = '\0';
81
82 while ( (t=strtok(s, " \t")) && n < MAX_OPT ) {
83 s = NULL;
84 opt[n++] = t;
85 }
86 }
87
88 /* find interpreter name */
89 if (!(p = strrchr(buf+2, '/')))
90 return NULL;
91
92 *nopts = n;
93 *opts = opt;
94
95 return p+1;
96}
97
98/*
99 * See http://msdn2.microsoft.com/en-us/library/17w5ykft(vs.71).aspx
100 * (Parsing C++ Command-Line Arguments)
101 */
102static char *
103quote_arg(const char *arg)
104{
105 /* count chars to quote */
106 int len = 0, n = 0;
107 int force_quotes = 0;
108 char *q, *d;
109 const char *p = arg;
110 if (!*p) force_quotes = 1;
111 while (*p) {
112 if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'')
113 force_quotes = 1;
114 else if (*p == '"')
115 n++;
116 else if (*p == '\\') {
117 int count = 0;
118 while (*p == '\\') {
119 count++;
120 p++;
121 len++;
122 }
123 if (*p == '"')
124 n += count*2 + 1;
125 else
126 n += count;
127 continue;
128 }
129 len++;
130 p++;
131 }
132 if (!force_quotes && n == 0)
133 return (char*)arg;
134
135 /* insert \ where necessary */
136 d = q = xmalloc(len+n+3);
137 *d++ = '"';
138 while (*arg) {
139 if (*arg == '"')
140 *d++ = '\\';
141 else if (*arg == '\\') {
142 int count = 0;
143 while (*arg == '\\') {
144 count++;
145 *d++ = *arg++;
146 }
147 while (count-- > 0)
148 *d++ = '\\';
149 if (*arg == '"') {
150 *d++ = '\\';
151 }
152 }
153 *d++ = *arg++;
154 }
155 *d++ = '"';
156 *d++ = 0;
157 return q;
158}
159
160static pid_t
161spawnveq(int mode, const char *path, const char *const *argv, const char *const *env)
162{
163 char **new_argv;
164 int i, argc = 0;
165 pid_t ret;
166
167 if (!argv) {
168 const char *empty_argv[] = { path, NULL };
169 return spawnve(mode, path, empty_argv, env);
170 }
171
172
173 while (argv[argc])
174 argc++;
175
176 new_argv = malloc(sizeof(*argv)*(argc+1));
177 for (i = 0;i < argc;i++)
178 new_argv[i] = quote_arg(argv[i]);
179 new_argv[argc] = NULL;
180 ret = spawnve(mode, path, (const char *const *)new_argv, env);
181 for (i = 0;i < argc;i++)
182 if (new_argv[i] != argv[i])
183 free(new_argv[i]);
184 free(new_argv);
185 return ret;
186}
187
188pid_t
189mingw_spawn_applet(int mode,
190 const char *applet,
191 const char *const *argv,
192 const char *const *envp)
193{
194 char **env = copy_environ(envp);
195 char path[MAX_PATH+20];
196 int ret;
197
198 sprintf(path, "BUSYBOX_APPLET_NAME=%s", applet);
199 env = env_setenv(env, path);
200 ret = spawnveq(mode, get_busybox_exec_path(), argv, (const char *const *)env);
201 free_environ(env);
202 return ret;
203}
204
205static pid_t
206mingw_spawn_interpreter(int mode, const char *prog, const char *const *argv, const char *const *envp)
207{
208 int ret;
209 char **opts;
210 int nopts;
211 const char *interpr = parse_interpreter(prog, &opts, &nopts);
212 const char **new_argv;
213 int argc = 0;
214
215 if (!interpr)
216 return spawnveq(mode, prog, argv, envp);
217
218
219 while (argv[argc])
220 argc++;
221 new_argv = malloc(sizeof(*argv)*(argc+nopts+2));
222 memcpy(new_argv+1, opts, sizeof(*opts)*nopts);
223 memcpy(new_argv+nopts+2, argv+1, sizeof(*argv)*argc);
224 new_argv[nopts+1] = prog; /* pass absolute path */
225
226 if (ENABLE_FEATURE_PREFER_APPLETS && find_applet_by_name(interpr) >= 0) {
227 new_argv[0] = interpr;
228 ret = mingw_spawn_applet(mode, interpr, new_argv, envp);
229 }
230 else {
231 char *path = xstrdup(getenv("PATH"));
232 char *tmp = path;
233 char *iprog = find_execable(interpr, &tmp);
234 free(path);
235 if (!iprog) {
236 free(new_argv);
237 errno = ENOENT;
238 return -1;
239 }
240 new_argv[0] = iprog;
241 ret = spawnveq(mode, iprog, new_argv, envp);
242 free(iprog);
243 }
244
245 free(new_argv);
246 return ret;
247}
248
249pid_t
250mingw_spawn_1(int mode, const char *cmd, const char *const *argv, const char *const *envp)
251{
252 int ret;
253
254 if (ENABLE_FEATURE_PREFER_APPLETS &&
255 find_applet_by_name(cmd) >= 0)
256 return mingw_spawn_applet(mode, cmd, argv++, envp);
257 else if (is_absolute_path(cmd))
258 return mingw_spawn_interpreter(mode, cmd, argv, envp);
259 else {
260 char *tmp, *path = getenv("PATH");
261 char *prog;
262
263 if (!path) {
264 errno = ENOENT;
265 return -1;
266 }
267
268 /* exists_execable() does not return new file name */
269 tmp = path = xstrdup(path);
270 prog = find_execable(cmd, &tmp);
271 free(path);
272 if (!prog) {
273 errno = ENOENT;
274 return -1;
275 }
276 ret = mingw_spawn_interpreter(mode, prog, argv, envp);
277 free(prog);
278 }
279 return ret;
280}
281
282pid_t
283mingw_spawn(char **argv)
284{
285 return mingw_spawn_1(P_NOWAIT, argv[0], (const char *const *)(argv+1), (const char *const *)environ);
286}
287
288int
289mingw_execvp(const char *cmd, const char *const *argv)
290{
291 int ret = (int)mingw_spawn_1(P_WAIT, cmd, argv, (const char *const *)environ);
292 if (ret != -1)
293 exit(ret);
294 return ret;
295}
296
297int
298mingw_execve(const char *cmd, const char *const *argv, const char *const *envp)
299{
300 int ret;
301 int mode = P_WAIT;
302
303 if (ENABLE_FEATURE_PREFER_APPLETS &&
304 find_applet_by_name(cmd) >= 0)
305 ret = mingw_spawn_applet(mode, cmd, argv, envp);
306 /*
307 * execve(bb_busybox_exec_path, argv, envp) won't work
308 * because argv[0] will be replaced to bb_busybox_exec_path
309 * by MSVC runtime
310 */
311 else if (argv && cmd != argv[0] && cmd == bb_busybox_exec_path)
312 ret = mingw_spawn_applet(mode, argv[0], argv, envp);
313 else
314 ret = mingw_spawn_interpreter(mode, cmd, argv, envp);
315 if (ret != -1)
316 exit(ret);
317 return ret;
318}
319
320int
321mingw_execv(const char *cmd, const char *const *argv)
322{
323 return mingw_execve(cmd, argv, (const char *const *)environ);
324}
325
326/* POSIX version in libbb/procps.c */
327procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
328{
329 PROCESSENTRY32 pe;
330
331 pe.dwSize = sizeof(pe);
332 if (!sp) {
333 sp = xzalloc(sizeof(struct procps_status_t));
334 sp->snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
335 if (sp->snapshot == INVALID_HANDLE_VALUE) {
336 free(sp);
337 return NULL;
338 }
339 if (!Process32First(sp->snapshot, &pe)) {
340 CloseHandle(sp->snapshot);
341 free(sp);
342 return NULL;
343 }
344 }
345 else {
346 if (!Process32Next(sp->snapshot, &pe)) {
347 CloseHandle(sp->snapshot);
348 free(sp);
349 return NULL;
350 }
351 }
352
353 sp->pid = pe.th32ProcessID;
354 strncpy(sp->comm, pe.szExeFile, COMM_LEN);
355 return sp;
356}
357
358int kill(pid_t pid, int sig)
359{
360 HANDLE h;
361
362 if (sig != SIGTERM) {
363 bb_error_msg("kill only supports SIGTERM");
364 errno = EINVAL;
365 return -1;
366 }
367 h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
368 if (h == NULL)
369 return -1;
370 if (TerminateProcess(h, 0) == 0)
371 return -1;
372 return 0;
373}
diff --git a/win32/pwd.h b/win32/pwd.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/pwd.h
diff --git a/win32/regex.c b/win32/regex.c
new file mode 100644
index 000000000..2cca16934
--- /dev/null
+++ b/win32/regex.c
@@ -0,0 +1,4929 @@
1/* Extended regular expression matching and search library,
2 version 0.12.
3 (Implements POSIX draft P10003.2/D11.2, except for
4 internationalization features.)
5
6 Copyright (C) 1993 Free Software Foundation, Inc.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22/* AIX requires this to be the first thing in the file. */
23#if defined (_AIX) && !defined (REGEX_MALLOC)
24 #pragma alloca
25#endif
26
27#ifndef _GNU_SOURCE
28#define _GNU_SOURCE
29#endif
30
31/* We need this for `regex.h', and perhaps for the Emacs include files. */
32#include <sys/types.h>
33
34/* We used to test for `BSTRING' here, but only GCC and Emacs define
35 `BSTRING', as far as I know, and neither of them use this code. */
36#include <string.h>
37#ifndef bcmp
38#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
39#endif
40#ifndef bcopy
41#define bcopy(s, d, n) memcpy ((d), (s), (n))
42#endif
43#ifndef bzero
44#define bzero(s, n) memset ((s), 0, (n))
45#endif
46
47#include <stdlib.h>
48
49
50/* Define the syntax stuff for \<, \>, etc. */
51
52/* This must be nonzero for the wordchar and notwordchar pattern
53 commands in re_match_2. */
54#ifndef Sword
55#define Sword 1
56#endif
57
58#ifdef SYNTAX_TABLE
59
60extern char *re_syntax_table;
61
62#else /* not SYNTAX_TABLE */
63
64/* How many characters in the character set. */
65#define CHAR_SET_SIZE 256
66
67static char re_syntax_table[CHAR_SET_SIZE];
68
69static void
70init_syntax_once ()
71{
72 register int c;
73 static int done = 0;
74
75 if (done)
76 return;
77
78 bzero (re_syntax_table, sizeof re_syntax_table);
79
80 for (c = 'a'; c <= 'z'; c++)
81 re_syntax_table[c] = Sword;
82
83 for (c = 'A'; c <= 'Z'; c++)
84 re_syntax_table[c] = Sword;
85
86 for (c = '0'; c <= '9'; c++)
87 re_syntax_table[c] = Sword;
88
89 re_syntax_table['_'] = Sword;
90
91 done = 1;
92}
93
94#endif /* not SYNTAX_TABLE */
95
96#define SYNTAX(c) re_syntax_table[c]
97
98
99/* Get the interface, including the syntax bits. */
100#include "regex.h"
101
102/* isalpha etc. are used for the character classes. */
103#include <ctype.h>
104
105#ifndef isascii
106#define isascii(c) 1
107#endif
108
109#ifdef isblank
110#define ISBLANK(c) (isascii (c) && isblank (c))
111#else
112#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
113#endif
114#ifdef isgraph
115#define ISGRAPH(c) (isascii (c) && isgraph (c))
116#else
117#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c))
118#endif
119
120#define ISPRINT(c) (isascii (c) && isprint (c))
121#define ISDIGIT(c) (isascii (c) && isdigit (c))
122#define ISALNUM(c) (isascii (c) && isalnum (c))
123#define ISALPHA(c) (isascii (c) && isalpha (c))
124#define ISCNTRL(c) (isascii (c) && iscntrl (c))
125#define ISLOWER(c) (isascii (c) && islower (c))
126#define ISPUNCT(c) (isascii (c) && ispunct (c))
127#define ISSPACE(c) (isascii (c) && isspace (c))
128#define ISUPPER(c) (isascii (c) && isupper (c))
129#define ISXDIGIT(c) (isascii (c) && isxdigit (c))
130
131#ifndef NULL
132#define NULL 0
133#endif
134
135/* We remove any previous definition of `SIGN_EXTEND_CHAR',
136 since ours (we hope) works properly with all combinations of
137 machines, compilers, `char' and `unsigned char' argument types.
138 (Per Bothner suggested the basic approach.) */
139#undef SIGN_EXTEND_CHAR
140#if __STDC__
141#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
142#else /* not __STDC__ */
143/* As in Harbison and Steele. */
144#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
145#endif
146
147/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we
148 use `alloca' instead of `malloc'. This is because using malloc in
149 re_search* or re_match* could cause memory leaks when C-g is used in
150 Emacs; also, malloc is slower and causes storage fragmentation. On
151 the other hand, malloc is more portable, and easier to debug.
152
153 Because we sometimes use alloca, some routines have to be macros,
154 not functions -- `alloca'-allocated space disappears at the end of the
155 function it is called in. */
156
157#ifdef REGEX_MALLOC
158
159#define REGEX_ALLOCATE malloc
160#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
161
162#else /* not REGEX_MALLOC */
163
164/* Emacs already defines alloca, sometimes. */
165#ifndef alloca
166
167/* Make alloca work the best possible way. */
168#ifdef __GNUC__
169#define alloca __builtin_alloca
170#else /* not __GNUC__ */
171#if HAVE_ALLOCA_H
172#include <alloca.h>
173#else /* not __GNUC__ or HAVE_ALLOCA_H */
174#ifndef _AIX /* Already did AIX, up at the top. */
175char *alloca ();
176#endif /* not _AIX */
177#endif /* not HAVE_ALLOCA_H */
178#endif /* not __GNUC__ */
179
180#endif /* not alloca */
181
182#define REGEX_ALLOCATE alloca
183
184/* Assumes a `char *destination' variable. */
185#define REGEX_REALLOCATE(source, osize, nsize) \
186 (destination = (char *) alloca (nsize), \
187 bcopy (source, destination, osize), \
188 destination)
189
190#endif /* not REGEX_MALLOC */
191
192
193/* True if `size1' is non-NULL and PTR is pointing anywhere inside
194 `string1' or just past its end. This works if PTR is NULL, which is
195 a good thing. */
196#define FIRST_STRING_P(ptr) \
197 (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
198
199/* (Re)Allocate N items of type T using malloc, or fail. */
200#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
201#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
202#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
203
204#define BYTEWIDTH 8 /* In bits. */
205
206#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
207
208#define MAX(a, b) ((a) > (b) ? (a) : (b))
209#define MIN(a, b) ((a) < (b) ? (a) : (b))
210
211typedef char boolean;
212#define false 0
213#define true 1
214
215/* These are the command codes that appear in compiled regular
216 expressions. Some opcodes are followed by argument bytes. A
217 command code can specify any interpretation whatsoever for its
218 arguments. Zero bytes may appear in the compiled regular expression.
219
220 The value of `exactn' is needed in search.c (search_buffer) in Emacs.
221 So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of
222 `exactn' we use here must also be 1. */
223
224typedef enum
225{
226 no_op = 0,
227
228 /* Followed by one byte giving n, then by n literal bytes. */
229 exactn = 1,
230
231 /* Matches any (more or less) character. */
232 anychar,
233
234 /* Matches any one char belonging to specified set. First
235 following byte is number of bitmap bytes. Then come bytes
236 for a bitmap saying which chars are in. Bits in each byte
237 are ordered low-bit-first. A character is in the set if its
238 bit is 1. A character too large to have a bit in the map is
239 automatically not in the set. */
240 charset,
241
242 /* Same parameters as charset, but match any character that is
243 not one of those specified. */
244 charset_not,
245
246 /* Start remembering the text that is matched, for storing in a
247 register. Followed by one byte with the register number, in
248 the range 0 to one less than the pattern buffer's re_nsub
249 field. Then followed by one byte with the number of groups
250 inner to this one. (This last has to be part of the
251 start_memory only because we need it in the on_failure_jump
252 of re_match_2.) */
253 start_memory,
254
255 /* Stop remembering the text that is matched and store it in a
256 memory register. Followed by one byte with the register
257 number, in the range 0 to one less than `re_nsub' in the
258 pattern buffer, and one byte with the number of inner groups,
259 just like `start_memory'. (We need the number of inner
260 groups here because we don't have any easy way of finding the
261 corresponding start_memory when we're at a stop_memory.) */
262 stop_memory,
263
264 /* Match a duplicate of something remembered. Followed by one
265 byte containing the register number. */
266 duplicate,
267
268 /* Fail unless at beginning of line. */
269 begline,
270
271 /* Fail unless at end of line. */
272 endline,
273
274 /* Succeeds if at beginning of buffer (if emacs) or at beginning
275 of string to be matched (if not). */
276 begbuf,
277
278 /* Analogously, for end of buffer/string. */
279 endbuf,
280
281 /* Followed by two byte relative address to which to jump. */
282 jump,
283
284 /* Same as jump, but marks the end of an alternative. */
285 jump_past_alt,
286
287 /* Followed by two-byte relative address of place to resume at
288 in case of failure. */
289 on_failure_jump,
290
291 /* Like on_failure_jump, but pushes a placeholder instead of the
292 current string position when executed. */
293 on_failure_keep_string_jump,
294
295 /* Throw away latest failure point and then jump to following
296 two-byte relative address. */
297 pop_failure_jump,
298
299 /* Change to pop_failure_jump if know won't have to backtrack to
300 match; otherwise change to jump. This is used to jump
301 back to the beginning of a repeat. If what follows this jump
302 clearly won't match what the repeat does, such that we can be
303 sure that there is no use backtracking out of repetitions
304 already matched, then we change it to a pop_failure_jump.
305 Followed by two-byte address. */
306 maybe_pop_jump,
307
308 /* Jump to following two-byte address, and push a dummy failure
309 point. This failure point will be thrown away if an attempt
310 is made to use it for a failure. A `+' construct makes this
311 before the first repeat. Also used as an intermediary kind
312 of jump when compiling an alternative. */
313 dummy_failure_jump,
314
315 /* Push a dummy failure point and continue. Used at the end of
316 alternatives. */
317 push_dummy_failure,
318
319 /* Followed by two-byte relative address and two-byte number n.
320 After matching N times, jump to the address upon failure. */
321 succeed_n,
322
323 /* Followed by two-byte relative address, and two-byte number n.
324 Jump to the address N times, then fail. */
325 jump_n,
326
327 /* Set the following two-byte relative address to the
328 subsequent two-byte number. The address *includes* the two
329 bytes of number. */
330 set_number_at,
331
332 wordchar, /* Matches any word-constituent character. */
333 notwordchar, /* Matches any char that is not a word-constituent. */
334
335 wordbeg, /* Succeeds if at word beginning. */
336 wordend, /* Succeeds if at word end. */
337
338 wordbound, /* Succeeds if at a word boundary. */
339 notwordbound /* Succeeds if not at a word boundary. */
340
341#ifdef emacs
342 ,before_dot, /* Succeeds if before point. */
343 at_dot, /* Succeeds if at point. */
344 after_dot, /* Succeeds if after point. */
345
346 /* Matches any character whose syntax is specified. Followed by
347 a byte which contains a syntax code, e.g., Sword. */
348 syntaxspec,
349
350 /* Matches any character whose syntax is not that specified. */
351 notsyntaxspec
352#endif /* emacs */
353} re_opcode_t;
354
355/* Common operations on the compiled pattern. */
356
357/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
358
359#define STORE_NUMBER(destination, number) \
360 do { \
361 (destination)[0] = (number) & 0377; \
362 (destination)[1] = (number) >> 8; \
363 } while (0)
364
365/* Same as STORE_NUMBER, except increment DESTINATION to
366 the byte after where the number is stored. Therefore, DESTINATION
367 must be an lvalue. */
368
369#define STORE_NUMBER_AND_INCR(destination, number) \
370 do { \
371 STORE_NUMBER (destination, number); \
372 (destination) += 2; \
373 } while (0)
374
375/* Put into DESTINATION a number stored in two contiguous bytes starting
376 at SOURCE. */
377
378#define EXTRACT_NUMBER(destination, source) \
379 do { \
380 (destination) = *(source) & 0377; \
381 (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \
382 } while (0)
383
384#ifdef DEBUG
385static void
386extract_number (dest, source)
387 int *dest;
388 unsigned char *source;
389{
390 int temp = SIGN_EXTEND_CHAR (*(source + 1));
391 *dest = *source & 0377;
392 *dest += temp << 8;
393}
394
395#ifndef EXTRACT_MACROS /* To debug the macros. */
396#undef EXTRACT_NUMBER
397#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
398#endif /* not EXTRACT_MACROS */
399
400#endif /* DEBUG */
401
402/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
403 SOURCE must be an lvalue. */
404
405#define EXTRACT_NUMBER_AND_INCR(destination, source) \
406 do { \
407 EXTRACT_NUMBER (destination, source); \
408 (source) += 2; \
409 } while (0)
410
411#ifdef DEBUG
412static void
413extract_number_and_incr (destination, source)
414 int *destination;
415 unsigned char **source;
416{
417 extract_number (destination, *source);
418 *source += 2;
419}
420
421#ifndef EXTRACT_MACROS
422#undef EXTRACT_NUMBER_AND_INCR
423#define EXTRACT_NUMBER_AND_INCR(dest, src) \
424 extract_number_and_incr (&dest, &src)
425#endif /* not EXTRACT_MACROS */
426
427#endif /* DEBUG */
428
429/* If DEBUG is defined, Regex prints many voluminous messages about what
430 it is doing (if the variable `debug' is nonzero). If linked with the
431 main program in `iregex.c', you can enter patterns and strings
432 interactively. And if linked with the main program in `main.c' and
433 the other test files, you can run the already-written tests. */
434
435#ifdef DEBUG
436
437/* We use standard I/O for debugging. */
438#include <stdio.h>
439
440/* It is useful to test things that ``must'' be true when debugging. */
441#include <assert.h>
442
443static int debug = 0;
444
445#define DEBUG_STATEMENT(e) e
446#define DEBUG_PRINT1(x) if (debug) printf (x)
447#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
448#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
449#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
450#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
451 if (debug) print_partial_compiled_pattern (s, e)
452#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
453 if (debug) print_double_string (w, s1, sz1, s2, sz2)
454
455
456extern void printchar ();
457
458/* Print the fastmap in human-readable form. */
459
460void
461print_fastmap (fastmap)
462 char *fastmap;
463{
464 unsigned was_a_range = 0;
465 unsigned i = 0;
466
467 while (i < (1 << BYTEWIDTH))
468 {
469 if (fastmap[i++])
470 {
471 was_a_range = 0;
472 printchar (i - 1);
473 while (i < (1 << BYTEWIDTH) && fastmap[i])
474 {
475 was_a_range = 1;
476 i++;
477 }
478 if (was_a_range)
479 {
480 printf ("-");
481 printchar (i - 1);
482 }
483 }
484 }
485 putchar ('\n');
486}
487
488
489/* Print a compiled pattern string in human-readable form, starting at
490 the START pointer into it and ending just before the pointer END. */
491
492void
493print_partial_compiled_pattern (start, end)
494 unsigned char *start;
495 unsigned char *end;
496{
497 int mcnt, mcnt2;
498 unsigned char *p = start;
499 unsigned char *pend = end;
500
501 if (start == NULL)
502 {
503 printf ("(null)\n");
504 return;
505 }
506
507 /* Loop over pattern commands. */
508 while (p < pend)
509 {
510 switch ((re_opcode_t) *p++)
511 {
512 case no_op:
513 printf ("/no_op");
514 break;
515
516 case exactn:
517 mcnt = *p++;
518 printf ("/exactn/%d", mcnt);
519 do
520 {
521 putchar ('/');
522 printchar (*p++);
523 }
524 while (--mcnt);
525 break;
526
527 case start_memory:
528 mcnt = *p++;
529 printf ("/start_memory/%d/%d", mcnt, *p++);
530 break;
531
532 case stop_memory:
533 mcnt = *p++;
534 printf ("/stop_memory/%d/%d", mcnt, *p++);
535 break;
536
537 case duplicate:
538 printf ("/duplicate/%d", *p++);
539 break;
540
541 case anychar:
542 printf ("/anychar");
543 break;
544
545 case charset:
546 case charset_not:
547 {
548 register int c;
549
550 printf ("/charset%s",
551 (re_opcode_t) *(p - 1) == charset_not ? "_not" : "");
552
553 assert (p + *p < pend);
554
555 for (c = 0; c < *p; c++)
556 {
557 unsigned bit;
558 unsigned char map_byte = p[1 + c];
559
560 putchar ('/');
561
562 for (bit = 0; bit < BYTEWIDTH; bit++)
563 if (map_byte & (1 << bit))
564 printchar (c * BYTEWIDTH + bit);
565 }
566 p += 1 + *p;
567 break;
568 }
569
570 case begline:
571 printf ("/begline");
572 break;
573
574 case endline:
575 printf ("/endline");
576 break;
577
578 case on_failure_jump:
579 extract_number_and_incr (&mcnt, &p);
580 printf ("/on_failure_jump/0/%d", mcnt);
581 break;
582
583 case on_failure_keep_string_jump:
584 extract_number_and_incr (&mcnt, &p);
585 printf ("/on_failure_keep_string_jump/0/%d", mcnt);
586 break;
587
588 case dummy_failure_jump:
589 extract_number_and_incr (&mcnt, &p);
590 printf ("/dummy_failure_jump/0/%d", mcnt);
591 break;
592
593 case push_dummy_failure:
594 printf ("/push_dummy_failure");
595 break;
596
597 case maybe_pop_jump:
598 extract_number_and_incr (&mcnt, &p);
599 printf ("/maybe_pop_jump/0/%d", mcnt);
600 break;
601
602 case pop_failure_jump:
603 extract_number_and_incr (&mcnt, &p);
604 printf ("/pop_failure_jump/0/%d", mcnt);
605 break;
606
607 case jump_past_alt:
608 extract_number_and_incr (&mcnt, &p);
609 printf ("/jump_past_alt/0/%d", mcnt);
610 break;
611
612 case jump:
613 extract_number_and_incr (&mcnt, &p);
614 printf ("/jump/0/%d", mcnt);
615 break;
616
617 case succeed_n:
618 extract_number_and_incr (&mcnt, &p);
619 extract_number_and_incr (&mcnt2, &p);
620 printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2);
621 break;
622
623 case jump_n:
624 extract_number_and_incr (&mcnt, &p);
625 extract_number_and_incr (&mcnt2, &p);
626 printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2);
627 break;
628
629 case set_number_at:
630 extract_number_and_incr (&mcnt, &p);
631 extract_number_and_incr (&mcnt2, &p);
632 printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2);
633 break;
634
635 case wordbound:
636 printf ("/wordbound");
637 break;
638
639 case notwordbound:
640 printf ("/notwordbound");
641 break;
642
643 case wordbeg:
644 printf ("/wordbeg");
645 break;
646
647 case wordend:
648 printf ("/wordend");
649
650#ifdef emacs
651 case before_dot:
652 printf ("/before_dot");
653 break;
654
655 case at_dot:
656 printf ("/at_dot");
657 break;
658
659 case after_dot:
660 printf ("/after_dot");
661 break;
662
663 case syntaxspec:
664 printf ("/syntaxspec");
665 mcnt = *p++;
666 printf ("/%d", mcnt);
667 break;
668
669 case notsyntaxspec:
670 printf ("/notsyntaxspec");
671 mcnt = *p++;
672 printf ("/%d", mcnt);
673 break;
674#endif /* emacs */
675
676 case wordchar:
677 printf ("/wordchar");
678 break;
679
680 case notwordchar:
681 printf ("/notwordchar");
682 break;
683
684 case begbuf:
685 printf ("/begbuf");
686 break;
687
688 case endbuf:
689 printf ("/endbuf");
690 break;
691
692 default:
693 printf ("?%d", *(p-1));
694 }
695 }
696 printf ("/\n");
697}
698
699
700void
701print_compiled_pattern (bufp)
702 struct re_pattern_buffer *bufp;
703{
704 unsigned char *buffer = bufp->buffer;
705
706 print_partial_compiled_pattern (buffer, buffer + bufp->used);
707 printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated);
708
709 if (bufp->fastmap_accurate && bufp->fastmap)
710 {
711 printf ("fastmap: ");
712 print_fastmap (bufp->fastmap);
713 }
714
715 printf ("re_nsub: %d\t", bufp->re_nsub);
716 printf ("regs_alloc: %d\t", bufp->regs_allocated);
717 printf ("can_be_null: %d\t", bufp->can_be_null);
718 printf ("newline_anchor: %d\n", bufp->newline_anchor);
719 printf ("no_sub: %d\t", bufp->no_sub);
720 printf ("not_bol: %d\t", bufp->not_bol);
721 printf ("not_eol: %d\t", bufp->not_eol);
722 printf ("syntax: %d\n", bufp->syntax);
723 /* Perhaps we should print the translate table? */
724}
725
726
727void
728print_double_string (where, string1, size1, string2, size2)
729 const char *where;
730 const char *string1;
731 const char *string2;
732 int size1;
733 int size2;
734{
735 unsigned this_char;
736
737 if (where == NULL)
738 printf ("(null)");
739 else
740 {
741 if (FIRST_STRING_P (where))
742 {
743 for (this_char = where - string1; this_char < size1; this_char++)
744 printchar (string1[this_char]);
745
746 where = string2;
747 }
748
749 for (this_char = where - string2; this_char < size2; this_char++)
750 printchar (string2[this_char]);
751 }
752}
753
754#else /* not DEBUG */
755
756#undef assert
757#define assert(e)
758
759#define DEBUG_STATEMENT(e)
760#define DEBUG_PRINT1(x)
761#define DEBUG_PRINT2(x1, x2)
762#define DEBUG_PRINT3(x1, x2, x3)
763#define DEBUG_PRINT4(x1, x2, x3, x4)
764#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
765#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
766
767#endif /* not DEBUG */
768
769/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can
770 also be assigned to arbitrarily: each pattern buffer stores its own
771 syntax, so it can be changed between regex compilations. */
772reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
773
774
775/* Specify the precise syntax of regexps for compilation. This provides
776 for compatibility for various utilities which historically have
777 different, incompatible syntaxes.
778
779 The argument SYNTAX is a bit mask comprised of the various bits
780 defined in regex.h. We return the old syntax. */
781
782reg_syntax_t
783re_set_syntax (syntax)
784 reg_syntax_t syntax;
785{
786 reg_syntax_t ret = re_syntax_options;
787
788 re_syntax_options = syntax;
789 return ret;
790}
791
792/* This table gives an error message for each of the error codes listed
793 in regex.h. Obviously the order here has to be same as there. */
794
795static const char *re_error_msg[] =
796 { NULL, /* REG_NOERROR */
797 "No match", /* REG_NOMATCH */
798 "Invalid regular expression", /* REG_BADPAT */
799 "Invalid collation character", /* REG_ECOLLATE */
800 "Invalid character class name", /* REG_ECTYPE */
801 "Trailing backslash", /* REG_EESCAPE */
802 "Invalid back reference", /* REG_ESUBREG */
803 "Unmatched [ or [^", /* REG_EBRACK */
804 "Unmatched ( or \\(", /* REG_EPAREN */
805 "Unmatched \\{", /* REG_EBRACE */
806 "Invalid content of \\{\\}", /* REG_BADBR */
807 "Invalid range end", /* REG_ERANGE */
808 "Memory exhausted", /* REG_ESPACE */
809 "Invalid preceding regular expression", /* REG_BADRPT */
810 "Premature end of regular expression", /* REG_EEND */
811 "Regular expression too big", /* REG_ESIZE */
812 "Unmatched ) or \\)", /* REG_ERPAREN */
813 };
814
815/* Subroutine declarations and macros for regex_compile. */
816
817static void store_op1 (), store_op2 ();
818static void insert_op1 (), insert_op2 ();
819static boolean at_begline_loc_p (), at_endline_loc_p ();
820static boolean group_in_compile_stack ();
821static reg_errcode_t compile_range ();
822
823/* Fetch the next character in the uncompiled pattern---translating it
824 if necessary. Also cast from a signed character in the constant
825 string passed to us by the user to an unsigned char that we can use
826 as an array index (in, e.g., `translate'). */
827#define PATFETCH(c) \
828 do {if (p == pend) return REG_EEND; \
829 c = (unsigned char) *p++; \
830 if (translate) c = translate[c]; \
831 } while (0)
832
833/* Fetch the next character in the uncompiled pattern, with no
834 translation. */
835#define PATFETCH_RAW(c) \
836 do {if (p == pend) return REG_EEND; \
837 c = (unsigned char) *p++; \
838 } while (0)
839
840/* Go backwards one character in the pattern. */
841#define PATUNFETCH p--
842
843
844/* If `translate' is non-null, return translate[D], else just D. We
845 cast the subscript to translate because some data is declared as
846 `char *', to avoid warnings when a string constant is passed. But
847 when we use a character as a subscript we must make it unsigned. */
848#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d))
849
850
851/* Macros for outputting the compiled pattern into `buffer'. */
852
853/* If the buffer isn't allocated when it comes in, use this. */
854#define INIT_BUF_SIZE 32
855
856/* Make sure we have at least N more bytes of space in buffer. */
857#define GET_BUFFER_SPACE(n) \
858 while (b - bufp->buffer + (n) > bufp->allocated) \
859 EXTEND_BUFFER ()
860
861/* Make sure we have one more byte of buffer space and then add C to it. */
862#define BUF_PUSH(c) \
863 do { \
864 GET_BUFFER_SPACE (1); \
865 *b++ = (unsigned char) (c); \
866 } while (0)
867
868
869/* Ensure we have two more bytes of buffer space and then append C1 and C2. */
870#define BUF_PUSH_2(c1, c2) \
871 do { \
872 GET_BUFFER_SPACE (2); \
873 *b++ = (unsigned char) (c1); \
874 *b++ = (unsigned char) (c2); \
875 } while (0)
876
877
878/* As with BUF_PUSH_2, except for three bytes. */
879#define BUF_PUSH_3(c1, c2, c3) \
880 do { \
881 GET_BUFFER_SPACE (3); \
882 *b++ = (unsigned char) (c1); \
883 *b++ = (unsigned char) (c2); \
884 *b++ = (unsigned char) (c3); \
885 } while (0)
886
887
888/* Store a jump with opcode OP at LOC to location TO. We store a
889 relative address offset by the three bytes the jump itself occupies. */
890#define STORE_JUMP(op, loc, to) \
891 store_op1 (op, loc, (to) - (loc) - 3)
892
893/* Likewise, for a two-argument jump. */
894#define STORE_JUMP2(op, loc, to, arg) \
895 store_op2 (op, loc, (to) - (loc) - 3, arg)
896
897/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */
898#define INSERT_JUMP(op, loc, to) \
899 insert_op1 (op, loc, (to) - (loc) - 3, b)
900
901/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */
902#define INSERT_JUMP2(op, loc, to, arg) \
903 insert_op2 (op, loc, (to) - (loc) - 3, arg, b)
904
905
906/* This is not an arbitrary limit: the arguments which represent offsets
907 into the pattern are two bytes long. So if 2^16 bytes turns out to
908 be too small, many things would have to change. */
909#define MAX_BUF_SIZE (1L << 16)
910
911
912/* Extend the buffer by twice its current size via realloc and
913 reset the pointers that pointed into the old block to point to the
914 correct places in the new one. If extending the buffer results in it
915 being larger than MAX_BUF_SIZE, then flag memory exhausted. */
916#define EXTEND_BUFFER() \
917 do { \
918 unsigned char *old_buffer = bufp->buffer; \
919 if (bufp->allocated == MAX_BUF_SIZE) \
920 return REG_ESIZE; \
921 bufp->allocated <<= 1; \
922 if (bufp->allocated > MAX_BUF_SIZE) \
923 bufp->allocated = MAX_BUF_SIZE; \
924 bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
925 if (bufp->buffer == NULL) \
926 return REG_ESPACE; \
927 /* If the buffer moved, move all the pointers into it. */ \
928 if (old_buffer != bufp->buffer) \
929 { \
930 b = (b - old_buffer) + bufp->buffer; \
931 begalt = (begalt - old_buffer) + bufp->buffer; \
932 if (fixup_alt_jump) \
933 fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
934 if (laststart) \
935 laststart = (laststart - old_buffer) + bufp->buffer; \
936 if (pending_exact) \
937 pending_exact = (pending_exact - old_buffer) + bufp->buffer; \
938 } \
939 } while (0)
940
941
942/* Since we have one byte reserved for the register number argument to
943 {start,stop}_memory, the maximum number of groups we can report
944 things about is what fits in that byte. */
945#define MAX_REGNUM 255
946
947/* But patterns can have more than `MAX_REGNUM' registers. We just
948 ignore the excess. */
949typedef unsigned regnum_t;
950
951
952/* Macros for the compile stack. */
953
954/* Since offsets can go either forwards or backwards, this type needs to
955 be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */
956typedef int pattern_offset_t;
957
958typedef struct
959{
960 pattern_offset_t begalt_offset;
961 pattern_offset_t fixup_alt_jump;
962 pattern_offset_t inner_group_offset;
963 pattern_offset_t laststart_offset;
964 regnum_t regnum;
965} compile_stack_elt_t;
966
967
968typedef struct
969{
970 compile_stack_elt_t *stack;
971 unsigned size;
972 unsigned avail; /* Offset of next open position. */
973} compile_stack_type;
974
975
976#define INIT_COMPILE_STACK_SIZE 32
977
978#define COMPILE_STACK_EMPTY (compile_stack.avail == 0)
979#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size)
980
981/* The next available element. */
982#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
983
984
985/* Set the bit for character C in a list. */
986#define SET_LIST_BIT(c) \
987 (b[((unsigned char) (c)) / BYTEWIDTH] \
988 |= 1 << (((unsigned char) c) % BYTEWIDTH))
989
990
991/* Get the next unsigned number in the uncompiled pattern. */
992#define GET_UNSIGNED_NUMBER(num) \
993 { if (p != pend) \
994 { \
995 PATFETCH (c); \
996 while (ISDIGIT (c)) \
997 { \
998 if (num < 0) \
999 num = 0; \
1000 num = num * 10 + c - '0'; \
1001 if (p == pend) \
1002 break; \
1003 PATFETCH (c); \
1004 } \
1005 } \
1006 }
1007
1008#define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
1009
1010#define IS_CHAR_CLASS(string) \
1011 (STREQ (string, "alpha") || STREQ (string, "upper") \
1012 || STREQ (string, "lower") || STREQ (string, "digit") \
1013 || STREQ (string, "alnum") || STREQ (string, "xdigit") \
1014 || STREQ (string, "space") || STREQ (string, "print") \
1015 || STREQ (string, "punct") || STREQ (string, "graph") \
1016 || STREQ (string, "cntrl") || STREQ (string, "blank"))
1017
1018/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
1019 Returns one of error codes defined in `regex.h', or zero for success.
1020
1021 Assumes the `allocated' (and perhaps `buffer') and `translate'
1022 fields are set in BUFP on entry.
1023
1024 If it succeeds, results are put in BUFP (if it returns an error, the
1025 contents of BUFP are undefined):
1026 `buffer' is the compiled pattern;
1027 `syntax' is set to SYNTAX;
1028 `used' is set to the length of the compiled pattern;
1029 `fastmap_accurate' is zero;
1030 `re_nsub' is the number of subexpressions in PATTERN;
1031 `not_bol' and `not_eol' are zero;
1032
1033 The `fastmap' and `newline_anchor' fields are neither
1034 examined nor set. */
1035
1036static reg_errcode_t
1037regex_compile (pattern, size, syntax, bufp)
1038 const char *pattern;
1039 int size;
1040 reg_syntax_t syntax;
1041 struct re_pattern_buffer *bufp;
1042{
1043 /* We fetch characters from PATTERN here. Even though PATTERN is
1044 `char *' (i.e., signed), we declare these variables as unsigned, so
1045 they can be reliably used as array indices. */
1046 register unsigned char c, c1;
1047
1048 /* A random tempory spot in PATTERN. */
1049 const char *p1;
1050
1051 /* Points to the end of the buffer, where we should append. */
1052 register unsigned char *b;
1053
1054 /* Keeps track of unclosed groups. */
1055 compile_stack_type compile_stack;
1056
1057 /* Points to the current (ending) position in the pattern. */
1058 const char *p = pattern;
1059 const char *pend = pattern + size;
1060
1061 /* How to translate the characters in the pattern. */
1062 char *translate = bufp->translate;
1063
1064 /* Address of the count-byte of the most recently inserted `exactn'
1065 command. This makes it possible to tell if a new exact-match
1066 character can be added to that command or if the character requires
1067 a new `exactn' command. */
1068 unsigned char *pending_exact = 0;
1069
1070 /* Address of start of the most recently finished expression.
1071 This tells, e.g., postfix * where to find the start of its
1072 operand. Reset at the beginning of groups and alternatives. */
1073 unsigned char *laststart = 0;
1074
1075 /* Address of beginning of regexp, or inside of last group. */
1076 unsigned char *begalt;
1077
1078 /* Place in the uncompiled pattern (i.e., the {) to
1079 which to go back if the interval is invalid. */
1080 const char *beg_interval;
1081
1082 /* Address of the place where a forward jump should go to the end of
1083 the containing expression. Each alternative of an `or' -- except the
1084 last -- ends with a forward jump of this sort. */
1085 unsigned char *fixup_alt_jump = 0;
1086
1087 /* Counts open-groups as they are encountered. Remembered for the
1088 matching close-group on the compile stack, so the same register
1089 number is put in the stop_memory as the start_memory. */
1090 regnum_t regnum = 0;
1091
1092#ifdef DEBUG
1093 DEBUG_PRINT1 ("\nCompiling pattern: ");
1094 if (debug)
1095 {
1096 unsigned debug_count;
1097
1098 for (debug_count = 0; debug_count < size; debug_count++)
1099 printchar (pattern[debug_count]);
1100 putchar ('\n');
1101 }
1102#endif /* DEBUG */
1103
1104 /* Initialize the compile stack. */
1105 compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
1106 if (compile_stack.stack == NULL)
1107 return REG_ESPACE;
1108
1109 compile_stack.size = INIT_COMPILE_STACK_SIZE;
1110 compile_stack.avail = 0;
1111
1112 /* Initialize the pattern buffer. */
1113 bufp->syntax = syntax;
1114 bufp->fastmap_accurate = 0;
1115 bufp->not_bol = bufp->not_eol = 0;
1116
1117 /* Set `used' to zero, so that if we return an error, the pattern
1118 printer (for debugging) will think there's no pattern. We reset it
1119 at the end. */
1120 bufp->used = 0;
1121
1122 /* Always count groups, whether or not bufp->no_sub is set. */
1123 bufp->re_nsub = 0;
1124
1125#if !defined (emacs) && !defined (SYNTAX_TABLE)
1126 /* Initialize the syntax table. */
1127 init_syntax_once ();
1128#endif
1129
1130 if (bufp->allocated == 0)
1131 {
1132 if (bufp->buffer)
1133 { /* If zero allocated, but buffer is non-null, try to realloc
1134 enough space. This loses if buffer's address is bogus, but
1135 that is the user's responsibility. */
1136 RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
1137 }
1138 else
1139 { /* Caller did not allocate a buffer. Do it for them. */
1140 bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
1141 }
1142 if (!bufp->buffer) return REG_ESPACE;
1143
1144 bufp->allocated = INIT_BUF_SIZE;
1145 }
1146
1147 begalt = b = bufp->buffer;
1148
1149 /* Loop through the uncompiled pattern until we're at the end. */
1150 while (p != pend)
1151 {
1152 PATFETCH (c);
1153
1154 switch (c)
1155 {
1156 case '^':
1157 {
1158 if ( /* If at start of pattern, it's an operator. */
1159 p == pattern + 1
1160 /* If context independent, it's an operator. */
1161 || syntax & RE_CONTEXT_INDEP_ANCHORS
1162 /* Otherwise, depends on what's come before. */
1163 || at_begline_loc_p (pattern, p, syntax))
1164 BUF_PUSH (begline);
1165 else
1166 goto normal_char;
1167 }
1168 break;
1169
1170
1171 case '$':
1172 {
1173 if ( /* If at end of pattern, it's an operator. */
1174 p == pend
1175 /* If context independent, it's an operator. */
1176 || syntax & RE_CONTEXT_INDEP_ANCHORS
1177 /* Otherwise, depends on what's next. */
1178 || at_endline_loc_p (p, pend, syntax))
1179 BUF_PUSH (endline);
1180 else
1181 goto normal_char;
1182 }
1183 break;
1184
1185
1186 case '+':
1187 case '?':
1188 if ((syntax & RE_BK_PLUS_QM)
1189 || (syntax & RE_LIMITED_OPS))
1190 goto normal_char;
1191 handle_plus:
1192 case '*':
1193 /* If there is no previous pattern... */
1194 if (!laststart)
1195 {
1196 if (syntax & RE_CONTEXT_INVALID_OPS)
1197 return REG_BADRPT;
1198 else if (!(syntax & RE_CONTEXT_INDEP_OPS))
1199 goto normal_char;
1200 }
1201
1202 {
1203 /* Are we optimizing this jump? */
1204 boolean keep_string_p = false;
1205
1206 /* 1 means zero (many) matches is allowed. */
1207 char zero_times_ok = 0, many_times_ok = 0;
1208
1209 /* If there is a sequence of repetition chars, collapse it
1210 down to just one (the right one). We can't combine
1211 interval operators with these because of, e.g., `a{2}*',
1212 which should only match an even number of `a's. */
1213
1214 for (;;)
1215 {
1216 zero_times_ok |= c != '+';
1217 many_times_ok |= c != '?';
1218
1219 if (p == pend)
1220 break;
1221
1222 PATFETCH (c);
1223
1224 if (c == '*'
1225 || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
1226 ;
1227
1228 else if (syntax & RE_BK_PLUS_QM && c == '\\')
1229 {
1230 if (p == pend) return REG_EESCAPE;
1231
1232 PATFETCH (c1);
1233 if (!(c1 == '+' || c1 == '?'))
1234 {
1235 PATUNFETCH;
1236 PATUNFETCH;
1237 break;
1238 }
1239
1240 c = c1;
1241 }
1242 else
1243 {
1244 PATUNFETCH;
1245 break;
1246 }
1247
1248 /* If we get here, we found another repeat character. */
1249 }
1250
1251 /* Star, etc. applied to an empty pattern is equivalent
1252 to an empty pattern. */
1253 if (!laststart)
1254 break;
1255
1256 /* Now we know whether or not zero matches is allowed
1257 and also whether or not two or more matches is allowed. */
1258 if (many_times_ok)
1259 { /* More than one repetition is allowed, so put in at the
1260 end a backward relative jump from `b' to before the next
1261 jump we're going to put in below (which jumps from
1262 laststart to after this jump).
1263
1264 But if we are at the `*' in the exact sequence `.*\n',
1265 insert an unconditional jump backwards to the .,
1266 instead of the beginning of the loop. This way we only
1267 push a failure point once, instead of every time
1268 through the loop. */
1269 assert (p - 1 > pattern);
1270
1271 /* Allocate the space for the jump. */
1272 GET_BUFFER_SPACE (3);
1273
1274 /* We know we are not at the first character of the pattern,
1275 because laststart was nonzero. And we've already
1276 incremented `p', by the way, to be the character after
1277 the `*'. Do we have to do something analogous here
1278 for null bytes, because of RE_DOT_NOT_NULL? */
1279 if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
1280 && zero_times_ok
1281 && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
1282 && !(syntax & RE_DOT_NEWLINE))
1283 { /* We have .*\n. */
1284 STORE_JUMP (jump, b, laststart);
1285 keep_string_p = true;
1286 }
1287 else
1288 /* Anything else. */
1289 STORE_JUMP (maybe_pop_jump, b, laststart - 3);
1290
1291 /* We've added more stuff to the buffer. */
1292 b += 3;
1293 }
1294
1295 /* On failure, jump from laststart to b + 3, which will be the
1296 end of the buffer after this jump is inserted. */
1297 GET_BUFFER_SPACE (3);
1298 INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
1299 : on_failure_jump,
1300 laststart, b + 3);
1301 pending_exact = 0;
1302 b += 3;
1303
1304 if (!zero_times_ok)
1305 {
1306 /* At least one repetition is required, so insert a
1307 `dummy_failure_jump' before the initial
1308 `on_failure_jump' instruction of the loop. This
1309 effects a skip over that instruction the first time
1310 we hit that loop. */
1311 GET_BUFFER_SPACE (3);
1312 INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
1313 b += 3;
1314 }
1315 }
1316 break;
1317
1318
1319 case '.':
1320 laststart = b;
1321 BUF_PUSH (anychar);
1322 break;
1323
1324
1325 case '[':
1326 {
1327 boolean had_char_class = false;
1328
1329 if (p == pend) return REG_EBRACK;
1330
1331 /* Ensure that we have enough space to push a charset: the
1332 opcode, the length count, and the bitset; 34 bytes in all. */
1333 GET_BUFFER_SPACE (34);
1334
1335 laststart = b;
1336
1337 /* We test `*p == '^' twice, instead of using an if
1338 statement, so we only need one BUF_PUSH. */
1339 BUF_PUSH (*p == '^' ? charset_not : charset);
1340 if (*p == '^')
1341 p++;
1342
1343 /* Remember the first position in the bracket expression. */
1344 p1 = p;
1345
1346 /* Push the number of bytes in the bitmap. */
1347 BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
1348
1349 /* Clear the whole map. */
1350 bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
1351
1352 /* charset_not matches newline according to a syntax bit. */
1353 if ((re_opcode_t) b[-2] == charset_not
1354 && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
1355 SET_LIST_BIT ('\n');
1356
1357 /* Read in characters and ranges, setting map bits. */
1358 for (;;)
1359 {
1360 if (p == pend) return REG_EBRACK;
1361
1362 PATFETCH (c);
1363
1364 /* \ might escape characters inside [...] and [^...]. */
1365 if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
1366 {
1367 if (p == pend) return REG_EESCAPE;
1368
1369 PATFETCH (c1);
1370 SET_LIST_BIT (c1);
1371 continue;
1372 }
1373
1374 /* Could be the end of the bracket expression. If it's
1375 not (i.e., when the bracket expression is `[]' so
1376 far), the ']' character bit gets set way below. */
1377 if (c == ']' && p != p1 + 1)
1378 break;
1379
1380 /* Look ahead to see if it's a range when the last thing
1381 was a character class. */
1382 if (had_char_class && c == '-' && *p != ']')
1383 return REG_ERANGE;
1384
1385 /* Look ahead to see if it's a range when the last thing
1386 was a character: if this is a hyphen not at the
1387 beginning or the end of a list, then it's the range
1388 operator. */
1389 if (c == '-'
1390 && !(p - 2 >= pattern && p[-2] == '[')
1391 && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
1392 && *p != ']')
1393 {
1394 reg_errcode_t ret
1395 = compile_range (&p, pend, translate, syntax, b);
1396 if (ret != REG_NOERROR) return ret;
1397 }
1398
1399 else if (p[0] == '-' && p[1] != ']')
1400 { /* This handles ranges made up of characters only. */
1401 reg_errcode_t ret;
1402
1403 /* Move past the `-'. */
1404 PATFETCH (c1);
1405
1406 ret = compile_range (&p, pend, translate, syntax, b);
1407 if (ret != REG_NOERROR) return ret;
1408 }
1409
1410 /* See if we're at the beginning of a possible character
1411 class. */
1412
1413 else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
1414 { /* Leave room for the null. */
1415 char str[CHAR_CLASS_MAX_LENGTH + 1];
1416
1417 PATFETCH (c);
1418 c1 = 0;
1419
1420 /* If pattern is `[[:'. */
1421 if (p == pend) return REG_EBRACK;
1422
1423 for (;;)
1424 {
1425 PATFETCH (c);
1426 if (c == ':' || c == ']' || p == pend
1427 || c1 == CHAR_CLASS_MAX_LENGTH)
1428 break;
1429 str[c1++] = c;
1430 }
1431 str[c1] = '\0';
1432
1433 /* If isn't a word bracketed by `[:' and:`]':
1434 undo the ending character, the letters, and leave
1435 the leading `:' and `[' (but set bits for them). */
1436 if (c == ':' && *p == ']')
1437 {
1438 int ch;
1439 boolean is_alnum = STREQ (str, "alnum");
1440 boolean is_alpha = STREQ (str, "alpha");
1441 boolean is_blank = STREQ (str, "blank");
1442 boolean is_cntrl = STREQ (str, "cntrl");
1443 boolean is_digit = STREQ (str, "digit");
1444 boolean is_graph = STREQ (str, "graph");
1445 boolean is_lower = STREQ (str, "lower");
1446 boolean is_print = STREQ (str, "print");
1447 boolean is_punct = STREQ (str, "punct");
1448 boolean is_space = STREQ (str, "space");
1449 boolean is_upper = STREQ (str, "upper");
1450 boolean is_xdigit = STREQ (str, "xdigit");
1451
1452 if (!IS_CHAR_CLASS (str)) return REG_ECTYPE;
1453
1454 /* Throw away the ] at the end of the character
1455 class. */
1456 PATFETCH (c);
1457
1458 if (p == pend) return REG_EBRACK;
1459
1460 for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
1461 {
1462 if ( (is_alnum && ISALNUM (ch))
1463 || (is_alpha && ISALPHA (ch))
1464 || (is_blank && ISBLANK (ch))
1465 || (is_cntrl && ISCNTRL (ch))
1466 || (is_digit && ISDIGIT (ch))
1467 || (is_graph && ISGRAPH (ch))
1468 || (is_lower && ISLOWER (ch))
1469 || (is_print && ISPRINT (ch))
1470 || (is_punct && ISPUNCT (ch))
1471 || (is_space && ISSPACE (ch))
1472 || (is_upper && ISUPPER (ch))
1473 || (is_xdigit && ISXDIGIT (ch)))
1474 SET_LIST_BIT (ch);
1475 }
1476 had_char_class = true;
1477 }
1478 else
1479 {
1480 c1++;
1481 while (c1--)
1482 PATUNFETCH;
1483 SET_LIST_BIT ('[');
1484 SET_LIST_BIT (':');
1485 had_char_class = false;
1486 }
1487 }
1488 else
1489 {
1490 had_char_class = false;
1491 SET_LIST_BIT (c);
1492 }
1493 }
1494
1495 /* Discard any (non)matching list bytes that are all 0 at the
1496 end of the map. Decrease the map-length byte too. */
1497 while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
1498 b[-1]--;
1499 b += b[-1];
1500 }
1501 break;
1502
1503
1504 case '(':
1505 if (syntax & RE_NO_BK_PARENS)
1506 goto handle_open;
1507 else
1508 goto normal_char;
1509
1510
1511 case ')':
1512 if (syntax & RE_NO_BK_PARENS)
1513 goto handle_close;
1514 else
1515 goto normal_char;
1516
1517
1518 case '\n':
1519 if (syntax & RE_NEWLINE_ALT)
1520 goto handle_alt;
1521 else
1522 goto normal_char;
1523
1524
1525 case '|':
1526 if (syntax & RE_NO_BK_VBAR)
1527 goto handle_alt;
1528 else
1529 goto normal_char;
1530
1531
1532 case '{':
1533 if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
1534 goto handle_interval;
1535 else
1536 goto normal_char;
1537
1538
1539 case '\\':
1540 if (p == pend) return REG_EESCAPE;
1541
1542 /* Do not translate the character after the \, so that we can
1543 distinguish, e.g., \B from \b, even if we normally would
1544 translate, e.g., B to b. */
1545 PATFETCH_RAW (c);
1546
1547 switch (c)
1548 {
1549 case '(':
1550 if (syntax & RE_NO_BK_PARENS)
1551 goto normal_backslash;
1552
1553 handle_open:
1554 bufp->re_nsub++;
1555 regnum++;
1556
1557 if (COMPILE_STACK_FULL)
1558 {
1559 RETALLOC (compile_stack.stack, compile_stack.size << 1,
1560 compile_stack_elt_t);
1561 if (compile_stack.stack == NULL) return REG_ESPACE;
1562
1563 compile_stack.size <<= 1;
1564 }
1565
1566 /* These are the values to restore when we hit end of this
1567 group. They are all relative offsets, so that if the
1568 whole pattern moves because of realloc, they will still
1569 be valid. */
1570 COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
1571 COMPILE_STACK_TOP.fixup_alt_jump
1572 = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
1573 COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
1574 COMPILE_STACK_TOP.regnum = regnum;
1575
1576 /* We will eventually replace the 0 with the number of
1577 groups inner to this one. But do not push a
1578 start_memory for groups beyond the last one we can
1579 represent in the compiled pattern. */
1580 if (regnum <= MAX_REGNUM)
1581 {
1582 COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
1583 BUF_PUSH_3 (start_memory, regnum, 0);
1584 }
1585
1586 compile_stack.avail++;
1587
1588 fixup_alt_jump = 0;
1589 laststart = 0;
1590 begalt = b;
1591 /* If we've reached MAX_REGNUM groups, then this open
1592 won't actually generate any code, so we'll have to
1593 clear pending_exact explicitly. */
1594 pending_exact = 0;
1595 break;
1596
1597
1598 case ')':
1599 if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
1600
1601 if (COMPILE_STACK_EMPTY)
1602 {
1603 if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
1604 goto normal_backslash;
1605 else
1606 return REG_ERPAREN;
1607 }
1608
1609 handle_close:
1610 if (fixup_alt_jump)
1611 { /* Push a dummy failure point at the end of the
1612 alternative for a possible future
1613 `pop_failure_jump' to pop. See comments at
1614 `push_dummy_failure' in `re_match_2'. */
1615 BUF_PUSH (push_dummy_failure);
1616
1617 /* We allocated space for this jump when we assigned
1618 to `fixup_alt_jump', in the `handle_alt' case below. */
1619 STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
1620 }
1621
1622 /* See similar code for backslashed left paren above. */
1623 if (COMPILE_STACK_EMPTY)
1624 {
1625 if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
1626 goto normal_char;
1627 else
1628 return REG_ERPAREN;
1629 }
1630
1631 /* Since we just checked for an empty stack above, this
1632 ``can't happen''. */
1633 assert (compile_stack.avail != 0);
1634 {
1635 /* We don't just want to restore into `regnum', because
1636 later groups should continue to be numbered higher,
1637 as in `(ab)c(de)' -- the second group is #2. */
1638 regnum_t this_group_regnum;
1639
1640 compile_stack.avail--;
1641 begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
1642 fixup_alt_jump
1643 = COMPILE_STACK_TOP.fixup_alt_jump
1644 ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
1645 : 0;
1646 laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
1647 this_group_regnum = COMPILE_STACK_TOP.regnum;
1648 /* If we've reached MAX_REGNUM groups, then this open
1649 won't actually generate any code, so we'll have to
1650 clear pending_exact explicitly. */
1651 pending_exact = 0;
1652
1653 /* We're at the end of the group, so now we know how many
1654 groups were inside this one. */
1655 if (this_group_regnum <= MAX_REGNUM)
1656 {
1657 unsigned char *inner_group_loc
1658 = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
1659
1660 *inner_group_loc = regnum - this_group_regnum;
1661 BUF_PUSH_3 (stop_memory, this_group_regnum,
1662 regnum - this_group_regnum);
1663 }
1664 }
1665 break;
1666
1667
1668 case '|': /* `\|'. */
1669 if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
1670 goto normal_backslash;
1671 handle_alt:
1672 if (syntax & RE_LIMITED_OPS)
1673 goto normal_char;
1674
1675 /* Insert before the previous alternative a jump which
1676 jumps to this alternative if the former fails. */
1677 GET_BUFFER_SPACE (3);
1678 INSERT_JUMP (on_failure_jump, begalt, b + 6);
1679 pending_exact = 0;
1680 b += 3;
1681
1682 /* The alternative before this one has a jump after it
1683 which gets executed if it gets matched. Adjust that
1684 jump so it will jump to this alternative's analogous
1685 jump (put in below, which in turn will jump to the next
1686 (if any) alternative's such jump, etc.). The last such
1687 jump jumps to the correct final destination. A picture:
1688 _____ _____
1689 | | | |
1690 | v | v
1691 a | b | c
1692
1693 If we are at `b', then fixup_alt_jump right now points to a
1694 three-byte space after `a'. We'll put in the jump, set
1695 fixup_alt_jump to right after `b', and leave behind three
1696 bytes which we'll fill in when we get to after `c'. */
1697
1698 if (fixup_alt_jump)
1699 STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
1700
1701 /* Mark and leave space for a jump after this alternative,
1702 to be filled in later either by next alternative or
1703 when know we're at the end of a series of alternatives. */
1704 fixup_alt_jump = b;
1705 GET_BUFFER_SPACE (3);
1706 b += 3;
1707
1708 laststart = 0;
1709 begalt = b;
1710 break;
1711
1712
1713 case '{':
1714 /* If \{ is a literal. */
1715 if (!(syntax & RE_INTERVALS)
1716 /* If we're at `\{' and it's not the open-interval
1717 operator. */
1718 || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
1719 || (p - 2 == pattern && p == pend))
1720 goto normal_backslash;
1721
1722 handle_interval:
1723 {
1724 /* If got here, then the syntax allows intervals. */
1725
1726 /* At least (most) this many matches must be made. */
1727 int lower_bound = -1, upper_bound = -1;
1728
1729 beg_interval = p - 1;
1730
1731 if (p == pend)
1732 {
1733 if (syntax & RE_NO_BK_BRACES)
1734 goto unfetch_interval;
1735 else
1736 return REG_EBRACE;
1737 }
1738
1739 GET_UNSIGNED_NUMBER (lower_bound);
1740
1741 if (c == ',')
1742 {
1743 GET_UNSIGNED_NUMBER (upper_bound);
1744 if (upper_bound < 0) upper_bound = RE_DUP_MAX;
1745 }
1746 else
1747 /* Interval such as `{1}' => match exactly once. */
1748 upper_bound = lower_bound;
1749
1750 if (lower_bound < 0 || upper_bound > RE_DUP_MAX
1751 || lower_bound > upper_bound)
1752 {
1753 if (syntax & RE_NO_BK_BRACES)
1754 goto unfetch_interval;
1755 else
1756 return REG_BADBR;
1757 }
1758
1759 if (!(syntax & RE_NO_BK_BRACES))
1760 {
1761 if (c != '\\') return REG_EBRACE;
1762
1763 PATFETCH (c);
1764 }
1765
1766 if (c != '}')
1767 {
1768 if (syntax & RE_NO_BK_BRACES)
1769 goto unfetch_interval;
1770 else
1771 return REG_BADBR;
1772 }
1773
1774 /* We just parsed a valid interval. */
1775
1776 /* If it's invalid to have no preceding re. */
1777 if (!laststart)
1778 {
1779 if (syntax & RE_CONTEXT_INVALID_OPS)
1780 return REG_BADRPT;
1781 else if (syntax & RE_CONTEXT_INDEP_OPS)
1782 laststart = b;
1783 else
1784 goto unfetch_interval;
1785 }
1786
1787 /* If the upper bound is zero, don't want to succeed at
1788 all; jump from `laststart' to `b + 3', which will be
1789 the end of the buffer after we insert the jump. */
1790 if (upper_bound == 0)
1791 {
1792 GET_BUFFER_SPACE (3);
1793 INSERT_JUMP (jump, laststart, b + 3);
1794 b += 3;
1795 }
1796
1797 /* Otherwise, we have a nontrivial interval. When
1798 we're all done, the pattern will look like:
1799 set_number_at <jump count> <upper bound>
1800 set_number_at <succeed_n count> <lower bound>
1801 succeed_n <after jump addr> <succed_n count>
1802 <body of loop>
1803 jump_n <succeed_n addr> <jump count>
1804 (The upper bound and `jump_n' are omitted if
1805 `upper_bound' is 1, though.) */
1806 else
1807 { /* If the upper bound is > 1, we need to insert
1808 more at the end of the loop. */
1809 unsigned nbytes = 10 + (upper_bound > 1) * 10;
1810
1811 GET_BUFFER_SPACE (nbytes);
1812
1813 /* Initialize lower bound of the `succeed_n', even
1814 though it will be set during matching by its
1815 attendant `set_number_at' (inserted next),
1816 because `re_compile_fastmap' needs to know.
1817 Jump to the `jump_n' we might insert below. */
1818 INSERT_JUMP2 (succeed_n, laststart,
1819 b + 5 + (upper_bound > 1) * 5,
1820 lower_bound);
1821 b += 5;
1822
1823 /* Code to initialize the lower bound. Insert
1824 before the `succeed_n'. The `5' is the last two
1825 bytes of this `set_number_at', plus 3 bytes of
1826 the following `succeed_n'. */
1827 insert_op2 (set_number_at, laststart, 5, lower_bound, b);
1828 b += 5;
1829
1830 if (upper_bound > 1)
1831 { /* More than one repetition is allowed, so
1832 append a backward jump to the `succeed_n'
1833 that starts this interval.
1834
1835 When we've reached this during matching,
1836 we'll have matched the interval once, so
1837 jump back only `upper_bound - 1' times. */
1838 STORE_JUMP2 (jump_n, b, laststart + 5,
1839 upper_bound - 1);
1840 b += 5;
1841
1842 /* The location we want to set is the second
1843 parameter of the `jump_n'; that is `b-2' as
1844 an absolute address. `laststart' will be
1845 the `set_number_at' we're about to insert;
1846 `laststart+3' the number to set, the source
1847 for the relative address. But we are
1848 inserting into the middle of the pattern --
1849 so everything is getting moved up by 5.
1850 Conclusion: (b - 2) - (laststart + 3) + 5,
1851 i.e., b - laststart.
1852
1853 We insert this at the beginning of the loop
1854 so that if we fail during matching, we'll
1855 reinitialize the bounds. */
1856 insert_op2 (set_number_at, laststart, b - laststart,
1857 upper_bound - 1, b);
1858 b += 5;
1859 }
1860 }
1861 pending_exact = 0;
1862 beg_interval = NULL;
1863 }
1864 break;
1865
1866 unfetch_interval:
1867 /* If an invalid interval, match the characters as literals. */
1868 assert (beg_interval);
1869 p = beg_interval;
1870 beg_interval = NULL;
1871
1872 /* normal_char and normal_backslash need `c'. */
1873 PATFETCH (c);
1874
1875 if (!(syntax & RE_NO_BK_BRACES))
1876 {
1877 if (p > pattern && p[-1] == '\\')
1878 goto normal_backslash;
1879 }
1880 goto normal_char;
1881
1882#ifdef emacs
1883 /* There is no way to specify the before_dot and after_dot
1884 operators. rms says this is ok. --karl */
1885 case '=':
1886 BUF_PUSH (at_dot);
1887 break;
1888
1889 case 's':
1890 laststart = b;
1891 PATFETCH (c);
1892 BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
1893 break;
1894
1895 case 'S':
1896 laststart = b;
1897 PATFETCH (c);
1898 BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
1899 break;
1900#endif /* emacs */
1901
1902
1903 case 'w':
1904 laststart = b;
1905 BUF_PUSH (wordchar);
1906 break;
1907
1908
1909 case 'W':
1910 laststart = b;
1911 BUF_PUSH (notwordchar);
1912 break;
1913
1914
1915 case '<':
1916 BUF_PUSH (wordbeg);
1917 break;
1918
1919 case '>':
1920 BUF_PUSH (wordend);
1921 break;
1922
1923 case 'b':
1924 BUF_PUSH (wordbound);
1925 break;
1926
1927 case 'B':
1928 BUF_PUSH (notwordbound);
1929 break;
1930
1931 case '`':
1932 BUF_PUSH (begbuf);
1933 break;
1934
1935 case '\'':
1936 BUF_PUSH (endbuf);
1937 break;
1938
1939 case '1': case '2': case '3': case '4': case '5':
1940 case '6': case '7': case '8': case '9':
1941 if (syntax & RE_NO_BK_REFS)
1942 goto normal_char;
1943
1944 c1 = c - '0';
1945
1946 if (c1 > regnum)
1947 return REG_ESUBREG;
1948
1949 /* Can't back reference to a subexpression if inside of it. */
1950 if (group_in_compile_stack (compile_stack, c1))
1951 goto normal_char;
1952
1953 laststart = b;
1954 BUF_PUSH_2 (duplicate, c1);
1955 break;
1956
1957
1958 case '+':
1959 case '?':
1960 if (syntax & RE_BK_PLUS_QM)
1961 goto handle_plus;
1962 else
1963 goto normal_backslash;
1964
1965 default:
1966 normal_backslash:
1967 /* You might think it would be useful for \ to mean
1968 not to translate; but if we don't translate it
1969 it will never match anything. */
1970 c = TRANSLATE (c);
1971 goto normal_char;
1972 }
1973 break;
1974
1975
1976 default:
1977 /* Expects the character in `c'. */
1978 normal_char:
1979 /* If no exactn currently being built. */
1980 if (!pending_exact
1981
1982 /* If last exactn not at current position. */
1983 || pending_exact + *pending_exact + 1 != b
1984
1985 /* We have only one byte following the exactn for the count. */
1986 || *pending_exact == (1 << BYTEWIDTH) - 1
1987
1988 /* If followed by a repetition operator. */
1989 || *p == '*' || *p == '^'
1990 || ((syntax & RE_BK_PLUS_QM)
1991 ? *p == '\\' && (p[1] == '+' || p[1] == '?')
1992 : (*p == '+' || *p == '?'))
1993 || ((syntax & RE_INTERVALS)
1994 && ((syntax & RE_NO_BK_BRACES)
1995 ? *p == '{'
1996 : (p[0] == '\\' && p[1] == '{'))))
1997 {
1998 /* Start building a new exactn. */
1999
2000 laststart = b;
2001
2002 BUF_PUSH_2 (exactn, 0);
2003 pending_exact = b - 1;
2004 }
2005
2006 BUF_PUSH (c);
2007 (*pending_exact)++;
2008 break;
2009 } /* switch (c) */
2010 } /* while p != pend */
2011
2012
2013 /* Through the pattern now. */
2014
2015 if (fixup_alt_jump)
2016 STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
2017
2018 if (!COMPILE_STACK_EMPTY)
2019 return REG_EPAREN;
2020
2021 free (compile_stack.stack);
2022
2023 /* We have succeeded; set the length of the buffer. */
2024 bufp->used = b - bufp->buffer;
2025
2026#ifdef DEBUG
2027 if (debug)
2028 {
2029 DEBUG_PRINT1 ("\nCompiled pattern: ");
2030 print_compiled_pattern (bufp);
2031 }
2032#endif /* DEBUG */
2033
2034 return REG_NOERROR;
2035} /* regex_compile */
2036
2037/* Subroutines for `regex_compile'. */
2038
2039/* Store OP at LOC followed by two-byte integer parameter ARG. */
2040
2041static void
2042store_op1 (op, loc, arg)
2043 re_opcode_t op;
2044 unsigned char *loc;
2045 int arg;
2046{
2047 *loc = (unsigned char) op;
2048 STORE_NUMBER (loc + 1, arg);
2049}
2050
2051
2052/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */
2053
2054static void
2055store_op2 (op, loc, arg1, arg2)
2056 re_opcode_t op;
2057 unsigned char *loc;
2058 int arg1, arg2;
2059{
2060 *loc = (unsigned char) op;
2061 STORE_NUMBER (loc + 1, arg1);
2062 STORE_NUMBER (loc + 3, arg2);
2063}
2064
2065
2066/* Copy the bytes from LOC to END to open up three bytes of space at LOC
2067 for OP followed by two-byte integer parameter ARG. */
2068
2069static void
2070insert_op1 (op, loc, arg, end)
2071 re_opcode_t op;
2072 unsigned char *loc;
2073 int arg;
2074 unsigned char *end;
2075{
2076 register unsigned char *pfrom = end;
2077 register unsigned char *pto = end + 3;
2078
2079 while (pfrom != loc)
2080 *--pto = *--pfrom;
2081
2082 store_op1 (op, loc, arg);
2083}
2084
2085
2086/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */
2087
2088static void
2089insert_op2 (op, loc, arg1, arg2, end)
2090 re_opcode_t op;
2091 unsigned char *loc;
2092 int arg1, arg2;
2093 unsigned char *end;
2094{
2095 register unsigned char *pfrom = end;
2096 register unsigned char *pto = end + 5;
2097
2098 while (pfrom != loc)
2099 *--pto = *--pfrom;
2100
2101 store_op2 (op, loc, arg1, arg2);
2102}
2103
2104
2105/* P points to just after a ^ in PATTERN. Return true if that ^ comes
2106 after an alternative or a begin-subexpression. We assume there is at
2107 least one character before the ^. */
2108
2109static boolean
2110at_begline_loc_p (pattern, p, syntax)
2111 const char *pattern, *p;
2112 reg_syntax_t syntax;
2113{
2114 const char *prev = p - 2;
2115 boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
2116
2117 return
2118 /* After a subexpression? */
2119 (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
2120 /* After an alternative? */
2121 || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
2122}
2123
2124
2125/* The dual of at_begline_loc_p. This one is for $. We assume there is
2126 at least one character after the $, i.e., `P < PEND'. */
2127
2128static boolean
2129at_endline_loc_p (p, pend, syntax)
2130 const char *p, *pend;
2131 int syntax;
2132{
2133 const char *next = p;
2134 boolean next_backslash = *next == '\\';
2135 const char *next_next = p + 1 < pend ? p + 1 : NULL;
2136
2137 return
2138 /* Before a subexpression? */
2139 (syntax & RE_NO_BK_PARENS ? *next == ')'
2140 : next_backslash && next_next && *next_next == ')')
2141 /* Before an alternative? */
2142 || (syntax & RE_NO_BK_VBAR ? *next == '|'
2143 : next_backslash && next_next && *next_next == '|');
2144}
2145
2146
2147/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
2148 false if it's not. */
2149
2150static boolean
2151group_in_compile_stack (compile_stack, regnum)
2152 compile_stack_type compile_stack;
2153 regnum_t regnum;
2154{
2155 int this_element;
2156
2157 for (this_element = compile_stack.avail - 1;
2158 this_element >= 0;
2159 this_element--)
2160 if (compile_stack.stack[this_element].regnum == regnum)
2161 return true;
2162
2163 return false;
2164}
2165
2166
2167/* Read the ending character of a range (in a bracket expression) from the
2168 uncompiled pattern *P_PTR (which ends at PEND). We assume the
2169 starting character is in `P[-2]'. (`P[-1]' is the character `-'.)
2170 Then we set the translation of all bits between the starting and
2171 ending characters (inclusive) in the compiled pattern B.
2172
2173 Return an error code.
2174
2175 We use these short variable names so we can use the same macros as
2176 `regex_compile' itself. */
2177
2178static reg_errcode_t
2179compile_range (p_ptr, pend, translate, syntax, b)
2180 const char **p_ptr, *pend;
2181 char *translate;
2182 reg_syntax_t syntax;
2183 unsigned char *b;
2184{
2185 unsigned this_char;
2186
2187 const char *p = *p_ptr;
2188 int range_start, range_end;
2189
2190 if (p == pend)
2191 return REG_ERANGE;
2192
2193 /* Even though the pattern is a signed `char *', we need to fetch
2194 with unsigned char *'s; if the high bit of the pattern character
2195 is set, the range endpoints will be negative if we fetch using a
2196 signed char *.
2197
2198 We also want to fetch the endpoints without translating them; the
2199 appropriate translation is done in the bit-setting loop below. */
2200 range_start = ((unsigned char *) p)[-2];
2201 range_end = ((unsigned char *) p)[0];
2202
2203 /* Have to increment the pointer into the pattern string, so the
2204 caller isn't still at the ending character. */
2205 (*p_ptr)++;
2206
2207 /* If the start is after the end, the range is empty. */
2208 if (range_start > range_end)
2209 return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
2210
2211 /* Here we see why `this_char' has to be larger than an `unsigned
2212 char' -- the range is inclusive, so if `range_end' == 0xff
2213 (assuming 8-bit characters), we would otherwise go into an infinite
2214 loop, since all characters <= 0xff. */
2215 for (this_char = range_start; this_char <= range_end; this_char++)
2216 {
2217 SET_LIST_BIT (TRANSLATE (this_char));
2218 }
2219
2220 return REG_NOERROR;
2221}
2222
2223/* Failure stack declarations and macros; both re_compile_fastmap and
2224 re_match_2 use a failure stack. These have to be macros because of
2225 REGEX_ALLOCATE. */
2226
2227
2228/* Number of failure points for which to initially allocate space
2229 when matching. If this number is exceeded, we allocate more
2230 space, so it is not a hard limit. */
2231#ifndef INIT_FAILURE_ALLOC
2232#define INIT_FAILURE_ALLOC 5
2233#endif
2234
2235/* Roughly the maximum number of failure points on the stack. Would be
2236 exactly that if always used MAX_FAILURE_SPACE each time we failed.
2237 This is a variable only so users of regex can assign to it; we never
2238 change it ourselves. */
2239int re_max_failures = 2000;
2240
2241typedef const unsigned char *fail_stack_elt_t;
2242
2243typedef struct
2244{
2245 fail_stack_elt_t *stack;
2246 unsigned size;
2247 unsigned avail; /* Offset of next open position. */
2248} fail_stack_type;
2249
2250#define FAIL_STACK_EMPTY() (fail_stack.avail == 0)
2251#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
2252#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size)
2253#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail])
2254
2255
2256/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */
2257
2258#define INIT_FAIL_STACK() \
2259 do { \
2260 fail_stack.stack = (fail_stack_elt_t *) \
2261 REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
2262 \
2263 if (fail_stack.stack == NULL) \
2264 return -2; \
2265 \
2266 fail_stack.size = INIT_FAILURE_ALLOC; \
2267 fail_stack.avail = 0; \
2268 } while (0)
2269
2270
2271/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
2272
2273 Return 1 if succeeds, and 0 if either ran out of memory
2274 allocating space for it or it was already too large.
2275
2276 REGEX_REALLOCATE requires `destination' be declared. */
2277
2278#define DOUBLE_FAIL_STACK(fail_stack) \
2279 ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \
2280 ? 0 \
2281 : ((fail_stack).stack = (fail_stack_elt_t *) \
2282 REGEX_REALLOCATE ((fail_stack).stack, \
2283 (fail_stack).size * sizeof (fail_stack_elt_t), \
2284 ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \
2285 \
2286 (fail_stack).stack == NULL \
2287 ? 0 \
2288 : ((fail_stack).size <<= 1, \
2289 1)))
2290
2291
2292/* Push PATTERN_OP on FAIL_STACK.
2293
2294 Return 1 if was able to do so and 0 if ran out of memory allocating
2295 space to do so. */
2296#define PUSH_PATTERN_OP(pattern_op, fail_stack) \
2297 ((FAIL_STACK_FULL () \
2298 && !DOUBLE_FAIL_STACK (fail_stack)) \
2299 ? 0 \
2300 : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \
2301 1))
2302
2303/* This pushes an item onto the failure stack. Must be a four-byte
2304 value. Assumes the variable `fail_stack'. Probably should only
2305 be called from within `PUSH_FAILURE_POINT'. */
2306#define PUSH_FAILURE_ITEM(item) \
2307 fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item
2308
2309/* The complement operation. Assumes `fail_stack' is nonempty. */
2310#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail]
2311
2312/* Used to omit pushing failure point id's when we're not debugging. */
2313#ifdef DEBUG
2314#define DEBUG_PUSH PUSH_FAILURE_ITEM
2315#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM ()
2316#else
2317#define DEBUG_PUSH(item)
2318#define DEBUG_POP(item_addr)
2319#endif
2320
2321
2322/* Push the information about the state we will need
2323 if we ever fail back to it.
2324
2325 Requires variables fail_stack, regstart, regend, reg_info, and
2326 num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be
2327 declared.
2328
2329 Does `return FAILURE_CODE' if runs out of memory. */
2330
2331#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \
2332 do { \
2333 char *destination; \
2334 /* Must be int, so when we don't save any registers, the arithmetic \
2335 of 0 + -1 isn't done as unsigned. */ \
2336 int this_reg; \
2337 \
2338 DEBUG_STATEMENT (failure_id++); \
2339 DEBUG_STATEMENT (nfailure_points_pushed++); \
2340 DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \
2341 DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\
2342 DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\
2343 \
2344 DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \
2345 DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \
2346 \
2347 /* Ensure we have enough space allocated for what we will push. */ \
2348 while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \
2349 { \
2350 if (!DOUBLE_FAIL_STACK (fail_stack)) \
2351 return failure_code; \
2352 \
2353 DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \
2354 (fail_stack).size); \
2355 DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\
2356 } \
2357 \
2358 /* Push the info, starting with the registers. */ \
2359 DEBUG_PRINT1 ("\n"); \
2360 \
2361 for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
2362 this_reg++) \
2363 { \
2364 DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \
2365 DEBUG_STATEMENT (num_regs_pushed++); \
2366 \
2367 DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
2368 PUSH_FAILURE_ITEM (regstart[this_reg]); \
2369 \
2370 DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
2371 PUSH_FAILURE_ITEM (regend[this_reg]); \
2372 \
2373 DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \
2374 DEBUG_PRINT2 (" match_null=%d", \
2375 REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \
2376 DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \
2377 DEBUG_PRINT2 (" matched_something=%d", \
2378 MATCHED_SOMETHING (reg_info[this_reg])); \
2379 DEBUG_PRINT2 (" ever_matched=%d", \
2380 EVER_MATCHED_SOMETHING (reg_info[this_reg])); \
2381 DEBUG_PRINT1 ("\n"); \
2382 PUSH_FAILURE_ITEM (reg_info[this_reg].word); \
2383 } \
2384 \
2385 DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\
2386 PUSH_FAILURE_ITEM (lowest_active_reg); \
2387 \
2388 DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\
2389 PUSH_FAILURE_ITEM (highest_active_reg); \
2390 \
2391 DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \
2392 DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
2393 PUSH_FAILURE_ITEM (pattern_place); \
2394 \
2395 DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \
2396 DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
2397 size2); \
2398 DEBUG_PRINT1 ("'\n"); \
2399 PUSH_FAILURE_ITEM (string_place); \
2400 \
2401 DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \
2402 DEBUG_PUSH (failure_id); \
2403 } while (0)
2404
2405/* This is the number of items that are pushed and popped on the stack
2406 for each register. */
2407#define NUM_REG_ITEMS 3
2408
2409/* Individual items aside from the registers. */
2410#ifdef DEBUG
2411#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */
2412#else
2413#define NUM_NONREG_ITEMS 4
2414#endif
2415
2416/* We push at most this many items on the stack. */
2417#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
2418
2419/* We actually push this many items. */
2420#define NUM_FAILURE_ITEMS \
2421 ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \
2422 + NUM_NONREG_ITEMS)
2423
2424/* How many items can still be added to the stack without overflowing it. */
2425#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
2426
2427
2428/* Pops what PUSH_FAIL_STACK pushes.
2429
2430 We restore into the parameters, all of which should be lvalues:
2431 STR -- the saved data position.
2432 PAT -- the saved pattern position.
2433 LOW_REG, HIGH_REG -- the highest and lowest active registers.
2434 REGSTART, REGEND -- arrays of string positions.
2435 REG_INFO -- array of information about each subexpression.
2436
2437 Also assumes the variables `fail_stack' and (if debugging), `bufp',
2438 `pend', `string1', `size1', `string2', and `size2'. */
2439
2440#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
2441{ \
2442 DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \
2443 int this_reg; \
2444 const unsigned char *string_temp; \
2445 \
2446 assert (!FAIL_STACK_EMPTY ()); \
2447 \
2448 /* Remove failure points and point to how many regs pushed. */ \
2449 DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \
2450 DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \
2451 DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \
2452 \
2453 assert (fail_stack.avail >= NUM_NONREG_ITEMS); \
2454 \
2455 DEBUG_POP (&failure_id); \
2456 DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \
2457 \
2458 /* If the saved string location is NULL, it came from an \
2459 on_failure_keep_string_jump opcode, and we want to throw away the \
2460 saved NULL, thus retaining our current position in the string. */ \
2461 string_temp = POP_FAILURE_ITEM (); \
2462 if (string_temp != NULL) \
2463 str = (const char *) string_temp; \
2464 \
2465 DEBUG_PRINT2 (" Popping string 0x%x: `", str); \
2466 DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
2467 DEBUG_PRINT1 ("'\n"); \
2468 \
2469 pat = (unsigned char *) POP_FAILURE_ITEM (); \
2470 DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \
2471 DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
2472 \
2473 /* Restore register info. */ \
2474 high_reg = (unsigned) POP_FAILURE_ITEM (); \
2475 DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \
2476 \
2477 low_reg = (unsigned) POP_FAILURE_ITEM (); \
2478 DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \
2479 \
2480 for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
2481 { \
2482 DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \
2483 \
2484 reg_info[this_reg].word = POP_FAILURE_ITEM (); \
2485 DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \
2486 \
2487 regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \
2488 DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
2489 \
2490 regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \
2491 DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
2492 } \
2493 \
2494 DEBUG_STATEMENT (nfailure_points_popped++); \
2495} /* POP_FAILURE_POINT */
2496
2497/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
2498 BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible
2499 characters can start a string that matches the pattern. This fastmap
2500 is used by re_search to skip quickly over impossible starting points.
2501
2502 The caller must supply the address of a (1 << BYTEWIDTH)-byte data
2503 area as BUFP->fastmap.
2504
2505 We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
2506 the pattern buffer.
2507
2508 Returns 0 if we succeed, -2 if an internal error. */
2509
2510int
2511re_compile_fastmap (bufp)
2512 struct re_pattern_buffer *bufp;
2513{
2514 int j, k;
2515 fail_stack_type fail_stack;
2516#ifndef REGEX_MALLOC
2517 char *destination;
2518#endif
2519 /* We don't push any register information onto the failure stack. */
2520 unsigned num_regs = 0;
2521
2522 register char *fastmap = bufp->fastmap;
2523 unsigned char *pattern = bufp->buffer;
2524 unsigned long size = bufp->used;
2525 const unsigned char *p = pattern;
2526 register unsigned char *pend = pattern + size;
2527
2528 /* Assume that each path through the pattern can be null until
2529 proven otherwise. We set this false at the bottom of switch
2530 statement, to which we get only if a particular path doesn't
2531 match the empty string. */
2532 boolean path_can_be_null = true;
2533
2534 /* We aren't doing a `succeed_n' to begin with. */
2535 boolean succeed_n_p = false;
2536
2537 assert (fastmap != NULL && p != NULL);
2538
2539 INIT_FAIL_STACK ();
2540 bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */
2541 bufp->fastmap_accurate = 1; /* It will be when we're done. */
2542 bufp->can_be_null = 0;
2543
2544 while (p != pend || !FAIL_STACK_EMPTY ())
2545 {
2546 if (p == pend)
2547 {
2548 bufp->can_be_null |= path_can_be_null;
2549
2550 /* Reset for next path. */
2551 path_can_be_null = true;
2552
2553 p = fail_stack.stack[--fail_stack.avail];
2554 }
2555
2556 /* We should never be about to go beyond the end of the pattern. */
2557 assert (p < pend);
2558
2559#ifdef SWITCH_ENUM_BUG
2560 switch ((int) ((re_opcode_t) *p++))
2561#else
2562 switch ((re_opcode_t) *p++)
2563#endif
2564 {
2565
2566 /* I guess the idea here is to simply not bother with a fastmap
2567 if a backreference is used, since it's too hard to figure out
2568 the fastmap for the corresponding group. Setting
2569 `can_be_null' stops `re_search_2' from using the fastmap, so
2570 that is all we do. */
2571 case duplicate:
2572 bufp->can_be_null = 1;
2573 return 0;
2574
2575
2576 /* Following are the cases which match a character. These end
2577 with `break'. */
2578
2579 case exactn:
2580 fastmap[p[1]] = 1;
2581 break;
2582
2583
2584 case charset:
2585 for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
2586 if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
2587 fastmap[j] = 1;
2588 break;
2589
2590
2591 case charset_not:
2592 /* Chars beyond end of map must be allowed. */
2593 for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
2594 fastmap[j] = 1;
2595
2596 for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
2597 if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
2598 fastmap[j] = 1;
2599 break;
2600
2601
2602 case wordchar:
2603 for (j = 0; j < (1 << BYTEWIDTH); j++)
2604 if (SYNTAX (j) == Sword)
2605 fastmap[j] = 1;
2606 break;
2607
2608
2609 case notwordchar:
2610 for (j = 0; j < (1 << BYTEWIDTH); j++)
2611 if (SYNTAX (j) != Sword)
2612 fastmap[j] = 1;
2613 break;
2614
2615
2616 case anychar:
2617 /* `.' matches anything ... */
2618 for (j = 0; j < (1 << BYTEWIDTH); j++)
2619 fastmap[j] = 1;
2620
2621 /* ... except perhaps newline. */
2622 if (!(bufp->syntax & RE_DOT_NEWLINE))
2623 fastmap['\n'] = 0;
2624
2625 /* Return if we have already set `can_be_null'; if we have,
2626 then the fastmap is irrelevant. Something's wrong here. */
2627 else if (bufp->can_be_null)
2628 return 0;
2629
2630 /* Otherwise, have to check alternative paths. */
2631 break;
2632
2633
2634#ifdef emacs
2635 case syntaxspec:
2636 k = *p++;
2637 for (j = 0; j < (1 << BYTEWIDTH); j++)
2638 if (SYNTAX (j) == (enum syntaxcode) k)
2639 fastmap[j] = 1;
2640 break;
2641
2642
2643 case notsyntaxspec:
2644 k = *p++;
2645 for (j = 0; j < (1 << BYTEWIDTH); j++)
2646 if (SYNTAX (j) != (enum syntaxcode) k)
2647 fastmap[j] = 1;
2648 break;
2649
2650
2651 /* All cases after this match the empty string. These end with
2652 `continue'. */
2653
2654
2655 case before_dot:
2656 case at_dot:
2657 case after_dot:
2658 continue;
2659#endif /* not emacs */
2660
2661
2662 case no_op:
2663 case begline:
2664 case endline:
2665 case begbuf:
2666 case endbuf:
2667 case wordbound:
2668 case notwordbound:
2669 case wordbeg:
2670 case wordend:
2671 case push_dummy_failure:
2672 continue;
2673
2674
2675 case jump_n:
2676 case pop_failure_jump:
2677 case maybe_pop_jump:
2678 case jump:
2679 case jump_past_alt:
2680 case dummy_failure_jump:
2681 EXTRACT_NUMBER_AND_INCR (j, p);
2682 p += j;
2683 if (j > 0)
2684 continue;
2685
2686 /* Jump backward implies we just went through the body of a
2687 loop and matched nothing. Opcode jumped to should be
2688 `on_failure_jump' or `succeed_n'. Just treat it like an
2689 ordinary jump. For a * loop, it has pushed its failure
2690 point already; if so, discard that as redundant. */
2691 if ((re_opcode_t) *p != on_failure_jump
2692 && (re_opcode_t) *p != succeed_n)
2693 continue;
2694
2695 p++;
2696 EXTRACT_NUMBER_AND_INCR (j, p);
2697 p += j;
2698
2699 /* If what's on the stack is where we are now, pop it. */
2700 if (!FAIL_STACK_EMPTY ()
2701 && fail_stack.stack[fail_stack.avail - 1] == p)
2702 fail_stack.avail--;
2703
2704 continue;
2705
2706
2707 case on_failure_jump:
2708 case on_failure_keep_string_jump:
2709 handle_on_failure_jump:
2710 EXTRACT_NUMBER_AND_INCR (j, p);
2711
2712 /* For some patterns, e.g., `(a?)?', `p+j' here points to the
2713 end of the pattern. We don't want to push such a point,
2714 since when we restore it above, entering the switch will
2715 increment `p' past the end of the pattern. We don't need
2716 to push such a point since we obviously won't find any more
2717 fastmap entries beyond `pend'. Such a pattern can match
2718 the null string, though. */
2719 if (p + j < pend)
2720 {
2721 if (!PUSH_PATTERN_OP (p + j, fail_stack))
2722 return -2;
2723 }
2724 else
2725 bufp->can_be_null = 1;
2726
2727 if (succeed_n_p)
2728 {
2729 EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */
2730 succeed_n_p = false;
2731 }
2732
2733 continue;
2734
2735
2736 case succeed_n:
2737 /* Get to the number of times to succeed. */
2738 p += 2;
2739
2740 /* Increment p past the n for when k != 0. */
2741 EXTRACT_NUMBER_AND_INCR (k, p);
2742 if (k == 0)
2743 {
2744 p -= 4;
2745 succeed_n_p = true; /* Spaghetti code alert. */
2746 goto handle_on_failure_jump;
2747 }
2748 continue;
2749
2750
2751 case set_number_at:
2752 p += 4;
2753 continue;
2754
2755
2756 case start_memory:
2757 case stop_memory:
2758 p += 2;
2759 continue;
2760
2761
2762 default:
2763 abort (); /* We have listed all the cases. */
2764 } /* switch *p++ */
2765
2766 /* Getting here means we have found the possible starting
2767 characters for one path of the pattern -- and that the empty
2768 string does not match. We need not follow this path further.
2769 Instead, look at the next alternative (remembered on the
2770 stack), or quit if no more. The test at the top of the loop
2771 does these things. */
2772 path_can_be_null = false;
2773 p = pend;
2774 } /* while p */
2775
2776 /* Set `can_be_null' for the last path (also the first path, if the
2777 pattern is empty). */
2778 bufp->can_be_null |= path_can_be_null;
2779 return 0;
2780} /* re_compile_fastmap */
2781
2782/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
2783 ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use
2784 this memory for recording register information. STARTS and ENDS
2785 must be allocated using the malloc library routine, and must each
2786 be at least NUM_REGS * sizeof (regoff_t) bytes long.
2787
2788 If NUM_REGS == 0, then subsequent matches should allocate their own
2789 register data.
2790
2791 Unless this function is called, the first search or match using
2792 PATTERN_BUFFER will allocate its own register data, without
2793 freeing the old data. */
2794
2795void
2796re_set_registers (bufp, regs, num_regs, starts, ends)
2797 struct re_pattern_buffer *bufp;
2798 struct re_registers *regs;
2799 unsigned num_regs;
2800 regoff_t *starts, *ends;
2801{
2802 if (num_regs)
2803 {
2804 bufp->regs_allocated = REGS_REALLOCATE;
2805 regs->num_regs = num_regs;
2806 regs->start = starts;
2807 regs->end = ends;
2808 }
2809 else
2810 {
2811 bufp->regs_allocated = REGS_UNALLOCATED;
2812 regs->num_regs = 0;
2813 regs->start = regs->end = (regoff_t) 0;
2814 }
2815}
2816
2817/* Searching routines. */
2818
2819/* Like re_search_2, below, but only one string is specified, and
2820 doesn't let you say where to stop matching. */
2821
2822int
2823re_search (bufp, string, size, startpos, range, regs)
2824 struct re_pattern_buffer *bufp;
2825 const char *string;
2826 int size, startpos, range;
2827 struct re_registers *regs;
2828{
2829 return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
2830 regs, size);
2831}
2832
2833
2834/* Using the compiled pattern in BUFP->buffer, first tries to match the
2835 virtual concatenation of STRING1 and STRING2, starting first at index
2836 STARTPOS, then at STARTPOS + 1, and so on.
2837
2838 STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
2839
2840 RANGE is how far to scan while trying to match. RANGE = 0 means try
2841 only at STARTPOS; in general, the last start tried is STARTPOS +
2842 RANGE.
2843
2844 In REGS, return the indices of the virtual concatenation of STRING1
2845 and STRING2 that matched the entire BUFP->buffer and its contained
2846 subexpressions.
2847
2848 Do not consider matching one past the index STOP in the virtual
2849 concatenation of STRING1 and STRING2.
2850
2851 We return either the position in the strings at which the match was
2852 found, -1 if no match, or -2 if error (such as failure
2853 stack overflow). */
2854
2855int
2856re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
2857 struct re_pattern_buffer *bufp;
2858 const char *string1, *string2;
2859 int size1, size2;
2860 int startpos;
2861 int range;
2862 struct re_registers *regs;
2863 int stop;
2864{
2865 int val;
2866 register char *fastmap = bufp->fastmap;
2867 register char *translate = bufp->translate;
2868 int total_size = size1 + size2;
2869 int endpos = startpos + range;
2870
2871 /* Check for out-of-range STARTPOS. */
2872 if (startpos < 0 || startpos > total_size)
2873 return -1;
2874
2875 /* Fix up RANGE if it might eventually take us outside
2876 the virtual concatenation of STRING1 and STRING2. */
2877 if (endpos < -1)
2878 range = -1 - startpos;
2879 else if (endpos > total_size)
2880 range = total_size - startpos;
2881
2882 /* If the search isn't to be a backwards one, don't waste time in a
2883 search for a pattern that must be anchored. */
2884 if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
2885 {
2886 if (startpos > 0)
2887 return -1;
2888 else
2889 range = 1;
2890 }
2891
2892 /* Update the fastmap now if not correct already. */
2893 if (fastmap && !bufp->fastmap_accurate)
2894 if (re_compile_fastmap (bufp) == -2)
2895 return -2;
2896
2897 /* Loop through the string, looking for a place to start matching. */
2898 for (;;)
2899 {
2900 /* If a fastmap is supplied, skip quickly over characters that
2901 cannot be the start of a match. If the pattern can match the
2902 null string, however, we don't need to skip characters; we want
2903 the first null string. */
2904 if (fastmap && startpos < total_size && !bufp->can_be_null)
2905 {
2906 if (range > 0) /* Searching forwards. */
2907 {
2908 register const char *d;
2909 register int lim = 0;
2910 int irange = range;
2911
2912 if (startpos < size1 && startpos + range >= size1)
2913 lim = range - (size1 - startpos);
2914
2915 d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
2916
2917 /* Written out as an if-else to avoid testing `translate'
2918 inside the loop. */
2919 if (translate)
2920 while (range > lim
2921 && !fastmap[(unsigned char)
2922 translate[(unsigned char) *d++]])
2923 range--;
2924 else
2925 while (range > lim && !fastmap[(unsigned char) *d++])
2926 range--;
2927
2928 startpos += irange - range;
2929 }
2930 else /* Searching backwards. */
2931 {
2932 register char c = (size1 == 0 || startpos >= size1
2933 ? string2[startpos - size1]
2934 : string1[startpos]);
2935
2936 if (!fastmap[(unsigned char) TRANSLATE (c)])
2937 goto advance;
2938 }
2939 }
2940
2941 /* If can't match the null string, and that's all we have left, fail. */
2942 if (range >= 0 && startpos == total_size && fastmap
2943 && !bufp->can_be_null)
2944 return -1;
2945
2946 val = re_match_2 (bufp, string1, size1, string2, size2,
2947 startpos, regs, stop);
2948 if (val >= 0)
2949 return startpos;
2950
2951 if (val == -2)
2952 return -2;
2953
2954 advance:
2955 if (!range)
2956 break;
2957 else if (range > 0)
2958 {
2959 range--;
2960 startpos++;
2961 }
2962 else
2963 {
2964 range++;
2965 startpos--;
2966 }
2967 }
2968 return -1;
2969} /* re_search_2 */
2970
2971/* Declarations and macros for re_match_2. */
2972
2973static int bcmp_translate ();
2974static boolean alt_match_null_string_p (),
2975 common_op_match_null_string_p (),
2976 group_match_null_string_p ();
2977
2978/* Structure for per-register (a.k.a. per-group) information.
2979 This must not be longer than one word, because we push this value
2980 onto the failure stack. Other register information, such as the
2981 starting and ending positions (which are addresses), and the list of
2982 inner groups (which is a bits list) are maintained in separate
2983 variables.
2984
2985 We are making a (strictly speaking) nonportable assumption here: that
2986 the compiler will pack our bit fields into something that fits into
2987 the type of `word', i.e., is something that fits into one item on the
2988 failure stack. */
2989typedef union
2990{
2991 fail_stack_elt_t word;
2992 struct
2993 {
2994 /* This field is one if this group can match the empty string,
2995 zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */
2996#define MATCH_NULL_UNSET_VALUE 3
2997 unsigned match_null_string_p : 2;
2998 unsigned is_active : 1;
2999 unsigned matched_something : 1;
3000 unsigned ever_matched_something : 1;
3001 } bits;
3002} register_info_type;
3003
3004#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p)
3005#define IS_ACTIVE(R) ((R).bits.is_active)
3006#define MATCHED_SOMETHING(R) ((R).bits.matched_something)
3007#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something)
3008
3009
3010/* Call this when have matched a real character; it sets `matched' flags
3011 for the subexpressions which we are currently inside. Also records
3012 that those subexprs have matched. */
3013#define SET_REGS_MATCHED() \
3014 do \
3015 { \
3016 unsigned r; \
3017 for (r = lowest_active_reg; r <= highest_active_reg; r++) \
3018 { \
3019 MATCHED_SOMETHING (reg_info[r]) \
3020 = EVER_MATCHED_SOMETHING (reg_info[r]) \
3021 = 1; \
3022 } \
3023 } \
3024 while (0)
3025
3026
3027/* This converts PTR, a pointer into one of the search strings `string1'
3028 and `string2' into an offset from the beginning of that string. */
3029#define POINTER_TO_OFFSET(ptr) \
3030 (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1)
3031
3032/* Registers are set to a sentinel when they haven't yet matched. */
3033#define REG_UNSET_VALUE ((char *) -1)
3034#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
3035
3036
3037/* Macros for dealing with the split strings in re_match_2. */
3038
3039#define MATCHING_IN_FIRST_STRING (dend == end_match_1)
3040
3041/* Call before fetching a character with *d. This switches over to
3042 string2 if necessary. */
3043#define PREFETCH() \
3044 while (d == dend) \
3045 { \
3046 /* End of string2 => fail. */ \
3047 if (dend == end_match_2) \
3048 goto fail; \
3049 /* End of string1 => advance to string2. */ \
3050 d = string2; \
3051 dend = end_match_2; \
3052 }
3053
3054
3055/* Test if at very beginning or at very end of the virtual concatenation
3056 of `string1' and `string2'. If only one string, it's `string2'. */
3057#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
3058#define AT_STRINGS_END(d) ((d) == end2)
3059
3060
3061/* Test if D points to a character which is word-constituent. We have
3062 two special cases to check for: if past the end of string1, look at
3063 the first character in string2; and if before the beginning of
3064 string2, look at the last character in string1. */
3065#define WORDCHAR_P(d) \
3066 (SYNTAX ((d) == end1 ? *string2 \
3067 : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \
3068 == Sword)
3069
3070/* Test if the character before D and the one at D differ with respect
3071 to being word-constituent. */
3072#define AT_WORD_BOUNDARY(d) \
3073 (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \
3074 || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
3075
3076
3077/* Free everything we malloc. */
3078#ifdef REGEX_MALLOC
3079#define FREE_VAR(var) if (var) free (var); var = NULL
3080#define FREE_VARIABLES() \
3081 do { \
3082 FREE_VAR (fail_stack.stack); \
3083 FREE_VAR (regstart); \
3084 FREE_VAR (regend); \
3085 FREE_VAR (old_regstart); \
3086 FREE_VAR (old_regend); \
3087 FREE_VAR (best_regstart); \
3088 FREE_VAR (best_regend); \
3089 FREE_VAR (reg_info); \
3090 FREE_VAR (reg_dummy); \
3091 FREE_VAR (reg_info_dummy); \
3092 } while (0)
3093#else /* not REGEX_MALLOC */
3094/* Some MIPS systems (at least) want this to free alloca'd storage. */
3095#define FREE_VARIABLES() alloca (0)
3096#endif /* not REGEX_MALLOC */
3097
3098
3099/* These values must meet several constraints. They must not be valid
3100 register values; since we have a limit of 255 registers (because
3101 we use only one byte in the pattern for the register number), we can
3102 use numbers larger than 255. They must differ by 1, because of
3103 NUM_FAILURE_ITEMS above. And the value for the lowest register must
3104 be larger than the value for the highest register, so we do not try
3105 to actually save any registers when none are active. */
3106#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
3107#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
3108
3109/* Matching routines. */
3110
3111#ifndef emacs /* Emacs never uses this. */
3112/* re_match is like re_match_2 except it takes only a single string. */
3113
3114int
3115re_match (bufp, string, size, pos, regs)
3116 struct re_pattern_buffer *bufp;
3117 const char *string;
3118 int size, pos;
3119 struct re_registers *regs;
3120 {
3121 return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size);
3122}
3123#endif /* not emacs */
3124
3125
3126/* re_match_2 matches the compiled pattern in BUFP against the
3127 the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
3128 and SIZE2, respectively). We start matching at POS, and stop
3129 matching at STOP.
3130
3131 If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
3132 store offsets for the substring each group matched in REGS. See the
3133 documentation for exactly how many groups we fill.
3134
3135 We return -1 if no match, -2 if an internal error (such as the
3136 failure stack overflowing). Otherwise, we return the length of the
3137 matched substring. */
3138
3139int
3140re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
3141 struct re_pattern_buffer *bufp;
3142 const char *string1, *string2;
3143 int size1, size2;
3144 int pos;
3145 struct re_registers *regs;
3146 int stop;
3147{
3148 /* General temporaries. */
3149 int mcnt;
3150 unsigned char *p1;
3151
3152 /* Just past the end of the corresponding string. */
3153 const char *end1, *end2;
3154
3155 /* Pointers into string1 and string2, just past the last characters in
3156 each to consider matching. */
3157 const char *end_match_1, *end_match_2;
3158
3159 /* Where we are in the data, and the end of the current string. */
3160 const char *d, *dend;
3161
3162 /* Where we are in the pattern, and the end of the pattern. */
3163 unsigned char *p = bufp->buffer;
3164 register unsigned char *pend = p + bufp->used;
3165
3166 /* We use this to map every character in the string. */
3167 char *translate = bufp->translate;
3168
3169 /* Failure point stack. Each place that can handle a failure further
3170 down the line pushes a failure point on this stack. It consists of
3171 restart, regend, and reg_info for all registers corresponding to
3172 the subexpressions we're currently inside, plus the number of such
3173 registers, and, finally, two char *'s. The first char * is where
3174 to resume scanning the pattern; the second one is where to resume
3175 scanning the strings. If the latter is zero, the failure point is
3176 a ``dummy''; if a failure happens and the failure point is a dummy,
3177 it gets discarded and the next next one is tried. */
3178 fail_stack_type fail_stack;
3179#ifdef DEBUG
3180 static unsigned failure_id = 0;
3181 unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
3182#endif
3183
3184 /* We fill all the registers internally, independent of what we
3185 return, for use in backreferences. The number here includes
3186 an element for register zero. */
3187 unsigned num_regs = bufp->re_nsub + 1;
3188
3189 /* The currently active registers. */
3190 unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
3191 unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
3192
3193 /* Information on the contents of registers. These are pointers into
3194 the input strings; they record just what was matched (on this
3195 attempt) by a subexpression part of the pattern, that is, the
3196 regnum-th regstart pointer points to where in the pattern we began
3197 matching and the regnum-th regend points to right after where we
3198 stopped matching the regnum-th subexpression. (The zeroth register
3199 keeps track of what the whole pattern matches.) */
3200 const char **regstart = NULL, **regend = NULL;
3201
3202 /* If a group that's operated upon by a repetition operator fails to
3203 match anything, then the register for its start will need to be
3204 restored because it will have been set to wherever in the string we
3205 are when we last see its open-group operator. Similarly for a
3206 register's end. */
3207 const char **old_regstart = NULL, **old_regend = NULL;
3208
3209 /* The is_active field of reg_info helps us keep track of which (possibly
3210 nested) subexpressions we are currently in. The matched_something
3211 field of reg_info[reg_num] helps us tell whether or not we have
3212 matched any of the pattern so far this time through the reg_num-th
3213 subexpression. These two fields get reset each time through any
3214 loop their register is in. */
3215 register_info_type *reg_info = NULL;
3216
3217 /* The following record the register info as found in the above
3218 variables when we find a match better than any we've seen before.
3219 This happens as we backtrack through the failure points, which in
3220 turn happens only if we have not yet matched the entire string. */
3221 unsigned best_regs_set = false;
3222 const char **best_regstart = NULL, **best_regend = NULL;
3223
3224 /* Logically, this is `best_regend[0]'. But we don't want to have to
3225 allocate space for that if we're not allocating space for anything
3226 else (see below). Also, we never need info about register 0 for
3227 any of the other register vectors, and it seems rather a kludge to
3228 treat `best_regend' differently than the rest. So we keep track of
3229 the end of the best match so far in a separate variable. We
3230 initialize this to NULL so that when we backtrack the first time
3231 and need to test it, it's not garbage. */
3232 const char *match_end = NULL;
3233
3234 /* Used when we pop values we don't care about. */
3235 const char **reg_dummy = NULL;
3236 register_info_type *reg_info_dummy = NULL;
3237
3238#ifdef DEBUG
3239 /* Counts the total number of registers pushed. */
3240 unsigned num_regs_pushed = 0;
3241#endif
3242
3243 DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
3244
3245 INIT_FAIL_STACK ();
3246
3247 /* Do not bother to initialize all the register variables if there are
3248 no groups in the pattern, as it takes a fair amount of time. If
3249 there are groups, we include space for register 0 (the whole
3250 pattern), even though we never use it, since it simplifies the
3251 array indexing. We should fix this. */
3252 if (bufp->re_nsub)
3253 {
3254 regstart = REGEX_TALLOC (num_regs, const char *);
3255 regend = REGEX_TALLOC (num_regs, const char *);
3256 old_regstart = REGEX_TALLOC (num_regs, const char *);
3257 old_regend = REGEX_TALLOC (num_regs, const char *);
3258 best_regstart = REGEX_TALLOC (num_regs, const char *);
3259 best_regend = REGEX_TALLOC (num_regs, const char *);
3260 reg_info = REGEX_TALLOC (num_regs, register_info_type);
3261 reg_dummy = REGEX_TALLOC (num_regs, const char *);
3262 reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
3263
3264 if (!(regstart && regend && old_regstart && old_regend && reg_info
3265 && best_regstart && best_regend && reg_dummy && reg_info_dummy))
3266 {
3267 FREE_VARIABLES ();
3268 return -2;
3269 }
3270 }
3271#ifdef REGEX_MALLOC
3272 else
3273 {
3274 /* We must initialize all our variables to NULL, so that
3275 `FREE_VARIABLES' doesn't try to free them. */
3276 regstart = regend = old_regstart = old_regend = best_regstart
3277 = best_regend = reg_dummy = NULL;
3278 reg_info = reg_info_dummy = (register_info_type *) NULL;
3279 }
3280#endif /* REGEX_MALLOC */
3281
3282 /* The starting position is bogus. */
3283 if (pos < 0 || pos > size1 + size2)
3284 {
3285 FREE_VARIABLES ();
3286 return -1;
3287 }
3288
3289 /* Initialize subexpression text positions to -1 to mark ones that no
3290 start_memory/stop_memory has been seen for. Also initialize the
3291 register information struct. */
3292 for (mcnt = 1; mcnt < num_regs; mcnt++)
3293 {
3294 regstart[mcnt] = regend[mcnt]
3295 = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
3296
3297 REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
3298 IS_ACTIVE (reg_info[mcnt]) = 0;
3299 MATCHED_SOMETHING (reg_info[mcnt]) = 0;
3300 EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
3301 }
3302
3303 /* We move `string1' into `string2' if the latter's empty -- but not if
3304 `string1' is null. */
3305 if (size2 == 0 && string1 != NULL)
3306 {
3307 string2 = string1;
3308 size2 = size1;
3309 string1 = 0;
3310 size1 = 0;
3311 }
3312 end1 = string1 + size1;
3313 end2 = string2 + size2;
3314
3315 /* Compute where to stop matching, within the two strings. */
3316 if (stop <= size1)
3317 {
3318 end_match_1 = string1 + stop;
3319 end_match_2 = string2;
3320 }
3321 else
3322 {
3323 end_match_1 = end1;
3324 end_match_2 = string2 + stop - size1;
3325 }
3326
3327 /* `p' scans through the pattern as `d' scans through the data.
3328 `dend' is the end of the input string that `d' points within. `d'
3329 is advanced into the following input string whenever necessary, but
3330 this happens before fetching; therefore, at the beginning of the
3331 loop, `d' can be pointing at the end of a string, but it cannot
3332 equal `string2'. */
3333 if (size1 > 0 && pos <= size1)
3334 {
3335 d = string1 + pos;
3336 dend = end_match_1;
3337 }
3338 else
3339 {
3340 d = string2 + pos - size1;
3341 dend = end_match_2;
3342 }
3343
3344 DEBUG_PRINT1 ("The compiled pattern is: ");
3345 DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
3346 DEBUG_PRINT1 ("The string to match is: `");
3347 DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
3348 DEBUG_PRINT1 ("'\n");
3349
3350 /* This loops over pattern commands. It exits by returning from the
3351 function if the match is complete, or it drops through if the match
3352 fails at this starting point in the input data. */
3353 for (;;)
3354 {
3355 DEBUG_PRINT2 ("\n0x%x: ", p);
3356
3357 if (p == pend)
3358 { /* End of pattern means we might have succeeded. */
3359 DEBUG_PRINT1 ("end of pattern ... ");
3360
3361 /* If we haven't matched the entire string, and we want the
3362 longest match, try backtracking. */
3363 if (d != end_match_2)
3364 {
3365 DEBUG_PRINT1 ("backtracking.\n");
3366
3367 if (!FAIL_STACK_EMPTY ())
3368 { /* More failure points to try. */
3369 boolean same_str_p = (FIRST_STRING_P (match_end)
3370 == MATCHING_IN_FIRST_STRING);
3371
3372 /* If exceeds best match so far, save it. */
3373 if (!best_regs_set
3374 || (same_str_p && d > match_end)
3375 || (!same_str_p && !MATCHING_IN_FIRST_STRING))
3376 {
3377 best_regs_set = true;
3378 match_end = d;
3379
3380 DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
3381
3382 for (mcnt = 1; mcnt < num_regs; mcnt++)
3383 {
3384 best_regstart[mcnt] = regstart[mcnt];
3385 best_regend[mcnt] = regend[mcnt];
3386 }
3387 }
3388 goto fail;
3389 }
3390
3391 /* If no failure points, don't restore garbage. */
3392 else if (best_regs_set)
3393 {
3394 restore_best_regs:
3395 /* Restore best match. It may happen that `dend ==
3396 end_match_1' while the restored d is in string2.
3397 For example, the pattern `x.*y.*z' against the
3398 strings `x-' and `y-z-', if the two strings are
3399 not consecutive in memory. */
3400 DEBUG_PRINT1 ("Restoring best registers.\n");
3401
3402 d = match_end;
3403 dend = ((d >= string1 && d <= end1)
3404 ? end_match_1 : end_match_2);
3405
3406 for (mcnt = 1; mcnt < num_regs; mcnt++)
3407 {
3408 regstart[mcnt] = best_regstart[mcnt];
3409 regend[mcnt] = best_regend[mcnt];
3410 }
3411 }
3412 } /* d != end_match_2 */
3413
3414 DEBUG_PRINT1 ("Accepting match.\n");
3415
3416 /* If caller wants register contents data back, do it. */
3417 if (regs && !bufp->no_sub)
3418 {
3419 /* Have the register data arrays been allocated? */
3420 if (bufp->regs_allocated == REGS_UNALLOCATED)
3421 { /* No. So allocate them with malloc. We need one
3422 extra element beyond `num_regs' for the `-1' marker
3423 GNU code uses. */
3424 regs->num_regs = MAX (RE_NREGS, num_regs + 1);
3425 regs->start = TALLOC (regs->num_regs, regoff_t);
3426 regs->end = TALLOC (regs->num_regs, regoff_t);
3427 if (regs->start == NULL || regs->end == NULL)
3428 return -2;
3429 bufp->regs_allocated = REGS_REALLOCATE;
3430 }
3431 else if (bufp->regs_allocated == REGS_REALLOCATE)
3432 { /* Yes. If we need more elements than were already
3433 allocated, reallocate them. If we need fewer, just
3434 leave it alone. */
3435 if (regs->num_regs < num_regs + 1)
3436 {
3437 regs->num_regs = num_regs + 1;
3438 RETALLOC (regs->start, regs->num_regs, regoff_t);
3439 RETALLOC (regs->end, regs->num_regs, regoff_t);
3440 if (regs->start == NULL || regs->end == NULL)
3441 return -2;
3442 }
3443 }
3444 else
3445 assert (bufp->regs_allocated == REGS_FIXED);
3446
3447 /* Convert the pointer data in `regstart' and `regend' to
3448 indices. Register zero has to be set differently,
3449 since we haven't kept track of any info for it. */
3450 if (regs->num_regs > 0)
3451 {
3452 regs->start[0] = pos;
3453 regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1
3454 : d - string2 + size1);
3455 }
3456
3457 /* Go through the first `min (num_regs, regs->num_regs)'
3458 registers, since that is all we initialized. */
3459 for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++)
3460 {
3461 if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
3462 regs->start[mcnt] = regs->end[mcnt] = -1;
3463 else
3464 {
3465 regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]);
3466 regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]);
3467 }
3468 }
3469
3470 /* If the regs structure we return has more elements than
3471 were in the pattern, set the extra elements to -1. If
3472 we (re)allocated the registers, this is the case,
3473 because we always allocate enough to have at least one
3474 -1 at the end. */
3475 for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
3476 regs->start[mcnt] = regs->end[mcnt] = -1;
3477 } /* regs && !bufp->no_sub */
3478
3479 FREE_VARIABLES ();
3480 DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
3481 nfailure_points_pushed, nfailure_points_popped,
3482 nfailure_points_pushed - nfailure_points_popped);
3483 DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
3484
3485 mcnt = d - pos - (MATCHING_IN_FIRST_STRING
3486 ? string1
3487 : string2 - size1);
3488
3489 DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
3490
3491 return mcnt;
3492 }
3493
3494 /* Otherwise match next pattern command. */
3495#ifdef SWITCH_ENUM_BUG
3496 switch ((int) ((re_opcode_t) *p++))
3497#else
3498 switch ((re_opcode_t) *p++)
3499#endif
3500 {
3501 /* Ignore these. Used to ignore the n of succeed_n's which
3502 currently have n == 0. */
3503 case no_op:
3504 DEBUG_PRINT1 ("EXECUTING no_op.\n");
3505 break;
3506
3507
3508 /* Match the next n pattern characters exactly. The following
3509 byte in the pattern defines n, and the n bytes after that
3510 are the characters to match. */
3511 case exactn:
3512 mcnt = *p++;
3513 DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
3514
3515 /* This is written out as an if-else so we don't waste time
3516 testing `translate' inside the loop. */
3517 if (translate)
3518 {
3519 do
3520 {
3521 PREFETCH ();
3522 if (translate[(unsigned char) *d++] != (char) *p++)
3523 goto fail;
3524 }
3525 while (--mcnt);
3526 }
3527 else
3528 {
3529 do
3530 {
3531 PREFETCH ();
3532 if (*d++ != (char) *p++) goto fail;
3533 }
3534 while (--mcnt);
3535 }
3536 SET_REGS_MATCHED ();
3537 break;
3538
3539
3540 /* Match any character except possibly a newline or a null. */
3541 case anychar:
3542 DEBUG_PRINT1 ("EXECUTING anychar.\n");
3543
3544 PREFETCH ();
3545
3546 if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
3547 || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
3548 goto fail;
3549
3550 SET_REGS_MATCHED ();
3551 DEBUG_PRINT2 (" Matched `%d'.\n", *d);
3552 d++;
3553 break;
3554
3555
3556 case charset:
3557 case charset_not:
3558 {
3559 register unsigned char c;
3560 boolean not = (re_opcode_t) *(p - 1) == charset_not;
3561
3562 DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
3563
3564 PREFETCH ();
3565 c = TRANSLATE (*d); /* The character to match. */
3566
3567 /* Cast to `unsigned' instead of `unsigned char' in case the
3568 bit list is a full 32 bytes long. */
3569 if (c < (unsigned) (*p * BYTEWIDTH)
3570 && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
3571 not = !not;
3572
3573 p += 1 + *p;
3574
3575 if (!not) goto fail;
3576
3577 SET_REGS_MATCHED ();
3578 d++;
3579 break;
3580 }
3581
3582
3583 /* The beginning of a group is represented by start_memory.
3584 The arguments are the register number in the next byte, and the
3585 number of groups inner to this one in the next. The text
3586 matched within the group is recorded (in the internal
3587 registers data structure) under the register number. */
3588 case start_memory:
3589 DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
3590
3591 /* Find out if this group can match the empty string. */
3592 p1 = p; /* To send to group_match_null_string_p. */
3593
3594 if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
3595 REG_MATCH_NULL_STRING_P (reg_info[*p])
3596 = group_match_null_string_p (&p1, pend, reg_info);
3597
3598 /* Save the position in the string where we were the last time
3599 we were at this open-group operator in case the group is
3600 operated upon by a repetition operator, e.g., with `(a*)*b'
3601 against `ab'; then we want to ignore where we are now in
3602 the string in case this attempt to match fails. */
3603 old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
3604 ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
3605 : regstart[*p];
3606 DEBUG_PRINT2 (" old_regstart: %d\n",
3607 POINTER_TO_OFFSET (old_regstart[*p]));
3608
3609 regstart[*p] = d;
3610 DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
3611
3612 IS_ACTIVE (reg_info[*p]) = 1;
3613 MATCHED_SOMETHING (reg_info[*p]) = 0;
3614
3615 /* This is the new highest active register. */
3616 highest_active_reg = *p;
3617
3618 /* If nothing was active before, this is the new lowest active
3619 register. */
3620 if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
3621 lowest_active_reg = *p;
3622
3623 /* Move past the register number and inner group count. */
3624 p += 2;
3625 break;
3626
3627
3628 /* The stop_memory opcode represents the end of a group. Its
3629 arguments are the same as start_memory's: the register
3630 number, and the number of inner groups. */
3631 case stop_memory:
3632 DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
3633
3634 /* We need to save the string position the last time we were at
3635 this close-group operator in case the group is operated
3636 upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
3637 against `aba'; then we want to ignore where we are now in
3638 the string in case this attempt to match fails. */
3639 old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
3640 ? REG_UNSET (regend[*p]) ? d : regend[*p]
3641 : regend[*p];
3642 DEBUG_PRINT2 (" old_regend: %d\n",
3643 POINTER_TO_OFFSET (old_regend[*p]));
3644
3645 regend[*p] = d;
3646 DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
3647
3648 /* This register isn't active anymore. */
3649 IS_ACTIVE (reg_info[*p]) = 0;
3650
3651 /* If this was the only register active, nothing is active
3652 anymore. */
3653 if (lowest_active_reg == highest_active_reg)
3654 {
3655 lowest_active_reg = NO_LOWEST_ACTIVE_REG;
3656 highest_active_reg = NO_HIGHEST_ACTIVE_REG;
3657 }
3658 else
3659 { /* We must scan for the new highest active register, since
3660 it isn't necessarily one less than now: consider
3661 (a(b)c(d(e)f)g). When group 3 ends, after the f), the
3662 new highest active register is 1. */
3663 unsigned char r = *p - 1;
3664 while (r > 0 && !IS_ACTIVE (reg_info[r]))
3665 r--;
3666
3667 /* If we end up at register zero, that means that we saved
3668 the registers as the result of an `on_failure_jump', not
3669 a `start_memory', and we jumped to past the innermost
3670 `stop_memory'. For example, in ((.)*) we save
3671 registers 1 and 2 as a result of the *, but when we pop
3672 back to the second ), we are at the stop_memory 1.
3673 Thus, nothing is active. */
3674 if (r == 0)
3675 {
3676 lowest_active_reg = NO_LOWEST_ACTIVE_REG;
3677 highest_active_reg = NO_HIGHEST_ACTIVE_REG;
3678 }
3679 else
3680 highest_active_reg = r;
3681 }
3682
3683 /* If just failed to match something this time around with a
3684 group that's operated on by a repetition operator, try to
3685 force exit from the ``loop'', and restore the register
3686 information for this group that we had before trying this
3687 last match. */
3688 if ((!MATCHED_SOMETHING (reg_info[*p])
3689 || (re_opcode_t) p[-3] == start_memory)
3690 && (p + 2) < pend)
3691 {
3692 boolean is_a_jump_n = false;
3693
3694 p1 = p + 2;
3695 mcnt = 0;
3696 switch ((re_opcode_t) *p1++)
3697 {
3698 case jump_n:
3699 is_a_jump_n = true;
3700 case pop_failure_jump:
3701 case maybe_pop_jump:
3702 case jump:
3703 case dummy_failure_jump:
3704 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
3705 if (is_a_jump_n)
3706 p1 += 2;
3707 break;
3708
3709 default:
3710 /* do nothing */ ;
3711 }
3712 p1 += mcnt;
3713
3714 /* If the next operation is a jump backwards in the pattern
3715 to an on_failure_jump right before the start_memory
3716 corresponding to this stop_memory, exit from the loop
3717 by forcing a failure after pushing on the stack the
3718 on_failure_jump's jump in the pattern, and d. */
3719 if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
3720 && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
3721 {
3722 /* If this group ever matched anything, then restore
3723 what its registers were before trying this last
3724 failed match, e.g., with `(a*)*b' against `ab' for
3725 regstart[1], and, e.g., with `((a*)*(b*)*)*'
3726 against `aba' for regend[3].
3727
3728 Also restore the registers for inner groups for,
3729 e.g., `((a*)(b*))*' against `aba' (register 3 would
3730 otherwise get trashed). */
3731
3732 if (EVER_MATCHED_SOMETHING (reg_info[*p]))
3733 {
3734 unsigned r;
3735
3736 EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
3737
3738 /* Restore this and inner groups' (if any) registers. */
3739 for (r = *p; r < *p + *(p + 1); r++)
3740 {
3741 regstart[r] = old_regstart[r];
3742
3743 /* xx why this test? */
3744 if ((int) old_regend[r] >= (int) regstart[r])
3745 regend[r] = old_regend[r];
3746 }
3747 }
3748 p1++;
3749 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
3750 PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
3751
3752 goto fail;
3753 }
3754 }
3755
3756 /* Move past the register number and the inner group count. */
3757 p += 2;
3758 break;
3759
3760
3761 /* \<digit> has been turned into a `duplicate' command which is
3762 followed by the numeric value of <digit> as the register number. */
3763 case duplicate:
3764 {
3765 register const char *d2, *dend2;
3766 int regno = *p++; /* Get which register to match against. */
3767 DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
3768
3769 /* Can't back reference a group which we've never matched. */
3770 if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
3771 goto fail;
3772
3773 /* Where in input to try to start matching. */
3774 d2 = regstart[regno];
3775
3776 /* Where to stop matching; if both the place to start and
3777 the place to stop matching are in the same string, then
3778 set to the place to stop, otherwise, for now have to use
3779 the end of the first string. */
3780
3781 dend2 = ((FIRST_STRING_P (regstart[regno])
3782 == FIRST_STRING_P (regend[regno]))
3783 ? regend[regno] : end_match_1);
3784 for (;;)
3785 {
3786 /* If necessary, advance to next segment in register
3787 contents. */
3788 while (d2 == dend2)
3789 {
3790 if (dend2 == end_match_2) break;
3791 if (dend2 == regend[regno]) break;
3792
3793 /* End of string1 => advance to string2. */
3794 d2 = string2;
3795 dend2 = regend[regno];
3796 }
3797 /* At end of register contents => success */
3798 if (d2 == dend2) break;
3799
3800 /* If necessary, advance to next segment in data. */
3801 PREFETCH ();
3802
3803 /* How many characters left in this segment to match. */
3804 mcnt = dend - d;
3805
3806 /* Want how many consecutive characters we can match in
3807 one shot, so, if necessary, adjust the count. */
3808 if (mcnt > dend2 - d2)
3809 mcnt = dend2 - d2;
3810
3811 /* Compare that many; failure if mismatch, else move
3812 past them. */
3813 if (translate
3814 ? bcmp_translate (d, d2, mcnt, translate)
3815 : bcmp (d, d2, mcnt))
3816 goto fail;
3817 d += mcnt, d2 += mcnt;
3818 }
3819 }
3820 break;
3821
3822
3823 /* begline matches the empty string at the beginning of the string
3824 (unless `not_bol' is set in `bufp'), and, if
3825 `newline_anchor' is set, after newlines. */
3826 case begline:
3827 DEBUG_PRINT1 ("EXECUTING begline.\n");
3828
3829 if (AT_STRINGS_BEG (d))
3830 {
3831 if (!bufp->not_bol) break;
3832 }
3833 else if (d[-1] == '\n' && bufp->newline_anchor)
3834 {
3835 break;
3836 }
3837 /* In all other cases, we fail. */
3838 goto fail;
3839
3840
3841 /* endline is the dual of begline. */
3842 case endline:
3843 DEBUG_PRINT1 ("EXECUTING endline.\n");
3844
3845 if (AT_STRINGS_END (d))
3846 {
3847 if (!bufp->not_eol) break;
3848 }
3849
3850 /* We have to ``prefetch'' the next character. */
3851 else if ((d == end1 ? *string2 : *d) == '\n'
3852 && bufp->newline_anchor)
3853 {
3854 break;
3855 }
3856 goto fail;
3857
3858
3859 /* Match at the very beginning of the data. */
3860 case begbuf:
3861 DEBUG_PRINT1 ("EXECUTING begbuf.\n");
3862 if (AT_STRINGS_BEG (d))
3863 break;
3864 goto fail;
3865
3866
3867 /* Match at the very end of the data. */
3868 case endbuf:
3869 DEBUG_PRINT1 ("EXECUTING endbuf.\n");
3870 if (AT_STRINGS_END (d))
3871 break;
3872 goto fail;
3873
3874
3875 /* on_failure_keep_string_jump is used to optimize `.*\n'. It
3876 pushes NULL as the value for the string on the stack. Then
3877 `pop_failure_point' will keep the current value for the
3878 string, instead of restoring it. To see why, consider
3879 matching `foo\nbar' against `.*\n'. The .* matches the foo;
3880 then the . fails against the \n. But the next thing we want
3881 to do is match the \n against the \n; if we restored the
3882 string value, we would be back at the foo.
3883
3884 Because this is used only in specific cases, we don't need to
3885 check all the things that `on_failure_jump' does, to make
3886 sure the right things get saved on the stack. Hence we don't
3887 share its code. The only reason to push anything on the
3888 stack at all is that otherwise we would have to change
3889 `anychar's code to do something besides goto fail in this
3890 case; that seems worse than this. */
3891 case on_failure_keep_string_jump:
3892 DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
3893
3894 EXTRACT_NUMBER_AND_INCR (mcnt, p);
3895 DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
3896
3897 PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
3898 break;
3899
3900
3901 /* Uses of on_failure_jump:
3902
3903 Each alternative starts with an on_failure_jump that points
3904 to the beginning of the next alternative. Each alternative
3905 except the last ends with a jump that in effect jumps past
3906 the rest of the alternatives. (They really jump to the
3907 ending jump of the following alternative, because tensioning
3908 these jumps is a hassle.)
3909
3910 Repeats start with an on_failure_jump that points past both
3911 the repetition text and either the following jump or
3912 pop_failure_jump back to this on_failure_jump. */
3913 case on_failure_jump:
3914 on_failure:
3915 DEBUG_PRINT1 ("EXECUTING on_failure_jump");
3916
3917 EXTRACT_NUMBER_AND_INCR (mcnt, p);
3918 DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
3919
3920 /* If this on_failure_jump comes right before a group (i.e.,
3921 the original * applied to a group), save the information
3922 for that group and all inner ones, so that if we fail back
3923 to this point, the group's information will be correct.
3924 For example, in \(a*\)*\1, we need the preceding group,
3925 and in \(\(a*\)b*\)\2, we need the inner group. */
3926
3927 /* We can't use `p' to check ahead because we push
3928 a failure point to `p + mcnt' after we do this. */
3929 p1 = p;
3930
3931 /* We need to skip no_op's before we look for the
3932 start_memory in case this on_failure_jump is happening as
3933 the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
3934 against aba. */
3935 while (p1 < pend && (re_opcode_t) *p1 == no_op)
3936 p1++;
3937
3938 if (p1 < pend && (re_opcode_t) *p1 == start_memory)
3939 {
3940 /* We have a new highest active register now. This will
3941 get reset at the start_memory we are about to get to,
3942 but we will have saved all the registers relevant to
3943 this repetition op, as described above. */
3944 highest_active_reg = *(p1 + 1) + *(p1 + 2);
3945 if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
3946 lowest_active_reg = *(p1 + 1);
3947 }
3948
3949 DEBUG_PRINT1 (":\n");
3950 PUSH_FAILURE_POINT (p + mcnt, d, -2);
3951 break;
3952
3953
3954 /* A smart repeat ends with `maybe_pop_jump'.
3955 We change it to either `pop_failure_jump' or `jump'. */
3956 case maybe_pop_jump:
3957 EXTRACT_NUMBER_AND_INCR (mcnt, p);
3958 DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
3959 {
3960 register unsigned char *p2 = p;
3961
3962 /* Compare the beginning of the repeat with what in the
3963 pattern follows its end. If we can establish that there
3964 is nothing that they would both match, i.e., that we
3965 would have to backtrack because of (as in, e.g., `a*a')
3966 then we can change to pop_failure_jump, because we'll
3967 never have to backtrack.
3968
3969 This is not true in the case of alternatives: in
3970 `(a|ab)*' we do need to backtrack to the `ab' alternative
3971 (e.g., if the string was `ab'). But instead of trying to
3972 detect that here, the alternative has put on a dummy
3973 failure point which is what we will end up popping. */
3974
3975 /* Skip over open/close-group commands. */
3976 while (p2 + 2 < pend
3977 && ((re_opcode_t) *p2 == stop_memory
3978 || (re_opcode_t) *p2 == start_memory))
3979 p2 += 3; /* Skip over args, too. */
3980
3981 /* If we're at the end of the pattern, we can change. */
3982 if (p2 == pend)
3983 {
3984 /* Consider what happens when matching ":\(.*\)"
3985 against ":/". I don't really understand this code
3986 yet. */
3987 p[-3] = (unsigned char) pop_failure_jump;
3988 DEBUG_PRINT1
3989 (" End of pattern: change to `pop_failure_jump'.\n");
3990 }
3991
3992 else if ((re_opcode_t) *p2 == exactn
3993 || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
3994 {
3995 register unsigned char c
3996 = *p2 == (unsigned char) endline ? '\n' : p2[2];
3997 p1 = p + mcnt;
3998
3999 /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
4000 to the `maybe_finalize_jump' of this case. Examine what
4001 follows. */
4002 if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
4003 {
4004 p[-3] = (unsigned char) pop_failure_jump;
4005 DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n",
4006 c, p1[5]);
4007 }
4008
4009 else if ((re_opcode_t) p1[3] == charset
4010 || (re_opcode_t) p1[3] == charset_not)
4011 {
4012 int not = (re_opcode_t) p1[3] == charset_not;
4013
4014 if (c < (unsigned char) (p1[4] * BYTEWIDTH)
4015 && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
4016 not = !not;
4017
4018 /* `not' is equal to 1 if c would match, which means
4019 that we can't change to pop_failure_jump. */
4020 if (!not)
4021 {
4022 p[-3] = (unsigned char) pop_failure_jump;
4023 DEBUG_PRINT1 (" No match => pop_failure_jump.\n");
4024 }
4025 }
4026 }
4027 }
4028 p -= 2; /* Point at relative address again. */
4029 if ((re_opcode_t) p[-1] != pop_failure_jump)
4030 {
4031 p[-1] = (unsigned char) jump;
4032 DEBUG_PRINT1 (" Match => jump.\n");
4033 goto unconditional_jump;
4034 }
4035 /* Note fall through. */
4036
4037
4038 /* The end of a simple repeat has a pop_failure_jump back to
4039 its matching on_failure_jump, where the latter will push a
4040 failure point. The pop_failure_jump takes off failure
4041 points put on by this pop_failure_jump's matching
4042 on_failure_jump; we got through the pattern to here from the
4043 matching on_failure_jump, so didn't fail. */
4044 case pop_failure_jump:
4045 {
4046 /* We need to pass separate storage for the lowest and
4047 highest registers, even though we don't care about the
4048 actual values. Otherwise, we will restore only one
4049 register from the stack, since lowest will == highest in
4050 `pop_failure_point'. */
4051 unsigned dummy_low_reg, dummy_high_reg;
4052 unsigned char *pdummy;
4053 const char *sdummy;
4054
4055 DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
4056 POP_FAILURE_POINT (sdummy, pdummy,
4057 dummy_low_reg, dummy_high_reg,
4058 reg_dummy, reg_dummy, reg_info_dummy);
4059 }
4060 /* Note fall through. */
4061
4062
4063 /* Unconditionally jump (without popping any failure points). */
4064 case jump:
4065 unconditional_jump:
4066 EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
4067 DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
4068 p += mcnt; /* Do the jump. */
4069 DEBUG_PRINT2 ("(to 0x%x).\n", p);
4070 break;
4071
4072
4073 /* We need this opcode so we can detect where alternatives end
4074 in `group_match_null_string_p' et al. */
4075 case jump_past_alt:
4076 DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
4077 goto unconditional_jump;
4078
4079
4080 /* Normally, the on_failure_jump pushes a failure point, which
4081 then gets popped at pop_failure_jump. We will end up at
4082 pop_failure_jump, also, and with a pattern of, say, `a+', we
4083 are skipping over the on_failure_jump, so we have to push
4084 something meaningless for pop_failure_jump to pop. */
4085 case dummy_failure_jump:
4086 DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
4087 /* It doesn't matter what we push for the string here. What
4088 the code at `fail' tests is the value for the pattern. */
4089 PUSH_FAILURE_POINT (0, 0, -2);
4090 goto unconditional_jump;
4091
4092
4093 /* At the end of an alternative, we need to push a dummy failure
4094 point in case we are followed by a `pop_failure_jump', because
4095 we don't want the failure point for the alternative to be
4096 popped. For example, matching `(a|ab)*' against `aab'
4097 requires that we match the `ab' alternative. */
4098 case push_dummy_failure:
4099 DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
4100 /* See comments just above at `dummy_failure_jump' about the
4101 two zeroes. */
4102 PUSH_FAILURE_POINT (0, 0, -2);
4103 break;
4104
4105 /* Have to succeed matching what follows at least n times.
4106 After that, handle like `on_failure_jump'. */
4107 case succeed_n:
4108 EXTRACT_NUMBER (mcnt, p + 2);
4109 DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
4110
4111 assert (mcnt >= 0);
4112 /* Originally, this is how many times we HAVE to succeed. */
4113 if (mcnt > 0)
4114 {
4115 mcnt--;
4116 p += 2;
4117 STORE_NUMBER_AND_INCR (p, mcnt);
4118 DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt);
4119 }
4120 else if (mcnt == 0)
4121 {
4122 DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2);
4123 p[2] = (unsigned char) no_op;
4124 p[3] = (unsigned char) no_op;
4125 goto on_failure;
4126 }
4127 break;
4128
4129 case jump_n:
4130 EXTRACT_NUMBER (mcnt, p + 2);
4131 DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
4132
4133 /* Originally, this is how many times we CAN jump. */
4134 if (mcnt)
4135 {
4136 mcnt--;
4137 STORE_NUMBER (p + 2, mcnt);
4138 goto unconditional_jump;
4139 }
4140 /* If don't have to jump any more, skip over the rest of command. */
4141 else
4142 p += 4;
4143 break;
4144
4145 case set_number_at:
4146 {
4147 DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
4148
4149 EXTRACT_NUMBER_AND_INCR (mcnt, p);
4150 p1 = p + mcnt;
4151 EXTRACT_NUMBER_AND_INCR (mcnt, p);
4152 DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
4153 STORE_NUMBER (p1, mcnt);
4154 break;
4155 }
4156
4157 case wordbound:
4158 DEBUG_PRINT1 ("EXECUTING wordbound.\n");
4159 if (AT_WORD_BOUNDARY (d))
4160 break;
4161 goto fail;
4162
4163 case notwordbound:
4164 DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
4165 if (AT_WORD_BOUNDARY (d))
4166 goto fail;
4167 break;
4168
4169 case wordbeg:
4170 DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
4171 if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
4172 break;
4173 goto fail;
4174
4175 case wordend:
4176 DEBUG_PRINT1 ("EXECUTING wordend.\n");
4177 if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
4178 && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
4179 break;
4180 goto fail;
4181
4182#ifdef emacs
4183#ifdef emacs19
4184 case before_dot:
4185 DEBUG_PRINT1 ("EXECUTING before_dot.\n");
4186 if (PTR_CHAR_POS ((unsigned char *) d) >= point)
4187 goto fail;
4188 break;
4189
4190 case at_dot:
4191 DEBUG_PRINT1 ("EXECUTING at_dot.\n");
4192 if (PTR_CHAR_POS ((unsigned char *) d) != point)
4193 goto fail;
4194 break;
4195
4196 case after_dot:
4197 DEBUG_PRINT1 ("EXECUTING after_dot.\n");
4198 if (PTR_CHAR_POS ((unsigned char *) d) <= point)
4199 goto fail;
4200 break;
4201#else /* not emacs19 */
4202 case at_dot:
4203 DEBUG_PRINT1 ("EXECUTING at_dot.\n");
4204 if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point)
4205 goto fail;
4206 break;
4207#endif /* not emacs19 */
4208
4209 case syntaxspec:
4210 DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
4211 mcnt = *p++;
4212 goto matchsyntax;
4213
4214 case wordchar:
4215 DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
4216 mcnt = (int) Sword;
4217 matchsyntax:
4218 PREFETCH ();
4219 if (SYNTAX (*d++) != (enum syntaxcode) mcnt)
4220 goto fail;
4221 SET_REGS_MATCHED ();
4222 break;
4223
4224 case notsyntaxspec:
4225 DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
4226 mcnt = *p++;
4227 goto matchnotsyntax;
4228
4229 case notwordchar:
4230 DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
4231 mcnt = (int) Sword;
4232 matchnotsyntax:
4233 PREFETCH ();
4234 if (SYNTAX (*d++) == (enum syntaxcode) mcnt)
4235 goto fail;
4236 SET_REGS_MATCHED ();
4237 break;
4238
4239#else /* not emacs */
4240 case wordchar:
4241 DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
4242 PREFETCH ();
4243 if (!WORDCHAR_P (d))
4244 goto fail;
4245 SET_REGS_MATCHED ();
4246 d++;
4247 break;
4248
4249 case notwordchar:
4250 DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
4251 PREFETCH ();
4252 if (WORDCHAR_P (d))
4253 goto fail;
4254 SET_REGS_MATCHED ();
4255 d++;
4256 break;
4257#endif /* not emacs */
4258
4259 default:
4260 abort ();
4261 }
4262 continue; /* Successfully executed one pattern command; keep going. */
4263
4264
4265 /* We goto here if a matching operation fails. */
4266 fail:
4267 if (!FAIL_STACK_EMPTY ())
4268 { /* A restart point is known. Restore to that state. */
4269 DEBUG_PRINT1 ("\nFAIL:\n");
4270 POP_FAILURE_POINT (d, p,
4271 lowest_active_reg, highest_active_reg,
4272 regstart, regend, reg_info);
4273
4274 /* If this failure point is a dummy, try the next one. */
4275 if (!p)
4276 goto fail;
4277
4278 /* If we failed to the end of the pattern, don't examine *p. */
4279 assert (p <= pend);
4280 if (p < pend)
4281 {
4282 boolean is_a_jump_n = false;
4283
4284 /* If failed to a backwards jump that's part of a repetition
4285 loop, need to pop this failure point and use the next one. */
4286 switch ((re_opcode_t) *p)
4287 {
4288 case jump_n:
4289 is_a_jump_n = true;
4290 case maybe_pop_jump:
4291 case pop_failure_jump:
4292 case jump:
4293 p1 = p + 1;
4294 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
4295 p1 += mcnt;
4296
4297 if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
4298 || (!is_a_jump_n
4299 && (re_opcode_t) *p1 == on_failure_jump))
4300 goto fail;
4301 break;
4302 default:
4303 /* do nothing */ ;
4304 }
4305 }
4306
4307 if (d >= string1 && d <= end1)
4308 dend = end_match_1;
4309 }
4310 else
4311 break; /* Matching at this starting point really fails. */
4312 } /* for (;;) */
4313
4314 if (best_regs_set)
4315 goto restore_best_regs;
4316
4317 FREE_VARIABLES ();
4318
4319 return -1; /* Failure to match. */
4320} /* re_match_2 */
4321
4322/* Subroutine definitions for re_match_2. */
4323
4324
4325/* We are passed P pointing to a register number after a start_memory.
4326
4327 Return true if the pattern up to the corresponding stop_memory can
4328 match the empty string, and false otherwise.
4329
4330 If we find the matching stop_memory, sets P to point to one past its number.
4331 Otherwise, sets P to an undefined byte less than or equal to END.
4332
4333 We don't handle duplicates properly (yet). */
4334
4335static boolean
4336group_match_null_string_p (p, end, reg_info)
4337 unsigned char **p, *end;
4338 register_info_type *reg_info;
4339{
4340 int mcnt;
4341 /* Point to after the args to the start_memory. */
4342 unsigned char *p1 = *p + 2;
4343
4344 while (p1 < end)
4345 {
4346 /* Skip over opcodes that can match nothing, and return true or
4347 false, as appropriate, when we get to one that can't, or to the
4348 matching stop_memory. */
4349
4350 switch ((re_opcode_t) *p1)
4351 {
4352 /* Could be either a loop or a series of alternatives. */
4353 case on_failure_jump:
4354 p1++;
4355 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
4356
4357 /* If the next operation is not a jump backwards in the
4358 pattern. */
4359
4360 if (mcnt >= 0)
4361 {
4362 /* Go through the on_failure_jumps of the alternatives,
4363 seeing if any of the alternatives cannot match nothing.
4364 The last alternative starts with only a jump,
4365 whereas the rest start with on_failure_jump and end
4366 with a jump, e.g., here is the pattern for `a|b|c':
4367
4368 /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
4369 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
4370 /exactn/1/c
4371
4372 So, we have to first go through the first (n-1)
4373 alternatives and then deal with the last one separately. */
4374
4375
4376 /* Deal with the first (n-1) alternatives, which start
4377 with an on_failure_jump (see above) that jumps to right
4378 past a jump_past_alt. */
4379
4380 while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
4381 {
4382 /* `mcnt' holds how many bytes long the alternative
4383 is, including the ending `jump_past_alt' and
4384 its number. */
4385
4386 if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
4387 reg_info))
4388 return false;
4389
4390 /* Move to right after this alternative, including the
4391 jump_past_alt. */
4392 p1 += mcnt;
4393
4394 /* Break if it's the beginning of an n-th alternative
4395 that doesn't begin with an on_failure_jump. */
4396 if ((re_opcode_t) *p1 != on_failure_jump)
4397 break;
4398
4399 /* Still have to check that it's not an n-th
4400 alternative that starts with an on_failure_jump. */
4401 p1++;
4402 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
4403 if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
4404 {
4405 /* Get to the beginning of the n-th alternative. */
4406 p1 -= 3;
4407 break;
4408 }
4409 }
4410
4411 /* Deal with the last alternative: go back and get number
4412 of the `jump_past_alt' just before it. `mcnt' contains
4413 the length of the alternative. */
4414 EXTRACT_NUMBER (mcnt, p1 - 2);
4415
4416 if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
4417 return false;
4418
4419 p1 += mcnt; /* Get past the n-th alternative. */
4420 } /* if mcnt > 0 */
4421 break;
4422
4423
4424 case stop_memory:
4425 assert (p1[1] == **p);
4426 *p = p1 + 2;
4427 return true;
4428
4429
4430 default:
4431 if (!common_op_match_null_string_p (&p1, end, reg_info))
4432 return false;
4433 }
4434 } /* while p1 < end */
4435
4436 return false;
4437} /* group_match_null_string_p */
4438
4439
4440/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
4441 It expects P to be the first byte of a single alternative and END one
4442 byte past the last. The alternative can contain groups. */
4443
4444static boolean
4445alt_match_null_string_p (p, end, reg_info)
4446 unsigned char *p, *end;
4447 register_info_type *reg_info;
4448{
4449 int mcnt;
4450 unsigned char *p1 = p;
4451
4452 while (p1 < end)
4453 {
4454 /* Skip over opcodes that can match nothing, and break when we get
4455 to one that can't. */
4456
4457 switch ((re_opcode_t) *p1)
4458 {
4459 /* It's a loop. */
4460 case on_failure_jump:
4461 p1++;
4462 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
4463 p1 += mcnt;
4464 break;
4465
4466 default:
4467 if (!common_op_match_null_string_p (&p1, end, reg_info))
4468 return false;
4469 }
4470 } /* while p1 < end */
4471
4472 return true;
4473} /* alt_match_null_string_p */
4474
4475
4476/* Deals with the ops common to group_match_null_string_p and
4477 alt_match_null_string_p.
4478
4479 Sets P to one after the op and its arguments, if any. */
4480
4481static boolean
4482common_op_match_null_string_p (p, end, reg_info)
4483 unsigned char **p, *end;
4484 register_info_type *reg_info;
4485{
4486 int mcnt;
4487 boolean ret;
4488 int reg_no;
4489 unsigned char *p1 = *p;
4490
4491 switch ((re_opcode_t) *p1++)
4492 {
4493 case no_op:
4494 case begline:
4495 case endline:
4496 case begbuf:
4497 case endbuf:
4498 case wordbeg:
4499 case wordend:
4500 case wordbound:
4501 case notwordbound:
4502#ifdef emacs
4503 case before_dot:
4504 case at_dot:
4505 case after_dot:
4506#endif
4507 break;
4508
4509 case start_memory:
4510 reg_no = *p1;
4511 assert (reg_no > 0 && reg_no <= MAX_REGNUM);
4512 ret = group_match_null_string_p (&p1, end, reg_info);
4513
4514 /* Have to set this here in case we're checking a group which
4515 contains a group and a back reference to it. */
4516
4517 if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
4518 REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
4519
4520 if (!ret)
4521 return false;
4522 break;
4523
4524 /* If this is an optimized succeed_n for zero times, make the jump. */
4525 case jump:
4526 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
4527 if (mcnt >= 0)
4528 p1 += mcnt;
4529 else
4530 return false;
4531 break;
4532
4533 case succeed_n:
4534 /* Get to the number of times to succeed. */
4535 p1 += 2;
4536 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
4537
4538 if (mcnt == 0)
4539 {
4540 p1 -= 4;
4541 EXTRACT_NUMBER_AND_INCR (mcnt, p1);
4542 p1 += mcnt;
4543 }
4544 else
4545 return false;
4546 break;
4547
4548 case duplicate:
4549 if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
4550 return false;
4551 break;
4552
4553 case set_number_at:
4554 p1 += 4;
4555
4556 default:
4557 /* All other opcodes mean we cannot match the empty string. */
4558 return false;
4559 }
4560
4561 *p = p1;
4562 return true;
4563} /* common_op_match_null_string_p */
4564
4565
4566/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
4567 bytes; nonzero otherwise. */
4568
4569static int
4570bcmp_translate(
4571 unsigned char *s1,
4572 unsigned char *s2,
4573 int len,
4574 char *translate
4575)
4576{
4577 register unsigned char *p1 = s1, *p2 = s2;
4578 while (len)
4579 {
4580 if (translate[*p1++] != translate[*p2++]) return 1;
4581 len--;
4582 }
4583 return 0;
4584}
4585
4586/* Entry points for GNU code. */
4587
4588/* re_compile_pattern is the GNU regular expression compiler: it
4589 compiles PATTERN (of length SIZE) and puts the result in BUFP.
4590 Returns 0 if the pattern was valid, otherwise an error string.
4591
4592 Assumes the `allocated' (and perhaps `buffer') and `translate' fields
4593 are set in BUFP on entry.
4594
4595 We call regex_compile to do the actual compilation. */
4596
4597const char *
4598re_compile_pattern (pattern, length, bufp)
4599 const char *pattern;
4600 int length;
4601 struct re_pattern_buffer *bufp;
4602{
4603 reg_errcode_t ret;
4604
4605 /* GNU code is written to assume at least RE_NREGS registers will be set
4606 (and at least one extra will be -1). */
4607 bufp->regs_allocated = REGS_UNALLOCATED;
4608
4609 /* And GNU code determines whether or not to get register information
4610 by passing null for the REGS argument to re_match, etc., not by
4611 setting no_sub. */
4612 bufp->no_sub = 0;
4613
4614 /* Match anchors at newline. */
4615 bufp->newline_anchor = 1;
4616
4617 ret = regex_compile (pattern, length, re_syntax_options, bufp);
4618
4619 return re_error_msg[(int) ret];
4620}
4621
4622/* Entry points compatible with 4.2 BSD regex library. We don't define
4623 them if this is an Emacs or POSIX compilation. */
4624
4625#if !defined (emacs) && !defined (_POSIX_SOURCE)
4626
4627/* BSD has one and only one pattern buffer. */
4628static struct re_pattern_buffer re_comp_buf;
4629
4630char *
4631re_comp (s)
4632 const char *s;
4633{
4634 reg_errcode_t ret;
4635
4636 if (!s)
4637 {
4638 if (!re_comp_buf.buffer)
4639 return "No previous regular expression";
4640 return 0;
4641 }
4642
4643 if (!re_comp_buf.buffer)
4644 {
4645 re_comp_buf.buffer = (unsigned char *) malloc (200);
4646 if (re_comp_buf.buffer == NULL)
4647 return "Memory exhausted";
4648 re_comp_buf.allocated = 200;
4649
4650 re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
4651 if (re_comp_buf.fastmap == NULL)
4652 return "Memory exhausted";
4653 }
4654
4655 /* Since `re_exec' always passes NULL for the `regs' argument, we
4656 don't need to initialize the pattern buffer fields which affect it. */
4657
4658 /* Match anchors at newlines. */
4659 re_comp_buf.newline_anchor = 1;
4660
4661 ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
4662
4663 /* Yes, we're discarding `const' here. */
4664 return (char *) re_error_msg[(int) ret];
4665}
4666
4667
4668int
4669re_exec (s)
4670 const char *s;
4671{
4672 const int len = strlen (s);
4673 return
4674 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
4675}
4676#endif /* not emacs and not _POSIX_SOURCE */
4677
4678/* POSIX.2 functions. Don't define these for Emacs. */
4679
4680#ifndef emacs
4681
4682/* regcomp takes a regular expression as a string and compiles it.
4683
4684 PREG is a regex_t *. We do not expect any fields to be initialized,
4685 since POSIX says we shouldn't. Thus, we set
4686
4687 `buffer' to the compiled pattern;
4688 `used' to the length of the compiled pattern;
4689 `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
4690 REG_EXTENDED bit in CFLAGS is set; otherwise, to
4691 RE_SYNTAX_POSIX_BASIC;
4692 `newline_anchor' to REG_NEWLINE being set in CFLAGS;
4693 `fastmap' and `fastmap_accurate' to zero;
4694 `re_nsub' to the number of subexpressions in PATTERN.
4695
4696 PATTERN is the address of the pattern string.
4697
4698 CFLAGS is a series of bits which affect compilation.
4699
4700 If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
4701 use POSIX basic syntax.
4702
4703 If REG_NEWLINE is set, then . and [^...] don't match newline.
4704 Also, regexec will try a match beginning after every newline.
4705
4706 If REG_ICASE is set, then we considers upper- and lowercase
4707 versions of letters to be equivalent when matching.
4708
4709 If REG_NOSUB is set, then when PREG is passed to regexec, that
4710 routine will report only success or failure, and nothing about the
4711 registers.
4712
4713 It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
4714 the return codes and their meanings.) */
4715
4716int
4717regcomp (preg, pattern, cflags)
4718 regex_t *preg;
4719 const char *pattern;
4720 int cflags;
4721{
4722 reg_errcode_t ret;
4723 unsigned syntax
4724 = (cflags & REG_EXTENDED) ?
4725 RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
4726
4727 /* regex_compile will allocate the space for the compiled pattern. */
4728 preg->buffer = 0;
4729 preg->allocated = 0;
4730
4731 /* Don't bother to use a fastmap when searching. This simplifies the
4732 REG_NEWLINE case: if we used a fastmap, we'd have to put all the
4733 characters after newlines into the fastmap. This way, we just try
4734 every character. */
4735 preg->fastmap = 0;
4736
4737 if (cflags & REG_ICASE)
4738 {
4739 unsigned i;
4740
4741 preg->translate = (char *) malloc (CHAR_SET_SIZE);
4742 if (preg->translate == NULL)
4743 return (int) REG_ESPACE;
4744
4745 /* Map uppercase characters to corresponding lowercase ones. */
4746 for (i = 0; i < CHAR_SET_SIZE; i++)
4747 preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
4748 }
4749 else
4750 preg->translate = NULL;
4751
4752 /* If REG_NEWLINE is set, newlines are treated differently. */
4753 if (cflags & REG_NEWLINE)
4754 { /* REG_NEWLINE implies neither . nor [^...] match newline. */
4755 syntax &= ~RE_DOT_NEWLINE;
4756 syntax |= RE_HAT_LISTS_NOT_NEWLINE;
4757 /* It also changes the matching behavior. */
4758 preg->newline_anchor = 1;
4759 }
4760 else
4761 preg->newline_anchor = 0;
4762
4763 preg->no_sub = !!(cflags & REG_NOSUB);
4764
4765 /* POSIX says a null character in the pattern terminates it, so we
4766 can use strlen here in compiling the pattern. */
4767 ret = regex_compile (pattern, strlen (pattern), syntax, preg);
4768
4769 /* POSIX doesn't distinguish between an unmatched open-group and an
4770 unmatched close-group: both are REG_EPAREN. */
4771 if (ret == REG_ERPAREN) ret = REG_EPAREN;
4772
4773 return (int) ret;
4774}
4775
4776
4777/* regexec searches for a given pattern, specified by PREG, in the
4778 string STRING.
4779
4780 If NMATCH is zero or REG_NOSUB was set in the cflags argument to
4781 `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at
4782 least NMATCH elements, and we set them to the offsets of the
4783 corresponding matched substrings.
4784
4785 EFLAGS specifies `execution flags' which affect matching: if
4786 REG_NOTBOL is set, then ^ does not match at the beginning of the
4787 string; if REG_NOTEOL is set, then $ does not match at the end.
4788
4789 We return 0 if we find a match and REG_NOMATCH if not. */
4790
4791int
4792regexec (preg, string, nmatch, pmatch, eflags)
4793 const regex_t *preg;
4794 const char *string;
4795 size_t nmatch;
4796 regmatch_t pmatch[];
4797 int eflags;
4798{
4799 int ret;
4800 struct re_registers regs;
4801 regex_t private_preg;
4802 int len = strlen (string);
4803 boolean want_reg_info = !preg->no_sub && nmatch > 0;
4804
4805 private_preg = *preg;
4806
4807 private_preg.not_bol = !!(eflags & REG_NOTBOL);
4808 private_preg.not_eol = !!(eflags & REG_NOTEOL);
4809
4810 /* The user has told us exactly how many registers to return
4811 information about, via `nmatch'. We have to pass that on to the
4812 matching routines. */
4813 private_preg.regs_allocated = REGS_FIXED;
4814
4815 if (want_reg_info)
4816 {
4817 regs.num_regs = nmatch;
4818 regs.start = TALLOC (nmatch, regoff_t);
4819 regs.end = TALLOC (nmatch, regoff_t);
4820 if (regs.start == NULL || regs.end == NULL)
4821 return (int) REG_NOMATCH;
4822 }
4823
4824 /* Perform the searching operation. */
4825 ret = re_search (&private_preg, string, len,
4826 /* start: */ 0, /* range: */ len,
4827 want_reg_info ? &regs : (struct re_registers *) 0);
4828
4829 /* Copy the register information to the POSIX structure. */
4830 if (want_reg_info)
4831 {
4832 if (ret >= 0)
4833 {
4834 unsigned r;
4835
4836 for (r = 0; r < nmatch; r++)
4837 {
4838 pmatch[r].rm_so = regs.start[r];
4839 pmatch[r].rm_eo = regs.end[r];
4840 }
4841 }
4842
4843 /* If we needed the temporary register info, free the space now. */
4844 free (regs.start);
4845 free (regs.end);
4846 }
4847
4848 /* We want zero return to mean success, unlike `re_search'. */
4849 return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
4850}
4851
4852
4853/* Returns a message corresponding to an error code, ERRCODE, returned
4854 from either regcomp or regexec. We don't use PREG here. */
4855
4856size_t
4857regerror (errcode, preg, errbuf, errbuf_size)
4858 int errcode;
4859 const regex_t *preg;
4860 char *errbuf;
4861 size_t errbuf_size;
4862{
4863 const char *msg;
4864 size_t msg_size;
4865
4866 if (errcode < 0
4867 || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0])))
4868 /* Only error codes returned by the rest of the code should be passed
4869 to this routine. If we are given anything else, or if other regex
4870 code generates an invalid error code, then the program has a bug.
4871 Dump core so we can fix it. */
4872 abort ();
4873
4874 msg = re_error_msg[errcode];
4875
4876 /* POSIX doesn't require that we do anything in this case, but why
4877 not be nice. */
4878 if (! msg)
4879 msg = "Success";
4880
4881 msg_size = strlen (msg) + 1; /* Includes the null. */
4882
4883 if (errbuf_size != 0)
4884 {
4885 if (msg_size > errbuf_size)
4886 {
4887 strncpy (errbuf, msg, errbuf_size - 1);
4888 errbuf[errbuf_size - 1] = 0;
4889 }
4890 else
4891 strcpy (errbuf, msg);
4892 }
4893
4894 return msg_size;
4895}
4896
4897
4898/* Free dynamically allocated space used by PREG. */
4899
4900void
4901regfree (preg)
4902 regex_t *preg;
4903{
4904 if (preg->buffer != NULL)
4905 free (preg->buffer);
4906 preg->buffer = NULL;
4907
4908 preg->allocated = 0;
4909 preg->used = 0;
4910
4911 if (preg->fastmap != NULL)
4912 free (preg->fastmap);
4913 preg->fastmap = NULL;
4914 preg->fastmap_accurate = 0;
4915
4916 if (preg->translate != NULL)
4917 free (preg->translate);
4918 preg->translate = NULL;
4919}
4920
4921#endif /* not emacs */
4922
4923/*
4924Local variables:
4925make-backup-files: t
4926version-control: t
4927trim-versions-without-asking: nil
4928End:
4929*/
diff --git a/win32/regex.h b/win32/regex.h
new file mode 100644
index 000000000..6eb64f140
--- /dev/null
+++ b/win32/regex.h
@@ -0,0 +1,490 @@
1/* Definitions for data structures and routines for the regular
2 expression library, version 0.12.
3
4 Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#ifndef __REGEXP_LIBRARY_H__
21#define __REGEXP_LIBRARY_H__
22
23/* POSIX says that <sys/types.h> must be included (by the caller) before
24 <regex.h>. */
25
26#ifdef VMS
27/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
28 should be there. */
29#include <stddef.h>
30#endif
31
32
33/* The following bits are used to determine the regexp syntax we
34 recognize. The set/not-set meanings are chosen so that Emacs syntax
35 remains the value 0. The bits are given in alphabetical order, and
36 the definitions shifted by one from the previous bit; thus, when we
37 add or remove a bit, only one other definition need change. */
38typedef unsigned reg_syntax_t;
39
40/* If this bit is not set, then \ inside a bracket expression is literal.
41 If set, then such a \ quotes the following character. */
42#define RE_BACKSLASH_ESCAPE_IN_LISTS (1)
43
44/* If this bit is not set, then + and ? are operators, and \+ and \? are
45 literals.
46 If set, then \+ and \? are operators and + and ? are literals. */
47#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
48
49/* If this bit is set, then character classes are supported. They are:
50 [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
51 [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
52 If not set, then character classes are not supported. */
53#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
54
55/* If this bit is set, then ^ and $ are always anchors (outside bracket
56 expressions, of course).
57 If this bit is not set, then it depends:
58 ^ is an anchor if it is at the beginning of a regular
59 expression or after an open-group or an alternation operator;
60 $ is an anchor if it is at the end of a regular expression, or
61 before a close-group or an alternation operator.
62
63 This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
64 POSIX draft 11.2 says that * etc. in leading positions is undefined.
65 We already implemented a previous draft which made those constructs
66 invalid, though, so we haven't changed the code back. */
67#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
68
69/* If this bit is set, then special characters are always special
70 regardless of where they are in the pattern.
71 If this bit is not set, then special characters are special only in
72 some contexts; otherwise they are ordinary. Specifically,
73 * + ? and intervals are only special when not after the beginning,
74 open-group, or alternation operator. */
75#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
76
77/* If this bit is set, then *, +, ?, and { cannot be first in an re or
78 immediately after an alternation or begin-group operator. */
79#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
80
81/* If this bit is set, then . matches newline.
82 If not set, then it doesn't. */
83#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
84
85/* If this bit is set, then . doesn't match NUL.
86 If not set, then it does. */
87#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
88
89/* If this bit is set, nonmatching lists [^...] do not match newline.
90 If not set, they do. */
91#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
92
93/* If this bit is set, either \{...\} or {...} defines an
94 interval, depending on RE_NO_BK_BRACES.
95 If not set, \{, \}, {, and } are literals. */
96#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
97
98/* If this bit is set, +, ? and | aren't recognized as operators.
99 If not set, they are. */
100#define RE_LIMITED_OPS (RE_INTERVALS << 1)
101
102/* If this bit is set, newline is an alternation operator.
103 If not set, newline is literal. */
104#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
105
106/* If this bit is set, then `{...}' defines an interval, and \{ and \}
107 are literals.
108 If not set, then `\{...\}' defines an interval. */
109#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
110
111/* If this bit is set, (...) defines a group, and \( and \) are literals.
112 If not set, \(...\) defines a group, and ( and ) are literals. */
113#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
114
115/* If this bit is set, then \<digit> matches <digit>.
116 If not set, then \<digit> is a back-reference. */
117#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
118
119/* If this bit is set, then | is an alternation operator, and \| is literal.
120 If not set, then \| is an alternation operator, and | is literal. */
121#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
122
123/* If this bit is set, then an ending range point collating higher
124 than the starting range point, as in [z-a], is invalid.
125 If not set, then when ending range point collates higher than the
126 starting range point, the range is ignored. */
127#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
128
129/* If this bit is set, then an unmatched ) is ordinary.
130 If not set, then an unmatched ) is invalid. */
131#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
132
133/* This global variable defines the particular regexp syntax to use (for
134 some interfaces). When a regexp is compiled, the syntax used is
135 stored in the pattern buffer, so changing this does not affect
136 already-compiled regexps. */
137extern reg_syntax_t re_syntax_options;
138
139/* Define combinations of the above bits for the standard possibilities.
140 (The [[[ comments delimit what gets put into the Texinfo file, so
141 don't delete them!) */
142/* [[[begin syntaxes]]] */
143#define RE_SYNTAX_EMACS 0
144
145#define RE_SYNTAX_AWK \
146 (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
147 | RE_NO_BK_PARENS | RE_NO_BK_REFS \
148 | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
149 | RE_UNMATCHED_RIGHT_PAREN_ORD)
150
151#define RE_SYNTAX_POSIX_AWK \
152 (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
153
154#define RE_SYNTAX_GREP \
155 (RE_BK_PLUS_QM | RE_CHAR_CLASSES \
156 | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
157 | RE_NEWLINE_ALT)
158
159#define RE_SYNTAX_EGREP \
160 (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
161 | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
162 | RE_NEWLINE_ALT | RE_NO_BK_PARENS \
163 | RE_NO_BK_VBAR)
164
165#define RE_SYNTAX_POSIX_EGREP \
166 (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
167
168/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
169#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
170
171#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
172
173/* Syntax bits common to both basic and extended POSIX regex syntax. */
174#define _RE_SYNTAX_POSIX_COMMON \
175 (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
176 | RE_INTERVALS | RE_NO_EMPTY_RANGES)
177
178#define RE_SYNTAX_POSIX_BASIC \
179 (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
180
181/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
182 RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
183 isn't minimal, since other operators, such as \`, aren't disabled. */
184#define RE_SYNTAX_POSIX_MINIMAL_BASIC \
185 (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
186
187#define RE_SYNTAX_POSIX_EXTENDED \
188 (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
189 | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
190 | RE_NO_BK_PARENS | RE_NO_BK_VBAR \
191 | RE_UNMATCHED_RIGHT_PAREN_ORD)
192
193/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
194 replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */
195#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
196 (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
197 | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
198 | RE_NO_BK_PARENS | RE_NO_BK_REFS \
199 | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
200/* [[[end syntaxes]]] */
201
202/* Maximum number of duplicates an interval can allow. Some systems
203 (erroneously) define this in other header files, but we want our
204 value, so remove any previous define. */
205#ifdef RE_DUP_MAX
206#undef RE_DUP_MAX
207#endif
208#define RE_DUP_MAX ((1 << 15) - 1)
209
210
211/* POSIX `cflags' bits (i.e., information for `regcomp'). */
212
213/* If this bit is set, then use extended regular expression syntax.
214 If not set, then use basic regular expression syntax. */
215#define REG_EXTENDED 1
216
217/* If this bit is set, then ignore case when matching.
218 If not set, then case is significant. */
219#define REG_ICASE (REG_EXTENDED << 1)
220
221/* If this bit is set, then anchors do not match at newline
222 characters in the string.
223 If not set, then anchors do match at newlines. */
224#define REG_NEWLINE (REG_ICASE << 1)
225
226/* If this bit is set, then report only success or fail in regexec.
227 If not set, then returns differ between not matching and errors. */
228#define REG_NOSUB (REG_NEWLINE << 1)
229
230
231/* POSIX `eflags' bits (i.e., information for regexec). */
232
233/* If this bit is set, then the beginning-of-line operator doesn't match
234 the beginning of the string (presumably because it's not the
235 beginning of a line).
236 If not set, then the beginning-of-line operator does match the
237 beginning of the string. */
238#define REG_NOTBOL 1
239
240/* Like REG_NOTBOL, except for the end-of-line. */
241#define REG_NOTEOL (1 << 1)
242
243
244/* If any error codes are removed, changed, or added, update the
245 `re_error_msg' table in regex.c. */
246typedef enum
247{
248 REG_NOERROR = 0, /* Success. */
249 REG_NOMATCH, /* Didn't find a match (for regexec). */
250
251 /* POSIX regcomp return error codes. (In the order listed in the
252 standard.) */
253 REG_BADPAT, /* Invalid pattern. */
254 REG_ECOLLATE, /* Not implemented. */
255 REG_ECTYPE, /* Invalid character class name. */
256 REG_EESCAPE, /* Trailing backslash. */
257 REG_ESUBREG, /* Invalid back reference. */
258 REG_EBRACK, /* Unmatched left bracket. */
259 REG_EPAREN, /* Parenthesis imbalance. */
260 REG_EBRACE, /* Unmatched \{. */
261 REG_BADBR, /* Invalid contents of \{\}. */
262 REG_ERANGE, /* Invalid range end. */
263 REG_ESPACE, /* Ran out of memory. */
264 REG_BADRPT, /* No preceding re for repetition op. */
265
266 /* Error codes we've added. */
267 REG_EEND, /* Premature end. */
268 REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
269 REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
270} reg_errcode_t;
271
272/* This data structure represents a compiled pattern. Before calling
273 the pattern compiler, the fields `buffer', `allocated', `fastmap',
274 `translate', and `no_sub' can be set. After the pattern has been
275 compiled, the `re_nsub' field is available. All other fields are
276 private to the regex routines. */
277
278struct re_pattern_buffer
279{
280/* [[[begin pattern_buffer]]] */
281 /* Space that holds the compiled pattern. It is declared as
282 `unsigned char *' because its elements are
283 sometimes used as array indexes. */
284 unsigned char *buffer;
285
286 /* Number of bytes to which `buffer' points. */
287 unsigned long allocated;
288
289 /* Number of bytes actually used in `buffer'. */
290 unsigned long used;
291
292 /* Syntax setting with which the pattern was compiled. */
293 reg_syntax_t syntax;
294
295 /* Pointer to a fastmap, if any, otherwise zero. re_search uses
296 the fastmap, if there is one, to skip over impossible
297 starting points for matches. */
298 char *fastmap;
299
300 /* Either a translate table to apply to all characters before
301 comparing them, or zero for no translation. The translation
302 is applied to a pattern when it is compiled and to a string
303 when it is matched. */
304 char *translate;
305
306 /* Number of subexpressions found by the compiler. */
307 size_t re_nsub;
308
309 /* Zero if this pattern cannot match the empty string, one else.
310 Well, in truth it's used only in `re_search_2', to see
311 whether or not we should use the fastmap, so we don't set
312 this absolutely perfectly; see `re_compile_fastmap' (the
313 `duplicate' case). */
314 unsigned can_be_null : 1;
315
316 /* If REGS_UNALLOCATED, allocate space in the `regs' structure
317 for `max (RE_NREGS, re_nsub + 1)' groups.
318 If REGS_REALLOCATE, reallocate space if necessary.
319 If REGS_FIXED, use what's there. */
320#define REGS_UNALLOCATED 0
321#define REGS_REALLOCATE 1
322#define REGS_FIXED 2
323 unsigned regs_allocated : 2;
324
325 /* Set to zero when `regex_compile' compiles a pattern; set to one
326 by `re_compile_fastmap' if it updates the fastmap. */
327 unsigned fastmap_accurate : 1;
328
329 /* If set, `re_match_2' does not return information about
330 subexpressions. */
331 unsigned no_sub : 1;
332
333 /* If set, a beginning-of-line anchor doesn't match at the
334 beginning of the string. */
335 unsigned not_bol : 1;
336
337 /* Similarly for an end-of-line anchor. */
338 unsigned not_eol : 1;
339
340 /* If true, an anchor at a newline matches. */
341 unsigned newline_anchor : 1;
342
343/* [[[end pattern_buffer]]] */
344};
345
346typedef struct re_pattern_buffer regex_t;
347
348
349/* search.c (search_buffer) in Emacs needs this one opcode value. It is
350 defined both in `regex.c' and here. */
351#define RE_EXACTN_VALUE 1
352
353/* Type for byte offsets within the string. POSIX mandates this. */
354typedef int regoff_t;
355
356
357/* This is the structure we store register match data in. See
358 regex.texinfo for a full description of what registers match. */
359struct re_registers
360{
361 unsigned num_regs;
362 regoff_t *start;
363 regoff_t *end;
364};
365
366
367/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
368 `re_match_2' returns information about at least this many registers
369 the first time a `regs' structure is passed. */
370#ifndef RE_NREGS
371#define RE_NREGS 30
372#endif
373
374
375/* POSIX specification for registers. Aside from the different names than
376 `re_registers', POSIX uses an array of structures, instead of a
377 structure of arrays. */
378typedef struct
379{
380 regoff_t rm_so; /* Byte offset from string's start to substring's start. */
381 regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
382} regmatch_t;
383
384/* Declarations for routines. */
385
386/* To avoid duplicating every routine declaration -- once with a
387 prototype (if we are ANSI), and once without (if we aren't) -- we
388 use the following macro to declare argument types. This
389 unfortunately clutters up the declarations a bit, but I think it's
390 worth it. */
391
392#if __STDC__
393
394#define _RE_ARGS(args) args
395
396#else /* not __STDC__ */
397
398#define _RE_ARGS(args) ()
399
400#endif /* not __STDC__ */
401
402/* Sets the current default syntax to SYNTAX, and return the old syntax.
403 You can also simply assign to the `re_syntax_options' variable. */
404extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
405
406/* Compile the regular expression PATTERN, with length LENGTH
407 and syntax given by the global `re_syntax_options', into the buffer
408 BUFFER. Return NULL if successful, and an error string if not. */
409extern const char *re_compile_pattern
410 _RE_ARGS ((const char *pattern, int length,
411 struct re_pattern_buffer *buffer));
412
413
414/* Compile a fastmap for the compiled pattern in BUFFER; used to
415 accelerate searches. Return 0 if successful and -2 if was an
416 internal error. */
417extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
418
419
420/* Search in the string STRING (with length LENGTH) for the pattern
421 compiled into BUFFER. Start searching at position START, for RANGE
422 characters. Return the starting position of the match, -1 for no
423 match, or -2 for an internal error. Also return register
424 information in REGS (if REGS and BUFFER->no_sub are nonzero). */
425extern int re_search
426 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
427 int length, int start, int range, struct re_registers *regs));
428
429
430/* Like `re_search', but search in the concatenation of STRING1 and
431 STRING2. Also, stop searching at index START + STOP. */
432extern int re_search_2
433 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
434 int length1, const char *string2, int length2,
435 int start, int range, struct re_registers *regs, int stop));
436
437
438/* Like `re_search', but return how many characters in STRING the regexp
439 in BUFFER matched, starting at position START. */
440extern int re_match
441 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
442 int length, int start, struct re_registers *regs));
443
444
445/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
446extern int re_match_2
447 _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
448 int length1, const char *string2, int length2,
449 int start, struct re_registers *regs, int stop));
450
451
452/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
453 ENDS. Subsequent matches using BUFFER and REGS will use this memory
454 for recording register information. STARTS and ENDS must be
455 allocated with malloc, and must each be at least `NUM_REGS * sizeof
456 (regoff_t)' bytes long.
457
458 If NUM_REGS == 0, then subsequent matches should allocate their own
459 register data.
460
461 Unless this function is called, the first search or match using
462 PATTERN_BUFFER will allocate its own register data, without
463 freeing the old data. */
464extern void re_set_registers
465 _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
466 unsigned num_regs, regoff_t *starts, regoff_t *ends));
467
468/* 4.2 bsd compatibility. */
469extern char *re_comp _RE_ARGS ((const char *));
470extern int re_exec _RE_ARGS ((const char *));
471
472/* POSIX compatibility. */
473extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));
474extern int regexec
475 _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch,
476 regmatch_t pmatch[], int eflags));
477extern size_t regerror
478 _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf,
479 size_t errbuf_size));
480extern void regfree _RE_ARGS ((regex_t *preg));
481
482#endif /* not __REGEXP_LIBRARY_H__ */
483
484/*
485Local variables:
486make-backup-files: t
487version-control: t
488trim-versions-without-asking: nil
489End:
490*/
diff --git a/win32/sched.h b/win32/sched.h
new file mode 100644
index 000000000..128bfe698
--- /dev/null
+++ b/win32/sched.h
@@ -0,0 +1 @@
static inline void sched_yield(void) {}
diff --git a/win32/sys/ioctl.h b/win32/sys/ioctl.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/sys/ioctl.h
diff --git a/win32/sys/mman.h b/win32/sys/mman.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/sys/mman.h
diff --git a/win32/sys/poll.h b/win32/sys/poll.h
new file mode 100644
index 000000000..b7aa59d97
--- /dev/null
+++ b/win32/sys/poll.h
@@ -0,0 +1,53 @@
1/* Header for poll(2) emulation
2 Contributed by Paolo Bonzini.
3
4 Copyright 2001, 2002, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.
5
6 This file is part of gnulib.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
21
22#ifndef _GL_POLL_H
23#define _GL_POLL_H
24
25/* fake a poll(2) environment */
26#define POLLIN 0x0001 /* any readable data available */
27#define POLLPRI 0x0002 /* OOB/Urgent readable data */
28#define POLLOUT 0x0004 /* file descriptor is writeable */
29#define POLLERR 0x0008 /* some poll error occurred */
30#define POLLHUP 0x0010 /* file descriptor was "hung up" */
31#define POLLNVAL 0x0020 /* requested events "invalid" */
32#define POLLRDNORM 0x0040
33#define POLLRDBAND 0x0080
34#define POLLWRNORM 0x0100
35#define POLLWRBAND 0x0200
36
37struct pollfd
38{
39 int fd; /* which file descriptor to poll */
40 short events; /* events we are interested in */
41 short revents; /* events found on return */
42};
43
44typedef unsigned long nfds_t;
45
46extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);
47
48/* Define INFTIM only if doing so conforms to POSIX. */
49#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)
50#define INFTIM (-1)
51#endif
52
53#endif /* _GL_POLL_H */
diff --git a/win32/sys/socket.h b/win32/sys/socket.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/sys/socket.h
diff --git a/win32/sys/sysmacros.h b/win32/sys/sysmacros.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/sys/sysmacros.h
diff --git a/win32/sys/times.h b/win32/sys/times.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/sys/times.h
diff --git a/win32/sys/un.h b/win32/sys/un.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/sys/un.h
diff --git a/win32/sys/utsname.h b/win32/sys/utsname.h
new file mode 100644
index 000000000..6f12efd58
--- /dev/null
+++ b/win32/sys/utsname.h
@@ -0,0 +1,66 @@
1/* Copyright (C) 1991,92,94,96,97,99,2002 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
18
19/*
20 * POSIX Standard: 4.4 System Identification <sys/utsname.h>
21 */
22
23#ifndef _SYS_UTSNAME_H
24#define _SYS_UTSNAME_H 1
25
26#define _UTSNAME_LENGTH 65
27
28#ifndef _UTSNAME_SYSNAME_LENGTH
29# define _UTSNAME_SYSNAME_LENGTH _UTSNAME_LENGTH
30#endif
31#ifndef _UTSNAME_NODENAME_LENGTH
32# define _UTSNAME_NODENAME_LENGTH _UTSNAME_LENGTH
33#endif
34#ifndef _UTSNAME_RELEASE_LENGTH
35# define _UTSNAME_RELEASE_LENGTH _UTSNAME_LENGTH
36#endif
37#ifndef _UTSNAME_VERSION_LENGTH
38# define _UTSNAME_VERSION_LENGTH _UTSNAME_LENGTH
39#endif
40#ifndef _UTSNAME_MACHINE_LENGTH
41# define _UTSNAME_MACHINE_LENGTH _UTSNAME_LENGTH
42#endif
43
44/* Structure describing the system and machine. */
45struct utsname
46 {
47 /* Name of the implementation of the operating system. */
48 char sysname[_UTSNAME_SYSNAME_LENGTH];
49
50 /* Name of this node on the network. */
51 char nodename[_UTSNAME_NODENAME_LENGTH];
52
53 /* Current release level of this implementation. */
54 char release[_UTSNAME_RELEASE_LENGTH];
55 /* Current version level of this release. */
56 char version[_UTSNAME_VERSION_LENGTH];
57
58 /* Name of the hardware type the system is running on. */
59 char machine[_UTSNAME_MACHINE_LENGTH];
60 };
61
62/* Put information about the system in NAME. */
63extern int uname (struct utsname *__name);
64
65
66#endif /* sys/utsname.h */
diff --git a/win32/sys/wait.h b/win32/sys/wait.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/win32/sys/wait.h
diff --git a/win32/termios.c b/win32/termios.c
new file mode 100644
index 000000000..12db40133
--- /dev/null
+++ b/win32/termios.c
@@ -0,0 +1,83 @@
1#include "libbb.h"
2
3int tcsetattr(int fd UNUSED_PARAM, int mode UNUSED_PARAM, const struct termios *t UNUSED_PARAM)
4{
5 return -1;
6}
7
8int tcgetattr(int fd UNUSED_PARAM, struct termios *t UNUSED_PARAM)
9{
10 return -1;
11}
12
13int64_t FAST_FUNC read_key(int fd, char *buf, int timeout)
14{
15 HANDLE cin = GetStdHandle(STD_INPUT_HANDLE);
16 INPUT_RECORD record;
17 DWORD nevent_out, mode;
18 int ret = -1;
19
20 if (fd != 0)
21 bb_error_msg_and_die("read_key only works on stdin");
22 if (cin == INVALID_HANDLE_VALUE)
23 return -1;
24 GetConsoleMode(cin, &mode);
25 SetConsoleMode(cin, 0);
26
27 if (timeout > 0) {
28 if (WaitForSingleObject(cin, timeout) != WAIT_OBJECT_0)
29 goto done;
30 }
31 while (1) {
32 if (!ReadConsoleInput(cin, &record, 1, &nevent_out))
33 goto done;
34 if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown)
35 continue;
36 if (!record.Event.KeyEvent.uChar.AsciiChar) {
37 DWORD state = record.Event.KeyEvent.dwControlKeyState;
38
39 if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED) &&
40 (record.Event.KeyEvent.wVirtualKeyCode >= 'A' &&
41 record.Event.KeyEvent.wVirtualKeyCode <= 'Z')) {
42 ret = record.Event.KeyEvent.wVirtualKeyCode & ~0x40;
43 break;
44 }
45
46 switch (record.Event.KeyEvent.wVirtualKeyCode) {
47 case VK_DELETE: ret = KEYCODE_DELETE; goto done;
48 case VK_INSERT: ret = KEYCODE_INSERT; goto done;
49 case VK_UP: ret = KEYCODE_UP; goto done;
50 case VK_DOWN: ret = KEYCODE_DOWN; goto done;
51 case VK_RIGHT:
52 if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) {
53 ret = KEYCODE_CTRL_RIGHT;
54 goto done;
55 }
56 ret = KEYCODE_RIGHT;
57 goto done;
58 case VK_LEFT:
59 if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) {
60 ret = KEYCODE_CTRL_LEFT;
61 goto done;
62 }
63 ret = KEYCODE_LEFT;
64 goto done;
65 case VK_HOME: ret = KEYCODE_HOME; goto done;
66 case VK_END: ret = KEYCODE_END; goto done;
67 case VK_PRIOR: ret = KEYCODE_PAGEUP; goto done;
68 case VK_NEXT: ret = KEYCODE_PAGEDOWN; goto done;
69 case VK_CAPITAL:
70 case VK_SHIFT:
71 case VK_CONTROL:
72 case VK_MENU:
73 break;
74 }
75 continue;
76 }
77 ret = record.Event.KeyEvent.uChar.AsciiChar;
78 break;
79 }
80 done:
81 SetConsoleMode(cin, mode);
82 return ret;
83}
diff --git a/win32/termios.h b/win32/termios.h
new file mode 100644
index 000000000..011a37eb9
--- /dev/null
+++ b/win32/termios.h
@@ -0,0 +1,129 @@
1/* iflag bits */
2#define IGNBRK 0x00001
3#define BRKINT 0x00002
4#define IGNPAR 0x00004
5#define IMAXBEL 0x00008
6#define INPCK 0x00010
7#define ISTRIP 0x00020
8#define INLCR 0x00040
9#define IGNCR 0x00080
10#define ICRNL 0x00100
11#define IXON 0x00400
12#define IXOFF 0x01000
13#define IUCLC 0x04000
14#define IXANY 0x08000
15#define PARMRK 0x10000
16
17/* oflag bits */
18
19#define OPOST 0x00001
20#define OLCUC 0x00002
21#define OCRNL 0x00004
22#define ONLCR 0x00008
23#define ONOCR 0x00010
24#define ONLRET 0x00020
25#define OFILL 0x00040
26#define CRDLY 0x00180
27#define CR0 0x00000
28#define CR1 0x00080
29#define CR2 0x00100
30#define CR3 0x00180
31#define NLDLY 0x00200
32#define NL0 0x00000
33#define NL1 0x00200
34#define BSDLY 0x00400
35#define BS0 0x00000
36#define BS1 0x00400
37#define TABDLY 0x01800
38#define TAB0 0x00000
39#define TAB1 0x00800
40#define TAB2 0x01000
41#define TAB3 0x01800
42#define XTABS 0x01800
43#define VTDLY 0x02000
44#define VT0 0x00000
45#define VT1 0x02000
46#define FFDLY 0x04000
47#define FF0 0x00000
48#define FF1 0x04000
49#define OFDEL 0x08000
50
51/* lflag bits */
52#define ISIG 0x0001
53#define ICANON 0x0002
54#define ECHO 0x0004
55#define ECHOE 0x0008
56#define ECHOK 0x0010
57#define ECHONL 0x0020
58#define NOFLSH 0x0040
59#define TOSTOP 0x0080
60#define IEXTEN 0x0100
61#define FLUSHO 0x0200
62#define ECHOKE 0x0400
63#define ECHOCTL 0x0800
64
65#define VDISCARD 1
66#define VEOL 2
67#define VEOL2 3
68#define VEOF 4
69#define VERASE 5
70#define VINTR 6
71#define VKILL 7
72#define VLNEXT 8
73#define VMIN 9
74#define VQUIT 10
75#define VREPRINT 11
76#define VSTART 12
77#define VSTOP 13
78#define VSUSP 14
79#define VSWTC 15
80#define VTIME 16
81#define VWERASE 17
82
83#define TCIFLUSH 0
84#define TCSAFLUSH 1
85#define TCSANOW 2
86#define TCSADRAIN 3
87#define TCSADFLUSH 4
88
89#define B0 0000000 /* hang up */
90#define B50 0000001
91#define B75 0000002
92#define B110 0000003
93#define B134 0000004
94#define B150 0000005
95#define B200 0000006
96#define B300 0000007
97#define B600 0000010
98#define B1200 0000011
99#define B1800 0000012
100#define B2400 0000013
101#define B4800 0000014
102#define B9600 0000015
103
104typedef unsigned char cc_t;
105typedef unsigned int tcflag_t;
106typedef unsigned int speed_t;
107typedef unsigned short otcflag_t;
108typedef unsigned char ospeed_t;
109
110#define NCCS 18
111struct termios {
112 tcflag_t c_iflag;
113 tcflag_t c_oflag;
114 tcflag_t c_cflag;
115 tcflag_t c_lflag;
116 char c_line;
117 cc_t c_cc[NCCS];
118 speed_t c_ispeed;
119 speed_t c_ospeed;
120};
121
122struct winsize {
123 unsigned short ws_row, ws_col;
124 unsigned short ws_xpixel, ws_ypixel;
125};
126
127int tcflush(int fd, int queue_selector);
128int tcgetattr(int fd, struct termios *t);
129int tcsetattr(int fd, int mode, const struct termios *t);
diff --git a/win32/uname.c b/win32/uname.c
new file mode 100644
index 000000000..da432e82d
--- /dev/null
+++ b/win32/uname.c
@@ -0,0 +1,50 @@
1#include "libbb.h"
2/* After libbb.h, since it needs sys/types.h on some systems */
3#include <sys/utsname.h>
4
5int uname(struct utsname *name)
6{
7 const char *unk = "unknown";
8 OSVERSIONINFO os_info;
9 SYSTEM_INFO sys_info;
10 DWORD len;
11
12 strcpy(name->sysname, "Windows_NT");
13
14 len = sizeof(name->nodename) - 1;
15 if ( !GetComputerName(name->nodename, &len) ) {
16 strcpy(name->nodename, unk);
17 }
18
19 memset(&os_info, 0, sizeof(OSVERSIONINFO));
20 os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
21
22 strcpy(name->release, unk);
23 strcpy(name->version, unk);
24 if (GetVersionEx(&os_info)) {
25 sprintf(name->release, "%d.%d", os_info.dwMajorVersion,
26 os_info.dwMinorVersion);
27 sprintf(name->version, "%d", os_info.dwBuildNumber);
28 }
29
30 strcpy(name->machine, unk);
31 GetSystemInfo(&sys_info);
32 switch (sys_info.wProcessorArchitecture) {
33 case PROCESSOR_ARCHITECTURE_AMD64:
34 strcpy(name->machine, "x86_64");
35 break;
36 case PROCESSOR_ARCHITECTURE_IA64:
37 strcpy(name->machine, "ia64");
38 break;
39 case PROCESSOR_ARCHITECTURE_INTEL:
40 if (sys_info.wProcessorLevel < 6) {
41 strcpy(name->machine, "i386");
42 }
43 else {
44 strcpy(name->machine, "i686");
45 }
46 break;
47 }
48
49 return 0;
50}
diff --git a/win32/winansi.c b/win32/winansi.c
new file mode 100644
index 000000000..c923bde56
--- /dev/null
+++ b/win32/winansi.c
@@ -0,0 +1,436 @@
1/*
2 * Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
3 */
4
5#include "libbb.h"
6#include <windows.h>
7#undef PACKED
8
9/*
10 Functions to be wrapped:
11*/
12#undef printf
13#undef fprintf
14#undef fputs
15/* TODO: write */
16
17/*
18 ANSI codes used by git: m, K
19
20 This file is git-specific. Therefore, this file does not attempt
21 to implement any codes that are not used by git.
22*/
23
24static HANDLE console;
25static WORD plain_attr;
26static WORD attr;
27static int negative;
28
29static void init(void)
30{
31 CONSOLE_SCREEN_BUFFER_INFO sbi;
32
33 static int initialized = 0;
34 if (initialized)
35 return;
36
37 console = GetStdHandle(STD_OUTPUT_HANDLE);
38 if (console == INVALID_HANDLE_VALUE)
39 console = NULL;
40
41 if (!console)
42 return;
43
44 GetConsoleScreenBufferInfo(console, &sbi);
45 attr = plain_attr = sbi.wAttributes;
46 negative = 0;
47
48 initialized = 1;
49}
50
51
52#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
53#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
54
55static void set_console_attr(void)
56{
57 WORD attributes = attr;
58 if (negative) {
59 attributes &= ~FOREGROUND_ALL;
60 attributes &= ~BACKGROUND_ALL;
61
62 /* This could probably use a bitmask
63 instead of a series of ifs */
64 if (attr & FOREGROUND_RED)
65 attributes |= BACKGROUND_RED;
66 if (attr & FOREGROUND_GREEN)
67 attributes |= BACKGROUND_GREEN;
68 if (attr & FOREGROUND_BLUE)
69 attributes |= BACKGROUND_BLUE;
70
71 if (attr & BACKGROUND_RED)
72 attributes |= FOREGROUND_RED;
73 if (attr & BACKGROUND_GREEN)
74 attributes |= FOREGROUND_GREEN;
75 if (attr & BACKGROUND_BLUE)
76 attributes |= FOREGROUND_BLUE;
77 }
78 SetConsoleTextAttribute(console, attributes);
79}
80
81static void erase_in_line(void)
82{
83 CONSOLE_SCREEN_BUFFER_INFO sbi;
84 DWORD dummy; /* Needed for Windows 7 (or Vista) regression */
85
86 if (!console)
87 return;
88
89 GetConsoleScreenBufferInfo(console, &sbi);
90 FillConsoleOutputCharacterA(console, ' ',
91 sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition,
92 &dummy);
93}
94
95static void erase_till_end_of_screen(void)
96{
97 CONSOLE_SCREEN_BUFFER_INFO sbi;
98 COORD pos;
99 DWORD dummy;
100
101 if (!console)
102 return;
103
104 GetConsoleScreenBufferInfo(console, &sbi);
105 FillConsoleOutputCharacterA(console, ' ',
106 sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition,
107 &dummy);
108
109 pos.X = 0;
110 for (pos.Y = sbi.dwCursorPosition.Y+1; pos.Y < sbi.dwSize.Y; pos.Y++)
111 FillConsoleOutputCharacterA(console, ' ', sbi.dwSize.X,
112 pos, &dummy);
113}
114
115static void move_cursor_back(int n)
116{
117 CONSOLE_SCREEN_BUFFER_INFO sbi;
118
119 if (!console)
120 return;
121
122 GetConsoleScreenBufferInfo(console, &sbi);
123 sbi.dwCursorPosition.X -= n;
124 SetConsoleCursorPosition(console, sbi.dwCursorPosition);
125}
126
127static void move_cursor(int x, int y)
128{
129 COORD pos;
130
131 if (!console)
132 return;
133
134 pos.X = x;
135 pos.Y = y;
136 SetConsoleCursorPosition(console, pos);
137}
138
139static const char *set_attr(const char *str)
140{
141 const char *func;
142 size_t len = strspn(str, "0123456789;");
143 func = str + len;
144
145 switch (*func) {
146 case 'm':
147 do {
148 long val = strtol(str, (char **)&str, 10);
149 switch (val) {
150 case 0: /* reset */
151 attr = plain_attr;
152 negative = 0;
153 break;
154 case 1: /* bold */
155 attr |= FOREGROUND_INTENSITY;
156 break;
157 case 2: /* faint */
158 case 22: /* normal */
159 attr &= ~FOREGROUND_INTENSITY;
160 break;
161 case 3: /* italic */
162 /* Unsupported */
163 break;
164 case 4: /* underline */
165 case 21: /* double underline */
166 /* Wikipedia says this flag does nothing */
167 /* Furthermore, mingw doesn't define this flag
168 attr |= COMMON_LVB_UNDERSCORE; */
169 break;
170 case 24: /* no underline */
171 /* attr &= ~COMMON_LVB_UNDERSCORE; */
172 break;
173 case 5: /* slow blink */
174 case 6: /* fast blink */
175 /* We don't have blink, but we do have
176 background intensity */
177 attr |= BACKGROUND_INTENSITY;
178 break;
179 case 25: /* no blink */
180 attr &= ~BACKGROUND_INTENSITY;
181 break;
182 case 7: /* negative */
183 negative = 1;
184 break;
185 case 27: /* positive */
186 negative = 0;
187 break;
188 case 8: /* conceal */
189 case 28: /* reveal */
190 /* Unsupported */
191 break;
192 case 30: /* Black */
193 attr &= ~FOREGROUND_ALL;
194 break;
195 case 31: /* Red */
196 attr &= ~FOREGROUND_ALL;
197 attr |= FOREGROUND_RED;
198 break;
199 case 32: /* Green */
200 attr &= ~FOREGROUND_ALL;
201 attr |= FOREGROUND_GREEN;
202 break;
203 case 33: /* Yellow */
204 attr &= ~FOREGROUND_ALL;
205 attr |= FOREGROUND_RED | FOREGROUND_GREEN;
206 break;
207 case 34: /* Blue */
208 attr &= ~FOREGROUND_ALL;
209 attr |= FOREGROUND_BLUE;
210 break;
211 case 35: /* Magenta */
212 attr &= ~FOREGROUND_ALL;
213 attr |= FOREGROUND_RED | FOREGROUND_BLUE;
214 break;
215 case 36: /* Cyan */
216 attr &= ~FOREGROUND_ALL;
217 attr |= FOREGROUND_GREEN | FOREGROUND_BLUE;
218 break;
219 case 37: /* White */
220 attr |= FOREGROUND_RED |
221 FOREGROUND_GREEN |
222 FOREGROUND_BLUE;
223 break;
224 case 38: /* Unknown */
225 break;
226 case 39: /* reset */
227 attr &= ~FOREGROUND_ALL;
228 attr |= (plain_attr & FOREGROUND_ALL);
229 break;
230 case 40: /* Black */
231 attr &= ~BACKGROUND_ALL;
232 break;
233 case 41: /* Red */
234 attr &= ~BACKGROUND_ALL;
235 attr |= BACKGROUND_RED;
236 break;
237 case 42: /* Green */
238 attr &= ~BACKGROUND_ALL;
239 attr |= BACKGROUND_GREEN;
240 break;
241 case 43: /* Yellow */
242 attr &= ~BACKGROUND_ALL;
243 attr |= BACKGROUND_RED | BACKGROUND_GREEN;
244 break;
245 case 44: /* Blue */
246 attr &= ~BACKGROUND_ALL;
247 attr |= BACKGROUND_BLUE;
248 break;
249 case 45: /* Magenta */
250 attr &= ~BACKGROUND_ALL;
251 attr |= BACKGROUND_RED | BACKGROUND_BLUE;
252 break;
253 case 46: /* Cyan */
254 attr &= ~BACKGROUND_ALL;
255 attr |= BACKGROUND_GREEN | BACKGROUND_BLUE;
256 break;
257 case 47: /* White */
258 attr |= BACKGROUND_RED |
259 BACKGROUND_GREEN |
260 BACKGROUND_BLUE;
261 break;
262 case 48: /* Unknown */
263 break;
264 case 49: /* reset */
265 attr &= ~BACKGROUND_ALL;
266 attr |= (plain_attr & BACKGROUND_ALL);
267 break;
268 default:
269 /* Unsupported code */
270 break;
271 }
272 str++;
273 } while (*(str-1) == ';');
274
275 set_console_attr();
276 break;
277 case 'D':
278 move_cursor_back(strtol(str, (char **)&str, 10));
279 break;
280 case 'H':
281 if (!len)
282 move_cursor(0, 0);
283 else {
284 int row = strtol(str, (char **)&str, 10);
285 if (*str == ';') {
286 int col = strtol(str+1, (char **)&str, 10);
287 move_cursor(col-1, row-1);
288 }
289 }
290 break;
291 case 'J':
292 erase_till_end_of_screen();
293 break;
294 case 'K':
295 erase_in_line();
296 break;
297 default:
298 /* Unsupported code */
299 break;
300 }
301
302 return func + 1;
303}
304
305static int ansi_emulate(const char *str, FILE *stream)
306{
307 int rv = 0;
308 const char *pos = str;
309
310 while (*pos) {
311 pos = strstr(str, "\033[");
312 if (pos) {
313 size_t len = pos - str;
314
315 if (len) {
316 size_t out_len = fwrite(str, 1, len, stream);
317 rv += out_len;
318 if (out_len < len)
319 return rv;
320 }
321
322 str = pos + 2;
323 rv += 2;
324
325 fflush(stream);
326
327 pos = set_attr(str);
328 rv += pos - str;
329 str = pos;
330 } else {
331 rv += strlen(str);
332 fputs(str, stream);
333 return rv;
334 }
335 }
336 return rv;
337}
338
339int winansi_fputs(const char *str, FILE *stream)
340{
341 int rv;
342
343 if (!isatty(fileno(stream)))
344 return fputs(str, stream);
345
346 init();
347
348 if (!console)
349 return fputs(str, stream);
350
351 rv = ansi_emulate(str, stream);
352
353 if (rv >= 0)
354 return 0;
355 else
356 return EOF;
357}
358
359static int winansi_vfprintf(FILE *stream, const char *format, va_list list)
360{
361 int len, rv;
362 char small_buf[256];
363 char *buf = small_buf;
364 va_list cp;
365
366 if (!isatty(fileno(stream)))
367 goto abort;
368
369 init();
370
371 if (!console)
372 goto abort;
373
374 va_copy(cp, list);
375 len = vsnprintf(small_buf, sizeof(small_buf), format, cp);
376 va_end(cp);
377
378 if (len > sizeof(small_buf) - 1) {
379 buf = malloc(len + 1);
380 if (!buf)
381 goto abort;
382
383 len = vsnprintf(buf, len + 1, format, list);
384 }
385
386 rv = ansi_emulate(buf, stream);
387
388 if (buf != small_buf)
389 free(buf);
390 return rv;
391
392abort:
393 rv = vfprintf(stream, format, list);
394 return rv;
395}
396
397int winansi_fprintf(FILE *stream, const char *format, ...)
398{
399 va_list list;
400 int rv;
401
402 va_start(list, format);
403 rv = winansi_vfprintf(stream, format, list);
404 va_end(list);
405
406 return rv;
407}
408
409int winansi_printf(const char *format, ...)
410{
411 va_list list;
412 int rv;
413
414 va_start(list, format);
415 rv = winansi_vfprintf(stdout, format, list);
416 va_end(list);
417
418 return rv;
419}
420
421int winansi_get_terminal_width_height(struct winsize *win)
422{
423 BOOL ret;
424 CONSOLE_SCREEN_BUFFER_INFO sbi;
425
426 init();
427
428 win->ws_row = 0;
429 win->ws_col = 0;
430 if ((ret=GetConsoleScreenBufferInfo(console, &sbi)) != 0) {
431 win->ws_row = sbi.srWindow.Bottom - sbi.srWindow.Top + 1;
432 win->ws_col = sbi.srWindow.Right - sbi.srWindow.Left + 1;
433 }
434
435 return ret ? 0 : -1;
436}