summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Config.in14
-rw-r--r--Makefile12
-rw-r--r--Makefile.flags6
-rw-r--r--README.win3238
-rw-r--r--archival/gzip.c14
-rw-r--r--coreutils/dd.c20
-rw-r--r--coreutils/dos2unix.c2
-rw-r--r--coreutils/ls.c9
-rw-r--r--coreutils/od_bloaty.c7
-rw-r--r--coreutils/test.c23
-rw-r--r--debianutils/which.c34
-rw-r--r--editors/patch.c8
-rw-r--r--findutils/grep.c8
-rw-r--r--include/libbb.h20
-rw-r--r--include/mingw.h347
-rw-r--r--include/platform.h35
-rw-r--r--libbb/Kbuild29
-rw-r--r--libbb/appletlib.c12
-rw-r--r--libbb/bb_basename.c5
-rw-r--r--libbb/copy_file.c5
-rw-r--r--libbb/execable.c35
-rw-r--r--libbb/getopt32.c2
-rw-r--r--libbb/lineedit.c10
-rw-r--r--libbb/make_directory.c15
-rw-r--r--libbb/messages.c6
-rw-r--r--libbb/platform.c15
-rw-r--r--libbb/vfork_daemon_rexec.c5
-rw-r--r--libbb/xfuncs_printf.c14
-rw-r--r--libbb/xreadlink.c2
-rw-r--r--scripts/defconfig.mingw32923
-rw-r--r--shell/ash.c1099
-rw-r--r--shell/builtin_ulimit.c9
-rw-r--r--win32/Kbuild13
-rw-r--r--win32/env.c119
-rw-r--r--win32/fnmatch.c488
-rw-r--r--win32/fnmatch.h84
-rw-r--r--win32/grp.h0
-rw-r--r--win32/mingw.c777
-rw-r--r--win32/netdb.h0
-rw-r--r--win32/process.c286
-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.h0
-rw-r--r--win32/sys/socket.h0
-rw-r--r--win32/sys/wait.h0
-rw-r--r--win32/termios.c36
-rw-r--r--win32/termios.h129
-rw-r--r--win32/winansi.c358
52 files changed, 10432 insertions, 61 deletions
diff --git a/Config.in b/Config.in
index a5d20038a..5339b4ab7 100644
--- a/Config.in
+++ b/Config.in
@@ -9,6 +9,20 @@ 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
12menu "Busybox Settings" 26menu "Busybox Settings"
13 27
14menu "General Configuration" 28menu "General Configuration"
diff --git a/Makefile b/Makefile
index 14f5cd149..547c7166e 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.
@@ -485,6 +486,7 @@ libs-y := \
485 sysklogd/ \ 486 sysklogd/ \
486 util-linux/ \ 487 util-linux/ \
487 util-linux/volume_id/ \ 488 util-linux/volume_id/ \
489 win32/ \
488 490
489endif # KBUILD_EXTMOD 491endif # KBUILD_EXTMOD
490 492
@@ -521,7 +523,7 @@ endif
521# command line. 523# command line.
522# This allow a user to issue only 'make' to build a kernel including modules 524# This allow a user to issue only 'make' to build a kernel including modules
523# Defaults busybox but it is usually overridden in the arch makefile 525# Defaults busybox but it is usually overridden in the arch makefile
524all: busybox doc 526all: busybox$(EXEEXT) doc
525 527
526-include $(srctree)/arch/$(ARCH)/Makefile 528-include $(srctree)/arch/$(ARCH)/Makefile
527 529
@@ -704,16 +706,16 @@ debug_kallsyms: .tmp_map$(last_kallsyms)
704endif # ifdef CONFIG_KALLSYMS 706endif # ifdef CONFIG_KALLSYMS
705 707
706# busybox image - including updated kernel symbols 708# busybox image - including updated kernel symbols
707busybox_unstripped: $(busybox-all) FORCE 709busybox_unstripped$(EXEEXT): $(busybox-all) FORCE
708 $(call if_changed_rule,busybox__) 710 $(call if_changed_rule,busybox__)
709 $(Q)rm -f .old_version 711 $(Q)rm -f .old_version
710 712
711busybox: busybox_unstripped 713busybox$(EXEEXT): busybox_unstripped$(EXEEXT)
712ifeq ($(SKIP_STRIP),y) 714ifeq ($(SKIP_STRIP),y)
713 $(Q)cp $< $@ 715 $(Q)cp $< $@
714else 716else
715 $(Q)$(STRIP) -s --remove-section=.note --remove-section=.comment \ 717 $(Q)$(STRIP) -s --remove-section=.note --remove-section=.comment \
716 busybox_unstripped -o $@ 718 busybox_unstripped$(EXEEXT) -o $@
717# strip is confused by PIE executable and does not set exec bits 719# strip is confused by PIE executable and does not set exec bits
718 $(Q)chmod a+x $@ 720 $(Q)chmod a+x $@
719endif 721endif
@@ -949,7 +951,7 @@ endif # CONFIG_MODULES
949 951
950# Directories & files removed with 'make clean' 952# Directories & files removed with 'make clean'
951CLEAN_DIRS += $(MODVERDIR) _install 0_lib 953CLEAN_DIRS += $(MODVERDIR) _install 0_lib
952CLEAN_FILES += busybox busybox_unstripped* busybox.links \ 954CLEAN_FILES += busybox$(EXEEXT) busybox_unstripped* busybox.links \
953 System.map .kernelrelease \ 955 System.map .kernelrelease \
954 .tmp_kallsyms* .tmp_version .tmp_busybox* .tmp_System.map 956 .tmp_kallsyms* .tmp_version .tmp_busybox* .tmp_System.map
955 957
diff --git a/Makefile.flags b/Makefile.flags
index 60bb888d8..920fee322 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -97,7 +97,13 @@ CFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_CFLAGS)))
97#")) 97#"))
98endif 98endif
99 99
100ifeq ($(CONFIG_PLATFORM_MINGW32),y)
101# These defintions are not strictly needed, but they help shut up fnmatch.c warnings
102CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0
103EXEEXT = .exe
104else
100LDLIBS += m crypt 105LDLIBS += m crypt
106endif
101 107
102ifeq ($(CONFIG_PAM),y) 108ifeq ($(CONFIG_PAM),y)
103LDLIBS += pam pam_misc 109LDLIBS += pam pam_misc
diff --git a/README.win32 b/README.win32
new file mode 100644
index 000000000..73e37cc6c
--- /dev/null
+++ b/README.win32
@@ -0,0 +1,38 @@
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
7busybox@busybox.net, especially with patches.
8
9pclouds@gmail.com
1015/04/2010
11
12Building
13========
14
15You need MinGW compiler and a POSIX environment (so that "make
16menuconfig" works). I cross compile from Linux, but MSYS or Cygwin
17should be OK.
18
19In order to compile the WinGW port you need to:
20
21Start with "make menuconfig":
22
23 - Select target platform as "MS Windows"
24 - If you cross compile, set
25 Busybox Settings -> Build Options -> Cross Compiler Prefix
26 - Select whatever applets/features you like
27
28Do "make"
29
30Attempts to make it work with MS Visual Studio are appreciated. You
31can start with porting kconfig ;-)
32
33Limitation
34==========
35
36 - Use forward slashes. Backslash support is very limited.
37 - Do not do wild things with Windows drive notation, like archiving a
38 whole drive. If you want it, tell us, preferably with patches.
diff --git a/archival/gzip.c b/archival/gzip.c
index a327d5435..958336303 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -1577,7 +1577,7 @@ static void compress_block(ct_data * ltree, ct_data * dtree)
1577 * trees or store, and output the encoded block to the zip file. This function 1577 * trees or store, and output the encoded block to the zip file. This function
1578 * returns the total compressed length for the file so far. 1578 * returns the total compressed length for the file so far.
1579 */ 1579 */
1580static ulg flush_block(char *buf, ulg stored_len, int eof) 1580static ulg flush_block(char *buf, ulg stored_len, int eof_)
1581{ 1581{
1582 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ 1582 ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
1583 int max_blindex; /* index of last bit length code of non zero freq */ 1583 int max_blindex; /* index of last bit length code of non zero freq */
@@ -1615,7 +1615,7 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
1615 * and if the zip file can be seeked (to rewrite the local header), 1615 * and if the zip file can be seeked (to rewrite the local header),
1616 * the whole file is transformed into a stored file: 1616 * the whole file is transformed into a stored file:
1617 */ 1617 */
1618 if (stored_len <= opt_lenb && eof && G2.compressed_len == 0L && seekable()) { 1618 if (stored_len <= opt_lenb && eof_ && G2.compressed_len == 0L && seekable()) {
1619 /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ 1619 /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
1620 if (buf == NULL) 1620 if (buf == NULL)
1621 bb_error_msg("block vanished"); 1621 bb_error_msg("block vanished");
@@ -1631,18 +1631,18 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
1631 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to 1631 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
1632 * transform a block into a stored block. 1632 * transform a block into a stored block.
1633 */ 1633 */
1634 send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */ 1634 send_bits((STORED_BLOCK << 1) + eof_, 3); /* send block type */
1635 G2.compressed_len = (G2.compressed_len + 3 + 7) & ~7L; 1635 G2.compressed_len = (G2.compressed_len + 3 + 7) & ~7L;
1636 G2.compressed_len += (stored_len + 4) << 3; 1636 G2.compressed_len += (stored_len + 4) << 3;
1637 1637
1638 copy_block(buf, (unsigned) stored_len, 1); /* with header */ 1638 copy_block(buf, (unsigned) stored_len, 1); /* with header */
1639 1639
1640 } else if (static_lenb == opt_lenb) { 1640 } else if (static_lenb == opt_lenb) {
1641 send_bits((STATIC_TREES << 1) + eof, 3); 1641 send_bits((STATIC_TREES << 1) + eof_, 3);
1642 compress_block((ct_data *) G2.static_ltree, (ct_data *) G2.static_dtree); 1642 compress_block((ct_data *) G2.static_ltree, (ct_data *) G2.static_dtree);
1643 G2.compressed_len += 3 + G2.static_len; 1643 G2.compressed_len += 3 + G2.static_len;
1644 } else { 1644 } else {
1645 send_bits((DYN_TREES << 1) + eof, 3); 1645 send_bits((DYN_TREES << 1) + eof_, 3);
1646 send_all_trees(G2.l_desc.max_code + 1, G2.d_desc.max_code + 1, 1646 send_all_trees(G2.l_desc.max_code + 1, G2.d_desc.max_code + 1,
1647 max_blindex + 1); 1647 max_blindex + 1);
1648 compress_block((ct_data *) G2.dyn_ltree, (ct_data *) G2.dyn_dtree); 1648 compress_block((ct_data *) G2.dyn_ltree, (ct_data *) G2.dyn_dtree);
@@ -1651,12 +1651,12 @@ static ulg flush_block(char *buf, ulg stored_len, int eof)
1651 Assert(G2.compressed_len == G1.bits_sent, "bad compressed size"); 1651 Assert(G2.compressed_len == G1.bits_sent, "bad compressed size");
1652 init_block(); 1652 init_block();
1653 1653
1654 if (eof) { 1654 if (eof_) {
1655 bi_windup(); 1655 bi_windup();
1656 G2.compressed_len += 7; /* align on byte boundary */ 1656 G2.compressed_len += 7; /* align on byte boundary */
1657 } 1657 }
1658 Tracev((stderr, "\ncomprlen %lu(%lu) ", G2.compressed_len >> 3, 1658 Tracev((stderr, "\ncomprlen %lu(%lu) ", G2.compressed_len >> 3,
1659 G2.compressed_len - 7 * eof)); 1659 G2.compressed_len - 7 * eof_));
1660 1660
1661 return G2.compressed_len >> 3; 1661 return G2.compressed_len >> 3;
1662} 1662}
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 7c1a0c0df..eb9f8885f 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -168,6 +168,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
168#endif 168#endif
169 }; 169 };
170 int exitcode = EXIT_FAILURE; 170 int exitcode = EXIT_FAILURE;
171 int devzero = 0;
171 size_t ibs = 512, obs = 512; 172 size_t ibs = 512, obs = 512;
172 ssize_t n, w; 173 ssize_t n, w;
173 char *ibuf, *obuf; 174 char *ibuf, *obuf;
@@ -285,7 +286,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
285#endif 286#endif
286 287
287 if (infile != NULL) 288 if (infile != NULL)
288 xmove_fd(xopen(infile, O_RDONLY), ifd); 289 if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) {
290 flags |= FLAG_NOERROR;
291 devzero = 1;
292 }
293 else
294 xmove_fd(xopen(infile, O_RDONLY), ifd);
289 else { 295 else {
290 infile = bb_msg_standard_input; 296 infile = bb_msg_standard_input;
291 } 297 }
@@ -312,7 +318,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
312 } else { 318 } else {
313 outfile = bb_msg_standard_output; 319 outfile = bb_msg_standard_output;
314 } 320 }
315 if (skip) { 321 if (skip && !devzero) {
316 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { 322 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) {
317 while (skip-- > 0) { 323 while (skip-- > 0) {
318 n = safe_read(ifd, ibuf, ibs); 324 n = safe_read(ifd, ibuf, ibs);
@@ -329,7 +335,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
329 } 335 }
330 336
331 while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { 337 while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
332 n = safe_read(ifd, ibuf, ibs); 338 if (devzero) {
339 memset(ibuf, 0, ibs);
340 n = ibs;
341 }
342 else
343 n = safe_read(ifd, ibuf, ibs);
333 if (n == 0) 344 if (n == 0)
334 break; 345 break;
335 if (n < 0) { 346 if (n < 0) {
@@ -383,7 +394,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
383 if (w < 0) goto out_status; 394 if (w < 0) goto out_status;
384 if (w > 0) G.out_part++; 395 if (w > 0) G.out_part++;
385 } 396 }
386 if (close(ifd) < 0) { 397
398 if (!devzero && close(ifd) < 0) {
387 die_infile: 399 die_infile:
388 bb_simple_perror_msg_and_die(infile); 400 bb_simple_perror_msg_and_die(infile);
389 } 401 }
diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c
index 1911f5319..1c8b4af1b 100644
--- a/coreutils/dos2unix.c
+++ b/coreutils/dos2unix.c
@@ -41,7 +41,9 @@ static void convert(char *fn, int conv_type)
41 temp_fn = xasprintf("%sXXXXXX", resolved_fn); 41 temp_fn = xasprintf("%sXXXXXX", resolved_fn);
42 i = mkstemp(temp_fn); 42 i = mkstemp(temp_fn);
43 if (i == -1 43 if (i == -1
44#if !ENABLE_PLATFORM_MINGW32
44 || fchmod(i, st.st_mode) == -1 45 || fchmod(i, st.st_mode) == -1
46#endif
45 ) { 47 ) {
46 bb_simple_perror_msg_and_die(temp_fn); 48 bb_simple_perror_msg_and_die(temp_fn);
47 } 49 }
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 1197f7d71..717b3f493 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -612,7 +612,12 @@ static NOINLINE unsigned list_single(const struct dnode *dn)
612 if (all_fmt & LIST_INO) 612 if (all_fmt & LIST_INO)
613 column += printf("%7llu ", (long long) dn->dstat.st_ino); 613 column += printf("%7llu ", (long long) dn->dstat.st_ino);
614 if (all_fmt & LIST_BLOCKS) 614 if (all_fmt & LIST_BLOCKS)
615#if ENABLE_PLATFORM_MINGW32
616 /* MinGW does not have st_blocks */
617 column += printf("%4"OFF_FMT"u ", (off_t)0);
618#else
615 column += printf("%4"OFF_FMT"u ", (off_t) (dn->dstat.st_blocks >> 1)); 619 column += printf("%4"OFF_FMT"u ", (off_t) (dn->dstat.st_blocks >> 1));
620#endif
616 if (all_fmt & LIST_MODEBITS) 621 if (all_fmt & LIST_MODEBITS)
617 column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode)); 622 column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
618 if (all_fmt & LIST_NLINKS) 623 if (all_fmt & LIST_NLINKS)
@@ -790,6 +795,7 @@ static void showfiles(struct dnode **dn, unsigned nfiles)
790} 795}
791 796
792 797
798#if !ENABLE_PLATFORM_MINGW32
793#if ENABLE_DESKTOP 799#if ENABLE_DESKTOP
794/* http://www.opengroup.org/onlinepubs/9699919799/utilities/ls.html 800/* http://www.opengroup.org/onlinepubs/9699919799/utilities/ls.html
795 * If any of the -l, -n, -s options is specified, each list 801 * If any of the -l, -n, -s options is specified, each list
@@ -818,6 +824,7 @@ static off_t calculate_blocks(struct dnode **dn)
818 return blocks >> 1; 824 return blocks >> 1;
819} 825}
820#endif 826#endif
827#endif
821 828
822 829
823static struct dnode **list_dir(const char *, unsigned *); 830static struct dnode **list_dir(const char *, unsigned *);
@@ -843,10 +850,12 @@ static void showdirs(struct dnode **dn, int first)
843 printf("%s:\n", (*dn)->fullname); 850 printf("%s:\n", (*dn)->fullname);
844 } 851 }
845 subdnp = list_dir((*dn)->fullname, &nfiles); 852 subdnp = list_dir((*dn)->fullname, &nfiles);
853#if !ENABLE_PLATFORM_MINGW32
846#if ENABLE_DESKTOP 854#if ENABLE_DESKTOP
847 if ((all_fmt & STYLE_MASK) == STYLE_LONG) 855 if ((all_fmt & STYLE_MASK) == STYLE_LONG)
848 printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp)); 856 printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp));
849#endif 857#endif
858#endif
850 if (nfiles > 0) { 859 if (nfiles > 0) {
851 /* list all files at this level */ 860 /* list all files at this level */
852 dnsort(subdnp, nfiles); 861 dnsort(subdnp, nfiles);
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c
index 6a532fa9d..7b1ab8981 100644
--- a/coreutils/od_bloaty.c
+++ b/coreutils/od_bloaty.c
@@ -84,6 +84,13 @@ typedef long long llong;
84# define LDBL_DIG DBL_DIG 84# define LDBL_DIG DBL_DIG
85#endif 85#endif
86 86
87#ifdef __MINGW32__
88/* symbol conflict */
89#define CHAR SIZE_CHAR
90#define SHORT SIZE_SHORT
91#define LONG SIZE_LONG
92#define INT SIZE_INT
93#endif
87enum size_spec { 94enum size_spec {
88 NO_SIZE, 95 NO_SIZE,
89 CHAR, 96 CHAR,
diff --git a/coreutils/test.c b/coreutils/test.c
index 5864c7f32..3115ce6e7 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -599,6 +599,29 @@ static int filstat(char *nm, enum token mode)
599 return 0; 599 return 0;
600 } 600 }
601 601
602#if ENABLE_PLATFORM_MINGW32
603 if (mode == FILEX) {
604 int len = strlen(nm), ret;
605 if (len >= 4 &&
606 (!strcmp(nm+len-4,".exe") ||
607 !strcmp(nm+len-4,".com")))
608 ret = stat(nm, &s);
609 else {
610 char *exepath;
611 exepath = malloc(len+5);
612 memcpy(exepath, nm, len);
613 memcpy(exepath+len, ".exe", 5);
614 ret = stat(exepath, &s);
615 if (ret < 0) {
616 memcpy(exepath+len, ".exe", 5);
617 ret = stat(exepath, &s);
618 }
619 free(exepath);
620 }
621 return ret >= 0;
622 }
623#endif
624
602 if (stat(nm, &s) != 0) 625 if (stat(nm, &s) != 0)
603 return 0; 626 return 0;
604 if (mode == FILEXIST) 627 if (mode == FILEXIST)
diff --git a/debianutils/which.c b/debianutils/which.c
index 1558e5c6d..59dedf58d 100644
--- a/debianutils/which.c
+++ b/debianutils/which.c
@@ -36,11 +36,26 @@ int which_main(int argc UNUSED_PARAM, char **argv)
36 do { 36 do {
37#if ENABLE_DESKTOP 37#if ENABLE_DESKTOP
38/* Much bloat just to support -a */ 38/* Much bloat just to support -a */
39 if (strchr(*argv, '/')) { 39 if (strchr(*argv, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(*argv, '\\'))) {
40 if (execable_file(*argv)) { 40 if (execable_file(*argv)) {
41 puts(*argv); 41 puts(*argv);
42 continue; 42 continue;
43 } 43 }
44 else if (ENABLE_PLATFORM_MINGW32) {
45 char path[PATH_MAX];
46 int len = strlen(*argv);
47 memcpy(path, *argv, len);
48 memcpy(path+len, ".exe", 5);
49 if (execable_file(path)) {
50 puts(path);
51 continue;
52 }
53 memcpy(path+len, ".com", 5);
54 if (execable_file(path)) {
55 puts(path);
56 continue;
57 }
58 }
44 status = EXIT_FAILURE; 59 status = EXIT_FAILURE;
45 } else { 60 } else {
46 char *path2 = xstrdup(path); 61 char *path2 = xstrdup(path);
@@ -66,11 +81,26 @@ int which_main(int argc UNUSED_PARAM, char **argv)
66 } 81 }
67#else 82#else
68/* Just ignoring -a */ 83/* Just ignoring -a */
69 if (strchr(*argv, '/')) { 84 if (strchr(*argv, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(*argv, '\\'))) {
70 if (execable_file(*argv)) { 85 if (execable_file(*argv)) {
71 puts(*argv); 86 puts(*argv);
72 continue; 87 continue;
73 } 88 }
89 else if (ENABLE_PLATFORM_MINGW32) {
90 char path[PATH_MAX];
91 int len = strlen(*argv);
92 memcpy(path, *argv, len);
93 memcpy(path+len, ".exe", 5);
94 if (execable_file(path)) {
95 puts(path);
96 continue;
97 }
98 memcpy(path+len, ".com", 5);
99 if (execable_file(path)) {
100 puts(path);
101 continue;
102 }
103 }
74 } else { 104 } else {
75 char *path2 = xstrdup(path); 105 char *path2 = xstrdup(path);
76 char *tmp = path2; 106 char *tmp = path2;
diff --git a/editors/patch.c b/editors/patch.c
index 62477af16..507112377 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -25,7 +25,7 @@ static unsigned copy_lines(FILE *src_stream, FILE *dst_stream, unsigned lines_co
25{ 25{
26 while (src_stream && lines_count) { 26 while (src_stream && lines_count) {
27 char *line; 27 char *line;
28 line = xmalloc_fgets(src_stream); 28 line = xmalloc_fgetline(src_stream);
29 if (line == NULL) { 29 if (line == NULL) {
30 break; 30 break;
31 } 31 }
@@ -180,7 +180,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
180 printf("patching file %s\n", new_filename); 180 printf("patching file %s\n", new_filename);
181 181
182 /* Handle all hunks for this file */ 182 /* Handle all hunks for this file */
183 patch_line = xmalloc_fgets(patch_file); 183 patch_line = xmalloc_fgetline(patch_file);
184 while (patch_line) { 184 while (patch_line) {
185 unsigned count; 185 unsigned count;
186 unsigned src_beg_line; 186 unsigned src_beg_line;
@@ -221,7 +221,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
221 221
222 while (1) { 222 while (1) {
223 free(patch_line); 223 free(patch_line);
224 patch_line = xmalloc_fgets(patch_file); 224 patch_line = xmalloc_fgetline(patch_file);
225 if (patch_line == NULL) 225 if (patch_line == NULL)
226 break; /* EOF */ 226 break; /* EOF */
227 if (!*patch_line) { 227 if (!*patch_line) {
@@ -239,7 +239,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
239 if (src_cur_line == src_last_line) 239 if (src_cur_line == src_last_line)
240 break; 240 break;
241 if (src_stream) { 241 if (src_stream) {
242 src_line = xmalloc_fgets(src_stream); 242 src_line = xmalloc_fgetline(src_stream);
243 if (src_line) { 243 if (src_line) {
244 int diff = strcmp(src_line, patch_line + 1); 244 int diff = strcmp(src_line, patch_line + 1);
245 src_cur_line++; 245 src_cur_line++;
diff --git a/findutils/grep.c b/findutils/grep.c
index be290118f..d5fe10320 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -124,6 +124,14 @@ enum {
124#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L) 124#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L)
125#define NUL_DELIMITED (option_mask32 & OPT_z) 125#define NUL_DELIMITED (option_mask32 & OPT_z)
126 126
127#if ENABLE_PLATFORM_MINGW32
128# define RE_TRANSLATE_TYPE unsigned char*
129# undef ENABLE_EXTRA_COMPAT
130# define ENABLE_EXTRA_COMPAT 0
131# undef IF_EXTRA_COMPAT
132# define IF_EXTRA_COMPAT(x)
133#endif
134
127struct globals { 135struct globals {
128 int max_matches; 136 int max_matches;
129#if !ENABLE_EXTRA_COMPAT 137#if !ENABLE_EXTRA_COMPAT
diff --git a/include/libbb.h b/include/libbb.h
index 2f67c7f72..58a5968c5 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -75,6 +75,11 @@
75# include <arpa/inet.h> 75# include <arpa/inet.h>
76#elif defined __APPLE__ 76#elif defined __APPLE__
77# include <netinet/in.h> 77# include <netinet/in.h>
78#elif ENABLE_PLATFORM_MINGW32
79# define WINVER 0x0501
80# include <winsock2.h>
81# include <ws2tcpip.h>
82# undef s_addr
78#else 83#else
79# include <arpa/inet.h> 84# include <arpa/inet.h>
80# if !defined(__socklen_t_defined) && !defined(_SOCKLEN_T_DECLARED) 85# if !defined(__socklen_t_defined) && !defined(_SOCKLEN_T_DECLARED)
@@ -90,7 +95,9 @@
90 95
91/* Some libc's forget to declare these, do it ourself */ 96/* Some libc's forget to declare these, do it ourself */
92 97
98#if !ENABLE_PLATFORM_MINGW32
93extern char **environ; 99extern char **environ;
100#endif
94#if defined(__GLIBC__) && __GLIBC__ < 2 101#if defined(__GLIBC__) && __GLIBC__ < 2
95int vdprintf(int d, const char *format, va_list ap); 102int vdprintf(int d, const char *format, va_list ap);
96#endif 103#endif
@@ -128,6 +135,10 @@ int sysinfo(struct sysinfo* info);
128# define BUFSIZ 4096 135# define BUFSIZ 4096
129#endif 136#endif
130 137
138/* Can't use ENABLE_PLATFORM_MINGW32 because it's also called by host compiler */
139#if ENABLE_PLATFORM_MINGW32
140# include "mingw.h"
141#endif
131 142
132/* Make all declarations hidden (-fvisibility flag only affects definitions) */ 143/* Make all declarations hidden (-fvisibility flag only affects definitions) */
133/* (don't include system headers after this until corresponding pop!) */ 144/* (don't include system headers after this until corresponding pop!) */
@@ -470,6 +481,7 @@ void xlisten(int s, int backlog) FAST_FUNC;
470void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) FAST_FUNC; 481void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) FAST_FUNC;
471ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, 482ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
472 socklen_t tolen) FAST_FUNC; 483 socklen_t tolen) FAST_FUNC;
484#if !ENABLE_PLATFORM_MINGW32
473/* SO_REUSEADDR allows a server to rebind to an address that is already 485/* SO_REUSEADDR allows a server to rebind to an address that is already
474 * "in use" by old connections to e.g. previous server instance which is 486 * "in use" by old connections to e.g. previous server instance which is
475 * killed or crashed. Without it bind will fail until all such connections 487 * killed or crashed. Without it bind will fail until all such connections
@@ -582,6 +594,7 @@ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags,
582 struct sockaddr *from, 594 struct sockaddr *from,
583 struct sockaddr *to, 595 struct sockaddr *to,
584 socklen_t sa_size) FAST_FUNC; 596 socklen_t sa_size) FAST_FUNC;
597#endif
585 598
586 599
587char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; 600char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC;
@@ -729,6 +742,9 @@ char *safe_getdomainname(void) FAST_FUNC;
729char* str_tolower(char *str) FAST_FUNC; 742char* str_tolower(char *str) FAST_FUNC;
730 743
731char *utoa(unsigned n) FAST_FUNC; 744char *utoa(unsigned n) FAST_FUNC;
745#if ENABLE_PLATFORM_MINGW32
746# define itoa bb_itoa
747#endif
732char *itoa(int n) FAST_FUNC; 748char *itoa(int n) FAST_FUNC;
733/* Returns a pointer past the formatted number, does NOT null-terminate */ 749/* Returns a pointer past the formatted number, does NOT null-terminate */
734char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) FAST_FUNC; 750char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) FAST_FUNC;
@@ -1555,7 +1571,11 @@ extern const char bb_path_group_file[];
1555extern const char bb_path_motd_file[]; 1571extern const char bb_path_motd_file[];
1556extern const char bb_path_wtmp_file[]; 1572extern const char bb_path_wtmp_file[];
1557extern const char bb_dev_null[]; 1573extern const char bb_dev_null[];
1574#if ENABLE_PLATFORM_MINGW32
1575#define bb_busybox_exec_path get_busybox_exec_path()
1576#else
1558extern const char bb_busybox_exec_path[]; 1577extern const char bb_busybox_exec_path[];
1578#endif
1559/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, 1579/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
1560 * but I want to save a few bytes here */ 1580 * but I want to save a few bytes here */
1561extern const char bb_PATH_root_path[]; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */ 1581extern 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..53a0a0d67
--- /dev/null
+++ b/include/mingw.h
@@ -0,0 +1,347 @@
1#include <sys/utime.h>
2
3#define NOIMPL(name,...) static inline int name(__VA_ARGS__) { errno = ENOSYS; return -1; }
4#define IMPL(name,ret,retval,...) static inline ret name(__VA_ARGS__) { return retval; }
5
6/*
7 * sys/types.h
8 */
9typedef int gid_t;
10typedef int uid_t;
11typedef int pid_t;
12
13/*
14 * arpa/inet.h
15 */
16static inline unsigned int git_ntohl(unsigned int x) { return (unsigned int)ntohl(x); }
17#define ntohl git_ntohl
18
19/*
20 * fcntl.h
21 */
22#define F_DUPFD 0
23#define F_GETFD 1
24#define F_SETFD 2
25#define F_GETFL 3
26#define F_SETFL 3
27#define FD_CLOEXEC 0x1
28#define O_NONBLOCK 04000
29
30/*
31 * grp.h
32 */
33
34struct group {
35 char *gr_name;
36 char *gr_passwd;
37 gid_t gr_gid;
38 char **gr_mem;
39};
40IMPL(getgrnam,struct group *,NULL,const char *name UNUSED_PARAM);
41IMPL(getgrgid,struct group *,NULL,gid_t gid UNUSED_PARAM);
42NOIMPL(initgroups,const char *group UNUSED_PARAM,gid_t gid UNUSED_PARAM);
43static inline void endgrent(void) {}
44
45/*
46 * limits.h
47 */
48#define NAME_MAX 255
49#define MAXSYMLINKS 20
50
51
52/*
53 * poll.h
54 */
55struct pollfd {
56 int fd; /* file descriptor */
57 short events; /* requested events */
58 short revents; /* returned events */
59};
60typedef unsigned long nfds_t;
61#define POLLIN 1
62#define POLLHUP 2
63
64int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
65
66/*
67 * pwd.h
68 */
69struct passwd {
70 char *pw_name;
71 char *pw_gecos;
72 char *pw_dir;
73 uid_t pw_uid;
74 gid_t pw_gid;
75};
76
77IMPL(getpwnam,struct passwd *,NULL,const char *name UNUSED_PARAM);
78struct passwd *getpwuid(int uid);
79
80/*
81 * signal.h
82 */
83#define SIGHUP 1
84#define SIGQUIT 3
85#define SIGKILL 9
86#define SIGUSR1 10
87#define SIGUSR2 12
88#define SIGPIPE 13
89#define SIGALRM 14
90#define SIGCHLD 17
91#define SIGCONT 18
92#define SIGSTOP 19
93#define SIGTSTP 20
94#define SIGTTIN 21
95#define SIGTTOU 22
96#define SIGXCPU 24
97#define SIGXFSZ 25
98#define SIGVTALRM 26
99#define SIGWINCH 28
100
101#define SIG_UNBLOCK 1
102
103typedef void (__cdecl *sighandler_t)(int);
104struct sigaction {
105 sighandler_t sa_handler;
106 unsigned sa_flags;
107 int sa_mask;
108};
109#define sigemptyset(x) (void)0
110#define SA_RESTART 0
111
112int sigaction(int sig, struct sigaction *in, struct sigaction *out);
113sighandler_t mingw_signal(int sig, sighandler_t handler);
114NOIMPL(sigfillset,int *mask UNUSED_PARAM);
115NOIMPL(FAST_FUNC sigprocmask_allsigs, int how UNUSED_PARAM);
116NOIMPL(FAST_FUNC sigaction_set,int signo UNUSED_PARAM, const struct sigaction *sa UNUSED_PARAM);
117
118#define signal mingw_signal
119/*
120 * stdio.h
121 */
122#define fseeko(f,o,w) fseek(f,o,w)
123
124int fdprintf(int fd, const char *format, ...);
125FILE* mingw_fopen(const char *filename, const char *mode);
126int mingw_rename(const char*, const char*);
127#define fopen mingw_fopen
128#define rename mingw_rename
129
130/*
131 * ANSI emulation wrappers
132 */
133
134int winansi_fputs(const char *str, FILE *stream);
135int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2)));
136int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3)));
137#define fputs winansi_fputs
138#define printf(...) winansi_printf(__VA_ARGS__)
139#define fprintf(...) winansi_fprintf(__VA_ARGS__)
140
141/*
142 * stdlib.h
143 */
144#define WIFEXITED(x) ((unsigned)(x) < 259) /* STILL_ACTIVE */
145#define WEXITSTATUS(x) ((x) & 0xff)
146#define WIFSIGNALED(x) ((unsigned)(x) > 259)
147#define WTERMSIG(x) ((x) & 0x7f)
148#define WCOREDUMP(x) 0
149
150int clearenv(void);
151char *mingw_getenv(const char *name);
152int mkstemp(char *template);
153char *realpath(const char *path, char *resolved_path);
154int setenv(const char *name, const char *value, int replace);
155void unsetenv(const char *env);
156
157#define getenv mingw_getenv
158/*
159 * string.h
160 */
161char *strsep(char **stringp, const char *delim);
162
163/*
164 * sys/ioctl.h
165 */
166
167#define TIOCGWINSZ 0x5413
168
169NOIMPL(ioctl,int fd UNUSED_PARAM, int code UNUSED_PARAM,...);
170
171/*
172 * sys/socket.h
173 */
174#define hstrerror strerror
175
176NOIMPL(mingw_socket,int domain UNUSED_PARAM, int type UNUSED_PARAM, int protocol UNUSED_PARAM);
177NOIMPL(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);
178NOIMPL(mingw_listen,SOCKET s UNUSED_PARAM,int backlog UNUSED_PARAM);
179NOIMPL(mingw_bind,SOCKET s UNUSED_PARAM,const struct sockaddr* sa UNUSED_PARAM,int salen UNUSED_PARAM);
180
181/* Windows declaration is different */
182#define socket mingw_socket
183#define sendto mingw_sendto
184#define listen mingw_listen
185#define bind mingw_bind
186
187/*
188 * sys/stat.h
189 */
190#define S_ISUID 04000
191#define S_ISGID 02000
192#define S_ISVTX 01000
193#ifndef S_IRWXU
194#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
195#endif
196#define S_IRWXG (S_IRWXU >> 3)
197#define S_IRWXO (S_IRWXG >> 3)
198
199#define S_IFSOCK 0140000
200#define S_IFLNK 0120000 /* Symbolic link */
201#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
202#define S_ISSOCK(x) 0
203
204#define S_IRGRP (S_IRUSR >> 3)
205#define S_IWGRP (S_IWUSR >> 3)
206#define S_IXGRP (S_IXUSR >> 3)
207#define S_IROTH (S_IRGRP >> 3)
208#define S_IWOTH (S_IWGRP >> 3)
209#define S_IXOTH (S_IXGRP >> 3)
210
211NOIMPL(fchmod,int fildes UNUSED_PARAM, mode_t mode UNUSED_PARAM);
212NOIMPL(fchown,int fd UNUSED_PARAM, uid_t uid UNUSED_PARAM, gid_t gid UNUSED_PARAM);
213int mingw_mkdir(const char *path, int mode);
214
215/* Use mingw_lstat() instead of lstat()/stat() and
216 * mingw_fstat() instead of fstat() on Windows.
217 */
218int mingw_lstat(const char *file_name, struct stat *buf);
219int mingw_fstat(int fd, struct stat *buf);
220
221#define mkdir mingw_mkdir
222#define stat(x,y) mingw_lstat(x,y)
223#define lseek _lseeki64
224#define fstat mingw_fstat
225#define lstat mingw_lstat
226#define _stati64 mingw_lstat
227
228/*
229 * sys/sysmacros.h
230 */
231#define makedev(a,b) 0*(a)*(b) /* avoid unused warning */
232#define minor(x) 0
233#define major(x) 0
234
235/*
236 * sys/time.h
237 */
238struct itimerval {
239 struct timeval it_value, it_interval;
240};
241#define ITIMER_REAL 0
242
243int setitimer(int type, struct itimerval *in, struct itimerval *out);
244
245/*
246 * sys/wait.h
247 */
248#define WNOHANG 1
249#define WUNTRACED 2
250int waitpid(pid_t pid, int *status, unsigned options);
251
252/*
253 * time.h
254 */
255struct tm *gmtime_r(const time_t *timep, struct tm *result);
256struct tm *localtime_r(const time_t *timep, struct tm *result);
257char *strptime(const char *s, const char *format, struct tm *tm);
258
259/*
260 * unistd.h
261 */
262#define PIPE_BUF 8192
263
264IMPL(alarm,unsigned int,0,unsigned int seconds UNUSED_PARAM);
265NOIMPL(chown,const char *path UNUSED_PARAM, uid_t uid UNUSED_PARAM, gid_t gid UNUSED_PARAM);
266NOIMPL(chroot,const char *root UNUSED_PARAM);
267int mingw_dup2 (int fd, int fdto);
268char *mingw_getcwd(char *pointer, int len);
269
270
271#ifdef USE_WIN32_MMAP
272int mingw_getpagesize(void);
273#define getpagesize mingw_getpagesize
274#else
275int getpagesize(void); /* defined in MinGW's libgcc.a */
276#endif
277
278IMPL(getgid,int,1,void);
279NOIMPL(getgroups,int n UNUSED_PARAM,gid_t *groups UNUSED_PARAM);
280IMPL(getppid,int,1,void);
281IMPL(getegid,int,1,void);
282IMPL(geteuid,int,1,void);
283NOIMPL(getsid,pid_t pid UNUSED_PARAM);
284IMPL(getuid,int,1,void);
285int fcntl(int fd, int cmd, ...);
286#define fork() -1
287IMPL(fsync,int,0,int fd UNUSED_PARAM);
288NOIMPL(kill,pid_t pid UNUSED_PARAM, int sig UNUSED_PARAM);
289int link(const char *oldpath, const char *newpath);
290NOIMPL(mknod,const char *name UNUSED_PARAM, mode_t mode UNUSED_PARAM, dev_t device UNUSED_PARAM);
291int mingw_open (const char *filename, int oflags, ...);
292int pipe(int filedes[2]);
293NOIMPL(readlink,const char *path UNUSED_PARAM, char *buf UNUSED_PARAM, size_t bufsiz UNUSED_PARAM);
294NOIMPL(setgid,gid_t gid UNUSED_PARAM);
295NOIMPL(setsid,void);
296NOIMPL(setuid,uid_t gid UNUSED_PARAM);
297unsigned int sleep(unsigned int seconds);
298NOIMPL(symlink,const char *oldpath UNUSED_PARAM, const char *newpath UNUSED_PARAM);
299static inline void sync(void) {}
300NOIMPL(ttyname_r,int fd UNUSED_PARAM, char *buf UNUSED_PARAM, int sz UNUSED_PARAM);
301int mingw_unlink(const char *pathname);
302NOIMPL(vfork,void);
303
304#define dup2 mingw_dup2
305#define getcwd mingw_getcwd
306#define lchown(a,b,c) chown(a,b,c)
307#define open mingw_open
308#define unlink mingw_unlink
309
310/*
311 * utime.h
312 */
313int mingw_utime(const char *file_name, const struct utimbuf *times);
314int utimes(const char *file_name, const struct timeval times[2]);
315
316#define utime mingw_utime
317
318/*
319 * MinGW specific
320 */
321#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
322#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
323#define PRIuMAX "I64u"
324
325pid_t mingw_spawn(char **argv);
326int mingw_execv(const char *cmd, const char *const *argv);
327int mingw_execvp(const char *cmd, const char *const *argv);
328int mingw_execve(const char *cmd, const char *const *argv, const char *const *envp);
329pid_t mingw_spawn_applet(int mode, const char *applet, const char *const *argv, const char *const *envp);
330pid_t mingw_spawn_1(int mode, const char *cmd, const char *const *argv, const char *const *envp);
331#define execvp mingw_execvp
332#define execve mingw_execve
333#define execv mingw_execv
334
335const char * next_path_sep(const char *path);
336#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
337#define is_absolute_path(path) ((path)[0] == '/' || has_dos_drive_prefix(path))
338
339/*
340 * helpers
341 */
342
343char **copy_environ(const char *const *env);
344void free_environ(char **env);
345char **env_setenv(char **env, const char *name);
346
347const char *get_busybox_exec_path(void);
diff --git a/include/platform.h b/include/platform.h
index f87add552..d1ac391eb 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -7,6 +7,16 @@
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
19
10/* Assume all these functions exist by default. Platforms where it is not 20/* Assume all these functions exist by default. Platforms where it is not
11 * true will #undef them below. 21 * true will #undef them below.
12 */ 22 */
@@ -139,7 +149,7 @@
139 149
140/* Make all declarations hidden (-fvisibility flag only affects definitions) */ 150/* Make all declarations hidden (-fvisibility flag only affects definitions) */
141/* (don't include system headers after this until corresponding pop!) */ 151/* (don't include system headers after this until corresponding pop!) */
142#if __GNUC_PREREQ(4,1) 152#if __GNUC_PREREQ(4,1) && !ENABLE_PLATFORM_MINGW32
143# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN _Pragma("GCC visibility push(hidden)") 153# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN _Pragma("GCC visibility push(hidden)")
144# define POP_SAVED_FUNCTION_VISIBILITY _Pragma("GCC visibility pop") 154# define POP_SAVED_FUNCTION_VISIBILITY _Pragma("GCC visibility pop")
145#else 155#else
@@ -160,6 +170,13 @@
160# define bswap_32 __bswap32 170# define bswap_32 __bswap32
161# define bswap_16 __bswap16 171# define bswap_16 __bswap16
162# define __BIG_ENDIAN__ (_BYTE_ORDER == _BIG_ENDIAN) 172# define __BIG_ENDIAN__ (_BYTE_ORDER == _BIG_ENDIAN)
173#elif ENABLE_PLATFORM_MINGW32
174# define __BIG_ENDIAN 0
175# define __LITTLE_ENDIAN 1
176# define __BYTE_ORDER __LITTLE_ENDIAN
177# define bswap_16(x) ((((x) & 0xFF00) >> 8) | (((x) & 0xFF) << 8))
178# define bswap_32(x) ((bswap_16(((x) & 0xFFFF0000L) >> 16)) | (bswap_16((x) & 0xFFFFL) << 16))
179# define bswap_64(x) ((bswap_32(((x) & 0xFFFFFFFF00000000LL) >> 32)) | (bswap_32((x) & 0xFFFFFFFFLL) << 32))
163#elif !defined __APPLE__ 180#elif !defined __APPLE__
164# include <byteswap.h> 181# include <byteswap.h>
165# include <endian.h> 182# include <endian.h>
@@ -229,7 +246,8 @@ typedef uint32_t bb__aliased_uint32_t FIX_ALIASING;
229/* ---- Compiler dependent settings ------------------------- */ 246/* ---- Compiler dependent settings ------------------------- */
230 247
231#if (defined __digital__ && defined __unix__) \ 248#if (defined __digital__ && defined __unix__) \
232 || defined __APPLE__ || defined __FreeBSD__ 249 || defined __APPLE__ || defined __FreeBSD__ \
250 || ENABLE_PLATFORM_MINGW32
233# undef HAVE_MNTENT_H 251# undef HAVE_MNTENT_H
234# undef HAVE_SYS_STATFS_H 252# undef HAVE_SYS_STATFS_H
235#else 253#else
@@ -346,6 +364,16 @@ typedef unsigned smalluint;
346# undef HAVE_STRCHRNUL 364# undef HAVE_STRCHRNUL
347#endif 365#endif
348 366
367#if ENABLE_PLATFORM_MINGW32
368# undef HAVE_FDPRINTF
369# undef HAVE_MKDTEMP
370# undef HAVE_SETBIT
371# undef HAVE_STRCASESTR
372# undef HAVE_STRCHRNUL
373# undef HAVE_STRSIGNAL
374# undef HAVE_VASPRINTF
375#endif
376
349#if defined(__WATCOMC__) 377#if defined(__WATCOMC__)
350# undef HAVE_FDPRINTF 378# undef HAVE_FDPRINTF
351# undef HAVE_MEMRCHR 379# undef HAVE_MEMRCHR
@@ -397,6 +425,9 @@ extern char *strchrnul(const char *s, int c) FAST_FUNC;
397#endif 425#endif
398 426
399#ifndef HAVE_VASPRINTF 427#ifndef HAVE_VASPRINTF
428# if ENABLE_PLATFORM_MINGW32
429# include <stdarg.h>
430# endif
400extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC; 431extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC;
401#endif 432#endif
402 433
diff --git a/libbb/Kbuild b/libbb/Kbuild
index 1b11d5d39..a8a1da1f9 100644
--- a/libbb/Kbuild
+++ b/libbb/Kbuild
@@ -37,27 +37,20 @@ lib-y += fgets_str.o
37lib-y += find_pid_by_name.o 37lib-y += find_pid_by_name.o
38lib-y += find_root_device.o 38lib-y += find_root_device.o
39lib-y += full_write.o 39lib-y += full_write.o
40lib-y += get_console.o
41lib-y += get_last_path_component.o 40lib-y += get_last_path_component.o
42lib-y += get_line_from_file.o 41lib-y += get_line_from_file.o
43lib-y += getopt32.o 42lib-y += getopt32.o
44lib-y += getpty.o
45lib-y += get_volsize.o 43lib-y += get_volsize.o
46lib-y += herror_msg.o 44lib-y += herror_msg.o
47lib-y += herror_msg_and_die.o 45lib-y += herror_msg_and_die.o
48lib-y += human_readable.o 46lib-y += human_readable.o
49lib-y += inet_common.o
50lib-y += info_msg.o 47lib-y += info_msg.o
51lib-y += inode_hash.o 48lib-y += inode_hash.o
52lib-y += isdirectory.o 49lib-y += isdirectory.o
53lib-y += kernel_version.o
54lib-y += last_char_is.o 50lib-y += last_char_is.o
55lib-y += lineedit.o lineedit_ptr_hack.o 51lib-y += lineedit.o lineedit_ptr_hack.o
56lib-y += llist.o 52lib-y += llist.o
57lib-y += login.o
58lib-y += make_directory.o 53lib-y += make_directory.o
59lib-y += makedev.o
60lib-y += match_fstype.o
61lib-y += md5.o 54lib-y += md5.o
62# Alternative (disabled) implementation 55# Alternative (disabled) implementation
63#lib-y += md5prime.o 56#lib-y += md5prime.o
@@ -81,17 +74,14 @@ lib-y += procps.o
81lib-y += progress.o 74lib-y += progress.o
82lib-y += ptr_to_globals.o 75lib-y += ptr_to_globals.o
83lib-y += read.o 76lib-y += read.o
84lib-y += read_key.o
85lib-y += recursive_action.o 77lib-y += recursive_action.o
86lib-y += remove_file.o 78lib-y += remove_file.o
87lib-y += run_shell.o 79lib-y += run_shell.o
88lib-y += safe_gethostname.o
89lib-y += safe_poll.o 80lib-y += safe_poll.o
90lib-y += safe_strncpy.o 81lib-y += safe_strncpy.o
91lib-y += safe_write.o 82lib-y += safe_write.o
92lib-y += setup_environment.o 83lib-y += setup_environment.o
93lib-y += sha1.o 84lib-y += sha1.o
94lib-y += signals.o
95lib-y += simplify_path.o 85lib-y += simplify_path.o
96lib-y += single_argv.o 86lib-y += single_argv.o
97lib-y += skip_whitespace.o 87lib-y += skip_whitespace.o
@@ -101,7 +91,6 @@ lib-y += strrstr.o
101lib-y += time.o 91lib-y += time.o
102lib-y += trim.o 92lib-y += trim.o
103lib-y += u_signal_names.o 93lib-y += u_signal_names.o
104lib-y += udp_io.o
105lib-y += uuencode.o 94lib-y += uuencode.o
106lib-y += vdprintf.o 95lib-y += vdprintf.o
107lib-y += verror_msg.o 96lib-y += verror_msg.o
@@ -111,15 +100,27 @@ lib-y += wfopen.o
111lib-y += wfopen_input.o 100lib-y += wfopen_input.o
112lib-y += write.o 101lib-y += write.o
113lib-y += xatonum.o 102lib-y += xatonum.o
114lib-y += xconnect.o 103lib-y += xfunc_die.o
115lib-y += xfuncs.o 104lib-y += xfuncs.o
116lib-y += xfuncs_printf.o 105lib-y += xfuncs_printf.o
117lib-y += xfunc_die.o
118lib-y += xgetcwd.o 106lib-y += xgetcwd.o
119lib-y += xgethostbyname.o
120lib-y += xreadlink.o 107lib-y += xreadlink.o
121lib-y += xrealloc_vector.o 108lib-y += xrealloc_vector.o
122 109
110lib-$(CONFIG_PLATFORM_POSIX) += get_console.o
111lib-$(CONFIG_PLATFORM_POSIX) += getpty.o
112lib-$(CONFIG_PLATFORM_POSIX) += inet_common.o
113lib-$(CONFIG_PLATFORM_POSIX) += kernel_version.o
114lib-$(CONFIG_PLATFORM_POSIX) += login.o
115lib-$(CONFIG_PLATFORM_POSIX) += makedev.o
116lib-$(CONFIG_PLATFORM_POSIX) += match_fstype.o
117lib-$(CONFIG_PLATFORM_POSIX) += read_key.o
118lib-$(CONFIG_PLATFORM_POSIX) += safe_gethostname.o
119lib-$(CONFIG_PLATFORM_POSIX) += signals.o
120lib-$(CONFIG_PLATFORM_POSIX) += udp_io.o
121lib-$(CONFIG_PLATFORM_POSIX) += xconnect.o
122lib-$(CONFIG_PLATFORM_POSIX) += xgethostbyname.o
123
123lib-$(CONFIG_FEATURE_UTMP) += utmp.o 124lib-$(CONFIG_FEATURE_UTMP) += utmp.o
124 125
125# A mix of optimizations (why build stuff we know won't be used) 126# A mix of optimizations (why build stuff we know won't be used)
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index a8cd8e65f..f6dc1f171 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -827,6 +827,18 @@ int main(int argc UNUSED_PARAM, char **argv)
827 applet_name = argv[0]; 827 applet_name = argv[0];
828 if (applet_name[0] == '-') 828 if (applet_name[0] == '-')
829 applet_name++; 829 applet_name++;
830 if (ENABLE_PLATFORM_MINGW32) {
831 const char *applet_name_env = getenv("BUSYBOX_APPLET_NAME");
832 if (applet_name_env && *applet_name_env) {
833 applet_name = applet_name_env;
834 unsetenv("BUSYBOX_APPLET_NAME");
835 }
836 else {
837 int len = strlen(applet_name);
838 if (len > 4 && !strcmp(applet_name+len-4, ".exe"))
839 argv[0][applet_name-argv[0]+len-4] = '\0';
840 }
841 }
830 applet_name = bb_basename(applet_name); 842 applet_name = bb_basename(applet_name);
831 843
832 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ 844 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */
diff --git a/libbb/bb_basename.c b/libbb/bb_basename.c
index bab4166d6..cc9b246e3 100644
--- a/libbb/bb_basename.c
+++ b/libbb/bb_basename.c
@@ -14,5 +14,10 @@ const char* FAST_FUNC bb_basename(const char *name)
14 const char *cp = strrchr(name, '/'); 14 const char *cp = strrchr(name, '/');
15 if (cp) 15 if (cp)
16 return cp + 1; 16 return cp + 1;
17 if (ENABLE_PLATFORM_MINGW32) {
18 cp = strrchr(name, '\\');
19 if (cp)
20 return cp + 1;
21 }
17 return name; 22 return name;
18} 23}
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index ed765d8f0..80a64f791 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -85,7 +85,12 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
85/* Inverse of cp -d ("cp without -d") */ 85/* Inverse of cp -d ("cp without -d") */
86#define FLAGS_DEREF (flags & (FILEUTILS_DEREFERENCE + FILEUTILS_DEREFERENCE_L0)) 86#define FLAGS_DEREF (flags & (FILEUTILS_DEREFERENCE + FILEUTILS_DEREFERENCE_L0))
87 87
88#if ENABLE_PLATFORM_MINGW32
89 /* stat can't be aliased, and MinGW uses lstat anyway */
90 if (lstat(source, &source_stat) < 0) {
91#else
88 if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) { 92 if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) {
93#endif
89 /* This may be a dangling symlink. 94 /* This may be a dangling symlink.
90 * Making [sym]links to dangling symlinks works, so... */ 95 * Making [sym]links to dangling symlinks works, so... */
91 if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) 96 if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK))
diff --git a/libbb/execable.c b/libbb/execable.c
index 5c7ac16a2..06b1c534b 100644
--- a/libbb/execable.c
+++ b/libbb/execable.c
@@ -16,6 +16,14 @@
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 int len = strlen(name);
21 return len > 4 &&
22 (!strcasecmp(name+len-4, ".exe") ||
23 !strcasecmp(name+len-4, ".com")) &&
24 !stat(name, &s) &&
25 S_ISREG(s.st_mode);
26 }
19 return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); 27 return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode));
20} 28}
21 29
@@ -28,13 +36,17 @@ int FAST_FUNC execable_file(const char *name)
28 * return NULL otherwise; (PATHp is undefined) 36 * return NULL otherwise; (PATHp is undefined)
29 * in all cases (*PATHp) contents will be trashed (s/:/NUL/). 37 * in all cases (*PATHp) contents will be trashed (s/:/NUL/).
30 */ 38 */
39#if !ENABLE_PLATFORM_MINGW32
40#define next_path_sep(s) strchr(s, ':')
41#endif
42
31char* FAST_FUNC find_execable(const char *filename, char **PATHp) 43char* FAST_FUNC find_execable(const char *filename, char **PATHp)
32{ 44{
33 char *p, *n; 45 char *p, *n;
34 46
35 p = *PATHp; 47 p = *PATHp;
36 while (p) { 48 while (p) {
37 n = strchr(p, ':'); 49 n = (char*)next_path_sep(p);
38 if (n) 50 if (n)
39 *n++ = '\0'; 51 *n++ = '\0';
40 if (*p != '\0') { /* it's not a PATH="foo::bar" situation */ 52 if (*p != '\0') { /* it's not a PATH="foo::bar" situation */
@@ -43,6 +55,27 @@ char* FAST_FUNC find_execable(const char *filename, char **PATHp)
43 *PATHp = n; 55 *PATHp = n;
44 return p; 56 return p;
45 } 57 }
58 if (ENABLE_PLATFORM_MINGW32) {
59 int len = strlen(p);
60 if (len > 4 &&
61 (!strcasecmp(p+len-4, ".exe") ||
62 !strcasecmp(p+len-4, ".com")))
63 ; /* nothing, already tested by find_execable() */
64 else {
65 char *np = xmalloc(len+4+1);
66 memcpy(np, p, len);
67 memcpy(np+len, ".exe", 5);
68 if (execable_file(np)) {
69 *PATHp = n;
70 return np;
71 }
72 memcpy(np+len, ".com", 5);
73 if (execable_file(np)) {
74 *PATHp = n;
75 return np;
76 }
77 }
78 }
46 free(p); 79 free(p);
47 } 80 }
48 p = n; 81 p = n;
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index b5f83c127..20e1b8a8b 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -534,7 +534,7 @@ getopt32(char **argv, const char *applet_opts, ...)
534 * run_nofork_applet_prime() does this, but we might end up here 534 * run_nofork_applet_prime() does this, but we might end up here
535 * also via gunzip_main() -> gzip_main(). Play safe. 535 * also via gunzip_main() -> gzip_main(). Play safe.
536 */ 536 */
537#ifdef __GLIBC__ 537#if defined(__GLIBC__) || ENABLE_PLATFORM_MINGW32
538 optind = 0; 538 optind = 0;
539#else /* BSD style */ 539#else /* BSD style */
540 optind = 1; 540 optind = 1;
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 18664b8c1..f7faf4639 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -686,7 +686,11 @@ static int path_parse(char ***p, int flags)
686 tmp = (char*)pth; 686 tmp = (char*)pth;
687 npth = 1; /* path component count */ 687 npth = 1; /* path component count */
688 while (1) { 688 while (1) {
689#if ENABLE_PLATFORM_MINGW32
690 tmp = next_path_sep(tmp);
691#else
689 tmp = strchr(tmp, ':'); 692 tmp = strchr(tmp, ':');
693#endif
690 if (!tmp) 694 if (!tmp)
691 break; 695 break;
692 if (*++tmp == '\0') 696 if (*++tmp == '\0')
@@ -698,7 +702,11 @@ static int path_parse(char ***p, int flags)
698 res[0] = tmp = xstrdup(pth); 702 res[0] = tmp = xstrdup(pth);
699 npth = 1; 703 npth = 1;
700 while (1) { 704 while (1) {
705#if ENABLE_PLATFORM_MINGW32
706 tmp = next_path_sep(tmp);
707#else
701 tmp = strchr(tmp, ':'); 708 tmp = strchr(tmp, ':');
709#endif
702 if (!tmp) 710 if (!tmp)
703 break; 711 break;
704 *tmp++ = '\0'; /* ':' -> '\0' */ 712 *tmp++ = '\0'; /* ':' -> '\0' */
@@ -1893,6 +1901,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1893 1901
1894 INIT_S(); 1902 INIT_S();
1895 1903
1904#if !ENABLE_PLATFORM_MINGW32
1896 if (tcgetattr(STDIN_FILENO, &initial_settings) < 0 1905 if (tcgetattr(STDIN_FILENO, &initial_settings) < 0
1897 || !(initial_settings.c_lflag & ECHO) 1906 || !(initial_settings.c_lflag & ECHO)
1898 ) { 1907 ) {
@@ -1906,6 +1915,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
1906 DEINIT_S(); 1915 DEINIT_S();
1907 return len; 1916 return len;
1908 } 1917 }
1918#endif
1909 1919
1910 init_unicode(); 1920 init_unicode();
1911 1921
diff --git a/libbb/make_directory.c b/libbb/make_directory.c
index 4486eb1ed..1eb8a8a49 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 1d0e58720..ffa8d00cd 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -44,7 +44,11 @@ const char bb_path_group_file[] ALIGN1 = "/etc/group";
44const char bb_path_gshadow_file[] ALIGN1 = "/etc/gshadow"; 44const char bb_path_gshadow_file[] ALIGN1 = "/etc/gshadow";
45const char bb_path_motd_file[] ALIGN1 = "/etc/motd"; 45const char bb_path_motd_file[] ALIGN1 = "/etc/motd";
46const char bb_dev_null[] ALIGN1 = "/dev/null"; 46const char bb_dev_null[] ALIGN1 = "/dev/null";
47#if ENABLE_PLATFORM_MINGW32
48/* bb_busybox_exec_path is redefined to get_busybox_exec_path() in libbb.h */
49#else
47const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH; 50const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH;
51#endif
48const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL; 52const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL;
49/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, 53/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
50 * but I want to save a few bytes here. Check libbb.h before changing! */ 54 * but I want to save a few bytes here. Check libbb.h before changing! */
@@ -57,6 +61,7 @@ const int const_int_1 = 1;
57 * and it will end up in bss */ 61 * and it will end up in bss */
58const int const_int_0 = 0; 62const int const_int_0 = 0;
59 63
64#if !ENABLE_PLATFORM_MINGW32 /* No wtmp on Windows */
60#include <utmp.h> 65#include <utmp.h>
61/* This is usually something like "/var/adm/wtmp" or "/var/log/wtmp" */ 66/* This is usually something like "/var/adm/wtmp" or "/var/log/wtmp" */
62const char bb_path_wtmp_file[] ALIGN1 = 67const char bb_path_wtmp_file[] ALIGN1 =
@@ -67,6 +72,7 @@ const char bb_path_wtmp_file[] ALIGN1 =
67#else 72#else
68#error unknown path to wtmp file 73#error unknown path to wtmp file
69#endif 74#endif
75#endif
70 76
71/* We use it for "global" data via *(struct global*)&bb_common_bufsiz1. 77/* We use it for "global" data via *(struct global*)&bb_common_bufsiz1.
72 * Since gcc insists on aligning struct global's members, it would be a pity 78 * Since gcc insists on aligning struct global's members, it would be a pity
diff --git a/libbb/platform.c b/libbb/platform.c
index 17ad3f75a..8642337d4 100644
--- a/libbb/platform.c
+++ b/libbb/platform.c
@@ -51,8 +51,21 @@ int fdprintf(int fd, const char *format, ...)
51 char *string_ptr; 51 char *string_ptr;
52 52
53 va_start(p, format); 53 va_start(p, format);
54 r = vasprintf(&string_ptr, format, p); 54 if (ENABLE_PLATFORM_MINGW32) {
55 string_ptr = xmalloc(1024);
56 r = vsnprintf(string_ptr, 1024, format, p);
57 }
58 else
59 r = vasprintf(&string_ptr, format, p);
55 va_end(p); 60 va_end(p);
61 if (ENABLE_PLATFORM_MINGW32 && r > 0) {
62 free(string_ptr);
63 r += 2;
64 string_ptr = xmalloc(r);
65 va_start(p, format);
66 r = vsnprintf(string_ptr, r, format, p);
67 va_end(p);
68 }
56 if (r >= 0) { 69 if (r >= 0) {
57 r = full_write(fd, string_ptr, r); 70 r = full_write(fd, string_ptr, r);
58 free(string_ptr); 71 free(string_ptr);
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 07024f5f0..08d9199c1 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. */
@@ -226,7 +229,7 @@ int FAST_FUNC spawn_and_wait(char **argv)
226 { 229 {
227 return run_nofork_applet(a, argv); 230 return run_nofork_applet(a, argv);
228 } 231 }
229#if BB_MMU 232#if BB_MMU && !ENABLE_PLATFORM_MINGW32
230 /* MMU only */ 233 /* MMU only */
231 /* a->noexec is true */ 234 /* a->noexec is true */
232 rc = fork(); 235 rc = fork();
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 7207ec58a..f8b1b81cd 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -287,8 +287,22 @@ char* FAST_FUNC xasprintf(const char *format, ...)
287 char *string_ptr; 287 char *string_ptr;
288 288
289 va_start(p, format); 289 va_start(p, format);
290#if ENABLE_PLATFORM_MINGW32
291 string_ptr = xmalloc(1024);
292 r = vsnprintf(string_ptr, 1024, format, p);
293 va_end(p);
294 if (r > 0) {
295 free(string_ptr);
296 r += 2;
297 string_ptr = xmalloc(r);
298 va_start(p, format);
299 r = vsnprintf(string_ptr, r, format, p);
300 va_end(p);
301 }
302#else
290 r = vasprintf(&string_ptr, format, p); 303 r = vasprintf(&string_ptr, format, p);
291 va_end(p); 304 va_end(p);
305#endif
292 306
293 if (r < 0) 307 if (r < 0)
294 bb_error_msg_and_die(bb_msg_memory_exhausted); 308 bb_error_msg_and_die(bb_msg_memory_exhausted);
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index faa0e1646..1a012456f 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/scripts/defconfig.mingw32 b/scripts/defconfig.mingw32
new file mode 100644
index 000000000..356a08226
--- /dev/null
+++ b/scripts/defconfig.mingw32
@@ -0,0 +1,923 @@
1#
2# Automatically generated make config: don't edit
3# Busybox version: 1.17.0.git
4# Thu Sep 9 01:05:40 2010
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
22CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
23# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
24# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
25CONFIG_SHOW_USAGE=y
26CONFIG_FEATURE_VERBOSE_USAGE=y
27CONFIG_FEATURE_COMPRESS_USAGE=y
28# CONFIG_FEATURE_INSTALLER is not set
29# CONFIG_LOCALE_SUPPORT is not set
30# CONFIG_UNICODE_SUPPORT is not set
31# CONFIG_UNICODE_USING_LOCALE is not set
32# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set
33CONFIG_SUBST_WCHAR=0
34CONFIG_LAST_SUPPORTED_WCHAR=0
35# CONFIG_UNICODE_COMBINING_WCHARS is not set
36# CONFIG_UNICODE_WIDE_WCHARS is not set
37# CONFIG_UNICODE_BIDI_SUPPORT is not set
38# CONFIG_UNICODE_NEUTRAL_TABLE is not set
39CONFIG_LONG_OPTS=y
40# CONFIG_FEATURE_DEVPTS is not set
41# CONFIG_FEATURE_CLEAN_UP is not set
42# CONFIG_FEATURE_UTMP is not set
43# CONFIG_FEATURE_WTMP is not set
44# CONFIG_FEATURE_PIDFILE is not set
45# CONFIG_FEATURE_SUID is not set
46# CONFIG_FEATURE_SUID_CONFIG is not set
47# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
48# CONFIG_SELINUX is not set
49CONFIG_FEATURE_PREFER_APPLETS=y
50CONFIG_BUSYBOX_EXEC_PATH=""
51# CONFIG_FEATURE_SYSLOG is not set
52# CONFIG_FEATURE_HAVE_RPC is not set
53
54#
55# Build Options
56#
57# CONFIG_STATIC is not set
58# CONFIG_PIE is not set
59# CONFIG_NOMMU is not set
60# CONFIG_BUILD_LIBBUSYBOX is not set
61# CONFIG_FEATURE_INDIVIDUAL is not set
62# CONFIG_FEATURE_SHARED_BUSYBOX is not set
63# CONFIG_LFS is not set
64CONFIG_CROSS_COMPILER_PREFIX="mingw32-"
65CONFIG_EXTRA_CFLAGS="-g -O0"
66
67#
68# Debugging Options
69#
70CONFIG_DEBUG=y
71# CONFIG_DEBUG_PESSIMIZE is not set
72# CONFIG_PLATFORM_MINGW32_TEST is not set
73# CONFIG_WERROR is not set
74CONFIG_NO_DEBUG_LIB=y
75# CONFIG_DMALLOC is not set
76# CONFIG_EFENCE is not set
77# CONFIG_INSTALL_NO_USR is not set
78# CONFIG_INSTALL_APPLET_SYMLINKS is not set
79# CONFIG_INSTALL_APPLET_HARDLINKS is not set
80# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
81# CONFIG_INSTALL_APPLET_DONT is not set
82# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
83# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
84# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
85CONFIG_PREFIX=""
86
87#
88# Busybox Library Tuning
89#
90CONFIG_PASSWORD_MINLEN=6
91CONFIG_MD5_SIZE_VS_SPEED=2
92# CONFIG_FEATURE_FAST_TOP is not set
93# CONFIG_FEATURE_ETC_NETWORKS is not set
94# CONFIG_FEATURE_CYGWIN_TTY is not set
95CONFIG_FEATURE_EDITING=y
96CONFIG_FEATURE_EDITING_MAX_LEN=1024
97# CONFIG_FEATURE_EDITING_VI is not set
98CONFIG_FEATURE_EDITING_HISTORY=0
99# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set
100CONFIG_FEATURE_TAB_COMPLETION=y
101# CONFIG_FEATURE_USERNAME_COMPLETION is not set
102# CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set
103# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set
104CONFIG_FEATURE_NON_POSIX_CP=y
105# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
106CONFIG_FEATURE_COPYBUF_KB=4
107# CONFIG_MONOTONIC_SYSCALL is not set
108CONFIG_IOCTL_HEX2STR_ERROR=y
109# CONFIG_FEATURE_HWIB is not set
110
111#
112# Applets
113#
114
115#
116# Archival Utilities
117#
118CONFIG_FEATURE_SEAMLESS_LZMA=y
119CONFIG_FEATURE_SEAMLESS_BZ2=y
120CONFIG_FEATURE_SEAMLESS_GZ=y
121CONFIG_FEATURE_SEAMLESS_Z=y
122CONFIG_AR=y
123CONFIG_FEATURE_AR_LONG_FILENAMES=y
124CONFIG_FEATURE_AR_CREATE=y
125CONFIG_BUNZIP2=y
126CONFIG_BZIP2=y
127# CONFIG_CPIO is not set
128# CONFIG_FEATURE_CPIO_O is not set
129# CONFIG_FEATURE_CPIO_P is not set
130# CONFIG_DPKG is not set
131# CONFIG_DPKG_DEB is not set
132# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
133CONFIG_GUNZIP=y
134CONFIG_GZIP=y
135CONFIG_FEATURE_GZIP_LONG_OPTIONS=y
136# CONFIG_LZOP is not set
137# CONFIG_LZOP_COMPR_HIGH is not set
138# CONFIG_RPM2CPIO is not set
139# CONFIG_RPM is not set
140CONFIG_TAR=y
141CONFIG_FEATURE_TAR_CREATE=y
142CONFIG_FEATURE_TAR_AUTODETECT=y
143# CONFIG_FEATURE_TAR_FROM is not set
144CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y
145# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set
146CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
147CONFIG_FEATURE_TAR_LONG_OPTIONS=y
148# CONFIG_FEATURE_TAR_UNAME_GNAME is not set
149# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set
150# CONFIG_FEATURE_TAR_SELINUX is not set
151CONFIG_UNCOMPRESS=y
152CONFIG_UNLZMA=y
153CONFIG_FEATURE_LZMA_FAST=y
154CONFIG_UNZIP=y
155
156#
157# Coreutils
158#
159CONFIG_BASENAME=y
160CONFIG_CAL=y
161CONFIG_CAT=y
162CONFIG_CATV=y
163# CONFIG_CHGRP is not set
164# CONFIG_CHMOD is not set
165# CONFIG_CHOWN is not set
166# CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set
167# CONFIG_CHROOT is not set
168CONFIG_CKSUM=y
169CONFIG_COMM=y
170CONFIG_CP=y
171CONFIG_FEATURE_CP_LONG_OPTIONS=y
172CONFIG_CUT=y
173# CONFIG_DATE is not set
174# CONFIG_FEATURE_DATE_ISOFMT is not set
175# CONFIG_FEATURE_DATE_COMPAT is not set
176CONFIG_DD=y
177# CONFIG_FEATURE_DD_SIGNAL_HANDLING is not set
178# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set
179CONFIG_FEATURE_DD_IBS_OBS=y
180# CONFIG_DF is not set
181# CONFIG_FEATURE_DF_FANCY is not set
182CONFIG_DIRNAME=y
183CONFIG_DOS2UNIX=y
184CONFIG_UNIX2DOS=y
185# CONFIG_DU is not set
186# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set
187CONFIG_ECHO=y
188# CONFIG_FEATURE_FANCY_ECHO is not set
189CONFIG_ENV=y
190CONFIG_FEATURE_ENV_LONG_OPTIONS=y
191CONFIG_EXPAND=y
192CONFIG_FEATURE_EXPAND_LONG_OPTIONS=y
193CONFIG_EXPR=y
194CONFIG_EXPR_MATH_SUPPORT_64=y
195CONFIG_FALSE=y
196CONFIG_FOLD=y
197# CONFIG_FSYNC is not set
198CONFIG_HEAD=y
199CONFIG_FEATURE_FANCY_HEAD=y
200# CONFIG_HOSTID is not set
201# CONFIG_ID is not set
202# CONFIG_INSTALL is not set
203# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set
204CONFIG_LENGTH=y
205# CONFIG_LN is not set
206# CONFIG_LOGNAME is not set
207CONFIG_LS=y
208CONFIG_FEATURE_LS_FILETYPES=y
209CONFIG_FEATURE_LS_FOLLOWLINKS=y
210CONFIG_FEATURE_LS_RECURSIVE=y
211CONFIG_FEATURE_LS_SORTFILES=y
212CONFIG_FEATURE_LS_TIMESTAMPS=y
213CONFIG_FEATURE_LS_USERNAME=y
214CONFIG_FEATURE_LS_COLOR=y
215CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
216CONFIG_MD5SUM=y
217CONFIG_MKDIR=y
218CONFIG_FEATURE_MKDIR_LONG_OPTIONS=y
219# CONFIG_MKFIFO is not set
220# CONFIG_MKNOD is not set
221CONFIG_MV=y
222CONFIG_FEATURE_MV_LONG_OPTIONS=y
223# CONFIG_NICE is not set
224# CONFIG_NOHUP is not set
225CONFIG_OD=y
226CONFIG_PRINTENV=y
227CONFIG_PRINTF=y
228CONFIG_PWD=y
229# CONFIG_READLINK is not set
230# CONFIG_FEATURE_READLINK_FOLLOW is not set
231# CONFIG_REALPATH is not set
232CONFIG_RM=y
233CONFIG_RMDIR=y
234CONFIG_FEATURE_RMDIR_LONG_OPTIONS=y
235CONFIG_SEQ=y
236# CONFIG_SHA1SUM is not set
237# CONFIG_SHA256SUM is not set
238# CONFIG_SHA512SUM is not set
239CONFIG_SLEEP=y
240CONFIG_FEATURE_FANCY_SLEEP=y
241# CONFIG_FEATURE_FLOAT_SLEEP is not set
242CONFIG_SORT=y
243CONFIG_FEATURE_SORT_BIG=y
244CONFIG_SPLIT=y
245CONFIG_FEATURE_SPLIT_FANCY=y
246# CONFIG_STAT is not set
247# CONFIG_FEATURE_STAT_FORMAT is not set
248# CONFIG_STTY is not set
249CONFIG_SUM=y
250# CONFIG_SYNC is not set
251CONFIG_TAC=y
252CONFIG_TAIL=y
253CONFIG_FEATURE_FANCY_TAIL=y
254CONFIG_TEE=y
255CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
256CONFIG_TEST=y
257CONFIG_FEATURE_TEST_64=y
258CONFIG_TOUCH=y
259CONFIG_TR=y
260CONFIG_FEATURE_TR_CLASSES=y
261CONFIG_FEATURE_TR_EQUIV=y
262CONFIG_TRUE=y
263# CONFIG_TTY is not set
264# CONFIG_UNAME is not set
265CONFIG_UNEXPAND=y
266CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS=y
267CONFIG_UNIQ=y
268# CONFIG_USLEEP is not set
269CONFIG_UUDECODE=y
270CONFIG_UUENCODE=y
271CONFIG_WC=y
272CONFIG_FEATURE_WC_LARGE=y
273# CONFIG_WHO is not set
274# CONFIG_WHOAMI is not set
275CONFIG_YES=y
276
277#
278# Common options for cp and mv
279#
280# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set
281
282#
283# Common options for ls, more and telnet
284#
285CONFIG_FEATURE_AUTOWIDTH=y
286
287#
288# Common options for df, du, ls
289#
290CONFIG_FEATURE_HUMAN_READABLE=y
291
292#
293# Common options for md5sum, sha1sum, sha256sum, sha512sum
294#
295CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
296# CONFIG_CHVT is not set
297# CONFIG_CLEAR is not set
298# CONFIG_DEALLOCVT is not set
299# CONFIG_DUMPKMAP is not set
300# CONFIG_KBD_MODE is not set
301# CONFIG_LOADFONT is not set
302# CONFIG_LOADKMAP is not set
303# CONFIG_OPENVT is not set
304# CONFIG_RESET is not set
305# CONFIG_RESIZE is not set
306# CONFIG_FEATURE_RESIZE_PRINT is not set
307# CONFIG_SETCONSOLE is not set
308# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
309# CONFIG_SETFONT is not set
310# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set
311CONFIG_DEFAULT_SETFONT_DIR=""
312# CONFIG_SETKEYCODES is not set
313# CONFIG_SETLOGCONS is not set
314# CONFIG_SHOWKEY is not set
315# CONFIG_FEATURE_LOADFONT_PSF2 is not set
316# CONFIG_FEATURE_LOADFONT_RAW is not set
317# CONFIG_MKTEMP is not set
318# CONFIG_PIPE_PROGRESS is not set
319# CONFIG_RUN_PARTS is not set
320# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
321# CONFIG_FEATURE_RUN_PARTS_FANCY is not set
322# CONFIG_START_STOP_DAEMON is not set
323# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
324# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
325# CONFIG_WHICH is not set
326
327#
328# Editors
329#
330CONFIG_AWK=y
331# CONFIG_FEATURE_AWK_LIBM is not set
332CONFIG_CMP=y
333CONFIG_DIFF=y
334CONFIG_FEATURE_DIFF_LONG_OPTIONS=y
335CONFIG_FEATURE_DIFF_DIR=y
336CONFIG_ED=y
337# CONFIG_PATCH is not set
338CONFIG_SED=y
339# CONFIG_VI is not set
340CONFIG_FEATURE_VI_MAX_LEN=0
341# CONFIG_FEATURE_VI_8BIT is not set
342# CONFIG_FEATURE_VI_COLON is not set
343# CONFIG_FEATURE_VI_YANKMARK is not set
344# CONFIG_FEATURE_VI_SEARCH is not set
345# CONFIG_FEATURE_VI_USE_SIGNALS is not set
346# CONFIG_FEATURE_VI_DOT_CMD is not set
347# CONFIG_FEATURE_VI_READONLY is not set
348# CONFIG_FEATURE_VI_SETOPTS is not set
349# CONFIG_FEATURE_VI_SET is not set
350# CONFIG_FEATURE_VI_WIN_RESIZE is not set
351# CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set
352# CONFIG_FEATURE_ALLOW_EXEC is not set
353
354#
355# Finding Utilities
356#
357CONFIG_FIND=y
358CONFIG_FEATURE_FIND_PRINT0=y
359CONFIG_FEATURE_FIND_MTIME=y
360CONFIG_FEATURE_FIND_MMIN=y
361# CONFIG_FEATURE_FIND_PERM is not set
362CONFIG_FEATURE_FIND_TYPE=y
363# CONFIG_FEATURE_FIND_XDEV is not set
364CONFIG_FEATURE_FIND_MAXDEPTH=y
365CONFIG_FEATURE_FIND_NEWER=y
366# CONFIG_FEATURE_FIND_INUM is not set
367# CONFIG_FEATURE_FIND_EXEC is not set
368# CONFIG_FEATURE_FIND_USER is not set
369# CONFIG_FEATURE_FIND_GROUP is not set
370CONFIG_FEATURE_FIND_NOT=y
371CONFIG_FEATURE_FIND_DEPTH=y
372CONFIG_FEATURE_FIND_PAREN=y
373CONFIG_FEATURE_FIND_SIZE=y
374CONFIG_FEATURE_FIND_PRUNE=y
375CONFIG_FEATURE_FIND_DELETE=y
376CONFIG_FEATURE_FIND_PATH=y
377CONFIG_FEATURE_FIND_REGEX=y
378# CONFIG_FEATURE_FIND_CONTEXT is not set
379# CONFIG_FEATURE_FIND_LINKS is not set
380CONFIG_GREP=y
381CONFIG_FEATURE_GREP_EGREP_ALIAS=y
382CONFIG_FEATURE_GREP_FGREP_ALIAS=y
383CONFIG_FEATURE_GREP_CONTEXT=y
384CONFIG_XARGS=y
385CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
386CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
387CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
388CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
389
390#
391# Init Utilities
392#
393# CONFIG_INIT is not set
394# CONFIG_FEATURE_USE_INITTAB is not set
395# CONFIG_FEATURE_KILL_REMOVED is not set
396CONFIG_FEATURE_KILL_DELAY=0
397# CONFIG_FEATURE_INIT_SCTTY is not set
398# CONFIG_FEATURE_INIT_SYSLOG is not set
399# CONFIG_FEATURE_EXTRA_QUIET is not set
400# CONFIG_FEATURE_INIT_COREDUMPS is not set
401# CONFIG_FEATURE_INITRD is not set
402# CONFIG_HALT is not set
403# CONFIG_FEATURE_CALL_TELINIT is not set
404CONFIG_TELINIT_PATH=""
405# CONFIG_MESG is not set
406
407#
408# Login/Password Management Utilities
409#
410# CONFIG_FEATURE_SHADOWPASSWDS is not set
411# CONFIG_USE_BB_PWD_GRP is not set
412# CONFIG_USE_BB_SHADOW is not set
413# CONFIG_USE_BB_CRYPT is not set
414# CONFIG_USE_BB_CRYPT_SHA is not set
415# CONFIG_ADDGROUP is not set
416# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set
417# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set
418# CONFIG_DELGROUP is not set
419# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set
420# CONFIG_FEATURE_CHECK_NAMES is not set
421# CONFIG_ADDUSER is not set
422# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
423CONFIG_FIRST_SYSTEM_ID=0
424CONFIG_LAST_SYSTEM_ID=0
425# CONFIG_DELUSER is not set
426# CONFIG_GETTY is not set
427# CONFIG_LOGIN is not set
428# CONFIG_PAM is not set
429# CONFIG_LOGIN_SCRIPTS is not set
430# CONFIG_FEATURE_NOLOGIN is not set
431# CONFIG_FEATURE_SECURETTY is not set
432# CONFIG_PASSWD is not set
433# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set
434# CONFIG_CRYPTPW is not set
435# CONFIG_CHPASSWD is not set
436# CONFIG_SU is not set
437# CONFIG_FEATURE_SU_SYSLOG is not set
438# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set
439# CONFIG_SULOGIN is not set
440# CONFIG_VLOCK is not set
441
442#
443# Linux Ext2 FS Progs
444#
445# CONFIG_CHATTR is not set
446# CONFIG_FSCK is not set
447# CONFIG_LSATTR is not set
448
449#
450# Linux Module Utilities
451#
452# CONFIG_MODPROBE_SMALL is not set
453# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set
454# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set
455# CONFIG_INSMOD is not set
456# CONFIG_RMMOD is not set
457# CONFIG_LSMOD is not set
458# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
459# CONFIG_MODPROBE is not set
460# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
461# CONFIG_DEPMOD is not set
462
463#
464# Options common to multiple modutils
465#
466# CONFIG_FEATURE_2_4_MODULES is not set
467# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
468# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
469# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
470# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
471# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
472# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
473# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
474# CONFIG_FEATURE_MODUTILS_ALIAS is not set
475# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
476CONFIG_DEFAULT_MODULES_DIR=""
477CONFIG_DEFAULT_DEPMOD_FILE=""
478
479#
480# Linux System Utilities
481#
482# CONFIG_ACPID is not set
483# CONFIG_FEATURE_ACPID_COMPAT is not set
484# CONFIG_BLKID is not set
485# CONFIG_DMESG is not set
486# CONFIG_FEATURE_DMESG_PRETTY is not set
487# CONFIG_FBSET is not set
488# CONFIG_FEATURE_FBSET_FANCY is not set
489# CONFIG_FEATURE_FBSET_READMODE is not set
490# CONFIG_FDFLUSH is not set
491# CONFIG_FDFORMAT is not set
492# CONFIG_FDISK is not set
493# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set
494# CONFIG_FEATURE_FDISK_WRITABLE is not set
495# CONFIG_FEATURE_AIX_LABEL is not set
496# CONFIG_FEATURE_SGI_LABEL is not set
497# CONFIG_FEATURE_SUN_LABEL is not set
498# CONFIG_FEATURE_OSF_LABEL is not set
499# CONFIG_FEATURE_FDISK_ADVANCED is not set
500# CONFIG_FINDFS is not set
501# CONFIG_FLOCK is not set
502# CONFIG_FREERAMDISK is not set
503# CONFIG_FSCK_MINIX is not set
504# CONFIG_MKFS_EXT2 is not set
505# CONFIG_MKFS_MINIX is not set
506# CONFIG_FEATURE_MINIX2 is not set
507# CONFIG_MKFS_REISER is not set
508# CONFIG_MKFS_VFAT is not set
509# CONFIG_GETOPT is not set
510# CONFIG_FEATURE_GETOPT_LONG is not set
511# CONFIG_HEXDUMP is not set
512# CONFIG_FEATURE_HEXDUMP_REVERSE is not set
513# CONFIG_HD is not set
514# CONFIG_HWCLOCK is not set
515# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set
516# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
517# CONFIG_IPCRM is not set
518# CONFIG_IPCS is not set
519# CONFIG_LOSETUP is not set
520# CONFIG_LSPCI is not set
521# CONFIG_LSUSB is not set
522# CONFIG_MDEV is not set
523# CONFIG_FEATURE_MDEV_CONF is not set
524# CONFIG_FEATURE_MDEV_RENAME is not set
525# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set
526# CONFIG_FEATURE_MDEV_EXEC is not set
527# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set
528# CONFIG_MKSWAP is not set
529# CONFIG_FEATURE_MKSWAP_UUID is not set
530# CONFIG_MORE is not set
531# CONFIG_FEATURE_USE_TERMIOS is not set
532# CONFIG_VOLUMEID is not set
533# CONFIG_FEATURE_VOLUMEID_EXT is not set
534# CONFIG_FEATURE_VOLUMEID_BTRFS is not set
535# CONFIG_FEATURE_VOLUMEID_REISERFS is not set
536# CONFIG_FEATURE_VOLUMEID_FAT is not set
537# CONFIG_FEATURE_VOLUMEID_HFS is not set
538# CONFIG_FEATURE_VOLUMEID_JFS is not set
539# CONFIG_FEATURE_VOLUMEID_XFS is not set
540# CONFIG_FEATURE_VOLUMEID_NTFS is not set
541# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set
542# CONFIG_FEATURE_VOLUMEID_UDF is not set
543# CONFIG_FEATURE_VOLUMEID_LUKS is not set
544# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set
545# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set
546# CONFIG_FEATURE_VOLUMEID_ROMFS is not set
547# CONFIG_FEATURE_VOLUMEID_SYSV is not set
548# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set
549# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set
550# CONFIG_MOUNT is not set
551# CONFIG_FEATURE_MOUNT_FAKE is not set
552# CONFIG_FEATURE_MOUNT_VERBOSE is not set
553# CONFIG_FEATURE_MOUNT_HELPERS is not set
554# CONFIG_FEATURE_MOUNT_LABEL is not set
555# CONFIG_FEATURE_MOUNT_NFS is not set
556# CONFIG_FEATURE_MOUNT_CIFS is not set
557# CONFIG_FEATURE_MOUNT_FLAGS is not set
558# CONFIG_FEATURE_MOUNT_FSTAB is not set
559# CONFIG_PIVOT_ROOT is not set
560# CONFIG_RDATE is not set
561# CONFIG_RDEV is not set
562# CONFIG_READPROFILE is not set
563# CONFIG_RTCWAKE is not set
564# CONFIG_SCRIPT is not set
565# CONFIG_SCRIPTREPLAY is not set
566# CONFIG_SETARCH is not set
567# CONFIG_SWAPONOFF is not set
568# CONFIG_FEATURE_SWAPON_PRI is not set
569# CONFIG_SWITCH_ROOT is not set
570# CONFIG_UMOUNT is not set
571# CONFIG_FEATURE_UMOUNT_ALL is not set
572# CONFIG_FEATURE_MOUNT_LOOP is not set
573# CONFIG_FEATURE_MOUNT_LOOP_CREATE is not set
574# CONFIG_FEATURE_MTAB_SUPPORT is not set
575
576#
577# Miscellaneous Utilities
578#
579# CONFIG_ADJTIMEX is not set
580# CONFIG_BBCONFIG is not set
581# CONFIG_BEEP is not set
582CONFIG_FEATURE_BEEP_FREQ=0
583CONFIG_FEATURE_BEEP_LENGTH_MS=0
584# CONFIG_CHAT is not set
585# CONFIG_FEATURE_CHAT_NOFAIL is not set
586# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
587# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set
588# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set
589# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set
590# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set
591# CONFIG_FEATURE_CHAT_CLR_ABORT is not set
592# CONFIG_CHRT is not set
593# CONFIG_CROND is not set
594# CONFIG_FEATURE_CROND_D is not set
595# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
596CONFIG_FEATURE_CROND_DIR=""
597# CONFIG_CRONTAB is not set
598CONFIG_DC=y
599# CONFIG_FEATURE_DC_LIBM is not set
600# CONFIG_DEVFSD is not set
601# CONFIG_DEVFSD_MODLOAD is not set
602# CONFIG_DEVFSD_FG_NP is not set
603# CONFIG_DEVFSD_VERBOSE is not set
604# CONFIG_FEATURE_DEVFS is not set
605# CONFIG_DEVMEM is not set
606# CONFIG_EJECT is not set
607# CONFIG_FEATURE_EJECT_SCSI is not set
608# CONFIG_FBSPLASH is not set
609# CONFIG_FLASHCP is not set
610# CONFIG_FLASH_LOCK is not set
611# CONFIG_FLASH_UNLOCK is not set
612# CONFIG_FLASH_ERASEALL is not set
613# CONFIG_IONICE is not set
614# CONFIG_INOTIFYD is not set
615# CONFIG_LAST is not set
616# CONFIG_FEATURE_LAST_SMALL is not set
617# CONFIG_FEATURE_LAST_FANCY is not set
618# CONFIG_LESS is not set
619CONFIG_FEATURE_LESS_MAXLINES=0
620# CONFIG_FEATURE_LESS_BRACKETS is not set
621# CONFIG_FEATURE_LESS_FLAGS is not set
622# CONFIG_FEATURE_LESS_MARKS is not set
623# CONFIG_FEATURE_LESS_REGEXP is not set
624# CONFIG_FEATURE_LESS_WINCH is not set
625# CONFIG_FEATURE_LESS_DASHCMD is not set
626# CONFIG_FEATURE_LESS_LINENUMS is not set
627# CONFIG_HDPARM is not set
628# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
629# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
630# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
631# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
632# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
633# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
634# CONFIG_MAKEDEVS is not set
635# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
636# CONFIG_FEATURE_MAKEDEVS_TABLE is not set
637# CONFIG_MAN is not set
638# CONFIG_MICROCOM is not set
639# CONFIG_MOUNTPOINT is not set
640# CONFIG_MT is not set
641# CONFIG_RAIDAUTORUN is not set
642# CONFIG_READAHEAD is not set
643# CONFIG_RUNLEVEL is not set
644# CONFIG_RX is not set
645# CONFIG_SETSID is not set
646# CONFIG_STRINGS is not set
647# CONFIG_TASKSET is not set
648# CONFIG_FEATURE_TASKSET_FANCY is not set
649# CONFIG_TIME is not set
650# CONFIG_TIMEOUT is not set
651# CONFIG_TTYSIZE is not set
652# CONFIG_VOLNAME is not set
653# CONFIG_WALL is not set
654# CONFIG_WATCHDOG is not set
655
656#
657# Networking Utilities
658#
659# CONFIG_FEATURE_IPV6 is not set
660# CONFIG_FEATURE_UNIX_LOCAL is not set
661# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set
662# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set
663# CONFIG_ARP is not set
664# CONFIG_ARPING is not set
665# CONFIG_BRCTL is not set
666# CONFIG_FEATURE_BRCTL_FANCY is not set
667# CONFIG_FEATURE_BRCTL_SHOW is not set
668# CONFIG_DNSD is not set
669# CONFIG_ETHER_WAKE is not set
670# CONFIG_FAKEIDENTD is not set
671# CONFIG_FTPD is not set
672# CONFIG_FEATURE_FTP_WRITE is not set
673# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set
674# CONFIG_FTPGET is not set
675# CONFIG_FTPPUT is not set
676# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
677# CONFIG_HOSTNAME is not set
678# CONFIG_HTTPD is not set
679# CONFIG_FEATURE_HTTPD_RANGES is not set
680# CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set
681# CONFIG_FEATURE_HTTPD_SETUID is not set
682# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set
683# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
684# CONFIG_FEATURE_HTTPD_CGI is not set
685# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set
686# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set
687# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set
688# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set
689# CONFIG_FEATURE_HTTPD_PROXY is not set
690# CONFIG_IFCONFIG is not set
691# CONFIG_FEATURE_IFCONFIG_STATUS is not set
692# CONFIG_FEATURE_IFCONFIG_SLIP is not set
693# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
694# CONFIG_FEATURE_IFCONFIG_HW is not set
695# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set
696# CONFIG_IFENSLAVE is not set
697# CONFIG_IFPLUGD is not set
698# CONFIG_IFUPDOWN is not set
699CONFIG_IFUPDOWN_IFSTATE_PATH=""
700# CONFIG_FEATURE_IFUPDOWN_IP is not set
701# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set
702# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
703# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
704# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
705# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
706# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
707# CONFIG_INETD is not set
708# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
709# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
710# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
711# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
712# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
713# CONFIG_FEATURE_INETD_RPC is not set
714# CONFIG_IP is not set
715# CONFIG_FEATURE_IP_ADDRESS is not set
716# CONFIG_FEATURE_IP_LINK is not set
717# CONFIG_FEATURE_IP_ROUTE is not set
718# CONFIG_FEATURE_IP_TUNNEL is not set
719# CONFIG_FEATURE_IP_RULE is not set
720# CONFIG_FEATURE_IP_SHORT_FORMS is not set
721# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
722# CONFIG_IPADDR is not set
723# CONFIG_IPLINK is not set
724# CONFIG_IPROUTE is not set
725# CONFIG_IPTUNNEL is not set
726# CONFIG_IPRULE is not set
727# CONFIG_IPCALC is not set
728# CONFIG_FEATURE_IPCALC_FANCY is not set
729# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
730# CONFIG_NAMEIF is not set
731# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
732# CONFIG_NC is not set
733# CONFIG_NC_SERVER is not set
734# CONFIG_NC_EXTRA is not set
735# CONFIG_NETSTAT is not set
736# CONFIG_FEATURE_NETSTAT_WIDE is not set
737# CONFIG_FEATURE_NETSTAT_PRG is not set
738# CONFIG_NSLOOKUP is not set
739# CONFIG_NTPD is not set
740# CONFIG_FEATURE_NTPD_SERVER is not set
741# CONFIG_PING is not set
742# CONFIG_PING6 is not set
743# CONFIG_FEATURE_FANCY_PING is not set
744# CONFIG_PSCAN is not set
745# CONFIG_ROUTE is not set
746# CONFIG_SLATTACH is not set
747# CONFIG_TCPSVD is not set
748# CONFIG_TELNET is not set
749# CONFIG_FEATURE_TELNET_TTYPE is not set
750# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
751# CONFIG_TELNETD is not set
752# CONFIG_FEATURE_TELNETD_STANDALONE is not set
753# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set
754# CONFIG_TFTP is not set
755# CONFIG_TFTPD is not set
756# CONFIG_FEATURE_TFTP_GET is not set
757# CONFIG_FEATURE_TFTP_PUT is not set
758# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set
759# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set
760# CONFIG_TFTP_DEBUG is not set
761# CONFIG_TRACEROUTE is not set
762# CONFIG_TRACEROUTE6 is not set
763# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set
764# CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set
765# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
766# CONFIG_TUNCTL is not set
767# CONFIG_FEATURE_TUNCTL_UG is not set
768# CONFIG_UDHCPD is not set
769# CONFIG_DHCPRELAY is not set
770# CONFIG_DUMPLEASES is not set
771# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set
772CONFIG_DHCPD_LEASES_FILE=""
773# CONFIG_UDHCPC is not set
774# CONFIG_FEATURE_UDHCPC_ARPING is not set
775# CONFIG_FEATURE_UDHCP_PORT is not set
776CONFIG_UDHCP_DEBUG=0
777# CONFIG_FEATURE_UDHCP_RFC3397 is not set
778CONFIG_UDHCPC_DEFAULT_SCRIPT=""
779CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0
780CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS=""
781# CONFIG_UDPSVD is not set
782# CONFIG_VCONFIG is not set
783# CONFIG_WGET is not set
784# CONFIG_FEATURE_WGET_STATUSBAR is not set
785# CONFIG_FEATURE_WGET_AUTHENTICATION is not set
786# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set
787# CONFIG_ZCIP is not set
788
789#
790# Print Utilities
791#
792# CONFIG_LPD is not set
793# CONFIG_LPR is not set
794# CONFIG_LPQ is not set
795
796#
797# Mail Utilities
798#
799# CONFIG_MAKEMIME is not set
800CONFIG_FEATURE_MIME_CHARSET=""
801# CONFIG_POPMAILDIR is not set
802# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set
803# CONFIG_REFORMIME is not set
804# CONFIG_FEATURE_REFORMIME_COMPAT is not set
805# CONFIG_SENDMAIL is not set
806
807#
808# Process Utilities
809#
810# CONFIG_FREE is not set
811# CONFIG_FUSER is not set
812# CONFIG_KILL is not set
813# CONFIG_KILLALL is not set
814# CONFIG_KILLALL5 is not set
815# CONFIG_NMETER is not set
816# CONFIG_PGREP is not set
817# CONFIG_PIDOF is not set
818# CONFIG_FEATURE_PIDOF_SINGLE is not set
819# CONFIG_FEATURE_PIDOF_OMIT is not set
820# CONFIG_PKILL is not set
821# CONFIG_PS is not set
822# CONFIG_FEATURE_PS_WIDE is not set
823# CONFIG_FEATURE_PS_TIME is not set
824# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set
825# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
826# CONFIG_RENICE is not set
827# CONFIG_BB_SYSCTL is not set
828# CONFIG_TOP is not set
829# CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set
830# CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set
831# CONFIG_FEATURE_TOP_SMP_CPU is not set
832# CONFIG_FEATURE_TOP_DECIMALS is not set
833# CONFIG_FEATURE_TOP_SMP_PROCESS is not set
834# CONFIG_FEATURE_TOPMEM is not set
835# CONFIG_FEATURE_SHOW_THREADS is not set
836# CONFIG_UPTIME is not set
837# CONFIG_WATCH is not set
838
839#
840# Runit Utilities
841#
842# CONFIG_RUNSV is not set
843# CONFIG_RUNSVDIR is not set
844# CONFIG_FEATURE_RUNSVDIR_LOG is not set
845# CONFIG_SV is not set
846CONFIG_SV_DEFAULT_SERVICE_DIR=""
847# CONFIG_SVLOGD is not set
848# CONFIG_CHPST is not set
849# CONFIG_SETUIDGID is not set
850# CONFIG_ENVUIDGID is not set
851# CONFIG_ENVDIR is not set
852# CONFIG_SOFTLIMIT is not set
853# CONFIG_CHCON is not set
854# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
855# CONFIG_GETENFORCE is not set
856# CONFIG_GETSEBOOL is not set
857# CONFIG_LOAD_POLICY is not set
858# CONFIG_MATCHPATHCON is not set
859# CONFIG_RESTORECON is not set
860# CONFIG_RUNCON is not set
861# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set
862# CONFIG_SELINUXENABLED is not set
863# CONFIG_SETENFORCE is not set
864# CONFIG_SETFILES is not set
865# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
866# CONFIG_SETSEBOOL is not set
867# CONFIG_SESTATUS is not set
868
869#
870# Shells
871#
872CONFIG_FEATURE_SH_IS_ASH=y
873# CONFIG_FEATURE_SH_IS_HUSH is not set
874# CONFIG_FEATURE_SH_IS_NONE is not set
875CONFIG_ASH=y
876CONFIG_ASH_BASH_COMPAT=y
877# CONFIG_ASH_JOB_CONTROL is not set
878CONFIG_ASH_ALIAS=y
879CONFIG_ASH_GETOPTS=y
880CONFIG_ASH_BUILTIN_ECHO=y
881CONFIG_ASH_BUILTIN_PRINTF=y
882CONFIG_ASH_BUILTIN_TEST=y
883CONFIG_ASH_CMDCMD=y
884# CONFIG_ASH_MAIL is not set
885CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
886CONFIG_ASH_RANDOM_SUPPORT=y
887CONFIG_ASH_EXPAND_PRMT=y
888# CONFIG_HUSH is not set
889# CONFIG_HUSH_BASH_COMPAT is not set
890# CONFIG_HUSH_HELP is not set
891# CONFIG_HUSH_INTERACTIVE is not set
892# CONFIG_HUSH_JOB is not set
893# CONFIG_HUSH_TICK is not set
894# CONFIG_HUSH_IF is not set
895# CONFIG_HUSH_LOOPS is not set
896# CONFIG_HUSH_CASE is not set
897# CONFIG_HUSH_FUNCTIONS is not set
898# CONFIG_HUSH_LOCAL is not set
899# CONFIG_HUSH_EXPORT_N is not set
900# CONFIG_HUSH_RANDOM_SUPPORT is not set
901# CONFIG_LASH is not set
902# CONFIG_MSH is not set
903CONFIG_SH_MATH_SUPPORT=y
904CONFIG_SH_MATH_SUPPORT_64=y
905CONFIG_FEATURE_SH_EXTRA_QUIET=y
906CONFIG_FEATURE_SH_STANDALONE=y
907CONFIG_FEATURE_SH_NOFORK=y
908# CONFIG_CTTYHACK is not set
909
910#
911# System Logging Utilities
912#
913# CONFIG_SYSLOGD is not set
914# CONFIG_FEATURE_ROTATE_LOGFILE is not set
915# CONFIG_FEATURE_REMOTE_LOG is not set
916# CONFIG_FEATURE_SYSLOGD_DUP is not set
917CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0
918# CONFIG_FEATURE_IPC_SYSLOG is not set
919CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0
920# CONFIG_LOGREAD is not set
921# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
922# CONFIG_KLOGD is not set
923# CONFIG_LOGGER is not set
diff --git a/shell/ash.c b/shell/ash.c
index d082333ba..16a331bb0 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -17,6 +17,18 @@
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" is still understood as executable (option to turn off?)
25 * - both / and \ are supported in PATH. Usually you must use /
26 * - trap/job does not work
27 * - /dev/null is supported for redirection
28 * - no $PPID
29 */
30
31/*
20 * The following should be set to reflect the type of system you have: 32 * The following should be set to reflect the type of system you have:
21 * JOBS -> 1 if you have Berkeley job control, 0 otherwise. 33 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
22 * define SYSV if you are running under System V. 34 * define SYSV if you are running under System V.
@@ -43,7 +55,9 @@
43#endif 55#endif
44 56
45#include "busybox.h" /* for applet_names */ 57#include "busybox.h" /* for applet_names */
58#ifndef __MINGW32__
46#include <paths.h> 59#include <paths.h>
60#endif
47#include <setjmp.h> 61#include <setjmp.h>
48#include <fnmatch.h> 62#include <fnmatch.h>
49 63
@@ -79,6 +93,41 @@
79# error "Do not even bother, ash will not run on NOMMU machine" 93# error "Do not even bother, ash will not run on NOMMU machine"
80#endif 94#endif
81 95
96#if ENABLE_PLATFORM_MINGW32
97struct forkshell;
98union node;
99struct strlist;
100struct job;
101
102typedef void (*forkpoint_fn)(struct forkshell *fs);
103struct forkshell {
104 /* filled by forkshell_copy() */
105 struct globals_var *gvp;
106 struct globals_misc *gmp;
107 struct tblentry **cmdtable;
108 struct localvar *localvars;
109 /* struct alias **atab; */
110 /* struct parsefile *g_parsefile; */
111 int fpid;
112 HANDLE hMapFile;
113 void *old_base;
114 int nodeptr_offset;
115 int size;
116
117 forkpoint_fn fp;
118 /* optional data, used by forkpoint_fn */
119 int flags;
120 int fd[10];
121 union node *n;
122 char **argv;
123 char *string;
124 struct strlist *strlist;
125 pid_t pid;
126};
127static void sticky_free(void *p);
128#define free(p) sticky_free(p)
129static int spawn_forkshell(struct job *jp, struct forkshell *fs, int mode);
130#endif
82 131
83/* ============ Hash table sizes. Configurable. */ 132/* ============ Hash table sizes. Configurable. */
84 133
@@ -774,7 +823,7 @@ static void
774opentrace(void) 823opentrace(void)
775{ 824{
776 char s[100]; 825 char s[100];
777#ifdef O_APPEND 826#if defined(O_APPEND) && !ENABLE_PLATFORM_MINGW32
778 int flags; 827 int flags;
779#endif 828#endif
780 829
@@ -799,7 +848,7 @@ opentrace(void)
799 return; 848 return;
800 } 849 }
801 } 850 }
802#ifdef O_APPEND 851#if defined(O_APPEND) && !ENABLE_PLATFORM_MINGW32
803 flags = fcntl(fileno(tracefile), F_GETFL); 852 flags = fcntl(fileno(tracefile), F_GETFL);
804 if (flags >= 0) 853 if (flags >= 0)
805 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); 854 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
@@ -2261,10 +2310,22 @@ path_advance(const char **path, const char *name)
2261 if (*path == NULL) 2310 if (*path == NULL)
2262 return NULL; 2311 return NULL;
2263 start = *path; 2312 start = *path;
2313#if ENABLE_PLATFORM_MINGW32
2314 p = next_path_sep(start);
2315 q = strchr(start, '%');
2316 if ((p && q && q < p) || (!p && q))
2317 p = q;
2318 if (!p)
2319 for (p = start; *p; p++)
2320 continue;
2321#else
2264 for (p = start; *p && *p != ':' && *p != '%'; p++) 2322 for (p = start; *p && *p != ':' && *p != '%'; p++)
2265 continue; 2323 continue;
2324#endif
2266 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ 2325 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2267 while (stackblocksize() < len) 2326
2327 /* preserve space for .exe too */
2328 while (stackblocksize() < (ENABLE_PLATFORM_MINGW32 ? len+4 : len))
2268 growstackblock(); 2329 growstackblock();
2269 q = stackblock(); 2330 q = stackblock();
2270 if (p != start) { 2331 if (p != start) {
@@ -2380,6 +2441,98 @@ cdopt(void)
2380static const char * 2441static const char *
2381updatepwd(const char *dir) 2442updatepwd(const char *dir)
2382{ 2443{
2444#if ENABLE_PLATFORM_MINGW32
2445 /*
2446 * Due to Windows drive notion, getting pwd is a completely
2447 * different thing. Handle it in a separate routine
2448 */
2449
2450 char *new;
2451 char *p;
2452 char *cdcomppath;
2453 const char *lim;
2454 /*
2455 * There are four cases
2456 * absdrive + abspath: c:/path
2457 * absdrive + !abspath: c:path
2458 * !absdrive + abspath: /path
2459 * !absdrive + !abspath: path
2460 *
2461 * Damn DOS!
2462 * c:path behaviour is "undefined"
2463 * To properly handle this case, I have to keep track of cwd
2464 * of every drive, which is too painful to do.
2465 * So when c:path is given, I assume it's c:${curdir}path
2466 * with ${curdir} comes from the current drive
2467 */
2468 int absdrive = *dir && dir[1] == ':';
2469 int abspath = absdrive ? dir[2] == '/' : *dir == '/';
2470 char *drive;
2471
2472 cdcomppath = ststrdup(dir);
2473 STARTSTACKSTR(new);
2474 if (!absdrive && curdir == nullstr)
2475 return 0;
2476 if (!abspath) {
2477 if (curdir == nullstr)
2478 return 0;
2479 new = stack_putstr(curdir, new);
2480 }
2481 new = makestrspace(strlen(dir) + 2, new);
2482
2483 drive = stackblock();
2484 if (absdrive) {
2485 *drive = *dir;
2486 cdcomppath += 2;
2487 dir += 2;
2488 } else {
2489 *drive = *curdir;
2490 }
2491 drive[1] = ':'; /* in case of absolute drive+path */
2492
2493 if (abspath)
2494 new = drive + 2;
2495 lim = drive + 3;
2496 if (!abspath) {
2497 if (new[-1] != '/')
2498 USTPUTC('/', new);
2499 if (new > lim && *lim == '/')
2500 lim++;
2501 } else {
2502 USTPUTC('/', new);
2503 cdcomppath ++;
2504 if (dir[1] == '/' && dir[2] != '/') {
2505 USTPUTC('/', new);
2506 cdcomppath++;
2507 lim++;
2508 }
2509 }
2510 p = strtok(cdcomppath, "/");
2511 while (p) {
2512 switch (*p) {
2513 case '.':
2514 if (p[1] == '.' && p[2] == '\0') {
2515 while (new > lim) {
2516 STUNPUTC(new);
2517 if (new[-1] == '/')
2518 break;
2519 }
2520 break;
2521 }
2522 if (p[1] == '\0')
2523 break;
2524 /* fall through */
2525 default:
2526 new = stack_putstr(p, new);
2527 USTPUTC('/', new);
2528 }
2529 p = strtok(0, "/");
2530 }
2531 if (new > lim)
2532 STUNPUTC(new);
2533 *new = 0;
2534 return stackblock();
2535#else
2383 char *new; 2536 char *new;
2384 char *p; 2537 char *p;
2385 char *cdcomppath; 2538 char *cdcomppath;
@@ -2433,6 +2586,7 @@ updatepwd(const char *dir)
2433 STUNPUTC(new); 2586 STUNPUTC(new);
2434 *new = 0; 2587 *new = 0;
2435 return stackblock(); 2588 return stackblock();
2589#endif
2436} 2590}
2437 2591
2438/* 2592/*
@@ -2527,7 +2681,7 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2527 } 2681 }
2528 if (!dest) 2682 if (!dest)
2529 dest = nullstr; 2683 dest = nullstr;
2530 if (*dest == '/') 2684 if (is_absolute_path(dest))
2531 goto step7; 2685 goto step7;
2532 if (*dest == '.') { 2686 if (*dest == '.') {
2533 c = dest[1]; 2687 c = dest[1];
@@ -3299,6 +3453,8 @@ setsignal(int signo)
3299 char cur_act, new_act; 3453 char cur_act, new_act;
3300 struct sigaction act; 3454 struct sigaction act;
3301 3455
3456 if (ENABLE_PLATFORM_MINGW32)
3457 return;
3302 t = trap[signo]; 3458 t = trap[signo];
3303 new_act = S_DFL; 3459 new_act = S_DFL;
3304 if (t != NULL) { /* trap for this sig is set */ 3460 if (t != NULL) { /* trap for this sig is set */
@@ -3606,7 +3762,7 @@ setjobctl(int on)
3606 if (--fd < 0) 3762 if (--fd < 0)
3607 goto out; 3763 goto out;
3608 } 3764 }
3609 fd = fcntl(fd, F_DUPFD, 10); 3765 fd = copyfd(fd, 10);
3610 if (ofd >= 0) 3766 if (ofd >= 0)
3611 close(ofd); 3767 close(ofd);
3612 if (fd < 0) 3768 if (fd < 0)
@@ -3780,6 +3936,53 @@ sprint_status(char *s, int status, int sigonly)
3780 return col; 3936 return col;
3781} 3937}
3782 3938
3939#if ENABLE_PLATFORM_MINGW32
3940/*
3941 * Windows does not know about parent-child relationship
3942 * They don't support waitpid(-1)
3943 */
3944static pid_t
3945waitpid_child(int *status)
3946{
3947 HANDLE *pidlist, *pidp;
3948 int pid_nr = 0;
3949 pid_t pid;
3950 DWORD win_status, idx;
3951 struct job *jb;
3952
3953 #define LOOP(stmt) \
3954 for (jb = curjob; jb; jb = jb->prev_job) { \
3955 struct procstat *ps, *psend; \
3956 if (jb->state == JOBDONE) \
3957 continue; \
3958 ps = jb->ps; \
3959 psend = ps + jb->nprocs; \
3960 while (ps < psend) { \
3961 if (ps->ps_pid != -1) { \
3962 stmt; \
3963 } \
3964 ps++; \
3965 } \
3966 }
3967
3968 LOOP(pid_nr++);
3969 pidp = pidlist = ckmalloc(sizeof(*pidlist)*pid_nr);
3970 LOOP(*pidp++ = (HANDLE)ps->ps_pid);
3971 #undef LOOP
3972
3973 idx = WaitForMultipleObjects(pid_nr, pidlist, FALSE, INFINITE);
3974 if (idx >= pid_nr) {
3975 free(pidlist);
3976 return -1;
3977 }
3978 GetExitCodeProcess(pidlist[idx], &win_status);
3979 pid = (int)pidlist[idx];
3980 free(pidlist);
3981 *status = (int)win_status;
3982 return pid;
3983}
3984#endif
3985
3783static int 3986static int
3784dowait(int wait_flags, struct job *job) 3987dowait(int wait_flags, struct job *job)
3785{ 3988{
@@ -3796,7 +3999,11 @@ dowait(int wait_flags, struct job *job)
3796 * NB: _not_ safe_waitpid, we need to detect EINTR */ 3999 * NB: _not_ safe_waitpid, we need to detect EINTR */
3797 if (doing_jobctl) 4000 if (doing_jobctl)
3798 wait_flags |= WUNTRACED; 4001 wait_flags |= WUNTRACED;
4002#if ENABLE_PLATFORM_MINGW32
4003 pid = waitpid_child(&status);
4004#else
3799 pid = waitpid(-1, &status, wait_flags); 4005 pid = waitpid(-1, &status, wait_flags);
4006#endif
3800 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", 4007 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
3801 pid, status, errno, strerror(errno))); 4008 pid, status, errno, strerror(errno)));
3802 if (pid <= 0) 4009 if (pid <= 0)
@@ -3819,6 +4026,8 @@ dowait(int wait_flags, struct job *job)
3819 jobno(jp), pid, ps->ps_status, status)); 4026 jobno(jp), pid, ps->ps_status, status));
3820 ps->ps_status = status; 4027 ps->ps_status = status;
3821 thisjob = jp; 4028 thisjob = jp;
4029 if (ENABLE_PLATFORM_MINGW32)
4030 ps->ps_pid = -1;
3822 } 4031 }
3823 if (ps->ps_status == -1) 4032 if (ps->ps_status == -1)
3824 state = JOBRUNNING; 4033 state = JOBRUNNING;
@@ -4050,6 +4259,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
4050 int retval; 4259 int retval;
4051 struct job *jp; 4260 struct job *jp;
4052 4261
4262 if (ENABLE_PLATFORM_MINGW32)
4263 return 0;
4264
4053 if (pending_sig) 4265 if (pending_sig)
4054 raise_exception(EXSIG); 4266 raise_exception(EXSIG);
4055 4267
@@ -4660,7 +4872,7 @@ static void
4660forkparent(struct job *jp, union node *n, int mode, pid_t pid) 4872forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4661{ 4873{
4662 TRACE(("In parent shell: child = %d\n", pid)); 4874 TRACE(("In parent shell: child = %d\n", pid));
4663 if (!jp) { 4875 if (!jp && !ENABLE_PLATFORM_MINGW32) { /* FIXME not quite understand this */
4664 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) 4876 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4665 continue; 4877 continue;
4666 jobless++; 4878 jobless++;
@@ -4700,6 +4912,9 @@ forkshell(struct job *jp, union node *n, int mode)
4700 int pid; 4912 int pid;
4701 4913
4702 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode)); 4914 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4915 if (ENABLE_PLATFORM_MINGW32)
4916 return -1;
4917
4703 pid = fork(); 4918 pid = fork();
4704 if (pid < 0) { 4919 if (pid < 0) {
4705 TRACE(("Fork failed, errno=%d", errno)); 4920 TRACE(("Fork failed, errno=%d", errno));
@@ -4896,11 +5111,39 @@ noclobberopen(const char *fname)
4896 */ 5111 */
4897/* openhere needs this forward reference */ 5112/* openhere needs this forward reference */
4898static void expandhere(union node *arg, int fd); 5113static void expandhere(union node *arg, int fd);
5114#if ENABLE_PLATFORM_MINGW32
5115static void
5116forkshell_openhere(struct forkshell *fs)
5117{
5118 union node *redir = fs->n;
5119 int pip[2];
5120
5121 pip[0] = fs->fd[0];
5122 pip[1] = fs->fd[1];
5123
5124 TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__));
5125
5126 close(pip[0]);
5127 ignoresig(SIGINT); //signal(SIGINT, SIG_IGN);
5128 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5129 ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN);
5130 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5131 signal(SIGPIPE, SIG_DFL);
5132 if (redir->type == NHERE) {
5133 size_t len = strlen(redir->nhere.doc->narg.text);
5134 full_write(pip[1], redir->nhere.doc->narg.text, len);
5135 } else /* NXHERE */
5136 expandhere(redir->nhere.doc, pip[1]);
5137 _exit(EXIT_SUCCESS);
5138}
5139#endif
5140
4899static int 5141static int
4900openhere(union node *redir) 5142openhere(union node *redir)
4901{ 5143{
4902 int pip[2]; 5144 int pip[2];
4903 size_t len = 0; 5145 size_t len = 0;
5146 IF_PLATFORM_MINGW32(struct forkshell fs);
4904 5147
4905 if (pipe(pip) < 0) 5148 if (pipe(pip) < 0)
4906 ash_msg_and_raise_error("pipe call failed"); 5149 ash_msg_and_raise_error("pipe call failed");
@@ -4911,6 +5154,16 @@ openhere(union node *redir)
4911 goto out; 5154 goto out;
4912 } 5155 }
4913 } 5156 }
5157#if ENABLE_PLATFORM_MINGW32
5158 memset(&fs, 0, sizeof(fs));
5159 fs.fp = forkshell_openhere;
5160 fs.flags = 0;
5161 fs.n = redir;
5162 fs.fd[0] = pip[0];
5163 fs.fd[1] = pip[1];
5164 if (spawn_forkshell(NULL, &fs, FORK_NOJOB) < 0)
5165 ash_msg_and_raise_error("unable to spawn shell");
5166#endif
4914 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { 5167 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4915 /* child */ 5168 /* child */
4916 close(pip[0]); 5169 close(pip[0]);
@@ -4936,6 +5189,31 @@ openredirect(union node *redir)
4936 char *fname; 5189 char *fname;
4937 int f; 5190 int f;
4938 5191
5192#if ENABLE_PLATFORM_MINGW32
5193 /* Support for /dev/null */
5194 switch (redir->nfile.type) {
5195 case NFROM:
5196 if (!strcmp(redir->nfile.expfname, "/dev/null"))
5197 return open("nul",O_RDWR);
5198 if (!strncmp(redir->nfile.expfname, "/dev/", 5)) {
5199 ash_msg("Unhandled device %s\n", redir->nfile.expfname);
5200 return -1;
5201 }
5202 break;
5203
5204 case NFROMTO:
5205 case NTO:
5206 case NCLOBBER:
5207 case NAPPEND:
5208 if (!strcmp(redir->nfile.expfname, "/dev/null"))
5209 return open("nul",O_RDWR);
5210 if (!strncmp(redir->nfile.expfname, "/dev/", 5)) {
5211 ash_msg("Unhandled device %s\n", redir->nfile.expfname);
5212 return -1;
5213 }
5214 break;
5215 }
5216#endif
4939 switch (redir->nfile.type) { 5217 switch (redir->nfile.type) {
4940 case NFROM: 5218 case NFROM:
4941 fname = redir->nfile.expfname; 5219 fname = redir->nfile.expfname;
@@ -5018,6 +5296,18 @@ copyfd(int from, int to)
5018 /*if (from != to)*/ 5296 /*if (from != to)*/
5019 newfd = dup2(from, to); 5297 newfd = dup2(from, to);
5020 } else { 5298 } else {
5299 if (ENABLE_PLATFORM_MINGW32) {
5300 char* fds = ckmalloc(to);
5301 int i,fd;
5302 memset(fds,0,to);
5303 while ((fd = dup(from)) < to && fd >= 0)
5304 fds[fd] = 1;
5305 for (i = 0;i < to;i ++)
5306 if (fds[i])
5307 close(i);
5308 free(fds);
5309 return fd;
5310 }
5021 newfd = fcntl(from, F_DUPFD, to); 5311 newfd = fcntl(from, F_DUPFD, to);
5022 } 5312 }
5023 if (newfd < 0) { 5313 if (newfd < 0) {
@@ -5162,7 +5452,7 @@ redirect(union node *redir, int flags)
5162#endif 5452#endif
5163 if (need_to_remember(sv, fd)) { 5453 if (need_to_remember(sv, fd)) {
5164 /* Copy old descriptor */ 5454 /* Copy old descriptor */
5165 i = fcntl(fd, F_DUPFD, 10); 5455 i = copyfd(fd, 10);
5166/* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds 5456/* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5167 * are closed in popredir() in the child, preventing them from leaking 5457 * are closed in popredir() in the child, preventing them from leaking
5168 * into child. (popredir() also cleans up the mess in case of failures) 5458 * into child. (popredir() also cleans up the mess in case of failures)
@@ -5627,6 +5917,8 @@ exptilde(char *startp, char *p, int flags)
5627 if (*name == '\0') { 5917 if (*name == '\0') {
5628 home = lookupvar(homestr); 5918 home = lookupvar(homestr);
5629 } else { 5919 } else {
5920 if (ENABLE_PLATFORM_MINGW32)
5921 goto lose;
5630 pw = getpwnam(name); 5922 pw = getpwnam(name);
5631 if (pw == NULL) 5923 if (pw == NULL)
5632 goto lose; 5924 goto lose;
@@ -5654,6 +5946,7 @@ struct backcmd { /* result of evalbackcmd */
5654 int fd; /* file descriptor to read from */ 5946 int fd; /* file descriptor to read from */
5655 int nleft; /* number of chars in buffer */ 5947 int nleft; /* number of chars in buffer */
5656 char *buf; /* buffer */ 5948 char *buf; /* buffer */
5949 IF_PLATFORM_MINGW32(struct forkshell fs);
5657 struct job *jp; /* job structure for command */ 5950 struct job *jp; /* job structure for command */
5658}; 5951};
5659 5952
@@ -5662,6 +5955,25 @@ static uint8_t back_exitstatus; /* exit status of backquoted command */
5662#define EV_EXIT 01 /* exit after evaluating tree */ 5955#define EV_EXIT 01 /* exit after evaluating tree */
5663static void evaltree(union node *, int); 5956static void evaltree(union node *, int);
5664 5957
5958#if ENABLE_PLATFORM_MINGW32
5959static void
5960forkshell_evalbackcmd(struct forkshell *fs)
5961{
5962 union node *n = fs->n;
5963 int pip[2] = {fs->fd[0], fs->fd[1]};
5964
5965 FORCE_INT_ON;
5966 close(pip[0]);
5967 if (pip[1] != 1) {
5968 /*close(1);*/
5969 copyfd(pip[1], 1 | COPYFD_EXACT);
5970 close(pip[1]);
5971 }
5972 eflag = 0;
5973 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5974 /* NOTREACHED */
5975}
5976#endif
5665static void FAST_FUNC 5977static void FAST_FUNC
5666evalbackcmd(union node *n, struct backcmd *result) 5978evalbackcmd(union node *n, struct backcmd *result)
5667{ 5979{
@@ -5670,6 +5982,7 @@ evalbackcmd(union node *n, struct backcmd *result)
5670 result->fd = -1; 5982 result->fd = -1;
5671 result->buf = NULL; 5983 result->buf = NULL;
5672 result->nleft = 0; 5984 result->nleft = 0;
5985 IF_PLATFORM_MINGW32(memset(&result->fs, 0, sizeof(result->fs)));
5673 result->jp = NULL; 5986 result->jp = NULL;
5674 if (n == NULL) 5987 if (n == NULL)
5675 goto out; 5988 goto out;
@@ -5684,6 +5997,14 @@ evalbackcmd(union node *n, struct backcmd *result)
5684 if (pipe(pip) < 0) 5997 if (pipe(pip) < 0)
5685 ash_msg_and_raise_error("pipe call failed"); 5998 ash_msg_and_raise_error("pipe call failed");
5686 jp = makejob(/*n,*/ 1); 5999 jp = makejob(/*n,*/ 1);
6000#if ENABLE_PLATFORM_MINGW32
6001 result->fs.fp = forkshell_evalbackcmd;
6002 result->fs.n = n;
6003 result->fs.fd[0] = pip[0];
6004 result->fs.fd[1] = pip[1];
6005 if (spawn_forkshell(jp, &result->fs, FORK_NOJOB) < 0)
6006 ash_msg_and_raise_error("unable to spawn shell");
6007#endif
5687 if (forkshell(jp, n, FORK_NOJOB) == 0) { 6008 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5688 FORCE_INT_ON; 6009 FORCE_INT_ON;
5689 close(pip[0]); 6010 close(pip[0]);
@@ -7299,7 +7620,7 @@ shellexec(char **argv, const char *path, int idx)
7299 7620
7300 clearredir(/*drop:*/ 1); 7621 clearredir(/*drop:*/ 1);
7301 envp = listvars(VEXPORT, VUNSET, 0); 7622 envp = listvars(VEXPORT, VUNSET, 0);
7302 if (strchr(argv[0], '/') != NULL 7623 if ((strchr(argv[0], '/') || (ENABLE_PLATFORM_MINGW32 && strchr(argv[0], '\\')))
7303#if ENABLE_FEATURE_SH_STANDALONE 7624#if ENABLE_FEATURE_SH_STANDALONE
7304 || (applet_no = find_applet_by_name(argv[0])) >= 0 7625 || (applet_no = find_applet_by_name(argv[0])) >= 0
7305#endif 7626#endif
@@ -7816,6 +8137,10 @@ static int funcblocksize; /* size of structures in function */
7816static int funcstringsize; /* size of strings in node */ 8137static int funcstringsize; /* size of strings in node */
7817static void *funcblock; /* block to allocate function from */ 8138static void *funcblock; /* block to allocate function from */
7818static char *funcstring; /* block to allocate strings from */ 8139static char *funcstring; /* block to allocate strings from */
8140#if ENABLE_PLATFORM_MINGW32
8141static int nodeptrsize;
8142static int *nodeptr;
8143#endif
7819 8144
7820/* flags in argument to evaltree */ 8145/* flags in argument to evaltree */
7821#define EV_EXIT 01 /* exit after evaluating tree */ 8146#define EV_EXIT 01 /* exit after evaluating tree */
@@ -7861,6 +8186,7 @@ sizenodelist(struct nodelist *lp)
7861{ 8186{
7862 while (lp) { 8187 while (lp) {
7863 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); 8188 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8189 IF_PLATFORM_MINGW32(nodeptrsize += 2);
7864 calcsize(lp->n); 8190 calcsize(lp->n);
7865 lp = lp->next; 8191 lp = lp->next;
7866 } 8192 }
@@ -7877,15 +8203,18 @@ calcsize(union node *n)
7877 calcsize(n->ncmd.redirect); 8203 calcsize(n->ncmd.redirect);
7878 calcsize(n->ncmd.args); 8204 calcsize(n->ncmd.args);
7879 calcsize(n->ncmd.assign); 8205 calcsize(n->ncmd.assign);
8206 IF_PLATFORM_MINGW32(nodeptrsize += 3);
7880 break; 8207 break;
7881 case NPIPE: 8208 case NPIPE:
7882 sizenodelist(n->npipe.cmdlist); 8209 sizenodelist(n->npipe.cmdlist);
8210 IF_PLATFORM_MINGW32(nodeptrsize++);
7883 break; 8211 break;
7884 case NREDIR: 8212 case NREDIR:
7885 case NBACKGND: 8213 case NBACKGND:
7886 case NSUBSHELL: 8214 case NSUBSHELL:
7887 calcsize(n->nredir.redirect); 8215 calcsize(n->nredir.redirect);
7888 calcsize(n->nredir.n); 8216 calcsize(n->nredir.n);
8217 IF_PLATFORM_MINGW32(nodeptrsize += 2);
7889 break; 8218 break;
7890 case NAND: 8219 case NAND:
7891 case NOR: 8220 case NOR:
@@ -7894,31 +8223,37 @@ calcsize(union node *n)
7894 case NUNTIL: 8223 case NUNTIL:
7895 calcsize(n->nbinary.ch2); 8224 calcsize(n->nbinary.ch2);
7896 calcsize(n->nbinary.ch1); 8225 calcsize(n->nbinary.ch1);
8226 IF_PLATFORM_MINGW32(nodeptrsize += 2);
7897 break; 8227 break;
7898 case NIF: 8228 case NIF:
7899 calcsize(n->nif.elsepart); 8229 calcsize(n->nif.elsepart);
7900 calcsize(n->nif.ifpart); 8230 calcsize(n->nif.ifpart);
7901 calcsize(n->nif.test); 8231 calcsize(n->nif.test);
8232 IF_PLATFORM_MINGW32(nodeptrsize += 3);
7902 break; 8233 break;
7903 case NFOR: 8234 case NFOR:
7904 funcstringsize += strlen(n->nfor.var) + 1; 8235 funcstringsize += strlen(n->nfor.var) + 1;
7905 calcsize(n->nfor.body); 8236 calcsize(n->nfor.body);
7906 calcsize(n->nfor.args); 8237 calcsize(n->nfor.args);
8238 IF_PLATFORM_MINGW32(nodeptrsize += 3);
7907 break; 8239 break;
7908 case NCASE: 8240 case NCASE:
7909 calcsize(n->ncase.cases); 8241 calcsize(n->ncase.cases);
7910 calcsize(n->ncase.expr); 8242 calcsize(n->ncase.expr);
8243 IF_PLATFORM_MINGW32(nodeptrsize += 2);
7911 break; 8244 break;
7912 case NCLIST: 8245 case NCLIST:
7913 calcsize(n->nclist.body); 8246 calcsize(n->nclist.body);
7914 calcsize(n->nclist.pattern); 8247 calcsize(n->nclist.pattern);
7915 calcsize(n->nclist.next); 8248 calcsize(n->nclist.next);
8249 IF_PLATFORM_MINGW32(nodeptrsize += 3);
7916 break; 8250 break;
7917 case NDEFUN: 8251 case NDEFUN:
7918 case NARG: 8252 case NARG:
7919 sizenodelist(n->narg.backquote); 8253 sizenodelist(n->narg.backquote);
7920 funcstringsize += strlen(n->narg.text) + 1; 8254 funcstringsize += strlen(n->narg.text) + 1;
7921 calcsize(n->narg.next); 8255 calcsize(n->narg.next);
8256 IF_PLATFORM_MINGW32(nodeptrsize += 3);
7922 break; 8257 break;
7923 case NTO: 8258 case NTO:
7924#if ENABLE_ASH_BASH_COMPAT 8259#if ENABLE_ASH_BASH_COMPAT
@@ -7930,28 +8265,34 @@ calcsize(union node *n)
7930 case NAPPEND: 8265 case NAPPEND:
7931 calcsize(n->nfile.fname); 8266 calcsize(n->nfile.fname);
7932 calcsize(n->nfile.next); 8267 calcsize(n->nfile.next);
8268 IF_PLATFORM_MINGW32(nodeptrsize += 2);
7933 break; 8269 break;
7934 case NTOFD: 8270 case NTOFD:
7935 case NFROMFD: 8271 case NFROMFD:
7936 calcsize(n->ndup.vname); 8272 calcsize(n->ndup.vname);
7937 calcsize(n->ndup.next); 8273 calcsize(n->ndup.next);
8274 IF_PLATFORM_MINGW32(nodeptrsize += 2);
7938 break; 8275 break;
7939 case NHERE: 8276 case NHERE:
7940 case NXHERE: 8277 case NXHERE:
7941 calcsize(n->nhere.doc); 8278 calcsize(n->nhere.doc);
7942 calcsize(n->nhere.next); 8279 calcsize(n->nhere.next);
8280 IF_PLATFORM_MINGW32(nodeptrsize += 2);
7943 break; 8281 break;
7944 case NNOT: 8282 case NNOT:
7945 calcsize(n->nnot.com); 8283 calcsize(n->nnot.com);
8284 IF_PLATFORM_MINGW32(nodeptrsize++);
7946 break; 8285 break;
7947 }; 8286 };
7948} 8287}
7949 8288
7950static char * 8289static char *
7951nodeckstrdup(char *s) 8290nodeckstrdup(const char *s)
7952{ 8291{
7953 char *rtn = funcstring; 8292 char *rtn = funcstring;
7954 8293
8294 if (!s)
8295 return NULL;
7955 strcpy(funcstring, s); 8296 strcpy(funcstring, s);
7956 funcstring += strlen(s) + 1; 8297 funcstring += strlen(s) + 1;
7957 return rtn; 8298 return rtn;
@@ -7959,6 +8300,18 @@ nodeckstrdup(char *s)
7959 8300
7960static union node *copynode(union node *); 8301static union node *copynode(union node *);
7961 8302
8303#if ENABLE_PLATFORM_MINGW32
8304# define SAVE_PTR(dst) {if (nodeptr) *nodeptr++ = (int)&(dst);}
8305# define SAVE_PTR2(dst1,dst2) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);}}
8306# define SAVE_PTR3(dst1,dst2,dst3) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);*nodeptr++ = (int)&(dst3);}}
8307# define SAVE_PTR4(dst1,dst2,dst3,dst4) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);*nodeptr++ = (int)&(dst3);*nodeptr++ = (int)&(dst4);}}
8308#else
8309# define SAVE_PTR(dst)
8310# define SAVE_PTR2(dst,dst2)
8311# define SAVE_PTR3(dst,dst2,dst3)
8312# define SAVE_PTR4(dst,dst2,dst3,dst4)
8313#endif
8314
7962static struct nodelist * 8315static struct nodelist *
7963copynodelist(struct nodelist *lp) 8316copynodelist(struct nodelist *lp)
7964{ 8317{
@@ -7970,6 +8323,7 @@ copynodelist(struct nodelist *lp)
7970 *lpp = funcblock; 8323 *lpp = funcblock;
7971 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist)); 8324 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7972 (*lpp)->n = copynode(lp->n); 8325 (*lpp)->n = copynode(lp->n);
8326 SAVE_PTR2((*lpp)->n, (*lpp)->next);
7973 lp = lp->next; 8327 lp = lp->next;
7974 lpp = &(*lpp)->next; 8328 lpp = &(*lpp)->next;
7975 } 8329 }
@@ -7992,16 +8346,19 @@ copynode(union node *n)
7992 new->ncmd.redirect = copynode(n->ncmd.redirect); 8346 new->ncmd.redirect = copynode(n->ncmd.redirect);
7993 new->ncmd.args = copynode(n->ncmd.args); 8347 new->ncmd.args = copynode(n->ncmd.args);
7994 new->ncmd.assign = copynode(n->ncmd.assign); 8348 new->ncmd.assign = copynode(n->ncmd.assign);
8349 SAVE_PTR3(new->ncmd.redirect,new->ncmd.args, new->ncmd.assign);
7995 break; 8350 break;
7996 case NPIPE: 8351 case NPIPE:
7997 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); 8352 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7998 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd; 8353 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8354 SAVE_PTR(new->npipe.cmdlist);
7999 break; 8355 break;
8000 case NREDIR: 8356 case NREDIR:
8001 case NBACKGND: 8357 case NBACKGND:
8002 case NSUBSHELL: 8358 case NSUBSHELL:
8003 new->nredir.redirect = copynode(n->nredir.redirect); 8359 new->nredir.redirect = copynode(n->nredir.redirect);
8004 new->nredir.n = copynode(n->nredir.n); 8360 new->nredir.n = copynode(n->nredir.n);
8361 SAVE_PTR2(new->nredir.redirect,new->nredir.n);
8005 break; 8362 break;
8006 case NAND: 8363 case NAND:
8007 case NOR: 8364 case NOR:
@@ -8010,31 +8367,37 @@ copynode(union node *n)
8010 case NUNTIL: 8367 case NUNTIL:
8011 new->nbinary.ch2 = copynode(n->nbinary.ch2); 8368 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8012 new->nbinary.ch1 = copynode(n->nbinary.ch1); 8369 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8370 SAVE_PTR2(new->nbinary.ch1,new->nbinary.ch2);
8013 break; 8371 break;
8014 case NIF: 8372 case NIF:
8015 new->nif.elsepart = copynode(n->nif.elsepart); 8373 new->nif.elsepart = copynode(n->nif.elsepart);
8016 new->nif.ifpart = copynode(n->nif.ifpart); 8374 new->nif.ifpart = copynode(n->nif.ifpart);
8017 new->nif.test = copynode(n->nif.test); 8375 new->nif.test = copynode(n->nif.test);
8376 SAVE_PTR3(new->nif.elsepart,new->nif.ifpart,new->nif.test);
8018 break; 8377 break;
8019 case NFOR: 8378 case NFOR:
8020 new->nfor.var = nodeckstrdup(n->nfor.var); 8379 new->nfor.var = nodeckstrdup(n->nfor.var);
8021 new->nfor.body = copynode(n->nfor.body); 8380 new->nfor.body = copynode(n->nfor.body);
8022 new->nfor.args = copynode(n->nfor.args); 8381 new->nfor.args = copynode(n->nfor.args);
8382 SAVE_PTR3(new->nfor.var,new->nfor.body,new->nfor.args);
8023 break; 8383 break;
8024 case NCASE: 8384 case NCASE:
8025 new->ncase.cases = copynode(n->ncase.cases); 8385 new->ncase.cases = copynode(n->ncase.cases);
8026 new->ncase.expr = copynode(n->ncase.expr); 8386 new->ncase.expr = copynode(n->ncase.expr);
8387 SAVE_PTR2(new->ncase.cases,new->ncase.expr);
8027 break; 8388 break;
8028 case NCLIST: 8389 case NCLIST:
8029 new->nclist.body = copynode(n->nclist.body); 8390 new->nclist.body = copynode(n->nclist.body);
8030 new->nclist.pattern = copynode(n->nclist.pattern); 8391 new->nclist.pattern = copynode(n->nclist.pattern);
8031 new->nclist.next = copynode(n->nclist.next); 8392 new->nclist.next = copynode(n->nclist.next);
8393 SAVE_PTR3(new->nclist.body,new->nclist.pattern,new->nclist.next);
8032 break; 8394 break;
8033 case NDEFUN: 8395 case NDEFUN:
8034 case NARG: 8396 case NARG:
8035 new->narg.backquote = copynodelist(n->narg.backquote); 8397 new->narg.backquote = copynodelist(n->narg.backquote);
8036 new->narg.text = nodeckstrdup(n->narg.text); 8398 new->narg.text = nodeckstrdup(n->narg.text);
8037 new->narg.next = copynode(n->narg.next); 8399 new->narg.next = copynode(n->narg.next);
8400 SAVE_PTR3(new->narg.backquote,new->narg.text,new->narg.next);
8038 break; 8401 break;
8039 case NTO: 8402 case NTO:
8040#if ENABLE_ASH_BASH_COMPAT 8403#if ENABLE_ASH_BASH_COMPAT
@@ -8047,6 +8410,7 @@ copynode(union node *n)
8047 new->nfile.fname = copynode(n->nfile.fname); 8410 new->nfile.fname = copynode(n->nfile.fname);
8048 new->nfile.fd = n->nfile.fd; 8411 new->nfile.fd = n->nfile.fd;
8049 new->nfile.next = copynode(n->nfile.next); 8412 new->nfile.next = copynode(n->nfile.next);
8413 SAVE_PTR2(new->nfile.fname,new->nfile.next);
8050 break; 8414 break;
8051 case NTOFD: 8415 case NTOFD:
8052 case NFROMFD: 8416 case NFROMFD:
@@ -8054,15 +8418,18 @@ copynode(union node *n)
8054 new->ndup.dupfd = n->ndup.dupfd; 8418 new->ndup.dupfd = n->ndup.dupfd;
8055 new->ndup.fd = n->ndup.fd; 8419 new->ndup.fd = n->ndup.fd;
8056 new->ndup.next = copynode(n->ndup.next); 8420 new->ndup.next = copynode(n->ndup.next);
8421 SAVE_PTR2(new->ndup.vname,new->ndup.next);
8057 break; 8422 break;
8058 case NHERE: 8423 case NHERE:
8059 case NXHERE: 8424 case NXHERE:
8060 new->nhere.doc = copynode(n->nhere.doc); 8425 new->nhere.doc = copynode(n->nhere.doc);
8061 new->nhere.fd = n->nhere.fd; 8426 new->nhere.fd = n->nhere.fd;
8062 new->nhere.next = copynode(n->nhere.next); 8427 new->nhere.next = copynode(n->nhere.next);
8428 SAVE_PTR2(new->nhere.doc,new->nhere.next);
8063 break; 8429 break;
8064 case NNOT: 8430 case NNOT:
8065 new->nnot.com = copynode(n->nnot.com); 8431 new->nnot.com = copynode(n->nnot.com);
8432 SAVE_PTR(new->nnot.com);
8066 break; 8433 break;
8067 }; 8434 };
8068 new->type = n->type; 8435 new->type = n->type;
@@ -8085,6 +8452,7 @@ copyfunc(union node *n)
8085 f = ckmalloc(blocksize + funcstringsize); 8452 f = ckmalloc(blocksize + funcstringsize);
8086 funcblock = (char *) f + offsetof(struct funcnode, n); 8453 funcblock = (char *) f + offsetof(struct funcnode, n);
8087 funcstring = (char *) f + blocksize; 8454 funcstring = (char *) f + blocksize;
8455 IF_PLATFORM_MINGW32(nodeptr = NULL);
8088 copynode(n); 8456 copynode(n);
8089 f->count = 0; 8457 f->count = 0;
8090 return f; 8458 return f;
@@ -8437,9 +8805,26 @@ evalcase(union node *n, int flags)
8437/* 8805/*
8438 * Kick off a subshell to evaluate a tree. 8806 * Kick off a subshell to evaluate a tree.
8439 */ 8807 */
8808#if ENABLE_PLATFORM_MINGW32
8809static void
8810forkshell_evalsubshell(struct forkshell *fs)
8811{
8812 union node *n = fs->n;
8813 int flags = fs->flags;
8814
8815 TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__));
8816 INT_ON;
8817 flags |= EV_EXIT;
8818 expredir(n->nredir.redirect);
8819 redirect(n->nredir.redirect, 0);
8820 evaltreenr(n->nredir.n, flags);
8821 /* never returns */
8822}
8823#endif
8440static void 8824static void
8441evalsubshell(union node *n, int flags) 8825evalsubshell(union node *n, int flags)
8442{ 8826{
8827 IF_PLATFORM_MINGW32(struct forkshell fs);
8443 struct job *jp; 8828 struct job *jp;
8444 int backgnd = (n->type == NBACKGND); 8829 int backgnd = (n->type == NBACKGND);
8445 int status; 8830 int status;
@@ -8449,6 +8834,14 @@ evalsubshell(union node *n, int flags)
8449 goto nofork; 8834 goto nofork;
8450 INT_OFF; 8835 INT_OFF;
8451 jp = makejob(/*n,*/ 1); 8836 jp = makejob(/*n,*/ 1);
8837#if ENABLE_PLATFORM_MINGW32
8838 memset(&fs, 0, sizeof(fs));
8839 fs.fp = forkshell_evalsubshell;
8840 fs.n = n;
8841 fs.flags = flags;
8842 if (spawn_forkshell(jp, &fs, backgnd) < 0)
8843 ash_msg_and_raise_error("unable to spawn shell");
8844#endif
8452 if (forkshell(jp, n, backgnd) == 0) { 8845 if (forkshell(jp, n, backgnd) == 0) {
8453 /* child */ 8846 /* child */
8454 INT_ON; 8847 INT_ON;
@@ -8525,9 +8918,35 @@ expredir(union node *n)
8525 * of the shell, which make the last process in a pipeline the parent 8918 * of the shell, which make the last process in a pipeline the parent
8526 * of all the rest.) 8919 * of all the rest.)
8527 */ 8920 */
8921#if ENABLE_PLATFORM_MINGW32
8922static void
8923forkshell_evalpipe(struct forkshell *fs)
8924{
8925 union node *n = fs->n;
8926 int flags = fs->flags;
8927 int prevfd = fs->fd[2];
8928 int pip[2] = {fs->fd[0], fs->fd[1]};
8929
8930 TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__));
8931 INT_ON;
8932 if (pip[1] >= 0) {
8933 close(pip[0]);
8934 }
8935 if (prevfd > 0) {
8936 dup2(prevfd, 0);
8937 close(prevfd);
8938 }
8939 if (pip[1] > 1) {
8940 dup2(pip[1], 1);
8941 close(pip[1]);
8942 }
8943 evaltreenr(n, flags);
8944}
8945#endif
8528static void 8946static void
8529evalpipe(union node *n, int flags) 8947evalpipe(union node *n, int flags)
8530{ 8948{
8949 IF_PLATFORM_MINGW32(struct forkshell fs);
8531 struct job *jp; 8950 struct job *jp;
8532 struct nodelist *lp; 8951 struct nodelist *lp;
8533 int pipelen; 8952 int pipelen;
@@ -8551,6 +8970,17 @@ evalpipe(union node *n, int flags)
8551 ash_msg_and_raise_error("pipe call failed"); 8970 ash_msg_and_raise_error("pipe call failed");
8552 } 8971 }
8553 } 8972 }
8973#if ENABLE_PLATFORM_MINGW32
8974 memset(&fs, 0, sizeof(fs));
8975 fs.fp = forkshell_evalpipe;
8976 fs.flags = flags;
8977 fs.n = lp->n;
8978 fs.fd[0] = pip[0];
8979 fs.fd[1] = pip[1];
8980 fs.fd[2] = prevfd;
8981 if (spawn_forkshell(jp, &fs, n->npipe.pipe_backgnd) < 0)
8982 ash_msg_and_raise_error("unable to spawn shell");
8983#endif
8554 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { 8984 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8555 INT_ON; 8985 INT_ON;
8556 if (pip[1] >= 0) { 8986 if (pip[1] >= 0) {
@@ -9019,6 +9449,20 @@ bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9019 * as POSIX mandates */ 9449 * as POSIX mandates */
9020 return back_exitstatus; 9450 return back_exitstatus;
9021} 9451}
9452
9453#if ENABLE_PLATFORM_MINGW32
9454static void
9455forkshell_shellexec(struct forkshell *fs)
9456{
9457 int idx = fs->fd[0];
9458 struct strlist *varlist = fs->strlist;
9459 char **argv = fs->argv;
9460 char *path = fs->string;
9461
9462 listsetvar(varlist, VEXPORT|VSTACK);
9463 shellexec(argv, path, idx);
9464}
9465#endif
9022static void 9466static void
9023evalcommand(union node *cmd, int flags) 9467evalcommand(union node *cmd, int flags)
9024{ 9468{
@@ -9195,6 +9639,26 @@ evalcommand(union node *cmd, int flags)
9195 } 9639 }
9196 } 9640 }
9197#endif 9641#endif
9642#if ENABLE_PLATFORM_MINGW32
9643 if (!(flags & EV_EXIT) || trap[0]) {
9644 struct forkshell fs;
9645
9646 memset(&fs, 0, sizeof(fs));
9647 fs.fp = forkshell_shellexec;
9648 fs.argv = argv;
9649 fs.string = (char*)path;
9650 fs.fd[0] = cmdentry.u.index;
9651 fs.strlist = varlist.list;
9652 jp = makejob(/*cmd,*/ 1);
9653 if (spawn_forkshell(jp, &fs, FORK_FG) < 0)
9654 ash_msg_and_raise_error("unable to spawn shell");
9655 exitstatus = waitforjob(jp);
9656 INT_ON;
9657 TRACE(("forked child exited with %d\n", exitstatus));
9658 break;
9659 }
9660 /* goes through to shellexec() */
9661#endif
9198 /* Fork off a child process if necessary. */ 9662 /* Fork off a child process if necessary. */
9199 if (!(flags & EV_EXIT) || may_have_traps) { 9663 if (!(flags & EV_EXIT) || may_have_traps) {
9200 INT_OFF; 9664 INT_OFF;
@@ -9578,7 +10042,7 @@ preadbuffer(void)
9578 more--; 10042 more--;
9579 10043
9580 c = *q; 10044 c = *q;
9581 if (c == '\0') { 10045 if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) {
9582 memmove(q, q + 1, more); 10046 memmove(q, q + 1, more);
9583 } else { 10047 } else {
9584 q++; 10048 q++;
@@ -12005,7 +12469,7 @@ find_dot_file(char *name)
12005 struct stat statb; 12469 struct stat statb;
12006 12470
12007 /* don't try this for absolute or relative paths */ 12471 /* don't try this for absolute or relative paths */
12008 if (strchr(name, '/')) 12472 if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\')))
12009 return name; 12473 return name;
12010 12474
12011 /* IIRC standards do not say whether . is to be searched. 12475 /* IIRC standards do not say whether . is to be searched.
@@ -12115,10 +12579,11 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
12115 struct stat statb; 12579 struct stat statb;
12116 int e; 12580 int e;
12117 int updatetbl; 12581 int updatetbl;
12582 IF_PLATFORM_MINGW32(int len);
12118 struct builtincmd *bcmd; 12583 struct builtincmd *bcmd;
12119 12584
12120 /* If name contains a slash, don't use PATH or hash table */ 12585 /* If name contains a slash, don't use PATH or hash table */
12121 if (strchr(name, '/') != NULL) { 12586 if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) {
12122 entry->u.index = -1; 12587 entry->u.index = -1;
12123 if (act & DO_ABS) { 12588 if (act & DO_ABS) {
12124 while (stat(name, &statb) < 0) { 12589 while (stat(name, &statb) < 0) {
@@ -12225,12 +12690,39 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
12225 } 12690 }
12226 } 12691 }
12227 /* if rehash, don't redo absolute path names */ 12692 /* if rehash, don't redo absolute path names */
12228 if (fullname[0] == '/' && idx <= prev) { 12693 if (is_absolute_path(fullname) && idx <= prev) {
12229 if (idx < prev) 12694 if (idx < prev)
12230 continue; 12695 continue;
12231 TRACE(("searchexec \"%s\": no change\n", name)); 12696 TRACE(("searchexec \"%s\": no change\n", name));
12232 goto success; 12697 goto success;
12233 } 12698 }
12699#if ENABLE_PLATFORM_MINGW32
12700 len = strlen(fullname);
12701 if (len > 4 &&
12702 (!strcasecmp(fullname+len-4, ".exe") ||
12703 !strcasecmp(fullname+len-4, ".com"))) {
12704 if (stat(fullname, &statb) < 0) {
12705 if (errno != ENOENT && errno != ENOTDIR)
12706 e = errno;
12707 goto loop;
12708 }
12709 }
12710 else {
12711 /* path_advance() has reserved space for .exe */
12712 memcpy(fullname+len, ".exe", 5);
12713 if (stat(fullname, &statb) < 0) {
12714 if (errno != ENOENT && errno != ENOTDIR)
12715 e = errno;
12716 memcpy(fullname+len, ".com", 5);
12717 if (stat(fullname, &statb) < 0) {
12718 if (errno != ENOENT && errno != ENOTDIR)
12719 e = errno;
12720 goto loop;
12721 }
12722 }
12723 fullname[len] = '\0';
12724 }
12725#else
12234 while (stat(fullname, &statb) < 0) { 12726 while (stat(fullname, &statb) < 0) {
12235#ifdef SYSV 12727#ifdef SYSV
12236 if (errno == EINTR) 12728 if (errno == EINTR)
@@ -12240,6 +12732,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
12240 e = errno; 12732 e = errno;
12241 goto loop; 12733 goto loop;
12242 } 12734 }
12735#endif
12243 e = EACCES; /* if we fail, this will be the error */ 12736 e = EACCES; /* if we fail, this will be the error */
12244 if (!S_ISREG(statb.st_mode)) 12737 if (!S_ISREG(statb.st_mode))
12245 continue; 12738 continue;
@@ -12491,6 +12984,8 @@ unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12491 12984
12492/* setmode.c */ 12985/* setmode.c */
12493 12986
12987#if !ENABLE_PLATFORM_MINGW32
12988
12494#include <sys/times.h> 12989#include <sys/times.h>
12495 12990
12496static const unsigned char timescmd_str[] ALIGN1 = { 12991static const unsigned char timescmd_str[] ALIGN1 = {
@@ -12523,6 +13018,13 @@ timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12523 13018
12524 return 0; 13019 return 0;
12525} 13020}
13021#else
13022static int FAST_FUNC
13023timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13024{
13025 return 0;
13026}
13027#endif
12526 13028
12527#if ENABLE_SH_MATH_SUPPORT 13029#if ENABLE_SH_MATH_SUPPORT
12528/* 13030/*
@@ -12760,13 +13262,41 @@ init(void)
12760 struct stat st1, st2; 13262 struct stat st1, st2;
12761 13263
12762 initvar(); 13264 initvar();
13265
13266#if ENABLE_PLATFORM_MINGW32
13267 /*
13268 * case insensitive env names from Windows world
13269 *
13270 * Some standard env names such as PATH is named Path and so on
13271 * ash itself is case sensitive, so "Path" will confuse it, as
13272 * MSVC getenv() is case insensitive.
13273 *
13274 * We may end up having both Path and PATH. Then Path will be chosen
13275 * because it appears first.
13276 */
13277 for (envp = environ; envp && *envp; envp++)
13278 if (!strncasecmp(*envp, "PATH=", 5) &&
13279 strncmp(*envp, "PATH=", 5))
13280 break;
13281 if (envp && *envp) {
13282 char *start, *end;
13283 for (envp = environ; envp && *envp; envp++) {
13284 end = strchr(*envp, '=');
13285 if (!end)
13286 continue;
13287 for (start = *envp;start < end;start++)
13288 *start = toupper(*start);
13289 }
13290 }
13291#endif
12763 for (envp = environ; envp && *envp; envp++) { 13292 for (envp = environ; envp && *envp; envp++) {
12764 if (strchr(*envp, '=')) { 13293 if (strchr(*envp, '=')) {
12765 setvareq(*envp, VEXPORT|VTEXTFIXED); 13294 setvareq(*envp, VEXPORT|VTEXTFIXED);
12766 } 13295 }
12767 } 13296 }
12768 13297
12769 setvar("PPID", utoa(getppid()), 0); 13298 if (!ENABLE_PLATFORM_MINGW32)
13299 setvar("PPID", utoa(getppid()), 0);
12770 13300
12771 p = lookupvar("PWD"); 13301 p = lookupvar("PWD");
12772 if (p) 13302 if (p)
@@ -12882,6 +13412,20 @@ static short profile_buf[16384];
12882extern int etext(); 13412extern int etext();
12883#endif 13413#endif
12884 13414
13415#if ENABLE_PLATFORM_MINGW32
13416static const forkpoint_fn forkpoints[] = {
13417 forkshell_openhere,
13418 forkshell_evalbackcmd,
13419 forkshell_evalsubshell,
13420 forkshell_evalpipe,
13421 forkshell_shellexec,
13422 NULL
13423};
13424
13425static struct forkshell* forkshell_prepare(struct forkshell *fs);
13426static void forkshell_init(const char *idstr);
13427#endif
13428
12885/* 13429/*
12886 * Main routine. We initialize things, parse the arguments, execute 13430 * Main routine. We initialize things, parse the arguments, execute
12887 * profiles if we're a login shell, and then call cmdloop to execute 13431 * profiles if we're a login shell, and then call cmdloop to execute
@@ -12949,6 +13493,15 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
12949 13493
12950 init(); 13494 init();
12951 setstackmark(&smark); 13495 setstackmark(&smark);
13496
13497#if ENABLE_PLATFORM_MINGW32
13498 if (argc == 3 && !strcmp(argv[1], "--forkshell")) {
13499 forkshell_init(argv[2]);
13500
13501 /* NOTREACHED */
13502 bb_error_msg_and_die("subshell ended unexpectedly");
13503 }
13504#endif
12952 procargs(argv); 13505 procargs(argv);
12953 13506
12954#if ENABLE_FEATURE_EDITING_SAVEHISTORY 13507#if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -13023,6 +13576,524 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
13023 /* NOTREACHED */ 13576 /* NOTREACHED */
13024} 13577}
13025 13578
13579/* FIXME: should consider running forkparent() and forkchild() */
13580static int
13581spawn_forkshell(struct job *jp, struct forkshell *fs, int mode)
13582{
13583 const char *argv[] = { "sh", "--forkshell", NULL, NULL };
13584 char buf[16];
13585
13586 struct forkshell *new;
13587 new = forkshell_prepare(fs);
13588 sprintf(buf, "%x", (unsigned int)new->hMapFile);
13589 argv[2] = buf;
13590 fs->pid = mingw_spawn_applet(P_NOWAIT, "sh", argv,
13591 (const char *const *)environ);
13592 CloseHandle(new->hMapFile);
13593 UnmapViewOfFile(new);
13594 if (fs->pid == -1) {
13595 free(jp);
13596 return -1;
13597 }
13598 forkparent(jp, fs->node, mode, fs->pid);
13599 return fs->pid;
13600}
13601
13602/*
13603 * forkshell_prepare() and friends
13604 *
13605 * The sequence is as follows:
13606 * - funcblocksize, funcstringsize, nodeptrsize are initialized
13607 * - forkshell_size(fs) is called to calculate the exact memory needed
13608 * - a new struct is allocated
13609 * - funcblock, funcstring, nodeptr are initialized from the new block
13610 * - forkshell_copy(fs) is called to copy recursively everything over
13611 * it will record all pointers along the way, to nodeptr
13612 *
13613 * When this memory is mapped elsewhere, pointer fixup will be needed
13614 */
13615#define SLIST_SIZE_BEGIN(name,type) \
13616static void \
13617name(type *p) \
13618{ \
13619 while (p) { \
13620 funcblocksize += sizeof(type);
13621 /* do something here with p */
13622#define SLIST_SIZE_END() \
13623 nodeptrsize++; \
13624 p = p->next; \
13625 } \
13626}
13627
13628#define SLIST_COPY_BEGIN(name,type) \
13629static type * \
13630name(type *vp) \
13631{ \
13632 type *start; \
13633 type **vpp; \
13634 vpp = &start; \
13635 while (vp) { \
13636 *vpp = funcblock; \
13637 funcblock = (char *) funcblock + sizeof(type);
13638 /* do something here with vpp and vp */
13639#define SLIST_COPY_END() \
13640 SAVE_PTR((*vpp)->next); \
13641 vp = vp->next; \
13642 vpp = &(*vpp)->next; \
13643 } \
13644 *vpp = NULL; \
13645 return start; \
13646}
13647
13648/*
13649 * struct var
13650 */
13651SLIST_SIZE_BEGIN(var_size,struct var)
13652funcstringsize += strlen(p->text) + 1;
13653nodeptrsize++; /* p->text */
13654SLIST_SIZE_END()
13655
13656SLIST_COPY_BEGIN(var_copy,struct var)
13657(*vpp)->text = nodeckstrdup(vp->text);
13658(*vpp)->flags = vp->flags;
13659/*
13660 * The only place that can set struct var#func is varinit[],
13661 * which will be fixed by forkshell_init()
13662 */
13663(*vpp)->func = NULL;
13664SAVE_PTR((*vpp)->text);
13665SLIST_COPY_END()
13666
13667/*
13668 * struct localvar
13669 */
13670SLIST_SIZE_BEGIN(localvar_size,struct localvar)
13671var_size(p->vp);
13672funcstringsize += strlen(p->text) + 1;
13673nodeptrsize += 2; /* p->vp, p->text */
13674SLIST_SIZE_END()
13675
13676SLIST_COPY_BEGIN(localvar_copy,struct localvar)
13677(*vpp)->text = nodeckstrdup(vp->text);
13678(*vpp)->flags = vp->flags;
13679(*vpp)->vp = var_copy(vp->vp);
13680SAVE_PTR2((*vpp)->vp, (*vpp)->text);
13681SLIST_COPY_END()
13682
13683/*
13684 * struct strlist
13685 */
13686SLIST_SIZE_BEGIN(strlist_size,struct strlist)
13687funcstringsize += strlen(p->text) + 1;
13688nodeptrsize++; /* p->text */
13689SLIST_SIZE_END()
13690
13691SLIST_COPY_BEGIN(strlist_copy,struct strlist)
13692(*vpp)->text = nodeckstrdup(vp->text);
13693SAVE_PTR((*vpp)->text);
13694SLIST_COPY_END()
13695
13696/*
13697 * struct tblentry
13698 */
13699static void
13700tblentry_size(struct tblentry *tep)
13701{
13702 while (tep) {
13703 funcblocksize += sizeof(struct tblentry) + strlen(tep->cmdname) + 1;
13704 /* CMDBUILTIN, e->param.cmd needs no pointer relocation */
13705 if (tep->cmdtype == CMDFUNCTION) {
13706 funcblocksize += offsetof(struct funcnode, n);
13707 calcsize(&tep->param.func->n);
13708 nodeptrsize++; /* tep->param.func */
13709 }
13710 nodeptrsize++; /* tep->next */
13711 tep = tep->next;
13712 }
13713}
13714
13715static struct tblentry *
13716tblentry_copy(struct tblentry *tep)
13717{
13718 struct tblentry *start;
13719 struct tblentry **newp;
13720 int size;
13721
13722 newp = &start;
13723 while (tep) {
13724 *newp = funcblock;
13725 size = sizeof(struct tblentry) + strlen(tep->cmdname) + 1;
13726
13727 funcblock = (char *) funcblock + size;
13728 memcpy(*newp, tep, size);
13729 switch (tep->cmdtype) {
13730 case CMDBUILTIN:
13731 /* No pointer saving, this field must be fixed by forkshell_init() */
13732 (*newp)->param.cmd = (const struct builtincmd *)(tep->param.cmd - builtintab);
13733 break;
13734 case CMDFUNCTION:
13735 (*newp)->param.func = funcblock;
13736 funcblock = (char *) funcblock + offsetof(struct funcnode, n);
13737 copynode(&tep->param.func->n);
13738 SAVE_PTR((*newp)->param.func);
13739 break;
13740 default:
13741 break;
13742 }
13743 SAVE_PTR((*newp)->next);
13744 tep = tep->next;
13745 newp = &(*newp)->next;
13746 }
13747 *newp = NULL;
13748 return start;
13749}
13750
13751static void
13752cmdtable_size(struct tblentry **cmdtablep)
13753{
13754 int i;
13755 nodeptrsize += CMDTABLESIZE;
13756 funcblocksize += sizeof(struct tblentry *)*CMDTABLESIZE;
13757 for (i = 0; i < CMDTABLESIZE; i++)
13758 tblentry_size(cmdtablep[i]);
13759}
13760
13761static struct tblentry **
13762cmdtable_copy(struct tblentry **cmdtablep)
13763{
13764 struct tblentry **new = funcblock;
13765 int i;
13766
13767 funcblock = (char *) funcblock + sizeof(struct tblentry *)*CMDTABLESIZE;
13768 for (i = 0; i < CMDTABLESIZE; i++) {
13769 new[i] = tblentry_copy(cmdtablep[i]);
13770 SAVE_PTR(new[i]);
13771 }
13772 return new;
13773}
13774
13775/*
13776 * char **
13777 */
13778static void
13779argv_size(char **p)
13780{
13781 while (p && *p) {
13782 funcblocksize += sizeof(char *);
13783 funcstringsize += strlen(*p)+1;
13784 nodeptrsize++;
13785 p++;
13786 }
13787 funcblocksize += sizeof(char *);
13788}
13789
13790static char **
13791argv_copy(char **p)
13792{
13793 char **new, **start = funcblock;
13794
13795 while (p && *p) {
13796 new = funcblock;
13797 funcblock = (char *) funcblock + sizeof(char *);
13798 *new = nodeckstrdup(*p);
13799 SAVE_PTR(*new);
13800 p++;
13801 new++;
13802 }
13803 new = funcblock;
13804 funcblock = (char *) funcblock + sizeof(char *);
13805 *new = NULL;
13806 return start;
13807}
13808
13809/*
13810 * struct redirtab
13811 */
13812static void
13813redirtab_size(struct redirtab *rdtp)
13814{
13815 while (rdtp) {
13816 funcblocksize += sizeof(*rdtp)+sizeof(rdtp->two_fd[0])*rdtp->pair_count;
13817 rdtp = rdtp->next;
13818 nodeptrsize++; /* rdtp->next */
13819 }
13820}
13821
13822static struct redirtab *
13823redirtab_copy(struct redirtab *rdtp)
13824{
13825 struct redirtab *start;
13826 struct redirtab **vpp;
13827
13828 vpp = &start;
13829 while (rdtp) {
13830 int size = sizeof(*rdtp)+sizeof(rdtp->two_fd[0])*rdtp->pair_count;
13831 *vpp = funcblock;
13832 funcblock = (char *) funcblock + size;
13833 memcpy(*vpp, rdtp, size);
13834 SAVE_PTR((*vpp)->next);
13835 rdtp = rdtp->next;
13836 vpp = &(*vpp)->next;
13837 }
13838 *vpp = NULL;
13839 return start;
13840}
13841
13842#undef shellparam
13843#undef redirlist
13844#undef varinit
13845#undef vartab
13846static void
13847globals_var_size(struct globals_var *gvp)
13848{
13849 int i;
13850
13851 funcblocksize += sizeof(struct globals_var);
13852 argv_size(gvp->shellparam.p);
13853 redirtab_size(gvp->redirlist);
13854 for (i = 0; i < VTABSIZE; i++)
13855 var_size(gvp->vartab[i]);
13856 for (i = 0; i < ARRAY_SIZE(varinit_data); i++)
13857 var_size(gvp->varinit+i);
13858 nodeptrsize += 2 + VTABSIZE; /* gvp->redirlist, gvp->shellparam.p, vartab */
13859}
13860
13861#undef g_nullredirs
13862#undef preverrout_fd
13863static struct globals_var *
13864globals_var_copy(struct globals_var *gvp)
13865{
13866 int i;
13867 struct globals_var *new;
13868
13869 new = funcblock;
13870 funcblock = (char *) funcblock + sizeof(struct globals_var);
13871
13872 /* shparam */
13873 memcpy(&new->shellparam, &gvp->shellparam, sizeof(struct shparam));
13874 new->shellparam.malloced = 0;
13875 new->shellparam.p = argv_copy(gvp->shellparam.p);
13876 SAVE_PTR(new->shellparam.p);
13877
13878 new->redirlist = redirtab_copy(gvp->redirlist);
13879 SAVE_PTR(new->redirlist);
13880
13881 new->g_nullredirs = gvp->g_nullredirs;
13882 new->preverrout_fd = gvp->preverrout_fd;
13883 for (i = 0; i < VTABSIZE; i++) {
13884 new->vartab[i] = var_copy(gvp->vartab[i]);
13885 SAVE_PTR(new->vartab[i]);
13886 }
13887
13888 /* Can't use var_copy because varinit is already allocated */
13889 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) {
13890 new->varinit[i].next = NULL;
13891 new->varinit[i].text = nodeckstrdup(gvp->varinit[i].text);
13892 SAVE_PTR(new->varinit[i].text);
13893 new->varinit[i].flags = gvp->varinit[i].flags;
13894 new->varinit[i].func = gvp->varinit[i].func;
13895 }
13896 return new;
13897}
13898
13899#undef minusc
13900#undef curdir
13901#undef physdir
13902#undef arg0
13903#undef nullstr
13904static void
13905globals_misc_size(struct globals_misc *p)
13906{
13907 funcblocksize += sizeof(struct globals_misc);
13908 funcstringsize += p->minusc ? strlen(p->minusc) + 1 : 1;
13909 if (p->curdir != p->nullstr)
13910 funcstringsize += strlen(p->curdir) + 1;
13911 if (p->physdir != p->nullstr)
13912 funcstringsize += strlen(p->physdir) + 1;
13913 funcstringsize += strlen(p->arg0) + 1;
13914 nodeptrsize += 4; /* minusc, curdir, physdir, arg0 */
13915}
13916
13917static struct globals_misc *
13918globals_misc_copy(struct globals_misc *p)
13919{
13920 struct globals_misc *new = funcblock;
13921
13922 funcblock = (char *) funcblock + sizeof(struct globals_misc);
13923 memcpy(new, p, sizeof(struct globals_misc));
13924
13925 new->minusc = nodeckstrdup(p->minusc);
13926 new->curdir = p->curdir != p->nullstr ? nodeckstrdup(p->curdir) : new->nullstr;
13927 new->physdir = p->physdir != p->nullstr ? nodeckstrdup(p->physdir) : new->nullstr;
13928 new->arg0 = nodeckstrdup(p->arg0);
13929 SAVE_PTR4(new->minusc, new->curdir, new->physdir, new->arg0);
13930 return new;
13931}
13932
13933static void
13934forkshell_size(struct forkshell *fs)
13935{
13936 funcblocksize += sizeof(struct forkshell);
13937 globals_var_size(fs->gvp);
13938 globals_misc_size(fs->gmp);
13939 cmdtable_size(fs->cmdtable);
13940 localvar_size(fs->localvars);
13941 /* optlist_transfer(sending, fd); */
13942 /* misc_transfer(sending, fd); */
13943
13944 calcsize(fs->n);
13945 argv_size(fs->argv);
13946 funcstringsize += (fs->string ? strlen(fs->string) : 0) + 1;
13947 strlist_size(fs->strlist);
13948
13949 nodeptrsize += 8; /* gvp, gmp, cmdtable, localvars, n, argv, string, strlist */
13950}
13951
13952static struct forkshell *
13953forkshell_copy(struct forkshell *fs)
13954{
13955 struct forkshell *new;
13956
13957 new = funcblock;
13958 funcblock = (char *) funcblock + sizeof(struct forkshell);
13959
13960 memcpy(new, fs, sizeof(struct forkshell)); /* non-pointer stuff */
13961 new->gvp = globals_var_copy(fs->gvp);
13962 new->gmp = globals_misc_copy(fs->gmp);
13963 new->cmdtable = cmdtable_copy(fs->cmdtable);
13964 new->localvars = localvar_copy(fs->localvars);
13965 SAVE_PTR4(new->gvp, new->gmp, new->cmdtable, new->localvars);
13966
13967 /* new->fs will be reconstructed from new->fpid */
13968 new->n = copynode(fs->n);
13969 new->argv = argv_copy(fs->argv);
13970 new->string = nodeckstrdup(fs->string);
13971 new->strlist = strlist_copy(fs->strlist);
13972 SAVE_PTR4(new->n, new->argv, new->string, new->strlist);
13973 return new;
13974}
13975
13976static struct forkshell *
13977forkshell_prepare(struct forkshell *fs)
13978{
13979 struct forkshell *new;
13980 int size, fp, nodeptr_offset;
13981 HANDLE h;
13982 SECURITY_ATTRIBUTES sa;
13983
13984 for (fp = 0; forkpoints[fp] && forkpoints[fp] != fs->fp; fp++)
13985 ;
13986
13987 if (!forkpoints[fp])
13988 bb_error_msg_and_die("invalid forkpoint %08x", (int)fs->fp);
13989 fs->fpid = fp;
13990
13991 /* Calculate size of "new" */
13992 fs->gvp = ash_ptr_to_globals_var;
13993 fs->gmp = ash_ptr_to_globals_misc;
13994 fs->cmdtable = cmdtable;
13995 fs->localvars = localvars;
13996
13997 nodeptrsize = 1; /* NULL terminated */
13998 funcblocksize = 0;
13999 funcstringsize = 0;
14000 forkshell_size(fs);
14001 size = funcblocksize + funcstringsize + nodeptrsize*sizeof(int);
14002
14003 /* Allocate, initialize pointers */
14004 memset(&sa, 0, sizeof(sa));
14005 sa.nLength = sizeof(sa);
14006 sa.lpSecurityDescriptor = NULL;
14007 sa.bInheritHandle = TRUE;
14008 h = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, size, NULL);
14009 new = (struct forkshell *)MapViewOfFile(h, FILE_MAP_WRITE, 0,0, 0);
14010 /* new = ckmalloc(size); */
14011 funcblock = new;
14012 funcstring = (char *) funcblock + funcblocksize;
14013 nodeptr = (int*)((char *) funcstring + funcstringsize);
14014 nodeptr_offset = (int) nodeptr - (int) new;
14015
14016 /* Now pack them all */
14017 forkshell_copy(fs);
14018
14019 /* Finish it up */
14020 *nodeptr = 0;
14021 new->size = size;
14022 new->nodeptr_offset = nodeptr_offset;
14023 new->old_base = new;
14024 new->hMapFile = h;
14025 return new;
14026}
14027
14028#undef exception_handler
14029#undef trap
14030#undef trap_ptr
14031static void *sticky_mem_start, *sticky_mem_end;
14032static void
14033forkshell_init(const char *idstr)
14034{
14035 struct forkshell *fs;
14036 int map_handle;
14037 HANDLE h;
14038 struct globals_var **gvpp;
14039 struct globals_misc **gmpp;
14040 int i;
14041
14042 if (sscanf(idstr, "%x", &map_handle) != 1)
14043 bb_error_msg_and_die("invalid forkshell ID");
14044
14045 h = (HANDLE)map_handle;
14046 fs = (struct forkshell *)MapViewOfFile(h, FILE_MAP_WRITE, 0,0, 0);
14047 if (!fs)
14048 bb_error_msg_and_die("Invalid forkshell memory");
14049
14050 /* this memory can't be freed */
14051 sticky_mem_start = fs;
14052 sticky_mem_end = (char *) fs + fs->size;
14053 /* pointer fixup */
14054 nodeptr = (int*)((char*)fs + fs->nodeptr_offset);
14055 while (*nodeptr) {
14056 int *ptr = (int*)((char*)fs + (*nodeptr - (int)fs->old_base));
14057 if (*ptr)
14058 *ptr -= ((int)fs->old_base - (int)fs);
14059 nodeptr++;
14060 }
14061 /* Now fix up stuff that can't be transferred */
14062 fs->fp = forkpoints[fs->fpid];
14063 for (i = 0; i < ARRAY_SIZE(varinit_data); i++)
14064 fs->gvp->varinit[i].func = varinit_data[i].func;
14065 for (i = 0; i < CMDTABLESIZE; i++) {
14066 struct tblentry *e = fs->cmdtable[i];
14067 while (e) {
14068 if (e->cmdtype == CMDBUILTIN)
14069 e->param.cmd = builtintab + (int)e->param.cmd;
14070 e = e->next;
14071 }
14072 }
14073 fs->gmp->exception_handler = ash_ptr_to_globals_misc->exception_handler;
14074 for (i = 0; i < NSIG; i++)
14075 fs->gmp->trap[i] = ash_ptr_to_globals_misc->trap[i];
14076 fs->gmp->trap_ptr = ash_ptr_to_globals_misc->trap_ptr;
14077
14078 /* Switch global variables */
14079 gvpp = (struct globals_var **)&ash_ptr_to_globals_var;
14080 *gvpp = fs->gvp;
14081 gmpp = (struct globals_misc **)&ash_ptr_to_globals_misc;
14082 *gmpp = fs->gmp;
14083 localvars = fs->localvars;
14084 cmdtable = fs->cmdtable;
14085
14086 fs->fp(fs);
14087}
14088
14089#undef free
14090static void
14091sticky_free(void *base)
14092{
14093 if (base >= sticky_mem_start && base < sticky_mem_end)
14094 return;
14095 free(base);
14096}
13026 14097
13027/*- 14098/*-
13028 * Copyright (c) 1989, 1991, 1993, 1994 14099 * Copyright (c) 1989, 1991, 1993, 1994
diff --git a/shell/builtin_ulimit.c b/shell/builtin_ulimit.c
index 9f9205eb6..7ef17b1b0 100644
--- a/shell/builtin_ulimit.c
+++ b/shell/builtin_ulimit.c
@@ -16,6 +16,14 @@
16 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 16 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 */ 17 */
18#include "libbb.h" 18#include "libbb.h"
19
20#if ENABLE_PLATFORM_MINGW32
21int FAST_FUNC shell_builtin_ulimit(char **argv)
22{
23 return 1;
24}
25#else
26
19#include "builtin_ulimit.h" 27#include "builtin_ulimit.h"
20 28
21 29
@@ -226,3 +234,4 @@ int FAST_FUNC shell_builtin_ulimit(char **argv)
226 234
227 return 0; 235 return 0;
228} 236}
237#endif
diff --git a/win32/Kbuild b/win32/Kbuild
new file mode 100644
index 000000000..a4a7f32d4
--- /dev/null
+++ b/win32/Kbuild
@@ -0,0 +1,13 @@
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) += mingw.o
10lib-$(CONFIG_PLATFORM_MINGW32) += process.o
11lib-$(CONFIG_PLATFORM_MINGW32) += regex.o
12lib-$(CONFIG_PLATFORM_MINGW32) += termios.o
13lib-$(CONFIG_PLATFORM_MINGW32) += winansi.o
diff --git a/win32/env.c b/win32/env.c
new file mode 100644
index 000000000..376ad9d47
--- /dev/null
+++ b/win32/env.c
@@ -0,0 +1,119 @@
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 }
108 return env;
109}
110
111void unsetenv(const char *env)
112{
113 env_setenv(environ, env);
114}
115
116int clearenv(void)
117{
118 bb_error_msg_and_die("clearenv() is not supported");
119}
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/mingw.c b/win32/mingw.c
new file mode 100644
index 000000000..0a7345374
--- /dev/null
+++ b/win32/mingw.c
@@ -0,0 +1,777 @@
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 (!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 *mode)
146{
147 if (!strcmp(filename, "/dev/null"))
148 filename = "nul";
149 return fopen(filename, mode);
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
159static inline time_t filetime_to_time_t(const FILETIME *ft)
160{
161 long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
162 winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
163 winTime /= 10000000; /* Nano to seconds resolution */
164 return (time_t)winTime;
165}
166
167static inline int file_attr_to_st_mode (DWORD attr)
168{
169 int fMode = S_IREAD;
170 if (attr & FILE_ATTRIBUTE_DIRECTORY)
171 fMode |= S_IFDIR;
172 else
173 fMode |= S_IFREG;
174 if (!(attr & FILE_ATTRIBUTE_READONLY))
175 fMode |= S_IWRITE;
176 return fMode;
177}
178
179static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fdata)
180{
181 if (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata))
182 return 0;
183
184 switch (GetLastError()) {
185 case ERROR_ACCESS_DENIED:
186 case ERROR_SHARING_VIOLATION:
187 case ERROR_LOCK_VIOLATION:
188 case ERROR_SHARING_BUFFER_EXCEEDED:
189 return EACCES;
190 case ERROR_BUFFER_OVERFLOW:
191 return ENAMETOOLONG;
192 case ERROR_NOT_ENOUGH_MEMORY:
193 return ENOMEM;
194 default:
195 return ENOENT;
196 }
197}
198
199/* We keep the do_lstat code in a separate function to avoid recursion.
200 * When a path ends with a slash, the stat will fail with ENOENT. In
201 * this case, we strip the trailing slashes and stat again.
202 */
203static int do_lstat(const char *file_name, struct stat *buf)
204{
205 WIN32_FILE_ATTRIBUTE_DATA fdata;
206
207 if (!(errno = get_file_attr(file_name, &fdata))) {
208 int len = strlen(file_name);
209
210 buf->st_ino = 0;
211 buf->st_gid = 0;
212 buf->st_uid = 0;
213 buf->st_nlink = 1;
214 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
215 if (len > 4 && !strcmp(file_name+len-4, ".exe"))
216 buf->st_mode |= S_IEXEC;
217 buf->st_size = fdata.nFileSizeLow |
218 (((off64_t)fdata.nFileSizeHigh)<<32);
219 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
220 buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
221 buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
222 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
223 return 0;
224 }
225 return -1;
226}
227
228/* We provide our own lstat/fstat functions, since the provided
229 * lstat/fstat functions are so slow. These stat functions are
230 * tailored for Git's usage (read: fast), and are not meant to be
231 * complete. Note that Git stat()s are redirected to mingw_lstat()
232 * too, since Windows doesn't really handle symlinks that well.
233 */
234int mingw_lstat(const char *file_name, struct stat *buf)
235{
236 int namelen;
237 static char alt_name[PATH_MAX];
238
239 if (!do_lstat(file_name, buf))
240 return 0;
241
242 /* if file_name ended in a '/', Windows returned ENOENT;
243 * try again without trailing slashes
244 */
245 if (errno != ENOENT)
246 return -1;
247
248 namelen = strlen(file_name);
249 if (namelen && file_name[namelen-1] != '/')
250 return -1;
251 while (namelen && file_name[namelen-1] == '/')
252 --namelen;
253 if (!namelen || namelen >= PATH_MAX)
254 return -1;
255
256 memcpy(alt_name, file_name, namelen);
257 alt_name[namelen] = 0;
258 return do_lstat(alt_name, buf);
259}
260
261#undef fstat
262int mingw_fstat(int fd, struct stat *buf)
263{
264 HANDLE fh = (HANDLE)_get_osfhandle(fd);
265 BY_HANDLE_FILE_INFORMATION fdata;
266
267 if (fh == INVALID_HANDLE_VALUE) {
268 errno = EBADF;
269 return -1;
270 }
271 /* direct non-file handles to MS's fstat() */
272 if (GetFileType(fh) != FILE_TYPE_DISK)
273 return _fstati64(fd, buf);
274
275 if (GetFileInformationByHandle(fh, &fdata)) {
276 buf->st_ino = 0;
277 buf->st_gid = 0;
278 buf->st_uid = 0;
279 buf->st_nlink = 1;
280 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
281 buf->st_size = fdata.nFileSizeLow |
282 (((off64_t)fdata.nFileSizeHigh)<<32);
283 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
284 buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
285 buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
286 buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
287 return 0;
288 }
289 errno = EBADF;
290 return -1;
291}
292
293static inline void time_t_to_filetime(time_t t, FILETIME *ft)
294{
295 long long winTime = t * 10000000LL + 116444736000000000LL;
296 ft->dwLowDateTime = winTime;
297 ft->dwHighDateTime = winTime >> 32;
298}
299
300int mingw_utime (const char *file_name, const struct utimbuf *times)
301{
302 FILETIME mft, aft;
303 int fh, rc;
304
305 /* must have write permission */
306 if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0)
307 return -1;
308
309 if (times) {
310 time_t_to_filetime(times->modtime, &mft);
311 time_t_to_filetime(times->actime, &aft);
312 }
313 else {
314 SYSTEMTIME st;
315 GetSystemTime(&st);
316 SystemTimeToFileTime(&st, &aft);
317 mft = aft;
318 }
319 if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
320 errno = EINVAL;
321 rc = -1;
322 } else
323 rc = 0;
324 close(fh);
325 return rc;
326}
327
328static inline void timeval_to_filetime(const struct timeval tv, FILETIME *ft)
329{
330 long long winTime = ((tv.tv_sec * 1000000LL) + tv.tv_usec) * 10LL + 116444736000000000LL;
331 ft->dwLowDateTime = winTime;
332 ft->dwHighDateTime = winTime >> 32;
333}
334
335int utimes(const char *file_name, const struct timeval times[2])
336{
337 FILETIME mft, aft;
338 int fh, rc;
339
340 /* must have write permission */
341 if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0)
342 return -1;
343
344 if (times) {
345 timeval_to_filetime(times[0], &aft);
346 timeval_to_filetime(times[1], &mft);
347 }
348 else {
349 SYSTEMTIME st;
350 GetSystemTime(&st);
351 SystemTimeToFileTime(&st, &aft);
352 mft = aft;
353 }
354 if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
355 errno = EINVAL;
356 rc = -1;
357 } else
358 rc = 0;
359 close(fh);
360 return rc;
361}
362
363unsigned int sleep (unsigned int seconds)
364{
365 Sleep(seconds*1000);
366 return 0;
367}
368
369int mkstemp(char *template)
370{
371 char *filename = mktemp(template);
372 if (filename == NULL)
373 return -1;
374 return open(filename, O_RDWR | O_CREAT, 0600);
375}
376
377/*
378 * This is like mktime, but without normalization of tm_wday and tm_yday.
379 */
380static time_t tm_to_time_t(const struct tm *tm)
381{
382 static const int mdays[] = {
383 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
384 };
385 int year = tm->tm_year - 70;
386 int month = tm->tm_mon;
387 int day = tm->tm_mday;
388
389 if (year < 0 || year > 129) /* algo only works for 1970-2099 */
390 return -1;
391 if (month < 0 || month > 11) /* array bounds */
392 return -1;
393 if (month < 2 || (year + 2) % 4)
394 day--;
395 return (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL +
396 tm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec;
397}
398
399int gettimeofday(struct timeval *tv, void *tz)
400{
401 SYSTEMTIME st;
402 struct tm tm;
403 GetSystemTime(&st);
404 tm.tm_year = st.wYear-1900;
405 tm.tm_mon = st.wMonth-1;
406 tm.tm_mday = st.wDay;
407 tm.tm_hour = st.wHour;
408 tm.tm_min = st.wMinute;
409 tm.tm_sec = st.wSecond;
410 tv->tv_sec = tm_to_time_t(&tm);
411 if (tv->tv_sec < 0)
412 return -1;
413 tv->tv_usec = st.wMilliseconds*1000;
414 return 0;
415}
416
417int pipe(int filedes[2])
418{
419 if (_pipe(filedes, PIPE_BUF, 0) < 0)
420 return -1;
421 return 0;
422}
423
424int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
425{
426 int i, pending;
427
428 if (timeout >= 0) {
429 if (nfds == 0) {
430 Sleep(timeout);
431 return 0;
432 }
433 errno = EINVAL;
434 return -1;
435 }
436
437 /* When there is only one fd to wait for, then we pretend that
438 * input is available and let the actual wait happen when the
439 * caller invokes read().
440 */
441 if (nfds == 1) {
442 if (!(ufds[0].events & POLLIN)) {
443 errno = EINVAL;
444 return -1;
445 }
446 ufds[0].revents = POLLIN;
447 return 0;
448 }
449
450repeat:
451 pending = 0;
452 for (i = 0; i < nfds; i++) {
453 DWORD avail = 0;
454 HANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);
455 if (h == INVALID_HANDLE_VALUE)
456 return -1; /* errno was set */
457
458 if (!(ufds[i].events & POLLIN)) {
459 errno = EINVAL;
460 return -1;
461 }
462
463 /* this emulation works only for pipes */
464 if (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {
465 int err = GetLastError();
466 if (err == ERROR_BROKEN_PIPE) {
467 ufds[i].revents = POLLHUP;
468 pending++;
469 } else {
470 errno = EINVAL;
471 return -1;
472 }
473 } else if (avail) {
474 ufds[i].revents = POLLIN;
475 pending++;
476 } else
477 ufds[i].revents = 0;
478 }
479 if (!pending) {
480 /* The only times that we spin here is when the process
481 * that is connected through the pipes is waiting for
482 * its own input data to become available. But since
483 * the process (pack-objects) is itself CPU intensive,
484 * it will happily pick up the time slice that we are
485 * relinguishing here.
486 */
487 Sleep(0);
488 goto repeat;
489 }
490 return 0;
491}
492
493struct tm *gmtime_r(const time_t *timep, struct tm *result)
494{
495 /* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */
496 memcpy(result, gmtime(timep), sizeof(struct tm));
497 return result;
498}
499
500struct tm *localtime_r(const time_t *timep, struct tm *result)
501{
502 /* localtime() in MSVCRT.DLL is thread-safe, but not reentrant */
503 memcpy(result, localtime(timep), sizeof(struct tm));
504 return result;
505}
506
507#undef getcwd
508char *mingw_getcwd(char *pointer, int len)
509{
510 int i;
511 char *ret = getcwd(pointer, len);
512 if (!ret)
513 return ret;
514 for (i = 0; ret[i]; i++)
515 if (ret[i] == '\\')
516 ret[i] = '/';
517 return ret;
518}
519
520#undef rename
521int mingw_rename(const char *pold, const char *pnew)
522{
523 DWORD attrs;
524
525 /*
526 * Try native rename() first to get errno right.
527 * It is based on MoveFile(), which cannot overwrite existing files.
528 */
529 if (!rename(pold, pnew))
530 return 0;
531 if (errno != EEXIST)
532 return -1;
533 if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
534 return 0;
535 /* TODO: translate more errors */
536 if (GetLastError() == ERROR_ACCESS_DENIED &&
537 (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
538 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
539 errno = EISDIR;
540 return -1;
541 }
542 if ((attrs & FILE_ATTRIBUTE_READONLY) &&
543 SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
544 if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
545 return 0;
546 /* revert file attributes on failure */
547 SetFileAttributes(pnew, attrs);
548 }
549 }
550 errno = EACCES;
551 return -1;
552}
553
554struct passwd *getpwuid(int uid)
555{
556 static char user_name[100];
557 static struct passwd p;
558
559 DWORD len = sizeof(user_name);
560 if (!GetUserName(user_name, &len))
561 return NULL;
562 p.pw_name = user_name;
563 p.pw_gecos = "unknown";
564 p.pw_dir = NULL;
565 return &p;
566}
567
568static HANDLE timer_event;
569static HANDLE timer_thread;
570static int timer_interval;
571static int one_shot;
572static sighandler_t timer_fn = SIG_DFL;
573
574/* The timer works like this:
575 * The thread, ticktack(), is a trivial routine that most of the time
576 * only waits to receive the signal to terminate. The main thread tells
577 * the thread to terminate by setting the timer_event to the signalled
578 * state.
579 * But ticktack() interrupts the wait state after the timer's interval
580 * length to call the signal handler.
581 */
582
583static __stdcall unsigned ticktack(void *dummy UNUSED_PARAM)
584{
585 while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
586 if (timer_fn == SIG_DFL)
587 bb_error_msg_and_die("Alarm");
588 if (timer_fn != SIG_IGN)
589 timer_fn(SIGALRM);
590 if (one_shot)
591 break;
592 }
593 return 0;
594}
595
596static int start_timer_thread(void)
597{
598 timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
599 if (timer_event) {
600 timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
601 if (!timer_thread ) {
602 errno = ENOMEM;
603 return -1;
604 }
605 } else {
606 errno = ENOMEM;
607 return -1;
608 }
609 return 0;
610}
611
612static void stop_timer_thread(void)
613{
614 if (timer_event)
615 SetEvent(timer_event); /* tell thread to terminate */
616 if (timer_thread) {
617 int rc = WaitForSingleObject(timer_thread, 1000);
618 if (rc == WAIT_TIMEOUT)
619 fprintf(stderr, "timer thread did not terminate timely");
620 else if (rc != WAIT_OBJECT_0)
621 fprintf(stderr, "waiting for timer thread failed: %lu",
622 GetLastError());
623 CloseHandle(timer_thread);
624 }
625 if (timer_event)
626 CloseHandle(timer_event);
627 timer_event = NULL;
628 timer_thread = NULL;
629}
630
631static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)
632{
633 return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
634}
635
636int setitimer(int type UNUSED_PARAM, struct itimerval *in, struct itimerval *out)
637{
638 static const struct timeval zero;
639 static int atexit_done;
640
641 if (out != NULL) {
642 errno = EINVAL;
643 return -1;
644 }
645 if (!is_timeval_eq(&in->it_interval, &zero) &&
646 !is_timeval_eq(&in->it_interval, &in->it_value)) {
647 errno = EINVAL;
648 return -1;
649 }
650
651 if (timer_thread)
652 stop_timer_thread();
653
654 if (is_timeval_eq(&in->it_value, &zero) &&
655 is_timeval_eq(&in->it_interval, &zero))
656 return 0;
657
658 timer_interval = in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000;
659 one_shot = is_timeval_eq(&in->it_interval, &zero);
660 if (!atexit_done) {
661 atexit(stop_timer_thread);
662 atexit_done = 1;
663 }
664 return start_timer_thread();
665}
666
667int sigaction(int sig, struct sigaction *in, struct sigaction *out)
668{
669 if (sig != SIGALRM) {
670 errno = EINVAL;
671 return -1;
672 }
673 if (out != NULL) {
674 errno = EINVAL;
675 return -1;
676 }
677
678 timer_fn = in->sa_handler;
679 return 0;
680}
681
682#undef signal
683sighandler_t mingw_signal(int sig, sighandler_t handler)
684{
685 sighandler_t old = timer_fn;
686 if (sig != SIGALRM)
687 return signal(sig, handler);
688 timer_fn = handler;
689 return old;
690}
691
692int link(const char *oldpath, const char *newpath)
693{
694 typedef BOOL WINAPI (*T)(const char*, const char*, LPSECURITY_ATTRIBUTES);
695 static T create_hard_link = NULL;
696 if (!create_hard_link) {
697 create_hard_link = (T) GetProcAddress(
698 GetModuleHandle("kernel32.dll"), "CreateHardLinkA");
699 if (!create_hard_link)
700 create_hard_link = (T)-1;
701 }
702 if (create_hard_link == (T)-1) {
703 errno = ENOSYS;
704 return -1;
705 }
706 if (!create_hard_link(newpath, oldpath, NULL)) {
707 errno = err_win_to_posix(GetLastError());
708 return -1;
709 }
710 return 0;
711}
712
713char *strsep(char **stringp, const char *delim)
714{
715 char *s, *old_stringp;
716 if (!*stringp)
717 return NULL;
718 old_stringp = s = *stringp;
719 while (*s) {
720 if (strchr(delim, *s)) {
721 *s = '\0';
722 *stringp = s+1;
723 return old_stringp;
724 }
725 s++;
726 }
727 *stringp = NULL;
728 return old_stringp;
729}
730
731char *realpath(const char *path, char *resolved_path)
732{
733 /* FIXME: need normalization */
734 return strcpy(resolved_path, path);
735}
736
737const char *get_busybox_exec_path(void)
738{
739 static char path[PATH_MAX] = "";
740
741 if (!*path)
742 GetModuleFileName(NULL, path, PATH_MAX);
743 return path;
744}
745
746#undef mkdir
747int mingw_mkdir(const char *path, int mode UNUSED_PARAM)
748{
749 return mkdir(path);
750}
751
752int fcntl(int fd UNUSED_PARAM, int cmd, ...)
753{
754 /*
755 * F_GETFL needs to be dealt at higher level
756 * Usually it does not matter if the call is
757 * fcntl(fd, F_SETFL, fcntl(fd, F_GETFD) | something)
758 * because F_SETFL is not supported
759 */
760 if (cmd == F_GETFD || cmd == F_SETFD || cmd == F_GETFL)
761 return 0;
762 errno = ENOSYS;
763 return -1;
764}
765
766#undef unlink
767int mingw_unlink(const char *pathname)
768{
769 /* read-only files cannot be removed */
770 chmod(pathname, 0666);
771 return unlink(pathname);
772}
773
774char *strptime(const char *s, const char *format, struct tm *tm)
775{
776 return NULL;
777}
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/process.c b/win32/process.c
new file mode 100644
index 000000000..13bf81797
--- /dev/null
+++ b/win32/process.c
@@ -0,0 +1,286 @@
1#include "libbb.h"
2
3int waitpid(pid_t pid, int *status, unsigned options)
4{
5 /* Windows does not understand parent-child */
6 if (options == 0 && pid != -1)
7 return _cwait(status, pid, 0);
8 errno = EINVAL;
9 return -1;
10}
11
12const char *
13next_path_sep(const char *path)
14{
15 static const char *from = NULL, *to;
16 static int has_semicolon;
17 int len = strlen(path);
18
19 if (!from || !(path >= from && path+len <= to)) {
20 from = path;
21 to = from+len;
22 has_semicolon = strchr(path, ';') != NULL;
23 }
24
25 /* Semicolons take precedence, it's Windows PATH */
26 if (has_semicolon)
27 return strchr(path, ';');
28 /* PATH=C:, not really a separator */
29 return strchr(has_dos_drive_prefix(path) ? path+2 : path, ':');
30}
31
32static const char *
33parse_interpreter(const char *cmd)
34{
35 static char buf[100];
36 char *p, *opt;
37 int n, fd;
38
39 /* don't even try a .exe */
40 n = strlen(cmd);
41 if (n >= 4 &&
42 (!strcasecmp(cmd+n-4, ".exe") ||
43 !strcasecmp(cmd+n-4, ".com")))
44 return NULL;
45
46 fd = open(cmd, O_RDONLY);
47 if (fd < 0)
48 return NULL;
49 n = read(fd, buf, sizeof(buf)-1);
50 close(fd);
51 if (n < 4) /* at least '#!/x' and not error */
52 return NULL;
53
54 if (buf[0] != '#' || buf[1] != '!')
55 return NULL;
56 buf[n] = '\0';
57 p = strchr(buf, '\n');
58 if (!p)
59 return NULL;
60
61 *p = '\0';
62 if (!(p = strrchr(buf+2, '/')) && !(p = strrchr(buf+2, '\\')))
63 return NULL;
64 /* strip options */
65 if ((opt = strchr(p+1, ' ')))
66 *opt = '\0';
67 return p+1;
68}
69
70/*
71 * See http://msdn2.microsoft.com/en-us/library/17w5ykft(vs.71).aspx
72 * (Parsing C++ Command-Line Arguments)
73 */
74static char *
75quote_arg(const char *arg)
76{
77 /* count chars to quote */
78 int len = 0, n = 0;
79 int force_quotes = 0;
80 char *q, *d;
81 const char *p = arg;
82 if (!*p) force_quotes = 1;
83 while (*p) {
84 if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'')
85 force_quotes = 1;
86 else if (*p == '"')
87 n++;
88 else if (*p == '\\') {
89 int count = 0;
90 while (*p == '\\') {
91 count++;
92 p++;
93 len++;
94 }
95 if (*p == '"')
96 n += count*2 + 1;
97 continue;
98 }
99 len++;
100 p++;
101 }
102 if (!force_quotes && n == 0)
103 return (char*)arg;
104
105 /* insert \ where necessary */
106 d = q = xmalloc(len+n+3);
107 *d++ = '"';
108 while (*arg) {
109 if (*arg == '"')
110 *d++ = '\\';
111 else if (*arg == '\\') {
112 int count = 0;
113 while (*arg == '\\') {
114 count++;
115 *d++ = *arg++;
116 }
117 if (*arg == '"') {
118 while (count-- > 0)
119 *d++ = '\\';
120 *d++ = '\\';
121 }
122 }
123 *d++ = *arg++;
124 }
125 *d++ = '"';
126 *d++ = 0;
127 return q;
128}
129
130static pid_t
131spawnveq(int mode, const char *path, const char *const *argv, const char *const *env)
132{
133 char **new_argv;
134 int i, argc = 0;
135 pid_t ret;
136
137 if (!argv) {
138 const char *empty_argv[] = { path, NULL };
139 return spawnve(mode, path, empty_argv, env);
140 }
141
142
143 while (argv[argc])
144 argc++;
145
146 new_argv = malloc(sizeof(*argv)*(argc+1));
147 for (i = 0;i < argc;i++)
148 new_argv[i] = quote_arg(argv[i]);
149 new_argv[argc] = NULL;
150 ret = spawnve(mode, path, (const char *const *)new_argv, env);
151 for (i = 0;i < argc;i++)
152 if (new_argv[i] != argv[i])
153 free(new_argv[i]);
154 free(new_argv);
155 return ret;
156}
157
158pid_t
159mingw_spawn_applet(int mode,
160 const char *applet,
161 const char *const *argv,
162 const char *const *envp)
163{
164 char **env = copy_environ(envp);
165 char path[MAX_PATH+20];
166 int ret;
167
168 sprintf(path, "BUSYBOX_APPLET_NAME=%s", applet);
169 env = env_setenv(env, path);
170 ret = spawnveq(mode, get_busybox_exec_path(), argv, (const char *const *)env);
171 free_environ(env);
172 return ret;
173}
174
175static pid_t
176mingw_spawn_interpreter(int mode, const char *prog, const char *const *argv, const char *const *envp)
177{
178 int ret;
179 const char *interpr = parse_interpreter(prog);
180
181 if (!interpr)
182 return spawnveq(mode, prog, argv, envp);
183
184 if (ENABLE_FEATURE_PREFER_APPLETS && !strcmp(interpr, "sh")) {
185 const char **new_argv;
186 int argc = 0;
187
188 while (argv[argc])
189 argc++;
190 new_argv = malloc(sizeof(*argv)*(argc+2));
191 memcpy(new_argv+1, argv, sizeof(*argv)*(argc+1));
192 new_argv[0] = prog; /* pass absolute path */
193 ret = mingw_spawn_applet(mode, "sh", new_argv, envp);
194 free(new_argv);
195 }
196 else {
197 char *path = xstrdup(getenv("PATH"));
198 char *tmp = path;
199 char *iprog = find_execable(interpr, &tmp);
200 free(path);
201 if (!prog) {
202 errno = ENOENT;
203 return -1;
204 }
205 ret = spawnveq(mode, iprog, argv, envp);
206 free(iprog);
207 }
208 return ret;
209}
210
211pid_t
212mingw_spawn_1(int mode, const char *cmd, const char *const *argv, const char *const *envp)
213{
214 int ret;
215
216 if (ENABLE_FEATURE_PREFER_APPLETS &&
217 find_applet_by_name(cmd) >= 0)
218 return mingw_spawn_applet(mode, cmd, argv++, envp);
219 else if (is_absolute_path(cmd))
220 return mingw_spawn_interpreter(mode, cmd, argv, envp);
221 else {
222 char *tmp, *path = getenv("PATH");
223 char *prog;
224
225 if (!path) {
226 errno = ENOENT;
227 return -1;
228 }
229
230 /* exists_execable() does not return new file name */
231 tmp = path = xstrdup(path);
232 prog = find_execable(cmd, &tmp);
233 free(path);
234 if (!prog) {
235 errno = ENOENT;
236 return -1;
237 }
238 ret = mingw_spawn_interpreter(mode, prog, argv, envp);
239 free(prog);
240 }
241 return ret;
242}
243
244pid_t
245mingw_spawn(char **argv)
246{
247 return mingw_spawn_1(P_NOWAIT, argv[0], (const char *const *)(argv+1), (const char *const *)environ);
248}
249
250int
251mingw_execvp(const char *cmd, const char *const *argv)
252{
253 int ret = (int)mingw_spawn_1(P_WAIT, cmd, argv, (const char *const *)environ);
254 if (ret != -1)
255 exit(ret);
256 return ret;
257}
258
259int
260mingw_execve(const char *cmd, const char *const *argv, const char *const *envp)
261{
262 int ret;
263 int mode = P_WAIT;
264
265 if (ENABLE_FEATURE_PREFER_APPLETS &&
266 find_applet_by_name(cmd) >= 0)
267 ret = mingw_spawn_applet(mode, cmd, argv, envp);
268 /*
269 * execve(bb_busybox_exec_path, argv, envp) won't work
270 * because argv[0] will be replaced to bb_busybox_exec_path
271 * by MSVC runtime
272 */
273 else if (argv && cmd != argv[0] && cmd == bb_busybox_exec_path)
274 ret = mingw_spawn_applet(mode, argv[0], argv, envp);
275 else
276 ret = mingw_spawn_interpreter(mode, cmd, argv, envp);
277 if (ret != -1)
278 exit(ret);
279 return ret;
280}
281
282int
283mingw_execv(const char *cmd, const char *const *argv)
284{
285 return mingw_execve(cmd, argv, (const char *const *)environ);
286}
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..e69de29bb
--- /dev/null
+++ b/win32/sys/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/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..6d85ff98e
--- /dev/null
+++ b/win32/termios.c
@@ -0,0 +1,36 @@
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 UNUSED_PARAM)
14{
15 static int initialized = 0;
16 HANDLE cin = GetStdHandle(STD_INPUT_HANDLE);
17 INPUT_RECORD record;
18 DWORD nevent_out;
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 if (!initialized) {
25 SetConsoleMode(cin, ENABLE_ECHO_INPUT);
26 initialized = 1;
27 }
28
29 while (1) {
30 if (!ReadConsoleInput(cin, &record, 1, &nevent_out))
31 return -1;
32 if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown)
33 continue;
34 return record.Event.KeyEvent.uChar.AsciiChar;
35 }
36}
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/winansi.c b/win32/winansi.c
new file mode 100644
index 000000000..e2e7010fb
--- /dev/null
+++ b/win32/winansi.c
@@ -0,0 +1,358 @@
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
85 if (!console)
86 return;
87
88 GetConsoleScreenBufferInfo(console, &sbi);
89 FillConsoleOutputCharacterA(console, ' ',
90 sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition,
91 NULL);
92}
93
94
95static const char *set_attr(const char *str)
96{
97 const char *func;
98 size_t len = strspn(str, "0123456789;");
99 func = str + len;
100
101 switch (*func) {
102 case 'm':
103 do {
104 long val = strtol(str, (char **)&str, 10);
105 switch (val) {
106 case 0: /* reset */
107 attr = plain_attr;
108 negative = 0;
109 break;
110 case 1: /* bold */
111 attr |= FOREGROUND_INTENSITY;
112 break;
113 case 2: /* faint */
114 case 22: /* normal */
115 attr &= ~FOREGROUND_INTENSITY;
116 break;
117 case 3: /* italic */
118 /* Unsupported */
119 break;
120 case 4: /* underline */
121 case 21: /* double underline */
122 /* Wikipedia says this flag does nothing */
123 /* Furthermore, mingw doesn't define this flag
124 attr |= COMMON_LVB_UNDERSCORE; */
125 break;
126 case 24: /* no underline */
127 /* attr &= ~COMMON_LVB_UNDERSCORE; */
128 break;
129 case 5: /* slow blink */
130 case 6: /* fast blink */
131 /* We don't have blink, but we do have
132 background intensity */
133 attr |= BACKGROUND_INTENSITY;
134 break;
135 case 25: /* no blink */
136 attr &= ~BACKGROUND_INTENSITY;
137 break;
138 case 7: /* negative */
139 negative = 1;
140 break;
141 case 27: /* positive */
142 negative = 0;
143 break;
144 case 8: /* conceal */
145 case 28: /* reveal */
146 /* Unsupported */
147 break;
148 case 30: /* Black */
149 attr &= ~FOREGROUND_ALL;
150 break;
151 case 31: /* Red */
152 attr &= ~FOREGROUND_ALL;
153 attr |= FOREGROUND_RED;
154 break;
155 case 32: /* Green */
156 attr &= ~FOREGROUND_ALL;
157 attr |= FOREGROUND_GREEN;
158 break;
159 case 33: /* Yellow */
160 attr &= ~FOREGROUND_ALL;
161 attr |= FOREGROUND_RED | FOREGROUND_GREEN;
162 break;
163 case 34: /* Blue */
164 attr &= ~FOREGROUND_ALL;
165 attr |= FOREGROUND_BLUE;
166 break;
167 case 35: /* Magenta */
168 attr &= ~FOREGROUND_ALL;
169 attr |= FOREGROUND_RED | FOREGROUND_BLUE;
170 break;
171 case 36: /* Cyan */
172 attr &= ~FOREGROUND_ALL;
173 attr |= FOREGROUND_GREEN | FOREGROUND_BLUE;
174 break;
175 case 37: /* White */
176 attr |= FOREGROUND_RED |
177 FOREGROUND_GREEN |
178 FOREGROUND_BLUE;
179 break;
180 case 38: /* Unknown */
181 break;
182 case 39: /* reset */
183 attr &= ~FOREGROUND_ALL;
184 attr |= (plain_attr & FOREGROUND_ALL);
185 break;
186 case 40: /* Black */
187 attr &= ~BACKGROUND_ALL;
188 break;
189 case 41: /* Red */
190 attr &= ~BACKGROUND_ALL;
191 attr |= BACKGROUND_RED;
192 break;
193 case 42: /* Green */
194 attr &= ~BACKGROUND_ALL;
195 attr |= BACKGROUND_GREEN;
196 break;
197 case 43: /* Yellow */
198 attr &= ~BACKGROUND_ALL;
199 attr |= BACKGROUND_RED | BACKGROUND_GREEN;
200 break;
201 case 44: /* Blue */
202 attr &= ~BACKGROUND_ALL;
203 attr |= BACKGROUND_BLUE;
204 break;
205 case 45: /* Magenta */
206 attr &= ~BACKGROUND_ALL;
207 attr |= BACKGROUND_RED | BACKGROUND_BLUE;
208 break;
209 case 46: /* Cyan */
210 attr &= ~BACKGROUND_ALL;
211 attr |= BACKGROUND_GREEN | BACKGROUND_BLUE;
212 break;
213 case 47: /* White */
214 attr |= BACKGROUND_RED |
215 BACKGROUND_GREEN |
216 BACKGROUND_BLUE;
217 break;
218 case 48: /* Unknown */
219 break;
220 case 49: /* reset */
221 attr &= ~BACKGROUND_ALL;
222 attr |= (plain_attr & BACKGROUND_ALL);
223 break;
224 default:
225 /* Unsupported code */
226 break;
227 }
228 str++;
229 } while (*(str-1) == ';');
230
231 set_console_attr();
232 break;
233 case 'K':
234 erase_in_line();
235 break;
236 default:
237 /* Unsupported code */
238 break;
239 }
240
241 return func + 1;
242}
243
244static int ansi_emulate(const char *str, FILE *stream)
245{
246 int rv = 0;
247 const char *pos = str;
248
249 while (*pos) {
250 pos = strstr(str, "\033[");
251 if (pos) {
252 size_t len = pos - str;
253
254 if (len) {
255 size_t out_len = fwrite(str, 1, len, stream);
256 rv += out_len;
257 if (out_len < len)
258 return rv;
259 }
260
261 str = pos + 2;
262 rv += 2;
263
264 fflush(stream);
265
266 pos = set_attr(str);
267 rv += pos - str;
268 str = pos;
269 } else {
270 rv += strlen(str);
271 fputs(str, stream);
272 return rv;
273 }
274 }
275 return rv;
276}
277
278int winansi_fputs(const char *str, FILE *stream)
279{
280 int rv;
281
282 if (!isatty(fileno(stream)))
283 return fputs(str, stream);
284
285 init();
286
287 if (!console)
288 return fputs(str, stream);
289
290 rv = ansi_emulate(str, stream);
291
292 if (rv >= 0)
293 return 0;
294 else
295 return EOF;
296}
297
298static int winansi_vfprintf(FILE *stream, const char *format, va_list list)
299{
300 int len, rv;
301 char small_buf[256];
302 char *buf = small_buf;
303 va_list cp;
304
305 if (!isatty(fileno(stream)))
306 goto abort;
307
308 init();
309
310 if (!console)
311 goto abort;
312
313 va_copy(cp, list);
314 len = vsnprintf(small_buf, sizeof(small_buf), format, cp);
315 va_end(cp);
316
317 if (len > sizeof(small_buf) - 1) {
318 buf = malloc(len + 1);
319 if (!buf)
320 goto abort;
321
322 len = vsnprintf(buf, len + 1, format, list);
323 }
324
325 rv = ansi_emulate(buf, stream);
326
327 if (buf != small_buf)
328 free(buf);
329 return rv;
330
331abort:
332 rv = vfprintf(stream, format, list);
333 return rv;
334}
335
336int winansi_fprintf(FILE *stream, const char *format, ...)
337{
338 va_list list;
339 int rv;
340
341 va_start(list, format);
342 rv = winansi_vfprintf(stream, format, list);
343 va_end(list);
344
345 return rv;
346}
347
348int winansi_printf(const char *format, ...)
349{
350 va_list list;
351 int rv;
352
353 va_start(list, format);
354 rv = winansi_vfprintf(stdout, format, list);
355 va_end(list);
356
357 return rv;
358}