aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2019-01-10 08:38:15 +0000
committerRon Yorston <rmy@pobox.com>2019-01-10 08:38:15 +0000
commitf99a280743e877c14ee90a3f9e93a34ca3476a27 (patch)
tree60ca3d17596e190c8c7cbca587168946598bee8a
parent40d5dd07ea1f290eaed30a03fd598e33a8eaf495 (diff)
parent6ca8e347fed8c24655df692f22694baf7c572770 (diff)
downloadbusybox-w32-f99a280743e877c14ee90a3f9e93a34ca3476a27.tar.gz
busybox-w32-f99a280743e877c14ee90a3f9e93a34ca3476a27.tar.bz2
busybox-w32-f99a280743e877c14ee90a3f9e93a34ca3476a27.zip
Merge branch 'busybox' into merge
-rw-r--r--Config.in2
-rw-r--r--Makefile2
-rw-r--r--archival/bbunzip.c12
-rw-r--r--archival/bzip2.c2
-rw-r--r--archival/cpio.c2
-rw-r--r--archival/dpkg.c2
-rw-r--r--archival/dpkg_deb.c2
-rw-r--r--archival/gzip.c2
-rw-r--r--archival/libarchive/lzo1x_9x.c2
-rw-r--r--archival/lzop.c2
-rw-r--r--archival/rpm.c4
-rw-r--r--archival/tar.c2
-rw-r--r--archival/unzip.c2
-rw-r--r--console-tools/dumpkmap.c2
-rw-r--r--console-tools/fgconsole.c2
-rw-r--r--console-tools/kbd_mode.c2
-rw-r--r--console-tools/loadfont.c4
-rw-r--r--console-tools/loadkmap.c2
-rw-r--r--console-tools/openvt.c2
-rw-r--r--console-tools/reset.c2
-rw-r--r--console-tools/resize.c2
-rw-r--r--console-tools/setconsole.c2
-rw-r--r--console-tools/setkeycodes.c2
-rw-r--r--coreutils/basename.c2
-rw-r--r--coreutils/chgrp.c2
-rw-r--r--coreutils/chmod.c2
-rw-r--r--coreutils/chown.c2
-rw-r--r--coreutils/cksum.c2
-rw-r--r--coreutils/comm.c2
-rw-r--r--coreutils/cp.c2
-rw-r--r--coreutils/cut.c2
-rw-r--r--coreutils/date.c6
-rw-r--r--coreutils/dd.c2
-rw-r--r--coreutils/df.c2
-rw-r--r--coreutils/dirname.c2
-rw-r--r--coreutils/dos2unix.c4
-rw-r--r--coreutils/du.c6
-rw-r--r--coreutils/echo.c4
-rw-r--r--coreutils/env.c2
-rw-r--r--coreutils/expand.c4
-rw-r--r--coreutils/expr.c2
-rw-r--r--coreutils/factor.c2
-rw-r--r--coreutils/fsync.c2
-rw-r--r--coreutils/head.c2
-rw-r--r--coreutils/hostid.c2
-rw-r--r--coreutils/id.c4
-rw-r--r--coreutils/link.c2
-rw-r--r--coreutils/ln.c2
-rw-r--r--coreutils/logname.c2
-rw-r--r--coreutils/ls.c4
-rw-r--r--coreutils/md5_sha1_sum.c10
-rw-r--r--coreutils/mkdir.c2
-rw-r--r--coreutils/mkfifo.c2
-rw-r--r--coreutils/mknod.c2
-rw-r--r--coreutils/mktemp.c2
-rw-r--r--coreutils/mv.c2
-rw-r--r--coreutils/nice.c2
-rw-r--r--coreutils/nl.c2
-rw-r--r--coreutils/nproc.c2
-rw-r--r--coreutils/paste.c2
-rw-r--r--coreutils/printenv.c2
-rw-r--r--coreutils/printf.c2
-rw-r--r--coreutils/pwd.c2
-rw-r--r--coreutils/readlink.c2
-rw-r--r--coreutils/realpath.c2
-rw-r--r--coreutils/rm.c2
-rw-r--r--coreutils/rmdir.c2
-rw-r--r--coreutils/seq.c2
-rw-r--r--coreutils/shred.c2
-rw-r--r--coreutils/sleep.c7
-rw-r--r--coreutils/sort.c2
-rw-r--r--coreutils/split.c2
-rw-r--r--coreutils/stat.c2
-rw-r--r--coreutils/stty.c2
-rw-r--r--coreutils/sum.c2
-rw-r--r--coreutils/sync.c2
-rw-r--r--coreutils/tac.c2
-rw-r--r--coreutils/tail.c2
-rw-r--r--coreutils/tee.c2
-rw-r--r--coreutils/test.c2
-rw-r--r--coreutils/timeout.c2
-rw-r--r--coreutils/touch.c2
-rw-r--r--coreutils/tr.c2
-rw-r--r--coreutils/truncate.c2
-rw-r--r--coreutils/tty.c2
-rw-r--r--coreutils/uname.c4
-rw-r--r--coreutils/uniq.c2
-rw-r--r--coreutils/unlink.c2
-rw-r--r--coreutils/usleep.c2
-rw-r--r--coreutils/uudecode.c4
-rw-r--r--coreutils/uuencode.c2
-rw-r--r--coreutils/wc.c2
-rw-r--r--coreutils/who.c6
-rw-r--r--coreutils/whoami.c2
-rw-r--r--coreutils/yes.c2
-rw-r--r--debianutils/pipe_progress.c2
-rw-r--r--debianutils/run_parts.c2
-rw-r--r--debianutils/which.c2
-rw-r--r--e2fsprogs/chattr.c2
-rw-r--r--e2fsprogs/fsck.c2
-rw-r--r--e2fsprogs/lsattr.c2
-rw-r--r--editors/awk.c2
-rw-r--r--editors/cmp.c2
-rw-r--r--editors/ed.c2
-rw-r--r--editors/patch.c2
-rw-r--r--editors/patch_toybox.c2
-rw-r--r--editors/vi.c2
-rw-r--r--findutils/find.c6
-rw-r--r--findutils/grep.c6
-rw-r--r--findutils/xargs.c2
-rw-r--r--include/libbb.h11
-rw-r--r--init/bootchartd.c2
-rw-r--r--init/halt.c6
-rw-r--r--init/init.c2
-rw-r--r--klibc-utils/nuke.c2
-rw-r--r--klibc-utils/resume.c2
-rw-r--r--klibc-utils/run-init.c2
-rw-r--r--libbb/appletlib.c8
-rw-r--r--libbb/lineedit.c32
-rw-r--r--libbb/procps.c8
-rw-r--r--libbb/signals.c10
-rw-r--r--loginutils/add-remove-shell.c4
-rw-r--r--loginutils/addgroup.c2
-rw-r--r--loginutils/deluser.c4
-rw-r--r--loginutils/passwd.c8
-rw-r--r--mailutils/makemime.c2
-rwxr-xr-xmake_single_applets.sh12
-rw-r--r--miscutils/adjtimex.c2
-rw-r--r--miscutils/bc.c7405
-rw-r--r--miscutils/beep.c2
-rw-r--r--miscutils/chat.c2
-rw-r--r--miscutils/crond.c2
-rw-r--r--miscutils/crontab.c2
-rw-r--r--miscutils/dc.c118
-rw-r--r--miscutils/devfsd.c2
-rw-r--r--miscutils/fbsplash.c2
-rw-r--r--miscutils/flash_eraseall.c2
-rw-r--r--miscutils/flashcp.c2
-rw-r--r--miscutils/hdparm.c2
-rw-r--r--miscutils/hexedit.c2
-rw-r--r--miscutils/i2c_tools.c8
-rw-r--r--miscutils/inotifyd.c2
-rw-r--r--miscutils/less.c2
-rw-r--r--miscutils/lsscsi.c2
-rw-r--r--miscutils/makedevs.c2
-rw-r--r--miscutils/man.c2
-rw-r--r--miscutils/microcom.c2
-rw-r--r--miscutils/mt.c2
-rw-r--r--miscutils/nandwrite.c4
-rw-r--r--miscutils/partprobe.c2
-rw-r--r--miscutils/raidautorun.c2
-rw-r--r--miscutils/readahead.c2
-rw-r--r--miscutils/rfkill.c2
-rw-r--r--miscutils/runlevel.c4
-rw-r--r--miscutils/setfattr.c2
-rw-r--r--miscutils/setserial.c2
-rw-r--r--miscutils/strings.c2
-rw-r--r--miscutils/time.c2
-rw-r--r--miscutils/ttysize.c2
-rw-r--r--miscutils/ubi_tools.c12
-rw-r--r--miscutils/ubirename.c2
-rw-r--r--miscutils/volname.c2
-rw-r--r--miscutils/watchdog.c2
-rw-r--r--modutils/depmod.c2
-rw-r--r--modutils/lsmod.c2
-rw-r--r--modutils/modinfo.c2
-rw-r--r--modutils/modprobe.c2
-rw-r--r--modutils/rmmod.c2
-rw-r--r--networking/Config.src11
-rw-r--r--networking/arp.c2
-rw-r--r--networking/arping.c2
-rw-r--r--networking/ether-wake.c2
-rw-r--r--networking/ftpgetput.c4
-rw-r--r--networking/hostname.c2
-rw-r--r--networking/ifplugd.c2
-rw-r--r--networking/ifupdown.c4
-rw-r--r--networking/inetd.c2
-rw-r--r--networking/ip.c4
-rw-r--r--networking/ipcalc.c2
-rw-r--r--networking/isrv_identd.c2
-rw-r--r--networking/libiproute/ipaddress.c4
-rw-r--r--networking/nbd-client.c8
-rw-r--r--networking/nslookup.c14
-rw-r--r--networking/ntpd.c2
-rw-r--r--networking/ping.c4
-rw-r--r--networking/pscan.c2
-rw-r--r--networking/route.c2
-rw-r--r--networking/slattach.c2
-rw-r--r--networking/ssl_client.c2
-rw-r--r--networking/tc.c2
-rw-r--r--networking/tcpudp.c2
-rw-r--r--networking/telnet.c205
-rw-r--r--networking/telnetd.c18
-rw-r--r--networking/tftp.c5
-rw-r--r--networking/tls.c79
-rw-r--r--networking/tls_aesgcm.c85
-rw-r--r--networking/tls_pstm.c109
-rw-r--r--networking/tls_pstm.h86
-rw-r--r--networking/tls_pstm_montgomery_reduce.c2
-rw-r--r--networking/tls_pstm_mul_comba.c2
-rw-r--r--networking/tls_pstm_sqr_comba.c2
-rw-r--r--networking/tls_rsa.c4
-rw-r--r--networking/traceroute.c2
-rw-r--r--networking/tunctl.c2
-rw-r--r--networking/udhcp/Config.src8
-rw-r--r--networking/udhcp/common.c33
-rw-r--r--networking/udhcp/common.h6
-rw-r--r--networking/udhcp/d6_dhcpc.c2
-rw-r--r--networking/udhcp/dhcpc.c8
-rw-r--r--networking/udhcp/dhcpd.c8
-rw-r--r--networking/vconfig.c2
-rw-r--r--networking/wget.c64
-rw-r--r--networking/whois.c2
-rw-r--r--networking/zcip.c2
-rw-r--r--printutils/lpd.c2
-rw-r--r--printutils/lpr.c4
-rw-r--r--procps/free.c2
-rw-r--r--procps/iostat.c2
-rw-r--r--procps/kill.c2
-rw-r--r--procps/lsof.c2
-rw-r--r--procps/mpstat.c2
-rw-r--r--procps/nmeter.c2
-rw-r--r--procps/pgrep.c4
-rw-r--r--procps/pidof.c2
-rw-r--r--procps/pmap.c8
-rw-r--r--procps/powertop.c2
-rw-r--r--procps/pstree.c2
-rw-r--r--procps/pwdx.c2
-rw-r--r--procps/sysctl.c2
-rw-r--r--procps/top.c2
-rw-r--r--procps/uptime.c2
-rw-r--r--procps/watch.c2
-rw-r--r--runit/chpst.c8
-rw-r--r--runit/runsv.c2
-rw-r--r--runit/runsvdir.c2
-rw-r--r--runit/sv.c6
-rw-r--r--runit/svlogd.c2
-rw-r--r--scripts/basic/split-include.c3
-rw-r--r--scripts/kconfig/conf.c6
-rw-r--r--scripts/kconfig/lxdialog/lxdialog.c2
-rw-r--r--scripts/kconfig/mconf.c7
-rw-r--r--shell/ash.c4
-rw-r--r--shell/cttyhack.c2
-rw-r--r--shell/hush.c6
-rwxr-xr-xsize_single_applets.sh14
-rw-r--r--sysklogd/klogd.c2
-rw-r--r--sysklogd/logger.c2
-rw-r--r--sysklogd/logread.c2
-rw-r--r--sysklogd/syslogd.c2
-rwxr-xr-xtestsuite/bc.tests314
-rw-r--r--testsuite/bc_add.bc26
-rw-r--r--testsuite/bc_add_results.txt38
-rw-r--r--testsuite/bc_arctangent.bc26
-rw-r--r--testsuite/bc_arctangent_results.txt25
-rw-r--r--testsuite/bc_array.bc35
-rw-r--r--testsuite/bc_array_results.txt426
-rw-r--r--testsuite/bc_arrays.bc10
-rw-r--r--testsuite/bc_arrays_results.txt3
-rw-r--r--testsuite/bc_bessel.bc844
-rw-r--r--testsuite/bc_bessel_results.txt843
-rw-r--r--testsuite/bc_boolean.bc181
-rw-r--r--testsuite/bc_boolean_results.txt181
-rw-r--r--testsuite/bc_cosine.bc44
-rw-r--r--testsuite/bc_cosine_results.txt41
-rw-r--r--testsuite/bc_decimal.bc36
-rw-r--r--testsuite/bc_decimal_results.txt51
-rw-r--r--testsuite/bc_divide.bc31
-rw-r--r--testsuite/bc_divide_results.txt31
-rw-r--r--testsuite/bc_exponent.bc22
-rw-r--r--testsuite/bc_exponent_results.txt25
-rw-r--r--testsuite/bc_log.bc22
-rw-r--r--testsuite/bc_log_results.txt22
-rw-r--r--testsuite/bc_misc.bc13
-rw-r--r--testsuite/bc_misc1.bc74
-rw-r--r--testsuite/bc_misc1_results.txt57
-rw-r--r--testsuite/bc_misc2.bc44
-rw-r--r--testsuite/bc_misc2_results.txt20
-rw-r--r--testsuite/bc_misc_results.txt4
-rw-r--r--testsuite/bc_modulus.bc70
-rw-r--r--testsuite/bc_modulus_results.txt69
-rw-r--r--testsuite/bc_multiply.bc42
-rw-r--r--testsuite/bc_multiply_results.txt43
-rw-r--r--testsuite/bc_numbers1.bc23
-rw-r--r--testsuite/bc_numbers1_results.txt17
-rw-r--r--testsuite/bc_numbers2.bc18
-rw-r--r--testsuite/bc_numbers2_results.txt50
-rw-r--r--testsuite/bc_pi.bc4
-rw-r--r--testsuite/bc_pi_results.txt135
-rw-r--r--testsuite/bc_power.bc44
-rw-r--r--testsuite/bc_power_results.txt73
-rw-r--r--testsuite/bc_sine.bc207
-rw-r--r--testsuite/bc_sine_results.txt204
-rw-r--r--testsuite/bc_sqrt.bc18
-rw-r--r--testsuite/bc_sqrt_results.txt16
-rw-r--r--testsuite/bc_strings.bc12
-rw-r--r--testsuite/bc_strings_results.txt5
-rw-r--r--testsuite/bc_subtract.bc32
-rw-r--r--testsuite/bc_subtract_results.txt36
-rw-r--r--testsuite/bc_vars.bc7
-rw-r--r--testsuite/bc_vars_results.txt12
-rwxr-xr-xtestsuite/dc.tests78
-rw-r--r--testsuite/dc_add.dc33
-rw-r--r--testsuite/dc_add_results.txt45
-rw-r--r--testsuite/dc_boolean.dc27
-rw-r--r--testsuite/dc_boolean_results.txt27
-rw-r--r--testsuite/dc_decimal.dc36
-rw-r--r--testsuite/dc_decimal_results.txt51
-rw-r--r--testsuite/dc_divide.dc33
-rw-r--r--testsuite/dc_divide_results.txt32
-rw-r--r--testsuite/dc_divmod.dc64
-rw-r--r--testsuite/dc_divmod_results.txt126
-rw-r--r--testsuite/dc_misc.dc1
-rw-r--r--testsuite/dc_misc_results.txt20
-rw-r--r--testsuite/dc_modexp.dc103
-rw-r--r--testsuite/dc_modexp_results.txt103
-rw-r--r--testsuite/dc_modulus.dc70
-rw-r--r--testsuite/dc_modulus_results.txt68
-rw-r--r--testsuite/dc_multiply.dc42
-rw-r--r--testsuite/dc_multiply_results.txt43
-rw-r--r--testsuite/dc_power.dc45
-rw-r--r--testsuite/dc_power_results.txt73
-rw-r--r--testsuite/dc_sqrt.dc14
-rw-r--r--testsuite/dc_sqrt_results.txt13
-rw-r--r--testsuite/dc_strings.dc37
-rw-r--r--testsuite/dc_strings_results.txt36
-rw-r--r--testsuite/dc_subtract.dc33
-rw-r--r--testsuite/dc_subtract_results.txt37
-rw-r--r--testsuite/dcx_vars.dc2
-rw-r--r--testsuite/dcx_vars_results.txt6
-rwxr-xr-xtestsuite/head.tests2
-rwxr-xr-xtestsuite/unzip.tests4
-rw-r--r--util-linux/acpid.c2
-rw-r--r--util-linux/blkdiscard.c2
-rw-r--r--util-linux/blkid.c2
-rw-r--r--util-linux/blockdev.c2
-rw-r--r--util-linux/cal.c2
-rw-r--r--util-linux/chrt.c2
-rw-r--r--util-linux/dmesg.c2
-rw-r--r--util-linux/eject.c2
-rw-r--r--util-linux/fallocate.c2
-rw-r--r--util-linux/fbset.c2
-rw-r--r--util-linux/fdformat.c2
-rw-r--r--util-linux/fdisk.c2
-rw-r--r--util-linux/findfs.c2
-rw-r--r--util-linux/flock.c2
-rw-r--r--util-linux/freeramdisk.c4
-rw-r--r--util-linux/fsck_minix.c2
-rw-r--r--util-linux/fsfreeze.c2
-rw-r--r--util-linux/fstrim.c2
-rw-r--r--util-linux/getopt.c2
-rw-r--r--util-linux/hexdump.c4
-rw-r--r--util-linux/ionice.c2
-rw-r--r--util-linux/ipcrm.c2
-rw-r--r--util-linux/last.c2
-rw-r--r--util-linux/losetup.c2
-rw-r--r--util-linux/lspci.c2
-rw-r--r--util-linux/lsusb.c2
-rw-r--r--util-linux/mdev.c14
-rw-r--r--util-linux/mesg.c2
-rw-r--r--util-linux/mkfs_ext2.c4
-rw-r--r--util-linux/mkfs_minix.c2
-rw-r--r--util-linux/mkfs_vfat.c4
-rw-r--r--util-linux/mkswap.c2
-rw-r--r--util-linux/more.c2
-rw-r--r--util-linux/mount.c2
-rw-r--r--util-linux/mountpoint.c2
-rw-r--r--util-linux/nsenter.c2
-rw-r--r--util-linux/pivot_root.c2
-rw-r--r--util-linux/rdate.c2
-rw-r--r--util-linux/rdev.c2
-rw-r--r--util-linux/readprofile.c2
-rw-r--r--util-linux/renice.c2
-rw-r--r--util-linux/rev.c2
-rw-r--r--util-linux/rtcwake.c2
-rw-r--r--util-linux/script.c2
-rw-r--r--util-linux/scriptreplay.c2
-rw-r--r--util-linux/setarch.c6
-rw-r--r--util-linux/setpriv.c2
-rw-r--r--util-linux/setsid.c2
-rw-r--r--util-linux/swaponoff.c4
-rw-r--r--util-linux/switch_root.c2
-rw-r--r--util-linux/taskset.c2
-rw-r--r--util-linux/uevent.c2
-rw-r--r--util-linux/umount.c2
-rw-r--r--util-linux/unshare.c2
-rw-r--r--util-linux/wall.c2
386 files changed, 14308 insertions, 714 deletions
diff --git a/Config.in b/Config.in
index a92360240..5bd98aa23 100644
--- a/Config.in
+++ b/Config.in
@@ -26,7 +26,7 @@ endchoice
26menu "Settings" 26menu "Settings"
27 27
28config DESKTOP 28config DESKTOP
29 bool "Enable compatibility for full-blown desktop systems" 29 bool "Enable compatibility for full-blown desktop systems (8kb)"
30 default y 30 default y
31 help 31 help
32 Enable applet options and features which are not essential. 32 Enable applet options and features which are not essential.
diff --git a/Makefile b/Makefile
index d6e84984e..cb1a932b5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
1VERSION = 1 1VERSION = 1
2PATCHLEVEL = 30 2PATCHLEVEL = 31
3SUBLEVEL = 0 3SUBLEVEL = 0
4EXTRAVERSION = .git 4EXTRAVERSION = .git
5NAME = Unnamed 5NAME = Unnamed
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index 2d810d131..bf99656e2 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -301,7 +301,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv)
301//usage: "Decompress to stdout" 301//usage: "Decompress to stdout"
302 302
303//config:config GUNZIP 303//config:config GUNZIP
304//config: bool "gunzip (12 kb)" 304//config: bool "gunzip (11 kb)"
305//config: default y 305//config: default y
306//config: select FEATURE_GZIP_DECOMPRESS 306//config: select FEATURE_GZIP_DECOMPRESS
307//config: help 307//config: help
@@ -310,7 +310,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv)
310//config: an archive, without decompressing it. 310//config: an archive, without decompressing it.
311//config: 311//config:
312//config:config ZCAT 312//config:config ZCAT
313//config: bool "zcat (25 kb)" 313//config: bool "zcat (24 kb)"
314//config: default y 314//config: default y
315//config: select FEATURE_GZIP_DECOMPRESS 315//config: select FEATURE_GZIP_DECOMPRESS
316//config: help 316//config: help
@@ -415,7 +415,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv)
415//usage: "Decompress to stdout" 415//usage: "Decompress to stdout"
416 416
417//config:config BUNZIP2 417//config:config BUNZIP2
418//config: bool "bunzip2 (8.8 kb)" 418//config: bool "bunzip2 (8.7 kb)"
419//config: default y 419//config: default y
420//config: select FEATURE_BZIP2_DECOMPRESS 420//config: select FEATURE_BZIP2_DECOMPRESS
421//config: help 421//config: help
@@ -429,7 +429,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv)
429//config: should probably say N here. 429//config: should probably say N here.
430//config: 430//config:
431//config:config BZCAT 431//config:config BZCAT
432//config: bool "bzcat (8.8 kb)" 432//config: bool "bzcat (8.7 kb)"
433//config: default y 433//config: default y
434//config: select FEATURE_BZIP2_DECOMPRESS 434//config: select FEATURE_BZIP2_DECOMPRESS
435//config: help 435//config: help
@@ -483,7 +483,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
483//usage: "Decompress to stdout" 483//usage: "Decompress to stdout"
484 484
485//config:config UNLZMA 485//config:config UNLZMA
486//config: bool "unlzma (8.6 kb)" 486//config: bool "unlzma (7.5 kb)"
487//config: default y 487//config: default y
488//config: help 488//config: help
489//config: unlzma is a compression utility using the Lempel-Ziv-Markov chain 489//config: unlzma is a compression utility using the Lempel-Ziv-Markov chain
@@ -492,7 +492,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv)
492//config: compressors. 492//config: compressors.
493//config: 493//config:
494//config:config LZCAT 494//config:config LZCAT
495//config: bool "lzcat (8.5 kb)" 495//config: bool "lzcat (7.5 kb)"
496//config: default y 496//config: default y
497//config: help 497//config: help
498//config: Alias to "unlzma -c". 498//config: Alias to "unlzma -c".
diff --git a/archival/bzip2.c b/archival/bzip2.c
index 357891ca3..38cc0219a 100644
--- a/archival/bzip2.c
+++ b/archival/bzip2.c
@@ -7,7 +7,7 @@
7 * about bzip2 library code. 7 * about bzip2 library code.
8 */ 8 */
9//config:config BZIP2 9//config:config BZIP2
10//config: bool "bzip2 (18 kb)" 10//config: bool "bzip2 (16 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: bzip2 is a compression utility using the Burrows-Wheeler block 13//config: bzip2 is a compression utility using the Burrows-Wheeler block
diff --git a/archival/cpio.c b/archival/cpio.c
index 9cacf9de6..0f37ffbb9 100644
--- a/archival/cpio.c
+++ b/archival/cpio.c
@@ -11,7 +11,7 @@
11 * Only supports new ASCII and CRC formats 11 * Only supports new ASCII and CRC formats
12 */ 12 */
13//config:config CPIO 13//config:config CPIO
14//config: bool "cpio (14 kb)" 14//config: bool "cpio (15 kb)"
15//config: default y 15//config: default y
16//config: help 16//config: help
17//config: cpio is an archival utility program used to create, modify, and 17//config: cpio is an archival utility program used to create, modify, and
diff --git a/archival/dpkg.c b/archival/dpkg.c
index 58bc4dba3..ddb5daf09 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -26,7 +26,7 @@
26 * - (unknown, please let me know when you find any) 26 * - (unknown, please let me know when you find any)
27 */ 27 */
28//config:config DPKG 28//config:config DPKG
29//config: bool "dpkg (44 kb)" 29//config: bool "dpkg (43 kb)"
30//config: default y 30//config: default y
31//config: select FEATURE_SEAMLESS_GZ 31//config: select FEATURE_SEAMLESS_GZ
32//config: help 32//config: help
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c
index dc4738d28..c2c4cbbcc 100644
--- a/archival/dpkg_deb.c
+++ b/archival/dpkg_deb.c
@@ -5,7 +5,7 @@
5 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
6 */ 6 */
7//config:config DPKG_DEB 7//config:config DPKG_DEB
8//config: bool "dpkg_deb" 8//config: bool "dpkg-deb (30 kb)"
9//config: default y 9//config: default y
10//config: select FEATURE_SEAMLESS_GZ 10//config: select FEATURE_SEAMLESS_GZ
11//config: help 11//config: help
diff --git a/archival/gzip.c b/archival/gzip.c
index 74d5d685f..12c1df242 100644
--- a/archival/gzip.c
+++ b/archival/gzip.c
@@ -22,7 +22,7 @@ gzip: bogus: No such file or directory
22aa: 85.1% -- replaced with aa.gz 22aa: 85.1% -- replaced with aa.gz
23*/ 23*/
24//config:config GZIP 24//config:config GZIP
25//config: bool "gzip (19 kb)" 25//config: bool "gzip (17 kb)"
26//config: default y 26//config: default y
27//config: help 27//config: help
28//config: gzip is used to compress files. 28//config: gzip is used to compress files.
diff --git a/archival/libarchive/lzo1x_9x.c b/archival/libarchive/lzo1x_9x.c
index 09ee4ba5c..df26b375f 100644
--- a/archival/libarchive/lzo1x_9x.c
+++ b/archival/libarchive/lzo1x_9x.c
@@ -487,7 +487,7 @@ static int find_match(lzo1x_999_t *c, lzo_swd_p s,
487} 487}
488 488
489/* this is a public functions, but there is no prototype in a header file */ 489/* this is a public functions, but there is no prototype in a header file */
490static int lzo1x_999_compress_internal(const uint8_t *in , unsigned in_len, 490static int lzo1x_999_compress_internal(const uint8_t *in, unsigned in_len,
491 uint8_t *out, unsigned *out_len, 491 uint8_t *out, unsigned *out_len,
492 void *wrkmem, 492 void *wrkmem,
493 unsigned good_length, 493 unsigned good_length,
diff --git a/archival/lzop.c b/archival/lzop.c
index 8f604254c..585632c4e 100644
--- a/archival/lzop.c
+++ b/archival/lzop.c
@@ -25,7 +25,7 @@
25 "Minimalized" for busybox by Alain Knaff 25 "Minimalized" for busybox by Alain Knaff
26*/ 26*/
27//config:config LZOP 27//config:config LZOP
28//config: bool "lzop (13 kb)" 28//config: bool "lzop (12 kb)"
29//config: default y 29//config: default y
30//config: help 30//config: help
31//config: Lzop compression/decompresion. 31//config: Lzop compression/decompresion.
diff --git a/archival/rpm.c b/archival/rpm.c
index 700f90979..3dd4d4777 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config RPM 9//config:config RPM
10//config: bool "rpm (33 kb)" 10//config: bool "rpm (32 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Mini RPM applet - queries and extracts RPM packages. 13//config: Mini RPM applet - queries and extracts RPM packages.
@@ -508,7 +508,7 @@ int rpm_main(int argc, char **argv)
508 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 508 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
509 */ 509 */
510//config:config RPM2CPIO 510//config:config RPM2CPIO
511//config: bool "rpm2cpio (20 kb)" 511//config: bool "rpm2cpio (21 kb)"
512//config: default y 512//config: default y
513//config: help 513//config: help
514//config: Converts a RPM file into a CPIO archive. 514//config: Converts a RPM file into a CPIO archive.
diff --git a/archival/tar.c b/archival/tar.c
index 7dd89a282..b9ae93004 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -23,7 +23,7 @@
23 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 23 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
24 */ 24 */
25//config:config TAR 25//config:config TAR
26//config: bool "tar (40 kb)" 26//config: bool "tar (39 kb)"
27//config: default y 27//config: default y
28//config: help 28//config: help
29//config: tar is an archiving program. It's commonly used with gzip to 29//config: tar is an archiving program. It's commonly used with gzip to
diff --git a/archival/unzip.c b/archival/unzip.c
index 473cbe2ec..6328f4bab 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -17,7 +17,7 @@
17 * Zip64 + other methods 17 * Zip64 + other methods
18 */ 18 */
19//config:config UNZIP 19//config:config UNZIP
20//config: bool "unzip (24 kb)" 20//config: bool "unzip (26 kb)"
21//config: default y 21//config: default y
22//config: help 22//config: help
23//config: unzip will list or extract files from a ZIP archive, 23//config: unzip will list or extract files from a ZIP archive,
diff --git a/console-tools/dumpkmap.c b/console-tools/dumpkmap.c
index f1c9287b5..fd4fd5623 100644
--- a/console-tools/dumpkmap.c
+++ b/console-tools/dumpkmap.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config DUMPKMAP 9//config:config DUMPKMAP
10//config: bool "dumpkmap (1.3 kb)" 10//config: bool "dumpkmap (1.6 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/console-tools/fgconsole.c b/console-tools/fgconsole.c
index a353becd5..554a32403 100644
--- a/console-tools/fgconsole.c
+++ b/console-tools/fgconsole.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config FGCONSOLE 9//config:config FGCONSOLE
10//config: bool "fgconsole (1.6 kb)" 10//config: bool "fgconsole (1.5 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/console-tools/kbd_mode.c b/console-tools/kbd_mode.c
index f16449dcd..cee37ab50 100644
--- a/console-tools/kbd_mode.c
+++ b/console-tools/kbd_mode.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config KBD_MODE 11//config:config KBD_MODE
12//config: bool "kbd_mode (4 kb)" 12//config: bool "kbd_mode (4.1 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX 14//config: select PLATFORM_LINUX
15//config: help 15//config: help
diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c
index 81d0c3db4..b5d4e8f43 100644
--- a/console-tools/loadfont.c
+++ b/console-tools/loadfont.c
@@ -10,14 +10,14 @@
10 * Licensed under GPLv2, see file LICENSE in this source tree. 10 * Licensed under GPLv2, see file LICENSE in this source tree.
11 */ 11 */
12//config:config LOADFONT 12//config:config LOADFONT
13//config: bool "loadfont (5.4 kb)" 13//config: bool "loadfont (5.2 kb)"
14//config: default y 14//config: default y
15//config: select PLATFORM_LINUX 15//config: select PLATFORM_LINUX
16//config: help 16//config: help
17//config: This program loads a console font from standard input. 17//config: This program loads a console font from standard input.
18//config: 18//config:
19//config:config SETFONT 19//config:config SETFONT
20//config: bool "setfont (26 kb)" 20//config: bool "setfont (24 kb)"
21//config: default y 21//config: default y
22//config: select PLATFORM_LINUX 22//config: select PLATFORM_LINUX
23//config: help 23//config: help
diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c
index 404aba1fb..d4981ad21 100644
--- a/console-tools/loadkmap.c
+++ b/console-tools/loadkmap.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LOADKMAP 9//config:config LOADKMAP
10//config: bool "loadkmap (1.5 kb)" 10//config: bool "loadkmap (1.8 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/console-tools/openvt.c b/console-tools/openvt.c
index 423122fe9..b01229a56 100644
--- a/console-tools/openvt.c
+++ b/console-tools/openvt.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config OPENVT 10//config:config OPENVT
11//config: bool "openvt (7 kb)" 11//config: bool "openvt (7.2 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/console-tools/reset.c b/console-tools/reset.c
index 614806ba7..113bb5c76 100644
--- a/console-tools/reset.c
+++ b/console-tools/reset.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config RESET 10//config:config RESET
11//config: bool "reset (275 bytes)" 11//config: bool "reset (345 bytes)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: This program is used to reset the terminal screen, if it 14//config: This program is used to reset the terminal screen, if it
diff --git a/console-tools/resize.c b/console-tools/resize.c
index 8aa487c41..59d468d48 100644
--- a/console-tools/resize.c
+++ b/console-tools/resize.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config RESIZE 9//config:config RESIZE
10//config: bool "resize (756 bytes)" 10//config: bool "resize (903 bytes)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: This program is used to (re)set the width and height of your current 13//config: This program is used to (re)set the width and height of your current
diff --git a/console-tools/setconsole.c b/console-tools/setconsole.c
index 7f0f9c711..0bc587241 100644
--- a/console-tools/setconsole.c
+++ b/console-tools/setconsole.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config SETCONSOLE 10//config:config SETCONSOLE
11//config: bool "setconsole (3.7 kb)" 11//config: bool "setconsole (3.6 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/console-tools/setkeycodes.c b/console-tools/setkeycodes.c
index 1363ac9d1..259946dbb 100644
--- a/console-tools/setkeycodes.c
+++ b/console-tools/setkeycodes.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config SETKEYCODES 11//config:config SETKEYCODES
12//config: bool "setkeycodes (1.7 kb)" 12//config: bool "setkeycodes (2.1 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX 14//config: select PLATFORM_LINUX
15//config: help 15//config: help
diff --git a/coreutils/basename.c b/coreutils/basename.c
index 812a5e63e..0dd2c43c7 100644
--- a/coreutils/basename.c
+++ b/coreutils/basename.c
@@ -14,7 +14,7 @@
14 * 3) Save some space by using strcmp(). Calling strncmp() here was silly. 14 * 3) Save some space by using strcmp(). Calling strncmp() here was silly.
15 */ 15 */
16//config:config BASENAME 16//config:config BASENAME
17//config: bool "basename (371 bytes)" 17//config: bool "basename (438 bytes)"
18//config: default y 18//config: default y
19//config: help 19//config: help
20//config: basename is used to strip the directory and suffix from filenames, 20//config: basename is used to strip the directory and suffix from filenames,
diff --git a/coreutils/chgrp.c b/coreutils/chgrp.c
index 27a0edf0d..ae216aa3f 100644
--- a/coreutils/chgrp.c
+++ b/coreutils/chgrp.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config CHGRP 9//config:config CHGRP
10//config: bool "chgrp (7.2 kb)" 10//config: bool "chgrp (7.6 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: chgrp is used to change the group ownership of files. 13//config: chgrp is used to change the group ownership of files.
diff --git a/coreutils/chmod.c b/coreutils/chmod.c
index 88989bf67..27e9b6b86 100644
--- a/coreutils/chmod.c
+++ b/coreutils/chmod.c
@@ -10,7 +10,7 @@
10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 10 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
11 */ 11 */
12//config:config CHMOD 12//config:config CHMOD
13//config: bool "chmod (5.1 kb)" 13//config: bool "chmod (5.5 kb)"
14//config: default y 14//config: default y
15//config: help 15//config: help
16//config: chmod is used to change the access permission of files. 16//config: chmod is used to change the access permission of files.
diff --git a/coreutils/chown.c b/coreutils/chown.c
index 6429fd030..a1c5c0224 100644
--- a/coreutils/chown.c
+++ b/coreutils/chown.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config CHOWN 9//config:config CHOWN
10//config: bool "chown (7.2 kb)" 10//config: bool "chown (7.6 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: chown is used to change the user and/or group ownership 13//config: chown is used to change the user and/or group ownership
diff --git a/coreutils/cksum.c b/coreutils/cksum.c
index e46e249f2..633322bc7 100644
--- a/coreutils/cksum.c
+++ b/coreutils/cksum.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config CKSUM 9//config:config CKSUM
10//config: bool "cksum (4.2 kb)" 10//config: bool "cksum (4.1 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: cksum is used to calculate the CRC32 checksum of a file. 13//config: cksum is used to calculate the CRC32 checksum of a file.
diff --git a/coreutils/comm.c b/coreutils/comm.c
index 4bee77677..c59fccdd1 100644
--- a/coreutils/comm.c
+++ b/coreutils/comm.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config COMM 9//config:config COMM
10//config: bool "comm (3.9 kb)" 10//config: bool "comm (4.2 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: comm is used to compare two files line by line and return 13//config: comm is used to compare two files line by line and return
diff --git a/coreutils/cp.c b/coreutils/cp.c
index b26c0e954..59e3d2f80 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -12,7 +12,7 @@
12 * Size reduction. 12 * Size reduction.
13 */ 13 */
14//config:config CP 14//config:config CP
15//config: bool "cp (9.7 kb)" 15//config: bool "cp (10 kb)"
16//config: default y 16//config: default y
17//config: help 17//config: help
18//config: cp is used to copy files and directories. 18//config: cp is used to copy files and directories.
diff --git a/coreutils/cut.c b/coreutils/cut.c
index cdd90ab44..e952dc17b 100644
--- a/coreutils/cut.c
+++ b/coreutils/cut.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config CUT 11//config:config CUT
12//config: bool "cut (5.3 kb)" 12//config: bool "cut (5.8 kb)"
13//config: default y 13//config: default y
14//config: help 14//config: help
15//config: cut is used to print selected parts of lines from 15//config: cut is used to print selected parts of lines from
diff --git a/coreutils/date.c b/coreutils/date.c
index 87dc3bbd0..3414d38ae 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -19,7 +19,7 @@
19 much as possible, missed out a lot of bounds checking */ 19 much as possible, missed out a lot of bounds checking */
20 20
21//config:config DATE 21//config:config DATE
22//config: bool "date (7.1 kb)" 22//config: bool "date (7 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: date is used to set the system date or display the 25//config: date is used to set the system date or display the
@@ -54,7 +54,7 @@
54//config: date -s (and other commands like touch -d) use more sensible 54//config: date -s (and other commands like touch -d) use more sensible
55//config: formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss). 55//config: formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss).
56//config: 56//config:
57//config: With this option off, 'date DATE' is 'date -s DATE' support 57//config: With this option off, 'date DATE' and 'date -s DATE' support
58//config: the same format. With it on, 'date DATE' additionally supports 58//config: the same format. With it on, 'date DATE' additionally supports
59//config: MMDDhhmm[[YY]YY][.ss] format. 59//config: MMDDhhmm[[YY]YY][.ss] format.
60 60
@@ -121,7 +121,7 @@
121//usage: "\n -d,--date TIME Display TIME, not 'now'" 121//usage: "\n -d,--date TIME Display TIME, not 'now'"
122//usage: ) 122//usage: )
123//usage: IF_FEATURE_DATE_ISOFMT( 123//usage: IF_FEATURE_DATE_ISOFMT(
124//usage: "\n -D FMT Use FMT for -d TIME conversion" 124//usage: "\n -D FMT Use FMT (strptime format) for -d TIME conversion"
125//usage: ) 125//usage: )
126//usage: "\n" 126//usage: "\n"
127//usage: "\nRecognized TIME formats:" 127//usage: "\nRecognized TIME formats:"
diff --git a/coreutils/dd.c b/coreutils/dd.c
index d73f6224b..e0af8f4a3 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config DD 9//config:config DD
10//config: bool "dd (7.1 kb)" 10//config: bool "dd (7.5 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: dd copies a file (from standard input to standard output, 13//config: dd copies a file (from standard input to standard output,
diff --git a/coreutils/df.c b/coreutils/df.c
index 50dccac52..f6d66e4b6 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -18,7 +18,7 @@
18 * Implement -P and -B; better coreutils compat; cleanup 18 * Implement -P and -B; better coreutils compat; cleanup
19 */ 19 */
20//config:config DF 20//config:config DF
21//config: bool "df (7.5 kb)" 21//config: bool "df (6.8 kb)"
22//config: default y 22//config: default y
23//config: help 23//config: help
24//config: df reports the amount of disk space used and available 24//config: df reports the amount of disk space used and available
diff --git a/coreutils/dirname.c b/coreutils/dirname.c
index 511267b78..5aad121b5 100644
--- a/coreutils/dirname.c
+++ b/coreutils/dirname.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config DIRNAME 9//config:config DIRNAME
10//config: bool "dirname (289 bytes)" 10//config: bool "dirname (329 bytes)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: dirname is used to strip a non-directory suffix from 13//config: dirname is used to strip a non-directory suffix from
diff --git a/coreutils/dos2unix.c b/coreutils/dos2unix.c
index 9f098e41e..4039ed38c 100644
--- a/coreutils/dos2unix.c
+++ b/coreutils/dos2unix.c
@@ -12,14 +12,14 @@
12 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 12 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
13 */ 13 */
14//config:config DOS2UNIX 14//config:config DOS2UNIX
15//config: bool "dos2unix (5.1 kb)" 15//config: bool "dos2unix (5.2 kb)"
16//config: default y 16//config: default y
17//config: help 17//config: help
18//config: dos2unix is used to convert a text file from DOS format to 18//config: dos2unix is used to convert a text file from DOS format to
19//config: UNIX format, and vice versa. 19//config: UNIX format, and vice versa.
20//config: 20//config:
21//config:config UNIX2DOS 21//config:config UNIX2DOS
22//config: bool "unix2dos (5.1 kb)" 22//config: bool "unix2dos (5.2 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: unix2dos is used to convert a text file from UNIX format to 25//config: unix2dos is used to convert a text file from UNIX format to
diff --git a/coreutils/du.c b/coreutils/du.c
index a0c99040e..0615a6e49 100644
--- a/coreutils/du.c
+++ b/coreutils/du.c
@@ -19,18 +19,16 @@
19 * 4) Fixed busybox bug #1284 involving long overflow with human_readable. 19 * 4) Fixed busybox bug #1284 involving long overflow with human_readable.
20 */ 20 */
21//config:config DU 21//config:config DU
22//config: bool "du (default blocksize of 512 bytes)" 22//config: bool "du (6.3 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: du is used to report the amount of disk space used 25//config: du is used to report the amount of disk space used
26//config: for specified files. 26//config: for specified files.
27//config: 27//config:
28//config:config FEATURE_DU_DEFAULT_BLOCKSIZE_1K 28//config:config FEATURE_DU_DEFAULT_BLOCKSIZE_1K
29//config: bool "Use a default blocksize of 1024 bytes (1K)" 29//config: bool "Use default blocksize of 1024 bytes (else it's 512 bytes)"
30//config: default y 30//config: default y
31//config: depends on DU 31//config: depends on DU
32//config: help
33//config: Use a blocksize of (1K) instead of the default 512b.
34 32
35//applet:IF_DU(APPLET(du, BB_DIR_USR_BIN, BB_SUID_DROP)) 33//applet:IF_DU(APPLET(du, BB_DIR_USR_BIN, BB_SUID_DROP))
36 34
diff --git a/coreutils/echo.c b/coreutils/echo.c
index e45b90940..5dc5be072 100644
--- a/coreutils/echo.c
+++ b/coreutils/echo.c
@@ -19,10 +19,10 @@
19 * The previous version did not allow 4-digit octals. 19 * The previous version did not allow 4-digit octals.
20 */ 20 */
21//config:config ECHO 21//config:config ECHO
22//config: bool "echo (basic SuSv3 version taking no options)" 22//config: bool "echo (1.8 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: echo is used to print a specified string to stdout. 25//config: echo prints a specified string to stdout.
26//config: 26//config:
27//config:# this entry also appears in shell/Config.in, next to the echo builtin 27//config:# this entry also appears in shell/Config.in, next to the echo builtin
28//config:config FEATURE_FANCY_ECHO 28//config:config FEATURE_FANCY_ECHO
diff --git a/coreutils/env.c b/coreutils/env.c
index 0aebead1b..878068f09 100644
--- a/coreutils/env.c
+++ b/coreutils/env.c
@@ -24,7 +24,7 @@
24 * - use xfunc_error_retval 24 * - use xfunc_error_retval
25 */ 25 */
26//config:config ENV 26//config:config ENV
27//config: bool "env (3.8 kb)" 27//config: bool "env (4 kb)"
28//config: default y 28//config: default y
29//config: help 29//config: help
30//config: env is used to set an environment variable and run 30//config: env is used to set an environment variable and run
diff --git a/coreutils/expand.c b/coreutils/expand.c
index 91084b80b..f7e4619f9 100644
--- a/coreutils/expand.c
+++ b/coreutils/expand.c
@@ -21,13 +21,13 @@
21 * Caveat: this versions of expand and unexpand don't accept tab lists. 21 * Caveat: this versions of expand and unexpand don't accept tab lists.
22 */ 22 */
23//config:config EXPAND 23//config:config EXPAND
24//config: bool "expand (5.8 kb)" 24//config: bool "expand (5.1 kb)"
25//config: default y 25//config: default y
26//config: help 26//config: help
27//config: By default, convert all tabs to spaces. 27//config: By default, convert all tabs to spaces.
28//config: 28//config:
29//config:config UNEXPAND 29//config:config UNEXPAND
30//config: bool "unexpand (6 kb)" 30//config: bool "unexpand (5.3 kb)"
31//config: default y 31//config: default y
32//config: help 32//config: help
33//config: By default, convert only leading sequences of blanks to tabs. 33//config: By default, convert only leading sequences of blanks to tabs.
diff --git a/coreutils/expr.c b/coreutils/expr.c
index 00bcf60d4..900248103 100644
--- a/coreutils/expr.c
+++ b/coreutils/expr.c
@@ -23,7 +23,7 @@
23 * provided they all associate ((x op x) op x). 23 * provided they all associate ((x op x) op x).
24 */ 24 */
25//config:config EXPR 25//config:config EXPR
26//config: bool "expr (6.1 kb)" 26//config: bool "expr (6.6 kb)"
27//config: default y 27//config: default y
28//config: help 28//config: help
29//config: expr is used to calculate numbers and print the result 29//config: expr is used to calculate numbers and print the result
diff --git a/coreutils/factor.c b/coreutils/factor.c
index ee3943a4a..47fe179dc 100644
--- a/coreutils/factor.c
+++ b/coreutils/factor.c
@@ -4,7 +4,7 @@
4 * Licensed under GPLv2, see file LICENSE in this source tree. 4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */ 5 */
6//config:config FACTOR 6//config:config FACTOR
7//config: bool "factor (2.6 kb)" 7//config: bool "factor (2.7 kb)"
8//config: default y 8//config: default y
9//config: help 9//config: help
10//config: factor factorizes integers 10//config: factor factorizes integers
diff --git a/coreutils/fsync.c b/coreutils/fsync.c
index 5e77e2c16..c7cba9f61 100644
--- a/coreutils/fsync.c
+++ b/coreutils/fsync.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config FSYNC 9//config:config FSYNC
10//config: bool "fsync (3.7 kb)" 10//config: bool "fsync (3.6 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: fsync is used to flush file-related cached blocks to disk. 13//config: fsync is used to flush file-related cached blocks to disk.
diff --git a/coreutils/head.c b/coreutils/head.c
index fc3a48d5b..1219dfe8b 100644
--- a/coreutils/head.c
+++ b/coreutils/head.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config HEAD 9//config:config HEAD
10//config: bool "head (3.7 kb)" 10//config: bool "head (3.8 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: head is used to print the first specified number of lines 13//config: head is used to print the first specified number of lines
diff --git a/coreutils/hostid.c b/coreutils/hostid.c
index d21e6d6ac..038809452 100644
--- a/coreutils/hostid.c
+++ b/coreutils/hostid.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config HOSTID 9//config:config HOSTID
10//config: bool "hostid (247 bytes)" 10//config: bool "hostid (286 bytes)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: hostid prints the numeric identifier (in hexadecimal) for 13//config: hostid prints the numeric identifier (in hexadecimal) for
diff --git a/coreutils/id.c b/coreutils/id.c
index 5a7fb9aaf..00c0cd8ab 100644
--- a/coreutils/id.c
+++ b/coreutils/id.c
@@ -13,13 +13,13 @@
13 * Added -G option Tito Ragusa (C) 2008 for SUSv3. 13 * Added -G option Tito Ragusa (C) 2008 for SUSv3.
14 */ 14 */
15//config:config ID 15//config:config ID
16//config: bool "id (6.7 kb)" 16//config: bool "id (7 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: id displays the current user and group ID names. 19//config: id displays the current user and group ID names.
20//config: 20//config:
21//config:config GROUPS 21//config:config GROUPS
22//config: bool "groups (6.5 kb)" 22//config: bool "groups (6.7 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: Print the group names associated with current user id. 25//config: Print the group names associated with current user id.
diff --git a/coreutils/link.c b/coreutils/link.c
index d8d583b7b..23e0cfdd0 100644
--- a/coreutils/link.c
+++ b/coreutils/link.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2, see file LICENSE in this source tree. 6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */ 7 */
8//config:config LINK 8//config:config LINK
9//config: bool "link (3.1 kb)" 9//config: bool "link (3.2 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: link creates hard links between files. 12//config: link creates hard links between files.
diff --git a/coreutils/ln.c b/coreutils/ln.c
index 2dda5dae9..3fe2f3f64 100644
--- a/coreutils/ln.c
+++ b/coreutils/ln.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LN 9//config:config LN
10//config: bool "ln (4.5 kb)" 10//config: bool "ln (4.9 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: ln is used to create hard or soft links between files. 13//config: ln is used to create hard or soft links between files.
diff --git a/coreutils/logname.c b/coreutils/logname.c
index e614ca7cf..31ce61f0c 100644
--- a/coreutils/logname.c
+++ b/coreutils/logname.c
@@ -16,7 +16,7 @@
16 * a diagnostic message and an error return. 16 * a diagnostic message and an error return.
17 */ 17 */
18//config:config LOGNAME 18//config:config LOGNAME
19//config: bool "logname (894 bytes)" 19//config: bool "logname (1.1 kb)"
20//config: default y 20//config: default y
21//config: help 21//config: help
22//config: logname is used to print the current user's login name. 22//config: logname is used to print the current user's login name.
diff --git a/coreutils/ls.c b/coreutils/ls.c
index fb4f998be..48927c964 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1206,8 +1206,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1206 nfiles = 0; 1206 nfiles = 0;
1207 do { 1207 do {
1208 cur = my_stat(*argv, *argv, 1208 cur = my_stat(*argv, *argv,
1209 /* follow links on command line unless -l, -s or -F: */ 1209 /* follow links on command line unless -l, -i, -s or -F: */
1210 !(option_mask32 & (OPT_l|OPT_s|OPT_F)) 1210 !(option_mask32 & (OPT_l|OPT_i|OPT_s|OPT_F))
1211 /* ... or if -H: */ 1211 /* ... or if -H: */
1212 || (option_mask32 & OPT_H) 1212 || (option_mask32 & OPT_H)
1213 /* ... or if -L, but my_stat always follows links if -L */ 1213 /* ... or if -L, but my_stat always follows links if -L */
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c
index 871145143..538df251b 100644
--- a/coreutils/md5_sha1_sum.c
+++ b/coreutils/md5_sha1_sum.c
@@ -6,31 +6,31 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config MD5SUM 8//config:config MD5SUM
9//config: bool "md5sum (6.8 kb)" 9//config: bool "md5sum (6.5 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: Compute and check MD5 message digest 12//config: Compute and check MD5 message digest
13//config: 13//config:
14//config:config SHA1SUM 14//config:config SHA1SUM
15//config: bool "sha1sum (6 kb)" 15//config: bool "sha1sum (5.9 kb)"
16//config: default y 16//config: default y
17//config: help 17//config: help
18//config: Compute and check SHA1 message digest 18//config: Compute and check SHA1 message digest
19//config: 19//config:
20//config:config SHA256SUM 20//config:config SHA256SUM
21//config: bool "sha256sum (7.1 kb)" 21//config: bool "sha256sum (7 kb)"
22//config: default y 22//config: default y
23//config: help 23//config: help
24//config: Compute and check SHA256 message digest 24//config: Compute and check SHA256 message digest
25//config: 25//config:
26//config:config SHA512SUM 26//config:config SHA512SUM
27//config: bool "sha512sum (7.6 kb)" 27//config: bool "sha512sum (7.4 kb)"
28//config: default y 28//config: default y
29//config: help 29//config: help
30//config: Compute and check SHA512 message digest 30//config: Compute and check SHA512 message digest
31//config: 31//config:
32//config:config SHA3SUM 32//config:config SHA3SUM
33//config: bool "sha3sum (6.3 kb)" 33//config: bool "sha3sum (6.1 kb)"
34//config: default y 34//config: default y
35//config: help 35//config: help
36//config: Compute and check SHA3 message digest 36//config: Compute and check SHA3 message digest
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
index 986353dc6..0ee1d1f72 100644
--- a/coreutils/mkdir.c
+++ b/coreutils/mkdir.c
@@ -14,7 +14,7 @@
14/* Nov 28, 2006 Yoshinori Sato <ysato@users.sourceforge.jp>: Add SELinux Support. 14/* Nov 28, 2006 Yoshinori Sato <ysato@users.sourceforge.jp>: Add SELinux Support.
15 */ 15 */
16//config:config MKDIR 16//config:config MKDIR
17//config: bool "mkdir (4.4 kb)" 17//config: bool "mkdir (4.5 kb)"
18//config: default y 18//config: default y
19//config: help 19//config: help
20//config: mkdir is used to create directories with the specified names. 20//config: mkdir is used to create directories with the specified names.
diff --git a/coreutils/mkfifo.c b/coreutils/mkfifo.c
index 0f614017e..e9d420ed8 100644
--- a/coreutils/mkfifo.c
+++ b/coreutils/mkfifo.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config MKFIFO 9//config:config MKFIFO
10//config: bool "mkfifo (3.7 kb)" 10//config: bool "mkfifo (3.8 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: mkfifo is used to create FIFOs (named pipes). 13//config: mkfifo is used to create FIFOs (named pipes).
diff --git a/coreutils/mknod.c b/coreutils/mknod.c
index d57167f7d..eee0ac71d 100644
--- a/coreutils/mknod.c
+++ b/coreutils/mknod.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config MKNOD 9//config:config MKNOD
10//config: bool "mknod (4 kb)" 10//config: bool "mknod (4.5 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: mknod is used to create FIFOs or block/character special 13//config: mknod is used to create FIFOs or block/character special
diff --git a/coreutils/mktemp.c b/coreutils/mktemp.c
index c041fedf7..5393320a5 100644
--- a/coreutils/mktemp.c
+++ b/coreutils/mktemp.c
@@ -29,7 +29,7 @@
29 * -p; else /tmp [deprecated] 29 * -p; else /tmp [deprecated]
30 */ 30 */
31//config:config MKTEMP 31//config:config MKTEMP
32//config: bool "mktemp (4 kb)" 32//config: bool "mktemp (4.2 kb)"
33//config: default y 33//config: default y
34//config: help 34//config: help
35//config: mktemp is used to create unique temporary files 35//config: mktemp is used to create unique temporary files
diff --git a/coreutils/mv.c b/coreutils/mv.c
index 6e11197a1..b9f8f6982 100644
--- a/coreutils/mv.c
+++ b/coreutils/mv.c
@@ -12,7 +12,7 @@
12 * Size reduction and improved error checking. 12 * Size reduction and improved error checking.
13 */ 13 */
14//config:config MV 14//config:config MV
15//config: bool "mv (9.8 kb)" 15//config: bool "mv (10 kb)"
16//config: default y 16//config: default y
17//config: help 17//config: help
18//config: mv is used to move or rename files or directories. 18//config: mv is used to move or rename files or directories.
diff --git a/coreutils/nice.c b/coreutils/nice.c
index da1696c42..28591ac61 100644
--- a/coreutils/nice.c
+++ b/coreutils/nice.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config NICE 9//config:config NICE
10//config: bool "nice (1.8 kb)" 10//config: bool "nice (2.1 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: nice runs a program with modified scheduling priority. 13//config: nice runs a program with modified scheduling priority.
diff --git a/coreutils/nl.c b/coreutils/nl.c
index 2fdc9d85e..aea019c56 100644
--- a/coreutils/nl.c
+++ b/coreutils/nl.c
@@ -5,7 +5,7 @@
5 * Licensed under GPLv2, see file LICENSE in this source tree. 5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */ 6 */
7//config:config NL 7//config:config NL
8//config: bool "nl (4.3 kb)" 8//config: bool "nl (4.6 kb)"
9//config: default y 9//config: default y
10//config: help 10//config: help
11//config: nl is used to number lines of files. 11//config: nl is used to number lines of files.
diff --git a/coreutils/nproc.c b/coreutils/nproc.c
index 0ea8d1001..31e452bc4 100644
--- a/coreutils/nproc.c
+++ b/coreutils/nproc.c
@@ -4,7 +4,7 @@
4 * Licensed under GPLv2, see LICENSE in this source tree 4 * Licensed under GPLv2, see LICENSE in this source tree
5 */ 5 */
6//config:config NPROC 6//config:config NPROC
7//config: bool "nproc (248 bytes)" 7//config: bool "nproc (3.7 kb)"
8//config: default y 8//config: default y
9//config: help 9//config: help
10//config: Print number of CPUs 10//config: Print number of CPUs
diff --git a/coreutils/paste.c b/coreutils/paste.c
index 52f67f951..3d81a5f1a 100644
--- a/coreutils/paste.c
+++ b/coreutils/paste.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config PASTE 9//config:config PASTE
10//config: bool "paste (4.5 kb)" 10//config: bool "paste (4.9 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: paste is used to paste lines of different files together 13//config: paste is used to paste lines of different files together
diff --git a/coreutils/printenv.c b/coreutils/printenv.c
index b0468b3f7..5e195deaa 100644
--- a/coreutils/printenv.c
+++ b/coreutils/printenv.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config PRINTENV 10//config:config PRINTENV
11//config: bool "printenv (1 kb)" 11//config: bool "printenv (1.3 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: printenv is used to print all or part of environment. 14//config: printenv is used to print all or part of environment.
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 67d3b2eda..5cf518699 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -38,7 +38,7 @@
38/* 19990508 Busy Boxed! Dave Cinege */ 38/* 19990508 Busy Boxed! Dave Cinege */
39 39
40//config:config PRINTF 40//config:config PRINTF
41//config: bool "printf (3.3 kb)" 41//config: bool "printf (3.8 kb)"
42//config: default y 42//config: default y
43//config: help 43//config: help
44//config: printf is used to format and print specified strings. 44//config: printf is used to format and print specified strings.
diff --git a/coreutils/pwd.c b/coreutils/pwd.c
index 345d85100..4c42284f4 100644
--- a/coreutils/pwd.c
+++ b/coreutils/pwd.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config PWD 9//config:config PWD
10//config: bool "pwd (3.4 kb)" 10//config: bool "pwd (3.7 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: pwd is used to print the current directory. 13//config: pwd is used to print the current directory.
diff --git a/coreutils/readlink.c b/coreutils/readlink.c
index 49361cea0..09d69df2b 100644
--- a/coreutils/readlink.c
+++ b/coreutils/readlink.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config READLINK 9//config:config READLINK
10//config: bool "readlink (3.6 kb)" 10//config: bool "readlink (4 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: This program reads a symbolic link and returns the name 13//config: This program reads a symbolic link and returns the name
diff --git a/coreutils/realpath.c b/coreutils/realpath.c
index 43923681c..f5f868744 100644
--- a/coreutils/realpath.c
+++ b/coreutils/realpath.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config REALPATH 10//config:config REALPATH
11//config: bool "realpath (1.1 kb)" 11//config: bool "realpath (1.6 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: Return the canonicalized absolute pathname. 14//config: Return the canonicalized absolute pathname.
diff --git a/coreutils/rm.c b/coreutils/rm.c
index b68a82dc4..fd94bb5c4 100644
--- a/coreutils/rm.c
+++ b/coreutils/rm.c
@@ -11,7 +11,7 @@
11 * Size reduction. 11 * Size reduction.
12 */ 12 */
13//config:config RM 13//config:config RM
14//config: bool "rm (4.9 kb)" 14//config: bool "rm (5.4 kb)"
15//config: default y 15//config: default y
16//config: help 16//config: help
17//config: rm is used to remove files or directories. 17//config: rm is used to remove files or directories.
diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c
index 955740494..5092a5dfc 100644
--- a/coreutils/rmdir.c
+++ b/coreutils/rmdir.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config RMDIR 9//config:config RMDIR
10//config: bool "rmdir (3.4 kb)" 10//config: bool "rmdir (3.5 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: rmdir is used to remove empty directories. 13//config: rmdir is used to remove empty directories.
diff --git a/coreutils/seq.c b/coreutils/seq.c
index c26ff06b9..beb339d1e 100644
--- a/coreutils/seq.c
+++ b/coreutils/seq.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config SEQ 9//config:config SEQ
10//config: bool "seq (3.6 kb)" 10//config: bool "seq (3.8 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: print a sequence of numbers 13//config: print a sequence of numbers
diff --git a/coreutils/shred.c b/coreutils/shred.c
index 0ebbc39ca..86d4b66b4 100644
--- a/coreutils/shred.c
+++ b/coreutils/shred.c
@@ -5,7 +5,7 @@
5 * Licensed under GPLv2, see file LICENSE in this source tree. 5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */ 6 */
7//config:config SHRED 7//config:config SHRED
8//config: bool "shred (5 kb)" 8//config: bool "shred (4.9 kb)"
9//config: default y 9//config: default y
10//config: help 10//config: help
11//config: Overwrite a file to hide its contents, and optionally delete it 11//config: Overwrite a file to hide its contents, and optionally delete it
diff --git a/coreutils/sleep.c b/coreutils/sleep.c
index 126665839..7bfaab920 100644
--- a/coreutils/sleep.c
+++ b/coreutils/sleep.c
@@ -13,7 +13,7 @@
13 * time suffixes for seconds, minutes, hours, and days. 13 * time suffixes for seconds, minutes, hours, and days.
14 */ 14 */
15//config:config SLEEP 15//config:config SLEEP
16//config: bool "sleep (1.7 kb)" 16//config: bool "sleep (2 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: sleep is used to pause for a specified number of seconds. 19//config: sleep is used to pause for a specified number of seconds.
@@ -68,6 +68,11 @@ int sleep_main(int argc UNUSED_PARAM, char **argv)
68 if (!*argv) 68 if (!*argv)
69 bb_show_usage(); 69 bb_show_usage();
70 70
71 /* GNU sleep accepts "inf", "INF", "infinity" and "INFINITY" */
72 if (strncasecmp(argv[0], "inf", 3) == 0)
73 for (;;)
74 sleep(INT_MAX);
75
71#if ENABLE_FEATURE_FANCY_SLEEP 76#if ENABLE_FEATURE_FANCY_SLEEP
72# if ENABLE_FLOAT_DURATION 77# if ENABLE_FLOAT_DURATION
73 /* undo busybox.c setlocale */ 78 /* undo busybox.c setlocale */
diff --git a/coreutils/sort.c b/coreutils/sort.c
index 05e5c9071..f04c6067b 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -12,7 +12,7 @@
12 * http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html 12 * http://www.opengroup.org/onlinepubs/007904975/utilities/sort.html
13 */ 13 */
14//config:config SORT 14//config:config SORT
15//config: bool "sort (7.4 kb)" 15//config: bool "sort (7.7 kb)"
16//config: default y 16//config: default y
17//config: help 17//config: help
18//config: sort is used to sort lines of text in specified files. 18//config: sort is used to sort lines of text in specified files.
diff --git a/coreutils/split.c b/coreutils/split.c
index 4e1db190c..c1e4ceab2 100644
--- a/coreutils/split.c
+++ b/coreutils/split.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config SPLIT 8//config:config SPLIT
9//config: bool "split (5.4 kb)" 9//config: bool "split (5 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: Split a file into pieces. 12//config: Split a file into pieces.
diff --git a/coreutils/stat.c b/coreutils/stat.c
index 43fad2324..32bc5e2d3 100644
--- a/coreutils/stat.c
+++ b/coreutils/stat.c
@@ -13,7 +13,7 @@
13 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 13 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
14 */ 14 */
15//config:config STAT 15//config:config STAT
16//config: bool "stat (10 kb)" 16//config: bool "stat (11 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: display file or filesystem status. 19//config: display file or filesystem status.
diff --git a/coreutils/stty.c b/coreutils/stty.c
index 424d909cf..6251f2aef 100644
--- a/coreutils/stty.c
+++ b/coreutils/stty.c
@@ -21,7 +21,7 @@
21 * Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001 21 * Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001
22 */ 22 */
23//config:config STTY 23//config:config STTY
24//config: bool "stty (8.6 kb)" 24//config: bool "stty (8.9 kb)"
25//config: default y 25//config: default y
26//config: help 26//config: help
27//config: stty is used to change and print terminal line settings. 27//config: stty is used to change and print terminal line settings.
diff --git a/coreutils/sum.c b/coreutils/sum.c
index ee758877f..dba8e8e76 100644
--- a/coreutils/sum.c
+++ b/coreutils/sum.c
@@ -13,7 +13,7 @@
13 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 13 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
14 */ 14 */
15//config:config SUM 15//config:config SUM
16//config: bool "sum (4.3 kb)" 16//config: bool "sum (4 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: checksum and count the blocks in a file 19//config: checksum and count the blocks in a file
diff --git a/coreutils/sync.c b/coreutils/sync.c
index 9be47ab64..b93476aee 100644
--- a/coreutils/sync.c
+++ b/coreutils/sync.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config SYNC 10//config:config SYNC
11//config: bool "sync (769 bytes)" 11//config: bool "sync (3.8 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: sync is used to flush filesystem buffers. 14//config: sync is used to flush filesystem buffers.
diff --git a/coreutils/tac.c b/coreutils/tac.c
index 6d3ea9c19..25e85f6f3 100644
--- a/coreutils/tac.c
+++ b/coreutils/tac.c
@@ -13,7 +13,7 @@
13 * http://www.uclibc.org/lists/busybox/2003-July/008813.html 13 * http://www.uclibc.org/lists/busybox/2003-July/008813.html
14 */ 14 */
15//config:config TAC 15//config:config TAC
16//config: bool "tac (4.1 kb)" 16//config: bool "tac (3.9 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: tac is used to concatenate and print files in reverse. 19//config: tac is used to concatenate and print files in reverse.
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 7335ba11e..14ed85d16 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -19,7 +19,7 @@
19 * 7) lseek attempted when count==0 even if arg was +0 (from top) 19 * 7) lseek attempted when count==0 even if arg was +0 (from top)
20 */ 20 */
21//config:config TAIL 21//config:config TAIL
22//config: bool "tail (7.1 kb)" 22//config: bool "tail (6.8 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: tail is used to print the last specified number of lines 25//config: tail is used to print the last specified number of lines
diff --git a/coreutils/tee.c b/coreutils/tee.c
index f0ec791bb..fe5694331 100644
--- a/coreutils/tee.c
+++ b/coreutils/tee.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config TEE 9//config:config TEE
10//config: bool "tee (4.3 kb)" 10//config: bool "tee (4.2 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: tee is used to read from standard input and write 13//config: tee is used to read from standard input and write
diff --git a/coreutils/test.c b/coreutils/test.c
index ddb66ddce..8d7dac025 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -20,7 +20,7 @@
20 * "This program is in the Public Domain." 20 * "This program is in the Public Domain."
21 */ 21 */
22//config:config TEST 22//config:config TEST
23//config: bool "test (3.6 kb)" 23//config: bool "test (4.1 kb)"
24//config: default y 24//config: default y
25//config: help 25//config: help
26//config: test is used to check file types and compare values, 26//config: test is used to check file types and compare values,
diff --git a/coreutils/timeout.c b/coreutils/timeout.c
index 3b2140807..258cd276f 100644
--- a/coreutils/timeout.c
+++ b/coreutils/timeout.c
@@ -28,7 +28,7 @@
28 * rewrite 14-11-2008 vda 28 * rewrite 14-11-2008 vda
29 */ 29 */
30//config:config TIMEOUT 30//config:config TIMEOUT
31//config: bool "timeout (5.5 kb)" 31//config: bool "timeout (6 kb)"
32//config: default y 32//config: default y
33//config: help 33//config: help
34//config: Runs a program and watches it. If it does not terminate in 34//config: Runs a program and watches it. If it does not terminate in
diff --git a/coreutils/touch.c b/coreutils/touch.c
index 857761578..b30811157 100644
--- a/coreutils/touch.c
+++ b/coreutils/touch.c
@@ -13,7 +13,7 @@
13 * Also, exiting on a failure was a bug. All args should be processed. 13 * Also, exiting on a failure was a bug. All args should be processed.
14 */ 14 */
15//config:config TOUCH 15//config:config TOUCH
16//config: bool "touch (5.8 kb)" 16//config: bool "touch (5.9 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: touch is used to create or change the access and/or 19//config: touch is used to create or change the access and/or
diff --git a/coreutils/tr.c b/coreutils/tr.c
index 10284e1c9..ae35a9ee3 100644
--- a/coreutils/tr.c
+++ b/coreutils/tr.c
@@ -19,7 +19,7 @@
19 * TODO: graph, print 19 * TODO: graph, print
20 */ 20 */
21//config:config TR 21//config:config TR
22//config: bool "tr (5.5 kb)" 22//config: bool "tr (5.1 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: tr is used to squeeze, and/or delete characters from standard 25//config: tr is used to squeeze, and/or delete characters from standard
diff --git a/coreutils/truncate.c b/coreutils/truncate.c
index f693570aa..233d0f2d1 100644
--- a/coreutils/truncate.c
+++ b/coreutils/truncate.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config TRUNCATE 8//config:config TRUNCATE
9//config: bool "truncate (4.7 kb)" 9//config: bool "truncate (4.2 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: truncate truncates files to a given size. If a file does 12//config: truncate truncates files to a given size. If a file does
diff --git a/coreutils/tty.c b/coreutils/tty.c
index 18ad7c566..ff6f2bb3b 100644
--- a/coreutils/tty.c
+++ b/coreutils/tty.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config TTY 9//config:config TTY
10//config: bool "tty (3.3 kb)" 10//config: bool "tty (3.6 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: tty is used to print the name of the current terminal to 13//config: tty is used to print the name of the current terminal to
diff --git a/coreutils/uname.c b/coreutils/uname.c
index 765809658..2a1602b4c 100644
--- a/coreutils/uname.c
+++ b/coreutils/uname.c
@@ -44,7 +44,7 @@
44 * Fix handling of -a to not print "unknown", add -o and -i support. 44 * Fix handling of -a to not print "unknown", add -o and -i support.
45 */ 45 */
46//config:config UNAME 46//config:config UNAME
47//config: bool "uname (3.7 kb)" 47//config: bool "uname (3.9 kb)"
48//config: default y 48//config: default y
49//config: help 49//config: help
50//config: uname is used to print system information. 50//config: uname is used to print system information.
@@ -59,7 +59,7 @@
59//config: 59//config:
60//can't use "ARCH" for this applet, all hell breaks loose in build system :) 60//can't use "ARCH" for this applet, all hell breaks loose in build system :)
61//config:config BB_ARCH 61//config:config BB_ARCH
62//config: bool "arch (1.6 kb)" 62//config: bool "arch (1.1 kb)"
63//config: default y 63//config: default y
64//config: help 64//config: help
65//config: Same as uname -m. 65//config: Same as uname -m.
diff --git a/coreutils/uniq.c b/coreutils/uniq.c
index f71557b67..317f45531 100644
--- a/coreutils/uniq.c
+++ b/coreutils/uniq.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config UNIQ 9//config:config UNIQ
10//config: bool "uniq (4.8 kb)" 10//config: bool "uniq (4.9 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: uniq is used to remove duplicate lines from a sorted file. 13//config: uniq is used to remove duplicate lines from a sorted file.
diff --git a/coreutils/unlink.c b/coreutils/unlink.c
index 61b108a84..24be81da6 100644
--- a/coreutils/unlink.c
+++ b/coreutils/unlink.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see LICENSE in this source tree 7 * Licensed under GPLv2, see LICENSE in this source tree
8 */ 8 */
9//config:config UNLINK 9//config:config UNLINK
10//config: bool "unlink (3.5 kb)" 10//config: bool "unlink (3.2 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: unlink deletes a file by calling unlink() 13//config: unlink deletes a file by calling unlink()
diff --git a/coreutils/usleep.c b/coreutils/usleep.c
index 684ab781b..51a015c44 100644
--- a/coreutils/usleep.c
+++ b/coreutils/usleep.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config USLEEP 9//config:config USLEEP
10//config: bool "usleep (1.1 kb)" 10//config: bool "usleep (1.3 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: usleep is used to pause for a specified number of microseconds. 13//config: usleep is used to pause for a specified number of microseconds.
diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c
index 5ef05ee4d..5f69e62b3 100644
--- a/coreutils/uudecode.c
+++ b/coreutils/uudecode.c
@@ -11,7 +11,7 @@
11 * "end" line 11 * "end" line
12 */ 12 */
13//config:config UUDECODE 13//config:config UUDECODE
14//config: bool "uudecode (5.9 kb)" 14//config: bool "uudecode (5.8 kb)"
15//config: default y 15//config: default y
16//config: help 16//config: help
17//config: uudecode is used to decode a uuencoded file. 17//config: uudecode is used to decode a uuencoded file.
@@ -175,7 +175,7 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv)
175//kbuild:lib-$(CONFIG_BASE64) += uudecode.o 175//kbuild:lib-$(CONFIG_BASE64) += uudecode.o
176 176
177//config:config BASE64 177//config:config BASE64
178//config: bool "base64 (5 kb)" 178//config: bool "base64 (4.9 kb)"
179//config: default y 179//config: default y
180//config: help 180//config: help
181//config: Base64 encode and decode 181//config: Base64 encode and decode
diff --git a/coreutils/uuencode.c b/coreutils/uuencode.c
index aa53b14a6..2807ef82a 100644
--- a/coreutils/uuencode.c
+++ b/coreutils/uuencode.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config UUENCODE 10//config:config UUENCODE
11//config: bool "uuencode (4.6 kb)" 11//config: bool "uuencode (4.4 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: uuencode is used to uuencode a file. 14//config: uuencode is used to uuencode a file.
diff --git a/coreutils/wc.c b/coreutils/wc.c
index c74b7a65f..99eb9dc87 100644
--- a/coreutils/wc.c
+++ b/coreutils/wc.c
@@ -33,7 +33,7 @@
33 * for which 'wc -c' should output '0'. 33 * for which 'wc -c' should output '0'.
34 */ 34 */
35//config:config WC 35//config:config WC
36//config: bool "wc (4.4 kb)" 36//config: bool "wc (4.5 kb)"
37//config: default y 37//config: default y
38//config: help 38//config: help
39//config: wc is used to print the number of bytes, words, and lines, 39//config: wc is used to print the number of bytes, words, and lines,
diff --git a/coreutils/who.c b/coreutils/who.c
index 80226c3d6..be9c3ccca 100644
--- a/coreutils/who.c
+++ b/coreutils/who.c
@@ -15,7 +15,7 @@
15 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 15 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
16 */ 16 */
17//config:config WHO 17//config:config WHO
18//config: bool "who (3.7 kb)" 18//config: bool "who (3.9 kb)"
19//config: default y 19//config: default y
20//config: depends on FEATURE_UTMP 20//config: depends on FEATURE_UTMP
21//config: help 21//config: help
@@ -23,14 +23,14 @@
23//config: 23//config:
24// procps-ng has this variation of "who": 24// procps-ng has this variation of "who":
25//config:config W 25//config:config W
26//config: bool "w (3.7 kb)" 26//config: bool "w (3.8 kb)"
27//config: default y 27//config: default y
28//config: depends on FEATURE_UTMP 28//config: depends on FEATURE_UTMP
29//config: help 29//config: help
30//config: Print users currently logged on. 30//config: Print users currently logged on.
31//config: 31//config:
32//config:config USERS 32//config:config USERS
33//config: bool "users (3.2 kb)" 33//config: bool "users (3.4 kb)"
34//config: default y 34//config: default y
35//config: depends on FEATURE_UTMP 35//config: depends on FEATURE_UTMP
36//config: help 36//config: help
diff --git a/coreutils/whoami.c b/coreutils/whoami.c
index 9dab15817..49b5dd368 100644
--- a/coreutils/whoami.c
+++ b/coreutils/whoami.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config WHOAMI 9//config:config WHOAMI
10//config: bool "whoami (2.9 kb)" 10//config: bool "whoami (3.2 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: whoami is used to print the username of the current 13//config: whoami is used to print the username of the current
diff --git a/coreutils/yes.c b/coreutils/yes.c
index 6dc47355e..a51b1ad8e 100644
--- a/coreutils/yes.c
+++ b/coreutils/yes.c
@@ -11,7 +11,7 @@
11 * Size reductions and removed redundant applet name prefix from error messages. 11 * Size reductions and removed redundant applet name prefix from error messages.
12 */ 12 */
13//config:config YES 13//config:config YES
14//config: bool "yes (956 bytes)" 14//config: bool "yes (1.2 kb)"
15//config: default y 15//config: default y
16//config: help 16//config: help
17//config: yes is used to repeatedly output a specific string, or 17//config: yes is used to repeatedly output a specific string, or
diff --git a/debianutils/pipe_progress.c b/debianutils/pipe_progress.c
index 8aa892e3c..fd08a145e 100644
--- a/debianutils/pipe_progress.c
+++ b/debianutils/pipe_progress.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config PIPE_PROGRESS 9//config:config PIPE_PROGRESS
10//config: bool "pipe_progress (225 bytes)" 10//config: bool "pipe_progress (275 bytes)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Display a dot to indicate pipe activity. 13//config: Display a dot to indicate pipe activity.
diff --git a/debianutils/run_parts.c b/debianutils/run_parts.c
index e4d61df35..c80cc863f 100644
--- a/debianutils/run_parts.c
+++ b/debianutils/run_parts.c
@@ -23,7 +23,7 @@
23 * broken compatibility because the BusyBox policy doesn't allow them. 23 * broken compatibility because the BusyBox policy doesn't allow them.
24 */ 24 */
25//config:config RUN_PARTS 25//config:config RUN_PARTS
26//config: bool "run-parts (5.6 kb)" 26//config: bool "run-parts (6.1 kb)"
27//config: default y 27//config: default y
28//config: help 28//config: help
29//config: run-parts is a utility designed to run all the scripts in a directory. 29//config: run-parts is a utility designed to run all the scripts in a directory.
diff --git a/debianutils/which.c b/debianutils/which.c
index 9b10b62f9..14d452cd5 100644
--- a/debianutils/which.c
+++ b/debianutils/which.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config WHICH 8//config:config WHICH
9//config: bool "which (3.7 kb)" 9//config: bool "which (3.8 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: which is used to find programs in your PATH and 12//config: which is used to find programs in your PATH and
diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c
index 76a5253b6..c93e209b5 100644
--- a/e2fsprogs/chattr.c
+++ b/e2fsprogs/chattr.c
@@ -10,7 +10,7 @@
10 * Public License 10 * Public License
11 */ 11 */
12//config:config CHATTR 12//config:config CHATTR
13//config: bool "chattr (3.2 kb)" 13//config: bool "chattr (3.8 kb)"
14//config: default y 14//config: default y
15//config: help 15//config: help
16//config: chattr changes the file attributes on a second extended file system. 16//config: chattr changes the file attributes on a second extended file system.
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c
index f5aa3dbe4..8a14b3bdc 100644
--- a/e2fsprogs/fsck.c
+++ b/e2fsprogs/fsck.c
@@ -34,7 +34,7 @@
34 * It doesn't guess filesystem types from on-disk format. 34 * It doesn't guess filesystem types from on-disk format.
35 */ 35 */
36//config:config FSCK 36//config:config FSCK
37//config: bool "fsck (6.7 kb)" 37//config: bool "fsck (7.4 kb)"
38//config: default y 38//config: default y
39//config: help 39//config: help
40//config: fsck is used to check and optionally repair one or more filesystems. 40//config: fsck is used to check and optionally repair one or more filesystems.
diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c
index 56c1187c1..be1488b79 100644
--- a/e2fsprogs/lsattr.c
+++ b/e2fsprogs/lsattr.c
@@ -10,7 +10,7 @@
10 * Public License 10 * Public License
11 */ 11 */
12//config:config LSATTR 12//config:config LSATTR
13//config: bool "lsattr (5 kb)" 13//config: bool "lsattr (5.5 kb)"
14//config: default y 14//config: default y
15//config: select PLATFORM_LINUX 15//config: select PLATFORM_LINUX
16//config: help 16//config: help
diff --git a/editors/awk.c b/editors/awk.c
index 8e79d3159..17bbdc62a 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config AWK 9//config:config AWK
10//config: bool "awk (22 kb)" 10//config: bool "awk (23 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Awk is used as a pattern scanning and processing language. 13//config: Awk is used as a pattern scanning and processing language.
diff --git a/editors/cmp.c b/editors/cmp.c
index 2a410fdec..6e27a841a 100644
--- a/editors/cmp.c
+++ b/editors/cmp.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config CMP 9//config:config CMP
10//config: bool "cmp (5.4 kb)" 10//config: bool "cmp (4.9 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: cmp is used to compare two files and returns the result 13//config: cmp is used to compare two files and returns the result
diff --git a/editors/ed.c b/editors/ed.c
index 05797692c..1a36add39 100644
--- a/editors/ed.c
+++ b/editors/ed.c
@@ -7,7 +7,7 @@
7 * The "ed" built-in command (much simplified) 7 * The "ed" built-in command (much simplified)
8 */ 8 */
9//config:config ED 9//config:config ED
10//config: bool "ed (25 kb)" 10//config: bool "ed (21 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: The original 1970's Unix text editor, from the days of teletypes. 13//config: The original 1970's Unix text editor, from the days of teletypes.
diff --git a/editors/patch.c b/editors/patch.c
index eca6bc5f6..0ce0210fd 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -21,7 +21,7 @@
21 * [file] which file to patch 21 * [file] which file to patch
22 */ 22 */
23//config:config PATCH 23//config:config PATCH
24//config: bool "patch (9.1 kb)" 24//config: bool "patch (9.4 kb)"
25//config: default y 25//config: default y
26//config: help 26//config: help
27//config: Apply a unified diff formatted patch. 27//config: Apply a unified diff formatted patch.
diff --git a/editors/patch_toybox.c b/editors/patch_toybox.c
index 2c958d287..3ffbf9084 100644
--- a/editors/patch_toybox.c
+++ b/editors/patch_toybox.c
@@ -26,7 +26,7 @@
26USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"up#i:R", TOYFLAG_USR|TOYFLAG_BIN)) 26USE_PATCH(NEWTOY(patch, USE_TOYBOX_DEBUG("x")"up#i:R", TOYFLAG_USR|TOYFLAG_BIN))
27 27
28config PATCH 28config PATCH
29 bool "patch (9.1 kb)" 29 bool "patch (9.4 kb)"
30 default y 30 default y
31 help 31 help
32 usage: patch [-i file] [-p depth] [-Ru] 32 usage: patch [-i file] [-p depth] [-Ru]
diff --git a/editors/vi.c b/editors/vi.c
index 57fac59ad..433a37908 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -19,7 +19,7 @@
19 * An "ex" line oriented mode- maybe using "cmdedit" 19 * An "ex" line oriented mode- maybe using "cmdedit"
20 */ 20 */
21//config:config VI 21//config:config VI
22//config: bool "vi (22 kb)" 22//config: bool "vi (23 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: 'vi' is a text editor. More specifically, it is the One True 25//config: 'vi' is a text editor. More specifically, it is the One True
diff --git a/findutils/find.c b/findutils/find.c
index 6407c6c5a..06ad1b39c 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -1467,6 +1467,12 @@ int find_main(int argc UNUSED_PARAM, char **argv)
1467 break; 1467 break;
1468 if (!saved[1]) 1468 if (!saved[1])
1469 break; /* it is "-" */ 1469 break; /* it is "-" */
1470 if (saved[1] == '-' && !saved[2]) {
1471 /* it is "--" */
1472 /* Try: find -- /dev/null */
1473 saved = *++past_HLP;
1474 break;
1475 }
1470 if ((saved+1)[strspn(saved+1, "HLP")] != '\0') 1476 if ((saved+1)[strspn(saved+1, "HLP")] != '\0')
1471 break; 1477 break;
1472 } 1478 }
diff --git a/findutils/grep.c b/findutils/grep.c
index 3e8ea9239..a4033a40b 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -18,19 +18,19 @@
18 * (C) 2006 Jac Goudsmit added -o option 18 * (C) 2006 Jac Goudsmit added -o option
19 */ 19 */
20//config:config GREP 20//config:config GREP
21//config: bool "grep (8.5 kb)" 21//config: bool "grep (8.6 kb)"
22//config: default y 22//config: default y
23//config: help 23//config: help
24//config: grep is used to search files for a specified pattern. 24//config: grep is used to search files for a specified pattern.
25//config: 25//config:
26//config:config EGREP 26//config:config EGREP
27//config: bool "egrep (7.6 kb)" 27//config: bool "egrep (7.8 kb)"
28//config: default y 28//config: default y
29//config: help 29//config: help
30//config: Alias to "grep -E". 30//config: Alias to "grep -E".
31//config: 31//config:
32//config:config FGREP 32//config:config FGREP
33//config: bool "fgrep (7.6 kb)" 33//config: bool "fgrep (7.8 kb)"
34//config: default y 34//config: default y
35//config: help 35//config: help
36//config: Alias to "grep -F". 36//config: Alias to "grep -F".
diff --git a/findutils/xargs.c b/findutils/xargs.c
index 6df8a035d..d014669bd 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -15,7 +15,7 @@
15 * http://www.opengroup.org/onlinepubs/007904975/utilities/xargs.html 15 * http://www.opengroup.org/onlinepubs/007904975/utilities/xargs.html
16 */ 16 */
17//config:config XARGS 17//config:config XARGS
18//config: bool "xargs (6.7 kb)" 18//config: bool "xargs (7.2 kb)"
19//config: default y 19//config: default y
20//config: help 20//config: help
21//config: xargs is used to execute a specified command for 21//config: xargs is used to execute a specified command for
diff --git a/include/libbb.h b/include/libbb.h
index dc1c81865..1b5994357 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -579,6 +579,8 @@ void sig_unblock(int sig) FAST_FUNC;
579int sigaction_set(int sig, const struct sigaction *act) FAST_FUNC; 579int sigaction_set(int sig, const struct sigaction *act) FAST_FUNC;
580/* SIG_BLOCK/SIG_UNBLOCK all signals: */ 580/* SIG_BLOCK/SIG_UNBLOCK all signals: */
581int sigprocmask_allsigs(int how) FAST_FUNC; 581int sigprocmask_allsigs(int how) FAST_FUNC;
582/* Return old set in the same set: */
583int sigprocmask2(int how, sigset_t *set) FAST_FUNC;
582#else 584#else
583#define bb_signals(s, f) 585#define bb_signals(s, f)
584#define kill_myself_with_sig(s) 586#define kill_myself_with_sig(s)
@@ -1835,7 +1837,7 @@ enum {
1835 FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION, 1837 FOR_SHELL = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION,
1836}; 1838};
1837line_input_t *new_line_input_t(int flags) FAST_FUNC; 1839line_input_t *new_line_input_t(int flags) FAST_FUNC;
1838/* So far static: void free_line_input_t(line_input_t *n) FAST_FUNC; */ 1840void free_line_input_t(line_input_t *n) FAST_FUNC;
1839/* 1841/*
1840 * maxsize must be >= 2. 1842 * maxsize must be >= 2.
1841 * Returns: 1843 * Returns:
@@ -1875,7 +1877,12 @@ struct smaprec {
1875 unsigned long stack; 1877 unsigned long stack;
1876 unsigned long smap_pss, smap_swap; 1878 unsigned long smap_pss, smap_swap;
1877 unsigned long smap_size; 1879 unsigned long smap_size;
1878 unsigned long smap_start; 1880 // For mixed 32/64 userspace, 32-bit pmap still needs
1881 // 64-bit field here to correctly show 64-bit processes:
1882 unsigned long long smap_start;
1883 // (strictly speaking, other fields need to be wider too,
1884 // but they are in kbytes, not bytes, and they hold sizes,
1885 // not start addresses, sizes tend to be less than 4 terabytes)
1879 char smap_mode[5]; 1886 char smap_mode[5];
1880 char *smap_name; 1887 char *smap_name;
1881}; 1888};
diff --git a/init/bootchartd.c b/init/bootchartd.c
index 373cde2d8..4377d90e3 100644
--- a/init/bootchartd.c
+++ b/init/bootchartd.c
@@ -23,7 +23,7 @@
23//config: help 23//config: help
24//config: Create extended header file compatible with "big" bootchartd. 24//config: Create extended header file compatible with "big" bootchartd.
25//config: "Big" bootchartd is a shell script and it dumps some 25//config: "Big" bootchartd is a shell script and it dumps some
26//config: "convenient" info int the header, such as: 26//config: "convenient" info into the header, such as:
27//config: title = Boot chart for `hostname` (`date`) 27//config: title = Boot chart for `hostname` (`date`)
28//config: system.uname = `uname -srvm` 28//config: system.uname = `uname -srvm`
29//config: system.release = `cat /etc/DISTRO-release` 29//config: system.release = `cat /etc/DISTRO-release`
diff --git a/init/halt.c b/init/halt.c
index e6dcb1c67..785c38130 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -7,19 +7,19 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config HALT 9//config:config HALT
10//config: bool "halt (3.7 kb)" 10//config: bool "halt (4 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Stop all processes and halt the system. 13//config: Stop all processes and halt the system.
14//config: 14//config:
15//config:config POWEROFF 15//config:config POWEROFF
16//config: bool "poweroff (3.7 kb)" 16//config: bool "poweroff (4 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: Stop all processes and power off the system. 19//config: Stop all processes and power off the system.
20//config: 20//config:
21//config:config REBOOT 21//config:config REBOOT
22//config: bool "reboot (3.7 kb)" 22//config: bool "reboot (4 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: Stop all processes and reboot the system. 25//config: Stop all processes and reboot the system.
diff --git a/init/init.c b/init/init.c
index fde35f6b6..87086b48b 100644
--- a/init/init.c
+++ b/init/init.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config INIT 11//config:config INIT
12//config: bool "init (9.3 kb)" 12//config: bool "init (10 kb)"
13//config: default y 13//config: default y
14//config: select FEATURE_SYSLOG 14//config: select FEATURE_SYSLOG
15//config: help 15//config: help
diff --git a/klibc-utils/nuke.c b/klibc-utils/nuke.c
index 60a5f7145..d7c16f5cf 100644
--- a/klibc-utils/nuke.c
+++ b/klibc-utils/nuke.c
@@ -4,7 +4,7 @@
4 * Licensed under GPLv2, see file LICENSE in this source tree. 4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */ 5 */
6//config:config NUKE 6//config:config NUKE
7//config: bool "nuke (2.4 kb)" 7//config: bool "nuke (2.9 kb)"
8//config: default y 8//config: default y
9//config: help 9//config: help
10//config: Alias to "rm -rf". 10//config: Alias to "rm -rf".
diff --git a/klibc-utils/resume.c b/klibc-utils/resume.c
index 3424f076b..2bf50f9b8 100644
--- a/klibc-utils/resume.c
+++ b/klibc-utils/resume.c
@@ -4,7 +4,7 @@
4 * Licensed under GPLv2, see file LICENSE in this source tree. 4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */ 5 */
6//config:config RESUME 6//config:config RESUME
7//config: bool "resume (3.3 kb)" 7//config: bool "resume (3.2 kb)"
8//config: default y 8//config: default y
9//config: help 9//config: help
10//config: Resume from saved "suspend-to-disk" image 10//config: Resume from saved "suspend-to-disk" image
diff --git a/klibc-utils/run-init.c b/klibc-utils/run-init.c
index 61c16fd0b..77fc0e60c 100644
--- a/klibc-utils/run-init.c
+++ b/klibc-utils/run-init.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2, see file LICENSE in this source tree. 6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */ 7 */
8//config:config RUN_INIT 8//config:config RUN_INIT
9//config: bool "run-init (7.5 kb)" 9//config: bool "run-init (7.7 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX 11//config: select PLATFORM_LINUX
12//config: help 12//config: help
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 3ff2b5dc6..8efb1754a 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -134,16 +134,16 @@ void FAST_FUNC bb_show_usage(void)
134{ 134{
135 if (ENABLE_SHOW_USAGE) { 135 if (ENABLE_SHOW_USAGE) {
136#ifdef SINGLE_APPLET_STR 136#ifdef SINGLE_APPLET_STR
137 /* Imagine that this applet is "true". Dont suck in printf! */ 137 /* Imagine that this applet is "true". Dont link in printf! */
138 const char *usage_string = unpack_usage_messages(); 138 const char *usage_string = unpack_usage_messages();
139 139
140 if (usage_string) { 140 if (usage_string) {
141 if (*usage_string == '\b') { 141 if (*usage_string == '\b') {
142 full_write2_str("No help available.\n\n"); 142 full_write2_str("No help available\n");
143 } else { 143 } else {
144 full_write2_str("Usage: "SINGLE_APPLET_STR" "); 144 full_write2_str("Usage: "SINGLE_APPLET_STR" ");
145 full_write2_str(usage_string); 145 full_write2_str(usage_string);
146 full_write2_str("\n\n"); 146 full_write2_str("\n");
147 } 147 }
148 if (ENABLE_FEATURE_CLEAN_UP) 148 if (ENABLE_FEATURE_CLEAN_UP)
149 dealloc_usage_messages((char*)usage_string); 149 dealloc_usage_messages((char*)usage_string);
@@ -162,7 +162,7 @@ void FAST_FUNC bb_show_usage(void)
162 full_write2_str(bb_banner); 162 full_write2_str(bb_banner);
163 full_write2_str(" multi-call binary\n"); 163 full_write2_str(" multi-call binary\n");
164 if (*p == '\b') 164 if (*p == '\b')
165 full_write2_str("\nNo help available.\n\n"); 165 full_write2_str("\nNo help available\n");
166 else { 166 else {
167 full_write2_str("\nUsage: "); 167 full_write2_str("\nUsage: ");
168 full_write2_str(applet_name); 168 full_write2_str(applet_name);
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 11a77ec69..0b4e326d8 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -1444,6 +1444,16 @@ void FAST_FUNC show_history(const line_input_t *st)
1444 printf("%4d %s\n", i, st->history[i]); 1444 printf("%4d %s\n", i, st->history[i]);
1445} 1445}
1446 1446
1447void FAST_FUNC free_line_input_t(line_input_t *n)
1448{
1449# if ENABLE_FEATURE_EDITING_SAVEHISTORY
1450 int i = n->cnt_history;
1451 while (i > 0)
1452 free(n->history[--i]);
1453#endif
1454 free(n);
1455}
1456
1447# if ENABLE_FEATURE_EDITING_SAVEHISTORY 1457# if ENABLE_FEATURE_EDITING_SAVEHISTORY
1448/* We try to ensure that concurrent additions to the history 1458/* We try to ensure that concurrent additions to the history
1449 * do not overwrite each other. 1459 * do not overwrite each other.
@@ -1453,14 +1463,6 @@ void FAST_FUNC show_history(const line_input_t *st)
1453 * than configured MAX_HISTORY lines. 1463 * than configured MAX_HISTORY lines.
1454 */ 1464 */
1455 1465
1456static void free_line_input_t(line_input_t *n)
1457{
1458 int i = n->cnt_history;
1459 while (i > 0)
1460 free(n->history[--i]);
1461 free(n);
1462}
1463
1464/* state->flags is already checked to be nonzero */ 1466/* state->flags is already checked to be nonzero */
1465static void load_history(line_input_t *st_parm) 1467static void load_history(line_input_t *st_parm)
1466{ 1468{
@@ -2380,6 +2382,18 @@ static int32_t reverse_i_search(int timeout)
2380} 2382}
2381#endif 2383#endif
2382 2384
2385#if ENABLE_FEATURE_EDITING_WINCH
2386static void sigaction2(int sig, struct sigaction *act)
2387{
2388 // Grr... gcc 8.1.1:
2389 // "passing argument 3 to restrict-qualified parameter aliases with argument 2"
2390 // dance around that...
2391 struct sigaction *oact FIX_ALIASING;
2392 oact = act;
2393 sigaction(sig, act, oact);
2394}
2395#endif
2396
2383/* maxsize must be >= 2. 2397/* maxsize must be >= 2.
2384 * Returns: 2398 * Returns:
2385 * -1 on read errors or EOF, or on bare Ctrl-D, 2399 * -1 on read errors or EOF, or on bare Ctrl-D,
@@ -2500,7 +2514,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2500 /* Install window resize handler (NB: after *all* init is complete) */ 2514 /* Install window resize handler (NB: after *all* init is complete) */
2501 S.SIGWINCH_handler.sa_handler = win_changed; 2515 S.SIGWINCH_handler.sa_handler = win_changed;
2502 S.SIGWINCH_handler.sa_flags = SA_RESTART; 2516 S.SIGWINCH_handler.sa_flags = SA_RESTART;
2503 sigaction(SIGWINCH, &S.SIGWINCH_handler, &S.SIGWINCH_handler); 2517 sigaction2(SIGWINCH, &S.SIGWINCH_handler);
2504#endif 2518#endif
2505 read_key_buffer[0] = 0; 2519 read_key_buffer[0] = 0;
2506 while (1) { 2520 while (1) {
diff --git a/libbb/procps.c b/libbb/procps.c
index 2484ab2d9..e6892d7ff 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -121,11 +121,11 @@ void FAST_FUNC free_procps_scan(procps_status_t* sp)
121} 121}
122 122
123#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP 123#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP
124static unsigned long fast_strtoul_16(char **endptr) 124static unsigned long long fast_strtoull_16(char **endptr)
125{ 125{
126 unsigned char c; 126 unsigned char c;
127 char *str = *endptr; 127 char *str = *endptr;
128 unsigned long n = 0; 128 unsigned long long n = 0;
129 129
130 /* Need to stop on both ' ' and '\n' */ 130 /* Need to stop on both ' ' and '\n' */
131 while ((c = *str++) > ' ') { 131 while ((c = *str++) > ' ') {
@@ -239,8 +239,8 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
239 239
240 *tp = ' '; 240 *tp = ' ';
241 tp = buf; 241 tp = buf;
242 currec.smap_start = fast_strtoul_16(&tp); 242 currec.smap_start = fast_strtoull_16(&tp);
243 currec.smap_size = (fast_strtoul_16(&tp) - currec.smap_start) >> 10; 243 currec.smap_size = (fast_strtoull_16(&tp) - currec.smap_start) >> 10;
244 244
245 strncpy(currec.smap_mode, tp, sizeof(currec.smap_mode)-1); 245 strncpy(currec.smap_mode, tp, sizeof(currec.smap_mode)-1);
246 246
diff --git a/libbb/signals.c b/libbb/signals.c
index 3f589321c..d3d84ef6a 100644
--- a/libbb/signals.c
+++ b/libbb/signals.c
@@ -31,6 +31,16 @@ int FAST_FUNC sigprocmask_allsigs(int how)
31 return sigprocmask(how, &set, NULL); 31 return sigprocmask(how, &set, NULL);
32} 32}
33 33
34int FAST_FUNC sigprocmask2(int how, sigset_t *set)
35{
36 // Grr... gcc 8.1.1:
37 // "passing argument 3 to restrict-qualified parameter aliases with argument 2"
38 // dance around that...
39 sigset_t *oset FIX_ALIASING;
40 oset = set;
41 return sigprocmask(how, set, oset);
42}
43
34void FAST_FUNC bb_signals(int sigs, void (*f)(int)) 44void FAST_FUNC bb_signals(int sigs, void (*f)(int))
35{ 45{
36 int sig_no = 0; 46 int sig_no = 0;
diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c
index 6d03de254..b09555aae 100644
--- a/loginutils/add-remove-shell.c
+++ b/loginutils/add-remove-shell.c
@@ -8,13 +8,13 @@
8 * for details. 8 * for details.
9 */ 9 */
10//config:config ADD_SHELL 10//config:config ADD_SHELL
11//config: bool "add-shell (2.8 kb)" 11//config: bool "add-shell (3.1 kb)"
12//config: default y if DESKTOP 12//config: default y if DESKTOP
13//config: help 13//config: help
14//config: Add shells to /etc/shells. 14//config: Add shells to /etc/shells.
15//config: 15//config:
16//config:config REMOVE_SHELL 16//config:config REMOVE_SHELL
17//config: bool "remove-shell (2.7 kb)" 17//config: bool "remove-shell (3 kb)"
18//config: default y if DESKTOP 18//config: default y if DESKTOP
19//config: help 19//config: help
20//config: Remove shells from /etc/shells. 20//config: Remove shells from /etc/shells.
diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c
index 6839eafbd..baa961ff3 100644
--- a/loginutils/addgroup.c
+++ b/loginutils/addgroup.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config ADDGROUP 11//config:config ADDGROUP
12//config: bool "addgroup (8.2 kb)" 12//config: bool "addgroup (8.6 kb)"
13//config: default y 13//config: default y
14//config: select LONG_OPTS 14//config: select LONG_OPTS
15//config: help 15//config: help
diff --git a/loginutils/deluser.c b/loginutils/deluser.c
index 5ee22d4f1..d7e9327ba 100644
--- a/loginutils/deluser.c
+++ b/loginutils/deluser.c
@@ -9,13 +9,13 @@
9 * Licensed under GPLv2, see file LICENSE in this source tree. 9 * Licensed under GPLv2, see file LICENSE in this source tree.
10 */ 10 */
11//config:config DELUSER 11//config:config DELUSER
12//config: bool "deluser (8.4 kb)" 12//config: bool "deluser (9.1 kb)"
13//config: default y 13//config: default y
14//config: help 14//config: help
15//config: Utility for deleting a user account. 15//config: Utility for deleting a user account.
16//config: 16//config:
17//config:config DELGROUP 17//config:config DELGROUP
18//config: bool "delgroup (5.6 kb)" 18//config: bool "delgroup (6.4 kb)"
19//config: default y 19//config: default y
20//config: help 20//config: help
21//config: Utility for deleting a group account. 21//config: Utility for deleting a group account.
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
index 59f47fc7b..30e096460 100644
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -43,7 +43,7 @@
43static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo) 43static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo)
44{ 44{
45 char salt[MAX_PW_SALT_LEN]; 45 char salt[MAX_PW_SALT_LEN];
46 char *orig = (char*)""; 46 char *orig = NULL;
47 char *newp = NULL; 47 char *newp = NULL;
48 char *cp = NULL; 48 char *cp = NULL;
49 char *ret = NULL; /* failure so far */ 49 char *ret = NULL; /* failure so far */
@@ -51,7 +51,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo
51 if (myuid != 0 && pw->pw_passwd[0]) { 51 if (myuid != 0 && pw->pw_passwd[0]) {
52 char *encrypted; 52 char *encrypted;
53 53
54 orig = bb_ask_noecho_stdin("Old password: "); /* returns ptr to static */ 54 orig = bb_ask_noecho_stdin("Old password: "); /* returns malloced str */
55 if (!orig) 55 if (!orig)
56 goto err_ret; 56 goto err_ret;
57 encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */ 57 encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */
@@ -64,11 +64,11 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo
64 if (ENABLE_FEATURE_CLEAN_UP) 64 if (ENABLE_FEATURE_CLEAN_UP)
65 free(encrypted); 65 free(encrypted);
66 } 66 }
67 newp = bb_ask_noecho_stdin("New password: "); /* returns ptr to static */ 67 newp = bb_ask_noecho_stdin("New password: "); /* returns malloced str */
68 if (!newp) 68 if (!newp)
69 goto err_ret; 69 goto err_ret;
70 if (ENABLE_FEATURE_PASSWD_WEAK_CHECK 70 if (ENABLE_FEATURE_PASSWD_WEAK_CHECK
71 && obscure(orig, newp, pw) 71 && obscure(orig, newp, pw) /* NB: passing NULL orig is ok */
72 && myuid != 0 72 && myuid != 0
73 ) { 73 ) {
74 goto err_ret; /* non-root is not allowed to have weak passwd */ 74 goto err_ret; /* non-root is not allowed to have weak passwd */
diff --git a/mailutils/makemime.c b/mailutils/makemime.c
index 7539d5134..53a1820f1 100644
--- a/mailutils/makemime.c
+++ b/mailutils/makemime.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config MAKEMIME 9//config:config MAKEMIME
10//config: bool "makemime (5.9 kb)" 10//config: bool "makemime (5.4 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Create MIME-formatted messages. 13//config: Create MIME-formatted messages.
diff --git a/make_single_applets.sh b/make_single_applets.sh
index aa1ace265..a37168cdf 100755
--- a/make_single_applets.sh
+++ b/make_single_applets.sh
@@ -27,6 +27,8 @@ allno="$cfg"
27for app in $apps; do 27for app in $apps; do
28 allno="`echo "$allno" | sed "s/^CONFIG_${app}=y\$/# CONFIG_${app} is not set/"`" 28 allno="`echo "$allno" | sed "s/^CONFIG_${app}=y\$/# CONFIG_${app} is not set/"`"
29done 29done
30# remove "busybox" as well
31allno="`echo "$allno" | sed "s/^CONFIG_BUSYBOX=y\$/# CONFIG_BUSYBOX is not set/"`"
30#echo "$allno" >.config_allno 32#echo "$allno" >.config_allno
31 33
32trap 'test -f .config.SV && mv .config.SV .config && touch .config' EXIT 34trap 'test -f .config.SV && mv .config.SV .config && touch .config' EXIT
@@ -70,6 +72,16 @@ for app; do
70 echo "NUM_APPLETS != 1 for ${app}: `cat include/NUM_APPLETS.h`" 72 echo "NUM_APPLETS != 1 for ${app}: `cat include/NUM_APPLETS.h`"
71 mv .config busybox_config_${app} 73 mv .config busybox_config_${app}
72 else 74 else
75 if grep -q 'use larger COMMON_BUFSIZE' busybox_make_${app}.log; then
76 # FEATURE_USE_BSS_TAIL=y is selected, and build system
77 # recommends rebuilding. Do so, and print some
78 # debug info to see whether it works right:
79 tail -n1 busybox_make_${app}.log
80 nm busybox_unstripped | grep ' _end'
81 make >/dev/null 2>&1
82 nm busybox_unstripped | grep ' _end'
83 grep ^bb_common_bufsiz1 busybox_unstripped.map
84 fi
73 grep -i -e error: -e warning: busybox_make_${app}.log \ 85 grep -i -e error: -e warning: busybox_make_${app}.log \
74 || rm busybox_make_${app}.log 86 || rm busybox_make_${app}.log
75 mv busybox busybox_${app} 87 mv busybox busybox_${app}
diff --git a/miscutils/adjtimex.c b/miscutils/adjtimex.c
index c1718e909..8ca90d58a 100644
--- a/miscutils/adjtimex.c
+++ b/miscutils/adjtimex.c
@@ -11,7 +11,7 @@
11 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 11 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
12 */ 12 */
13//config:config ADJTIMEX 13//config:config ADJTIMEX
14//config: bool "adjtimex (4.5 kb)" 14//config: bool "adjtimex (4.7 kb)"
15//config: default y 15//config: default y
16//config: select PLATFORM_LINUX 16//config: select PLATFORM_LINUX
17//config: help 17//config: help
diff --git a/miscutils/bc.c b/miscutils/bc.c
new file mode 100644
index 000000000..7fecb264d
--- /dev/null
+++ b/miscutils/bc.c
@@ -0,0 +1,7405 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4 * Adapted from https://github.com/gavinhoward/bc
5 * Original code copyright (c) 2018 Gavin D. Howard and contributors.
6 */
7//TODO: GNU extensions:
8// support "define f(*param[])" - "pass array by reference" syntax
9
10#define DEBUG_LEXER 0
11#define DEBUG_COMPILE 0
12#define DEBUG_EXEC 0
13// This can be left enabled for production as well:
14#define SANITY_CHECKS 1
15
16//config:config BC
17//config: bool "bc (45 kb)"
18//config: default y
19//config: select FEATURE_DC_BIG
20//config: help
21//config: bc is a command-line, arbitrary-precision calculator with a
22//config: Turing-complete language. See the GNU bc manual
23//config: (https://www.gnu.org/software/bc/manual/bc.html) and bc spec
24//config: (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html).
25//config:
26//config: This bc has five differences to the GNU bc:
27//config: 1) The period (.) is a shortcut for "last", as in the BSD bc.
28//config: 2) Arrays are copied before being passed as arguments to
29//config: functions. This behavior is required by the bc spec.
30//config: 3) Arrays can be passed to the builtin "length" function to get
31//config: the number of elements in the array. This prints "1":
32//config: a[0] = 0; length(a[])
33//config: 4) The precedence of the boolean "not" operator (!) is equal to
34//config: that of the unary minus (-) negation operator. This still
35//config: allows POSIX-compliant scripts to work while somewhat
36//config: preserving expected behavior (versus C) and making parsing
37//config: easier.
38//config: 5) "read()" accepts expressions, not only numeric literals.
39//config:
40//config:config DC
41//config: bool "dc (36 kb)"
42//config: default y
43//config: help
44//config: dc is a reverse-polish notation command-line calculator which
45//config: supports unlimited precision arithmetic. See the FreeBSD man page
46//config: (https://www.unix.com/man-page/FreeBSD/1/dc/) and GNU dc manual
47//config: (https://www.gnu.org/software/bc/manual/dc-1.05/html_mono/dc.html).
48//config:
49//config: This dc has a few differences from the two above:
50//config: 1) When printing a byte stream (command "P"), this dc follows what
51//config: the FreeBSD dc does.
52//config: 2) Implements the GNU extensions for divmod ("~") and
53//config: modular exponentiation ("|").
54//config: 3) Implements all FreeBSD extensions, except for "J" and "M".
55//config: 4) Like the FreeBSD dc, this dc supports extended registers.
56//config: However, they are implemented differently. When it encounters
57//config: whitespace where a register should be, it skips the whitespace.
58//config: If the character following is not a lowercase letter, an error
59//config: is issued. Otherwise, the register name is parsed by the
60//config: following regex: [a-z][a-z0-9_]*
61//config: This generally means that register names will be surrounded by
62//config: whitespace. Examples:
63//config: l idx s temp L index S temp2 < do_thing
64//config: Also note that, like the FreeBSD dc, extended registers are not
65//config: allowed unless the "-x" option is given.
66//config:
67//config:if BC || DC # for menuconfig indenting
68//config:
69//config:config FEATURE_DC_BIG
70//config: bool "Use bc code base for dc (larger, more features)"
71//config: default y
72//config:
73//config:config FEATURE_DC_LIBM
74//config: bool "Enable power and exp functions (requires libm)"
75//config: default y
76//config: depends on DC && !BC && !FEATURE_DC_BIG
77//config: help
78//config: Enable power and exp functions.
79//config: NOTE: This will require libm to be present for linking.
80//config:
81//config:config FEATURE_BC_INTERACTIVE
82//config: bool "Interactive mode (+4kb)"
83//config: default y
84//config: depends on BC || (DC && FEATURE_DC_BIG)
85//config: help
86//config: Enable interactive mode: when started on a tty,
87//config: ^C interrupts execution and returns to command line,
88//config: errors also return to command line instead of exiting,
89//config: line editing with history is available.
90//config:
91//config: With this option off, input can still be taken from tty,
92//config: but all errors are fatal, ^C is fatal,
93//config: tty is treated exactly the same as any other
94//config: standard input (IOW: no line editing).
95//config:
96//config:config FEATURE_BC_LONG_OPTIONS
97//config: bool "Enable bc/dc long options"
98//config: default y
99//config: depends on BC || (DC && FEATURE_DC_BIG)
100//config:
101//config:endif
102
103//applet:IF_BC(APPLET(bc, BB_DIR_USR_BIN, BB_SUID_DROP))
104//applet:IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP))
105
106//kbuild:lib-$(CONFIG_BC) += bc.o
107//kbuild:lib-$(CONFIG_DC) += bc.o
108
109//See www.gnu.org/software/bc/manual/bc.html
110//usage:#define bc_trivial_usage
111//usage: "[-sqlw] FILE..."
112//usage:
113//usage:#define bc_full_usage "\n"
114//usage: "\nArbitrary precision calculator"
115//usage: "\n"
116///////: "\n -i Interactive" - has no effect for now
117//usage: "\n -q Quiet"
118//usage: "\n -l Load standard math library"
119//usage: "\n -s Be POSIX compatible"
120//usage: "\n -w Warn if extensions are used"
121///////: "\n -v Version"
122//usage: "\n"
123//usage: "\n$BC_LINE_LENGTH changes output width"
124//usage:
125//usage:#define bc_example_usage
126//usage: "3 + 4.129\n"
127//usage: "1903 - 2893\n"
128//usage: "-129 * 213.28935\n"
129//usage: "12 / -1932\n"
130//usage: "12 % 12\n"
131//usage: "34 ^ 189\n"
132//usage: "scale = 13\n"
133//usage: "ibase = 2\n"
134//usage: "obase = A\n"
135//usage:
136//usage:#define dc_trivial_usage
137//usage: IF_FEATURE_DC_BIG("[-x] ")"[-eSCRIPT]... [-fFILE]... [FILE]..."
138//usage:
139//usage:#define dc_full_usage "\n"
140//usage: "\nTiny RPN calculator. Operations:"
141//usage: "\n+, -, *, /, %, ~, ^," IF_FEATURE_DC_BIG(" |,")
142//usage: "\np - print top of the stack without popping"
143//usage: "\nf - print entire stack"
144//usage: "\nk - pop the value and set the precision"
145//usage: "\ni - pop the value and set input radix"
146//usage: "\no - pop the value and set output radix"
147//usage: "\nExamples: dc -e'2 2 + p' -> 4, dc -e'8 8 * 2 2 + / p' -> 16"
148//usage:
149//usage:#define dc_example_usage
150//usage: "$ dc -e'2 2 + p'\n"
151//usage: "4\n"
152//usage: "$ dc -e'8 8 \\* 2 2 + / p'\n"
153//usage: "16\n"
154//usage: "$ dc -e'0 1 & p'\n"
155//usage: "0\n"
156//usage: "$ dc -e'0 1 | p'\n"
157//usage: "1\n"
158//usage: "$ echo '72 9 / 8 * p' | dc\n"
159//usage: "64\n"
160
161#include "libbb.h"
162#include "common_bufsiz.h"
163
164#if !ENABLE_BC && !ENABLE_FEATURE_DC_BIG
165# include "dc.c"
166#else
167
168#if DEBUG_LEXER
169static uint8_t lex_indent;
170#define dbg_lex(...) \
171 do { \
172 fprintf(stderr, "%*s", lex_indent, ""); \
173 bb_error_msg(__VA_ARGS__); \
174 } while (0)
175#define dbg_lex_enter(...) \
176 do { \
177 dbg_lex(__VA_ARGS__); \
178 lex_indent++; \
179 } while (0)
180#define dbg_lex_done(...) \
181 do { \
182 lex_indent--; \
183 dbg_lex(__VA_ARGS__); \
184 } while (0)
185#else
186# define dbg_lex(...) ((void)0)
187# define dbg_lex_enter(...) ((void)0)
188# define dbg_lex_done(...) ((void)0)
189#endif
190
191#if DEBUG_COMPILE
192# define dbg_compile(...) bb_error_msg(__VA_ARGS__)
193#else
194# define dbg_compile(...) ((void)0)
195#endif
196
197#if DEBUG_EXEC
198# define dbg_exec(...) bb_error_msg(__VA_ARGS__)
199#else
200# define dbg_exec(...) ((void)0)
201#endif
202
203typedef enum BcStatus {
204 BC_STATUS_SUCCESS = 0,
205 BC_STATUS_FAILURE = 1,
206} BcStatus;
207
208#define BC_VEC_INVALID_IDX ((size_t) -1)
209#define BC_VEC_START_CAP (1 << 5)
210
211typedef void (*BcVecFree)(void *) FAST_FUNC;
212
213typedef struct BcVec {
214 char *v;
215 size_t len;
216 size_t cap;
217 size_t size;
218 BcVecFree dtor;
219} BcVec;
220
221typedef signed char BcDig;
222
223typedef struct BcNum {
224 BcDig *restrict num;
225 size_t rdx;
226 size_t len;
227 size_t cap;
228 bool neg;
229} BcNum;
230
231#define BC_NUM_MAX_IBASE 36
232// larger value might speed up BIGNUM calculations a bit:
233#define BC_NUM_DEF_SIZE 16
234#define BC_NUM_PRINT_WIDTH 69
235
236#define BC_NUM_KARATSUBA_LEN 32
237
238typedef enum BcInst {
239#if ENABLE_BC
240 BC_INST_INC_PRE,
241 BC_INST_DEC_PRE,
242 BC_INST_INC_POST,
243 BC_INST_DEC_POST,
244#endif
245 XC_INST_NEG, // order
246
247 XC_INST_REL_EQ, // should
248 XC_INST_REL_LE, // match
249 XC_INST_REL_GE, // LEX
250 XC_INST_REL_NE, // constants
251 XC_INST_REL_LT, // for
252 XC_INST_REL_GT, // these
253
254 XC_INST_POWER, // operations
255 XC_INST_MULTIPLY, // |
256 XC_INST_DIVIDE, // |
257 XC_INST_MODULUS, // |
258 XC_INST_PLUS, // |
259 XC_INST_MINUS, // |
260
261 XC_INST_BOOL_NOT, // |
262 XC_INST_BOOL_OR, // |
263 XC_INST_BOOL_AND, // |
264#if ENABLE_BC
265 BC_INST_ASSIGN_POWER, // |
266 BC_INST_ASSIGN_MULTIPLY,// |
267 BC_INST_ASSIGN_DIVIDE, // |
268 BC_INST_ASSIGN_MODULUS, // |
269 BC_INST_ASSIGN_PLUS, // |
270 BC_INST_ASSIGN_MINUS, // |
271#endif
272 XC_INST_ASSIGN, // V
273
274 XC_INST_NUM,
275 XC_INST_VAR,
276 XC_INST_ARRAY_ELEM,
277 XC_INST_ARRAY,
278 XC_INST_SCALE_FUNC,
279
280 XC_INST_IBASE, // order of these constans should match other enums
281 XC_INST_OBASE, // order of these constans should match other enums
282 XC_INST_SCALE, // order of these constans should match other enums
283 IF_BC(BC_INST_LAST,) // order of these constans should match other enums
284 XC_INST_LENGTH,
285 XC_INST_READ,
286 XC_INST_SQRT,
287
288 XC_INST_PRINT,
289 XC_INST_PRINT_POP,
290 XC_INST_STR,
291 XC_INST_PRINT_STR,
292
293#if ENABLE_BC
294 BC_INST_HALT,
295 BC_INST_JUMP,
296 BC_INST_JUMP_ZERO,
297
298 BC_INST_CALL,
299 BC_INST_RET0,
300#endif
301 XC_INST_RET,
302
303 XC_INST_POP,
304#if ENABLE_DC
305 DC_INST_POP_EXEC,
306
307 DC_INST_MODEXP,
308 DC_INST_DIVMOD,
309
310 DC_INST_EXECUTE,
311 DC_INST_EXEC_COND,
312
313 DC_INST_ASCIIFY,
314 DC_INST_PRINT_STREAM,
315
316 DC_INST_PRINT_STACK,
317 DC_INST_CLEAR_STACK,
318 DC_INST_STACK_LEN,
319 DC_INST_DUPLICATE,
320 DC_INST_SWAP,
321
322 DC_INST_LOAD,
323 DC_INST_PUSH_VAR,
324 DC_INST_PUSH_TO_VAR,
325
326 DC_INST_QUIT,
327 DC_INST_NQUIT,
328
329 DC_INST_INVALID = -1,
330#endif
331} BcInst;
332
333typedef struct BcId {
334 char *name;
335 size_t idx;
336} BcId;
337
338typedef struct BcFunc {
339 BcVec code;
340 IF_BC(BcVec labels;)
341 IF_BC(BcVec autos;)
342 IF_BC(BcVec strs;)
343 IF_BC(BcVec consts;)
344 IF_BC(size_t nparams;)
345 IF_BC(bool voidfunc;)
346} BcFunc;
347
348typedef enum BcResultType {
349 XC_RESULT_TEMP,
350 IF_BC(BC_RESULT_VOID,) // same as TEMP, but INST_PRINT will ignore it
351
352 XC_RESULT_VAR,
353 XC_RESULT_ARRAY_ELEM,
354 XC_RESULT_ARRAY,
355
356 XC_RESULT_STR,
357
358 //code uses "inst - XC_INST_IBASE + XC_RESULT_IBASE" construct,
359 XC_RESULT_IBASE, // relative order should match for: XC_INST_IBASE
360 XC_RESULT_OBASE, // relative order should match for: XC_INST_OBASE
361 XC_RESULT_SCALE, // relative order should match for: XC_INST_SCALE
362 IF_BC(BC_RESULT_LAST,) // relative order should match for: BC_INST_LAST
363 XC_RESULT_CONSTANT,
364 IF_BC(BC_RESULT_ONE,)
365} BcResultType;
366
367typedef union BcResultData {
368 BcNum n;
369 BcVec v;
370 BcId id;
371} BcResultData;
372
373typedef struct BcResult {
374 BcResultType t;
375 BcResultData d;
376} BcResult;
377
378typedef struct BcInstPtr {
379 size_t func;
380 size_t inst_idx;
381} BcInstPtr;
382
383typedef enum BcLexType {
384 XC_LEX_EOF,
385 XC_LEX_INVALID,
386
387 XC_LEX_NLINE,
388 XC_LEX_WHITESPACE,
389 XC_LEX_STR,
390 XC_LEX_NAME,
391 XC_LEX_NUMBER,
392
393 XC_LEX_1st_op,
394 XC_LEX_NEG = XC_LEX_1st_op, // order
395
396 XC_LEX_OP_REL_EQ, // should
397 XC_LEX_OP_REL_LE, // match
398 XC_LEX_OP_REL_GE, // INST
399 XC_LEX_OP_REL_NE, // constants
400 XC_LEX_OP_REL_LT, // for
401 XC_LEX_OP_REL_GT, // these
402
403 XC_LEX_OP_POWER, // operations
404 XC_LEX_OP_MULTIPLY, // |
405 XC_LEX_OP_DIVIDE, // |
406 XC_LEX_OP_MODULUS, // |
407 XC_LEX_OP_PLUS, // |
408 XC_LEX_OP_MINUS, // |
409 XC_LEX_OP_last = XC_LEX_OP_MINUS,
410#if ENABLE_BC
411 BC_LEX_OP_BOOL_NOT, // |
412 BC_LEX_OP_BOOL_OR, // |
413 BC_LEX_OP_BOOL_AND, // |
414
415 BC_LEX_OP_ASSIGN_POWER, // |
416 BC_LEX_OP_ASSIGN_MULTIPLY, // |
417 BC_LEX_OP_ASSIGN_DIVIDE, // |
418 BC_LEX_OP_ASSIGN_MODULUS, // |
419 BC_LEX_OP_ASSIGN_PLUS, // |
420 BC_LEX_OP_ASSIGN_MINUS, // |
421
422 BC_LEX_OP_ASSIGN, // V
423
424 BC_LEX_OP_INC,
425 BC_LEX_OP_DEC,
426
427 BC_LEX_LPAREN, // () are 0x28 and 0x29
428 BC_LEX_RPAREN, // must be LPAREN+1: code uses (c - '(' + BC_LEX_LPAREN)
429
430 BC_LEX_LBRACKET, // [] are 0x5B and 0x5D
431 BC_LEX_COMMA,
432 BC_LEX_RBRACKET, // must be LBRACKET+2: code uses (c - '[' + BC_LEX_LBRACKET)
433
434 BC_LEX_LBRACE, // {} are 0x7B and 0x7D
435 BC_LEX_SCOLON,
436 BC_LEX_RBRACE, // must be LBRACE+2: code uses (c - '{' + BC_LEX_LBRACE)
437
438 BC_LEX_KEY_1st_keyword,
439 BC_LEX_KEY_AUTO = BC_LEX_KEY_1st_keyword,
440 BC_LEX_KEY_BREAK,
441 BC_LEX_KEY_CONTINUE,
442 BC_LEX_KEY_DEFINE,
443 BC_LEX_KEY_ELSE,
444 BC_LEX_KEY_FOR,
445 BC_LEX_KEY_HALT,
446 // code uses "type - BC_LEX_KEY_IBASE + XC_INST_IBASE" construct,
447 BC_LEX_KEY_IBASE, // relative order should match for: XC_INST_IBASE
448 BC_LEX_KEY_OBASE, // relative order should match for: XC_INST_OBASE
449 BC_LEX_KEY_IF,
450 BC_LEX_KEY_LAST, // relative order should match for: BC_INST_LAST
451 BC_LEX_KEY_LENGTH,
452 BC_LEX_KEY_LIMITS,
453 BC_LEX_KEY_PRINT,
454 BC_LEX_KEY_QUIT,
455 BC_LEX_KEY_READ,
456 BC_LEX_KEY_RETURN,
457 BC_LEX_KEY_SCALE,
458 BC_LEX_KEY_SQRT,
459 BC_LEX_KEY_WHILE,
460#endif // ENABLE_BC
461
462#if ENABLE_DC
463 DC_LEX_OP_BOOL_NOT = XC_LEX_OP_last + 1,
464 DC_LEX_OP_ASSIGN,
465
466 DC_LEX_LPAREN,
467 DC_LEX_SCOLON,
468 DC_LEX_READ,
469 DC_LEX_IBASE,
470 DC_LEX_SCALE,
471 DC_LEX_OBASE,
472 DC_LEX_LENGTH,
473 DC_LEX_PRINT,
474 DC_LEX_QUIT,
475 DC_LEX_SQRT,
476 DC_LEX_LBRACE,
477
478 DC_LEX_EQ_NO_REG,
479 DC_LEX_OP_MODEXP,
480 DC_LEX_OP_DIVMOD,
481
482 DC_LEX_COLON,
483 DC_LEX_ELSE,
484 DC_LEX_EXECUTE,
485 DC_LEX_PRINT_STACK,
486 DC_LEX_CLEAR_STACK,
487 DC_LEX_STACK_LEVEL,
488 DC_LEX_DUPLICATE,
489 DC_LEX_SWAP,
490 DC_LEX_POP,
491
492 DC_LEX_ASCIIFY,
493 DC_LEX_PRINT_STREAM,
494
495 // code uses "t - DC_LEX_STORE_IBASE + XC_INST_IBASE" construct,
496 DC_LEX_STORE_IBASE, // relative order should match for: XC_INST_IBASE
497 DC_LEX_STORE_OBASE, // relative order should match for: XC_INST_OBASE
498 DC_LEX_STORE_SCALE, // relative order should match for: XC_INST_SCALE
499 DC_LEX_LOAD,
500 DC_LEX_LOAD_POP,
501 DC_LEX_STORE_PUSH,
502 DC_LEX_PRINT_POP,
503 DC_LEX_NQUIT,
504 DC_LEX_SCALE_FACTOR,
505#endif
506} BcLexType;
507// must match order of BC_LEX_KEY_foo etc above
508#if ENABLE_BC
509struct BcLexKeyword {
510 char name8[8];
511};
512#define LEX_KW_ENTRY(a, b) \
513 { .name8 = a /*, .posix = b */ }
514static const struct BcLexKeyword bc_lex_kws[20] = {
515 LEX_KW_ENTRY("auto" , 1), // 0
516 LEX_KW_ENTRY("break" , 1), // 1
517 LEX_KW_ENTRY("continue", 0), // 2 note: this one has no terminating NUL
518 LEX_KW_ENTRY("define" , 1), // 3
519 LEX_KW_ENTRY("else" , 0), // 4
520 LEX_KW_ENTRY("for" , 1), // 5
521 LEX_KW_ENTRY("halt" , 0), // 6
522 LEX_KW_ENTRY("ibase" , 1), // 7
523 LEX_KW_ENTRY("obase" , 1), // 8
524 LEX_KW_ENTRY("if" , 1), // 9
525 LEX_KW_ENTRY("last" , 0), // 10
526 LEX_KW_ENTRY("length" , 1), // 11
527 LEX_KW_ENTRY("limits" , 0), // 12
528 LEX_KW_ENTRY("print" , 0), // 13
529 LEX_KW_ENTRY("quit" , 1), // 14
530 LEX_KW_ENTRY("read" , 0), // 15
531 LEX_KW_ENTRY("return" , 1), // 16
532 LEX_KW_ENTRY("scale" , 1), // 17
533 LEX_KW_ENTRY("sqrt" , 1), // 18
534 LEX_KW_ENTRY("while" , 1), // 19
535};
536#undef LEX_KW_ENTRY
537#define STRING_else (bc_lex_kws[4].name8)
538#define STRING_for (bc_lex_kws[5].name8)
539#define STRING_if (bc_lex_kws[9].name8)
540#define STRING_while (bc_lex_kws[19].name8)
541enum {
542 POSIX_KWORD_MASK = 0
543 | (1 << 0) // 0
544 | (1 << 1) // 1
545 | (0 << 2) // 2
546 | (1 << 3) // 3
547 | (0 << 4) // 4
548 | (1 << 5) // 5
549 | (0 << 6) // 6
550 | (1 << 7) // 7
551 | (1 << 8) // 8
552 | (1 << 9) // 9
553 | (0 << 10) // 10
554 | (1 << 11) // 11
555 | (0 << 12) // 12
556 | (0 << 13) // 13
557 | (1 << 14) // 14
558 | (0 << 15) // 15
559 | (1 << 16) // 16
560 | (1 << 17) // 17
561 | (1 << 18) // 18
562 | (1 << 19) // 19
563};
564#define keyword_is_POSIX(i) ((1 << (i)) & POSIX_KWORD_MASK)
565
566// This is a bit array that corresponds to token types. An entry is
567// true if the token is valid in an expression, false otherwise.
568// Used to figure out when expr parsing should stop *without error message*
569// - 0 element indicates this condition. 1 means "this token is to be eaten
570// as part of the expression", it can then still be determined to be invalid
571// by later processing.
572enum {
573#define EXBITS(a,b,c,d,e,f,g,h) \
574 ((uint64_t)((a << 0)+(b << 1)+(c << 2)+(d << 3)+(e << 4)+(f << 5)+(g << 6)+(h << 7)))
575 BC_PARSE_EXPRS_BITS = 0 // corresponding BC_LEX_xyz:
576 + (EXBITS(0,0,0,0,0,1,1,1) << (0*8)) // 0: EOF INVAL NL WS STR NAME NUM -
577 + (EXBITS(1,1,1,1,1,1,1,1) << (1*8)) // 8: == <= >= != < > ^ *
578 + (EXBITS(1,1,1,1,1,1,1,1) << (2*8)) // 16: / % + - ! || && ^=
579 + (EXBITS(1,1,1,1,1,1,1,1) << (3*8)) // 24: *= /= %= += -= = ++ --
580 + (EXBITS(1,1,0,0,0,0,0,0) << (4*8)) // 32: ( ) [ , ] { ; }
581 + (EXBITS(0,0,0,0,0,0,0,1) << (5*8)) // 40: auto break cont define else for halt ibase
582 + (EXBITS(1,0,1,1,0,0,0,1) << (6*8)) // 48: obase if last length limits print quit read
583 + (EXBITS(0,1,1,0,0,0,0,0) << (7*8)) // 56: return scale sqrt while
584#undef EXBITS
585};
586static ALWAYS_INLINE long lex_allowed_in_bc_expr(unsigned i)
587{
588#if ULONG_MAX > 0xffffffff
589 // 64-bit version (will not work correctly for 32-bit longs!)
590 return BC_PARSE_EXPRS_BITS & (1UL << i);
591#else
592 // 32-bit version
593 unsigned long m = (uint32_t)BC_PARSE_EXPRS_BITS;
594 if (i >= 32) {
595 m = (uint32_t)(BC_PARSE_EXPRS_BITS >> 32);
596 i &= 31;
597 }
598 return m & (1UL << i);
599#endif
600}
601
602// This is an array of data for operators that correspond to
603// [XC_LEX_1st_op...] token types.
604static const uint8_t bc_ops_prec_and_assoc[] ALIGN1 = {
605#define OP(p,l) ((int)(l) * 0x10 + (p))
606 OP(1, false), // neg
607 OP(6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), OP( 6, true ), // == <= >= != < >
608 OP(2, false), // pow
609 OP(3, true ), OP( 3, true ), OP( 3, true ), // mul div mod
610 OP(4, true ), OP( 4, true ), // + -
611 OP(1, false), // not
612 OP(7, true ), OP( 7, true ), // or and
613 OP(5, false), OP( 5, false ), OP( 5, false ), OP( 5, false ), OP( 5, false ), // ^= *= /= %= +=
614 OP(5, false), OP( 5, false ), // -= =
615 OP(0, false), OP( 0, false ), // inc dec
616#undef OP
617};
618#define bc_operation_PREC(i) (bc_ops_prec_and_assoc[i] & 0x0f)
619#define bc_operation_LEFT(i) (bc_ops_prec_and_assoc[i] & 0x10)
620#endif // ENABLE_BC
621
622#if ENABLE_DC
623static const //BcLexType - should be this type
624uint8_t
625dc_char_to_LEX[] ALIGN1 = {
626 // %&'(
627 XC_LEX_OP_MODULUS, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_LPAREN,
628 // )*+,
629 XC_LEX_INVALID, XC_LEX_OP_MULTIPLY, XC_LEX_OP_PLUS, XC_LEX_INVALID,
630 // -./
631 XC_LEX_OP_MINUS, XC_LEX_INVALID, XC_LEX_OP_DIVIDE,
632 // 0123456789
633 XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID,
634 XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID,
635 XC_LEX_INVALID, XC_LEX_INVALID,
636 // :;<=>?@
637 DC_LEX_COLON, DC_LEX_SCOLON, XC_LEX_OP_REL_GT, XC_LEX_OP_REL_EQ,
638 XC_LEX_OP_REL_LT, DC_LEX_READ, XC_LEX_INVALID,
639 // ABCDEFGH
640 XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID,
641 XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_EQ_NO_REG, XC_LEX_INVALID,
642 // IJKLMNOP
643 DC_LEX_IBASE, XC_LEX_INVALID, DC_LEX_SCALE, DC_LEX_LOAD_POP,
644 XC_LEX_INVALID, DC_LEX_OP_BOOL_NOT, DC_LEX_OBASE, DC_LEX_PRINT_STREAM,
645 // QRSTUVWX
646 DC_LEX_NQUIT, DC_LEX_POP, DC_LEX_STORE_PUSH, XC_LEX_INVALID,
647 XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID, DC_LEX_SCALE_FACTOR,
648 // YZ
649 XC_LEX_INVALID, DC_LEX_LENGTH,
650 // [\]
651 XC_LEX_INVALID, XC_LEX_INVALID, XC_LEX_INVALID,
652 // ^_`
653 XC_LEX_OP_POWER, XC_LEX_NEG, XC_LEX_INVALID,
654 // abcdefgh
655 DC_LEX_ASCIIFY, XC_LEX_INVALID, DC_LEX_CLEAR_STACK, DC_LEX_DUPLICATE,
656 DC_LEX_ELSE, DC_LEX_PRINT_STACK, XC_LEX_INVALID, XC_LEX_INVALID,
657 // ijklmnop
658 DC_LEX_STORE_IBASE, XC_LEX_INVALID, DC_LEX_STORE_SCALE, DC_LEX_LOAD,
659 XC_LEX_INVALID, DC_LEX_PRINT_POP, DC_LEX_STORE_OBASE, DC_LEX_PRINT,
660 // qrstuvwx
661 DC_LEX_QUIT, DC_LEX_SWAP, DC_LEX_OP_ASSIGN, XC_LEX_INVALID,
662 XC_LEX_INVALID, DC_LEX_SQRT, XC_LEX_INVALID, DC_LEX_EXECUTE,
663 // yz
664 XC_LEX_INVALID, DC_LEX_STACK_LEVEL,
665 // {|}~
666 DC_LEX_LBRACE, DC_LEX_OP_MODEXP, XC_LEX_INVALID, DC_LEX_OP_DIVMOD,
667};
668static const //BcInst - should be this type. Using signed narrow type since DC_INST_INVALID is -1
669int8_t
670dc_LEX_to_INST[] ALIGN1 = { //starts at XC_LEX_OP_POWER // corresponding XC/DC_LEX_xyz:
671 XC_INST_POWER, XC_INST_MULTIPLY, // XC_LEX_OP_POWER XC_LEX_OP_MULTIPLY
672 XC_INST_DIVIDE, XC_INST_MODULUS, // XC_LEX_OP_DIVIDE XC_LEX_OP_MODULUS
673 XC_INST_PLUS, XC_INST_MINUS, // XC_LEX_OP_PLUS XC_LEX_OP_MINUS
674 XC_INST_BOOL_NOT, // DC_LEX_OP_BOOL_NOT
675 DC_INST_INVALID, // DC_LEX_OP_ASSIGN
676 XC_INST_REL_GT, // DC_LEX_LPAREN
677 DC_INST_INVALID, // DC_LEX_SCOLON
678 DC_INST_INVALID, // DC_LEX_READ
679 XC_INST_IBASE, // DC_LEX_IBASE
680 XC_INST_SCALE, // DC_LEX_SCALE
681 XC_INST_OBASE, // DC_LEX_OBASE
682 XC_INST_LENGTH, // DC_LEX_LENGTH
683 XC_INST_PRINT, // DC_LEX_PRINT
684 DC_INST_QUIT, // DC_LEX_QUIT
685 XC_INST_SQRT, // DC_LEX_SQRT
686 XC_INST_REL_GE, // DC_LEX_LBRACE
687 XC_INST_REL_EQ, // DC_LEX_EQ_NO_REG
688 DC_INST_MODEXP, DC_INST_DIVMOD, // DC_LEX_OP_MODEXP DC_LEX_OP_DIVMOD
689 DC_INST_INVALID, DC_INST_INVALID, // DC_LEX_COLON DC_LEX_ELSE
690 DC_INST_EXECUTE, // DC_LEX_EXECUTE
691 DC_INST_PRINT_STACK, DC_INST_CLEAR_STACK, // DC_LEX_PRINT_STACK DC_LEX_CLEAR_STACK
692 DC_INST_STACK_LEN, DC_INST_DUPLICATE, // DC_LEX_STACK_LEVEL DC_LEX_DUPLICATE
693 DC_INST_SWAP, XC_INST_POP, // DC_LEX_SWAP DC_LEX_POP
694 DC_INST_ASCIIFY, DC_INST_PRINT_STREAM, // DC_LEX_ASCIIFY DC_LEX_PRINT_STREAM
695 DC_INST_INVALID, DC_INST_INVALID, // DC_LEX_STORE_IBASE DC_LEX_STORE_OBASE
696 DC_INST_INVALID, DC_INST_INVALID, // DC_LEX_STORE_SCALE DC_LEX_LOAD
697 DC_INST_INVALID, DC_INST_INVALID, // DC_LEX_LOAD_POP DC_LEX_STORE_PUSH
698 XC_INST_PRINT, DC_INST_NQUIT, // DC_LEX_PRINT_POP DC_LEX_NQUIT
699 XC_INST_SCALE_FUNC, // DC_LEX_SCALE_FACTOR
700 // DC_INST_INVALID in this table either means that corresponding LEX
701 // is not possible for dc, or that it does not compile one-to-one
702 // to a single INST.
703};
704#endif // ENABLE_DC
705
706typedef struct BcParse {
707 smallint lex; // was BcLexType // first member is most used
708 smallint lex_last; // was BcLexType
709 size_t lex_line;
710 const char *lex_inbuf;
711 const char *lex_next_at; // last lex_next() was called at this string
712 const char *lex_filename;
713 FILE *lex_input_fp;
714 BcVec lex_strnumbuf;
715
716 BcFunc *func;
717 size_t fidx;
718 IF_BC(size_t in_funcdef;)
719 IF_BC(BcVec exits;)
720 IF_BC(BcVec conds;)
721 IF_BC(BcVec ops;)
722} BcParse;
723
724typedef struct BcProgram {
725 size_t len;
726 size_t nchars;
727
728 size_t scale;
729 size_t ib_t;
730 size_t ob_t;
731
732 BcVec results;
733 BcVec exestack;
734
735 BcVec fns;
736 IF_BC(BcVec fn_map;)
737
738 BcVec vars;
739 BcVec var_map;
740
741 BcVec arrs;
742 BcVec arr_map;
743
744 IF_DC(BcVec strs;)
745 IF_DC(BcVec consts;)
746
747 BcNum zero;
748 IF_BC(BcNum one;)
749 IF_BC(BcNum last;)
750} BcProgram;
751
752struct globals {
753 BcParse prs; // first member is most used
754
755 // For error messages. Can be set to current parsed line,
756 // or [TODO] to current executing line (can be before last parsed one)
757 size_t err_line;
758
759 BcVec input_buffer;
760
761 IF_FEATURE_BC_INTERACTIVE(smallint ttyin;)
762 IF_FEATURE_CLEAN_UP(smallint exiting;)
763
764 BcProgram prog;
765
766 BcVec files;
767
768 char *env_args;
769
770#if ENABLE_FEATURE_EDITING
771 line_input_t *line_input_state;
772#endif
773} FIX_ALIASING;
774#define G (*ptr_to_globals)
775#define INIT_G() do { \
776 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
777} while (0)
778#define FREE_G() do { \
779 FREE_PTR_TO_GLOBALS(); \
780} while (0)
781#define G_posix (ENABLE_BC && (option_mask32 & BC_FLAG_S))
782#define G_warn (ENABLE_BC && (option_mask32 & BC_FLAG_W))
783#define G_exreg (ENABLE_DC && (option_mask32 & DC_FLAG_X))
784#if ENABLE_FEATURE_BC_INTERACTIVE
785# define G_interrupt bb_got_signal
786# define G_ttyin G.ttyin
787#else
788# define G_interrupt 0
789# define G_ttyin 0
790#endif
791#if ENABLE_FEATURE_CLEAN_UP
792# define G_exiting G.exiting
793#else
794# define G_exiting 0
795#endif
796#define IS_BC (ENABLE_BC && (!ENABLE_DC || applet_name[0] == 'b'))
797#define IS_DC (ENABLE_DC && (!ENABLE_BC || applet_name[0] != 'b'))
798
799#if ENABLE_BC
800# define BC_PARSE_REL (1 << 0)
801# define BC_PARSE_PRINT (1 << 1)
802# define BC_PARSE_ARRAY (1 << 2)
803# define BC_PARSE_NOCALL (1 << 3)
804#endif
805
806#define BC_PROG_MAIN 0
807#define BC_PROG_READ 1
808#if ENABLE_DC
809#define BC_PROG_REQ_FUNCS 2
810#endif
811
812#define BC_FLAG_W (1 << 0)
813#define BC_FLAG_V (1 << 1)
814#define BC_FLAG_S (1 << 2)
815#define BC_FLAG_Q (1 << 3)
816#define BC_FLAG_L (1 << 4)
817#define BC_FLAG_I ((1 << 5) * ENABLE_DC)
818#define DC_FLAG_X ((1 << 6) * ENABLE_DC)
819
820#define BC_MAX_OBASE ((unsigned) 999)
821#define BC_MAX_DIM ((unsigned) INT_MAX)
822#define BC_MAX_SCALE ((unsigned) UINT_MAX)
823#define BC_MAX_STRING ((unsigned) UINT_MAX - 1)
824#define BC_MAX_NUM BC_MAX_STRING
825// Unused apart from "limits" message. Just show a "biggish number" there.
826//#define BC_MAX_EXP ((unsigned long) LONG_MAX)
827//#define BC_MAX_VARS ((unsigned long) SIZE_MAX - 1)
828#define BC_MAX_EXP_STR "999999999"
829#define BC_MAX_VARS_STR "999999999"
830
831#define BC_MAX_OBASE_STR "999"
832
833#if INT_MAX == 2147483647
834# define BC_MAX_DIM_STR "2147483647"
835#elif INT_MAX == 9223372036854775807
836# define BC_MAX_DIM_STR "9223372036854775807"
837#else
838# error Strange INT_MAX
839#endif
840
841#if UINT_MAX == 4294967295
842# define BC_MAX_SCALE_STR "4294967295"
843# define BC_MAX_STRING_STR "4294967294"
844#elif UINT_MAX == 18446744073709551615
845# define BC_MAX_SCALE_STR "18446744073709551615"
846# define BC_MAX_STRING_STR "18446744073709551614"
847#else
848# error Strange UINT_MAX
849#endif
850#define BC_MAX_NUM_STR BC_MAX_STRING_STR
851
852// In configurations where errors abort instead of propagating error
853// return code up the call chain, functions returning BC_STATUS
854// actually don't return anything, they always succeed and return "void".
855// A macro wrapper is provided, which makes this statement work:
856// s = zbc_func(...)
857// and makes it visible to the compiler that s is always zero,
858// allowing compiler to optimize dead code after the statement.
859//
860// To make code more readable, each such function has a "z"
861// ("always returning zero") prefix, i.e. zbc_foo or zdc_foo.
862//
863#if ENABLE_FEATURE_BC_INTERACTIVE || ENABLE_FEATURE_CLEAN_UP
864# define ERRORS_ARE_FATAL 0
865# define ERRORFUNC /*nothing*/
866# define IF_ERROR_RETURN_POSSIBLE(a) a
867# define BC_STATUS BcStatus
868# define RETURN_STATUS(v) return (v)
869# define COMMA_SUCCESS /*nothing*/
870#else
871# define ERRORS_ARE_FATAL 1
872# define ERRORFUNC NORETURN
873# define IF_ERROR_RETURN_POSSIBLE(a) /*nothing*/
874# define BC_STATUS void
875# define RETURN_STATUS(v) do { ((void)(v)); return; } while (0)
876# define COMMA_SUCCESS ,BC_STATUS_SUCCESS
877#endif
878
879//
880// Utility routines
881//
882
883#define BC_MAX(a, b) ((a) > (b) ? (a) : (b))
884#define BC_MIN(a, b) ((a) < (b) ? (a) : (b))
885
886static void fflush_and_check(void)
887{
888 fflush_all();
889 if (ferror(stdout) || ferror(stderr))
890 bb_perror_msg_and_die("output error");
891}
892
893#if ENABLE_FEATURE_CLEAN_UP
894#define QUIT_OR_RETURN_TO_MAIN \
895do { \
896 IF_FEATURE_BC_INTERACTIVE(G_ttyin = 0;) /* do not loop in main loop anymore */ \
897 G_exiting = 1; \
898 return BC_STATUS_FAILURE; \
899} while (0)
900#else
901static void quit(void) NORETURN;
902static void quit(void)
903{
904 if (ferror(stdin))
905 bb_perror_msg_and_die("input error");
906 fflush_and_check();
907 dbg_exec("quit(): exiting with exitcode SUCCESS");
908 exit(0);
909}
910#define QUIT_OR_RETURN_TO_MAIN quit()
911#endif
912
913static void bc_verror_msg(const char *fmt, va_list p)
914{
915 const char *sv = sv; // for compiler
916 if (G.prs.lex_filename) {
917 sv = applet_name;
918 applet_name = xasprintf("%s: %s:%lu", applet_name,
919 G.prs.lex_filename, (unsigned long)G.err_line
920 );
921 }
922 bb_verror_msg(fmt, p, NULL);
923 if (G.prs.lex_filename) {
924 free((char*)applet_name);
925 applet_name = sv;
926 }
927}
928
929static NOINLINE ERRORFUNC int bc_error_fmt(const char *fmt, ...)
930{
931 va_list p;
932
933 va_start(p, fmt);
934 bc_verror_msg(fmt, p);
935 va_end(p);
936
937 if (ENABLE_FEATURE_CLEAN_UP || G_ttyin)
938 IF_ERROR_RETURN_POSSIBLE(return BC_STATUS_FAILURE);
939 exit(1);
940}
941
942#if ENABLE_BC
943static NOINLINE BC_STATUS zbc_posix_error_fmt(const char *fmt, ...)
944{
945 va_list p;
946
947 // Are non-POSIX constructs totally ok?
948 if (!(option_mask32 & (BC_FLAG_S|BC_FLAG_W)))
949 RETURN_STATUS(BC_STATUS_SUCCESS); // yes
950
951 va_start(p, fmt);
952 bc_verror_msg(fmt, p);
953 va_end(p);
954
955 // Do we treat non-POSIX constructs as errors?
956 if (!(option_mask32 & BC_FLAG_S))
957 RETURN_STATUS(BC_STATUS_SUCCESS); // no, it's a warning
958
959 if (ENABLE_FEATURE_CLEAN_UP || G_ttyin)
960 RETURN_STATUS(BC_STATUS_FAILURE);
961 exit(1);
962}
963#define zbc_posix_error_fmt(...) (zbc_posix_error_fmt(__VA_ARGS__) COMMA_SUCCESS)
964#endif
965
966// We use error functions with "return bc_error(FMT[, PARAMS])" idiom.
967// This idiom begs for tail-call optimization, but for it to work,
968// function must not have caller-cleaned parameters on stack.
969// Unfortunately, vararg function API does exactly that on most arches.
970// Thus, use these shims for the cases when we have no vararg PARAMS:
971static ERRORFUNC int bc_error(const char *msg)
972{
973 IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("%s", msg);
974}
975static ERRORFUNC int bc_error_at(const char *msg)
976{
977 const char *err_at = G.prs.lex_next_at;
978 if (err_at) {
979 IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt(
980 "%s at '%.*s'",
981 msg,
982 (int)(strchrnul(err_at, '\n') - err_at),
983 err_at
984 );
985 }
986 IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("%s", msg);
987}
988static ERRORFUNC int bc_error_bad_character(char c)
989{
990 if (!c)
991 IF_ERROR_RETURN_POSSIBLE(return) bc_error("NUL character");
992 IF_ERROR_RETURN_POSSIBLE(return) bc_error_fmt("bad character '%c'", c);
993}
994static ERRORFUNC int bc_error_bad_function_definition(void)
995{
996 IF_ERROR_RETURN_POSSIBLE(return) bc_error_at("bad function definition");
997}
998static ERRORFUNC int bc_error_bad_expression(void)
999{
1000 IF_ERROR_RETURN_POSSIBLE(return) bc_error_at("bad expression");
1001}
1002static ERRORFUNC int bc_error_bad_assignment(void)
1003{
1004 IF_ERROR_RETURN_POSSIBLE(return) bc_error_at(
1005 "bad assignment: left side must be variable or array element"
1006 );
1007}
1008static ERRORFUNC int bc_error_bad_token(void)
1009{
1010 IF_ERROR_RETURN_POSSIBLE(return) bc_error_at("bad token");
1011}
1012static ERRORFUNC int bc_error_stack_has_too_few_elements(void)
1013{
1014 IF_ERROR_RETURN_POSSIBLE(return) bc_error("stack has too few elements");
1015}
1016static ERRORFUNC int bc_error_variable_is_wrong_type(void)
1017{
1018 IF_ERROR_RETURN_POSSIBLE(return) bc_error("variable is wrong type");
1019}
1020#if ENABLE_BC
1021static BC_STATUS zbc_POSIX_requires(const char *msg)
1022{
1023 RETURN_STATUS(zbc_posix_error_fmt("POSIX requires %s", msg));
1024}
1025#define zbc_POSIX_requires(...) (zbc_POSIX_requires(__VA_ARGS__) COMMA_SUCCESS)
1026static BC_STATUS zbc_POSIX_does_not_allow(const char *msg)
1027{
1028 RETURN_STATUS(zbc_posix_error_fmt("%s%s", "POSIX does not allow ", msg));
1029}
1030#define zbc_POSIX_does_not_allow(...) (zbc_POSIX_does_not_allow(__VA_ARGS__) COMMA_SUCCESS)
1031static BC_STATUS zbc_POSIX_does_not_allow_bool_ops_this_is_bad(const char *msg)
1032{
1033 RETURN_STATUS(zbc_posix_error_fmt("%s%s %s", "POSIX does not allow ", "boolean operators; this is bad:", msg));
1034}
1035#define zbc_POSIX_does_not_allow_bool_ops_this_is_bad(...) (zbc_POSIX_does_not_allow_bool_ops_this_is_bad(__VA_ARGS__) COMMA_SUCCESS)
1036static BC_STATUS zbc_POSIX_does_not_allow_empty_X_expression_in_for(const char *msg)
1037{
1038 RETURN_STATUS(zbc_posix_error_fmt("%san empty %s expression in 'for()'", "POSIX does not allow ", msg));
1039}
1040#define zbc_POSIX_does_not_allow_empty_X_expression_in_for(...) (zbc_POSIX_does_not_allow_empty_X_expression_in_for(__VA_ARGS__) COMMA_SUCCESS)
1041#endif
1042
1043static void bc_vec_grow(BcVec *v, size_t n)
1044{
1045 size_t cap = v->cap * 2;
1046 while (cap < v->len + n) cap *= 2;
1047 v->v = xrealloc(v->v, v->size * cap);
1048 v->cap = cap;
1049}
1050
1051static void bc_vec_init(BcVec *v, size_t esize, BcVecFree dtor)
1052{
1053 v->size = esize;
1054 v->cap = BC_VEC_START_CAP;
1055 v->len = 0;
1056 v->dtor = dtor;
1057 v->v = xmalloc(esize * BC_VEC_START_CAP);
1058}
1059
1060static void bc_char_vec_init(BcVec *v)
1061{
1062 bc_vec_init(v, sizeof(char), NULL);
1063}
1064
1065static void bc_vec_expand(BcVec *v, size_t req)
1066{
1067 if (v->cap < req) {
1068 v->v = xrealloc(v->v, v->size * req);
1069 v->cap = req;
1070 }
1071}
1072
1073static void bc_vec_pop(BcVec *v)
1074{
1075 v->len--;
1076 if (v->dtor)
1077 v->dtor(v->v + (v->size * v->len));
1078}
1079
1080static void bc_vec_npop(BcVec *v, size_t n)
1081{
1082 if (!v->dtor)
1083 v->len -= n;
1084 else {
1085 size_t len = v->len - n;
1086 while (v->len > len) v->dtor(v->v + (v->size * --v->len));
1087 }
1088}
1089
1090static void bc_vec_pop_all(BcVec *v)
1091{
1092 bc_vec_npop(v, v->len);
1093}
1094
1095static size_t bc_vec_push(BcVec *v, const void *data)
1096{
1097 size_t len = v->len;
1098 if (len >= v->cap) bc_vec_grow(v, 1);
1099 memmove(v->v + (v->size * len), data, v->size);
1100 v->len++;
1101 return len;
1102}
1103
1104// G.prog.results often needs "pop old operand, push result" idiom.
1105// Can do this without a few extra ops
1106static size_t bc_result_pop_and_push(const void *data)
1107{
1108 BcVec *v = &G.prog.results;
1109 char *last;
1110 size_t len = v->len - 1;
1111
1112 last = v->v + (v->size * len);
1113 if (v->dtor)
1114 v->dtor(last);
1115 memmove(last, data, v->size);
1116 return len;
1117}
1118
1119static size_t bc_vec_pushByte(BcVec *v, char data)
1120{
1121 return bc_vec_push(v, &data);
1122}
1123
1124static size_t bc_vec_pushZeroByte(BcVec *v)
1125{
1126 //return bc_vec_pushByte(v, '\0');
1127 // better:
1128 return bc_vec_push(v, &const_int_0);
1129}
1130
1131static void bc_vec_pushAt(BcVec *v, const void *data, size_t idx)
1132{
1133 if (idx == v->len)
1134 bc_vec_push(v, data);
1135 else {
1136 char *ptr;
1137
1138 if (v->len == v->cap) bc_vec_grow(v, 1);
1139
1140 ptr = v->v + v->size * idx;
1141
1142 memmove(ptr + v->size, ptr, v->size * (v->len++ - idx));
1143 memmove(ptr, data, v->size);
1144 }
1145}
1146
1147static void bc_vec_string(BcVec *v, size_t len, const char *str)
1148{
1149 bc_vec_pop_all(v);
1150 bc_vec_expand(v, len + 1);
1151 memcpy(v->v, str, len);
1152 v->len = len;
1153
1154 bc_vec_pushZeroByte(v);
1155}
1156
1157static void *bc_vec_item(const BcVec *v, size_t idx)
1158{
1159 return v->v + v->size * idx;
1160}
1161
1162static void *bc_vec_item_rev(const BcVec *v, size_t idx)
1163{
1164 return v->v + v->size * (v->len - idx - 1);
1165}
1166
1167static void *bc_vec_top(const BcVec *v)
1168{
1169 return v->v + v->size * (v->len - 1);
1170}
1171
1172static FAST_FUNC void bc_vec_free(void *vec)
1173{
1174 BcVec *v = (BcVec *) vec;
1175 bc_vec_pop_all(v);
1176 free(v->v);
1177}
1178
1179static BcFunc* xc_program_func(size_t idx)
1180{
1181 return bc_vec_item(&G.prog.fns, idx);
1182}
1183// BC_PROG_MAIN is zeroth element, so:
1184#define xc_program_func_BC_PROG_MAIN() ((BcFunc*)(G.prog.fns.v))
1185
1186#if ENABLE_BC
1187static BcFunc* bc_program_current_func(void)
1188{
1189 BcInstPtr *ip = bc_vec_top(&G.prog.exestack);
1190 BcFunc *func = xc_program_func(ip->func);
1191 return func;
1192}
1193#endif
1194
1195static char** xc_program_str(size_t idx)
1196{
1197#if ENABLE_BC
1198 if (IS_BC) {
1199 BcFunc *func = bc_program_current_func();
1200 return bc_vec_item(&func->strs, idx);
1201 }
1202#endif
1203 IF_DC(return bc_vec_item(&G.prog.strs, idx);)
1204}
1205
1206static char** xc_program_const(size_t idx)
1207{
1208#if ENABLE_BC
1209 if (IS_BC) {
1210 BcFunc *func = bc_program_current_func();
1211 return bc_vec_item(&func->consts, idx);
1212 }
1213#endif
1214 IF_DC(return bc_vec_item(&G.prog.consts, idx);)
1215}
1216
1217static int bc_id_cmp(const void *e1, const void *e2)
1218{
1219 return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name);
1220}
1221
1222static FAST_FUNC void bc_id_free(void *id)
1223{
1224 free(((BcId *) id)->name);
1225}
1226
1227static size_t bc_map_find_ge(const BcVec *v, const void *ptr)
1228{
1229 size_t low = 0, high = v->len;
1230
1231 while (low < high) {
1232 size_t mid = (low + high) / 2;
1233 BcId *id = bc_vec_item(v, mid);
1234 int result = bc_id_cmp(ptr, id);
1235
1236 if (result == 0)
1237 return mid;
1238 if (result < 0)
1239 high = mid;
1240 else
1241 low = mid + 1;
1242 }
1243
1244 return low;
1245}
1246
1247static int bc_map_insert(BcVec *v, const void *ptr, size_t *i)
1248{
1249 size_t n = *i = bc_map_find_ge(v, ptr);
1250
1251 if (n == v->len)
1252 bc_vec_push(v, ptr);
1253 else if (!bc_id_cmp(ptr, bc_vec_item(v, n)))
1254 return 0; // "was not inserted"
1255 else
1256 bc_vec_pushAt(v, ptr, n);
1257 return 1; // "was inserted"
1258}
1259
1260#if ENABLE_BC
1261static size_t bc_map_find_exact(const BcVec *v, const void *ptr)
1262{
1263 size_t i = bc_map_find_ge(v, ptr);
1264 if (i >= v->len) return BC_VEC_INVALID_IDX;
1265 return bc_id_cmp(ptr, bc_vec_item(v, i)) ? BC_VEC_INVALID_IDX : i;
1266}
1267#endif
1268
1269static void bc_num_setToZero(BcNum *n, size_t scale)
1270{
1271 n->len = 0;
1272 n->neg = false;
1273 n->rdx = scale;
1274}
1275
1276static void bc_num_zero(BcNum *n)
1277{
1278 bc_num_setToZero(n, 0);
1279}
1280
1281static void bc_num_one(BcNum *n)
1282{
1283 bc_num_setToZero(n, 0);
1284 n->len = 1;
1285 n->num[0] = 1;
1286}
1287
1288// Note: this also sets BcNum to zero
1289static void bc_num_init(BcNum *n, size_t req)
1290{
1291 req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
1292 //memset(n, 0, sizeof(BcNum)); - cleared by assignments below
1293 n->num = xmalloc(req);
1294 n->cap = req;
1295 n->rdx = 0;
1296 n->len = 0;
1297 n->neg = false;
1298}
1299
1300static void bc_num_init_DEF_SIZE(BcNum *n)
1301{
1302 bc_num_init(n, BC_NUM_DEF_SIZE);
1303}
1304
1305static void bc_num_expand(BcNum *n, size_t req)
1306{
1307 req = req >= BC_NUM_DEF_SIZE ? req : BC_NUM_DEF_SIZE;
1308 if (req > n->cap) {
1309 n->num = xrealloc(n->num, req);
1310 n->cap = req;
1311 }
1312}
1313
1314static FAST_FUNC void bc_num_free(void *num)
1315{
1316 free(((BcNum *) num)->num);
1317}
1318
1319static void bc_num_copy(BcNum *d, BcNum *s)
1320{
1321 if (d != s) {
1322 bc_num_expand(d, s->cap);
1323 d->len = s->len;
1324 d->neg = s->neg;
1325 d->rdx = s->rdx;
1326 memcpy(d->num, s->num, sizeof(BcDig) * d->len);
1327 }
1328}
1329
1330static BC_STATUS zbc_num_ulong_abs(BcNum *n, unsigned long *result_p)
1331{
1332 size_t i;
1333 unsigned long result;
1334
1335 result = 0;
1336 i = n->len;
1337 while (i > n->rdx) {
1338 unsigned long prev = result;
1339 result = result * 10 + n->num[--i];
1340 // Even overflowed N*10 can still satisfy N*10>=N. For example,
1341 // 0x1ff00000 * 10 is 0x13f600000,
1342 // or 0x3f600000 truncated to 32 bits. Which is larger.
1343 // However, (N*10)/8 < N check is always correct.
1344 if ((result / 8) < prev)
1345 RETURN_STATUS(bc_error("overflow"));
1346 }
1347 *result_p = result;
1348
1349 RETURN_STATUS(BC_STATUS_SUCCESS);
1350}
1351#define zbc_num_ulong_abs(...) (zbc_num_ulong_abs(__VA_ARGS__) COMMA_SUCCESS)
1352
1353static BC_STATUS zbc_num_ulong(BcNum *n, unsigned long *result_p)
1354{
1355 if (n->neg) RETURN_STATUS(bc_error("negative number"));
1356
1357 RETURN_STATUS(zbc_num_ulong_abs(n, result_p));
1358}
1359#define zbc_num_ulong(...) (zbc_num_ulong(__VA_ARGS__) COMMA_SUCCESS)
1360
1361#if ULONG_MAX == 0xffffffffUL // 10 digits: 4294967295
1362# define ULONG_NUM_BUFSIZE (10 > BC_NUM_DEF_SIZE ? 10 : BC_NUM_DEF_SIZE)
1363#elif ULONG_MAX == 0xffffffffffffffffULL // 20 digits: 18446744073709551615
1364# define ULONG_NUM_BUFSIZE (20 > BC_NUM_DEF_SIZE ? 20 : BC_NUM_DEF_SIZE)
1365#endif
1366// minimum BC_NUM_DEF_SIZE, so that bc_num_expand() in bc_num_ulong2num()
1367// would not hit realloc() code path - not good if num[] is not malloced
1368
1369static void bc_num_ulong2num(BcNum *n, unsigned long val)
1370{
1371 BcDig *ptr;
1372
1373 bc_num_zero(n);
1374
1375 if (val == 0) return;
1376
1377 bc_num_expand(n, ULONG_NUM_BUFSIZE);
1378
1379 ptr = n->num;
1380 for (;;) {
1381 n->len++;
1382 *ptr++ = val % 10;
1383 val /= 10;
1384 if (val == 0) break;
1385 }
1386}
1387
1388static void bc_num_subArrays(BcDig *restrict a, BcDig *restrict b, size_t len)
1389{
1390 size_t i, j;
1391 for (i = 0; i < len; ++i) {
1392 a[i] -= b[i];
1393 for (j = i; a[j] < 0;) {
1394 a[j++] += 10;
1395 a[j] -= 1;
1396 }
1397 }
1398}
1399
1400static ssize_t bc_num_compare(BcDig *restrict a, BcDig *restrict b, size_t len)
1401{
1402 size_t i = len;
1403 for (;;) {
1404 int c;
1405 if (i == 0)
1406 return 0;
1407 i--;
1408 c = a[i] - b[i];
1409 if (c != 0) {
1410 i++;
1411 if (c < 0)
1412 return -i;
1413 return i;
1414 }
1415 }
1416}
1417
1418#define BC_NUM_NEG(n, neg) ((((ssize_t)(n)) ^ -((ssize_t)(neg))) + (neg))
1419#define BC_NUM_ONE(n) ((n)->len == 1 && (n)->rdx == 0 && (n)->num[0] == 1)
1420#define BC_NUM_INT(n) ((n)->len - (n)->rdx)
1421//#define BC_NUM_AREQ(a, b) (BC_MAX((a)->rdx, (b)->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1)
1422static /*ALWAYS_INLINE*/ size_t BC_NUM_AREQ(BcNum *a, BcNum *b)
1423{
1424 return BC_MAX(a->rdx, b->rdx) + BC_MAX(BC_NUM_INT(a), BC_NUM_INT(b)) + 1;
1425}
1426//#define BC_NUM_MREQ(a, b, scale) (BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX((scale), (a)->rdx + (b)->rdx) + 1)
1427static /*ALWAYS_INLINE*/ size_t BC_NUM_MREQ(BcNum *a, BcNum *b, size_t scale)
1428{
1429 return BC_NUM_INT(a) + BC_NUM_INT(b) + BC_MAX(scale, a->rdx + b->rdx) + 1;
1430}
1431
1432static ssize_t bc_num_cmp(BcNum *a, BcNum *b)
1433{
1434 size_t i, min, a_int, b_int, diff;
1435 BcDig *max_num, *min_num;
1436 bool a_max, neg;
1437 ssize_t cmp;
1438
1439 if (a == b) return 0;
1440 if (a->len == 0) return BC_NUM_NEG(!!b->len, !b->neg);
1441 if (b->len == 0) return BC_NUM_NEG(1, a->neg);
1442
1443 if (a->neg != b->neg) // signs of a and b differ
1444 // +a,-b = a>b = 1 or -a,+b = a<b = -1
1445 return (int)b->neg - (int)a->neg;
1446 neg = a->neg; // 1 if both negative, 0 if both positive
1447
1448 a_int = BC_NUM_INT(a);
1449 b_int = BC_NUM_INT(b);
1450 a_int -= b_int;
1451
1452 if (a_int != 0) return (ssize_t) a_int;
1453
1454 a_max = (a->rdx > b->rdx);
1455 if (a_max) {
1456 min = b->rdx;
1457 diff = a->rdx - b->rdx;
1458 max_num = a->num + diff;
1459 min_num = b->num;
1460 // neg = (a_max == neg); - NOP (maps 1->1 and 0->0)
1461 } else {
1462 min = a->rdx;
1463 diff = b->rdx - a->rdx;
1464 max_num = b->num + diff;
1465 min_num = a->num;
1466 neg = !neg; // same as "neg = (a_max == neg)"
1467 }
1468
1469 cmp = bc_num_compare(max_num, min_num, b_int + min);
1470 if (cmp != 0) return BC_NUM_NEG(cmp, neg);
1471
1472 for (max_num -= diff, i = diff - 1; i < diff; --i) {
1473 if (max_num[i]) return BC_NUM_NEG(1, neg);
1474 }
1475
1476 return 0;
1477}
1478
1479static void bc_num_truncate(BcNum *n, size_t places)
1480{
1481 if (places == 0) return;
1482
1483 n->rdx -= places;
1484
1485 if (n->len != 0) {
1486 n->len -= places;
1487 memmove(n->num, n->num + places, n->len * sizeof(BcDig));
1488 }
1489}
1490
1491static void bc_num_extend(BcNum *n, size_t places)
1492{
1493 size_t len = n->len + places;
1494
1495 if (places != 0) {
1496 if (n->cap < len) bc_num_expand(n, len);
1497
1498 memmove(n->num + places, n->num, sizeof(BcDig) * n->len);
1499 memset(n->num, 0, sizeof(BcDig) * places);
1500
1501 n->len += places;
1502 n->rdx += places;
1503 }
1504}
1505
1506static void bc_num_clean(BcNum *n)
1507{
1508 while (n->len > 0 && n->num[n->len - 1] == 0) --n->len;
1509 if (n->len == 0)
1510 n->neg = false;
1511 else if (n->len < n->rdx)
1512 n->len = n->rdx;
1513}
1514
1515static void bc_num_retireMul(BcNum *n, size_t scale, bool neg1, bool neg2)
1516{
1517 if (n->rdx < scale)
1518 bc_num_extend(n, scale - n->rdx);
1519 else
1520 bc_num_truncate(n, n->rdx - scale);
1521
1522 bc_num_clean(n);
1523 if (n->len != 0) n->neg = !neg1 != !neg2;
1524}
1525
1526static void bc_num_split(BcNum *restrict n, size_t idx, BcNum *restrict a,
1527 BcNum *restrict b)
1528{
1529 if (idx < n->len) {
1530 b->len = n->len - idx;
1531 a->len = idx;
1532 a->rdx = b->rdx = 0;
1533
1534 memcpy(b->num, n->num + idx, b->len * sizeof(BcDig));
1535 memcpy(a->num, n->num, idx * sizeof(BcDig));
1536 } else {
1537 bc_num_zero(b);
1538 bc_num_copy(a, n);
1539 }
1540
1541 bc_num_clean(a);
1542 bc_num_clean(b);
1543}
1544
1545static BC_STATUS zbc_num_shift(BcNum *n, size_t places)
1546{
1547 if (places == 0 || n->len == 0) RETURN_STATUS(BC_STATUS_SUCCESS);
1548
1549 // This check makes sense only if size_t is (much) larger than BC_MAX_NUM.
1550 if (SIZE_MAX > (BC_MAX_NUM | 0xff)) {
1551 if (places + n->len > BC_MAX_NUM)
1552 RETURN_STATUS(bc_error("number too long: must be [1,"BC_MAX_NUM_STR"]"));
1553 }
1554
1555 if (n->rdx >= places)
1556 n->rdx -= places;
1557 else {
1558 bc_num_extend(n, places - n->rdx);
1559 n->rdx = 0;
1560 }
1561
1562 bc_num_clean(n);
1563
1564 RETURN_STATUS(BC_STATUS_SUCCESS);
1565}
1566#define zbc_num_shift(...) (zbc_num_shift(__VA_ARGS__) COMMA_SUCCESS)
1567
1568typedef BC_STATUS (*BcNumBinaryOp)(BcNum *, BcNum *, BcNum *, size_t) FAST_FUNC;
1569
1570static BC_STATUS zbc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale,
1571 BcNumBinaryOp op, size_t req)
1572{
1573 BcStatus s;
1574 BcNum num2, *ptr_a, *ptr_b;
1575 bool init = false;
1576
1577 if (c == a) {
1578 ptr_a = &num2;
1579 memcpy(ptr_a, c, sizeof(BcNum));
1580 init = true;
1581 } else
1582 ptr_a = a;
1583
1584 if (c == b) {
1585 ptr_b = &num2;
1586 if (c != a) {
1587 memcpy(ptr_b, c, sizeof(BcNum));
1588 init = true;
1589 }
1590 } else
1591 ptr_b = b;
1592
1593 if (init)
1594 bc_num_init(c, req);
1595 else
1596 bc_num_expand(c, req);
1597
1598 s = BC_STATUS_SUCCESS;
1599 IF_ERROR_RETURN_POSSIBLE(s =) op(ptr_a, ptr_b, c, scale);
1600
1601 if (init) bc_num_free(&num2);
1602
1603 RETURN_STATUS(s);
1604}
1605#define zbc_num_binary(...) (zbc_num_binary(__VA_ARGS__) COMMA_SUCCESS)
1606
1607static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
1608static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
1609static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
1610static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
1611static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
1612static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale);
1613
1614static FAST_FUNC BC_STATUS zbc_num_add(BcNum *a, BcNum *b, BcNum *c, size_t scale)
1615{
1616 BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_a : zbc_num_s;
1617 (void) scale;
1618 RETURN_STATUS(zbc_num_binary(a, b, c, false, op, BC_NUM_AREQ(a, b)));
1619}
1620
1621static FAST_FUNC BC_STATUS zbc_num_sub(BcNum *a, BcNum *b, BcNum *c, size_t scale)
1622{
1623 BcNumBinaryOp op = (!a->neg == !b->neg) ? zbc_num_s : zbc_num_a;
1624 (void) scale;
1625 RETURN_STATUS(zbc_num_binary(a, b, c, true, op, BC_NUM_AREQ(a, b)));
1626}
1627
1628static FAST_FUNC BC_STATUS zbc_num_mul(BcNum *a, BcNum *b, BcNum *c, size_t scale)
1629{
1630 size_t req = BC_NUM_MREQ(a, b, scale);
1631 RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_m, req));
1632}
1633
1634static FAST_FUNC BC_STATUS zbc_num_div(BcNum *a, BcNum *b, BcNum *c, size_t scale)
1635{
1636 size_t req = BC_NUM_MREQ(a, b, scale);
1637 RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_d, req));
1638}
1639
1640static FAST_FUNC BC_STATUS zbc_num_mod(BcNum *a, BcNum *b, BcNum *c, size_t scale)
1641{
1642 size_t req = BC_NUM_MREQ(a, b, scale);
1643 RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_rem, req));
1644}
1645
1646static FAST_FUNC BC_STATUS zbc_num_pow(BcNum *a, BcNum *b, BcNum *c, size_t scale)
1647{
1648 RETURN_STATUS(zbc_num_binary(a, b, c, scale, zbc_num_p, a->len * b->len + 1));
1649}
1650
1651static const BcNumBinaryOp zxc_program_ops[] = {
1652 zbc_num_pow, zbc_num_mul, zbc_num_div, zbc_num_mod, zbc_num_add, zbc_num_sub,
1653};
1654#define zbc_num_add(...) (zbc_num_add(__VA_ARGS__) COMMA_SUCCESS)
1655#define zbc_num_sub(...) (zbc_num_sub(__VA_ARGS__) COMMA_SUCCESS)
1656#define zbc_num_mul(...) (zbc_num_mul(__VA_ARGS__) COMMA_SUCCESS)
1657#define zbc_num_div(...) (zbc_num_div(__VA_ARGS__) COMMA_SUCCESS)
1658#define zbc_num_mod(...) (zbc_num_mod(__VA_ARGS__) COMMA_SUCCESS)
1659#define zbc_num_pow(...) (zbc_num_pow(__VA_ARGS__) COMMA_SUCCESS)
1660
1661static BC_STATUS zbc_num_inv(BcNum *a, BcNum *b, size_t scale)
1662{
1663 BcNum one;
1664 BcDig num[2];
1665
1666 one.cap = 2;
1667 one.num = num;
1668 bc_num_one(&one);
1669
1670 RETURN_STATUS(zbc_num_div(&one, a, b, scale));
1671}
1672#define zbc_num_inv(...) (zbc_num_inv(__VA_ARGS__) COMMA_SUCCESS)
1673
1674static FAST_FUNC BC_STATUS zbc_num_a(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
1675{
1676 BcDig *ptr, *ptr_a, *ptr_b, *ptr_c;
1677 size_t i, max, min_rdx, min_int, diff, a_int, b_int;
1678 unsigned carry;
1679
1680 // Because this function doesn't need to use scale (per the bc spec),
1681 // I am hijacking it to say whether it's doing an add or a subtract.
1682
1683 if (a->len == 0) {
1684 bc_num_copy(c, b);
1685 if (sub && c->len) c->neg = !c->neg;
1686 RETURN_STATUS(BC_STATUS_SUCCESS);
1687 }
1688 if (b->len == 0) {
1689 bc_num_copy(c, a);
1690 RETURN_STATUS(BC_STATUS_SUCCESS);
1691 }
1692
1693 c->neg = a->neg;
1694 c->rdx = BC_MAX(a->rdx, b->rdx);
1695 min_rdx = BC_MIN(a->rdx, b->rdx);
1696 c->len = 0;
1697
1698 if (a->rdx > b->rdx) {
1699 diff = a->rdx - b->rdx;
1700 ptr = a->num;
1701 ptr_a = a->num + diff;
1702 ptr_b = b->num;
1703 } else {
1704 diff = b->rdx - a->rdx;
1705 ptr = b->num;
1706 ptr_a = a->num;
1707 ptr_b = b->num + diff;
1708 }
1709
1710 ptr_c = c->num;
1711 for (i = 0; i < diff; ++i, ++c->len)
1712 ptr_c[i] = ptr[i];
1713
1714 ptr_c += diff;
1715 a_int = BC_NUM_INT(a);
1716 b_int = BC_NUM_INT(b);
1717
1718 if (a_int > b_int) {
1719 min_int = b_int;
1720 max = a_int;
1721 ptr = ptr_a;
1722 } else {
1723 min_int = a_int;
1724 max = b_int;
1725 ptr = ptr_b;
1726 }
1727
1728 carry = 0;
1729 for (i = 0; i < min_rdx + min_int; ++i) {
1730 unsigned in = (unsigned)ptr_a[i] + (unsigned)ptr_b[i] + carry;
1731 carry = in / 10;
1732 ptr_c[i] = (BcDig)(in % 10);
1733 }
1734 for (; i < max + min_rdx; ++i) {
1735 unsigned in = (unsigned)ptr[i] + carry;
1736 carry = in / 10;
1737 ptr_c[i] = (BcDig)(in % 10);
1738 }
1739 c->len += i;
1740
1741 if (carry != 0) c->num[c->len++] = (BcDig) carry;
1742
1743 RETURN_STATUS(BC_STATUS_SUCCESS); // can't make void, see zbc_num_binary()
1744}
1745
1746static FAST_FUNC BC_STATUS zbc_num_s(BcNum *a, BcNum *b, BcNum *restrict c, size_t sub)
1747{
1748 ssize_t cmp;
1749 BcNum *minuend, *subtrahend;
1750 size_t start;
1751 bool aneg, bneg, neg;
1752
1753 // Because this function doesn't need to use scale (per the bc spec),
1754 // I am hijacking it to say whether it's doing an add or a subtract.
1755
1756 if (a->len == 0) {
1757 bc_num_copy(c, b);
1758 if (sub && c->len) c->neg = !c->neg;
1759 RETURN_STATUS(BC_STATUS_SUCCESS);
1760 }
1761 if (b->len == 0) {
1762 bc_num_copy(c, a);
1763 RETURN_STATUS(BC_STATUS_SUCCESS);
1764 }
1765
1766 aneg = a->neg;
1767 bneg = b->neg;
1768 a->neg = b->neg = false;
1769
1770 cmp = bc_num_cmp(a, b);
1771
1772 a->neg = aneg;
1773 b->neg = bneg;
1774
1775 if (cmp == 0) {
1776 bc_num_setToZero(c, BC_MAX(a->rdx, b->rdx));
1777 RETURN_STATUS(BC_STATUS_SUCCESS);
1778 }
1779 if (cmp > 0) {
1780 neg = a->neg;
1781 minuend = a;
1782 subtrahend = b;
1783 } else {
1784 neg = b->neg;
1785 if (sub) neg = !neg;
1786 minuend = b;
1787 subtrahend = a;
1788 }
1789
1790 bc_num_copy(c, minuend);
1791 c->neg = neg;
1792
1793 if (c->rdx < subtrahend->rdx) {
1794 bc_num_extend(c, subtrahend->rdx - c->rdx);
1795 start = 0;
1796 } else
1797 start = c->rdx - subtrahend->rdx;
1798
1799 bc_num_subArrays(c->num + start, subtrahend->num, subtrahend->len);
1800
1801 bc_num_clean(c);
1802
1803 RETURN_STATUS(BC_STATUS_SUCCESS); // can't make void, see zbc_num_binary()
1804}
1805
1806static FAST_FUNC BC_STATUS zbc_num_k(BcNum *restrict a, BcNum *restrict b,
1807 BcNum *restrict c)
1808#define zbc_num_k(...) (zbc_num_k(__VA_ARGS__) COMMA_SUCCESS)
1809{
1810 BcStatus s;
1811 size_t max = BC_MAX(a->len, b->len), max2 = (max + 1) / 2;
1812 BcNum l1, h1, l2, h2, m2, m1, z0, z1, z2, temp;
1813 bool aone;
1814
1815 if (a->len == 0 || b->len == 0) {
1816 bc_num_zero(c);
1817 RETURN_STATUS(BC_STATUS_SUCCESS);
1818 }
1819 aone = BC_NUM_ONE(a);
1820 if (aone || BC_NUM_ONE(b)) {
1821 bc_num_copy(c, aone ? b : a);
1822 RETURN_STATUS(BC_STATUS_SUCCESS);
1823 }
1824
1825 if (a->len + b->len < BC_NUM_KARATSUBA_LEN
1826 || a->len < BC_NUM_KARATSUBA_LEN
1827 || b->len < BC_NUM_KARATSUBA_LEN
1828 ) {
1829 size_t i, j, len;
1830
1831 bc_num_expand(c, a->len + b->len + 1);
1832
1833 memset(c->num, 0, sizeof(BcDig) * c->cap);
1834 c->len = len = 0;
1835
1836 for (i = 0; i < b->len; ++i) {
1837 unsigned carry = 0;
1838 for (j = 0; j < a->len; ++j) {
1839 unsigned in = c->num[i + j];
1840 in += (unsigned)a->num[j] * (unsigned)b->num[i] + carry;
1841 // note: compilers prefer _unsigned_ div/const
1842 carry = in / 10;
1843 c->num[i + j] = (BcDig)(in % 10);
1844 }
1845
1846 c->num[i + j] += (BcDig) carry;
1847 len = BC_MAX(len, i + j + !!carry);
1848
1849#if ENABLE_FEATURE_BC_INTERACTIVE
1850 // a=2^1000000
1851 // a*a <- without check below, this will not be interruptible
1852 if (G_interrupt) return BC_STATUS_FAILURE;
1853#endif
1854 }
1855
1856 c->len = len;
1857
1858 RETURN_STATUS(BC_STATUS_SUCCESS);
1859 }
1860
1861 bc_num_init(&l1, max);
1862 bc_num_init(&h1, max);
1863 bc_num_init(&l2, max);
1864 bc_num_init(&h2, max);
1865 bc_num_init(&m1, max);
1866 bc_num_init(&m2, max);
1867 bc_num_init(&z0, max);
1868 bc_num_init(&z1, max);
1869 bc_num_init(&z2, max);
1870 bc_num_init(&temp, max + max);
1871
1872 bc_num_split(a, max2, &l1, &h1);
1873 bc_num_split(b, max2, &l2, &h2);
1874
1875 s = zbc_num_add(&h1, &l1, &m1, 0);
1876 if (s) goto err;
1877 s = zbc_num_add(&h2, &l2, &m2, 0);
1878 if (s) goto err;
1879
1880 s = zbc_num_k(&h1, &h2, &z0);
1881 if (s) goto err;
1882 s = zbc_num_k(&m1, &m2, &z1);
1883 if (s) goto err;
1884 s = zbc_num_k(&l1, &l2, &z2);
1885 if (s) goto err;
1886
1887 s = zbc_num_sub(&z1, &z0, &temp, 0);
1888 if (s) goto err;
1889 s = zbc_num_sub(&temp, &z2, &z1, 0);
1890 if (s) goto err;
1891
1892 s = zbc_num_shift(&z0, max2 * 2);
1893 if (s) goto err;
1894 s = zbc_num_shift(&z1, max2);
1895 if (s) goto err;
1896 s = zbc_num_add(&z0, &z1, &temp, 0);
1897 if (s) goto err;
1898 s = zbc_num_add(&temp, &z2, c, 0);
1899 err:
1900 bc_num_free(&temp);
1901 bc_num_free(&z2);
1902 bc_num_free(&z1);
1903 bc_num_free(&z0);
1904 bc_num_free(&m2);
1905 bc_num_free(&m1);
1906 bc_num_free(&h2);
1907 bc_num_free(&l2);
1908 bc_num_free(&h1);
1909 bc_num_free(&l1);
1910 RETURN_STATUS(s);
1911}
1912
1913static FAST_FUNC BC_STATUS zbc_num_m(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1914{
1915 BcStatus s;
1916 BcNum cpa, cpb;
1917 size_t maxrdx = BC_MAX(a->rdx, b->rdx);
1918
1919 scale = BC_MAX(scale, a->rdx);
1920 scale = BC_MAX(scale, b->rdx);
1921 scale = BC_MIN(a->rdx + b->rdx, scale);
1922 maxrdx = BC_MAX(maxrdx, scale);
1923
1924 bc_num_init(&cpa, a->len);
1925 bc_num_init(&cpb, b->len);
1926
1927 bc_num_copy(&cpa, a);
1928 bc_num_copy(&cpb, b);
1929 cpa.neg = cpb.neg = false;
1930
1931 s = zbc_num_shift(&cpa, maxrdx);
1932 if (s) goto err;
1933 s = zbc_num_shift(&cpb, maxrdx);
1934 if (s) goto err;
1935 s = zbc_num_k(&cpa, &cpb, c);
1936 if (s) goto err;
1937
1938 maxrdx += scale;
1939 bc_num_expand(c, c->len + maxrdx);
1940
1941 if (c->len < maxrdx) {
1942 memset(c->num + c->len, 0, (c->cap - c->len) * sizeof(BcDig));
1943 c->len += maxrdx;
1944 }
1945
1946 c->rdx = maxrdx;
1947 bc_num_retireMul(c, scale, a->neg, b->neg);
1948 err:
1949 bc_num_free(&cpb);
1950 bc_num_free(&cpa);
1951 RETURN_STATUS(s);
1952}
1953#define zbc_num_m(...) (zbc_num_m(__VA_ARGS__) COMMA_SUCCESS)
1954
1955static FAST_FUNC BC_STATUS zbc_num_d(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
1956{
1957 BcStatus s;
1958 size_t len, end, i;
1959 BcNum cp;
1960
1961 if (b->len == 0)
1962 RETURN_STATUS(bc_error("divide by zero"));
1963 if (a->len == 0) {
1964 bc_num_setToZero(c, scale);
1965 RETURN_STATUS(BC_STATUS_SUCCESS);
1966 }
1967 if (BC_NUM_ONE(b)) {
1968 bc_num_copy(c, a);
1969 bc_num_retireMul(c, scale, a->neg, b->neg);
1970 RETURN_STATUS(BC_STATUS_SUCCESS);
1971 }
1972
1973 bc_num_init(&cp, BC_NUM_MREQ(a, b, scale));
1974 bc_num_copy(&cp, a);
1975 len = b->len;
1976
1977 if (len > cp.len) {
1978 bc_num_expand(&cp, len + 2);
1979 bc_num_extend(&cp, len - cp.len);
1980 }
1981
1982 if (b->rdx > cp.rdx) bc_num_extend(&cp, b->rdx - cp.rdx);
1983 cp.rdx -= b->rdx;
1984 if (scale > cp.rdx) bc_num_extend(&cp, scale - cp.rdx);
1985
1986 if (b->rdx == b->len) {
1987 for (;;) {
1988 if (len == 0) break;
1989 len--;
1990 if (b->num[len] != 0)
1991 break;
1992 }
1993 len++;
1994 }
1995
1996 if (cp.cap == cp.len) bc_num_expand(&cp, cp.len + 1);
1997
1998 // We want an extra zero in front to make things simpler.
1999 cp.num[cp.len++] = 0;
2000 end = cp.len - len;
2001
2002 bc_num_expand(c, cp.len);
2003
2004 bc_num_zero(c);
2005 memset(c->num + end, 0, (c->cap - end) * sizeof(BcDig));
2006 c->rdx = cp.rdx;
2007 c->len = cp.len;
2008
2009 s = BC_STATUS_SUCCESS;
2010 for (i = end - 1; i < end; --i) {
2011 BcDig *n, q;
2012 n = cp.num + i;
2013 for (q = 0; n[len] != 0 || bc_num_compare(n, b->num, len) >= 0; ++q)
2014 bc_num_subArrays(n, b->num, len);
2015 c->num[i] = q;
2016#if ENABLE_FEATURE_BC_INTERACTIVE
2017 // a=2^100000
2018 // scale=40000
2019 // 1/a <- without check below, this will not be interruptible
2020 if (G_interrupt) {
2021 s = BC_STATUS_FAILURE;
2022 break;
2023 }
2024#endif
2025 }
2026
2027 bc_num_retireMul(c, scale, a->neg, b->neg);
2028 bc_num_free(&cp);
2029
2030 RETURN_STATUS(s);
2031}
2032#define zbc_num_d(...) (zbc_num_d(__VA_ARGS__) COMMA_SUCCESS)
2033
2034static FAST_FUNC BC_STATUS zbc_num_r(BcNum *a, BcNum *b, BcNum *restrict c,
2035 BcNum *restrict d, size_t scale, size_t ts)
2036{
2037 BcStatus s;
2038 BcNum temp;
2039 bool neg;
2040
2041 if (b->len == 0)
2042 RETURN_STATUS(bc_error("divide by zero"));
2043
2044 if (a->len == 0) {
2045 bc_num_setToZero(d, ts);
2046 RETURN_STATUS(BC_STATUS_SUCCESS);
2047 }
2048
2049 bc_num_init(&temp, d->cap);
2050 s = zbc_num_d(a, b, c, scale);
2051 if (s) goto err;
2052
2053 if (scale != 0) scale = ts;
2054
2055 s = zbc_num_m(c, b, &temp, scale);
2056 if (s) goto err;
2057 s = zbc_num_sub(a, &temp, d, scale);
2058 if (s) goto err;
2059
2060 if (ts > d->rdx && d->len) bc_num_extend(d, ts - d->rdx);
2061
2062 neg = d->neg;
2063 bc_num_retireMul(d, ts, a->neg, b->neg);
2064 d->neg = neg;
2065 err:
2066 bc_num_free(&temp);
2067 RETURN_STATUS(s);
2068}
2069#define zbc_num_r(...) (zbc_num_r(__VA_ARGS__) COMMA_SUCCESS)
2070
2071static FAST_FUNC BC_STATUS zbc_num_rem(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
2072{
2073 BcStatus s;
2074 BcNum c1;
2075 size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts);
2076
2077 bc_num_init(&c1, len);
2078 s = zbc_num_r(a, b, &c1, c, scale, ts);
2079 bc_num_free(&c1);
2080
2081 RETURN_STATUS(s);
2082}
2083#define zbc_num_rem(...) (zbc_num_rem(__VA_ARGS__) COMMA_SUCCESS)
2084
2085static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size_t scale)
2086{
2087 BcStatus s = BC_STATUS_SUCCESS;
2088 BcNum copy;
2089 unsigned long pow;
2090 size_t i, powrdx, resrdx;
2091 bool neg;
2092
2093 // GNU bc does not allow 2^2.0 - we do
2094 for (i = 0; i < b->rdx; i++)
2095 if (b->num[i] != 0)
2096 RETURN_STATUS(bc_error("not an integer"));
2097
2098 if (b->len == 0) {
2099 bc_num_one(c);
2100 RETURN_STATUS(BC_STATUS_SUCCESS);
2101 }
2102 if (a->len == 0) {
2103 bc_num_setToZero(c, scale);
2104 RETURN_STATUS(BC_STATUS_SUCCESS);
2105 }
2106 if (BC_NUM_ONE(b)) {
2107 if (!b->neg)
2108 bc_num_copy(c, a);
2109 else
2110 s = zbc_num_inv(a, c, scale);
2111 RETURN_STATUS(s);
2112 }
2113
2114 neg = b->neg;
2115 s = zbc_num_ulong_abs(b, &pow);
2116 if (s) RETURN_STATUS(s);
2117 // b is not used beyond this point
2118
2119 bc_num_init(&copy, a->len);
2120 bc_num_copy(&copy, a);
2121
2122 if (!neg) {
2123 if (a->rdx > scale)
2124 scale = a->rdx;
2125 if (a->rdx * pow < scale)
2126 scale = a->rdx * pow;
2127 }
2128
2129
2130 for (powrdx = a->rdx; !(pow & 1); pow >>= 1) {
2131 powrdx <<= 1;
2132 s = zbc_num_mul(&copy, &copy, &copy, powrdx);
2133 if (s) goto err;
2134 // Not needed: zbc_num_mul() has a check for ^C:
2135 //if (G_interrupt) {
2136 // s = BC_STATUS_FAILURE;
2137 // goto err;
2138 //}
2139 }
2140
2141 bc_num_copy(c, &copy);
2142
2143 for (resrdx = powrdx, pow >>= 1; pow != 0; pow >>= 1) {
2144 powrdx <<= 1;
2145 s = zbc_num_mul(&copy, &copy, &copy, powrdx);
2146 if (s) goto err;
2147
2148 if (pow & 1) {
2149 resrdx += powrdx;
2150 s = zbc_num_mul(c, &copy, c, resrdx);
2151 if (s) goto err;
2152 }
2153 // Not needed: zbc_num_mul() has a check for ^C:
2154 //if (G_interrupt) {
2155 // s = BC_STATUS_FAILURE;
2156 // goto err;
2157 //}
2158 }
2159
2160 if (neg) {
2161 s = zbc_num_inv(c, c, scale);
2162 if (s) goto err;
2163 }
2164
2165 if (c->rdx > scale) bc_num_truncate(c, c->rdx - scale);
2166
2167 // We can't use bc_num_clean() here.
2168 for (i = 0; i < c->len; ++i)
2169 if (c->num[i] != 0)
2170 goto skip;
2171 bc_num_setToZero(c, scale);
2172 skip:
2173
2174 err:
2175 bc_num_free(&copy);
2176 RETURN_STATUS(s);
2177}
2178#define zbc_num_p(...) (zbc_num_p(__VA_ARGS__) COMMA_SUCCESS)
2179
2180static BC_STATUS zbc_num_sqrt(BcNum *a, BcNum *restrict b, size_t scale)
2181{
2182 BcStatus s;
2183 BcNum num1, num2, half, f, fprime, *x0, *x1, *temp;
2184 BcDig half_digs[1];
2185 size_t pow, len, digs, digs1, resrdx, req, times = 0;
2186 ssize_t cmp = 1, cmp1 = SSIZE_MAX, cmp2 = SSIZE_MAX;
2187
2188 req = BC_MAX(scale, a->rdx) + ((BC_NUM_INT(a) + 1) >> 1) + 1;
2189 bc_num_expand(b, req);
2190
2191 if (a->len == 0) {
2192 bc_num_setToZero(b, scale);
2193 RETURN_STATUS(BC_STATUS_SUCCESS);
2194 }
2195 if (a->neg) {
2196 RETURN_STATUS(bc_error("negative number"));
2197 }
2198 if (BC_NUM_ONE(a)) {
2199 bc_num_one(b);
2200 bc_num_extend(b, scale);
2201 RETURN_STATUS(BC_STATUS_SUCCESS);
2202 }
2203
2204 scale = BC_MAX(scale, a->rdx) + 1;
2205 len = a->len + scale;
2206
2207 bc_num_init(&num1, len);
2208 bc_num_init(&num2, len);
2209
2210 half.cap = ARRAY_SIZE(half_digs);
2211 half.num = half_digs;
2212 bc_num_one(&half);
2213 half_digs[0] = 5;
2214 half.rdx = 1;
2215
2216 bc_num_init(&f, len);
2217 bc_num_init(&fprime, len);
2218
2219 x0 = &num1;
2220 x1 = &num2;
2221
2222 bc_num_one(x0);
2223 pow = BC_NUM_INT(a);
2224
2225 if (pow) {
2226 if (pow & 1)
2227 x0->num[0] = 2;
2228 else
2229 x0->num[0] = 6;
2230
2231 pow -= 2 - (pow & 1);
2232
2233 bc_num_extend(x0, pow);
2234
2235 // Make sure to move the radix back.
2236 x0->rdx -= pow;
2237 }
2238
2239 x0->rdx = digs = digs1 = 0;
2240 resrdx = scale + 2;
2241 len = BC_NUM_INT(x0) + resrdx - 1;
2242
2243 while (cmp != 0 || digs < len) {
2244 s = zbc_num_div(a, x0, &f, resrdx);
2245 if (s) goto err;
2246 s = zbc_num_add(x0, &f, &fprime, resrdx);
2247 if (s) goto err;
2248 s = zbc_num_mul(&fprime, &half, x1, resrdx);
2249 if (s) goto err;
2250
2251 cmp = bc_num_cmp(x1, x0);
2252 digs = x1->len - (unsigned long long) llabs(cmp);
2253
2254 if (cmp == cmp2 && digs == digs1)
2255 times += 1;
2256 else
2257 times = 0;
2258
2259 resrdx += times > 4;
2260
2261 cmp2 = cmp1;
2262 cmp1 = cmp;
2263 digs1 = digs;
2264
2265 temp = x0;
2266 x0 = x1;
2267 x1 = temp;
2268 }
2269
2270 bc_num_copy(b, x0);
2271 scale -= 1;
2272 if (b->rdx > scale) bc_num_truncate(b, b->rdx - scale);
2273 err:
2274 bc_num_free(&fprime);
2275 bc_num_free(&f);
2276 bc_num_free(&num2);
2277 bc_num_free(&num1);
2278 RETURN_STATUS(s);
2279}
2280#define zbc_num_sqrt(...) (zbc_num_sqrt(__VA_ARGS__) COMMA_SUCCESS)
2281
2282static BC_STATUS zbc_num_divmod(BcNum *a, BcNum *b, BcNum *c, BcNum *d,
2283 size_t scale)
2284{
2285 BcStatus s;
2286 BcNum num2, *ptr_a;
2287 bool init = false;
2288 size_t ts = BC_MAX(scale + b->rdx, a->rdx), len = BC_NUM_MREQ(a, b, ts);
2289
2290 if (c == a) {
2291 memcpy(&num2, c, sizeof(BcNum));
2292 ptr_a = &num2;
2293 bc_num_init(c, len);
2294 init = true;
2295 } else {
2296 ptr_a = a;
2297 bc_num_expand(c, len);
2298 }
2299
2300 s = zbc_num_r(ptr_a, b, c, d, scale, ts);
2301
2302 if (init) bc_num_free(&num2);
2303
2304 RETURN_STATUS(s);
2305}
2306#define zbc_num_divmod(...) (zbc_num_divmod(__VA_ARGS__) COMMA_SUCCESS)
2307
2308#if ENABLE_DC
2309static BC_STATUS zdc_num_modexp(BcNum *a, BcNum *b, BcNum *c, BcNum *restrict d)
2310{
2311 BcStatus s;
2312 BcNum base, exp, two, temp;
2313 BcDig two_digs[1];
2314
2315 if (c->len == 0)
2316 RETURN_STATUS(bc_error("divide by zero"));
2317 if (a->rdx || b->rdx || c->rdx)
2318 RETURN_STATUS(bc_error("not an integer"));
2319 if (b->neg)
2320 RETURN_STATUS(bc_error("negative number"));
2321
2322 bc_num_expand(d, c->len);
2323 bc_num_init(&base, c->len);
2324 bc_num_init(&exp, b->len);
2325 bc_num_init(&temp, b->len);
2326
2327 two.cap = ARRAY_SIZE(two_digs);
2328 two.num = two_digs;
2329 bc_num_one(&two);
2330 two_digs[0] = 2;
2331
2332 bc_num_one(d);
2333
2334 s = zbc_num_rem(a, c, &base, 0);
2335 if (s) goto err;
2336 bc_num_copy(&exp, b);
2337
2338 while (exp.len != 0) {
2339 s = zbc_num_divmod(&exp, &two, &exp, &temp, 0);
2340 if (s) goto err;
2341
2342 if (BC_NUM_ONE(&temp)) {
2343 s = zbc_num_mul(d, &base, &temp, 0);
2344 if (s) goto err;
2345 s = zbc_num_rem(&temp, c, d, 0);
2346 if (s) goto err;
2347 }
2348
2349 s = zbc_num_mul(&base, &base, &temp, 0);
2350 if (s) goto err;
2351 s = zbc_num_rem(&temp, c, &base, 0);
2352 if (s) goto err;
2353 }
2354 err:
2355 bc_num_free(&temp);
2356 bc_num_free(&exp);
2357 bc_num_free(&base);
2358 RETURN_STATUS(s);
2359}
2360#define zdc_num_modexp(...) (zdc_num_modexp(__VA_ARGS__) COMMA_SUCCESS)
2361#endif // ENABLE_DC
2362
2363static FAST_FUNC void bc_string_free(void *string)
2364{
2365 free(*(char**)string);
2366}
2367
2368static void bc_func_init(BcFunc *f)
2369{
2370 bc_char_vec_init(&f->code);
2371 IF_BC(bc_vec_init(&f->labels, sizeof(size_t), NULL);)
2372 IF_BC(bc_vec_init(&f->autos, sizeof(BcId), bc_id_free);)
2373 IF_BC(bc_vec_init(&f->strs, sizeof(char *), bc_string_free);)
2374 IF_BC(bc_vec_init(&f->consts, sizeof(char *), bc_string_free);)
2375 IF_BC(f->nparams = 0;)
2376}
2377
2378static FAST_FUNC void bc_func_free(void *func)
2379{
2380 BcFunc *f = (BcFunc *) func;
2381 bc_vec_free(&f->code);
2382 IF_BC(bc_vec_free(&f->labels);)
2383 IF_BC(bc_vec_free(&f->autos);)
2384 IF_BC(bc_vec_free(&f->strs);)
2385 IF_BC(bc_vec_free(&f->consts);)
2386}
2387
2388static void bc_array_expand(BcVec *a, size_t len);
2389
2390static void bc_array_init(BcVec *a, bool nums)
2391{
2392 if (nums)
2393 bc_vec_init(a, sizeof(BcNum), bc_num_free);
2394 else
2395 bc_vec_init(a, sizeof(BcVec), bc_vec_free);
2396 bc_array_expand(a, 1);
2397}
2398
2399static void bc_array_expand(BcVec *a, size_t len)
2400{
2401 if (a->dtor == bc_num_free
2402 // && a->size == sizeof(BcNum) - always true
2403 ) {
2404 BcNum n;
2405 while (len > a->len) {
2406 bc_num_init_DEF_SIZE(&n);
2407 bc_vec_push(a, &n);
2408 }
2409 } else {
2410 BcVec v;
2411 while (len > a->len) {
2412 bc_array_init(&v, true);
2413 bc_vec_push(a, &v);
2414 }
2415 }
2416}
2417
2418static void bc_array_copy(BcVec *d, const BcVec *s)
2419{
2420 BcNum *dnum, *snum;
2421 size_t i;
2422
2423 bc_vec_pop_all(d);
2424 bc_vec_expand(d, s->cap);
2425 d->len = s->len;
2426
2427 dnum = (void*)d->v;
2428 snum = (void*)s->v;
2429 for (i = 0; i < s->len; i++, dnum++, snum++) {
2430 bc_num_init(dnum, snum->len);
2431 bc_num_copy(dnum, snum);
2432 }
2433}
2434
2435#if ENABLE_DC
2436static void dc_result_copy(BcResult *d, BcResult *src)
2437{
2438 d->t = src->t;
2439
2440 switch (d->t) {
2441 case XC_RESULT_TEMP:
2442 case XC_RESULT_IBASE:
2443 case XC_RESULT_SCALE:
2444 case XC_RESULT_OBASE:
2445 bc_num_init(&d->d.n, src->d.n.len);
2446 bc_num_copy(&d->d.n, &src->d.n);
2447 break;
2448 case XC_RESULT_VAR:
2449 case XC_RESULT_ARRAY:
2450 case XC_RESULT_ARRAY_ELEM:
2451 d->d.id.name = xstrdup(src->d.id.name);
2452 break;
2453 case XC_RESULT_CONSTANT:
2454 case XC_RESULT_STR:
2455 memcpy(&d->d.n, &src->d.n, sizeof(BcNum));
2456 break;
2457 default: // placate compiler
2458 // BC_RESULT_VOID, BC_RESULT_LAST, BC_RESULT_ONE - do not happen
2459 break;
2460 }
2461}
2462#endif // ENABLE_DC
2463
2464static FAST_FUNC void bc_result_free(void *result)
2465{
2466 BcResult *r = (BcResult *) result;
2467
2468 switch (r->t) {
2469 case XC_RESULT_TEMP:
2470 IF_BC(case BC_RESULT_VOID:)
2471 case XC_RESULT_IBASE:
2472 case XC_RESULT_SCALE:
2473 case XC_RESULT_OBASE:
2474 bc_num_free(&r->d.n);
2475 break;
2476 case XC_RESULT_VAR:
2477 case XC_RESULT_ARRAY:
2478 case XC_RESULT_ARRAY_ELEM:
2479 free(r->d.id.name);
2480 break;
2481 default:
2482 // Do nothing.
2483 break;
2484 }
2485}
2486
2487static int bad_input_byte(char c)
2488{
2489 if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'?
2490 || c > 0x7e
2491 ) {
2492 bc_error_fmt("illegal character 0x%02x", c);
2493 return 1;
2494 }
2495 return 0;
2496}
2497
2498static void xc_read_line(BcVec *vec, FILE *fp)
2499{
2500 again:
2501 bc_vec_pop_all(vec);
2502 fflush_and_check();
2503
2504#if ENABLE_FEATURE_BC_INTERACTIVE
2505 if (G_interrupt) { // ^C was pressed
2506 intr:
2507 if (fp != stdin) {
2508 // ^C while running a script (bc SCRIPT): die.
2509 // We do not return to interactive prompt:
2510 // user might be running us from a shell,
2511 // and SCRIPT might be intended to terminate
2512 // (e.g. contain a "halt" stmt).
2513 // ^C dropping user into a bc prompt instead of
2514 // the shell would be unexpected.
2515 xfunc_die();
2516 }
2517 // ^C while interactive input
2518 G_interrupt = 0;
2519 // GNU bc says "interrupted execution."
2520 // GNU dc says "Interrupt!"
2521 fputs("\ninterrupted execution\n", stderr);
2522 }
2523
2524# if ENABLE_FEATURE_EDITING
2525 if (G_ttyin && fp == stdin) {
2526 int n, i;
2527# define line_buf bb_common_bufsiz1
2528 n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE);
2529 if (n <= 0) { // read errors or EOF, or ^D, or ^C
2530 if (n == 0) // ^C
2531 goto intr;
2532 bc_vec_pushZeroByte(vec); // ^D or EOF (or error)
2533 return;
2534 }
2535 i = 0;
2536 for (;;) {
2537 char c = line_buf[i++];
2538 if (c == '\0') break;
2539 if (bad_input_byte(c)) goto again;
2540 }
2541 bc_vec_string(vec, n, line_buf);
2542# undef line_buf
2543 } else
2544# endif
2545#endif
2546 {
2547 int c;
2548 bool bad_chars = 0;
2549
2550 do {
2551 get_char:
2552#if ENABLE_FEATURE_BC_INTERACTIVE
2553 if (G_interrupt) {
2554 // ^C was pressed: ignore entire line, get another one
2555 goto again;
2556 }
2557#endif
2558 c = fgetc(fp);
2559 if (c == '\0')
2560 goto get_char;
2561 if (c == EOF) {
2562 if (ferror(fp))
2563 bb_perror_msg_and_die("input error");
2564 // Note: EOF does not append '\n'
2565 break;
2566 }
2567 bad_chars |= bad_input_byte(c);
2568 bc_vec_pushByte(vec, (char)c);
2569 } while (c != '\n');
2570
2571 if (bad_chars) {
2572 // Bad chars on this line
2573 if (!G.prs.lex_filename) { // stdin
2574 // ignore entire line, get another one
2575 goto again;
2576 }
2577 bb_perror_msg_and_die("file '%s' is not text", G.prs.lex_filename);
2578 }
2579 bc_vec_pushZeroByte(vec);
2580 }
2581}
2582
2583//
2584// Parsing routines
2585//
2586
2587// "Input numbers may contain the characters 0-9 and A-Z.
2588// (Note: They must be capitals. Lower case letters are variable names.)
2589// Single digit numbers always have the value of the digit regardless of
2590// the value of ibase. (i.e. A = 10.) For multi-digit numbers, bc changes
2591// all input digits greater or equal to ibase to the value of ibase-1.
2592// This makes the number ZZZ always be the largest 3 digit number of the
2593// input base."
2594static bool xc_num_strValid(const char *val)
2595{
2596 bool radix = false;
2597 for (;;) {
2598 BcDig c = *val++;
2599 if (c == '\0')
2600 break;
2601 if (c == '.') {
2602 if (radix) return false;
2603 radix = true;
2604 continue;
2605 }
2606 if ((c < '0' || c > '9') && (c < 'A' || c > 'Z'))
2607 return false;
2608 }
2609 return true;
2610}
2611
2612// Note: n is already "bc_num_zero()"ed,
2613// leading zeroes in "val" are removed
2614static void bc_num_parseDecimal(BcNum *n, const char *val)
2615{
2616 size_t len, i;
2617 const char *ptr;
2618
2619 len = strlen(val);
2620 if (len == 0)
2621 return;
2622
2623 bc_num_expand(n, len + 1); // +1 for e.g. "A" converting into 10
2624
2625 ptr = strchr(val, '.');
2626
2627 n->rdx = 0;
2628 if (ptr != NULL)
2629 n->rdx = (size_t)((val + len) - (ptr + 1));
2630
2631 for (i = 0; val[i]; ++i) {
2632 if (val[i] != '0' && val[i] != '.') {
2633 // Not entirely zero value - convert it, and exit
2634 if (len == 1) {
2635 unsigned c = val[0] - '0';
2636 n->len = 1;
2637 if (c > 9) { // A-Z => 10-36
2638 n->len = 2;
2639 c -= ('A' - '9' - 1);
2640 n->num[1] = c/10;
2641 c = c%10;
2642 }
2643 n->num[0] = c;
2644 break;
2645 }
2646 i = len - 1;
2647 for (;;) {
2648 char c = val[i] - '0';
2649 if (c > 9) // A-Z => 9
2650 c = 9;
2651 n->num[n->len] = c;
2652 n->len++;
2653 skip_dot:
2654 if (i == 0) break;
2655 if (val[--i] == '.') goto skip_dot;
2656 }
2657 break;
2658 }
2659 }
2660 // if for() exits without hitting if(), the value is entirely zero
2661}
2662
2663// Note: n is already "bc_num_zero()"ed,
2664// leading zeroes in "val" are removed
2665static void bc_num_parseBase(BcNum *n, const char *val, unsigned base_t)
2666{
2667 BcStatus s;
2668 BcNum mult, result;
2669 BcNum temp;
2670 BcNum base;
2671 BcDig temp_digs[ULONG_NUM_BUFSIZE];
2672 BcDig base_digs[ULONG_NUM_BUFSIZE];
2673 size_t digits;
2674
2675 bc_num_init_DEF_SIZE(&mult);
2676
2677 temp.cap = ARRAY_SIZE(temp_digs);
2678 temp.num = temp_digs;
2679
2680 base.cap = ARRAY_SIZE(base_digs);
2681 base.num = base_digs;
2682 bc_num_ulong2num(&base, base_t);
2683 base_t--;
2684
2685 for (;;) {
2686 unsigned v;
2687 char c;
2688
2689 c = *val++;
2690 if (c == '\0') goto int_err;
2691 if (c == '.') break;
2692
2693 v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10);
2694 if (v > base_t) v = base_t;
2695
2696 s = zbc_num_mul(n, &base, &mult, 0);
2697 if (s) goto int_err;
2698 bc_num_ulong2num(&temp, v);
2699 s = zbc_num_add(&mult, &temp, n, 0);
2700 if (s) goto int_err;
2701 }
2702
2703 bc_num_init(&result, base.len);
2704 //bc_num_zero(&result); - already is
2705 bc_num_one(&mult);
2706
2707 digits = 0;
2708 for (;;) {
2709 unsigned v;
2710 char c;
2711
2712 c = *val++;
2713 if (c == '\0') break;
2714 digits++;
2715
2716 v = (unsigned)(c <= '9' ? c - '0' : c - 'A' + 10);
2717 if (v > base_t) v = base_t;
2718
2719 s = zbc_num_mul(&result, &base, &result, 0);
2720 if (s) goto err;
2721 bc_num_ulong2num(&temp, v);
2722 s = zbc_num_add(&result, &temp, &result, 0);
2723 if (s) goto err;
2724 s = zbc_num_mul(&mult, &base, &mult, 0);
2725 if (s) goto err;
2726 }
2727
2728 s = zbc_num_div(&result, &mult, &result, digits);
2729 if (s) goto err;
2730 s = zbc_num_add(n, &result, n, digits);
2731 if (s) goto err;
2732
2733 if (n->len != 0) {
2734 if (n->rdx < digits)
2735 bc_num_extend(n, digits - n->rdx);
2736 } else
2737 bc_num_zero(n);
2738 err:
2739 bc_num_free(&result);
2740 int_err:
2741 bc_num_free(&mult);
2742}
2743
2744static BC_STATUS zxc_num_parse(BcNum *n, const char *val, unsigned base_t)
2745{
2746 size_t i;
2747
2748 if (!xc_num_strValid(val))
2749 RETURN_STATUS(bc_error("bad number string"));
2750
2751 bc_num_zero(n);
2752 while (*val == '0')
2753 val++;
2754 for (i = 0; ; ++i) {
2755 if (val[i] == '\0')
2756 RETURN_STATUS(BC_STATUS_SUCCESS);
2757 if (val[i] != '.' && val[i] != '0')
2758 break;
2759 }
2760
2761 if (base_t == 10 || val[1] == '\0')
2762 // Decimal, or single-digit number
2763 bc_num_parseDecimal(n, val);
2764 else
2765 bc_num_parseBase(n, val, base_t);
2766
2767 RETURN_STATUS(BC_STATUS_SUCCESS);
2768}
2769#define zxc_num_parse(...) (zxc_num_parse(__VA_ARGS__) COMMA_SUCCESS)
2770
2771// p->lex_inbuf points to the current string to be parsed.
2772// if p->lex_inbuf points to '\0', it's either EOF or it points after
2773// last processed line's terminating '\n' (and more reading needs to be done
2774// to get next character).
2775//
2776// If you are in a situation where that is a possibility, call peek_inbuf().
2777// If necessary, it performs more reading and changes p->lex_inbuf,
2778// then it returns *p->lex_inbuf (which will be '\0' only if it's EOF).
2779// After it, just referencing *p->lex_inbuf is valid, and if it wasn't '\0',
2780// it's ok to do p->lex_inbuf++ once without end-of-buffer checking.
2781//
2782// eat_inbuf() is equvalent to "peek_inbuf(); if (c) p->lex_inbuf++":
2783// it returns current char and advances the pointer (if not EOF).
2784// After eat_inbuf(), referencing p->lex_inbuf[-1] and *p->lex_inbuf is valid.
2785//
2786// In many cases, you can use fast *p->lex_inbuf instead of peek_inbuf():
2787// unless prev char might have been '\n', *p->lex_inbuf is '\0' ONLY
2788// on real EOF, not end-of-buffer.
2789//
2790// bc cases to test interactively:
2791// 1 #comment\ - prints "1<newline>" at once (comment is not continued)
2792// 1 #comment/* - prints "1<newline>" at once
2793// 1 #comment" - prints "1<newline>" at once
2794// 1\#comment - error at once (\ is not a line continuation)
2795// 1 + /*"*/2 - prints "3<newline>" at once
2796// 1 + /*#*/2 - prints "3<newline>" at once
2797// "str\" - prints "str\" at once
2798// "str#" - prints "str#" at once
2799// "str/*" - prints "str/*" at once
2800// "str#\ - waits for second line
2801// end" - ...prints "str#\<newline>end"
2802static char peek_inbuf(void)
2803{
2804 if (*G.prs.lex_inbuf == '\0'
2805 && G.prs.lex_input_fp
2806 ) {
2807 xc_read_line(&G.input_buffer, G.prs.lex_input_fp);
2808 G.prs.lex_inbuf = G.input_buffer.v;
2809 if (G.input_buffer.len <= 1) // on EOF, len is 1 (NUL byte)
2810 G.prs.lex_input_fp = NULL;
2811 }
2812 return *G.prs.lex_inbuf;
2813}
2814static char eat_inbuf(void)
2815{
2816 char c = peek_inbuf();
2817 if (c) G.prs.lex_inbuf++;
2818 return c;
2819}
2820
2821static void xc_lex_lineComment(void)
2822{
2823 BcParse *p = &G.prs;
2824 char c;
2825
2826 // Try: echo -n '#foo' | bc
2827 p->lex = XC_LEX_WHITESPACE;
2828
2829 // Not peek_inbuf(): we depend on input being done in whole lines:
2830 // '\0' which isn't the EOF can only be seen after '\n'.
2831 while ((c = *p->lex_inbuf) != '\n' && c != '\0')
2832 p->lex_inbuf++;
2833}
2834
2835static void xc_lex_whitespace(void)
2836{
2837 BcParse *p = &G.prs;
2838
2839 p->lex = XC_LEX_WHITESPACE;
2840 for (;;) {
2841 // We depend here on input being done in whole lines:
2842 // '\0' which isn't the EOF can only be seen after '\n'.
2843 char c = *p->lex_inbuf;
2844 if (c == '\n') // this is XC_LEX_NLINE, not XC_LEX_WHITESPACE
2845 break;
2846 if (!isspace(c))
2847 break;
2848 p->lex_inbuf++;
2849 }
2850}
2851
2852static BC_STATUS zxc_lex_number(char last)
2853{
2854 BcParse *p = &G.prs;
2855 bool pt;
2856 char last_valid_ch;
2857
2858 bc_vec_pop_all(&p->lex_strnumbuf);
2859 bc_vec_pushByte(&p->lex_strnumbuf, last);
2860
2861// bc: "Input numbers may contain the characters 0-9 and A-Z.
2862// (Note: They must be capitals. Lower case letters are variable names.)
2863// Single digit numbers always have the value of the digit regardless of
2864// the value of ibase. (i.e. A = 10.) For multi-digit numbers, bc changes
2865// all input digits greater or equal to ibase to the value of ibase-1.
2866// This makes the number ZZZ always be the largest 3 digit number of the
2867// input base."
2868// dc only allows A-F, the rules about single-char and multi-char are the same.
2869 last_valid_ch = (IS_BC ? 'Z' : 'F');
2870 pt = (last == '.');
2871 p->lex = XC_LEX_NUMBER;
2872 for (;;) {
2873 // We depend here on input being done in whole lines:
2874 // '\0' which isn't the EOF can only be seen after '\n'.
2875 char c = *p->lex_inbuf;
2876 check_c:
2877 if (c == '\0')
2878 break;
2879 if (c == '\\' && p->lex_inbuf[1] == '\n') {
2880 p->lex_inbuf += 2;
2881 p->lex_line++;
2882 dbg_lex("++p->lex_line=%zd", p->lex_line);
2883 c = peek_inbuf(); // force next line to be read
2884 goto check_c;
2885 }
2886 if (!isdigit(c) && (c < 'A' || c > last_valid_ch)) {
2887 if (c != '.') break;
2888 // if '.' was already seen, stop on second one:
2889 if (pt) break;
2890 pt = true;
2891 }
2892 // c is one of "0-9A-Z."
2893 last = c;
2894 bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf);
2895 p->lex_inbuf++;
2896 }
2897 if (last == '.') // remove trailing '.' if any
2898 bc_vec_pop(&p->lex_strnumbuf);
2899 bc_vec_pushZeroByte(&p->lex_strnumbuf);
2900
2901 G.err_line = G.prs.lex_line;
2902 RETURN_STATUS(BC_STATUS_SUCCESS);
2903}
2904#define zxc_lex_number(...) (zxc_lex_number(__VA_ARGS__) COMMA_SUCCESS)
2905
2906static void xc_lex_name(void)
2907{
2908 BcParse *p = &G.prs;
2909 size_t i;
2910 const char *buf;
2911
2912 p->lex = XC_LEX_NAME;
2913
2914 // Since names can't cross lines with \<newline>,
2915 // we depend on the fact that whole line is in the buffer
2916 i = 0;
2917 buf = p->lex_inbuf - 1;
2918 for (;;) {
2919 char c = buf[i];
2920 if ((c < 'a' || c > 'z') && !isdigit(c) && c != '_') break;
2921 i++;
2922 }
2923
2924#if 0 // We do not protect against people with gigabyte-long names
2925 // This check makes sense only if size_t is (much) larger than BC_MAX_STRING.
2926 if (SIZE_MAX > (BC_MAX_STRING | 0xff)) {
2927 if (i > BC_MAX_STRING)
2928 return bc_error("name too long: must be [1,"BC_MAX_STRING_STR"]");
2929 }
2930#endif
2931 bc_vec_string(&p->lex_strnumbuf, i, buf);
2932
2933 // Increment the index. We minus 1 because it has already been incremented.
2934 p->lex_inbuf += i - 1;
2935
2936 //return BC_STATUS_SUCCESS;
2937}
2938
2939IF_BC(static BC_STATUS zbc_lex_token(void);)
2940IF_DC(static BC_STATUS zdc_lex_token(void);)
2941#define zbc_lex_token(...) (zbc_lex_token(__VA_ARGS__) COMMA_SUCCESS)
2942#define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS)
2943
2944static BC_STATUS zxc_lex_next(void)
2945{
2946 BcParse *p = &G.prs;
2947 BcStatus s;
2948
2949 G.err_line = p->lex_line;
2950 p->lex_last = p->lex;
2951//why?
2952// if (p->lex_last == XC_LEX_EOF)
2953// RETURN_STATUS(bc_error("end of file"));
2954
2955 // Loop until failure or we don't have whitespace. This
2956 // is so the parser doesn't get inundated with whitespace.
2957 // Comments are also XC_LEX_WHITESPACE tokens and eaten here.
2958 s = BC_STATUS_SUCCESS;
2959 do {
2960 if (*p->lex_inbuf == '\0') {
2961 p->lex = XC_LEX_EOF;
2962 if (peek_inbuf() == '\0')
2963 RETURN_STATUS(BC_STATUS_SUCCESS);
2964 }
2965 p->lex_next_at = p->lex_inbuf;
2966 dbg_lex("next string to parse:'%.*s'",
2967 (int)(strchrnul(p->lex_next_at, '\n') - p->lex_next_at),
2968 p->lex_next_at
2969 );
2970 if (IS_BC) {
2971 IF_BC(s = zbc_lex_token());
2972 } else {
2973 IF_DC(s = zdc_lex_token());
2974 }
2975 } while (!s && p->lex == XC_LEX_WHITESPACE);
2976 dbg_lex("p->lex from string:%d", p->lex);
2977
2978 RETURN_STATUS(s);
2979}
2980#define zxc_lex_next(...) (zxc_lex_next(__VA_ARGS__) COMMA_SUCCESS)
2981
2982#if ENABLE_BC
2983static BC_STATUS zbc_lex_skip_if_at_NLINE(void)
2984{
2985 if (G.prs.lex == XC_LEX_NLINE)
2986 RETURN_STATUS(zxc_lex_next());
2987 RETURN_STATUS(BC_STATUS_SUCCESS);
2988}
2989#define zbc_lex_skip_if_at_NLINE(...) (zbc_lex_skip_if_at_NLINE(__VA_ARGS__) COMMA_SUCCESS)
2990
2991static BC_STATUS zbc_lex_next_and_skip_NLINE(void)
2992{
2993 BcStatus s;
2994 s = zxc_lex_next();
2995 if (s) RETURN_STATUS(s);
2996 // if(cond)<newline>stmt is accepted too (but not 2+ newlines)
2997 s = zbc_lex_skip_if_at_NLINE();
2998 RETURN_STATUS(s);
2999}
3000#define zbc_lex_next_and_skip_NLINE(...) (zbc_lex_next_and_skip_NLINE(__VA_ARGS__) COMMA_SUCCESS)
3001
3002static BC_STATUS zbc_lex_identifier(void)
3003{
3004 BcParse *p = &G.prs;
3005 BcStatus s;
3006 unsigned i;
3007 const char *buf = p->lex_inbuf - 1;
3008
3009 for (i = 0; i < ARRAY_SIZE(bc_lex_kws); ++i) {
3010 const char *keyword8 = bc_lex_kws[i].name8;
3011 unsigned j = 0;
3012 while (buf[j] != '\0' && buf[j] == keyword8[j]) {
3013 j++;
3014 if (j == 8) goto match;
3015 }
3016 if (keyword8[j] != '\0')
3017 continue;
3018 match:
3019 // buf starts with keyword bc_lex_kws[i]
3020 if (isalnum(buf[j]) || buf[j]=='_')
3021 continue; // "ifz" does not match "if" keyword, "if." does
3022 p->lex = BC_LEX_KEY_1st_keyword + i;
3023 if (!keyword_is_POSIX(i)) {
3024 s = zbc_posix_error_fmt("%sthe '%.8s' keyword", "POSIX does not allow ", bc_lex_kws[i].name8);
3025 if (s) RETURN_STATUS(s);
3026 }
3027
3028 // We minus 1 because the index has already been incremented.
3029 p->lex_inbuf += j - 1;
3030 RETURN_STATUS(BC_STATUS_SUCCESS);
3031 }
3032
3033 xc_lex_name();
3034 s = BC_STATUS_SUCCESS;
3035
3036 if (p->lex_strnumbuf.len > 2) {
3037 // Prevent this:
3038 // >>> qwe=1
3039 // bc: POSIX only allows one character names; this is bad: 'qwe=1
3040 // '
3041 unsigned len = strchrnul(buf, '\n') - buf;
3042 s = zbc_posix_error_fmt("POSIX only allows one character names; this is bad: '%.*s'", len, buf);
3043 }
3044
3045 RETURN_STATUS(s);
3046}
3047#define zbc_lex_identifier(...) (zbc_lex_identifier(__VA_ARGS__) COMMA_SUCCESS)
3048
3049static BC_STATUS zbc_lex_string(void)
3050{
3051 BcParse *p = &G.prs;
3052
3053 p->lex = XC_LEX_STR;
3054 bc_vec_pop_all(&p->lex_strnumbuf);
3055 for (;;) {
3056 char c = peek_inbuf(); // strings can cross lines
3057 if (c == '\0') {
3058 RETURN_STATUS(bc_error("unterminated string"));
3059 }
3060 if (c == '"')
3061 break;
3062 if (c == '\n') {
3063 p->lex_line++;
3064 dbg_lex("++p->lex_line=%zd", p->lex_line);
3065 }
3066 bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf);
3067 p->lex_inbuf++;
3068 }
3069 bc_vec_pushZeroByte(&p->lex_strnumbuf);
3070 p->lex_inbuf++;
3071
3072 G.err_line = p->lex_line;
3073 RETURN_STATUS(BC_STATUS_SUCCESS);
3074}
3075#define zbc_lex_string(...) (zbc_lex_string(__VA_ARGS__) COMMA_SUCCESS)
3076
3077static void parse_lex_by_checking_eq_sign(unsigned with_and_without)
3078{
3079 BcParse *p = &G.prs;
3080 if (*p->lex_inbuf == '=') {
3081 // ^^^ not using peek_inbuf() since '==' etc can't be split across lines
3082 p->lex_inbuf++;
3083 with_and_without >>= 8; // store "with" value
3084 } // else store "without" value
3085 p->lex = (with_and_without & 0xff);
3086}
3087#define parse_lex_by_checking_eq_sign(with, without) \
3088 parse_lex_by_checking_eq_sign(((with)<<8)|(without))
3089
3090static BC_STATUS zbc_lex_comment(void)
3091{
3092 BcParse *p = &G.prs;
3093
3094 p->lex = XC_LEX_WHITESPACE;
3095 // here lex_inbuf is at '*' of opening comment delimiter
3096 for (;;) {
3097 char c;
3098
3099 p->lex_inbuf++;
3100 c = peek_inbuf();
3101 check_star:
3102 if (c == '*') {
3103 p->lex_inbuf++;
3104 c = *p->lex_inbuf; // no need to peek_inbuf()
3105 if (c == '/')
3106 break;
3107 goto check_star;
3108 }
3109 if (c == '\0') {
3110 RETURN_STATUS(bc_error("unterminated comment"));
3111 }
3112 if (c == '\n') {
3113 p->lex_line++;
3114 dbg_lex("++p->lex_line=%zd", p->lex_line);
3115 }
3116 }
3117 p->lex_inbuf++; // skip trailing '/'
3118
3119 G.err_line = p->lex_line;
3120 RETURN_STATUS(BC_STATUS_SUCCESS);
3121}
3122#define zbc_lex_comment(...) (zbc_lex_comment(__VA_ARGS__) COMMA_SUCCESS)
3123
3124#undef zbc_lex_token
3125static BC_STATUS zbc_lex_token(void)
3126{
3127 BcParse *p = &G.prs;
3128 BcStatus s = BC_STATUS_SUCCESS;
3129 char c = eat_inbuf();
3130 char c2;
3131
3132 // This is the workhorse of the lexer.
3133 switch (c) {
3134// case '\0': // probably never reached
3135// p->lex_inbuf--;
3136// p->lex = XC_LEX_EOF;
3137// break;
3138 case '\n':
3139 p->lex_line++;
3140 dbg_lex("++p->lex_line=%zd", p->lex_line);
3141 p->lex = XC_LEX_NLINE;
3142 break;
3143 case '\t':
3144 case '\v':
3145 case '\f':
3146 case '\r':
3147 case ' ':
3148 xc_lex_whitespace();
3149 break;
3150 case '!':
3151 parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_NE, BC_LEX_OP_BOOL_NOT);
3152 if (p->lex == BC_LEX_OP_BOOL_NOT) {
3153 s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("!");
3154 if (s) RETURN_STATUS(s);
3155 }
3156 break;
3157 case '"':
3158 s = zbc_lex_string();
3159 break;
3160 case '#':
3161 s = zbc_POSIX_does_not_allow("'#' script comments");
3162 if (s) RETURN_STATUS(s);
3163 xc_lex_lineComment();
3164 break;
3165 case '%':
3166 parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MODULUS, XC_LEX_OP_MODULUS);
3167 break;
3168 case '&':
3169 c2 = *p->lex_inbuf;
3170 if (c2 == '&') {
3171 s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("&&");
3172 if (s) RETURN_STATUS(s);
3173 p->lex_inbuf++;
3174 p->lex = BC_LEX_OP_BOOL_AND;
3175 } else {
3176 p->lex = XC_LEX_INVALID;
3177 s = bc_error_bad_character('&');
3178 }
3179 break;
3180 case '(':
3181 case ')':
3182 p->lex = (BcLexType)(c - '(' + BC_LEX_LPAREN);
3183 break;
3184 case '*':
3185 parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MULTIPLY, XC_LEX_OP_MULTIPLY);
3186 break;
3187 case '+':
3188 c2 = *p->lex_inbuf;
3189 if (c2 == '+') {
3190 p->lex_inbuf++;
3191 p->lex = BC_LEX_OP_INC;
3192 } else
3193 parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_PLUS, XC_LEX_OP_PLUS);
3194 break;
3195 case ',':
3196 p->lex = BC_LEX_COMMA;
3197 break;
3198 case '-':
3199 c2 = *p->lex_inbuf;
3200 if (c2 == '-') {
3201 p->lex_inbuf++;
3202 p->lex = BC_LEX_OP_DEC;
3203 } else
3204 parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_MINUS, XC_LEX_OP_MINUS);
3205 break;
3206 case '.':
3207 if (isdigit(*p->lex_inbuf))
3208 s = zxc_lex_number(c);
3209 else {
3210 p->lex = BC_LEX_KEY_LAST;
3211 s = zbc_POSIX_does_not_allow("'.' as 'last'");
3212 }
3213 break;
3214 case '/':
3215 c2 = *p->lex_inbuf;
3216 if (c2 == '*')
3217 s = zbc_lex_comment();
3218 else
3219 parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_DIVIDE, XC_LEX_OP_DIVIDE);
3220 break;
3221 case '0':
3222 case '1':
3223 case '2':
3224 case '3':
3225 case '4':
3226 case '5':
3227 case '6':
3228 case '7':
3229 case '8':
3230 case '9':
3231 case 'A':
3232 case 'B':
3233 case 'C':
3234 case 'D':
3235 case 'E':
3236 case 'F':
3237 case 'G':
3238 case 'H':
3239 case 'I':
3240 case 'J':
3241 case 'K':
3242 case 'L':
3243 case 'M':
3244 case 'N':
3245 case 'O':
3246 case 'P':
3247 case 'Q':
3248 case 'R':
3249 case 'S':
3250 case 'T':
3251 case 'U':
3252 case 'V':
3253 case 'W':
3254 case 'X':
3255 case 'Y':
3256 case 'Z':
3257 s = zxc_lex_number(c);
3258 break;
3259 case ';':
3260 p->lex = BC_LEX_SCOLON;
3261 break;
3262 case '<':
3263 parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_LE, XC_LEX_OP_REL_LT);
3264 break;
3265 case '=':
3266 parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_EQ, BC_LEX_OP_ASSIGN);
3267 break;
3268 case '>':
3269 parse_lex_by_checking_eq_sign(XC_LEX_OP_REL_GE, XC_LEX_OP_REL_GT);
3270 break;
3271 case '[':
3272 case ']':
3273 p->lex = (BcLexType)(c - '[' + BC_LEX_LBRACKET);
3274 break;
3275 case '\\':
3276 if (*p->lex_inbuf == '\n') {
3277 p->lex = XC_LEX_WHITESPACE;
3278 p->lex_inbuf++;
3279 } else
3280 s = bc_error_bad_character(c);
3281 break;
3282 case '^':
3283 parse_lex_by_checking_eq_sign(BC_LEX_OP_ASSIGN_POWER, XC_LEX_OP_POWER);
3284 break;
3285 case 'a':
3286 case 'b':
3287 case 'c':
3288 case 'd':
3289 case 'e':
3290 case 'f':
3291 case 'g':
3292 case 'h':
3293 case 'i':
3294 case 'j':
3295 case 'k':
3296 case 'l':
3297 case 'm':
3298 case 'n':
3299 case 'o':
3300 case 'p':
3301 case 'q':
3302 case 'r':
3303 case 's':
3304 case 't':
3305 case 'u':
3306 case 'v':
3307 case 'w':
3308 case 'x':
3309 case 'y':
3310 case 'z':
3311 s = zbc_lex_identifier();
3312 break;
3313 case '{':
3314 case '}':
3315 p->lex = (BcLexType)(c - '{' + BC_LEX_LBRACE);
3316 break;
3317 case '|':
3318 c2 = *p->lex_inbuf;
3319 if (c2 == '|') {
3320 s = zbc_POSIX_does_not_allow_bool_ops_this_is_bad("||");
3321 if (s) RETURN_STATUS(s);
3322 p->lex_inbuf++;
3323 p->lex = BC_LEX_OP_BOOL_OR;
3324 } else {
3325 p->lex = XC_LEX_INVALID;
3326 s = bc_error_bad_character(c);
3327 }
3328 break;
3329 default:
3330 p->lex = XC_LEX_INVALID;
3331 s = bc_error_bad_character(c);
3332 break;
3333 }
3334
3335 RETURN_STATUS(s);
3336}
3337#define zbc_lex_token(...) (zbc_lex_token(__VA_ARGS__) COMMA_SUCCESS)
3338#endif // ENABLE_BC
3339
3340#if ENABLE_DC
3341static BC_STATUS zdc_lex_register(void)
3342{
3343 BcParse *p = &G.prs;
3344 if (G_exreg && isspace(*p->lex_inbuf)) {
3345 xc_lex_whitespace(); // eats whitespace (but not newline)
3346 p->lex_inbuf++; // xc_lex_name() expects this
3347 xc_lex_name();
3348 } else {
3349 bc_vec_pop_all(&p->lex_strnumbuf);
3350 bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf++);
3351 bc_vec_pushZeroByte(&p->lex_strnumbuf);
3352 p->lex = XC_LEX_NAME;
3353 }
3354
3355 RETURN_STATUS(BC_STATUS_SUCCESS);
3356}
3357#define zdc_lex_register(...) (zdc_lex_register(__VA_ARGS__) COMMA_SUCCESS)
3358
3359static BC_STATUS zdc_lex_string(void)
3360{
3361 BcParse *p = &G.prs;
3362 size_t depth;
3363
3364 p->lex = XC_LEX_STR;
3365 bc_vec_pop_all(&p->lex_strnumbuf);
3366
3367 depth = 1;
3368 for (;;) {
3369 char c = peek_inbuf();
3370 if (c == '\0') {
3371 RETURN_STATUS(bc_error("unterminated string"));
3372 }
3373 if (c == '[') depth++;
3374 if (c == ']')
3375 if (--depth == 0)
3376 break;
3377 if (c == '\n') {
3378 p->lex_line++;
3379 dbg_lex("++p->lex_line=%zd", p->lex_line);
3380 }
3381 bc_vec_push(&p->lex_strnumbuf, p->lex_inbuf);
3382 p->lex_inbuf++;
3383 }
3384 bc_vec_pushZeroByte(&p->lex_strnumbuf);
3385 p->lex_inbuf++; // skip trailing ']'
3386
3387 G.err_line = p->lex_line;
3388 RETURN_STATUS(BC_STATUS_SUCCESS);
3389}
3390#define zdc_lex_string(...) (zdc_lex_string(__VA_ARGS__) COMMA_SUCCESS)
3391
3392#undef zdc_lex_token
3393static BC_STATUS zdc_lex_token(void)
3394{
3395 static const //BcLexType - should be this type, but narrower type saves size:
3396 uint8_t
3397 dc_lex_regs[] ALIGN1 = {
3398 XC_LEX_OP_REL_EQ, XC_LEX_OP_REL_LE, XC_LEX_OP_REL_GE, XC_LEX_OP_REL_NE,
3399 XC_LEX_OP_REL_LT, XC_LEX_OP_REL_GT, DC_LEX_SCOLON, DC_LEX_COLON,
3400 DC_LEX_ELSE, DC_LEX_LOAD, DC_LEX_LOAD_POP, DC_LEX_OP_ASSIGN,
3401 DC_LEX_STORE_PUSH,
3402 };
3403
3404 BcParse *p = &G.prs;
3405 BcStatus s;
3406 char c, c2;
3407 size_t i;
3408
3409 for (i = 0; i < ARRAY_SIZE(dc_lex_regs); ++i) {
3410 if (p->lex_last == dc_lex_regs[i])
3411 RETURN_STATUS(zdc_lex_register());
3412 }
3413
3414 s = BC_STATUS_SUCCESS;
3415 c = eat_inbuf();
3416 if (c >= '%' && c <= '~'
3417 && (p->lex = dc_char_to_LEX[c - '%']) != XC_LEX_INVALID
3418 ) {
3419 RETURN_STATUS(s);
3420 }
3421
3422 // This is the workhorse of the lexer.
3423 switch (c) {
3424// case '\0': // probably never reached
3425// p->lex = XC_LEX_EOF;
3426// break;
3427 case '\n':
3428 // '\n' is XC_LEX_NLINE, not XC_LEX_WHITESPACE
3429 // (and "case '\n':" is not just empty here)
3430 // only to allow interactive dc have a way to exit
3431 // "parse" stage of "parse,execute" loop
3432 // on <enter>, not on _next_ token (which would mean
3433 // commands are not executed on pressing <enter>).
3434 // IOW: typing "1p<enter>" should print "1" _at once_,
3435 // not after some more input.
3436 p->lex_line++;
3437 dbg_lex("++p->lex_line=%zd", p->lex_line);
3438 p->lex = XC_LEX_NLINE;
3439 break;
3440 case '\t':
3441 case '\v':
3442 case '\f':
3443 case '\r':
3444 case ' ':
3445 xc_lex_whitespace();
3446 break;
3447 case '!':
3448 c2 = *p->lex_inbuf;
3449 if (c2 == '=')
3450 p->lex = XC_LEX_OP_REL_NE;
3451 else if (c2 == '<')
3452 p->lex = XC_LEX_OP_REL_LE;
3453 else if (c2 == '>')
3454 p->lex = XC_LEX_OP_REL_GE;
3455 else
3456 RETURN_STATUS(bc_error_bad_character(c));
3457 p->lex_inbuf++;
3458 break;
3459 case '#':
3460 xc_lex_lineComment();
3461 break;
3462 case '.':
3463 if (isdigit(*p->lex_inbuf))
3464 s = zxc_lex_number(c);
3465 else
3466 s = bc_error_bad_character(c);
3467 break;
3468 case '0':
3469 case '1':
3470 case '2':
3471 case '3':
3472 case '4':
3473 case '5':
3474 case '6':
3475 case '7':
3476 case '8':
3477 case '9':
3478 case 'A':
3479 case 'B':
3480 case 'C':
3481 case 'D':
3482 case 'E':
3483 case 'F':
3484 s = zxc_lex_number(c);
3485 break;
3486 case '[':
3487 s = zdc_lex_string();
3488 break;
3489 default:
3490 p->lex = XC_LEX_INVALID;
3491 s = bc_error_bad_character(c);
3492 break;
3493 }
3494
3495 RETURN_STATUS(s);
3496}
3497#define zdc_lex_token(...) (zdc_lex_token(__VA_ARGS__) COMMA_SUCCESS)
3498#endif // ENABLE_DC
3499
3500static void xc_parse_push(unsigned i)
3501{
3502 BcVec *code = &G.prs.func->code;
3503 dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, code->len, i);
3504 bc_vec_pushByte(code, (uint8_t)i);
3505}
3506
3507static void xc_parse_pushName(char *name)
3508{
3509#if 1
3510 BcVec *code = &G.prs.func->code;
3511 size_t pos = code->len;
3512 size_t len = strlen(name) + 1;
3513
3514 bc_vec_expand(code, pos + len);
3515 strcpy(code->v + pos, name);
3516 code->len = pos + len;
3517#else
3518 // Smaller code, but way slow:
3519 do {
3520 xc_parse_push(*name);
3521 } while (*name++);
3522#endif
3523}
3524
3525// Indexes < 0xfc are encoded verbatim, else first byte is
3526// 0xfc, 0xfd, 0xfe or 0xff, encoding "1..4 bytes",
3527// followed by that many bytes, lsb first.
3528// (The above describes 32-bit case).
3529#define SMALL_INDEX_LIMIT (0x100 - sizeof(size_t))
3530
3531static void xc_parse_pushIndex(size_t idx)
3532{
3533 size_t mask;
3534 unsigned amt;
3535
3536 dbg_lex("%s:%d pushing index %zd", __func__, __LINE__, idx);
3537 if (idx < SMALL_INDEX_LIMIT) {
3538 xc_parse_push(idx);
3539 return;
3540 }
3541
3542 mask = ((size_t)0xff) << (sizeof(idx) * 8 - 8);
3543 amt = sizeof(idx);
3544 for (;;) {
3545 if (idx & mask) break;
3546 mask >>= 8;
3547 amt--;
3548 }
3549 // amt is at least 1 here - "one byte of length data follows"
3550
3551 xc_parse_push((SMALL_INDEX_LIMIT - 1) + amt);
3552
3553 do {
3554 xc_parse_push((unsigned char)idx);
3555 idx >>= 8;
3556 } while (idx != 0);
3557}
3558
3559static void xc_parse_pushInst_and_Index(unsigned inst, size_t idx)
3560{
3561 xc_parse_push(inst);
3562 xc_parse_pushIndex(idx);
3563}
3564
3565#if ENABLE_BC
3566static void bc_parse_pushJUMP(size_t idx)
3567{
3568 xc_parse_pushInst_and_Index(BC_INST_JUMP, idx);
3569}
3570
3571static void bc_parse_pushJUMP_ZERO(size_t idx)
3572{
3573 xc_parse_pushInst_and_Index(BC_INST_JUMP_ZERO, idx);
3574}
3575
3576static BC_STATUS zbc_parse_pushSTR(void)
3577{
3578 BcParse *p = &G.prs;
3579 char *str = xstrdup(p->lex_strnumbuf.v);
3580
3581 xc_parse_pushInst_and_Index(XC_INST_STR, p->func->strs.len);
3582 bc_vec_push(&p->func->strs, &str);
3583
3584 RETURN_STATUS(zxc_lex_next());
3585}
3586#define zbc_parse_pushSTR(...) (zbc_parse_pushSTR(__VA_ARGS__) COMMA_SUCCESS)
3587#endif
3588
3589static void xc_parse_pushNUM(void)
3590{
3591 BcParse *p = &G.prs;
3592 char *num = xstrdup(p->lex_strnumbuf.v);
3593#if ENABLE_BC && ENABLE_DC
3594 size_t idx = bc_vec_push(IS_BC ? &p->func->consts : &G.prog.consts, &num);
3595#elif ENABLE_BC
3596 size_t idx = bc_vec_push(&p->func->consts, &num);
3597#else // DC
3598 size_t idx = bc_vec_push(&G.prog.consts, &num);
3599#endif
3600 xc_parse_pushInst_and_Index(XC_INST_NUM, idx);
3601}
3602
3603static BC_STATUS zxc_parse_text_init(const char *text)
3604{
3605 G.prs.func = xc_program_func(G.prs.fidx);
3606 G.prs.lex_inbuf = text;
3607 G.prs.lex = G.prs.lex_last = XC_LEX_INVALID;
3608 RETURN_STATUS(zxc_lex_next());
3609}
3610#define zxc_parse_text_init(...) (zxc_parse_text_init(__VA_ARGS__) COMMA_SUCCESS)
3611
3612// Called when parsing or execution detects a failure,
3613// resets execution structures.
3614static void xc_program_reset(void)
3615{
3616 BcFunc *f;
3617 BcInstPtr *ip;
3618
3619 bc_vec_npop(&G.prog.exestack, G.prog.exestack.len - 1);
3620 bc_vec_pop_all(&G.prog.results);
3621
3622 f = xc_program_func_BC_PROG_MAIN();
3623 ip = bc_vec_top(&G.prog.exestack);
3624 ip->inst_idx = f->code.len;
3625}
3626
3627// Called when parsing code detects a failure,
3628// resets parsing structures.
3629static void xc_parse_reset(void)
3630{
3631 BcParse *p = &G.prs;
3632 if (p->fidx != BC_PROG_MAIN) {
3633 bc_func_free(p->func);
3634 bc_func_init(p->func);
3635
3636 p->fidx = BC_PROG_MAIN;
3637 p->func = xc_program_func_BC_PROG_MAIN();
3638 }
3639
3640 p->lex_inbuf += strlen(p->lex_inbuf);
3641 p->lex = XC_LEX_EOF;
3642
3643 IF_BC(bc_vec_pop_all(&p->exits);)
3644 IF_BC(bc_vec_pop_all(&p->conds);)
3645 IF_BC(bc_vec_pop_all(&p->ops);)
3646
3647 xc_program_reset();
3648}
3649
3650static void xc_parse_free(void)
3651{
3652 IF_BC(bc_vec_free(&G.prs.exits);)
3653 IF_BC(bc_vec_free(&G.prs.conds);)
3654 IF_BC(bc_vec_free(&G.prs.ops);)
3655 bc_vec_free(&G.prs.lex_strnumbuf);
3656}
3657
3658static void xc_parse_create(size_t fidx)
3659{
3660 BcParse *p = &G.prs;
3661 memset(p, 0, sizeof(BcParse));
3662
3663 bc_char_vec_init(&p->lex_strnumbuf);
3664 IF_BC(bc_vec_init(&p->exits, sizeof(size_t), NULL);)
3665 IF_BC(bc_vec_init(&p->conds, sizeof(size_t), NULL);)
3666 IF_BC(bc_vec_init(&p->ops, sizeof(BcLexType), NULL);)
3667
3668 p->fidx = fidx;
3669 p->func = xc_program_func(fidx);
3670}
3671
3672static void xc_program_add_fn(void)
3673{
3674 //size_t idx;
3675 BcFunc f;
3676 bc_func_init(&f);
3677 //idx =
3678 bc_vec_push(&G.prog.fns, &f);
3679 //return idx;
3680}
3681
3682#if ENABLE_BC
3683
3684// Note: takes ownership of 'name' (must be malloced)
3685static size_t bc_program_addFunc(char *name)
3686{
3687 size_t idx;
3688 BcId entry, *entry_ptr;
3689 int inserted;
3690
3691 entry.name = name;
3692 entry.idx = G.prog.fns.len;
3693
3694 inserted = bc_map_insert(&G.prog.fn_map, &entry, &idx);
3695 if (!inserted) free(name);
3696
3697 entry_ptr = bc_vec_item(&G.prog.fn_map, idx);
3698 idx = entry_ptr->idx;
3699
3700 if (!inserted) {
3701 // There is already a function with this name.
3702 // It'll be redefined now, clear old definition.
3703 BcFunc *func = xc_program_func(entry_ptr->idx);
3704 bc_func_free(func);
3705 bc_func_init(func);
3706 } else {
3707 xc_program_add_fn();
3708 }
3709
3710 return idx;
3711}
3712
3713#define BC_PARSE_TOP_OP(p) (*(BcLexType*)bc_vec_top(&(p)->ops))
3714// We can calculate the conversion between tokens and exprs by subtracting the
3715// position of the first operator in the lex enum and adding the position of the
3716// first in the expr enum. Note: This only works for binary operators.
3717#define BC_TOKEN_2_INST(t) ((char) ((t) - XC_LEX_OP_POWER + XC_INST_POWER))
3718
3719static BC_STATUS zbc_parse_expr(uint8_t flags);
3720#define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS)
3721
3722static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed);
3723#define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS)
3724
3725static BC_STATUS zbc_parse_stmt(void)
3726{
3727 RETURN_STATUS(zbc_parse_stmt_possibly_auto(false));
3728}
3729#define zbc_parse_stmt(...) (zbc_parse_stmt(__VA_ARGS__) COMMA_SUCCESS)
3730
3731static BC_STATUS zbc_parse_stmt_allow_NLINE_before(const char *after_X)
3732{
3733 BcParse *p = &G.prs;
3734 // "if(cond)<newline>stmt" is accepted too, but not 2+ newlines.
3735 // Same for "else", "while()", "for()".
3736 BcStatus s = zbc_lex_next_and_skip_NLINE();
3737 if (s) RETURN_STATUS(s);
3738 if (p->lex == XC_LEX_NLINE)
3739 RETURN_STATUS(bc_error_fmt("no statement after '%s'", after_X));
3740
3741 RETURN_STATUS(zbc_parse_stmt());
3742}
3743#define zbc_parse_stmt_allow_NLINE_before(...) (zbc_parse_stmt_allow_NLINE_before(__VA_ARGS__) COMMA_SUCCESS)
3744
3745static void bc_parse_operator(BcLexType type, size_t start, size_t *nexprs)
3746{
3747 BcParse *p = &G.prs;
3748 char l, r = bc_operation_PREC(type - XC_LEX_1st_op);
3749 bool left = bc_operation_LEFT(type - XC_LEX_1st_op);
3750
3751 while (p->ops.len > start) {
3752 BcLexType t = BC_PARSE_TOP_OP(p);
3753 if (t == BC_LEX_LPAREN) break;
3754
3755 l = bc_operation_PREC(t - XC_LEX_1st_op);
3756 if (l >= r && (l != r || !left)) break;
3757
3758 xc_parse_push(BC_TOKEN_2_INST(t));
3759 bc_vec_pop(&p->ops);
3760 *nexprs -= (t != BC_LEX_OP_BOOL_NOT && t != XC_LEX_NEG);
3761 }
3762
3763 bc_vec_push(&p->ops, &type);
3764}
3765
3766static BC_STATUS zbc_parse_rightParen(size_t ops_bgn, size_t *nexs)
3767{
3768 BcParse *p = &G.prs;
3769 BcLexType top;
3770
3771 if (p->ops.len <= ops_bgn)
3772 RETURN_STATUS(bc_error_bad_expression());
3773 top = BC_PARSE_TOP_OP(p);
3774
3775 while (top != BC_LEX_LPAREN) {
3776 xc_parse_push(BC_TOKEN_2_INST(top));
3777
3778 bc_vec_pop(&p->ops);
3779 *nexs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG);
3780
3781 if (p->ops.len <= ops_bgn)
3782 RETURN_STATUS(bc_error_bad_expression());
3783 top = BC_PARSE_TOP_OP(p);
3784 }
3785
3786 bc_vec_pop(&p->ops);
3787
3788 RETURN_STATUS(BC_STATUS_SUCCESS);
3789}
3790#define zbc_parse_rightParen(...) (zbc_parse_rightParen(__VA_ARGS__) COMMA_SUCCESS)
3791
3792static BC_STATUS zbc_parse_params(uint8_t flags)
3793{
3794 BcParse *p = &G.prs;
3795 BcStatus s;
3796 size_t nparams;
3797
3798 dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex);
3799 flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY;
3800
3801 s = zxc_lex_next();
3802 if (s) RETURN_STATUS(s);
3803
3804 nparams = 0;
3805 if (p->lex != BC_LEX_RPAREN) {
3806 for (;;) {
3807 s = zbc_parse_expr(flags);
3808 if (s) RETURN_STATUS(s);
3809 nparams++;
3810 if (p->lex != BC_LEX_COMMA) {
3811 if (p->lex == BC_LEX_RPAREN)
3812 break;
3813 RETURN_STATUS(bc_error_bad_token());
3814 }
3815 s = zxc_lex_next();
3816 if (s) RETURN_STATUS(s);
3817 }
3818 }
3819
3820 xc_parse_pushInst_and_Index(BC_INST_CALL, nparams);
3821
3822 RETURN_STATUS(BC_STATUS_SUCCESS);
3823}
3824#define zbc_parse_params(...) (zbc_parse_params(__VA_ARGS__) COMMA_SUCCESS)
3825
3826// Note: takes ownership of 'name' (must be malloced)
3827static BC_STATUS zbc_parse_call(char *name, uint8_t flags)
3828{
3829 BcParse *p = &G.prs;
3830 BcStatus s;
3831 BcId entry, *entry_ptr;
3832 size_t idx;
3833
3834 entry.name = name;
3835
3836 s = zbc_parse_params(flags);
3837 if (s) goto err;
3838
3839 if (p->lex != BC_LEX_RPAREN) {
3840 s = bc_error_bad_token();
3841 goto err;
3842 }
3843
3844 idx = bc_map_find_exact(&G.prog.fn_map, &entry);
3845
3846 if (idx == BC_VEC_INVALID_IDX) {
3847 // No such function exists, create an empty one
3848 bc_program_addFunc(name);
3849 idx = bc_map_find_exact(&G.prog.fn_map, &entry);
3850 } else
3851 free(name);
3852
3853 entry_ptr = bc_vec_item(&G.prog.fn_map, idx);
3854 xc_parse_pushIndex(entry_ptr->idx);
3855
3856 RETURN_STATUS(zxc_lex_next());
3857 err:
3858 free(name);
3859 RETURN_STATUS(s);
3860}
3861#define zbc_parse_call(...) (zbc_parse_call(__VA_ARGS__) COMMA_SUCCESS)
3862
3863static BC_STATUS zbc_parse_name(BcInst *type, uint8_t flags)
3864{
3865 BcParse *p = &G.prs;
3866 BcStatus s;
3867 char *name;
3868
3869 name = xstrdup(p->lex_strnumbuf.v);
3870 s = zxc_lex_next();
3871 if (s) goto err;
3872
3873 if (p->lex == BC_LEX_LBRACKET) {
3874 s = zxc_lex_next();
3875 if (s) goto err;
3876
3877 if (p->lex == BC_LEX_RBRACKET) {
3878 if (!(flags & BC_PARSE_ARRAY)) {
3879 s = bc_error_bad_expression();
3880 goto err;
3881 }
3882 *type = XC_INST_ARRAY;
3883 } else {
3884 *type = XC_INST_ARRAY_ELEM;
3885 flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
3886 s = zbc_parse_expr(flags);
3887 if (s) goto err;
3888 }
3889 s = zxc_lex_next();
3890 if (s) goto err;
3891 xc_parse_push(*type);
3892 xc_parse_pushName(name);
3893 free(name);
3894 } else if (p->lex == BC_LEX_LPAREN) {
3895 if (flags & BC_PARSE_NOCALL) {
3896 s = bc_error_bad_token();
3897 goto err;
3898 }
3899 *type = BC_INST_CALL;
3900 s = zbc_parse_call(name, flags);
3901 } else {
3902 *type = XC_INST_VAR;
3903 xc_parse_push(XC_INST_VAR);
3904 xc_parse_pushName(name);
3905 free(name);
3906 }
3907
3908 RETURN_STATUS(s);
3909 err:
3910 free(name);
3911 RETURN_STATUS(s);
3912}
3913#define zbc_parse_name(...) (zbc_parse_name(__VA_ARGS__) COMMA_SUCCESS)
3914
3915static BC_STATUS zbc_parse_read(void)
3916{
3917 BcParse *p = &G.prs;
3918 BcStatus s;
3919
3920 s = zxc_lex_next();
3921 if (s) RETURN_STATUS(s);
3922 if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token());
3923
3924 s = zxc_lex_next();
3925 if (s) RETURN_STATUS(s);
3926 if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token());
3927
3928 xc_parse_push(XC_INST_READ);
3929
3930 RETURN_STATUS(s);
3931}
3932#define zbc_parse_read(...) (zbc_parse_read(__VA_ARGS__) COMMA_SUCCESS)
3933
3934static BC_STATUS zbc_parse_builtin(BcLexType type, uint8_t flags, BcInst *prev)
3935{
3936 BcParse *p = &G.prs;
3937 BcStatus s;
3938
3939 s = zxc_lex_next();
3940 if (s) RETURN_STATUS(s);
3941 if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token());
3942
3943 flags = (flags & ~(BC_PARSE_PRINT | BC_PARSE_REL)) | BC_PARSE_ARRAY;
3944
3945 s = zxc_lex_next();
3946 if (s) RETURN_STATUS(s);
3947
3948 s = zbc_parse_expr(flags);
3949 if (s) RETURN_STATUS(s);
3950
3951 if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token());
3952
3953 *prev = (type == BC_LEX_KEY_LENGTH) ? XC_INST_LENGTH : XC_INST_SQRT;
3954 xc_parse_push(*prev);
3955
3956 RETURN_STATUS(s);
3957}
3958#define zbc_parse_builtin(...) (zbc_parse_builtin(__VA_ARGS__) COMMA_SUCCESS)
3959
3960static BC_STATUS zbc_parse_scale(BcInst *type, uint8_t flags)
3961{
3962 BcParse *p = &G.prs;
3963 BcStatus s;
3964
3965 s = zxc_lex_next();
3966 if (s) RETURN_STATUS(s);
3967
3968 if (p->lex != BC_LEX_LPAREN) {
3969 *type = XC_INST_SCALE;
3970 xc_parse_push(XC_INST_SCALE);
3971 RETURN_STATUS(BC_STATUS_SUCCESS);
3972 }
3973
3974 *type = XC_INST_SCALE_FUNC;
3975 flags &= ~(BC_PARSE_PRINT | BC_PARSE_REL);
3976
3977 s = zxc_lex_next();
3978 if (s) RETURN_STATUS(s);
3979
3980 s = zbc_parse_expr(flags);
3981 if (s) RETURN_STATUS(s);
3982 if (p->lex != BC_LEX_RPAREN)
3983 RETURN_STATUS(bc_error_bad_token());
3984 xc_parse_push(XC_INST_SCALE_FUNC);
3985
3986 RETURN_STATUS(zxc_lex_next());
3987}
3988#define zbc_parse_scale(...) (zbc_parse_scale(__VA_ARGS__) COMMA_SUCCESS)
3989
3990static BC_STATUS zbc_parse_incdec(BcInst *prev, size_t *nexs, uint8_t flags)
3991{
3992 BcParse *p = &G.prs;
3993 BcStatus s;
3994 BcLexType type;
3995 char inst;
3996 BcInst etype = *prev;
3997
3998 if (etype == XC_INST_VAR || etype == XC_INST_ARRAY_ELEM
3999 || etype == XC_INST_SCALE || etype == BC_INST_LAST
4000 || etype == XC_INST_IBASE || etype == XC_INST_OBASE
4001 ) {
4002 *prev = inst = BC_INST_INC_POST + (p->lex != BC_LEX_OP_INC);
4003 xc_parse_push(inst);
4004 s = zxc_lex_next();
4005 } else {
4006 *prev = inst = BC_INST_INC_PRE + (p->lex != BC_LEX_OP_INC);
4007
4008 s = zxc_lex_next();
4009 if (s) RETURN_STATUS(s);
4010 type = p->lex;
4011
4012 // Because we parse the next part of the expression
4013 // right here, we need to increment this.
4014 *nexs = *nexs + 1;
4015
4016 switch (type) {
4017 case XC_LEX_NAME:
4018 s = zbc_parse_name(prev, flags | BC_PARSE_NOCALL);
4019 break;
4020 case BC_LEX_KEY_IBASE:
4021 case BC_LEX_KEY_LAST:
4022 case BC_LEX_KEY_OBASE:
4023 xc_parse_push(type - BC_LEX_KEY_IBASE + XC_INST_IBASE);
4024 s = zxc_lex_next();
4025 break;
4026 case BC_LEX_KEY_SCALE:
4027 s = zxc_lex_next();
4028 if (s) RETURN_STATUS(s);
4029 if (p->lex == BC_LEX_LPAREN)
4030 s = bc_error_bad_token();
4031 else
4032 xc_parse_push(XC_INST_SCALE);
4033 break;
4034 default:
4035 s = bc_error_bad_token();
4036 break;
4037 }
4038
4039 if (!s) xc_parse_push(inst);
4040 }
4041
4042 RETURN_STATUS(s);
4043}
4044#define zbc_parse_incdec(...) (zbc_parse_incdec(__VA_ARGS__) COMMA_SUCCESS)
4045
4046static int bc_parse_inst_isLeaf(BcInst p)
4047{
4048 return (p >= XC_INST_NUM && p <= XC_INST_SQRT)
4049 || p == BC_INST_INC_POST
4050 || p == BC_INST_DEC_POST
4051 ;
4052}
4053#define BC_PARSE_LEAF(prev, bin_last, rparen) \
4054 (!(bin_last) && ((rparen) || bc_parse_inst_isLeaf(prev)))
4055
4056static BC_STATUS zbc_parse_minus(BcInst *prev, size_t ops_bgn,
4057 bool rparen, bool bin_last, size_t *nexprs)
4058{
4059 BcParse *p = &G.prs;
4060 BcStatus s;
4061 BcLexType type;
4062
4063 s = zxc_lex_next();
4064 if (s) RETURN_STATUS(s);
4065
4066 type = BC_PARSE_LEAF(*prev, bin_last, rparen) ? XC_LEX_OP_MINUS : XC_LEX_NEG;
4067 *prev = BC_TOKEN_2_INST(type);
4068
4069 // We can just push onto the op stack because this is the largest
4070 // precedence operator that gets pushed. Inc/dec does not.
4071 if (type != XC_LEX_OP_MINUS)
4072 bc_vec_push(&p->ops, &type);
4073 else
4074 bc_parse_operator(type, ops_bgn, nexprs);
4075
4076 RETURN_STATUS(s);
4077}
4078#define zbc_parse_minus(...) (zbc_parse_minus(__VA_ARGS__) COMMA_SUCCESS)
4079
4080static BC_STATUS zbc_parse_print(void)
4081{
4082 BcParse *p = &G.prs;
4083 BcStatus s;
4084 BcLexType type;
4085
4086 for (;;) {
4087 s = zxc_lex_next();
4088 if (s) RETURN_STATUS(s);
4089 type = p->lex;
4090 if (type == XC_LEX_STR) {
4091 s = zbc_parse_pushSTR();
4092 } else {
4093 s = zbc_parse_expr(0);
4094 }
4095 if (s) RETURN_STATUS(s);
4096 xc_parse_push(XC_INST_PRINT_POP);
4097 if (p->lex != BC_LEX_COMMA)
4098 break;
4099 }
4100
4101 RETURN_STATUS(s);
4102}
4103#define zbc_parse_print(...) (zbc_parse_print(__VA_ARGS__) COMMA_SUCCESS)
4104
4105static BC_STATUS zbc_parse_return(void)
4106{
4107 BcParse *p = &G.prs;
4108 BcStatus s;
4109 BcLexType t;
4110
4111 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
4112 s = zxc_lex_next();
4113 if (s) RETURN_STATUS(s);
4114
4115 t = p->lex;
4116 if (t == XC_LEX_NLINE || t == BC_LEX_SCOLON || t == BC_LEX_RBRACE)
4117 xc_parse_push(BC_INST_RET0);
4118 else {
4119//TODO: if (p->func->voidfunc) ERROR
4120 s = zbc_parse_expr(0);
4121 if (s) RETURN_STATUS(s);
4122
4123 if (t != BC_LEX_LPAREN // "return EXPR", no ()
4124 || p->lex_last != BC_LEX_RPAREN // example: "return (a) + b"
4125 ) {
4126 s = zbc_POSIX_requires("parentheses around return expressions");
4127 if (s) RETURN_STATUS(s);
4128 }
4129
4130 xc_parse_push(XC_INST_RET);
4131 }
4132
4133 dbg_lex_done("%s:%d done", __func__, __LINE__);
4134 RETURN_STATUS(s);
4135}
4136#define zbc_parse_return(...) (zbc_parse_return(__VA_ARGS__) COMMA_SUCCESS)
4137
4138static void rewrite_label_to_current(size_t idx)
4139{
4140 BcParse *p = &G.prs;
4141 size_t *label = bc_vec_item(&p->func->labels, idx);
4142 *label = p->func->code.len;
4143}
4144
4145static BC_STATUS zbc_parse_if(void)
4146{
4147 BcParse *p = &G.prs;
4148 BcStatus s;
4149 size_t ip_idx;
4150
4151 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
4152 s = zxc_lex_next();
4153 if (s) RETURN_STATUS(s);
4154 if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token());
4155
4156 s = zxc_lex_next();
4157 if (s) RETURN_STATUS(s);
4158 s = zbc_parse_expr(BC_PARSE_REL);
4159 if (s) RETURN_STATUS(s);
4160 if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token());
4161
4162 // Encode "if zero, jump to ..."
4163 // Pushed value (destination of the jump) is uninitialized,
4164 // will be rewritten to be address of "end of if()" or of "else".
4165 ip_idx = bc_vec_push(&p->func->labels, &ip_idx);
4166 bc_parse_pushJUMP_ZERO(ip_idx);
4167
4168 s = zbc_parse_stmt_allow_NLINE_before(STRING_if);
4169 if (s) RETURN_STATUS(s);
4170
4171 dbg_lex("%s:%d in if after stmt: p->lex:%d", __func__, __LINE__, p->lex);
4172 if (p->lex == BC_LEX_KEY_ELSE) {
4173 size_t ip2_idx;
4174
4175 // Encode "after then_stmt, jump to end of if()"
4176 ip2_idx = bc_vec_push(&p->func->labels, &ip2_idx);
4177 dbg_lex("%s:%d after if() then_stmt: BC_INST_JUMP to %zd", __func__, __LINE__, ip2_idx);
4178 bc_parse_pushJUMP(ip2_idx);
4179
4180 dbg_lex("%s:%d rewriting 'if_zero' label to jump to 'else'-> %zd", __func__, __LINE__, p->func->code.len);
4181 rewrite_label_to_current(ip_idx);
4182
4183 ip_idx = ip2_idx;
4184
4185 s = zbc_parse_stmt_allow_NLINE_before(STRING_else);
4186 if (s) RETURN_STATUS(s);
4187 }
4188
4189 dbg_lex("%s:%d rewriting label to jump after 'if' body-> %zd", __func__, __LINE__, p->func->code.len);
4190 rewrite_label_to_current(ip_idx);
4191
4192 dbg_lex_done("%s:%d done", __func__, __LINE__);
4193 RETURN_STATUS(s);
4194}
4195#define zbc_parse_if(...) (zbc_parse_if(__VA_ARGS__) COMMA_SUCCESS)
4196
4197static BC_STATUS zbc_parse_while(void)
4198{
4199 BcParse *p = &G.prs;
4200 BcStatus s;
4201 size_t cond_idx;
4202 size_t ip_idx;
4203
4204 s = zxc_lex_next();
4205 if (s) RETURN_STATUS(s);
4206 if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token());
4207 s = zxc_lex_next();
4208 if (s) RETURN_STATUS(s);
4209
4210 cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len);
4211 ip_idx = cond_idx + 1;
4212 bc_vec_push(&p->conds, &cond_idx);
4213
4214 bc_vec_push(&p->exits, &ip_idx);
4215 bc_vec_push(&p->func->labels, &ip_idx);
4216
4217 s = zbc_parse_expr(BC_PARSE_REL);
4218 if (s) RETURN_STATUS(s);
4219 if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token());
4220
4221 bc_parse_pushJUMP_ZERO(ip_idx);
4222
4223 s = zbc_parse_stmt_allow_NLINE_before(STRING_while);
4224 if (s) RETURN_STATUS(s);
4225
4226 dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, cond_idx);
4227 bc_parse_pushJUMP(cond_idx);
4228
4229 dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len);
4230 rewrite_label_to_current(ip_idx);
4231
4232 bc_vec_pop(&p->exits);
4233 bc_vec_pop(&p->conds);
4234
4235 RETURN_STATUS(s);
4236}
4237#define zbc_parse_while(...) (zbc_parse_while(__VA_ARGS__) COMMA_SUCCESS)
4238
4239static BC_STATUS zbc_parse_for(void)
4240{
4241 BcParse *p = &G.prs;
4242 BcStatus s;
4243 size_t cond_idx, exit_idx, body_idx, update_idx;
4244
4245 dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex);
4246 s = zxc_lex_next();
4247 if (s) RETURN_STATUS(s);
4248 if (p->lex != BC_LEX_LPAREN) RETURN_STATUS(bc_error_bad_token());
4249 s = zxc_lex_next();
4250 if (s) RETURN_STATUS(s);
4251
4252 if (p->lex != BC_LEX_SCOLON) {
4253 s = zbc_parse_expr(0);
4254 xc_parse_push(XC_INST_POP);
4255 if (s) RETURN_STATUS(s);
4256 } else {
4257 s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("init");
4258 if (s) RETURN_STATUS(s);
4259 }
4260
4261 if (p->lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token());
4262 s = zxc_lex_next();
4263 if (s) RETURN_STATUS(s);
4264
4265 cond_idx = bc_vec_push(&p->func->labels, &p->func->code.len);
4266 update_idx = cond_idx + 1;
4267 body_idx = update_idx + 1;
4268 exit_idx = body_idx + 1;
4269
4270 if (p->lex != BC_LEX_SCOLON)
4271 s = zbc_parse_expr(BC_PARSE_REL);
4272 else {
4273 // Set this for the next call to xc_parse_pushNUM().
4274 // This is safe to set because the current token is a semicolon,
4275 // which has no string requirement.
4276 bc_vec_string(&p->lex_strnumbuf, 1, "1");
4277 xc_parse_pushNUM();
4278 s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("condition");
4279 }
4280 if (s) RETURN_STATUS(s);
4281
4282 if (p->lex != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token());
4283
4284 s = zxc_lex_next();
4285 if (s) RETURN_STATUS(s);
4286
4287 bc_parse_pushJUMP_ZERO(exit_idx);
4288 bc_parse_pushJUMP(body_idx);
4289
4290 bc_vec_push(&p->conds, &update_idx);
4291 bc_vec_push(&p->func->labels, &p->func->code.len);
4292
4293 if (p->lex != BC_LEX_RPAREN) {
4294 s = zbc_parse_expr(0);
4295 if (s) RETURN_STATUS(s);
4296 if (p->lex != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token());
4297 xc_parse_push(XC_INST_POP);
4298 } else {
4299 s = zbc_POSIX_does_not_allow_empty_X_expression_in_for("update");
4300 if (s) RETURN_STATUS(s);
4301 }
4302
4303 bc_parse_pushJUMP(cond_idx);
4304 bc_vec_push(&p->func->labels, &p->func->code.len);
4305
4306 bc_vec_push(&p->exits, &exit_idx);
4307 bc_vec_push(&p->func->labels, &exit_idx);
4308
4309 s = zbc_parse_stmt_allow_NLINE_before(STRING_for);
4310 if (s) RETURN_STATUS(s);
4311
4312 dbg_lex("%s:%d BC_INST_JUMP to %zd", __func__, __LINE__, update_idx);
4313 bc_parse_pushJUMP(update_idx);
4314
4315 dbg_lex("%s:%d rewriting label-> %zd", __func__, __LINE__, p->func->code.len);
4316 rewrite_label_to_current(exit_idx);
4317
4318 bc_vec_pop(&p->exits);
4319 bc_vec_pop(&p->conds);
4320
4321 RETURN_STATUS(BC_STATUS_SUCCESS);
4322}
4323#define zbc_parse_for(...) (zbc_parse_for(__VA_ARGS__) COMMA_SUCCESS)
4324
4325static BC_STATUS zbc_parse_break_or_continue(BcLexType type)
4326{
4327 BcParse *p = &G.prs;
4328 size_t i;
4329
4330 if (type == BC_LEX_KEY_BREAK) {
4331 if (p->exits.len == 0) // none of the enclosing blocks is a loop
4332 RETURN_STATUS(bc_error_bad_token());
4333 i = *(size_t*)bc_vec_top(&p->exits);
4334 } else {
4335 i = *(size_t*)bc_vec_top(&p->conds);
4336 }
4337 bc_parse_pushJUMP(i);
4338
4339 RETURN_STATUS(zxc_lex_next());
4340}
4341#define zbc_parse_break_or_continue(...) (zbc_parse_break_or_continue(__VA_ARGS__) COMMA_SUCCESS)
4342
4343static BC_STATUS zbc_func_insert(BcFunc *f, char *name, bool var)
4344{
4345 BcId *autoid;
4346 BcId a;
4347 size_t i;
4348
4349 autoid = (void*)f->autos.v;
4350 for (i = 0; i < f->autos.len; i++, autoid++) {
4351 if (strcmp(name, autoid->name) == 0
4352 && var == autoid->idx
4353 ) {
4354 RETURN_STATUS(bc_error("duplicate function parameter or auto name"));
4355 }
4356 }
4357
4358 a.idx = var;
4359 a.name = name;
4360
4361 bc_vec_push(&f->autos, &a);
4362
4363 RETURN_STATUS(BC_STATUS_SUCCESS);
4364}
4365#define zbc_func_insert(...) (zbc_func_insert(__VA_ARGS__) COMMA_SUCCESS)
4366
4367static BC_STATUS zbc_parse_funcdef(void)
4368{
4369 BcParse *p = &G.prs;
4370 BcStatus s;
4371 bool var, comma, voidfunc;
4372 char *name;
4373
4374 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
4375 s = zxc_lex_next();
4376 if (s) RETURN_STATUS(s);
4377 if (p->lex != XC_LEX_NAME)
4378 RETURN_STATUS(bc_error_bad_function_definition());
4379
4380 // To be maximally both POSIX and GNU-compatible,
4381 // "void" is not treated as a normal keyword:
4382 // you can have variable named "void", and even a function
4383 // named "void": "define void() { return 6; }" is ok.
4384 // _Only_ "define void f() ..." syntax treats "void"
4385 // specially.
4386 voidfunc = (strcmp(p->lex_strnumbuf.v, "void") == 0);
4387
4388 s = zxc_lex_next();
4389 if (s) RETURN_STATUS(s);
4390
4391 voidfunc = (voidfunc && p->lex == XC_LEX_NAME);
4392 if (voidfunc) {
4393 s = zxc_lex_next();
4394 if (s) RETURN_STATUS(s);
4395 }
4396
4397 if (p->lex != BC_LEX_LPAREN)
4398 RETURN_STATUS(bc_error_bad_function_definition());
4399
4400 p->fidx = bc_program_addFunc(xstrdup(p->lex_strnumbuf.v));
4401 p->func = xc_program_func(p->fidx);
4402 p->func->voidfunc = voidfunc;
4403
4404 s = zxc_lex_next();
4405 if (s) RETURN_STATUS(s);
4406
4407 comma = false;
4408 while (p->lex != BC_LEX_RPAREN) {
4409 if (p->lex != XC_LEX_NAME)
4410 RETURN_STATUS(bc_error_bad_function_definition());
4411
4412 ++p->func->nparams;
4413
4414 name = xstrdup(p->lex_strnumbuf.v);
4415 s = zxc_lex_next();
4416 if (s) goto err;
4417
4418 var = p->lex != BC_LEX_LBRACKET;
4419
4420 if (!var) {
4421 s = zxc_lex_next();
4422 if (s) goto err;
4423
4424 if (p->lex != BC_LEX_RBRACKET) {
4425 s = bc_error_bad_function_definition();
4426 goto err;
4427 }
4428
4429 s = zxc_lex_next();
4430 if (s) goto err;
4431 }
4432
4433 comma = p->lex == BC_LEX_COMMA;
4434 if (comma) {
4435 s = zxc_lex_next();
4436 if (s) goto err;
4437 }
4438
4439 s = zbc_func_insert(p->func, name, var);
4440 if (s) goto err;
4441 }
4442
4443 if (comma) RETURN_STATUS(bc_error_bad_function_definition());
4444
4445 s = zxc_lex_next();
4446 if (s) RETURN_STATUS(s);
4447
4448 if (p->lex != BC_LEX_LBRACE) {
4449 s = zbc_POSIX_requires("the left brace be on the same line as the function header");
4450 if (s) RETURN_STATUS(s);
4451 }
4452
4453 // Prevent "define z()<newline>" from being interpreted as function with empty stmt as body
4454 s = zbc_lex_skip_if_at_NLINE();
4455 if (s) RETURN_STATUS(s);
4456 // GNU bc requires a {} block even if function body has single stmt, enforce this
4457 if (p->lex != BC_LEX_LBRACE)
4458 RETURN_STATUS(bc_error("function { body } expected"));
4459
4460 p->in_funcdef++; // to determine whether "return" stmt is allowed, and such
4461 s = zbc_parse_stmt_possibly_auto(true);
4462 p->in_funcdef--;
4463 if (s) RETURN_STATUS(s);
4464
4465 xc_parse_push(BC_INST_RET0);
4466
4467 // Subsequent code generation is into main program
4468 p->fidx = BC_PROG_MAIN;
4469 p->func = xc_program_func_BC_PROG_MAIN();
4470
4471 dbg_lex_done("%s:%d done", __func__, __LINE__);
4472 RETURN_STATUS(s);
4473 err:
4474 dbg_lex_done("%s:%d done (error)", __func__, __LINE__);
4475 free(name);
4476 RETURN_STATUS(s);
4477}
4478#define zbc_parse_funcdef(...) (zbc_parse_funcdef(__VA_ARGS__) COMMA_SUCCESS)
4479
4480static BC_STATUS zbc_parse_auto(void)
4481{
4482 BcParse *p = &G.prs;
4483 BcStatus s;
4484 char *name;
4485
4486 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
4487 s = zxc_lex_next();
4488 if (s) RETURN_STATUS(s);
4489
4490 for (;;) {
4491 bool var;
4492
4493 if (p->lex != XC_LEX_NAME)
4494 RETURN_STATUS(bc_error_at("bad 'auto' syntax"));
4495
4496 name = xstrdup(p->lex_strnumbuf.v);
4497 s = zxc_lex_next();
4498 if (s) goto err;
4499
4500 var = (p->lex != BC_LEX_LBRACKET);
4501 if (!var) {
4502 s = zxc_lex_next();
4503 if (s) goto err;
4504
4505 if (p->lex != BC_LEX_RBRACKET) {
4506 s = bc_error_at("bad 'auto' syntax");
4507 goto err;
4508 }
4509 s = zxc_lex_next();
4510 if (s) goto err;
4511 }
4512
4513 s = zbc_func_insert(p->func, name, var);
4514 if (s) goto err;
4515
4516 if (p->lex == XC_LEX_NLINE
4517 || p->lex == BC_LEX_SCOLON
4518 //|| p->lex == BC_LEX_RBRACE // allow "define f() {auto a}"
4519 ) {
4520 break;
4521 }
4522 if (p->lex != BC_LEX_COMMA)
4523 RETURN_STATUS(bc_error_at("bad 'auto' syntax"));
4524 s = zxc_lex_next(); // skip comma
4525 if (s) RETURN_STATUS(s);
4526 }
4527
4528 dbg_lex_done("%s:%d done", __func__, __LINE__);
4529 RETURN_STATUS(BC_STATUS_SUCCESS);
4530 err:
4531 free(name);
4532 dbg_lex_done("%s:%d done (ERROR)", __func__, __LINE__);
4533 RETURN_STATUS(s);
4534}
4535#define zbc_parse_auto(...) (zbc_parse_auto(__VA_ARGS__) COMMA_SUCCESS)
4536
4537#undef zbc_parse_stmt_possibly_auto
4538static BC_STATUS zbc_parse_stmt_possibly_auto(bool auto_allowed)
4539{
4540 BcParse *p = &G.prs;
4541 BcStatus s = BC_STATUS_SUCCESS;
4542
4543 dbg_lex_enter("%s:%d entered, p->lex:%d", __func__, __LINE__, p->lex);
4544
4545 if (p->lex == XC_LEX_NLINE) {
4546 dbg_lex_done("%s:%d done (seen XC_LEX_NLINE)", __func__, __LINE__);
4547 RETURN_STATUS(s);
4548 }
4549 if (p->lex == BC_LEX_SCOLON) {
4550 dbg_lex_done("%s:%d done (seen BC_LEX_SCOLON)", __func__, __LINE__);
4551 RETURN_STATUS(s);
4552 }
4553
4554 if (p->lex == BC_LEX_LBRACE) {
4555 dbg_lex("%s:%d BC_LEX_LBRACE: (auto_allowed:%d)", __func__, __LINE__, auto_allowed);
4556 do {
4557 s = zxc_lex_next();
4558 if (s) RETURN_STATUS(s);
4559 } while (p->lex == XC_LEX_NLINE);
4560 if (auto_allowed && p->lex == BC_LEX_KEY_AUTO) {
4561 dbg_lex("%s:%d calling zbc_parse_auto()", __func__, __LINE__);
4562 s = zbc_parse_auto();
4563 if (s) RETURN_STATUS(s);
4564 }
4565 while (p->lex != BC_LEX_RBRACE) {
4566 dbg_lex("%s:%d block parsing loop", __func__, __LINE__);
4567 s = zbc_parse_stmt();
4568 if (s) RETURN_STATUS(s);
4569 // Check that next token is a correct stmt delimiter -
4570 // disallows "print 1 print 2" and such.
4571 if (p->lex == BC_LEX_RBRACE)
4572 break;
4573 if (p->lex != BC_LEX_SCOLON
4574 && p->lex != XC_LEX_NLINE
4575 ) {
4576 RETURN_STATUS(bc_error_at("bad statement terminator"));
4577 }
4578 s = zxc_lex_next();
4579 if (s) RETURN_STATUS(s);
4580 }
4581 s = zxc_lex_next();
4582 dbg_lex_done("%s:%d done (seen BC_LEX_RBRACE)", __func__, __LINE__);
4583 RETURN_STATUS(s);
4584 }
4585
4586 dbg_lex("%s:%d p->lex:%d", __func__, __LINE__, p->lex);
4587 switch (p->lex) {
4588 case XC_LEX_OP_MINUS:
4589 case BC_LEX_OP_INC:
4590 case BC_LEX_OP_DEC:
4591 case BC_LEX_OP_BOOL_NOT:
4592 case BC_LEX_LPAREN:
4593 case XC_LEX_NAME:
4594 case XC_LEX_NUMBER:
4595 case BC_LEX_KEY_IBASE:
4596 case BC_LEX_KEY_LAST:
4597 case BC_LEX_KEY_LENGTH:
4598 case BC_LEX_KEY_OBASE:
4599 case BC_LEX_KEY_READ:
4600 case BC_LEX_KEY_SCALE:
4601 case BC_LEX_KEY_SQRT:
4602 s = zbc_parse_expr(BC_PARSE_PRINT);
4603 break;
4604 case XC_LEX_STR:
4605 s = zbc_parse_pushSTR();
4606 xc_parse_push(XC_INST_PRINT_STR);
4607 break;
4608 case BC_LEX_KEY_BREAK:
4609 case BC_LEX_KEY_CONTINUE:
4610 s = zbc_parse_break_or_continue(p->lex);
4611 break;
4612 case BC_LEX_KEY_FOR:
4613 s = zbc_parse_for();
4614 break;
4615 case BC_LEX_KEY_HALT:
4616 xc_parse_push(BC_INST_HALT);
4617 s = zxc_lex_next();
4618 break;
4619 case BC_LEX_KEY_IF:
4620 s = zbc_parse_if();
4621 break;
4622 case BC_LEX_KEY_LIMITS:
4623 // "limits" is a compile-time command,
4624 // the output is produced at _parse time_.
4625 printf(
4626 "BC_BASE_MAX = "BC_MAX_OBASE_STR "\n"
4627 "BC_DIM_MAX = "BC_MAX_DIM_STR "\n"
4628 "BC_SCALE_MAX = "BC_MAX_SCALE_STR "\n"
4629 "BC_STRING_MAX = "BC_MAX_STRING_STR"\n"
4630 // "BC_NUM_MAX = "BC_MAX_NUM_STR "\n" - GNU bc does not show this
4631 "MAX Exponent = "BC_MAX_EXP_STR "\n"
4632 "Number of vars = "BC_MAX_VARS_STR "\n"
4633 );
4634 s = zxc_lex_next();
4635 break;
4636 case BC_LEX_KEY_PRINT:
4637 s = zbc_parse_print();
4638 break;
4639 case BC_LEX_KEY_QUIT:
4640 // "quit" is a compile-time command. For example,
4641 // "if (0 == 1) quit" terminates when parsing the statement,
4642 // not when it is executed
4643 QUIT_OR_RETURN_TO_MAIN;
4644 case BC_LEX_KEY_RETURN:
4645 if (!p->in_funcdef)
4646 RETURN_STATUS(bc_error("'return' not in a function"));
4647 s = zbc_parse_return();
4648 break;
4649 case BC_LEX_KEY_WHILE:
4650 s = zbc_parse_while();
4651 break;
4652 default:
4653 s = bc_error_bad_token();
4654 break;
4655 }
4656
4657 dbg_lex_done("%s:%d done", __func__, __LINE__);
4658 RETURN_STATUS(s);
4659}
4660#define zbc_parse_stmt_possibly_auto(...) (zbc_parse_stmt_possibly_auto(__VA_ARGS__) COMMA_SUCCESS)
4661
4662static BC_STATUS zbc_parse_stmt_or_funcdef(void)
4663{
4664 BcParse *p = &G.prs;
4665 BcStatus s;
4666
4667 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
4668//why?
4669// if (p->lex == XC_LEX_EOF)
4670// s = bc_error("end of file");
4671// else
4672 if (p->lex == BC_LEX_KEY_DEFINE) {
4673 dbg_lex("%s:%d p->lex:BC_LEX_KEY_DEFINE", __func__, __LINE__);
4674 s = zbc_parse_funcdef();
4675 } else {
4676 dbg_lex("%s:%d p->lex:%d (not BC_LEX_KEY_DEFINE)", __func__, __LINE__, p->lex);
4677 s = zbc_parse_stmt();
4678 }
4679
4680 dbg_lex_done("%s:%d done", __func__, __LINE__);
4681 RETURN_STATUS(s);
4682}
4683#define zbc_parse_stmt_or_funcdef(...) (zbc_parse_stmt_or_funcdef(__VA_ARGS__) COMMA_SUCCESS)
4684
4685#undef zbc_parse_expr
4686static BC_STATUS zbc_parse_expr(uint8_t flags)
4687{
4688 BcParse *p = &G.prs;
4689 BcInst prev = XC_INST_PRINT;
4690 size_t nexprs = 0, ops_bgn = p->ops.len;
4691 unsigned nparens, nrelops;
4692 bool paren_first, rprn, assign, bin_last, incdec;
4693
4694 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
4695 paren_first = (p->lex == BC_LEX_LPAREN);
4696 nparens = nrelops = 0;
4697 rprn = assign = incdec = false;
4698 bin_last = true;
4699
4700 for (;;) {
4701 bool get_token;
4702 BcStatus s;
4703 BcLexType t = p->lex;
4704
4705 if (!lex_allowed_in_bc_expr(t))
4706 break;
4707
4708 dbg_lex("%s:%d t:%d", __func__, __LINE__, t);
4709 get_token = false;
4710 s = BC_STATUS_SUCCESS;
4711 switch (t) {
4712 case BC_LEX_OP_INC:
4713 case BC_LEX_OP_DEC:
4714 dbg_lex("%s:%d LEX_OP_INC/DEC", __func__, __LINE__);
4715 if (incdec) RETURN_STATUS(bc_error_bad_assignment());
4716 s = zbc_parse_incdec(&prev, &nexprs, flags);
4717 incdec = true;
4718 rprn = bin_last = false;
4719 //get_token = false; - already is
4720 break;
4721 case XC_LEX_OP_MINUS:
4722 dbg_lex("%s:%d LEX_OP_MINUS", __func__, __LINE__);
4723 s = zbc_parse_minus(&prev, ops_bgn, rprn, bin_last, &nexprs);
4724 rprn = false;
4725 //get_token = false; - already is
4726 bin_last = (prev == XC_INST_MINUS);
4727 if (bin_last) incdec = false;
4728 break;
4729 case BC_LEX_OP_ASSIGN_POWER:
4730 case BC_LEX_OP_ASSIGN_MULTIPLY:
4731 case BC_LEX_OP_ASSIGN_DIVIDE:
4732 case BC_LEX_OP_ASSIGN_MODULUS:
4733 case BC_LEX_OP_ASSIGN_PLUS:
4734 case BC_LEX_OP_ASSIGN_MINUS:
4735 case BC_LEX_OP_ASSIGN:
4736 dbg_lex("%s:%d LEX_ASSIGNxyz", __func__, __LINE__);
4737 if (prev != XC_INST_VAR && prev != XC_INST_ARRAY_ELEM
4738 && prev != XC_INST_SCALE && prev != XC_INST_IBASE
4739 && prev != XC_INST_OBASE && prev != BC_INST_LAST
4740 ) {
4741 RETURN_STATUS(bc_error_bad_assignment());
4742 }
4743 // Fallthrough.
4744 case XC_LEX_OP_POWER:
4745 case XC_LEX_OP_MULTIPLY:
4746 case XC_LEX_OP_DIVIDE:
4747 case XC_LEX_OP_MODULUS:
4748 case XC_LEX_OP_PLUS:
4749 case XC_LEX_OP_REL_EQ:
4750 case XC_LEX_OP_REL_LE:
4751 case XC_LEX_OP_REL_GE:
4752 case XC_LEX_OP_REL_NE:
4753 case XC_LEX_OP_REL_LT:
4754 case XC_LEX_OP_REL_GT:
4755 case BC_LEX_OP_BOOL_NOT:
4756 case BC_LEX_OP_BOOL_OR:
4757 case BC_LEX_OP_BOOL_AND:
4758 dbg_lex("%s:%d LEX_OP_xyz", __func__, __LINE__);
4759 if (t == BC_LEX_OP_BOOL_NOT) {
4760 if (!bin_last && p->lex_last != BC_LEX_OP_BOOL_NOT)
4761 RETURN_STATUS(bc_error_bad_expression());
4762 } else if (prev == XC_INST_BOOL_NOT) {
4763 RETURN_STATUS(bc_error_bad_expression());
4764 }
4765
4766 nrelops += (t >= XC_LEX_OP_REL_EQ && t <= XC_LEX_OP_REL_GT);
4767 prev = BC_TOKEN_2_INST(t);
4768 bc_parse_operator(t, ops_bgn, &nexprs);
4769 rprn = incdec = false;
4770 get_token = true;
4771 bin_last = (t != BC_LEX_OP_BOOL_NOT);
4772 break;
4773 case BC_LEX_LPAREN:
4774 dbg_lex("%s:%d LEX_LPAREN", __func__, __LINE__);
4775 if (BC_PARSE_LEAF(prev, bin_last, rprn))
4776 RETURN_STATUS(bc_error_bad_expression());
4777 bc_vec_push(&p->ops, &t);
4778 nparens++;
4779 get_token = true;
4780 rprn = incdec = false;
4781 break;
4782 case BC_LEX_RPAREN:
4783 dbg_lex("%s:%d LEX_RPAREN", __func__, __LINE__);
4784//why?
4785// if (p->lex_last == BC_LEX_LPAREN) {
4786// RETURN_STATUS(bc_error_at("empty expression"));
4787// }
4788 if (bin_last || prev == XC_INST_BOOL_NOT)
4789 RETURN_STATUS(bc_error_bad_expression());
4790 if (nparens == 0) {
4791 goto exit_loop;
4792 }
4793 s = zbc_parse_rightParen(ops_bgn, &nexprs);
4794 nparens--;
4795 get_token = true;
4796 rprn = true;
4797 bin_last = incdec = false;
4798 break;
4799 case XC_LEX_NAME:
4800 dbg_lex("%s:%d LEX_NAME", __func__, __LINE__);
4801 if (BC_PARSE_LEAF(prev, bin_last, rprn))
4802 RETURN_STATUS(bc_error_bad_expression());
4803 s = zbc_parse_name(&prev, flags & ~BC_PARSE_NOCALL);
4804 rprn = (prev == BC_INST_CALL);
4805 bin_last = false;
4806 //get_token = false; - already is
4807 nexprs++;
4808 break;
4809 case XC_LEX_NUMBER:
4810 dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__);
4811 if (BC_PARSE_LEAF(prev, bin_last, rprn))
4812 RETURN_STATUS(bc_error_bad_expression());
4813 xc_parse_pushNUM();
4814 prev = XC_INST_NUM;
4815 get_token = true;
4816 rprn = bin_last = false;
4817 nexprs++;
4818 break;
4819 case BC_LEX_KEY_IBASE:
4820 case BC_LEX_KEY_LAST:
4821 case BC_LEX_KEY_OBASE:
4822 dbg_lex("%s:%d LEX_IBASE/LAST/OBASE", __func__, __LINE__);
4823 if (BC_PARSE_LEAF(prev, bin_last, rprn))
4824 RETURN_STATUS(bc_error_bad_expression());
4825 prev = (char) (t - BC_LEX_KEY_IBASE + XC_INST_IBASE);
4826 xc_parse_push((char) prev);
4827 get_token = true;
4828 rprn = bin_last = false;
4829 nexprs++;
4830 break;
4831 case BC_LEX_KEY_LENGTH:
4832 case BC_LEX_KEY_SQRT:
4833 dbg_lex("%s:%d LEX_LEN/SQRT", __func__, __LINE__);
4834 if (BC_PARSE_LEAF(prev, bin_last, rprn))
4835 RETURN_STATUS(bc_error_bad_expression());
4836 s = zbc_parse_builtin(t, flags, &prev);
4837 get_token = true;
4838 rprn = bin_last = incdec = false;
4839 nexprs++;
4840 break;
4841 case BC_LEX_KEY_READ:
4842 dbg_lex("%s:%d LEX_READ", __func__, __LINE__);
4843 if (BC_PARSE_LEAF(prev, bin_last, rprn))
4844 RETURN_STATUS(bc_error_bad_expression());
4845 s = zbc_parse_read();
4846 prev = XC_INST_READ;
4847 get_token = true;
4848 rprn = bin_last = incdec = false;
4849 nexprs++;
4850 break;
4851 case BC_LEX_KEY_SCALE:
4852 dbg_lex("%s:%d LEX_SCALE", __func__, __LINE__);
4853 if (BC_PARSE_LEAF(prev, bin_last, rprn))
4854 RETURN_STATUS(bc_error_bad_expression());
4855 s = zbc_parse_scale(&prev, flags);
4856 //get_token = false; - already is
4857 rprn = bin_last = false;
4858 nexprs++;
4859 break;
4860 default:
4861 RETURN_STATUS(bc_error_bad_token());
4862 }
4863
4864 if (s || G_interrupt) // error, or ^C: stop parsing
4865 RETURN_STATUS(BC_STATUS_FAILURE);
4866 if (get_token) {
4867 s = zxc_lex_next();
4868 if (s) RETURN_STATUS(s);
4869 }
4870 }
4871 exit_loop:
4872
4873 while (p->ops.len > ops_bgn) {
4874 BcLexType top = BC_PARSE_TOP_OP(p);
4875 assign = (top >= BC_LEX_OP_ASSIGN_POWER && top <= BC_LEX_OP_ASSIGN);
4876
4877 if (top == BC_LEX_LPAREN || top == BC_LEX_RPAREN)
4878 RETURN_STATUS(bc_error_bad_expression());
4879
4880 xc_parse_push(BC_TOKEN_2_INST(top));
4881
4882 nexprs -= (top != BC_LEX_OP_BOOL_NOT && top != XC_LEX_NEG);
4883 bc_vec_pop(&p->ops);
4884 }
4885
4886 if (prev == XC_INST_BOOL_NOT || nexprs != 1)
4887 RETURN_STATUS(bc_error_bad_expression());
4888
4889 if (!(flags & BC_PARSE_REL) && nrelops) {
4890 BcStatus s;
4891 s = zbc_POSIX_does_not_allow("comparison operators outside if or loops");
4892 if (s) RETURN_STATUS(s);
4893 } else if ((flags & BC_PARSE_REL) && nrelops > 1) {
4894 BcStatus s;
4895 s = zbc_POSIX_requires("exactly one comparison operator per condition");
4896 if (s) RETURN_STATUS(s);
4897 }
4898
4899 if (flags & BC_PARSE_PRINT) {
4900 if (paren_first || !assign)
4901 xc_parse_push(XC_INST_PRINT);
4902 xc_parse_push(XC_INST_POP);
4903 }
4904
4905 dbg_lex_done("%s:%d done", __func__, __LINE__);
4906 RETURN_STATUS(BC_STATUS_SUCCESS);
4907}
4908#define zbc_parse_expr(...) (zbc_parse_expr(__VA_ARGS__) COMMA_SUCCESS)
4909
4910#endif // ENABLE_BC
4911
4912#if ENABLE_DC
4913
4914static BC_STATUS zdc_parse_register(void)
4915{
4916 BcParse *p = &G.prs;
4917 BcStatus s;
4918
4919 s = zxc_lex_next();
4920 if (s) RETURN_STATUS(s);
4921 if (p->lex != XC_LEX_NAME) RETURN_STATUS(bc_error_bad_token());
4922
4923 xc_parse_pushName(p->lex_strnumbuf.v);
4924
4925 RETURN_STATUS(s);
4926}
4927#define zdc_parse_register(...) (zdc_parse_register(__VA_ARGS__) COMMA_SUCCESS)
4928
4929static void dc_parse_string(void)
4930{
4931 BcParse *p = &G.prs;
4932 char *str;
4933 size_t len = G.prog.strs.len;
4934
4935 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
4936
4937 str = xstrdup(p->lex_strnumbuf.v);
4938 xc_parse_pushInst_and_Index(XC_INST_STR, len);
4939 bc_vec_push(&G.prog.strs, &str);
4940
4941 // Explanation needed here
4942 xc_program_add_fn();
4943 p->func = xc_program_func(p->fidx);
4944
4945 dbg_lex_done("%s:%d done", __func__, __LINE__);
4946}
4947
4948static BC_STATUS zdc_parse_mem(uint8_t inst, bool name, bool store)
4949{
4950 BcStatus s;
4951
4952 xc_parse_push(inst);
4953 if (name) {
4954 s = zdc_parse_register();
4955 if (s) RETURN_STATUS(s);
4956 }
4957
4958 if (store) {
4959 xc_parse_push(DC_INST_SWAP);
4960 xc_parse_push(XC_INST_ASSIGN);
4961 xc_parse_push(XC_INST_POP);
4962 }
4963
4964 RETURN_STATUS(BC_STATUS_SUCCESS);
4965}
4966#define zdc_parse_mem(...) (zdc_parse_mem(__VA_ARGS__) COMMA_SUCCESS)
4967
4968static BC_STATUS zdc_parse_cond(uint8_t inst)
4969{
4970 BcParse *p = &G.prs;
4971 BcStatus s;
4972
4973 xc_parse_push(inst);
4974 xc_parse_push(DC_INST_EXEC_COND);
4975
4976 s = zdc_parse_register();
4977 if (s) RETURN_STATUS(s);
4978
4979 s = zxc_lex_next();
4980 if (s) RETURN_STATUS(s);
4981
4982 // Note that 'else' part can not be on the next line:
4983 // echo -e '[1p]sa [2p]sb 2 1>a eb' | dc - OK, prints "2"
4984 // echo -e '[1p]sa [2p]sb 2 1>a\neb' | dc - parse error
4985 if (p->lex == DC_LEX_ELSE) {
4986 s = zdc_parse_register();
4987 if (s) RETURN_STATUS(s);
4988 s = zxc_lex_next();
4989 } else {
4990 xc_parse_push('\0');
4991 }
4992
4993 RETURN_STATUS(s);
4994}
4995#define zdc_parse_cond(...) (zdc_parse_cond(__VA_ARGS__) COMMA_SUCCESS)
4996
4997static BC_STATUS zdc_parse_token(BcLexType t)
4998{
4999 BcStatus s;
5000 uint8_t inst;
5001 bool assign, get_token;
5002
5003 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
5004 s = BC_STATUS_SUCCESS;
5005 get_token = true;
5006 switch (t) {
5007 case XC_LEX_OP_REL_EQ:
5008 case XC_LEX_OP_REL_LE:
5009 case XC_LEX_OP_REL_GE:
5010 case XC_LEX_OP_REL_NE:
5011 case XC_LEX_OP_REL_LT:
5012 case XC_LEX_OP_REL_GT:
5013 dbg_lex("%s:%d LEX_OP_REL_xyz", __func__, __LINE__);
5014 s = zdc_parse_cond(t - XC_LEX_OP_REL_EQ + XC_INST_REL_EQ);
5015 get_token = false;
5016 break;
5017 case DC_LEX_SCOLON:
5018 case DC_LEX_COLON:
5019 dbg_lex("%s:%d LEX_[S]COLON", __func__, __LINE__);
5020 s = zdc_parse_mem(XC_INST_ARRAY_ELEM, true, t == DC_LEX_COLON);
5021 break;
5022 case XC_LEX_STR:
5023 dbg_lex("%s:%d LEX_STR", __func__, __LINE__);
5024 dc_parse_string();
5025 break;
5026 case XC_LEX_NEG:
5027 dbg_lex("%s:%d LEX_NEG", __func__, __LINE__);
5028 s = zxc_lex_next();
5029 if (s) RETURN_STATUS(s);
5030 if (G.prs.lex != XC_LEX_NUMBER)
5031 RETURN_STATUS(bc_error_bad_token());
5032 xc_parse_pushNUM();
5033 xc_parse_push(XC_INST_NEG);
5034 break;
5035 case XC_LEX_NUMBER:
5036 dbg_lex("%s:%d LEX_NUMBER", __func__, __LINE__);
5037 xc_parse_pushNUM();
5038 break;
5039 case DC_LEX_READ:
5040 dbg_lex("%s:%d LEX_KEY_READ", __func__, __LINE__);
5041 xc_parse_push(XC_INST_READ);
5042 break;
5043 case DC_LEX_OP_ASSIGN:
5044 case DC_LEX_STORE_PUSH:
5045 dbg_lex("%s:%d LEX_OP_ASSIGN/STORE_PUSH", __func__, __LINE__);
5046 assign = (t == DC_LEX_OP_ASSIGN);
5047 inst = assign ? XC_INST_VAR : DC_INST_PUSH_TO_VAR;
5048 s = zdc_parse_mem(inst, true, assign);
5049 break;
5050 case DC_LEX_LOAD:
5051 case DC_LEX_LOAD_POP:
5052 dbg_lex("%s:%d LEX_OP_LOAD[_POP]", __func__, __LINE__);
5053 inst = t == DC_LEX_LOAD_POP ? DC_INST_PUSH_VAR : DC_INST_LOAD;
5054 s = zdc_parse_mem(inst, true, false);
5055 break;
5056 case DC_LEX_STORE_IBASE:
5057 case DC_LEX_STORE_SCALE:
5058 case DC_LEX_STORE_OBASE:
5059 dbg_lex("%s:%d LEX_OP_STORE_I/OBASE/SCALE", __func__, __LINE__);
5060 inst = t - DC_LEX_STORE_IBASE + XC_INST_IBASE;
5061 s = zdc_parse_mem(inst, false, true);
5062 break;
5063 default:
5064 dbg_lex_done("%s:%d done (bad token)", __func__, __LINE__);
5065 RETURN_STATUS(bc_error_bad_token());
5066 }
5067
5068 if (!s && get_token) s = zxc_lex_next();
5069
5070 dbg_lex_done("%s:%d done", __func__, __LINE__);
5071 RETURN_STATUS(s);
5072}
5073#define zdc_parse_token(...) (zdc_parse_token(__VA_ARGS__) COMMA_SUCCESS)
5074
5075static BC_STATUS zdc_parse_expr(void)
5076{
5077 BcParse *p = &G.prs;
5078 int i;
5079
5080 if (p->lex == XC_LEX_NLINE)
5081 RETURN_STATUS(zxc_lex_next());
5082
5083 i = (int)p->lex - (int)XC_LEX_OP_POWER;
5084 if (i >= 0) {
5085 BcInst inst = dc_LEX_to_INST[i];
5086 if (inst != DC_INST_INVALID) {
5087 xc_parse_push(inst);
5088 RETURN_STATUS(zxc_lex_next());
5089 }
5090 }
5091 RETURN_STATUS(zdc_parse_token(p->lex));
5092}
5093#define zdc_parse_expr(...) (zdc_parse_expr(__VA_ARGS__) COMMA_SUCCESS)
5094
5095static BC_STATUS zdc_parse_exprs_until_eof(void)
5096{
5097 BcParse *p = &G.prs;
5098 dbg_lex_enter("%s:%d entered, p->lex:%d", __func__, __LINE__, p->lex);
5099 while (p->lex != XC_LEX_EOF) {
5100 BcStatus s = zdc_parse_expr();
5101 if (s) RETURN_STATUS(s);
5102 }
5103
5104 dbg_lex_done("%s:%d done", __func__, __LINE__);
5105 RETURN_STATUS(BC_STATUS_SUCCESS);
5106}
5107#define zdc_parse_exprs_until_eof(...) (zdc_parse_exprs_until_eof(__VA_ARGS__) COMMA_SUCCESS)
5108
5109#endif // ENABLE_DC
5110
5111//
5112// Execution engine
5113//
5114
5115#define BC_PROG_STR(n) (!(n)->num && !(n)->cap)
5116#define BC_PROG_NUM(r, n) \
5117 ((r)->t != XC_RESULT_ARRAY && (r)->t != XC_RESULT_STR && !BC_PROG_STR(n))
5118
5119#define STACK_HAS_MORE_THAN(s, n) ((s)->len > ((size_t)(n)))
5120#define STACK_HAS_EQUAL_OR_MORE_THAN(s, n) ((s)->len >= ((size_t)(n)))
5121
5122static BcVec* xc_program_search(char *id, bool var)
5123{
5124 BcId e, *ptr;
5125 BcVec *v, *map;
5126 size_t i;
5127 int new;
5128
5129 v = var ? &G.prog.vars : &G.prog.arrs;
5130 map = var ? &G.prog.var_map : &G.prog.arr_map;
5131
5132 e.name = id;
5133 e.idx = v->len;
5134 new = bc_map_insert(map, &e, &i); // 1 if insertion was successful
5135
5136 if (new) {
5137 BcVec v2;
5138 bc_array_init(&v2, var);
5139 bc_vec_push(v, &v2);
5140 }
5141
5142 ptr = bc_vec_item(map, i);
5143 if (new) ptr->name = xstrdup(e.name);
5144 return bc_vec_item(v, ptr->idx);
5145}
5146
5147// 'num' need not be initialized on entry
5148static BC_STATUS zxc_program_num(BcResult *r, BcNum **num)
5149{
5150 switch (r->t) {
5151 case XC_RESULT_STR:
5152 case XC_RESULT_TEMP:
5153 IF_BC(case BC_RESULT_VOID:)
5154 case XC_RESULT_IBASE:
5155 case XC_RESULT_SCALE:
5156 case XC_RESULT_OBASE:
5157 *num = &r->d.n;
5158 break;
5159 case XC_RESULT_CONSTANT: {
5160 BcStatus s;
5161 char *str;
5162 size_t len;
5163
5164 str = *xc_program_const(r->d.id.idx);
5165 len = strlen(str);
5166
5167 bc_num_init(&r->d.n, len);
5168
5169 s = zxc_num_parse(&r->d.n, str, G.prog.ib_t);
5170 if (s) {
5171 bc_num_free(&r->d.n);
5172 RETURN_STATUS(s);
5173 }
5174 *num = &r->d.n;
5175 r->t = XC_RESULT_TEMP;
5176 break;
5177 }
5178 case XC_RESULT_VAR:
5179 case XC_RESULT_ARRAY:
5180 case XC_RESULT_ARRAY_ELEM: {
5181 BcVec *v;
5182 void *p;
5183 v = xc_program_search(r->d.id.name, r->t == XC_RESULT_VAR);
5184// dc variables are all stacks, so here we have this:
5185 p = bc_vec_top(v);
5186// TODO: eliminate these stacks for bc-only config?
5187 if (r->t == XC_RESULT_ARRAY_ELEM) {
5188 v = p;
5189 if (v->len <= r->d.id.idx)
5190 bc_array_expand(v, r->d.id.idx + 1);
5191 *num = bc_vec_item(v, r->d.id.idx);
5192 } else {
5193 *num = p;
5194 }
5195 break;
5196 }
5197#if ENABLE_BC
5198 case BC_RESULT_LAST:
5199 *num = &G.prog.last;
5200 break;
5201 case BC_RESULT_ONE:
5202 *num = &G.prog.one;
5203 break;
5204#endif
5205#if SANITY_CHECKS
5206 default:
5207 // Testing the theory that dc does not reach LAST/ONE
5208 bb_error_msg_and_die("BUG:%d", r->t);
5209#endif
5210 }
5211
5212 RETURN_STATUS(BC_STATUS_SUCCESS);
5213}
5214#define zxc_program_num(...) (zxc_program_num(__VA_ARGS__) COMMA_SUCCESS)
5215
5216static BC_STATUS zxc_program_binOpPrep(BcResult **l, BcNum **ln,
5217 BcResult **r, BcNum **rn, bool assign)
5218{
5219 BcStatus s;
5220 BcResultType lt, rt;
5221
5222 if (!STACK_HAS_MORE_THAN(&G.prog.results, 1))
5223 RETURN_STATUS(bc_error_stack_has_too_few_elements());
5224
5225 *r = bc_vec_item_rev(&G.prog.results, 0);
5226 *l = bc_vec_item_rev(&G.prog.results, 1);
5227
5228 s = zxc_program_num(*l, ln);
5229 if (s) RETURN_STATUS(s);
5230 s = zxc_program_num(*r, rn);
5231 if (s) RETURN_STATUS(s);
5232
5233 lt = (*l)->t;
5234 rt = (*r)->t;
5235
5236 // We run this again under these conditions in case any vector has been
5237 // reallocated out from under the BcNums or arrays we had.
5238 if (lt == rt && (lt == XC_RESULT_VAR || lt == XC_RESULT_ARRAY_ELEM)) {
5239 s = zxc_program_num(*l, ln);
5240 if (s) RETURN_STATUS(s);
5241 }
5242
5243 if (!BC_PROG_NUM((*l), (*ln)) && (!assign || (*l)->t != XC_RESULT_VAR))
5244 RETURN_STATUS(bc_error_variable_is_wrong_type());
5245 if (!assign && !BC_PROG_NUM((*r), (*ln)))
5246 RETURN_STATUS(bc_error_variable_is_wrong_type());
5247
5248 RETURN_STATUS(s);
5249}
5250#define zxc_program_binOpPrep(...) (zxc_program_binOpPrep(__VA_ARGS__) COMMA_SUCCESS)
5251
5252static void xc_program_binOpRetire(BcResult *r)
5253{
5254 r->t = XC_RESULT_TEMP;
5255 bc_vec_pop(&G.prog.results);
5256 bc_result_pop_and_push(r);
5257}
5258
5259// Note: *r and *n need not be initialized by caller
5260static BC_STATUS zxc_program_prep(BcResult **r, BcNum **n)
5261{
5262 BcStatus s;
5263
5264 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
5265 RETURN_STATUS(bc_error_stack_has_too_few_elements());
5266 *r = bc_vec_top(&G.prog.results);
5267
5268 s = zxc_program_num(*r, n);
5269 if (s) RETURN_STATUS(s);
5270
5271 if (!BC_PROG_NUM((*r), (*n)))
5272 RETURN_STATUS(bc_error_variable_is_wrong_type());
5273
5274 RETURN_STATUS(s);
5275}
5276#define zxc_program_prep(...) (zxc_program_prep(__VA_ARGS__) COMMA_SUCCESS)
5277
5278static void xc_program_retire(BcResult *r, BcResultType t)
5279{
5280 r->t = t;
5281 bc_result_pop_and_push(r);
5282}
5283
5284static BC_STATUS zxc_program_op(char inst)
5285{
5286 BcStatus s;
5287 BcResult *opd1, *opd2, res;
5288 BcNum *n1, *n2;
5289
5290 s = zxc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
5291 if (s) RETURN_STATUS(s);
5292 bc_num_init_DEF_SIZE(&res.d.n);
5293
5294 s = BC_STATUS_SUCCESS;
5295 IF_ERROR_RETURN_POSSIBLE(s =) zxc_program_ops[inst - XC_INST_POWER](n1, n2, &res.d.n, G.prog.scale);
5296 if (s) goto err;
5297 xc_program_binOpRetire(&res);
5298
5299 RETURN_STATUS(s);
5300 err:
5301 bc_num_free(&res.d.n);
5302 RETURN_STATUS(s);
5303}
5304#define zxc_program_op(...) (zxc_program_op(__VA_ARGS__) COMMA_SUCCESS)
5305
5306static BC_STATUS zxc_program_read(void)
5307{
5308 BcStatus s;
5309 BcParse sv_parse;
5310 BcVec buf;
5311 BcInstPtr ip;
5312 BcFunc *f;
5313
5314 bc_char_vec_init(&buf);
5315 xc_read_line(&buf, stdin);
5316
5317 f = xc_program_func(BC_PROG_READ);
5318 bc_vec_pop_all(&f->code);
5319
5320 sv_parse = G.prs; // struct copy
5321 xc_parse_create(BC_PROG_READ);
5322 //G.err_line = G.prs.lex_line = 1; - not needed, error line info is not printed for read()
5323
5324 s = zxc_parse_text_init(buf.v);
5325 if (s) goto exec_err;
5326 if (IS_BC) {
5327 IF_BC(s = zbc_parse_expr(0));
5328 } else {
5329 IF_DC(s = zdc_parse_exprs_until_eof());
5330 }
5331 if (s) goto exec_err;
5332 if (G.prs.lex != XC_LEX_NLINE && G.prs.lex != XC_LEX_EOF) {
5333 s = bc_error_at("bad read() expression");
5334 goto exec_err;
5335 }
5336 xc_parse_push(XC_INST_RET);
5337
5338 ip.func = BC_PROG_READ;
5339 ip.inst_idx = 0;
5340 bc_vec_push(&G.prog.exestack, &ip);
5341
5342 exec_err:
5343 xc_parse_free();
5344 G.prs = sv_parse; // struct copy
5345 bc_vec_free(&buf);
5346 RETURN_STATUS(s);
5347}
5348#define zxc_program_read(...) (zxc_program_read(__VA_ARGS__) COMMA_SUCCESS)
5349
5350static size_t xc_program_index(char *code, size_t *bgn)
5351{
5352 unsigned char *bytes = (void*)(code + *bgn);
5353 unsigned amt;
5354 unsigned i;
5355 size_t res;
5356
5357 amt = *bytes++;
5358 if (amt < SMALL_INDEX_LIMIT) {
5359 *bgn += 1;
5360 return amt;
5361 }
5362 amt -= (SMALL_INDEX_LIMIT - 1); // amt is 1 or more here
5363 *bgn += amt + 1;
5364
5365 res = 0;
5366 i = 0;
5367 do {
5368 res |= (size_t)(*bytes++) << i;
5369 i += 8;
5370 } while (--amt != 0);
5371
5372 return res;
5373}
5374
5375static char *xc_program_name(char *code, size_t *bgn)
5376{
5377 code += *bgn;
5378 *bgn += strlen(code) + 1;
5379
5380 return xstrdup(code);
5381}
5382
5383static void xc_program_printString(const char *str)
5384{
5385#if ENABLE_DC
5386 if (!str[0] && IS_DC) {
5387 // Example: echo '[]ap' | dc
5388 // should print two bytes: 0x00, 0x0A
5389 bb_putchar('\0');
5390 return;
5391 }
5392#endif
5393 while (*str) {
5394 char c = *str++;
5395 if (c == '\\') {
5396 static const char esc[] ALIGN1 = "nabfrt""e\\";
5397 char *n;
5398
5399 c = *str++;
5400 n = strchr(esc, c); // note: c can be NUL
5401 if (!n) {
5402 // Just print the backslash and following character
5403 bb_putchar('\\');
5404 ++G.prog.nchars;
5405 } else {
5406 if (n - esc == 0) // "\n" ?
5407 G.prog.nchars = SIZE_MAX;
5408 c = "\n\a\b\f\r\t""\\\\""\\"[n - esc];
5409 // n a b f r t e \ \<end of line>
5410 }
5411 }
5412 putchar(c);
5413 ++G.prog.nchars;
5414 }
5415}
5416
5417static void bc_num_printNewline(void)
5418{
5419 if (G.prog.nchars == G.prog.len - 1) {
5420 bb_putchar('\\');
5421 bb_putchar('\n');
5422 G.prog.nchars = 0;
5423 }
5424}
5425
5426#if ENABLE_DC
5427static FAST_FUNC void dc_num_printChar(size_t num, size_t width, bool radix)
5428{
5429 (void) radix;
5430 bb_putchar((char) num);
5431 G.prog.nchars += width;
5432}
5433#endif
5434
5435static FAST_FUNC void bc_num_printDigits(size_t num, size_t width, bool radix)
5436{
5437 size_t exp, pow;
5438
5439 bc_num_printNewline();
5440 bb_putchar(radix ? '.' : ' ');
5441 ++G.prog.nchars;
5442
5443 bc_num_printNewline();
5444 for (exp = 0, pow = 1; exp < width - 1; ++exp, pow *= 10)
5445 continue;
5446
5447 for (exp = 0; exp < width; pow /= 10, ++G.prog.nchars, ++exp) {
5448 size_t dig;
5449 bc_num_printNewline();
5450 dig = num / pow;
5451 num -= dig * pow;
5452 bb_putchar(((char) dig) + '0');
5453 }
5454}
5455
5456static FAST_FUNC void bc_num_printHex(size_t num, size_t width, bool radix)
5457{
5458 if (radix) {
5459 bc_num_printNewline();
5460 bb_putchar('.');
5461 G.prog.nchars++;
5462 }
5463
5464 bc_num_printNewline();
5465 bb_putchar(bb_hexdigits_upcase[num]);
5466 G.prog.nchars += width;
5467}
5468
5469static void bc_num_printDecimal(BcNum *n)
5470{
5471 size_t i, rdx = n->rdx - 1;
5472
5473 if (n->neg) {
5474 bb_putchar('-');
5475 G.prog.nchars++;
5476 }
5477
5478 for (i = n->len - 1; i < n->len; --i)
5479 bc_num_printHex((size_t) n->num[i], 1, i == rdx);
5480}
5481
5482typedef void (*BcNumDigitOp)(size_t, size_t, bool) FAST_FUNC;
5483
5484static BC_STATUS zxc_num_printNum(BcNum *n, unsigned base_t, size_t width, BcNumDigitOp print)
5485{
5486 BcStatus s;
5487 BcVec stack;
5488 BcNum base;
5489 BcDig base_digs[ULONG_NUM_BUFSIZE];
5490 BcNum intp, fracp, digit, frac_len;
5491 unsigned long dig, *ptr;
5492 size_t i;
5493 bool radix;
5494
5495 if (n->len == 0) {
5496 print(0, width, false);
5497 RETURN_STATUS(BC_STATUS_SUCCESS);
5498 }
5499
5500 bc_vec_init(&stack, sizeof(long), NULL);
5501 bc_num_init(&intp, n->len);
5502 bc_num_init(&fracp, n->rdx);
5503 bc_num_init(&digit, width);
5504 bc_num_init(&frac_len, BC_NUM_INT(n));
5505 bc_num_copy(&intp, n);
5506 bc_num_one(&frac_len);
5507 base.cap = ARRAY_SIZE(base_digs);
5508 base.num = base_digs;
5509 bc_num_ulong2num(&base, base_t);
5510
5511 bc_num_truncate(&intp, intp.rdx);
5512 s = zbc_num_sub(n, &intp, &fracp, 0);
5513 if (s) goto err;
5514
5515 while (intp.len != 0) {
5516 s = zbc_num_divmod(&intp, &base, &intp, &digit, 0);
5517 if (s) goto err;
5518 s = zbc_num_ulong(&digit, &dig);
5519 if (s) goto err;
5520 bc_vec_push(&stack, &dig);
5521 }
5522
5523 for (i = 0; i < stack.len; ++i) {
5524 ptr = bc_vec_item_rev(&stack, i);
5525 print(*ptr, width, false);
5526 }
5527
5528 if (!n->rdx) goto err;
5529
5530 for (radix = true; frac_len.len <= n->rdx; radix = false) {
5531 s = zbc_num_mul(&fracp, &base, &fracp, n->rdx);
5532 if (s) goto err;
5533 s = zbc_num_ulong(&fracp, &dig);
5534 if (s) goto err;
5535 bc_num_ulong2num(&intp, dig);
5536 s = zbc_num_sub(&fracp, &intp, &fracp, 0);
5537 if (s) goto err;
5538 print(dig, width, radix);
5539 s = zbc_num_mul(&frac_len, &base, &frac_len, 0);
5540 if (s) goto err;
5541 }
5542 err:
5543 bc_num_free(&frac_len);
5544 bc_num_free(&digit);
5545 bc_num_free(&fracp);
5546 bc_num_free(&intp);
5547 bc_vec_free(&stack);
5548 RETURN_STATUS(s);
5549}
5550#define zxc_num_printNum(...) (zxc_num_printNum(__VA_ARGS__) COMMA_SUCCESS)
5551
5552static BC_STATUS zxc_num_printBase(BcNum *n)
5553{
5554 BcStatus s;
5555 size_t width;
5556 BcNumDigitOp print;
5557 bool neg = n->neg;
5558
5559 if (neg) {
5560 bb_putchar('-');
5561 G.prog.nchars++;
5562 }
5563
5564 n->neg = false;
5565
5566 if (G.prog.ob_t <= 16) {
5567 width = 1;
5568 print = bc_num_printHex;
5569 } else {
5570 unsigned i = G.prog.ob_t - 1;
5571 width = 0;
5572 for (;;) {
5573 width++;
5574 i /= 10;
5575 if (i == 0)
5576 break;
5577 }
5578 print = bc_num_printDigits;
5579 }
5580
5581 s = zxc_num_printNum(n, G.prog.ob_t, width, print);
5582 n->neg = neg;
5583
5584 RETURN_STATUS(s);
5585}
5586#define zxc_num_printBase(...) (zxc_num_printBase(__VA_ARGS__) COMMA_SUCCESS)
5587
5588static BC_STATUS zxc_num_print(BcNum *n, bool newline)
5589{
5590 BcStatus s = BC_STATUS_SUCCESS;
5591
5592 bc_num_printNewline();
5593
5594 if (n->len == 0) {
5595 bb_putchar('0');
5596 ++G.prog.nchars;
5597 } else if (G.prog.ob_t == 10)
5598 bc_num_printDecimal(n);
5599 else
5600 s = zxc_num_printBase(n);
5601
5602 if (newline) {
5603 bb_putchar('\n');
5604 G.prog.nchars = 0;
5605 }
5606
5607 RETURN_STATUS(s);
5608}
5609#define zxc_num_print(...) (zxc_num_print(__VA_ARGS__) COMMA_SUCCESS)
5610
5611#if !ENABLE_DC
5612// for bc, idx is always 0
5613#define xc_program_print(inst, idx) \
5614 xc_program_print(inst)
5615#endif
5616static BC_STATUS xc_program_print(char inst, size_t idx)
5617{
5618 BcStatus s;
5619 BcResult *r;
5620 BcNum *num;
5621 IF_NOT_DC(size_t idx = 0);
5622
5623 if (!STACK_HAS_MORE_THAN(&G.prog.results, idx))
5624 RETURN_STATUS(bc_error_stack_has_too_few_elements());
5625
5626 r = bc_vec_item_rev(&G.prog.results, idx);
5627#if ENABLE_BC
5628 if (inst == XC_INST_PRINT && r->t == BC_RESULT_VOID)
5629 // void function's result on stack, ignore
5630 RETURN_STATUS(BC_STATUS_SUCCESS);
5631#endif
5632 s = zxc_program_num(r, &num);
5633 if (s) RETURN_STATUS(s);
5634
5635 if (BC_PROG_NUM(r, num)) {
5636 s = zxc_num_print(num, /*newline:*/ inst == XC_INST_PRINT);
5637#if ENABLE_BC
5638 if (!s && IS_BC) bc_num_copy(&G.prog.last, num);
5639#endif
5640 } else {
5641 char *str;
5642
5643 idx = (r->t == XC_RESULT_STR) ? r->d.id.idx : num->rdx;
5644 str = *xc_program_str(idx);
5645
5646 if (inst == XC_INST_PRINT_STR) {
5647 char *nl;
5648 G.prog.nchars += printf("%s", str);
5649 nl = strrchr(str, '\n');
5650 if (nl)
5651 G.prog.nchars = strlen(nl + 1);
5652 } else {
5653 xc_program_printString(str);
5654 if (inst == XC_INST_PRINT)
5655 bb_putchar('\n');
5656 }
5657 }
5658
5659 if (!s && inst != XC_INST_PRINT) bc_vec_pop(&G.prog.results);
5660
5661 RETURN_STATUS(s);
5662}
5663#define zxc_program_print(...) (xc_program_print(__VA_ARGS__) COMMA_SUCCESS)
5664
5665static BC_STATUS zxc_program_negate(void)
5666{
5667 BcStatus s;
5668 BcResult res, *ptr;
5669 BcNum *num;
5670
5671 s = zxc_program_prep(&ptr, &num);
5672 if (s) RETURN_STATUS(s);
5673
5674 bc_num_init(&res.d.n, num->len);
5675 bc_num_copy(&res.d.n, num);
5676 if (res.d.n.len) res.d.n.neg = !res.d.n.neg;
5677
5678 xc_program_retire(&res, XC_RESULT_TEMP);
5679
5680 RETURN_STATUS(s);
5681}
5682#define zxc_program_negate(...) (zxc_program_negate(__VA_ARGS__) COMMA_SUCCESS)
5683
5684static BC_STATUS zxc_program_logical(char inst)
5685{
5686 BcStatus s;
5687 BcResult *opd1, *opd2, res;
5688 BcNum *n1, *n2;
5689 ssize_t cond;
5690
5691 s = zxc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
5692 if (s) RETURN_STATUS(s);
5693
5694 bc_num_init_DEF_SIZE(&res.d.n);
5695
5696 if (inst == XC_INST_BOOL_AND)
5697 cond = bc_num_cmp(n1, &G.prog.zero) && bc_num_cmp(n2, &G.prog.zero);
5698 else if (inst == XC_INST_BOOL_OR)
5699 cond = bc_num_cmp(n1, &G.prog.zero) || bc_num_cmp(n2, &G.prog.zero);
5700 else {
5701 cond = bc_num_cmp(n1, n2);
5702 switch (inst) {
5703 case XC_INST_REL_EQ:
5704 cond = (cond == 0);
5705 break;
5706 case XC_INST_REL_LE:
5707 cond = (cond <= 0);
5708 break;
5709 case XC_INST_REL_GE:
5710 cond = (cond >= 0);
5711 break;
5712 case XC_INST_REL_LT:
5713 cond = (cond < 0);
5714 break;
5715 case XC_INST_REL_GT:
5716 cond = (cond > 0);
5717 break;
5718 default: // = case XC_INST_REL_NE:
5719 //cond = (cond != 0); - not needed
5720 break;
5721 }
5722 }
5723
5724 if (cond) bc_num_one(&res.d.n);
5725 //else bc_num_zero(&res.d.n); - already is
5726
5727 xc_program_binOpRetire(&res);
5728
5729 RETURN_STATUS(s);
5730}
5731#define zxc_program_logical(...) (zxc_program_logical(__VA_ARGS__) COMMA_SUCCESS)
5732
5733#if ENABLE_DC
5734static BC_STATUS zdc_program_assignStr(BcResult *r, BcVec *v, bool push)
5735{
5736 BcNum n2;
5737 BcResult res;
5738
5739 memset(&n2, 0, sizeof(BcNum));
5740 n2.rdx = res.d.id.idx = r->d.id.idx;
5741 res.t = XC_RESULT_STR;
5742
5743 if (!push) {
5744 if (!STACK_HAS_MORE_THAN(&G.prog.results, 1))
5745 RETURN_STATUS(bc_error_stack_has_too_few_elements());
5746 bc_vec_pop(v);
5747 bc_vec_pop(&G.prog.results);
5748 }
5749
5750 bc_result_pop_and_push(&res);
5751 bc_vec_push(v, &n2);
5752
5753 RETURN_STATUS(BC_STATUS_SUCCESS);
5754}
5755#define zdc_program_assignStr(...) (zdc_program_assignStr(__VA_ARGS__) COMMA_SUCCESS)
5756#endif // ENABLE_DC
5757
5758static BC_STATUS zxc_program_popResultAndCopyToVar(char *name, bool var)
5759{
5760 BcStatus s;
5761 BcResult *ptr, r;
5762 BcVec *v;
5763 BcNum *n;
5764
5765 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
5766 RETURN_STATUS(bc_error_stack_has_too_few_elements());
5767
5768 ptr = bc_vec_top(&G.prog.results);
5769 if ((ptr->t == XC_RESULT_ARRAY) != !var)
5770 RETURN_STATUS(bc_error_variable_is_wrong_type());
5771 v = xc_program_search(name, var);
5772
5773#if ENABLE_DC
5774 if (ptr->t == XC_RESULT_STR && !var)
5775 RETURN_STATUS(bc_error_variable_is_wrong_type());
5776 if (ptr->t == XC_RESULT_STR)
5777 RETURN_STATUS(zdc_program_assignStr(ptr, v, true));
5778#endif
5779
5780 s = zxc_program_num(ptr, &n);
5781 if (s) RETURN_STATUS(s);
5782
5783 // Do this once more to make sure that pointers were not invalidated.
5784 v = xc_program_search(name, var);
5785
5786 if (var) {
5787 bc_num_init_DEF_SIZE(&r.d.n);
5788 bc_num_copy(&r.d.n, n);
5789 } else {
5790 bc_array_init(&r.d.v, true);
5791 bc_array_copy(&r.d.v, (BcVec *) n);
5792 }
5793
5794 bc_vec_push(v, &r.d);
5795 bc_vec_pop(&G.prog.results);
5796
5797 RETURN_STATUS(s);
5798}
5799#define zxc_program_popResultAndCopyToVar(...) (zxc_program_popResultAndCopyToVar(__VA_ARGS__) COMMA_SUCCESS)
5800
5801static BC_STATUS zxc_program_assign(char inst)
5802{
5803 BcStatus s;
5804 BcResult *left, *right, res;
5805 BcNum *l, *r;
5806 bool assign = (inst == XC_INST_ASSIGN);
5807 bool ib, sc;
5808
5809 s = zxc_program_binOpPrep(&left, &l, &right, &r, assign);
5810 if (s) RETURN_STATUS(s);
5811
5812 ib = left->t == XC_RESULT_IBASE;
5813 sc = left->t == XC_RESULT_SCALE;
5814
5815#if ENABLE_DC
5816 if (right->t == XC_RESULT_STR) {
5817 BcVec *v;
5818
5819 if (left->t != XC_RESULT_VAR)
5820 RETURN_STATUS(bc_error_variable_is_wrong_type());
5821 v = xc_program_search(left->d.id.name, true);
5822
5823 RETURN_STATUS(zdc_program_assignStr(right, v, false));
5824 }
5825#endif
5826
5827 if (left->t == XC_RESULT_CONSTANT
5828 || left->t == XC_RESULT_TEMP
5829 IF_BC(|| left->t == BC_RESULT_VOID)
5830 ) {
5831 RETURN_STATUS(bc_error_bad_assignment());
5832 }
5833
5834#if ENABLE_BC
5835 if (assign)
5836 bc_num_copy(l, r);
5837 else {
5838 s = BC_STATUS_SUCCESS;
5839 IF_ERROR_RETURN_POSSIBLE(s =) zxc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, G.prog.scale);
5840 }
5841 if (s) RETURN_STATUS(s);
5842#else
5843 bc_num_copy(l, r);
5844#endif
5845
5846 if (ib || sc || left->t == XC_RESULT_OBASE) {
5847 static const char *const msg[] = {
5848 "bad ibase; must be [2,16]", //XC_RESULT_IBASE
5849 "bad obase; must be [2,"BC_MAX_OBASE_STR"]", //XC_RESULT_OBASE
5850 "bad scale; must be [0,"BC_MAX_SCALE_STR"]", //XC_RESULT_SCALE
5851 };
5852 size_t *ptr;
5853 size_t max;
5854 unsigned long val;
5855
5856 s = zbc_num_ulong(l, &val);
5857 if (s) RETURN_STATUS(s);
5858 s = left->t - XC_RESULT_IBASE;
5859 if (sc) {
5860 max = BC_MAX_SCALE;
5861 ptr = &G.prog.scale;
5862 } else {
5863 if (val < 2)
5864 RETURN_STATUS(bc_error(msg[s]));
5865 max = ib ? BC_NUM_MAX_IBASE : BC_MAX_OBASE;
5866 ptr = ib ? &G.prog.ib_t : &G.prog.ob_t;
5867 }
5868
5869 if (val > max)
5870 RETURN_STATUS(bc_error(msg[s]));
5871
5872 *ptr = (size_t) val;
5873 s = BC_STATUS_SUCCESS;
5874 }
5875
5876 bc_num_init(&res.d.n, l->len);
5877 bc_num_copy(&res.d.n, l);
5878 xc_program_binOpRetire(&res);
5879
5880 RETURN_STATUS(s);
5881}
5882#define zxc_program_assign(...) (zxc_program_assign(__VA_ARGS__) COMMA_SUCCESS)
5883
5884#if !ENABLE_DC
5885#define xc_program_pushVar(code, bgn, pop, copy) \
5886 xc_program_pushVar(code, bgn)
5887// for bc, 'pop' and 'copy' are always false
5888#endif
5889static BC_STATUS xc_program_pushVar(char *code, size_t *bgn,
5890 bool pop, bool copy)
5891{
5892 BcResult r;
5893 char *name = xc_program_name(code, bgn);
5894
5895 r.t = XC_RESULT_VAR;
5896 r.d.id.name = name;
5897
5898#if ENABLE_DC
5899 if (pop || copy) {
5900 BcVec *v = xc_program_search(name, true);
5901 BcNum *num = bc_vec_top(v);
5902
5903 free(name);
5904 if (!STACK_HAS_MORE_THAN(v, 1 - copy)) {
5905 RETURN_STATUS(bc_error_stack_has_too_few_elements());
5906 }
5907
5908 if (!BC_PROG_STR(num)) {
5909 r.t = XC_RESULT_TEMP;
5910 bc_num_init_DEF_SIZE(&r.d.n);
5911 bc_num_copy(&r.d.n, num);
5912 } else {
5913 r.t = XC_RESULT_STR;
5914 r.d.id.idx = num->rdx;
5915 }
5916
5917 if (!copy) bc_vec_pop(v);
5918 }
5919#endif // ENABLE_DC
5920
5921 bc_vec_push(&G.prog.results, &r);
5922
5923 RETURN_STATUS(BC_STATUS_SUCCESS);
5924}
5925#define zxc_program_pushVar(...) (xc_program_pushVar(__VA_ARGS__) COMMA_SUCCESS)
5926
5927static BC_STATUS zbc_program_pushArray(char *code, size_t *bgn, char inst)
5928{
5929 BcStatus s = BC_STATUS_SUCCESS;
5930 BcResult r;
5931 BcNum *num;
5932
5933 r.d.id.name = xc_program_name(code, bgn);
5934
5935 if (inst == XC_INST_ARRAY) {
5936 r.t = XC_RESULT_ARRAY;
5937 bc_vec_push(&G.prog.results, &r);
5938 } else {
5939 BcResult *operand;
5940 unsigned long temp;
5941
5942 s = zxc_program_prep(&operand, &num);
5943 if (s) goto err;
5944 s = zbc_num_ulong(num, &temp);
5945 if (s) goto err;
5946
5947 if (temp > BC_MAX_DIM) {
5948 s = bc_error("array too long; must be [1,"BC_MAX_DIM_STR"]");
5949 goto err;
5950 }
5951
5952 r.d.id.idx = (size_t) temp;
5953 xc_program_retire(&r, XC_RESULT_ARRAY_ELEM);
5954 }
5955 err:
5956 if (s) free(r.d.id.name);
5957 RETURN_STATUS(s);
5958}
5959#define zbc_program_pushArray(...) (zbc_program_pushArray(__VA_ARGS__) COMMA_SUCCESS)
5960
5961#if ENABLE_BC
5962static BC_STATUS zbc_program_incdec(char inst)
5963{
5964 BcStatus s;
5965 BcResult *ptr, res, copy;
5966 BcNum *num;
5967 char inst2 = inst;
5968
5969 s = zxc_program_prep(&ptr, &num);
5970 if (s) RETURN_STATUS(s);
5971
5972 if (inst == BC_INST_INC_POST || inst == BC_INST_DEC_POST) {
5973 copy.t = XC_RESULT_TEMP;
5974 bc_num_init(&copy.d.n, num->len);
5975 bc_num_copy(&copy.d.n, num);
5976 }
5977
5978 res.t = BC_RESULT_ONE;
5979 inst = (inst == BC_INST_INC_PRE || inst == BC_INST_INC_POST)
5980 ? BC_INST_ASSIGN_PLUS
5981 : BC_INST_ASSIGN_MINUS;
5982
5983 bc_vec_push(&G.prog.results, &res);
5984 s = zxc_program_assign(inst);
5985 if (s) RETURN_STATUS(s);
5986
5987 if (inst2 == BC_INST_INC_POST || inst2 == BC_INST_DEC_POST) {
5988 bc_result_pop_and_push(&copy);
5989 }
5990
5991 RETURN_STATUS(s);
5992}
5993#define zbc_program_incdec(...) (zbc_program_incdec(__VA_ARGS__) COMMA_SUCCESS)
5994
5995static BC_STATUS zbc_program_call(char *code, size_t *idx)
5996{
5997 BcInstPtr ip;
5998 size_t i, nparams;
5999 BcId *a;
6000 BcFunc *func;
6001
6002 nparams = xc_program_index(code, idx);
6003 ip.func = xc_program_index(code, idx);
6004 func = xc_program_func(ip.func);
6005
6006 if (func->code.len == 0) {
6007 RETURN_STATUS(bc_error("undefined function"));
6008 }
6009 if (nparams != func->nparams) {
6010 RETURN_STATUS(bc_error_fmt("function has %u parameters, but called with %u", func->nparams, nparams));
6011 }
6012 ip.inst_idx = 0;
6013
6014 for (i = 0; i < nparams; ++i) {
6015 BcResult *arg;
6016 BcStatus s;
6017
6018 a = bc_vec_item(&func->autos, nparams - 1 - i);
6019 arg = bc_vec_top(&G.prog.results);
6020
6021 if ((!a->idx) != (arg->t == XC_RESULT_ARRAY) // array/variable mismatch
6022 // || arg->t == XC_RESULT_STR - impossible, f("str") is not a legal syntax (strings are not bc expressions)
6023 ) {
6024 RETURN_STATUS(bc_error_variable_is_wrong_type());
6025 }
6026 s = zxc_program_popResultAndCopyToVar(a->name, a->idx);
6027 if (s) RETURN_STATUS(s);
6028 }
6029
6030 a = bc_vec_item(&func->autos, i);
6031 for (; i < func->autos.len; i++, a++) {
6032 BcVec *v;
6033
6034 v = xc_program_search(a->name, a->idx);
6035 if (a->idx) {
6036 BcNum n2;
6037 bc_num_init_DEF_SIZE(&n2);
6038 bc_vec_push(v, &n2);
6039 } else {
6040 BcVec v2;
6041 bc_array_init(&v2, true);
6042 bc_vec_push(v, &v2);
6043 }
6044 }
6045
6046 bc_vec_push(&G.prog.exestack, &ip);
6047
6048 RETURN_STATUS(BC_STATUS_SUCCESS);
6049}
6050#define zbc_program_call(...) (zbc_program_call(__VA_ARGS__) COMMA_SUCCESS)
6051
6052static BC_STATUS zbc_program_return(char inst)
6053{
6054 BcResult res;
6055 BcFunc *f;
6056 BcId *a;
6057 size_t i;
6058 BcInstPtr *ip = bc_vec_top(&G.prog.exestack);
6059
6060 f = xc_program_func(ip->func);
6061
6062 res.t = XC_RESULT_TEMP;
6063 if (inst == XC_INST_RET) {
6064 // bc needs this for e.g. RESULT_CONSTANT ("return 5")
6065 // because bc constants are per-function.
6066 // TODO: maybe avoid if value is already RESULT_TEMP?
6067 BcStatus s;
6068 BcNum *num;
6069 BcResult *operand = bc_vec_top(&G.prog.results);
6070
6071 s = zxc_program_num(operand, &num);
6072 if (s) RETURN_STATUS(s);
6073 bc_num_init(&res.d.n, num->len);
6074 bc_num_copy(&res.d.n, num);
6075 bc_vec_pop(&G.prog.results);
6076 } else {
6077 if (f->voidfunc)
6078 res.t = BC_RESULT_VOID;
6079 bc_num_init_DEF_SIZE(&res.d.n);
6080 //bc_num_zero(&res.d.n); - already is
6081 }
6082 bc_vec_push(&G.prog.results, &res);
6083
6084 bc_vec_pop(&G.prog.exestack);
6085
6086 // We need to pop arguments as well, so this takes that into account.
6087 a = (void*)f->autos.v;
6088 for (i = 0; i < f->autos.len; i++, a++) {
6089 BcVec *v;
6090 v = xc_program_search(a->name, a->idx);
6091 bc_vec_pop(v);
6092 }
6093
6094 RETURN_STATUS(BC_STATUS_SUCCESS);
6095}
6096#define zbc_program_return(...) (zbc_program_return(__VA_ARGS__) COMMA_SUCCESS)
6097#endif // ENABLE_BC
6098
6099static unsigned long xc_program_scale(BcNum *n)
6100{
6101 return (unsigned long) n->rdx;
6102}
6103
6104static unsigned long xc_program_len(BcNum *n)
6105{
6106 size_t len = n->len;
6107
6108 if (n->rdx != len) return len;
6109 for (;;) {
6110 if (len == 0) break;
6111 len--;
6112 if (n->num[len] != 0) break;
6113 }
6114 return len;
6115}
6116
6117static BC_STATUS zxc_program_builtin(char inst)
6118{
6119 BcStatus s;
6120 BcResult *opnd;
6121 BcNum *num;
6122 BcResult res;
6123 bool len = (inst == XC_INST_LENGTH);
6124
6125 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
6126 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6127 opnd = bc_vec_top(&G.prog.results);
6128
6129 s = zxc_program_num(opnd, &num);
6130 if (s) RETURN_STATUS(s);
6131
6132#if ENABLE_DC
6133 if (!BC_PROG_NUM(opnd, num) && !len)
6134 RETURN_STATUS(bc_error_variable_is_wrong_type());
6135#endif
6136
6137 bc_num_init_DEF_SIZE(&res.d.n);
6138
6139 if (inst == XC_INST_SQRT)
6140 s = zbc_num_sqrt(num, &res.d.n, G.prog.scale);
6141#if ENABLE_BC
6142 else if (len != 0 && opnd->t == XC_RESULT_ARRAY) {
6143 bc_num_ulong2num(&res.d.n, (unsigned long) ((BcVec *) num)->len);
6144 }
6145#endif
6146#if ENABLE_DC
6147 else if (len != 0 && !BC_PROG_NUM(opnd, num)) {
6148 char **str;
6149 size_t idx = opnd->t == XC_RESULT_STR ? opnd->d.id.idx : num->rdx;
6150
6151 str = xc_program_str(idx);
6152 bc_num_ulong2num(&res.d.n, strlen(*str));
6153 }
6154#endif
6155 else {
6156 bc_num_ulong2num(&res.d.n, len ? xc_program_len(num) : xc_program_scale(num));
6157 }
6158
6159 xc_program_retire(&res, XC_RESULT_TEMP);
6160
6161 RETURN_STATUS(s);
6162}
6163#define zxc_program_builtin(...) (zxc_program_builtin(__VA_ARGS__) COMMA_SUCCESS)
6164
6165#if ENABLE_DC
6166static BC_STATUS zdc_program_divmod(void)
6167{
6168 BcStatus s;
6169 BcResult *opd1, *opd2, res, res2;
6170 BcNum *n1, *n2;
6171
6172 s = zxc_program_binOpPrep(&opd1, &n1, &opd2, &n2, false);
6173 if (s) RETURN_STATUS(s);
6174
6175 bc_num_init_DEF_SIZE(&res.d.n);
6176 bc_num_init(&res2.d.n, n2->len);
6177
6178 s = zbc_num_divmod(n1, n2, &res2.d.n, &res.d.n, G.prog.scale);
6179 if (s) goto err;
6180
6181 xc_program_binOpRetire(&res2);
6182 res.t = XC_RESULT_TEMP;
6183 bc_vec_push(&G.prog.results, &res);
6184
6185 RETURN_STATUS(s);
6186 err:
6187 bc_num_free(&res2.d.n);
6188 bc_num_free(&res.d.n);
6189 RETURN_STATUS(s);
6190}
6191#define zdc_program_divmod(...) (zdc_program_divmod(__VA_ARGS__) COMMA_SUCCESS)
6192
6193static BC_STATUS zdc_program_modexp(void)
6194{
6195 BcStatus s;
6196 BcResult *r1, *r2, *r3, res;
6197 BcNum *n1, *n2, *n3;
6198
6199 if (!STACK_HAS_MORE_THAN(&G.prog.results, 2))
6200 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6201 s = zxc_program_binOpPrep(&r2, &n2, &r3, &n3, false);
6202 if (s) RETURN_STATUS(s);
6203
6204 r1 = bc_vec_item_rev(&G.prog.results, 2);
6205 s = zxc_program_num(r1, &n1);
6206 if (s) RETURN_STATUS(s);
6207 if (!BC_PROG_NUM(r1, n1))
6208 RETURN_STATUS(bc_error_variable_is_wrong_type());
6209
6210 // Make sure that the values have their pointers updated, if necessary.
6211 if (r1->t == XC_RESULT_VAR || r1->t == XC_RESULT_ARRAY_ELEM) {
6212 if (r1->t == r2->t) {
6213 s = zxc_program_num(r2, &n2);
6214 if (s) RETURN_STATUS(s);
6215 }
6216 if (r1->t == r3->t) {
6217 s = zxc_program_num(r3, &n3);
6218 if (s) RETURN_STATUS(s);
6219 }
6220 }
6221
6222 bc_num_init(&res.d.n, n3->len);
6223 s = zdc_num_modexp(n1, n2, n3, &res.d.n);
6224 if (s) goto err;
6225
6226 bc_vec_pop(&G.prog.results);
6227 xc_program_binOpRetire(&res);
6228
6229 RETURN_STATUS(s);
6230 err:
6231 bc_num_free(&res.d.n);
6232 RETURN_STATUS(s);
6233}
6234#define zdc_program_modexp(...) (zdc_program_modexp(__VA_ARGS__) COMMA_SUCCESS)
6235
6236static void dc_program_stackLen(void)
6237{
6238 BcResult res;
6239 size_t len = G.prog.results.len;
6240
6241 res.t = XC_RESULT_TEMP;
6242
6243 bc_num_init_DEF_SIZE(&res.d.n);
6244 bc_num_ulong2num(&res.d.n, len);
6245 bc_vec_push(&G.prog.results, &res);
6246}
6247
6248static BC_STATUS zdc_program_asciify(void)
6249{
6250 BcStatus s;
6251 BcResult *r, res;
6252 BcNum *num, n;
6253 char **strs;
6254 char *str;
6255 char c;
6256 size_t idx;
6257
6258 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
6259 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6260
6261 r = bc_vec_top(&G.prog.results);
6262 s = zxc_program_num(r, &num);
6263 if (s) RETURN_STATUS(s);
6264
6265 if (BC_PROG_NUM(r, num)) {
6266 unsigned long val;
6267 BcNum strmb;
6268 BcDig strmb_digs[ULONG_NUM_BUFSIZE];
6269
6270 bc_num_init_DEF_SIZE(&n);
6271 bc_num_copy(&n, num);
6272 bc_num_truncate(&n, n.rdx);
6273
6274 strmb.cap = ARRAY_SIZE(strmb_digs);
6275 strmb.num = strmb_digs;
6276 bc_num_ulong2num(&strmb, 0x100);
6277
6278 s = zbc_num_mod(&n, &strmb, &n, 0);
6279 if (s) goto num_err;
6280 s = zbc_num_ulong(&n, &val);
6281 if (s) goto num_err;
6282
6283 c = (char) val;
6284
6285 bc_num_free(&n);
6286 } else {
6287 char *sp;
6288 idx = (r->t == XC_RESULT_STR) ? r->d.id.idx : num->rdx;
6289 sp = *xc_program_str(idx);
6290 c = sp[0];
6291 }
6292
6293 strs = (void*)G.prog.strs.v;
6294 for (idx = 0; idx < G.prog.strs.len; idx++) {
6295 if (strs[idx][0] == c && strs[idx][1] == '\0') {
6296 goto dup;
6297 }
6298 }
6299 str = xzalloc(2);
6300 str[0] = c;
6301 //str[1] = '\0'; - already is
6302 bc_vec_push(&G.prog.strs, &str);
6303 dup:
6304 res.t = XC_RESULT_STR;
6305 res.d.id.idx = idx;
6306 bc_result_pop_and_push(&res);
6307
6308 RETURN_STATUS(BC_STATUS_SUCCESS);
6309 num_err:
6310 bc_num_free(&n);
6311 RETURN_STATUS(s);
6312}
6313#define zdc_program_asciify(...) (zdc_program_asciify(__VA_ARGS__) COMMA_SUCCESS)
6314
6315static BC_STATUS zdc_program_printStream(void)
6316{
6317 BcStatus s;
6318 BcResult *r;
6319 BcNum *n;
6320 size_t idx;
6321
6322 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
6323 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6324 r = bc_vec_top(&G.prog.results);
6325
6326 s = zxc_program_num(r, &n);
6327 if (s) RETURN_STATUS(s);
6328
6329 if (BC_PROG_NUM(r, n)) {
6330 s = zxc_num_printNum(n, 0x100, 1, dc_num_printChar);
6331 } else {
6332 char *str;
6333 idx = (r->t == XC_RESULT_STR) ? r->d.id.idx : n->rdx;
6334 str = *xc_program_str(idx);
6335 fputs(str, stdout);
6336 }
6337
6338 RETURN_STATUS(s);
6339}
6340#define zdc_program_printStream(...) (zdc_program_printStream(__VA_ARGS__) COMMA_SUCCESS)
6341
6342static BC_STATUS zdc_program_nquit(void)
6343{
6344 BcStatus s;
6345 BcResult *opnd;
6346 BcNum *num;
6347 unsigned long val;
6348
6349 s = zxc_program_prep(&opnd, &num);
6350 if (s) RETURN_STATUS(s);
6351 s = zbc_num_ulong(num, &val);
6352 if (s) RETURN_STATUS(s);
6353
6354 bc_vec_pop(&G.prog.results);
6355
6356 if (G.prog.exestack.len < val)
6357 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6358 if (G.prog.exestack.len == val) {
6359 QUIT_OR_RETURN_TO_MAIN;
6360 }
6361
6362 bc_vec_npop(&G.prog.exestack, val);
6363
6364 RETURN_STATUS(s);
6365}
6366#define zdc_program_nquit(...) (zdc_program_nquit(__VA_ARGS__) COMMA_SUCCESS)
6367
6368static BC_STATUS zdc_program_execStr(char *code, size_t *bgn, bool cond)
6369{
6370 BcStatus s = BC_STATUS_SUCCESS;
6371 BcResult *r;
6372 BcFunc *f;
6373 BcInstPtr ip;
6374 size_t fidx, sidx;
6375
6376 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
6377 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6378
6379 r = bc_vec_top(&G.prog.results);
6380
6381 if (cond) {
6382 BcNum *n = n; // for compiler
6383 bool exec;
6384 char *name;
6385 char *then_name = xc_program_name(code, bgn);
6386 char *else_name = NULL;
6387
6388 if (code[*bgn] == '\0')
6389 (*bgn) += 1;
6390 else
6391 else_name = xc_program_name(code, bgn);
6392
6393 exec = r->d.n.len != 0;
6394 name = then_name;
6395 if (!exec && else_name != NULL) {
6396 exec = true;
6397 name = else_name;
6398 }
6399
6400 if (exec) {
6401 BcVec *v;
6402 v = xc_program_search(name, true);
6403 n = bc_vec_top(v);
6404 }
6405
6406 free(then_name);
6407 free(else_name);
6408
6409 if (!exec) goto exit;
6410 if (!BC_PROG_STR(n)) {
6411 s = bc_error_variable_is_wrong_type();
6412 goto exit;
6413 }
6414
6415 sidx = n->rdx;
6416 } else {
6417 if (r->t == XC_RESULT_STR) {
6418 sidx = r->d.id.idx;
6419 } else if (r->t == XC_RESULT_VAR) {
6420 BcNum *n;
6421 s = zxc_program_num(r, &n);
6422 if (s || !BC_PROG_STR(n)) goto exit;
6423 sidx = n->rdx;
6424 } else
6425 goto exit;
6426 }
6427
6428 fidx = sidx + BC_PROG_REQ_FUNCS;
6429
6430 f = xc_program_func(fidx);
6431
6432 if (f->code.len == 0) {
6433 BcParse sv_parse;
6434 char *str;
6435
6436 sv_parse = G.prs; // struct copy
6437 xc_parse_create(fidx);
6438 str = *xc_program_str(sidx);
6439 s = zxc_parse_text_init(str);
6440 if (s) goto err;
6441
6442 s = zdc_parse_exprs_until_eof();
6443 if (s) goto err;
6444 xc_parse_push(DC_INST_POP_EXEC);
6445 if (G.prs.lex != XC_LEX_EOF)
6446 s = bc_error_bad_expression();
6447 xc_parse_free();
6448 G.prs = sv_parse; // struct copy
6449 if (s) {
6450 err:
6451 bc_vec_pop_all(&f->code);
6452 goto exit;
6453 }
6454 }
6455
6456 ip.inst_idx = 0;
6457 ip.func = fidx;
6458
6459 bc_vec_pop(&G.prog.results);
6460 bc_vec_push(&G.prog.exestack, &ip);
6461
6462 RETURN_STATUS(BC_STATUS_SUCCESS);
6463 exit:
6464 bc_vec_pop(&G.prog.results);
6465 RETURN_STATUS(s);
6466}
6467#define zdc_program_execStr(...) (zdc_program_execStr(__VA_ARGS__) COMMA_SUCCESS)
6468#endif // ENABLE_DC
6469
6470static void xc_program_pushGlobal(char inst)
6471{
6472 BcResult res;
6473 unsigned long val;
6474
6475 res.t = inst - XC_INST_IBASE + XC_RESULT_IBASE;
6476 if (inst == XC_INST_IBASE)
6477 val = (unsigned long) G.prog.ib_t;
6478 else if (inst == XC_INST_SCALE)
6479 val = (unsigned long) G.prog.scale;
6480 else
6481 val = (unsigned long) G.prog.ob_t;
6482
6483 bc_num_init_DEF_SIZE(&res.d.n);
6484 bc_num_ulong2num(&res.d.n, val);
6485 bc_vec_push(&G.prog.results, &res);
6486}
6487
6488static BC_STATUS zxc_program_exec(void)
6489{
6490 BcResult r, *ptr;
6491 BcInstPtr *ip = bc_vec_top(&G.prog.exestack);
6492 BcFunc *func = xc_program_func(ip->func);
6493 char *code = func->code.v;
6494
6495 dbg_exec("func:%zd bytes:%zd ip:%zd results.len:%d",
6496 ip->func, func->code.len, ip->inst_idx, G.prog.results.len);
6497 while (ip->inst_idx < func->code.len) {
6498 BcStatus s = BC_STATUS_SUCCESS;
6499 char inst = code[ip->inst_idx++];
6500
6501 dbg_exec("inst at %zd:%d results.len:%d", ip->inst_idx - 1, inst, G.prog.results.len);
6502 switch (inst) {
6503 case XC_INST_RET:
6504 if (IS_DC) { // end of '?' reached
6505 bc_vec_pop(&G.prog.exestack);
6506 goto read_updated_ip;
6507 }
6508 // bc: fall through
6509#if ENABLE_BC
6510 case BC_INST_RET0:
6511 dbg_exec("BC_INST_RET[0]:");
6512 s = zbc_program_return(inst);
6513 goto read_updated_ip;
6514 case BC_INST_JUMP_ZERO: {
6515 BcNum *num;
6516 bool zero;
6517 dbg_exec("BC_INST_JUMP_ZERO:");
6518 s = zxc_program_prep(&ptr, &num);
6519 if (s) RETURN_STATUS(s);
6520 zero = (bc_num_cmp(num, &G.prog.zero) == 0);
6521 bc_vec_pop(&G.prog.results);
6522 if (!zero) {
6523 xc_program_index(code, &ip->inst_idx);
6524 break;
6525 }
6526 // else: fall through
6527 }
6528 case BC_INST_JUMP: {
6529 size_t idx = xc_program_index(code, &ip->inst_idx);
6530 size_t *addr = bc_vec_item(&func->labels, idx);
6531 dbg_exec("BC_INST_JUMP: to %ld", (long)*addr);
6532 ip->inst_idx = *addr;
6533 break;
6534 }
6535 case BC_INST_CALL:
6536 dbg_exec("BC_INST_CALL:");
6537 s = zbc_program_call(code, &ip->inst_idx);
6538 goto read_updated_ip;
6539 case BC_INST_INC_PRE:
6540 case BC_INST_DEC_PRE:
6541 case BC_INST_INC_POST:
6542 case BC_INST_DEC_POST:
6543 dbg_exec("BC_INST_INCDEC:");
6544 s = zbc_program_incdec(inst);
6545 break;
6546 case BC_INST_HALT:
6547 dbg_exec("BC_INST_HALT:");
6548 QUIT_OR_RETURN_TO_MAIN;
6549 break;
6550 case XC_INST_BOOL_OR:
6551 case XC_INST_BOOL_AND:
6552#endif // ENABLE_BC
6553 case XC_INST_REL_EQ:
6554 case XC_INST_REL_LE:
6555 case XC_INST_REL_GE:
6556 case XC_INST_REL_NE:
6557 case XC_INST_REL_LT:
6558 case XC_INST_REL_GT:
6559 dbg_exec("BC_INST_BOOL:");
6560 s = zxc_program_logical(inst);
6561 break;
6562 case XC_INST_READ:
6563 dbg_exec("XC_INST_READ:");
6564 s = zxc_program_read();
6565 goto read_updated_ip;
6566 case XC_INST_VAR:
6567 dbg_exec("XC_INST_VAR:");
6568 s = zxc_program_pushVar(code, &ip->inst_idx, false, false);
6569 break;
6570 case XC_INST_ARRAY_ELEM:
6571 case XC_INST_ARRAY:
6572 dbg_exec("XC_INST_ARRAY[_ELEM]:");
6573 s = zbc_program_pushArray(code, &ip->inst_idx, inst);
6574 break;
6575#if ENABLE_BC
6576 case BC_INST_LAST:
6577 dbg_exec("BC_INST_LAST:");
6578 r.t = BC_RESULT_LAST;
6579 bc_vec_push(&G.prog.results, &r);
6580 break;
6581#endif
6582 case XC_INST_IBASE:
6583 case XC_INST_OBASE:
6584 case XC_INST_SCALE:
6585 dbg_exec("XC_INST_internalvar(%d):", inst - XC_INST_IBASE);
6586 xc_program_pushGlobal(inst);
6587 break;
6588 case XC_INST_SCALE_FUNC:
6589 case XC_INST_LENGTH:
6590 case XC_INST_SQRT:
6591 dbg_exec("BC_INST_builtin:");
6592 s = zxc_program_builtin(inst);
6593 break;
6594 case XC_INST_NUM:
6595 dbg_exec("XC_INST_NUM:");
6596 r.t = XC_RESULT_CONSTANT;
6597 r.d.id.idx = xc_program_index(code, &ip->inst_idx);
6598 bc_vec_push(&G.prog.results, &r);
6599 break;
6600 case XC_INST_POP:
6601 dbg_exec("XC_INST_POP:");
6602 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
6603 s = bc_error_stack_has_too_few_elements();
6604 else
6605 bc_vec_pop(&G.prog.results);
6606 break;
6607 case XC_INST_PRINT:
6608 case XC_INST_PRINT_POP:
6609 case XC_INST_PRINT_STR:
6610 dbg_exec("XC_INST_PRINTxyz(%d):", inst - XC_INST_PRINT);
6611 s = zxc_program_print(inst, 0);
6612 break;
6613 case XC_INST_STR:
6614 dbg_exec("XC_INST_STR:");
6615 r.t = XC_RESULT_STR;
6616 r.d.id.idx = xc_program_index(code, &ip->inst_idx);
6617 bc_vec_push(&G.prog.results, &r);
6618 break;
6619 case XC_INST_POWER:
6620 case XC_INST_MULTIPLY:
6621 case XC_INST_DIVIDE:
6622 case XC_INST_MODULUS:
6623 case XC_INST_PLUS:
6624 case XC_INST_MINUS:
6625 dbg_exec("BC_INST_binaryop:");
6626 s = zxc_program_op(inst);
6627 break;
6628 case XC_INST_BOOL_NOT: {
6629 BcNum *num;
6630 dbg_exec("XC_INST_BOOL_NOT:");
6631 s = zxc_program_prep(&ptr, &num);
6632 if (s) RETURN_STATUS(s);
6633 bc_num_init_DEF_SIZE(&r.d.n);
6634 if (bc_num_cmp(num, &G.prog.zero) == 0)
6635 bc_num_one(&r.d.n);
6636 //else bc_num_zero(&r.d.n); - already is
6637 xc_program_retire(&r, XC_RESULT_TEMP);
6638 break;
6639 }
6640 case XC_INST_NEG:
6641 dbg_exec("XC_INST_NEG:");
6642 s = zxc_program_negate();
6643 break;
6644#if ENABLE_BC
6645 case BC_INST_ASSIGN_POWER:
6646 case BC_INST_ASSIGN_MULTIPLY:
6647 case BC_INST_ASSIGN_DIVIDE:
6648 case BC_INST_ASSIGN_MODULUS:
6649 case BC_INST_ASSIGN_PLUS:
6650 case BC_INST_ASSIGN_MINUS:
6651#endif
6652 case XC_INST_ASSIGN:
6653 dbg_exec("BC_INST_ASSIGNxyz:");
6654 s = zxc_program_assign(inst);
6655 break;
6656#if ENABLE_DC
6657 case DC_INST_POP_EXEC:
6658 dbg_exec("DC_INST_POP_EXEC:");
6659 bc_vec_pop(&G.prog.exestack);
6660 goto read_updated_ip;
6661 case DC_INST_MODEXP:
6662 dbg_exec("DC_INST_MODEXP:");
6663 s = zdc_program_modexp();
6664 break;
6665 case DC_INST_DIVMOD:
6666 dbg_exec("DC_INST_DIVMOD:");
6667 s = zdc_program_divmod();
6668 break;
6669 case DC_INST_EXECUTE:
6670 case DC_INST_EXEC_COND:
6671 dbg_exec("DC_INST_EXEC[_COND]:");
6672 s = zdc_program_execStr(code, &ip->inst_idx, inst == DC_INST_EXEC_COND);
6673 goto read_updated_ip;
6674 case DC_INST_PRINT_STACK: {
6675 size_t idx;
6676 dbg_exec("DC_INST_PRINT_STACK:");
6677 for (idx = 0; idx < G.prog.results.len; ++idx) {
6678 s = zxc_program_print(XC_INST_PRINT, idx);
6679 if (s) break;
6680 }
6681 break;
6682 }
6683 case DC_INST_CLEAR_STACK:
6684 dbg_exec("DC_INST_CLEAR_STACK:");
6685 bc_vec_pop_all(&G.prog.results);
6686 break;
6687 case DC_INST_STACK_LEN:
6688 dbg_exec("DC_INST_STACK_LEN:");
6689 dc_program_stackLen();
6690 break;
6691 case DC_INST_DUPLICATE:
6692 dbg_exec("DC_INST_DUPLICATE:");
6693 if (!STACK_HAS_MORE_THAN(&G.prog.results, 0))
6694 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6695 ptr = bc_vec_top(&G.prog.results);
6696 dc_result_copy(&r, ptr);
6697 bc_vec_push(&G.prog.results, &r);
6698 break;
6699 case DC_INST_SWAP: {
6700 BcResult *ptr2;
6701 dbg_exec("DC_INST_SWAP:");
6702 if (!STACK_HAS_MORE_THAN(&G.prog.results, 1))
6703 RETURN_STATUS(bc_error_stack_has_too_few_elements());
6704 ptr = bc_vec_item_rev(&G.prog.results, 0);
6705 ptr2 = bc_vec_item_rev(&G.prog.results, 1);
6706 memcpy(&r, ptr, sizeof(BcResult));
6707 memcpy(ptr, ptr2, sizeof(BcResult));
6708 memcpy(ptr2, &r, sizeof(BcResult));
6709 break;
6710 }
6711 case DC_INST_ASCIIFY:
6712 dbg_exec("DC_INST_ASCIIFY:");
6713 s = zdc_program_asciify();
6714 break;
6715 case DC_INST_PRINT_STREAM:
6716 dbg_exec("DC_INST_PRINT_STREAM:");
6717 s = zdc_program_printStream();
6718 break;
6719 case DC_INST_LOAD:
6720 case DC_INST_PUSH_VAR: {
6721 bool copy = inst == DC_INST_LOAD;
6722 s = zxc_program_pushVar(code, &ip->inst_idx, true, copy);
6723 break;
6724 }
6725 case DC_INST_PUSH_TO_VAR: {
6726 char *name = xc_program_name(code, &ip->inst_idx);
6727 s = zxc_program_popResultAndCopyToVar(name, true);
6728 free(name);
6729 break;
6730 }
6731 case DC_INST_QUIT:
6732 dbg_exec("DC_INST_QUIT:");
6733 if (G.prog.exestack.len <= 2)
6734 QUIT_OR_RETURN_TO_MAIN;
6735 bc_vec_npop(&G.prog.exestack, 2);
6736 goto read_updated_ip;
6737 case DC_INST_NQUIT:
6738 dbg_exec("DC_INST_NQUIT:");
6739 s = zdc_program_nquit();
6740 //goto read_updated_ip; - just fall through to it
6741#endif // ENABLE_DC
6742 read_updated_ip:
6743 // Instruction stack has changed, read new pointers
6744 ip = bc_vec_top(&G.prog.exestack);
6745 func = xc_program_func(ip->func);
6746 code = func->code.v;
6747 dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->inst_idx);
6748 }
6749
6750 if (s || G_interrupt) {
6751 xc_program_reset();
6752 RETURN_STATUS(s);
6753 }
6754
6755 fflush_and_check();
6756 }
6757
6758 RETURN_STATUS(BC_STATUS_SUCCESS);
6759}
6760#define zxc_program_exec(...) (zxc_program_exec(__VA_ARGS__) COMMA_SUCCESS)
6761
6762static unsigned xc_vm_envLen(const char *var)
6763{
6764 char *lenv;
6765 unsigned len;
6766
6767 lenv = getenv(var);
6768 len = BC_NUM_PRINT_WIDTH;
6769 if (!lenv) return len;
6770
6771 len = bb_strtou(lenv, NULL, 10) - 1;
6772 if (errno || len < 2 || len >= INT_MAX)
6773 len = BC_NUM_PRINT_WIDTH;
6774
6775 return len;
6776}
6777
6778static BC_STATUS zxc_vm_process(const char *text)
6779{
6780 BcStatus s;
6781
6782 dbg_lex_enter("%s:%d entered", __func__, __LINE__);
6783 s = zxc_parse_text_init(text); // does the first zxc_lex_next()
6784 if (s) RETURN_STATUS(s);
6785
6786 while (G.prs.lex != XC_LEX_EOF) {
6787 BcInstPtr *ip;
6788 BcFunc *f;
6789
6790 dbg_lex("%s:%d G.prs.lex:%d, parsing...", __func__, __LINE__, G.prs.lex);
6791 if (IS_BC) {
6792#if ENABLE_BC
6793 s = zbc_parse_stmt_or_funcdef();
6794 if (s) goto err;
6795
6796 // Check that next token is a correct stmt delimiter -
6797 // disallows "print 1 print 2" and such.
6798 if (G.prs.lex != BC_LEX_SCOLON
6799 && G.prs.lex != XC_LEX_NLINE
6800 && G.prs.lex != XC_LEX_EOF
6801 ) {
6802 bc_error_at("bad statement terminator");
6803 goto err;
6804 }
6805 // The above logic is fragile. Check these examples:
6806 // - interactive read() still works
6807#endif
6808 } else {
6809#if ENABLE_DC
6810 s = zdc_parse_expr();
6811#endif
6812 }
6813 if (s || G_interrupt) {
6814 err:
6815 xc_parse_reset(); // includes xc_program_reset()
6816 RETURN_STATUS(BC_STATUS_FAILURE);
6817 }
6818
6819 dbg_lex("%s:%d executing...", __func__, __LINE__);
6820 s = zxc_program_exec();
6821 if (s) {
6822 xc_program_reset();
6823 break;
6824 }
6825
6826 ip = (void*)G.prog.exestack.v;
6827#if SANITY_CHECKS
6828 if (G.prog.exestack.len != 1) // should have only main's IP
6829 bb_error_msg_and_die("BUG:call stack");
6830 if (ip->func != BC_PROG_MAIN)
6831 bb_error_msg_and_die("BUG:not MAIN");
6832#endif
6833 f = xc_program_func_BC_PROG_MAIN();
6834 // bc discards strings, constants and code after each
6835 // top-level statement in the "main program".
6836 // This prevents "yes 1 | bc" from growing its memory
6837 // without bound. This can be done because data stack
6838 // is empty and thus can't hold any references to
6839 // strings or constants, there is no generated code
6840 // which can hold references (after we discard one
6841 // we just executed). Code of functions can have references,
6842 // but bc stores function strings/constants in per-function
6843 // storage.
6844 if (IS_BC) {
6845#if SANITY_CHECKS
6846 if (G.prog.results.len != 0) // should be empty
6847 bb_error_msg_and_die("BUG:data stack");
6848#endif
6849 IF_BC(bc_vec_pop_all(&f->strs);)
6850 IF_BC(bc_vec_pop_all(&f->consts);)
6851 // We are at SCOLON/NLINE, skip it:
6852 s = zxc_lex_next();
6853 if (s) goto err;
6854 } else {
6855 if (G.prog.results.len == 0
6856 && G.prog.vars.len == 0
6857 ) {
6858 // If stack is empty and no registers exist (TODO: or they are all empty),
6859 // we can get rid of accumulated strings and constants.
6860 // In this example dc process should not grow
6861 // its memory consumption with time:
6862 // yes 1pc | dc
6863 IF_DC(bc_vec_pop_all(&G.prog.strs);)
6864 IF_DC(bc_vec_pop_all(&G.prog.consts);)
6865 }
6866 // The code is discarded always (below), thus this example
6867 // should also not grow its memory consumption with time,
6868 // even though its data stack is not empty:
6869 // { echo 1; yes dk; } | dc
6870 }
6871 // We drop generated and executed code for both bc and dc:
6872 bc_vec_pop_all(&f->code);
6873 ip->inst_idx = 0;
6874 }
6875
6876 dbg_lex_done("%s:%d done", __func__, __LINE__);
6877 RETURN_STATUS(s);
6878}
6879#define zxc_vm_process(...) (zxc_vm_process(__VA_ARGS__) COMMA_SUCCESS)
6880
6881static BC_STATUS zxc_vm_execute_FILE(FILE *fp, const char *filename)
6882{
6883 // So far bc/dc have no way to include a file from another file,
6884 // therefore we know G.prs.lex_filename == NULL on entry
6885 //const char *sv_file;
6886 BcStatus s;
6887
6888 G.prs.lex_filename = filename;
6889 G.prs.lex_input_fp = fp;
6890 G.err_line = G.prs.lex_line = 1;
6891 dbg_lex("p->lex_line reset to 1");
6892
6893 do {
6894 s = zxc_vm_process("");
6895 // We do not stop looping on errors here if reading stdin.
6896 // Example: start interactive bc and enter "return".
6897 // It should say "'return' not in a function"
6898 // but should not exit.
6899 } while (G.prs.lex_input_fp == stdin);
6900 G.prs.lex_filename = NULL;
6901 RETURN_STATUS(s);
6902}
6903#define zxc_vm_execute_FILE(...) (zxc_vm_execute_FILE(__VA_ARGS__) COMMA_SUCCESS)
6904
6905static BC_STATUS zxc_vm_file(const char *file)
6906{
6907 BcStatus s;
6908 FILE *fp;
6909
6910 fp = xfopen_for_read(file);
6911 s = zxc_vm_execute_FILE(fp, file);
6912 fclose(fp);
6913
6914 RETURN_STATUS(s);
6915}
6916#define zxc_vm_file(...) (zxc_vm_file(__VA_ARGS__) COMMA_SUCCESS)
6917
6918#if ENABLE_BC
6919static void bc_vm_info(void)
6920{
6921 printf("%s "BB_VER"\n"
6922 "Adapted from https://github.com/gavinhoward/bc\n"
6923 "Original code (c) 2018 Gavin D. Howard and contributors\n"
6924 , applet_name);
6925}
6926
6927static void bc_args(char **argv)
6928{
6929 unsigned opts;
6930 int i;
6931
6932 GETOPT_RESET();
6933#if ENABLE_FEATURE_BC_LONG_OPTIONS
6934 opts = option_mask32 |= getopt32long(argv, "wvsqli",
6935 "warn\0" No_argument "w"
6936 "version\0" No_argument "v"
6937 "standard\0" No_argument "s"
6938 "quiet\0" No_argument "q"
6939 "mathlib\0" No_argument "l"
6940 "interactive\0" No_argument "i"
6941 );
6942#else
6943 opts = option_mask32 |= getopt32(argv, "wvsqli");
6944#endif
6945 if (getenv("POSIXLY_CORRECT"))
6946 option_mask32 |= BC_FLAG_S;
6947
6948 if (opts & BC_FLAG_V) {
6949 bc_vm_info();
6950 exit(0);
6951 }
6952
6953 for (i = optind; argv[i]; ++i)
6954 bc_vec_push(&G.files, argv + i);
6955}
6956
6957static void bc_vm_envArgs(void)
6958{
6959 BcVec v;
6960 char *buf;
6961 char *env_args = getenv("BC_ENV_ARGS");
6962
6963 if (!env_args) return;
6964
6965 G.env_args = xstrdup(env_args);
6966 buf = G.env_args;
6967
6968 bc_vec_init(&v, sizeof(char *), NULL);
6969
6970 while (*(buf = skip_whitespace(buf)) != '\0') {
6971 bc_vec_push(&v, &buf);
6972 buf = skip_non_whitespace(buf);
6973 if (!*buf)
6974 break;
6975 *buf++ = '\0';
6976 }
6977
6978 // NULL terminate, and pass argv[] so that first arg is argv[1]
6979 if (sizeof(int) == sizeof(char*)) {
6980 bc_vec_push(&v, &const_int_0);
6981 } else {
6982 static char *const nullptr = NULL;
6983 bc_vec_push(&v, &nullptr);
6984 }
6985 bc_args(((char **)v.v) - 1);
6986
6987 bc_vec_free(&v);
6988}
6989
6990static const char bc_lib[] ALIGN1 = {
6991 "scale=20"
6992"\n" "define e(x){"
6993"\n" "auto b,s,n,r,d,i,p,f,v"
6994////////////////"if(x<0)return(1/e(-x))" // and drop 'n' and x<0 logic below
6995//^^^^^^^^^^^^^^^^ this would work, and is even more precise than GNU bc:
6996//e(-.998896): GNU:.36828580434569428695
6997// above code:.36828580434569428696
6998// actual value:.3682858043456942869594...
6999// but for now let's be "GNU compatible"
7000"\n" "b=ibase"
7001"\n" "ibase=A"
7002"\n" "if(x<0){"
7003"\n" "n=1"
7004"\n" "x=-x"
7005"\n" "}"
7006"\n" "s=scale"
7007"\n" "r=6+s+.44*x"
7008"\n" "scale=scale(x)+1"
7009"\n" "while(x>1){"
7010"\n" "d+=1"
7011"\n" "x/=2"
7012"\n" "scale+=1"
7013"\n" "}"
7014"\n" "scale=r"
7015"\n" "r=x+1"
7016"\n" "p=x"
7017"\n" "f=v=1"
7018"\n" "for(i=2;v;++i){"
7019"\n" "p*=x"
7020"\n" "f*=i"
7021"\n" "v=p/f"
7022"\n" "r+=v"
7023"\n" "}"
7024"\n" "while(d--)r*=r"
7025"\n" "scale=s"
7026"\n" "ibase=b"
7027"\n" "if(n)return(1/r)"
7028"\n" "return(r/1)"
7029"\n" "}"
7030"\n" "define l(x){"
7031"\n" "auto b,s,r,p,a,q,i,v"
7032"\n" "b=ibase"
7033"\n" "ibase=A"
7034"\n" "if(x<=0){"
7035"\n" "r=(1-10^scale)/1"
7036"\n" "ibase=b"
7037"\n" "return(r)"
7038"\n" "}"
7039"\n" "s=scale"
7040"\n" "scale+=6"
7041"\n" "p=2"
7042"\n" "while(x>=2){"
7043"\n" "p*=2"
7044"\n" "x=sqrt(x)"
7045"\n" "}"
7046"\n" "while(x<=.5){"
7047"\n" "p*=2"
7048"\n" "x=sqrt(x)"
7049"\n" "}"
7050"\n" "r=a=(x-1)/(x+1)"
7051"\n" "q=a*a"
7052"\n" "v=1"
7053"\n" "for(i=3;v;i+=2){"
7054"\n" "a*=q"
7055"\n" "v=a/i"
7056"\n" "r+=v"
7057"\n" "}"
7058"\n" "r*=p"
7059"\n" "scale=s"
7060"\n" "ibase=b"
7061"\n" "return(r/1)"
7062"\n" "}"
7063"\n" "define s(x){"
7064"\n" "auto b,s,r,a,q,i"
7065"\n" "if(x<0)return(-s(-x))"
7066"\n" "b=ibase"
7067"\n" "ibase=A"
7068"\n" "s=scale"
7069"\n" "scale=1.1*s+2"
7070"\n" "a=a(1)"
7071"\n" "scale=0"
7072"\n" "q=(x/a+2)/4"
7073"\n" "x-=4*q*a"
7074"\n" "if(q%2)x=-x"
7075"\n" "scale=s+2"
7076"\n" "r=a=x"
7077"\n" "q=-x*x"
7078"\n" "for(i=3;a;i+=2){"
7079"\n" "a*=q/(i*(i-1))"
7080"\n" "r+=a"
7081"\n" "}"
7082"\n" "scale=s"
7083"\n" "ibase=b"
7084"\n" "return(r/1)"
7085"\n" "}"
7086"\n" "define c(x){"
7087"\n" "auto b,s"
7088"\n" "b=ibase"
7089"\n" "ibase=A"
7090"\n" "s=scale"
7091"\n" "scale*=1.2"
7092"\n" "x=s(2*a(1)+x)"
7093"\n" "scale=s"
7094"\n" "ibase=b"
7095"\n" "return(x/1)"
7096"\n" "}"
7097"\n" "define a(x){"
7098"\n" "auto b,s,r,n,a,m,t,f,i,u"
7099"\n" "b=ibase"
7100"\n" "ibase=A"
7101"\n" "n=1"
7102"\n" "if(x<0){"
7103"\n" "n=-1"
7104"\n" "x=-x"
7105"\n" "}"
7106"\n" "if(scale<65){"
7107"\n" "if(x==1)return(.7853981633974483096156608458198757210492923498437764552437361480/n)"
7108"\n" "if(x==.2)return(.1973955598498807583700497651947902934475851037878521015176889402/n)"
7109"\n" "}"
7110"\n" "s=scale"
7111"\n" "if(x>.2){"
7112"\n" "scale+=5"
7113"\n" "a=a(.2)"
7114"\n" "}"
7115"\n" "scale=s+3"
7116"\n" "while(x>.2){"
7117"\n" "m+=1"
7118"\n" "x=(x-.2)/(1+.2*x)"
7119"\n" "}"
7120"\n" "r=u=x"
7121"\n" "f=-x*x"
7122"\n" "t=1"
7123"\n" "for(i=3;t;i+=2){"
7124"\n" "u*=f"
7125"\n" "t=u/i"
7126"\n" "r+=t"
7127"\n" "}"
7128"\n" "scale=s"
7129"\n" "ibase=b"
7130"\n" "return((m*a+r)/n)"
7131"\n" "}"
7132"\n" "define j(n,x){"
7133"\n" "auto b,s,o,a,i,v,f"
7134"\n" "b=ibase"
7135"\n" "ibase=A"
7136"\n" "s=scale"
7137"\n" "scale=0"
7138"\n" "n/=1"
7139"\n" "if(n<0){"
7140"\n" "n=-n"
7141"\n" "o=n%2"
7142"\n" "}"
7143"\n" "a=1"
7144"\n" "for(i=2;i<=n;++i)a*=i"
7145"\n" "scale=1.5*s"
7146"\n" "a=(x^n)/2^n/a"
7147"\n" "r=v=1"
7148"\n" "f=-x*x/4"
7149"\n" "scale+=length(a)-scale(a)"
7150"\n" "for(i=1;v;++i){"
7151"\n" "v=v*f/i/(n+i)"
7152"\n" "r+=v"
7153"\n" "}"
7154"\n" "scale=s"
7155"\n" "ibase=b"
7156"\n" "if(o)a=-a"
7157"\n" "return(a*r/1)"
7158"\n" "}"
7159};
7160#endif // ENABLE_BC
7161
7162static BC_STATUS zxc_vm_exec(void)
7163{
7164 char **fname;
7165 BcStatus s;
7166 size_t i;
7167
7168#if ENABLE_BC
7169 if (option_mask32 & BC_FLAG_L) {
7170 // We know that internal library is not buggy,
7171 // thus error checking is normally disabled.
7172# define DEBUG_LIB 0
7173 s = zxc_vm_process(bc_lib);
7174 if (DEBUG_LIB && s) RETURN_STATUS(s);
7175 }
7176#endif
7177
7178 s = BC_STATUS_SUCCESS;
7179 fname = (void*)G.files.v;
7180 for (i = 0; i < G.files.len; i++) {
7181 s = zxc_vm_file(*fname++);
7182 if (ENABLE_FEATURE_CLEAN_UP && !G_ttyin && s) {
7183 // Debug config, non-interactive mode:
7184 // return all the way back to main.
7185 // Non-debug builds do not come here
7186 // in non-interactive mode, they exit.
7187 RETURN_STATUS(s);
7188 }
7189 }
7190
7191 if (IS_BC || (option_mask32 & BC_FLAG_I))
7192 s = zxc_vm_execute_FILE(stdin, /*filename:*/ NULL);
7193
7194 RETURN_STATUS(s);
7195}
7196#define zxc_vm_exec(...) (zxc_vm_exec(__VA_ARGS__) COMMA_SUCCESS)
7197
7198#if ENABLE_FEATURE_CLEAN_UP
7199static void xc_program_free(void)
7200{
7201 bc_vec_free(&G.prog.fns);
7202 IF_BC(bc_vec_free(&G.prog.fn_map);)
7203 bc_vec_free(&G.prog.vars);
7204 bc_vec_free(&G.prog.var_map);
7205 bc_vec_free(&G.prog.arrs);
7206 bc_vec_free(&G.prog.arr_map);
7207 IF_DC(bc_vec_free(&G.prog.strs);)
7208 IF_DC(bc_vec_free(&G.prog.consts);)
7209 bc_vec_free(&G.prog.results);
7210 bc_vec_free(&G.prog.exestack);
7211 IF_BC(bc_num_free(&G.prog.last);)
7212 //IF_BC(bc_num_free(&G.prog.zero);)
7213 IF_BC(bc_num_free(&G.prog.one);)
7214 bc_vec_free(&G.input_buffer);
7215}
7216#endif
7217
7218static void xc_program_init(void)
7219{
7220 BcInstPtr ip;
7221
7222 // memset(&G.prog, 0, sizeof(G.prog)); - already is
7223 memset(&ip, 0, sizeof(BcInstPtr));
7224
7225 // G.prog.nchars = G.prog.scale = 0; - already is
7226 G.prog.ib_t = 10;
7227 G.prog.ob_t = 10;
7228
7229 IF_BC(bc_num_init_DEF_SIZE(&G.prog.last);)
7230 //IF_BC(bc_num_zero(&G.prog.last);) - already is
7231
7232 //bc_num_init_DEF_SIZE(&G.prog.zero); - not needed
7233 //bc_num_zero(&G.prog.zero); - already is
7234
7235 IF_BC(bc_num_init_DEF_SIZE(&G.prog.one);)
7236 IF_BC(bc_num_one(&G.prog.one);)
7237
7238 bc_vec_init(&G.prog.fns, sizeof(BcFunc), bc_func_free);
7239 IF_BC(bc_vec_init(&G.prog.fn_map, sizeof(BcId), bc_id_free);)
7240
7241 if (IS_BC) {
7242 // Names are chosen simply to be distinct and never match
7243 // a valid function name (and be short)
7244 IF_BC(bc_program_addFunc(xstrdup(""))); // func #0: main
7245 IF_BC(bc_program_addFunc(xstrdup("1"))); // func #1: for read()
7246 } else {
7247 // in dc, functions have no names
7248 xc_program_add_fn();
7249 xc_program_add_fn();
7250 }
7251
7252 bc_vec_init(&G.prog.vars, sizeof(BcVec), bc_vec_free);
7253 bc_vec_init(&G.prog.var_map, sizeof(BcId), bc_id_free);
7254
7255 bc_vec_init(&G.prog.arrs, sizeof(BcVec), bc_vec_free);
7256 bc_vec_init(&G.prog.arr_map, sizeof(BcId), bc_id_free);
7257
7258 IF_DC(bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free);)
7259 IF_DC(bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free);)
7260 bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free);
7261 bc_vec_init(&G.prog.exestack, sizeof(BcInstPtr), NULL);
7262 bc_vec_push(&G.prog.exestack, &ip);
7263
7264 bc_char_vec_init(&G.input_buffer);
7265}
7266
7267static int xc_vm_init(const char *env_len)
7268{
7269 G.prog.len = xc_vm_envLen(env_len);
7270#if ENABLE_FEATURE_EDITING
7271 G.line_input_state = new_line_input_t(DO_HISTORY);
7272#endif
7273 bc_vec_init(&G.files, sizeof(char *), NULL);
7274
7275 xc_program_init();
7276 IF_BC(if (IS_BC) bc_vm_envArgs();)
7277 xc_parse_create(BC_PROG_MAIN);
7278
7279//TODO: in GNU bc, the check is (isatty(0) && isatty(1)),
7280//-i option unconditionally enables this regardless of isatty():
7281 if (isatty(0)) {
7282#if ENABLE_FEATURE_BC_INTERACTIVE
7283 G_ttyin = 1;
7284 // With SA_RESTART, most system calls will restart
7285 // (IOW: they won't fail with EINTR).
7286 // In particular, this means ^C won't cause
7287 // stdout to get into "error state" if SIGINT hits
7288 // within write() syscall.
7289 //
7290 // The downside is that ^C while tty input is taken
7291 // will only be handled after [Enter] since read()
7292 // from stdin is not interrupted by ^C either,
7293 // it restarts, thus fgetc() does not return on ^C.
7294 // (This problem manifests only if line editing is disabled)
7295 signal_SA_RESTART_empty_mask(SIGINT, record_signo);
7296
7297 // Without SA_RESTART, this exhibits a bug:
7298 // "while (1) print 1" and try ^C-ing it.
7299 // Intermittently, instead of returning to input line,
7300 // you'll get "output error: Interrupted system call"
7301 // and exit.
7302 //signal_no_SA_RESTART_empty_mask(SIGINT, record_signo);
7303#endif
7304 return 1; // "tty"
7305 }
7306 return 0; // "not a tty"
7307}
7308
7309static BcStatus xc_vm_run(void)
7310{
7311 BcStatus st = zxc_vm_exec();
7312#if ENABLE_FEATURE_CLEAN_UP
7313 if (G_exiting) // it was actually "halt" or "quit"
7314 st = EXIT_SUCCESS;
7315
7316 bc_vec_free(&G.files);
7317 xc_program_free();
7318 xc_parse_free();
7319 free(G.env_args);
7320# if ENABLE_FEATURE_EDITING
7321 free_line_input_t(G.line_input_state);
7322# endif
7323 FREE_G();
7324#endif
7325 dbg_exec("exiting with exitcode %d", st);
7326 return st;
7327}
7328
7329#if ENABLE_BC
7330int bc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
7331int bc_main(int argc UNUSED_PARAM, char **argv)
7332{
7333 int is_tty;
7334
7335 INIT_G();
7336
7337 is_tty = xc_vm_init("BC_LINE_LENGTH");
7338
7339 bc_args(argv);
7340
7341 if (is_tty && !(option_mask32 & BC_FLAG_Q))
7342 bc_vm_info();
7343
7344 return xc_vm_run();
7345}
7346#endif
7347
7348#if ENABLE_DC
7349int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
7350int dc_main(int argc UNUSED_PARAM, char **argv)
7351{
7352 int noscript;
7353
7354 INIT_G();
7355
7356 // TODO: dc (GNU bc 1.07.1) 1.4.1 seems to use width
7357 // 1 char wider than bc from the same package.
7358 // Both default width, and xC_LINE_LENGTH=N are wider:
7359 // "DC_LINE_LENGTH=5 dc -e'123456 p'" prints:
7360 // |1234\ |
7361 // |56 |
7362 // "echo '123456' | BC_LINE_LENGTH=5 bc" prints:
7363 // |123\ |
7364 // |456 |
7365 // Do the same, or it's a bug?
7366 xc_vm_init("DC_LINE_LENGTH");
7367
7368 // Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs
7369 noscript = BC_FLAG_I;
7370 for (;;) {
7371 int n = getopt(argc, argv, "e:f:x");
7372 if (n <= 0)
7373 break;
7374 switch (n) {
7375 case 'e':
7376 noscript = 0;
7377 n = zxc_vm_process(optarg);
7378 if (n) return n;
7379 break;
7380 case 'f':
7381 noscript = 0;
7382 n = zxc_vm_file(optarg);
7383 if (n) return n;
7384 break;
7385 case 'x':
7386 option_mask32 |= DC_FLAG_X;
7387 break;
7388 default:
7389 bb_show_usage();
7390 }
7391 }
7392 argv += optind;
7393
7394 while (*argv) {
7395 noscript = 0;
7396 bc_vec_push(&G.files, argv++);
7397 }
7398
7399 option_mask32 |= noscript; // set BC_FLAG_I if we need to interpret stdin
7400
7401 return xc_vm_run();
7402}
7403#endif
7404
7405#endif // DC_BIG
diff --git a/miscutils/beep.c b/miscutils/beep.c
index 0c8a8225e..92faa1cd5 100644
--- a/miscutils/beep.c
+++ b/miscutils/beep.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config BEEP 9//config:config BEEP
10//config: bool "beep (3 kb)" 10//config: bool "beep (2.4 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/miscutils/chat.c b/miscutils/chat.c
index 2dfe52c4f..5183d1369 100644
--- a/miscutils/chat.c
+++ b/miscutils/chat.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10//config:config CHAT 10//config:config CHAT
11//config: bool "chat (6.6 kb)" 11//config: bool "chat (6.3 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: Simple chat utility. 14//config: Simple chat utility.
diff --git a/miscutils/crond.c b/miscutils/crond.c
index f6580a9d4..2e36c406b 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config CROND 11//config:config CROND
12//config: bool "crond (13 kb)" 12//config: bool "crond (14 kb)"
13//config: default y 13//config: default y
14//config: select FEATURE_SYSLOG 14//config: select FEATURE_SYSLOG
15//config: help 15//config: help
diff --git a/miscutils/crontab.c b/miscutils/crontab.c
index 4787fa08f..96dc4741a 100644
--- a/miscutils/crontab.c
+++ b/miscutils/crontab.c
@@ -10,7 +10,7 @@
10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 10 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
11 */ 11 */
12//config:config CRONTAB 12//config:config CRONTAB
13//config: bool "crontab (9.7 kb)" 13//config: bool "crontab (10 kb)"
14//config: default y 14//config: default y
15//config: help 15//config: help
16//config: Crontab manipulates the crontab for a particular user. Only 16//config: Crontab manipulates the crontab for a particular user. Only
diff --git a/miscutils/dc.c b/miscutils/dc.c
index f752a1377..0d09f5e2b 100644
--- a/miscutils/dc.c
+++ b/miscutils/dc.c
@@ -2,50 +2,11 @@
2/* 2/*
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4 */ 4 */
5//config:config DC 5
6//config: bool "dc (4.2 kb)" 6/* config/applet/usage bits are in bc.c */
7//config: default y 7
8//config: help 8//#include "libbb.h"
9//config: Dc is a reverse-polish desk calculator which supports unlimited 9//#include "common_bufsiz.h"
10//config: precision arithmetic.
11//config:
12//config:config FEATURE_DC_LIBM
13//config: bool "Enable power and exp functions (requires libm)"
14//config: default y
15//config: depends on DC
16//config: help
17//config: Enable power and exp functions.
18//config: NOTE: This will require libm to be present for linking.
19
20//applet:IF_DC(APPLET(dc, BB_DIR_USR_BIN, BB_SUID_DROP))
21
22//kbuild:lib-$(CONFIG_DC) += dc.o
23
24//usage:#define dc_trivial_usage
25//usage: "EXPRESSION..."
26//usage:
27//usage:#define dc_full_usage "\n\n"
28//usage: "Tiny RPN calculator. Operations:\n"
29//usage: "+, add, -, sub, *, mul, /, div, %, mod, "IF_FEATURE_DC_LIBM("**, exp, ")"and, or, not, xor,\n"
30//usage: "p - print top of the stack (without popping),\n"
31//usage: "f - print entire stack,\n"
32//usage: "o - pop the value and set output radix (must be 10, 16, 8 or 2).\n"
33//usage: "Examples: 'dc 2 2 add p' -> 4, 'dc 8 8 mul 2 2 + / p' -> 16"
34//usage:
35//usage:#define dc_example_usage
36//usage: "$ dc 2 2 + p\n"
37//usage: "4\n"
38//usage: "$ dc 8 8 \\* 2 2 + / p\n"
39//usage: "16\n"
40//usage: "$ dc 0 1 and p\n"
41//usage: "0\n"
42//usage: "$ dc 0 1 or p\n"
43//usage: "1\n"
44//usage: "$ echo 72 9 div 8 mul p | dc\n"
45//usage: "64\n"
46
47#include "libbb.h"
48#include "common_bufsiz.h"
49#include <math.h> 10#include <math.h>
50 11
51#if 0 12#if 0
@@ -59,7 +20,6 @@ typedef unsigned long long data_t;
59#define DATA_FMT LL_FMT 20#define DATA_FMT LL_FMT
60#endif 21#endif
61 22
62
63struct globals { 23struct globals {
64 unsigned pointer; 24 unsigned pointer;
65 unsigned base; 25 unsigned base;
@@ -75,7 +35,6 @@ enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(
75 base = 10; \ 35 base = 10; \
76} while (0) 36} while (0)
77 37
78
79static void check_under(void) 38static void check_under(void)
80{ 39{
81 if (pointer == 0) 40 if (pointer == 0)
@@ -223,25 +182,25 @@ struct op {
223 182
224static const struct op operators[] = { 183static const struct op operators[] = {
225#if ENABLE_FEATURE_DC_LIBM 184#if ENABLE_FEATURE_DC_LIBM
226 {"**", power}, 185 {"^", power},
227 {"exp", power}, 186// {"exp", power},
228 {"pow", power}, 187// {"pow", power},
229#endif 188#endif
230 {"%", mod}, 189 {"%", mod},
231 {"mod", mod}, 190// {"mod", mod},
191 // logic ops are not standard, remove?
232 {"and", and}, 192 {"and", and},
233 {"or", or}, 193 {"or", or},
234 {"not", not}, 194 {"not", not},
235 {"eor", eor},
236 {"xor", eor}, 195 {"xor", eor},
237 {"+", add}, 196 {"+", add},
238 {"add", add}, 197// {"add", add},
239 {"-", sub}, 198 {"-", sub},
240 {"sub", sub}, 199// {"sub", sub},
241 {"*", mul}, 200 {"*", mul},
242 {"mul", mul}, 201// {"mul", mul},
243 {"/", divide}, 202 {"/", divide},
244 {"div", divide}, 203// {"div", divide},
245 {"p", print_no_pop}, 204 {"p", print_no_pop},
246 {"f", print_stack_no_pop}, 205 {"f", print_stack_no_pop},
247 {"o", set_output_base}, 206 {"o", set_output_base},
@@ -282,23 +241,50 @@ static void stack_machine(const char *argument)
282 bb_error_msg_and_die("syntax error at '%s'", argument); 241 bb_error_msg_and_die("syntax error at '%s'", argument);
283} 242}
284 243
244static void process_file(FILE *fp)
245{
246 char *line;
247 while ((line = xmalloc_fgetline(fp)) != NULL) {
248 stack_machine(line);
249 free(line);
250 }
251}
252
285int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 253int dc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
286int dc_main(int argc UNUSED_PARAM, char **argv) 254int dc_main(int argc UNUSED_PARAM, char **argv)
287{ 255{
256 bool script = 0;
257
288 INIT_G(); 258 INIT_G();
289 259
290 argv++; 260 /* Run -e'SCRIPT' and -fFILE in order of appearance, then handle FILEs */
291 if (!argv[0]) { 261 for (;;) {
292 /* take stuff from stdin if no args are given */ 262 int n = getopt(argc, argv, "e:f:");
293 char *line; 263 if (n <= 0)
294 while ((line = xmalloc_fgetline(stdin)) != NULL) { 264 break;
295 stack_machine(line); 265 switch (n) {
296 free(line); 266 case 'e':
267 script = 1;
268 stack_machine(optarg);
269 break;
270 case 'f':
271 script = 1;
272 process_file(xfopen_for_read(optarg));
273 break;
274 default:
275 bb_show_usage();
297 } 276 }
298 } else {
299 do {
300 stack_machine(*argv);
301 } while (*++argv);
302 } 277 }
278 argv += optind;
279
280 if (*argv) {
281 do
282 process_file(xfopen_for_read(*argv++));
283 while (*argv);
284 } else if (!script) {
285 /* Take stuff from stdin if no args are given */
286 process_file(stdin);
287 }
288
303 return EXIT_SUCCESS; 289 return EXIT_SUCCESS;
304} 290}
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c
index 814714f53..3bf06b965 100644
--- a/miscutils/devfsd.c
+++ b/miscutils/devfsd.c
@@ -694,7 +694,7 @@ static void process_config_line(const char *line, unsigned long *event_mask)
694 return; 694 return;
695 695
696 process_config_line_err: 696 process_config_line_err:
697 msg_logger_and_die(LOG_ERR, bb_msg_bad_config, msg , line); 697 msg_logger_and_die(LOG_ERR, bb_msg_bad_config, msg, line);
698} /* End Function process_config_line */ 698} /* End Function process_config_line */
699 699
700static int do_servicing(int fd, unsigned long event_mask) 700static int do_servicing(int fd, unsigned long event_mask)
diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c
index bc3c61055..bba22d6d1 100644
--- a/miscutils/fbsplash.c
+++ b/miscutils/fbsplash.c
@@ -21,7 +21,7 @@
21 * "exit" (or just close fifo) - well you guessed it. 21 * "exit" (or just close fifo) - well you guessed it.
22 */ 22 */
23//config:config FBSPLASH 23//config:config FBSPLASH
24//config: bool "fbsplash (27 kb)" 24//config: bool "fbsplash (26 kb)"
25//config: default y 25//config: default y
26//config: select PLATFORM_LINUX 26//config: select PLATFORM_LINUX
27//config: help 27//config: help
diff --git a/miscutils/flash_eraseall.c b/miscutils/flash_eraseall.c
index 8e93060ca..a3dabdadb 100644
--- a/miscutils/flash_eraseall.c
+++ b/miscutils/flash_eraseall.c
@@ -11,7 +11,7 @@
11 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 11 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
12 */ 12 */
13//config:config FLASH_ERASEALL 13//config:config FLASH_ERASEALL
14//config: bool "flash_eraseall (5.5 kb)" 14//config: bool "flash_eraseall (5.9 kb)"
15//config: default n # doesn't build on Ubuntu 8.04 15//config: default n # doesn't build on Ubuntu 8.04
16//config: help 16//config: help
17//config: The flash_eraseall binary from mtd-utils as of git head c4c6a59eb. 17//config: The flash_eraseall binary from mtd-utils as of git head c4c6a59eb.
diff --git a/miscutils/flashcp.c b/miscutils/flashcp.c
index 858cee194..1ca9d158d 100644
--- a/miscutils/flashcp.c
+++ b/miscutils/flashcp.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config FLASHCP 9//config:config FLASHCP
10//config: bool "flashcp (5.4 kb)" 10//config: bool "flashcp (5.3 kb)"
11//config: default n # doesn't build on Ubuntu 8.04 11//config: default n # doesn't build on Ubuntu 8.04
12//config: help 12//config: help
13//config: The flashcp binary, inspired by mtd-utils as of git head 5eceb74f7. 13//config: The flashcp binary, inspired by mtd-utils as of git head 5eceb74f7.
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c
index 0bbe6ca10..342e240fa 100644
--- a/miscutils/hdparm.c
+++ b/miscutils/hdparm.c
@@ -12,7 +12,7 @@
12 * - by Mark Lord (C) 1994-2002 -- freely distributable 12 * - by Mark Lord (C) 1994-2002 -- freely distributable
13 */ 13 */
14//config:config HDPARM 14//config:config HDPARM
15//config: bool "hdparm (23 kb)" 15//config: bool "hdparm (25 kb)"
16//config: default y 16//config: default y
17//config: select PLATFORM_LINUX 17//config: select PLATFORM_LINUX
18//config: help 18//config: help
diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c
index 298eb8149..5c2f4a555 100644
--- a/miscutils/hexedit.c
+++ b/miscutils/hexedit.c
@@ -4,7 +4,7 @@
4 * Licensed under GPLv2, see file LICENSE in this source tree. 4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */ 5 */
6//config:config HEXEDIT 6//config:config HEXEDIT
7//config: bool "hexedit (20 kb)" 7//config: bool "hexedit (21 kb)"
8//config: default y 8//config: default y
9//config: help 9//config: help
10//config: Edit file in hexadecimal. 10//config: Edit file in hexadecimal.
diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c
index 6a2134063..610fed5d6 100644
--- a/miscutils/i2c_tools.c
+++ b/miscutils/i2c_tools.c
@@ -9,28 +9,28 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config I2CGET 11//config:config I2CGET
12//config: bool "i2cget (5.6 kb)" 12//config: bool "i2cget (5.5 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX 14//config: select PLATFORM_LINUX
15//config: help 15//config: help
16//config: Read from I2C/SMBus chip registers. 16//config: Read from I2C/SMBus chip registers.
17//config: 17//config:
18//config:config I2CSET 18//config:config I2CSET
19//config: bool "i2cset (6.9 kb)" 19//config: bool "i2cset (6.7 kb)"
20//config: default y 20//config: default y
21//config: select PLATFORM_LINUX 21//config: select PLATFORM_LINUX
22//config: help 22//config: help
23//config: Set I2C registers. 23//config: Set I2C registers.
24//config: 24//config:
25//config:config I2CDUMP 25//config:config I2CDUMP
26//config: bool "i2cdump (7.2 kb)" 26//config: bool "i2cdump (7.1 kb)"
27//config: default y 27//config: default y
28//config: select PLATFORM_LINUX 28//config: select PLATFORM_LINUX
29//config: help 29//config: help
30//config: Examine I2C registers. 30//config: Examine I2C registers.
31//config: 31//config:
32//config:config I2CDETECT 32//config:config I2CDETECT
33//config: bool "i2cdetect (7.2 kb)" 33//config: bool "i2cdetect (7.1 kb)"
34//config: default y 34//config: default y
35//config: select PLATFORM_LINUX 35//config: select PLATFORM_LINUX
36//config: help 36//config: help
diff --git a/miscutils/inotifyd.c b/miscutils/inotifyd.c
index 0060797ed..ec0321941 100644
--- a/miscutils/inotifyd.c
+++ b/miscutils/inotifyd.c
@@ -27,7 +27,7 @@
27 * See below for mask names explanation. 27 * See below for mask names explanation.
28 */ 28 */
29//config:config INOTIFYD 29//config:config INOTIFYD
30//config: bool "inotifyd (3.5 kb)" 30//config: bool "inotifyd (3.6 kb)"
31//config: default n # doesn't build on Knoppix 5 31//config: default n # doesn't build on Knoppix 5
32//config: help 32//config: help
33//config: Simple inotify daemon. Reports filesystem changes. Requires 33//config: Simple inotify daemon. Reports filesystem changes. Requires
diff --git a/miscutils/less.c b/miscutils/less.c
index 6b5c8c2dd..ad23b7d0d 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -20,7 +20,7 @@
20 * redirected input has been read from stdin 20 * redirected input has been read from stdin
21 */ 21 */
22//config:config LESS 22//config:config LESS
23//config: bool "less (15 kb)" 23//config: bool "less (16 kb)"
24//config: default y 24//config: default y
25//config: help 25//config: help
26//config: 'less' is a pager, meaning that it displays text files. It possesses 26//config: 'less' is a pager, meaning that it displays text files. It possesses
diff --git a/miscutils/lsscsi.c b/miscutils/lsscsi.c
index 0aaa01ded..f737d33d9 100644
--- a/miscutils/lsscsi.c
+++ b/miscutils/lsscsi.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LSSCSI 9//config:config LSSCSI
10//config: bool "lsscsi (2.4 kb)" 10//config: bool "lsscsi (2.5 kb)"
11//config: default y 11//config: default y
12//config: #select PLATFORM_LINUX 12//config: #select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c
index 80975c652..93c550042 100644
--- a/miscutils/makedevs.c
+++ b/miscutils/makedevs.c
@@ -7,7 +7,7 @@
7 * known bugs: can't deal with alpha ranges 7 * known bugs: can't deal with alpha ranges
8 */ 8 */
9//config:config MAKEDEVS 9//config:config MAKEDEVS
10//config: bool "makedevs (9.3 kb)" 10//config: bool "makedevs (9.2 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: 'makedevs' is a utility used to create a batch of devices with 13//config: 'makedevs' is a utility used to create a batch of devices with
diff --git a/miscutils/man.c b/miscutils/man.c
index 4ff58a9a0..fd5d90c1a 100644
--- a/miscutils/man.c
+++ b/miscutils/man.c
@@ -3,7 +3,7 @@
3 * Licensed under GPLv2, see file LICENSE in this source tree. 3 * Licensed under GPLv2, see file LICENSE in this source tree.
4 */ 4 */
5//config:config MAN 5//config:config MAN
6//config: bool "man (27 kb)" 6//config: bool "man (26 kb)"
7//config: default y 7//config: default y
8//config: help 8//config: help
9//config: Format and display manual pages. 9//config: Format and display manual pages.
diff --git a/miscutils/microcom.c b/miscutils/microcom.c
index fa090057e..399d4cf7f 100644
--- a/miscutils/microcom.c
+++ b/miscutils/microcom.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10//config:config MICROCOM 10//config:config MICROCOM
11//config: bool "microcom (5.6 kb)" 11//config: bool "microcom (5.7 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: The poor man's minicom utility for chatting with serial port devices. 14//config: The poor man's minicom utility for chatting with serial port devices.
diff --git a/miscutils/mt.c b/miscutils/mt.c
index fad656e95..9f1aecfca 100644
--- a/miscutils/mt.c
+++ b/miscutils/mt.c
@@ -3,7 +3,7 @@
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4 */ 4 */
5//config:config MT 5//config:config MT
6//config: bool "mt (2.6 kb)" 6//config: bool "mt (2.5 kb)"
7//config: default y 7//config: default y
8//config: help 8//config: help
9//config: mt is used to control tape devices. You can use the mt utility 9//config: mt is used to control tape devices. You can use the mt utility
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c
index 29c800612..09bcaaf63 100644
--- a/miscutils/nandwrite.c
+++ b/miscutils/nandwrite.c
@@ -8,14 +8,14 @@
8 * TODO: add support for large (>4GB) MTD devices 8 * TODO: add support for large (>4GB) MTD devices
9 */ 9 */
10//config:config NANDWRITE 10//config:config NANDWRITE
11//config: bool "nandwrite (5.9 kb)" 11//config: bool "nandwrite (4.8 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
15//config: Write to the specified MTD device, with bad blocks awareness 15//config: Write to the specified MTD device, with bad blocks awareness
16//config: 16//config:
17//config:config NANDDUMP 17//config:config NANDDUMP
18//config: bool "nanddump (6.3 kb)" 18//config: bool "nanddump (5.2 kb)"
19//config: default y 19//config: default y
20//config: select PLATFORM_LINUX 20//config: select PLATFORM_LINUX
21//config: help 21//config: help
diff --git a/miscutils/partprobe.c b/miscutils/partprobe.c
index d1ae27348..0abed6ff1 100644
--- a/miscutils/partprobe.c
+++ b/miscutils/partprobe.c
@@ -5,7 +5,7 @@
5 * Licensed under GPLv2, see file LICENSE in this source tree. 5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */ 6 */
7//config:config PARTPROBE 7//config:config PARTPROBE
8//config: bool "partprobe (3.6 kb)" 8//config: bool "partprobe (3.5 kb)"
9//config: default y 9//config: default y
10//config: select PLATFORM_LINUX 10//config: select PLATFORM_LINUX
11//config: help 11//config: help
diff --git a/miscutils/raidautorun.c b/miscutils/raidautorun.c
index d315c2734..39816ab1f 100644
--- a/miscutils/raidautorun.c
+++ b/miscutils/raidautorun.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config RAIDAUTORUN 9//config:config RAIDAUTORUN
10//config: bool "raidautorun (1.4 kb)" 10//config: bool "raidautorun (1.3 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/miscutils/readahead.c b/miscutils/readahead.c
index 972302a18..cc0ba5ba3 100644
--- a/miscutils/readahead.c
+++ b/miscutils/readahead.c
@@ -10,7 +10,7 @@
10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 10 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
11 */ 11 */
12//config:config READAHEAD 12//config:config READAHEAD
13//config: bool "readahead (2 kb)" 13//config: bool "readahead (1.5 kb)"
14//config: default y 14//config: default y
15//config: depends on LFS 15//config: depends on LFS
16//config: select PLATFORM_LINUX 16//config: select PLATFORM_LINUX
diff --git a/miscutils/rfkill.c b/miscutils/rfkill.c
index ae38c182d..766bad8c7 100644
--- a/miscutils/rfkill.c
+++ b/miscutils/rfkill.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config RFKILL 9//config:config RFKILL
10//config: bool "rfkill (5.3 kb)" 10//config: bool "rfkill (4.4 kb)"
11//config: default n # doesn't build on Ubuntu 9.04 11//config: default n # doesn't build on Ubuntu 9.04
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/miscutils/runlevel.c b/miscutils/runlevel.c
index 0b2098564..2f1581ead 100644
--- a/miscutils/runlevel.c
+++ b/miscutils/runlevel.c
@@ -12,11 +12,11 @@
12 * initially busyboxified by Bernhard Reutner-Fischer 12 * initially busyboxified by Bernhard Reutner-Fischer
13 */ 13 */
14//config:config RUNLEVEL 14//config:config RUNLEVEL
15//config: bool "runlevel (518 bytes)" 15//config: bool "runlevel (559 bytes)"
16//config: default y 16//config: default y
17//config: depends on FEATURE_UTMP 17//config: depends on FEATURE_UTMP
18//config: help 18//config: help
19//config: find the current and previous system runlevel. 19//config: Find the current and previous system runlevel.
20//config: 20//config:
21//config: This applet uses utmp but does not rely on busybox supporing 21//config: This applet uses utmp but does not rely on busybox supporing
22//config: utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc. 22//config: utmp on purpose. It is used by e.g. emdebian via /etc/init.d/rc.
diff --git a/miscutils/setfattr.c b/miscutils/setfattr.c
index 12eebc56e..9792c2660 100644
--- a/miscutils/setfattr.c
+++ b/miscutils/setfattr.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2, see file LICENSE in this source tree. 6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */ 7 */
8//config:config SETFATTR 8//config:config SETFATTR
9//config: bool "setfattr (3.6 kb)" 9//config: bool "setfattr (3.7 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: Set/delete extended attributes on files 12//config: Set/delete extended attributes on files
diff --git a/miscutils/setserial.c b/miscutils/setserial.c
index fd88ed106..71b274568 100644
--- a/miscutils/setserial.c
+++ b/miscutils/setserial.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config SETSERIAL 10//config:config SETSERIAL
11//config: bool "setserial (6.6 kb)" 11//config: bool "setserial (6.9 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/miscutils/strings.c b/miscutils/strings.c
index ccb05f6d4..51412f401 100644
--- a/miscutils/strings.c
+++ b/miscutils/strings.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config STRINGS 9//config:config STRINGS
10//config: bool "strings (4.3 kb)" 10//config: bool "strings (4.6 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: strings prints the printable character sequences for each file 13//config: strings prints the printable character sequences for each file
diff --git a/miscutils/time.c b/miscutils/time.c
index 7d6a7a29f..064888ab8 100644
--- a/miscutils/time.c
+++ b/miscutils/time.c
@@ -10,7 +10,7 @@
10 * Heavily modified for busybox by Erik Andersen <andersen@codepoet.org> 10 * Heavily modified for busybox by Erik Andersen <andersen@codepoet.org>
11 */ 11 */
12//config:config TIME 12//config:config TIME
13//config: bool "time (7 kb)" 13//config: bool "time (6.8 kb)"
14//config: default y 14//config: default y
15//config: help 15//config: help
16//config: The time command runs the specified program with the given arguments. 16//config: The time command runs the specified program with the given arguments.
diff --git a/miscutils/ttysize.c b/miscutils/ttysize.c
index 2c2d4ec33..d635b29ce 100644
--- a/miscutils/ttysize.c
+++ b/miscutils/ttysize.c
@@ -10,7 +10,7 @@
10 * Licensed under GPLv2, see file LICENSE in this source tree. 10 * Licensed under GPLv2, see file LICENSE in this source tree.
11 */ 11 */
12//config:config TTYSIZE 12//config:config TTYSIZE
13//config: bool "ttysize (372 bytes)" 13//config: bool "ttysize (432 bytes)"
14//config: default y 14//config: default y
15//config: help 15//config: help
16//config: A replacement for "stty size". Unlike stty, can report only width, 16//config: A replacement for "stty size". Unlike stty, can report only width,
diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c
index a947abab5..dc7af25a4 100644
--- a/miscutils/ubi_tools.c
+++ b/miscutils/ubi_tools.c
@@ -4,42 +4,42 @@
4 * Licensed under GPLv2, see file LICENSE in this source tree. 4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */ 5 */
6//config:config UBIATTACH 6//config:config UBIATTACH
7//config: bool "ubiattach (4.7 kb)" 7//config: bool "ubiattach (4.2 kb)"
8//config: default y 8//config: default y
9//config: select PLATFORM_LINUX 9//config: select PLATFORM_LINUX
10//config: help 10//config: help
11//config: Attach MTD device to an UBI device. 11//config: Attach MTD device to an UBI device.
12//config: 12//config:
13//config:config UBIDETACH 13//config:config UBIDETACH
14//config: bool "ubidetach (4.6 kb)" 14//config: bool "ubidetach (4.1 kb)"
15//config: default y 15//config: default y
16//config: select PLATFORM_LINUX 16//config: select PLATFORM_LINUX
17//config: help 17//config: help
18//config: Detach MTD device from an UBI device. 18//config: Detach MTD device from an UBI device.
19//config: 19//config:
20//config:config UBIMKVOL 20//config:config UBIMKVOL
21//config: bool "ubimkvol (5.8 kb)" 21//config: bool "ubimkvol (5.3 kb)"
22//config: default y 22//config: default y
23//config: select PLATFORM_LINUX 23//config: select PLATFORM_LINUX
24//config: help 24//config: help
25//config: Create a UBI volume. 25//config: Create a UBI volume.
26//config: 26//config:
27//config:config UBIRMVOL 27//config:config UBIRMVOL
28//config: bool "ubirmvol (5.2 kb)" 28//config: bool "ubirmvol (4.9 kb)"
29//config: default y 29//config: default y
30//config: select PLATFORM_LINUX 30//config: select PLATFORM_LINUX
31//config: help 31//config: help
32//config: Delete a UBI volume. 32//config: Delete a UBI volume.
33//config: 33//config:
34//config:config UBIRSVOL 34//config:config UBIRSVOL
35//config: bool "ubirsvol (4.6 kb)" 35//config: bool "ubirsvol (4.2 kb)"
36//config: default y 36//config: default y
37//config: select PLATFORM_LINUX 37//config: select PLATFORM_LINUX
38//config: help 38//config: help
39//config: Resize a UBI volume. 39//config: Resize a UBI volume.
40//config: 40//config:
41//config:config UBIUPDATEVOL 41//config:config UBIUPDATEVOL
42//config: bool "ubiupdatevol (5.6 kb)" 42//config: bool "ubiupdatevol (5.2 kb)"
43//config: default y 43//config: default y
44//config: select PLATFORM_LINUX 44//config: select PLATFORM_LINUX
45//config: help 45//config: help
diff --git a/miscutils/ubirename.c b/miscutils/ubirename.c
index ecc8fe137..21bd10111 100644
--- a/miscutils/ubirename.c
+++ b/miscutils/ubirename.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config UBIRENAME 9//config:config UBIRENAME
10//config: bool "ubirename (2.2 kb)" 10//config: bool "ubirename (2.4 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/miscutils/volname.c b/miscutils/volname.c
index 6e6bbaa44..027d01272 100644
--- a/miscutils/volname.c
+++ b/miscutils/volname.c
@@ -28,7 +28,7 @@
28 * Matthew Stoltenberg <d3matt@gmail.com> 28 * Matthew Stoltenberg <d3matt@gmail.com>
29 */ 29 */
30//config:config VOLNAME 30//config:config VOLNAME
31//config: bool "volname (1.7 kb)" 31//config: bool "volname (1.6 kb)"
32//config: default y 32//config: default y
33//config: help 33//config: help
34//config: Prints a CD-ROM volume name. 34//config: Prints a CD-ROM volume name.
diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c
index 392d05646..1e9ecc5e8 100644
--- a/miscutils/watchdog.c
+++ b/miscutils/watchdog.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config WATCHDOG 11//config:config WATCHDOG
12//config: bool "watchdog (5.1 kb)" 12//config: bool "watchdog (5.3 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX 14//config: select PLATFORM_LINUX
15//config: help 15//config: help
diff --git a/modutils/depmod.c b/modutils/depmod.c
index 004c67a11..b5244fc60 100644
--- a/modutils/depmod.c
+++ b/modutils/depmod.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config DEPMOD 10//config:config DEPMOD
11//config: bool "depmod (26 kb)" 11//config: bool "depmod (27 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/modutils/lsmod.c b/modutils/lsmod.c
index 84860cd79..694205fda 100644
--- a/modutils/lsmod.c
+++ b/modutils/lsmod.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config LSMOD 10//config:config LSMOD
11//config: bool "lsmod (4.3 kb)" 11//config: bool "lsmod (1.9 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/modutils/modinfo.c b/modutils/modinfo.c
index 3f91622a9..1e63f745f 100644
--- a/modutils/modinfo.c
+++ b/modutils/modinfo.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config MODINFO 8//config:config MODINFO
9//config: bool "modinfo (25 kb)" 9//config: bool "modinfo (24 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX 11//config: select PLATFORM_LINUX
12//config: help 12//config: help
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index 291e4cb90..0a372a049 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config MODPROBE 10//config:config MODPROBE
11//config: bool "modprobe (29 kb)" 11//config: bool "modprobe (28 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/modutils/rmmod.c b/modutils/rmmod.c
index df50e58af..a3548879c 100644
--- a/modutils/rmmod.c
+++ b/modutils/rmmod.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config RMMOD 10//config:config RMMOD
11//config: bool "rmmod (3.6 kb)" 11//config: bool "rmmod (3.3 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/networking/Config.src b/networking/Config.src
index 2ce5287de..04d644bc9 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -46,6 +46,17 @@ config VERBOSE_RESOLUTION_ERRORS
46 "can't resolve 'hostname.com'" and want to know more. 46 "can't resolve 'hostname.com'" and want to know more.
47 This may increase size of your executable a bit. 47 This may increase size of your executable a bit.
48 48
49config FEATURE_TLS_SHA1
50 bool "In TLS code, support ciphers which use deprecated SHA1"
51 depends on TLS
52 default n
53 help
54 Selecting this option increases interoperability with very old
55 servers, but slightly increases code size.
56
57 Most TLS servers support SHA256 today (2018), since SHA1 is
58 considered possibly insecure (although not yet definitely broken).
59
49INSERT 60INSERT
50 61
51source networking/udhcp/Config.in 62source networking/udhcp/Config.in
diff --git a/networking/arp.c b/networking/arp.c
index 177ab1571..71bfe3cbf 100644
--- a/networking/arp.c
+++ b/networking/arp.c
@@ -13,7 +13,7 @@
13 * modified for getopt32 by Arne Bernin <arne [at] alamut.de> 13 * modified for getopt32 by Arne Bernin <arne [at] alamut.de>
14 */ 14 */
15//config:config ARP 15//config:config ARP
16//config: bool "arp (11 kb)" 16//config: bool "arp (10 kb)"
17//config: default y 17//config: default y
18//config: select PLATFORM_LINUX 18//config: select PLATFORM_LINUX
19//config: help 19//config: help
diff --git a/networking/arping.c b/networking/arping.c
index 788fded3c..901578b68 100644
--- a/networking/arping.c
+++ b/networking/arping.c
@@ -6,7 +6,7 @@
6 * Busybox port: Nick Fedchik <nick@fedchik.org.ua> 6 * Busybox port: Nick Fedchik <nick@fedchik.org.ua>
7 */ 7 */
8//config:config ARPING 8//config:config ARPING
9//config: bool "arping (9.3 kb)" 9//config: bool "arping (9 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX 11//config: select PLATFORM_LINUX
12//config: help 12//config: help
diff --git a/networking/ether-wake.c b/networking/ether-wake.c
index 6677f07d5..acaac16f8 100644
--- a/networking/ether-wake.c
+++ b/networking/ether-wake.c
@@ -64,7 +64,7 @@
64 * filter. That configuration consumes more power. 64 * filter. That configuration consumes more power.
65 */ 65 */
66//config:config ETHER_WAKE 66//config:config ETHER_WAKE
67//config: bool "ether-wake (6.6 kb)" 67//config: bool "ether-wake (4.9 kb)"
68//config: default y 68//config: default y
69//config: select PLATFORM_LINUX 69//config: select PLATFORM_LINUX
70//config: help 70//config: help
diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c
index 84ca547ff..bff90538f 100644
--- a/networking/ftpgetput.c
+++ b/networking/ftpgetput.c
@@ -13,13 +13,13 @@
13 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 13 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
14 */ 14 */
15//config:config FTPGET 15//config:config FTPGET
16//config: bool "ftpget (8 kb)" 16//config: bool "ftpget (7.8 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: Retrieve a remote file via FTP. 19//config: Retrieve a remote file via FTP.
20//config: 20//config:
21//config:config FTPPUT 21//config:config FTPPUT
22//config: bool "ftpput (7.7 kb)" 22//config: bool "ftpput (7.5 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: Store a remote file via FTP. 25//config: Store a remote file via FTP.
diff --git a/networking/hostname.c b/networking/hostname.c
index 8e3238d99..248d8b65a 100644
--- a/networking/hostname.c
+++ b/networking/hostname.c
@@ -10,7 +10,7 @@
10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 10 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
11 */ 11 */
12//config:config HOSTNAME 12//config:config HOSTNAME
13//config: bool "hostname (5.6 kb)" 13//config: bool "hostname (5.5 kb)"
14//config: default y 14//config: default y
15//config: help 15//config: help
16//config: Show or set the system's host name. 16//config: Show or set the system's host name.
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index 9a67d24d8..026ff1cc8 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config IFPLUGD 9//config:config IFPLUGD
10//config: bool "ifplugd (9.9 kb)" 10//config: bool "ifplugd (10 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 80fce87a6..8a6efc976 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -17,7 +17,7 @@
17 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 17 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
18 */ 18 */
19//config:config IFUP 19//config:config IFUP
20//config: bool "ifup (17 kb)" 20//config: bool "ifup (14 kb)"
21//config: default y 21//config: default y
22//config: help 22//config: help
23//config: Activate the specified interfaces. This applet makes use 23//config: Activate the specified interfaces. This applet makes use
@@ -33,7 +33,7 @@
33//config: via busybox or via standalone utilities. 33//config: via busybox or via standalone utilities.
34//config: 34//config:
35//config:config IFDOWN 35//config:config IFDOWN
36//config: bool "ifdown (15 kb)" 36//config: bool "ifdown (13 kb)"
37//config: default y 37//config: default y
38//config: help 38//config: help
39//config: Deactivate the specified interfaces. 39//config: Deactivate the specified interfaces.
diff --git a/networking/inetd.c b/networking/inetd.c
index ca1a97268..8f871ee12 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -488,7 +488,7 @@ static void block_CHLD_HUP_ALRM(sigset_t *m)
488 sigaddset(m, SIGCHLD); 488 sigaddset(m, SIGCHLD);
489 sigaddset(m, SIGHUP); 489 sigaddset(m, SIGHUP);
490 sigaddset(m, SIGALRM); 490 sigaddset(m, SIGALRM);
491 sigprocmask(SIG_BLOCK, m, m); /* old sigmask is stored in m */ 491 sigprocmask2(SIG_BLOCK, m); /* old sigmask is stored in m */
492} 492}
493 493
494static void restore_sigmask(sigset_t *m) 494static void restore_sigmask(sigset_t *m)
diff --git a/networking/ip.c b/networking/ip.c
index 97d618cd9..034ee4fc8 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -9,7 +9,7 @@
9 * Bernhard Reutner-Fischer rewrote to use index_in_substr_array 9 * Bernhard Reutner-Fischer rewrote to use index_in_substr_array
10 */ 10 */
11//config:config IP 11//config:config IP
12//config: bool "ip (34 kb)" 12//config: bool "ip (35 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX 14//config: select PLATFORM_LINUX
15//config: help 15//config: help
@@ -28,7 +28,7 @@
28//config: Short form of "ip addr" 28//config: Short form of "ip addr"
29//config: 29//config:
30//config:config IPLINK 30//config:config IPLINK
31//config: bool "iplink (16 kb)" 31//config: bool "iplink (17 kb)"
32//config: default y 32//config: default y
33//config: select FEATURE_IP_LINK 33//config: select FEATURE_IP_LINK
34//config: select PLATFORM_LINUX 34//config: select PLATFORM_LINUX
diff --git a/networking/ipcalc.c b/networking/ipcalc.c
index cdae8eea8..67f768836 100644
--- a/networking/ipcalc.c
+++ b/networking/ipcalc.c
@@ -12,7 +12,7 @@
12 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 12 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
13 */ 13 */
14//config:config IPCALC 14//config:config IPCALC
15//config: bool "ipcalc (4.3 kb)" 15//config: bool "ipcalc (4.4 kb)"
16//config: default y 16//config: default y
17//config: help 17//config: help
18//config: ipcalc takes an IP address and netmask and calculates the 18//config: ipcalc takes an IP address and netmask and calculates the
diff --git a/networking/isrv_identd.c b/networking/isrv_identd.c
index 0c33dde4f..f564d604a 100644
--- a/networking/isrv_identd.c
+++ b/networking/isrv_identd.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config FAKEIDENTD 9//config:config FAKEIDENTD
10//config: bool "fakeidentd (8.9 kb)" 10//config: bool "fakeidentd (8.7 kb)"
11//config: default y 11//config: default y
12//config: select FEATURE_SYSLOG 12//config: select FEATURE_SYSLOG
13//config: help 13//config: help
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c
index 9ec665b69..d088caf4c 100644
--- a/networking/libiproute/ipaddress.c
+++ b/networking/libiproute/ipaddress.c
@@ -327,6 +327,10 @@ static int FAST_FUNC print_addrinfo(const struct sockaddr_nl *who UNUSED_PARAM,
327 ifa->ifa_flags &= ~IFA_F_TENTATIVE; 327 ifa->ifa_flags &= ~IFA_F_TENTATIVE;
328 printf("tentative "); 328 printf("tentative ");
329 } 329 }
330 if (ifa->ifa_flags & IFA_F_DADFAILED) {
331 ifa->ifa_flags &= ~IFA_F_DADFAILED;
332 printf("dadfailed ");
333 }
330 if (ifa->ifa_flags & IFA_F_DEPRECATED) { 334 if (ifa->ifa_flags & IFA_F_DEPRECATED) {
331 ifa->ifa_flags &= ~IFA_F_DEPRECATED; 335 ifa->ifa_flags &= ~IFA_F_DEPRECATED;
332 printf("deprecated "); 336 printf("deprecated ");
diff --git a/networking/nbd-client.c b/networking/nbd-client.c
index 103756b59..0dc8d0c43 100644
--- a/networking/nbd-client.c
+++ b/networking/nbd-client.c
@@ -4,7 +4,7 @@
4 * Licensed under GPLv2, see file LICENSE in this source tree. 4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */ 5 */
6//config:config NBDCLIENT 6//config:config NBDCLIENT
7//config: bool "nbd-client (4.6 kb)" 7//config: bool "nbd-client (6 kb)"
8//config: default y 8//config: default y
9//config: help 9//config: help
10//config: Network block device client 10//config: Network block device client
@@ -163,7 +163,9 @@ int nbdclient_main(int argc, char **argv)
163 int sock, nbd; 163 int sock, nbd;
164 int ro; 164 int ro;
165 int proto_new; // 0 for old, 1 for new 165 int proto_new; // 0 for old, 1 for new
166#if BB_MMU
166 char *data; 167 char *data;
168#endif
167 169
168 // Make sure BLOCKDEV exists 170 // Make sure BLOCKDEV exists
169 nbd = xopen(device, O_RDWR); 171 nbd = xopen(device, O_RDWR);
@@ -200,7 +202,9 @@ int nbdclient_main(int argc, char **argv)
200 ioctl(nbd, NBD_SET_SIZE_BLOCKS, size_blocks); 202 ioctl(nbd, NBD_SET_SIZE_BLOCKS, size_blocks);
201 ioctl(nbd, NBD_CLEAR_SOCK); 203 ioctl(nbd, NBD_CLEAR_SOCK);
202 ro = !!(old_nbd_header.flags & htons(2)); 204 ro = !!(old_nbd_header.flags & htons(2));
205#if BB_MMU
203 data = old_nbd_header.data; 206 data = old_nbd_header.data;
207#endif
204 } else { 208 } else {
205 unsigned namelen; 209 unsigned namelen;
206 uint16_t handshake_flags; 210 uint16_t handshake_flags;
@@ -230,7 +234,9 @@ int nbdclient_main(int argc, char **argv)
230 ioctl(nbd, NBD_SET_FLAGS, 234 ioctl(nbd, NBD_SET_FLAGS,
231 ntohs(new_nbd_header.transmission_flags)); 235 ntohs(new_nbd_header.transmission_flags));
232 ro = !!(new_nbd_header.transmission_flags & htons(2)); 236 ro = !!(new_nbd_header.transmission_flags & htons(2));
237#if BB_MMU
233 data = new_nbd_header.data; 238 data = new_nbd_header.data;
239#endif
234 } 240 }
235 241
236 if (ioctl(nbd, BLKROSET, &ro) < 0) { 242 if (ioctl(nbd, BLKROSET, &ro) < 0) {
diff --git a/networking/nslookup.c b/networking/nslookup.c
index e153eb585..24e09d4f0 100644
--- a/networking/nslookup.c
+++ b/networking/nslookup.c
@@ -1,7 +1,7 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2 2
3//config:config NSLOOKUP 3//config:config NSLOOKUP
4//config: bool "nslookup (4.5 kb)" 4//config: bool "nslookup (9.7 kb)"
5//config: default y 5//config: default y
6//config: help 6//config: help
7//config: nslookup is a tool to query Internet name servers. 7//config: nslookup is a tool to query Internet name servers.
@@ -257,7 +257,7 @@ int nslookup_main(int argc, char **argv)
257struct ns { 257struct ns {
258 const char *name; 258 const char *name;
259 len_and_sockaddr *lsa; 259 len_and_sockaddr *lsa;
260 int failures; 260 //UNUSED: int failures;
261 int replies; 261 int replies;
262}; 262};
263 263
@@ -320,6 +320,7 @@ struct globals {
320 struct query *query; 320 struct query *query;
321 char *search; 321 char *search;
322 smalluint have_search_directive; 322 smalluint have_search_directive;
323 smalluint exitcode;
323} FIX_ALIASING; 324} FIX_ALIASING;
324#define G (*(struct globals*)bb_common_bufsiz1) 325#define G (*(struct globals*)bb_common_bufsiz1)
325#define INIT_G() do { \ 326#define INIT_G() do { \
@@ -593,7 +594,7 @@ static int send_queries(struct ns *ns)
593 594
594 /* Retry immediately on SERVFAIL */ 595 /* Retry immediately on SERVFAIL */
595 if (rcode == 2) { 596 if (rcode == 2) {
596 ns->failures++; 597 //UNUSED: ns->failures++;
597 if (servfail_retry) { 598 if (servfail_retry) {
598 servfail_retry--; 599 servfail_retry--;
599 write(pfd.fd, G.query[qn].query, G.query[qn].qlen); 600 write(pfd.fd, G.query[qn].query, G.query[qn].qlen);
@@ -612,9 +613,12 @@ static int send_queries(struct ns *ns)
612 if (rcode != 0) { 613 if (rcode != 0) {
613 printf("** server can't find %s: %s\n", 614 printf("** server can't find %s: %s\n",
614 G.query[qn].name, rcodes[rcode]); 615 G.query[qn].name, rcodes[rcode]);
616 G.exitcode = EXIT_FAILURE;
615 } else { 617 } else {
616 if (parse_reply(reply, recvlen) < 0) 618 if (parse_reply(reply, recvlen) < 0) {
617 printf("*** Can't find %s: Parse error\n", G.query[qn].name); 619 printf("*** Can't find %s: Parse error\n", G.query[qn].name);
620 G.exitcode = EXIT_FAILURE;
621 }
618 } 622 }
619 bb_putchar('\n'); 623 bb_putchar('\n');
620 n_replies++; 624 n_replies++;
@@ -988,7 +992,7 @@ int nslookup_main(int argc UNUSED_PARAM, char **argv)
988 free(G.query); 992 free(G.query);
989 } 993 }
990 994
991 return EXIT_SUCCESS; 995 return G.exitcode;
992} 996}
993 997
994#endif 998#endif
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 041cac762..855815ece 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -41,7 +41,7 @@
41 *********************************************************************** 41 ***********************************************************************
42 */ 42 */
43//config:config NTPD 43//config:config NTPD
44//config: bool "ntpd (17 kb)" 44//config: bool "ntpd (22 kb)"
45//config: default y 45//config: default y
46//config: select PLATFORM_LINUX 46//config: select PLATFORM_LINUX
47//config: help 47//config: help
diff --git a/networking/ping.c b/networking/ping.c
index 570184fee..b534c74c7 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -25,7 +25,7 @@
25 * The code was modified by Bart Visscher <magick@linux-fan.com> 25 * The code was modified by Bart Visscher <magick@linux-fan.com>
26 */ 26 */
27//config:config PING 27//config:config PING
28//config: bool "ping (9.5 kb)" 28//config: bool "ping (10 kb)"
29//config: default y 29//config: default y
30//config: select PLATFORM_LINUX 30//config: select PLATFORM_LINUX
31//config: help 31//config: help
@@ -33,7 +33,7 @@
33//config: elicit an ICMP ECHO_RESPONSE from a host or gateway. 33//config: elicit an ICMP ECHO_RESPONSE from a host or gateway.
34//config: 34//config:
35//config:config PING6 35//config:config PING6
36//config: bool "ping6 (10 kb)" 36//config: bool "ping6 (11 kb)"
37//config: default y 37//config: default y
38//config: depends on FEATURE_IPV6 38//config: depends on FEATURE_IPV6
39//config: help 39//config: help
diff --git a/networking/pscan.c b/networking/pscan.c
index 95b0a937d..2715ef2df 100644
--- a/networking/pscan.c
+++ b/networking/pscan.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config PSCAN 8//config:config PSCAN
9//config: bool "pscan (6.6 kb)" 9//config: bool "pscan (6 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: Simple network port scanner. 12//config: Simple network port scanner.
diff --git a/networking/route.c b/networking/route.c
index 8387ce1bb..ac1d94c28 100644
--- a/networking/route.c
+++ b/networking/route.c
@@ -25,7 +25,7 @@
25 * remove ridiculous amounts of bloat. 25 * remove ridiculous amounts of bloat.
26 */ 26 */
27//config:config ROUTE 27//config:config ROUTE
28//config: bool "route (8.9 kb)" 28//config: bool "route (8.7 kb)"
29//config: default y 29//config: default y
30//config: select PLATFORM_LINUX 30//config: select PLATFORM_LINUX
31//config: help 31//config: help
diff --git a/networking/slattach.c b/networking/slattach.c
index e0a388926..c6feca248 100644
--- a/networking/slattach.c
+++ b/networking/slattach.c
@@ -13,7 +13,7 @@
13 * - The -F options allows disabling of RTS/CTS flow control. 13 * - The -F options allows disabling of RTS/CTS flow control.
14 */ 14 */
15//config:config SLATTACH 15//config:config SLATTACH
16//config: bool "slattach (6.1 kb)" 16//config: bool "slattach (6.2 kb)"
17//config: default y 17//config: default y
18//config: select PLATFORM_LINUX 18//config: select PLATFORM_LINUX
19//config: help 19//config: help
diff --git a/networking/ssl_client.c b/networking/ssl_client.c
index 49aec6b99..cd0ee5722 100644
--- a/networking/ssl_client.c
+++ b/networking/ssl_client.c
@@ -4,7 +4,7 @@
4 * Licensed under GPLv2, see file LICENSE in this source tree. 4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */ 5 */
6//config:config SSL_CLIENT 6//config:config SSL_CLIENT
7//config: bool "ssl_client (23 kb)" 7//config: bool "ssl_client (25 kb)"
8//config: default y 8//config: default y
9//config: select TLS 9//config: select TLS
10//config: help 10//config: help
diff --git a/networking/tc.c b/networking/tc.c
index 4fa3e47bf..3e9808328 100644
--- a/networking/tc.c
+++ b/networking/tc.c
@@ -7,7 +7,7 @@
7 * Bernhard Reutner-Fischer adjusted for busybox 7 * Bernhard Reutner-Fischer adjusted for busybox
8 */ 8 */
9//config:config TC 9//config:config TC
10//config: bool "tc (3.1 kb)" 10//config: bool "tc (8.3 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Show / manipulate traffic control settings 13//config: Show / manipulate traffic control settings
diff --git a/networking/tcpudp.c b/networking/tcpudp.c
index c914221ae..a0af64981 100644
--- a/networking/tcpudp.c
+++ b/networking/tcpudp.c
@@ -29,7 +29,7 @@
29 * - don't know how to retrieve ORIGDST for udp. 29 * - don't know how to retrieve ORIGDST for udp.
30 */ 30 */
31//config:config TCPSVD 31//config:config TCPSVD
32//config: bool "tcpsvd (13 kb)" 32//config: bool "tcpsvd (14 kb)"
33//config: default y 33//config: default y
34//config: help 34//config: help
35//config: tcpsvd listens on a TCP port and runs a program for each new 35//config: tcpsvd listens on a TCP port and runs a program for each new
diff --git a/networking/telnet.c b/networking/telnet.c
index 1e6be85bd..fa1628723 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -20,7 +20,7 @@
20 * by Fernando Silveira <swrh@gmx.net> 20 * by Fernando Silveira <swrh@gmx.net>
21 */ 21 */
22//config:config TELNET 22//config:config TELNET
23//config: bool "telnet (8.7 kb)" 23//config: bool "telnet (8.8 kb)"
24//config: default y 24//config: default y
25//config: help 25//config: help
26//config: Telnet is an interface to the TELNET protocol, but is also commonly 26//config: Telnet is an interface to the TELNET protocol, but is also commonly
@@ -94,19 +94,19 @@ enum {
94 IACBUFSIZE = 128, 94 IACBUFSIZE = 128,
95 95
96 CHM_TRY = 0, 96 CHM_TRY = 0,
97 CHM_ON = 1, 97 CHM_ON = 1,
98 CHM_OFF = 2, 98 CHM_OFF = 2,
99 99
100 UF_ECHO = 0x01, 100 UF_ECHO = 0x01,
101 UF_SGA = 0x02, 101 UF_SGA = 0x02,
102 102
103 TS_NORMAL = 0, 103 TS_NORMAL = 0,
104 TS_COPY = 1, 104 TS_COPY = 1,
105 TS_IAC = 2, 105 TS_IAC = 2,
106 TS_OPT = 3, 106 TS_OPT = 3,
107 TS_SUB1 = 4, 107 TS_SUB1 = 4,
108 TS_SUB2 = 5, 108 TS_SUB2 = 5,
109 TS_CR = 6, 109 TS_CR = 6,
110}; 110};
111 111
112typedef unsigned char byte; 112typedef unsigned char byte;
@@ -152,8 +152,10 @@ static void subneg(byte c);
152 152
153static void iac_flush(void) 153static void iac_flush(void)
154{ 154{
155 full_write(netfd, G.iacbuf, G.iaclen); 155 if (G.iaclen != 0) {
156 G.iaclen = 0; 156 full_write(netfd, G.iacbuf, G.iaclen);
157 G.iaclen = 0;
158 }
157} 159}
158 160
159static void doexit(int ev) NORETURN; 161static void doexit(int ev) NORETURN;
@@ -244,25 +246,34 @@ static void handle_net_output(int len)
244 246
245static void handle_net_input(int len) 247static void handle_net_input(int len)
246{ 248{
249 byte c;
247 int i; 250 int i;
248 int cstart = 0; 251 int cstart = cstart; /* for compiler */
249 252
250 for (i = 0; i < len; i++) { 253 i = 0;
251 byte c = G.buf[i]; 254 //bb_error_msg("[%u,'%.*s']", G.telstate, len, G.buf);
252 255 if (G.telstate == TS_NORMAL) { /* most typical state */
253 if (G.telstate == TS_NORMAL) { /* most typical state */ 256 while (i < len) {
254 if (c == IAC) { 257 c = G.buf[i];
255 cstart = i; 258 i++;
256 G.telstate = TS_IAC; 259 if (c == IAC) /* unlikely */
257 } 260 goto got_IAC;
258 else if (c == '\r') { 261 if (c != '\r') /* likely */
259 cstart = i + 1; 262 continue;
260 G.telstate = TS_CR; 263 G.telstate = TS_CR;
261 } 264 cstart = i;
262 /* No IACs were seen so far, no need to copy 265 goto got_special;
263 * bytes within G.buf: */
264 continue;
265 } 266 }
267 full_write(STDOUT_FILENO, G.buf, len);
268 return;
269 got_IAC:
270 G.telstate = TS_IAC;
271 cstart = i - 1;
272 got_special: ;
273 }
274
275 for (; i < len; i++) {
276 c = G.buf[i];
266 277
267 switch (G.telstate) { 278 switch (G.telstate) {
268 case TS_CR: 279 case TS_CR:
@@ -278,20 +289,19 @@ static void handle_net_input(int len)
278 /* Similar to NORMAL, but in TS_COPY we need to copy bytes */ 289 /* Similar to NORMAL, but in TS_COPY we need to copy bytes */
279 if (c == IAC) 290 if (c == IAC)
280 G.telstate = TS_IAC; 291 G.telstate = TS_IAC;
281 else 292 else {
282 G.buf[cstart++] = c; 293 G.buf[cstart++] = c;
283 if (c == '\r') 294 if (c == '\r')
284 G.telstate = TS_CR; 295 G.telstate = TS_CR;
296 }
285 break; 297 break;
286 298
287 case TS_IAC: /* Prev char was IAC */ 299 case TS_IAC: /* Prev char was IAC */
288 if (c == IAC) { /* IAC IAC -> one IAC */ 300 switch (c) {
301 case IAC: /* IAC IAC -> one IAC */
289 G.buf[cstart++] = c; 302 G.buf[cstart++] = c;
290 G.telstate = TS_COPY; 303 G.telstate = TS_COPY;
291 break; 304 break;
292 }
293 /* else */
294 switch (c) {
295 case SB: 305 case SB:
296 G.telstate = TS_SUB1; 306 G.telstate = TS_SUB1;
297 break; 307 break;
@@ -320,103 +330,83 @@ static void handle_net_input(int len)
320 } 330 }
321 } 331 }
322 332
323 if (G.telstate != TS_NORMAL) { 333 /* We had some IACs, or CR */
324 /* We had some IACs, or CR */ 334 iac_flush();
325 if (G.iaclen) 335 if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */
326 iac_flush(); 336 G.telstate = TS_NORMAL;
327 if (G.telstate == TS_COPY) /* we aren't in the middle of IAC */ 337 if (cstart != 0)
328 G.telstate = TS_NORMAL; 338 full_write(STDOUT_FILENO, G.buf, cstart);
329 len = cstart;
330 }
331
332 if (len)
333 full_write(STDOUT_FILENO, G.buf, len);
334} 339}
335 340
336static void put_iac(int c) 341static void put_iac(int c)
337{ 342{
338 G.iacbuf[G.iaclen++] = c; 343 int iaclen = G.iaclen;
344 if (iaclen >= IACBUFSIZE) {
345 iac_flush();
346 iaclen = 0;
347 }
348 G.iacbuf[iaclen] = c; /* "... & 0xff" is implicit */
349 G.iaclen = iaclen + 1;
339} 350}
340 351
341static void put_iac2_merged(unsigned wwdd_and_c) 352static void put_iac2_msb_lsb(unsigned x_y)
342{ 353{
343 if (G.iaclen + 3 > IACBUFSIZE) 354 put_iac(x_y >> 8); /* "... & 0xff" is implicit */
344 iac_flush(); 355 put_iac(x_y); /* "... & 0xff" is implicit */
356}
357#define put_iac2_x_y(x,y) put_iac2_msb_lsb(((x)<<8) + (y))
358
359static void put_iac4_msb_lsb(unsigned x_y_z_t)
360{
361 put_iac2_msb_lsb(x_y_z_t >> 16);
362 put_iac2_msb_lsb(x_y_z_t); /* "... & 0xffff" is implicit */
363}
364#define put_iac4_x_y_z_t(x,y,z,t) put_iac4_msb_lsb(((x)<<24) + ((y)<<16) + ((z)<<8) + (t))
345 365
366static void put_iac3_IAC_x_y_merged(unsigned wwdd_and_c)
367{
346 put_iac(IAC); 368 put_iac(IAC);
347 put_iac(wwdd_and_c >> 8); 369 put_iac2_msb_lsb(wwdd_and_c);
348 put_iac(wwdd_and_c & 0xff);
349} 370}
350#define put_iac2(wwdd,c) put_iac2_merged(((wwdd)<<8) + (c)) 371#define put_iac3_IAC_x_y(wwdd,c) put_iac3_IAC_x_y_merged(((wwdd)<<8) + (c))
351 372
352#if ENABLE_FEATURE_TELNET_TTYPE 373#if ENABLE_FEATURE_TELNET_TTYPE
353static void put_iac_subopt(byte c, char *str) 374static void put_iac_subopt(byte c, char *str)
354{ 375{
355 int len = strlen(str) + 6; // ( 2 + 1 + 1 + strlen + 2 ) 376 put_iac4_x_y_z_t(IAC, SB, c, 0);
356
357 if (G.iaclen + len > IACBUFSIZE)
358 iac_flush();
359
360 put_iac(IAC);
361 put_iac(SB);
362 put_iac(c);
363 put_iac(0);
364 377
365 while (*str) 378 while (*str)
366 put_iac(*str++); 379 put_iac(*str++);
367 380
368 put_iac(IAC); 381 put_iac2_x_y(IAC, SE);
369 put_iac(SE);
370} 382}
371#endif 383#endif
372 384
373#if ENABLE_FEATURE_TELNET_AUTOLOGIN 385#if ENABLE_FEATURE_TELNET_AUTOLOGIN
374static void put_iac_subopt_autologin(void) 386static void put_iac_subopt_autologin(void)
375{ 387{
376 int len = strlen(G.autologin) + 6; // (2 + 1 + 1 + strlen + 2) 388 const char *p;
377 const char *p = "USER";
378
379 if (G.iaclen + len > IACBUFSIZE)
380 iac_flush();
381
382 put_iac(IAC);
383 put_iac(SB);
384 put_iac(TELOPT_NEW_ENVIRON);
385 put_iac(TELQUAL_IS);
386 put_iac(NEW_ENV_VAR);
387
388 while (*p)
389 put_iac(*p++);
390 389
391 put_iac(NEW_ENV_VALUE); 390 put_iac4_x_y_z_t(IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_IS);
391 put_iac4_x_y_z_t(NEW_ENV_VAR, 'U', 'S', 'E'); /* "USER" */
392 put_iac2_x_y('R', NEW_ENV_VALUE);
392 393
393 p = G.autologin; 394 p = G.autologin;
394 while (*p) 395 while (*p)
395 put_iac(*p++); 396 put_iac(*p++);
396 397
397 put_iac(IAC); 398 put_iac2_x_y(IAC, SE);
398 put_iac(SE);
399} 399}
400#endif 400#endif
401 401
402#if ENABLE_FEATURE_TELNET_WIDTH 402#if ENABLE_FEATURE_TELNET_WIDTH
403static void put_iac_naws(byte c, int x, int y) 403static void put_iac_naws(byte c, int x, int y)
404{ 404{
405 if (G.iaclen + 9 > IACBUFSIZE) 405 put_iac3_IAC_x_y(SB, c);
406 iac_flush();
407 406
408 put_iac(IAC); 407 put_iac4_msb_lsb((x << 16) + y);
409 put_iac(SB);
410 put_iac(c);
411 408
412 /* "... & 0xff" implicitly done below */ 409 put_iac2_x_y(IAC, SE);
413 put_iac(x >> 8);
414 put_iac(x);
415 put_iac(y >> 8);
416 put_iac(y);
417
418 put_iac(IAC);
419 put_iac(SE);
420} 410}
421#endif 411#endif
422 412
@@ -445,8 +435,8 @@ static void will_charmode(void)
445 G.telflags |= (UF_ECHO | UF_SGA); 435 G.telflags |= (UF_ECHO | UF_SGA);
446 setConMode(); 436 setConMode();
447 437
448 put_iac2(DO, TELOPT_ECHO); 438 put_iac3_IAC_x_y(DO, TELOPT_ECHO);
449 put_iac2(DO, TELOPT_SGA); 439 put_iac3_IAC_x_y(DO, TELOPT_SGA);
450 iac_flush(); 440 iac_flush();
451} 441}
452 442
@@ -456,24 +446,24 @@ static void do_linemode(void)
456 G.telflags &= ~(UF_ECHO | UF_SGA); 446 G.telflags &= ~(UF_ECHO | UF_SGA);
457 setConMode(); 447 setConMode();
458 448
459 put_iac2(DONT, TELOPT_ECHO); 449 put_iac3_IAC_x_y(DONT, TELOPT_ECHO);
460 put_iac2(DONT, TELOPT_SGA); 450 put_iac3_IAC_x_y(DONT, TELOPT_SGA);
461 iac_flush(); 451 iac_flush();
462} 452}
463 453
464static void to_notsup(char c) 454static void to_notsup(char c)
465{ 455{
466 if (G.telwish == WILL) 456 if (G.telwish == WILL)
467 put_iac2(DONT, c); 457 put_iac3_IAC_x_y(DONT, c);
468 else if (G.telwish == DO) 458 else if (G.telwish == DO)
469 put_iac2(WONT, c); 459 put_iac3_IAC_x_y(WONT, c);
470} 460}
471 461
472static void to_echo(void) 462static void to_echo(void)
473{ 463{
474 /* if server requests ECHO, don't agree */ 464 /* if server requests ECHO, don't agree */
475 if (G.telwish == DO) { 465 if (G.telwish == DO) {
476 put_iac2(WONT, TELOPT_ECHO); 466 put_iac3_IAC_x_y(WONT, TELOPT_ECHO);
477 return; 467 return;
478 } 468 }
479 if (G.telwish == DONT) 469 if (G.telwish == DONT)
@@ -489,9 +479,9 @@ static void to_echo(void)
489 G.telflags ^= UF_ECHO; 479 G.telflags ^= UF_ECHO;
490 480
491 if (G.telflags & UF_ECHO) 481 if (G.telflags & UF_ECHO)
492 put_iac2(DO, TELOPT_ECHO); 482 put_iac3_IAC_x_y(DO, TELOPT_ECHO);
493 else 483 else
494 put_iac2(DONT, TELOPT_ECHO); 484 put_iac3_IAC_x_y(DONT, TELOPT_ECHO);
495 485
496 setConMode(); 486 setConMode();
497 full_write1_str("\r\n"); /* sudden modec */ 487 full_write1_str("\r\n"); /* sudden modec */
@@ -509,9 +499,9 @@ static void to_sga(void)
509 499
510 G.telflags ^= UF_SGA; /* toggle */ 500 G.telflags ^= UF_SGA; /* toggle */
511 if (G.telflags & UF_SGA) 501 if (G.telflags & UF_SGA)
512 put_iac2(DO, TELOPT_SGA); 502 put_iac3_IAC_x_y(DO, TELOPT_SGA);
513 else 503 else
514 put_iac2(DONT, TELOPT_SGA); 504 put_iac3_IAC_x_y(DONT, TELOPT_SGA);
515} 505}
516 506
517#if ENABLE_FEATURE_TELNET_TTYPE 507#if ENABLE_FEATURE_TELNET_TTYPE
@@ -519,9 +509,9 @@ static void to_ttype(void)
519{ 509{
520 /* Tell server we will (or won't) do TTYPE */ 510 /* Tell server we will (or won't) do TTYPE */
521 if (G.ttype) 511 if (G.ttype)
522 put_iac2(WILL, TELOPT_TTYPE); 512 put_iac3_IAC_x_y(WILL, TELOPT_TTYPE);
523 else 513 else
524 put_iac2(WONT, TELOPT_TTYPE); 514 put_iac3_IAC_x_y(WONT, TELOPT_TTYPE);
525} 515}
526#endif 516#endif
527 517
@@ -530,9 +520,9 @@ static void to_new_environ(void)
530{ 520{
531 /* Tell server we will (or will not) do AUTOLOGIN */ 521 /* Tell server we will (or will not) do AUTOLOGIN */
532 if (G.autologin) 522 if (G.autologin)
533 put_iac2(WILL, TELOPT_NEW_ENVIRON); 523 put_iac3_IAC_x_y(WILL, TELOPT_NEW_ENVIRON);
534 else 524 else
535 put_iac2(WONT, TELOPT_NEW_ENVIRON); 525 put_iac3_IAC_x_y(WONT, TELOPT_NEW_ENVIRON);
536} 526}
537#endif 527#endif
538 528
@@ -540,7 +530,7 @@ static void to_new_environ(void)
540static void to_naws(void) 530static void to_naws(void)
541{ 531{
542 /* Tell server we will do NAWS */ 532 /* Tell server we will do NAWS */
543 put_iac2(WILL, TELOPT_NAWS); 533 put_iac3_IAC_x_y(WILL, TELOPT_NAWS);
544} 534}
545#endif 535#endif
546 536
@@ -649,6 +639,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv)
649 bb_show_usage(); 639 bb_show_usage();
650 640
651 xmove_fd(create_and_connect_stream_or_die(host, port), netfd); 641 xmove_fd(create_and_connect_stream_or_die(host, port), netfd);
642 printf("Connected to %s\n", host);
652 643
653 setsockopt_keepalive(netfd); 644 setsockopt_keepalive(netfd);
654 645
diff --git a/networking/telnetd.c b/networking/telnetd.c
index a6bafa21d..caef15181 100644
--- a/networking/telnetd.c
+++ b/networking/telnetd.c
@@ -865,11 +865,25 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv)
865 skip3: 865 skip3:
866 if (/*ts->size2 < BUFSIZE &&*/ FD_ISSET(ts->ptyfd, &rdfdset)) { 866 if (/*ts->size2 < BUFSIZE &&*/ FD_ISSET(ts->ptyfd, &rdfdset)) {
867 /* Read from pty to buffer 2 */ 867 /* Read from pty to buffer 2 */
868 int eio = 0;
869 read_pty:
868 count = MIN(BUFSIZE - ts->rdidx2, BUFSIZE - ts->size2); 870 count = MIN(BUFSIZE - ts->rdidx2, BUFSIZE - ts->size2);
869 count = safe_read(ts->ptyfd, TS_BUF2(ts) + ts->rdidx2, count); 871 count = safe_read(ts->ptyfd, TS_BUF2(ts) + ts->rdidx2, count);
870 if (count <= 0) { 872 if (count <= 0) {
871 if (count < 0 && errno == EAGAIN) 873 if (count < 0) {
872 goto skip4; 874 if (errno == EAGAIN)
875 goto skip4;
876 /* login process might call vhangup(),
877 * which causes intermittent EIOs on read above
878 * (observed on kernel 4.12.0). Try up to 10 ms.
879 */
880 if (errno == EIO && eio < 10) {
881 eio++;
882 //bb_error_msg("EIO pty %u", eio);
883 usleep(1000);
884 goto read_pty;
885 }
886 }
873 goto kill_session; 887 goto kill_session;
874 } 888 }
875 ts->size2 += count; 889 ts->size2 += count;
diff --git a/networking/tftp.c b/networking/tftp.c
index 4cd39186a..d20d4ca4b 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -19,7 +19,7 @@
19 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 19 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
20 */ 20 */
21//config:config TFTP 21//config:config TFTP
22//config: bool "tftp (12 kb)" 22//config: bool "tftp (11 kb)"
23//config: default y 23//config: default y
24//config: help 24//config: help
25//config: Trivial File Transfer Protocol client. TFTP is usually used 25//config: Trivial File Transfer Protocol client. TFTP is usually used
@@ -41,9 +41,6 @@
41//config: In other words: it should be run from inetd in nowait mode, 41//config: In other words: it should be run from inetd in nowait mode,
42//config: or from udpsvd. Example: "udpsvd -E 0 69 tftpd DIR" 42//config: or from udpsvd. Example: "udpsvd -E 0 69 tftpd DIR"
43//config: 43//config:
44//config:comment "Common options for tftp/tftpd"
45//config: depends on TFTP || TFTPD
46//config:
47//config:config FEATURE_TFTP_GET 44//config:config FEATURE_TFTP_GET
48//config: bool "Enable 'tftp get' and/or tftpd upload code" 45//config: bool "Enable 'tftp get' and/or tftpd upload code"
49//config: default y 46//config: default y
diff --git a/networking/tls.c b/networking/tls.c
index 38eb79798..d2385efe8 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -6,6 +6,8 @@
6//config:config TLS 6//config:config TLS
7//config: bool #No description makes it a hidden option 7//config: bool #No description makes it a hidden option
8//config: default n 8//config: default n
9//Note:
10//Config.src also defines FEATURE_TLS_SHA1 option
9 11
10//kbuild:lib-$(CONFIG_TLS) += tls.o 12//kbuild:lib-$(CONFIG_TLS) += tls.o
11//kbuild:lib-$(CONFIG_TLS) += tls_pstm.o 13//kbuild:lib-$(CONFIG_TLS) += tls_pstm.o
@@ -400,7 +402,7 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer
400 dump_hex(fmt, buffer, len); 402 dump_hex(fmt, buffer, len);
401 dbg(" (%u bytes) ", (int)len); 403 dbg(" (%u bytes) ", (int)len);
402 len = sha_peek(&tls->hsd->handshake_hash_ctx, h); 404 len = sha_peek(&tls->hsd->handshake_hash_ctx, h);
403 if (len == SHA1_OUTSIZE) 405 if (ENABLE_FEATURE_TLS_SHA1 && len == SHA1_OUTSIZE)
404 dump_hex("sha1:%s\n", h, len); 406 dump_hex("sha1:%s\n", h, len);
405 else 407 else
406 if (len == SHA256_OUTSIZE) 408 if (len == SHA256_OUTSIZE)
@@ -411,6 +413,12 @@ static void hash_handshake(tls_state_t *tls, const char *fmt, const void *buffer
411#endif 413#endif
412} 414}
413 415
416#if !ENABLE_FEATURE_TLS_SHA1
417# define TLS_MAC_SIZE(tls) SHA256_OUTSIZE
418#else
419# define TLS_MAC_SIZE(tls) (tls)->MAC_size
420#endif
421
414// RFC 2104: 422// RFC 2104:
415// HMAC(key, text) based on a hash H (say, sha256) is: 423// HMAC(key, text) based on a hash H (say, sha256) is:
416// ipad = [0x36 x INSIZE] 424// ipad = [0x36 x INSIZE]
@@ -427,6 +435,11 @@ typedef struct hmac_precomputed {
427} hmac_precomputed_t; 435} hmac_precomputed_t;
428 436
429typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC; 437typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC;
438#if !ENABLE_FEATURE_TLS_SHA1
439#define hmac_begin(pre,key,key_size,begin) \
440 hmac_begin(pre,key,key_size)
441#define begin sha256_begin
442#endif
430static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin) 443static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size, md5sha_begin_func *begin)
431{ 444{
432 uint8_t key_xor_ipad[SHA_INSIZE]; 445 uint8_t key_xor_ipad[SHA_INSIZE];
@@ -467,6 +480,7 @@ static void hmac_begin(hmac_precomputed_t *pre, uint8_t *key, unsigned key_size,
467 md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE); 480 md5sha_hash(&pre->hashed_key_xor_ipad, key_xor_ipad, SHA_INSIZE);
468 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE); 481 md5sha_hash(&pre->hashed_key_xor_opad, key_xor_opad, SHA_INSIZE);
469} 482}
483#undef begin
470 484
471static unsigned hmac_sha_precomputed_v( 485static unsigned hmac_sha_precomputed_v(
472 hmac_precomputed_t *pre, 486 hmac_precomputed_t *pre,
@@ -504,6 +518,10 @@ static unsigned hmac_sha_precomputed(hmac_precomputed_t *pre_init, uint8_t *out,
504 return len; 518 return len;
505} 519}
506 520
521#if !ENABLE_FEATURE_TLS_SHA1
522#define hmac(tls,out,key,key_size,...) \
523 hmac(out,key,key_size, __VA_ARGS__)
524#endif
507static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...) 525static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...)
508{ 526{
509 hmac_precomputed_t pre; 527 hmac_precomputed_t pre;
@@ -513,9 +531,9 @@ static unsigned hmac(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_
513 va_start(va, key_size); 531 va_start(va, key_size);
514 532
515 hmac_begin(&pre, key, key_size, 533 hmac_begin(&pre, key, key_size,
516 (tls->MAC_size == SHA256_OUTSIZE) 534 (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE)
517 ? sha256_begin 535 ? sha1_begin
518 : sha1_begin 536 : sha256_begin
519 ); 537 );
520 len = hmac_sha_precomputed_v(&pre, out, va); 538 len = hmac_sha_precomputed_v(&pre, out, va);
521 539
@@ -685,7 +703,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un
685 703
686 /* Calculate MAC signature */ 704 /* Calculate MAC signature */
687 hmac(tls, buf + size, /* result */ 705 hmac(tls, buf + size, /* result */
688 tls->client_write_MAC_key, tls->MAC_size, 706 tls->client_write_MAC_key, TLS_MAC_SIZE(tls),
689 &tls->write_seq64_be, sizeof(tls->write_seq64_be), 707 &tls->write_seq64_be, sizeof(tls->write_seq64_be),
690 xhdr, RECHDR_LEN, 708 xhdr, RECHDR_LEN,
691 buf, size, 709 buf, size,
@@ -693,7 +711,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un
693 ); 711 );
694 tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be)); 712 tls->write_seq64_be = SWAP_BE64(1 + SWAP_BE64(tls->write_seq64_be));
695 713
696 size += tls->MAC_size; 714 size += TLS_MAC_SIZE(tls);
697 715
698 // RFC 5246: 716 // RFC 5246:
699 // 6.2.3.1. Null or Standard Stream Cipher 717 // 6.2.3.1. Null or Standard Stream Cipher
@@ -778,7 +796,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un
778 796
779 tls_get_random(buf - AES_BLOCK_SIZE, AES_BLOCK_SIZE); /* IV */ 797 tls_get_random(buf - AES_BLOCK_SIZE, AES_BLOCK_SIZE); /* IV */
780 dbg("before crypt: 5 hdr + %u data + %u hash bytes\n", 798 dbg("before crypt: 5 hdr + %u data + %u hash bytes\n",
781 size - tls->MAC_size, tls->MAC_size); 799 size - TLS_MAC_SIZE(tls), TLS_MAC_SIZE(tls));
782 800
783 /* Fill IV and padding in outbuf */ 801 /* Fill IV and padding in outbuf */
784 // RFC is talking nonsense: 802 // RFC is talking nonsense:
@@ -1093,7 +1111,7 @@ static int tls_xread_record(tls_state_t *tls, const char *expected)
1093 tls_aesgcm_decrypt(tls, p, sz); 1111 tls_aesgcm_decrypt(tls, p, sz);
1094 dbg("encrypted size:%u\n", sz); 1112 dbg("encrypted size:%u\n", sz);
1095 } else 1113 } else
1096 if (tls->min_encrypted_len_on_read > tls->MAC_size) { 1114 if (tls->min_encrypted_len_on_read > TLS_MAC_SIZE(tls)) {
1097 /* AES+SHA */ 1115 /* AES+SHA */
1098 uint8_t *p = tls->inbuf + RECHDR_LEN; 1116 uint8_t *p = tls->inbuf + RECHDR_LEN;
1099 int padding_len; 1117 int padding_len;
@@ -1112,7 +1130,7 @@ static int tls_xread_record(tls_state_t *tls, const char *expected)
1112 padding_len = p[sz - 1]; 1130 padding_len = p[sz - 1];
1113 dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len); 1131 dbg("encrypted size:%u type:0x%02x padding_length:0x%02x\n", sz, p[0], padding_len);
1114 padding_len++; 1132 padding_len++;
1115 sz -= tls->MAC_size + padding_len; /* drop MAC and padding */ 1133 sz -= TLS_MAC_SIZE(tls) + padding_len; /* drop MAC and padding */
1116 } else { 1134 } else {
1117 /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */ 1135 /* if nonzero, then it's TLS_RSA_WITH_NULL_SHA256: drop MAC */
1118 /* else: no encryption yet on input, subtract zero = NOP */ 1136 /* else: no encryption yet on input, subtract zero = NOP */
@@ -1472,15 +1490,19 @@ static ALWAYS_INLINE void fill_handshake_record_hdr(void *buf, unsigned type, un
1472 1490
1473static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni) 1491static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1474{ 1492{
1475#define NUM_CIPHERS (13 + ALLOW_RSA_NULL_SHA256) 1493#define NUM_CIPHERS (7 + 6 * ENABLE_FEATURE_TLS_SHA1 + ALLOW_RSA_NULL_SHA256)
1476 static const uint8_t ciphers[] = { 1494 static const uint8_t ciphers[] = {
1477 0x00,(1 + NUM_CIPHERS) * 2, //len16_be 1495 0x00,2 + NUM_CIPHERS*2, //len16_be
1478 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV 1496 0x00,0xFF, //not a cipher - TLS_EMPTY_RENEGOTIATION_INFO_SCSV
1479 /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */ 1497 /* ^^^^^^ RFC 5746 Renegotiation Indication Extension - some servers will refuse to work with us otherwise */
1498#if ENABLE_FEATURE_TLS_SHA1
1480 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ 1499 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/
1481 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ 1500 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/
1482 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA 1501 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA
1483 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl) 1502 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl)
1503 // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA
1504 // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA
1505#endif
1484 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ 1506 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/
1485 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1507 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1486 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 1508 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256
@@ -1491,12 +1513,16 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1491 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 1513 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256
1492 // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac" 1514 // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac"
1493 //possibly these too: 1515 //possibly these too:
1516#if ENABLE_FEATURE_TLS_SHA1
1494 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 1517 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
1495 // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 1518 // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
1519#endif
1496 // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 1520 // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
1497 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1521 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1522#if ENABLE_FEATURE_TLS_SHA1
1498 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA 1523 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA
1499 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA 1524 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA
1525#endif
1500 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 1526 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256
1501 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 1527 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256
1502 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 1528 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256
@@ -1511,9 +1537,17 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1511 0x00,0x04, //ext len 1537 0x00,0x04, //ext len
1512 0x00,0x02, //list len 1538 0x00,0x02, //list len
1513 0x00,0x1d, //curve_x25519 (RFC 7748) 1539 0x00,0x1d, //curve_x25519 (RFC 7748)
1540 //0x00,0x1e, //curve_x448 (RFC 7748)
1514 //0x00,0x17, //curve_secp256r1 1541 //0x00,0x17, //curve_secp256r1
1515 //0x00,0x18, //curve_secp384r1 1542 //0x00,0x18, //curve_secp384r1
1516 //0x00,0x19, //curve_secp521r1 1543 //0x00,0x19, //curve_secp521r1
1544//TODO: implement secp256r1 (at least): dl.fedoraproject.org immediately aborts
1545//if only x25519/x448 are advertised, seems to support only secpNNNr1 curves:
1546// openssl s_client -connect dl.fedoraproject.org:443 -debug -tls1_2 -cipher ECDHE-RSA-AES128-GCM-SHA256
1547//Peer signing digest: SHA512
1548//Peer signature type: RSA
1549//Server Temp Key: ECDH, P-256, 256 bits
1550//TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
1517 }; 1551 };
1518 //static const uint8_t signature_algorithms[] = { 1552 //static const uint8_t signature_algorithms[] = {
1519 // 000d 1553 // 000d
@@ -1530,7 +1564,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1530 uint8_t session_id_len; 1564 uint8_t session_id_len;
1531 /* uint8_t session_id[]; */ 1565 /* uint8_t session_id[]; */
1532 uint8_t cipherid_len16_hi, cipherid_len16_lo; 1566 uint8_t cipherid_len16_hi, cipherid_len16_lo;
1533 uint8_t cipherid[(1 + NUM_CIPHERS) * 2]; /* actually variable */ 1567 uint8_t cipherid[2 + NUM_CIPHERS*2]; /* actually variable */
1534 uint8_t comprtypes_len; 1568 uint8_t comprtypes_len;
1535 uint8_t comprtypes[1]; /* actually variable */ 1569 uint8_t comprtypes[1]; /* actually variable */
1536 /* Extensions (SNI shown): 1570 /* Extensions (SNI shown):
@@ -1578,7 +1612,7 @@ static void send_client_hello_and_alloc_hsd(tls_state_t *tls, const char *sni)
1578 memset(record->rand32, 0x11, sizeof(record->rand32)); 1612 memset(record->rand32, 0x11, sizeof(record->rand32));
1579 /* record->session_id_len = 0; - already is */ 1613 /* record->session_id_len = 0; - already is */
1580 1614
1581 BUILD_BUG_ON(sizeof(ciphers) != 2 + (1 + NUM_CIPHERS) * 2 + 2); 1615 BUILD_BUG_ON(sizeof(ciphers) != 2 + 2 + NUM_CIPHERS*2 + 2);
1582 memcpy(&record->cipherid_len16_hi, ciphers, sizeof(ciphers)); 1616 memcpy(&record->cipherid_len16_hi, ciphers, sizeof(ciphers));
1583 1617
1584 ptr = (void*)(record + 1); 1618 ptr = (void*)(record + 1);
@@ -1675,31 +1709,42 @@ static void get_server_hello(tls_state_t *tls)
1675 1709
1676 /* Set up encryption params based on selected cipher */ 1710 /* Set up encryption params based on selected cipher */
1677#if 0 1711#if 0
1712#if ENABLE_FEATURE_TLS_SHA1
1678 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/ 1713 0xC0,0x09, // 1 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - ok: wget https://is.gd/
1679 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/ 1714 0xC0,0x0A, // 2 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ok: wget https://is.gd/
1680 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA 1715 0xC0,0x13, // 3 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA
1681 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl) 1716 0xC0,0x14, // 4 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher ECDHE-RSA-AES256-SHA (might fail with older openssl)
1717 // 0xC0,0x18, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA
1718 // 0xC0,0x19, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA
1719#endif
1682 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/ 1720 0xC0,0x23, // 5 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ok: wget https://is.gd/
1683 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1721 // 0xC0,0x24, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1684 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256 1722 0xC0,0x27, // 6 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-SHA256
1685 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1723 // 0xC0,0x28, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1686 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/ 1724 0xC0,0x2B, // 7 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - ok: wget https://is.gd/
1687 // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC" 1725 // 0xC0,0x2C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - wget https://is.gd/: "TLS error from peer (alert code 20): bad MAC"
1726//TODO: GCM_SHA384 ciphers can be supported, only need sha384-based PRF?
1688 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256 1727 0xC0,0x2F, // 8 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher ECDHE-RSA-AES128-GCM-SHA256
1689 // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac" 1728 // 0xC0,0x30, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher ECDHE-RSA-AES256-GCM-SHA384: "decryption failed or bad record mac"
1690 //possibly these too: 1729 //possibly these too:
1730#if ENABLE_FEATURE_TLS_SHA1
1691 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 1731 // 0xC0,0x35, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
1692 // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 1732 // 0xC0,0x36, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
1733#endif
1693 // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 1734 // 0xC0,0x37, // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
1694 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet 1735 // 0xC0,0x38, // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - can't do SHA384 yet
1736#if ENABLE_FEATURE_TLS_SHA1
1695 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA 1737 0x00,0x2F, // 9 TLS_RSA_WITH_AES_128_CBC_SHA - ok: openssl s_server ... -cipher AES128-SHA
1696 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA 1738 0x00,0x35, //10 TLS_RSA_WITH_AES_256_CBC_SHA - ok: openssl s_server ... -cipher AES256-SHA
1739#endif
1697 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256 1740 0x00,0x3C, //11 TLS_RSA_WITH_AES_128_CBC_SHA256 - ok: openssl s_server ... -cipher AES128-SHA256
1698 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256 1741 0x00,0x3D, //12 TLS_RSA_WITH_AES_256_CBC_SHA256 - ok: openssl s_server ... -cipher AES256-SHA256
1699 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256 1742 0x00,0x9C, //13 TLS_RSA_WITH_AES_128_GCM_SHA256 - ok: openssl s_server ... -cipher AES128-GCM-SHA256
1700 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac" 1743 // 0x00,0x9D, // TLS_RSA_WITH_AES_256_GCM_SHA384 - openssl s_server ... -cipher AES256-GCM-SHA384: "decryption failed or bad record mac"
1744#if ALLOW_RSA_NULL_SHA256
1701 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256 1745 0x00,0x3B, // TLS_RSA_WITH_NULL_SHA256
1702#endif 1746#endif
1747#endif
1703 cipherid1 = cipherid[1]; 1748 cipherid1 = cipherid[1];
1704 tls->cipher_id = 0x100 * cipherid[0] + cipherid1; 1749 tls->cipher_id = 0x100 * cipherid[0] + cipherid1;
1705 tls->key_size = AES256_KEYSIZE; 1750 tls->key_size = AES256_KEYSIZE;
@@ -1712,7 +1757,7 @@ static void get_server_hello(tls_state_t *tls)
1712 /* Odd numbered C0xx use AES128 (even ones use AES256) */ 1757 /* Odd numbered C0xx use AES128 (even ones use AES256) */
1713 tls->key_size = AES128_KEYSIZE; 1758 tls->key_size = AES128_KEYSIZE;
1714 } 1759 }
1715 if (cipherid1 <= 0x14) { 1760 if (ENABLE_FEATURE_TLS_SHA1 && cipherid1 <= 0x19) {
1716 tls->MAC_size = SHA1_OUTSIZE; 1761 tls->MAC_size = SHA1_OUTSIZE;
1717 } else 1762 } else
1718 if (cipherid1 >= 0x2B && cipherid1 <= 0x30) { 1763 if (cipherid1 >= 0x2B && cipherid1 <= 0x30) {
@@ -1723,13 +1768,13 @@ static void get_server_hello(tls_state_t *tls)
1723 } 1768 }
1724 } else { 1769 } else {
1725 /* All 00xx are RSA */ 1770 /* All 00xx are RSA */
1726 if (cipherid1 == 0x2F 1771 if ((ENABLE_FEATURE_TLS_SHA1 && cipherid1 == 0x2F)
1727 || cipherid1 == 0x3C 1772 || cipherid1 == 0x3C
1728 || cipherid1 == 0x9C 1773 || cipherid1 == 0x9C
1729 ) { 1774 ) {
1730 tls->key_size = AES128_KEYSIZE; 1775 tls->key_size = AES128_KEYSIZE;
1731 } 1776 }
1732 if (cipherid1 <= 0x35) { 1777 if (ENABLE_FEATURE_TLS_SHA1 && cipherid1 <= 0x35) {
1733 tls->MAC_size = SHA1_OUTSIZE; 1778 tls->MAC_size = SHA1_OUTSIZE;
1734 } else 1779 } else
1735 if (cipherid1 == 0x9C /*|| cipherid1 == 0x9D*/) { 1780 if (cipherid1 == 0x9C /*|| cipherid1 == 0x9D*/) {
@@ -2227,7 +2272,7 @@ void FAST_FUNC tls_handshake(tls_state_t *tls, const char *sni)
2227 tls->min_encrypted_len_on_read = tls->MAC_size; 2272 tls->min_encrypted_len_on_read = tls->MAC_size;
2228 } else 2273 } else
2229 if (!(tls->flags & ENCRYPTION_AESGCM)) { 2274 if (!(tls->flags & ENCRYPTION_AESGCM)) {
2230 unsigned mac_blocks = (unsigned)(tls->MAC_size + AES_BLOCK_SIZE-1) / AES_BLOCK_SIZE; 2275 unsigned mac_blocks = (unsigned)(TLS_MAC_SIZE(tls) + AES_BLOCK_SIZE-1) / AES_BLOCK_SIZE;
2231 /* all incoming packets now should be encrypted and have 2276 /* all incoming packets now should be encrypted and have
2232 * at least IV + (MAC padded to blocksize): 2277 * at least IV + (MAC padded to blocksize):
2233 */ 2278 */
diff --git a/networking/tls_aesgcm.c b/networking/tls_aesgcm.c
index 688df85fb..a4663cd79 100644
--- a/networking/tls_aesgcm.c
+++ b/networking/tls_aesgcm.c
@@ -35,38 +35,87 @@ static ALWAYS_INLINE void FlattenSzInBits(byte* buf, word32 sz)
35 35
36static void RIGHTSHIFTX(byte* x) 36static void RIGHTSHIFTX(byte* x)
37{ 37{
38 int i; 38#define l ((unsigned long*)x)
39 int carryOut = 0; 39#if 0
40 int carryIn = 0;
41 int borrow = x[15] & 0x01;
42 40
41 // Generic byte-at-a-time algorithm
42 int i;
43 byte carryIn = (x[15] & 0x01) ? 0xE1 : 0;
43 for (i = 0; i < AES_BLOCK_SIZE; i++) { 44 for (i = 0; i < AES_BLOCK_SIZE; i++) {
44 carryOut = x[i] & 0x01; 45 byte carryOut = (x[i] << 7); // zero, or 0x80
45 x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0); 46 x[i] = (x[i] >> 1) ^ carryIn;
47 carryIn = carryOut;
48 }
49
50#elif BB_BIG_ENDIAN
51
52 // Big-endian can shift-right in larger than byte chunks
53 // (we use the fact that 'x' is long-aligned)
54 unsigned long carryIn = (x[15] & 0x01)
55 ? ((unsigned long)0xE1 << (LONG_BIT-8))
56 : 0;
57# if ULONG_MAX <= 0xffffffff
58 int i;
59 for (i = 0; i < AES_BLOCK_SIZE/sizeof(long); i++) {
60 unsigned long carryOut = l[i] << (LONG_BIT-1); // zero, or 0x800..00
61 l[i] = (l[i] >> 1) ^ carryIn;
46 carryIn = carryOut; 62 carryIn = carryOut;
47 } 63 }
48 if (borrow) x[0] ^= 0xE1; 64# else
65 // 64-bit code: need to process only 2 words
66 unsigned long carryOut = l[0] << (LONG_BIT-1); // zero, or 0x800..00
67 l[0] = (l[0] >> 1) ^ carryIn;
68 l[1] = (l[1] >> 1) ^ carryOut;
69# endif
70
71#else /* LITTLE_ENDIAN */
72
73 // In order to use word-sized ops, little-endian needs to byteswap.
74 // On x86, code size increase is ~10 bytes compared to byte-by-byte.
75 unsigned long carryIn = (x[15] & 0x01)
76 ? ((unsigned long)0xE1 << (LONG_BIT-8))
77 : 0;
78# if ULONG_MAX <= 0xffffffff
79 int i;
80 for (i = 0; i < AES_BLOCK_SIZE/sizeof(long); i++) {
81 unsigned long ti = SWAP_BE32(l[i]);
82 unsigned long carryOut = ti << (LONG_BIT-1); // zero, or 0x800..00
83 ti = (ti >> 1) ^ carryIn;
84 l[i] = SWAP_BE32(ti);
85 carryIn = carryOut;
86 }
87# else
88 // 64-bit code: need to process only 2 words
89 unsigned long tt = SWAP_BE64(l[0]);
90 unsigned long carryOut = tt << (LONG_BIT-1); // zero, or 0x800..00
91 tt = (tt >> 1) ^ carryIn; l[0] = SWAP_BE64(tt);
92 tt = SWAP_BE64(l[1]);
93 tt = (tt >> 1) ^ carryOut; l[1] = SWAP_BE64(tt);
94# endif
95
96#endif /* LITTLE_ENDIAN */
97#undef l
49} 98}
50 99
100// Caller guarantees X is aligned
51static void GMULT(byte* X, byte* Y) 101static void GMULT(byte* X, byte* Y)
52{ 102{
53 byte Z[AES_BLOCK_SIZE] ALIGNED_long; 103 byte Z[AES_BLOCK_SIZE] ALIGNED_long;
54 byte V[AES_BLOCK_SIZE] ALIGNED_long; 104 //byte V[AES_BLOCK_SIZE] ALIGNED_long;
55 int i, j; 105 int i;
56 106
57 XMEMSET(Z, 0, AES_BLOCK_SIZE); 107 XMEMSET(Z, 0, AES_BLOCK_SIZE);
58 XMEMCPY(V, X, AES_BLOCK_SIZE); 108 //XMEMCPY(V, X, AES_BLOCK_SIZE);
59 for (i = 0; i < AES_BLOCK_SIZE; i++) 109 for (i = 0; i < AES_BLOCK_SIZE; i++) {
60 { 110 uint32_t y = 0x800000 | Y[i];
61 byte y = Y[i]; 111 for (;;) { // for every bit in Y[i], from msb to lsb
62 for (j = 0; j < 8; j++)
63 {
64 if (y & 0x80) { 112 if (y & 0x80) {
65 xorbuf_aligned_AES_BLOCK_SIZE(Z, V); 113 xorbuf_aligned_AES_BLOCK_SIZE(Z, X); // was V, not X
66 } 114 }
67 115 RIGHTSHIFTX(X); // was V, not X
68 RIGHTSHIFTX(V);
69 y = y << 1; 116 y = y << 1;
117 if ((int32_t)y < 0) // if bit 0x80000000 set = if 8 iterations done
118 break;
70 } 119 }
71 } 120 }
72 XMEMCPY(X, Z, AES_BLOCK_SIZE); 121 XMEMCPY(X, Z, AES_BLOCK_SIZE);
diff --git a/networking/tls_pstm.c b/networking/tls_pstm.c
index e12e6c9d4..e5544ab11 100644
--- a/networking/tls_pstm.c
+++ b/networking/tls_pstm.c
@@ -47,13 +47,18 @@
47//#include "../cryptoApi.h" 47//#include "../cryptoApi.h"
48#ifndef DISABLE_PSTM 48#ifndef DISABLE_PSTM
49 49
50#undef pstm_mul_2d
50static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c); //bbox: was int16 b 51static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c); //bbox: was int16 b
52#define pstm_mul_2d(a, b, c) (pstm_mul_2d(a, b, c), PSTM_OKAY)
51 53
52/******************************************************************************/ 54/******************************************************************************/
53/* 55/*
54 init an pstm_int for a given size 56 init an pstm_int for a given size
55 */ 57 */
56int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) 58#undef pstm_init_size
59#define pstm_init_size(pool, a, size) \
60 pstm_init_size( a, size)
61int32 FAST_FUNC pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size)
57{ 62{
58//bbox 63//bbox
59// uint16 x; 64// uint16 x;
@@ -75,12 +80,17 @@ int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size)
75// } 80// }
76 return PSTM_OKAY; 81 return PSTM_OKAY;
77} 82}
83#undef pstm_init_size
84#define pstm_init_size(pool, a, size) (pstm_init_size(a, size), PSTM_OKAY)
78 85
79/******************************************************************************/ 86/******************************************************************************/
80/* 87/*
81 Init a new pstm_int. 88 Init a new pstm_int.
82*/ 89*/
83int32 pstm_init(psPool_t *pool, pstm_int * a) 90#undef pstm_init
91#define pstm_init(pool, a) \
92 pstm_init( a)
93static int32 pstm_init(psPool_t *pool, pstm_int * a)
84{ 94{
85//bbox 95//bbox
86// int32 i; 96// int32 i;
@@ -106,12 +116,15 @@ int32 pstm_init(psPool_t *pool, pstm_int * a)
106 116
107 return PSTM_OKAY; 117 return PSTM_OKAY;
108} 118}
119#undef pstm_init
120#define pstm_init(pool, a) (pstm_init(a), PSTM_OKAY)
109 121
110/******************************************************************************/ 122/******************************************************************************/
111/* 123/*
112 Grow as required 124 Grow as required
113 */ 125 */
114int32 pstm_grow(pstm_int * a, int size) 126#undef pstm_grow
127int32 FAST_FUNC pstm_grow(pstm_int * a, int size)
115{ 128{
116 int i; //bbox: was int16 129 int i; //bbox: was int16
117 pstm_digit *tmp; 130 pstm_digit *tmp;
@@ -142,11 +155,13 @@ int32 pstm_grow(pstm_int * a, int size)
142 } 155 }
143 return PSTM_OKAY; 156 return PSTM_OKAY;
144} 157}
158#define pstm_grow(a, size) (pstm_grow(a, size), PSTM_OKAY)
145 159
146/******************************************************************************/ 160/******************************************************************************/
147/* 161/*
148 copy, b = a (b must be pre-allocated) 162 copy, b = a (b must be pre-allocated)
149 */ 163 */
164#undef pstm_copy
150int32 pstm_copy(pstm_int * a, pstm_int * b) 165int32 pstm_copy(pstm_int * a, pstm_int * b)
151{ 166{
152 int32 res, n; 167 int32 res, n;
@@ -195,6 +210,7 @@ int32 pstm_copy(pstm_int * a, pstm_int * b)
195 b->sign = a->sign; 210 b->sign = a->sign;
196 return PSTM_OKAY; 211 return PSTM_OKAY;
197} 212}
213#define pstm_copy(a, b) (pstm_copy(a, b), PSTM_OKAY)
198 214
199/******************************************************************************/ 215/******************************************************************************/
200/* 216/*
@@ -204,7 +220,7 @@ int32 pstm_copy(pstm_int * a, pstm_int * b)
204 leading "used" digit will be non-zero. Typically very fast. Also fixes 220 leading "used" digit will be non-zero. Typically very fast. Also fixes
205 the sign if there are no more leading digits 221 the sign if there are no more leading digits
206*/ 222*/
207void pstm_clamp(pstm_int * a) 223void FAST_FUNC pstm_clamp(pstm_int * a)
208{ 224{
209/* decrease used while the most significant digit is zero. */ 225/* decrease used while the most significant digit is zero. */
210 while (a->used > 0 && a->dp[a->used - 1] == 0) { 226 while (a->used > 0 && a->dp[a->used - 1] == 0) {
@@ -220,7 +236,7 @@ void pstm_clamp(pstm_int * a)
220/* 236/*
221 clear one (frees). 237 clear one (frees).
222 */ 238 */
223void pstm_clear(pstm_int * a) 239void FAST_FUNC pstm_clear(pstm_int * a)
224{ 240{
225 int32 i; 241 int32 i;
226/* 242/*
@@ -248,6 +264,7 @@ void pstm_clear(pstm_int * a)
248/* 264/*
249 clear many (frees). 265 clear many (frees).
250 */ 266 */
267#if 0 //UNUSED
251void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2, 268void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2,
252 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, 269 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5,
253 pstm_int *mp6, pstm_int *mp7) 270 pstm_int *mp6, pstm_int *mp7)
@@ -272,12 +289,13 @@ void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2,
272 } 289 }
273 } 290 }
274} 291}
292#endif
275 293
276/******************************************************************************/ 294/******************************************************************************/
277/* 295/*
278 Set to zero. 296 Set to zero.
279 */ 297 */
280void pstm_zero(pstm_int * a) 298static void pstm_zero(pstm_int * a)
281{ 299{
282 int32 n; 300 int32 n;
283 pstm_digit *tmp; 301 pstm_digit *tmp;
@@ -296,7 +314,7 @@ void pstm_zero(pstm_int * a)
296/* 314/*
297 Compare maginitude of two ints (unsigned). 315 Compare maginitude of two ints (unsigned).
298 */ 316 */
299int32 pstm_cmp_mag(pstm_int * a, pstm_int * b) 317int32 FAST_FUNC pstm_cmp_mag(pstm_int * a, pstm_int * b)
300{ 318{
301 int n; //bbox: was int16 319 int n; //bbox: was int16
302 pstm_digit *tmpa, *tmpb; 320 pstm_digit *tmpa, *tmpb;
@@ -336,7 +354,7 @@ int32 pstm_cmp_mag(pstm_int * a, pstm_int * b)
336/* 354/*
337 Compare two ints (signed) 355 Compare two ints (signed)
338 */ 356 */
339int32 pstm_cmp(pstm_int * a, pstm_int * b) 357int32 FAST_FUNC pstm_cmp(pstm_int * a, pstm_int * b)
340{ 358{
341/* 359/*
342 compare based on sign 360 compare based on sign
@@ -364,7 +382,7 @@ int32 pstm_cmp(pstm_int * a, pstm_int * b)
364 pstm_ints can be initialized more precisely when they will populated 382 pstm_ints can be initialized more precisely when they will populated
365 using pstm_read_unsigned_bin since the length of the byte stream is known 383 using pstm_read_unsigned_bin since the length of the byte stream is known
366*/ 384*/
367int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len) 385int32 FAST_FUNC pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len)
368{ 386{
369 int32 size; 387 int32 size;
370/* 388/*
@@ -385,7 +403,7 @@ int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len)
385 called pstm_init_for_read_unsigned_bin first. There is some grow logic 403 called pstm_init_for_read_unsigned_bin first. There is some grow logic
386 here if the default pstm_init was used but we don't really want to hit it. 404 here if the default pstm_init was used but we don't really want to hit it.
387*/ 405*/
388int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c) 406int32 FAST_FUNC pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c)
389{ 407{
390 /* zero the int */ 408 /* zero the int */
391 pstm_zero (a); 409 pstm_zero (a);
@@ -460,7 +478,7 @@ int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c)
460/******************************************************************************/ 478/******************************************************************************/
461/* 479/*
462*/ 480*/
463int pstm_count_bits (pstm_int * a) 481static int pstm_count_bits(pstm_int * a)
464{ 482{
465 int r; //bbox: was int16 483 int r; //bbox: was int16
466 pstm_digit q; 484 pstm_digit q;
@@ -482,14 +500,14 @@ int pstm_count_bits (pstm_int * a)
482} 500}
483 501
484/******************************************************************************/ 502/******************************************************************************/
485int32 pstm_unsigned_bin_size(pstm_int *a) 503int32 FAST_FUNC pstm_unsigned_bin_size(pstm_int *a)
486{ 504{
487 int32 size = pstm_count_bits (a); 505 int32 size = pstm_count_bits (a);
488 return (size / 8 + ((size & 7) != 0 ? 1 : 0)); 506 return (size / 8 + ((size & 7) != 0 ? 1 : 0));
489} 507}
490 508
491/******************************************************************************/ 509/******************************************************************************/
492void pstm_set(pstm_int *a, pstm_digit b) 510static void pstm_set(pstm_int *a, pstm_digit b)
493{ 511{
494 pstm_zero(a); 512 pstm_zero(a);
495 a->dp[0] = b; 513 a->dp[0] = b;
@@ -500,7 +518,7 @@ void pstm_set(pstm_int *a, pstm_digit b)
500/* 518/*
501 Right shift 519 Right shift
502*/ 520*/
503void pstm_rshd(pstm_int *a, int x) 521static void pstm_rshd(pstm_int *a, int x)
504{ 522{
505 int y; //bbox: was int16 523 int y; //bbox: was int16
506 524
@@ -529,7 +547,8 @@ void pstm_rshd(pstm_int *a, int x)
529/* 547/*
530 Shift left a certain amount of digits. 548 Shift left a certain amount of digits.
531 */ 549 */
532int32 pstm_lshd(pstm_int * a, int b) 550#undef pstm_lshd
551static int32 pstm_lshd(pstm_int * a, int b)
533{ 552{
534 int x; //bbox: was int16 553 int x; //bbox: was int16
535 int32 res; 554 int32 res;
@@ -577,12 +596,13 @@ int32 pstm_lshd(pstm_int * a, int b)
577 } 596 }
578 return PSTM_OKAY; 597 return PSTM_OKAY;
579} 598}
599#define pstm_lshd(a, b) (pstm_lshd(a, b), PSTM_OKAY)
580 600
581/******************************************************************************/ 601/******************************************************************************/
582/* 602/*
583 computes a = 2**b 603 computes a = 2**b
584*/ 604*/
585int32 pstm_2expt(pstm_int *a, int b) 605static int32 pstm_2expt(pstm_int *a, int b)
586{ 606{
587 int z; //bbox: was int16 607 int z; //bbox: was int16
588 608
@@ -616,7 +636,7 @@ int32 pstm_2expt(pstm_int *a, int b)
616/* 636/*
617 637
618*/ 638*/
619int32 pstm_mul_2(pstm_int * a, pstm_int * b) 639int32 FAST_FUNC pstm_mul_2(pstm_int * a, pstm_int * b)
620{ 640{
621 int32 res; 641 int32 res;
622 int x, oldused; //bbox: was int16 642 int x, oldused; //bbox: was int16
@@ -682,7 +702,7 @@ int32 pstm_mul_2(pstm_int * a, pstm_int * b)
682/* 702/*
683 unsigned subtraction ||a|| >= ||b|| ALWAYS! 703 unsigned subtraction ||a|| >= ||b|| ALWAYS!
684*/ 704*/
685int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) 705int32 FAST_FUNC s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
686{ 706{
687 int oldbused, oldused; //bbox: was int16 707 int oldbused, oldused; //bbox: was int16
688 int32 x; 708 int32 x;
@@ -779,7 +799,7 @@ static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
779/* 799/*
780 800
781*/ 801*/
782int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) 802int32 FAST_FUNC pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
783{ 803{
784 int32 res; 804 int32 res;
785 int sa, sb; //bbox: was int16 805 int sa, sb; //bbox: was int16
@@ -824,6 +844,7 @@ int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
824/* 844/*
825 c = a - b 845 c = a - b
826*/ 846*/
847#if 0 //UNUSED
827int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c) 848int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c)
828{ 849{
829 pstm_int tmp; 850 pstm_int tmp;
@@ -837,12 +858,13 @@ int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c)
837 pstm_clear(&tmp); 858 pstm_clear(&tmp);
838 return res; 859 return res;
839} 860}
861#endif
840 862
841/******************************************************************************/ 863/******************************************************************************/
842/* 864/*
843 setups the montgomery reduction 865 setups the montgomery reduction
844*/ 866*/
845int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho) 867static int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho)
846{ 868{
847 pstm_digit x, b; 869 pstm_digit x, b;
848 870
@@ -878,7 +900,7 @@ int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho)
878 * computes a = B**n mod b without division or multiplication useful for 900 * computes a = B**n mod b without division or multiplication useful for
879 * normalizing numbers in a Montgomery system. 901 * normalizing numbers in a Montgomery system.
880 */ 902 */
881int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b) 903static int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b)
882{ 904{
883 int32 x; 905 int32 x;
884 int bits; //bbox: was int16 906 int bits; //bbox: was int16
@@ -916,6 +938,7 @@ int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b)
916/* 938/*
917 c = a * 2**d 939 c = a * 2**d
918*/ 940*/
941#undef pstm_mul_2d
919static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c) 942static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c)
920{ 943{
921 pstm_digit carry, carrytmp, shift; 944 pstm_digit carry, carrytmp, shift;
@@ -956,11 +979,13 @@ static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c)
956 pstm_clamp(c); 979 pstm_clamp(c);
957 return PSTM_OKAY; 980 return PSTM_OKAY;
958} 981}
982#define pstm_mul_2d(a, b, c) (pstm_mul_2d(a, b, c), PSTM_OKAY)
959 983
960/******************************************************************************/ 984/******************************************************************************/
961/* 985/*
962 c = a mod 2**d 986 c = a mod 2**d
963*/ 987*/
988#undef pstm_mod_2d
964static int32 pstm_mod_2d(pstm_int *a, int b, pstm_int *c) //bbox: was int16 b 989static int32 pstm_mod_2d(pstm_int *a, int b, pstm_int *c) //bbox: was int16 b
965{ 990{
966 int x; //bbox: was int16 991 int x; //bbox: was int16
@@ -991,13 +1016,15 @@ static int32 pstm_mod_2d(pstm_int *a, int b, pstm_int *c) //bbox: was int16 b
991 pstm_clamp (c); 1016 pstm_clamp (c);
992 return PSTM_OKAY; 1017 return PSTM_OKAY;
993} 1018}
1019#define pstm_mod_2d(a, b, c) (pstm_mod_2d(a, b, c), PSTM_OKAY)
994 1020
995 1021
996/******************************************************************************/ 1022/******************************************************************************/
997/* 1023/*
998 c = a * b 1024 c = a * b
999*/ 1025*/
1000int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c) 1026#undef pstm_mul_d
1027static int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c)
1001{ 1028{
1002 pstm_word w; 1029 pstm_word w;
1003 int32 res; 1030 int32 res;
@@ -1027,12 +1054,16 @@ int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c)
1027 pstm_clamp(c); 1054 pstm_clamp(c);
1028 return PSTM_OKAY; 1055 return PSTM_OKAY;
1029} 1056}
1057#define pstm_mul_d(a, b, c) (pstm_mul_d(a, b, c), PSTM_OKAY)
1030 1058
1031/******************************************************************************/ 1059/******************************************************************************/
1032/* 1060/*
1033 c = a / 2**b 1061 c = a / 2**b
1034*/ 1062*/
1035int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c, 1063#undef pstm_div_2d
1064#define pstm_div_2d(pool, a, b, c, d) \
1065 pstm_div_2d( a, b, c, d)
1066static int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c,
1036 pstm_int *d) 1067 pstm_int *d)
1037{ 1068{
1038 pstm_digit D, r, rr; 1069 pstm_digit D, r, rr;
@@ -1113,11 +1144,14 @@ LBL_DONE:
1113 } 1144 }
1114 return res; 1145 return res;
1115} 1146}
1147#undef pstm_div_2d
1148#define pstm_div_2d(pool, a, b, c, d) (pstm_div_2d(a, b, c, d), PSTM_OKAY)
1116 1149
1117/******************************************************************************/ 1150/******************************************************************************/
1118/* 1151/*
1119 b = a/2 1152 b = a/2
1120*/ 1153*/
1154#if 0 //UNUSED
1121int32 pstm_div_2(pstm_int * a, pstm_int * b) 1155int32 pstm_div_2(pstm_int * a, pstm_int * b)
1122{ 1156{
1123 int x, oldused; //bbox: was int16 1157 int x, oldused; //bbox: was int16
@@ -1161,12 +1195,16 @@ int32 pstm_div_2(pstm_int * a, pstm_int * b)
1161 pstm_clamp (b); 1195 pstm_clamp (b);
1162 return PSTM_OKAY; 1196 return PSTM_OKAY;
1163} 1197}
1198#endif
1164 1199
1165/******************************************************************************/ 1200/******************************************************************************/
1166/* 1201/*
1167 Creates "a" then copies b into it 1202 Creates "a" then copies b into it
1168 */ 1203 */
1169int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int toSqr) 1204#undef pstm_init_copy
1205#define pstm_init_copy(pool, a, b, toSqr) \
1206 pstm_init_copy( a, b, toSqr)
1207static int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int toSqr)
1170{ 1208{
1171 int x; //bbox: was int16 1209 int x; //bbox: was int16
1172 int32 res; 1210 int32 res;
@@ -1191,6 +1229,8 @@ int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int toSqr)
1191 } 1229 }
1192 return pstm_copy(b, a); 1230 return pstm_copy(b, a);
1193} 1231}
1232#undef pstm_init_copy
1233#define pstm_init_copy(pool, a, b, toSqr) (pstm_init_copy(a, b, toSqr), PSTM_OKAY)
1194 1234
1195/******************************************************************************/ 1235/******************************************************************************/
1196/* 1236/*
@@ -1274,7 +1314,7 @@ static uint64 psDiv128(uint128 *numerator, uint64 denominator)
1274/* 1314/*
1275 a/b => cb + d == a 1315 a/b => cb + d == a
1276*/ 1316*/
1277int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, 1317static int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1278 pstm_int *d) 1318 pstm_int *d)
1279{ 1319{
1280 pstm_int q, x, y, t1, t2; 1320 pstm_int q, x, y, t1, t2;
@@ -1487,7 +1527,7 @@ LBL_T1:pstm_clear (&t1);
1487 Swap the elements of two integers, for cases where you can't simply swap 1527 Swap the elements of two integers, for cases where you can't simply swap
1488 the pstm_int pointers around 1528 the pstm_int pointers around
1489*/ 1529*/
1490void pstm_exch(pstm_int * a, pstm_int * b) 1530static void pstm_exch(pstm_int * a, pstm_int * b)
1491{ 1531{
1492 pstm_int t; 1532 pstm_int t;
1493 1533
@@ -1500,7 +1540,7 @@ void pstm_exch(pstm_int * a, pstm_int * b)
1500/* 1540/*
1501 c = a mod b, 0 <= c < b 1541 c = a mod b, 0 <= c < b
1502*/ 1542*/
1503int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c) 1543static int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
1504{ 1544{
1505 pstm_int t; 1545 pstm_int t;
1506 int32 err; 1546 int32 err;
@@ -1527,7 +1567,7 @@ int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
1527/* 1567/*
1528 d = a * b (mod c) 1568 d = a * b (mod c)
1529*/ 1569*/
1530int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, 1570int32 FAST_FUNC pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1531 pstm_int *d) 1571 pstm_int *d)
1532{ 1572{
1533 int32 res; 1573 int32 res;
@@ -1560,7 +1600,7 @@ int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
1560 * y = g**x (mod b) 1600 * y = g**x (mod b)
1561 * Some restrictions... x must be positive and < b 1601 * Some restrictions... x must be positive and < b
1562 */ 1602 */
1563int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, 1603int32 FAST_FUNC pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
1564 pstm_int *Y) 1604 pstm_int *Y)
1565{ 1605{
1566 pstm_int M[32], res; /* Keep this winsize based: (1 << max_winsize) */ 1606 pstm_int M[32], res; /* Keep this winsize based: (1 << max_winsize) */
@@ -1801,7 +1841,7 @@ LBL_RES:pstm_clear(&res);
1801/* 1841/*
1802 1842
1803*/ 1843*/
1804int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) 1844int32 FAST_FUNC pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
1805{ 1845{
1806 int32 res; 1846 int32 res;
1807 int sa, sb; //bbox: was int16 1847 int sa, sb; //bbox: was int16
@@ -1862,6 +1902,7 @@ static void pstm_reverse (unsigned char *s, int len) //bbox: was int16 len
1862 No reverse. Useful in some of the EIP-154 PKA stuff where special byte 1902 No reverse. Useful in some of the EIP-154 PKA stuff where special byte
1863 order seems to come into play more often 1903 order seems to come into play more often
1864*/ 1904*/
1905#if 0 //UNUSED
1865int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b) 1906int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b)
1866{ 1907{
1867 int32 res; 1908 int32 res;
@@ -1883,11 +1924,12 @@ int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b)
1883 pstm_clear(&t); 1924 pstm_clear(&t);
1884 return PS_SUCCESS; 1925 return PS_SUCCESS;
1885} 1926}
1927#endif
1886/******************************************************************************/ 1928/******************************************************************************/
1887/* 1929/*
1888 1930
1889*/ 1931*/
1890int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b) 1932int32 FAST_FUNC pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b)
1891{ 1933{
1892 int32 res; 1934 int32 res;
1893 int x; //bbox: was int16 1935 int x; //bbox: was int16
@@ -1910,11 +1952,12 @@ int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b)
1910 return PS_SUCCESS; 1952 return PS_SUCCESS;
1911} 1953}
1912 1954
1955#if 0 //UNUSED
1913/******************************************************************************/ 1956/******************************************************************************/
1914/* 1957/*
1915 compare against a single digit 1958 compare against a single digit
1916*/ 1959*/
1917int32 pstm_cmp_d(pstm_int *a, pstm_digit b) 1960static int32 pstm_cmp_d(pstm_int *a, pstm_digit b)
1918{ 1961{
1919 /* compare based on sign */ 1962 /* compare based on sign */
1920 if ((b && a->used == 0) || a->sign == PSTM_NEG) { 1963 if ((b && a->used == 0) || a->sign == PSTM_NEG) {
@@ -2259,5 +2302,7 @@ LBL_Y: pstm_clear(&y);
2259LBL_X: pstm_clear(&x); 2302LBL_X: pstm_clear(&x);
2260 return res; 2303 return res;
2261} 2304}
2305#endif //UNUSED
2306
2262#endif /* !DISABLE_PSTM */ 2307#endif /* !DISABLE_PSTM */
2263/******************************************************************************/ 2308/******************************************************************************/
diff --git a/networking/tls_pstm.h b/networking/tls_pstm.h
index df705adce..bc7a0119a 100644
--- a/networking/tls_pstm.h
+++ b/networking/tls_pstm.h
@@ -136,148 +136,148 @@ typedef struct {
136#define pstm_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? PS_TRUE : PS_FALSE) 136#define pstm_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? PS_TRUE : PS_FALSE)
137#define pstm_abs(a, b) { pstm_copy(a, b); (b)->sign = 0; } 137#define pstm_abs(a, b) { pstm_copy(a, b); (b)->sign = 0; }
138 138
139extern void pstm_set(pstm_int *a, pstm_digit b); 139//made static:extern void pstm_set(pstm_int *a, pstm_digit b);
140 140
141extern void pstm_zero(pstm_int * a); 141//made static:extern void pstm_zero(pstm_int * a);
142 142
143//bbox: pool unused 143//bbox: pool unused
144#define pstm_init(pool, a) \ 144#define pstm_init(pool, a) \
145 pstm_init( a) 145 pstm_init( a)
146extern int32 pstm_init(psPool_t *pool, pstm_int * a); 146//made static:extern int32 pstm_init(psPool_t *pool, pstm_int * a);
147 147
148//bbox: pool unused 148//bbox: pool unused
149#define pstm_init_size(pool, a, size) \ 149#define pstm_init_size(pool, a, size) \
150 pstm_init_size( a, size) 150 pstm_init_size( a, size)
151extern int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size); 151extern int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size) FAST_FUNC;
152 152
153//bbox: pool unused 153//bbox: pool unused
154#define pstm_init_copy(pool, a, b, toSqr) \ 154#define pstm_init_copy(pool, a, b, toSqr) \
155 pstm_init_copy( a, b, toSqr) 155 pstm_init_copy( a, b, toSqr)
156extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, 156//made static:extern int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b,
157 int toSqr); //bbox: was int16 toSqr 157//made static: int toSqr); //bbox: was int16 toSqr
158 158
159extern int pstm_count_bits (pstm_int * a); //bbox: was returning int16 159//made static:extern int pstm_count_bits (pstm_int * a) FAST_FUNC; //bbox: was returning int16
160 160
161//bbox: pool unused 161//bbox: pool unused
162#define pstm_init_for_read_unsigned_bin(pool, a, len) \ 162#define pstm_init_for_read_unsigned_bin(pool, a, len) \
163 pstm_init_for_read_unsigned_bin( a, len) 163 pstm_init_for_read_unsigned_bin( a, len)
164extern int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, 164extern int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a,
165 uint32 len); 165 uint32 len) FAST_FUNC;
166 166
167extern int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c); 167extern int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c) FAST_FUNC;
168 168
169extern int32 pstm_unsigned_bin_size(pstm_int *a); 169extern int32 pstm_unsigned_bin_size(pstm_int *a) FAST_FUNC;
170 170
171extern int32 pstm_copy(pstm_int * a, pstm_int * b); 171extern int32 pstm_copy(pstm_int * a, pstm_int * b);
172 172
173extern void pstm_exch(pstm_int * a, pstm_int * b); 173//made static:extern void pstm_exch(pstm_int * a, pstm_int * b);
174 174
175extern void pstm_clear(pstm_int * a); 175extern void pstm_clear(pstm_int * a) FAST_FUNC;
176 176
177extern void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2, 177extern void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2,
178 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, pstm_int *mp6, 178 pstm_int *mp3, pstm_int *mp4, pstm_int *mp5, pstm_int *mp6,
179 pstm_int *mp7); 179 pstm_int *mp7) FAST_FUNC;
180 180
181extern int32 pstm_grow(pstm_int * a, int size); //bbox: was int16 size 181extern int32 pstm_grow(pstm_int * a, int size) FAST_FUNC; //bbox: was int16 size
182 182
183extern void pstm_clamp(pstm_int * a); 183extern void pstm_clamp(pstm_int * a) FAST_FUNC;
184 184
185extern int32 pstm_cmp(pstm_int * a, pstm_int * b); 185extern int32 pstm_cmp(pstm_int * a, pstm_int * b) FAST_FUNC;
186 186
187extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b); 187extern int32 pstm_cmp_mag(pstm_int * a, pstm_int * b) FAST_FUNC;
188 188
189extern void pstm_rshd(pstm_int *a, int x); //bbox: was int16 x 189//made static:extern void pstm_rshd(pstm_int *a, int x); //bbox: was int16 x
190 190
191extern int32 pstm_lshd(pstm_int * a, int b); //bbox: was int16 b 191//made static:extern int32 pstm_lshd(pstm_int * a, int b); //bbox: was int16 b
192 192
193//bbox: pool unused 193//bbox: pool unused
194#define pstm_div(pool, a, b, c, d) \ 194#define pstm_div(pool, a, b, c, d) \
195 pstm_div( a, b, c, d) 195 pstm_div( a, b, c, d)
196extern int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, 196//made static:extern int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
197 pstm_int *d); 197//made static: pstm_int *d);
198 198
199//bbox: pool unused 199//bbox: pool unused
200#define pstm_div_2d(pool, a, b, c, d) \ 200#define pstm_div_2d(pool, a, b, c, d) \
201 pstm_div_2d( a, b, c, d) 201 pstm_div_2d( a, b, c, d)
202extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c, 202//made static:extern int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c,
203 pstm_int *d); //bbox: was int16 b 203//made static: pstm_int *d); //bbox: was int16 b
204 204
205extern int32 pstm_div_2(pstm_int * a, pstm_int * b); 205extern int32 pstm_div_2(pstm_int * a, pstm_int * b) FAST_FUNC;
206 206
207extern int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c); 207extern int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) FAST_FUNC;
208 208
209extern int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c); 209extern int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c) FAST_FUNC;
210 210
211//bbox: pool unused 211//bbox: pool unused
212#define pstm_sub_d(pool, a, b, c) \ 212#define pstm_sub_d(pool, a, b, c) \
213 pstm_sub_d( a, b, c) 213 pstm_sub_d( a, b, c)
214extern int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c); 214extern int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c) FAST_FUNC;
215 215
216extern int32 pstm_mul_2(pstm_int * a, pstm_int * b); 216extern int32 pstm_mul_2(pstm_int * a, pstm_int * b) FAST_FUNC;
217 217
218//bbox: pool unused 218//bbox: pool unused
219#define pstm_mod(pool, a, b, c) \ 219#define pstm_mod(pool, a, b, c) \
220 pstm_mod( a, b, c) 220 pstm_mod( a, b, c)
221extern int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c); 221//made static:extern int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c);
222 222
223//bbox: pool unused 223//bbox: pool unused
224#define pstm_mulmod(pool, a, b, c, d) \ 224#define pstm_mulmod(pool, a, b, c, d) \
225 pstm_mulmod( a, b, c, d) 225 pstm_mulmod( a, b, c, d)
226extern int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c, 226extern int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
227 pstm_int *d); 227 pstm_int *d) FAST_FUNC;
228 228
229//bbox: pool unused 229//bbox: pool unused
230#define pstm_exptmod(pool, G, X, P, Y) \ 230#define pstm_exptmod(pool, G, X, P, Y) \
231 pstm_exptmod( G, X, P, Y) 231 pstm_exptmod( G, X, P, Y)
232extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P, 232extern int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
233 pstm_int *Y); 233 pstm_int *Y) FAST_FUNC;
234 234
235extern int32 pstm_2expt(pstm_int *a, int b); //bbox: was int16 b 235//made static:extern int32 pstm_2expt(pstm_int *a, int b); //bbox: was int16 b
236 236
237extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c); 237extern int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c) FAST_FUNC;
238 238
239//bbox: pool unused 239//bbox: pool unused
240#define pstm_to_unsigned_bin(pool, a, b) \ 240#define pstm_to_unsigned_bin(pool, a, b) \
241 pstm_to_unsigned_bin( a, b) 241 pstm_to_unsigned_bin( a, b)
242extern int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, 242extern int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a,
243 unsigned char *b); 243 unsigned char *b) FAST_FUNC;
244 244
245//bbox: pool unused 245//bbox: pool unused
246#define pstm_to_unsigned_bin_nr(pool, a, b) \ 246#define pstm_to_unsigned_bin_nr(pool, a, b) \
247 pstm_to_unsigned_bin_nr( a, b) 247 pstm_to_unsigned_bin_nr( a, b)
248extern int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, 248extern int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a,
249 unsigned char *b); 249 unsigned char *b) FAST_FUNC;
250 250
251extern int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho); 251//made static:extern int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho);
252 252
253//bbox: pool unused 253//bbox: pool unused
254#define pstm_montgomery_reduce(pool, a, m, mp, paD, paDlen) \ 254#define pstm_montgomery_reduce(pool, a, m, mp, paD, paDlen) \
255 pstm_montgomery_reduce( a, m, mp, paD, paDlen) 255 pstm_montgomery_reduce( a, m, mp, paD, paDlen)
256extern int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, 256extern int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m,
257 pstm_digit mp, pstm_digit *paD, uint32 paDlen); 257 pstm_digit mp, pstm_digit *paD, uint32 paDlen) FAST_FUNC;
258 258
259#define pstm_mul_comba(pool, A, B, C, paD, paDlen) \ 259#define pstm_mul_comba(pool, A, B, C, paD, paDlen) \
260 pstm_mul_comba( A, B, C, paD, paDlen) 260 pstm_mul_comba( A, B, C, paD, paDlen)
261extern int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, 261extern int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B,
262 pstm_int *C, pstm_digit *paD, uint32 paDlen); 262 pstm_int *C, pstm_digit *paD, uint32 paDlen) FAST_FUNC;
263 263
264//bbox: pool unused 264//bbox: pool unused
265#define pstm_sqr_comba(pool, A, B, paD, paDlen) \ 265#define pstm_sqr_comba(pool, A, B, paD, paDlen) \
266 pstm_sqr_comba( A, B, paD, paDlen) 266 pstm_sqr_comba( A, B, paD, paDlen)
267extern int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, 267extern int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B,
268 pstm_digit *paD, uint32 paDlen); 268 pstm_digit *paD, uint32 paDlen) FAST_FUNC;
269 269
270extern int32 pstm_cmp_d(pstm_int *a, pstm_digit b); 270//made static:extern int32 pstm_cmp_d(pstm_int *a, pstm_digit b);
271 271
272extern int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b); 272//made static:extern int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b);
273 273
274extern int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c); 274//made static:extern int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c);
275 275
276//bbox: pool unused 276//bbox: pool unused
277#define pstm_invmod(pool, a, b, c) \ 277#define pstm_invmod(pool, a, b, c) \
278 pstm_invmod( a, b, c) 278 pstm_invmod( a, b, c)
279extern int32 pstm_invmod(psPool_t *pool, pstm_int * a, pstm_int * b, 279extern int32 pstm_invmod(psPool_t *pool, pstm_int * a, pstm_int * b,
280 pstm_int * c); 280 pstm_int * c) FAST_FUNC;
281 281
282#else /* DISABLE_PSTM */ 282#else /* DISABLE_PSTM */
283 typedef int32 pstm_int; 283 typedef int32 pstm_int;
diff --git a/networking/tls_pstm_montgomery_reduce.c b/networking/tls_pstm_montgomery_reduce.c
index 3391755e1..d46e2aa2b 100644
--- a/networking/tls_pstm_montgomery_reduce.c
+++ b/networking/tls_pstm_montgomery_reduce.c
@@ -340,7 +340,7 @@ asm( \
340#define LO 0 340#define LO 0
341 341
342/* computes x/R == x (mod N) via Montgomery Reduction */ 342/* computes x/R == x (mod N) via Montgomery Reduction */
343int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, 343int32 FAST_FUNC pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m,
344 pstm_digit mp, pstm_digit *paD, uint32 paDlen) 344 pstm_digit mp, pstm_digit *paD, uint32 paDlen)
345{ 345{
346 pstm_digit *c, *_c, *tmpm, mu; 346 pstm_digit *c, *_c, *tmpm, mu;
diff --git a/networking/tls_pstm_mul_comba.c b/networking/tls_pstm_mul_comba.c
index 6ba152bc1..ac4fcc3ef 100644
--- a/networking/tls_pstm_mul_comba.c
+++ b/networking/tls_pstm_mul_comba.c
@@ -754,7 +754,7 @@ static int32 pstm_mul_comba32(pstm_int *A, pstm_int *B, pstm_int *C)
754 754
755/******************************************************************************/ 755/******************************************************************************/
756 756
757int32 pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C, 757int32 FAST_FUNC pstm_mul_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_int *C,
758 pstm_digit *paD, uint32 paDlen) 758 pstm_digit *paD, uint32 paDlen)
759{ 759{
760#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS 760#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
diff --git a/networking/tls_pstm_sqr_comba.c b/networking/tls_pstm_sqr_comba.c
index d5c74d2f0..8604132d6 100644
--- a/networking/tls_pstm_sqr_comba.c
+++ b/networking/tls_pstm_sqr_comba.c
@@ -1085,7 +1085,7 @@ static int32 pstm_sqr_comba32(pstm_int *A, pstm_int *B)
1085/******************************************************************************/ 1085/******************************************************************************/
1086/* 1086/*
1087 */ 1087 */
1088int32 pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_digit *paD, 1088int32 FAST_FUNC pstm_sqr_comba(psPool_t *pool, pstm_int *A, pstm_int *B, pstm_digit *paD,
1089 uint32 paDlen) 1089 uint32 paDlen)
1090{ 1090{
1091#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS 1091#ifdef USE_1024_KEY_SPEED_OPTIMIZATIONS
diff --git a/networking/tls_rsa.c b/networking/tls_rsa.c
index 631397e4d..5fda1cb49 100644
--- a/networking/tls_rsa.c
+++ b/networking/tls_rsa.c
@@ -173,7 +173,9 @@ error:
173 res = PS_FAILURE; 173 res = PS_FAILURE;
174done: 174done:
175 if (type == PRIVKEY_TYPE && key->optimized) { 175 if (type == PRIVKEY_TYPE && key->optimized) {
176 pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL); 176 //pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL);
177 pstm_clear(&tmpa);
178 pstm_clear(&tmpb);
177 } 179 }
178 pstm_clear(&tmp); 180 pstm_clear(&tmp);
179 return res; 181 return res;
diff --git a/networking/traceroute.c b/networking/traceroute.c
index a027b928a..bdf451186 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -217,7 +217,7 @@
217//config: Utility to trace the route of IP packets. 217//config: Utility to trace the route of IP packets.
218//config: 218//config:
219//config:config TRACEROUTE6 219//config:config TRACEROUTE6
220//config: bool "traceroute6 (12 kb)" 220//config: bool "traceroute6 (13 kb)"
221//config: default y 221//config: default y
222//config: depends on FEATURE_IPV6 222//config: depends on FEATURE_IPV6
223//config: help 223//config: help
diff --git a/networking/tunctl.c b/networking/tunctl.c
index f2dc645a1..a0e3926e9 100644
--- a/networking/tunctl.c
+++ b/networking/tunctl.c
@@ -10,7 +10,7 @@
10 * Licensed under GPLv2, see file LICENSE in this source tree. 10 * Licensed under GPLv2, see file LICENSE in this source tree.
11 */ 11 */
12//config:config TUNCTL 12//config:config TUNCTL
13//config: bool "tunctl (6.4 kb)" 13//config: bool "tunctl (6.2 kb)"
14//config: default y 14//config: default y
15//config: select PLATFORM_LINUX 15//config: select PLATFORM_LINUX
16//config: help 16//config: help
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src
index e5958804b..f16fc0a4f 100644
--- a/networking/udhcp/Config.src
+++ b/networking/udhcp/Config.src
@@ -4,7 +4,7 @@
4# 4#
5 5
6config UDHCPD 6config UDHCPD
7 bool "udhcpd" 7 bool "udhcpd (21 kb)"
8 default y 8 default y
9 select PLATFORM_LINUX 9 select PLATFORM_LINUX
10 help 10 help
@@ -44,7 +44,7 @@ config DHCPD_LEASES_FILE
44 of the file. Normally it is safe to leave it untouched. 44 of the file. Normally it is safe to leave it untouched.
45 45
46config DUMPLEASES 46config DUMPLEASES
47 bool "dumpleases (6.4 kb)" 47 bool "dumpleases (5.1 kb)"
48 default y 48 default y
49 help 49 help
50 dumpleases displays the leases written out by the udhcpd. 50 dumpleases displays the leases written out by the udhcpd.
@@ -52,7 +52,7 @@ config DUMPLEASES
52 by the absolute time that it expires in seconds from epoch. 52 by the absolute time that it expires in seconds from epoch.
53 53
54config DHCPRELAY 54config DHCPRELAY
55 bool "dhcprelay (5.8 kb)" 55 bool "dhcprelay (5.2 kb)"
56 default y 56 default y
57 help 57 help
58 dhcprelay listens for DHCP requests on one or more interfaces 58 dhcprelay listens for DHCP requests on one or more interfaces
@@ -60,7 +60,7 @@ config DHCPRELAY
60 server. 60 server.
61 61
62config UDHCPC 62config UDHCPC
63 bool "udhcpc" 63 bool "udhcpc (24 kb)"
64 default y 64 default y
65 select PLATFORM_LINUX 65 select PLATFORM_LINUX
66 help 66 help
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index e5fd74f91..fc4de5716 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -272,6 +272,15 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code)
272 goto complain; /* complain and return NULL */ 272 goto complain; /* complain and return NULL */
273 273
274 if (optionptr[OPT_CODE] == code) { 274 if (optionptr[OPT_CODE] == code) {
275 if (optionptr[OPT_LEN] == 0) {
276 /* So far no valid option with length 0 known.
277 * Having this check means that searching
278 * for DHCP_MESSAGE_TYPE need not worry
279 * that returned pointer might be unsafe
280 * to dereference.
281 */
282 goto complain; /* complain and return NULL */
283 }
275 log_option("option found", optionptr); 284 log_option("option found", optionptr);
276 return optionptr + OPT_DATA; 285 return optionptr + OPT_DATA;
277 } 286 }
@@ -289,6 +298,16 @@ uint8_t* FAST_FUNC udhcp_get_option(struct dhcp_packet *packet, int code)
289 return NULL; 298 return NULL;
290} 299}
291 300
301uint8_t* FAST_FUNC udhcp_get_option32(struct dhcp_packet *packet, int code)
302{
303 uint8_t *r = udhcp_get_option(packet, code);
304 if (r) {
305 if (r[-OPT_DATA + OPT_LEN] != 4)
306 r = NULL;
307 }
308 return r;
309}
310
292/* Return the position of the 'end' option (no bounds checking) */ 311/* Return the position of the 'end' option (no bounds checking) */
293int FAST_FUNC udhcp_end_option(uint8_t *optionptr) 312int FAST_FUNC udhcp_end_option(uint8_t *optionptr)
294{ 313{
@@ -403,6 +422,7 @@ static NOINLINE void attach_option(
403 if (errno) 422 if (errno)
404 bb_error_msg_and_die("malformed hex string '%s'", buffer); 423 bb_error_msg_and_die("malformed hex string '%s'", buffer);
405 length = end - allocated; 424 length = end - allocated;
425 buffer = allocated;
406 } 426 }
407#if ENABLE_FEATURE_UDHCP_RFC3397 427#if ENABLE_FEATURE_UDHCP_RFC3397
408 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) { 428 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_DNS_STRING) {
@@ -422,15 +442,14 @@ static NOINLINE void attach_option(
422 new->data = xmalloc(length + OPT_DATA); 442 new->data = xmalloc(length + OPT_DATA);
423 new->data[OPT_CODE] = optflag->code; 443 new->data[OPT_CODE] = optflag->code;
424 new->data[OPT_LEN] = length; 444 new->data[OPT_LEN] = length;
425 memcpy(new->data + OPT_DATA, (allocated ? allocated : buffer), 445 memcpy(new->data + OPT_DATA, buffer, length);
426 length);
427 } else { 446 } else {
428 new->data = xmalloc(length + D6_OPT_DATA); 447 new->data = xmalloc(length + D6_OPT_DATA);
429 new->data[D6_OPT_CODE] = optflag->code >> 8; 448 new->data[D6_OPT_CODE] = optflag->code >> 8;
430 new->data[D6_OPT_CODE + 1] = optflag->code & 0xff; 449 new->data[D6_OPT_CODE + 1] = optflag->code & 0xff;
431 new->data[D6_OPT_LEN] = length >> 8; 450 new->data[D6_OPT_LEN] = length >> 8;
432 new->data[D6_OPT_LEN + 1] = length & 0xff; 451 new->data[D6_OPT_LEN + 1] = length & 0xff;
433 memcpy(new->data + D6_OPT_DATA, (allocated ? allocated : buffer), 452 memcpy(new->data + D6_OPT_DATA, buffer,
434 length); 453 length);
435 } 454 }
436 455
@@ -453,6 +472,8 @@ static NOINLINE void attach_option(
453 /* actually 255 is ok too, but adding a space can overlow it */ 472 /* actually 255 is ok too, but adding a space can overlow it */
454 473
455 existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); 474 existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length);
475// So far dhcp_optflags[] has no OPTION_STRING[_HOST] | OPTION_LIST items
476#if 0
456 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING 477 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING
457 || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST 478 || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST
458 ) { 479 ) {
@@ -460,7 +481,9 @@ static NOINLINE void attach_option(
460 existing->data[OPT_DATA + old_len] = ' '; 481 existing->data[OPT_DATA + old_len] = ' ';
461 old_len++; 482 old_len++;
462 } 483 }
463 memcpy(existing->data + OPT_DATA + old_len, (allocated ? allocated : buffer), length); 484#endif
485
486 memcpy(existing->data + OPT_DATA + old_len, buffer, length);
464 existing->data[OPT_LEN] = old_len + length; 487 existing->data[OPT_LEN] = old_len + length;
465 } /* else, ignore the data, we could put this in a second option in the future */ 488 } /* else, ignore the data, we could put this in a second option in the future */
466 } /* else, ignore the new data */ 489 } /* else, ignore the new data */
@@ -534,7 +557,7 @@ int FAST_FUNC udhcp_str2optset(const char *const_str, void *arg,
534 if (retval) 557 if (retval)
535 retval = udhcp_str2nip(val, buffer + 4); 558 retval = udhcp_str2nip(val, buffer + 4);
536 break; 559 break;
537case_OPTION_STRING: 560 case_OPTION_STRING:
538 case OPTION_STRING: 561 case OPTION_STRING:
539 case OPTION_STRING_HOST: 562 case OPTION_STRING_HOST:
540#if ENABLE_FEATURE_UDHCP_RFC3397 563#if ENABLE_FEATURE_UDHCP_RFC3397
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 7ad603d33..62f9a2a4a 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -119,7 +119,7 @@ enum {
119//#define DHCP_TIME_SERVER 0x04 /* RFC 868 time server (32-bit, 0 = 1.1.1900) */ 119//#define DHCP_TIME_SERVER 0x04 /* RFC 868 time server (32-bit, 0 = 1.1.1900) */
120//#define DHCP_NAME_SERVER 0x05 /* IEN 116 _really_ ancient kind of NS */ 120//#define DHCP_NAME_SERVER 0x05 /* IEN 116 _really_ ancient kind of NS */
121//#define DHCP_DNS_SERVER 0x06 121//#define DHCP_DNS_SERVER 0x06
122//#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) 122//#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) */
123//#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */ 123//#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */
124//#define DHCP_LPR_SERVER 0x09 124//#define DHCP_LPR_SERVER 0x09
125#define DHCP_HOST_NAME 0x0c /* 12: either client informs server or server gives name to client */ 125#define DHCP_HOST_NAME 0x0c /* 12: either client informs server or server gives name to client */
@@ -205,6 +205,10 @@ extern const uint8_t dhcp_option_lengths[] ALIGN1;
205unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings); 205unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings);
206 206
207uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; 207uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC;
208/* Same as above + ensures that option length is 4 bytes
209 * (returns NULL if size is different)
210 */
211uint8_t *udhcp_get_option32(struct dhcp_packet *packet, int code) FAST_FUNC;
208int udhcp_end_option(uint8_t *optionptr) FAST_FUNC; 212int udhcp_end_option(uint8_t *optionptr) FAST_FUNC;
209void udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt) FAST_FUNC; 213void udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt) FAST_FUNC;
210#if ENABLE_UDHCPC || ENABLE_UDHCPD 214#if ENABLE_UDHCPC || ENABLE_UDHCPD
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 3c6129249..38c91cbb4 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2, see file LICENSE in this source tree. 9 * Licensed under GPLv2, see file LICENSE in this source tree.
10 */ 10 */
11//config:config UDHCPC6 11//config:config UDHCPC6
12//config: bool "udhcpc6" 12//config: bool "udhcpc6 (21 kb)"
13//config: default n # not yet ready 13//config: default n # not yet ready
14//config: depends on FEATURE_IPV6 14//config: depends on FEATURE_IPV6
15//config: help 15//config: help
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 4b23e4d39..dcec8cdfd 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -531,7 +531,7 @@ static char **fill_envp(struct dhcp_packet *packet)
531 temp = udhcp_get_option(packet, code); 531 temp = udhcp_get_option(packet, code);
532 *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name); 532 *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name);
533 putenv(*curr++); 533 putenv(*curr++);
534 if (code == DHCP_SUBNET) { 534 if (code == DHCP_SUBNET && temp[-OPT_DATA + OPT_LEN] == 4) {
535 /* Subnet option: make things like "$ip/$mask" possible */ 535 /* Subnet option: make things like "$ip/$mask" possible */
536 uint32_t subnet; 536 uint32_t subnet;
537 move_from_unaligned32(subnet, temp); 537 move_from_unaligned32(subnet, temp);
@@ -1691,7 +1691,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1691 * They say ISC DHCP client supports this case. 1691 * They say ISC DHCP client supports this case.
1692 */ 1692 */
1693 server_addr = 0; 1693 server_addr = 0;
1694 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1694 temp = udhcp_get_option32(&packet, DHCP_SERVER_ID);
1695 if (!temp) { 1695 if (!temp) {
1696 bb_error_msg("no server ID, using 0.0.0.0"); 1696 bb_error_msg("no server ID, using 0.0.0.0");
1697 } else { 1697 } else {
@@ -1718,7 +1718,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1718 struct in_addr temp_addr; 1718 struct in_addr temp_addr;
1719 uint8_t *temp; 1719 uint8_t *temp;
1720 1720
1721 temp = udhcp_get_option(&packet, DHCP_LEASE_TIME); 1721 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME);
1722 if (!temp) { 1722 if (!temp) {
1723 bb_error_msg("no lease time with ACK, using 1 hour lease"); 1723 bb_error_msg("no lease time with ACK, using 1 hour lease");
1724 lease_seconds = 60 * 60; 1724 lease_seconds = 60 * 60;
@@ -1813,7 +1813,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1813 uint32_t svid; 1813 uint32_t svid;
1814 uint8_t *temp; 1814 uint8_t *temp;
1815 1815
1816 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1816 temp = udhcp_get_option32(&packet, DHCP_SERVER_ID);
1817 if (!temp) { 1817 if (!temp) {
1818 non_matching_svid: 1818 non_matching_svid:
1819 log1("received DHCP NAK with wrong" 1819 log1("received DHCP NAK with wrong"
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index a8cd3f03b..0c55fa5e4 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -378,7 +378,7 @@ struct config_keyword {
378#define OFS(field) offsetof(struct server_config_t, field) 378#define OFS(field) offsetof(struct server_config_t, field)
379 379
380static const struct config_keyword keywords[] = { 380static const struct config_keyword keywords[] = {
381 /* keyword handler variable address default */ 381 /* keyword handler variable address default */
382 {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"}, 382 {"start" , udhcp_str2nip , OFS(start_ip ), "192.168.0.20"},
383 {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"}, 383 {"end" , udhcp_str2nip , OFS(end_ip ), "192.168.0.254"},
384 {"interface" , read_str , OFS(interface ), "eth0"}, 384 {"interface" , read_str , OFS(interface ), "eth0"},
@@ -640,7 +640,7 @@ static void add_server_options(struct dhcp_packet *packet)
640static uint32_t select_lease_time(struct dhcp_packet *packet) 640static uint32_t select_lease_time(struct dhcp_packet *packet)
641{ 641{
642 uint32_t lease_time_sec = server_config.max_lease_sec; 642 uint32_t lease_time_sec = server_config.max_lease_sec;
643 uint8_t *lease_time_opt = udhcp_get_option(packet, DHCP_LEASE_TIME); 643 uint8_t *lease_time_opt = udhcp_get_option32(packet, DHCP_LEASE_TIME);
644 if (lease_time_opt) { 644 if (lease_time_opt) {
645 move_from_unaligned32(lease_time_sec, lease_time_opt); 645 move_from_unaligned32(lease_time_sec, lease_time_opt);
646 lease_time_sec = ntohl(lease_time_sec); 646 lease_time_sec = ntohl(lease_time_sec);
@@ -987,7 +987,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
987 } 987 }
988 988
989 /* Get SERVER_ID if present */ 989 /* Get SERVER_ID if present */
990 server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID); 990 server_id_opt = udhcp_get_option32(&packet, DHCP_SERVER_ID);
991 if (server_id_opt) { 991 if (server_id_opt) {
992 uint32_t server_id_network_order; 992 uint32_t server_id_network_order;
993 move_from_unaligned32(server_id_network_order, server_id_opt); 993 move_from_unaligned32(server_id_network_order, server_id_opt);
@@ -1011,7 +1011,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
1011 } 1011 }
1012 1012
1013 /* Get REQUESTED_IP if present */ 1013 /* Get REQUESTED_IP if present */
1014 requested_ip_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP); 1014 requested_ip_opt = udhcp_get_option32(&packet, DHCP_REQUESTED_IP);
1015 if (requested_ip_opt) { 1015 if (requested_ip_opt) {
1016 move_from_unaligned32(requested_nip, requested_ip_opt); 1016 move_from_unaligned32(requested_nip, requested_ip_opt);
1017 } 1017 }
diff --git a/networking/vconfig.c b/networking/vconfig.c
index 8548c8c3b..3cc5f2460 100644
--- a/networking/vconfig.c
+++ b/networking/vconfig.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config VCONFIG 9//config:config VCONFIG
10//config: bool "vconfig (2.5 kb)" 10//config: bool "vconfig (2.3 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/networking/wget.c b/networking/wget.c
index ae5c945d0..3cae1192c 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -9,7 +9,7 @@
9 * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2. 9 * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2.
10 */ 10 */
11//config:config WGET 11//config:config WGET
12//config: bool "wget (35 kb)" 12//config: bool "wget (38 kb)"
13//config: default y 13//config: default y
14//config: help 14//config: help
15//config: wget is a utility for non-interactive download of files from HTTP 15//config: wget is a utility for non-interactive download of files from HTTP
@@ -123,14 +123,14 @@
123//usage:#define wget_trivial_usage 123//usage:#define wget_trivial_usage
124//usage: IF_FEATURE_WGET_LONG_OPTIONS( 124//usage: IF_FEATURE_WGET_LONG_OPTIONS(
125//usage: "[-c|--continue] [--spider] [-q|--quiet] [-O|--output-document FILE]\n" 125//usage: "[-c|--continue] [--spider] [-q|--quiet] [-O|--output-document FILE]\n"
126//usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n" 126//usage: " [-o|--output-file FILE] [--header 'header: value'] [-Y|--proxy on/off]\n"
127/* Since we ignore these opts, we don't show them in --help */ 127/* Since we ignore these opts, we don't show them in --help */
128/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */ 128/* //usage: " [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */
129/* //usage: " [-nv] [-nc] [-nH] [-np]" */ 129/* //usage: " [-nv] [-nc] [-nH] [-np]" */
130//usage: " [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 130//usage: " [-P DIR] [-S|--server-response] [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
131//usage: ) 131//usage: )
132//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS( 132//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS(
133//usage: "[-cq] [-O FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]" 133//usage: "[-cq] [-O FILE] [-o FILE] [-Y on/off] [-P DIR] [-S] [-U AGENT]"
134//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..." 134//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
135//usage: ) 135//usage: )
136//usage:#define wget_full_usage "\n\n" 136//usage:#define wget_full_usage "\n\n"
@@ -147,6 +147,7 @@
147//usage: "\n -T SEC Network read timeout is SEC seconds" 147//usage: "\n -T SEC Network read timeout is SEC seconds"
148//usage: ) 148//usage: )
149//usage: "\n -O FILE Save to FILE ('-' for stdout)" 149//usage: "\n -O FILE Save to FILE ('-' for stdout)"
150//usage: "\n -o FILE Log messages to FILE"
150//usage: "\n -U STR Use STR for User-Agent header" 151//usage: "\n -U STR Use STR for User-Agent header"
151//usage: "\n -Y on/off Use proxy" 152//usage: "\n -Y on/off Use proxy"
152 153
@@ -231,9 +232,11 @@ struct globals {
231 unsigned char user_headers; /* Headers mentioned by the user */ 232 unsigned char user_headers; /* Headers mentioned by the user */
232#endif 233#endif
233 char *fname_out; /* where to direct output (-O) */ 234 char *fname_out; /* where to direct output (-O) */
235 char *fname_log; /* where to direct log (-o) */
234 const char *proxy_flag; /* Use proxies if env vars are set */ 236 const char *proxy_flag; /* Use proxies if env vars are set */
235 const char *user_agent; /* "User-Agent" header field */ 237 const char *user_agent; /* "User-Agent" header field */
236 int output_fd; 238 int output_fd;
239 int log_fd;
237 int o_flags; 240 int o_flags;
238#if ENABLE_FEATURE_WGET_TIMEOUT 241#if ENABLE_FEATURE_WGET_TIMEOUT
239 unsigned timeout_seconds; 242 unsigned timeout_seconds;
@@ -262,16 +265,17 @@ enum {
262 WGET_OPT_QUIET = (1 << 1), 265 WGET_OPT_QUIET = (1 << 1),
263 WGET_OPT_SERVER_RESPONSE = (1 << 2), 266 WGET_OPT_SERVER_RESPONSE = (1 << 2),
264 WGET_OPT_OUTNAME = (1 << 3), 267 WGET_OPT_OUTNAME = (1 << 3),
265 WGET_OPT_PREFIX = (1 << 4), 268 WGET_OPT_LOGNAME = (1 << 4),
266 WGET_OPT_PROXY = (1 << 5), 269 WGET_OPT_PREFIX = (1 << 5),
267 WGET_OPT_USER_AGENT = (1 << 6), 270 WGET_OPT_PROXY = (1 << 6),
268 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 7), 271 WGET_OPT_USER_AGENT = (1 << 7),
269 WGET_OPT_RETRIES = (1 << 8), 272 WGET_OPT_NETWORK_READ_TIMEOUT = (1 << 8),
270 WGET_OPT_nsomething = (1 << 9), 273 WGET_OPT_RETRIES = (1 << 9),
271 WGET_OPT_HEADER = (1 << 10) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 274 WGET_OPT_nsomething = (1 << 10),
272 WGET_OPT_POST_DATA = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 275 WGET_OPT_HEADER = (1 << 11) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
273 WGET_OPT_SPIDER = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 276 WGET_OPT_POST_DATA = (1 << 12) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
274 WGET_OPT_NO_CHECK_CERT = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS, 277 WGET_OPT_SPIDER = (1 << 13) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
278 WGET_OPT_NO_CHECK_CERT = (1 << 14) * ENABLE_FEATURE_WGET_LONG_OPTIONS,
275}; 279};
276 280
277enum { 281enum {
@@ -287,6 +291,10 @@ static void progress_meter(int flag)
287 if (option_mask32 & WGET_OPT_QUIET) 291 if (option_mask32 & WGET_OPT_QUIET)
288 return; 292 return;
289 293
294 /* Don't save progress to log file */
295 if (G.log_fd >= 0)
296 return;
297
290 if (flag == PROGRESS_START) 298 if (flag == PROGRESS_START)
291 bb_progress_init(&G.pmt, G.curfile); 299 bb_progress_init(&G.pmt, G.curfile);
292 300
@@ -900,6 +908,10 @@ static void NOINLINE retrieve_file_data(FILE *dfp)
900 polldata.fd = fileno(dfp); 908 polldata.fd = fileno(dfp);
901 polldata.events = POLLIN | POLLPRI; 909 polldata.events = POLLIN | POLLPRI;
902#endif 910#endif
911 if (G.output_fd == 1)
912 fprintf(stderr, "writing to stdout\n");
913 else
914 fprintf(stderr, "saving to '%s'\n", G.fname_out);
903 progress_meter(PROGRESS_START); 915 progress_meter(PROGRESS_START);
904 916
905 if (G.chunked) 917 if (G.chunked)
@@ -1045,6 +1057,10 @@ static void NOINLINE retrieve_file_data(FILE *dfp)
1045 G.chunked = 0; /* makes it show 100% even for chunked download */ 1057 G.chunked = 0; /* makes it show 100% even for chunked download */
1046 G.got_clen = 1; /* makes it show 100% even for download of (formerly) unknown size */ 1058 G.got_clen = 1; /* makes it show 100% even for download of (formerly) unknown size */
1047 progress_meter(PROGRESS_END); 1059 progress_meter(PROGRESS_END);
1060 if (G.output_fd == 1)
1061 fprintf(stderr, "written to stdout\n");
1062 else
1063 fprintf(stderr, "'%s' saved\n", G.fname_out);
1048} 1064}
1049 1065
1050static void download_one_url(const char *url) 1066static void download_one_url(const char *url)
@@ -1404,6 +1420,8 @@ However, in real world it was observed that some web servers
1404 xclose(G.output_fd); 1420 xclose(G.output_fd);
1405 G.output_fd = -1; 1421 G.output_fd = -1;
1406 } 1422 }
1423 } else {
1424 fprintf(stderr, "remote file exists\n");
1407 } 1425 }
1408 1426
1409 if (dfp != sfp) { 1427 if (dfp != sfp) {
@@ -1433,6 +1451,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
1433 "quiet\0" No_argument "q" 1451 "quiet\0" No_argument "q"
1434 "server-response\0" No_argument "S" 1452 "server-response\0" No_argument "S"
1435 "output-document\0" Required_argument "O" 1453 "output-document\0" Required_argument "O"
1454 "output-file\0" Required_argument "o"
1436 "directory-prefix\0" Required_argument "P" 1455 "directory-prefix\0" Required_argument "P"
1437 "proxy\0" Required_argument "Y" 1456 "proxy\0" Required_argument "Y"
1438 "user-agent\0" Required_argument "U" 1457 "user-agent\0" Required_argument "U"
@@ -1476,7 +1495,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1476#if ENABLE_FEATURE_WGET_LONG_OPTIONS 1495#if ENABLE_FEATURE_WGET_LONG_OPTIONS
1477#endif 1496#endif
1478 GETOPT32(argv, "^" 1497 GETOPT32(argv, "^"
1479 "cqSO:P:Y:U:T:+" 1498 "cqSO:o:P:Y:U:T:+"
1480 /*ignored:*/ "t:" 1499 /*ignored:*/ "t:"
1481 /*ignored:*/ "n::" 1500 /*ignored:*/ "n::"
1482 /* wget has exactly four -n<letter> opts, all of which we can ignore: 1501 /* wget has exactly four -n<letter> opts, all of which we can ignore:
@@ -1491,7 +1510,7 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1491 "-1" /* at least one URL */ 1510 "-1" /* at least one URL */
1492 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::") /* --header is a list */ 1511 IF_FEATURE_WGET_LONG_OPTIONS(":\xff::") /* --header is a list */
1493 LONGOPTS 1512 LONGOPTS
1494 , &G.fname_out, &G.dir_prefix, 1513 , &G.fname_out, &G.fname_log, &G.dir_prefix,
1495 &G.proxy_flag, &G.user_agent, 1514 &G.proxy_flag, &G.user_agent,
1496 IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL), 1515 IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL),
1497 NULL, /* -t RETRIES */ 1516 NULL, /* -t RETRIES */
@@ -1553,12 +1572,25 @@ IF_DESKTOP( "no-parent\0" No_argument "\xf0")
1553 G.o_flags = O_WRONLY | O_CREAT | O_TRUNC; 1572 G.o_flags = O_WRONLY | O_CREAT | O_TRUNC;
1554 } 1573 }
1555 1574
1575 G.log_fd = -1;
1576 if (G.fname_log) { /* -o FILE ? */
1577 if (!LONE_DASH(G.fname_log)) { /* not -o - ? */
1578 /* compat with wget: -o FILE can overwrite */
1579 G.log_fd = xopen(G.fname_log, O_WRONLY | O_CREAT | O_TRUNC);
1580 /* Redirect only stderr to log file, so -O - will work */
1581 xdup2(G.log_fd, STDERR_FILENO);
1582 }
1583 }
1584
1556 while (*argv) 1585 while (*argv)
1557 download_one_url(*argv++); 1586 download_one_url(*argv++);
1558 1587
1559 if (G.output_fd >= 0) 1588 if (G.output_fd >= 0)
1560 xclose(G.output_fd); 1589 xclose(G.output_fd);
1561 1590
1591 if (G.log_fd >= 0)
1592 xclose(G.log_fd);
1593
1562#if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_WGET_LONG_OPTIONS 1594#if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_WGET_LONG_OPTIONS
1563 free(G.extra_headers); 1595 free(G.extra_headers);
1564#endif 1596#endif
diff --git a/networking/whois.c b/networking/whois.c
index f3da32b4e..55e1de964 100644
--- a/networking/whois.c
+++ b/networking/whois.c
@@ -10,7 +10,7 @@
10 * Add proxy support 10 * Add proxy support
11 */ 11 */
12//config:config WHOIS 12//config:config WHOIS
13//config: bool "whois (6.6 kb)" 13//config: bool "whois (6.3 kb)"
14//config: default y 14//config: default y
15//config: help 15//config: help
16//config: whois is a client for the whois directory service 16//config: whois is a client for the whois directory service
diff --git a/networking/zcip.c b/networking/zcip.c
index 94e49adcb..434762f12 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -14,7 +14,7 @@
14 * certainly be used. Its naming is built over multicast DNS. 14 * certainly be used. Its naming is built over multicast DNS.
15 */ 15 */
16//config:config ZCIP 16//config:config ZCIP
17//config: bool "zcip (7.8 kb)" 17//config: bool "zcip (8.4 kb)"
18//config: default y 18//config: default y
19//config: select PLATFORM_LINUX 19//config: select PLATFORM_LINUX
20//config: select FEATURE_SYSLOG 20//config: select FEATURE_SYSLOG
diff --git a/printutils/lpd.c b/printutils/lpd.c
index 662d3a224..ce5944026 100644
--- a/printutils/lpd.c
+++ b/printutils/lpd.c
@@ -70,7 +70,7 @@
70 * mv -f ./"$DATAFILE" save/ 70 * mv -f ./"$DATAFILE" save/
71 */ 71 */
72//config:config LPD 72//config:config LPD
73//config: bool "lpd (5.3 kb)" 73//config: bool "lpd (5.5 kb)"
74//config: default y 74//config: default y
75//config: help 75//config: help
76//config: lpd is a print spooling daemon. 76//config: lpd is a print spooling daemon.
diff --git a/printutils/lpr.c b/printutils/lpr.c
index 808ecb5dc..7acb6c357 100644
--- a/printutils/lpr.c
+++ b/printutils/lpr.c
@@ -12,13 +12,13 @@
12 * See RFC 1179 for protocol description. 12 * See RFC 1179 for protocol description.
13 */ 13 */
14//config:config LPR 14//config:config LPR
15//config: bool "lpr (10 kb)" 15//config: bool "lpr (9.9 kb)"
16//config: default y 16//config: default y
17//config: help 17//config: help
18//config: lpr sends files (or standard input) to a print spooling daemon. 18//config: lpr sends files (or standard input) to a print spooling daemon.
19//config: 19//config:
20//config:config LPQ 20//config:config LPQ
21//config: bool "lpq (10 kb)" 21//config: bool "lpq (9.9 kb)"
22//config: default y 22//config: default y
23//config: help 23//config: help
24//config: lpq is a print spool queue examination and manipulation program. 24//config: lpq is a print spool queue examination and manipulation program.
diff --git a/procps/free.c b/procps/free.c
index ee0cd981a..3acfc4072 100644
--- a/procps/free.c
+++ b/procps/free.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config FREE 9//config:config FREE
10//config: bool "free (2.4 kb)" 10//config: bool "free (3.1 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX #sysinfo() 12//config: select PLATFORM_LINUX #sysinfo()
13//config: help 13//config: help
diff --git a/procps/iostat.c b/procps/iostat.c
index 09aae7102..7bf567c34 100644
--- a/procps/iostat.c
+++ b/procps/iostat.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config IOSTAT 9//config:config IOSTAT
10//config: bool "iostat (7.4 kb)" 10//config: bool "iostat (7.6 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Report CPU and I/O statistics 13//config: Report CPU and I/O statistics
diff --git a/procps/kill.c b/procps/kill.c
index 4477dedb7..073e74332 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config KILL 10//config:config KILL
11//config: bool "kill (2.6 kb)" 11//config: bool "kill (3.1 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: The command kill sends the specified signal to the specified 14//config: The command kill sends the specified signal to the specified
diff --git a/procps/lsof.c b/procps/lsof.c
index 4917cf899..21ac85ed3 100644
--- a/procps/lsof.c
+++ b/procps/lsof.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LSOF 9//config:config LSOF
10//config: bool "lsof (3.6 kb)" 10//config: bool "lsof (3.4 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Show open files in the format of: 13//config: Show open files in the format of:
diff --git a/procps/mpstat.c b/procps/mpstat.c
index 3c72f2705..e7dc4312a 100644
--- a/procps/mpstat.c
+++ b/procps/mpstat.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config MPSTAT 9//config:config MPSTAT
10//config: bool "mpstat (10 kb)" 10//config: bool "mpstat (9.8 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Per-processor statistics 13//config: Per-processor statistics
diff --git a/procps/nmeter.c b/procps/nmeter.c
index 166c8ab18..a01d19a6a 100644
--- a/procps/nmeter.c
+++ b/procps/nmeter.c
@@ -6,7 +6,7 @@
6 * Contact me: vda.linux@googlemail.com 6 * Contact me: vda.linux@googlemail.com
7 */ 7 */
8//config:config NMETER 8//config:config NMETER
9//config: bool "nmeter (10 kb)" 9//config: bool "nmeter (11 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: Prints selected system stats continuously, one line per update. 12//config: Prints selected system stats continuously, one line per update.
diff --git a/procps/pgrep.c b/procps/pgrep.c
index a16a6e959..495e0ef9d 100644
--- a/procps/pgrep.c
+++ b/procps/pgrep.c
@@ -7,13 +7,13 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config PGREP 9//config:config PGREP
10//config: bool "pgrep (6.8 kb)" 10//config: bool "pgrep (6.5 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Look for processes by name. 13//config: Look for processes by name.
14//config: 14//config:
15//config:config PKILL 15//config:config PKILL
16//config: bool "pkill (7.6 kb)" 16//config: bool "pkill (7.5 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: Send signals to processes by name. 19//config: Send signals to processes by name.
diff --git a/procps/pidof.c b/procps/pidof.c
index 98d7949f8..5595e3421 100644
--- a/procps/pidof.c
+++ b/procps/pidof.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config PIDOF 9//config:config PIDOF
10//config: bool "pidof (6.6 kb)" 10//config: bool "pidof (6.3 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Pidof finds the process id's (pids) of the named programs. It prints 13//config: Pidof finds the process id's (pids) of the named programs. It prints
diff --git a/procps/pmap.c b/procps/pmap.c
index c8fa0d280..9e541c707 100644
--- a/procps/pmap.c
+++ b/procps/pmap.c
@@ -37,6 +37,12 @@
37# define DASHES "--------" 37# define DASHES "--------"
38#endif 38#endif
39 39
40#if ULLONG_MAX == 0xffffffff
41# define AFMTLL "8"
42#else
43# define AFMTLL "16"
44#endif
45
40enum { 46enum {
41 OPT_x = 1 << 0, 47 OPT_x = 1 << 0,
42 OPT_q = 1 << 1, 48 OPT_q = 1 << 1,
@@ -46,7 +52,7 @@ static void print_smaprec(struct smaprec *currec, void *data)
46{ 52{
47 unsigned opt = (uintptr_t)data; 53 unsigned opt = (uintptr_t)data;
48 54
49 printf("%0" AFMT "lx ", currec->smap_start); 55 printf("%0" AFMTLL "llx ", currec->smap_start);
50 56
51 if (opt & OPT_x) 57 if (opt & OPT_x)
52 printf("%7lu %7lu %7lu %7lu ", 58 printf("%7lu %7lu %7lu %7lu ",
diff --git a/procps/powertop.c b/procps/powertop.c
index 004b4ce19..e70f5433b 100644
--- a/procps/powertop.c
+++ b/procps/powertop.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2, see file LICENSE in this source tree. 9 * Licensed under GPLv2, see file LICENSE in this source tree.
10 */ 10 */
11//config:config POWERTOP 11//config:config POWERTOP
12//config: bool "powertop (9.1 kb)" 12//config: bool "powertop (9.6 kb)"
13//config: default y 13//config: default y
14//config: help 14//config: help
15//config: Analyze power consumption on Intel-based laptops 15//config: Analyze power consumption on Intel-based laptops
diff --git a/procps/pstree.c b/procps/pstree.c
index 4fda1c21c..1d124d2d2 100644
--- a/procps/pstree.c
+++ b/procps/pstree.c
@@ -10,7 +10,7 @@
10 * Licensed under GPLv2, see file LICENSE in this source tree. 10 * Licensed under GPLv2, see file LICENSE in this source tree.
11 */ 11 */
12//config:config PSTREE 12//config:config PSTREE
13//config: bool "pstree (9.4 kb)" 13//config: bool "pstree (9.3 kb)"
14//config: default y 14//config: default y
15//config: help 15//config: help
16//config: Display a tree of processes. 16//config: Display a tree of processes.
diff --git a/procps/pwdx.c b/procps/pwdx.c
index 6009e2aa3..24ba25d90 100644
--- a/procps/pwdx.c
+++ b/procps/pwdx.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10//config:config PWDX 10//config:config PWDX
11//config: bool "pwdx (3.5 kb)" 11//config: bool "pwdx (3.7 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: Report current working directory of a process 14//config: Report current working directory of a process
diff --git a/procps/sysctl.c b/procps/sysctl.c
index 827e09cce..5fa7646d1 100644
--- a/procps/sysctl.c
+++ b/procps/sysctl.c
@@ -11,7 +11,7 @@
11 * v1.01.1 - busybox applet aware by <solar@gentoo.org> 11 * v1.01.1 - busybox applet aware by <solar@gentoo.org>
12 */ 12 */
13//config:config BB_SYSCTL 13//config:config BB_SYSCTL
14//config: bool "sysctl (6.9 kb)" 14//config: bool "sysctl (7.4 kb)"
15//config: default y 15//config: default y
16//config: help 16//config: help
17//config: Configure kernel parameters at runtime. 17//config: Configure kernel parameters at runtime.
diff --git a/procps/top.c b/procps/top.c
index f016f5501..3db077060 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -50,7 +50,7 @@
50 * chroot . ./top -bn1 >top1.out 50 * chroot . ./top -bn1 >top1.out
51 */ 51 */
52//config:config TOP 52//config:config TOP
53//config: bool "top (17 kb)" 53//config: bool "top (18 kb)"
54//config: default y 54//config: default y
55//config: help 55//config: help
56//config: The top program provides a dynamic real-time view of a running 56//config: The top program provides a dynamic real-time view of a running
diff --git a/procps/uptime.c b/procps/uptime.c
index 3262f41b4..31581271f 100644
--- a/procps/uptime.c
+++ b/procps/uptime.c
@@ -12,7 +12,7 @@
12 * Added FEATURE_UPTIME_UTMP_SUPPORT flag. 12 * Added FEATURE_UPTIME_UTMP_SUPPORT flag.
13 */ 13 */
14//config:config UPTIME 14//config:config UPTIME
15//config: bool "uptime (632 bytes)" 15//config: bool "uptime (3.7 kb)"
16//config: default y 16//config: default y
17//config: select PLATFORM_LINUX #sysinfo() 17//config: select PLATFORM_LINUX #sysinfo()
18//config: help 18//config: help
diff --git a/procps/watch.c b/procps/watch.c
index 420e6d3d1..dbe427aad 100644
--- a/procps/watch.c
+++ b/procps/watch.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config WATCH 10//config:config WATCH
11//config: bool "watch (4.1 kb)" 11//config: bool "watch (4.4 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: watch is used to execute a program periodically, showing 14//config: watch is used to execute a program periodically, showing
diff --git a/runit/chpst.c b/runit/chpst.c
index c2641ce8a..5e77245f6 100644
--- a/runit/chpst.c
+++ b/runit/chpst.c
@@ -28,20 +28,20 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29 29
30//config:config CHPST 30//config:config CHPST
31//config: bool "chpst (8.7 kb)" 31//config: bool "chpst (9 kb)"
32//config: default y 32//config: default y
33//config: help 33//config: help
34//config: chpst changes the process state according to the given options, and 34//config: chpst changes the process state according to the given options, and
35//config: execs specified program. 35//config: execs specified program.
36//config: 36//config:
37//config:config SETUIDGID 37//config:config SETUIDGID
38//config: bool "setuidgid (4.2 kb)" 38//config: bool "setuidgid (4 kb)"
39//config: default y 39//config: default y
40//config: help 40//config: help
41//config: Sets soft resource limits as specified by options 41//config: Sets soft resource limits as specified by options
42//config: 42//config:
43//config:config ENVUIDGID 43//config:config ENVUIDGID
44//config: bool "envuidgid (3.6 kb)" 44//config: bool "envuidgid (3.9 kb)"
45//config: default y 45//config: default y
46//config: help 46//config: help
47//config: Sets $UID to account's uid and $GID to account's gid 47//config: Sets $UID to account's uid and $GID to account's gid
@@ -54,7 +54,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54//config: in the given directory 54//config: in the given directory
55//config: 55//config:
56//config:config SOFTLIMIT 56//config:config SOFTLIMIT
57//config: bool "softlimit (4.3 kb)" 57//config: bool "softlimit (4.5 kb)"
58//config: default y 58//config: default y
59//config: help 59//config: help
60//config: Sets soft resource limits as specified by options 60//config: Sets soft resource limits as specified by options
diff --git a/runit/runsv.c b/runit/runsv.c
index a67280b4b..ccc762d78 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -28,7 +28,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29 29
30//config:config RUNSV 30//config:config RUNSV
31//config: bool "runsv (7.2 kb)" 31//config: bool "runsv (7.8 kb)"
32//config: default y 32//config: default y
33//config: help 33//config: help
34//config: runsv starts and monitors a service and optionally an appendant log 34//config: runsv starts and monitors a service and optionally an appendant log
diff --git a/runit/runsvdir.c b/runit/runsvdir.c
index 11ab40abf..55dd47e0d 100644
--- a/runit/runsvdir.c
+++ b/runit/runsvdir.c
@@ -28,7 +28,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 28/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29 29
30//config:config RUNSVDIR 30//config:config RUNSVDIR
31//config: bool "runsvdir (6 kb)" 31//config: bool "runsvdir (6.3 kb)"
32//config: default y 32//config: default y
33//config: help 33//config: help
34//config: runsvdir starts a runsv process for each subdirectory, or symlink to 34//config: runsvdir starts a runsv process for each subdirectory, or symlink to
diff --git a/runit/sv.c b/runit/sv.c
index 8054daedf..5c249ff95 100644
--- a/runit/sv.c
+++ b/runit/sv.c
@@ -154,7 +154,7 @@ Exit Codes
154/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */ 154/* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
155 155
156//config:config SV 156//config:config SV
157//config: bool "sv (7.8 kb)" 157//config: bool "sv (8.5 kb)"
158//config: default y 158//config: default y
159//config: help 159//config: help
160//config: sv reports the current status and controls the state of services 160//config: sv reports the current status and controls the state of services
@@ -169,14 +169,14 @@ Exit Codes
169//config: Defaults to "/var/service" 169//config: Defaults to "/var/service"
170//config: 170//config:
171//config:config SVC 171//config:config SVC
172//config: bool "svc (7.8 kb)" 172//config: bool "svc (8.4 kb)"
173//config: default y 173//config: default y
174//config: help 174//config: help
175//config: svc controls the state of services monitored by the runsv supervisor. 175//config: svc controls the state of services monitored by the runsv supervisor.
176//config: It is compatible with daemontools command with the same name. 176//config: It is compatible with daemontools command with the same name.
177//config: 177//config:
178//config:config SVOK 178//config:config SVOK
179//config: bool "svok" 179//config: bool "svok (1.5 kb)"
180//config: default y 180//config: default y
181//config: help 181//config: help
182//config: svok checks whether runsv supervisor is running. 182//config: svok checks whether runsv supervisor is running.
diff --git a/runit/svlogd.c b/runit/svlogd.c
index b0690d794..c9e5346d1 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -124,7 +124,7 @@ log message, you can use a pattern like this instead
124-*: *: pid * 124-*: *: pid *
125*/ 125*/
126//config:config SVLOGD 126//config:config SVLOGD
127//config: bool "svlogd (15 kb)" 127//config: bool "svlogd (16 kb)"
128//config: default y 128//config: default y
129//config: help 129//config: help
130//config: svlogd continuously reads log data from its standard input, optionally 130//config: svlogd continuously reads log data from its standard input, optionally
diff --git a/scripts/basic/split-include.c b/scripts/basic/split-include.c
index 8127fe261..9a9260f2c 100644
--- a/scripts/basic/split-include.c
+++ b/scripts/basic/split-include.c
@@ -133,7 +133,8 @@ int main(int argc, const char * argv [])
133 is_same = 0; 133 is_same = 0;
134 if ((fp_target = fopen(ptarget, "r")) != NULL) 134 if ((fp_target = fopen(ptarget, "r")) != NULL)
135 { 135 {
136 fgets(old_line, buffer_size, fp_target); 136 if (!fgets(old_line, buffer_size, fp_target))
137 ERROR_EXIT(ptarget);
137 if (fclose(fp_target) != 0) 138 if (fclose(fp_target) != 0)
138 ERROR_EXIT(ptarget); 139 ERROR_EXIT(ptarget);
139 if (!strcmp(line, old_line)) 140 if (!strcmp(line, old_line))
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index f69591c69..80bd55a68 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -142,7 +142,8 @@ static void conf_askvalue(struct symbol *sym, const char *def)
142 check_stdin(); 142 check_stdin();
143 case ask_all: 143 case ask_all:
144 fflush(stdout); 144 fflush(stdout);
145 fgets(line, 128, stdin); 145 if (!fgets(line, 128, stdin))
146 exit(1);
146 return; 147 return;
147 case set_default: 148 case set_default:
148 printf("%s\n", def); 149 printf("%s\n", def);
@@ -395,7 +396,8 @@ static int conf_choice(struct menu *menu)
395 check_stdin(); 396 check_stdin();
396 case ask_all: 397 case ask_all:
397 fflush(stdout); 398 fflush(stdout);
398 fgets(line, 128, stdin); 399 if (!fgets(line, 128, stdin))
400 exit(1);
399 strip(line); 401 strip(line);
400 if (line[0] == '?') { 402 if (line[0] == '?') {
401 printf("\n%s\n", menu->sym->help ? 403 printf("\n%s\n", menu->sym->help ?
diff --git a/scripts/kconfig/lxdialog/lxdialog.c b/scripts/kconfig/lxdialog/lxdialog.c
index 79f6c5fb5..5b8e3e947 100644
--- a/scripts/kconfig/lxdialog/lxdialog.c
+++ b/scripts/kconfig/lxdialog/lxdialog.c
@@ -189,7 +189,7 @@ int j_inputbox(const char *t, int ac, const char *const *av)
189 int ret = dialog_inputbox(t, av[2], atoi(av[3]), atoi(av[4]), 189 int ret = dialog_inputbox(t, av[2], atoi(av[3]), atoi(av[4]),
190 ac == 6 ? av[5] : (char *)NULL); 190 ac == 6 ? av[5] : (char *)NULL);
191 if (ret == 0) 191 if (ret == 0)
192 fprintf(stderr, dialog_input_result); 192 fprintf(stderr, "%s", dialog_input_result);
193 return ret; 193 return ret;
194} 194}
195 195
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 9fc837c9f..cda0473ac 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -498,7 +498,8 @@ static int exec_conf(void)
498 498
499 *argptr++ = NULL; 499 *argptr++ = NULL;
500 500
501 pipe(pipefd); 501 if (pipe(pipefd))
502 _exit(EXIT_FAILURE);
502 pid = fork(); 503 pid = fork();
503 if (pid == 0) { 504 if (pid == 0) {
504 sigprocmask(SIG_SETMASK, &osset, NULL); 505 sigprocmask(SIG_SETMASK, &osset, NULL);
@@ -863,9 +864,11 @@ static void conf(struct menu *menu)
863static void show_textbox(const char *title, const char *text, int r, int c) 864static void show_textbox(const char *title, const char *text, int r, int c)
864{ 865{
865 int fd; 866 int fd;
867 int len = strlen(text);
866 868
867 fd = creat(".help.tmp", 0777); 869 fd = creat(".help.tmp", 0777);
868 write(fd, text, strlen(text)); 870 if (write(fd, text, len) != len)
871 exit(1);
869 close(fd); 872 close(fd);
870 show_file(".help.tmp", title, r, c); 873 show_file(".help.tmp", title, r, c);
871 unlink(".help.tmp"); 874 unlink(".help.tmp");
diff --git a/shell/ash.c b/shell/ash.c
index 6d5c55d70..50d5ce9d4 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -31,7 +31,7 @@
31 */ 31 */
32 32
33//config:config ASH 33//config:config ASH
34//config: bool "ash (77 kb)" 34//config: bool "ash (78 kb)"
35//config: default y 35//config: default y
36//config: depends on !NOMMU 36//config: depends on !NOMMU
37//config: help 37//config: help
@@ -4600,7 +4600,7 @@ wait_block_or_sig(int *status)
4600 /* Children exist, but none are ready. Sleep until interesting signal */ 4600 /* Children exist, but none are ready. Sleep until interesting signal */
4601#if 1 4601#if 1
4602 sigfillset(&mask); 4602 sigfillset(&mask);
4603 sigprocmask(SIG_SETMASK, &mask, &mask); 4603 sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */
4604 while (!got_sigchld && !pending_sig) 4604 while (!got_sigchld && !pending_sig)
4605 sigsuspend(&mask); 4605 sigsuspend(&mask);
4606 sigprocmask(SIG_SETMASK, &mask, NULL); 4606 sigprocmask(SIG_SETMASK, &mask, NULL);
diff --git a/shell/cttyhack.c b/shell/cttyhack.c
index ec1b6c429..b9ee59bd0 100644
--- a/shell/cttyhack.c
+++ b/shell/cttyhack.c
@@ -5,7 +5,7 @@
5 * Licensed under GPLv2, see file LICENSE in this source tree. 5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */ 6 */
7//config:config CTTYHACK 7//config:config CTTYHACK
8//config: bool "cttyhack (2.5 kb)" 8//config: bool "cttyhack (2.4 kb)"
9//config: default y 9//config: default y
10//config: help 10//config: help
11//config: One common problem reported on the mailing list is the "can't 11//config: One common problem reported on the mailing list is the "can't
diff --git a/shell/hush.c b/shell/hush.c
index 90191408d..920a85299 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -93,7 +93,7 @@
93 * add =~ regex match operator: STR =~ REGEX 93 * add =~ regex match operator: STR =~ REGEX
94 */ 94 */
95//config:config HUSH 95//config:config HUSH
96//config: bool "hush (64 kb)" 96//config: bool "hush (68 kb)"
97//config: default y 97//config: default y
98//config: help 98//config: help
99//config: hush is a small shell. It handles the normal flow control 99//config: hush is a small shell. It handles the normal flow control
@@ -5998,7 +5998,7 @@ static const char *first_special_char_in_vararg(const char *cp)
5998#endif 5998#endif
5999static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash) 5999static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash)
6000{ 6000{
6001#if !BASH_PATTERN_SUBST 6001#if !BASH_PATTERN_SUBST && ENABLE_HUSH_CASE
6002 const int do_unbackslash = 0; 6002 const int do_unbackslash = 0;
6003#endif 6003#endif
6004 char *exp_str; 6004 char *exp_str;
@@ -11442,7 +11442,7 @@ static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid
11442 * and get stuck in sigsuspend... 11442 * and get stuck in sigsuspend...
11443 */ 11443 */
11444 sigfillset(&oldset); /* block all signals, remember old set */ 11444 sigfillset(&oldset); /* block all signals, remember old set */
11445 sigprocmask(SIG_SETMASK, &oldset, &oldset); 11445 sigprocmask2(SIG_SETMASK, &oldset);
11446 11446
11447 if (!sigisemptyset(&G.pending_set)) { 11447 if (!sigisemptyset(&G.pending_set)) {
11448 /* Crap! we raced with some signal! */ 11448 /* Crap! we raced with some signal! */
diff --git a/size_single_applets.sh b/size_single_applets.sh
index ee16d4de7..4b70e761f 100755
--- a/size_single_applets.sh
+++ b/size_single_applets.sh
@@ -1,4 +1,12 @@
1#!/bin/bash 1#!/bin/bash
2# Which config to use when updating the sizes in "official"
3# source tree? I am using x86 glibc toolchain of some typical distro,
4# not-static build, 32-bit defconfig build:
5# # CONFIG_STATIC is not set
6# CONFIG_CROSS_COMPILER_PREFIX=""
7# CONFIG_EXTRA_CFLAGS="-m32"
8# CONFIG_EXTRA_LDFLAGS="-m32"
9
2# The list of all applet config symbols 10# The list of all applet config symbols
3test -f include/applets.h || { echo "No include/applets.h file"; exit 1; } 11test -f include/applets.h || { echo "No include/applets.h file"; exit 1; }
4apps="` 12apps="`
@@ -48,9 +56,9 @@ grep ^IF_ include/applets.h \
48 b="busybox_${app}" 56 b="busybox_${app}"
49 test -f "$b" || continue 57 test -f "$b" || continue
50 58
51 file=`grep -lF "bool \"$name" $(find -name '*.c') | xargs` 59 file=`grep -l "bool \"$name[\" ]" $(find -name '*.c') | xargs`
52 # so far all such items are in .c files; if need to check Config.* files: 60 # A few applets have their CONFIG items in Config.* files, not .c files:
53 #test "$file" || file=`grep -lF "bool \"$name" $(find -name 'Config.*') | xargs` 61 test "$file" || file=`grep -l "bool \"$name[\" ]" $(find -name 'Config.*') | xargs`
54 test "$file" || continue 62 test "$file" || continue
55 #echo "FILE:'$file'" 63 #echo "FILE:'$file'"
56 64
diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c
index 25ddf3172..76eccf1da 100644
--- a/sysklogd/klogd.c
+++ b/sysklogd/klogd.c
@@ -17,7 +17,7 @@
17 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 17 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
18 */ 18 */
19//config:config KLOGD 19//config:config KLOGD
20//config: bool "klogd (5.5 kb)" 20//config: bool "klogd (5.7 kb)"
21//config: default y 21//config: default y
22//config: help 22//config: help
23//config: klogd is a utility which intercepts and logs all 23//config: klogd is a utility which intercepts and logs all
diff --git a/sysklogd/logger.c b/sysklogd/logger.c
index 1e0384c09..4d692d6fc 100644
--- a/sysklogd/logger.c
+++ b/sysklogd/logger.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LOGGER 9//config:config LOGGER
10//config: bool "logger (6.4 kb)" 10//config: bool "logger (6.3 kb)"
11//config: default y 11//config: default y
12//config: select FEATURE_SYSLOG 12//config: select FEATURE_SYSLOG
13//config: help 13//config: help
diff --git a/sysklogd/logread.c b/sysklogd/logread.c
index da552e087..ea41fc0c8 100644
--- a/sysklogd/logread.c
+++ b/sysklogd/logread.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config LOGREAD 11//config:config LOGREAD
12//config: bool "logread (6 kb)" 12//config: bool "logread (4.8 kb)"
13//config: default y 13//config: default y
14//WRONG: it should be compilable without SYSLOG=y: 14//WRONG: it should be compilable without SYSLOG=y:
15//WRONG: depends on FEATURE_IPC_SYSLOG 15//WRONG: depends on FEATURE_IPC_SYSLOG
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 5630d97fc..f12359476 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -13,7 +13,7 @@
13 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 13 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
14 */ 14 */
15//config:config SYSLOGD 15//config:config SYSLOGD
16//config: bool "syslogd (12 kb)" 16//config: bool "syslogd (13 kb)"
17//config: default y 17//config: default y
18//config: help 18//config: help
19//config: The syslogd utility is used to record logs of all the 19//config: The syslogd utility is used to record logs of all the
diff --git a/testsuite/bc.tests b/testsuite/bc.tests
new file mode 100755
index 000000000..3fde60a2c
--- /dev/null
+++ b/testsuite/bc.tests
@@ -0,0 +1,314 @@
1#!/bin/sh
2# Copyright 2018 by Denys Vlasenko
3# Licensed under GPLv2 or later, see file LICENSE in this source tree.
4
5. ./testing.sh
6
7# testing "test name" "command" "expected result" "file input" "stdin"
8
9testing "bc comment" \
10 "bc" \
11 "3\n" \
12 "" "1 /* comment */ + 2"
13
14testing "bc /*/ is not a closed comment" \
15 "bc" \
16 "4\n" \
17 "" "1 /*/ + 2 */ + 3"
18
19# this needs interactive testing
20testing "bc comment with \"" \
21 "bc" \
22 "3\n" \
23 "" "1 /* \" */ + 2"
24
25# this needs interactive testing
26testing "bc \"string/*\" is not a comment" \
27 "bc" \
28 "string/*9\n" \
29 "" "\"string/*\";9"
30
31testing "bc comment 3: unterminated #comment" \
32 "bc" \
33 "" \
34 "" "#foo" # no trailing newline
35
36testing "bc backslash 1" \
37 "bc" \
38 "3\n" \
39 "" "1 \\\\\n + 2"
40
41testing "bc string 1" \
42 "bc" \
43 "STR\n" \
44 "" "\"STR\n\""
45
46testing "bc read() 4<EOF>" \
47 "bc input" \
48 "4\n" \
49 "read();halt" "4"
50
51testing "bc read()^2" \
52 "bc input" \
53 "16\n" \
54 "read()^2;halt" "4\n"
55
56testing "bc read()*read()" \
57 "bc input" \
58 "20\n" \
59 "read()*read();halt" "4\n5"
60
61testing "bc if 0 else" \
62 "bc" \
63 "2\n9\n" \
64 "" "if (0) 1 else 2; 9"
65
66testing "bc if 1 else" \
67 "bc" \
68 "1\n9\n" \
69 "" "if (1) 1 else 2; 9"
70
71testing "bc if 1 if 1 else else" \
72 "bc" \
73 "1\n9\n" \
74 "" "if (1) if (1) 1 else 2 else 3; 9"
75
76testing "bc if 0 else if 1" \
77 "bc" \
78 "2\n9\n" \
79 "" "if (0) 1 else if (1) 2; 9"
80
81testing "bc for (;;)" \
82 "bc" \
83 "2\n3\n2\n9\n" \
84 "" "i=2; for (;;) { 2; if(--i==0) break; 3; }; 9"
85
86testing "bc for (;cond;)" \
87 "bc" \
88 "1\n2\n3\n9\n" \
89 "" "i=0; for(;i<3;)++i; 9"
90
91testing "bc for (;cond;upd)" \
92 "bc" \
93 "1\n2\n3\n9\n" \
94 "" "i=1; for(;i<4;i++)i; 9"
95
96testing "bc for (init;cond;upd)" \
97 "bc" \
98 "1\n2\n3\n9\n" \
99 "" "for(i=1;i<4;i++)i; 9"
100
101testing "bc for (;;) {break}" \
102 "bc" \
103 "2\n9\n" \
104 "" "for (;;) {2;break}; 9"
105
106testing "bc define {return}" \
107 "bc" \
108 "0\n9\n" \
109 "" "define w() {return}\nw();9"
110
111testing "bc define auto" \
112 "bc" \
113 "8\n9\n" \
114 "" "define w() { auto z; return 8; }; w(); 9"
115
116testing "bc define auto array same name" \
117 "bc" \
118 "8\n9\n" \
119 "" "define w(x) { auto x[]; return x; }; w(8); 9"
120
121testing "bc define with body on next line" \
122 "bc" \
123 "8\n9\n" \
124 "" "define w()\n{ auto z; return 8; }\nw()\n9"
125
126testing "bc void function" \
127 "bc" \
128 "void9\n" \
129 "" "define void w() {print \"void\"}\nw()\n9"
130
131# Extra POSIX compat - GNU bc does not allow this
132testing "bc function named 'void'" \
133 "bc" \
134 "void0\n9\n" \
135 "" "define void() {print \"void\"}\nvoid()\n9"
136
137# Extra POSIX compat - GNU bc does not allow this
138testing "bc variable named 'void'" \
139 "bc" \
140 "6\n9\n" \
141 "" "void=6\nvoid\n9"
142
143testing "bc if(cond)<NL>" \
144 "bc" \
145 "9\n" \
146 "" "if(0)\n3\n9"
147
148testing "bc if(cond) stmt else<NL>" \
149 "bc" \
150 "4\n9\n" \
151 "" "if(0)3 else\n4\n9"
152
153testing "bc while(cond)<NL>" \
154 "bc" \
155 "8\n7\n6\n5\n4\n3\n2\n1\n9\n" \
156 "" "i=9;while(--i)\ni\n9"
157
158testing "bc ifz does not match if keyword" \
159 "bc" \
160 "1\n2\n2\n3\n" \
161 "" "ifz=1;ifz\n++ifz;ifz++\nifz"
162
163# had parse error on "f()-N"
164testing "bc -l 'e(0)-2'" \
165 "bc -l" \
166 "-1.00000000000000000000\n" \
167 "" "e(0)-2"
168
169testing "bc (!a&&b)" \
170 "bc" \
171 "0\n" \
172 "" "(!a&&b)"
173
174# check that dc code is not messing this up (no NUL printing!)
175testing "bc print \"\"" \
176 "bc" \
177 "" \
178 "" "print \"\""
179
180testing "bc print 1,2,3" \
181 "bc" \
182 "123" \
183 "" "print 1,2,3"
184
185testing "bc { print 1 }" \
186 "bc" \
187 "1" \
188 "" "{ print 1 }"
189
190testing "bc nested loops and breaks" \
191 "bc" \
192 "\
19311
19421
19531
19622
19712
19899
199" \
200 "" "\
201if(1) {
202 11
203 while(1) {
204 21
205 while(1) {
206 31
207 break
208 32
209 }
210 22
211 break
212 23
213 }
214 12
215} else {
216 88
217}
21899
219"
220
221testing "bc continue in if" \
222 "bc" \
223 "\
22411
22521
22611
22731
22899
229" \
230 "" "\
231i=2
232while(i--) {
233 11
234 if(i) {
235 21
236 continue
237 22
238 } else {
239 31
240 continue
241 32
242 }
243 12
244}
24599
246"
247
248testing "bc continue in for" \
249 "bc" \
250 "\
2511
25277
2532
25499
255" \
256 "" "\
257for(i=1; i<3; i++) {
258 i
259 if(i==2) continue
260 77
261}
26299
263"
264
265testing "bc ibase" \
266 "bc" \
267 "99\n1295\n1224\n" \
268 "" "a=ZZ;a;ibase=36;a=ZZ;a;ibase=Z;a=ZZ;a"
269
270testing "bc parsing of numbers" \
271 "bc 2>&1 | bc 2>&1 | md5sum 2>&1" \
272 "465d8c01308d0863b6f5669e8a1c69fb -\n" \
273 "" '
274for (b = 2; b <= 16; ++b) {
275 if (b == 10) continue
276 obase = 10
277 print "ibase = A; ibase = ", b, "\n"
278 obase = b
279 for (i = 0; i <= 65536; ++i) {
280 i
281 print "0.", i, "\n"
282 print "1.", i, "\n"
283 print i, ".", i, "\n"
284 }
285}'
286
287testing "bc printing of numbers" \
288 "bc 2>&1 | bc 2>&1 | md5sum 2>&1" \
289 "d884b35d251ca096410712743aeafb9e -\n" \
290 "" '
291for (b = 2; b <= 101; ++b) {
292 if (b == 10) continue
293 s = b * b
294 print "obase = ", b, "\n"
295 for (i = 0; i <= s; ++i) {
296 i
297 print "0.", i, "\n"
298 print "1.", i, "\n"
299 print i, ".", i, "\n"
300 }
301 2189432174861923048671023498128347619023487610234689172304.192748960128745108927461089237469018723460
302}'
303
304for f in bc*.bc; do
305 r="`basename "$f" .bc`_results.txt"
306 test -f "$r" || continue
307 # testing "test name" "command" "expected result" "file input" "stdin"
308 testing "bc -lq $f" \
309 "{ { bc -lq $f 2>&1; echo E:\$? >&2; } | diff -u - $r; echo E:\$?; } 2>&1" \
310 "E:0\nE:0\n" \
311 "" ""
312done
313
314exit $FAILCOUNT
diff --git a/testsuite/bc_add.bc b/testsuite/bc_add.bc
new file mode 100644
index 000000000..ee03b4bb6
--- /dev/null
+++ b/testsuite/bc_add.bc
@@ -0,0 +1,26 @@
10 + 0
20 + 1
31 + 1
41 + 0
52 + 5
6237 + 483
7999 + 999
82374623 + 324869356734856
92378639084586723980562 + 23468729367839
1037298367203972395108367910823465293084561329084561390845613409516734503870691837451 + 785621394067928346918023476190834672198467134908618723249671349062187346898241093486139046139084613490817356023871869102746182749061872609129847
111.1 + 0
120 + 1.1
13457283.731284923576 + 37842934672834.3874629385672354
141.0 + 0.1
153746289134067138046 + 0.138375863945672398456712389456273486293
16-1 + -1
17-4 + -15
18-1346782 + -1287904651762468913476
1999999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
2099999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999995 + 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005
2199999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
2299999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999899999999999999999999999999999999999999999999999999999999999999 + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
2399999999999999999999999999999999999989999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
24-1889985797 + 2012747315
250 + -14338.391079082
26-2422297 + 1.3134942556
diff --git a/testsuite/bc_add_results.txt b/testsuite/bc_add_results.txt
new file mode 100644
index 000000000..c3b4d6d2a
--- /dev/null
+++ b/testsuite/bc_add_results.txt
@@ -0,0 +1,38 @@
10
21
32
41
57
6720
71998
8324869359109479
92378639108055453348401
1078562139406792834691802347619083467219846713490861872324967138636055\
1145508706362018540498696043776980521464405852627147161556994835657433\
1200967298
131.1
141.1
1537842935130118.1187478621432354
161.1
173746289134067138046.138375863945672398456712389456273486293
18-2
19-19
20-1287904651762470260258
21100000000000000000000000000000000000000000000000000000000000.0000000\
2200000000000000000000000000000000000000000000000000000000000000000000\
23000000000000000000000000000000000000000000000
24100000000000000000000000000000000000000000000000000000000000.0000000\
2500000000000000000000000000000000000000000000000000000000000000000000\
26000000000000000000000000000000000000000000000
27100000000000000000000000000000000000000000000000000000000000.0000000\
2800000000000000000000000000000000000000000000000000000000000000000000\
29000000000000000000000000000000000000000009999
3099999999999999999999999999999999999999999999999999999999999.99999999\
3199999999999999999999999999999999999999999999999999000000000000000000\
3200000000000000000000000000000000000000009999
3399999999999999999999999999999999999990000000000000000000000.00000000\
3400000000000000000000000000000000000000000000000000000000000000000000\
3500000000000000000000000000000000000000009999
36122761518
37-14338.391079082
38-2422295.6865057444
diff --git a/testsuite/bc_arctangent.bc b/testsuite/bc_arctangent.bc
new file mode 100644
index 000000000..f665ea90b
--- /dev/null
+++ b/testsuite/bc_arctangent.bc
@@ -0,0 +1,26 @@
1a(.267)
2a(1)
3scale = 64
4a(.267)
5a(1)
6scale = 100
7a(.267)
8a(1)
9scale = 20
10a(0)
11a(.5)
12a(0.577350269189625764509148780501)
13a(1.5)
14a(1.7320508075688772935274463415)
15a(2)
16a(3)
17a(1000)
18a(-.5)
19a(-0.577350269189625764509148780501)
20a(-1.5)
21a(-1.7320508075688772935274463415)
22a(-2)
23a(-3)
24a(-1000)
25a(-3249917614.2821897119)
26a(-694706362.1974670468)
diff --git a/testsuite/bc_arctangent_results.txt b/testsuite/bc_arctangent_results.txt
new file mode 100644
index 000000000..e77c63779
--- /dev/null
+++ b/testsuite/bc_arctangent_results.txt
@@ -0,0 +1,25 @@
1.26091356923294057959
2.78539816339744830961
3.2609135692329405795967852677779865639774740239882445822329882917
4.7853981633974483096156608458198757210492923498437764552437361480
5.2609135692329405795967852677779865639774740239882445822329882917230\
6650591934644905491823044536954978
7.7853981633974483096156608458198757210492923498437764552437361480769\
8541015715522496570087063355292669
90
10.46364760900080611621
11.52359877559829887307
12.98279372324732906798
131.04719755119659774615
141.10714871779409050301
151.24904577239825442582
161.56979632712822975256
17-.46364760900080611621
18-.52359877559829887307
19-.98279372324732906798
20-1.04719755119659774615
21-1.10714871779409050301
22-1.24904577239825442582
23-1.56979632712822975256
24-1.57079632648719651151
25-1.57079632535543952711
diff --git a/testsuite/bc_array.bc b/testsuite/bc_array.bc
new file mode 100644
index 000000000..3bb680178
--- /dev/null
+++ b/testsuite/bc_array.bc
@@ -0,0 +1,35 @@
1#! /usr/bin/bc -q
2
3define z(a[]) {
4 for (i = 0; i < l; ++i) {
5 a[i]
6 }
7}
8
9define x(a[]) {
10
11 for (i = 0; i < l; ++i) {
12 a[i] = -i
13 }
14
15 z(a[])
16}
17
18for (i = 0; i < 101; ++i) {
19 a[i] = i
20}
21
22a[104] = 204
23
24l = length(a[])
25
26for (i = 0; i <= l; ++i) {
27 a[i]
28}
29
30z(a[])
31x(a[])
32z(a[])
33l
34
35halt
diff --git a/testsuite/bc_array_results.txt b/testsuite/bc_array_results.txt
new file mode 100644
index 000000000..a757b7fb5
--- /dev/null
+++ b/testsuite/bc_array_results.txt
@@ -0,0 +1,426 @@
10
21
32
43
54
65
76
87
98
109
1110
1211
1312
1413
1514
1615
1716
1817
1918
2019
2120
2221
2322
2423
2524
2625
2726
2827
2928
3029
3130
3231
3332
3433
3534
3635
3736
3837
3938
4039
4140
4241
4342
4443
4544
4645
4746
4847
4948
5049
5150
5251
5352
5453
5554
5655
5756
5857
5958
6059
6160
6261
6362
6463
6564
6665
6766
6867
6968
7069
7170
7271
7372
7473
7574
7675
7776
7877
7978
8079
8180
8281
8382
8483
8584
8685
8786
8887
8988
9089
9190
9291
9392
9493
9594
9695
9796
9897
9998
10099
101100
1020
1030
1040
105204
1060
1070
1081
1092
1103
1114
1125
1136
1147
1158
1169
11710
11811
11912
12013
12114
12215
12316
12417
12518
12619
12720
12821
12922
13023
13124
13225
13326
13427
13528
13629
13730
13831
13932
14033
14134
14235
14336
14437
14538
14639
14740
14841
14942
15043
15144
15245
15346
15447
15548
15649
15750
15851
15952
16053
16154
16255
16356
16457
16558
16659
16760
16861
16962
17063
17164
17265
17366
17467
17568
17669
17770
17871
17972
18073
18174
18275
18376
18477
18578
18679
18780
18881
18982
19083
19184
19285
19386
19487
19588
19689
19790
19891
19992
20093
20194
20295
20396
20497
20598
20699
207100
2080
2090
2100
211204
2120
2130
214-1
215-2
216-3
217-4
218-5
219-6
220-7
221-8
222-9
223-10
224-11
225-12
226-13
227-14
228-15
229-16
230-17
231-18
232-19
233-20
234-21
235-22
236-23
237-24
238-25
239-26
240-27
241-28
242-29
243-30
244-31
245-32
246-33
247-34
248-35
249-36
250-37
251-38
252-39
253-40
254-41
255-42
256-43
257-44
258-45
259-46
260-47
261-48
262-49
263-50
264-51
265-52
266-53
267-54
268-55
269-56
270-57
271-58
272-59
273-60
274-61
275-62
276-63
277-64
278-65
279-66
280-67
281-68
282-69
283-70
284-71
285-72
286-73
287-74
288-75
289-76
290-77
291-78
292-79
293-80
294-81
295-82
296-83
297-84
298-85
299-86
300-87
301-88
302-89
303-90
304-91
305-92
306-93
307-94
308-95
309-96
310-97
311-98
312-99
313-100
314-101
315-102
316-103
317-104
3180
3190
3200
3211
3222
3233
3244
3255
3266
3277
3288
3299
33010
33111
33212
33313
33414
33515
33616
33717
33818
33919
34020
34121
34222
34323
34424
34525
34626
34727
34828
34929
35030
35131
35232
35333
35434
35535
35636
35737
35838
35939
36040
36141
36242
36343
36444
36545
36646
36747
36848
36949
37050
37151
37252
37353
37454
37555
37656
37757
37858
37959
38060
38161
38262
38363
38464
38565
38666
38767
38868
38969
39070
39171
39272
39373
39474
39575
39676
39777
39878
39979
40080
40181
40282
40383
40484
40585
40686
40787
40888
40989
41090
41191
41292
41393
41494
41595
41696
41797
41898
41999
420100
4210
4220
4230
424204
4250
426105
diff --git a/testsuite/bc_arrays.bc b/testsuite/bc_arrays.bc
new file mode 100644
index 000000000..26a284b8d
--- /dev/null
+++ b/testsuite/bc_arrays.bc
@@ -0,0 +1,10 @@
1a[0] = 1
2a[2-1] = 2
3
4a[0]+a[0]
5
6a[2-1]+a[2-1]
7
8a[5] = 2
9a[5.789]
10
diff --git a/testsuite/bc_arrays_results.txt b/testsuite/bc_arrays_results.txt
new file mode 100644
index 000000000..200035ffa
--- /dev/null
+++ b/testsuite/bc_arrays_results.txt
@@ -0,0 +1,3 @@
12
24
32
diff --git a/testsuite/bc_bessel.bc b/testsuite/bc_bessel.bc
new file mode 100644
index 000000000..a52fa356b
--- /dev/null
+++ b/testsuite/bc_bessel.bc
@@ -0,0 +1,844 @@
1j(0, 0)
2j(0, .5)
3j(0, -.5)
4j(0, 1)
5j(0, -1)
6j(0, 1.5)
7j(0, -1.5)
8j(0, 1.74)
9j(0, -1.74)
10j(0, 2)
11j(0, -2)
12j(0, 3.2345)
13j(0, -3.2345)
14j(0, 100)
15j(0, -100)
16j(0, -.5)
17j(0, .5)
18j(0, -1)
19j(0, 1)
20j(0, -1.5)
21j(0, 1.5)
22j(0, -1.74)
23j(0, 1.74)
24j(0, -2)
25j(0, 2)
26j(0, -3.2345)
27j(0, 3.2345)
28j(0, -100)
29j(0, 100)
30j(.5, 0)
31j(.5, .5)
32j(.5, -.5)
33j(.5, 1)
34j(.5, -1)
35j(.5, 1.5)
36j(.5, -1.5)
37j(.5, 1.74)
38j(.5, -1.74)
39j(.5, 2)
40j(.5, -2)
41j(.5, 3.2345)
42j(.5, -3.2345)
43j(.5, 100)
44j(.5, -100)
45j(.5, -.5)
46j(.5, .5)
47j(.5, -1)
48j(.5, 1)
49j(.5, -1.5)
50j(.5, 1.5)
51j(.5, -1.74)
52j(.5, 1.74)
53j(.5, -2)
54j(.5, 2)
55j(.5, -3.2345)
56j(.5, 3.2345)
57j(.5, -100)
58j(.5, 100)
59j(-.5, 0)
60j(-.5, .5)
61j(-.5, -.5)
62j(-.5, 1)
63j(-.5, -1)
64j(-.5, 1.5)
65j(-.5, -1.5)
66j(-.5, 1.74)
67j(-.5, -1.74)
68j(-.5, 2)
69j(-.5, -2)
70j(-.5, 3.2345)
71j(-.5, -3.2345)
72j(-.5, 100)
73j(-.5, -100)
74j(-.5, -.5)
75j(-.5, .5)
76j(-.5, -1)
77j(-.5, 1)
78j(-.5, -1.5)
79j(-.5, 1.5)
80j(-.5, -1.74)
81j(-.5, 1.74)
82j(-.5, -2)
83j(-.5, 2)
84j(-.5, -3.2345)
85j(-.5, 3.2345)
86j(-.5, -100)
87j(-.5, 100)
88j(1, 0)
89j(1, .5)
90j(1, -.5)
91j(1, 1)
92j(1, -1)
93j(1, 1.5)
94j(1, -1.5)
95j(1, 1.74)
96j(1, -1.74)
97j(1, 2)
98j(1, -2)
99j(1, 3.2345)
100j(1, -3.2345)
101j(1, 100)
102j(1, -100)
103j(1, -.5)
104j(1, .5)
105j(1, -1)
106j(1, 1)
107j(1, -1.5)
108j(1, 1.5)
109j(1, -1.74)
110j(1, 1.74)
111j(1, -2)
112j(1, 2)
113j(1, -3.2345)
114j(1, 3.2345)
115j(1, -100)
116j(1, 100)
117j(-1, 0)
118j(-1, .5)
119j(-1, -.5)
120j(-1, 1)
121j(-1, -1)
122j(-1, 1.5)
123j(-1, -1.5)
124j(-1, 1.74)
125j(-1, -1.74)
126j(-1, 2)
127j(-1, -2)
128j(-1, 3.2345)
129j(-1, -3.2345)
130j(-1, 100)
131j(-1, -100)
132j(-1, -.5)
133j(-1, .5)
134j(-1, -1)
135j(-1, 1)
136j(-1, -1.5)
137j(-1, 1.5)
138j(-1, -1.74)
139j(-1, 1.74)
140j(-1, -2)
141j(-1, 2)
142j(-1, -3.2345)
143j(-1, 3.2345)
144j(-1, -100)
145j(-1, 100)
146j(1.5, 0)
147j(1.5, .5)
148j(1.5, -.5)
149j(1.5, 1)
150j(1.5, -1)
151j(1.5, 1.5)
152j(1.5, -1.5)
153j(1.5, 1.74)
154j(1.5, -1.74)
155j(1.5, 2)
156j(1.5, -2)
157j(1.5, 3.2345)
158j(1.5, -3.2345)
159j(1.5, 100)
160j(1.5, -100)
161j(1.5, -.5)
162j(1.5, .5)
163j(1.5, -1)
164j(1.5, 1)
165j(1.5, -1.5)
166j(1.5, 1.5)
167j(1.5, -1.74)
168j(1.5, 1.74)
169j(1.5, -2)
170j(1.5, 2)
171j(1.5, -3.2345)
172j(1.5, 3.2345)
173j(1.5, -100)
174j(1.5, 100)
175j(-1.5, 0)
176j(-1.5, .5)
177j(-1.5, -.5)
178j(-1.5, 1)
179j(-1.5, -1)
180j(-1.5, 1.5)
181j(-1.5, -1.5)
182j(-1.5, 1.74)
183j(-1.5, -1.74)
184j(-1.5, 2)
185j(-1.5, -2)
186j(-1.5, 3.2345)
187j(-1.5, -3.2345)
188j(-1.5, 100)
189j(-1.5, -100)
190j(-1.5, -.5)
191j(-1.5, .5)
192j(-1.5, -1)
193j(-1.5, 1)
194j(-1.5, -1.5)
195j(-1.5, 1.5)
196j(-1.5, -1.74)
197j(-1.5, 1.74)
198j(-1.5, -2)
199j(-1.5, 2)
200j(-1.5, -3.2345)
201j(-1.5, 3.2345)
202j(-1.5, -100)
203j(-1.5, 100)
204j(1.74, 0)
205j(1.74, .5)
206j(1.74, -.5)
207j(1.74, 1)
208j(1.74, -1)
209j(1.74, 1.5)
210j(1.74, -1.5)
211j(1.74, 1.74)
212j(1.74, -1.74)
213j(1.74, 2)
214j(1.74, -2)
215j(1.74, 3.2345)
216j(1.74, -3.2345)
217j(1.74, 100)
218j(1.74, -100)
219j(1.74, -.5)
220j(1.74, .5)
221j(1.74, -1)
222j(1.74, 1)
223j(1.74, -1.5)
224j(1.74, 1.5)
225j(1.74, -1.74)
226j(1.74, 1.74)
227j(1.74, -2)
228j(1.74, 2)
229j(1.74, -3.2345)
230j(1.74, 3.2345)
231j(1.74, -100)
232j(1.74, 100)
233j(-1.74, 0)
234j(-1.74, .5)
235j(-1.74, -.5)
236j(-1.74, 1)
237j(-1.74, -1)
238j(-1.74, 1.5)
239j(-1.74, -1.5)
240j(-1.74, 1.74)
241j(-1.74, -1.74)
242j(-1.74, 2)
243j(-1.74, -2)
244j(-1.74, 3.2345)
245j(-1.74, -3.2345)
246j(-1.74, 100)
247j(-1.74, -100)
248j(-1.74, -.5)
249j(-1.74, .5)
250j(-1.74, -1)
251j(-1.74, 1)
252j(-1.74, -1.5)
253j(-1.74, 1.5)
254j(-1.74, -1.74)
255j(-1.74, 1.74)
256j(-1.74, -2)
257j(-1.74, 2)
258j(-1.74, -3.2345)
259j(-1.74, 3.2345)
260j(-1.74, -100)
261j(-1.74, 100)
262j(2, 0)
263j(2, .5)
264j(2, -.5)
265j(2, 1)
266j(2, -1)
267j(2, 1.5)
268j(2, -1.5)
269j(2, 1.74)
270j(2, -1.74)
271j(2, 2)
272j(2, -2)
273j(2, 3.2345)
274j(2, -3.2345)
275j(2, 100)
276j(2, -100)
277j(2, -.5)
278j(2, .5)
279j(2, -1)
280j(2, 1)
281j(2, -1.5)
282j(2, 1.5)
283j(2, -1.74)
284j(2, 1.74)
285j(2, -2)
286j(2, 2)
287j(2, -3.2345)
288j(2, 3.2345)
289j(2, -100)
290j(2, 100)
291j(-2, 0)
292j(-2, .5)
293j(-2, -.5)
294j(-2, 1)
295j(-2, -1)
296j(-2, 1.5)
297j(-2, -1.5)
298j(-2, 1.74)
299j(-2, -1.74)
300j(-2, 2)
301j(-2, -2)
302j(-2, 3.2345)
303j(-2, -3.2345)
304j(-2, 100)
305j(-2, -100)
306j(-2, -.5)
307j(-2, .5)
308j(-2, -1)
309j(-2, 1)
310j(-2, -1.5)
311j(-2, 1.5)
312j(-2, -1.74)
313j(-2, 1.74)
314j(-2, -2)
315j(-2, 2)
316j(-2, -3.2345)
317j(-2, 3.2345)
318j(-2, -100)
319j(-2, 100)
320j(3.2345, 0)
321j(3.2345, .5)
322j(3.2345, -.5)
323j(3.2345, 1)
324j(3.2345, -1)
325j(3.2345, 1.5)
326j(3.2345, -1.5)
327j(3.2345, 1.74)
328j(3.2345, -1.74)
329j(3.2345, 2)
330j(3.2345, -2)
331j(3.2345, 3.2345)
332j(3.2345, -3.2345)
333j(3.2345, 100)
334j(3.2345, -100)
335j(3.2345, -.5)
336j(3.2345, .5)
337j(3.2345, -1)
338j(3.2345, 1)
339j(3.2345, -1.5)
340j(3.2345, 1.5)
341j(3.2345, -1.74)
342j(3.2345, 1.74)
343j(3.2345, -2)
344j(3.2345, 2)
345j(3.2345, -3.2345)
346j(3.2345, 3.2345)
347j(3.2345, -100)
348j(3.2345, 100)
349j(-3.2345, 0)
350j(-3.2345, .5)
351j(-3.2345, -.5)
352j(-3.2345, 1)
353j(-3.2345, -1)
354j(-3.2345, 1.5)
355j(-3.2345, -1.5)
356j(-3.2345, 1.74)
357j(-3.2345, -1.74)
358j(-3.2345, 2)
359j(-3.2345, -2)
360j(-3.2345, 3.2345)
361j(-3.2345, -3.2345)
362j(-3.2345, 100)
363j(-3.2345, -100)
364j(-3.2345, -.5)
365j(-3.2345, .5)
366j(-3.2345, -1)
367j(-3.2345, 1)
368j(-3.2345, -1.5)
369j(-3.2345, 1.5)
370j(-3.2345, -1.74)
371j(-3.2345, 1.74)
372j(-3.2345, -2)
373j(-3.2345, 2)
374j(-3.2345, -3.2345)
375j(-3.2345, 3.2345)
376j(-3.2345, -100)
377j(-3.2345, 100)
378j(100, 0)
379j(100, .5)
380j(100, -.5)
381j(100, 1)
382j(100, -1)
383j(100, 1.5)
384j(100, -1.5)
385j(100, 1.74)
386j(100, -1.74)
387j(100, 2)
388j(100, -2)
389j(100, 3.2345)
390j(100, -3.2345)
391j(100, 100)
392j(100, -100)
393j(100, -.5)
394j(100, .5)
395j(100, -1)
396j(100, 1)
397j(100, -1.5)
398j(100, 1.5)
399j(100, -1.74)
400j(100, 1.74)
401j(100, -2)
402j(100, 2)
403j(100, -3.2345)
404j(100, 3.2345)
405j(100, -100)
406j(100, 100)
407j(-100, 0)
408j(-100, .5)
409j(-100, -.5)
410j(-100, 1)
411j(-100, -1)
412j(-100, 1.5)
413j(-100, -1.5)
414j(-100, 1.74)
415j(-100, -1.74)
416j(-100, 2)
417j(-100, -2)
418j(-100, 3.2345)
419j(-100, -3.2345)
420j(-100, 100)
421j(-100, -100)
422j(-100, -.5)
423j(-100, .5)
424j(-100, -1)
425j(-100, 1)
426j(-100, -1.5)
427j(-100, 1.5)
428j(-100, -1.74)
429j(-100, 1.74)
430j(-100, -2)
431j(-100, 2)
432j(-100, -3.2345)
433j(-100, 3.2345)
434j(-100, -100)
435j(-100, 100)
436j(-.5, 0)
437j(-.5, .5)
438j(-.5, -.5)
439j(-.5, 1)
440j(-.5, -1)
441j(-.5, 1.5)
442j(-.5, -1.5)
443j(-.5, 1.74)
444j(-.5, -1.74)
445j(-.5, 2)
446j(-.5, -2)
447j(-.5, 3.2345)
448j(-.5, -3.2345)
449j(-.5, 100)
450j(-.5, -100)
451j(-.5, -.5)
452j(-.5, .5)
453j(-.5, -1)
454j(-.5, 1)
455j(-.5, -1.5)
456j(-.5, 1.5)
457j(-.5, -1.74)
458j(-.5, 1.74)
459j(-.5, -2)
460j(-.5, 2)
461j(-.5, -3.2345)
462j(-.5, 3.2345)
463j(-.5, -100)
464j(-.5, 100)
465j(.5, 0)
466j(.5, .5)
467j(.5, -.5)
468j(.5, 1)
469j(.5, -1)
470j(.5, 1.5)
471j(.5, -1.5)
472j(.5, 1.74)
473j(.5, -1.74)
474j(.5, 2)
475j(.5, -2)
476j(.5, 3.2345)
477j(.5, -3.2345)
478j(.5, 100)
479j(.5, -100)
480j(.5, -.5)
481j(.5, .5)
482j(.5, -1)
483j(.5, 1)
484j(.5, -1.5)
485j(.5, 1.5)
486j(.5, -1.74)
487j(.5, 1.74)
488j(.5, -2)
489j(.5, 2)
490j(.5, -3.2345)
491j(.5, 3.2345)
492j(.5, -100)
493j(.5, 100)
494j(-1, 0)
495j(-1, .5)
496j(-1, -.5)
497j(-1, 1)
498j(-1, -1)
499j(-1, 1.5)
500j(-1, -1.5)
501j(-1, 1.74)
502j(-1, -1.74)
503j(-1, 2)
504j(-1, -2)
505j(-1, 3.2345)
506j(-1, -3.2345)
507j(-1, 100)
508j(-1, -100)
509j(-1, -.5)
510j(-1, .5)
511j(-1, -1)
512j(-1, 1)
513j(-1, -1.5)
514j(-1, 1.5)
515j(-1, -1.74)
516j(-1, 1.74)
517j(-1, -2)
518j(-1, 2)
519j(-1, -3.2345)
520j(-1, 3.2345)
521j(-1, -100)
522j(-1, 100)
523j(1, 0)
524j(1, .5)
525j(1, -.5)
526j(1, 1)
527j(1, -1)
528j(1, 1.5)
529j(1, -1.5)
530j(1, 1.74)
531j(1, -1.74)
532j(1, 2)
533j(1, -2)
534j(1, 3.2345)
535j(1, -3.2345)
536j(1, 100)
537j(1, -100)
538j(1, -.5)
539j(1, .5)
540j(1, -1)
541j(1, 1)
542j(1, -1.5)
543j(1, 1.5)
544j(1, -1.74)
545j(1, 1.74)
546j(1, -2)
547j(1, 2)
548j(1, -3.2345)
549j(1, 3.2345)
550j(1, -100)
551j(1, 100)
552j(-1.5, 0)
553j(-1.5, .5)
554j(-1.5, -.5)
555j(-1.5, 1)
556j(-1.5, -1)
557j(-1.5, 1.5)
558j(-1.5, -1.5)
559j(-1.5, 1.74)
560j(-1.5, -1.74)
561j(-1.5, 2)
562j(-1.5, -2)
563j(-1.5, 3.2345)
564j(-1.5, -3.2345)
565j(-1.5, 100)
566j(-1.5, -100)
567j(-1.5, -.5)
568j(-1.5, .5)
569j(-1.5, -1)
570j(-1.5, 1)
571j(-1.5, -1.5)
572j(-1.5, 1.5)
573j(-1.5, -1.74)
574j(-1.5, 1.74)
575j(-1.5, -2)
576j(-1.5, 2)
577j(-1.5, -3.2345)
578j(-1.5, 3.2345)
579j(-1.5, -100)
580j(-1.5, 100)
581j(1.5, 0)
582j(1.5, .5)
583j(1.5, -.5)
584j(1.5, 1)
585j(1.5, -1)
586j(1.5, 1.5)
587j(1.5, -1.5)
588j(1.5, 1.74)
589j(1.5, -1.74)
590j(1.5, 2)
591j(1.5, -2)
592j(1.5, 3.2345)
593j(1.5, -3.2345)
594j(1.5, 100)
595j(1.5, -100)
596j(1.5, -.5)
597j(1.5, .5)
598j(1.5, -1)
599j(1.5, 1)
600j(1.5, -1.5)
601j(1.5, 1.5)
602j(1.5, -1.74)
603j(1.5, 1.74)
604j(1.5, -2)
605j(1.5, 2)
606j(1.5, -3.2345)
607j(1.5, 3.2345)
608j(1.5, -100)
609j(1.5, 100)
610j(-1.74, 0)
611j(-1.74, .5)
612j(-1.74, -.5)
613j(-1.74, 1)
614j(-1.74, -1)
615j(-1.74, 1.5)
616j(-1.74, -1.5)
617j(-1.74, 1.74)
618j(-1.74, -1.74)
619j(-1.74, 2)
620j(-1.74, -2)
621j(-1.74, 3.2345)
622j(-1.74, -3.2345)
623j(-1.74, 100)
624j(-1.74, -100)
625j(-1.74, -.5)
626j(-1.74, .5)
627j(-1.74, -1)
628j(-1.74, 1)
629j(-1.74, -1.5)
630j(-1.74, 1.5)
631j(-1.74, -1.74)
632j(-1.74, 1.74)
633j(-1.74, -2)
634j(-1.74, 2)
635j(-1.74, -3.2345)
636j(-1.74, 3.2345)
637j(-1.74, -100)
638j(-1.74, 100)
639j(1.74, 0)
640j(1.74, .5)
641j(1.74, -.5)
642j(1.74, 1)
643j(1.74, -1)
644j(1.74, 1.5)
645j(1.74, -1.5)
646j(1.74, 1.74)
647j(1.74, -1.74)
648j(1.74, 2)
649j(1.74, -2)
650j(1.74, 3.2345)
651j(1.74, -3.2345)
652j(1.74, 100)
653j(1.74, -100)
654j(1.74, -.5)
655j(1.74, .5)
656j(1.74, -1)
657j(1.74, 1)
658j(1.74, -1.5)
659j(1.74, 1.5)
660j(1.74, -1.74)
661j(1.74, 1.74)
662j(1.74, -2)
663j(1.74, 2)
664j(1.74, -3.2345)
665j(1.74, 3.2345)
666j(1.74, -100)
667j(1.74, 100)
668j(-2, 0)
669j(-2, .5)
670j(-2, -.5)
671j(-2, 1)
672j(-2, -1)
673j(-2, 1.5)
674j(-2, -1.5)
675j(-2, 1.74)
676j(-2, -1.74)
677j(-2, 2)
678j(-2, -2)
679j(-2, 3.2345)
680j(-2, -3.2345)
681j(-2, 100)
682j(-2, -100)
683j(-2, -.5)
684j(-2, .5)
685j(-2, -1)
686j(-2, 1)
687j(-2, -1.5)
688j(-2, 1.5)
689j(-2, -1.74)
690j(-2, 1.74)
691j(-2, -2)
692j(-2, 2)
693j(-2, -3.2345)
694j(-2, 3.2345)
695j(-2, -100)
696j(-2, 100)
697j(2, 0)
698j(2, .5)
699j(2, -.5)
700j(2, 1)
701j(2, -1)
702j(2, 1.5)
703j(2, -1.5)
704j(2, 1.74)
705j(2, -1.74)
706j(2, 2)
707j(2, -2)
708j(2, 3.2345)
709j(2, -3.2345)
710j(2, 100)
711j(2, -100)
712j(2, -.5)
713j(2, .5)
714j(2, -1)
715j(2, 1)
716j(2, -1.5)
717j(2, 1.5)
718j(2, -1.74)
719j(2, 1.74)
720j(2, -2)
721j(2, 2)
722j(2, -3.2345)
723j(2, 3.2345)
724j(2, -100)
725j(2, 100)
726j(-3.2345, 0)
727j(-3.2345, .5)
728j(-3.2345, -.5)
729j(-3.2345, 1)
730j(-3.2345, -1)
731j(-3.2345, 1.5)
732j(-3.2345, -1.5)
733j(-3.2345, 1.74)
734j(-3.2345, -1.74)
735j(-3.2345, 2)
736j(-3.2345, -2)
737j(-3.2345, 3.2345)
738j(-3.2345, -3.2345)
739j(-3.2345, 100)
740j(-3.2345, -100)
741j(-3.2345, -.5)
742j(-3.2345, .5)
743j(-3.2345, -1)
744j(-3.2345, 1)
745j(-3.2345, -1.5)
746j(-3.2345, 1.5)
747j(-3.2345, -1.74)
748j(-3.2345, 1.74)
749j(-3.2345, -2)
750j(-3.2345, 2)
751j(-3.2345, -3.2345)
752j(-3.2345, 3.2345)
753j(-3.2345, -100)
754j(-3.2345, 100)
755j(3.2345, 0)
756j(3.2345, .5)
757j(3.2345, -.5)
758j(3.2345, 1)
759j(3.2345, -1)
760j(3.2345, 1.5)
761j(3.2345, -1.5)
762j(3.2345, 1.74)
763j(3.2345, -1.74)
764j(3.2345, 2)
765j(3.2345, -2)
766j(3.2345, 3.2345)
767j(3.2345, -3.2345)
768j(3.2345, 100)
769j(3.2345, -100)
770j(3.2345, -.5)
771j(3.2345, .5)
772j(3.2345, -1)
773j(3.2345, 1)
774j(3.2345, -1.5)
775j(3.2345, 1.5)
776j(3.2345, -1.74)
777j(3.2345, 1.74)
778j(3.2345, -2)
779j(3.2345, 2)
780j(3.2345, -3.2345)
781j(3.2345, 3.2345)
782j(3.2345, -100)
783j(3.2345, 100)
784j(-100, 0)
785j(-100, .5)
786j(-100, -.5)
787j(-100, 1)
788j(-100, -1)
789j(-100, 1.5)
790j(-100, -1.5)
791j(-100, 1.74)
792j(-100, -1.74)
793j(-100, 2)
794j(-100, -2)
795j(-100, 3.2345)
796j(-100, -3.2345)
797j(-100, 100)
798j(-100, -100)
799j(-100, -.5)
800j(-100, .5)
801j(-100, -1)
802j(-100, 1)
803j(-100, -1.5)
804j(-100, 1.5)
805j(-100, -1.74)
806j(-100, 1.74)
807j(-100, -2)
808j(-100, 2)
809j(-100, -3.2345)
810j(-100, 3.2345)
811j(-100, -100)
812j(-100, 100)
813j(100, 0)
814j(100, .5)
815j(100, -.5)
816j(100, 1)
817j(100, -1)
818j(100, 1.5)
819j(100, -1.5)
820j(100, 1.74)
821j(100, -1.74)
822j(100, 2)
823j(100, -2)
824j(100, 3.2345)
825j(100, -3.2345)
826j(100, 100)
827j(100, -100)
828j(100, -.5)
829j(100, .5)
830j(100, -1)
831j(100, 1)
832j(100, -1.5)
833j(100, 1.5)
834j(100, -1.74)
835j(100, 1.74)
836j(100, -2)
837j(100, 2)
838j(100, -3.2345)
839j(100, 3.2345)
840j(100, -100)
841j(100, 100)
842j(3, 0.75)
843scale = 0; j(40, 0.75)
844halt \ No newline at end of file
diff --git a/testsuite/bc_bessel_results.txt b/testsuite/bc_bessel_results.txt
new file mode 100644
index 000000000..4bbb3c86b
--- /dev/null
+++ b/testsuite/bc_bessel_results.txt
@@ -0,0 +1,843 @@
11.00000000000000000000
2.93846980724081290422
3.93846980724081290422
4.76519768655796655144
5.76519768655796655144
6.51182767173591812874
7.51182767173591812874
8.37483214773176892693
9.37483214773176892693
10.22389077914123566805
11.22389077914123566805
12-.32896462175888702221
13-.32896462175888702221
14.01998585030422312242
15.01998585030422312242
16.93846980724081290422
17.93846980724081290422
18.76519768655796655144
19.76519768655796655144
20.51182767173591812874
21.51182767173591812874
22.37483214773176892693
23.37483214773176892693
24.22389077914123566805
25.22389077914123566805
26-.32896462175888702221
27-.32896462175888702221
28.01998585030422312242
29.01998585030422312242
301.00000000000000000000
31.93846980724081290422
32.93846980724081290422
33.76519768655796655144
34.76519768655796655144
35.51182767173591812874
36.51182767173591812874
37.37483214773176892693
38.37483214773176892693
39.22389077914123566805
40.22389077914123566805
41-.32896462175888702221
42-.32896462175888702221
43.01998585030422312242
44.01998585030422312242
45.93846980724081290422
46.93846980724081290422
47.76519768655796655144
48.76519768655796655144
49.51182767173591812874
50.51182767173591812874
51.37483214773176892693
52.37483214773176892693
53.22389077914123566805
54.22389077914123566805
55-.32896462175888702221
56-.32896462175888702221
57.01998585030422312242
58.01998585030422312242
591.00000000000000000000
60.93846980724081290422
61.93846980724081290422
62.76519768655796655144
63.76519768655796655144
64.51182767173591812874
65.51182767173591812874
66.37483214773176892693
67.37483214773176892693
68.22389077914123566805
69.22389077914123566805
70-.32896462175888702221
71-.32896462175888702221
72.01998585030422312242
73.01998585030422312242
74.93846980724081290422
75.93846980724081290422
76.76519768655796655144
77.76519768655796655144
78.51182767173591812874
79.51182767173591812874
80.37483214773176892693
81.37483214773176892693
82.22389077914123566805
83.22389077914123566805
84-.32896462175888702221
85-.32896462175888702221
86.01998585030422312242
87.01998585030422312242
880
89.24226845767487388638
90-.24226845767487388638
91.44005058574493351595
92-.44005058574493351595
93.55793650791009964199
94-.55793650791009964199
95.57976044202797131452
96-.57976044202797131452
97.57672480775687338720
98-.57672480775687338720
99.24741588607612652213
100-.24741588607612652213
101-.07714535201411215803
102.07714535201411215803
103-.24226845767487388638
104.24226845767487388638
105-.44005058574493351595
106.44005058574493351595
107-.55793650791009964199
108.55793650791009964199
109-.57976044202797131452
110.57976044202797131452
111-.57672480775687338720
112.57672480775687338720
113-.24741588607612652213
114.24741588607612652213
115.07714535201411215803
116-.07714535201411215803
1170
118-.24226845767487388638
119.24226845767487388638
120-.44005058574493351595
121.44005058574493351595
122-.55793650791009964199
123.55793650791009964199
124-.57976044202797131452
125.57976044202797131452
126-.57672480775687338720
127.57672480775687338720
128-.24741588607612652213
129.24741588607612652213
130.07714535201411215803
131-.07714535201411215803
132.24226845767487388638
133-.24226845767487388638
134.44005058574493351595
135-.44005058574493351595
136.55793650791009964199
137-.55793650791009964199
138.57976044202797131452
139-.57976044202797131452
140.57672480775687338720
141-.57672480775687338720
142.24741588607612652213
143-.24741588607612652213
144-.07714535201411215803
145.07714535201411215803
1460
147.24226845767487388638
148-.24226845767487388638
149.44005058574493351595
150-.44005058574493351595
151.55793650791009964199
152-.55793650791009964199
153.57976044202797131452
154-.57976044202797131452
155.57672480775687338720
156-.57672480775687338720
157.24741588607612652213
158-.24741588607612652213
159-.07714535201411215803
160.07714535201411215803
161-.24226845767487388638
162.24226845767487388638
163-.44005058574493351595
164.44005058574493351595
165-.55793650791009964199
166.55793650791009964199
167-.57976044202797131452
168.57976044202797131452
169-.57672480775687338720
170.57672480775687338720
171-.24741588607612652213
172.24741588607612652213
173.07714535201411215803
174-.07714535201411215803
1750
176-.24226845767487388638
177.24226845767487388638
178-.44005058574493351595
179.44005058574493351595
180-.55793650791009964199
181.55793650791009964199
182-.57976044202797131452
183.57976044202797131452
184-.57672480775687338720
185.57672480775687338720
186-.24741588607612652213
187.24741588607612652213
188.07714535201411215803
189-.07714535201411215803
190.24226845767487388638
191-.24226845767487388638
192.44005058574493351595
193-.44005058574493351595
194.55793650791009964199
195-.55793650791009964199
196.57976044202797131452
197-.57976044202797131452
198.57672480775687338720
199-.57672480775687338720
200.24741588607612652213
201-.24741588607612652213
202-.07714535201411215803
203.07714535201411215803
2040
205.24226845767487388638
206-.24226845767487388638
207.44005058574493351595
208-.44005058574493351595
209.55793650791009964199
210-.55793650791009964199
211.57976044202797131452
212-.57976044202797131452
213.57672480775687338720
214-.57672480775687338720
215.24741588607612652213
216-.24741588607612652213
217-.07714535201411215803
218.07714535201411215803
219-.24226845767487388638
220.24226845767487388638
221-.44005058574493351595
222.44005058574493351595
223-.55793650791009964199
224.55793650791009964199
225-.57976044202797131452
226.57976044202797131452
227-.57672480775687338720
228.57672480775687338720
229-.24741588607612652213
230.24741588607612652213
231.07714535201411215803
232-.07714535201411215803
2330
234-.24226845767487388638
235.24226845767487388638
236-.44005058574493351595
237.44005058574493351595
238-.55793650791009964199
239.55793650791009964199
240-.57976044202797131452
241.57976044202797131452
242-.57672480775687338720
243.57672480775687338720
244-.24741588607612652213
245.24741588607612652213
246.07714535201411215803
247-.07714535201411215803
248.24226845767487388638
249-.24226845767487388638
250.44005058574493351595
251-.44005058574493351595
252.55793650791009964199
253-.55793650791009964199
254.57976044202797131452
255-.57976044202797131452
256.57672480775687338720
257-.57672480775687338720
258.24741588607612652213
259-.24741588607612652213
260-.07714535201411215803
261.07714535201411215803
2620
263.03060402345868264130
264.03060402345868264130
265.11490348493190048046
266.11490348493190048046
267.23208767214421472723
268.23208767214421472723
269.29155916494406017021
270.29155916494406017021
271.35283402861563771915
272.35283402861563771915
273.48195017505993913050
274.48195017505993913050
275-.02152875734450536558
276-.02152875734450536558
277.03060402345868264130
278.03060402345868264130
279.11490348493190048046
280.11490348493190048046
281.23208767214421472723
282.23208767214421472723
283.29155916494406017021
284.29155916494406017021
285.35283402861563771915
286.35283402861563771915
287.48195017505993913050
288.48195017505993913050
289-.02152875734450536558
290-.02152875734450536558
2910
292.03060402345868264130
293.03060402345868264130
294.11490348493190048046
295.11490348493190048046
296.23208767214421472723
297.23208767214421472723
298.29155916494406017021
299.29155916494406017021
300.35283402861563771915
301.35283402861563771915
302.48195017505993913050
303.48195017505993913050
304-.02152875734450536558
305-.02152875734450536558
306.03060402345868264130
307.03060402345868264130
308.11490348493190048046
309.11490348493190048046
310.23208767214421472723
311.23208767214421472723
312.29155916494406017021
313.29155916494406017021
314.35283402861563771915
315.35283402861563771915
316.48195017505993913050
317.48195017505993913050
318-.02152875734450536558
319-.02152875734450536558
3200
321.00256372999458724407
322-.00256372999458724407
323.01956335398266840591
324-.01956335398266840591
325.06096395114113963064
326-.06096395114113963064
327.09049051186641988137
328-.09049051186641988137
329.12894324947440205109
330-.12894324947440205109
331.34859607875298354805
332-.34859607875298354805
333.07628420172033194340
334-.07628420172033194340
335-.00256372999458724407
336.00256372999458724407
337-.01956335398266840591
338.01956335398266840591
339-.06096395114113963064
340.06096395114113963064
341-.09049051186641988137
342.09049051186641988137
343-.12894324947440205109
344.12894324947440205109
345-.34859607875298354805
346.34859607875298354805
347-.07628420172033194340
348.07628420172033194340
3490
350-.00256372999458724407
351.00256372999458724407
352-.01956335398266840591
353.01956335398266840591
354-.06096395114113963064
355.06096395114113963064
356-.09049051186641988137
357.09049051186641988137
358-.12894324947440205109
359.12894324947440205109
360-.34859607875298354805
361.34859607875298354805
362-.07628420172033194340
363.07628420172033194340
364.00256372999458724407
365-.00256372999458724407
366.01956335398266840591
367-.01956335398266840591
368.06096395114113963064
369-.06096395114113963064
370.09049051186641988137
371-.09049051186641988137
372.12894324947440205109
373-.12894324947440205109
374.34859607875298354805
375-.34859607875298354805
376.07628420172033194340
377-.07628420172033194340
3780
3790
3800
3810
3820
3830
3840
3850
3860
3870
3880
3890
3900
391.09636667329586155967
392.09636667329586155967
3930
3940
3950
3960
3970
3980
3990
4000
4010
4020
4030
4040
405.09636667329586155967
406.09636667329586155967
4070
4080
4090
4100
4110
4120
4130
4140
4150
4160
4170
4180
4190
420.09636667329586155967
421.09636667329586155967
4220
4230
4240
4250
4260
4270
4280
4290
4300
4310
4320
4330
434.09636667329586155967
435.09636667329586155967
4361.00000000000000000000
437.93846980724081290422
438.93846980724081290422
439.76519768655796655144
440.76519768655796655144
441.51182767173591812874
442.51182767173591812874
443.37483214773176892693
444.37483214773176892693
445.22389077914123566805
446.22389077914123566805
447-.32896462175888702221
448-.32896462175888702221
449.01998585030422312242
450.01998585030422312242
451.93846980724081290422
452.93846980724081290422
453.76519768655796655144
454.76519768655796655144
455.51182767173591812874
456.51182767173591812874
457.37483214773176892693
458.37483214773176892693
459.22389077914123566805
460.22389077914123566805
461-.32896462175888702221
462-.32896462175888702221
463.01998585030422312242
464.01998585030422312242
4651.00000000000000000000
466.93846980724081290422
467.93846980724081290422
468.76519768655796655144
469.76519768655796655144
470.51182767173591812874
471.51182767173591812874
472.37483214773176892693
473.37483214773176892693
474.22389077914123566805
475.22389077914123566805
476-.32896462175888702221
477-.32896462175888702221
478.01998585030422312242
479.01998585030422312242
480.93846980724081290422
481.93846980724081290422
482.76519768655796655144
483.76519768655796655144
484.51182767173591812874
485.51182767173591812874
486.37483214773176892693
487.37483214773176892693
488.22389077914123566805
489.22389077914123566805
490-.32896462175888702221
491-.32896462175888702221
492.01998585030422312242
493.01998585030422312242
4940
495-.24226845767487388638
496.24226845767487388638
497-.44005058574493351595
498.44005058574493351595
499-.55793650791009964199
500.55793650791009964199
501-.57976044202797131452
502.57976044202797131452
503-.57672480775687338720
504.57672480775687338720
505-.24741588607612652213
506.24741588607612652213
507.07714535201411215803
508-.07714535201411215803
509.24226845767487388638
510-.24226845767487388638
511.44005058574493351595
512-.44005058574493351595
513.55793650791009964199
514-.55793650791009964199
515.57976044202797131452
516-.57976044202797131452
517.57672480775687338720
518-.57672480775687338720
519.24741588607612652213
520-.24741588607612652213
521-.07714535201411215803
522.07714535201411215803
5230
524.24226845767487388638
525-.24226845767487388638
526.44005058574493351595
527-.44005058574493351595
528.55793650791009964199
529-.55793650791009964199
530.57976044202797131452
531-.57976044202797131452
532.57672480775687338720
533-.57672480775687338720
534.24741588607612652213
535-.24741588607612652213
536-.07714535201411215803
537.07714535201411215803
538-.24226845767487388638
539.24226845767487388638
540-.44005058574493351595
541.44005058574493351595
542-.55793650791009964199
543.55793650791009964199
544-.57976044202797131452
545.57976044202797131452
546-.57672480775687338720
547.57672480775687338720
548-.24741588607612652213
549.24741588607612652213
550.07714535201411215803
551-.07714535201411215803
5520
553-.24226845767487388638
554.24226845767487388638
555-.44005058574493351595
556.44005058574493351595
557-.55793650791009964199
558.55793650791009964199
559-.57976044202797131452
560.57976044202797131452
561-.57672480775687338720
562.57672480775687338720
563-.24741588607612652213
564.24741588607612652213
565.07714535201411215803
566-.07714535201411215803
567.24226845767487388638
568-.24226845767487388638
569.44005058574493351595
570-.44005058574493351595
571.55793650791009964199
572-.55793650791009964199
573.57976044202797131452
574-.57976044202797131452
575.57672480775687338720
576-.57672480775687338720
577.24741588607612652213
578-.24741588607612652213
579-.07714535201411215803
580.07714535201411215803
5810
582.24226845767487388638
583-.24226845767487388638
584.44005058574493351595
585-.44005058574493351595
586.55793650791009964199
587-.55793650791009964199
588.57976044202797131452
589-.57976044202797131452
590.57672480775687338720
591-.57672480775687338720
592.24741588607612652213
593-.24741588607612652213
594-.07714535201411215803
595.07714535201411215803
596-.24226845767487388638
597.24226845767487388638
598-.44005058574493351595
599.44005058574493351595
600-.55793650791009964199
601.55793650791009964199
602-.57976044202797131452
603.57976044202797131452
604-.57672480775687338720
605.57672480775687338720
606-.24741588607612652213
607.24741588607612652213
608.07714535201411215803
609-.07714535201411215803
6100
611-.24226845767487388638
612.24226845767487388638
613-.44005058574493351595
614.44005058574493351595
615-.55793650791009964199
616.55793650791009964199
617-.57976044202797131452
618.57976044202797131452
619-.57672480775687338720
620.57672480775687338720
621-.24741588607612652213
622.24741588607612652213
623.07714535201411215803
624-.07714535201411215803
625.24226845767487388638
626-.24226845767487388638
627.44005058574493351595
628-.44005058574493351595
629.55793650791009964199
630-.55793650791009964199
631.57976044202797131452
632-.57976044202797131452
633.57672480775687338720
634-.57672480775687338720
635.24741588607612652213
636-.24741588607612652213
637-.07714535201411215803
638.07714535201411215803
6390
640.24226845767487388638
641-.24226845767487388638
642.44005058574493351595
643-.44005058574493351595
644.55793650791009964199
645-.55793650791009964199
646.57976044202797131452
647-.57976044202797131452
648.57672480775687338720
649-.57672480775687338720
650.24741588607612652213
651-.24741588607612652213
652-.07714535201411215803
653.07714535201411215803
654-.24226845767487388638
655.24226845767487388638
656-.44005058574493351595
657.44005058574493351595
658-.55793650791009964199
659.55793650791009964199
660-.57976044202797131452
661.57976044202797131452
662-.57672480775687338720
663.57672480775687338720
664-.24741588607612652213
665.24741588607612652213
666.07714535201411215803
667-.07714535201411215803
6680
669.03060402345868264130
670.03060402345868264130
671.11490348493190048046
672.11490348493190048046
673.23208767214421472723
674.23208767214421472723
675.29155916494406017021
676.29155916494406017021
677.35283402861563771915
678.35283402861563771915
679.48195017505993913050
680.48195017505993913050
681-.02152875734450536558
682-.02152875734450536558
683.03060402345868264130
684.03060402345868264130
685.11490348493190048046
686.11490348493190048046
687.23208767214421472723
688.23208767214421472723
689.29155916494406017021
690.29155916494406017021
691.35283402861563771915
692.35283402861563771915
693.48195017505993913050
694.48195017505993913050
695-.02152875734450536558
696-.02152875734450536558
6970
698.03060402345868264130
699.03060402345868264130
700.11490348493190048046
701.11490348493190048046
702.23208767214421472723
703.23208767214421472723
704.29155916494406017021
705.29155916494406017021
706.35283402861563771915
707.35283402861563771915
708.48195017505993913050
709.48195017505993913050
710-.02152875734450536558
711-.02152875734450536558
712.03060402345868264130
713.03060402345868264130
714.11490348493190048046
715.11490348493190048046
716.23208767214421472723
717.23208767214421472723
718.29155916494406017021
719.29155916494406017021
720.35283402861563771915
721.35283402861563771915
722.48195017505993913050
723.48195017505993913050
724-.02152875734450536558
725-.02152875734450536558
7260
727-.00256372999458724407
728.00256372999458724407
729-.01956335398266840591
730.01956335398266840591
731-.06096395114113963064
732.06096395114113963064
733-.09049051186641988137
734.09049051186641988137
735-.12894324947440205109
736.12894324947440205109
737-.34859607875298354805
738.34859607875298354805
739-.07628420172033194340
740.07628420172033194340
741.00256372999458724407
742-.00256372999458724407
743.01956335398266840591
744-.01956335398266840591
745.06096395114113963064
746-.06096395114113963064
747.09049051186641988137
748-.09049051186641988137
749.12894324947440205109
750-.12894324947440205109
751.34859607875298354805
752-.34859607875298354805
753.07628420172033194340
754-.07628420172033194340
7550
756.00256372999458724407
757-.00256372999458724407
758.01956335398266840591
759-.01956335398266840591
760.06096395114113963064
761-.06096395114113963064
762.09049051186641988137
763-.09049051186641988137
764.12894324947440205109
765-.12894324947440205109
766.34859607875298354805
767-.34859607875298354805
768.07628420172033194340
769-.07628420172033194340
770-.00256372999458724407
771.00256372999458724407
772-.01956335398266840591
773.01956335398266840591
774-.06096395114113963064
775.06096395114113963064
776-.09049051186641988137
777.09049051186641988137
778-.12894324947440205109
779.12894324947440205109
780-.34859607875298354805
781.34859607875298354805
782-.07628420172033194340
783.07628420172033194340
7840
7850
7860
7870
7880
7890
7900
7910
7920
7930
7940
7950
7960
797.09636667329586155967
798.09636667329586155967
7990
8000
8010
8020
8030
8040
8050
8060
8070
8080
8090
8100
811.09636667329586155967
812.09636667329586155967
8130
8140
8150
8160
8170
8180
8190
8200
8210
8220
8230
8240
8250
826.09636667329586155967
827.09636667329586155967
8280
8290
8300
8310
8320
8330
8340
8350
8360
8370
8380
8390
840.09636667329586155967
841.09636667329586155967
842.00848438342327410884
8430
diff --git a/testsuite/bc_boolean.bc b/testsuite/bc_boolean.bc
new file mode 100644
index 000000000..021afc5f9
--- /dev/null
+++ b/testsuite/bc_boolean.bc
@@ -0,0 +1,181 @@
1!0
2!1
3!(-129)
44 && 5
54 && 0
60 && 5
74 && 5 && 7
84 && 0 && 7
90 && 5 && 7
104 && 5 && 0
110 && 0 && 7
124 && 0 && 0
130 && 5 && 0
14!4 && 5
15!4 && 0
16!0 && 5
174 && !5
184 && !0
190 && !5
20!4 && 5 && 7
21!4 && 0 && 7
22!0 && 5 && 7
23!4 && 5 && 0
24!0 && 0 && 7
25!4 && 0 && 0
26!0 && 5 && 0
274 && !5 && 7
284 && !0 && 7
290 && !5 && 7
304 && !5 && 0
310 && !0 && 7
324 && !0 && 0
330 && !5 && 0
344 && 5 && !7
354 && 0 && !7
360 && 5 && !7
374 && 5 && !0
380 && 0 && !7
394 && 0 && !0
400 && 5 && !0
41!4 && !5 && 7
42!4 && !0 && 7
43!0 && !5 && 7
44!4 && !5 && 0
45!0 && !0 && 7
46!4 && !0 && 0
47!0 && !5 && 0
48!4 && 5 && !7
49!4 && 0 && !7
50!0 && 5 && !7
51!4 && 5 && !0
52!0 && 0 && !7
53!4 && 0 && !0
54!0 && 5 && !0
554 && !5 && !7
564 && !0 && !7
570 && !5 && !7
584 && !5 && !0
590 && !0 && !7
604 && !0 && !0
610 && !5 && !0
62!4 && !5 && !7
63!4 && !0 && !7
64!0 && !5 && !7
65!4 && !5 && !0
66!0 && !0 && !7
67!4 && !0 && !0
68!0 && !5 && !0
693 < 4 && 7
703 && 4 >= 4
713 > 4 && 7
723 && 4 >= 5
733 < 4 && 0
740 && 4 >= 4
753 > 4 && 0
760 && 4 >= 5
773 > 4 && 0
780 && 4 < 4
793 >= 4 && 0
800 && 4 >= 5
813 < 4 && 7
823 && 4 >= 4
833 > 4 && 7 > 4
843 >= 2 && 4 >= 5
853 < 4 && 0 > -1
864 < 3 && 4 >= 4
873 > 4 && 3 == 3
883 != 3 && 4 >= 5
893 > 4 && 0 > 1
900 >= 0 && 4 < 4
913 >= 4 && 0 >= 1
920 <= -1 && 4 >= 5
934 || 5
944 || 0
950 || 5
964 || 5 || 7
974 || 0 || 7
980 || 5 || 7
994 || 5 || 0
1000 || 0 || 7
1014 || 0 || 0
1020 || 5 || 0
103!4 || 5
104!4 || 0
105!0 || 5
1064 || !5
1074 || !0
1080 || !5
109!4 || 5 || 7
110!4 || 0 || 7
111!0 || 5 || 7
112!4 || 5 || 0
113!0 || 0 || 7
114!4 || 0 || 0
115!0 || 5 || 0
1164 || !5 || 7
1174 || !0 || 7
1180 || !5 || 7
1194 || !5 || 0
1200 || !0 || 7
1214 || !0 || 0
1220 || !5 || 0
1234 || 5 || !7
1244 || 0 || !7
1250 || 5 || !7
1264 || 5 || !0
1270 || 0 || !7
1284 || 0 || !0
1290 || 5 || !0
130!4 || !5 || 7
131!4 || !0 || 7
132!0 || !5 || 7
133!4 || !5 || 0
134!0 || !0 || 7
135!4 || !0 || 0
136!0 || !5 || 0
137!4 || 5 || !7
138!4 || 0 || !7
139!0 || 5 || !7
140!4 || 5 || !0
141!0 || 0 || !7
142!4 || 0 || !0
143!0 || 5 || !0
1444 || !5 || !7
1454 || !0 || !7
1460 || !5 || !7
1474 || !5 || !0
1480 || !0 || !7
1494 || !0 || !0
1500 || !5 || !0
151!4 || !5 || !7
152!4 || !0 || !7
153!0 || !5 || !7
154!4 || !5 || !0
155!0 || !0 || !7
156!4 || !0 || !0
157!0 || !5 || !0
1583 < 4 || 7
1593 || 4 >= 4
1603 > 4 || 7
1613 || 4 >= 5
1623 < 4 || 0
1630 || 4 >= 4
1643 > 4 || 0
1650 || 4 >= 5
1663 > 4 || 0
1670 || 4 < 4
1683 >= 4 || 0
1690 || 4 >= 5
1703 < 4 || 7
1713 || 4 >= 4
1723 > 4 || 7 > 4
1733 >= 2 || 4 >= 5
1743 < 4 || 0 > -1
1754 < 3 || 4 >= 4
1763 > 4 || 3 == 3
1773 != 3 || 4 >= 5
1783 > 4 || 0 > 1
1790 >= 0 || 4 < 4
1803 >= 4 || 0 >= 1
1810 <= -1 || 4 >= 5
diff --git a/testsuite/bc_boolean_results.txt b/testsuite/bc_boolean_results.txt
new file mode 100644
index 000000000..ea59389c0
--- /dev/null
+++ b/testsuite/bc_boolean_results.txt
@@ -0,0 +1,181 @@
11
20
30
41
50
60
71
80
90
100
110
120
130
140
150
161
170
181
190
200
210
221
230
240
250
260
270
281
290
300
310
320
330
340
350
360
371
380
390
400
410
420
430
440
451
460
470
480
490
500
510
520
530
541
550
560
570
580
590
601
610
620
630
640
650
660
670
680
691
701
710
720
730
740
750
760
770
780
790
800
811
821
830
840
851
860
870
880
890
900
910
920
931
941
951
961
971
981
991
1001
1011
1021
1031
1040
1051
1061
1071
1080
1091
1101
1111
1121
1131
1140
1151
1161
1171
1181
1191
1201
1211
1220
1231
1241
1251
1261
1270
1281
1291
1301
1311
1321
1330
1341
1351
1361
1371
1380
1391
1401
1411
1421
1431
1441
1451
1460
1471
1481
1491
1501
1510
1521
1531
1541
1551
1561
1571
1581
1591
1601
1611
1621
1631
1640
1650
1660
1670
1680
1690
1701
1711
1721
1731
1741
1751
1761
1770
1780
1791
1800
1810
diff --git a/testsuite/bc_cosine.bc b/testsuite/bc_cosine.bc
new file mode 100644
index 000000000..9e67df4c6
--- /dev/null
+++ b/testsuite/bc_cosine.bc
@@ -0,0 +1,44 @@
1scale = 25
2p = 4 * a(1)
3scale = 20
4c(0)
5c(0.5)
6c(1)
7c(2)
8c(3)
9c(-0.5)
10c(-1)
11c(-2)
12c(-3)
13c(p / 7)
14c(-p / 7)
15c(p / 4)
16c(-p / 4)
17c(p / 3)
18c(-p / 3)
19c(p / 2)
20c(-p / 2)
21c(3 * p / 4)
22c(3 * -p / 4)
23c(p)
24c(-p)
25c(3 * p / 2)
26c(3 * -p / 2)
27c(7 * p / 4)
28c(7 * -p / 4)
29c(13 * p / 4)
30c(13 * -p / 4)
31c(2 * p)
32c(2 * -p)
33c(131231)
34c(-131231)
35c(859799894.3562378245)
36c(859799894.3562378245)
37c(4307371)
38c(3522556.3323810191)
39c(44961070)
40c(6918619.1574479809)
41c(190836996.2180244164)
42c(34934)
43c(2483599)
44c(13720376)
diff --git a/testsuite/bc_cosine_results.txt b/testsuite/bc_cosine_results.txt
new file mode 100644
index 000000000..43d640f00
--- /dev/null
+++ b/testsuite/bc_cosine_results.txt
@@ -0,0 +1,41 @@
11.00000000000000000000
2.87758256189037271611
3.54030230586813971740
4-.41614683654714238699
5-.98999249660044545727
6.87758256189037271611
7.54030230586813971740
8-.41614683654714238699
9-.98999249660044545727
10.90096886790241912623
11.90096886790241912623
12.70710678118654752440
13.70710678118654752440
14.50000000000000000000
15.50000000000000000000
160
170
18-.70710678118654752439
19-.70710678118654752439
20-1.00000000000000000000
21-1.00000000000000000000
220
230
24.70710678118654752439
25.70710678118654752439
26-.70710678118654752440
27-.70710678118654752440
281.00000000000000000000
291.00000000000000000000
30.92427123447397657316
31.92427123447397657316
32-.04198856352825241211
33-.04198856352825241211
34-.75581969921220636368
35-.01644924448939844182
36-.97280717522127222547
37-.92573947460230585966
38-.14343824233852988038
39.87259414746802343203
40.93542606623067050616
41-.52795540572178251550
diff --git a/testsuite/bc_decimal.bc b/testsuite/bc_decimal.bc
new file mode 100644
index 000000000..9b1788c67
--- /dev/null
+++ b/testsuite/bc_decimal.bc
@@ -0,0 +1,36 @@
10
20.0
3.00000
4000000000000000000000000.00000000000000000000000
5000000000000000000000000000135482346782356
6000000000000000000000000002
71
811
9123
107505
111023468723275435238491972521917846
124343472432431705867392073517038270398027352709027389273920739037937960379637893607893607893670530278200795207952702873892786172916728961783907893607418973587857386079679267926737520730925372983782793652793
13-1
14-203
15-57
16-18586
17-31378682943772818461924738352952347258
18-823945628745673589495067238723986520375698237620834674509627345273096287563846592384526349872634895763257893467523987578690283762897568459072348758071071087813501875908127359018715023841710239872301387278
19.123521346523546
200.1245923756273856
21-.1024678456387
22-0.8735863475634587
234.0
24-6.0
25234237468293576.000000000000000000000000000000
2623987623568943567.00000000000000000005677834650000000000000
2723856934568940675.000000000000000435676782300000000000000456784
2877567648698496.000000000000000000587674750000000000458563800000000000000
292348672354968723.2374823546000000000003256987394502346892435623870000000034578
30-2354768.000000000000000000000000000000000000
31-96739874567.000000000347683456
32-3764568345.000000000004573845000000347683460
33-356784356.934568495770004586495678300000000
3474325437345273852773827101738273127312738521733017537073520735207307570358738257390761276072160719802671980267018728630178.7082681027680521760217867841276127681270867827821768173178207830710978017738178678012767377058785378278207385237085237803278203782037237582795870
35-756752732785273851273728537852738257837283678965738527385272983678372867327835672967385278372637862738627836279863782673862783670.71738178361738718367186378610738617836781603760178367018603760178107735278372832783728367826738627836278378260736270367362073867097307925
369812734012837410982345719208345712908357412903587192048571920458712.23957182459817249058172945781
diff --git a/testsuite/bc_decimal_results.txt b/testsuite/bc_decimal_results.txt
new file mode 100644
index 000000000..275d431c6
--- /dev/null
+++ b/testsuite/bc_decimal_results.txt
@@ -0,0 +1,51 @@
10
20
30
40
5135482346782356
62
71
811
9123
107505
111023468723275435238491972521917846
1243434724324317058673920735170382703980273527090273892739207390379379\
1360379637893607893607893670530278200795207952702873892786172916728961\
1478390789360741897358785738607967926792673752073092537298378279365279\
153
16-1
17-203
18-57
19-18586
20-31378682943772818461924738352952347258
21-8239456287456735894950672387239865203756982376208346745096273452730\
2296287563846592384526349872634895763257893467523987578690283762897568\
2345907234875807107108781350187590812735901871502384171023987230138727\
248
25.123521346523546
26.1245923756273856
27-.1024678456387
28-.8735863475634587
294.0
30-6.0
31234237468293576.000000000000000000000000000000
3223987623568943567.00000000000000000005677834650000000000000
3323856934568940675.000000000000000435676782300000000000000456784
3477567648698496.00000000000000000058767475000000000045856380000000000\
350000
362348672354968723.237482354600000000000325698739450234689243562387000\
370000034578
38-2354768.000000000000000000000000000000000000
39-96739874567.000000000347683456
40-3764568345.000000000004573845000000347683460
41-356784356.934568495770004586495678300000000
4274325437345273852773827101738273127312738521733017537073520735207307\
43570358738257390761276072160719802671980267018728630178.7082681027680\
4452176021786784127612768127086782782176817317820783071097801773817867\
458012767377058785378278207385237085237803278203782037237582795870
46-7567527327852738512737285378527382578372836789657385273852729836783\
4772867327835672967385278372637862738627836279863782673862783670.71738\
4817836173871836718637861073861783678160376017836701860376017810773527\
498372832783728367826738627836278378260736270367362073867097307925
509812734012837410982345719208345712908357412903587192048571920458712.\
5123957182459817249058172945781
diff --git a/testsuite/bc_divide.bc b/testsuite/bc_divide.bc
new file mode 100644
index 000000000..4d0caddc9
--- /dev/null
+++ b/testsuite/bc_divide.bc
@@ -0,0 +1,31 @@
10 / 1
20 / 321566
30 / 0.3984567238456
41 / 1
51 / 1287469297356
61 / 0.2395672438567234
71 / 237586239856.0293596728392360
81249687284356 / 3027949207835207
9378617298617396719 / 35748521
109348576237845624358 / 0.9857829375461
1135768293846193284 / 2374568947.045762839567823
12-78987234567812345 / 876542837618936
13-356789237555535468 / 0.3375273860984786903
14-5203475364850390 / 435742903748307.70869378534043296404530458
15-0.37861723347576903 / 7385770896
16-0.399454682043962 / 0.34824389304
17-0.6920414523873204 / 356489645223.76076045304879030
18-35872917389671.7573280963748 / 73924708
19-78375896314.4836709876983 / 0.78356798637817
20-2374123896417.143789621437581 / 347821469423789.1473856783960
21-896729350238549726 / -34976289345762
22-2374568293458762348596 / -0.8792370647234987679
23-237584692306721845726038 / -21783910782374529637.978102738746189024761
24-0.23457980123576298375682 / -1375486293874612
25-0.173897061862478951264 / -0.8179327486017634987516298745
26-0.9186739823576829347586 / -0.235678293458756239846
27-0.9375896183746982374568 / -13784962873546.0928729395476283745
28-2930754618923467.12323745862937465 / -734869238465
29-23745861923467.874675129834675 / -0.23542357869124756
30-3878923750692883.7238596702834756902 / -7384192674957215364986723.9738461923487621983
311 / 0.00000000000000000000000000000000000000000002346728372937352457354204563027
diff --git a/testsuite/bc_divide_results.txt b/testsuite/bc_divide_results.txt
new file mode 100644
index 000000000..c19f2f9b0
--- /dev/null
+++ b/testsuite/bc_divide_results.txt
@@ -0,0 +1,31 @@
10
20
30
41.00000000000000000000
5.00000000000077671755
64.17419336592637110778
7.00000000000420899796
8.00041271738677857404
910591131829.40901859967857131767
109483402361494453751.52388015648196297248
1115063068.13735316451497043884
12-90.11223545260531110575
13-1057067521778623447.45138528213564485251
14-11.94161814246320631346
15-.00000000005126306228
16-1.14705437777218917343
17-.00000000000194126663
18-485262.88923145638029569727
19-100024372711.74763635544535424582
20-.00682569681609989277
2125638.20711150436682153521
222700714504347599627864.24626421085374010264
2310906.42973524078145692731
24.00000000000000017054
25.21260557443109085166
263.89799997647407910677
27.00000000000006801538
283988.13076601933678578945
29100864416620775.31076855630746548983
30.00000000052530099381
3142612515855353136519261264261472677699404182.78776061098893912189
diff --git a/testsuite/bc_exponent.bc b/testsuite/bc_exponent.bc
new file mode 100644
index 000000000..40bcf3c5a
--- /dev/null
+++ b/testsuite/bc_exponent.bc
@@ -0,0 +1,22 @@
1e(0)
2e(0.5)
3e(1)
4e(1.5)
5e(1.74)
6e(2)
7e(3.2345)
8e(5.283957)
9e(13.23857)
10e(100)
11e(283.238957)
12e(-0.5)
13e(-1)
14e(-1.5)
15e(-1.74)
16e(-2)
17e(-3.2345)
18e(-5.283957)
19e(-13.23857)
20e(-100)
21e(-283.238957)
22e(142.749502399)
diff --git a/testsuite/bc_exponent_results.txt b/testsuite/bc_exponent_results.txt
new file mode 100644
index 000000000..a1f1fe2b4
--- /dev/null
+++ b/testsuite/bc_exponent_results.txt
@@ -0,0 +1,25 @@
11.00000000000000000000
21.64872127070012814684
32.71828182845904523536
44.48168907033806482260
55.69734342267199101193
67.38905609893065022723
725.39367176822616278859
8197.14845034328553587817
9561613.96621445383501864766
1026881171418161354484126255515800135873611118.77374192241519160861
1110212124131159922810249757193864245307850725332411569566443792548720\
1275182918653384240389953781407569563117008113027037939783.70141667971\
13570827872
14.60653065971263342360
15.36787944117144232159
16.22313016014842982893
17.17552040061699687169
18.13533528323661269189
19.03937988996342191888
20.00507231985977442865
21.00000178058250000525
220
230
2498928445824097165243611240348236907682258759298273030827411201.25833\
25645622510213538
diff --git a/testsuite/bc_log.bc b/testsuite/bc_log.bc
new file mode 100644
index 000000000..54115e380
--- /dev/null
+++ b/testsuite/bc_log.bc
@@ -0,0 +1,22 @@
1l(0)
2l(0.5)
3l(1)
4l(1.5)
5l(1.74)
6l(2)
7l(3.2345)
8l(5.283957)
9l(13.23857)
10l(100)
11l(283.238957)
12l(-0.5)
13l(-1)
14l(-1.5)
15l(-1.74)
16l(-2)
17l(-3.2345)
18l(-5.283957)
19l(-13.23857)
20l(-100)
21l(-283.238957)
22l(10430710.3325472917)
diff --git a/testsuite/bc_log_results.txt b/testsuite/bc_log_results.txt
new file mode 100644
index 000000000..ce840a0d9
--- /dev/null
+++ b/testsuite/bc_log_results.txt
@@ -0,0 +1,22 @@
1-99999999999999999999.00000000000000000000
2-.69314718055994530941
30
4.40546510810816438197
5.55388511322643765995
6.69314718055994530941
71.17387435650190306676
81.66467524885255369652
92.58313453863349348434
104.60517018598809136803
115.64629091238730017971
12-99999999999999999999.00000000000000000000
13-99999999999999999999.00000000000000000000
14-99999999999999999999.00000000000000000000
15-99999999999999999999.00000000000000000000
16-99999999999999999999.00000000000000000000
17-99999999999999999999.00000000000000000000
18-99999999999999999999.00000000000000000000
19-99999999999999999999.00000000000000000000
20-99999999999999999999.00000000000000000000
21-99999999999999999999.00000000000000000000
2216.16026492940839137014
diff --git a/testsuite/bc_misc.bc b/testsuite/bc_misc.bc
new file mode 100644
index 000000000..571f4a87e
--- /dev/null
+++ b/testsuite/bc_misc.bc
@@ -0,0 +1,13 @@
14.1*1.-13^ - 74 - 1284597623841*1.-13^ - 757
24.1*1.\
3-1\
43^ - 74 - 1284597623841*1.\
5-1\
63^ - 757
7obase = 9
84.1*1.-13^ - 74 - 1284597623841*1.-13^ - 757
94.1*1.\
10-1\
113^ - 74 - 1284597623841*1.\
12-1\
133^ - 757
diff --git a/testsuite/bc_misc1.bc b/testsuite/bc_misc1.bc
new file mode 100644
index 000000000..f666d701a
--- /dev/null
+++ b/testsuite/bc_misc1.bc
@@ -0,0 +1,74 @@
1define x(x) {
2 return(x)
3}
4define y() {
5 return;
6}
7define z() {return}
8scale = 0
9x=2
10x[0]=3
11x
12x[0]
13scale
14ibase
15obase
16x ( 7 )
17x + x( 8 )
18x - x[0]
19321 * x
202 ^ x[0]
21x++
22--x
23x += 9
24x
25length(2381)
26sqrt(9)
27scale(238.1)
28x=2
29x[0]=3
30(x)
31(x[0])
32(scale)
33(ibase)
34(obase)
35(x ( 7 ))
36(x + x( 8 ))
37(x - x[0])
38(321 * x)
39(2 ^ x[0])
40(x++)
41(--x)
42(x += 9)
43(length(2381))
44(sqrt(9))
45(scale(238.1))
46(scale = 0)
47(x = 10)
48(x += 100)
49(x -= 10)
50(x *= 10)
51(x /= 100)
52(x ^= 10)
53(x = sqrt(x))
54(x[1 - 1])
55x[(1 - 1)]
562 + \
573
58++ibase
59--ibase
60++obase
61--obase
62++last
63--last
64last
65last = 100
66last
67. = 150
68.
69++scale
70--scale
71y()
72z()
732 + /*
74*/3
diff --git a/testsuite/bc_misc1_results.txt b/testsuite/bc_misc1_results.txt
new file mode 100644
index 000000000..a9c278069
--- /dev/null
+++ b/testsuite/bc_misc1_results.txt
@@ -0,0 +1,57 @@
12
23
30
410
510
67
710
8-1
9642
108
112
122
1311
144
153
161
172
183
190
2010
2110
227
2310
24-1
25642
268
272
282
2911
304
313
321
330
3410
35110
36100
371000
3810
3910000000000
40100000
413
423
435
4411
4510
4610
4710
4811
4910
5010
51100
52150
531
540
550
560
575
diff --git a/testsuite/bc_misc2.bc b/testsuite/bc_misc2.bc
new file mode 100644
index 000000000..44fc40fa1
--- /dev/null
+++ b/testsuite/bc_misc2.bc
@@ -0,0 +1,44 @@
1define x() {
2"x"
3return ( 1 )
4}
5define y() {
6"y"
7return (2)
8}
9define z() {
10"z"
11return (3)
12}
13
14if ( x() == y() ) {1}
151
16if ( x() <= y() ) {2}
17if ( y() >= x() ) {3}
18if ( x() != y() ) {4}
19if ( x() < y() ) {5}
20if ( y() > x() ) {6}
21
22if ( x() == z() ) {11}
2311
24if ( x() <= z() ) {12}
25if ( z() >= x() ) {13}
26if ( x() != z() ) {14}
27if ( x() < z() ) {15}
28if ( z() > x() ) {16}
29
30x = -10
31while (x <= 0) {
32 x
33 if (x == -5) break;
34 x += 1
35}
36
37define u() {
38 auto a[];
39 return a[0]
40}
41
42u()
43
44if (x == -4) x else x - 4
diff --git a/testsuite/bc_misc2_results.txt b/testsuite/bc_misc2_results.txt
new file mode 100644
index 000000000..022ca8728
--- /dev/null
+++ b/testsuite/bc_misc2_results.txt
@@ -0,0 +1,20 @@
1xy1
2xy2
3yx3
4xy4
5xy5
6yx6
7xz11
8xz12
9zx13
10xz14
11xz15
12zx16
13-10
14-9
15-8
16-7
17-6
18-5
190
20-9
diff --git a/testsuite/bc_misc_results.txt b/testsuite/bc_misc_results.txt
new file mode 100644
index 000000000..e2db76e0e
--- /dev/null
+++ b/testsuite/bc_misc_results.txt
@@ -0,0 +1,4 @@
1-1284597623836.9
2-1284597623836.9
3-4483684050181.80
4-4483684050181.80
diff --git a/testsuite/bc_modulus.bc b/testsuite/bc_modulus.bc
new file mode 100644
index 000000000..e2656a6e9
--- /dev/null
+++ b/testsuite/bc_modulus.bc
@@ -0,0 +1,70 @@
11 % 1
22 % 1
316 % 4
415 % 4
517 % 4
62389473 % 5
739240687239 % 1
8346728934 % 23958
93496723859067234 % 298375462837546928347623059375486
10-1 % 1
11-2 % 1
12-47589634875689345 % 37869235
13-1274852934765 % 2387628935486273546
14-6324758963 % 237854962
151 % -1
162 % -1
172 % -2
182 % -3
1916 % 5
2015 % 5
2114 % 5
2289237423 % -237856923854
23123647238946 % -12467
24-1 % -1
25-2 % -1
26-2 % -2
27-2 % -3
28-13 % -7
29-14 % -7
30-15 % -7
31-12784956 % -32746
32-127849612 % -23712347682193
331 % 0.2395672438567234
34scale = 0
351 % 1
362 % 1
3716 % 4
3815 % 4
3917 % 4
402389473 % 5
4139240687239 % 1
42346728934 % 23958
433496723859067234 % 298375462837546928347623059375486
44-1 % 1
45-2 % 1
46-47589634875689345 % 37869235
47-1274852934765 % 2387628935486273546
48-6324758963 % 237854962
491 % -1
502 % -1
512 % -2
522 % -3
5316 % 5
5415 % 5
5514 % 5
5689237423 % -237856923854
57123647238946 % -12467
58-1 % -1
59-2 % -1
60-2 % -2
61-2 % -3
62-13 % -7
63-14 % -7
64-15 % -7
65-12784956 % -32746
66-127849612 % -23712347682193
67-3191280681 % 641165986
68scale = 0; -899510228 % -2448300078.40314
69scale = 0; -7424863 % -207.2609738667
70scale = 0; 3769798918 % 0.6
diff --git a/testsuite/bc_modulus_results.txt b/testsuite/bc_modulus_results.txt
new file mode 100644
index 000000000..e85145be7
--- /dev/null
+++ b/testsuite/bc_modulus_results.txt
@@ -0,0 +1,69 @@
10
20
30
40
50
60
70
8.00000000000000002026
92747189239559.46904933397471305894
100
110
12-.00000000000011057855
13-.00076922992566770712
14-.00000000000050364144
150
160
170
18.00000000000000000002
190
200
210
22.00000000070585524350
23.00000000000000002898
240
250
260
27-.00000000000000000002
28-.00000000000000000005
290
30-.00000000000000000002
31-.00000000000000011722
32-.00000002640923745817
33.000000000000000000000404744340951948
340
350
360
373
381
393
400
418758
423496723859067234
430
440
45-8236960
46-1274852934765
47-140529951
480
490
500
512
521
530
544
5589237423
566692
570
580
590
60-2
61-6
620
63-1
64-14016
65-127849612
66-626616737
67-899510228.00000
68-153.1331732059
69.4
diff --git a/testsuite/bc_multiply.bc b/testsuite/bc_multiply.bc
new file mode 100644
index 000000000..8d5aa36d5
--- /dev/null
+++ b/testsuite/bc_multiply.bc
@@ -0,0 +1,42 @@
10 * 0
20.000 * 0
31 * 0
40 * 1
50 * 2498752389672835476
6873246913745129084576134 * 0
71 * 472638590273489273456
812374861230476103672835496 * 1
91 * 1
102 * 1
111 * 2
122 * 2
133 * 14
1417 * 8
151892467513846753 * 1872439821374591038746
16328962735862.2973546835638947635 * 1728465791348762356
1738745962374538.387427384672934867234 * 0.1932476528394672837568923754
189878894576289457634856.2738627161689017387608947567654 * 37842939768237596237854203.29874372139852739126739621793162
19-1 * 1
20-1 * 2
2178893457 * -34876238956
22235678324957634 * -0.2349578349672389576
23-12849567821934 * 12738462937681
241274861293467.927843682937462 * -28935678239
252936077239872.12937462836 * -0.012842357682435762
262387692387566.2378569237546 * -272189345628.123875629835876
270.012348629356782835962 * -23487692356
280.4768349567348675934 * -0.23756834576934857638495
290.98748395367485962735486 * -4675839462354867.376834956738456
30-321784627934586 * -235762378596
31-32578623567892356 * -0.32567384579638456
32-35768232346876 * -2348672935602387620.28375682349576237856
33-0.2356728394765234 * -238759624356978
34-0.2345768212346780 * -0.235768124697074385948943532045
35-0.370873860736785306278630 * -7835678398607.7086378076867096270
36-78365713707.7089637863786730 * -738580798679306780
37-73867038956790490258249 * -0.7379862716391723672803679
38-378621971598721837710387 * -98465373878350798.09743896037963078560
3937164201 * 2931559660
40679468076118972457796560530571.46287161642138401685 * 93762.2836
41.000000000000000000000000001 * .0000000000000000000000001
42scale = 0; 237854962 * -26
diff --git a/testsuite/bc_multiply_results.txt b/testsuite/bc_multiply_results.txt
new file mode 100644
index 000000000..1dee19c37
--- /dev/null
+++ b/testsuite/bc_multiply_results.txt
@@ -0,0 +1,43 @@
10
20
30
40
50
60
7472638590273489273456
812374861230476103672835496
91
102
112
124
1342
14136
153543531533584430580556128344529291738
16568600835566479683035874339053.4411638427543228060
177487566285885.8557453089005171423976251098
18373846412427291014394738378015501363938345620046.7869650248829232267\
192297002026819
20-1
21-2
22-2751507058396910892
23-55374468980751.0837656919743223184
24-163683743464924630346895054
25-36888976187143312550878.567134791289418
26-37706154097.69662826215753378160
27-649904428532907022680241.94791869424754101064
28-290040807.350385412976669306472
29-.11328089187650139309272
30-4617316439035114.40320367843985107357898
3175864709277486862054521256
3210610005628108234.92015040406042336
3384007879267445533366251128067927.91168012197674537856
3456269158624557.1027018519702852
35.055305737239900889424090264801
362906048299183.472237078104362540110129
3757879411419313585866282299201.3825582163029400
3854512860676747314187949.9414724679950990587298071
3937281153992026463004361915151761464058058.54968338992209002720
40108949072447731660
4163708478450213482928510139572007971.83536929222529239687
420
43-6184229012
diff --git a/testsuite/bc_numbers1.bc b/testsuite/bc_numbers1.bc
new file mode 100644
index 000000000..fd4e225ee
--- /dev/null
+++ b/testsuite/bc_numbers1.bc
@@ -0,0 +1,23 @@
1ibase=G
2define f() {
3a00=00;a01=01;a02=02;a03=03;a04=04;a05=05;a06=06;a07=07;a08=08;a09=09;a0a=0A;a0b=0B;a0c=0C;a0d=0D;a0e=0E;a0f=0F
4a10=10;a11=11;a12=12;a13=13;a14=14;a15=15;a16=16;a17=17;a18=18;a19=19;a1a=1A;a1b=1B;a1c=1C;a1d=1D;a1e=1E;a1f=1F
5a20=20;a21=21;a22=22;a23=23;a24=24;a25=25;a26=26;a27=27;a28=28;a29=29;a2a=2A;a2b=2B;a2c=2C;a2d=2D;a2e=2E;a2f=2F
6a30=30;a31=31;a32=32;a33=33;a34=34;a35=35;a36=36;a37=37;a38=38;a39=39;a3a=3A;a3b=3B;a3c=3C;a3d=3D;a3e=3E;a3f=3F
7a40=40;a41=41;a42=42;a43=43;a44=44;a45=45;a46=46;a47=47;a48=48;a49=49;a4a=4A;a4b=4B;a4c=4C;a4d=4D;a4e=4E;a4f=4F
8a50=50;a51=51;a52=52;a53=53;a54=54;a55=55;a56=56;a57=57;a58=58;a59=59;a5a=5A;a5b=5B;a5c=5C;a5d=5D;a5e=5E;a5f=5F
9a60=60;a61=61;a62=62;a63=63;a64=64;a65=65;a66=66;a67=67;a68=68;a69=69;a6a=6A;a6b=6B;a6c=6C;a6d=6D;a6e=6E;a6f=6F
10a70=70;a71=71;a72=72;a73=73;a74=74;a75=75;a76=76;a77=77;a78=78;a79=79;a7a=7A;a7b=7B;a7c=7C;a7d=7D;a7e=7E;a7f=7F
11a80=80;a81=81;a82=82;a83=83;a84=84;a85=85;a86=86;a87=87;a88=88;a89=89;a8a=8A;a8b=8B;a8c=8C;a8d=8D;a8e=8E;a8f=8F
12a90=90;a91=91;a92=92;a93=93;a94=94;a95=95;a96=96;a97=97;a98=98;a99=99;a9a=9A;a9b=9B;a9c=9C;a9d=9D;a9e=9E;a9f=9F
13aa0=A0;aa1=A1;aa2=A2;aa3=A3;aa4=A4;aa5=A5;aa6=A6;aa7=A7;aa8=A8;aa9=A9;aaa=AA;aab=AB;aac=AC;aad=AD;aae=AE;aaf=AF
14ab0=B0;ab1=B1;ab2=B2;ab3=B3;ab4=B4;ab5=B5;ab6=B6;ab7=B7;ab8=B8;ab9=B9;aba=BA;abb=BB;abc=BC;abd=BD;abe=BE;abf=BF
15ac0=C0;ac1=C1;ac2=C2;ac3=C3;ac4=C4;ac5=C5;ac6=C6;ac7=C7;ac8=C8;ac9=C9;aca=CA;acb=CB;acc=CC;acd=CD;ace=CE;acf=CF
16ad0=D0;ad1=D1;ad2=D2;ad3=D3;ad4=D4;ad5=D5;ad6=D6;ad7=D7;ad8=D8;ad9=D9;ada=DA;adb=DB;adc=DC;add=DD;ade=DE;adf=DF
17ae0=E0;ae1=E1;ae2=E2;ae3=E3;ae4=E4;ae5=E5;ae6=E6;ae7=E7;ae8=E8;ae9=E9;aea=EA;aeb=EB;aec=EC;aed=ED;aee=EE;aef=EF
18af0=F0;af1=F1;af2=F2;af3=F3;af4=F4;af5=F5;af6=F6;af7=F7;af8=F8;af9=F9;afa=FA;afb=FB;afc=FC;afd=FD;afe=FE;aff=FF
19# this tests "index encoding" in bc.c: are numbers after 0xfc encoded correctly?
20af0;af1;af2;af3;af4;af5;af6;af7;af8;af9;afa;afb;afc;afd;afe;aff
21}
22f()
23halt
diff --git a/testsuite/bc_numbers1_results.txt b/testsuite/bc_numbers1_results.txt
new file mode 100644
index 000000000..e0ace1049
--- /dev/null
+++ b/testsuite/bc_numbers1_results.txt
@@ -0,0 +1,17 @@
1240
2241
3242
4243
5244
6245
7246
8247
9248
10249
11250
12251
13252
14253
15254
16255
170
diff --git a/testsuite/bc_numbers2.bc b/testsuite/bc_numbers2.bc
new file mode 100644
index 000000000..208fe0d4d
--- /dev/null
+++ b/testsuite/bc_numbers2.bc
@@ -0,0 +1,18 @@
1define f() {
2 "ibase:";ibase
3 a=A;a
4 a=F;a
5 a=G;a
6 a=Z;a
7 a=0A;a
8 a=0F;a
9 a=0G;a
10 a=0Z;a
11}
12f()
13ibase=9;f()
14ibase=A;f()
15ibase=F;f()
16ibase=G;f()
17#ibase=Z;f()
18halt
diff --git a/testsuite/bc_numbers2_results.txt b/testsuite/bc_numbers2_results.txt
new file mode 100644
index 000000000..e3400bd92
--- /dev/null
+++ b/testsuite/bc_numbers2_results.txt
@@ -0,0 +1,50 @@
1ibase:10
210
315
416
535
610
715
816
935
100
11ibase:9
1210
1315
1416
1535
1610
1715
1816
1935
200
21ibase:10
2210
2315
2416
2535
2610
2715
2816
2935
300
31ibase:15
3210
3315
3416
3535
3610
3715
3816
3935
400
41ibase:16
4210
4315
4416
4535
4610
4715
4816
4935
500
diff --git a/testsuite/bc_pi.bc b/testsuite/bc_pi.bc
new file mode 100644
index 000000000..b98419f12
--- /dev/null
+++ b/testsuite/bc_pi.bc
@@ -0,0 +1,4 @@
1for (i = 0; i <= 100; ++i) {
2 scale = i
3 4 * a(1)
4}
diff --git a/testsuite/bc_pi_results.txt b/testsuite/bc_pi_results.txt
new file mode 100644
index 000000000..128d6c0ca
--- /dev/null
+++ b/testsuite/bc_pi_results.txt
@@ -0,0 +1,135 @@
10
22.8
33.12
43.140
53.1412
63.14156
73.141592
83.1415924
93.14159264
103.141592652
113.1415926532
123.14159265356
133.141592653588
143.1415926535896
153.14159265358976
163.141592653589792
173.1415926535897932
183.14159265358979320
193.141592653589793236
203.1415926535897932384
213.14159265358979323844
223.141592653589793238460
233.1415926535897932384624
243.14159265358979323846264
253.141592653589793238462640
263.1415926535897932384626432
273.14159265358979323846264336
283.141592653589793238462643380
293.1415926535897932384626433832
303.14159265358979323846264338324
313.141592653589793238462643383276
323.1415926535897932384626433832792
333.14159265358979323846264338327948
343.141592653589793238462643383279500
353.1415926535897932384626433832795028
363.14159265358979323846264338327950288
373.141592653589793238462643383279502884
383.1415926535897932384626433832795028840
393.14159265358979323846264338327950288416
403.141592653589793238462643383279502884196
413.1415926535897932384626433832795028841968
423.14159265358979323846264338327950288419716
433.141592653589793238462643383279502884197168
443.1415926535897932384626433832795028841971692
453.14159265358979323846264338327950288419716936
463.141592653589793238462643383279502884197169396
473.1415926535897932384626433832795028841971693992
483.14159265358979323846264338327950288419716939936
493.141592653589793238462643383279502884197169399372
503.1415926535897932384626433832795028841971693993748
513.14159265358979323846264338327950288419716939937508
523.141592653589793238462643383279502884197169399375104
533.1415926535897932384626433832795028841971693993751056
543.14159265358979323846264338327950288419716939937510580
553.141592653589793238462643383279502884197169399375105820
563.1415926535897932384626433832795028841971693993751058208
573.14159265358979323846264338327950288419716939937510582096
583.141592653589793238462643383279502884197169399375105820972
593.1415926535897932384626433832795028841971693993751058209748
603.14159265358979323846264338327950288419716939937510582097492
613.141592653589793238462643383279502884197169399375105820974944
623.1415926535897932384626433832795028841971693993751058209749444
633.14159265358979323846264338327950288419716939937510582097494456
643.141592653589793238462643383279502884197169399375105820974944592
653.1415926535897932384626433832795028841971693993751058209749445920
663.14159265358979323846264338327950288419716939937510582097494459228
673.141592653589793238462643383279502884197169399375105820974944592304
683.141592653589793238462643383279502884197169399375105820974944592307\
696
703.141592653589793238462643383279502884197169399375105820974944592307\
7180
723.141592653589793238462643383279502884197169399375105820974944592307\
73816
743.141592653589793238462643383279502884197169399375105820974944592307\
758164
763.141592653589793238462643383279502884197169399375105820974944592307\
7781640
783.141592653589793238462643383279502884197169399375105820974944592307\
79816404
803.141592653589793238462643383279502884197169399375105820974944592307\
818164060
823.141592653589793238462643383279502884197169399375105820974944592307\
8381640628
843.141592653589793238462643383279502884197169399375105820974944592307\
85816406284
863.141592653589793238462643383279502884197169399375105820974944592307\
878164062860
883.141592653589793238462643383279502884197169399375105820974944592307\
8981640628620
903.141592653589793238462643383279502884197169399375105820974944592307\
91816406286208
923.141592653589793238462643383279502884197169399375105820974944592307\
938164062862088
943.141592653589793238462643383279502884197169399375105820974944592307\
9581640628620896
963.141592653589793238462643383279502884197169399375105820974944592307\
97816406286208996
983.141592653589793238462643383279502884197169399375105820974944592307\
998164062862089984
1003.141592653589793238462643383279502884197169399375105820974944592307\
10181640628620899860
1023.141592653589793238462643383279502884197169399375105820974944592307\
103816406286208998628
1043.141592653589793238462643383279502884197169399375105820974944592307\
1058164062862089986280
1063.141592653589793238462643383279502884197169399375105820974944592307\
10781640628620899862800
1083.141592653589793238462643383279502884197169399375105820974944592307\
109816406286208998628032
1103.141592653589793238462643383279502884197169399375105820974944592307\
1118164062862089986280348
1123.141592653589793238462643383279502884197169399375105820974944592307\
11381640628620899862803480
1143.141592653589793238462643383279502884197169399375105820974944592307\
115816406286208998628034824
1163.141592653589793238462643383279502884197169399375105820974944592307\
1178164062862089986280348252
1183.141592653589793238462643383279502884197169399375105820974944592307\
11981640628620899862803482532
1203.141592653589793238462643383279502884197169399375105820974944592307\
121816406286208998628034825340
1223.141592653589793238462643383279502884197169399375105820974944592307\
1238164062862089986280348253420
1243.141592653589793238462643383279502884197169399375105820974944592307\
12581640628620899862803482534208
1263.141592653589793238462643383279502884197169399375105820974944592307\
127816406286208998628034825342116
1283.141592653589793238462643383279502884197169399375105820974944592307\
1298164062862089986280348253421168
1303.141592653589793238462643383279502884197169399375105820974944592307\
13181640628620899862803482534211704
1323.141592653589793238462643383279502884197169399375105820974944592307\
133816406286208998628034825342117064
1343.141592653589793238462643383279502884197169399375105820974944592307\
1358164062862089986280348253421170676
diff --git a/testsuite/bc_power.bc b/testsuite/bc_power.bc
new file mode 100644
index 000000000..5657cdd7b
--- /dev/null
+++ b/testsuite/bc_power.bc
@@ -0,0 +1,44 @@
10 ^ 0
20 ^ 1
30 ^ 1894
41 ^ 0
539746823 ^ 0
60.238672983047682 ^ 0
718394762374689237468.97354862973846 ^ 0
81 ^ 1
92 ^ 1
1018927361346 ^ 1
110.23523785962738592635777 ^ 1
12328956734869213746.89782398457234 ^ 1
138937 ^ 98
140.124876812394 ^ 2396
1593762.2836 ^ 13
161 ^ -1
172 ^ -1
1810 ^ -1
19683734768 ^ -1
2038579623756.897937568235 ^ -1
211 ^ -32467
222 ^ -53
2323897 ^ -213
24-1 ^ 1
25-1 ^ 2
26-2 ^ 1
27-2 ^ 2
28-237 ^ 294
29-3746 ^ 28
30-0.3548 ^ 35
31-4267.234 ^ 37
32-326.3246 ^ 78
33-1 ^ -1
34-1 ^ -2
35-2 ^ -1
36-2 ^ -2
37-237 ^ -293
38-784 ^ -23
39-86 ^ -7
40-0.23424398 ^ -781
41-178.234786 ^ -879
42-1274.346 ^ -768
430 ^ -251
44-0.2959371298 ^ 227
diff --git a/testsuite/bc_power_results.txt b/testsuite/bc_power_results.txt
new file mode 100644
index 000000000..997f44f59
--- /dev/null
+++ b/testsuite/bc_power_results.txt
@@ -0,0 +1,73 @@
11
20
30
41
51
61
71
81
92
1018927361346
11.23523785962738592635777
12328956734869213746.89782398457234
1316473742664221279051571200630760751138799221376964991600670000200609\
1408006052596520320731708604393844468006290371918262741885989163144389\
1539367835091560809036359941703341471396407660150658436796925310445979\
1621333166245765946557344383284626113908419359990042883048537750217279\
1717481980123593363177308481941550382845381799410533956718500484099889\
18610805653325917409549921909941664118421333562129
190
2043287877285033571298394739716218787350087163435619825150259705419.98\
21016445740928054425
221.00000000000000000000
23.50000000000000000000
24.10000000000000000000
25.00000000146255543348
26.00000000002592041867
271.00000000000000000000
28.00000000000000011102
290
30-1
311
32-2
334
3414997322375665265051328725757939209353051902095893907150382724666290\
3549749481660976421019742616298227588464420182758442163654172400528243\
3600885441207762486233574213374503090372518590691583139696652847404883\
3708573912261119588874308960204159666762789603037188471170006223907416\
3860492840269152716750700089148882139254399347568222390231015487895905\
3973727080561379177721440905866857248917982113340543176658480139248897\
4054802503253413282808814063861470711399810899724515727713334909764746\
4127910290211411231279325882505708287941671508154740003122373284699097\
4278346501539634198926772266511968381368929692275950529960923432771985\
4312597189390708050983487158873301681237787429436264801751664042999180\
443448659818912436089
4511478830555358864333472551120140548480416206583184496764727387456058\
46792742209537931243951391229607936
47-.00000000000000017759
48-2067373624686414405470850679965010694114490999957199847684803894306\
4956243666149296582304582679590231948238805965642713928910384741502707\
50.23224479257866798694
5111606078892843496082360561256965139908586179418605021706789617179085\
5285768049299693425729565480314913006780973928345684673490252494674985\
530186164225375953066263609289359900615361965737717208159874390.293769\
5470206344604971
55-1.00000000000000000000
561.00000000000000000000
57-.50000000000000000000
58.25000000000000000000
590
600
61-.00000000000002874159
62-1945134149489344891879057554905782841936258356736314337975569799825\
6394091939572752348215929683891336730843553721422164737465108229034947\
6487333189564755763444242676978610321731298729194092653999616928308494\
6526419468484566422775668903315088810746121307679948574976162519479931\
6618935243698160094347216562490000767121041786977792546155155934655909\
6714123833869470494708767968978717730012864171105540029928688274136791\
6898175053824022144065005509214813689232148489884560100200475909009813\
69340098100705258138.98542904577525702068
700
710
720
730
diff --git a/testsuite/bc_sine.bc b/testsuite/bc_sine.bc
new file mode 100644
index 000000000..d3a547bcd
--- /dev/null
+++ b/testsuite/bc_sine.bc
@@ -0,0 +1,207 @@
1scale = 25
2p = 4 * a(1)
3scale = 20
4s(0)
5s(0.5)
6s(1)
7s(2)
8s(3)
9s(-0.5)
10s(-1)
11s(-2)
12s(-3)
13s(p / 7)
14s(-p / 7)
15s(p / 4)
16s(-p / 4)
17s(p / 3)
18s(-p / 3)
19s(p / 2)
20s(-p / 2)
21s(3 * p / 4)
22s(3 * -p / 4)
23s(p)
24s(-p)
25s(3 * p / 2)
26s(3 * -p / 2)
27s(7 * p / 4)
28s(7 * -p / 4)
29s(13 * p / 4)
30s(13 * -p / 4)
31s(2 * p)
32s(2 * -p)
33s(131231)
34s(-131231)
35s(69.1967507777)
36s(10828)
37s(-16248506.847013148)
38s(2050281000)
39s(8224939)
40s(11334231.1154662464)
41s(-4109411249.2986954846)
42s(-2395915402.13984)
43s(-2795874313)
44s(-2262647256)
45s(3323158182.1239222084)
46s(99901384)
47s(-4202726050.2780080957)
48s(2870000621.3228830588)
49s(-4230239450.981045150)
50s(-1517506941.2678857223)
51s(4004582176)
52s(-4193724543.1108508063)
53s(-3432511261)
54s(1804484812)
55s(3229084127)
56s(-3565317246.583937244)
57s(3503281621)
58s(-3469146313.1766891244)
59s(-2257308049.307721068)
60s(-3978441809)
61s(3431564304.3752537)
62s(1249644440.2464914559)
63s(2395558891.1188487974)
64s(-2607820706.4079280116)
65s(1208310007)
66s(-3758597557.863203175)
67s(1186920672)
68s(-3988103872)
69s(-4280635328.4194857577)
70s(1051748072)
71s(-1884006279)
72s(-1046568719.2698663389)
73s(2482991410)
74s(-2106101268.1154045959)
75s(3530359346.77217900)
76s(-3373362543)
77s(2601598062)
78s(2987020862)
79s(-12033356.2057140648)
80s(-3721760707)
81s(2842387705.4145759704)
82s(3515832681.1808393297)
83s(-3658522034.16149)
84s(3963658030.2860423992)
85s(2977802215.597946655)
86s(-4271392570.4091498761)
87s(2378692585)
88s(-3545193743.629374782)
89s(-1762458738)
90s(-1174277828.4264040126)
91s(-1724994857)
92s(2802750230.1783499408)
93s(-3068133550)
94s(3324811474.621822235)
95s(2873024984)
96s(-3509056632.3888206298)
97s(1772903162.647192879)
98s(2836543102)
99s(4117858580.186)
100s(2988632386.4063754522)
101s(-4256784971.1770067447)
102s(2280820447)
103s(-2865200306)
104s(-3329592486)
105s(519126268)
106s(-2452430452)
107s(-2693220186.62104082)
108s(-3796811992.14485798)
109s(3619792326)
110s(2697791049.3038381550)
111s(3751267834.2808166557)
112s(-3761719074)
113s(-3824087631)
114s(2119301150)
115s(1398148974)
116s(-3386564819.1351816969)
117s(-3171483098)
118s(3688944941.3273318162)
119s(3060521119)
120s(-3527110404)
121s(3699631193)
122s(3872838898)
123s(3880350192)
124s(-4109411249.2986954846)
125s(-2395915402.13984)
126s(-2795874313)
127s(-2262647256)
128s(3323158182.1239222084)
129s(99901384)
130s(-4202726050.2780080957)
131s(2870000621.3228830588)
132s(-4230239450.981045150)
133s(-1517506941.2678857223)
134s(4004582176)
135s(-4193724543.1108508063)
136s(-3432511261)
137s(1804484812)
138s(3229084127)
139s(-3565317246.583937244)
140s(3503281621)
141s(-3469146313.1766891244)
142s(-2257308049.307721068)
143s(-3978441809)
144s(3431564304.3752537)
145s(1249644440.2464914559)
146s(2395558891.1188487974)
147s(-2607820706.4079280116)
148s(1208310007)
149s(-3758597557.863203175)
150s(1186920672)
151s(-3988103872)
152s(-4280635328.4194857577)
153s(1051748072)
154s(-1884006279)
155s(-1046568719.2698663389)
156s(2482991410)
157s(-2106101268.1154045959)
158s(3530359346.77217900)
159s(-3373362543)
160s(2601598062)
161s(2576349783.2446436039)
162s(2987020862)
163s(-12033356.2057140648)
164s(-3721760707)
165s(2842387705.4145759704)
166s(3515832681.1808393297)
167s(-3658522034.16149)
168s(3963658030.2860423992)
169s(2977802215.597946655)
170s(-4271392570.4091498761)
171s(2378692585)
172s(-3545193743.629374782)
173s(-1762458738)
174s(-1174277828.4264040126)
175s(-1724994857)
176s(2802750230.1783499408)
177s(-3068133550)
178s(3324811474.621822235)
179s(2873024984)
180s(-3509056632.3888206298)
181s(1772903162.647192879)
182s(2836543102)
183s(4117858580.186)
184s(2988632386.4063754522)
185s(-4256784971.1770067447)
186s(2280820447)
187s(-2865200306)
188s(-3329592486)
189s(519126268)
190s(-2452430452)
191s(-2693220186.62104082)
192s(-3796811992.14485798)
193s(3619792326)
194s(2697791049.3038381550)
195s(3751267834.2808166557)
196s(-3761719074)
197s(-3824087631)
198s(2119301150)
199s(1398148974)
200s(-3386564819.1351816969)
201s(-3171483098)
202s(3688944941.3273318162)
203s(3060521119)
204s(-3527110404)
205s(3699631193)
206s(3872838898)
207s(3880350192)
diff --git a/testsuite/bc_sine_results.txt b/testsuite/bc_sine_results.txt
new file mode 100644
index 000000000..7a4a1ab0c
--- /dev/null
+++ b/testsuite/bc_sine_results.txt
@@ -0,0 +1,204 @@
10
2.47942553860420300027
3.84147098480789650665
4.90929742682568169539
5.14112000805986722210
6-.47942553860420300027
7-.84147098480789650665
8-.90929742682568169539
9-.14112000805986722210
10.43388373911755812047
11-.43388373911755812047
12.70710678118654752439
13-.70710678118654752439
14.86602540378443864676
15-.86602540378443864676
161.00000000000000000000
17-1.00000000000000000000
18.70710678118654752440
19-.70710678118654752440
200
210
22-1.00000000000000000000
231.00000000000000000000
24-.70710678118654752440
25.70710678118654752440
26-.70710678118654752439
27.70710678118654752439
280
290
30.38173640790989719211
31-.38173640790989719211
32.08162149793819434415
33.87714140586973771462
34-.91157035998052051623
35-.69638975047120679880
36-.94806056135672896231
37-.54548669379730874215
38.14605234154783145589
39-.12183062787430962391
40-.89832305526331682409
41-.99513029384033555290
42.76528428398894958149
43.51077956237618482050
44-.75908868040685122962
45-.37015497140201575652
46-.51432535569032144654
47.68890201397514289831
48.88200006249578882510
49-.01188893762444044480
50-.55298206739629427055
51-.39165958853437135625
52.17732674488831117445
53-.09648816960119759281
54.15728984163381104344
55-.31554983227150461370
56-.72225704678824601977
57.96170480789326775287
58-.47636475887571231114
59-.98999375714278585763
60-.06715264746977580303
61-.69464867397161089634
62.58037673122614640119
63-.44244898040675115062
64.04242496278231069061
65.96417934585711006987
66-.54513053517818430563
67-.28604677908958958915
68-.68003854521180919710
69.26597321569379963920
70-.34591048991595943570
71-.17084074152217894535
72-.42880744669595980174
73.36518031021580667844
74-.03514839609475800827
75.93891962312087620513
76-.69421849362562852947
77.15169857474887222961
78-.00226070393499995347
79.96209233301706432156
80-.79937182245558378826
81.99966966326862290520
82.85234799672007656117
83-.20824280061137520443
84-.00761257856348159450
85.10708922858398661064
86-.80233147080821341443
87.26521358383069223461
88-.95173930946495828679
89.66210405748455769256
90.30054820568403786217
91.21640593048970779808
92-.87596287572245980692
93.74627849623707962934
94-.25747200288605259984
95-.14700538617135227740
96-.06294254604551440990
97.67948313824962059899
98.83714389089726798409
99.33805040346429707760
100.80273418514828673749
101.72262501870089953244
102-.77469383027517310713
103-.15575896025754423345
104.22191568853026376075
105.25137052589938954082
106-.80534308288073574163
107-.44963537508211028805
108-.92368907556208259630
109-.80963411623457804531
110-.96822928101198069490
111-.46604999828123759716
112.63275578793565409192
113-.40563425346575205109
114.13095444406203282638
115.96217617474547242151
116-.16256793375739137005
117.71791623784197898982
118-.10713685791219679248
119.50758780541979250307
120-.09795373670371402656
121.14605234154783145589
122-.12183062787430962391
123-.89832305526331682409
124-.99513029384033555290
125.76528428398894958149
126.51077956237618482050
127-.75908868040685122962
128-.37015497140201575652
129-.51432535569032144654
130.68890201397514289831
131.88200006249578882510
132-.01188893762444044480
133-.55298206739629427055
134-.39165958853437135625
135.17732674488831117445
136-.09648816960119759281
137.15728984163381104344
138-.31554983227150461370
139-.72225704678824601977
140.96170480789326775287
141-.47636475887571231114
142-.98999375714278585763
143-.06715264746977580303
144-.69464867397161089634
145.58037673122614640119
146-.44244898040675115062
147.04242496278231069061
148.96417934585711006987
149-.54513053517818430563
150-.28604677908958958915
151-.68003854521180919710
152.26597321569379963920
153-.34591048991595943570
154-.17084074152217894535
155-.42880744669595980174
156.36518031021580667844
157-.03514839609475800827
158.75884554410943292265
159.93891962312087620513
160-.69421849362562852947
161.15169857474887222961
162-.00226070393499995347
163.96209233301706432156
164-.79937182245558378826
165.99966966326862290520
166.85234799672007656117
167-.20824280061137520443
168-.00761257856348159450
169.10708922858398661064
170-.80233147080821341443
171.26521358383069223461
172-.95173930946495828679
173.66210405748455769256
174.30054820568403786217
175.21640593048970779808
176-.87596287572245980692
177.74627849623707962934
178-.25747200288605259984
179-.14700538617135227740
180-.06294254604551440990
181.67948313824962059899
182.83714389089726798409
183.33805040346429707760
184.80273418514828673749
185.72262501870089953244
186-.77469383027517310713
187-.15575896025754423345
188.22191568853026376075
189.25137052589938954082
190-.80534308288073574163
191-.44963537508211028805
192-.92368907556208259630
193-.80963411623457804531
194-.96822928101198069490
195-.46604999828123759716
196.63275578793565409192
197-.40563425346575205109
198.13095444406203282638
199.96217617474547242151
200-.16256793375739137005
201.71791623784197898982
202-.10713685791219679248
203.50758780541979250307
204-.09795373670371402656
diff --git a/testsuite/bc_sqrt.bc b/testsuite/bc_sqrt.bc
new file mode 100644
index 000000000..afd87ff0f
--- /dev/null
+++ b/testsuite/bc_sqrt.bc
@@ -0,0 +1,18 @@
1scale = 20
2sqrt(0)
3sqrt(2)
4sqrt(4)
5sqrt(9)
6sqrt(16)
7sqrt(25)
8sqrt(121)
9sqrt(48765)
10sqrt(9287356207356)
11sqrt(0.189274385967238956872354)
12sqrt(12389467137496823.134567829387456283946)
13sqrt(.0000000000000000000000000000123)
14sqrt(1)
15scale = 0;
16sqrt(1407)
17sqrt(79101)
18scale = 6; sqrt(88.1247699921300025847737099094480986051698668662822009535526240)
diff --git a/testsuite/bc_sqrt_results.txt b/testsuite/bc_sqrt_results.txt
new file mode 100644
index 000000000..10a4fa95d
--- /dev/null
+++ b/testsuite/bc_sqrt_results.txt
@@ -0,0 +1,16 @@
10
21.41421356237309504880
32.00000000000000000000
43.00000000000000000000
54.00000000000000000000
65.00000000000000000000
711.00000000000000000000
8220.82798735667542192643
93047516.39985021245496456781
10.435056761776252544285578
11111307983.260397019622398608908
12.0000000000000035071355833500363
131.00000000000000000000
1437
15281
169.3874794269883757005315658512340070115147163425837869223395574
diff --git a/testsuite/bc_strings.bc b/testsuite/bc_strings.bc
new file mode 100644
index 000000000..1cb7d6a61
--- /dev/null
+++ b/testsuite/bc_strings.bc
@@ -0,0 +1,12 @@
1"string"
2"another string"
3"yet
4another
5string"
6"noescapes\n"
7"newline
8"
9print "string"
10print "newline\n"
11
12print "\\\e\n"
diff --git a/testsuite/bc_strings_results.txt b/testsuite/bc_strings_results.txt
new file mode 100644
index 000000000..89b01ac49
--- /dev/null
+++ b/testsuite/bc_strings_results.txt
@@ -0,0 +1,5 @@
1stringanother stringyet
2another
3stringnoescapes\nnewline
4stringnewline
5\\
diff --git a/testsuite/bc_subtract.bc b/testsuite/bc_subtract.bc
new file mode 100644
index 000000000..61ea953ea
--- /dev/null
+++ b/testsuite/bc_subtract.bc
@@ -0,0 +1,32 @@
10 - 0
20 - 1
31 - 0
41 - 1
55 - 2
62 - 9
7321974 - 12845976238457
82874519803456710938465 - 384723854
910000000000000000000000000000000000000000 - 999999999999999999999999999999999999999
1010000000000000000000000000000000000000000 - 9999999999999999999999999999999999999999
1110000000000000000000000000000000000000000 - 999999999999999999999999999999999999999.99999999999999999999999999999999999
1210000000000000000000000000000000000000000 - 9999999999999999999999999999999999999999.9999999999999999999999999999999999
1310000000000000000000000000000000000000000 - 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1410000000000000000000000000000000000000001 - 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1510000000000000000000000000000000000000000.0000000001 - 0.0000000000000000000000000000000000000000000000000000000000000000000000000001
16-2 - 6
17-23784692345 - 182934721309467230894628735496027345
18-224352354962873059862 - -1245723576829456278354960278345
19-3468273598 - -12354243
20-0.92345768293 - -2354768923
21-712384634.123476823 - -24768293376
22-1879234638 - -0.917234869234
23-0.9172438692134 - -0.971284967124
24-0.1283475123465 - -0.937462346
25-124765829346.2837468293562 - -0.923467829346
26-12476829385769 - -1928476259034.8378629356
27-0.38476284395876345 - -94875394587623.2357869324857
28-4674596708467.34754789403674343567 - -48672394852354698.237548629345
29979519669 - 3018100865
30929002449 - 3280677283
310 - -525898
323- - -3
diff --git a/testsuite/bc_subtract_results.txt b/testsuite/bc_subtract_results.txt
new file mode 100644
index 000000000..6850b5bc1
--- /dev/null
+++ b/testsuite/bc_subtract_results.txt
@@ -0,0 +1,36 @@
10
2-1
31
40
53
6-7
7-12845975916483
82874519803456326214611
99000000000000000000000000000000000000001
101
119000000000000000000000000000000000000000.000000000000000000000000000\
1200000001
13.0000000000000000000000000000000001
149999999999999999999999999999999999999999.999999999999999999999999999\
1599999999999999999999999999999999999999999999999999999999999
1610000000000000000000000000000000000000000.99999999999999999999999999\
17999999999999999999999999999999999999999999999999999999999999
1810000000000000000000000000000000000000000.00000000009999999999999999\
1999999999999999999999999999999999999999999999999999
20-8
21-182934721309467230894628759280719690
221245723576605103923392087218483
23-3455919355
242354768922.07654231707
2524055908741.876523177
26-1879234637.082765130766
27.0540410979106
28.8091148336535
29-124765829345.3602790000102
30-10548353126734.1621370644
3194875394587622.85102408852693655
3248667720255646230.89000073530825656433
33-2038581196
34-2351674834
35525898
360
diff --git a/testsuite/bc_vars.bc b/testsuite/bc_vars.bc
new file mode 100644
index 000000000..91e3572c2
--- /dev/null
+++ b/testsuite/bc_vars.bc
@@ -0,0 +1,7 @@
1scale=10;123981239.981273987 * 12983791827398.29836472638
2scale=100;759634576394.3946587934658364895 / 9834759834895386.36459364958346
334895734986539489834759837489573498573.398475984759837485734987598345 + 9823749832749872384234872934.28347982374987239847982374
4a=123123123.987239874; b=123123123.239479823748; a+b
520347023.23498723984 - 28934723874.234720384
6scale=100;a=739534985.895347284957;b=238746782364.2374623784; c = a / b; c
7s7298367203972395108367910823465293084561329084561390845613409516734503870691837451 + 785621394067928346918023476190834672198467134908618723249671349062187346898241093486139046139084613490817356023871869102746182749061872609129847
diff --git a/testsuite/bc_vars_results.txt b/testsuite/bc_vars_results.txt
new file mode 100644
index 000000000..6597d8439
--- /dev/null
+++ b/testsuite/bc_vars_results.txt
@@ -0,0 +1,12 @@
11609746610419572350599.59456175545
2.0000772397688552681359718594121969204138521230712049526233926741658\
3845368495051158801794834809672994
434895734996363239667509709873808371507.68195580850970988421481133834\
55
6246246247.226719697748
7-28914376850.99973314416
8.0030975704827179453786044330548590249517387192084765414205077089498\
9482709063381782183114683451531598
1078562139406792834691802347619083467219846713490861872324967134906218\
1173468982410934861390461390846134908173560238718691027461827490618726\
1209129847
diff --git a/testsuite/dc.tests b/testsuite/dc.tests
index a5da5372d..1708a4835 100755
--- a/testsuite/dc.tests
+++ b/testsuite/dc.tests
@@ -12,45 +12,91 @@ testing "dc basic syntax (stdin, multiple args)" \
12 "" "10 20+p" 12 "" "10 20+p"
13 13
14testing "dc basic syntax (argv, single arg)" \ 14testing "dc basic syntax (argv, single arg)" \
15 "dc '10 20+p'" \ 15 "dc -e'10 20+p'" \
16 "30\n" \ 16 "30\n" \
17 "" "" 17 "" ""
18 18
19testing "dc basic syntax (argv, multiple args)" \ 19testing "dc basic syntax (argv, multiple args)" \
20 "dc 10 20+p" \ 20 "dc -e10 -e20+p" \
21 "30\n" \ 21 "30\n" \
22 "" "" 22 "" ""
23 23
24testing "dc complex with spaces (single arg)" \ 24testing "dc complex with spaces (single arg)" \
25 "dc '8 8 * 2 2 + / p'" \ 25 "dc -e'8 8 * 2 2 + / p'" \
26 "16\n" \ 26 "16\n" \
27 "" "" 27 "" ""
28 28
29testing "dc complex without spaces (single arg)" \ 29testing "dc complex without spaces (single arg)" \
30 "dc '8 8*2 2+/p'" \ 30 "dc -e'8 8*2 2+/p'" \
31 "16\n" \ 31 "16\n" \
32 "" "" 32 "" ""
33 33
34testing "dc complex with spaces (multiple args)" \ 34testing "dc complex with spaces (multiple args)" \
35 "dc 8 8 \* 2 2 + / p" \ 35 "dc -e8 -e8 -e\* -e2 -e2 -e+ -e/ -ep" \
36 "16\n" \ 36 "16\n" \
37 "" "" 37 "" ""
38 38
39testing "dc complex without spaces (multiple args)" \ 39testing "dc complex without spaces (multiple args)" \
40 "dc 8 8\*2 2+/p" \ 40 "dc -e8 -e8\*2 -e2+/p" \
41 "16\n" \ 41 "16\n" \
42 "" "" 42 "" ""
43 43
44exit $FAILCOUNT 44testing "dc read" \
45 "dc -finput" \
46 "2\n9\n1\n" \
47 "1?2\nf" "9\n"
45 48
46# we do not support arguments 49testing "dc read string" \
47testing "dc -e <exprs>" \ 50 "dc -finput" \
48 "dc -e '10 2+f'" \ 51 "2\nstr\n1\n" \
49 "12\n" \ 52 "1?2\nf" "[str]\n"
50 "" "" 53
54optional FEATURE_DC_BIG
55# All tests below depend on FEATURE_DC_BIG
56
57testing "dc '>a' (conditional execute string) 1" \
58 "dc" \
59 "1\n9\n" \
60 "" "[1p]sa [2p]sb 1 2>a\n9p"
61
62testing "dc '>a' (conditional execute string) 2" \
63 "dc" \
64 "9\n" \
65 "" "[1p]sa [2p]sb 2 1>a\n9p"
51 66
52testing "dc -f <exprs-from-given-file>" \ 67testing "dc '>aeb' (conditional execute string with else)" \
53 "dc -f input" \ 68 "dc" \
54 "12\n" \ 69 "2\n9\n" \
55 "10 2+f" "" 70 "" "[1p]sa [2p]sb 2 1>aeb\n9p"
56 71
72testing "dc space can be a register" \
73 "dc" \
74 "2\n9\n" \
75 "" "[2p]s \n[3p]\nl x\n9p"
76
77testing "dc newline can be a register" \
78 "dc" \
79 "2\n9\n" \
80 "" "[2p]s\n[3p]l\nx\n9p"
81
82for f in dc_*.dc; do
83 r="`basename "$f" .dc`_results.txt"
84 test -f "$r" || continue
85 # testing "test name" "command" "expected result" "file input" "stdin"
86 testing "dc $f" \
87 "{ { dc $f 2>&1; echo E:\$? >&2; } | diff -u - $r; echo E:\$?; } 2>&1" \
88 "E:0\nE:0\n" \
89 "" ""
90done
91
92for f in dcx_*.dc; do
93 r="`basename "$f" .dc`_results.txt"
94 test -f "$r" || continue
95 # testing "test name" "command" "expected result" "file input" "stdin"
96 testing "dc -x $f" \
97 "{ { dc -x $f 2>&1; echo E:\$? >&2; } | diff -u - $r; echo E:\$?; } 2>&1" \
98 "E:0\nE:0\n" \
99 "" ""
100done
101
102exit $FAILCOUNT
diff --git a/testsuite/dc_add.dc b/testsuite/dc_add.dc
new file mode 100644
index 000000000..42da2f1f3
--- /dev/null
+++ b/testsuite/dc_add.dc
@@ -0,0 +1,33 @@
10 0+pR
20 0 0++pR
30 1+pR
40 1 1++pR
51 1+pR
61 0+pR
72 5+pR
8237 483+pR
9999 999+pR
102374623 324869356734856+pR
112378639084586723980562 23468729367839+pR
1237298367203972395108367910823465293084561329084561390845613409516734503870691837451 785621394067928346918023476190834672198467134908618723249671349062187346898241093486139046139084613490817356023871869102746182749061872609129847+pR
131.1 0+pR
140 1.1+pR
15457283.731284923576 37842934672834.3874629385672354+pR
161.0 0.1+pR
173746289134067138046 0.138375863945672398456712389456273486293+pR
18_1 _1+pR
19_4 _15+pR
20_1346782 _1287904651762468913476+pR
2199999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR
2299999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999995 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005+pR
2399999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR
2499999999999999999999999999999999999999999999999999999999999.999999999999999999999999999999999999999999999999999999999899999999999999999999999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR
2599999999999999999999999999999999999989999999999999999999999.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+pR
26_1889985797 2012747315+pR
270 _14338.391079082+pR
28_2422297 1.3134942556+pR
29_1289374 1289374.2893417 0.238971 28937.28971+++pR
301289374 1289374.2893417 _0.238971 28937.28971+++pR
311289374 1289374.2893417 0.238971 _28937.28971+++pR
321289374 1289374.2893417 _0.238971 _28937.28971+++pR
331289374 _1289374.2893417 _0.238971 _28937.28971+++pR
diff --git a/testsuite/dc_add_results.txt b/testsuite/dc_add_results.txt
new file mode 100644
index 000000000..542a62ea3
--- /dev/null
+++ b/testsuite/dc_add_results.txt
@@ -0,0 +1,45 @@
10
20
31
42
52
61
77
8720
91998
10324869359109479
112378639108055453348401
1278562139406792834691802347619083467219846713490861872324967138636055\
1345508706362018540498696043776980521464405852627147161556994835657433\
1400967298
151.1
161.1
1737842935130118.1187478621432354
181.1
193746289134067138046.138375863945672398456712389456273486293
20-2
21-19
22-1287904651762470260258
23100000000000000000000000000000000000000000000000000000000000.0000000\
2400000000000000000000000000000000000000000000000000000000000000000000\
25000000000000000000000000000000000000000000000
26100000000000000000000000000000000000000000000000000000000000.0000000\
2700000000000000000000000000000000000000000000000000000000000000000000\
28000000000000000000000000000000000000000000000
29100000000000000000000000000000000000000000000000000000000000.0000000\
3000000000000000000000000000000000000000000000000000000000000000000000\
31000000000000000000000000000000000000000009999
3299999999999999999999999999999999999999999999999999999999999.99999999\
3399999999999999999999999999999999999999999999999999000000000000000000\
3400000000000000000000000000000000000000009999
3599999999999999999999999999999999999990000000000000000000000.00000000\
3600000000000000000000000000000000000000000000000000000000000000000000\
3700000000000000000000000000000000000000009999
38122761518
39-14338.391079082
40-2422295.6865057444
4128937.8180227
422607685.3400807
432549811.2386027
442549810.7606607
45-28937.8180227
diff --git a/testsuite/dc_boolean.dc b/testsuite/dc_boolean.dc
new file mode 100644
index 000000000..ea72623b8
--- /dev/null
+++ b/testsuite/dc_boolean.dc
@@ -0,0 +1,27 @@
10 1(pR
21 1(pR
32 1(pR
4_1 1(pR
5_1 0(pR
6_1 _1(pR
7_1 _2(pR
80 1{pR
91 1{pR
102 1{pR
11_1 1{pR
12_1 0{pR
13_1 _1{pR
14_1 _2{pR
150 0GpR
160 1GpR
171 0GpR
18_1 _1GpR
190 _1GpR
20_1 0GpR
211 1GpR
22238 2GpR
230NpR
241NpR
25_1NpR
262398NpR
27_2983.2389NpR
diff --git a/testsuite/dc_boolean_results.txt b/testsuite/dc_boolean_results.txt
new file mode 100644
index 000000000..6d29c5b60
--- /dev/null
+++ b/testsuite/dc_boolean_results.txt
@@ -0,0 +1,27 @@
10
20
31
40
50
60
71
80
91
101
110
120
131
141
151
160
170
181
190
200
211
220
231
240
250
260
270
diff --git a/testsuite/dc_decimal.dc b/testsuite/dc_decimal.dc
new file mode 100644
index 000000000..ebbb2dc91
--- /dev/null
+++ b/testsuite/dc_decimal.dc
@@ -0,0 +1,36 @@
10pR
20.0pR
3.0000pR
4000000000000000000000000.00000000000000000000000pR
5000000000000000000000000000135482346782356pR
6000000000000000000000000002pR
71pR
811pR
9123pR
107505pR
111023468723275435238491972521917846pR
124343472432431705867392073517038270398027352709027389273920739037937960379637893607893607893670530278200795207952702873892786172916728961783907893607418973587857386079679267926737520730925372983782793652793pR
13_1pR
14_203pR
15_57pR
16_18586pR
17_31378682943772818461924738352952347258pR
18_823945628745673589495067238723986520375698237620834674509627345273096287563846592384526349872634895763257893467523987578690283762897568459072348758071071087813501875908127359018715023841710239872301387278pR
19.123521346523546pR
200.1245923756273856pR
21_.1024678456387pR
22_0.8735863475634587pR
234.0pR
24_6.0pR
25234237468293576.000000000000000000000000000000pR
2623987623568943567.00000000000000000005677834650000000000000pR
2723856934568940675.000000000000000435676782300000000000000456784pR
2877567648698496.000000000000000000587674750000000000458563800000000000000pR
292348672354968723.2374823546000000000003256987394502346892435623870000000034578pR
30_2354768.000000000000000000000000000000000000pR
31_96739874567.000000000347683456pR
32_3764568345.000000000004573845000000347683460pR
33_356784356.934568495770004586495678300000000pR
3474325437345273852773827101738273127312738521733017537073520735207307570358738257390761276072160719802671980267018728630178.7082681027680521760217867841276127681270867827821768173178207830710978017738178678012767377058785378278207385237085237803278203782037237582795870pR
35_756752732785273851273728537852738257837283678965738527385272983678372867327835672967385278372637862738627836279863782673862783670.71738178361738718367186378610738617836781603760178367018603760178107735278372832783728367826738627836278378260736270367362073867097307925pR
369812734012837410982345719208345712908357412903587192048571920458712.23957182459817249058172945781pR
diff --git a/testsuite/dc_decimal_results.txt b/testsuite/dc_decimal_results.txt
new file mode 100644
index 000000000..275d431c6
--- /dev/null
+++ b/testsuite/dc_decimal_results.txt
@@ -0,0 +1,51 @@
10
20
30
40
5135482346782356
62
71
811
9123
107505
111023468723275435238491972521917846
1243434724324317058673920735170382703980273527090273892739207390379379\
1360379637893607893607893670530278200795207952702873892786172916728961\
1478390789360741897358785738607967926792673752073092537298378279365279\
153
16-1
17-203
18-57
19-18586
20-31378682943772818461924738352952347258
21-8239456287456735894950672387239865203756982376208346745096273452730\
2296287563846592384526349872634895763257893467523987578690283762897568\
2345907234875807107108781350187590812735901871502384171023987230138727\
248
25.123521346523546
26.1245923756273856
27-.1024678456387
28-.8735863475634587
294.0
30-6.0
31234237468293576.000000000000000000000000000000
3223987623568943567.00000000000000000005677834650000000000000
3323856934568940675.000000000000000435676782300000000000000456784
3477567648698496.00000000000000000058767475000000000045856380000000000\
350000
362348672354968723.237482354600000000000325698739450234689243562387000\
370000034578
38-2354768.000000000000000000000000000000000000
39-96739874567.000000000347683456
40-3764568345.000000000004573845000000347683460
41-356784356.934568495770004586495678300000000
4274325437345273852773827101738273127312738521733017537073520735207307\
43570358738257390761276072160719802671980267018728630178.7082681027680\
4452176021786784127612768127086782782176817317820783071097801773817867\
458012767377058785378278207385237085237803278203782037237582795870
46-7567527327852738512737285378527382578372836789657385273852729836783\
4772867327835672967385278372637862738627836279863782673862783670.71738\
4817836173871836718637861073861783678160376017836701860376017810773527\
498372832783728367826738627836278378260736270367362073867097307925
509812734012837410982345719208345712908357412903587192048571920458712.\
5123957182459817249058172945781
diff --git a/testsuite/dc_divide.dc b/testsuite/dc_divide.dc
new file mode 100644
index 000000000..38b874e9f
--- /dev/null
+++ b/testsuite/dc_divide.dc
@@ -0,0 +1,33 @@
120k
20 1/pR
30 321566/pR
40 0.3984567238456/pR
51 1/pR
61 1287469297356/pR
71 0.2395672438567234/pR
81 237586239856.0293596728392360/pR
91249687284356 3027949207835207/pR
10378617298617396719 35748521/pR
119348576237845624358 0.9857829375461/pR
1235768293846193284 2374568947.045762839567823/pR
13_78987234567812345 876542837618936/pR
14_356789237555535468 0.3375273860984786903/pR
15_5203475364850390 435742903748307.70869378534043296404530458/pR
16_0.37861723347576903 7385770896/pR
17_0.399454682043962 0.34824389304/pR
18_0.6920414523873204 356489645223.76076045304879030/pR
19_35872917389671.7573280963748 73924708/pR
20_78375896314.4836709876983 0.78356798637817/pR
21_2374123896417.143789621437581 347821469423789.1473856783960/pR
22_896729350238549726 _34976289345762/pR
23_2374568293458762348596 _0.8792370647234987679/pR
24_237584692306721845726038 _21783910782374529637.978102738746189024761/pR
25_0.23457980123576298375682 _1375486293874612/pR
26_0.173897061862478951264 _0.8179327486017634987516298745/pR
27_0.9186739823576829347586 _0.235678293458756239846/pR
28_0.9375896183746982374568 _13784962873546.0928729395476283745/pR
29_2930754618923467.12323745862937465 _734869238465/pR
30_23745861923467.874675129834675 _0.23542357869124756/pR
31_3878923750692883.7238596702834756902 _7384192674957215364986723.9738461923487621983/pR
321 0.00000000000000000000000000000000000000000002346728372937352457354204563027/pR
33239854711289345712 2891374 182 .2893 ///pR
diff --git a/testsuite/dc_divide_results.txt b/testsuite/dc_divide_results.txt
new file mode 100644
index 000000000..340ae94c1
--- /dev/null
+++ b/testsuite/dc_divide_results.txt
@@ -0,0 +1,32 @@
10
20
30
41.00000000000000000000
5.00000000000077671755
64.17419336592637110778
7.00000000000420899796
8.00041271738677857404
910591131829.40901859967857131767
109483402361494453751.52388015648196297248
1115063068.13735316451497043884
12-90.11223545260531110575
13-1057067521778623447.45138528213564485251
14-11.94161814246320631346
15-.00000000005126306228
16-1.14705437777218917343
17-.00000000000194126663
18-485262.88923145638029569727
19-100024372711.74763635544535424582
20-.00682569681609989277
2125638.20711150436682153521
222700714504347599627864.24626421085374010264
2310906.42973524078145692731
24.00000000000000017054
25.21260557443109085166
263.89799997647407910677
27.00000000000006801538
283988.13076601933678578945
29100864416620775.31076855630746548983
30.00000000052530099381
3142612515855353136519261264261472677699404182.78776061098893912189
3252187553294928.31582417732156163799
diff --git a/testsuite/dc_divmod.dc b/testsuite/dc_divmod.dc
new file mode 100644
index 000000000..1633203ff
--- /dev/null
+++ b/testsuite/dc_divmod.dc
@@ -0,0 +1,64 @@
120k
20 1~pRpR
30 321566~pRpR
40 0.3984567238456~pRpR
51 1~pRpR
61 1287469297356~pRpR
71 0.2395672438567234~pRpR
81 237586239856.0293596728392360~pRpR
91249687284356 3027949207835207~pRpR
10378617298617396719 35748521~pRpR
119348576237845624358 0.9857829375461~pRpR
1235768293846193284 2374568947.045762839567823~pRpR
13_78987234567812345 876542837618936~pRpR
14_356789237555535468 0.3375273860984786903~pRpR
15_5203475364850390 435742903748307.70869378534043296404530458~pRpR
16_0.37861723347576903 7385770896~pRpR
17_0.399454682043962 0.34824389304~pRpR
18_0.6920414523873204 356489645223.76076045304879030~pRpR
19_35872917389671.7573280963748 73924708~pRpR
20_78375896314.4836709876983 0.78356798637817~pRpR
21_2374123896417.143789621437581 347821469423789.1473856783960~pRpR
22_896729350238549726 _34976289345762~pRpR
23_2374568293458762348596 _0.8792370647234987679~pRpR
24_237584692306721845726038 _21783910782374529637.978102738746189024761~pRpR
25_0.23457980123576298375682 _1375486293874612~pRpR
26_0.173897061862478951264 _0.8179327486017634987516298745~pRpR
27_0.9186739823576829347586 _0.235678293458756239846~pRpR
28_0.9375896183746982374568 _13784962873546.0928729395476283745~pRpR
29_2930754618923467.12323745862937465 _734869238465~pRpR
30_23745861923467.874675129834675 _0.23542357869124756~pRpR
31_3878923750692883.7238596702834756902 _7384192674957215364986723.9738461923487621983~pRpR
321 0.00000000000000000000000000000000000000000002346728372937352457354204563027~pRpR
330k
340 1~pRpR
350 321566~pRpR
360 0.3984567238456~pRpR
371 1~pRpR
381 1287469297356~pRpR
391 0.2395672438567234~pRpR
401 237586239856.0293596728392360~pRpR
411249687284356 3027949207835207~pRpR
42378617298617396719 35748521~pRpR
439348576237845624358 0.9857829375461~pRpR
4435768293846193284 2374568947.045762839567823~pRpR
45_78987234567812345 876542837618936~pRpR
46_356789237555535468 0.3375273860984786903~pRpR
47_5203475364850390 435742903748307.70869378534043296404530458~pRpR
48_0.37861723347576903 7385770896~pRpR
49_0.399454682043962 0.34824389304~pRpR
50_0.6920414523873204 356489645223.76076045304879030~pRpR
51_35872917389671.7573280963748 73924708~pRpR
52_78375896314.4836709876983 0.78356798637817~pRpR
53_2374123896417.143789621437581 347821469423789.1473856783960~pRpR
54_896729350238549726 _34976289345762~pRpR
55_2374568293458762348596 _0.8792370647234987679~pRpR
56_237584692306721845726038 _21783910782374529637.978102738746189024761~pRpR
57_0.23457980123576298375682 _1375486293874612~pRpR
58_0.173897061862478951264 _0.8179327486017634987516298745~pRpR
59_0.9186739823576829347586 _0.235678293458756239846~pRpR
60_0.9375896183746982374568 _13784962873546.0928729395476283745~pRpR
61_2930754618923467.12323745862937465 _734869238465~pRpR
62_23745861923467.874675129834675 _0.23542357869124756~pRpR
63_3878923750692883.7238596702834756902 _7384192674957215364986723.9738461923487621983~pRpR
641 0.00000000000000000000000000000000000000000002346728372937352457354204563027~pRpR
diff --git a/testsuite/dc_divmod_results.txt b/testsuite/dc_divmod_results.txt
new file mode 100644
index 000000000..c55e9303d
--- /dev/null
+++ b/testsuite/dc_divmod_results.txt
@@ -0,0 +1,126 @@
10
20
30
40
50
60
70
81.00000000000000000000
9.00000000165742620220
10.00000000000077671755
11.000000000000000000000404744340951948
124.17419336592637110778
13.000000001121901731436913388268041440
14.00000000000420899796
15.00000053204123177372
16.00041271738677857404
17.00000000000027633393
1810591131829.40901859967857131767
19.000000000000000000008615446968672
209483402361494453751.52388015648196297248
21.00000000001477790730322167374655468
2215063068.13735316451497043884
23-.00000456715270151800
24-90.11223545260531110575
25-.000000000000000000002529869118878532347
26-1057067521778623447.45138528213564485251
27-.0000022326265743225222025732006233770753463532
28-11.94161814246320631346
29-.00000000004830962712
30-.00000000005126306228
31-.0000000000000000000013970700728
32-1.14705437777218917343
33-.0000000001738947526290727016287423110
34-.00000000000194126663
35-.00000000000045885284
36-485262.88923145638029569727
37-.0000000000000000000075040663382506
38-100024372711.74763635544535424582
39-.000001609445227594519190694403080
40-.00682569681609989277
41-.00000019041665271998
4225638.20711150436682153521
43-.000000000000000000005200979673140462744
442700714504347599627864.24626421085374010264
45-.15832010238185026960887316509782343287709
4610906.42973524078145692731
47-.00000436867838665327682
48.00000000000000017054
49-.000000000000000000004322546241638067588696083330
50.21260557443109085166
51-.00000000000000000000103666428264443764258
523.89799997647407910677
53-.000000130244568783188524951028009600190
54.00000000000006801538
55-.00000000467404345575
563988.13076601933678578945
57-.0000000000000000000004406586308076852
58100864416620775.31076855630746548983
59-53336.193401942302558132911110799109649707477
60.00000000052530099381
61.0000000000000000000000000000000000000000000000000000000000000001907\
62266929376630027064745963897
6342612515855353136519261264261472677699404182.78776061098893912189
640
650
660
670
680
690
700
711
721
730
74.0417310245731064
754
761.0000000000000000
770
781249687284356
790
8014621810
8110591131829
82.5164321195789
839483402361494453751
84326154559.235716791539036
8515063068
86-98379182108105
87-90
88-.1523548944025685359
89-1057067521778623447
90-410303423619005.20436836125523739550164962
91-11
92-.37861723347576903
930
94-.051210789003962
95-1
96-.69204145238732040
970
98-65736175.7573280963748
99-485262
100-.58582391357943
101-100024372711
102-2374123896417.143789621437581
1030
104-7243991903570
10525638
106-.2165246218974912344
1072700714504347599627864
108-9361314145225494248.811531234062495956534
10910906
110-.23457980123576298375682
1110
112-.1738970618624789512640000000
1130
114-.2116391019814142152206
1153
116-.9375896183746982374568
1170
118-96095925047.12323745862937465
1193988
120-.07316224567061600
121100864416620775
122-3878923750692883.7238596702834756902
1230
124.0000000000000000000000000000000000000000000184866017689020776005643\
1253621086
12642612515855353136519261264261472677699404182
diff --git a/testsuite/dc_misc.dc b/testsuite/dc_misc.dc
new file mode 100644
index 000000000..222a3ad26
--- /dev/null
+++ b/testsuite/dc_misc.dc
@@ -0,0 +1 @@
zp198202389.289374pzp[Hello, World!]pzpzpfrfczpfR
diff --git a/testsuite/dc_misc_results.txt b/testsuite/dc_misc_results.txt
new file mode 100644
index 000000000..fb321a817
--- /dev/null
+++ b/testsuite/dc_misc_results.txt
@@ -0,0 +1,20 @@
10
2198202389.289374
32
4Hello, World!
54
65
75
84
9Hello, World!
102
11198202389.289374
120
134
145
15Hello, World!
162
17198202389.289374
180
190
200
diff --git a/testsuite/dc_modexp.dc b/testsuite/dc_modexp.dc
new file mode 100644
index 000000000..a6afb9985
--- /dev/null
+++ b/testsuite/dc_modexp.dc
@@ -0,0 +1,103 @@
10 0 1|pR
21 0 1|pR
31 0 2|pR
40 10 1|pR
51 293 1|pR
61 2789365 2|pR
7100 8 7|pR
810922384 15031007 201|pR
93346529 189 254|pR
104113416930 197 14|pR
117709 5887 111|pR
125487406 3252 128|pR
132080527 2279453822 219|pR
1448895 50678 232|pR
151535808383 2902995144 18|pR
168437837 2882198 69|pR
1735363 25806 2|pR
183221177403 1560419989 189|pR
19227 42775 163|pR
202811398069 37500 173|pR
2115046850 3859895697 195|pR
2215770756 3621999893 119|pR
236937927 3719297189 183|pR
2412573 43819 209|pR
2542098463 7584603 136|pR
268656683 1328292415 226|pR
27209 81 157|pR
28141 13317429 26|pR
29809485795 60745 101|pR
304882 1388217898 38|pR
31750704 78 119|pR
32668879580 2888860497 179|pR
331152725844 15295742 154|pR
3416160694 8981529 154|pR
35216 102 3|pR
363691227289 5344109 232|pR
372195559299 61 222|pR
382478990626 13007440 30|pR
3945083 44 117|pR
40224 55824 53|pR
411372700133 89 94|pR
42205 10422 48|pR
4311887 12 73|pR
445955 24353 114|pR
451201697310 789722419 6|pR
4656577 231 229|pR
4796 38841 189|pR
486529661 5636520 209|pR
4911005 15955685 27|pR
509709 231 132|pR
5159790 1034579699 166|pR
5247892 14536879 79|pR
5348 208 21|pR
5433036 3877 65|pR
55164 6527085 249|pR
5612146850 224 37|pR
57218 16425679 62|pR
5851 27641 95|pR
593076735605 49154 32|pR
60515652717 4117874315 143|pR
61300672671 720768884 110|pR
629422066 206 5|pR
6343 97 13|pR
64545174510 65319 126|pR
653317462730 704990271 51|pR
6647316 23231 202|pR
677236571 4379567 106|pR
682584584521 2459274189 29|pR
6961562 5035178 178|pR
7065302 112 151|pR
7163040 2168854052 213|pR
729039611 2370306559 62|pR
7316414384 1020652061 83|pR
747491 3853569905 172|pR
751180322494 46670 84|pR
763823343557 3865107254 127|pR
776240872 55335 39|pR
782281401897 1098411 251|pR
7961 2949190429 231|pR
808981024 162 43|pR
811 3568883218 212|pR
824217100969 3471787779 8|pR
833232237 13 243|pR
8429280 3972452706 100|pR
8513077 6431923 216|pR
86104 3098510775 140|pR
879503298 174 242|pR
883424695712 12184 23|pR
89184 15066347 151|pR
902935856 14003205 184|pR
911386637762 2128151420 71|pR
92154 11960656 12|pR
93743976432 4004778779 136|pR
943909160595 3575680922 21|pR
9526133 3580 147|pR
96409154 170 68|pR
97149 55629 40|pR
985753 13776176 32|pR
993831447473 658273178 98|pR
1001527252003 2300622 207|pR
1013363824553 8244645 215|pR
10220 145 101|pR
1034005077294 2196555621 94|pR
diff --git a/testsuite/dc_modexp_results.txt b/testsuite/dc_modexp_results.txt
new file mode 100644
index 000000000..5bf0f146e
--- /dev/null
+++ b/testsuite/dc_modexp_results.txt
@@ -0,0 +1,103 @@
11
21
31
40
50
61
74
874
91
100
1198
120
1372
141
151
161
171
18108
1936
2052
2165
228
23181
2422
257
26123
2793
2821
2917
3020
311
32108
3358
3422
350
36105
37161
3816
3940
4015
4145
4225
4364
4469
450
46225
4727
481
4922
5073
5192
5238
5315
5416
55173
5633
5732
5821
5925
60109
6171
621
634
6462
6515
6690
6729
685
6940
7084
7140
7253
738
7431
7564
7644
7714
7813
79145
801
811
821
8376
840
85189
86104
87192
889
89119
9056
9145
924
9332
9416
95135
964
9729
981
9949
1000
101128
1026
10318
diff --git a/testsuite/dc_modulus.dc b/testsuite/dc_modulus.dc
new file mode 100644
index 000000000..613944b20
--- /dev/null
+++ b/testsuite/dc_modulus.dc
@@ -0,0 +1,70 @@
120k
21 1%pR
32 1%pR
416 4%pR
515 4%pR
617 4%pR
72389473 5%pR
839240687239 1%pR
9346728934 23958%pR
103496723859067234 298375462837546928347623059375486%pR
11_1 1%pR
12_2 1%pR
13_47589634875689345 37869235%pR
14_1274852934765 2387628935486273546%pR
15_6324758963 237854962%pR
161 _1%pR
172 _1%pR
182 _2%pR
192 _3%pR
2016 5%pR
2115 5%pR
2214 5%pR
2389237423 _237856923854%pR
24123647238946 _12467%pR
25_1 _1%pR
26_2 _1%pR
27_2 _2%pR
28_2 _3%pR
29_13 _7%pR
30_14 _7%pR
31_15 _7%pR
32_12784956 _32746%pR
33_127849612 _23712347682193%pR
340k
351 1%pR
362 1%pR
3716 4%pR
3815 4%pR
3917 4%pR
402389473 5%pR
4139240687239 1%pR
42346728934 23958%pR
433496723859067234 298375462837546928347623059375486%pR
44_1 1%pR
45_2 1%pR
46_47589634875689345 37869235%pR
47_1274852934765 2387628935486273546%pR
48_6324758963 237854962%pR
491 _1%pR
502 _1%pR
512 _2%pR
522 _3%pR
5316 5%pR
5415 5%pR
5514 5%pR
5689237423 _237856923854%pR
57123647238946 _12467%pR
58_1 _1%pR
59_2 _1%pR
60_2 _2%pR
61_2 _3%pR
62_13 _7%pR
63_14 _7%pR
64_15 _7%pR
65_12784956 _32746%pR
66_127849612 _23712347682193%pR
67_3191280681 641165986%pR
680k _899510228 _2448300078.40314%pR
690k _7424863 _207.2609738667%pR
700k 3769798918 0.6%pR
diff --git a/testsuite/dc_modulus_results.txt b/testsuite/dc_modulus_results.txt
new file mode 100644
index 000000000..7d718d22a
--- /dev/null
+++ b/testsuite/dc_modulus_results.txt
@@ -0,0 +1,68 @@
10
20
30
40
50
60
70
8.00000000000000002026
92747189239559.46904933397471305894
100
110
12-.00000000000011057855
13-.00076922992566770712
14-.00000000000050364144
150
160
170
18.00000000000000000002
190
200
210
22.00000000070585524350
23.00000000000000002898
240
250
260
27-.00000000000000000002
28-.00000000000000000005
290
30-.00000000000000000002
31-.00000000000000011722
32-.00000002640923745817
330
340
350
363
371
383
390
408758
413496723859067234
420
430
44-8236960
45-1274852934765
46-140529951
470
480
490
502
511
520
534
5489237423
556692
560
570
580
59-2
60-6
610
62-1
63-14016
64-127849612
65-626616737
66-899510228.00000
67-153.1331732059
68.4
diff --git a/testsuite/dc_multiply.dc b/testsuite/dc_multiply.dc
new file mode 100644
index 000000000..1f9041d06
--- /dev/null
+++ b/testsuite/dc_multiply.dc
@@ -0,0 +1,42 @@
10 0*pR
20.000 0*pR
31 0*pR
40 1*pR
50 2498752389672835476*pR
6873246913745129084576134 0*pR
71 472638590273489273456*pR
812374861230476103672835496 1*pR
91 1*pR
102 1*pR
111 2*pR
122 2*pR
133 14*pR
1417 8*pR
151892467513846753 1872439821374591038746*pR
16328962735862.2973546835638947635 1728465791348762356*pR
1738745962374538.387427384672934867234 0.1932476528394672837568923754*pR
189878894576289457634856.2738627161689017387608947567654 37842939768237596237854203.29874372139852739126739621793162*pR
19_1 1*pR
20_1 2*pR
2178893457 _34876238956*pR
22235678324957634 _0.2349578349672389576*pR
23_12849567821934 12738462937681*pR
241274861293467.927843682937462 _28935678239*pR
252936077239872.12937462836 _0.012842357682435762*pR
262387692387566.2378569237546 _272189345628.123875629835876*pR
270.012348629356782835962 _23487692356*pR
280.4768349567348675934 _0.23756834576934857638495*pR
290.98748395367485962735486 _4675839462354867.376834956738456*pR
30_321784627934586 _235762378596*pR
31_32578623567892356 _0.32567384579638456*pR
32_35768232346876 _2348672935602387620.28375682349576237856*pR
33_0.2356728394765234 _238759624356978*pR
34_0.2345768212346780 _0.235768124697074385948943532045*pR
35_0.370873860736785306278630 _7835678398607.7086378076867096270*pR
36_78365713707.7089637863786730 _738580798679306780*pR
37_73867038956790490258249 _0.7379862716391723672803679*pR
38_378621971598721837710387 _98465373878350798.09743896037963078560*pR
3937164201 2931559660*pR
40679468076118972457796560530571.46287161642138401685 93762.2836*pR
41.000000000000000000000000001 .0000000000000000000000001*pR
42239 289 _98 .8937 _.1893 28937*****pR
diff --git a/testsuite/dc_multiply_results.txt b/testsuite/dc_multiply_results.txt
new file mode 100644
index 000000000..9666059a5
--- /dev/null
+++ b/testsuite/dc_multiply_results.txt
@@ -0,0 +1,43 @@
10
20
30
40
50
60
7472638590273489273456
812374861230476103672835496
91
102
112
124
1342
14136
153543531533584430580556128344529291738
16568600835566479683035874339053.4411638427543228060
177487566285885.8557453089005171423976251098
18373846412427291014394738378015501363938345620046.7869650248829232267\
192297002026819
20-1
21-2
22-2751507058396910892
23-55374468980751.0837656919743223184
24-163683743464924630346895054
25-36888976187143312550878.567134791289418
26-37706154097.696628262157533781
27-649904428532907022680241.947918694247541
28-290040807.350385412976669306472
29-.11328089187650139309272
30-4617316439035114.40320367843985107357898
3175864709277486862054521256
3210610005628108234.92015040406042336
3384007879267445533366251128067927.91168012197674537856
3456269158624557.1027018519702852
35.055305737239900889424090264801
362906048299183.472237078104362540110129
3757879411419313585866282299201.3825582163029400
3854512860676747314187949.9414724679950990587298071
3937281153992026463004361915151761464058058.54968338992209002720
40108949072447731660
4163708478450213482928510139572007971.83536929222529239687
420
4333137343861.8586
diff --git a/testsuite/dc_power.dc b/testsuite/dc_power.dc
new file mode 100644
index 000000000..b58ae0cbc
--- /dev/null
+++ b/testsuite/dc_power.dc
@@ -0,0 +1,45 @@
120k
20 0^pR
30 1^pR
40 1894^pR
51 0^pR
639746823 0^pR
70.238672983047682 0^pR
818394762374689237468.97354862973846 0^pR
91 1^pR
102 1^pR
1118927361346 1^pR
120.23523785962738592635777 1^pR
13328956734869213746.89782398457234 1^pR
148937 98^pR
150.124876812394 2396^pR
1693762.2836 13^pR
171 _1^pR
182 _1^pR
1910 _1^pR
20683734768 _1^pR
2138579623756.897937568235 _1^pR
221 _32467^pR
232 _53^pR
2423897 _213^pR
25_1 1^pR
26_1 2^pR
27_2 1^pR
28_2 2^pR
29_237 294^pR
30_3746 28^pR
31_0.3548 35^pR
32_4267.234 37^pR
33_326.3246 78^pR
34_1 _1^pR
35_1 _2^pR
36_2 _1^pR
37_2 _2^pR
38_237 _293^pR
39_784 _23^pR
40_86 _7^pR
41_0.23424398 _781^pR
42_178.234786 _879^pR
43_1274.346 _768^pR
440 _251^pR
45_0.2959371298 227^pR
diff --git a/testsuite/dc_power_results.txt b/testsuite/dc_power_results.txt
new file mode 100644
index 000000000..997f44f59
--- /dev/null
+++ b/testsuite/dc_power_results.txt
@@ -0,0 +1,73 @@
11
20
30
41
51
61
71
81
92
1018927361346
11.23523785962738592635777
12328956734869213746.89782398457234
1316473742664221279051571200630760751138799221376964991600670000200609\
1408006052596520320731708604393844468006290371918262741885989163144389\
1539367835091560809036359941703341471396407660150658436796925310445979\
1621333166245765946557344383284626113908419359990042883048537750217279\
1717481980123593363177308481941550382845381799410533956718500484099889\
18610805653325917409549921909941664118421333562129
190
2043287877285033571298394739716218787350087163435619825150259705419.98\
21016445740928054425
221.00000000000000000000
23.50000000000000000000
24.10000000000000000000
25.00000000146255543348
26.00000000002592041867
271.00000000000000000000
28.00000000000000011102
290
30-1
311
32-2
334
3414997322375665265051328725757939209353051902095893907150382724666290\
3549749481660976421019742616298227588464420182758442163654172400528243\
3600885441207762486233574213374503090372518590691583139696652847404883\
3708573912261119588874308960204159666762789603037188471170006223907416\
3860492840269152716750700089148882139254399347568222390231015487895905\
3973727080561379177721440905866857248917982113340543176658480139248897\
4054802503253413282808814063861470711399810899724515727713334909764746\
4127910290211411231279325882505708287941671508154740003122373284699097\
4278346501539634198926772266511968381368929692275950529960923432771985\
4312597189390708050983487158873301681237787429436264801751664042999180\
443448659818912436089
4511478830555358864333472551120140548480416206583184496764727387456058\
46792742209537931243951391229607936
47-.00000000000000017759
48-2067373624686414405470850679965010694114490999957199847684803894306\
4956243666149296582304582679590231948238805965642713928910384741502707\
50.23224479257866798694
5111606078892843496082360561256965139908586179418605021706789617179085\
5285768049299693425729565480314913006780973928345684673490252494674985\
530186164225375953066263609289359900615361965737717208159874390.293769\
5470206344604971
55-1.00000000000000000000
561.00000000000000000000
57-.50000000000000000000
58.25000000000000000000
590
600
61-.00000000000002874159
62-1945134149489344891879057554905782841936258356736314337975569799825\
6394091939572752348215929683891336730843553721422164737465108229034947\
6487333189564755763444242676978610321731298729194092653999616928308494\
6526419468484566422775668903315088810746121307679948574976162519479931\
6618935243698160094347216562490000767121041786977792546155155934655909\
6714123833869470494708767968978717730012864171105540029928688274136791\
6898175053824022144065005509214813689232148489884560100200475909009813\
69340098100705258138.98542904577525702068
700
710
720
730
diff --git a/testsuite/dc_sqrt.dc b/testsuite/dc_sqrt.dc
new file mode 100644
index 000000000..7c13fdd0b
--- /dev/null
+++ b/testsuite/dc_sqrt.dc
@@ -0,0 +1,14 @@
120k
20vpR
32vpR
44vpR
59vpR
616vpR
725vpR
8121vpR
948765vpR
109287356207356vpR
110.189274385967238956872354vpR
1212389467137496823.134567829387456283946vpR
13.0000000000000000000000000000123vpR
141vpR
diff --git a/testsuite/dc_sqrt_results.txt b/testsuite/dc_sqrt_results.txt
new file mode 100644
index 000000000..5ded8c294
--- /dev/null
+++ b/testsuite/dc_sqrt_results.txt
@@ -0,0 +1,13 @@
10
21.41421356237309504880
32.00000000000000000000
43.00000000000000000000
54.00000000000000000000
65.00000000000000000000
711.00000000000000000000
8220.82798735667542192643
93047516.39985021245496456781
10.435056761776252544285578
11111307983.260397019622398608908
12.0000000000000035071355833500363
131.00000000000000000000
diff --git a/testsuite/dc_strings.dc b/testsuite/dc_strings.dc
new file mode 100644
index 000000000..2f6b38d88
--- /dev/null
+++ b/testsuite/dc_strings.dc
@@ -0,0 +1,37 @@
1[Hello, World!]ZpR
2[Hello, World!]pR
3[Hello, \[ World!]ZpR
4[Hello, \[ World!]pR
5[Hello, \] World!]ZpR
6[Hello, \] World!]pR
7[30pR]
8[29pR]
9[28pR]
10[27pR]
11[26pR]
12[25pR]
13[24pR]
14[23pR]
15[22pR]
16[21pR]
17[20pR]
18[19pR]
19[18pR]
20[17pR]
21[16pR]
22[15pR]
23[14pR]
24[13pR]
25[12pR]
26[11pR]
27[10pR]
28[9pR]
29[8pR]
30[7pR]
31[6pR]
32[5pR]
33[4pR]
34[3pR]
35[2pR]
36[1pR]
37[xz0<x]dsxx
diff --git a/testsuite/dc_strings_results.txt b/testsuite/dc_strings_results.txt
new file mode 100644
index 000000000..e49b9b288
--- /dev/null
+++ b/testsuite/dc_strings_results.txt
@@ -0,0 +1,36 @@
113
2Hello, World!
3Hello, \[ World!]ZpR
4[Hello, \[ World!]pR
5[Hello, \] World!]ZpR
6[Hello, \] World!
71
82
93
104
115
126
137
148
159
1610
1711
1812
1913
2014
2115
2216
2317
2418
2519
2620
2721
2822
2923
3024
3125
3226
3327
3428
3529
3630
diff --git a/testsuite/dc_subtract.dc b/testsuite/dc_subtract.dc
new file mode 100644
index 000000000..2cb4104fb
--- /dev/null
+++ b/testsuite/dc_subtract.dc
@@ -0,0 +1,33 @@
10 0-pR
20 1-pR
31 0-pR
41 1-pR
55 2-pR
62 9-pR
7321974 12845976238457-pR
82874519803456710938465 384723854-pR
910000000000000000000000000000000000000000 999999999999999999999999999999999999999-pR
1010000000000000000000000000000000000000000 9999999999999999999999999999999999999999-pR
1110000000000000000000000000000000000000000 999999999999999999999999999999999999999.99999999999999999999999999999999999-pR
1210000000000000000000000000000000000000000 9999999999999999999999999999999999999999.9999999999999999999999999999999999-pR
1310000000000000000000000000000000000000000 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000001-pR
1410000000000000000000000000000000000000001 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000001-pR
1510000000000000000000000000000000000000000.0000000001 0.0000000000000000000000000000000000000000000000000000000000000000000000000001-pR
16_2 6-pR
17_23784692345 182934721309467230894628735496027345-pR
18_224352354962873059862 _1245723576829456278354960278345-pR
19_3468273598 _12354243-pR
20_0.92345768293 _2354768923-pR
21_712384634.123476823 _24768293376-pR
22_1879234638 _0.917234869234-pR
23_0.9172438692134 _0.971284967124-pR
24_0.1283475123465 _0.937462346-pR
25_124765829346.2837468293562 _0.923467829346-pR
26_12476829385769 _1928476259034.8378629356-pR
27_0.38476284395876345 _94875394587623.2357869324857-pR
28_4674596708467.34754789403674343567 _48672394852354698.237548629345-pR
29979519669 3018100865-pR
30929002449 3280677283-pR
310 _525898-pR
323 _3-pR
332 _1 2893714 _2189367411289 _.8921374 3.9201384----pR
diff --git a/testsuite/dc_subtract_results.txt b/testsuite/dc_subtract_results.txt
new file mode 100644
index 000000000..9f7726254
--- /dev/null
+++ b/testsuite/dc_subtract_results.txt
@@ -0,0 +1,37 @@
10
2-1
31
40
53
6-7
7-12845975916483
82874519803456326214611
99000000000000000000000000000000000000001
101
119000000000000000000000000000000000000000.000000000000000000000000000\
1200000001
13.0000000000000000000000000000000001
149999999999999999999999999999999999999999.999999999999999999999999999\
1599999999999999999999999999999999999999999999999999999999999
1610000000000000000000000000000000000000000.99999999999999999999999999\
17999999999999999999999999999999999999999999999999999999999999
1810000000000000000000000000000000000000000.00000000009999999999999999\
1999999999999999999999999999999999999999999999999999
20-8
21-182934721309467230894628759280719690
221245723576605103923392087218483
23-3455919355
242354768922.07654231707
2524055908741.876523177
26-1879234637.082765130766
27.0540410979106
28.8091148336535
29-124765829345.3602790000102
30-10548353126734.1621370644
3194875394587622.85102408852693655
3248667720255646230.89000073530825656433
33-2038581196
34-2351674834
35525898
366
37-2189370304999.1877242
diff --git a/testsuite/dcx_vars.dc b/testsuite/dcx_vars.dc
new file mode 100644
index 000000000..bbe73b47d
--- /dev/null
+++ b/testsuite/dcx_vars.dc
@@ -0,0 +1,2 @@
1298734.8921702348sx_928374892.28937syzpRlxly+pR
2298734.8921702348S xotj _928374892.28937S yotp zpRl xotj l yotp-pRzpR L xotj L yotp-pR
diff --git a/testsuite/dcx_vars_results.txt b/testsuite/dcx_vars_results.txt
new file mode 100644
index 000000000..6f18e7a84
--- /dev/null
+++ b/testsuite/dcx_vars_results.txt
@@ -0,0 +1,6 @@
10
2-928076157.3971997652
30
4928673627.1815402348
50
6928673627.1815402348
diff --git a/testsuite/head.tests b/testsuite/head.tests
index 50660d267..97bf889d8 100755
--- a/testsuite/head.tests
+++ b/testsuite/head.tests
@@ -31,10 +31,12 @@ testing "head -n <positive number>" \
31 "line 1\nline 2\n" \ 31 "line 1\nline 2\n" \
32 "" "" 32 "" ""
33 33
34optional FEATURE_FANCY_HEAD
34testing "head -n <negative number>" \ 35testing "head -n <negative number>" \
35 "head -n -9 head.input" \ 36 "head -n -9 head.input" \
36 "line 1\nline 2\nline 3\n" \ 37 "line 1\nline 2\nline 3\n" \
37 "" "" 38 "" ""
39SKIP=
38 40
39rm head.input 41rm head.input
40 42
diff --git a/testsuite/unzip.tests b/testsuite/unzip.tests
index af53de9df..e198dfc4b 100755
--- a/testsuite/unzip.tests
+++ b/testsuite/unzip.tests
@@ -31,10 +31,10 @@ rmdir foo
31rm foo.zip 31rm foo.zip
32 32
33# File containing some damaged encrypted stream 33# File containing some damaged encrypted stream
34optional FEATURE_UNZIP_CDF 34optional FEATURE_UNZIP_CDF CONFIG_UNICODE_SUPPORT
35testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \ 35testing "unzip (bad archive)" "uudecode; unzip bad.zip 2>&1; echo \$?" \
36"Archive: bad.zip 36"Archive: bad.zip
37 inflating: ]3j½r«IK-%Ix 37 inflating: ]3j½r«I??K-%Ix
38unzip: corrupted data 38unzip: corrupted data
39unzip: inflate error 39unzip: inflate error
401 401
diff --git a/util-linux/acpid.c b/util-linux/acpid.c
index 4f491fa14..7274b6866 100644
--- a/util-linux/acpid.c
+++ b/util-linux/acpid.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config ACPID 9//config:config ACPID
10//config: bool "acpid (8.7 kb)" 10//config: bool "acpid (9 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/util-linux/blkdiscard.c b/util-linux/blkdiscard.c
index e4902e5b5..a77c7d057 100644
--- a/util-linux/blkdiscard.c
+++ b/util-linux/blkdiscard.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config BLKDISCARD 8//config:config BLKDISCARD
9//config: bool "blkdiscard (5.3 kb)" 9//config: bool "blkdiscard (4.3 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX 11//config: select PLATFORM_LINUX
12//config: help 12//config: help
diff --git a/util-linux/blkid.c b/util-linux/blkid.c
index a56b69661..008ae5d9e 100644
--- a/util-linux/blkid.c
+++ b/util-linux/blkid.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config BLKID 9//config:config BLKID
10//config: bool "blkid (11 kb)" 10//config: bool "blkid (12 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: select VOLUMEID 13//config: select VOLUMEID
diff --git a/util-linux/blockdev.c b/util-linux/blockdev.c
index e53ade995..5d8e465b4 100644
--- a/util-linux/blockdev.c
+++ b/util-linux/blockdev.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2, see file LICENSE in this source tree. 6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */ 7 */
8//config:config BLOCKDEV 8//config:config BLOCKDEV
9//config: bool "blockdev (2.4 kb)" 9//config: bool "blockdev (2.3 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: Performs some ioctls with block devices. 12//config: Performs some ioctls with block devices.
diff --git a/util-linux/cal.c b/util-linux/cal.c
index a4a20d5f0..006bc817b 100644
--- a/util-linux/cal.c
+++ b/util-linux/cal.c
@@ -11,7 +11,7 @@
11 * Major size reduction... over 50% (>1.5k) on i386. 11 * Major size reduction... over 50% (>1.5k) on i386.
12 */ 12 */
13//config:config CAL 13//config:config CAL
14//config: bool "cal (6.5 kb)" 14//config: bool "cal (5.8 kb)"
15//config: default y 15//config: default y
16//config: help 16//config: help
17//config: cal is used to display a monthly calendar. 17//config: cal is used to display a monthly calendar.
diff --git a/util-linux/chrt.c b/util-linux/chrt.c
index 45459d940..28e65457c 100644
--- a/util-linux/chrt.c
+++ b/util-linux/chrt.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config CHRT 8//config:config CHRT
9//config: bool "chrt (4.4 kb)" 9//config: bool "chrt (4.7 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: Manipulate real-time attributes of a process. 12//config: Manipulate real-time attributes of a process.
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c
index 6da9d9f4e..b797c7b2a 100644
--- a/util-linux/dmesg.c
+++ b/util-linux/dmesg.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2, see file LICENSE in this source tree. 9 * Licensed under GPLv2, see file LICENSE in this source tree.
10 */ 10 */
11//config:config DMESG 11//config:config DMESG
12//config: bool "dmesg (3.5 kb)" 12//config: bool "dmesg (3.7 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX 14//config: select PLATFORM_LINUX
15//config: help 15//config: help
diff --git a/util-linux/eject.c b/util-linux/eject.c
index 6c30facd2..749e2c986 100644
--- a/util-linux/eject.c
+++ b/util-linux/eject.c
@@ -13,7 +13,7 @@
13 * Most of the dirty work blatantly ripped off from cat.c =) 13 * Most of the dirty work blatantly ripped off from cat.c =)
14 */ 14 */
15//config:config EJECT 15//config:config EJECT
16//config: bool "eject (4.1 kb)" 16//config: bool "eject (4 kb)"
17//config: default y 17//config: default y
18//config: select PLATFORM_LINUX 18//config: select PLATFORM_LINUX
19//config: help 19//config: help
diff --git a/util-linux/fallocate.c b/util-linux/fallocate.c
index 8542586dc..3935e7c9b 100644
--- a/util-linux/fallocate.c
+++ b/util-linux/fallocate.c
@@ -5,7 +5,7 @@
5 * Licensed under GPLv2, see file LICENSE in this source tree. 5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */ 6 */
7//config:config FALLOCATE 7//config:config FALLOCATE
8//config: bool "fallocate (5 kb)" 8//config: bool "fallocate (4.1 kb)"
9//config: default y 9//config: default y
10//config: help 10//config: help
11//config: Preallocate space for files. 11//config: Preallocate space for files.
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
index 11cb20cb2..699a19372 100644
--- a/util-linux/fbset.c
+++ b/util-linux/fbset.c
@@ -12,7 +12,7 @@
12 * Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) 12 * Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be)
13 */ 13 */
14//config:config FBSET 14//config:config FBSET
15//config: bool "fbset (5.8 kb)" 15//config: bool "fbset (5.9 kb)"
16//config: default y 16//config: default y
17//config: select PLATFORM_LINUX 17//config: select PLATFORM_LINUX
18//config: help 18//config: help
diff --git a/util-linux/fdformat.c b/util-linux/fdformat.c
index c72da8b89..ff3bc4870 100644
--- a/util-linux/fdformat.c
+++ b/util-linux/fdformat.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2, see file LICENSE in this source tree. 6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */ 7 */
8//config:config FDFORMAT 8//config:config FDFORMAT
9//config: bool "fdformat (4.5 kb)" 9//config: bool "fdformat (4.4 kb)"
10//config: default y 10//config: default y
11//config: select PLATFORM_LINUX 11//config: select PLATFORM_LINUX
12//config: help 12//config: help
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index 288b9235f..58e93bb92 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config FDISK 10//config:config FDISK
11//config: bool "fdisk (41 kb)" 11//config: bool "fdisk (37 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/util-linux/findfs.c b/util-linux/findfs.c
index 1102eeff5..7ca9dc96b 100644
--- a/util-linux/findfs.c
+++ b/util-linux/findfs.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config FINDFS 10//config:config FINDFS
11//config: bool "findfs (11 kb)" 11//config: bool "findfs (12 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: select VOLUMEID 14//config: select VOLUMEID
diff --git a/util-linux/flock.c b/util-linux/flock.c
index dd0bfd430..130627e93 100644
--- a/util-linux/flock.c
+++ b/util-linux/flock.c
@@ -4,7 +4,7 @@
4 * This is free software, licensed under the GNU General Public License v2. 4 * This is free software, licensed under the GNU General Public License v2.
5 */ 5 */
6//config:config FLOCK 6//config:config FLOCK
7//config: bool "flock (6.1 kb)" 7//config: bool "flock (6.3 kb)"
8//config: default y 8//config: default y
9//config: help 9//config: help
10//config: Manage locks from shell scripts 10//config: Manage locks from shell scripts
diff --git a/util-linux/freeramdisk.c b/util-linux/freeramdisk.c
index 6752e49d8..d27113d97 100644
--- a/util-linux/freeramdisk.c
+++ b/util-linux/freeramdisk.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2, see file LICENSE in this source tree. 9 * Licensed under GPLv2, see file LICENSE in this source tree.
10 */ 10 */
11//config:config FDFLUSH 11//config:config FDFLUSH
12//config: bool "fdflush (1.4 kb)" 12//config: bool "fdflush (1.3 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX 14//config: select PLATFORM_LINUX
15//config: help 15//config: help
@@ -22,7 +22,7 @@
22//config: leave this disabled. 22//config: leave this disabled.
23//config: 23//config:
24//config:config FREERAMDISK 24//config:config FREERAMDISK
25//config: bool "freeramdisk (1.4 kb)" 25//config: bool "freeramdisk (1.3 kb)"
26//config: default y 26//config: default y
27//config: select PLATFORM_LINUX 27//config: select PLATFORM_LINUX
28//config: help 28//config: help
diff --git a/util-linux/fsck_minix.c b/util-linux/fsck_minix.c
index c4612f251..f523da945 100644
--- a/util-linux/fsck_minix.c
+++ b/util-linux/fsck_minix.c
@@ -86,7 +86,7 @@
86 * enforced (but it's not much fun on a character device :-). 86 * enforced (but it's not much fun on a character device :-).
87 */ 87 */
88//config:config FSCK_MINIX 88//config:config FSCK_MINIX
89//config: bool "fsck_minix" 89//config: bool "fsck.minix (13 kb)"
90//config: default y 90//config: default y
91//config: help 91//config: help
92//config: The minix filesystem is a nice, small, compact, read-write filesystem 92//config: The minix filesystem is a nice, small, compact, read-write filesystem
diff --git a/util-linux/fsfreeze.c b/util-linux/fsfreeze.c
index c485810aa..fb0b3c4bd 100644
--- a/util-linux/fsfreeze.c
+++ b/util-linux/fsfreeze.c
@@ -5,7 +5,7 @@
5 * Licensed under GPLv2, see file LICENSE in this source tree. 5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */ 6 */
7//config:config FSFREEZE 7//config:config FSFREEZE
8//config: bool "fsfreeze (3.6 kb)" 8//config: bool "fsfreeze (3.5 kb)"
9//config: default y 9//config: default y
10//config: select PLATFORM_LINUX 10//config: select PLATFORM_LINUX
11//config: select LONG_OPTS 11//config: select LONG_OPTS
diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c
index 558a94a9e..48948e839 100644
--- a/util-linux/fstrim.c
+++ b/util-linux/fstrim.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config FSTRIM 10//config:config FSTRIM
11//config: bool "fstrim (5.5 kb)" 11//config: bool "fstrim (4.4 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/util-linux/getopt.c b/util-linux/getopt.c
index 4431a7e74..1666d3d30 100644
--- a/util-linux/getopt.c
+++ b/util-linux/getopt.c
@@ -29,7 +29,7 @@
29 * Replaced our_malloc with xmalloc and our_realloc with xrealloc 29 * Replaced our_malloc with xmalloc and our_realloc with xrealloc
30 */ 30 */
31//config:config GETOPT 31//config:config GETOPT
32//config: bool "getopt (5.6 kb)" 32//config: bool "getopt (5.8 kb)"
33//config: default y 33//config: default y
34//config: help 34//config: help
35//config: The getopt utility is used to break up (parse) options in command 35//config: The getopt utility is used to break up (parse) options in command
diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c
index 719feaf4e..065b83980 100644
--- a/util-linux/hexdump.c
+++ b/util-linux/hexdump.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 */ 10 */
11//config:config HEXDUMP 11//config:config HEXDUMP
12//config: bool "hexdump (8.8 kb)" 12//config: bool "hexdump (8.6 kb)"
13//config: default y 13//config: default y
14//config: help 14//config: help
15//config: The hexdump utility is used to display binary data in a readable 15//config: The hexdump utility is used to display binary data in a readable
@@ -26,7 +26,7 @@
26//config: aimed to be portable. 26//config: aimed to be portable.
27//config: 27//config:
28//config:config HD 28//config:config HD
29//config: bool "hd (8 kb)" 29//config: bool "hd (7.8 kb)"
30//config: default y 30//config: default y
31//config: help 31//config: help
32//config: hd is an alias to hexdump -C. 32//config: hd is an alias to hexdump -C.
diff --git a/util-linux/ionice.c b/util-linux/ionice.c
index 5b9664d25..daf64d537 100644
--- a/util-linux/ionice.c
+++ b/util-linux/ionice.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config IONICE 9//config:config IONICE
10//config: bool "ionice (3.6 kb)" 10//config: bool "ionice (3.8 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/util-linux/ipcrm.c b/util-linux/ipcrm.c
index a93ceee11..3d3ad0b56 100644
--- a/util-linux/ipcrm.c
+++ b/util-linux/ipcrm.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config IPCRM 10//config:config IPCRM
11//config: bool "ipcrm (2.9 kb)" 11//config: bool "ipcrm (3.2 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: The ipcrm utility allows the removal of System V interprocess 14//config: The ipcrm utility allows the removal of System V interprocess
diff --git a/util-linux/last.c b/util-linux/last.c
index f5ee8e5f4..689aa7a34 100644
--- a/util-linux/last.c
+++ b/util-linux/last.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LAST 9//config:config LAST
10//config: bool "last (6.2 kb)" 10//config: bool "last (6.1 kb)"
11//config: default y 11//config: default y
12//config: depends on FEATURE_WTMP 12//config: depends on FEATURE_WTMP
13//config: help 13//config: help
diff --git a/util-linux/losetup.c b/util-linux/losetup.c
index 6b171d710..bf480e9bf 100644
--- a/util-linux/losetup.c
+++ b/util-linux/losetup.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LOSETUP 9//config:config LOSETUP
10//config: bool "losetup (5.4 kb)" 10//config: bool "losetup (5.5 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/util-linux/lspci.c b/util-linux/lspci.c
index 0000fbfda..a6b4e850f 100644
--- a/util-linux/lspci.c
+++ b/util-linux/lspci.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LSPCI 9//config:config LSPCI
10//config: bool "lspci (5.7 kb)" 10//config: bool "lspci (6.3 kb)"
11//config: default y 11//config: default y
12//config: #select PLATFORM_LINUX 12//config: #select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/util-linux/lsusb.c b/util-linux/lsusb.c
index 33639413a..e27aa7f31 100644
--- a/util-linux/lsusb.c
+++ b/util-linux/lsusb.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config LSUSB 9//config:config LSUSB
10//config: bool "lsusb (3.5 kb)" 10//config: bool "lsusb (4.2 kb)"
11//config: default y 11//config: default y
12//config: #select PLATFORM_LINUX 12//config: #select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 4b4eeafba..63b55536a 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10//config:config MDEV 10//config:config MDEV
11//config: bool "mdev (16 kb)" 11//config: bool "mdev (17 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
@@ -808,6 +808,16 @@ static void make_device(char *device_name, char *path, int operation)
808 } /* for (;;) */ 808 } /* for (;;) */
809} 809}
810 810
811static ssize_t readlink2(char *buf, size_t bufsize)
812{
813 // Grr... gcc 8.1.1:
814 // "passing argument 2 to restrict-qualified parameter aliases with argument 1"
815 // dance around that...
816 char *obuf FIX_ALIASING;
817 obuf = buf;
818 return readlink(buf, obuf, bufsize);
819}
820
811/* File callback for /sys/ traversal. 821/* File callback for /sys/ traversal.
812 * We act only on "/sys/.../dev" (pseudo)file 822 * We act only on "/sys/.../dev" (pseudo)file
813 */ 823 */
@@ -831,7 +841,7 @@ static int FAST_FUNC fileAction(const char *fileName,
831 /* Read ".../subsystem" symlink in the same directory where ".../dev" is */ 841 /* Read ".../subsystem" symlink in the same directory where ".../dev" is */
832 strcpy(subsys, path); 842 strcpy(subsys, path);
833 strcpy(subsys + len, "/subsystem"); 843 strcpy(subsys + len, "/subsystem");
834 res = readlink(subsys, subsys, sizeof(subsys)-1); 844 res = readlink2(subsys, sizeof(subsys)-1);
835 if (res > 0) { 845 if (res > 0) {
836 subsys[res] = '\0'; 846 subsys[res] = '\0';
837 free(G.subsystem); 847 free(G.subsystem);
diff --git a/util-linux/mesg.c b/util-linux/mesg.c
index 35c4ec13d..c7b696853 100644
--- a/util-linux/mesg.c
+++ b/util-linux/mesg.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config MESG 9//config:config MESG
10//config: bool "mesg (1.2 kb)" 10//config: bool "mesg (1.4 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: Mesg controls access to your terminal by others. It is typically 13//config: Mesg controls access to your terminal by others. It is typically
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index bda168f1e..845ba0a24 100644
--- a/util-linux/mkfs_ext2.c
+++ b/util-linux/mkfs_ext2.c
@@ -8,14 +8,14 @@
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10//config:config MKE2FS 10//config:config MKE2FS
11//config: bool "mke2fs (9.7 kb)" 11//config: bool "mke2fs (10 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
15//config: Utility to create EXT2 filesystems. 15//config: Utility to create EXT2 filesystems.
16//config: 16//config:
17//config:config MKFS_EXT2 17//config:config MKFS_EXT2
18//config: bool "mkfs.ext2 (9.8 kb)" 18//config: bool "mkfs.ext2 (10 kb)"
19//config: default y 19//config: default y
20//config: select PLATFORM_LINUX 20//config: select PLATFORM_LINUX
21//config: help 21//config: help
diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c
index 69dfcd123..e191acbd0 100644
--- a/util-linux/mkfs_minix.c
+++ b/util-linux/mkfs_minix.c
@@ -63,7 +63,7 @@
63 * removed getopt based parser and added a hand rolled one. 63 * removed getopt based parser and added a hand rolled one.
64 */ 64 */
65//config:config MKFS_MINIX 65//config:config MKFS_MINIX
66//config: bool "mkfs_minix" 66//config: bool "mkfs.minix (10 kb)"
67//config: default y 67//config: default y
68//config: select PLATFORM_LINUX 68//config: select PLATFORM_LINUX
69//config: help 69//config: help
diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c
index 6a6dc652f..b760fb2aa 100644
--- a/util-linux/mkfs_vfat.c
+++ b/util-linux/mkfs_vfat.c
@@ -8,14 +8,14 @@
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10//config:config MKDOSFS 10//config:config MKDOSFS
11//config: bool "mkdosfs (6.8 kb)" 11//config: bool "mkdosfs (7.2 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
15//config: Utility to create FAT32 filesystems. 15//config: Utility to create FAT32 filesystems.
16//config: 16//config:
17//config:config MKFS_VFAT 17//config:config MKFS_VFAT
18//config: bool "mkfs.vfat (6.8 kb)" 18//config: bool "mkfs.vfat (7.2 kb)"
19//config: default y 19//config: default y
20//config: select PLATFORM_LINUX 20//config: select PLATFORM_LINUX
21//config: help 21//config: help
diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c
index 2eb16bd84..38413606d 100644
--- a/util-linux/mkswap.c
+++ b/util-linux/mkswap.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config MKSWAP 9//config:config MKSWAP
10//config: bool "mkswap (5.8 kb)" 10//config: bool "mkswap (6.3 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: The mkswap utility is used to configure a file or disk partition as 13//config: The mkswap utility is used to configure a file or disk partition as
diff --git a/util-linux/more.c b/util-linux/more.c
index fafc80403..a9ea76ab4 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -14,7 +14,7 @@
14 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 14 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
15 */ 15 */
16//config:config MORE 16//config:config MORE
17//config: bool "more (6.7 kb)" 17//config: bool "more (7 kb)"
18//config: default y 18//config: default y
19//config: help 19//config: help
20//config: more is a simple utility which allows you to read text one screen 20//config: more is a simple utility which allows you to read text one screen
diff --git a/util-linux/mount.c b/util-linux/mount.c
index fa2e7b114..526b4130c 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -18,7 +18,7 @@
18// 18//
19 19
20//config:config MOUNT 20//config:config MOUNT
21//config: bool "mount (30 kb)" 21//config: bool "mount (23 kb)"
22//config: default y 22//config: default y
23//config: select PLATFORM_LINUX 23//config: select PLATFORM_LINUX
24//config: help 24//config: help
diff --git a/util-linux/mountpoint.c b/util-linux/mountpoint.c
index 6b21a5fb3..a44cf6013 100644
--- a/util-linux/mountpoint.c
+++ b/util-linux/mountpoint.c
@@ -9,7 +9,7 @@
9 * Based on sysvinit's mountpoint 9 * Based on sysvinit's mountpoint
10 */ 10 */
11//config:config MOUNTPOINT 11//config:config MOUNTPOINT
12//config: bool "mountpoint (4.5 kb)" 12//config: bool "mountpoint (4.9 kb)"
13//config: default y 13//config: default y
14//config: help 14//config: help
15//config: mountpoint checks if the directory is a mountpoint. 15//config: mountpoint checks if the directory is a mountpoint.
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
index ae8103a52..4eeaa9f3e 100644
--- a/util-linux/nsenter.c
+++ b/util-linux/nsenter.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config NSENTER 9//config:config NSENTER
10//config: bool "nsenter (8.6 kb)" 10//config: bool "nsenter (6.5 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/util-linux/pivot_root.c b/util-linux/pivot_root.c
index d6a26b912..41f29da32 100644
--- a/util-linux/pivot_root.c
+++ b/util-linux/pivot_root.c
@@ -9,7 +9,7 @@
9 * Licensed under GPLv2, see file LICENSE in this source tree. 9 * Licensed under GPLv2, see file LICENSE in this source tree.
10 */ 10 */
11//config:config PIVOT_ROOT 11//config:config PIVOT_ROOT
12//config: bool "pivot_root (898 bytes)" 12//config: bool "pivot_root (1.1 kb)"
13//config: default y 13//config: default y
14//config: select PLATFORM_LINUX 14//config: select PLATFORM_LINUX
15//config: help 15//config: help
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
index 5ec795208..70f829e7f 100644
--- a/util-linux/rdate.c
+++ b/util-linux/rdate.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */ 9 */
10//config:config RDATE 10//config:config RDATE
11//config: bool "rdate (6 kb)" 11//config: bool "rdate (5.6 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: The rdate utility allows you to synchronize the date and time of your 14//config: The rdate utility allows you to synchronize the date and time of your
diff --git a/util-linux/rdev.c b/util-linux/rdev.c
index 97279ce61..d6b515ebc 100644
--- a/util-linux/rdev.c
+++ b/util-linux/rdev.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10//config:config RDEV 10//config:config RDEV
11//config: bool "rdev (1.4 kb)" 11//config: bool "rdev (1.8 kb)"
12//config: default y 12//config: default y
13//config: help 13//config: help
14//config: Print the device node associated with the filesystem mounted at '/'. 14//config: Print the device node associated with the filesystem mounted at '/'.
diff --git a/util-linux/readprofile.c b/util-linux/readprofile.c
index 219c0c18c..cab2c4319 100644
--- a/util-linux/readprofile.c
+++ b/util-linux/readprofile.c
@@ -32,7 +32,7 @@
32 * Paul Mundt <lethal@linux-sh.org>. 32 * Paul Mundt <lethal@linux-sh.org>.
33 */ 33 */
34//config:config READPROFILE 34//config:config READPROFILE
35//config: bool "readprofile (7.2 kb)" 35//config: bool "readprofile (7.1 kb)"
36//config: default y 36//config: default y
37//config: #select PLATFORM_LINUX 37//config: #select PLATFORM_LINUX
38//config: help 38//config: help
diff --git a/util-linux/renice.c b/util-linux/renice.c
index ee0fb3c8e..a318ffce0 100644
--- a/util-linux/renice.c
+++ b/util-linux/renice.c
@@ -18,7 +18,7 @@
18 * following IDs (if any). Multiple switches are allowed. 18 * following IDs (if any). Multiple switches are allowed.
19 */ 19 */
20//config:config RENICE 20//config:config RENICE
21//config: bool "renice (3.8 kb)" 21//config: bool "renice (4.2 kb)"
22//config: default y 22//config: default y
23//config: help 23//config: help
24//config: Renice alters the scheduling priority of one or more running 24//config: Renice alters the scheduling priority of one or more running
diff --git a/util-linux/rev.c b/util-linux/rev.c
index c90b4bbaf..31800fa51 100644
--- a/util-linux/rev.c
+++ b/util-linux/rev.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2, see file LICENSE in this source tree. 6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */ 7 */
8//config:config REV 8//config:config REV
9//config: bool "rev (4.5 kb)" 9//config: bool "rev (4.4 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: Reverse lines of a file or files. 12//config: Reverse lines of a file or files.
diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c
index 8ffa4f3a6..29c440b82 100644
--- a/util-linux/rtcwake.c
+++ b/util-linux/rtcwake.c
@@ -23,7 +23,7 @@
23 * That flag should not be needed on systems with adjtime support. 23 * That flag should not be needed on systems with adjtime support.
24 */ 24 */
25//config:config RTCWAKE 25//config:config RTCWAKE
26//config: bool "rtcwake (6.4 kb)" 26//config: bool "rtcwake (6.8 kb)"
27//config: default y 27//config: default y
28//config: select PLATFORM_LINUX 28//config: select PLATFORM_LINUX
29//config: help 29//config: help
diff --git a/util-linux/script.c b/util-linux/script.c
index aac77c3ba..4eac5e94f 100644
--- a/util-linux/script.c
+++ b/util-linux/script.c
@@ -11,7 +11,7 @@
11 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 11 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
12 */ 12 */
13//config:config SCRIPT 13//config:config SCRIPT
14//config: bool "script (8 kb)" 14//config: bool "script (8.6 kb)"
15//config: default y 15//config: default y
16//config: help 16//config: help
17//config: The script makes typescript of terminal session. 17//config: The script makes typescript of terminal session.
diff --git a/util-linux/scriptreplay.c b/util-linux/scriptreplay.c
index e3083ab93..3c032eec5 100644
--- a/util-linux/scriptreplay.c
+++ b/util-linux/scriptreplay.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config SCRIPTREPLAY 9//config:config SCRIPTREPLAY
10//config: bool "scriptreplay (2.6 kb)" 10//config: bool "scriptreplay (2.4 kb)"
11//config: default y 11//config: default y
12//config: help 12//config: help
13//config: This program replays a typescript, using timing information 13//config: This program replays a typescript, using timing information
diff --git a/util-linux/setarch.c b/util-linux/setarch.c
index 520865318..57051a683 100644
--- a/util-linux/setarch.c
+++ b/util-linux/setarch.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config SETARCH 9//config:config SETARCH
10//config: bool "setarch (3.4 kb)" 10//config: bool "setarch (3.6 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
@@ -17,14 +17,14 @@
17//config: (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...). 17//config: (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
18//config: 18//config:
19//config:config LINUX32 19//config:config LINUX32
20//config: bool "linux32 (3.2 kb)" 20//config: bool "linux32 (3.3 kb)"
21//config: default y 21//config: default y
22//config: select PLATFORM_LINUX 22//config: select PLATFORM_LINUX
23//config: help 23//config: help
24//config: Alias to "setarch linux32". 24//config: Alias to "setarch linux32".
25//config: 25//config:
26//config:config LINUX64 26//config:config LINUX64
27//config: bool "linux64 (3.2 kb)" 27//config: bool "linux64 (3.3 kb)"
28//config: default y 28//config: default y
29//config: select PLATFORM_LINUX 29//config: select PLATFORM_LINUX
30//config: help 30//config: help
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c
index af079fae8..b69b8cbb6 100644
--- a/util-linux/setpriv.c
+++ b/util-linux/setpriv.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config SETPRIV 9//config:config SETPRIV
10//config: bool "setpriv (3.4 kb)" 10//config: bool "setpriv (6.6 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: select LONG_OPTS 13//config: select LONG_OPTS
diff --git a/util-linux/setsid.c b/util-linux/setsid.c
index 8385a9115..cdad8c1d3 100644
--- a/util-linux/setsid.c
+++ b/util-linux/setsid.c
@@ -14,7 +14,7 @@
14 * - busyboxed 14 * - busyboxed
15 */ 15 */
16//config:config SETSID 16//config:config SETSID
17//config: bool "setsid (3.9 kb)" 17//config: bool "setsid (3.6 kb)"
18//config: default y 18//config: default y
19//config: help 19//config: help
20//config: setsid runs a program in a new session 20//config: setsid runs a program in a new session
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index f432ce180..567869cc7 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config SWAPON 9//config:config SWAPON
10//config: bool "swapon (4.9 kb)" 10//config: bool "swapon (15 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
@@ -34,7 +34,7 @@
34//config: Enable support for setting swap device priority in swapon. 34//config: Enable support for setting swap device priority in swapon.
35//config: 35//config:
36//config:config SWAPOFF 36//config:config SWAPOFF
37//config: bool "swapoff (4.3 kb)" 37//config: bool "swapoff (14 kb)"
38//config: default y 38//config: default y
39//config: select PLATFORM_LINUX 39//config: select PLATFORM_LINUX
40//config: 40//config:
diff --git a/util-linux/switch_root.c b/util-linux/switch_root.c
index 947dd0cdc..ae9d412d1 100644
--- a/util-linux/switch_root.c
+++ b/util-linux/switch_root.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9//config:config SWITCH_ROOT 9//config:config SWITCH_ROOT
10//config: bool "switch_root (5.2 kb)" 10//config: bool "switch_root (5.5 kb)"
11//config: default y 11//config: default y
12//config: select PLATFORM_LINUX 12//config: select PLATFORM_LINUX
13//config: help 13//config: help
diff --git a/util-linux/taskset.c b/util-linux/taskset.c
index 67df1cb73..ed8878ad4 100644
--- a/util-linux/taskset.c
+++ b/util-linux/taskset.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config TASKSET 8//config:config TASKSET
9//config: bool "taskset (4.1 kb)" 9//config: bool "taskset (4.2 kb)"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: Retrieve or set a processes's CPU affinity. 12//config: Retrieve or set a processes's CPU affinity.
diff --git a/util-linux/uevent.c b/util-linux/uevent.c
index 7ff866cec..761743f45 100644
--- a/util-linux/uevent.c
+++ b/util-linux/uevent.c
@@ -4,7 +4,7 @@
4 * Licensed under GPLv2, see file LICENSE in this source tree. 4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */ 5 */
6//config:config UEVENT 6//config:config UEVENT
7//config: bool "uevent (3.2 kb)" 7//config: bool "uevent (3.1 kb)"
8//config: default y 8//config: default y
9//config: select PLATFORM_LINUX 9//config: select PLATFORM_LINUX
10//config: help 10//config: help
diff --git a/util-linux/umount.c b/util-linux/umount.c
index e2329f8b3..077b635c8 100644
--- a/util-linux/umount.c
+++ b/util-linux/umount.c
@@ -8,7 +8,7 @@
8 * Licensed under GPLv2, see file LICENSE in this source tree. 8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */ 9 */
10//config:config UMOUNT 10//config:config UMOUNT
11//config: bool "umount (4.5 kb)" 11//config: bool "umount (5.1 kb)"
12//config: default y 12//config: default y
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
14//config: help 14//config: help
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
index fffee28a0..61fc71197 100644
--- a/util-linux/unshare.c
+++ b/util-linux/unshare.c
@@ -7,7 +7,7 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9//config:config UNSHARE 9//config:config UNSHARE
10//config: bool "unshare (9.2 kb)" 10//config: bool "unshare (7.2 kb)"
11//config: default y 11//config: default y
12//config: depends on !NOMMU 12//config: depends on !NOMMU
13//config: select PLATFORM_LINUX 13//config: select PLATFORM_LINUX
diff --git a/util-linux/wall.c b/util-linux/wall.c
index 939736592..23fb87517 100644
--- a/util-linux/wall.c
+++ b/util-linux/wall.c
@@ -6,7 +6,7 @@
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */ 7 */
8//config:config WALL 8//config:config WALL
9//config: bool "wall (2.5 kb)" 9//config: bool "wall (2.6 kb)"
10//config: default y 10//config: default y
11//config: depends on FEATURE_UTMP 11//config: depends on FEATURE_UTMP
12//config: help 12//config: help