summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Libc_version1
-rw-r--r--Make.defs16
-rw-r--r--Makefile131
-rw-r--r--README254
-rw-r--r--README.ash115
-rw-r--r--as/6809/const.h501
-rw-r--r--as/Makefile46
-rw-r--r--as/TODO1
-rw-r--r--as/address.h30
-rw-r--r--as/as.c300
-rw-r--r--as/asm/calljmp.asm70
-rw-r--r--as/asm/ea.asm109
-rw-r--r--as/asm/each.asm145
-rw-r--r--as/asm/easlow.as1219
-rw-r--r--as/asm/f.asm114
-rw-r--r--as/asm/fadd.asm271
-rw-r--r--as/asm/farcall.asm10
-rw-r--r--as/asm/group1.asm31
-rw-r--r--as/asm/group6.asm24
-rw-r--r--as/asm/group7.asm34
-rw-r--r--as/asm/imul.asm33
-rw-r--r--as/asm/incdec.asm83
-rw-r--r--as/asm/inher.asm127
-rw-r--r--as/asm/inout.asm25
-rw-r--r--as/asm/movspec.asm246
-rw-r--r--as/asm/pushpop.asm86
-rw-r--r--as/asm/seg.asm6
-rw-r--r--as/asm/shdouble.asm34
-rw-r--r--as/asm/shift.asm119
-rw-r--r--as/asm/summary.as385
-rw-r--r--as/asm/xchg.asm103
-rw-r--r--as/assemble.c309
-rw-r--r--as/bin/calljmp.binbin0 -> 146 bytes
-rw-r--r--as/bin/ea.binbin0 -> 441 bytes
-rw-r--r--as/bin/each.binbin0 -> 657 bytes
-rw-r--r--as/bin/f.binbin0 -> 181 bytes
-rw-r--r--as/bin/fadd.binbin0 -> 605 bytes
-rw-r--r--as/bin/farcall.binbin0 -> 41 bytes
-rw-r--r--as/bin/group1.binbin0 -> 115 bytes
-rw-r--r--as/bin/group6.binbin0 -> 38 bytes
-rw-r--r--as/bin/group7.binbin0 -> 53 bytes
-rw-r--r--as/bin/imul.binbin0 -> 119 bytes
-rw-r--r--as/bin/incdec.binbin0 -> 116 bytes
-rw-r--r--as/bin/inher.binbin0 -> 129 bytes
-rw-r--r--as/bin/inout.binbin0 -> 54 bytes
-rw-r--r--as/bin/movspec.binbin0 -> 682 bytes
-rw-r--r--as/bin/pushpop.binbin0 -> 128 bytes
-rw-r--r--as/bin/seg.binbin0 -> 16 bytes
-rw-r--r--as/bin/shdouble.binbin0 -> 61 bytes
-rw-r--r--as/bin/shift.binbin0 -> 276 bytes
-rw-r--r--as/bin/xchg.binbin0 -> 234 bytes
-rw-r--r--as/byteord.h18
-rwxr-xr-xas/chk9
-rw-r--r--as/const.h409
-rw-r--r--as/error.c105
-rw-r--r--as/express.c382
-rw-r--r--as/file.h12
-rw-r--r--as/flag.h5
-rw-r--r--as/genbin.c220
-rw-r--r--as/genlist.c461
-rw-r--r--as/genobj.c680
-rw-r--r--as/gensym.c210
-rw-r--r--as/globvar.h93
-rw-r--r--as/macro.c174
-rw-r--r--as/macro.h10
-rw-r--r--as/mops.c2835
-rw-r--r--as/obj1/calljmp.objbin0 -> 200 bytes
-rw-r--r--as/obj1/ea.objbin0 -> 472 bytes
-rw-r--r--as/obj1/each.objbin0 -> 715 bytes
-rw-r--r--as/obj1/f.objbin0 -> 207 bytes
-rw-r--r--as/obj1/fadd.objbin0 -> 1069 bytes
-rw-r--r--as/obj1/farcall.objbin0 -> 71 bytes
-rw-r--r--as/obj1/group1.objbin0 -> 145 bytes
-rw-r--r--as/obj1/group6.objbin0 -> 67 bytes
-rw-r--r--as/obj1/group7.objbin0 -> 82 bytes
-rw-r--r--as/obj1/imul.objbin0 -> 147 bytes
-rw-r--r--as/obj1/incdec.objbin0 -> 146 bytes
-rw-r--r--as/obj1/inher.objbin0 -> 158 bytes
-rw-r--r--as/obj1/inout.objbin0 -> 82 bytes
-rw-r--r--as/obj1/movspec.objbin0 -> 722 bytes
-rw-r--r--as/obj1/pushpop.objbin0 -> 159 bytes
-rw-r--r--as/obj1/seg.objbin0 -> 42 bytes
-rw-r--r--as/obj1/shdouble.objbin0 -> 106 bytes
-rw-r--r--as/obj1/shift.objbin0 -> 308 bytes
-rw-r--r--as/obj1/xchg.objbin0 -> 264 bytes
-rw-r--r--as/opcode.h157
-rw-r--r--as/pops.c1048
-rw-r--r--as/proto.h218
-rw-r--r--as/readsrc.c340
-rw-r--r--as/scan.c247
-rw-r--r--as/scan.h12
-rw-r--r--as/source.h4
-rw-r--r--as/table.c944
-rw-r--r--as/todo14
-rw-r--r--as/type.h167
-rw-r--r--bcc/6809/const.h52
-rw-r--r--bcc/Makefile43
-rw-r--r--bcc/align.h16
-rw-r--r--bcc/assign.c387
-rw-r--r--bcc/bcc-cc1.c25
-rw-r--r--bcc/bcc.bugs169
-rw-r--r--bcc/bcc.c961
-rw-r--r--bcc/bcc.c.gnu983
-rw-r--r--bcc/bcc.doc177
-rw-r--r--bcc/byteord.h13
-rw-r--r--bcc/codefrag.c1843
-rw-r--r--bcc/condcode.h16
-rw-r--r--bcc/const.h52
-rw-r--r--bcc/debug.c202
-rw-r--r--bcc/declare.c1124
-rw-r--r--bcc/express.c466
-rw-r--r--bcc/exptree.c1087
-rw-r--r--bcc/floatop.c173
-rw-r--r--bcc/function.c413
-rw-r--r--bcc/gencode.c736
-rw-r--r--bcc/gencode.h101
-rw-r--r--bcc/genloads.c1255
-rw-r--r--bcc/glogcode.c560
-rw-r--r--bcc/hardop.c510
-rw-r--r--bcc/input.c771
-rw-r--r--bcc/input.h37
-rw-r--r--bcc/label.c429
-rw-r--r--bcc/label.h24
-rw-r--r--bcc/loadexp.c180
-rw-r--r--bcc/longop.c169
-rw-r--r--bcc/misc/sformat56
-rw-r--r--bcc/misc/test/8queens.pas33
-rw-r--r--bcc/misc/test/8queens.t74
-rw-r--r--bcc/misc/test/atol.t29
-rw-r--r--bcc/misc/test/bigsievec.t29
-rw-r--r--bcc/misc/test/bt.t373
-rw-r--r--bcc/misc/test/cast.t144
-rw-r--r--bcc/misc/test/cast1.t144
-rw-r--r--bcc/misc/test/castest.t74
-rw-r--r--bcc/misc/test/ctype.t38
-rw-r--r--bcc/misc/test/error.t78
-rw-r--r--bcc/misc/test/extern.t236
-rw-r--r--bcc/misc/test/hilbert.t169
-rw-r--r--bcc/misc/test/longtest.c24
-rw-r--r--bcc/misc/test/longtest.dat15
-rwxr-xr-xbcc/misc/test/longtest.mak3
-rwxr-xr-xbcc/misc/test/longtest.sh4
-rw-r--r--bcc/misc/test/miniltest.t72
-rw-r--r--bcc/misc/test/op1.t120
-rw-r--r--bcc/misc/test/opcmp.t106
-rw-r--r--bcc/misc/test/oplong.t264
-rw-r--r--bcc/misc/test/opplus.t122
-rw-r--r--bcc/misc/test/opsoft.t259
-rw-r--r--bcc/misc/test/puzzle.t178
-rw-r--r--bcc/misc/test/sierpin.t123
-rw-r--r--bcc/misc/test/sievec.t28
-rw-r--r--bcc/misc/test/sievecp.t45
-rw-r--r--bcc/misc/test/sievei.t28
-rw-r--r--bcc/misc/test/sort.t104
-rw-r--r--bcc/misc/test/stdio.t87
-rw-r--r--bcc/os.h78
-rw-r--r--bcc/output.c813
-rw-r--r--bcc/output.h14
-rw-r--r--bcc/parse.h19
-rw-r--r--bcc/preproc.c944
-rw-r--r--bcc/preserve.c216
-rw-r--r--bcc/proto.h397
-rw-r--r--bcc/reg.h139
-rw-r--r--bcc/sc.h27
-rw-r--r--bcc/scan.c806
-rw-r--r--bcc/scan.h201
-rw-r--r--bcc/sizes.h50
-rw-r--r--bcc/softop.c225
-rw-r--r--bcc/state.c793
-rw-r--r--bcc/table.c668
-rw-r--r--bcc/table.h71
-rw-r--r--bcc/tags341
-rw-r--r--bcc/type.c203
-rw-r--r--bcc/type.h98
-rw-r--r--bcc/types.h206
-rw-r--r--dis88/Makefile51
-rw-r--r--dis88/README90
l---------dis88/a.out.h1
-rw-r--r--dis88/ansi.h58
-rw-r--r--dis88/dis.h (renamed from dis.h)9
-rw-r--r--dis88/dis88.1147
-rw-r--r--dis88/disfp.c (renamed from disfp.c)0
-rw-r--r--dis88/dishand.c (renamed from dishand.c)10
-rw-r--r--dis88/dismain.c (renamed from dismain.c)27
-rw-r--r--dis88/disrel.c (renamed from disrel.c)0
-rw-r--r--dis88/distabs.c (renamed from distabs.c)8
-rw-r--r--dis88/old_a.out.h117
-rw-r--r--elksemu/Kernel_patch19
-rw-r--r--elksemu/Makefile29
-rw-r--r--elksemu/V-files.tarbin0 -> 10240 bytes
-rw-r--r--elksemu/Version1
-rw-r--r--elksemu/elks.c258
-rw-r--r--elksemu/elks.h96
-rw-r--r--elksemu/elks_signal.c36
-rw-r--r--elksemu/elks_sys.c723
-rw-r--r--ld/6809/config.h28
-rw-r--r--ld/Makefile29
-rw-r--r--ld/README.199417
-rw-r--r--ld/a.out.h115
-rw-r--r--ld/align.h10
-rw-r--r--ld/bugs17
-rw-r--r--ld/byteord.h20
-rw-r--r--ld/config.h28
-rw-r--r--ld/const.h14
-rw-r--r--ld/dumps.c68
-rw-r--r--ld/globvar.h14
-rw-r--r--ld/include/fcntl.h2
-rw-r--r--ld/io.c607
-rw-r--r--ld/ld.c191
-rw-r--r--ld/obj.h54
-rw-r--r--ld/readobj.c373
-rw-r--r--ld/table.c206
-rw-r--r--ld/type.h163
-rw-r--r--ld/typeconv.c536
-rw-r--r--ld/writebin.c997
-rw-r--r--libc-0.0.4/COPYING481
-rw-r--r--libc-0.0.4/Changes127
-rw-r--r--libc-0.0.4/Contributors8
-rw-r--r--libc-0.0.4/KERNEL37
-rw-r--r--libc-0.0.4/MAGIC23
-rw-r--r--libc-0.0.4/Make.defs64
-rw-r--r--libc-0.0.4/Makefile71
-rwxr-xr-xlibc-0.0.4/New_subdir67
-rw-r--r--libc-0.0.4/Pre_main55
-rw-r--r--libc-0.0.4/README70
-rw-r--r--libc-0.0.4/TODO54
-rw-r--r--libc-0.0.4/bcc/Config2
-rw-r--r--libc-0.0.4/bcc/Makefile58
-rw-r--r--libc-0.0.4/bcc/__ldivmod.c195
-rw-r--r--libc-0.0.4/bcc/alloca.c50
-rw-r--r--libc-0.0.4/bcc/bcc_bsw.c487
-rw-r--r--libc-0.0.4/bcc/bcc_int.c162
-rw-r--r--libc-0.0.4/bcc/bcc_io.c189
-rw-r--r--libc-0.0.4/bcc/bcc_long.c479
-rw-r--r--libc-0.0.4/bcc/heap.c116
-rw-r--r--libc-0.0.4/crt0.c57
-rw-r--r--libc-0.0.4/crt0.obin0 -> 125 bytes
-rw-r--r--libc-0.0.4/error/Config2
-rw-r--r--libc-0.0.4/error/Makefile17
-rw-r--r--libc-0.0.4/error/README10
-rw-r--r--libc-0.0.4/error/__assert.c28
-rw-r--r--libc-0.0.4/error/error.c57
-rw-r--r--libc-0.0.4/error/liberror.txt121
-rw-r--r--libc-0.0.4/error/perror.c19
-rw-r--r--libc-0.0.4/error/sys_errlist.c75
-rw-r--r--libc-0.0.4/error/sys_siglist.c38
-rw-r--r--libc-0.0.4/grp/Makefile41
-rw-r--r--libc-0.0.4/grp/__getgrent.c168
-rw-r--r--libc-0.0.4/grp/config-grp.h65
-rw-r--r--libc-0.0.4/grp/fgetgrent.c35
-rw-r--r--libc-0.0.4/grp/getgrgid.c48
-rw-r--r--libc-0.0.4/grp/getgrnam.c51
-rw-r--r--libc-0.0.4/grp/grent.c57
-rw-r--r--libc-0.0.4/grp/initgroups.c80
-rw-r--r--libc-0.0.4/grp/test_grp.c107
-rw-r--r--libc-0.0.4/include/a.out.h115
-rw-r--r--libc-0.0.4/include/ar.h18
-rw-r--r--libc-0.0.4/include/assert.h23
-rw-r--r--libc-0.0.4/include/ctype.h37
-rw-r--r--libc-0.0.4/include/dirent.h45
-rw-r--r--libc-0.0.4/include/dos.h34
-rw-r--r--libc-0.0.4/include/errno.h25
-rw-r--r--libc-0.0.4/include/fcntl.h20
-rw-r--r--libc-0.0.4/include/features.h36
-rw-r--r--libc-0.0.4/include/getopt.h17
-rw-r--r--libc-0.0.4/include/grp.h37
-rw-r--r--libc-0.0.4/include/limits.h33
l---------libc-0.0.4/include/linuxmt1
-rw-r--r--libc-0.0.4/include/malloc.h29
-rw-r--r--libc-0.0.4/include/memory.h1
-rw-r--r--libc-0.0.4/include/paths.h20
-rw-r--r--libc-0.0.4/include/pwd.h40
-rw-r--r--libc-0.0.4/include/regexp.h21
-rw-r--r--libc-0.0.4/include/regmagic.h5
-rw-r--r--libc-0.0.4/include/search.h94
-rw-r--r--libc-0.0.4/include/setjmp.h26
-rw-r--r--libc-0.0.4/include/sgtty.h1
-rw-r--r--libc-0.0.4/include/signal.h85
-rw-r--r--libc-0.0.4/include/stdarg.h38
-rw-r--r--libc-0.0.4/include/stddef.h26
-rw-r--r--libc-0.0.4/include/stdio.h125
-rw-r--r--libc-0.0.4/include/stdlib.h30
-rw-r--r--libc-0.0.4/include/string.h52
-rw-r--r--libc-0.0.4/include/strings.h1
-rw-r--r--libc-0.0.4/include/sys/cdefs.h33
-rw-r--r--libc-0.0.4/include/sys/errno.h1
-rw-r--r--libc-0.0.4/include/sys/fcntl.h1
-rw-r--r--libc-0.0.4/include/sys/file.h35
-rw-r--r--libc-0.0.4/include/sys/ioctl.h9
-rw-r--r--libc-0.0.4/include/sys/param.h18
-rw-r--r--libc-0.0.4/include/sys/signal.h1
-rw-r--r--libc-0.0.4/include/sys/stat.h27
-rw-r--r--libc-0.0.4/include/sys/types.h2
-rw-r--r--libc-0.0.4/include/sys/wait.h2
-rw-r--r--libc-0.0.4/include/termcap.h21
-rw-r--r--libc-0.0.4/include/termio.h1
-rw-r--r--libc-0.0.4/include/termios.h24
-rw-r--r--libc-0.0.4/include/time.h61
-rw-r--r--libc-0.0.4/include/unistd.h34
-rw-r--r--libc-0.0.4/include/utime.h15
-rw-r--r--libc-0.0.4/include/utmp.h48
-rw-r--r--libc-0.0.4/include/varargs.h12
-rw-r--r--libc-0.0.4/kinclude/Config1
-rw-r--r--libc-0.0.4/kinclude/arch/errno.h127
-rw-r--r--libc-0.0.4/kinclude/arch/ioctl.h9
-rw-r--r--libc-0.0.4/kinclude/arch/types.h48
-rw-r--r--libc-0.0.4/kinclude/linuxmt/errno.h1
-rw-r--r--libc-0.0.4/kinclude/linuxmt/fcntl.h70
-rw-r--r--libc-0.0.4/kinclude/linuxmt/ioctl.h1
-rw-r--r--libc-0.0.4/kinclude/linuxmt/stat.h55
-rw-r--r--libc-0.0.4/kinclude/linuxmt/termios.h258
-rw-r--r--libc-0.0.4/kinclude/linuxmt/types.h31
-rw-r--r--libc-0.0.4/libc.abin0 -> 65272 bytes
-rw-r--r--libc-0.0.4/malloc1/Config1
-rw-r--r--libc-0.0.4/malloc1/Makefile24
-rw-r--r--libc-0.0.4/malloc1/README9
-rw-r--r--libc-0.0.4/malloc1/malloc.c540
-rw-r--r--libc-0.0.4/malloc1/malloc.h29
-rw-r--r--libc-0.0.4/malloc2/Config1
-rw-r--r--libc-0.0.4/malloc2/README19
-rw-r--r--libc-0.0.4/malloc2/makefile23
-rw-r--r--libc-0.0.4/malloc2/malloc.c127
-rw-r--r--libc-0.0.4/malloc2/malloc.h21
-rw-r--r--libc-0.0.4/malloc2/stack.c10
-rw-r--r--libc-0.0.4/misc/Config1
-rw-r--r--libc-0.0.4/misc/Makefile45
-rw-r--r--libc-0.0.4/misc/aliases.c109
-rw-r--r--libc-0.0.4/misc/atexit.c102
-rw-r--r--libc-0.0.4/misc/atoi.c24
-rw-r--r--libc-0.0.4/misc/atol.c24
-rw-r--r--libc-0.0.4/misc/bsearch.c46
-rw-r--r--libc-0.0.4/misc/cputype.c344
-rw-r--r--libc-0.0.4/misc/ctype.c68
-rw-r--r--libc-0.0.4/misc/getenv.c26
-rw-r--r--libc-0.0.4/misc/getopt.c122
-rw-r--r--libc-0.0.4/misc/itoa.c24
-rw-r--r--libc-0.0.4/misc/lsearch.c47
-rw-r--r--libc-0.0.4/misc/ltoa.c37
-rw-r--r--libc-0.0.4/misc/ltostr.c43
-rw-r--r--libc-0.0.4/misc/popen.c42
-rw-r--r--libc-0.0.4/misc/putenv.c56
-rw-r--r--libc-0.0.4/misc/qsort.c166
-rw-r--r--libc-0.0.4/misc/rand.c61
-rw-r--r--libc-0.0.4/misc/strtod.c96
-rw-r--r--libc-0.0.4/misc/strtol.c106
-rw-r--r--libc-0.0.4/misc/system.c49
-rw-r--r--libc-0.0.4/msdos/Config1
-rw-r--r--libc-0.0.4/msdos/Makefile36
-rw-r--r--libc-0.0.4/msdos/TODO8
-rw-r--r--libc-0.0.4/msdos/i86.c163
-rw-r--r--libc-0.0.4/msdos/msdos.c540
-rw-r--r--libc-0.0.4/pwd/Config1
-rw-r--r--libc-0.0.4/pwd/Makefile40
-rw-r--r--libc-0.0.4/pwd/__getpwent.c152
-rw-r--r--libc-0.0.4/pwd/fgetpwent.c35
-rw-r--r--libc-0.0.4/pwd/getpw.c51
-rw-r--r--libc-0.0.4/pwd/getpwnam.c52
-rw-r--r--libc-0.0.4/pwd/getpwuid.c44
-rw-r--r--libc-0.0.4/pwd/putpwent.c39
-rw-r--r--libc-0.0.4/pwd/pwent.c62
-rwxr-xr-xlibc-0.0.4/pwd/test_pwdbin0 -> 6436 bytes
-rw-r--r--libc-0.0.4/pwd/test_pwd.c91
-rw-r--r--libc-0.0.4/regexp/Config1
-rw-r--r--libc-0.0.4/regexp/Makefile28
-rw-r--r--libc-0.0.4/regexp/Makefile.org63
-rw-r--r--libc-0.0.4/regexp/README84
-rw-r--r--libc-0.0.4/regexp/README.rdb6
-rw-r--r--libc-0.0.4/regexp/patch.132
-rw-r--r--libc-0.0.4/regexp/patch.227
-rw-r--r--libc-0.0.4/regexp/patch.346
-rw-r--r--libc-0.0.4/regexp/patch.465
-rw-r--r--libc-0.0.4/regexp/regerror.c14
-rw-r--r--libc-0.0.4/regexp/regexp.3176
-rw-r--r--libc-0.0.4/regexp/regexp.c1213
-rw-r--r--libc-0.0.4/regexp/regexp.h21
-rw-r--r--libc-0.0.4/regexp/regmagic.h5
-rw-r--r--libc-0.0.4/regexp/regsub.c82
-rw-r--r--libc-0.0.4/regexp/tests127
-rw-r--r--libc-0.0.4/regexp/timer.c182
-rw-r--r--libc-0.0.4/regexp/try.c238
-rw-r--r--libc-0.0.4/stdio1/BUGS15
-rw-r--r--libc-0.0.4/stdio1/Config3
-rw-r--r--libc-0.0.4/stdio1/NOTICE17
-rw-r--r--libc-0.0.4/stdio1/README13
-rw-r--r--libc-0.0.4/stdio1/TODO33
-rw-r--r--libc-0.0.4/stdio1/__ffillbuf.c55
-rw-r--r--libc-0.0.4/stdio1/__stdio_init.c66
-rw-r--r--libc-0.0.4/stdio1/fclose.c41
-rw-r--r--libc-0.0.4/stdio1/fcntl.h72
-rw-r--r--libc-0.0.4/stdio1/fflush.c36
-rw-r--r--libc-0.0.4/stdio1/fgetc.c39
-rw-r--r--libc-0.0.4/stdio1/fgets.c50
-rw-r--r--libc-0.0.4/stdio1/fopen.c80
-rw-r--r--libc-0.0.4/stdio1/fputc.c53
-rw-r--r--libc-0.0.4/stdio1/fputs.c32
-rw-r--r--libc-0.0.4/stdio1/idealgetline.c67
-rw-r--r--libc-0.0.4/stdio1/libc.a0
-rw-r--r--libc-0.0.4/stdio1/makefile36
-rw-r--r--libc-0.0.4/stdio1/old_printf.c230
-rw-r--r--libc-0.0.4/stdio1/printf.c649
-rw-r--r--libc-0.0.4/stdio1/puts.c26
-rw-r--r--libc-0.0.4/stdio1/scanf.c151
-rw-r--r--libc-0.0.4/stdio1/stdio.h135
-rwxr-xr-xlibc-0.0.4/stdio1/test.sh12
-rw-r--r--libc-0.0.4/stdio2/Config4
-rw-r--r--libc-0.0.4/stdio2/Funcs43
-rw-r--r--libc-0.0.4/stdio2/Makefile39
-rw-r--r--libc-0.0.4/stdio2/printf.c362
-rw-r--r--libc-0.0.4/stdio2/scanf.c511
-rw-r--r--libc-0.0.4/stdio2/stdio.c738
-rw-r--r--libc-0.0.4/stdio2/stdio.c.old730
-rw-r--r--libc-0.0.4/stdio2/stdio.h125
-rw-r--r--libc-0.0.4/string/Config1
-rw-r--r--libc-0.0.4/string/Makefile31
-rw-r--r--libc-0.0.4/string/strcasecmp.c26
-rw-r--r--libc-0.0.4/string/strcspn.c32
-rw-r--r--libc-0.0.4/string/string.c667
-rw-r--r--libc-0.0.4/string/string.h52
-rw-r--r--libc-0.0.4/string/strncasecmp.c28
-rw-r--r--libc-0.0.4/string/strpbrk.c21
-rw-r--r--libc-0.0.4/string/strsep.c38
-rw-r--r--libc-0.0.4/string/strspn.c44
-rw-r--r--libc-0.0.4/string/strstr.c54
-rw-r--r--libc-0.0.4/string/strtok.c71
-rw-r--r--libc-0.0.4/syscall/Config1
-rw-r--r--libc-0.0.4/syscall/Makefile45
-rw-r--r--libc-0.0.4/syscall/TODO7
-rw-r--r--libc-0.0.4/syscall/dirent.c84
-rw-r--r--libc-0.0.4/syscall/execve.c114
-rw-r--r--libc-0.0.4/syscall/getinfo.c32
-rw-r--r--libc-0.0.4/syscall/mksyscall303
-rw-r--r--libc-0.0.4/syscall/setjmp.c50
-rw-r--r--libc-0.0.4/syscall/signal.c94
-rw-r--r--libc-0.0.4/syscall/syscall.dat148
-rw-r--r--libc-0.0.4/syscall/syslibc.c330
-rw-r--r--libc-0.0.4/termios/Config1
-rw-r--r--libc-0.0.4/termios/Makefile27
-rw-r--r--libc-0.0.4/termios/README7
-rw-r--r--libc-0.0.4/termios/termios.c142
-rw-r--r--libc-0.0.4/tests/Config2
-rw-r--r--libc-0.0.4/tests/README19
-rw-r--r--libc-0.0.4/tests/Real_make19
-rw-r--r--libc-0.0.4/tests/compr.c383
-rw-r--r--libc-0.0.4/tests/env.c82
-rw-r--r--libc-0.0.4/tests/ft.c1217
-rwxr-xr-xlibc-0.0.4/tests/grab.c80
-rw-r--r--libc-0.0.4/tests/hd.c90
-rw-r--r--libc-0.0.4/tests/line2.c15
-rw-r--r--libc-0.0.4/tests/lines.c36
-rwxr-xr-xlibc-0.0.4/tests/ls.c1049
-rw-r--r--libc-0.0.4/tests/makefile17
-rw-r--r--libc-0.0.4/tests/ouch.c27
-rw-r--r--libc-0.0.4/tests/rand.c16
-rw-r--r--libc-0.0.4/tests/size.c51
-rw-r--r--libc-0.0.4/tests/sync.c1
-rw-r--r--libc-0.0.4/tests/ucomp.c108
-rw-r--r--libc-0.0.4/tests/wc.c133
-rw-r--r--tests/Makefile23
-rw-r--r--unproto/Makefile97
-rw-r--r--unproto/README130
-rw-r--r--unproto/Shar.Headers50
-rw-r--r--unproto/cpp.sh9
-rw-r--r--unproto/error.c78
-rw-r--r--unproto/error.h4
-rw-r--r--unproto/example.c140
-rw-r--r--unproto/example.out173
-rw-r--r--unproto/stdarg.h38
-rw-r--r--unproto/symbol.c161
-rw-r--r--unproto/symbol.h11
-rw-r--r--unproto/tok_class.c180
-rw-r--r--unproto/tok_io.c464
-rw-r--r--unproto/tok_pool.c104
-rw-r--r--unproto/token.h47
-rw-r--r--unproto/unproto.179
-rw-r--r--unproto/unproto.c749
-rw-r--r--unproto/varargs.c32
-rw-r--r--unproto/vstring.c91
-rw-r--r--unproto/vstring.h14
478 files changed, 65918 insertions, 296 deletions
diff --git a/Libc_version b/Libc_version
new file mode 100644
index 0000000..81340c7
--- /dev/null
+++ b/Libc_version
@@ -0,0 +1 @@
+0.0.4
diff --git a/Make.defs b/Make.defs
new file mode 100644
index 0000000..0297154
--- /dev/null
+++ b/Make.defs
@@ -0,0 +1,16 @@
+
+# WALL =-Wall -Wtraditional -Wshadow -Wid-clash-14 -Wpointer-arith \
+# -Wcast-qual -Wcast-align -Wconversion -Waggregate-return \
+# -Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls \
+# -Wnested-externs -Winline
+
+# unproto is yukky
+WALL=-Wno-comment
+CCFLAGS =-Wall $(WALL) -O2 -fno-strength-reduce
+LDFLAGS =-s
+
+BCCHOME =/usr/bcc
+LIBDIR =$(BCCHOME)/lib/bcc
+BINDIR =/usr/bin
+CC =gcc
+CFLAGS =$(CCFLAGS)
diff --git a/Makefile b/Makefile
index 05d2488..b47ed39 100644
--- a/Makefile
+++ b/Makefile
@@ -1,49 +1,82 @@
-# Makefile for dis
-
-# @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01
-# Makefile for 8088 symbolic disassembler
-
-# Copyright (C) 1987 G. M. Harding, all rights reserved.
-# Permission to copy and redistribute is hereby granted,
-# provided full source code, with all copyright notices,
-# accompanies any redistribution.
-
-# This Makefile automates the process of compiling and linking
-# a symbolic object-file disassembler program for the Intel
-# 8088 CPU. Relatively machine-independent code is contained in
-# the file dismain.c; lookup tables and handler routines, which
-# are by their nature machine-specific, are contained in two
-# files named distabs.c and dishand.c, respectively. (A third
-# machine-specific file, disfp.c, contains handler routines for
-# floating-point coprocessor opcodes.) A header file, dis.h,
-# attempts to mediate between the machine-specific and machine-
-# independent portions of the code. An attempt has been made to
-# isolate machine dependencies and to deal with them in fairly
-# straightforward ways. Thus, it should be possible to target a
-# different CPU by rewriting the handler routines and changing
-# the initialization data in the lookup tables. It should not
-# be necessary to alter the formats of the tables.
-
-CFLAGS =-O -wo
-OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o
-
-all: dis88
-
-dis88: $(OBJ)
- cc -i -o dis88 $(OBJ)
- install -S 5kw dis88
-
-install: /usr/bin/dis88
-
-/usr/bin/dis88: dis88
- install -cs -o bin dis88 $@
-
-disrel.o: disrel.c
-dismain.o: dismain.c dis.h
-distabs.o: distabs.c dis.h
-dishand.o: dishand.c dis.h
-disfp.o: disfp.c dis.h
-
-
-clean:
- rm -f *.bak *.o core dis88
+
+export TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
+
+include Make.defs
+
+PARTS= ld as unproto bcc
+TESTDIRS= tests dis88
+DISTFILES=Makefile Make.defs README README.ash Libc_version
+DISTDIRS= elksemu $(TESTDIRS)
+
+default:
+ @echo You have to do make install as root
+ @echo Or:
+ @echo
+ @echo 'make bcc'
+ @echo 'su -c "make install-bcc"'
+ @echo 'make library'
+ @echo 'su -c "make install-lib"'
+ @echo 'make elksemu'
+ @echo 'su -c "make install-emu"'
+ @echo 'make tests'
+ @echo
+
+install: install-bcc install-lib install-emu tests
+
+bcc: dummy
+ @for i in $(PARTS) ; do make -C $$i || exit 1; done
+
+clean: clean_rest
+ make -C libc realclean
+
+clean_rest: dummy
+ @for i in $(PARTS) ; do make -C $$i clean || exit 1; done
+ @for i in $(DISTDIRS) ; do make -C $$i clean || exit 1; done
+
+tests: dummy
+ @test -f $(BINDIR)/bcc -a -f $(LIBDIR)/ld86 || \
+ ( echo 'Must do "make install-bcc" first' && exit 1 )
+ @test -f $(LIBDIR)/i86/crt0.o || \
+ ( echo 'Must do "make install-lib" first' && exit 1 )
+ @for i in $(TESTDIRS) ; do make -C $$i || exit 1; done
+
+library: link_libc
+ @test -f $(BINDIR)/bcc -a -f $(LIBDIR)/ld86 || \
+ ( echo 'Must do "make install-bcc" first' && exit 1 )
+ make -C libc
+
+elksemu: dummy
+ @test -f libc/syscall/call_tab.v || \
+ ( echo 'Must do "make library" first' && exit 1 )
+ make -C elksemu
+
+install-bcc: dummy
+ @for i in $(PARTS) ; do make -C $$i install || exit 1; done
+
+install-lib: link_libc
+ @test -f $(BINDIR)/bcc -a -f $(LIBDIR)/ld86 || \
+ ( echo 'Must do "make install-bcc" first' && exit 1 )
+ make -C libc install
+
+install-emu: dummy
+ @test -f libc/syscall/call_tab.v || \
+ ( echo 'Must do "make library" first' && exit 1 )
+ make -C elksemu install
+
+link_libc: dummy
+ @if [ -f Libc_version ] ; then \
+ rm -f libc ; ln -fs libc-`cat Libc_version` libc ; fi
+
+distribution: clean_rest
+ -rm -f libc
+ make -C libc dist_ver
+ tar xzf libc-8086-`cat Libc_version`.tar.gz
+ tar cf /tmp/Development.tar $(DISTFILES) $(PARTS) $(DISTDIRS) \
+ libc-`cat Libc_version`
+ rm -rf libc-`cat Libc_version` Libc_version
+ rm -rf /tmp/linux-86
+ mkdir /tmp/linux-86
+ (cd /tmp/linux-86 ; tar xf ../Development.tar ; rm ../Development.tar)
+ (cd /tmp; tar czf Development.tar.gz linux-86 ; rm -rf linux-86)
+
+dummy:
diff --git a/README b/README
index a007634..d117a44 100644
--- a/README
+++ b/README
@@ -1,239 +1,31 @@
- dis88
- Beta Release
- 87/09/01
- ---
- G. M. HARDING
- POB 4142
- Santa Clara CA 95054-0142
+This is a development environment for ELKS-86
+You have to do make install as root
+Or:
- "Dis88" is a symbolic disassembler for the Intel 8088 CPU,
- designed to run under the PC/IX operating system on an IBM XT
- or fully-compatible clone. Its output is in the format of, and
- is completely compatible with, the PC/IX assembler, "as". The
- program is copyrighted by its author, but may be copied and re-
- distributed freely provided that complete source code, with all
- copyright notices, accompanies any distribution. This provision
- also applies to any modifications you may make. You are urged
- to comment such changes, giving, as a miminum, your name and
- complete address.
+$ make bcc
+$ su -c "make install-bcc"
+$ make library
+$ su -c "make install-lib"
+$ make elksemu
+$ su -c "make install-emu"
+$ make tests
- This release of the program is a beta release, which means
- that it has been extensively, but not exhaustively, tested.
- User comments, recommendations, and bug fixes are welcome. The
- principal features of the current release are:
+All from the top directory.
+Once this is done new files will be /lib/elksemu, /usr/bcc/* and /usr/bin/bcc
- (a) The ability to disassemble any file in PC/IX object
- format, making full use of symbol and relocation information if
- it is present, regardless of whether the file is executable or
- linkable, and regardless of whether it has continuous or split
- I/D space;
+The bcc command defaults to using /usr/bcc/include and /usr/bcc/lib. Beware
+that /usr/bcc/include is a symlink into this directory.
- (b) Automatic generation of synthetic labels when no sym-
- bol table is available; and
+The as86 and ld86 with this are _different_ from the ones needed for the
+linux-i386 kernel but can replace them, the kernel-i386 ones _will_ _not_
+work correctly here!
- (c) Optional output of address and object-code informa-
- tion as assembler comment text.
+To compile the various tools as Linux-8086 binaries cd into the relevent
+directory and do a "make clean ; make" from there, note you'll have to
+do "ld" before "as". Currently bcc won't work this way.
- Limitations of the current release are:
+I _strongly_ suggest you install the kernel patch in the elksemu directory
+in your Linux-i386 kernel, it makes things _far_ easier.
- (a) Numeric co-processor (i.e., 8087) mnemonics are not
- supported. Instructions for the co-processor are disassembled
- as CPU escape sequences, or as interrupts, depending on how
- they were assembled in the first place. This limitation will be
- addressed in a future release.
-
- (b) Symbolic references within the object file's data
- segment are not supported. Thus, for example, if a data segment
- location is initialized to point to a text segment address, no
- reference to a text segment symbol will be detected. This limi-
- tation is likely to remain in future releases, because object
- code does not, in most cases, contain sufficient information to
- allow meaningful interpretation of pure data. (Note, however,
- that symbolic references to the data segment from within the
- text segment are always supported.)
-
- As a final caveat, be aware that the PC/IX assembler does
- not recognize the "esc" mnemonic, even though it refers to a
- completely valid CPU operation which is documented in all the
- Intel literature. Thus, the corresponding opcodes (0xd8 through
- 0xdf) are disassembled as .byte directives. For reference, how-
- ever, the syntactically-correct "esc" instruction is output as
- a comment.
-
- To build the disassembler program, transfer all the source
- files, together with the Makefile, to a suitable (preferably
- empty) PC/IX directory. Then, simply type "make".
-
- To use dis88, place it in a directory which appears in
- your $PATH list. It may then be invoked by name from whatever
- directory you happen to be in. As a minimum, the program must
- be invoked with one command-line argument: the name of the ob-
- ject file to be disassembled. (Dis88 will complain if the file
- specified is not an object file.) Optionally, you may specify
- an output file; stdout is the default. One command-line switch
- is available: "-o", which makes the program display addresses
- and object code along with its mnemonic disassembly.
-
- The "-o" option is useful primarily for verifying the cor-
- rectness of the program's output. In particular, it may be used
- to check the accuracy of local relative jump opcodes. These
- jumps often target local labels, which are lost at assembly
- time; thus, the disassembly may contain cryptic instructions
- like "jnz .+39". As a user convenience, all relative jump and
- call opcodes are output with a comment which identifies the
- physical target address.
-
- By convention, the release level of the program as a whole
- is the SID of the file disrel.c, and this SID string appears in
- each disassembly. Release 2.1 of the program is the first beta
- release to be distributed on Usenet.
-
-
-.TH dis88 1 LOCAL
-.SH "NAME"
-dis88 \- 8088 symbolic disassembler
-.SH "SYNOPSIS"
-\fBdis88\fP [ -o ] ifile [ ofile ]
-.SH "DESCRIPTION"
-Dis88 reads ifile, which must be in PC/IX a.out format.
-It interprets the binary opcodes and data locations, and
-writes corresponding assembler source code to stdout, or
-to ofile if specified. The program's output is in the
-format of, and fully compatible with, the PC/IX assembler,
-as(1). If a symbol table is present in ifile, labels and
-references will be symbolic in the output. If the input
-file lacks a symbol table, the fact will be noted, and the
-disassembly will proceed, with the disassembler generating
-synthetic labels as needed. If the input file has split
-I/D space, or if it is executable, the disassembler will
-make all necessary adjustments in address-reference calculations.
-.PP
-If the "-o" option appears, object code will be included
-in comments during disassembly of the text segment. This
-feature is used primarily for debugging the disassembler
-itself, but may provide information of passing interest
-to users.
-.PP
-The program always outputs the current machine address
-before disassembling an opcode. If a symbol table is
-present, this address is output as an assembler comment;
-otherwise, it is incorporated into the synthetic label
-which is generated internally. Since relative jumps,
-especially short ones, may target unlabelled locations,
-the program always outputs the physical target address
-as a comment, to assist the user in following the code.
-.PP
-The text segment of an object file is always padded to
-an even machine address. In addition, if the file has
-split I/D space, the text segment will be padded to a
-paragraph boundary (i.e., an address divisible by 16).
-As a result of this padding, the disassembler may produce
-a few spurious, but harmless, instructions at the
-end of the text segment.
-.PP
-Disassembly of the data segment is a difficult matter.
-The information to which initialized data refers cannot
-be inferred from context, except in the special case
-of an external data or address reference, which will be
-reflected in the relocation table. Internal data and
-address references will already be resolved in the object file,
-and cannot be recreated. Therefore, the data
-segment is disassembled as a byte stream, with long
-stretches of null data represented by an appropriate
-".zerow" pseudo-op. This limitation notwithstanding,
-labels (as opposed to symbolic references) are always
-output at appropriate points within the data segment.
-.PP
-If disassembly of the data segment is difficult, disassembly of the
-bss segment is quite easy, because uninitialized data is all
-zero by definition. No data
-is output in the bss segment, but symbolic labels are
-output as appropriate.
-.PP
-For each opcode which takes an operand, a particular
-symbol type (text, data, or bss) is appropriate. This
-tidy correspondence is complicated somewhat, however,
-by the existence of assembler symbolic constants and
-segment override opcodes. Therefore, the disassembler's
-symbol lookup routine attempts to apply a certain amount
-of intelligence when it is asked to find a symbol. If
-it cannot match on a symbol of the preferred type, it
-may return a symbol of some other type, depending on
-preassigned (and somewhat arbitrary) rankings within
-each type. Finally, if all else fails, it returns a
-string containing the address sought as a hex constant;
-this behavior allows calling routines to use the output
-of the lookup function regardless of the success of its
-search.
-.PP
-It is worth noting, at this point, that the symbol lookup
-routine operates linearly, and has not been optimized in
-any way. Execution time is thus likely to increase
-geometrically with input file size. The disassembler is
-internally limited to 1500 symbol table entries and 1500
-relocation table entries; while these limits are generous
-(/unix, itself, has fewer than 800 symbols), they are not
-guaranteed to be adequate in all cases. If the symbol
-table or the relocation table overflows, the disassembly
-aborts.
-.PP
-Finally, users should be aware of a bug in the assembler,
-which causes it not to parse the "esc" mnemonic, even
-though "esc" is a completely legitimate opcode which is
-documented in all the Intel literature. To accommodate
-this deficiency, the disassembler translates opcodes of
-the "esc" family to .byte directives, but notes the
-correct mnemonic in a comment for reference.
-.PP
-In all cases, it should be possible to submit the output
-of the disassembler program to the assembler, and assemble
-it without error. In most cases, the resulting object
-code will be identical to the original; in any event, it
-will be functionally equivalent.
-.SH "SEE ALSO"
-adb(1), as(1), cc(1), ld(1).
-.br
-"Assembler Reference Manual" in the PC/IX Programmer's
-Guide.
-.SH "DIAGNOSTICS"
-"can't access input file" if the input file cannot be
-found, opened, or read.
-.sp
-"can't open output file" if the output file cannot be
-created.
-.sp
-"warning: host/cpu clash" if the program is run on a
-machine with a different CPU.
-.sp
-"input file not in object format" if the magic number
-does not correspond to that of a PC/IX object file.
-.sp
-"not an 8086/8088 object file" if the CPU ID of the
-file header is incorrect.
-.sp
-"reloc table overflow" if there are more than 1500
-entries in the relocation table.
-.sp
-"symbol table overflow" if there are more than 1500
-entries in the symbol table.
-.sp
-"lseek error" if the input file is corrupted (should
-never happen).
-.sp
-"warning: no symbols" if the symbol table is missing.
-.sp
-"can't reopen input file" if the input file is removed
-or altered during program execution (should never happen).
-.SH "BUGS"
-Numeric co-processor (i.e., 8087) mnemonics are not currently supported.
-Instructions for the co-processor are
-disassembled as CPU escape sequences, or as interrupts,
-depending on how they were assembled in the first place.
-.sp
-Despite the program's best efforts, a symbol retrieved
-from the symbol table may sometimes be different from
-the symbol used in the original assembly.
-.sp
-The disassembler's internal tables are of fixed size,
-and the program aborts if they overflow.
+-Rob.
diff --git a/README.ash b/README.ash
new file mode 100644
index 0000000..7c84985
--- /dev/null
+++ b/README.ash
@@ -0,0 +1,115 @@
+Building /bin/ash
+
+After doing make install for 'bcc' unpack ash-linux-0.2.tar.gz; within this
+rename builtins to builtings.in then patch with this patchfile.
+
+You'll also need to turn on 'JOBS' on line 58 of shell.h when libc can
+provide the functions.
+
+If you don't install the elksemu kernel patch you'll also have to make
+sure that the programs that are run by the make file are interpreted
+through elksemu. If it's installed you should be able just to type 'make'.
+
+diff -ru ash-linux-0.2/Makefile ash/Makefile
+--- ash-linux-0.2/Makefile Sun May 15 20:16:13 1994
++++ ash/Makefile Sat Mar 16 11:28:19 1996
+@@ -1,5 +1,9 @@
+ # Makefile,v 1.7 1993/08/09 04:58:18 mycroft Exp
+
++CC=bcc
++CFLAGS=-DSHELL
++LDFLAGS=-s
++
+ PROG= sh
+ SRCS= builtins.c cd.c dirent.c echo.c error.c eval.c exec.c expand.c \
+ input.c jobs.c mail.c main.c memalloc.c miscbltin.c \
+@@ -14,8 +18,8 @@
+
+ OBJS = $(OBJ1) $(OBJ2)
+
+-CFLAGS = -O2 -fomit-frame-pointer -m486 -DSHELL -I/usr/include/bsd -I.
+-LDFLAGS = -s -lbsd
++# CFLAGS = -O2 -fomit-frame-pointer -m486 -DSHELL -I/usr/include/bsd -I.
++# LDFLAGS = -s -lbsd
+
+ CLEANFILES =\
+ builtins.c builtins.h init.c mkinit mknodes mksyntax \
+@@ -32,7 +36,7 @@
+ token.def: mktokens
+ sh ./mktokens
+
+-builtins.h builtins.c: mkbuiltins builtins
++builtins.h builtins.c: mkbuiltins builtins.in
+ sh ./mkbuiltins
+
+ init.c: mkinit $(SRCS)
+Only in ash-linux-0.2: builtins
+Only in ash: builtins.in
+diff -ru ash-linux-0.2/main.c ash/main.c
+--- ash-linux-0.2/main.c Mon Oct 4 19:47:56 1993
++++ ash/main.c Sun Feb 18 21:57:59 1996
+@@ -321,9 +321,9 @@
+ /*
+ * Should never be called.
+ */
+-#endif
+
+ void
+ exit(exitstatus) {
+ _exit(exitstatus);
+ }
++#endif
+diff -ru ash-linux-0.2/miscbltin.c ash/miscbltin.c
+--- ash-linux-0.2/miscbltin.c Mon Oct 4 19:47:56 1993
++++ ash/miscbltin.c Sun Feb 18 21:56:14 1996
+@@ -45,6 +45,7 @@
+
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <ctype.h>
+ #include "shell.h"
+ #include "options.h"
+ #include "var.h"
+@@ -208,14 +209,18 @@
+ umask(mask);
+ } else {
+ #ifndef __linux__
++#ifndef __BCC__
+ void *set;
+ if ((set = setmode (ap)) == 0)
+ #endif
++#endif
+ error("Illegal number: %s", ap);
+
+ #ifndef __linux__
++#ifndef __BCC__
+ mask = getmode (set, ~mask & 0777);
+ umask(~mask & 0777);
++#endif
+ #endif
+ }
+ }
+diff -ru ash-linux-0.2/mkbuiltins ash/mkbuiltins
+--- ash-linux-0.2/mkbuiltins Sun Apr 18 18:37:04 1993
++++ ash/mkbuiltins Mon Feb 12 19:42:46 1996
+@@ -54,7 +54,7 @@
+ #include "builtins.h"
+
+ !
+-awk '/^[^#]/ {if('$havejobs' || $2 != "-j") print $0}' builtins |
++awk '/^[^#]/ {if('$havejobs' || $2 != "-j") print $0}' builtins.in |
+ sed 's/-j//' > $temp
+ awk '{ printf "int %s();\n", $1}' $temp
+ echo '
+diff -ru ash-linux-0.2/shell.h ash/shell.h
+--- ash-linux-0.2/shell.h Mon Oct 4 19:47:56 1993
++++ ash/shell.h Sat Mar 16 11:28:54 1996
+@@ -60,7 +60,7 @@
+ #define DIRENT 1
+ #define UDIR 0
+ #define ATTY 0
+-#define BSD
++/* #define BSD */
+ /* #define DEBUG */
+
+ #ifdef __STDC__
diff --git a/as/6809/const.h b/as/6809/const.h
new file mode 100644
index 0000000..abd9469
--- /dev/null
+++ b/as/6809/const.h
@@ -0,0 +1,501 @@
+#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */
+#define LOW_BYTE 0 /* must be changed for big-endian */
+
+/* const.h - constants for assembler */
+
+/* major switches */
+
+#undef I80386 /* generate 80386 code */
+#define MC6809 /* generate 6809 code */
+#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */
+#undef SOS_EDOS /* source OS is EDOS */
+
+/* defaults */
+
+#define DIRCHAR '/' /* character separating filename from dir */
+#define INBUFSIZE 8192
+#define SOS_EOLSTR "\012"
+
+/* defaults modified by switches */
+
+#ifdef SOS_EDOS
+# undef INBUFSIZE
+# define INBUFSIZE 512
+# undef SOS_EOLSTR
+# define SOS_EOLSTR "\015\012"
+# define STAKSIZ 256 /* table grows up to stack less this */
+#endif
+
+/* booleans */
+
+#define FALSE 0
+#define TRUE 1
+
+/* ASCII constants */
+
+#define ETB 23
+
+/* C tricks */
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+#define NULL 0
+
+/* O/S constants */
+
+#define CREAT_PERMS 0666
+#define EOF (-1)
+#define STDIN 0
+#define STDOUT 1
+
+/* register codes (internal to assembler) */
+
+#ifdef I80386
+
+/* index regs must be first */
+
+#define BPREG 0
+#define BXREG 1
+#define DIREG 2
+#define SIREG 3
+#define MAX16BITINDREG 3
+
+#define EAXREG 4
+#define EBPREG 5
+#define EBXREG 6
+#define ECXREG 7
+#define EDIREG 8
+#define EDXREG 9
+#define ESIREG 10
+#define ESPREG 11
+#define MAXINDREG 11
+
+#define AXREG 12
+#define CXREG 13
+#define DXREG 14
+#define SPREG 15
+
+#define AHREG 16
+#define ALREG 17
+#define BHREG 18
+#define BLREG 19
+#define CHREG 20
+#define CLREG 21
+#define DHREG 22
+#define DLREG 23
+
+#define CSREG 24
+#define DSREG 25
+#define ESREG 26
+#define FSREG 27
+#define GSREG 28
+#define SSREG 29
+
+#define CR0REG 30
+#define CR2REG 31
+#define CR3REG 32
+#define DR0REG 33
+#define DR1REG 34
+#define DR2REG 35
+#define DR3REG 36
+#define DR6REG 37
+#define DR7REG 38
+#define TR6REG 39
+#define TR7REG 40
+
+#define NOREG 41
+
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* index regs must be first, then PC, then other regs */
+
+#define AREG 5
+#define BREG 6
+#define CCREG 7
+#define DPREG 8
+#define DREG 9
+#define MAXINDREG 3
+#define NOREG 10
+#define PCREG 4
+#define SREG 0
+#define UREG 1
+#define XREG 2
+#define YREG 3
+
+#endif
+
+#ifdef I80386
+
+/* type and size keywords */
+
+#define BYTEOP 0
+#define DWORDOP 1
+#define FWORDOP 2
+#define FAROP 3
+#define PTROP 4
+#define PWORDOP 5
+#define QWORDOP 6
+#define TBYTEOP 7
+#define WORDOP 8
+#endif
+
+/* special chars */
+
+#define EOL 0
+#define MACROCHAR '?'
+
+/* symbol codes */
+
+/* the first 2 must be from chars in identifiers */
+#define IDENT 0
+#define INTCONST 1
+
+/* the next few are best for other possibly-multi-char tokens */
+#define ADDOP 2 /* also ++ */
+#define BINCONST 3
+#define CHARCONST 4
+#define GREATERTHAN 5 /* also >> and context-sensitive */
+#define HEXCONST 6
+#define LESSTHAN 7 /* also << and context-sensitive */
+#define SUBOP 8 /* also -- */
+#define WHITESPACE 9
+
+#define ANDOP 10
+#define COMMA 11
+#define EOLSYM 12
+#define EQOP 13
+#define IMMEDIATE 14
+#define INDIRECT 15
+#define LBRACKET 16
+#define LPAREN 17
+#define MACROARG 18
+#define NOTOP 19
+#define OROP 20
+#define OTHERSYM 21
+#define POSTINCOP 22
+#define PREDECOP 23
+#define RBRACKET 24
+#define RPAREN 25
+#define SLASH 26 /* context-sensitive */
+#define SLOP 27
+#define SROP 28
+#define STAR 29 /* context-sensitive */
+#define STRINGCONST 30
+#define COLON 31
+
+/* these are from assembler errors module */
+
+/* syntax errors */
+
+#define COMEXP 0
+#define DELEXP 1
+#define FACEXP 2
+#define IREGEXP 3
+#define LABEXP 4
+#define LPEXP 5
+#define OPEXP 6
+#define RBEXP 7
+#define REGEXP 8
+#define RPEXP 9
+#define SPEXP 10
+
+/* expression errors */
+
+#define ABSREQ 11
+#define NONIMPREQ 12
+#define RELBAD 13
+
+/* label errors */
+
+#define ILLAB 14
+#define MACUID 15
+#define MISLAB 16
+#define MNUID 17
+#define REGUID 18
+#define RELAB 19
+#define UNBLAB 20
+#define UNLAB 21
+#define VARLAB 22
+
+/* addressing errors */
+
+#define ABOUNDS 23
+#define DBOUNDS 24
+#define ILLMOD 25
+#define ILLREG 26
+
+/* control structure errors */
+
+#define ELSEBAD 27
+#define ELSEIFBAD 27
+#define ENDBBAD 28
+#define ENDIFBAD 27
+#define EOFBLOCK 29
+#define EOFIF 30
+
+#define EOFLC 31
+#define EOFMAC 32
+#define FAILERR 33
+
+/* overflow errors */
+
+#define BLOCKOV 34
+#define BWRAP 35
+#define COUNTOV 36
+#define COUNTUN 37
+#define GETOV 38
+#define IFOV 39
+
+#define LINLONG 40
+#define MACOV 41
+#define OBJSYMOV 42
+#define OWRITE 43
+#define PAROV 44
+#define SYMOV 45
+#define SYMOUTOV 46
+
+/* i/o errors */
+
+#define OBJOUT 47
+
+/* miscellaneous errors */
+
+#define CTLINS 48
+#define FURTHER 49
+#define NOIMPORT 50
+#define NOTIMPLEMENTED 51
+#define REENTER 52
+#define SEGREL 53
+
+/* warnings */
+
+#define MINWARN 54
+#define ALREADY 54
+#define SHORTB 55
+
+/* symbol table entry */
+
+ /* type entry contains following flags */
+#define ENTBIT (1<<0) /* entry point (=OBJ_N_MASK) */
+#define COMMBIT (1<<1) /* common */
+#define LABIT (1<<2) /* label (a PC location or defined by EQU) */
+#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */
+#define MACBIT (1<<4) /* macro */
+#define REDBIT (1<<5) /* redefined */
+#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */
+#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */
+
+ /* data entry contains following flags, valid */
+ /* for expressions as well as syms */
+#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT \ PAGE1 */
+#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT \ PAGE2 */
+#define REGBIT (1<<2) /* register = MNREGBIT \ REGBIT */
+#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT \ SIZEBIT */
+#define SEGM 15 /* 1st 4 bits reused for segment if !MNREGBIT */
+#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */
+#define FORBIT (1<<5) /* forward referenced */
+#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */
+#define UNDBIT (1<<7) /* undefined */
+
+/* pseudo-op routine numbers */
+/* conditionals are first, this is used to test if op is a conditional */
+
+#define ELSEOP 0
+#define ELSEIFOP 1
+#define ELSEIFCOP 2
+#define ENDIFOP 3
+#define IFOP 4
+#define IFCOP 5
+#define MAXCOND 6 /* limit of conditionals */
+
+#define BLOCKOP 6
+#define COMMOP 7
+#define ENDOP 8
+#define ENDBOP 9
+#define ENTEROP 10
+#define ENTRYOP 11
+#define EQUOP 12
+#define EXPORTOP 13
+#define FAILOP 14
+#define FCBOP 15
+#define FCCOP 16
+#define FDBOP 17
+#define GETOP 18
+#define IDENTOP 19
+#define IMPORTOP 20
+#define _LISTOP 21
+#define LOCOP 22
+#define _MACLISTOP 23
+#define MACROOP 24
+#define _MAPOP 25
+#define ORGOP 26
+#define RMBOP 27
+#define SETOP 28
+#define SETDPOP 29
+#define _WARNOP 30
+
+#ifdef I80386
+
+/* further pseudo-ops */
+
+#define BSSOP 31
+#define COMMOP1 32
+#define DATAOP 33
+#define TEXTOP 34
+#define USE16OP 35
+#define USE32OP 36
+
+/* machine-op routine numbers */
+
+#define ARPL 37
+#define BCC 38
+#define BOUND 39
+#define CALL 40
+#define DIVMUL 41
+#define ENTER 42
+#define GROUP1 43
+#define GROUP2 44
+#define GROUP6 45
+#define GROUP7 46
+#define GROUP8 47
+#define GvEv 48
+#define IMUL 49
+#define IN 50
+#define INCDEC 51
+#define INHER 52
+#define INHER16 53
+#define INHER32 54
+#define INHER_A 55
+#define INT 56
+#define JCC 57
+#define JCXZ 58
+#define LEA 59
+#define LOAD_FULL_POINTER 60
+#define MOV 61
+#define MOVX 62
+#define NEGNOT 63
+#define OUT 64
+#define PUSHPOP 65
+#define RET 66
+#define RETF 67
+#define SEG 68
+#define SETCC 69
+#define SH_DOUBLE 70
+#define TEST 71
+#define XCHG 72
+
+/* further pseudo-ops */
+
+#define BLKWOP 73
+#define EVENOP 74
+#define FQBOP 75
+#define ALIGNOP 76
+
+/* further machine-ops */
+
+#define CALLI 77
+
+/* yet further pseudo-ops */
+
+#define LCOMMOP 78
+#define LCOMMOP1 79
+
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* machine-op routine numbers */
+
+#define ALL 31 /* all address modes allowed, like LDA */
+#define ALTER 32 /* all but immediate, like STA */
+#define IMMED 33 /* immediate only (ANDCC, ORCC) */
+#define INDEXD 34 /* indexed (LEA's) */
+#define INHER 35 /* inherent, like CLC or CLRA */
+#define LONG 36 /* long branches */
+#define SHORT 37 /* short branches */
+#define SSTAK 38 /* S-stack (PSHS, PULS) */
+#define SWAP 39 /* TFR, EXG */
+#define USTAK 40 /* U-stack (PSHU,PULU) */
+
+/* yet further pseudo-ops */
+
+#define LCOMMOP 41
+
+#endif
+
+/* object code format (Introl) */
+
+#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */
+
+#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */
+
+#define OBJ_ABS 0x40 /* absolute code command */
+#define OBJ_OFFSET_REL 0x80 /* offset relocation command */
+#define OBJ_SET_SEG 0x20 /* set segment command */
+#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */
+#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */
+#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */
+#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */
+
+#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */
+#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */
+oops - RELBIT misplaced
+#endif
+#define OBJ_E_MASK 0x80 /* exported bit (symbols) */
+#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */
+oops - EXPBIT misplaced
+#endif
+#define OBJ_I_MASK 0x40 /* imported bit (symbols) */
+#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */
+oops - IMPBIT misplaced
+#endif
+#define OBJ_N_MASK 0x01 /* entry bit (symbols) */
+#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */
+oops - ENTBIT misplaced
+#endif
+#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */
+#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */
+#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */
+#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */
+
+#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */
+#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */
+
+#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */
+#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */
+
+#define SYMLIS_NAMELEN 26
+#define SYMLIS_LEN (sizeof (struct sym_listing_s))
+
+#define FILNAMLEN 64 /* max length of a file name */
+#define LINLEN 256 /* max length of input line */
+#define LINUM_LEN 5 /* length of formatted line number */
+
+#define SPTSIZ 1024 /* number of symbol ptrs */
+ /* pseudo-op flags */
+#define POPHI 1 /* set to print hi byte of adr */
+#define POPLO 2 /* to print lo byte of ADR */
+#define POPLC 4 /* to print LC */
+#define POPLONG 8 /* to print high word of ADR */
+#define MAXBLOCK 8 /* max nesting level of BLOCK stack */
+#define MAXGET 8 /* max nesting level of GET stack */
+#define MAXIF 8 /* max nesting level of IF stack */
+#define MACPSIZ (128/sizeof (struct schain_s))
+ /* size of macro param buffer */
+#define MAXMAC 8 /* max nesting level of macro stack */
+#define NLOC 16 /* number of location counters */
+#ifdef I80386
+#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */
+#endif
+
+/* special segments */
+
+#define BSSLOC 3
+#define DATALOC 3
+#define DPLOC 2
+#define STRLOC 1
+#define TEXTLOC 0
diff --git a/as/Makefile b/as/Makefile
new file mode 100644
index 0000000..a4c5456
--- /dev/null
+++ b/as/Makefile
@@ -0,0 +1,46 @@
+
+ifneq ($(TOPDIR),)
+include $(TOPDIR)/Make.defs
+else
+CC=bcc
+LDFLAGS=-s
+endif
+
+OBJS =as.o assemble.o error.o express.o \
+ genbin.o genlist.o genobj.o gensym.o \
+ macro.o mops.o pops.o readsrc.o \
+ scan.o table.o typeconv.o
+
+all: as86
+
+as86: $(OBJS)
+ $(CC) $(LDFLAGS) $(OBJS) -o as86
+
+install: all
+ install -d $(LIBDIR)
+ install -m 755 as86 $(LIBDIR)
+
+typeconv.o: dummy
+ -cp -p ../ld/typeconv.o .
+
+dummy:
+
+clean:
+ rm -f *.o as86
+
+as.o: const.h type.h byteord.h macro.h file.h flag.h globvar.h
+assemble.o: const.h type.h address.h globvar.h opcode.h scan.h
+error.o: const.h type.h
+express.o: const.h type.h address.h globvar.h scan.h source.h
+genbin.o: const.h type.h address.h file.h globvar.h
+genlist.o: const.h type.h address.h flag.h file.h globvar.h macro.h scan.h \
+ source.h
+genobj.o: const.h type.h address.h file.h globvar.h
+gensym.o: const.h type.h flag.h file.h globvar.h
+macro.o: const.h type.h globvar.h scan.h macro.h
+mops.o: const.h type.h globvar.h opcode.h scan.h address.h
+pops.o: const.h type.h address.h flag.h globvar.h opcode.h scan.h
+readsrc.o: const.h type.h flag.h file.h globvar.h macro.h scan.h source.h
+scan.o: const.h type.h globvar.h scan.h
+table.o: const.h type.h globvar.h opcode.h scan.h
+
diff --git a/as/TODO b/as/TODO
new file mode 100644
index 0000000..b8166c8
--- /dev/null
+++ b/as/TODO
@@ -0,0 +1 @@
+6809/const.h is out of date.
diff --git a/as/address.h b/as/address.h
new file mode 100644
index 0000000..26fcf33
--- /dev/null
+++ b/as/address.h
@@ -0,0 +1,30 @@
+/* address.h - global variables involving addresses for assembler */
+
+EXTERN struct address_s lastexp;/* last expression parsed */
+
+EXTERN union
+{
+ char fcbuf[LINLEN - 6]; /* buffer for fcb and fcc data */
+ /* data is absolute in 1 char pieces */
+ /* limited by FCC\t"" etc on line */
+ struct address_s fdbuf[(LINLEN - 4) / 2];
+ /* buffer for fdb data */
+ /* data can be of any 2-byte adr type */
+ /* limited by FDB\t and commas on line */
+#if SIZEOF_OFFSET_T > 2
+ struct address_s fqbuf[(LINLEN - 4) / 4];
+ /* buffer for fqb data */
+ /* data can be of any 4-byte adr type */
+ /* limited by FQB\t and commas on line */
+#endif
+}
+ databuf;
+
+EXTERN bool_t fcflag;
+EXTERN bool_t fdflag;
+#if SIZEOF_OFFSET_T > 2
+EXTERN bool_t fqflag;
+#endif
+
+EXTERN struct address_s immadr;
+EXTERN smallcount_t immcount;
diff --git a/as/as.c b/as/as.c
new file mode 100644
index 0000000..6d50828
--- /dev/null
+++ b/as/as.c
@@ -0,0 +1,300 @@
+/* as.c - assembler */
+
+/*
+ usage: as source [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] [-guw]
+ in any order (but no repeated file options)
+*/
+
+#include "const.h"
+#include "type.h"
+#include "byteord.h"
+#include "macro.h"
+#undef EXTERN
+#define EXTERN
+#include "file.h"
+#include "flag.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void exit P((int status));
+void *malloc P((unsigned size));
+char *strcpy P((char *s1, const char *s2));
+unsigned strlen P((const char *s));
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+int close P((int fd));
+int creat P((const char *path, int mode));
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+PUBLIC char hexdigit[] = "0123456789ABCDEF"; /* XXX - ld uses lower case */
+
+PRIVATE struct block_s hid_blockstak[MAXBLOCK]; /* block stack */
+PRIVATE struct lc_s hid_lctab[NLOC]; /* location counter table */
+PRIVATE struct if_s hid_ifstak[MAXBLOCK]; /* if stack */
+PRIVATE struct schain_s hid_mcpar[MACPSIZ]; /* MACRO params */
+PRIVATE struct macro_s hid_macstak[MAXBLOCK]; /* macro stack */
+PRIVATE struct sym_s *hid_spt[SPTSIZ]; /* hash table */
+
+FORWARD void initp1 P((void));
+FORWARD int my_creat P((char *name, char *message));
+FORWARD void process_args P((int argc, char **argv));
+FORWARD void summary P((fd_t fd));
+FORWARD void summ_number P((unsigned num));
+FORWARD void usage P((void));
+
+#ifndef USERMEM
+#define USERMEM (sizeof(int) <= 2 ? (unsigned) 0xAC00 : (unsigned) 0x28000L)
+#endif
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ heapptr = malloc(USERMEM);
+ heapend = heapptr + USERMEM;
+ if (heapptr == 0)
+ as_abort("cannot allocate memory");
+#ifdef SOS_EDOS
+ heapend = stackreg() - STAKSIZ;
+#endif
+ initp1();
+ initp1p2();
+ inst_keywords();
+ initbin();
+ initobj();
+ initsource(); /* only nec to init for unsupported mem file */
+ typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN);
+ warn.global = TRUE; /* constant */
+ process_args(argc, argv);
+ initscan();
+
+ assemble(); /* doesn't return, maybe use setjmp */
+
+ /* NOTREACHED */
+ return 0;
+}
+
+PUBLIC void as_abort(message)
+char *message;
+{
+ write(STDOUT, "as: ", 4);
+ write(STDOUT, message, strlen(message));
+ write(STDOUT, "\n", 1);
+ exit(1);
+}
+
+PUBLIC void finishup()
+{
+ bintrailer();
+ objtrailer();
+ if (list.global ||symgen)
+ gensym(); /* output to lstfil and/or symfil */
+ if (list.global ||toterr != 0 || totwarn != 0)
+ summary(lstfil);
+ if (lstfil != STDOUT && (toterr != 0 || totwarn != 0))
+ summary(STDOUT);
+ statistics();
+ exit(toterr != 0 ? 1 : 0); /* should close output files and check */
+}
+
+/* initialise constant nonzero values */
+
+PRIVATE void initp1()
+{
+#ifdef I80386
+ idefsize = defsize = sizeof (char *) > 2 ? 4 : 2;
+#endif
+ lctabtop = lctab + NLOC;
+ lstfil = STDOUT;
+ mapnum = 15; /* default map number for symbol table */
+ spt_top = (spt = hid_spt) + SPTSIZ;
+}
+
+/* initialise nonzero values which start same each pass */
+
+PUBLIC void initp1p2()
+{
+ register struct lc_s *lcp;
+
+ ifflag = TRUE;
+ pedata = UNDBIT; /* program entry point not defined */
+ blockstak = hid_blockstak + MAXBLOCK;
+ ifstak = hid_ifstak + MAXIF;
+ macstak = hid_macstak + MAXMAC;
+ macptop = (macpar = hid_mcpar) + MACPSIZ;
+ lctabtop = (lcptr = lctab = hid_lctab) + NLOC;
+ for (lcp = lctab; lcp < lctabtop; ++lcp)
+ /* init of lcdata/lc (many times) in loop to save space */
+ {
+ lcp->data = lcdata = RELBIT; /* lc relocatable until 1st ORG */
+ lcp->lc = lc = 0;
+ }
+}
+
+PRIVATE int my_creat(name, message)
+char *name;
+char *message;
+{
+ int fd;
+
+#ifdef O_BINARY
+ if ((fd = open(name, O_RDWR|O_BINARY|O_CREAT|O_TRUNC, CREAT_PERMS)) < 0 || fd > 255)
+#else
+ if ((fd = creat(name, CREAT_PERMS)) < 0 || fd > 255)
+#endif
+ as_abort(message);
+ return fd;
+}
+
+PRIVATE void process_args(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+ bool_t isnextarg;
+ char *nextarg = 0;
+
+ if (argc <= 1)
+ usage();
+ do
+ {
+ arg = *++argv;
+ if (arg[0] == '-')
+ {
+ if (arg[2] != 0)
+ usage(); /* no multiple options */
+ isnextarg = FALSE;
+ if (argc > 2)
+ {
+ nextarg = argv[1];
+ if (nextarg[0] != 0 && nextarg[0] != '-')
+ isnextarg = TRUE;
+ }
+ switch (arg[1])
+ {
+#ifdef I80386
+ case '0':
+ idefsize = defsize = 0x2;
+ break;
+ case '3':
+ idefsize = defsize = 0x4;
+ break;
+ case 'a':
+ asld_compatible = TRUE;
+ break;
+#endif
+ case 'b':
+ if (!isnextarg || binfil != 0)
+ usage();
+ binfil = my_creat(nextarg, "error creating binary file");
+ binaryg = TRUE;
+ --argc;
+ ++argv;
+ break;
+ case 'g':
+ globals_only_in_obj = TRUE;
+ break;
+#ifdef I80386
+ case 'j':
+ jumps_long = TRUE;
+ break;
+#endif
+ case 'l':
+ list.global = TRUE;
+ goto get_any_list_file;
+ case 'm':
+ maclist.global = TRUE;
+ get_any_list_file:
+ if (isnextarg)
+ {
+ if (lstfil != STDOUT)
+ usage();
+ lstfil = my_creat(nextarg, "error creating list file");
+ --argc;
+ ++argv;
+ }
+ break;
+ case 'n':
+ if (!isnextarg)
+ usage();
+ truefilename = nextarg;
+ --argc;
+ ++argv;
+ break;
+ case 'o':
+ if (!isnextarg || objfil != 0)
+ usage();
+ objectg = TRUE;
+ objfil = my_creat(nextarg, "error creating object file");
+ --argc;
+ ++argv;
+ break;
+ case 's':
+ if (!isnextarg || symfil != 0)
+ usage();
+ symgen = TRUE;
+ symfil = my_creat(nextarg, "error creating symbol file");
+ --argc;
+ ++argv;
+ break;
+ case 'u':
+ inidata = IMPBIT | SEGM;
+ break;
+ case 'w':
+ warn.semaphore = -1;
+ break;
+ default:
+ usage(); /* bad option */
+ }
+ }
+ else if (infil != 0)
+ usage(); /* no multiple sources */
+ else
+ {
+ if (strlen(arg) > FILNAMLEN)
+ as_abort("source file name too long");
+ infil = open_input(strcpy(filnamptr, arg));
+ infiln = infil0 = 1;
+ }
+ }
+ while (--argc != 1);
+ inidata = (~binaryg & inidata) | (RELBIT | UNDBIT);
+} /* IMPBIT from inidata unless binaryg */
+
+PRIVATE void summary(fd)
+int fd;
+{
+ innum = fd;
+ writenl();
+ summ_number(toterr);
+ writesn(" errors");
+ summ_number(totwarn);
+ writesn(" warnings");
+}
+
+PRIVATE void summ_number(num)
+unsigned num;
+{
+ /* format number like line numbers, build it at free spot heapptr */
+ *build_number(num, LINUM_LEN, heapptr) = 0;
+ writes(heapptr);
+}
+
+PRIVATE void usage()
+{
+ as_abort(
+#ifdef I80386
+"usage: as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src");
+#else
+ "usage: as [-guw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src");
+#endif
+}
diff --git a/as/asm/calljmp.asm b/as/asm/calljmp.asm
new file mode 100644
index 0000000..36a6ea4
--- /dev/null
+++ b/as/asm/calljmp.asm
@@ -0,0 +1,70 @@
+ CALL 0x10:0x20 ; not implemented
+ CALL AL; ; illeg
+ CALL DS ; illeg
+
+ CALL REL16
+
+ CALL AX
+ CALL BX
+ CALL CX
+ CALL DX
+ CALL SP
+ CALL BP
+ CALL SI
+ CALL DI
+
+ CALL BYTE [BX] ; illeg
+ CALL [BX]
+ CALL WORD [BX]
+
+ USE32
+ CALL REL32
+
+ USE16
+ CALL EAX
+ CALL EBX
+ CALL ECX
+ CALL EDX
+ CALL ESP
+ CALL EBP
+ CALL ESI
+ CALL EDI
+
+ CALL DWORD [BX]
+
+ JMP 0x10:0x20 ; not implemented
+ JMP AL; ; illeg
+ JMP DS ; illeg
+
+ JMP REL16
+
+ JMP AX
+ JMP BX
+ JMP CX
+ JMP DX
+ JMP SP
+ JMP BP
+ JMP SI
+ JMP DI
+
+ JMP BYTE [BX] ; illeg
+ JMP [BX]
+ JMP WORD [BX]
+
+ USE32
+ JMP REL32
+
+ USE16
+ JMP EAX
+ JMP EBX
+ JMP ECX
+ JMP EDX
+ JMP ESP
+ JMP EBP
+ JMP ESI
+ JMP EDI
+
+ JMP DWORD [BX]
+
+REL16:
+REL32:
diff --git a/as/asm/ea.asm b/as/asm/ea.asm
new file mode 100644
index 0000000..8717a73
--- /dev/null
+++ b/as/asm/ea.asm
@@ -0,0 +1,109 @@
+ MOV AX,[BX+SI]
+ MOV AX,[BX+DI]
+ MOV AX,[BP+SI]
+ MOV AX,[BP+DI]
+ MOV AX,[SI]
+ MOV AX,[DI]
+ MOV AX,[0x1234]
+ MOV AX,[BX]
+
+ MOV AX,[BX+SI+0x12]
+ MOV AX,[BX+DI+0x12]
+ MOV AX,[BP+SI+0x12]
+ MOV AX,[BP+DI+0x12]
+ MOV AX,[SI+0x12]
+ MOV AX,[DI+0x12]
+ MOV AX,[BP+0x12]
+ MOV AX,[BX+0x12]
+
+ MOV AX,[BX+SI+0x1234]
+ MOV AX,[BX+DI+0x1234]
+ MOV AX,[BP+SI+0x1234]
+ MOV AX,[BP+DI+0x1234]
+ MOV AX,[SI+0x1234]
+ MOV AX,[DI+0x1234]
+ MOV AX,[BP+0x1234]
+ MOV AX,[BX+0x1234]
+
+ MOV AL,AL
+ MOV AL,AH
+ MOV AL,BL
+ MOV AL,BH
+ MOV AL,CL
+ MOV AL,CH
+ MOV AL,DL
+ MOV AL,DH
+
+ MOV AX,AX
+ MOV AX,CX
+ MOV AX,DX
+ MOV AX,BX
+ MOV AX,SP
+ MOV AX,BP
+ MOV AX,SI
+ MOV AX,DI
+
+ MOV AX,[EAX]
+ MOV AX,[ECX]
+ MOV AX,[EDX]
+ MOV AX,[EBX]
+
+ MOV AX,[0x12345678]
+ MOV AX,[ESI]
+ MOV AX,[EDI]
+
+ MOV AX,[EAX+0x12]
+ MOV AX,[ECX+0x12]
+ MOV AX,[EDX+0x12]
+ MOV AX,[EBX+0x12]
+
+ MOV AX,[EBP+0x12]
+ MOV AX,[ESI+0x12]
+ MOV AX,[EDI+0x12]
+
+ MOV AX,[EAX+0x12345678]
+ MOV AX,[ECX+0x12345678]
+ MOV AX,[EDX+0x12345678]
+ MOV AX,[EBX+0x12345678]
+
+ MOV AX,[EBP+0x12345678]
+ MOV AX,[ESI+0x12345678]
+ MOV AX,[EDI+0x12345678]
+
+ MOV EAX,EAX
+ MOV EAX,ECX
+ MOV EAX,EDX
+ MOV EAX,EBX
+ MOV EAX,ESP
+ MOV EAX,EBP
+ MOV EAX,ESI
+ MOV EAX,EDI
+
+ MOV AX,[EAX+ESI*2]
+ MOV AX,[ECX+ESI*2]
+ MOV AX,[EDX+ESI*2]
+ MOV AX,[EBX+ESI*2]
+ MOV AX,[ESP+ESI*2]
+ MOV AX,[ESI*2+0x12345678]
+ MOV AX,[ESI+ESI*2]
+ MOV AX,[EDI+ESI*2]
+
+ MOV AX,[EAX+ESI*2+0x12]
+ MOV AX,[ECX+ESI*2+0x12]
+ MOV AX,[EDX+ESI*2+0x12]
+ MOV AX,[EBX+ESI*2+0x12]
+ MOV AX,[ESP+ESI*2+0x12]
+ MOV AX,[ESP+0x12]
+ MOV AX,[EBP+ESI*2+0x12]
+ MOV AX,[ESI+ESI*2+0x12]
+ MOV AX,[EDI+ESI*2+0x12]
+
+ MOV AX,[EAX+ESI*2+0x12345678]
+ MOV AX,[ECX+ESI*2+0x12345678]
+ MOV AX,[EDX+ESI*2+0x12345678]
+ MOV AX,[EBX+ESI*2+0x12345678]
+ MOV AX,[ESP+ESI*2+0x12345678]
+ MOV AX,[ESP+0x12345678]
+ MOV AX,[EBP+ESI*2+0x12345678]
+ MOV AX,[ESI+ESI*2+0x12345678]
+ MOV AX,[EDI+ESI*2+0x12345678]
diff --git a/as/asm/each.asm b/as/asm/each.asm
new file mode 100644
index 0000000..2145489
--- /dev/null
+++ b/as/asm/each.asm
@@ -0,0 +1,145 @@
+aaa
+aad
+aam
+aas
+adc bx,[esi*4]
+add bx,[esi*4]
+and bx,[esi*4]
+arpl [esi*4],bx
+bound bx,[esi*4]
+bsf bx,[esi*4]
+bsr bx,[esi*4]
+bswap ebx
+bt [esi*4],bx
+btc [esi*4],bx
+btr [esi*4],bx
+bts [esi*4],bx
+call [esi*4]
+cbw
+cwde
+clc
+cld
+cli
+clts
+cmc
+cmp bx,[esi*4]
+cmpsb
+cmpsw
+cmpsd
+cmpxchg [esi*4],bx
+cwd
+cdq
+daa
+das
+dec [esi*4]
+div [esi*4]
+enter 0x200,3
+hlt
+idiv [esi*4]
+imul [esi*4]
+in al,0x20
+inc [esi*4]
+insb
+insw
+insd
+int 0x20
+into
+invd
+invlpg [esi*4]
+iret
+iretd
+jnz many
+many:
+jmp [esi*4]
+lahf
+lar bx,[esi*4]
+lea bx,[esi*4]
+leave
+lgdt [esi*4]
+lidt [esi*4]
+lds bx,[esi*4]
+les bx,[esi*4]
+lfs bx,[esi*4]
+lgs bx,[esi*4]
+lss bx,[esi*4]
+lldt [esi*4]
+lmsw [esi*4]
+lock
+lodsb
+lodsw
+lodsd
+loop alot
+alot:
+lsl bx,[esi*4]
+ltr [esi*4]
+mov ax,[esi*4]
+mov bx,[esi*4]
+mov cr0,eax
+movsb
+movsw
+movsd
+movsx bx,byte [esi*4]
+movzx bx,byte [esi*4]
+mul [esi*4]
+neg [esi*4]
+nop
+not [esi*4]
+or bx,[esi*4]
+out 0x20,al
+outsb
+outsw
+outsd
+pop [esi*4]
+popa
+popad
+popf
+popfd
+push [esi*4]
+pusha
+pushad
+pushf
+pushfd
+rcl [esi*4],1
+rcr [esi*4],1
+rol [esi*4],1
+ror [esi*4],1
+rep
+repe
+repz
+repne
+repnz
+ret
+retf
+sahf
+sal [esi*4],1
+sar [esi*4],1
+shl [esi*4],1
+shr [esi*4],1
+sbb bx,[esi*4]
+scasb
+scasw
+scasd
+setnz byte [esi*4]
+sgdt [esi*4]
+sidt [esi*4]
+shld [esi*4],bx,1
+shrd [esi*4],bx,1
+sldt [esi*4]
+smsw [esi*4]
+stc
+std
+sti
+stosb
+stosw
+stosd
+str [esi*4]
+sub bx,[esi*4]
+test bx,[esi*4]
+verr [esi*4]
+verw [esi*4]
+wait
+wbinvd
+xadd [esi*4],bx
+xchg bx,[esi*4]
+xlat
+xor bx,[esi*4]
diff --git a/as/asm/easlow.as b/as/asm/easlow.as
new file mode 100644
index 0000000..75d71e2
--- /dev/null
+++ b/as/asm/easlow.as
@@ -0,0 +1,1219 @@
+ MOV AL,[0]
+ MOV AH,[1]
+ MOV BL,[-1] ; illeg
+ MOV BH,[127]
+ MOV CL,[-128] ; illeg
+ MOV CH,[128]
+ MOV DL,[-129] ; illeg
+ MOV DH,[32767]
+ MOV AL,[-32768] ; illeg
+ MOV AH,[32768]
+ MOV BL,[-32769] ; illeg
+ MOV BH,[$7FFFFFFF] ; illeg
+ MOV CL,[$80000000] ; illeg
+
+ MOV AL,AL
+ MOV AL,AH
+ MOV AL,BL
+ MOV AL,BH
+ MOV AL,CL
+ MOV AL,CH
+ MOV AL,DL
+ MOV AL,DH
+
+ MOV AL,AX ; illeg
+ MOV AL,BX ; illeg
+ MOV AL,CX ; illeg
+ MOV AL,DX ; illeg
+ MOV AL,BP ; illeg
+ MOV AL,DI ; illeg
+ MOV AL,SI ; illeg
+ MOV AL,SP ; illeg
+
+ MOV AH,AL
+ MOV AH,AH
+ MOV AH,BL
+ MOV AH,BH
+ MOV AH,CL
+ MOV AH,CH
+ MOV AH,DL
+ MOV AH,DH
+
+ MOV AH,AX ; illeg
+ MOV AH,BX ; illeg
+ MOV AH,CX ; illeg
+ MOV AH,DX ; illeg
+ MOV AH,BP ; illeg
+ MOV AH,DI ; illeg
+ MOV AH,SI ; illeg
+ MOV AH,SP ; illeg
+
+ MOV BL,AL
+ MOV BL,AH
+ MOV BL,BL
+ MOV BL,BH
+ MOV BL,CL
+ MOV BL,CH
+ MOV BL,DL
+ MOV BL,DH
+
+ MOV BL,AX ; illeg
+ MOV BL,BX ; illeg
+ MOV BL,CX ; illeg
+ MOV BL,DX ; illeg
+ MOV BL,BP ; illeg
+ MOV BL,DI ; illeg
+ MOV BL,SI ; illeg
+ MOV BL,SP ; illeg
+
+ MOV BH,AL
+ MOV BH,AH
+ MOV BH,BL
+ MOV BH,BH
+ MOV BH,CL
+ MOV BH,CH
+ MOV BH,DL
+ MOV BH,DH
+
+ MOV BH,AX ; illeg
+ MOV BH,BX ; illeg
+ MOV BH,CX ; illeg
+ MOV BH,DX ; illeg
+ MOV BH,BP ; illeg
+ MOV BH,DI ; illeg
+ MOV BH,SI ; illeg
+ MOV BH,SP ; illeg
+
+ MOV CL,AL
+ MOV CL,AH
+ MOV CL,BL
+ MOV CL,BH
+ MOV CL,CL
+ MOV CL,CH
+ MOV CL,DL
+ MOV CL,DH
+
+ MOV CL,AX ; illeg
+ MOV CL,BX ; illeg
+ MOV CL,CX ; illeg
+ MOV CL,DX ; illeg
+ MOV CL,BP ; illeg
+ MOV CL,DI ; illeg
+ MOV CL,SI ; illeg
+ MOV CL,SP ; illeg
+
+ MOV CH,AL
+ MOV CH,AH
+ MOV CH,BL
+ MOV CH,BH
+ MOV CH,CL
+ MOV CH,CH
+ MOV CH,DL
+ MOV CH,DH
+
+ MOV CH,AX ; illeg
+ MOV CH,BX ; illeg
+ MOV CH,CX ; illeg
+ MOV CH,DX ; illeg
+ MOV CH,BP ; illeg
+ MOV CH,DI ; illeg
+ MOV CH,SI ; illeg
+ MOV CH,SP ; illeg
+
+ MOV DL,AL
+ MOV DL,AH
+ MOV DL,BL
+ MOV DL,BH
+ MOV DL,CL
+ MOV DL,CH
+ MOV DL,DL
+ MOV DL,DH
+
+ MOV DL,AX ; illeg
+ MOV DL,BX ; illeg
+ MOV DL,CX ; illeg
+ MOV DL,DX ; illeg
+ MOV DL,BP ; illeg
+ MOV DL,DI ; illeg
+ MOV DL,SI ; illeg
+ MOV DL,SP ; illeg
+
+ MOV DH,AL
+ MOV DH,AH
+ MOV DH,BL
+ MOV DH,BH
+ MOV DH,CL
+ MOV DH,CH
+ MOV DH,DL
+ MOV DH,DH
+
+ MOV DH,AX ; illeg
+ MOV DH,BX ; illeg
+ MOV DH,CX ; illeg
+ MOV DH,DX ; illeg
+ MOV DH,BP ; illeg
+ MOV DH,DI ; illeg
+ MOV DH,SI ; illeg
+ MOV DH,SP ; illeg
+
+ MOV AL,[AL] ; illeg
+ MOV AH,[AH] ; illeg
+ MOV BL,[BL] ; illeg
+ MOV BH,[BH] ; illeg
+ MOV CL,[CL] ; illeg
+ MOV CH,[CH] ; illeg
+ MOV DL,[DL] ; illeg
+ MOV DH,[DH] ; illeg
+
+ MOV AL,[AX] ; illeg
+ MOV AH,[BX]
+ MOV BL,[CX] ; illeg
+ MOV BH,[DX] ; illeg
+ MOV CL,[BP]
+ MOV CH,[DI]
+ MOV DL,[SI]
+ MOV DH,[SP] ; illeg
+
+ MOV AL,[AX+1] ; illeg
+ MOV AH,[BX+1]
+ MOV BL,[CX+1] ; illeg
+ MOV BH,[DX+1] ; illeg
+ MOV CL,[BP+1]
+ MOV CH,[DI+1]
+ MOV DL,[SI+1]
+ MOV DH,[SP+1] ; illeg
+
+ MOV AL,[AX-1] ; illeg
+ MOV AH,[BX-1]
+ MOV BL,[CX-1] ; illeg
+ MOV BH,[DX-1] ; illeg
+ MOV CL,[BP-1]
+ MOV CH,[DI-1]
+ MOV DL,[SI-1]
+ MOV DH,[SP-1] ; illeg
+
+ MOV AL,[AX+127] ; illeg
+ MOV AH,[BX+127]
+ MOV BL,[CX+127] ; illeg
+ MOV BH,[DX+127] ; illeg
+ MOV CL,[BP+127]
+ MOV CH,[DI+127]
+ MOV DL,[SI+127]
+ MOV DH,[SP+127] ; illeg
+
+ MOV AL,[AX-128] ; illeg
+ MOV AH,[BX-128]
+ MOV BL,[CX-128] ; illeg
+ MOV BH,[DX-128] ; illeg
+ MOV CL,[BP-128]
+ MOV CH,[DI-128]
+ MOV DL,[SI-128]
+ MOV DH,[SP-128] ; illeg
+
+ MOV AL,[AX+128] ; illeg
+ MOV AH,[BX+128]
+ MOV BL,[CX+128] ; illeg
+ MOV BH,[DX+128] ; illeg
+ MOV CL,[BP+128]
+ MOV CH,[DI+128]
+ MOV DL,[SI+128]
+ MOV DH,[SP+128] ; illeg
+
+ MOV AL,[AX-129] ; illeg
+ MOV AH,[BX-129]
+ MOV BL,[CX-129] ; illeg
+ MOV BH,[DX-129] ; illeg
+ MOV CL,[BP-129]
+ MOV CH,[DI-129]
+ MOV DL,[SI-129]
+ MOV DH,[SP-129] ; illeg
+
+ MOV AL,[AX+32767] ; illeg
+ MOV AH,[BX+32767]
+ MOV BL,[CX+32767] ; illeg
+ MOV BH,[DX+32767] ; illeg
+ MOV CL,[BP+32767]
+ MOV CH,[DI+32767]
+ MOV DL,[SI+32767]
+ MOV DH,[SP+32767] ; illeg
+
+ MOV AL,[AX-32768] ; illeg
+ MOV AH,[BX-32768]
+ MOV BL,[CX-32768] ; illeg
+ MOV BH,[DX-32768] ; illeg
+ MOV CL,[BP-32768]
+ MOV CH,[DI-32768]
+ MOV DL,[SI-32768]
+ MOV DH,[SP-32768] ; illeg
+
+ MOV AL,[AX+32768] ; illeg
+ MOV AH,[BX+32768]
+ MOV BL,[CX+32768] ; illeg
+ MOV BH,[DX+32768] ; illeg
+ MOV CL,[BP+32768]
+ MOV CH,[DI+32768]
+ MOV DL,[SI+32768]
+ MOV DH,[SP+32768] ; illeg
+
+ MOV AL,[AX-32769] ; illeg
+ MOV AH,[BX-32769]
+ MOV BL,[CX-32769] ; illeg
+ MOV BH,[DX-32769] ; illeg
+ MOV CL,[BP-32769]
+ MOV CH,[DI-32769]
+ MOV DL,[SI-32769]
+ MOV DH,[SP-32769] ; illeg
+
+ MOV AL,[AX+$7FFFFFFF] ; illeg
+ MOV AH,[BX+$7FFFFFFF] ; illeg (bounds)
+ MOV BL,[CX+$7FFFFFFF] ; illeg
+ MOV BH,[DX+$7FFFFFFF] ; illeg
+ MOV CL,[BP+$7FFFFFFF] ; illeg (bounds)
+ MOV CH,[DI+$7FFFFFFF] ; illeg (bounds)
+ MOV DL,[SI+$7FFFFFFF] ; illeg (bounds)
+ MOV DH,[SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[AX-$80000000] ; illeg
+ MOV AH,[BX-$80000000] ; illeg (bounds)
+ MOV BL,[CX-$80000000] ; illeg
+ MOV BH,[DX-$80000000] ; illeg
+ MOV CL,[BP-$80000000] ; illeg (bounds)
+ MOV CH,[DI-$80000000] ; illeg (bounds)
+ MOV DL,[SI-$80000000] ; illeg (bounds)
+ MOV DH,[SP-$80000000] ; illeg
+
+ MOV AL,[AX+AX] ; illeg
+ MOV AH,[AX+BX] ; illeg
+ MOV BL,[AX+CX] ; illeg
+ MOV BH,[AX+DX] ; illeg
+ MOV CL,[AX+BP] ; illeg
+ MOV CH,[AX+DI] ; illeg
+ MOV DL,[AX+SI] ; illeg
+ MOV DH,[AX+SP] ; illeg
+
+ MOV AL,[BX+AX] ; illeg
+ MOV AH,[BX+BX] ; illeg
+ MOV BL,[BX+CX] ; illeg
+ MOV BH,[BX+DX] ; illeg
+ MOV CL,[BX+BP] ; illeg
+ MOV CH,[BX+DI]
+ MOV DL,[BX+SI]
+ MOV DH,[BX+SP] ; illeg
+
+ MOV AL,[CX+AX] ; illeg
+ MOV AH,[CX+BX] ; illeg
+ MOV BL,[CX+CX] ; illeg
+ MOV BH,[CX+DX] ; illeg
+ MOV CL,[CX+BP] ; illeg
+ MOV CH,[CX+DI] ; illeg
+ MOV DL,[CX+SI] ; illeg
+ MOV DH,[CX+SP] ; illeg
+
+ MOV AL,[DX+AX] ; illeg
+ MOV AH,[DX+BX] ; illeg
+ MOV BL,[DX+CX] ; illeg
+ MOV BH,[DX+DX] ; illeg
+ MOV CL,[DX+BP] ; illeg
+ MOV CH,[DX+DI] ; illeg
+ MOV DL,[DX+SI] ; illeg
+ MOV DH,[DX+SP] ; illeg
+
+ MOV AL,[BP+AX] ; illeg
+ MOV AH,[BP+BX] ; illeg
+ MOV BL,[BP+CX] ; illeg
+ MOV BH,[BP+DX] ; illeg
+ MOV CL,[BP+BP] ; illeg
+ MOV CH,[BP+DI]
+ MOV DL,[BP+SI]
+ MOV DH,[BP+SP] ; illeg
+
+ MOV AL,[DI+AX] ; illeg
+ MOV AH,[DI+BX]
+ MOV BL,[DI+CX] ; illeg
+ MOV BH,[DI+DX] ; illeg
+ MOV CL,[DI+BP]
+ MOV CH,[DI+DI] ; illeg
+ MOV DL,[DI+SI] ; illeg
+ MOV DH,[DI+SP] ; illeg
+
+ MOV AL,[SI+AX] ; illeg
+ MOV AH,[SI+BX]
+ MOV BL,[SI+CX] ; illeg
+ MOV BH,[SI+DX] ; illeg
+ MOV CL,[SI+BP]
+ MOV CH,[SI+DI] ; illeg
+ MOV DL,[SI+SI] ; illeg
+ MOV DH,[SI+SP] ; illeg
+
+ MOV AL,[SP+AX] ; illeg
+ MOV AH,[SP+BX] ; illeg
+ MOV BL,[SP+CX] ; illeg
+ MOV BH,[SP+DX] ; illeg
+ MOV CL,[SP+BP] ; illeg
+ MOV CH,[SP+DI] ; illeg
+ MOV DL,[SP+SI] ; illeg
+ MOV DH,[SP+SP] ; illeg
+
+ MOV AL,[AX+AX+1] ; illeg
+ MOV AH,[AX+BX+1] ; illeg
+ MOV BL,[AX+CX+1] ; illeg
+ MOV BH,[AX+DX+1] ; illeg
+ MOV CL,[AX+BP+1] ; illeg
+ MOV CH,[AX+DI+1] ; illeg
+ MOV DL,[AX+SI+1] ; illeg
+ MOV DH,[AX+SP+1] ; illeg
+
+ MOV AL,[BX+AX+1] ; illeg
+ MOV AH,[BX+BX+1] ; illeg
+ MOV BL,[BX+CX+1] ; illeg
+ MOV BH,[BX+DX+1] ; illeg
+ MOV CL,[BX+BP+1] ; illeg
+ MOV CH,[BX+DI+1]
+ MOV DL,[BX+SI+1]
+ MOV DH,[BX+SP+1] ; illeg
+
+ MOV AL,[CX+AX+1] ; illeg
+ MOV AH,[CX+BX+1] ; illeg
+ MOV BL,[CX+CX+1] ; illeg
+ MOV BH,[CX+DX+1] ; illeg
+ MOV CL,[CX+BP+1] ; illeg
+ MOV CH,[CX+DI+1] ; illeg
+ MOV DL,[CX+SI+1] ; illeg
+ MOV DH,[CX+SP+1] ; illeg
+
+ MOV AL,[DX+AX+1] ; illeg
+ MOV AH,[DX+BX+1] ; illeg
+ MOV BL,[DX+CX+1] ; illeg
+ MOV BH,[DX+DX+1] ; illeg
+ MOV CL,[DX+BP+1] ; illeg
+ MOV CH,[DX+DI+1] ; illeg
+ MOV DL,[DX+SI+1] ; illeg
+ MOV DH,[DX+SP+1] ; illeg
+
+ MOV AL,[BP+AX+1] ; illeg
+ MOV AH,[BP+BX+1] ; illeg
+ MOV BL,[BP+CX+1] ; illeg
+ MOV BH,[BP+DX+1] ; illeg
+ MOV CL,[BP+BP+1] ; illeg
+ MOV CH,[BP+DI+1]
+ MOV DL,[BP+SI+1]
+ MOV DH,[BP+SP+1] ; illeg
+
+ MOV AL,[DI+AX+1] ; illeg
+ MOV AH,[DI+BX+1]
+ MOV BL,[DI+CX+1] ; illeg
+ MOV BH,[DI+DX+1] ; illeg
+ MOV CL,[DI+BP+1]
+ MOV CH,[DI+DI+1] ; illeg
+ MOV DL,[DI+SI+1] ; illeg
+ MOV DH,[DI+SP+1] ; illeg
+
+ MOV AL,[SI+AX+1] ; illeg
+ MOV AH,[SI+BX+1]
+ MOV BL,[SI+CX+1] ; illeg
+ MOV BH,[SI+DX+1] ; illeg
+ MOV CL,[SI+BP+1]
+ MOV CH,[SI+DI+1] ; illeg
+ MOV DL,[SI+SI+1] ; illeg
+ MOV DH,[SI+SP+1] ; illeg
+
+ MOV AL,[SP+AX+1] ; illeg
+ MOV AH,[SP+BX+1] ; illeg
+ MOV BL,[SP+CX+1] ; illeg
+ MOV BH,[SP+DX+1] ; illeg
+ MOV CL,[SP+BP+1] ; illeg
+ MOV CH,[SP+DI+1] ; illeg
+ MOV DL,[SP+SI+1] ; illeg
+ MOV DH,[SP+SP+1] ; illeg
+
+ MOV AL,[AX+AX-1] ; illeg
+ MOV AH,[AX+BX-1] ; illeg
+ MOV BL,[AX+CX-1] ; illeg
+ MOV BH,[AX+DX-1] ; illeg
+ MOV CL,[AX+BP-1] ; illeg
+ MOV CH,[AX+DI-1] ; illeg
+ MOV DL,[AX+SI-1] ; illeg
+ MOV DH,[AX+SP-1] ; illeg
+
+ MOV AL,[BX+AX-1] ; illeg
+ MOV AH,[BX+BX-1] ; illeg
+ MOV BL,[BX+CX-1] ; illeg
+ MOV BH,[BX+DX-1] ; illeg
+ MOV CL,[BX+BP-1] ; illeg
+ MOV CH,[BX+DI-1]
+ MOV DL,[BX+SI-1]
+ MOV DH,[BX+SP-1] ; illeg
+
+ MOV AL,[CX+AX-1] ; illeg
+ MOV AH,[CX+BX-1] ; illeg
+ MOV BL,[CX+CX-1] ; illeg
+ MOV BH,[CX+DX-1] ; illeg
+ MOV CL,[CX+BP-1] ; illeg
+ MOV CH,[CX+DI-1] ; illeg
+ MOV DL,[CX+SI-1] ; illeg
+ MOV DH,[CX+SP-1] ; illeg
+
+ MOV AL,[DX+AX-1] ; illeg
+ MOV AH,[DX+BX-1] ; illeg
+ MOV BL,[DX+CX-1] ; illeg
+ MOV BH,[DX+DX-1] ; illeg
+ MOV CL,[DX+BP-1] ; illeg
+ MOV CH,[DX+DI-1] ; illeg
+ MOV DL,[DX+SI-1] ; illeg
+ MOV DH,[DX+SP-1] ; illeg
+
+ MOV AL,[BP+AX-1] ; illeg
+ MOV AH,[BP+BX-1] ; illeg
+ MOV BL,[BP+CX-1] ; illeg
+ MOV BH,[BP+DX-1] ; illeg
+ MOV CL,[BP+BP-1] ; illeg
+ MOV CH,[BP+DI-1]
+ MOV DL,[BP+SI-1]
+ MOV DH,[BP+SP-1] ; illeg
+
+ MOV AL,[DI+AX-1] ; illeg
+ MOV AH,[DI+BX-1]
+ MOV BL,[DI+CX-1] ; illeg
+ MOV BH,[DI+DX-1] ; illeg
+ MOV CL,[DI+BP-1]
+ MOV CH,[DI+DI-1] ; illeg
+ MOV DL,[DI+SI-1] ; illeg
+ MOV DH,[DI+SP-1] ; illeg
+
+ MOV AL,[SI+AX-1] ; illeg
+ MOV AH,[SI+BX-1]
+ MOV BL,[SI+CX-1] ; illeg
+ MOV BH,[SI+DX-1] ; illeg
+ MOV CL,[SI+BP-1]
+ MOV CH,[SI+DI-1] ; illeg
+ MOV DL,[SI+SI-1] ; illeg
+ MOV DH,[SI+SP-1] ; illeg
+
+ MOV AL,[SP+AX-1] ; illeg
+ MOV AH,[SP+BX-1] ; illeg
+ MOV BL,[SP+CX-1] ; illeg
+ MOV BH,[SP+DX-1] ; illeg
+ MOV CL,[SP+BP-1] ; illeg
+ MOV CH,[SP+DI-1] ; illeg
+ MOV DL,[SP+SI-1] ; illeg
+ MOV DH,[SP+SP-1] ; illeg
+
+ MOV AL,[AX+AX+127] ; illeg
+ MOV AH,[AX+BX+127] ; illeg
+ MOV BL,[AX+CX+127] ; illeg
+ MOV BH,[AX+DX+127] ; illeg
+ MOV CL,[AX+BP+127] ; illeg
+ MOV CH,[AX+DI+127] ; illeg
+ MOV DL,[AX+SI+127] ; illeg
+ MOV DH,[AX+SP+127] ; illeg
+
+ MOV AL,[BX+AX+127] ; illeg
+ MOV AH,[BX+BX+127] ; illeg
+ MOV BL,[BX+CX+127] ; illeg
+ MOV BH,[BX+DX+127] ; illeg
+ MOV CL,[BX+BP+127] ; illeg
+ MOV CH,[BX+DI+127]
+ MOV DL,[BX+SI+127]
+ MOV DH,[BX+SP+127] ; illeg
+
+ MOV AL,[CX+AX+127] ; illeg
+ MOV AH,[CX+BX+127] ; illeg
+ MOV BL,[CX+CX+127] ; illeg
+ MOV BH,[CX+DX+127] ; illeg
+ MOV CL,[CX+BP+127] ; illeg
+ MOV CH,[CX+DI+127] ; illeg
+ MOV DL,[CX+SI+127] ; illeg
+ MOV DH,[CX+SP+127] ; illeg
+
+ MOV AL,[DX+AX+127] ; illeg
+ MOV AH,[DX+BX+127] ; illeg
+ MOV BL,[DX+CX+127] ; illeg
+ MOV BH,[DX+DX+127] ; illeg
+ MOV CL,[DX+BP+127] ; illeg
+ MOV CH,[DX+DI+127] ; illeg
+ MOV DL,[DX+SI+127] ; illeg
+ MOV DH,[DX+SP+127] ; illeg
+
+ MOV AL,[BP+AX+127] ; illeg
+ MOV AH,[BP+BX+127] ; illeg
+ MOV BL,[BP+CX+127] ; illeg
+ MOV BH,[BP+DX+127] ; illeg
+ MOV CL,[BP+BP+127] ; illeg
+ MOV CH,[BP+DI+127]
+ MOV DL,[BP+SI+127]
+ MOV DH,[BP+SP+127] ; illeg
+
+ MOV AL,[DI+AX+127] ; illeg
+ MOV AH,[DI+BX+127]
+ MOV BL,[DI+CX+127] ; illeg
+ MOV BH,[DI+DX+127] ; illeg
+ MOV CL,[DI+BP+127]
+ MOV CH,[DI+DI+127] ; illeg
+ MOV DL,[DI+SI+127] ; illeg
+ MOV DH,[DI+SP+127] ; illeg
+
+ MOV AL,[SI+AX+127] ; illeg
+ MOV AH,[SI+BX+127]
+ MOV BL,[SI+CX+127] ; illeg
+ MOV BH,[SI+DX+127] ; illeg
+ MOV CL,[SI+BP+127]
+ MOV CH,[SI+DI+127] ; illeg
+ MOV DL,[SI+SI+127] ; illeg
+ MOV DH,[SI+SP+127] ; illeg
+
+ MOV AL,[SP+AX+127] ; illeg
+ MOV AH,[SP+BX+127] ; illeg
+ MOV BL,[SP+CX+127] ; illeg
+ MOV BH,[SP+DX+127] ; illeg
+ MOV CL,[SP+BP+127] ; illeg
+ MOV CH,[SP+DI+127] ; illeg
+ MOV DL,[SP+SI+127] ; illeg
+ MOV DH,[SP+SP+127] ; illeg
+
+ MOV AL,[AX+AX-128] ; illeg
+ MOV AH,[AX+BX-128] ; illeg
+ MOV BL,[AX+CX-128] ; illeg
+ MOV BH,[AX+DX-128] ; illeg
+ MOV CL,[AX+BP-128] ; illeg
+ MOV CH,[AX+DI-128] ; illeg
+ MOV DL,[AX+SI-128] ; illeg
+ MOV DH,[AX+SP-128] ; illeg
+
+ MOV AL,[BX+AX-128] ; illeg
+ MOV AH,[BX+BX-128] ; illeg
+ MOV BL,[BX+CX-128] ; illeg
+ MOV BH,[BX+DX-128] ; illeg
+ MOV CL,[BX+BP-128] ; illeg
+ MOV CH,[BX+DI-128]
+ MOV DL,[BX+SI-128]
+ MOV DH,[BX+SP-128] ; illeg
+
+ MOV AL,[CX+AX-128] ; illeg
+ MOV AH,[CX+BX-128] ; illeg
+ MOV BL,[CX+CX-128] ; illeg
+ MOV BH,[CX+DX-128] ; illeg
+ MOV CL,[CX+BP-128] ; illeg
+ MOV CH,[CX+DI-128] ; illeg
+ MOV DL,[CX+SI-128] ; illeg
+ MOV DH,[CX+SP-128] ; illeg
+
+ MOV AL,[DX+AX-128] ; illeg
+ MOV AH,[DX+BX-128] ; illeg
+ MOV BL,[DX+CX-128] ; illeg
+ MOV BH,[DX+DX-128] ; illeg
+ MOV CL,[DX+BP-128] ; illeg
+ MOV CH,[DX+DI-128] ; illeg
+ MOV DL,[DX+SI-128] ; illeg
+ MOV DH,[DX+SP-128] ; illeg
+
+ MOV AL,[BP+AX-128] ; illeg
+ MOV AH,[BP+BX-128] ; illeg
+ MOV BL,[BP+CX-128] ; illeg
+ MOV BH,[BP+DX-128] ; illeg
+ MOV CL,[BP+BP-128] ; illeg
+ MOV CH,[BP+DI-128]
+ MOV DL,[BP+SI-128]
+ MOV DH,[BP+SP-128] ; illeg
+
+ MOV AL,[DI+AX-128] ; illeg
+ MOV AH,[DI+BX-128]
+ MOV BL,[DI+CX-128] ; illeg
+ MOV BH,[DI+DX-128] ; illeg
+ MOV CL,[DI+BP-128]
+ MOV CH,[DI+DI-128] ; illeg
+ MOV DL,[DI+SI-128] ; illeg
+ MOV DH,[DI+SP-128] ; illeg
+
+ MOV AL,[SI+AX-128] ; illeg
+ MOV AH,[SI+BX-128]
+ MOV BL,[SI+CX-128] ; illeg
+ MOV BH,[SI+DX-128] ; illeg
+ MOV CL,[SI+BP-128]
+ MOV CH,[SI+DI-128] ; illeg
+ MOV DL,[SI+SI-128] ; illeg
+ MOV DH,[SI+SP-128] ; illeg
+
+ MOV AL,[SP+AX-128] ; illeg
+ MOV AH,[SP+BX-128] ; illeg
+ MOV BL,[SP+CX-128] ; illeg
+ MOV BH,[SP+DX-128] ; illeg
+ MOV CL,[SP+BP-128] ; illeg
+ MOV CH,[SP+DI-128] ; illeg
+ MOV DL,[SP+SI-128] ; illeg
+ MOV DH,[SP+SP-128] ; illeg
+
+ MOV AL,[AX+AX+128] ; illeg
+ MOV AH,[AX+BX+128] ; illeg
+ MOV BL,[AX+CX+128] ; illeg
+ MOV BH,[AX+DX+128] ; illeg
+ MOV CL,[AX+BP+128] ; illeg
+ MOV CH,[AX+DI+128] ; illeg
+ MOV DL,[AX+SI+128] ; illeg
+ MOV DH,[AX+SP+128] ; illeg
+
+ MOV AL,[BX+AX+128] ; illeg
+ MOV AH,[BX+BX+128] ; illeg
+ MOV BL,[BX+CX+128] ; illeg
+ MOV BH,[BX+DX+128] ; illeg
+ MOV CL,[BX+BP+128] ; illeg
+ MOV CH,[BX+DI+128]
+ MOV DL,[BX+SI+128]
+ MOV DH,[BX+SP+128] ; illeg
+
+ MOV AL,[CX+AX+128] ; illeg
+ MOV AH,[CX+BX+128] ; illeg
+ MOV BL,[CX+CX+128] ; illeg
+ MOV BH,[CX+DX+128] ; illeg
+ MOV CL,[CX+BP+128] ; illeg
+ MOV CH,[CX+DI+128] ; illeg
+ MOV DL,[CX+SI+128] ; illeg
+ MOV DH,[CX+SP+128] ; illeg
+
+ MOV AL,[DX+AX+128] ; illeg
+ MOV AH,[DX+BX+128] ; illeg
+ MOV BL,[DX+CX+128] ; illeg
+ MOV BH,[DX+DX+128] ; illeg
+ MOV CL,[DX+BP+128] ; illeg
+ MOV CH,[DX+DI+128] ; illeg
+ MOV DL,[DX+SI+128] ; illeg
+ MOV DH,[DX+SP+128] ; illeg
+
+ MOV AL,[BP+AX+128] ; illeg
+ MOV AH,[BP+BX+128] ; illeg
+ MOV BL,[BP+CX+128] ; illeg
+ MOV BH,[BP+DX+128] ; illeg
+ MOV CL,[BP+BP+128] ; illeg
+ MOV CH,[BP+DI+128]
+ MOV DL,[BP+SI+128]
+ MOV DH,[BP+SP+128] ; illeg
+
+ MOV AL,[DI+AX+128] ; illeg
+ MOV AH,[DI+BX+128]
+ MOV BL,[DI+CX+128] ; illeg
+ MOV BH,[DI+DX+128] ; illeg
+ MOV CL,[DI+BP+128]
+ MOV CH,[DI+DI+128] ; illeg
+ MOV DL,[DI+SI+128] ; illeg
+ MOV DH,[DI+SP+128] ; illeg
+
+ MOV AL,[SI+AX+128] ; illeg
+ MOV AH,[SI+BX+128]
+ MOV BL,[SI+CX+128] ; illeg
+ MOV BH,[SI+DX+128] ; illeg
+ MOV CL,[SI+BP+128]
+ MOV CH,[SI+DI+128] ; illeg
+ MOV DL,[SI+SI+128] ; illeg
+ MOV DH,[SI+SP+128] ; illeg
+
+ MOV AL,[SP+AX+128] ; illeg
+ MOV AH,[SP+BX+128] ; illeg
+ MOV BL,[SP+CX+128] ; illeg
+ MOV BH,[SP+DX+128] ; illeg
+ MOV CL,[SP+BP+128] ; illeg
+ MOV CH,[SP+DI+128] ; illeg
+ MOV DL,[SP+SI+128] ; illeg
+ MOV DH,[SP+SP+128] ; illeg
+
+ MOV AL,[AX+AX-129] ; illeg
+ MOV AH,[AX+BX-129] ; illeg
+ MOV BL,[AX+CX-129] ; illeg
+ MOV BH,[AX+DX-129] ; illeg
+ MOV CL,[AX+BP-129] ; illeg
+ MOV CH,[AX+DI-129] ; illeg
+ MOV DL,[AX+SI-129] ; illeg
+ MOV DH,[AX+SP-129] ; illeg
+
+ MOV AL,[BX+AX-129] ; illeg
+ MOV AH,[BX+BX-129] ; illeg
+ MOV BL,[BX+CX-129] ; illeg
+ MOV BH,[BX+DX-129] ; illeg
+ MOV CL,[BX+BP-129] ; illeg
+ MOV CH,[BX+DI-129]
+ MOV DL,[BX+SI-129]
+ MOV DH,[BX+SP-129] ; illeg
+
+ MOV AL,[CX+AX-129] ; illeg
+ MOV AH,[CX+BX-129] ; illeg
+ MOV BL,[CX+CX-129] ; illeg
+ MOV BH,[CX+DX-129] ; illeg
+ MOV CL,[CX+BP-129] ; illeg
+ MOV CH,[CX+DI-129] ; illeg
+ MOV DL,[CX+SI-129] ; illeg
+ MOV DH,[CX+SP-129] ; illeg
+
+ MOV AL,[DX+AX-129] ; illeg
+ MOV AH,[DX+BX-129] ; illeg
+ MOV BL,[DX+CX-129] ; illeg
+ MOV BH,[DX+DX-129] ; illeg
+ MOV CL,[DX+BP-129] ; illeg
+ MOV CH,[DX+DI-129] ; illeg
+ MOV DL,[DX+SI-129] ; illeg
+ MOV DH,[DX+SP-129] ; illeg
+
+ MOV AL,[BP+AX-129] ; illeg
+ MOV AH,[BP+BX-129] ; illeg
+ MOV BL,[BP+CX-129] ; illeg
+ MOV BH,[BP+DX-129] ; illeg
+ MOV CL,[BP+BP-129] ; illeg
+ MOV CH,[BP+DI-129]
+ MOV DL,[BP+SI-129]
+ MOV DH,[BP+SP-129] ; illeg
+
+ MOV AL,[DI+AX-129] ; illeg
+ MOV AH,[DI+BX-129]
+ MOV BL,[DI+CX-129] ; illeg
+ MOV BH,[DI+DX-129] ; illeg
+ MOV CL,[DI+BP-129]
+ MOV CH,[DI+DI-129] ; illeg
+ MOV DL,[DI+SI-129] ; illeg
+ MOV DH,[DI+SP-129] ; illeg
+
+ MOV AL,[SI+AX-129] ; illeg
+ MOV AH,[SI+BX-129]
+ MOV BL,[SI+CX-129] ; illeg
+ MOV BH,[SI+DX-129] ; illeg
+ MOV CL,[SI+BP-129]
+ MOV CH,[SI+DI-129] ; illeg
+ MOV DL,[SI+SI-129] ; illeg
+ MOV DH,[SI+SP-129] ; illeg
+
+ MOV AL,[SP+AX-129] ; illeg
+ MOV AH,[SP+BX-129] ; illeg
+ MOV BL,[SP+CX-129] ; illeg
+ MOV BH,[SP+DX-129] ; illeg
+ MOV CL,[SP+BP-129] ; illeg
+ MOV CH,[SP+DI-129] ; illeg
+ MOV DL,[SP+SI-129] ; illeg
+ MOV DH,[SP+SP-129] ; illeg
+
+ MOV AL,[AX+AX+32767] ; illeg
+ MOV AH,[AX+BX+32767] ; illeg
+ MOV BL,[AX+CX+32767] ; illeg
+ MOV BH,[AX+DX+32767] ; illeg
+ MOV CL,[AX+BP+32767] ; illeg
+ MOV CH,[AX+DI+32767] ; illeg
+ MOV DL,[AX+SI+32767] ; illeg
+ MOV DH,[AX+SP+32767] ; illeg
+
+ MOV AL,[BX+AX+32767] ; illeg
+ MOV AH,[BX+BX+32767] ; illeg
+ MOV BL,[BX+CX+32767] ; illeg
+ MOV BH,[BX+DX+32767] ; illeg
+ MOV CL,[BX+BP+32767] ; illeg
+ MOV CH,[BX+DI+32767]
+ MOV DL,[BX+SI+32767]
+ MOV DH,[BX+SP+32767] ; illeg
+
+ MOV AL,[CX+AX+32767] ; illeg
+ MOV AH,[CX+BX+32767] ; illeg
+ MOV BL,[CX+CX+32767] ; illeg
+ MOV BH,[CX+DX+32767] ; illeg
+ MOV CL,[CX+BP+32767] ; illeg
+ MOV CH,[CX+DI+32767] ; illeg
+ MOV DL,[CX+SI+32767] ; illeg
+ MOV DH,[CX+SP+32767] ; illeg
+
+ MOV AL,[DX+AX+32767] ; illeg
+ MOV AH,[DX+BX+32767] ; illeg
+ MOV BL,[DX+CX+32767] ; illeg
+ MOV BH,[DX+DX+32767] ; illeg
+ MOV CL,[DX+BP+32767] ; illeg
+ MOV CH,[DX+DI+32767] ; illeg
+ MOV DL,[DX+SI+32767] ; illeg
+ MOV DH,[DX+SP+32767] ; illeg
+
+ MOV AL,[BP+AX+32767] ; illeg
+ MOV AH,[BP+BX+32767] ; illeg
+ MOV BL,[BP+CX+32767] ; illeg
+ MOV BH,[BP+DX+32767] ; illeg
+ MOV CL,[BP+BP+32767] ; illeg
+ MOV CH,[BP+DI+32767]
+ MOV DL,[BP+SI+32767]
+ MOV DH,[BP+SP+32767] ; illeg
+
+ MOV AL,[DI+AX+32767] ; illeg
+ MOV AH,[DI+BX+32767]
+ MOV BL,[DI+CX+32767] ; illeg
+ MOV BH,[DI+DX+32767] ; illeg
+ MOV CL,[DI+BP+32767]
+ MOV CH,[DI+DI+32767] ; illeg
+ MOV DL,[DI+SI+32767] ; illeg
+ MOV DH,[DI+SP+32767] ; illeg
+
+ MOV AL,[SI+AX+32767] ; illeg
+ MOV AH,[SI+BX+32767]
+ MOV BL,[SI+CX+32767] ; illeg
+ MOV BH,[SI+DX+32767] ; illeg
+ MOV CL,[SI+BP+32767]
+ MOV CH,[SI+DI+32767] ; illeg
+ MOV DL,[SI+SI+32767] ; illeg
+ MOV DH,[SI+SP+32767] ; illeg
+
+ MOV AL,[SP+AX+32767] ; illeg
+ MOV AH,[SP+BX+32767] ; illeg
+ MOV BL,[SP+CX+32767] ; illeg
+ MOV BH,[SP+DX+32767] ; illeg
+ MOV CL,[SP+BP+32767] ; illeg
+ MOV CH,[SP+DI+32767] ; illeg
+ MOV DL,[SP+SI+32767] ; illeg
+ MOV DH,[SP+SP+32767] ; illeg
+
+ MOV AL,[AX+AX-32768] ; illeg
+ MOV AH,[AX+BX-32768] ; illeg
+ MOV BL,[AX+CX-32768] ; illeg
+ MOV BH,[AX+DX-32768] ; illeg
+ MOV CL,[AX+BP-32768] ; illeg
+ MOV CH,[AX+DI-32768] ; illeg
+ MOV DL,[AX+SI-32768] ; illeg
+ MOV DH,[AX+SP-32768] ; illeg
+
+ MOV AL,[BX+AX-32768] ; illeg
+ MOV AH,[BX+BX-32768] ; illeg
+ MOV BL,[BX+CX-32768] ; illeg
+ MOV BH,[BX+DX-32768] ; illeg
+ MOV CL,[BX+BP-32768] ; illeg
+ MOV CH,[BX+DI-32768]
+ MOV DL,[BX+SI-32768]
+ MOV DH,[BX+SP-32768] ; illeg
+
+ MOV AL,[CX+AX-32768] ; illeg
+ MOV AH,[CX+BX-32768] ; illeg
+ MOV BL,[CX+CX-32768] ; illeg
+ MOV BH,[CX+DX-32768] ; illeg
+ MOV CL,[CX+BP-32768] ; illeg
+ MOV CH,[CX+DI-32768] ; illeg
+ MOV DL,[CX+SI-32768] ; illeg
+ MOV DH,[CX+SP-32768] ; illeg
+
+ MOV AL,[DX+AX-32768] ; illeg
+ MOV AH,[DX+BX-32768] ; illeg
+ MOV BL,[DX+CX-32768] ; illeg
+ MOV BH,[DX+DX-32768] ; illeg
+ MOV CL,[DX+BP-32768] ; illeg
+ MOV CH,[DX+DI-32768] ; illeg
+ MOV DL,[DX+SI-32768] ; illeg
+ MOV DH,[DX+SP-32768] ; illeg
+
+ MOV AL,[BP+AX-32768] ; illeg
+ MOV AH,[BP+BX-32768] ; illeg
+ MOV BL,[BP+CX-32768] ; illeg
+ MOV BH,[BP+DX-32768] ; illeg
+ MOV CL,[BP+BP-32768] ; illeg
+ MOV CH,[BP+DI-32768]
+ MOV DL,[BP+SI-32768]
+ MOV DH,[BP+SP-32768] ; illeg
+
+ MOV AL,[DI+AX-32768] ; illeg
+ MOV AH,[DI+BX-32768]
+ MOV BL,[DI+CX-32768] ; illeg
+ MOV BH,[DI+DX-32768] ; illeg
+ MOV CL,[DI+BP-32768]
+ MOV CH,[DI+DI-32768] ; illeg
+ MOV DL,[DI+SI-32768] ; illeg
+ MOV DH,[DI+SP-32768] ; illeg
+
+ MOV AL,[SI+AX-32768] ; illeg
+ MOV AH,[SI+BX-32768]
+ MOV BL,[SI+CX-32768] ; illeg
+ MOV BH,[SI+DX-32768] ; illeg
+ MOV CL,[SI+BP-32768]
+ MOV CH,[SI+DI-32768] ; illeg
+ MOV DL,[SI+SI-32768] ; illeg
+ MOV DH,[SI+SP-32768] ; illeg
+
+ MOV AL,[SP+AX-32768] ; illeg
+ MOV AH,[SP+BX-32768] ; illeg
+ MOV BL,[SP+CX-32768] ; illeg
+ MOV BH,[SP+DX-32768] ; illeg
+ MOV CL,[SP+BP-32768] ; illeg
+ MOV CH,[SP+DI-32768] ; illeg
+ MOV DL,[SP+SI-32768] ; illeg
+ MOV DH,[SP+SP-32768] ; illeg
+
+ MOV AL,[AX+AX+32768] ; illeg
+ MOV AH,[AX+BX+32768] ; illeg
+ MOV BL,[AX+CX+32768] ; illeg
+ MOV BH,[AX+DX+32768] ; illeg
+ MOV CL,[AX+BP+32768] ; illeg
+ MOV CH,[AX+DI+32768] ; illeg
+ MOV DL,[AX+SI+32768] ; illeg
+ MOV DH,[AX+SP+32768] ; illeg
+
+ MOV AL,[BX+AX+32768] ; illeg
+ MOV AH,[BX+BX+32768] ; illeg
+ MOV BL,[BX+CX+32768] ; illeg
+ MOV BH,[BX+DX+32768] ; illeg
+ MOV CL,[BX+BP+32768] ; illeg
+ MOV CH,[BX+DI+32768]
+ MOV DL,[BX+SI+32768]
+ MOV DH,[BX+SP+32768] ; illeg
+
+ MOV AL,[CX+AX+32768] ; illeg
+ MOV AH,[CX+BX+32768] ; illeg
+ MOV BL,[CX+CX+32768] ; illeg
+ MOV BH,[CX+DX+32768] ; illeg
+ MOV CL,[CX+BP+32768] ; illeg
+ MOV CH,[CX+DI+32768] ; illeg
+ MOV DL,[CX+SI+32768] ; illeg
+ MOV DH,[CX+SP+32768] ; illeg
+
+ MOV AL,[DX+AX+32768] ; illeg
+ MOV AH,[DX+BX+32768] ; illeg
+ MOV BL,[DX+CX+32768] ; illeg
+ MOV BH,[DX+DX+32768] ; illeg
+ MOV CL,[DX+BP+32768] ; illeg
+ MOV CH,[DX+DI+32768] ; illeg
+ MOV DL,[DX+SI+32768] ; illeg
+ MOV DH,[DX+SP+32768] ; illeg
+
+ MOV AL,[BP+AX+32768] ; illeg
+ MOV AH,[BP+BX+32768] ; illeg
+ MOV BL,[BP+CX+32768] ; illeg
+ MOV BH,[BP+DX+32768] ; illeg
+ MOV CL,[BP+BP+32768] ; illeg
+ MOV CH,[BP+DI+32768]
+ MOV DL,[BP+SI+32768]
+ MOV DH,[BP+SP+32768] ; illeg
+
+ MOV AL,[DI+AX+32768] ; illeg
+ MOV AH,[DI+BX+32768]
+ MOV BL,[DI+CX+32768] ; illeg
+ MOV BH,[DI+DX+32768] ; illeg
+ MOV CL,[DI+BP+32768]
+ MOV CH,[DI+DI+32768] ; illeg
+ MOV DL,[DI+SI+32768] ; illeg
+ MOV DH,[DI+SP+32768] ; illeg
+
+ MOV AL,[SI+AX+32768] ; illeg
+ MOV AH,[SI+BX+32768]
+ MOV BL,[SI+CX+32768] ; illeg
+ MOV BH,[SI+DX+32768] ; illeg
+ MOV CL,[SI+BP+32768]
+ MOV CH,[SI+DI+32768] ; illeg
+ MOV DL,[SI+SI+32768] ; illeg
+ MOV DH,[SI+SP+32768] ; illeg
+
+ MOV AL,[SP+AX+32768] ; illeg
+ MOV AH,[SP+BX+32768] ; illeg
+ MOV BL,[SP+CX+32768] ; illeg
+ MOV BH,[SP+DX+32768] ; illeg
+ MOV CL,[SP+BP+32768] ; illeg
+ MOV CH,[SP+DI+32768] ; illeg
+ MOV DL,[SP+SI+32768] ; illeg
+ MOV DH,[SP+SP+32768] ; illeg
+
+ MOV AL,[AX+AX-32769] ; illeg
+ MOV AH,[AX+BX-32769] ; illeg
+ MOV BL,[AX+CX-32769] ; illeg
+ MOV BH,[AX+DX-32769] ; illeg
+ MOV CL,[AX+BP-32769] ; illeg
+ MOV CH,[AX+DI-32769] ; illeg
+ MOV DL,[AX+SI-32769] ; illeg
+ MOV DH,[AX+SP-32769] ; illeg
+
+ MOV AL,[BX+AX-32769] ; illeg
+ MOV AH,[BX+BX-32769] ; illeg
+ MOV BL,[BX+CX-32769] ; illeg
+ MOV BH,[BX+DX-32769] ; illeg
+ MOV CL,[BX+BP-32769] ; illeg
+ MOV CH,[BX+DI-32769]
+ MOV DL,[BX+SI-32769]
+ MOV DH,[BX+SP-32769] ; illeg
+
+ MOV AL,[CX+AX-32769] ; illeg
+ MOV AH,[CX+BX-32769] ; illeg
+ MOV BL,[CX+CX-32769] ; illeg
+ MOV BH,[CX+DX-32769] ; illeg
+ MOV CL,[CX+BP-32769] ; illeg
+ MOV CH,[CX+DI-32769] ; illeg
+ MOV DL,[CX+SI-32769] ; illeg
+ MOV DH,[CX+SP-32769] ; illeg
+
+ MOV AL,[DX+AX-32769] ; illeg
+ MOV AH,[DX+BX-32769] ; illeg
+ MOV BL,[DX+CX-32769] ; illeg
+ MOV BH,[DX+DX-32769] ; illeg
+ MOV CL,[DX+BP-32769] ; illeg
+ MOV CH,[DX+DI-32769] ; illeg
+ MOV DL,[DX+SI-32769] ; illeg
+ MOV DH,[DX+SP-32769] ; illeg
+
+ MOV AL,[BP+AX-32769] ; illeg
+ MOV AH,[BP+BX-32769] ; illeg
+ MOV BL,[BP+CX-32769] ; illeg
+ MOV BH,[BP+DX-32769] ; illeg
+ MOV CL,[BP+BP-32769] ; illeg
+ MOV CH,[BP+DI-32769]
+ MOV DL,[BP+SI-32769]
+ MOV DH,[BP+SP-32769] ; illeg
+
+ MOV AL,[DI+AX-32769] ; illeg
+ MOV AH,[DI+BX-32769]
+ MOV BL,[DI+CX-32769] ; illeg
+ MOV BH,[DI+DX-32769] ; illeg
+ MOV CL,[DI+BP-32769]
+ MOV CH,[DI+DI-32769] ; illeg
+ MOV DL,[DI+SI-32769] ; illeg
+ MOV DH,[DI+SP-32769] ; illeg
+
+ MOV AL,[SI+AX-32769] ; illeg
+ MOV AH,[SI+BX-32769]
+ MOV BL,[SI+CX-32769] ; illeg
+ MOV BH,[SI+DX-32769] ; illeg
+ MOV CL,[SI+BP-32769]
+ MOV CH,[SI+DI-32769] ; illeg
+ MOV DL,[SI+SI-32769] ; illeg
+ MOV DH,[SI+SP-32769] ; illeg
+
+ MOV AL,[SP+AX-32769] ; illeg
+ MOV AH,[SP+BX-32769] ; illeg
+ MOV BL,[SP+CX-32769] ; illeg
+ MOV BH,[SP+DX-32769] ; illeg
+ MOV CL,[SP+BP-32769] ; illeg
+ MOV CH,[SP+DI-32769] ; illeg
+ MOV DL,[SP+SI-32769] ; illeg
+ MOV DH,[SP+SP-32769] ; illeg
+
+ MOV AL,[AX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[AX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[AX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[AX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[AX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[AX+DI+$7FFFFFFF] ; illeg
+ MOV DL,[AX+SI+$7FFFFFFF] ; illeg
+ MOV DH,[AX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[BX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[BX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[BX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[BX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[BX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[BX+DI+$7FFFFFFF] ; illeg (bounds)
+ MOV DL,[BX+SI+$7FFFFFFF] ; illeg (bounds)
+ MOV DH,[BX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[CX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[CX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[CX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[CX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[CX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[CX+DI+$7FFFFFFF] ; illeg
+ MOV DL,[CX+SI+$7FFFFFFF] ; illeg
+ MOV DH,[CX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[DX+AX+$7FFFFFFF] ; illeg
+ MOV AH,[DX+BX+$7FFFFFFF] ; illeg
+ MOV BL,[DX+CX+$7FFFFFFF] ; illeg
+ MOV BH,[DX+DX+$7FFFFFFF] ; illeg
+ MOV CL,[DX+BP+$7FFFFFFF] ; illeg
+ MOV CH,[DX+DI+$7FFFFFFF] ; illeg
+ MOV DL,[DX+SI+$7FFFFFFF] ; illeg
+ MOV DH,[DX+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[BP+AX+$7FFFFFFF] ; illeg
+ MOV AH,[BP+BX+$7FFFFFFF] ; illeg
+ MOV BL,[BP+CX+$7FFFFFFF] ; illeg
+ MOV BH,[BP+DX+$7FFFFFFF] ; illeg
+ MOV CL,[BP+BP+$7FFFFFFF] ; illeg
+ MOV CH,[BP+DI+$7FFFFFFF] ; illeg (bounds)
+ MOV DL,[BP+SI+$7FFFFFFF] ; illeg (bounds)
+ MOV DH,[BP+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[DI+AX+$7FFFFFFF] ; illeg
+ MOV AH,[DI+BX+$7FFFFFFF] ; illeg (bounds)
+ MOV BL,[DI+CX+$7FFFFFFF] ; illeg
+ MOV BH,[DI+DX+$7FFFFFFF] ; illeg
+ MOV CL,[DI+BP+$7FFFFFFF] ; illeg (bounds)
+ MOV CH,[DI+DI+$7FFFFFFF] ; illeg
+ MOV DL,[DI+SI+$7FFFFFFF] ; illeg
+ MOV DH,[DI+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[SI+AX+$7FFFFFFF] ; illeg
+ MOV AH,[SI+BX+$7FFFFFFF] ; illeg (bounds)
+ MOV BL,[SI+CX+$7FFFFFFF] ; illeg
+ MOV BH,[SI+DX+$7FFFFFFF] ; illeg
+ MOV CL,[SI+BP+$7FFFFFFF] ; illeg (bounds)
+ MOV CH,[SI+DI+$7FFFFFFF] ; illeg
+ MOV DL,[SI+SI+$7FFFFFFF] ; illeg
+ MOV DH,[SI+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[SP+AX+$7FFFFFFF] ; illeg
+ MOV AH,[SP+BX+$7FFFFFFF] ; illeg
+ MOV BL,[SP+CX+$7FFFFFFF] ; illeg
+ MOV BH,[SP+DX+$7FFFFFFF] ; illeg
+ MOV CL,[SP+BP+$7FFFFFFF] ; illeg
+ MOV CH,[SP+DI+$7FFFFFFF] ; illeg
+ MOV DL,[SP+SI+$7FFFFFFF] ; illeg
+ MOV DH,[SP+SP+$7FFFFFFF] ; illeg
+
+ MOV AL,[AX+AX-$80000000] ; illeg
+ MOV AH,[AX+BX-$80000000] ; illeg
+ MOV BL,[AX+CX-$80000000] ; illeg
+ MOV BH,[AX+DX-$80000000] ; illeg
+ MOV CL,[AX+BP-$80000000] ; illeg
+ MOV CH,[AX+DI-$80000000] ; illeg
+ MOV DL,[AX+SI-$80000000] ; illeg
+ MOV DH,[AX+SP-$80000000] ; illeg
+
+ MOV AL,[BX+AX-$80000000] ; illeg
+ MOV AH,[BX+BX-$80000000] ; illeg
+ MOV BL,[BX+CX-$80000000] ; illeg
+ MOV BH,[BX+DX-$80000000] ; illeg
+ MOV CL,[BX+BP-$80000000] ; illeg
+ MOV CH,[BX+DI-$80000000] ; illeg (bounds)
+ MOV DL,[BX+SI-$80000000] ; illeg (bounds)
+ MOV DH,[BX+SP-$80000000] ; illeg
+
+ MOV AL,[CX+AX-$80000000] ; illeg
+ MOV AH,[CX+BX-$80000000] ; illeg
+ MOV BL,[CX+CX-$80000000] ; illeg
+ MOV BH,[CX+DX-$80000000] ; illeg
+ MOV CL,[CX+BP-$80000000] ; illeg
+ MOV CH,[CX+DI-$80000000] ; illeg
+ MOV DL,[CX+SI-$80000000] ; illeg
+ MOV DH,[CX+SP-$80000000] ; illeg
+
+ MOV AL,[DX+AX-$80000000] ; illeg
+ MOV AH,[DX+BX-$80000000] ; illeg
+ MOV BL,[DX+CX-$80000000] ; illeg
+ MOV BH,[DX+DX-$80000000] ; illeg
+ MOV CL,[DX+BP-$80000000] ; illeg
+ MOV CH,[DX+DI-$80000000] ; illeg
+ MOV DL,[DX+SI-$80000000] ; illeg
+ MOV DH,[DX+SP-$80000000] ; illeg
+
+ MOV AL,[BP+AX-$80000000] ; illeg
+ MOV AH,[BP+BX-$80000000] ; illeg
+ MOV BL,[BP+CX-$80000000] ; illeg
+ MOV BH,[BP+DX-$80000000] ; illeg
+ MOV CL,[BP+BP-$80000000] ; illeg
+ MOV CH,[BP+DI-$80000000] ; illeg (bounds)
+ MOV DL,[BP+SI-$80000000] ; illeg (bounds)
+ MOV DH,[BP+SP-$80000000] ; illeg
+
+ MOV AL,[DI+AX-$80000000] ; illeg
+ MOV AH,[DI+BX-$80000000] ; illeg (bounds)
+ MOV BL,[DI+CX-$80000000] ; illeg
+ MOV BH,[DI+DX-$80000000] ; illeg
+ MOV CL,[DI+BP-$80000000] ; illeg (bounds)
+ MOV CH,[DI+DI-$80000000] ; illeg
+ MOV DL,[DI+SI-$80000000] ; illeg
+ MOV DH,[DI+SP-$80000000] ; illeg
+
+ MOV AL,[SI+AX-$80000000] ; illeg
+ MOV AH,[SI+BX-$80000000] ; illeg (bounds)
+ MOV BL,[SI+CX-$80000000] ; illeg
+ MOV BH,[SI+DX-$80000000] ; illeg
+ MOV CL,[SI+BP-$80000000] ; illeg (bounds)
+ MOV CH,[SI+DI-$80000000] ; illeg
+ MOV DL,[SI+SI-$80000000] ; illeg
+ MOV DH,[SI+SP-$80000000] ; illeg
+
+ MOV AL,[SP+AX-$80000000] ; illeg
+ MOV AH,[SP+BX-$80000000] ; illeg
+ MOV BL,[SP+CX-$80000000] ; illeg
+ MOV BH,[SP+DX-$80000000] ; illeg
+ MOV CL,[SP+BP-$80000000] ; illeg
+ MOV CH,[SP+DI-$80000000] ; illeg
+ MOV DL,[SP+SI-$80000000] ; illeg
+ MOV DH,[SP+SP-$80000000] ; illeg
diff --git a/as/asm/f.asm b/as/asm/f.asm
new file mode 100644
index 0000000..c067bf9
--- /dev/null
+++ b/as/asm/f.asm
@@ -0,0 +1,114 @@
+; [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st]
+ fadd qword [ebx]
+ fadd dword [ebx]
+ fadd st,st(1)
+ fadd st(1),st
+ fdiv qword [ebx]
+ fdiv dword [ebx]
+ fdiv st,st(1) ; special swapping for this
+
+; [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st
+ faddp st(1),st
+
+; [fbld fbstp] mem10r
+ fbld tbyte [ebx]
+ fbstp tbyte [ebx]
+
+; [fcom fcomp] [mem4r mem8r optional-st(i)]
+ fcom dword [ebx]
+ fcom qword [ebx]
+ fcom
+ fcom st(1)
+
+; ffree st(i)
+ ffree st(1)
+
+; [fucom fucomp fxch] optional-st(i)
+ fucom
+ fucom st(1)
+
+; [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i]
+ fiadd word [ebx]
+ fiadd dword [ebx]
+
+; [fild fistp] [mem2i mem4i mem8i]
+ fild word [ebx]
+ fild dword [ebx]
+ fild qword [ebx]
+
+; [fld fstp] [mem4r mem8r mem10r st(i)]
+ fld dword [ebx]
+ fld qword [ebx]
+ fld tbyte [ebx]
+ fld st(1)
+
+; [fldcw fnstcw] mem2i
+ fldcw word [ebx]
+ fnstcw word [ebx]
+
+; [fldenv fnsave fnstenv frstor] mem
+ fldenv [ebx]
+ fnsave [ebx]
+ fnstenv [ebx]
+ frstor [ebx]
+
+; fnstsw [mem2i ax]
+ fnstsw word [ebx]
+ fnstsw ax
+
+; fst [mem4r mem8r st(i)]
+ fst dword [ebx]
+ fst qword [ebx]
+ fst st(1)
+
+; fstcw mem2i (wait)
+ fstcw word [ebx]
+
+; fstsw [mem2i ax] (wait)
+ fstsw word [ebx]
+ fstsw ax
+
+; [fsave fstenv] mem (wait)
+ fsave [ebx]
+ fstenv [ebx]
+
+; [fxxx] (no operands)
+ fnop ; D9D0
+ fchs ; D9E0
+ fabs ; D9E1
+ ftst ; D9E4
+ fxam ; D9E5
+ fld1 ; D9E8
+ fldl2t ; D9E9
+ fldl2e ; D9EA
+ fldpi ; D9EB
+ fldlg2 ; D9EC
+ fldln2 ; D9ED
+ fldz ; D9EE
+ f2xm1 ; D9F0
+ fyl2x ; D9F1
+ fptan ; D9F2
+ fpatan ; D9F3
+ fxtract ; D9F4
+ fprem1 ; D9F5
+ fdecstp ; D9F6
+ fincstp ; D9F7
+ fprem ; D9F8
+ fyl2xp1 ; D9F9
+ fsqrt ; D9FA
+ fsincos ; D9FB
+ frndint ; D9FC
+ fscale ; D9FD
+ fsin ; D9FE
+ fcos ; D9FF
+ fucompp ; DAE9
+ feni ; 9BDBE0
+ fneni ; DBE0
+ fdisi ; 9BDBE1
+ fndisi ; DBE1
+ fclex ; 9BDBE2
+ fnclex ; DBE2
+ finit ; 9BDBE3
+ fninit ; DBE3
+ fsetpm ; DBE4
+ fcompp ; DED9
diff --git a/as/asm/fadd.asm b/as/asm/fadd.asm
new file mode 100644
index 0000000..d18f002
--- /dev/null
+++ b/as/asm/fadd.asm
@@ -0,0 +1,271 @@
+_fadd:
+ PUSH BP
+ MOV BP,SP
+ MOV EAX,DWORD PTR [BP+4]
+ MOV EDX,DWORD PTR [BP+8]
+ MOV EBX,DWORD PTR [BP+12]
+ MOV ECX,DWORD PTR [BP+16]
+ CALL faddfxfy
+ MOV DWORD PTR _facc,EAX
+ MOV DWORD PTR _facc+4,EDX
+ POP BP
+ RET
+
+fsubfxfy:
+ XOR ECX,#$80000000 ; complement sign bit, fall into add routine
+faddfxfy:
+ PUSH EBP
+ PUSH EDI
+ PUSH ESI
+ MOV EDI,ECX ; free CL for shifts
+ MOV ESI,EDX ; this mainly for consistent naming
+ AND ESI,#$7FFFFFFF ; discard sign so comparison is simple
+ AND EDI,#$7FFFFFFF
+
+ CMP ESI,EDI
+ JA XBIG
+ JB SWAP
+ CMP EAX,EBX
+ JAE XBIG
+SWAP:
+ XCHG EDX,ECX
+ XCHG ESI,EDI
+ XCHG EAX,EBX
+XBIG:
+ AND ESI,#$000FFFFF ; discard exponent
+ AND EDI,#$000FFFFF
+ OR ESI,#$00100000 ; normalize
+ OR EDI,#$00100000
+
+ SHR ECX,32-(1+11)
+ SHR EDX,32-(1+11)
+ MOV EBP,ECX ; prepare to compare signs (want high bits 0)
+ SUB CX,DX ; get difference of signs in CX
+ NEG CX ; D holds sign and exponent of both throughout
+ CMP CX,#(64-11)+2
+ JAE TO_DONE1 ; x dominates y
+ XOR BP,DX
+ AND BP,#$0800 ; see if signs are same
+ JNZ TO_SUBTRACT ; else roundoff reg EBP is 0
+
+ CMP CL,#32
+ JAE TO_ADD_BIGSHIFT
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ ADD EAX,EBX
+ ADC ESI,EDI
+ SUB EBX,EBX
+
+; result DX(1+11):SI:AX:BP:BX but needs normalization
+
+NORMALIZE:
+ MOV CX,DX
+ AND CX,#$07FF
+ TEST ESI,#$00200000
+ JZ NORMALIZE2
+ BR LOVERFLOW
+
+TO_DONE1:
+ JMP DONE1
+
+TO_SUBTRACT:
+ BR SUBTRACT
+
+TO_ADD_BIGSHIFT:
+ BR ADD_BIGSHIFT
+
+TO_NORMLITTLE:
+ BR NORMLITTLE
+
+; result DX(1):CX(11):SI:AX:BP:BX
+
+NORMALIZE2:
+ SHRD EDI,ESI,32-11
+ ; top 11 bits of ESI known 0 and BSR is slooow
+ BSR EDI,EDI ; index of leading 1 bit in EDI is 11..31 in DI
+ JZ TO_NORMLITTLE ; ESI is zero (flag wrong in Intel Manual)
+ SUB DI,#31
+ NEG DI
+ PUSH CX ; gr
+ MOV CX,DI ; rr
+ SHLD ESI,EAX,CL
+ SHLD EAX,EBP,CL
+ SHLD EBP,EBX,CL
+ SHL EBX,CL
+ POP CX ; rr
+ SUB CX,DI
+ JC UNDERFLOW
+
+ROUND:
+ CMP EBP,#$80000000 ; test roundoff register
+ JA ROUNDUP
+ JB DONE ; no rounding
+ TEST EBX,EBX
+ JNZ ROUNDUP
+ TEST AL,#1 ; ambiguous case, round to even
+ JZ DONE ; even, no rounding
+ROUNDUP:
+ ADD EAX,#1
+ ADC ESI,#0
+ SUB EBP,EBP
+ SUB EBX,EBX
+ TEST ESI,#$00200000
+ JNZ LOVERFLOW ; rounding may cause overflow!
+
+DONE:
+ AND DX,#$0800 ; extract sign of largest and result
+ OR DX,CX ; include exponent with sign
+DONE1:
+ SHL EDX,32-(1+11)
+ AND ESI,#$000FFFFF ; discard normalization bit
+ OR EDX,ESI
+ POP ESI
+ POP EDI
+ POP EBP
+ RET
+
+UNDERFLOW: ; should have error message here
+ANSWER0:
+ SUB EDX,EDX
+ MOV EAX,EDX
+ POP ESI
+ POP EDI
+ POP EBP
+ RET
+
+LOVERFLOW: ; carry bit must be right-shifted back in
+ SHR ESI,1
+ RCR EAX,1
+ RCR EBP,1
+ RCR EBX,1
+ INC CX
+ CMP CX,#$0800
+ JNZ ROUND
+
+OVERFLOW: ; should have error message here
+ MOV EDX,#$FFE00000 ; + infinity
+ SUB EAX,EAX
+ POP ESI
+ POP EDI
+ POP EBP
+ RET
+
+ADD_BIGSHIFT:
+ SUB CL,#32
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ ADD EAX,EDI
+ ADC ESI,#0
+ XCHG EBP,EBX
+ BR NORMALIZE
+
+NORMLITTLE:
+ SHLD ESI,EAX,32-(1+11)
+ SHLD EAX,EBP,32-(1+11)
+ SHLD EBP,EBX,32-(1+11)
+ SHL EBX,20
+ SUB CL,#32-(1+11)
+ JC UNDERFLOW
+ BR NORMALIZE2
+
+SUBTRACT:
+ SUB EBP,EBP ; set up roundoff register
+ CMP CL,#32
+ JAE SUBTRACT_BIGSHIFT
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ NEG EBP
+ SBB EAX,EBX
+ SBB ESI,EDI
+ SUB EBX,EBX
+ MOV CX,DX
+ AND CX,#$07FF
+ BR NORMALIZE2
+
+SUBTRACT_BIGSHIFT:
+ SUB CL,#32
+ SHRD EBP,EBX,CL
+ SHRD EBX,EDI,CL
+ SHR EDI,CL
+ NEG EBX
+ NEG EBP
+ SBB EBX,#0
+ SBB EAX,EDI
+ SBB ESI,#0
+ XCHG EBP,EBX
+ MOV CX,DX
+ AND CX,#$07FF
+ BR NORMALIZE2
+
+TO_ANSWER0:
+ BR ANSWER0
+
+TO_OVERFLOW:
+ JMP TO_OVERFLOW
+
+TO_UNDERFLOW:
+ BR UNDERFLOW
+
+fmulfxfy:
+ PUSH EBP
+ PUSH EDI
+ PUSH ESI
+ MOV ESI,EDX ; free DX for multiplications
+ MOV EDI,ECX ; this mainly for consistent naming
+ SHR EDX,32-(1+11)
+ SHR ECX,32-(1+11)
+ MOV BP,DX
+ XOR BP,CX
+ AND BP,#$0800 ; extract sign
+ AND DX,#$07FF ; exp(x)
+ JZ TO_ANSWER0
+ AND CX,#$07FF ; exp(y)
+ JZ TO_ANSWER0
+ ADD CX,DX
+ SUB CX,#$0400
+ JB TO_UNDERFLOW
+ CMP CX,#$07FF
+ JA TO_OVERFLOW ; probably not quite right
+
+ AND ESI,#$000FFFFF ; discard sign and exponent
+ AND EDI,#$000FFFFF
+ OR ESI,#$00100000 ; normalize
+ OR EDI,#$00100000
+
+; exponent is in CX, sign in BP, operands in ESI:EAX and EDI:EBX, DX is free
+; product to go in ESI:EAX:EBP:EBX
+; terminology: x * y = (x32:x0) * (y32:y0) = x32y32 + x32y0 + x0y32 +x0y0
+
+ PUSH CX
+ PUSH BP
+ MOV ECX,EAX
+ MUL EBX ; x0y0
+ MOV EBP,EDX ; x0y0.high in EBP
+ XCHG EBX,EAX ; x0y0.low in EBX (final), y0 in EAX
+ MUL ESI ; x32y0
+ PUSH EAX ; x32y0.low on stack
+ PUSH EDX ; x32y0.high on stack
+ MOV EAX,ESI
+ MUL EDI ; x32y32
+ MOV ESI,EDX ; x32y32.high in ESI (final except carries)
+ XCHG ECX,EAX ; x32y32.low in ECX, x0 in EAX
+ MUL EDI ; x0y32
+
+ ADD EBP,EAX ; x0y0.high + x0y32.low
+ POP EAX ; x32y0.high
+ ADC EAX,EDX ; x32y0.high + x0y32.high
+ ADC ESI,#0
+ POP EDX ; x32y0.low
+ ADD EBP,EDX ; (x0y0.high + x0y32.low) + x32y0.low
+ ADC EAX,ECX ; (x32y0.high + x0y32.high) + x32y32.low
+ ADC ESI,#0
+ POP DX ; sign
+ POP CX ; exponent
+ ADD CX,#13 ; temp fixup
+ BR NORMALIZE2
+
+_facc:
+ .word 0,0
diff --git a/as/asm/farcall.asm b/as/asm/farcall.asm
new file mode 100644
index 0000000..6a779d9
--- /dev/null
+++ b/as/asm/farcall.asm
@@ -0,0 +1,10 @@
+call 1:2
+call far [1]
+use32
+call far [1]
+
+use16
+jmp 1:2
+jmp far [1]
+use32
+jmp far [1]
diff --git a/as/asm/group1.asm b/as/asm/group1.asm
new file mode 100644
index 0000000..fe2fb45
--- /dev/null
+++ b/as/asm/group1.asm
@@ -0,0 +1,31 @@
+ ADD AL,#3
+ ADD AX,#$1234
+ ADD EAX,#$12345678
+ ADD BL,#3
+ ADD BX,#$1234
+ ADD EBX,#$12345678
+ ADD BYTE [BX],#3
+ ADD BYTE 3[BX],#4
+ ADD BYTE [BX+SI],#4
+ ADD WORD [BX],#$1234
+ ADD DWORD [BX],#$12345678
+ ADD BYTE [BX],#3
+ ADD WORD [BX],#-3
+ ADD DWORD [BX],#-3
+ ADD CL,BL
+ ADD CX,BX
+ ADD ECX,EBX
+ ADD [BX],CL
+ ADD [BX],CX
+ ADD [BX],ECX
+ ADD CL,[BX]
+ ADD CX,[BX]
+ ADD ECX,[BX]
+
+ ADC CL,BL
+ AND CL,BL
+ CMP CL,BL
+ OR CL,BL
+ SUB CL,BL
+ SBB CL,BL
+ XOR CL,BL
diff --git a/as/asm/group6.asm b/as/asm/group6.asm
new file mode 100644
index 0000000..f742672
--- /dev/null
+++ b/as/asm/group6.asm
@@ -0,0 +1,24 @@
+; group6.asm
+; 0F 00 /nnn
+
+; LLDT r/m16 nnn = 010
+; LTR r/m16 nnn = 011
+; SLDT r/m16 nnn = 000
+; STR r/m16 nnn = 001
+; VERR r/m16 nnn = 100
+; VERW r/m16 nnn = 101
+
+ LLDT AL ; illeg size
+ LLDT EAX ; illeg size
+ LLDT WORD $1234 ; immed not allowed
+ LLDT DS ; segreg not allowed
+
+ LLDT AX
+ LLDT [BX]
+ LLDT [EAX]
+
+ LTR BX
+ SLDT [BP]
+ STR [EBX]
+ VERR CX
+ VERW [SI]
diff --git a/as/asm/group7.asm b/as/asm/group7.asm
new file mode 100644
index 0000000..0df497c
--- /dev/null
+++ b/as/asm/group7.asm
@@ -0,0 +1,34 @@
+; group7.asm
+; 0F 01 /nnn
+
+; INVLPG m nnn = 111
+; LGDT m16&32 nnn = 010
+; LIDT m16&32 nnn = 011
+; LMSW r/m16 nnn = 110
+; SGDT m nnn = 000
+; SIDT m nnn = 001
+; SMSW r/m16 nnn = 100
+
+ LGDT EAX ; register not allowed
+ LGDT #$1234 ; immed not allowed
+ LGDT WORD PTR [BX] ; illegal size
+
+ LGDT [BX]
+ LGDT PWORD PTR [BX]
+ LGDT FWORD PTR [BX]
+ LGDT [EAX]
+
+ INVLPG [EDI]
+ SGDT [BP]
+ SIDT [EBX]
+
+ LMSW AL ; illeg size
+ LMSW EAX ; illeg size
+ LMSW #$1234 ; immed not allowed
+ LMSW DS ; segreg not allowed
+
+ LMSW AX
+ LMSW [BX]
+ LMSW [EAX]
+
+ SMSW BX
diff --git a/as/asm/imul.asm b/as/asm/imul.asm
new file mode 100644
index 0000000..e2772c2
--- /dev/null
+++ b/as/asm/imul.asm
@@ -0,0 +1,33 @@
+ use32
+
+ imul bl
+ imul byte ptr [esi]
+ imul bx
+ imul word ptr [esi]
+ imul ebx
+ imul dword ptr [esi]
+
+ imul ax,bx
+ imul ax,[esi]
+ imul eax,ebx
+ imul eax,[esi]
+
+ imul ax,bx,22
+ imul ax,[esi],22
+ imul eax,ebx,22
+ imul eax,[esi],22
+
+ imul ax,[22]
+ imul eax,[22]
+ imul ax,#22
+ imul eax,#22
+
+ imul ax,bx,300
+ imul ax,[esi],300
+ imul eax,ebx,300000
+ imul eax,[esi],300000
+
+ imul ax,[300]
+ imul eax,[300000]
+ imul ax,#300
+ imul eax,#300000
diff --git a/as/asm/incdec.asm b/as/asm/incdec.asm
new file mode 100644
index 0000000..573861c
--- /dev/null
+++ b/as/asm/incdec.asm
@@ -0,0 +1,83 @@
+ INC AL
+ INC AH
+ INC BL
+ INC BH
+ INC CL
+ INC CH
+ INC DL
+ INC DH
+ INC #1 ; illeg
+ INC BYTE #1 ; illeg
+ INC [BX] ; illeg
+ INC BYTE [BX]
+
+ INC AX
+ INC BX
+ INC CX
+ INC DX
+ INC SP
+ INC BP
+ INC SI
+ INC DI
+ INC CS ; illeg
+ INC DS ; illeg
+ INC ES ; illeg
+ INC FS ; illeg
+ INC GS ; illeg
+ INC #$1234 ; illeg
+ INC WORD #$1234 ; illeg
+ INC WORD [BX]
+
+ INC EAX
+ INC EBX
+ INC ECX
+ INC EDX
+ INC ESP
+ INC EBP
+ INC ESI
+ INC EDI
+ INC #$12345678 ; illeg
+ INC DWORD #$12345678 ; illeg
+ INC DWORD [BX]
+
+ DEC AL
+ DEC AH
+ DEC BL
+ DEC BH
+ DEC CL
+ DEC CH
+ DEC DL
+ DEC DH
+ DEC #1 ; illeg
+ DEC BYTE #1 ; illeg
+ DEC [BX] ; illeg
+ DEC BYTE [BX]
+
+ DEC AX
+ DEC BX
+ DEC CX
+ DEC DX
+ DEC SP
+ DEC BP
+ DEC SI
+ DEC DI
+ DEC CS ; illeg
+ DEC DS ; illeg
+ DEC ES ; illeg
+ DEC FS ; illeg
+ DEC GS ; illeg
+ DEC #$1234 ; illeg
+ DEC WORD #$1234 ; illeg
+ DEC WORD [BX]
+
+ DEC EAX
+ DEC EBX
+ DEC ECX
+ DEC EDX
+ DEC ESP
+ DEC EBP
+ DEC ESI
+ DEC EDI
+ DEC #$12345678 ; illeg
+ DEC DWORD #$12345678 ; illeg
+ DEC DWORD [BX]
diff --git a/as/asm/inher.asm b/as/asm/inher.asm
new file mode 100644
index 0000000..f1343fa
--- /dev/null
+++ b/as/asm/inher.asm
@@ -0,0 +1,127 @@
+; INHER.ASM
+
+; INHER opcodes
+
+ AAA
+ AAS
+
+ CLC
+ CLD
+ CLI
+ CLTS
+ CMC
+ CMPSB
+
+ DAA
+ DAS
+
+ HLT
+
+ INTO
+ INSB
+
+ LAHF
+ LEAVE
+ LOCK
+ LODSB
+
+ MOVSB
+
+ NOP
+
+ OUTSB
+
+ REP
+ REPE
+ REPNE
+
+ SAHF
+ SCASB
+ STC
+ STD
+ STI
+ STOSB
+
+ WAIT
+
+; INHER16 and INHER32 opcodes
+
+ USE16
+
+ CBW
+ CWD
+ CWDE
+ CDQ
+ CMPSW
+ CMPSD
+
+ INSW
+ INSD
+ IRET
+ IRETD
+
+ LODSW
+ LODSD
+
+ MOVSW
+ MOVSD
+
+ OUTSW
+ OUTSD
+
+ POPA
+ POPAD
+ POPF
+ POPFD
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+
+ SCASW
+ SCASD
+ STOSW
+ STOSW
+
+ XLAT
+ XLATB
+
+ USE32
+
+ CBW
+ CWD
+ CWDE
+ CDQ
+ CMPSW
+ CMPSD
+
+ INSW
+ INSD
+ IRET
+ IRETD
+
+ LODSW
+ LODSD
+
+ MOVSW
+ MOVSD
+
+ OUTSW
+ OUTSD
+
+ POPA
+ POPAD
+ POPF
+ POPFD
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+
+ SCASW
+ SCASD
+ STOSW
+ STOSW
+
+ XLAT
+ XLATB
diff --git a/as/asm/inout.asm b/as/asm/inout.asm
new file mode 100644
index 0000000..3f0a3f2
--- /dev/null
+++ b/as/asm/inout.asm
@@ -0,0 +1,25 @@
+ IN EAX,DX ; plain IN is no longer allowed
+ INB
+ IN AL,DX
+ INW
+ IN AX,DX
+ IN EAX,DX
+ IN AL,$20
+ IN AL,$101
+ IN AX,$20
+ IN AX,$101
+ IN EAX,$20
+ IN EAX,$101
+
+ OUTB DX,EAX ; plain OUT is no longer allowed
+ OUTB
+ OUT DX,AL
+ OUTW
+ OUT DX,AX
+ OUT DX,EAX
+ OUT $20,AL
+ OUT $101,AL
+ OUT $20,AX
+ OUT #101,AX
+ OUT $20,EAX
+ OUT $101,EAX
diff --git a/as/asm/movspec.asm b/as/asm/movspec.asm
new file mode 100644
index 0000000..a4f9c15
--- /dev/null
+++ b/as/asm/movspec.asm
@@ -0,0 +1,246 @@
+mov eax,cr0
+mov eax,cr2
+mov eax,cr3
+mov eax,dr0
+mov eax,dr1
+mov eax,dr2
+mov eax,dr3
+mov eax,dr6
+mov eax,dr7
+mov eax,tr3
+mov eax,tr4
+mov eax,tr5
+mov eax,tr6
+mov eax,tr7
+
+mov cr0,eax
+mov cr2,eax
+mov cr3,eax
+mov dr0,eax
+mov dr1,eax
+mov dr2,eax
+mov dr3,eax
+mov dr6,eax
+mov dr7,eax
+mov tr3,eax
+mov tr4,eax
+mov tr5,eax
+mov tr6,eax
+mov tr7,eax
+
+
+mov ebx,cr0
+mov ebx,cr2
+mov ebx,cr3
+mov ebx,dr0
+mov ebx,dr1
+mov ebx,dr2
+mov ebx,dr3
+mov ebx,dr6
+mov ebx,dr7
+mov ebx,tr3
+mov ebx,tr4
+mov ebx,tr5
+mov ebx,tr6
+mov ebx,tr7
+
+mov cr0,ebx
+mov cr2,ebx
+mov cr3,ebx
+mov dr0,ebx
+mov dr1,ebx
+mov dr2,ebx
+mov dr3,ebx
+mov dr6,ebx
+mov dr7,ebx
+mov tr3,ebx
+mov tr4,ebx
+mov tr5,ebx
+mov tr6,ebx
+mov tr7,ebx
+
+
+mov ecx,cr0
+mov ecx,cr2
+mov ecx,cr3
+mov ecx,dr0
+mov ecx,dr1
+mov ecx,dr2
+mov ecx,dr3
+mov ecx,dr6
+mov ecx,dr7
+mov ecx,tr3
+mov ecx,tr4
+mov ecx,tr5
+mov ecx,tr6
+mov ecx,tr7
+
+mov cr0,ecx
+mov cr2,ecx
+mov cr3,ecx
+mov dr0,ecx
+mov dr1,ecx
+mov dr2,ecx
+mov dr3,ecx
+mov dr6,ecx
+mov dr7,ecx
+mov tr3,ecx
+mov tr4,ecx
+mov tr5,ecx
+mov tr6,ecx
+mov tr7,ecx
+
+
+mov edx,cr0
+mov edx,cr2
+mov edx,cr3
+mov edx,dr0
+mov edx,dr1
+mov edx,dr2
+mov edx,dr3
+mov edx,dr6
+mov edx,dr7
+mov edx,tr3
+mov edx,tr4
+mov edx,tr5
+mov edx,tr6
+mov edx,tr7
+
+mov cr0,edx
+mov cr2,edx
+mov cr3,edx
+mov dr0,edx
+mov dr1,edx
+mov dr2,edx
+mov dr3,edx
+mov dr6,edx
+mov dr7,edx
+mov tr3,edx
+mov tr4,edx
+mov tr5,edx
+mov tr6,edx
+mov tr7,edx
+
+
+mov esi,cr0
+mov esi,cr2
+mov esi,cr3
+mov esi,dr0
+mov esi,dr1
+mov esi,dr2
+mov esi,dr3
+mov esi,dr6
+mov esi,dr7
+mov esi,tr3
+mov esi,tr4
+mov esi,tr5
+mov esi,tr6
+mov esi,tr7
+
+mov cr0,esi
+mov cr2,esi
+mov cr3,esi
+mov dr0,esi
+mov dr1,esi
+mov dr2,esi
+mov dr3,esi
+mov dr6,esi
+mov dr7,esi
+mov tr3,esi
+mov tr4,esi
+mov tr5,esi
+mov tr6,esi
+mov tr7,esi
+
+
+mov edi,cr0
+mov edi,cr2
+mov edi,cr3
+mov edi,dr0
+mov edi,dr1
+mov edi,dr2
+mov edi,dr3
+mov edi,dr6
+mov edi,dr7
+mov edi,tr3
+mov edi,tr4
+mov edi,tr5
+mov edi,tr6
+mov edi,tr7
+
+mov cr0,edi
+mov cr2,edi
+mov cr3,edi
+mov dr0,edi
+mov dr1,edi
+mov dr2,edi
+mov dr3,edi
+mov dr6,edi
+mov dr7,edi
+mov tr3,edi
+mov tr4,edi
+mov tr5,edi
+mov tr6,edi
+mov tr7,edi
+
+
+mov esp,cr0
+mov esp,cr2
+mov esp,cr3
+mov esp,dr0
+mov esp,dr1
+mov esp,dr2
+mov esp,dr3
+mov esp,dr6
+mov esp,dr7
+mov esp,tr3
+mov esp,tr4
+mov esp,tr5
+mov esp,tr6
+mov esp,tr7
+
+mov cr0,esp
+mov cr2,esp
+mov cr3,esp
+mov dr0,esp
+mov dr1,esp
+mov dr2,esp
+mov dr3,esp
+mov dr6,esp
+mov dr7,esp
+mov tr3,esp
+mov tr4,esp
+mov tr5,esp
+mov tr6,esp
+mov tr7,esp
+
+
+mov ebp,cr0
+mov ebp,cr2
+mov ebp,cr3
+mov ebp,dr0
+mov ebp,dr1
+mov ebp,dr2
+mov ebp,dr3
+mov ebp,dr6
+mov ebp,dr7
+mov ebp,tr3
+mov ebp,tr4
+mov ebp,tr5
+mov ebp,tr6
+mov ebp,tr7
+
+mov cr0,ebp
+mov cr2,ebp
+mov cr3,ebp
+mov dr0,ebp
+mov dr1,ebp
+mov dr2,ebp
+mov dr3,ebp
+mov dr6,ebp
+mov dr7,ebp
+mov tr3,ebp
+mov tr4,ebp
+mov tr5,ebp
+mov tr6,ebp
+mov tr7,ebp
diff --git a/as/asm/pushpop.asm b/as/asm/pushpop.asm
new file mode 100644
index 0000000..b45117a
--- /dev/null
+++ b/as/asm/pushpop.asm
@@ -0,0 +1,86 @@
+ PUSH AL ; illeg
+ PUSH AH ; illeg
+ PUSH BL ; illeg
+ PUSH BH ; illeg
+ PUSH CL ; illeg
+ PUSH CH ; illeg
+ PUSH DL ; illeg
+ PUSH DH ; illeg
+ PUSH #1 ; illeg
+ PUSH BYTE #1 ; illeg
+ PUSH [BX] ; illeg
+ PUSH BYTE [BX] ; illeg
+ PUSH WORD #-1 ; right way to push a signed byte value
+
+ PUSH AX
+ PUSH BX
+ PUSH CX
+ PUSH DX
+ PUSH SP
+ PUSH BP
+ PUSH SI
+ PUSH DI
+ PUSH CS
+ PUSH DS
+ PUSH ES
+ PUSH FS
+ PUSH GS
+ PUSH SS
+ PUSH #$1234 ; illeg
+ PUSH WORD #$1234
+ PUSH WORD [BX]
+
+ PUSH EAX
+ PUSH EBX
+ PUSH ECX
+ PUSH EDX
+ PUSH ESP
+ PUSH EBP
+ PUSH ESI
+ PUSH EDI
+ PUSH #$12345678 ; illeg
+ PUSH DWORD #$12345678
+ PUSH DWORD [BX]
+
+ POP AL ; illeg
+ POP AH ; illeg
+ POP BL ; illeg
+ POP BH ; illeg
+ POP CL ; illeg
+ POP CH ; illeg
+ POP DL ; illeg
+ POP DH ; illeg
+ POP #1 ; illeg
+ POP BYTE #1 ; illeg
+ POP [BX] ; illeg
+ POP BYTE [BX] ; illeg
+
+ POP AX
+ POP BX
+ POP CX
+ POP DX
+ POP SP
+ POP BP
+ POP SI
+ POP DI
+ POP CS ; illeg
+ POP DS
+ POP ES
+ POP FS
+ POP GS
+ POP SS
+ POP #$1234 ; illeg
+ POP WORD #$1234 ; illeg
+ POP WORD [BX]
+
+ POP EAX
+ POP EBX
+ POP ECX
+ POP EDX
+ POP ESP
+ POP EBP
+ POP ESI
+ POP EDI
+ POP #$12345678 ; illeg
+ POP DWORD #$12345678 ; illeg
+ POP DWORD [BX]
diff --git a/as/asm/seg.asm b/as/asm/seg.asm
new file mode 100644
index 0000000..0394615
--- /dev/null
+++ b/as/asm/seg.asm
@@ -0,0 +1,6 @@
+ SEG CS
+ SEG DS
+ SEG ES
+ SEG FS
+ SEG GS
+ SEG SS
diff --git a/as/asm/shdouble.asm b/as/asm/shdouble.asm
new file mode 100644
index 0000000..1080ece
--- /dev/null
+++ b/as/asm/shdouble.asm
@@ -0,0 +1,34 @@
+; SHDOUBLE.ASM
+
+ILLEGALS EQU 1
+
+; 0F A4 SHLD r/m16,r16,imm8 3/7
+; 0F A4 SHLD r/m32,r32,imm8 3/7
+; 0F A5 SHLD r/m16,r16,CL 3/7
+; 0F A5 SHLD r/m32,r32,CL 3/7
+
+; 0F AC SHRD r/m16,r16,imm8 3/7
+; 0F AC SHRD r/m32,r32,imm8 3/7
+; 0F AD SHRD r/m16,r16,CL 3/7
+; 0F AD SHRD r/m32,r32,CL 3/7
+
+IF ILLEGALS
+ SHLD AL,BL,8 ; byte size
+ SHLD AX,8,8 ; immediate source
+ SHLD AX,DS,8 ; segment register
+ SHLD AX,[BX],8 ; non-register source
+ SHLD AX,BX,256 ; shift count too big
+ SHLD AL,BL,8 ; byte size
+ENDIF
+
+ SHLD BX,CX,3
+ SHLD EDX,ESI,1
+ SHLD CX,BX,CL
+ SHLD ESI,EDX,1
+ SHLD [BX],CX,3
+ SHLD [BX],ECX,1
+ SHLD [SI],BX,CL
+ SHLD [SI],EBX,CL
+
+ SHRD BX,CX,3
+ SHRD CX,BX,CL
diff --git a/as/asm/shift.asm b/as/asm/shift.asm
new file mode 100644
index 0000000..35cc23f
--- /dev/null
+++ b/as/asm/shift.asm
@@ -0,0 +1,119 @@
+ RCL AL,CL
+ RCL AH,CL
+ RCL BL,CL
+ RCL BH,CL
+ RCL CL,CL
+ RCL CH,CL
+ RCL DL,CL
+ RCL DH,CL
+ RCL #1,CL ; illeg
+ RCL [BX],CL ; illeg
+ RCL BYTE [BX],CL
+
+ RCL AX,CL
+ RCL BX,CL
+ RCL CX,CL
+ RCL DX,CL
+ RCL SP,CL
+ RCL BP,CL
+ RCL SI,CL
+ RCL DI,CL
+ RCL CS,CL ; illeg
+ RCL DS,CL ; illeg
+ RCL ES,CL ; illeg
+ RCL FS,CL ; illeg
+ RCL GS,CL ; illeg
+ RCL WORD [BX],CL
+
+ RCL EAX,CL
+ RCL EBX,CL
+ RCL ECX,CL
+ RCL EDX,CL
+ RCL ESP,CL
+ RCL EBP,CL
+ RCL ESI,CL
+ RCL EDI,CL
+ RCL DWORD [BX],CL
+
+ RCL AL,1
+ RCL AH,1
+ RCL BL,1
+ RCL BH,1
+ RCL CL,1
+ RCL CH,1
+ RCL DL,1
+ RCL DH,1
+ RCL #1,1 ; illeg
+ RCL [BX],1 ; illeg
+ RCL BYTE [BX],1
+
+ RCL AX,1
+ RCL BX,1
+ RCL CX,1
+ RCL DX,1
+ RCL SP,1
+ RCL BP,1
+ RCL SI,1
+ RCL DI,1
+ RCL CS,1 ; illeg
+ RCL DS,1 ; illeg
+ RCL ES,1 ; illeg
+ RCL FS,1 ; illeg
+ RCL GS,1 ; illeg
+ RCL WORD [BX],1
+
+ RCL EAX,1
+ RCL EBX,1
+ RCL ECX,1
+ RCL EDX,1
+ RCL ESP,1
+ RCL EBP,1
+ RCL ESI,1
+ RCL EDI,1
+ RCL DWORD [BX],1
+
+ RCL AL,15
+ RCL AH,15
+ RCL BL,15
+ RCL BH,15
+ RCL CL,15
+ RCL CH,15
+ RCL DL,15
+ RCL DH,15
+ RCL #1,15 ; illeg
+ RCL [BX],15 ; illeg
+ RCL BYTE [BX],15
+ RCL AL,$1000
+
+ RCL AX,15
+ RCL BX,15
+ RCL CX,15
+ RCL DX,15
+ RCL SP,15
+ RCL BP,15
+ RCL SI,15
+ RCL DI,15
+ RCL CS,15 ; illeg
+ RCL DS,15 ; illeg
+ RCL ES,15 ; illeg
+ RCL FS,15 ; illeg
+ RCL GS,15 ; illeg
+ RCL WORD [BX],15
+
+ RCL EAX,15
+ RCL EBX,15
+ RCL ECX,15
+ RCL EDX,15
+ RCL ESP,15
+ RCL EBP,15
+ RCL ESI,15
+ RCL EDI,15
+ RCL DWORD [BX],15
+
+ RCR AX,7
+ ROL AX,7
+ ROR AX,7
+ SAL AX,7
+ SAR AX,7
+ SHL AX,7
+ SHR AX,7
diff --git a/as/asm/summary.as b/as/asm/summary.as
new file mode 100644
index 0000000..cd62e37
--- /dev/null
+++ b/as/asm/summary.as
@@ -0,0 +1,385 @@
+general:
+ ; AL,imm8
+ ; AX,imm16
+ ; EAX,imm32
+ ; r/m8,imm8
+ ; r/m16,imm16
+ ; r/m32.imm32
+ ; r/m16,signed imm8
+ ; r/m32,signed imm8
+ ; r/m8,r8
+ ; r/m16,r16
+ ; r/m32,r32
+ ; r8,r/m8
+ ; r16,r/m16
+ ; r32,r/m32
+
+shiftcount:
+ ; 1
+ ; CL
+ ; imm8
+unary alterable:
+ ; r/m8
+ ; r/m16
+ ; r/m32
+
+ AAA
+ AAD ; [unsupported base]
+ AAM ; [unsupported base]
+ AAS
+ ADC ; general
+ ADD ; general
+ AND ; general
+ ARPL ; r/m16,r16
+ BOUND ; r16,m16&16
+ BOUND ; r32,m32&32
+ BSF ; r16,r/m16
+ BSF ; r32,r/m32
+ BSR ; r16,r/m16
+ BSR ; r32,r/m32
+ BSWAP ; r32
+ BT ; r/m16,r16
+ BT ; r/m32,r32
+ BT ; r/m16,imm8
+ BT ; r/m32,imm8
+ BTC ; r/m16,r16
+ BTC ; r/m32,r32
+ BTC ; r/m16,imm8
+ BTC ; r/m32,imm8
+ BTR ; r/m16,r16
+ BTR ; r/m32,r32
+ BTR ; r/m16,imm8
+ BTR ; r/m32,imm8
+ BTS ; r/m16,r16
+ BTS ; r/m32,r32
+ BTS ; r/m16,imm8
+ BTS ; r/m32,imm8
+ CALL ; rel16
+ CALL ; r/m16
+ CALL ; ptr16:16
+ CALL ; m16:16
+ CALL ; rel32
+ CALL ; r/m32
+ CALL ; ptr16:32
+ CALL ; m16:32
+ CBW
+ CDQ
+ CLC
+ CLD
+ CLI
+ CLTS
+ CMC
+ CMP ; general
+ CMPS ; [segreg:]m8,m8
+ CMPS ; [segreg:]m16,m16
+ CMPS ; [segreg:]m32,m32
+ CMPSB
+ CMPSW
+ CMPSD
+ CMPXCHG ; r/m8,r8
+ CMPXCHG ; r/m16,r16
+ CMPXCHG ; r/m32,r32
+ CWD
+ CWDE
+ DAA
+ DAS
+ DEC ; unary alterable
+ DEC ; r16
+ DEC ; r32
+ DIV ; AL,r/m8
+ DIV ; AX,r/m16
+ DIV ; EAX,r/m32
+ ENTER ; imm16,imm8
+ HLT
+ IDIV ; AL,r/m8
+ IDIV ; AX,r/m16
+ IDIV ; EAX,r/m32
+ IMUL ; r/m8
+ IMUL ; r/m16
+ IMUL ; r/m32
+ IMUL ; r16,r/m16
+ IMUL ; r32,r/m32
+ IMUL ; r16,r/m16,imm8
+ IMUL ; r32,r/m32,imm8
+ IMUL ; r16,imm8
+ IMUL ; r32,imm8
+ IMUL ; r16,r/m16,imm16
+ IMUL ; r32,r/m32,imm32
+ IMUL ; r16,imm16
+ IMUL ; r32,imm32
+ IN ; AL,imm8
+ IN ; AX,imm8
+ IN ; EAX,imm8
+ IN ; AL,DX
+ IN ; AX,DX
+ IN ; EAX,DX
+ INC ; unary alterable
+ INC ; r16
+ INC ; r32
+ INSB
+ INSW
+ INSD
+ INT ; imm8
+ INTO
+ INVD
+ INVLPG ; m
+ IRET
+ IRETD
+ JCC ; rel8
+ JCC ; rel16/32
+ JA
+ JAE
+ JB
+ JBE
+ JC
+ JCXZ
+ JECXZ
+ JE
+ JG
+ JGE
+ JL
+ JLE
+ JNA
+ JNAE
+ JNB
+ JNBE
+ JNC
+ JNE
+ JNG
+ JNGE
+ JNL
+ JNLE
+ JNO
+ JNP
+ JNS
+ JNZ
+ JO
+ JP
+ JPE
+ JPO
+ JS
+ JZ
+ JMP ; rel8
+ JMP ; rel16
+ JMP ; r/m16
+ JMP ; ptr16:16
+ JMP ; m16:16
+ JMP ; rel32
+ JMP ; r/m32
+ JMP ; ptr16:32
+ JMP ; m16:32
+ LAHF
+ LAR ; r16,r/m16
+ LAR ; r32,r/m32
+ LEA ; r16,m
+ LEA ; r32,m
+ LEAVE
+ LGDT ; m16&32
+ LIDT ; m16&32
+ LDS ; r16,m16:16
+ LDS ; r32,m16:32
+ LES ; r16,m16:16
+ LES ; r32,m16:32
+ LFS ; r16,m16:16
+ LFS ; r32,m16:32
+ LGS ; r16,m16:16
+ LGS ; r32,m16:32
+ LSS ; r16,m16:16
+ LSS ; r32,m16:32
+ LLDT ; r/m16
+ LMSW ; r/m16
+ LOCK
+ LODS ; [segreg:]m8
+ LODS ; [segreg:]m16
+ LODS ; [segreg:]m32
+ LODSB
+ LODSW
+ LODSD
+ LOOP ; rel8
+ LOOPE ; rel8
+ LOOPZ ; rel8
+ LOOPNE ; rel8
+ LOOPNZ ; rel8
+ LSL ; r16,r/m16
+ LSL ; r32,r/m32
+ LTR ; r/m16
+ MOV ; r/m8,r8
+ MOV ; r/m16,r16
+ MOV ; r/m32,r32
+ MOV ; r8,r/m8
+ MOV ; r16,r/m16
+ MOV ; r32,r/m32
+ MOV ; r/m16,Sreg
+ MOV ; Sreg,r/m16
+ MOV ; AL,moffs8
+ MOV ; AX,moffs16
+ MOV ; EAX,moffs32
+ MOV ; moffs8,AL
+ MOV ; moffs16,AX
+ MOV ; moffs32,EAX
+ MOV ; r8,imm8
+ MOV ; r16,imm16
+ MOV ; r32,imm32
+ MOV ; r32,CR0/CR2/CR3
+ MOV ; r/m8,imm8
+ MOV ; r/m16,imm16
+ MOV ; r/m32,imm32
+ MOV ; r32,CR0/CR2/CR3
+ MOV ; CR0/CR2/CR3,r32
+ MOV ; r32,DR0/DR1/DR2/DR3/DR6/DR7
+ MOV ; DR0/DR1/DR2/DR3/DR6/DR7,r32
+ MOV ; r32,TR6/TR7
+ MOV ; TR6/TR7,r32
+ MOVS ; [segreg:]m8,m8
+ MOVS ; [segreg:]m16,m16
+ MOVS ; [segreg:]m32,m32
+ MOVSB
+ MOVSW
+ MOVSD
+ MOVSX ; r16,r/m8
+ MOVSX ; r32,r/m8
+ MOVSX ; r32,r/m16
+ MOVZX ; r16,r/m8
+ MOVZX ; r32,r/m8
+ MOVZX ; r32,r/m16
+ MUL ; AL,r/m8
+ MUL ; AX,r/m16
+ MUL ; EAX,r/m32
+ NEG ; unary alterable
+ NOP
+ NOT ; unary alterable
+ OR ; general
+ OUT ; imm8,AL
+ OUT ; imm8,AX
+ OUT ; imm8,EAX
+ OUT ; DX,AL
+ OUT ; DX,AX
+ OUT ; DX,EAX
+ OUTS ; [segreg:]m8
+ OUTS ; [segreg:]m16
+ OUTS ; [segreg:]m32
+ OUTSB
+ OUTSW
+ OUTSD
+ POP ; m16
+ POP ; m32
+ POP ; r16
+ POP ; r32
+ POP ; DS
+ POP ; ES
+ POP ; FS
+ POP ; GS
+ POP ; SS
+ POPA
+ POPAD
+ POPF
+ POPFD
+ PUSH ; m16
+ PUSH ; m32
+ PUSH ; r16
+ PUSH ; r32
+ PUSH ; imm8
+ PUSH ; imm16
+ PUSH ; imm32
+ PUSH ; CS
+ PUSH ; DS
+ PUSH ; ES
+ PUSH ; FS
+ PUSH ; GS
+ PUSH ; SS
+ PUSHA
+ PUSHAD
+ PUSHF
+ PUSHFD
+ RCL ; shiftcount
+ RCR ; shiftcount
+ ROL ; shiftcount
+ ROR ; shiftcount
+ REP ; INS/MOVS/OUTS/STOS
+ REPE ; CMPS/SCAS
+ REPNE ; CMPS/SCAS
+ RET
+ RET ; imm16
+ SAHF
+ SAL ; shiftcount
+ SAR ; shiftcount
+ SHL ; shiftcount
+ SHR ; shiftcount
+ SBB ; general
+ SCASB
+ SCASW
+ SCASD
+ SETA ; r/m8
+ SETAE ; r/m8
+ SETB ; r/m8
+ SETBE ; r/m8
+ SETC ; r/m8
+ SETE ; r/m8
+ SETG ; r/m8
+ SETGE ; r/m8
+ SETL ; r/m8
+ SETLE ; r/m8
+ SETNA ; r/m8
+ SETNAE ; r/m8
+ SETNB ; r/m8
+ SETNBE ; r/m8
+ SETNC ; r/m8
+ SETNE ; r/m8
+ SETNG ; r/m8
+ SETNGE ; r/m8
+ SETNL ; r/m8
+ SETNLE ; r/m8
+ SETNO ; r/m8
+ SETNP ; r/m8
+ SETNS ; r/m8
+ SETNZ ; r/m8
+ SETO ; r/m8
+ SETP ; r/m8
+ SETPE ; r/m8
+ SETPO ; r/m8
+ SETS ; r/m8
+ SETZ ; r/m8
+ SGDT ; m
+ SHLD ; r/m16,r16,imm8
+ SHLD ; r/m32,r32,imm8
+ SHLD ; r/m16,r16,CL
+ SHLD ; r/m32,r32,CL
+ SHRD ; r/m16,r16,imm8
+ SHRD ; r/m32,r32,imm8
+ SHRD ; r/m16,r16,CL
+ SHRD ; r/m32,r32,CL
+ SIDT ; m
+ SLDT ; r/m16
+ SMSW ; r/m16
+ STC
+ STD
+ STI
+ STOSB
+ STOSW
+ STOSD
+ STR ; r/m16
+ SUB ; general
+ TEST ; AL,imm8
+ TEST ; AX,imm16
+ TEST ; EAX,imm32
+ TEST ; r/m8,imm8
+ TEST ; r/m16,imm16
+ TEST ; r/m32,imm32
+ TEST ; r/m8,r8
+ TEST ; r/m16,r16
+ TEST ; r/m32/r32
+ VERR ; r/m16
+ VERW ; r/m16
+ WAIT
+ WBINVD
+ XADD ; r/m8,r8
+ XADD ; r/m16,r16
+ XADD ; r/m32,r32
+ XCHG ; AX,r16
+ XCHG ; EAX,r32
+ XCHG ; r/m8,r8
+ XCHG ; r/m16,r16
+ XCHG ; r/m32,r32
+ XLAT ; [segreg:]m8
+ XLATB
+ XOR ; general
diff --git a/as/asm/xchg.asm b/as/asm/xchg.asm
new file mode 100644
index 0000000..f05157f
--- /dev/null
+++ b/as/asm/xchg.asm
@@ -0,0 +1,103 @@
+ XCHG AX,BL ; illeg
+ XCHG AX,BYTE [BX] ; illeg
+ XCHG AX,DS ; illeg
+ XCHG AX,#1 ; illeg
+
+ XCHG AX,AX
+ XCHG AX,BX
+ XCHG AX,CX
+ XCHG AX,DX
+ XCHG AX,SP
+ XCHG AX,BP
+ XCHG AX,SI
+ XCHG AX,DI
+
+ XCHG AX,AX
+ XCHG BX,AX
+ XCHG CX,AX
+ XCHG DX,AX
+ XCHG SP,AX
+ XCHG BP,AX
+ XCHG SI,AX
+ XCHG DI,AX
+
+ XCHG EAX,EAX
+ XCHG EAX,EBX
+ XCHG EAX,ECX
+ XCHG EAX,EDX
+ XCHG EAX,ESP
+ XCHG EAX,EBP
+ XCHG EAX,ESI
+ XCHG EAX,EDI
+
+ XCHG EAX,EAX
+ XCHG EBX,EAX
+ XCHG ECX,EAX
+ XCHG EDX,EAX
+ XCHG ESP,EAX
+ XCHG EBP,EAX
+ XCHG ESI,EAX
+ XCHG EDI,EAX
+
+ XCHG AL,AL
+ XCHG AL,AH
+ XCHG AL,BL
+ XCHG AL,BH
+ XCHG BL,CL
+ XCHG BL,CH
+ XCHG BL,DL
+ XCHG BL,DH
+
+ XCHG [BX],AL
+ XCHG [BX],AH
+ XCHG [BX],BL
+ XCHG [BX],BH
+ XCHG [BX],CL
+ XCHG [BX],CH
+ XCHG [BX],DL
+ XCHG [BX],DH
+
+ XCHG AL,[BX]
+ XCHG AH,[BX]
+ XCHG BL,[BX]
+ XCHG BH,[BX]
+ XCHG CL,[BX]
+ XCHG CH,[BX]
+ XCHG DL,[BX]
+ XCHG DH,[BX]
+
+ XCHG [BX],AX
+ XCHG [BX],BX
+ XCHG [BX],CX
+ XCHG [BX],DX
+ XCHG [BX],SP
+ XCHG [BX],BP
+ XCHG [BX],SI
+ XCHG [BX],DI
+
+ XCHG AX,[BX]
+ XCHG BX,[BX]
+ XCHG CX,[BX]
+ XCHG DX,[BX]
+ XCHG SP,[BX]
+ XCHG BP,[BX]
+ XCHG SI,[BX]
+ XCHG DI,[BX]
+
+ XCHG [BX],EAX
+ XCHG [BX],EBX
+ XCHG [BX],ECX
+ XCHG [BX],EDX
+ XCHG [BX],ESP
+ XCHG [BX],EBP
+ XCHG [BX],ESI
+ XCHG [BX],EDI
+
+ XCHG AX,[EBX]
+ XCHG BX,[EBX]
+ XCHG CX,[EBX]
+ XCHG DX,[EBX]
+ XCHG SP,[EBX]
+ XCHG BP,[EBX]
+ XCHG SI,[EBX]
+ XCHG DI,[EBX]
diff --git a/as/assemble.c b/as/assemble.c
new file mode 100644
index 0000000..1fdef1a
--- /dev/null
+++ b/as/assemble.c
@@ -0,0 +1,309 @@
+/* assemble.c - main loop for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+
+PRIVATE bool_t nocolonlabel; /* set for labels not followed by ':' */
+PRIVATE void (*routine) P((void));
+PRIVATE pfv rout_table[] =
+{
+ pelse,
+ pelseif,
+ pelsifc,
+ pendif,
+ pif,
+ pifc,
+
+ /* start of non-conditionals */
+ palign,
+ pasciz,
+ pblkw,
+ pblock,
+ pbss,
+ pcomm,
+ pcomm1,
+ pdata,
+ pendb,
+ penter,
+ pentry,
+ pequ,
+ peven,
+ pexport,
+ pfail,
+ pfcb,
+ pfcc,
+ pfdb,
+ pfqb,
+ pget,
+ pglobl,
+ pident,
+ pimport,
+ plcomm,
+ plcomm1,
+ plist,
+ ploc,
+ pmaclist,
+ pmacro,
+ pmap,
+ porg,
+ pproceof,
+ prmb,
+ psect,
+ pset,
+ psetdp,
+ ptext,
+#ifdef I80386
+ puse16,
+ puse32,
+#endif
+ pwarn,
+ /* end of pseudo-ops */
+
+#ifdef I80386
+ mbcc,
+ mbswap,
+ mcall,
+ mcalli,
+ mdivmul,
+ menter,
+ mEwGw,
+ mExGx,
+ mf_inher,
+ mf_m,
+ mf_m2,
+ mf_m2_ax,
+ mf_m2_m4,
+ mf_m2_m4_m8,
+ mf_m4_m8_optst,
+ mf_m4_m8_st,
+ mf_m4_m8_stst,
+ mf_m4_m8_m10_st,
+ mf_m10,
+ mf_optst,
+ mf_st,
+ mf_stst,
+ mf_w_inher,
+ mf_w_m,
+ mf_w_m2,
+ mf_w_m2_ax,
+ mgroup1,
+ mgroup2,
+ mgroup6,
+ mgroup7,
+ mgroup8,
+ mGvEv,
+ mGvMa,
+ mGvMp,
+ mimul,
+ min,
+ mincdec,
+ minher,
+ minher16,
+ minher32,
+ minhera,
+ mint,
+ mjcc,
+ mjcxz,
+ mlea,
+ mmov,
+ mmovx,
+ mnegnot,
+ mout,
+ mpushpop,
+ mret,
+ mseg,
+ msetcc,
+ mshdouble,
+ mtest,
+ mxchg,
+#endif /* I80386 */
+
+#ifdef MC6809
+ mall, /* all address modes allowed, like LDA */
+ malter, /* all but immediate, like STA */
+ mimmed, /* immediate only (ANDCC, ORCC) */
+ mindex, /* indexed (LEA's) */
+ minher, /* inherent, like CLC or CLRA */
+ mlong, /* long branches */
+ mshort, /* short branches */
+ msstak, /* S-stack (PSHS, PULS) */
+ mswap, /* TFR, EXG */
+ mustak, /* U-stack (PSHU,PULU) */
+#endif /* MC6809 */
+};
+
+FORWARD void asline P((void));
+
+/*
+ This uses registers as follows: A is for work and is not preserved by
+ the subroutines.B holds the last symbol code, X usually points to data
+ about the last symbol, U usually holds the value of last expression
+ or symbol, and Y points to the current char. The value in Y is needed
+ by READCH and GETSYM. EXPRES needs B and Y, and returns a value in U.
+ If the expression starts with an identifier, X must point to its string.
+ LOOKUP needs a string pointer in X and length in A. It returns a table
+ pointer in X (unless not assembling and not found), symbol type in A
+ and overflow in CC.
+*/
+
+PUBLIC void assemble()
+{
+ while (TRUE)
+ {
+ asline();
+ if (label != NUL_PTR) /* must be confirmed if still set */
+ { /* it is nulled by EQU, COMM and SET */
+#ifndef MC6809
+#define NEEDENDLABEL ILLAB
+ if (nocolonlabel)
+ error(NEEDENDLABEL);
+#endif
+ label->type |= LABIT; /* confirm, perhaps redundant */
+ if (label->type & REDBIT)
+ {
+ /* REDBIT meant 'GLOBLBIT' while LABIT was not set. */
+ label->type |= EXPBIT;
+ label->type &= ~REDBIT;
+ }
+ if ((mcount | popflags) == 0)
+ /* unaccompanied label, display adr like EQU and SET */
+ showlabel();
+ label = NUL_PTR; /* reset for next line */
+ }
+ skipline();
+ listline();
+ genbin();
+ genobj();
+ binmbuf = lc += lcjump
+#ifdef I80386
+ + immcount
+#endif
+ ;
+ }
+}
+
+PRIVATE void asline()
+{
+ register struct sym_s *symptr;
+
+ postb = popflags = pcrflag =
+#ifdef I80386
+ sprefix = oprefix = aprefix =
+#endif
+ immcount = lastexp.data = lcjump = 0;
+#ifdef I80386
+ sib = NO_SIB;
+#endif
+#if SIZEOF_OFFSET_T > 2
+ fqflag =
+#endif
+ fdflag = fcflag = FALSE;
+ readline();
+ getsym();
+ if (sym != IDENT) /* expect label, mnemonic or macro */
+ return; /* anything else is a comment */
+ symptr = gsymptr;
+ if (!ifflag)
+ /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */
+ {
+ if (symptr == NUL_PTR || !(symptr->type & MNREGBIT) ||
+ symptr->data & REGBIT ||
+ symptr->value_reg_or_op.op.routine >= MIN_NONCOND)
+ return;
+ }
+ else if (!(symptr->type & (MACBIT | MNREGBIT)))
+ /* not macro, op, pseudo-op or register, expect label */
+ {
+ if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */
+ {
+ sym = COLON;
+ ++lineptr;
+ }
+ if (symptr->type & (LABIT | VARBIT))
+ {
+ if (symptr->type & REDBIT)
+ labelerror(RELAB);
+ label = symptr;
+ }
+ else if (checksegrel(symptr))
+ {
+ symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */
+#ifdef MC6809
+#if 0
+ if (sym == COLON)
+ symptr->type |= EXPBIT;
+#endif
+#endif
+ symptr->data = (symptr->data & FORBIT) | lcdata;
+ /* remember if forward referenced */
+ symptr->value_reg_or_op.value = lc;
+ /* unless changed by EQU,COMM or SET */
+ label = symptr;
+ }
+ getsym();
+ if (sym != IDENT)
+ {
+ if (sym == EQOP)
+ {
+ getsym();
+ pequ();
+ }
+ return; /* anything but ident is comment */
+ }
+ symptr = gsymptr;
+ }
+ if (symptr->type & MACBIT)
+ {
+ entermac(symptr);
+ return;
+ }
+ if (!(symptr->type & MNREGBIT))
+ {
+ error(OPEXP);
+ return;
+ }
+ if (symptr->data & REGBIT)
+ {
+ error(REGUID);
+ return;
+ }
+ mnsize = 0;
+ if ((page = (symptr->data & (PAGE1 | PAGE2))) != 0)
+ {
+#ifdef MNSIZE
+ if (page == (PAGE1 | PAGE2))
+ {
+ mnsize = 1;
+ page = 0;
+ }
+ else
+#endif
+ {
+#ifdef PAGE2_OPCODE
+ if (page == PAGE2)
+ page = PAGE2_OPCODE;
+ else
+#endif
+ page = PAGE1_OPCODE;
+ mcount = 1;
+ }
+ }
+ opcode = symptr->value_reg_or_op.op.opcode;
+ routine = rout_table[symptr->value_reg_or_op.op.routine];
+ getsym();
+ (*routine)();
+ if (sym != EOLSYM)
+ error(JUNK_AFTER_OPERANDS);
+#ifdef I80386
+ if (aprefix != 0)
+ ++mcount;
+ if (oprefix != 0)
+ ++mcount;
+ if (sprefix != 0)
+ ++mcount;
+#endif
+}
diff --git a/as/bin/calljmp.bin b/as/bin/calljmp.bin
new file mode 100644
index 0000000..90c022f
--- /dev/null
+++ b/as/bin/calljmp.bin
Binary files differ
diff --git a/as/bin/ea.bin b/as/bin/ea.bin
new file mode 100644
index 0000000..5edc0b0
--- /dev/null
+++ b/as/bin/ea.bin
Binary files differ
diff --git a/as/bin/each.bin b/as/bin/each.bin
new file mode 100644
index 0000000..211155f
--- /dev/null
+++ b/as/bin/each.bin
Binary files differ
diff --git a/as/bin/f.bin b/as/bin/f.bin
new file mode 100644
index 0000000..ce695a0
--- /dev/null
+++ b/as/bin/f.bin
Binary files differ
diff --git a/as/bin/fadd.bin b/as/bin/fadd.bin
new file mode 100644
index 0000000..9afa6fc
--- /dev/null
+++ b/as/bin/fadd.bin
Binary files differ
diff --git a/as/bin/farcall.bin b/as/bin/farcall.bin
new file mode 100644
index 0000000..797a87c
--- /dev/null
+++ b/as/bin/farcall.bin
Binary files differ
diff --git a/as/bin/group1.bin b/as/bin/group1.bin
new file mode 100644
index 0000000..64a01bf
--- /dev/null
+++ b/as/bin/group1.bin
Binary files differ
diff --git a/as/bin/group6.bin b/as/bin/group6.bin
new file mode 100644
index 0000000..22ff663
--- /dev/null
+++ b/as/bin/group6.bin
Binary files differ
diff --git a/as/bin/group7.bin b/as/bin/group7.bin
new file mode 100644
index 0000000..9570eee
--- /dev/null
+++ b/as/bin/group7.bin
Binary files differ
diff --git a/as/bin/imul.bin b/as/bin/imul.bin
new file mode 100644
index 0000000..2b8ea16
--- /dev/null
+++ b/as/bin/imul.bin
Binary files differ
diff --git a/as/bin/incdec.bin b/as/bin/incdec.bin
new file mode 100644
index 0000000..676e5fa
--- /dev/null
+++ b/as/bin/incdec.bin
Binary files differ
diff --git a/as/bin/inher.bin b/as/bin/inher.bin
new file mode 100644
index 0000000..b37b3eb
--- /dev/null
+++ b/as/bin/inher.bin
Binary files differ
diff --git a/as/bin/inout.bin b/as/bin/inout.bin
new file mode 100644
index 0000000..a215490
--- /dev/null
+++ b/as/bin/inout.bin
Binary files differ
diff --git a/as/bin/movspec.bin b/as/bin/movspec.bin
new file mode 100644
index 0000000..6a5ef0a
--- /dev/null
+++ b/as/bin/movspec.bin
Binary files differ
diff --git a/as/bin/pushpop.bin b/as/bin/pushpop.bin
new file mode 100644
index 0000000..f95d6b5
--- /dev/null
+++ b/as/bin/pushpop.bin
Binary files differ
diff --git a/as/bin/seg.bin b/as/bin/seg.bin
new file mode 100644
index 0000000..43445a6
--- /dev/null
+++ b/as/bin/seg.bin
Binary files differ
diff --git a/as/bin/shdouble.bin b/as/bin/shdouble.bin
new file mode 100644
index 0000000..91bda37
--- /dev/null
+++ b/as/bin/shdouble.bin
Binary files differ
diff --git a/as/bin/shift.bin b/as/bin/shift.bin
new file mode 100644
index 0000000..1e31fac
--- /dev/null
+++ b/as/bin/shift.bin
Binary files differ
diff --git a/as/bin/xchg.bin b/as/bin/xchg.bin
new file mode 100644
index 0000000..6455b67
--- /dev/null
+++ b/as/bin/xchg.bin
Binary files differ
diff --git a/as/byteord.h b/as/byteord.h
new file mode 100644
index 0000000..a0d14e1
--- /dev/null
+++ b/as/byteord.h
@@ -0,0 +1,18 @@
+/* byteord.h - byte order dependencies for C compiler, assembler, linker */
+
+/* These are for the targets of everything and for linker source too. */
+
+#ifdef I8086
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */
+#endif
+
+#ifdef I80386
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0
+#endif
+
+#ifdef MC6809
+# define BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
diff --git a/as/chk b/as/chk
new file mode 100755
index 0000000..89c73de
--- /dev/null
+++ b/as/chk
@@ -0,0 +1,9 @@
+for i in `ls asm/*.asm`
+do
+ j=`basename $i .asm`
+ ./as asm/$j.asm -b $j.bin -o $j.obj > /dev/null
+ cmp $j.bin bin/$j.bin
+ cmp $j.obj obj1/$j.obj
+ rm $j.bin $j.obj
+done
+
diff --git a/as/const.h b/as/const.h
new file mode 100644
index 0000000..4aa68a1
--- /dev/null
+++ b/as/const.h
@@ -0,0 +1,409 @@
+#define align(x) /* ((x) = ((int) (x) + (4-1)) & ~(4-1)) */
+#define LOW_BYTE 0 /* must be changed for big-endian */
+
+/* const.h - constants for assembler */
+
+/* major switches */
+
+#define I80386 /* generate 80386 code */
+#undef MC6809 /* generate 6809 code */
+#define MNSIZE /* allow byte size in mnemonic, e.g. "movb" */
+#undef SOS_EDOS /* source OS is EDOS */
+
+/* defaults */
+
+#define DIRCHAR '/' /* character separating filename from dir */
+#define INBUFSIZE 8192
+#define SOS_EOLSTR "\012"
+
+/* defaults modified by switches */
+
+#ifdef SOS_EDOS
+# undef INBUFSIZE
+# define INBUFSIZE 512
+# undef SOS_EOLSTR
+# define SOS_EOLSTR "\015\012"
+# define STAKSIZ 256 /* table grows up to stack less this */
+#endif
+
+/* booleans */
+
+#define FALSE 0
+#define TRUE 1
+
+/* ASCII constants */
+
+#define ETB 23
+
+/* C tricks */
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+#define NUL_PTR ((void*)0)
+
+/* O/S constants */
+
+#define CREAT_PERMS 0666
+#define EOF (-1)
+#define STDIN 0
+#define STDOUT 1
+
+enum
+{
+/* Register codes (internal to assembler). */
+#ifdef I80386
+
+/* Index regs must be first. */
+ BPREG,
+ BXREG,
+ DIREG,
+ SIREG,
+#define MAX16BITINDREG SIREG
+
+ EAXREG,
+ EBPREG,
+ EBXREG,
+ ECXREG,
+ EDIREG,
+ EDXREG,
+ ESIREG,
+ ESPREG,
+#define MAXINDREG ESPREG
+
+ AXREG,
+ CXREG,
+ DXREG,
+ SPREG,
+
+ AHREG,
+ ALREG,
+ BHREG,
+ BLREG,
+ CHREG,
+ CLREG,
+ DHREG,
+ DLREG,
+
+ CSREG,
+ DSREG,
+ ESREG,
+ FSREG,
+ GSREG,
+ SSREG,
+
+ CR0REG,
+ CR2REG,
+ CR3REG,
+ DR0REG,
+ DR1REG,
+ DR2REG,
+ DR3REG,
+ DR6REG,
+ DR7REG,
+ TR3REG,
+ TR4REG,
+ TR5REG,
+ TR6REG,
+ TR7REG,
+
+ ST0REG,
+ ST1REG,
+ ST2REG,
+ ST3REG,
+ ST4REG,
+ ST5REG,
+ ST6REG,
+ ST7REG,
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* Index regs must be first, then PC. */
+ SREG,
+ UREG,
+ XREG,
+ YREG,
+#define MAXINDREG YREG
+
+ PCREG,
+ AREG,
+ BREG,
+ CCREG,
+ DPREG,
+ DREG,
+#endif /* MC6809 */
+
+ NOREG
+};
+
+#ifdef I80386
+enum
+{
+/* Type and size keywords. */
+ BYTEOP,
+ DWORDOP,
+ FWORDOP,
+ FAROP,
+ PTROP,
+ PWORDOP,
+ QWORDOP,
+ TBYTEOP,
+ WORDOP
+};
+#endif /* I80386 */
+
+/* special chars */
+
+#define EOL 0
+#define MACROCHAR '?'
+
+enum
+{
+/* Symbol codes. */
+
+/* The first 2 must be from chars in identifiers. */
+ IDENT,
+ INTCONST,
+
+/* The next few are best for other possibly-multi-char tokens. */
+ ADDOP, /* also ++ */
+ BINCONST,
+ CHARCONST,
+ GREATERTHAN, /* also >> and context-sensitive */
+ HEXCONST,
+ LESSTHAN, /* also << and context-sensitive */
+ SUBOP, /* also -- */
+ WHITESPACE,
+
+ ANDOP,
+ COMMA,
+ EOLSYM,
+ EQOP,
+ IMMEDIATE,
+ INDIRECT,
+ LBRACKET,
+ LPAREN,
+ MACROARG,
+ NOTOP,
+ OROP,
+ OTHERSYM,
+ POSTINCOP,
+ PREDECOP,
+ RBRACKET,
+ RPAREN,
+ SLASH, /* context-sensitive */
+ SLOP,
+ SROP,
+ STAR, /* context-sensitive */
+ STRINGCONST,
+ COLON
+};
+
+enum
+{
+/* Error codes. */
+
+/* Syntax errors. */
+ COMEXP,
+ DELEXP,
+ FACEXP,
+ IREGEXP,
+ LABEXP,
+ LPEXP,
+ OPEXP,
+ RBEXP,
+ REGEXP,
+ RPEXP,
+ SPEXP,
+
+/* Expression errors. */
+ ABSREQ,
+ NONIMPREQ,
+ RELBAD,
+
+/* Label errors. */
+ ILLAB,
+ MACUID,
+ MISLAB,
+ MNUID,
+ REGUID,
+ RELAB,
+ UNBLAB,
+ UNLAB,
+ VARLAB,
+
+/* Addressing errors. */
+ ABOUNDS,
+ DBOUNDS,
+ ILLMOD,
+ ILLREG,
+
+/* Control structure errors. */
+ ELSEBAD,
+#define ELSEIFBAD ELSEBAD
+ ENDBBAD,
+#define ENDIFBAD ELSEBAD
+ EOFBLOCK,
+ EOFIF,
+ EOFLC,
+ EOFMAC,
+ FAILERR,
+
+/* Overflow errors. */
+ BLOCKOV,
+ BWRAP,
+ COUNTOV,
+ COUNTUN,
+ GETOV,
+ IFOV,
+
+ LINLONG,
+ MACOV,
+ OBJSYMOV,
+ OWRITE,
+ PAROV,
+ SYMOV,
+ SYMOUTOV,
+
+/* I/O errors. */
+ OBJOUT,
+
+/* Miscellaneous errors. */
+ AL_AX_EAX_EXP,
+ CTLINS,
+ FURTHER,
+ ILL_IMM_MODE,
+ ILL_IND_TO_IND,
+ ILL_IND,
+ ILL_IND_PTR,
+ ILL_SCALE,
+ ILL_SECTION,
+ ILL_SEG_REG,
+ ILL_SOURCE_EA,
+ ILL_SIZE,
+ IMM_REQ,
+ INDEX_REG_EXP,
+ IND_REQ,
+ MISMATCHED_SIZE,
+ NOIMPORT,
+ REENTER,
+ REL_REQ,
+ REPEATED_DISPL,
+ SEGREL,
+ SEG_REG_REQ,
+ SIZE_UNK,
+ UNKNOWN_ESCAPE_SEQUENCE,
+
+ FP_REG_REQ,
+ FP_REG_NOT_ALLOWED,
+ ILL_FP_REG,
+ ILL_FP_REG_PAIR,
+ JUNK_AFTER_OPERANDS,
+
+ ALREADY,
+
+/* Warnings. */
+#define MINWARN SHORTB
+ SHORTB
+};
+
+/* symbol table entry */
+
+ /* type entry contains following flags */
+#define ENTBIT (1<<0) /* entry point (= OBJ_N_MASK) */
+#define COMMBIT (1<<1) /* common */
+#define LABIT (1<<2) /* label (a PC location or defined by EQU) */
+#define MNREGBIT (1<<3) /* mnemonic for op or pseudo-op, or register */
+#define MACBIT (1<<4) /* macro */
+#define REDBIT (1<<5) /* redefined (if with LABIT or VARBIT), to do
+ * with SA_MASK (if with COMMBIT), otherwise
+ * means globl */
+#define VARBIT (1<<6) /* variable (i.e. something defined by SET) */
+#define EXPBIT (1<<7) /* exported (= OBJ_E_MASK) */
+
+ /* data entry contains following flags, valid */
+ /* for expressions as well as syms */
+#define PAGE1 (1<<0) /* page 1 machine op = MNREGBIT | PAGE1 */
+#define PAGE2 (1<<1) /* page 2 machine op = MNREGBIT | PAGE2 */
+#define REGBIT (1<<2) /* register = MNREGBIT | REGBIT */
+#define SIZEBIT (1<<3) /* sizing mnemonic = MNREGBIT | SIZEBIT */
+#define SEGM 0x0F /* 1st 4 bits reused for segment if !MNREGBIT */
+#define RELBIT (1<<4) /* relative (= OBJ_A_MASK) */
+#define FORBIT (1<<5) /* forward referenced */
+#define IMPBIT (1<<6) /* imported (= OBJ_I_MASK) */
+#define UNDBIT (1<<7) /* undefined */
+
+/* object code format (Introl) */
+
+#define OBJ_SEGSZ_TWO 0x02 /* size 2 code for segment size descriptor */
+
+#define OBJ_MAX_ABS_LEN 64 /* max length of chunk of absolute code */
+
+#define OBJ_ABS 0x40 /* absolute code command */
+#define OBJ_OFFSET_REL 0x80 /* offset relocation command */
+#define OBJ_SET_SEG 0x20 /* set segment command */
+#define OBJ_SKIP_1 0x11 /* skip with 1 byte count */
+#define OBJ_SKIP_2 0x12 /* skip with 2 byte count */
+#define OBJ_SKIP_4 0x13 /* skip with 4 byte count */
+#define OBJ_SYMBOL_REL 0xC0 /* symbol relocation command */
+
+#define OBJ_A_MASK 0x10 /* absolute bit(symbols) */
+#if OBJ_A_MASK - RELBIT /* must match internal format (~byte 1 -> 0) */
+oops - RELBIT misplaced
+#endif
+#define OBJ_E_MASK 0x80 /* exported bit (symbols) */
+#if OBJ_E_MASK - EXPBIT /* must match internal format (byte 0 -> 0) */
+oops - EXPBIT misplaced
+#endif
+#define OBJ_I_MASK 0x40 /* imported bit (symbols) */
+#if OBJ_I_MASK - IMPBIT /* must match internal format (byte 1 -> 0) */
+oops - IMPBIT misplaced
+#endif
+#define OBJ_N_MASK 0x01 /* entry bit (symbols) */
+#if OBJ_N_MASK - ENTBIT /* must match internal format (byte 0 -> 1) */
+oops - ENTBIT misplaced
+#endif
+#define OBJ_SA_MASK 0x20 /* size allocation bit (symbols) */
+#define OBJ_SZ_ONE 0x40 /* size one code for symbol value */
+#define OBJ_SZ_TWO 0x80 /* size two code for symbol value */
+#define OBJ_SZ_FOUR 0xC0 /* size four code for symbol value */
+
+#define OBJ_R_MASK 0x20 /* PC-rel bit (off & sym reloc commands) */
+#define OBJ_SEGM_MASK 0x0F /* segment mask (symbols, off reloc command) */
+
+#define OBJ_OF_MASK 0x03 /* offset size code for symbol reloc */
+#define OBJ_S_MASK 0x04 /* symbol number size code for symbol reloc */
+
+#define SYMLIS_NAMELEN 26
+#define SYMLIS_LEN (sizeof (struct sym_listing_s))
+
+#define FILNAMLEN 64 /* max length of a file name */
+#define LINLEN 256 /* max length of input line */
+#define LINUM_LEN 5 /* length of formatted line number */
+
+#define SPTSIZ 1024 /* number of symbol ptrs */
+ /* pseudo-op flags */
+#define POPHI 1 /* set to print hi byte of adr */
+#define POPLO 2 /* to print lo byte of ADR */
+#define POPLC 4 /* to print LC */
+#define POPLONG 8 /* to print high word of ADR */
+#define MAXBLOCK 8 /* max nesting level of BLOCK stack */
+#define MAXGET 8 /* max nesting level of GET stack */
+#define MAXIF 8 /* max nesting level of IF stack */
+#define MACPSIZ (128 / sizeof (struct schain_s))
+ /* size of macro param buffer */
+#define MAXMAC 8 /* max nesting level of macro stack */
+#define NLOC 16 /* number of location counters */
+#ifdef I80386
+#define NO_SIB 0340 /* illegal sib (3 with 4) to mean no sib */
+#endif
+
+/* special segments */
+
+#define BSSLOC 3
+#define DATALOC 3
+#define DPLOC 2
+#define STRLOC 1
+#define TEXTLOC 0
diff --git a/as/error.c b/as/error.c
new file mode 100644
index 0000000..9493790
--- /dev/null
+++ b/as/error.c
@@ -0,0 +1,105 @@
+/* error.c - error routines for assembler */
+
+#include "const.h"
+#include "type.h"
+
+#ifdef STDC_HEADERS_MISSING
+char *strcpy P((char *s1, const char *s2));
+#else
+#include <string.h>
+#endif
+
+PRIVATE char *errormessage[] =
+{
+ "comma expected",
+ "delimiter expected",
+ "factor expected",
+ "index register expected",
+ "label expected",
+ "left parentheses expected",
+ "opcode expected",
+ "right bracket expected",
+ "register expected",
+ "right parentheses expected",
+ "space expected",
+ "absolute expression required",
+ "non-imported expression required",
+ "relocation impossible",
+ "illegal label",
+ "MACRO used as identifier",
+ "missing label",
+ "opcode used as identifier",
+ "register used as identifier",
+ "redefined label",
+ "unbound label",
+ "undefined label",
+ "variable used as label",
+ "address out of bounds",
+ "data out of bounds",
+ "illegal address mode",
+ "illegal register",
+ "no matching IF",
+ "no matching BLOCK",
+ "end of file in BLOCK",
+ "end of file in IF",
+ "location counter was undefined at end",
+ "end of file in MACRO",
+ "user-generated error",
+ "BLOCK stack overflow",
+ "binary file wrap-around",
+ "counter overflow",
+ "counter underflow",
+ "GET stack overflow",
+ "IF stack overflow",
+ "line too long",
+ "MACRO stack overflow",
+ "object symbol table overflow",
+ "program overwrite",
+ "parameter table overflow",
+ "symbol table overflow",
+ "output symbol table overflow",
+ "error writing object file",
+ "al, ax or eax expected",
+ "control character in string",
+ "futher errors suppressed",
+ "illegal immediate mode",
+ "illegal indirect to indirect",
+ "illegal indirection",
+ "illegal indirection from previous 'ptr'",
+ "illegal scale",
+ "illegal section",
+ "illegal segment register",
+ "illegal source effective address",
+ "illegal size",
+ "immediate expression expected",
+ "index register expected",
+ "indirect expression required",
+ "mismatched size",
+ "no imports with binary file output",
+ "multiple ENTER pseudo-ops",
+ "relative expression required",
+ "repeated displacement",
+ "segment or relocatability redefined",
+ "segment register required",
+ "size unknown",
+ "unknown escape sequence",
+ "FP register required",
+ "FP register not allowed",
+ "illegal FP register",
+ "illegal FP register pair",
+ "junk after operands",
+ "already defined",
+ "short branch would do",
+ "unknown error",
+};
+
+/* build null-terminated error message for given error at given spot */
+
+PUBLIC char *build_error_message(errnum, buf)
+error_pt errnum;
+char *buf;
+{
+ if (errnum >= sizeof errormessage / sizeof errormessage[0])
+ errnum = sizeof errormessage / sizeof errormessage[0] - 1;
+ return strcpy(buf, errormessage[errnum]);
+}
diff --git a/as/express.c b/as/express.c
new file mode 100644
index 0000000..54dff2f
--- /dev/null
+++ b/as/express.c
@@ -0,0 +1,382 @@
+/* express.c - expression handler for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "globvar.h"
+#include "scan.h"
+#include "source.h"
+
+FORWARD void experror P((error_pt errnum));
+FORWARD void expundefined P((void));
+FORWARD void simple2 P((void));
+FORWARD void simple P((void));
+FORWARD void term P((void));
+FORWARD void factor2 P((void));
+
+PUBLIC void absexpres()
+{
+ expres();
+ chkabs();
+}
+
+/* check lastexp.data is abs */
+
+PUBLIC void chkabs()
+{
+ if (lastexp.data & RELBIT)
+ {
+ if (pass != 0)
+ error(ABSREQ);
+ expundefined();
+ }
+}
+
+PRIVATE void experror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ expundefined();
+}
+
+PRIVATE void expundefined()
+{
+ lastexp.data = FORBIT | UNDBIT;
+}
+
+PUBLIC void nonimpexpres()
+{
+ expres();
+ if (lastexp.data & IMPBIT)
+ experror(NONIMPREQ);
+}
+
+/* generate relocation error if pass 2, make lastexp.data forward&undefined */
+
+PUBLIC void showrelbad()
+{
+ if (pass != 0)
+ error(RELBAD);
+ expundefined();
+}
+
+PUBLIC void symabsexpres()
+{
+ getsym();
+ absexpres();
+}
+
+PUBLIC void symexpres()
+{
+ getsym();
+ expres();
+}
+
+/*
+ expres() parses expression = simple expression [op simple expression],
+ where op is =, < or >.
+ Parameters: sym, number in number, identifier from symname to lineptr - 1.
+ Returns value in lastexp.
+*/
+
+PUBLIC void expres()
+{
+ offset_t leftoffset;
+
+ simple();
+ leftoffset = lastexp.offset;
+ if (sym == EQOP)
+ {
+ simple2();
+ if (leftoffset == lastexp.offset)
+ lastexp.offset = -1;
+ else
+ lastexp.offset = 0;
+ }
+ else if (sym == LESSTHAN)
+ {
+ /* context-sensitive, LESSTHAN really means less than here */
+ simple2();
+ if (leftoffset < lastexp.offset)
+ lastexp.offset = -1;
+ else
+ lastexp.offset = 0;
+ }
+ else if (sym == GREATERTHAN)
+ {
+ /* context-sensitive, GREATERTHAN really means greater than here */
+ simple2();
+ if (leftoffset > lastexp.offset)
+ lastexp.offset = -1;
+ else
+ lastexp.offset = 0;
+ }
+}
+
+/* get symbol and 2nd simple expression, check both rel or both abs */
+
+PRIVATE void simple2()
+{
+ unsigned char leftdata;
+
+ leftdata = lastexp.data;
+ getsym();
+ simple();
+ if ((leftdata | lastexp.data) & IMPBIT ||
+ (leftdata ^ lastexp.data) & (RELBIT | SEGM))
+ showrelbad();
+ else
+ lastexp.data = (leftdata & lastexp.data) & ~(RELBIT | SEGM);
+}
+
+/*
+ simple() parses simple expression = [+-] term {op term},
+ where op is +, -, or \ (OR).
+*/
+
+PRIVATE void simple()
+{
+ offset_t leftoffset;
+ unsigned char leftdata;
+
+ if (sym == ADDOP || sym == SUBOP)
+ lastexp.data = lastexp.offset = 0;
+ else
+ term();
+ while (TRUE)
+ {
+ leftoffset = lastexp.offset;
+ leftdata = lastexp.data;
+ if (sym == ADDOP)
+ {
+ getsym();
+ term();
+ if (leftdata & lastexp.data & RELBIT)
+ showrelbad(); /* rel + rel no good */
+ else
+ lastexp.data |= leftdata;
+ lastexp.offset += leftoffset;
+ }
+ else if (sym == SUBOP)
+ {
+ getsym();
+ term();
+ /* check not abs - rel or rel - rel with mismatch */
+ if (lastexp.data & RELBIT &&
+ (!(leftdata & RELBIT) ||
+ (leftdata | lastexp.data) & IMPBIT ||
+ (leftdata ^ lastexp.data) & (RELBIT | SEGM)))
+ showrelbad();
+ else
+ lastexp.data = ((leftdata | lastexp.data) & ~(RELBIT | SEGM))
+ | ((leftdata ^ lastexp.data) & (RELBIT | SEGM));
+ lastexp.offset = leftoffset - lastexp.offset;
+ }
+ else if (sym == OROP)
+ {
+ getsym();
+ term();
+ lastexp.data |= leftdata;
+ chkabs(); /* both must be absolute */
+ lastexp.offset |= leftoffset;
+ }
+ else
+ return;
+ }
+}
+
+/* term() parses term = factor {op factor}, where op is *, /, &, <<, or >>. */
+
+PRIVATE void term()
+{
+ offset_t leftoffset;
+
+ factor();
+ while (TRUE)
+ {
+ leftoffset = lastexp.offset;
+ if (sym == STAR)
+ {
+ /* context-sensitive, STAR means multiplication here */
+ factor2();
+ lastexp.offset *= leftoffset;
+ }
+ else if (sym == SLASH)
+ {
+ /* context-sensitive, SLASH means division here */
+ factor2();
+ lastexp.offset = leftoffset / lastexp.offset;
+ }
+ else if (sym == ANDOP)
+ {
+ factor2();
+ lastexp.offset &= leftoffset;
+ }
+ else if (sym == SLOP)
+ {
+ factor2();
+ lastexp.offset = leftoffset << lastexp.offset;
+ }
+ else if (sym == SROP)
+ {
+ factor2();
+ lastexp.offset = leftoffset >> lastexp.offset;
+ }
+ else
+ return;
+ }
+}
+
+/* get symbol and 2nd or later factor, check both abs */
+
+PRIVATE void factor2()
+{
+ unsigned char leftdata;
+
+ leftdata = lastexp.data;
+ getsym();
+ factor();
+ lastexp.data |= leftdata;
+ chkabs();
+}
+
+/*
+ factor() parses factor = number | identifier | * | (expression) | ! factor,
+ ! is complementation. Returns value in lastexp.offset, possible flags
+ IMPBIT, FORBIT, RELBIT and UNDBIT in lastexp.data, and segment in SEGM
+ part of lastexp.data, and lastexp.sym at imported symbol if IMPBIT.
+ If the factor is an identifier, LOOKUP is used to get its value
+ (so the ident is installed in the symbol table if necessary, with
+ default flags inidata). If the identifier is not a label,
+ (could be imported, or later in the program), its FORBIT is set.
+ The expression FORBIT, IMPBIT, RELBIT, UNDBIT and SEGM are then
+ taken from the identifier.
+*/
+
+PUBLIC void factor()
+{
+ switch (sym)
+ {
+ case SLASH:
+ /* context-sensitive, SLASH means a hex number here */
+ context_hexconst();
+ case INTCONST:
+ lastexp.data = 0; /* absolute & not forward or undefined */
+ lastexp.offset = number;
+ getsym();
+ return;
+ case IDENT:
+ {
+ register struct sym_s *symptr;
+
+ symptr = gsymptr;
+ if (symptr->type & (MNREGBIT | MACBIT))
+ experror(symptr->type & MACBIT ? MACUID :
+ symptr->data & REGBIT ? REGUID : MNUID);
+ else
+ {
+ if (!(symptr->type & (LABIT | VARBIT)))
+ {
+ symptr->data |= FORBIT;
+ lastexp.sym = symptr;
+ }
+ if (pass == 0)
+ {
+ lastexp.data = symptr->data &
+ (FORBIT | RELBIT | UNDBIT | SEGM);
+ /* possible flags for pass 1 */
+ lastexp.offset = symptr->value_reg_or_op.value;
+ }
+ else
+ {
+ if ((lastexp.data = symptr->data) & IMPBIT)
+ lastexp.offset = 0; /* value != 0 for commons */
+ /* OK even if UNDBIT */
+ else
+ {
+ lastexp.offset = symptr->value_reg_or_op.value;
+ if (lastexp.data & UNDBIT)
+ experror(UNBLAB);
+ }
+ }
+ }
+ getsym();
+ return;
+ }
+ case LBRACKET:
+ if (!asld_compatible)
+ break; /* error, LPAREN is the grouping symbol */
+ getsym();
+ expres();
+ if (sym != RBRACKET)
+ error(RBEXP);
+ else
+ getsym();
+ return;
+ case LPAREN:
+ if (asld_compatible)
+ break; /* error, LBRACKET is the grouping symbol */
+ getsym();
+ expres();
+ if (sym != RPAREN)
+ error(RPEXP);
+ else
+ getsym();
+ return;
+ case NOTOP:
+ getsym();
+ factor();
+ chkabs();
+ lastexp.offset = ~lastexp.offset;
+ return;
+ case STAR:
+ /* context-sensitive, STAR means location counter here */
+ lastexp.offset = lc;
+ if ((lastexp.data = lcdata) & UNDBIT && pass != 0)
+ experror(UNBLAB);
+ getsym();
+ return;
+ }
+ experror(FACEXP);
+}
+
+/*
+ string compare for IFC/ELSEIFC
+ expects (<string1>,<string2>)
+ returns logical value in lastexp
+*/
+
+PUBLIC void scompare()
+{
+ /* prepare flags for OK, lastexp.offset for error */
+ lastexp.data = lastexp.offset = 0;
+ if (sym != LPAREN)
+ experror(LPEXP);
+ else
+ {
+ register char *string1;
+ register char *string2;
+
+ for (string2 = string1 = lineptr; *string2 != ')'; ++string2)
+ if (*string2 == 0 || *string2 == ')')
+ {
+ symname = string2;
+ experror(COMEXP);
+ return;
+ }
+ while (*string1++ == *string2++)
+ ;
+ if (string2[-1] == ')')
+ {
+ if (string1[-1] == ',')
+ lastexp.offset = TRUE; /* else leave FALSE */
+ }
+ else /* FALSE, keep reading to verify syntax */
+ for (; *string2 != ')'; ++string2)
+ if (*string2 == 0 || *string2 == ',')
+ {
+ symname = string2;
+ experror(RPEXP);
+ }
+ }
+}
diff --git a/as/file.h b/as/file.h
new file mode 100644
index 0000000..1272d47
--- /dev/null
+++ b/as/file.h
@@ -0,0 +1,12 @@
+/* file.h - global variables involving files for assembler */
+
+EXTERN fd_t binfil; /* binary output file (0 = memory) */
+EXTERN char *filnamptr; /* file name pointer */
+EXTERN fd_t infil0; /* initial input file */
+EXTERN fd_t infil; /* current input file (stacked, 0 = memory) */
+EXTERN unsigned char infiln; /* innum when file was opened */
+EXTERN unsigned char innum; /* counter for calls to open */
+EXTERN fd_t lstfil; /* list output file (0 = standard) */
+EXTERN fd_t objfil; /* object output file */
+EXTERN fd_t symfil; /* symbol table output file */
+EXTERN char *truefilename; /* in case actual source name is a tmpname */
diff --git a/as/flag.h b/as/flag.h
new file mode 100644
index 0000000..791dcc1
--- /dev/null
+++ b/as/flag.h
@@ -0,0 +1,5 @@
+/* flag.h - global structured-flag variables for assembler */
+
+EXTERN struct flags_s list; /* listing on/off */
+EXTERN struct flags_s maclist; /* list macros on/off */
+EXTERN struct flags_s warn; /* warnings on/off */
diff --git a/as/genbin.c b/as/genbin.c
new file mode 100644
index 0000000..ce16405
--- /dev/null
+++ b/as/genbin.c
@@ -0,0 +1,220 @@
+/* genbin.c - binary code generation routines for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "file.h"
+#include "globvar.h"
+
+PRIVATE char *asmbeg; /* beginning of assembler code */
+ /* for overwrite check */
+ /* bss-init to zero = NULL and not changed */
+PRIVATE offset_t binfbuf; /* binary code buffer for file (counter) */
+PRIVATE offset_t binmax; /* maximum value of binmbuf for pass 1 */
+PRIVATE offset_t binmin; /* minimum value of binmbuf for pass 1 */
+
+FORWARD void putbinoffset P((offset_t offset, count_t size));
+
+/* write header to binary file */
+
+PUBLIC void binheader()
+{
+ if ((innum = binfil) != 0x0)
+ {
+ writec(0x0); /* binary header byte */
+#ifdef LONG_BINHEADER
+ writeoff(binmax - binmin); /* program length */
+ writeoff(binfbuf = binmin); /* program start */
+#else
+ writew((unsigned) (binmax - binmin)); /* program length */
+ writew((unsigned) (binfbuf = binmin)); /* program start */
+#endif
+ }
+}
+
+/* write trailer to binary file */
+
+PUBLIC void bintrailer()
+{
+ if ((innum = binfil) != 0x0)
+ {
+ writec(0xFF); /* binary trailer byte */
+ writew(0x0); /* further trailer bytes */
+#ifdef LONG_BINHEADER
+ writeoff(pedata & UNDBIT ? binmin : progent); /* entry point */
+#else
+ writew(pedata & UNDBIT ? (unsigned) binmin : (unsigned) progent);
+#endif
+ }
+}
+
+/* generate binary code for current line */
+
+PUBLIC void genbin()
+{
+ struct address_s *adrptr;
+ char *bufptr;
+ unsigned char remaining;
+
+ if (binaryg && mcount != 0x0)
+ {
+ if (popflags)
+ {
+ if (fcflag)
+ {
+ bufptr = databuf.fcbuf;
+ remaining = mcount;
+ do
+ putbin(*bufptr++);
+ while (--remaining != 0x0);
+ }
+ if (fdflag)
+ {
+ adrptr = databuf.fdbuf;
+ remaining = mcount;
+ do
+ {
+ putbinoffset(adrptr->offset, 0x2);
+ ++adrptr;
+ }
+ while ((remaining -= 0x2) != 0x0);
+ }
+#if SIZEOF_OFFSET_T > 0x2
+ if (fqflag)
+ {
+ adrptr = databuf.fqbuf;
+ remaining = mcount;
+ do
+ {
+ putbinoffset(adrptr->offset, 0x4);
+ ++adrptr;
+ }
+ while ((remaining -= 0x4) != 0x0);
+ }
+#endif
+ }
+ else
+ {
+ remaining = mcount - 0x1; /* count opcode immediately */
+#ifdef I80386
+ if (aprefix != 0x0)
+ {
+ putbin(aprefix);
+ --remaining;
+ }
+ if (oprefix != 0x0)
+ {
+ putbin(oprefix);
+ --remaining;
+ }
+ if (sprefix != 0x0)
+ {
+ putbin(sprefix);
+ --remaining;
+ }
+#endif
+ if (page != 0x0)
+ {
+ putbin(page);
+ --remaining;
+ }
+ putbin(opcode);
+ if (remaining != 0x0)
+ {
+ if (postb != 0x0)
+ {
+ putbin(postb);
+ --remaining;
+ }
+#ifdef I80386
+ if (sib != NO_SIB)
+ {
+ putbin(sib);
+ --remaining;
+ }
+#endif
+ if (remaining != 0x0)
+ putbinoffset(lastexp.offset, remaining);
+ }
+#ifdef I80386
+ if (immcount != 0x0)
+ putbinoffset(immadr.offset, immcount);
+#endif
+ }
+ /* else no code for this instruction, or already generated */
+ }
+}
+
+/* initialise private variables */
+
+PUBLIC void initbin()
+{
+ binmin = -1; /* greater than anything */
+}
+
+/* write char to binary file or directly to memory */
+
+PUBLIC void putbin(ch)
+opcode_pt ch;
+{
+ if (binfil != 0x0)
+ {
+ if (!binaryc) /* pass 1, just record limits */
+ {
+ if (binmbuf < binmin)
+ binmin = binmbuf;
+ if (++binmbuf > binmax)
+ binmax = binmbuf;
+ }
+ else
+ {
+ if (binfbuf > binmbuf)
+ error(BWRAP); /* file buffer ahead of memory buffer */
+ else
+ {
+ innum = binfil;
+ while (binfbuf < binmbuf)
+ {
+ writec(0x0);/* pad with nulls if file buffer behind */
+ ++binfbuf;
+ }
+ writec(ch);
+ binmbuf = ++binfbuf;
+ }
+ }
+ }
+ else if (binaryc && !(lcdata & UNDBIT))
+ /* memory output, and enabled */
+ {
+ register char *bufptr;
+
+ if ((bufptr = (char *) binmbuf) >= asmbeg && bufptr < heapptr)
+ error(OWRITE);
+ else
+ *bufptr = ch;
+ ++binmbuf;
+ }
+}
+
+/* write sized offset to binary file or directly to memory */
+
+PRIVATE void putbinoffset(offset, size)
+offset_t offset;
+count_t size;
+{
+ char buf[sizeof offset];
+
+#if SIZEOF_OFFSET_T > 0x2
+ u4cn(buf, offset, size);
+#else
+ u2cn(buf, offset, size);
+#endif
+ putbin(buf[0]);
+ if (size > 0x1)
+ putbin(buf[1]);
+ if (size > 0x2)
+ {
+ putbin(buf[2]);
+ putbin(buf[3]);
+ }
+}
diff --git a/as/genlist.c b/as/genlist.c
new file mode 100644
index 0000000..eb3b277
--- /dev/null
+++ b/as/genlist.c
@@ -0,0 +1,461 @@
+/* genlist.c - generate listing and error reports for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+#include "macro.h"
+#include "scan.h"
+#include "source.h"
+
+#ifdef STDC_HEADERS_MISSING
+void *memset P((void *s, int c, unsigned n));
+unsigned strlen P((const char *s));
+#else
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#define CODE_LIST_LENGTH (sizeof (struct code_listing_s) - 1)
+ /* length of formatted code listing */
+#define MAXERR 6 /* maximum errors listed per line */
+
+struct error_s /* to record error info */
+{
+ unsigned char errnum;
+ unsigned char position;
+};
+
+/* code listing format */
+
+struct code_listing_s
+{
+ union linum_macro_u
+ {
+ char linum[LINUM_LEN];
+ struct
+ {
+ char pad[1];
+ char mark[1];
+ char level[1];
+ }
+ macro;
+ }
+ linum_or_macro;
+ char padlinum[1];
+ char lc[4];
+ char padlc[1];
+#ifdef I80386
+ char lprefix[2];
+ char aprefix[2];
+ char oprefix[2];
+ char sprefix[2];
+#endif
+ char page[2];
+ char opcode[2];
+ char postb[2];
+#ifdef I80386
+ char sib[2];
+#endif
+ char padopcode[1];
+#if SIZEOF_OFFSET_T > 2
+ char displ4[2];
+ char displ3[2];
+#endif
+ char displ2[2];
+ char displ1[2];
+ char reldispl[1];
+ char paddispl[1];
+#ifdef I80386
+ char imm4[2];
+ char imm3[2];
+ char imm2[2];
+ char imm1[2];
+ char relimm[1];
+ char padimm[1];
+#endif
+ char nullterm;
+};
+
+PRIVATE struct error_s errbuf[MAXERR]; /* error buffer */
+PRIVATE unsigned char errcount; /* # errors in line */
+PRIVATE bool_t erroverflow; /* set if too many errors on line */
+
+FORWARD char *build_1hex_number P((opcode_pt num, char *where));
+FORWARD void list1 P((fd_t fd));
+FORWARD void listcode P((void));
+FORWARD void listerrors P((void));
+FORWARD void paderrorline P((unsigned nspaces));
+
+/* format 1 byte number as 2 hex digits, return ptr to end */
+
+PRIVATE char *build_1hex_number(num, where)
+opcode_pt num;
+register char *where;
+{
+ where[0] = hexdigit[((unsigned) num % 256) / 16];
+ where[1] = hexdigit[(unsigned) num % 16];
+ return where + 2;
+}
+
+/* format 2 byte number as 4 hex digits, return ptr to end */
+
+PUBLIC char *build_2hex_number(num, where)
+unsigned num;
+char *where;
+{
+ return build_1hex_number((opcode_pt) num,
+ build_1hex_number((opcode_pt) (num / 256), where));
+}
+
+/* format 2 byte number as decimal with given width (pad with leading '0's) */
+/* return ptr to end */
+
+PUBLIC char *build_number(num, width, where)
+unsigned num;
+unsigned width;
+register char *where;
+{
+ static unsigned powers_of_10[] = {1, 10, 100, 1000, 10000,};
+ unsigned char digit;
+ unsigned char power;
+ register unsigned power_of_10;
+
+ power = 5; /* actually 1 more than power */
+ do
+ {
+ for (digit = '0', power_of_10 = (powers_of_10 - 1)[power];
+ num >= power_of_10; num -= power_of_10)
+ ++digit;
+ if (power <= width)
+ *where++ = digit;
+ }
+ while (--power != 0);
+ return where;
+}
+
+/* record number and position of error (or error buffer overflow) */
+
+PUBLIC void error(errnum)
+error_pt errnum;
+{
+ register struct error_s *errptr;
+ register struct error_s *errptrlow;
+ unsigned char position;
+
+ if ((unsigned) errnum < MINWARN || warn.current)
+ {
+ if (errcount >= MAXERR)
+ erroverflow = TRUE;
+ else
+ {
+ position = symname - linebuf;
+ for (errptr = errbuf + errcount;
+ errptr > errbuf && errptr->position > position;
+ errptr = errptrlow)
+ {
+ errptrlow = errptr - 1;
+ errptr->errnum = errptrlow->errnum;
+ errptr->position = errptrlow->position;
+ }
+ errptr->errnum = errnum;
+ errptr->position = position;
+ ++errcount;
+ if ((unsigned)errnum >= MINWARN)
+ ++totwarn;
+ else
+ ++toterr;
+ }
+ }
+}
+
+/* list 1 line to list file if any errors or flags permit */
+/* list line to console as well if any errors and list file is not console */
+
+PUBLIC void listline()
+{
+ if (!listpre)
+ {
+ if (errcount || (list.current && (!macflag || mcount != 0)) ||
+ (macflag && maclist.current))
+ list1(lstfil);
+ if (errcount)
+ {
+ if (lstfil != STDOUT)
+ list1(STDOUT);
+ errcount = 0;
+ erroverflow = FALSE;
+ }
+ }
+}
+
+/* list 1 line unconditionally */
+
+PRIVATE void list1(fd)
+fd_t fd;
+{
+ innum = fd;
+ listcode();
+ write(innum, linebuf, (unsigned) (lineptr - linebuf));
+ writenl();
+ if (errcount != 0)
+ listerrors();
+ listpre = TRUE;
+}
+
+/* list object code for 1 line */
+
+PRIVATE void listcode()
+{
+ unsigned char count;
+ struct code_listing_s *listptr;
+ unsigned numlength;
+ char *numptr;
+
+ listptr = (struct code_listing_s *) heapptr;
+ memset((char *) listptr, ' ', sizeof *listptr);
+ listptr->nullterm = 0;
+ if (macflag)
+ {
+ listptr->linum_or_macro.macro.mark[0] = '+';
+ listptr->linum_or_macro.macro.level[0] = maclevel + ('a' - 1);
+ }
+ else
+ {
+ numlength = LINUM_LEN;
+ numptr = listptr->linum_or_macro.linum;
+ if (infiln != infil0)
+ {
+ *numptr++ = infiln - infil0 + ('a' - 1);
+ numlength = LINUM_LEN - 1;
+ }
+ build_number(linum, numlength, numptr);
+ }
+ if ((count = mcount) != 0 || popflags & POPLC)
+ build_2hex_number((u16_T) lc, listptr->lc);
+ if (popflags & POPLO)
+ {
+#if SIZEOF_OFFSET_T > 2
+ if (popflags & POPLONG)
+ build_2hex_number((u16_T) (lastexp.offset / (offset_t) 0x10000L),
+ listptr->displ4);
+#endif
+ if (popflags & POPHI)
+ build_2hex_number((u16_T) lastexp.offset, listptr->displ2);
+ else
+ build_1hex_number((opcode_pt) /* XXX */(u16_T) lastexp.offset, listptr->displ1);
+ if (lastexp.data & RELBIT)
+ listptr->reldispl[0] = '>';
+ }
+ else if (count != 0)
+ {
+#ifdef I80386
+ if (aprefix != 0)
+ {
+ --count;
+ build_1hex_number(aprefix, listptr->aprefix);
+ }
+ if (oprefix != 0)
+ {
+ --count;
+ build_1hex_number(oprefix, listptr->oprefix);
+ }
+ if (sprefix != 0)
+ {
+ --count;
+ build_1hex_number(sprefix, listptr->sprefix);
+ }
+#endif
+ if (page != 0)
+ {
+ build_1hex_number(page, listptr->page);
+ --count;
+ }
+ build_1hex_number(opcode, listptr->opcode);
+ --count;
+ if (postb != 0)
+ {
+ --count;
+ build_1hex_number(postb,
+#ifdef MC6809
+ count == 0 ? listptr->displ1 :
+#endif
+ listptr->postb);
+ }
+#ifdef I80386
+ if (sib != NO_SIB)
+ {
+ --count;
+ build_1hex_number(sib, listptr->sib);
+ }
+#endif
+ if (count > 0)
+ {
+ build_1hex_number((opcode_pt) lastexp.offset, listptr->displ1);
+ if (lastexp.data & RELBIT)
+ listptr->reldispl[0] = '>';
+ }
+ if (count > 1)
+ build_1hex_number((opcode_pt) (lastexp.offset >> 0x8),
+ listptr->displ2);
+#if SIZEOF_OFFSET_T > 2
+ if (count > 2)
+ {
+ build_1hex_number((opcode_pt) (lastexp.offset >> 0x10),
+ listptr->displ3);
+ build_1hex_number((opcode_pt) (lastexp.offset >> 0x18),
+ listptr->displ4);
+ }
+#endif
+#ifdef I80386
+ if (immcount > 0)
+ {
+ build_1hex_number((opcode_pt) immadr.offset, listptr->imm1);
+ if (immadr.data & RELBIT)
+ listptr->relimm[0] = '>';
+ }
+ if (immcount > 1)
+ build_1hex_number((opcode_pt) (immadr.offset >> 0x8),
+ listptr->imm2);
+ if (immcount > 2)
+ {
+ build_1hex_number((opcode_pt) (immadr.offset >> 0x10),
+ listptr->imm3);
+ build_1hex_number((opcode_pt) (immadr.offset >> 0x18),
+ listptr->imm4);
+ }
+#endif
+ }
+ writes((char *) listptr);
+}
+
+/* list errors, assuming some */
+
+PRIVATE void listerrors()
+{
+ unsigned char column;
+ unsigned char errcol; /* column # in error line */
+ unsigned char errcolw; /* working column in error line */
+ char *errmsg;
+ struct error_s *errptr;
+ char *linep;
+ unsigned char remaining;
+
+ paderrorline(CODE_LIST_LENGTH - LINUM_LEN);
+ remaining = errcount;
+ column = 0; /* column to match with error column */
+ errcolw = errcol = CODE_LIST_LENGTH; /* working & col number on err line */
+ errptr = errbuf;
+ linep = linebuf;
+ do
+ {
+ while (column < errptr->position)
+ {
+ ++column;
+ if (*linep++ == '\t') /* next tab (standard tabs only) */
+ errcolw = (errcolw + 8) & 0xf8;
+ else
+ ++errcolw;
+ while (errcolw > errcol)
+ {
+ writec(' ');
+ ++errcol;
+ }
+ }
+ if (errcolw < errcol) /* position under error on new line */
+ {
+ writenl();
+ paderrorline((unsigned) errcolw - LINUM_LEN);
+ }
+ writec('^');
+ writes(errmsg = build_error_message(errptr->errnum, heapptr));
+ errcol += strlen(errmsg);
+ ++errptr;
+ }
+ while (--remaining != 0);
+ writenl();
+ if (erroverflow)
+ {
+ paderrorline(CODE_LIST_LENGTH - LINUM_LEN);
+ writesn(build_error_message(FURTHER, heapptr));
+ }
+}
+
+/* pad out error line to begin under 1st char of source listing */
+
+PRIVATE void paderrorline(nspaces)
+unsigned nspaces;
+{
+ int nstars = LINUM_LEN;
+
+ while (nstars-- != 0)
+ writec('*'); /* stars under line number */
+ while (nspaces-- != 0)
+ writec(' '); /* spaces out to error position */
+}
+
+/* write 1 character */
+
+PUBLIC void writec(ch)
+char ch;
+{
+ write(innum, &ch, 1);
+}
+
+/* write newline */
+
+PUBLIC void writenl()
+{
+ writes(SOS_EOLSTR);
+}
+
+/* write 1 offset_t, order to suit target */
+
+PUBLIC void writeoff(offset)
+offset_t offset;
+{
+ char buf[sizeof offset];
+
+#if SIZEOF_OFFSET_T > 2
+ u4c4(buf, offset);
+#else
+ u2c2(buf, offset);
+#endif
+ write(innum, buf, sizeof buf);
+}
+
+/* write string */
+
+PUBLIC void writes(s)
+char *s;
+{
+ write(innum, s, strlen(s));
+}
+
+/* write string followed by newline */
+
+PUBLIC void writesn(s)
+char *s;
+{
+ writes(s);
+ writenl();
+}
+
+/* write 1 word, order to suit target */
+
+PUBLIC void writew(word)
+unsigned word;
+{
+ char buf[2];
+
+ u2c2(buf, (u16_T) word);
+ write(innum, buf, sizeof buf);
+}
diff --git a/as/genobj.c b/as/genobj.c
new file mode 100644
index 0000000..2992232
--- /dev/null
+++ b/as/genobj.c
@@ -0,0 +1,680 @@
+/* genobj.c - object code generation routines for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "file.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+char *strcpy P((char *s1, const char *s2));
+char *strrchr P((const char *s, int c));
+unsigned strlen P((const char *s));
+#else
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#define OBJBUFSIZE 512 /* size of object code output buffer */
+#define isge2byteoffset(offset) ((offset) >= 0x100)
+#define isge4byteoffset(offset) ((offset) >= 0x10000L)
+
+PRIVATE char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */
+PRIVATE char *absbuf; /* start */
+PRIVATE char *absbufend; /* last location + 1 */
+PRIVATE char *absbufptr; /* current location */
+PRIVATE struct sym_s **arrext; /* array of external symbol ptrs */
+PRIVATE char hid_objbuf[OBJBUFSIZE]; /* object code buffer */
+PRIVATE unsigned numext; /* number of external symbols */
+PRIVATE char *objbuf; /* start */
+PRIVATE char *objbufend; /* last location + 1 */
+PRIVATE char *objbufptr; /* current location */
+PRIVATE unsigned char relsize; /* current relocation size, 0 init */
+ /* local to genobjadr, but here */
+ /* because of static re-init bug */
+PRIVATE offset_t rmbcount; /* accumulator for repeated RMB's */
+
+FORWARD void flushabs P((void));
+FORWARD void flushrmb P((void));
+FORWARD void genobjadr P((struct address_s *adrptr, int size));
+FORWARD void putobj1 P((opcode_pt ch));
+FORWARD void putobj4 P((u32_T offset));
+FORWARD void putobjoffset P((offset_t offset, count_t size));
+FORWARD void putobjword P((unsigned word));
+FORWARD void writeobj P((char *buf, unsigned count));
+
+/* accumulate RMB requests into 1 (so + and - requests cancel) */
+
+PUBLIC void accumulate_rmb(offset)
+offset_t offset;
+{
+ if (objectc)
+ {
+ flushabs();
+ rmbcount += offset;
+ }
+}
+
+/* flush absolute object code buffer to object code buffer if necessary */
+
+PRIVATE void flushabs()
+{
+ if (absbufptr > absbuf)
+ {
+ putobj1((absbufptr - absbuf) | OBJ_ABS);
+ {
+ register char *bufptr;
+
+ bufptr = absbuf;
+ do
+ putobj1(*bufptr);
+ while (++bufptr < absbufptr);
+ absbufptr = absbuf;
+ }
+ }
+}
+
+/* flush object code buffer if necessary */
+
+PUBLIC void flushobj()
+{
+ int ntowrite;
+
+ if ((ntowrite = objbufptr - objbuf) > 0)
+ {
+ if (write(objfil, objbuf, (unsigned) ntowrite) != ntowrite)
+ {
+ error(OBJOUT);
+ listline();
+ finishup();
+ }
+ objbufptr = objbuf;
+ }
+}
+
+/* flush RMB count if necessary */
+
+PRIVATE void flushrmb()
+{
+ count_t size;
+
+ if (rmbcount != 0)
+ {
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(rmbcount))
+ {
+ putobj1(OBJ_SKIP_4);
+ size = 4;
+ }
+ else
+#endif
+ if (isge2byteoffset(rmbcount))
+ {
+ putobj1(OBJ_SKIP_2);
+ size = 2;
+ }
+ else
+ {
+ putobj1(OBJ_SKIP_1);
+ size = 1;
+ }
+ putobjoffset(rmbcount, size);
+ rmbcount = 0;
+ }
+}
+
+/* generate object code for current line */
+
+/*
+ any address parameter is (regrettably) in lastexp
+ any immediate parameter is (corectly) in immadr
+*/
+
+PUBLIC void genobj()
+{
+ struct address_s *adrptr;
+ char *bufptr;
+ unsigned char remaining;
+
+ if (objectc && mcount != 0)
+ {
+ if (popflags)
+ {
+ if (fcflag)
+ {
+ bufptr = databuf.fcbuf;
+ remaining = mcount;
+ do
+ putabs(*bufptr++);
+ while (--remaining != 0);
+ }
+ if (fdflag)
+ {
+ adrptr = databuf.fdbuf;
+ remaining = mcount;
+ do
+ genobjadr(adrptr++, 2);
+ while ((remaining -= 2) != 0);
+ }
+#if SIZEOF_OFFSET_T > 2
+ if (fqflag)
+ {
+ adrptr = databuf.fqbuf;
+ remaining = mcount;
+ do
+ genobjadr(adrptr++, 4);
+ while ((remaining -= 4) != 0);
+ }
+#endif
+ }
+ else
+ {
+ remaining = mcount - 1; /* count opcode immediately */
+#ifdef I80386
+ if (aprefix != 0)
+ {
+ putabs(aprefix);
+ --remaining;
+ }
+ if (oprefix != 0)
+ {
+ putabs(oprefix);
+ --remaining;
+ }
+ if (sprefix != 0)
+ {
+ putabs(sprefix);
+ --remaining;
+ }
+#endif
+ if (page != 0)
+ {
+ putabs(page);
+ --remaining;
+ }
+ putabs(opcode);
+ if (remaining != 0)
+ {
+ if (postb != 0)
+ {
+ putabs(postb);
+ --remaining;
+ }
+#ifdef I80386
+ if (sib != NO_SIB)
+ {
+ putabs(sib);
+ --remaining;
+ }
+#endif
+ if (remaining != 0)
+ genobjadr(&lastexp, remaining);
+ }
+ }
+#ifdef I80386
+ if (immcount != 0)
+ genobjadr(&immadr, immcount);
+#endif
+ }
+}
+
+/* generate object code for current address */
+
+PRIVATE void genobjadr(adrptr, size)
+struct address_s *adrptr;
+smallcount_t size;
+{
+ unsigned char byte;
+ unsigned symnum;
+
+ if (!(adrptr->data & RELBIT))
+ {
+ /* absolute address */
+
+ char buf[sizeof(offset_t)];
+
+#if SIZEOF_OFFSET_T > 2
+ u4cn(buf, adrptr->offset, size);
+#else
+ u2cn(buf, adrptr->offset, size);
+#endif
+ putabs(buf[0]);
+ if (size > 1)
+ putabs(buf[1]);
+ if (size > 2)
+ {
+ putabs(buf[2]);
+ putabs(buf[3]);
+ }
+ }
+ else
+ {
+ /* relocatable address */
+ if (size != relsize)
+ /* set reloc size index |00|0000xx| */
+ putobj((relsize = size) == 4 ? 0x03 : relsize);
+ if (!(adrptr->data & IMPBIT))
+ {
+ /* offset relocation (known offset) */
+ putobj((adrptr->data & SEGM) | OBJ_OFFSET_REL | pcrflag);
+ putobjoffset(adrptr->offset, size);
+ }
+ else
+ {
+ /* symbol relocation (imported symbol + offset) */
+ {
+ register struct sym_s **copyptr;
+
+ for (copyptr = arrext, symnum = 0;
+ symnum < numext && *copyptr++ != adrptr->sym; ++symnum)
+ ;
+ }
+ byte = OBJ_SYMBOL_REL;
+ if (isge2byteoffset(symnum))
+ byte = OBJ_SYMBOL_REL | OBJ_S_MASK;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(adrptr->offset))
+ {
+ byte |= 0x03; /* 4 byte offset */
+ size = 4;
+ }
+ else
+#endif
+ if (isge2byteoffset(adrptr->offset))
+ {
+ byte |= 0x02; /* 2 byte offset */
+ size = 2;
+ }
+ else if (adrptr->offset != 0)
+ {
+ byte |= 0x01; /* 1 byte offset */
+ size = 1;
+ }
+ else
+ size = 0;
+ putobj(byte | pcrflag);
+ if (isge2byteoffset(symnum))
+ putobjword(symnum);
+ else
+ putobj1((opcode_pt) symnum);
+ if (adrptr->offset != 0)
+ putobjoffset(adrptr->offset, size);
+ }
+ }
+}
+
+/* initialise private variables */
+
+PUBLIC void initobj()
+{
+ absbufend = (absbufptr = absbuf = hid_absbuf) + sizeof hid_absbuf;
+ objbufend = (objbufptr = objbuf = hid_objbuf) + sizeof hid_objbuf;
+}
+
+/*
+ write header to object file
+ also build array of imported/exported symbols
+*/
+
+PUBLIC void objheader()
+{
+ static char module_header[] =
+ {
+#ifdef I80386
+ 0xA3, 0x86,
+ 1, 0,
+ (char) (0xA3 + 0x86 + 1 + 0),
+#endif
+#ifdef MC6809
+ 'S', '1', /* 2 byte magic number */
+ 0, 1, /* 2 byte number of modules in file */
+ 'S' + '1' + 0 + 1, /* 1 byte checksum */
+#endif
+ };
+ static char seg_max_sizes[] =
+ {
+ 0x55, /* all segments have maximum size 2^16 */
+ 0x55, /* this is encoded by 0b01 4 times per byte */
+ 0x55, /* other codes are 0b00 = max size 2^8 */
+ 0x55, /* 0b10 = max size 2^24, 0b11 = max 2^32 */
+ };
+ unsigned char byte;
+ register struct sym_s **copyptr;
+ struct sym_s **copytop;
+ struct sym_s **hashptr;
+ struct lc_s *lcp;
+ char module_name[FILNAMLEN + 1];
+ char *nameptr;
+ unsigned offset;
+ unsigned segsizebytes;
+ unsigned size;
+ unsigned char sizebits;
+ unsigned strsiz; /* size of object string table */
+ unsigned symosiz; /* size of object symbol table */
+ register struct sym_s *symptr;
+ u32_T textlength;
+
+ if ((objectc = objectg) == 0)
+ return;
+ writeobj(module_header, sizeof module_header);
+
+ /* calculate number of imported/exported symbols */
+ /* and lengths of symbol and string tables */
+ /* build array of imported/exported symbols */
+
+ symosiz = 0;
+ if (truefilename == NUL_PTR)
+ truefilename = filnamptr;
+ nameptr = strrchr(truefilename, DIRCHAR);
+ strcpy(module_name, nameptr != NUL_PTR ? nameptr + 1 : truefilename);
+ if ((nameptr = strrchr(module_name, '.')) != NUL_PTR)
+ *nameptr = 0;
+ strsiz = strlen(module_name) + 1;
+ align(heapptr);
+ for (hashptr = spt, arrext = copyptr = (struct sym_s **) heapptr;
+ hashptr < spt_top;)
+ if ((symptr = *hashptr++) != NUL_PTR)
+ do
+ {
+ if ((symptr->type & EXPBIT || symptr->data & IMPBIT) ||
+ (!globals_only_in_obj && symptr->name[0] != '.' &&
+ !(symptr->type & (MNREGBIT | MACBIT | VARBIT))))
+ {
+ if (copyptr >= (struct sym_s **) heapend)
+ {
+ heapptr = (char *) copyptr;
+ fatalerror(OBJSYMOV);
+ }
+ *copyptr++ = symptr;
+ strsiz += symptr->length + 1;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(symptr->value_reg_or_op.value))
+ size = 4 + 4;
+ /* 4 is size of offset into string table and flags */
+ /* 2nd 4 is for 4 byte offset */
+ else
+#endif
+ if (isge2byteoffset(symptr->value_reg_or_op.value))
+ size = 4 + 2;
+ else if (symptr->value_reg_or_op.value != 0)
+ size = 4 + 1;
+ else
+ size = 4;
+ symosiz += size;
+ ++numext;
+ }
+ }
+ while ((symptr = symptr->next) != NUL_PTR);
+ heapptr = (char *) (copytop = copyptr);
+
+ /* calculate length of text, and number of seg size bytes in header */
+
+ textlength = segsizebytes = 0;
+ lcp = lctab;
+ do
+ if (lcp->lc != 0)
+ {
+ textlength += lcp->lc; /* assuming text starts at 0 */
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(lcp->lc))
+ segsizebytes += 4;
+ else
+#endif
+ segsizebytes += 2; /* use 2 byte size if possible */
+ }
+ while (++lcp < lctabtop);
+
+/*
+ offset to text = length of header since only 1 module
+ header consists of:
+ module header sizeof module_header
+ offset to start of text 4
+ length of text 4
+ length of string area 2
+ class 1
+ revision 1
+ seg max sizes sizeof seg_max_sizes
+ seg size descriptors 4
+ seg sizes segsizebytes
+ symbol count 2
+ symbol offsets and types symosiz
+ strings strsiz
+*/
+
+ /* offset to start of text */
+
+ putobj4((u32_T) (sizeof module_header + 4 + 4 + 2 + 1 + 1 +
+ sizeof seg_max_sizes + 4 + segsizebytes + 2 +
+ symosiz) + strsiz);
+
+ /* length of text */
+
+ putobj4((u32_T) textlength);
+
+ /* length of string area */
+
+ putobjword(strsiz);
+
+ /* class and revision */
+
+ putobj1(0);
+ putobj1(0);
+
+ /* segment max sizes (constant) */
+
+ writeobj(seg_max_sizes, sizeof seg_max_sizes);
+
+ /* segment size descriptors */
+ /* produce only 0 and 2 byte sizes */
+
+ lcp = lctabtop;
+ byte = 0;
+ sizebits = OBJ_SEGSZ_TWO << 6;
+ do
+ {
+ --lcp;
+ if (lcp->lc != 0)
+ {
+ byte |= sizebits;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(lcp->lc))
+ byte |= sizebits >> 1; /* XXX - convert size 2 to size 4 */
+#endif
+ }
+ if ((sizebits >>= 2) == 0)
+ {
+ putobj1(byte);
+ byte = 0;
+ sizebits = OBJ_SEGSZ_TWO << 6;
+ }
+ }
+ while (lcp > lctab);
+
+ /* segment sizes */
+
+ do /* lcp starts at lctab */
+ if (lcp->lc != 0)
+ {
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(lcp->lc))
+ putobj4(lcp->lc);
+ else
+#endif
+ putobjword((unsigned) lcp->lc);
+ }
+ while (++lcp < lctabtop);
+
+ /* symbol count */
+
+ putobjword(numext);
+
+ /* symbol offsets and types */
+
+ offset = strlen(module_name) + 1; /* 1st symbol begins after name */
+ for (copyptr = arrext; copyptr < copytop;)
+ {
+ putobjword(offset);
+ symptr = *copyptr++;
+ byte = symptr->type & OBJ_N_MASK;
+#if SIZEOF_OFFSET_T > 2
+ if (isge4byteoffset(symptr->value_reg_or_op.value))
+ {
+ byte |= OBJ_SZ_FOUR;
+ size = 4;
+ }
+ else
+#endif
+ if (isge2byteoffset(symptr->value_reg_or_op.value))
+ {
+ byte |= OBJ_SZ_TWO;
+ size = 2;
+ }
+ else if (symptr->value_reg_or_op.value != 0)
+ {
+ byte |= OBJ_SZ_ONE;
+ size = 1;
+ }
+ else
+ size = 0;
+ if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
+ {
+ byte |= OBJ_SA_MASK;
+ symptr->data &= ~OBJ_I_MASK;
+ }
+ putobjword((unsigned)
+ (byte << 0x8) |
+ (symptr->type & OBJ_E_MASK) | /* |E|0000000| */
+ ((symptr->data & (OBJ_I_MASK | OBJ_A_MASK | OBJ_SEGM_MASK)) ^
+ /* |0|I|0|A|SEGM| */
+ RELBIT)); /* RELBIT by negative logic */
+ if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
+ symptr->data |= OBJ_I_MASK;
+ if (size != 0)
+ putobjoffset(symptr->value_reg_or_op.value, size);
+ offset += symptr->length + 1;
+ }
+
+ /* strings */
+
+ writeobj(module_name, strlen(module_name));
+ putobj1(0);
+ for (copyptr = arrext; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writeobj(symptr->name, symptr->length);
+ putobj1(0);
+ }
+ putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */
+}
+
+/* write trailer to object file */
+
+PUBLIC void objtrailer()
+{
+ if (objectc)
+ {
+ putobj(0); /* end of object file */
+ flushobj();
+ }
+}
+
+/* write char to absolute object code buffer, flush if necessary */
+
+PUBLIC void putabs(ch)
+opcode_pt ch;
+{
+ if (objectc)
+ {
+ if (rmbcount != 0)
+ flushrmb();
+ if (absbufptr >= absbufend)
+ flushabs();
+ *absbufptr++ = ch;
+ }
+}
+
+/* write char to object code buffer, flush if necessary */
+
+PUBLIC void putobj(ch)
+opcode_pt ch;
+{
+ if (objectc)
+ {
+ flushabs();
+ flushrmb();
+ putobj1(ch);
+ }
+}
+
+/* write char to object code buffer assuming nothing in absolute & rmb bufs */
+
+PRIVATE void putobj1(ch)
+opcode_pt ch;
+{
+ if (objbufptr >= objbufend)
+ flushobj();
+ *objbufptr++ = ch;
+}
+
+/* write 32 bit offset to object code buffer assuming ... */
+
+PRIVATE void putobj4(offset)
+u32_T offset;
+{
+ char buf[sizeof offset];
+
+ u4c4(buf, offset);
+ writeobj(buf, sizeof buf);
+}
+
+/* write sized offset to object code buffer assuming ... */
+
+PRIVATE void putobjoffset(offset, size)
+offset_t offset;
+count_t size;
+{
+ char buf[sizeof offset];
+
+#if SIZEOF_OFFSET_T > 2
+ u4cn(buf, offset, size);
+#else
+ u2cn(buf, offset, size);
+#endif
+ putobj1(buf[0]);
+ if (size > 1)
+ putobj1(buf[1]);
+ if (size > 2)
+ {
+ putobj1(buf[2]);
+ putobj1(buf[3]);
+ }
+}
+
+/* write word to object code buffer assuming ... */
+
+PRIVATE void putobjword(word)
+unsigned word;
+{
+ char buf[sizeof word];
+
+ u2c2(buf, word);
+ putobj1(buf[0]);
+ putobj1(buf[1]);
+}
+
+/* write several bytes to object code buffer assuming ... */
+
+PRIVATE void writeobj(buf, count)
+char *buf;
+unsigned count;
+{
+ do
+ putobj1(*buf++);
+ while (--count);
+}
diff --git a/as/gensym.c b/as/gensym.c
new file mode 100644
index 0000000..c5c6d1b
--- /dev/null
+++ b/as/gensym.c
@@ -0,0 +1,210 @@
+/* gensym.c - generate symbol table for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void *memset P((void *s, int c, unsigned n));
+int strcmp P((const char *s1, const char *s2));
+#else
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+FORWARD int printsym P((register struct sym_s *symptr, unsigned column));
+FORWARD void sort P((struct sym_s **array, struct sym_s **top,
+ bool_pt nameflag));
+
+/* sort labels in symbol table on name and value */
+/* if listing, write human-readable table to list file */
+/* if symbol file, write machine-readable tables to it */
+/* pointers become relative to start of file */
+
+PUBLIC void gensym()
+{
+ unsigned column;
+ struct sym_s **copyptr;
+ struct sym_s **copytop;
+ register struct sym_s **hashptr;
+ unsigned label_count; /* number of labels */
+ unsigned labels_length; /* length of all label strings */
+ unsigned label_stringptr; /* offset of label str from start of file */
+ register struct sym_s *symptr;
+ struct sym_s **symlptr; /* start of symbol output list */
+
+ labels_length = label_count = 0;
+
+ /* make copy of all relavant symbol ptrs on heap */
+ /* original ptrs can now be modified, but need to be an array for sort */
+
+ align(heapptr);
+ for (hashptr = spt, symlptr = copyptr = (struct sym_s **) heapptr;
+ hashptr < spt_top;)
+ if ((symptr = *hashptr++) != NUL_PTR)
+ do
+ if (!(symptr->type & (MACBIT | MNREGBIT | VARBIT)))
+ {
+ if (copyptr >= (struct sym_s **) heapend)
+ {
+ heapptr = (char *) copyptr;
+ error(SYMOUTOV); /* avoid recursive fatalerror */
+ listline(); /* the main job is OK if here */
+ goto sort_symbols;
+ }
+ *copyptr++ = symptr;
+ ++label_count;
+ labels_length += symptr->length + 3; /* 3 for type, value */
+ }
+ while ((symptr = symptr->next) != NUL_PTR);
+
+sort_symbols:
+ sort(symlptr, copyptr, TRUE); /* sort on name */
+ heapptr = (char *) (copytop = copyptr);
+ if (list.global)
+ {
+ innum = lstfil;
+ writenl();
+ writesn("Symbols:");
+ for (copyptr = symlptr, column = 0; copyptr < copytop;)
+ column = printsym(*copyptr++, column);
+ if (column != 0)
+ writenl();
+ }
+ if ((innum = symfil) != 0)
+ {
+ writew(mapnum);
+ label_count *= 2; /* now length of ptr table (2 bytes per ptr) */
+ label_stringptr = label_count + 6;
+ /* offset to current string in symbol file */
+ /* 6 is length of header */
+ labels_length += label_stringptr;
+ /* offset to ptr table sorted on value */
+ writew(labels_length + label_count);
+ /* total length of symbol file */
+ writew(label_count);
+ for (copyptr = symlptr; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writew((unsigned)
+ (symptr->next = (struct sym_s *) label_stringptr));
+ /* reuse "next" to record string position */
+ label_stringptr += symptr->length + 3;
+ }
+ for (copyptr = symlptr; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writew((unsigned) symptr->value_reg_or_op.value);
+ writec(symptr->type);
+ write(innum, symptr->name, (unsigned) (symptr->length - 1));
+ writec(symptr->name[symptr->length - 1] | 0x80);
+ }
+ sort(symlptr, copyptr, FALSE);
+ /* sort on value */
+ for (copyptr = symlptr; copyptr < copytop;)
+ {
+ symptr = *copyptr++;
+ writew((unsigned) symptr->next); /* now has string position */
+ }
+ }
+}
+
+/* print symbol nicely formatted for given column */
+
+PRIVATE int printsym(symptr, column)
+register struct sym_s *symptr;
+unsigned column;
+{
+ unsigned char length;
+ register struct sym_listing_s *listptr;
+ char *outname;
+ char *symname;
+
+ listptr = (struct sym_listing_s *) heapptr;
+ memset((char *) listptr, ' ', SYMLIS_LEN);
+ listptr->nullterm = 0;
+ if ((length = symptr->length) > SYMLIS_NAMELEN)
+ {
+ outname = listptr->name;
+ outname[length = SYMLIS_NAMELEN] = '+';
+ }
+ else
+ outname = (listptr->name + SYMLIS_NAMELEN) - length;
+ symname = symptr->name;
+ do
+ *outname++ = *symname++;
+ while (--length != 0);
+ listptr->ar[0] = symptr->data & RELBIT ? 'R' : 'A';
+ listptr->segm[0] = hexdigit[symptr->data & SEGM];
+ if (symptr->type & COMMBIT)
+ listptr->cein[0] = 'C';
+ else if (symptr->type & ENTBIT)
+ listptr->cein[0] = 'N';
+ else if (symptr->type & EXPBIT)
+ listptr->cein[0] = 'E';
+ else if (symptr->data & IMPBIT)
+ listptr->cein[0] = 'I';
+#if SIZEOF_OFFSET_T > 2
+ build_2hex_number((unsigned) (symptr->value_reg_or_op.value >> 16),
+ listptr->value);
+#endif
+ build_2hex_number((unsigned) symptr->value_reg_or_op.value,
+ listptr->value);
+ writes((char *) listptr);
+ if ((column += SYMLIS_LEN) > (80 - SYMLIS_LEN))
+ {
+ writenl();
+ column = 0;
+ }
+ return column;
+}
+
+/* shell sort symbols */
+
+PRIVATE void sort(array, top, nameflag)
+struct sym_s **array;
+struct sym_s **top;
+bool_pt nameflag;
+{
+ int gap;
+ int i;
+ int j;
+ register struct sym_s **left;
+ register struct sym_s **right;
+ int size;
+ struct sym_s *swap;
+
+ size = top - array;
+ /* choose gaps according to Knuth V3 p95 */
+ for (gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j)
+ ;
+ do
+ {
+ for (j = gap; j < size; ++j)
+ for (i = j - gap; i >= 0; i -= gap)
+ {
+ left = &array[i];
+ right = &array[i + gap];
+ if ((bool_t) nameflag)
+ {
+ if (strcmp((*left)->name, (*right)->name) <= 0)
+ break;
+ }
+ else if ((unsigned) (*left)->value_reg_or_op.value <=
+ (*right)->value_reg_or_op.value)
+ break;
+ swap = *left;
+ *left = *right;
+ *right = swap;
+ }
+ }
+ while ((gap /= 3) != 0);
+}
diff --git a/as/globvar.h b/as/globvar.h
new file mode 100644
index 0000000..f2896fb
--- /dev/null
+++ b/as/globvar.h
@@ -0,0 +1,93 @@
+/* globvar.h - global variables for assembler */
+
+/* global control and bookkeeping */
+
+EXTERN bool_t binaryc; /* current binary code flag */
+EXTERN bool_t binaryg; /* global binary code flag */
+EXTERN offset_t binmbuf; /* offset in binary code buffer for memory */
+
+EXTERN unsigned char dirpag; /* direct page */
+
+EXTERN bool_t globals_only_in_obj; /* global symbols only in object file */
+
+EXTERN bool_t jumps_long; /* make all jumps long */
+
+EXTERN unsigned char mapnum; /* global map number */
+
+EXTERN bool_t objectc; /* current object code flag */
+EXTERN bool_t objectg; /* global object code flag */
+
+EXTERN bool_t pass; /* pass, FALSE means 0, TRUE means 1 */
+
+EXTERN offset_t progent; /* program entry point */
+
+EXTERN bool_t symgen; /* generate symbol table flag */
+
+EXTERN unsigned toterr; /* total errors */
+EXTERN unsigned totwarn; /* total warnings */
+
+/* bookeeping for current line */
+
+EXTERN char *linebuf; /* buffer */
+
+/* for symbol table routines */
+
+EXTERN char *heapend; /* end of free space for symbol list */
+EXTERN char *heapptr; /* next free space in symbol list */
+EXTERN unsigned char inidata; /* init sym entry data governed by "u" flag */
+EXTERN struct sym_s **spt; /* symbol pointer table */
+EXTERN struct sym_s **spt_top; /* top of symbol ptr table */
+
+/* for translator */
+
+EXTERN struct sym_s *label; /* non-null if valid label starts line */
+EXTERN unsigned char pedata; /* shows how PROGENT bound, flags like LCDATA*/
+EXTERN unsigned char popflags; /* pseudo-op flags */
+
+/* for BLOCK stack */
+
+EXTERN struct block_s *blockstak; /* stack ptr */
+EXTERN unsigned char blocklevel; /* nesting level */
+
+/* for IF stack */
+
+EXTERN struct if_s *ifstak; /* stack ptr */
+EXTERN unsigned char iflevel; /* nesting level */
+EXTERN bool_t ifflag; /* set if assembling */
+
+/* location counters for various segments */
+
+EXTERN offset_t lc; /* location counter */
+EXTERN unsigned char lcdata; /* shows how lc is bound */
+ /* FORBIT is set if lc is forward referenced */
+ /* RELBIT is is if lc is relocat. (not ASEG) */
+EXTERN offset_t lcjump; /* lc jump between lines */
+#define mcount (((unsigned char *) &lcjump)[LOW_BYTE])
+ /* low byte of lcjump */
+EXTERN struct lc_s *lcptr; /* top of current spot in lctab */
+EXTERN struct lc_s *lctab; /* start of lctab */
+EXTERN struct lc_s *lctabtop; /* top of lctab */
+
+/* for code generator */
+
+EXTERN opsize_t mnsize; /* 1 if forced byte operand size, else 0 */
+EXTERN opcode_t page;
+EXTERN opcode_t opcode;
+EXTERN opcode_t postb; /* postbyte, 0 if none */
+EXTERN unsigned char pcrflag; /* OBJ_RMASK set if addressing is PC-relative */
+
+#ifdef I80386
+
+EXTERN opcode_t aprefix; /* address size prefix or 0 */
+EXTERN bool_t asld_compatible; /* asld compatibility flag */
+EXTERN opsize_t defsize; /* current default size */
+EXTERN opsize_t idefsize; /* initial default size */
+EXTERN opcode_t oprefix; /* operand size prefix or 0 */
+EXTERN opcode_t sprefix; /* segment prefix or 0 */
+EXTERN opcode_t sib; /* scale-index-base byte */
+
+#endif
+
+/* miscellaneous */
+
+extern char hexdigit[];
diff --git a/as/macro.c b/as/macro.c
new file mode 100644
index 0000000..37048a8
--- /dev/null
+++ b/as/macro.c
@@ -0,0 +1,174 @@
+/* macro.c - expand macros for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "macro.h"
+
+#ifdef STDC_HEADERS_MISSING
+int strncmp P((const char *s1, const char *s2, unsigned n));
+#else
+#include <string.h>
+#endif
+
+/*
+ Enter macro: stack macro and get its parameters.
+ Parameters form a linked list of null-terminated strings of form
+ next:string. The first string is the macro number in 4 bytes.
+*/
+
+PUBLIC void entermac(symptr)
+struct sym_s *symptr;
+{
+ if (maclevel >= MAXMAC)
+ error(MACOV);
+ else if (macpar + 2 > macptop)
+ error(PAROV); /* no room for 0th param */
+ /* (2 structs to fit it!) */
+ else
+ {
+ char ch;
+ struct schain_s *param1;
+ register char *reglineptr;
+ register char *stringptr;
+
+ ++maclevel;
+ (--macstak)->text = (char *) symptr->value_reg_or_op.value;
+ macstak->parameters = param1 = macpar;
+ param1->next = NUL_PTR;
+ *(stringptr = build_number(++macnum, 3, param1->string)) = 0;
+ macpar = (struct schain_s *) (stringptr + 1);
+ /* TODO: alignment */
+ getsym();
+ if (sym != LPAREN)
+ return; /* no other params */
+ reglineptr = lineptr;
+ stringptr = macpar->string;
+ while (TRUE)
+ {
+ if (stringptr >= (char *) macptop)
+ {
+ symname = reglineptr;
+ error(PAROV);
+ return;
+ }
+ ch = *reglineptr++;
+ if (ch == '/')
+ /* escaped means no special meaning for slash, comma, paren */
+ ch = *reglineptr++;
+ else if (ch == ',' || ch == ')')
+ {
+ if (stringptr >= (char *) macptop)
+ {
+ symname = reglineptr;
+ error(PAROV); /* no room for null */
+ return;
+ }
+ *stringptr = 0;
+ param1->next = macpar; /* ptr from previous */
+ (param1 = macpar)->next = NUL_PTR;
+ /* this goes nowhere */
+ macpar = (struct schain_s *) (stringptr + 1);
+ /* but is finished OK - TODO align */
+ stringptr = macpar->string;
+ if (ch == ')')
+ return;
+ continue;
+ }
+ if ((*stringptr++ = ch) == 0)
+ {
+ symname = reglineptr;
+ error(RPEXP);
+ return;
+ }
+ }
+ }
+}
+
+/* MACRO pseudo-op */
+
+PUBLIC void pmacro()
+{
+ bool_t saving;
+ bool_t savingc;
+ struct sym_s *symptr=0;
+
+ saving = /* prepare for bad macro */
+ savingc = FALSE; /* normally don't save comments */
+ macload = TRUE; /* show loading */
+ if (label != NUL_PTR)
+ error(ILLAB);
+ else if (sym != IDENT)
+ error(LABEXP);
+ else
+ {
+ symptr = gsymptr;
+ if (symptr->type & MNREGBIT)
+ error(LABEXP);
+ else if (symptr->type & LABIT || symptr->data & FORBIT)
+ error(RELAB);
+ else if (pass == 0 || symptr->type & REDBIT)
+ /* copy on pass 0, also pass 1 if redefined */
+ {
+ saving = TRUE;
+ if (symptr->type & MACBIT)
+ symptr->type |= REDBIT;
+ else
+ symptr->type |= MACBIT;
+ symptr->data = UNDBIT; /* undefined till end */
+ symptr->value_reg_or_op.value = (unsigned) heapptr;
+ /* beginning of store for macro */
+ /* value s.b. (char *) */
+ getsym_nolookup(); /* test for "C" */
+ if (sym == IDENT && lineptr == symname + 1 && *symname == 'C')
+ savingc = TRUE;
+ }
+ }
+ while (TRUE)
+ {
+ skipline();
+ listline();
+ readline();
+ if (!macload)
+ break; /* macload cleared to show eof */
+ getsym_nolookup();
+ if (sym == IDENT)
+ {
+ if (lineptr == symname + 4 && strncmp(symname, "MEND", 4) == 0)
+ break;
+ }
+ else if (sym != MACROARG)
+ {
+ if (!savingc)
+ continue; /* don't save comment */
+ }
+ if (!saving)
+ continue;
+ {
+ register char *reglineptr;
+ register char *regheapptr;
+
+ reglineptr = linebuf;
+ regheapptr = heapptr;
+ do
+ {
+ if (regheapptr >= heapend)
+ {
+ heapptr = regheapptr;
+ fatalerror(SYMOV); /* won't fit */
+ }
+ }
+ while ((*regheapptr++ = *reglineptr++) != EOLCHAR);
+ heapptr = regheapptr;
+ }
+ }
+ macload = FALSE;
+ if (saving)
+ {
+ *heapptr++ = ETB;
+ symptr->data = 0;
+ }
+}
diff --git a/as/macro.h b/as/macro.h
new file mode 100644
index 0000000..c37bd00
--- /dev/null
+++ b/as/macro.h
@@ -0,0 +1,10 @@
+/* macro.h - global variables for macro expansion for assembler */
+
+EXTERN bool_t macflag; /* inside macro flag */
+EXTERN bool_t macload; /* loading macro flag */
+EXTERN unsigned macnum; /* macro call counter */
+
+EXTERN unsigned char maclevel; /* nesting level */
+EXTERN struct schain_s *macpar; /* parameter save buffer */
+EXTERN struct schain_s *macptop; /* top of param buffer (+1) */
+EXTERN struct macro_s *macstak; /* stack ptr */
diff --git a/as/mops.c b/as/mops.c
new file mode 100644
index 0000000..38b8a69
--- /dev/null
+++ b/as/mops.c
@@ -0,0 +1,2835 @@
+/* mops.c - handle pseudo-ops */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "address.h"
+
+#define is8bitadr(offset) ((offset_t) offset < 0x100)
+#define is8bitsignedoffset(offset) ((offset_t) (offset) + 0x80 < 0x100)
+#define pass2 pass
+
+FORWARD void mshort2 P((void));
+FORWARD reg_pt regchk P((void));
+FORWARD void reldata P((void));
+
+#ifdef I80386
+
+#define iswordadr(offset) ((offset_t) (offset) < 0x10000L)
+#define iswordoffset(offset) ((offset_t) (offset) + 0x8000L < 0x10000L)
+#define iswordorswordoffset(offset) ((offset_t) (offset) + 0xFFFFL < 0x1FFFEL)
+
+#define BYTE_SEGWORD 0x00
+#define isspecreg(r) ((r) >= CR0REG && (r) <= TR7REG)
+
+#define BASE_MASK 0x07
+#define BASE_SHIFT 0
+#define INDEX_MASK 0x38
+#define INDEX_SHIFT 3
+#define MOD_MASK 0xC0
+# define REG_MOD 0xC0
+# define MEM0_MOD 0x00
+# define MEM1_MOD 0x40
+# define MEM2_MOD 0x80
+#define REG_MASK 0x38
+#define REG_SHIFT 3
+#define RM_MASK 0x07
+#define RM_SHIFT 0
+# define D16_RM 0x06
+# define D32_RM 0x05
+# define SIB_NOBASE 0x05
+# define SIB_RM 0x04
+#define SREG_MASK 0x38
+#define SREG_SHIFT 3
+#define SS_MASK 0xC0
+#define SS_SHIFT 6
+
+#define SEGMOV 0x04
+#define SIGNBIT 0x02
+#define TOREGBIT 0x02
+#define WORDBIT 0x01
+
+PRIVATE opcode_t baseind16[] =
+{
+ 0x00, /* BP + BP, illegal */
+ 0x00, /* BX + BP, illegal */
+ 0x03, /* DI + BP */
+ 0x02, /* SI + BP */
+ 0x00, /* BP + BX, illegal */
+ 0x00, /* BX + BX, illegal */
+ 0x01, /* DI + BX */
+ 0x00, /* SI + BX */
+ 0x03, /* BP + DI */
+ 0x01, /* BX + DI */
+ 0x00, /* DI + DI, illegal */
+ 0x00, /* SI + DI, illegal */
+ 0x02, /* BP + SI */
+ 0x00, /* BX + SI */
+ 0x00, /* DI + SI, illegal */
+ 0x00, /* SI + SI, illegal */
+};
+
+PRIVATE opcode_t regbits[] =
+{
+ 0x05 << REG_SHIFT, /* BP */
+ 0x03 << REG_SHIFT, /* BX */
+ 0x07 << REG_SHIFT, /* DI */
+ 0x06 << REG_SHIFT, /* SI */
+
+ 0x00 << REG_SHIFT, /* EAX */
+ 0x05 << REG_SHIFT, /* EBP */
+ 0x03 << REG_SHIFT, /* EBX */
+ 0x01 << REG_SHIFT, /* ECX */
+ 0x07 << REG_SHIFT, /* EDI */
+ 0x02 << REG_SHIFT, /* EDX */
+ 0x06 << REG_SHIFT, /* ESI */
+ 0x04 << REG_SHIFT, /* ESP */
+
+ 0x00 << REG_SHIFT, /* AX */
+ 0x01 << REG_SHIFT, /* CX */
+ 0x02 << REG_SHIFT, /* DX */
+ 0x04 << REG_SHIFT, /* SP */
+
+ 0x04 << REG_SHIFT, /* AH */
+ 0x00 << REG_SHIFT, /* AL */
+ 0x07 << REG_SHIFT, /* BH */
+ 0x03 << REG_SHIFT, /* BL */
+ 0x05 << REG_SHIFT, /* CH */
+ 0x01 << REG_SHIFT, /* CL */
+ 0x06 << REG_SHIFT, /* DH */
+ 0x02 << REG_SHIFT, /* DL */
+
+ 0x01 << REG_SHIFT, /* CS */
+ 0x03 << REG_SHIFT, /* DS */
+ 0x00 << REG_SHIFT, /* ES */
+ 0x04 << REG_SHIFT, /* FS */
+ 0x05 << REG_SHIFT, /* GS */
+ 0x02 << REG_SHIFT, /* SS */
+
+ 0x00 << REG_SHIFT, /* CR0 */
+ 0x02 << REG_SHIFT, /* CR2 */
+ 0x03 << REG_SHIFT, /* CR3 */
+
+ 0x00 << REG_SHIFT, /* DR0 */
+ 0x01 << REG_SHIFT, /* DR1 */
+ 0x02 << REG_SHIFT, /* DR2 */
+ 0x03 << REG_SHIFT, /* DR3 */
+ 0x06 << REG_SHIFT, /* DR6 */
+ 0x07 << REG_SHIFT, /* DR7 */
+
+ 0x03 << REG_SHIFT, /* TR3 */
+ 0x04 << REG_SHIFT, /* TR4 */
+ 0x05 << REG_SHIFT, /* TR5 */
+ 0x06 << REG_SHIFT, /* TR6 */
+ 0x07 << REG_SHIFT, /* TR7 */
+
+ 0x00 << REG_SHIFT, /* ST(0) */
+ 0x01 << REG_SHIFT, /* ST(1) */
+ 0x02 << REG_SHIFT, /* ST(2) */
+ 0x03 << REG_SHIFT, /* ST(3) */
+ 0x04 << REG_SHIFT, /* ST(4) */
+ 0x05 << REG_SHIFT, /* ST(5) */
+ 0x06 << REG_SHIFT, /* ST(6) */
+ 0x07 << REG_SHIFT, /* ST(7) */
+};
+
+PRIVATE opsize_t regsize[] =
+{
+ 2, /* BP */
+ 2, /* BX */
+ 2, /* DI */
+ 2, /* SI */
+
+ 4, /* EAX */
+ 4, /* EBP */
+ 4, /* EBX */
+ 4, /* ECX */
+ 4, /* EDI */
+ 4, /* EDX */
+ 4, /* ESI */
+ 4, /* ESP */
+
+ 2, /* AX */
+ 2, /* CX */
+ 2, /* DX */
+ 2, /* SP */
+
+ 1, /* AH */
+ 1, /* AL */
+ 1, /* BH */
+ 1, /* BL */
+ 1, /* CH */
+ 1, /* CL */
+ 1, /* DH */
+ 1, /* DL */
+
+ 2, /* CS */
+ 2, /* DS */
+ 2, /* ES */
+ 2, /* FS */
+ 2, /* GS */
+ 2, /* SS */
+
+ 4, /* CR0 */
+ 4, /* CR2 */
+ 4, /* CR3 */
+
+ 4, /* DR0 */
+ 4, /* DR1 */
+ 4, /* DR2 */
+ 4, /* DR3 */
+ 4, /* DR6 */
+ 4, /* DR7 */
+
+ 4, /* TR3 */
+ 4, /* TR4 */
+ 4, /* TR5 */
+ 4, /* TR6 */
+ 4, /* TR7 */
+
+ 10, /* ST(0) */
+ 10, /* ST(1) */
+ 10, /* ST(2) */
+ 10, /* ST(3) */
+ 10, /* ST(4) */
+ 10, /* ST(5) */
+ 10, /* ST(6) */
+ 10, /* ST(7) */
+
+ 0, /* NOREG */
+};
+
+PRIVATE opcode_t regsegword[] =
+{
+ WORDBIT, /* BP */
+ WORDBIT, /* BX */
+ WORDBIT, /* DI */
+ WORDBIT, /* SI */
+
+ WORDBIT, /* EAX */
+ WORDBIT, /* EBP */
+ WORDBIT, /* EBX */
+ WORDBIT, /* ECX */
+ WORDBIT, /* EDI */
+ WORDBIT, /* EDX */
+ WORDBIT, /* ESI */
+ WORDBIT, /* ESP */
+
+ WORDBIT, /* AX */
+ WORDBIT, /* CX */
+ WORDBIT, /* DX */
+ WORDBIT, /* SP */
+
+ BYTE_SEGWORD, /* AH */
+ BYTE_SEGWORD, /* AL */
+ BYTE_SEGWORD, /* BH */
+ BYTE_SEGWORD, /* BL */
+ BYTE_SEGWORD, /* CH */
+ BYTE_SEGWORD, /* CL */
+ BYTE_SEGWORD, /* DH */
+ BYTE_SEGWORD, /* DL */
+
+ SEGMOV, /* CS */
+ SEGMOV, /* DS */
+ SEGMOV, /* ES */
+ SEGMOV, /* FS */
+ SEGMOV, /* GS */
+ SEGMOV, /* SS */
+
+ 0x20, /* CR0 */
+ 0x20, /* CR2 */
+ 0x20, /* CR3 */
+
+ 0x21, /* DR0 */
+ 0x21, /* DR1 */
+ 0x21, /* DR2 */
+ 0x21, /* DR3 */
+ 0x21, /* DR6 */
+ 0x21, /* DR7 */
+
+ 0x24, /* TR3 */
+ 0x24, /* TR4 */
+ 0x24, /* TR5 */
+ 0x24, /* TR6 */
+ 0x24, /* TR7 */
+
+ 0x00, /* ST(0) */
+ 0x00, /* ST(1) */
+ 0x00, /* ST(2) */
+ 0x00, /* ST(3) */
+ 0x00, /* ST(4) */
+ 0x00, /* ST(5) */
+ 0x00, /* ST(6) */
+ 0x00, /* ST(7) */
+
+ 0x00, /* NOREG */
+};
+
+PRIVATE opcode_t rm[] =
+{
+ 0x05, /* BP */
+ 0x03, /* BX */
+ 0x07, /* DI */
+ 0x06, /* SI */
+
+ 0x00, /* EAX */
+ 0x05, /* EBP */
+ 0x03, /* EBX */
+ 0x01, /* ECX */
+ 0x07, /* EDI */
+ 0x02, /* EDX */
+ 0x06, /* ESI */
+ 0x04, /* ESP */
+
+ 0x00, /* AX */
+ 0x01, /* CX */
+ 0x02, /* DX */
+ 0x04, /* SP */
+
+ 0x04, /* AH */
+ 0x00, /* AL */
+ 0x07, /* BH */
+ 0x03, /* BL */
+ 0x05, /* CH */
+ 0x01, /* CL */
+ 0x06, /* DH */
+ 0x02, /* DL */
+
+ 0x01, /* CS */
+ 0x03, /* DS */
+ 0x00, /* ES */
+ 0x04, /* FS */
+ 0x05, /* GS */
+ 0x02, /* SS */
+
+ 0x00, /* CR0 */
+ 0x00, /* CR2 */
+ 0x00, /* CR3 */
+
+ 0x00, /* DR0 */
+ 0x00, /* DR1 */
+ 0x00, /* DR2 */
+ 0x00, /* DR3 */
+ 0x00, /* DR6 */
+ 0x00, /* DR7 */
+
+ 0x00, /* TR3 */
+ 0x00, /* TR4 */
+ 0x00, /* TR5 */
+ 0x00, /* TR6 */
+ 0x00, /* TR7 */
+
+ 0x00, /* ST(0) */
+ 0x00, /* ST(1) */
+ 0x00, /* ST(2) */
+ 0x00, /* ST(3) */
+ 0x00, /* ST(4) */
+ 0x00, /* ST(5) */
+ 0x00, /* ST(6) */
+ 0x00, /* ST(7) */
+
+ 0x04, /* null index reg for sib only */
+};
+
+PRIVATE opcode_t rmfunny[] =
+{
+ 0x06, /* BP */
+ 0x07, /* BX */
+ 0x05, /* DI */
+ 0x04, /* SI */
+};
+
+PRIVATE opcode_t segoverride[] =
+{
+ 0x2E, /* CS */
+ 0x3E, /* DS */
+ 0x26, /* ES */
+ 0x64, /* FS */
+ 0x65, /* GS */
+ 0x36, /* SS */
+};
+
+PRIVATE opcode_t ss[] = /* scale to ss bits */
+{
+ 0x00, /* x0, illegal */
+ 0x00 << SS_SHIFT, /* x1 */
+ 0x01 << SS_SHIFT, /* x2 */
+ 0x00, /* x3, illegal */
+ 0x02 << SS_SHIFT, /* x4 */
+ 0x00, /* x5, illegal */
+ 0x00, /* x6, illegal */
+ 0x00, /* x7, illegal */
+ 0x03 << SS_SHIFT, /* x8 */
+};
+
+PRIVATE unsigned char calljmp_kludge;
+PRIVATE opcode_t direction;
+PRIVATE bool_t fpreg_allowed;
+PRIVATE opcode_t segword;
+/*
+ Values of segword:
+ BYTE_SEGWORD for byte ea's.
+ SEGMOV for segment registers
+ opcode for special registers
+ WORDBIT for other word and dword ea's
+*/
+
+PRIVATE struct ea_s source;
+PRIVATE struct ea_s source2;
+PRIVATE struct ea_s target;
+
+FORWARD void Eb P((struct ea_s *eap));
+FORWARD void Ew P((struct ea_s *eap));
+FORWARD void Ev P((struct ea_s *eap));
+FORWARD void Ex P((struct ea_s *eap));
+FORWARD void Gd P((struct ea_s *eap));
+FORWARD void Gw P((struct ea_s *eap));
+FORWARD void Gv P((struct ea_s *eap));
+FORWARD void Gx P((struct ea_s *eap));
+FORWARD void buildea P((struct ea_s *eap));
+FORWARD void buildfloat P((void));
+FORWARD void buildfreg P((void));
+FORWARD void buildimm P((struct ea_s *eap, bool_pt signflag));
+FORWARD void buildregular P((void));
+FORWARD void buildsegword P((struct ea_s *eap));
+FORWARD void buildunary P((opcode_pt opc));
+FORWARD opsize_pt displsize P((struct ea_s *eap));
+FORWARD reg_pt fpregchk P((void));
+FORWARD bool_pt getaccumreg P((struct ea_s *eap));
+FORWARD void getbinary P((void));
+FORWARD bool_pt getdxreg P((struct ea_s *eap));
+FORWARD void getea P((struct ea_s *eap));
+FORWARD void getimmed P((struct ea_s *eap, count_t immed_count));
+FORWARD void getindirect P((struct ea_s *eap));
+FORWARD void getshift P((struct ea_s *eap));
+FORWARD reg_pt indregchk P((reg_pt matchreg));
+FORWARD void kgerror P((error_pt errnum));
+FORWARD void lbranch P((int backamount));
+FORWARD void notbytesize P((struct ea_s *eap));
+FORWARD void notimmed P((struct ea_s *eap));
+FORWARD void notindirect P((struct ea_s *eap));
+FORWARD void notsegorspecreg P((struct ea_s *eap));
+FORWARD void yesimmed P((struct ea_s *eap));
+FORWARD void yes_samesize P((void));
+
+PRIVATE void Eb(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ if (eap->size != 0x1)
+ {
+#ifndef NODEFAULTSIZE
+ if (eap->size == 0x0)
+ eap->size = 0x1;
+ else
+#endif
+ kgerror(ILL_SIZE);
+ }
+}
+
+PRIVATE void Ew(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ if (eap->size != 0x2)
+ {
+#ifndef NODEFAULTSIZE
+ if (eap->size == 0x0)
+ eap->size = 0x2;
+ else
+#endif
+ kgerror(ILL_SIZE);
+ }
+}
+
+PRIVATE void Ev(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ notbytesize(eap);
+}
+
+PRIVATE void Ex(eap)
+register struct ea_s *eap;
+{
+ getea(eap);
+ notimmed(eap);
+ notsegorspecreg(eap);
+}
+
+PRIVATE void Gd(eap)
+register struct ea_s *eap;
+{
+ Gx(eap);
+ if (eap->size != 0x4)
+ kgerror(ILL_SIZE);
+}
+
+PRIVATE void Gw(eap)
+register struct ea_s *eap;
+{
+ Gx(eap);
+ if (eap->size != 0x2)
+ kgerror(ILL_SIZE);
+}
+
+PRIVATE void Gv(eap)
+register struct ea_s *eap;
+{
+ Gx(eap);
+ notbytesize(eap);
+}
+
+PRIVATE void Gx(eap)
+register struct ea_s *eap;
+{
+ Ex(eap);
+ notindirect(eap);
+}
+
+PRIVATE void buildea(eap)
+register struct ea_s *eap;
+{
+ opsize_t asize;
+
+ ++mcount;
+ lastexp = eap->displ;
+ if (eap->indcount == 0x0)
+ postb = REG_MOD | rm[eap->base];
+ else
+ {
+ if (eap->base == NOREG)
+ {
+ if (eap->index == NOREG)
+ {
+ if ((asize = displsize(eap)) > 0x2)
+ postb = D32_RM;
+ else
+ postb = D16_RM;
+ }
+ else
+ {
+ asize = 0x4;
+ postb = SIB_NOBASE; /* for sib later */
+ }
+ }
+ else
+ {
+ if (eap->base > MAX16BITINDREG)
+ {
+ asize = 0x4;
+ postb = rm[eap->base];
+ }
+ else
+ {
+ asize = 0x2;
+ if (!(lastexp.data & UNDBIT) &&
+ !iswordorswordoffset(lastexp.offset))
+ error(ABOUNDS);
+ if (eap->index == NOREG)
+ postb = rmfunny[eap->base];
+ else if (eap->base <= MAX16BITINDREG)
+ postb = baseind16[eap->base + 0x4 * eap->index];
+ }
+ }
+ if (asize != defsize)
+ aprefix = 0x67;
+ if (eap->base == NOREG)
+ mcount += asize;
+ else if (lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
+ !is8bitsignedoffset(lastexp.offset))
+ {
+ postb |= MEM2_MOD;
+ mcount += asize;
+ }
+ else if (lastexp.offset != 0x0 ||
+ (eap->base == BPREG && eap->index == NOREG) ||
+ eap->base == EBPREG)
+ {
+ postb |= MEM1_MOD;
+ ++mcount;
+ }
+ if (asize > 0x2 && (eap->base == ESPREG || eap->index != NOREG))
+ {
+ sib = ss[eap->scale] |
+ (rm[eap->index] << INDEX_SHIFT) |
+ (postb & RM_MASK);
+ postb = (postb & MOD_MASK) | SIB_RM;
+ ++mcount;
+ }
+ }
+}
+
+PRIVATE void buildfloat()
+{
+ if (mcount != 0x0)
+ {
+ buildea(&source);
+ oprefix = 0x0;
+ postb |= (opcode & 0x07) << REG_SHIFT;
+ opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
+ }
+}
+
+PRIVATE void buildfreg()
+{
+ mcount += 0x2;
+ oprefix = 0x0;
+ postb = REG_MOD | ((opcode & 0x07) << REG_SHIFT) | (target.base - ST0REG);
+ opcode = ESCAPE_OPCODE_BASE | ((opcode & 0x70) >> 0x4);
+}
+
+PRIVATE void buildimm(eap, signflag)
+register struct ea_s *eap;
+bool_pt signflag;
+{
+ immadr = eap->displ;
+ immcount = eap->size;
+ if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)))
+ {
+ if (immcount == 0x1)
+ {
+ if ((offset_t) (immadr.offset + 0x80) >= 0x180)
+ datatoobig();
+ }
+ else if (signflag && is8bitsignedoffset(immadr.offset))
+ {
+ opcode |= SIGNBIT;
+ immcount = 0x1;
+ }
+ else if (immcount == 0x2)
+ {
+ if ((offset_t) (immadr.offset + 0x8000L) >= 0x18000L)
+ datatoobig();
+ }
+ }
+}
+
+PRIVATE void buildregular()
+{
+ if (mcount != 0x0)
+ {
+ buildea(&target);
+ postb |= regbits[source.base];
+ }
+}
+
+/* Check size and build segword. */
+
+PRIVATE void buildsegword(eap)
+register struct ea_s *eap;
+{
+ if (eap->size == 0x0)
+#ifdef NODEFAULTSIZE
+ kgerror(SIZE_UNK);
+#else
+ eap->size = defsize;
+#endif
+ if (eap->indcount != 0x0 || eap->base == NOREG)
+ {
+ segword = WORDBIT;
+ if (eap->size == 0x1)
+ segword = BYTE_SEGWORD;
+ }
+ else
+ segword = regsegword[eap->base];
+}
+
+PRIVATE void buildunary(opc)
+opcode_pt opc;
+{
+ if (mcount != 0x0)
+ {
+ buildea(&target);
+ postb |= opcode;
+ opcode = opc;
+ }
+}
+
+PRIVATE opsize_pt displsize(eap)
+register struct ea_s *eap;
+{
+ opsize_t asize;
+
+ asize = defsize;
+ if (!(eap->displ.data & UNDBIT))
+ {
+ if (asize > 0x2)
+ {
+ if (!(eap->displ.data & (FORBIT | RELBIT)) &&
+ iswordadr(eap->displ.offset))
+ asize = 0x2;
+ }
+ else if (!iswordorswordoffset(eap->displ.offset))
+ /* should really use iswordadr() */
+ /* but compiler generates signed offsets */
+ {
+ if (!(eap->displ.data & (FORBIT | RELBIT)))
+ asize = 0x4;
+ else if (pass2)
+ error(ABOUNDS);
+ }
+ }
+ return asize;
+}
+
+PRIVATE reg_pt fpregchk()
+{
+ reg_pt fpreg;
+
+ fpreg_allowed = TRUE;
+ fpreg = regchk();
+ fpreg_allowed = FALSE;
+ if (fpreg != ST0REG)
+ return NOREG;
+ getsym();
+ if (sym == LPAREN)
+ {
+ getsym();
+ if (sym != INTCONST || (unsigned) number >= 0x8)
+ error(ILL_FP_REG);
+ else
+ {
+ fpreg += number;
+ getsym();
+ if (sym != RPAREN)
+ error(RPEXP);
+ else
+ getsym();
+ }
+ }
+ return fpreg;
+}
+
+PRIVATE bool_pt getaccumreg(eap)
+register struct ea_s *eap;
+{
+ if ((eap->base = regchk()) != AXREG && eap->base != ALREG
+ && eap->base != EAXREG)
+ return FALSE;
+ getsym();
+ if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
+ oprefix = 0x66;
+ return TRUE;
+}
+
+/*
+ Get binary ea's in target & source (flipped if direction is set).
+ Put size in source if not already.
+ Initialise direction, segword, bump mcount.
+*/
+
+PRIVATE void getbinary()
+{
+ ++mcount;
+ getea(&target);
+ if (target.indcount == 0x0 && target.base == NOREG)
+ {
+ error(ILL_IMM_MODE);
+ target.base = AXREG;
+ target.size = defsize;
+ }
+ getcomma();
+ getea(&source);
+ if (source.size == 0x0)
+ source.size = target.size;
+ else if (target.size != 0x0 && target.size != source.size)
+ {
+ kgerror(MISMATCHED_SIZE);
+ return;
+ }
+ if (source.indcount == 0x0 && regsegword[target.base] < SEGMOV)
+ direction = 0x0;
+ else if (target.indcount == 0x0 && regsegword[source.base] < SEGMOV)
+ {
+ struct ea_s swap;
+
+ direction = TOREGBIT;
+ swap = source;
+ source = target;
+ target = swap;
+ }
+ else if (target.indcount != 0x0)
+ {
+ kgerror(ILL_IND_TO_IND);
+ return;
+ }
+ else
+ {
+ kgerror(ILL_SEG_REG);
+ return;
+ }
+ buildsegword(&source);
+}
+
+PRIVATE bool_pt getdxreg(eap)
+register struct ea_s *eap;
+{
+ if ((eap->base = regchk()) != DXREG)
+ return FALSE;
+ getsym();
+ return TRUE;
+}
+
+/* parse effective address */
+
+/*
+ Syntax is restrictive in that displacements must be in the right spots
+ and will not be added up.
+
+ optional size-type prefix, which is
+ BYTE
+ BYTE PTR
+ WORD
+ WORD PTR
+ DWORD
+ DWORD PTR
+ PTR
+ reg
+ segreg
+ [scaled index]
+ where scaled index =
+ indreg
+ indreg*scale
+ indreg+indreg
+ indreg+indreg*scale
+ [scaled index+displ]
+ [scaled index-displ]
+ optional-immediate-prefix displ[scaled index]
+ [displ]
+ optional-imediate-prefix displ
+ (scaled index) -- anachronism
+ optional-imediate-prefix displ(scaled index) -- anachronism
+*/
+
+PRIVATE void getea(eap)
+register struct ea_s *eap;
+{
+ bool_t leading_displ;
+ bool_t leading_immed;
+ register struct sym_s *symptr;
+
+ leading_immed = leading_displ = lastexp.data = eap->indcount
+ = lastexp.offset = 0x0;
+ eap->index = eap->base = NOREG;
+ eap->scale = 0x1;
+ eap->size = mnsize; /* 0x1 for byte ops, else 0x0 */
+
+ if (sym == IDENT)
+ {
+ if ((symptr = gsymptr)->type & MNREGBIT)
+ {
+ if (symptr->data & SIZEBIT)
+ {
+ getsym();
+ if (symptr->value_reg_or_op.op.opcode == 0x0)
+ eap->indcount = 0x2 - calljmp_kludge;
+ else
+ {
+ if (eap->size != 0x0)
+ {
+ if (eap->size != symptr->value_reg_or_op.op.opcode)
+ error(MISMATCHED_SIZE);
+ }
+ else
+ eap->size = symptr->value_reg_or_op.op.opcode;
+ if (eap->size > 0x1 && eap->size != defsize)
+ oprefix = 0x66;
+ if (sym == IDENT &&
+ (symptr = gsymptr)->type & MNREGBIT &&
+ symptr->data & SIZEBIT &&
+ symptr->value_reg_or_op.op.routine == PTROP)
+ {
+ getsym();
+ eap->indcount = 0x2 - calljmp_kludge;
+ }
+ }
+ }
+ }
+ if (!(symptr->type & (LABIT | MACBIT | MNREGBIT | VARBIT)))
+ symptr->data |= FORBIT; /* show seen in advance */
+ }
+ if ((eap->base = regchk()) != NOREG)
+ {
+ getsym();
+ if (eap->indcount != 0x0)
+ {
+ error(ILL_IND_PTR);
+ eap->indcount = 0x0;
+ }
+ if (eap->size != 0x0 && eap->size != regsize[eap->base])
+ error(MISMATCHED_SIZE);
+ if ((eap->size = regsize[eap->base]) > 0x1 && eap->size != defsize)
+ oprefix = 0x66;
+ eap->displ = lastexp;
+ return;
+ }
+ if (sym != lindirect)
+ {
+ if (sym == IMMEDIATE || sym == STAR)
+ {
+ /* context-sensitive, STAR means signed immediate here */
+ leading_immed = TRUE;
+ getsym();
+ }
+ leading_displ = TRUE;
+ expres();
+ eap->displ = lastexp;
+ }
+ if (sym == lindirect)
+ {
+ getsym();
+ eap->indcount = 0x2 - calljmp_kludge;
+ if ((eap->base = indregchk((reg_pt) NOREG)) != NOREG)
+ {
+ if (eap->indcount == 0x0 && leading_displ)
+ error(IND_REQ);
+ getsym();
+ if (sym == ADDOP)
+ {
+ getsym();
+ if ((eap->index = indregchk(eap->base)) != NOREG)
+ getsym();
+ else
+ {
+ if (eap->indcount == 0x0)
+ error(IND_REQ);
+ if (leading_displ)
+ error(REPEATED_DISPL);
+ expres(); /* this eats ADDOP, SUBOP, MULOP */
+ }
+ }
+ if (sym == STAR)
+ {
+ /* context-sensitive, STAR means scaled here*/
+ if (eap->index == NOREG && eap->base == ESPREG)
+ {
+ error(INDEX_REG_EXP);
+ eap->base = EAXREG;
+ }
+ getsym();
+ factor();
+ chkabs();
+ if (!(lastexp.data & UNDBIT) && lastexp.offset != 0x1)
+ {
+ if (eap->base <= MAX16BITINDREG ||
+ (lastexp.offset != 0x2 && lastexp.offset != 0x4 &&
+ lastexp.offset != 0x8))
+ error(ILL_SCALE);
+ else
+ {
+ eap->scale = lastexp.offset;
+ if (eap->index == NOREG)
+ {
+ eap->index = eap->base;
+ eap->base = NOREG;
+ }
+ }
+ }
+ lastexp.data = lastexp.offset = 0x0;
+ }
+ if ((sym == ADDOP || sym == SUBOP))
+ {
+ if (eap->indcount == 0x0)
+ error(IND_REQ);
+ if (leading_displ)
+ error(REPEATED_DISPL);
+ expres();
+ }
+ }
+ else
+ {
+ if (leading_displ)
+ error(REPEATED_DISPL);
+ expres();
+ }
+ if (sym != rindirect)
+ error(rindexp);
+ else
+ getsym();
+ }
+ else if (!leading_immed && idefsize <= 0x2)
+ eap->indcount = 0x1; /* compatibility kludge */
+ if (!leading_displ)
+ eap->displ = lastexp;
+}
+
+PRIVATE void getimmed(eap, immed_count)
+struct ea_s *eap;
+count_t immed_count;
+{
+ getea(eap);
+ yesimmed(eap);
+ if (mcount != 0x0)
+ {
+ eap->size = immed_count;
+ buildimm(eap, FALSE);
+ }
+}
+
+PRIVATE void getindirect(eap)
+register struct ea_s *eap;
+{
+ getea(eap);
+ if (eap->indcount == 0x0)
+ kgerror(IND_REQ);
+}
+
+PRIVATE void getshift(eap)
+register struct ea_s *eap;
+{
+ getcomma();
+ getea(eap);
+ if (eap->base != CLREG)
+ yesimmed(eap);
+}
+
+/*
+ Check if current symbol is a compatible index register.
+ Generate error if it is a reg but not a compatible index.
+ Return register number (adjusted if necessary to a legal index) or NOREG.
+*/
+
+PRIVATE reg_pt indregchk(matchreg)
+reg_pt matchreg;
+{
+ reg_pt reg;
+
+ if ((reg = regchk()) != NOREG)
+ {
+ switch (matchreg)
+ {
+ case BPREG:
+ case BXREG:
+ if (reg != DIREG && reg != SIREG)
+ {
+ reg = SIREG;
+ error(INDEX_REG_EXP);
+ }
+ break;
+ case DIREG:
+ case SIREG:
+ if (reg != BPREG && reg != BXREG)
+ {
+ reg = BXREG;
+ error(INDEX_REG_EXP);
+ }
+ break;
+ case NOREG:
+ break;
+ default:
+ if (reg <= MAX16BITINDREG || reg == ESPREG)
+ {
+ reg = EAXREG;
+ error(INDEX_REG_EXP);
+ }
+ break;
+ }
+ if (reg > MAXINDREG && calljmp_kludge == 0x0)
+ {
+ if (matchreg != NOREG)
+ reg = EAXREG;
+ else
+ reg = BXREG;
+ error(INDEX_REG_EXP);
+ }
+ }
+ return reg;
+}
+
+PRIVATE void kgerror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ sprefix = oprefix = aprefix = mcount = 0x0;
+}
+
+PRIVATE void lbranch(backamount)
+int backamount;
+{
+ mcount += defsize + 0x1;
+ if (pass2)
+ {
+ reldata();
+ if (!(lastexp.data & (RELBIT | UNDBIT)))
+ {
+ lastexp.offset = lastexp.offset - lc - lcjump;
+ if (backamount != 0x0 && !(lastexp.data & IMPBIT) &&
+ lastexp.offset + backamount < 0x80 + backamount)
+ error(SHORTB); /* -0x8? to 0x7F, warning */
+ }
+ }
+}
+
+/* BCC (long branches emulated by short branch over & long jump) */
+
+PUBLIC void mbcc()
+{
+ getea(&target);
+ if (target.indcount >= 0x2 || target.base != NOREG)
+ kgerror(REL_REQ);
+ else
+ {
+ if (defsize != 0x2)
+ {
+ page = PAGE1_OPCODE;
+ ++mcount;
+ opcode += 0x10;
+ lbranch(0x84);
+ }
+ else
+ {
+ aprefix = opcode ^ 0x1; /* kludged storage for short branch
+ over */
+ oprefix = defsize + 0x1;
+ mcount += 0x2;
+ opcode = JMP_OPCODE;
+ lbranch(0x83);
+ mcount -= 0x2;
+ }
+ }
+}
+
+/* bswap r32 */
+
+PUBLIC void mbswap()
+{
+ ++mcount;
+ Gd(&target);
+ opcode |= rm[target.base];
+}
+
+/* BR, CALL, J, JMP */
+
+PUBLIC void mcall()
+{
+ opcode_pt far_diff;
+ bool_t indirect;
+ register struct sym_s *symptr;
+
+ far_diff = 0x0;
+ if (sym == IDENT && (symptr = gsymptr)->type & MNREGBIT &&
+ symptr->data & SIZEBIT &&
+ symptr->value_reg_or_op.op.routine == FAROP)
+ {
+ far_diff = 0x8;
+ getsym();
+ }
+ indirect = FALSE;
+ if (asld_compatible && idefsize <= 0x2)
+ {
+ calljmp_kludge = 0x2;
+ if (sym == INDIRECT)
+ {
+ calljmp_kludge = 0x0;
+ indirect = TRUE;
+ getsym();
+ }
+ }
+ getea(&target);
+ if (indirect && target.indcount == 0x1)
+ target.indcount = 0x2;
+ calljmp_kludge = 0x0;
+ if (sym == COLON)
+ {
+ if (opcode == JMP_SHORT_OPCODE)
+ opcode = JMP_OPCODE;
+ ++mcount;
+ yesimmed(&target);
+ getsym();
+ getea(&source);
+ yesimmed(&source);
+ if (mcount != 0x0)
+ {
+ if (opcode == JMP_OPCODE)
+ opcode = 0xEA;
+ else
+ opcode = 0x9A;
+ lastexp = source.displ;
+ if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
+ defsize == 0x2 &&
+ (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
+ datatoobig();
+ mcount += defsize;
+ target.size = 0x2;
+ buildimm(&target, FALSE);
+ }
+ }
+ else if (target.indcount >= 0x2 || target.base != NOREG)
+ {
+ ++mcount;
+ notsegorspecreg(&target);
+ if (target.indcount == 0)
+ notbytesize(&target);
+ if (mcount != 0x0)
+ {
+ if (opcode == JMP_SHORT_OPCODE)
+ opcode = JMP_OPCODE;
+ buildea(&target);
+ if (opcode == JMP_OPCODE)
+ opcode = 0x20;
+ else
+ opcode = 0x10;
+ postb |= opcode + far_diff;
+ opcode = 0xFF;
+ }
+ }
+ else if (opcode == JMP_SHORT_OPCODE)
+ {
+ if (jumps_long)
+ {
+ opcode = JMP_OPCODE;
+ lbranch(0x83);
+ }
+ else
+ {
+ lastexp = target.displ;
+ if (lastexp.data & IMPBIT)
+ {
+ error(NONIMPREQ);
+ lastexp.data = FORBIT | UNDBIT;
+ }
+ mshort2();
+ }
+ }
+ else
+ lbranch(opcode == JMP_OPCODE ? 0x83 : 0x0);
+}
+
+/* CALLI, JMPI */
+
+PUBLIC void mcalli()
+{
+ bool_t indirect;
+
+ ++mcount;
+ indirect = FALSE;
+ if (sym == INDIRECT)
+ {
+ getsym();
+ indirect = TRUE;
+ }
+ getea(&target);
+ if (target.indcount >= 0x2 || target.base != NOREG)
+ indirect = TRUE;
+ if (indirect)
+ {
+ buildea(&target);
+ if (opcode == 0xEA)
+ opcode = 0x28;
+ else
+ opcode = 0x18;
+ postb |= opcode;
+ opcode = 0xFF;
+ }
+ else
+ {
+ getcomma();
+ getea(&source);
+ yesimmed(&source);
+ if (mcount != 0x0)
+ {
+ lastexp = target.displ;
+ if (!(lastexp.data & (FORBIT | RELBIT | UNDBIT)) &&
+ defsize == 0x2 &&
+ (offset_t) (lastexp.offset + 0x8000L) >= 0x18000L)
+ datatoobig();
+ mcount += defsize;
+ source.size = 0x2;
+ buildimm(&source, FALSE);
+ }
+ }
+}
+
+/* DIV, IDIV, MUL */
+
+PUBLIC void mdivmul()
+{
+ if (getaccumreg(&source))
+ {
+ ++mcount;
+ getcomma();
+ Ex(&target);
+ yes_samesize();
+ buildunary(0xF6 | regsegword[source.base]);
+ }
+ else
+ mnegnot();
+}
+
+/* ENTER */
+
+PUBLIC void menter()
+{
+ ++mcount;
+ getimmed(&target, 0x2);
+ getcomma();
+ getimmed(&source, 0x1);
+ if (mcount != 0x0)
+ {
+ mcount += 2;
+ lastexp = target.displ; /* getimmed(&source) wiped it out */
+ }
+}
+
+/* arpl r/m16,r16 (Intel manual opcode chart wrongly says EwRw) */
+
+PUBLIC void mEwGw()
+{
+ ++mcount;
+ Ew(&target);
+ getcomma();
+ Gw(&source);
+ oprefix = 0x0;
+ buildregular();
+}
+
+/* [cmpxchg xadd] [r/m8,r8 r/m16,r16, r/m32,r32] */
+
+PUBLIC void mExGx()
+{
+ ++mcount;
+ Ex(&target);
+ getcomma();
+ Gx(&source);
+ yes_samesize();
+ opcode |= segword;
+ buildregular();
+}
+
+PUBLIC void mf_inher()
+{
+ mcount += 0x2;
+ postb = REG_MOD | (opcode & ~REG_MOD);
+ opcode = ESCAPE_OPCODE_BASE | (opcode >> 0x6);
+ if (opcode == ESCAPE_OPCODE_BASE)
+ opcode = ESCAPE_OPCODE_BASE | 0x6; /* fix up encoding of fcompp */
+}
+
+/* [fldenv fnsave fnstenv frstor] mem */
+
+PUBLIC void mf_m()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size != 0x0)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* [fldcw fnstcw] mem2i */
+
+PUBLIC void mf_m2()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size != 0x0 && source.size != 0x2)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* fnstsw [mem2i ax] */
+
+PUBLIC void mf_m2_ax()
+{
+ if (getaccumreg(&target))
+ {
+ if (target.base != AXREG)
+ kgerror(ILLREG);
+ else
+ {
+ opcode = 0x74;
+ target.base = ST0REG; /* fake, really ax */
+ buildfreg();
+ }
+ }
+ else
+ mf_m2();
+}
+
+/* [fiadd ficom ficomp fidiv fidivr fimul fist fisub fisubr] [mem2i mem4i] */
+
+PUBLIC void mf_m2_m4()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x2)
+ opcode |= 0x40;
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* [fild fistp] [mem2i mem4i mem8i] */
+
+PUBLIC void mf_m2_m4_m8()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x2)
+ opcode |= 0x40;
+ else if (source.size == 0x8)
+ opcode |= 0x45; /* low bits 0 -> 5 and 3 -> 7 */
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* [fcom fcomp] [mem4r mem8r optional-st(i)] */
+
+PUBLIC void mf_m4_m8_optst()
+{
+ if (sym == EOLSYM)
+ {
+ target.base = ST1REG;
+ buildfreg();
+ }
+ else
+ mf_m4_m8_st();
+}
+
+/* [fadd fdiv fdivr fmul fsub fsubr] [mem4r mem8r st,st(i) st(i),st] */
+
+PUBLIC void mf_m4_m8_stst()
+{
+ target.base = fpregchk();
+ if (target.base != NOREG)
+ {
+ getcomma();
+ source.base = fpregchk();
+ if (source.base == NOREG)
+ {
+ error(FP_REG_REQ);
+ source.base = ST0REG;
+ }
+ if (target.base == ST0REG)
+ target.base = source.base;
+ else
+ {
+ if (source.base != ST0REG)
+ error(ILL_FP_REG_PAIR);
+ opcode |= 0x40;
+ if ((opcode & 0x07) >= 0x4)
+ opcode ^= 0x01; /* weird swap of fdiv/fdivr, fsub/fsubr */
+ }
+ buildfreg();
+ }
+ else
+ {
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x8)
+ opcode |= 0x40;
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+ }
+}
+
+/* fst [mem4r mem8r st(i)] */
+
+PUBLIC void mf_m4_m8_st()
+{
+ target.base = fpregchk();
+ if (target.base != NOREG)
+ {
+ if (opcode == FST_ENCODED)
+ opcode |= 0x40;
+ buildfreg();
+ }
+ else
+ {
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x8)
+ opcode |= 0x40;
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+ }
+}
+
+/* [fld fstp] [mem4r mem8r mem10r st(i)] */
+
+PUBLIC void mf_m4_m8_m10_st()
+{
+ target.base = fpregchk();
+ if (target.base != NOREG)
+ {
+ if (opcode == FSTP_ENCODED)
+ opcode |= 0x40;
+ buildfreg();
+ }
+ else
+ {
+ ++mcount;
+ getindirect(&source);
+ if (source.size == 0x0)
+ kgerror(SIZE_UNK);
+ else if (source.size == 0x8)
+ opcode |= 0x40;
+ else if (source.size == 0xA)
+ opcode |= 0x25; /* low bits 0 -> 5 and 3 -> 7 */
+ else if (source.size != 0x4)
+ kgerror(ILL_SIZE);
+ buildfloat();
+ }
+}
+
+/* [fbld fbstp] mem10r */
+
+PUBLIC void mf_m10()
+{
+ ++mcount;
+ getindirect(&source);
+ if (source.size != 0xA)
+ kgerror(ILL_SIZE);
+ buildfloat();
+}
+
+/* ffree st(i) */
+
+PUBLIC void mf_st()
+{
+ target.base = fpregchk();
+ if (target.base == NOREG)
+ kgerror(FP_REG_REQ);
+ buildfreg();
+}
+
+/* [fucom fucomp fxch] optional-st(i) */
+
+PUBLIC void mf_optst()
+{
+ if (sym == EOLSYM)
+ {
+ target.base = ST1REG;
+ buildfreg();
+ }
+ else
+ mf_st();
+}
+
+/* [faddp fdivp fdivrp fmulp fsubp fsubrp] st(i),st */
+
+PUBLIC void mf_stst()
+{
+ target.base = fpregchk();
+ if (target.base == NOREG)
+ {
+ kgerror(FP_REG_REQ);
+ return;
+ }
+ getcomma();
+ source.base = fpregchk();
+ if (source.base == NOREG)
+ {
+ kgerror(FP_REG_REQ);
+ return;
+ }
+ if (source.base != ST0REG)
+ {
+ kgerror(ILL_FP_REG);
+ return;
+ }
+ buildfreg();
+}
+
+PUBLIC void mf_w_inher()
+{
+ sprefix = WAIT_OPCODE;
+ mf_inher();
+}
+
+/* [fsave fstenv] mem */
+
+PUBLIC void mf_w_m()
+{
+ sprefix = WAIT_OPCODE;
+ mf_m();
+}
+
+/* fstcw mem2i */
+
+PUBLIC void mf_w_m2()
+{
+ sprefix = WAIT_OPCODE;
+ mf_m2();
+}
+
+/* fstsw [mem2i ax] */
+
+PUBLIC void mf_w_m2_ax()
+{
+ sprefix = WAIT_OPCODE;
+ mf_m2_ax();
+}
+
+/* ADC, ADD, AND, CMP, OR, SBB, SUB, XOR */
+
+PUBLIC void mgroup1()
+{
+ getbinary();
+ notsegorspecreg(&source);
+ if (mcount != 0x0)
+ {
+ if (source.base == NOREG)
+ {
+ if (target.indcount == 0x0 && (target.base == ALREG ||
+ target.base == AXREG ||
+ (target.base == EAXREG &&
+ (source.displ.data & (FORBIT | RELBIT | UNDBIT) ||
+ !is8bitsignedoffset(source.displ.offset)))))
+ {
+ opcode |= 0x04 | segword;
+ buildimm(&source, FALSE);
+ }
+ else
+ {
+ buildunary(0x80 | segword);
+ buildimm(&source, TRUE);
+ }
+ }
+ else
+ {
+ opcode |= direction | segword;
+ buildregular();
+ }
+ }
+}
+
+/* RCL, RCR, ROL, ROR, SAL, SAR, SHL, SHR */
+
+PUBLIC void mgroup2()
+{
+ ++mcount;
+ Ex(&target);
+ buildsegword(&target);
+ getshift(&source);
+ if (mcount != 0x0)
+ {
+ buildunary(0xD0 | segword);
+ if (source.base == CLREG)
+ opcode |= 0x2;
+ else if (source.displ.offset != 0x1)
+ {
+ opcode -= 0x10;
+ source.size = 0x1;
+ buildimm(&source, FALSE);
+ }
+ }
+}
+
+/* LLDT, LTR, SLDT, STR, VERR, VERW */
+
+PUBLIC void mgroup6()
+{
+ ++mcount;
+ Ew(&target);
+ oprefix = 0x0;
+ buildunary(0x0);
+}
+
+/* INVLPG, LGDT, LIDT, LMSW, SGDT, SIDT, SMSW */
+
+PUBLIC void mgroup7()
+{
+ ++mcount;
+ if (opcode == 0x20 || opcode == 0x30)
+ {
+ Ew(&target);
+ oprefix = 0x0;
+ }
+ else
+ {
+ getindirect(&target);
+ oprefix = 0x0;
+ if (target.size != 0x0 && target.size != 0x6)
+ error(MISMATCHED_SIZE); /* XXX - size 6 wrong for INVLPG? */
+ }
+ buildunary(0x1);
+}
+
+/* BT, BTR, BTS, BTC */
+
+PUBLIC void mgroup8()
+{
+ ++mcount;
+ Ev(&target);
+ getcomma();
+ /* Gv or Ib */
+ getea(&source);
+ notindirect(&source);
+ notsegorspecreg(&source);
+ if (mcount != 0x0)
+ {
+ if (source.base == NOREG)
+ {
+ buildunary(0xBA);
+ source.size = 0x1;
+ buildimm(&source, TRUE);
+ }
+ else
+ {
+ yes_samesize();
+ opcode += 0x83;
+ buildregular();
+ }
+ }
+}
+
+/* BSF, BSR, LAR, LSL (Intel manual opcode chart wrongly says GvEw for L*) */
+
+PUBLIC void mGvEv()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ Ev(&target);
+ yes_samesize();
+ buildregular();
+}
+
+/* bound [r16,m16&16 r32,m32&32] */
+
+PUBLIC void mGvMa()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ getindirect(&target);
+ yes_samesize();
+ buildregular();
+}
+
+/* LDS, LES, LFS, LGS, LSS */
+
+PUBLIC void mGvMp()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ getindirect(&target);
+ if (target.size != 0x0 && target.size != 0x2 + source.size)
+ error(MISMATCHED_SIZE);
+ buildregular();
+}
+
+/* IMUL */
+
+PUBLIC void mimul()
+{
+ ++mcount;
+ Ex(&target);
+ if (sym != COMMA)
+ {
+ buildsegword(&target);
+ buildunary(0xF6 | segword);
+ return;
+ }
+ getcomma();
+ notindirect(&target);
+ source = target; /* direction is swapped */
+ getea(&target);
+ notsegorspecreg(&target);
+ yes_samesize();
+ if (sym != COMMA && (target.indcount != 0x0 || target.base != NOREG))
+ {
+ page = PAGE1_OPCODE;
+ ++mcount;
+ opcode = 0xAF;
+ buildregular();
+ }
+ else
+ {
+ if (sym == COMMA)
+ {
+ getsym();
+ getea(&source2);
+ yesimmed(&source2);
+ }
+ else
+ {
+ source2 = target;
+ target = source;
+ }
+ source2.size = target.size;
+ if (is8bitsignedoffset(source2.displ.offset))
+ {
+ source2.size = 0x1;
+ opcode = 0x6B;
+ }
+ else
+ {
+ source2.size = target.size;
+ opcode = 0x69;
+ }
+ buildregular();
+ if (mcount != 0x0)
+ buildimm(&source2, FALSE);
+ }
+}
+
+/* IN */
+
+PUBLIC void min()
+{
+ ++mcount;
+ if (opcode & WORDBIT) /* inw; ind not supported */
+ mnsize = 0x2;
+ if (sym == EOLSYM && mnsize != 0x0)
+ target.size = mnsize;
+ else
+ {
+ if (getaccumreg(&target))
+ {
+ if (mnsize != 0x0 && regsize[target.base] != mnsize)
+ error(MISMATCHED_SIZE);
+ getcomma();
+ }
+ else
+ target.size = regsize[target.base = mnsize < 0x2 ? ALREG : AXREG];
+ opcode |= regsegword[target.base];
+ if (!getdxreg(&source))
+ {
+ getimmed(&source, 0x1);
+ opcode -= 0x8;
+ }
+ }
+ if (target.size > 0x1 && target.size != defsize)
+ oprefix = 0x66;
+}
+
+/* DEC, INC */
+
+PUBLIC void mincdec()
+{
+ ++mcount;
+ Ex(&target);
+ buildsegword(&target);
+ if (target.indcount == 0x0 && segword == WORDBIT)
+ opcode |= 0x40 | rm[target.base];
+ else
+ buildunary(0xFE | segword);
+}
+
+/* CBW, CWD, CMPSW, INSW, IRET, LODSW, POPA, POPF, PUSHA, PUSHF */
+/* MOVSW, OUTSW, SCASW, STOSW */
+
+PUBLIC void minher16()
+{
+ minher();
+ if (defsize != 0x2)
+ oprefix = 0x66;
+}
+
+/* CWDE, CDQ, CMPSD, INSD, IRETD, LODSD, POPAD, POPFD, PUSHAD, PUSHFD */
+/* MOVSD, OUTSD, SCASD, STOSD */
+
+PUBLIC void minher32()
+{
+ minher();
+ if (defsize != 0x4)
+ oprefix = 0x66;
+}
+
+/* AAD, AAM */
+
+PUBLIC void minhera()
+{
+ ++mcount;
+ if (sym == EOLSYM)
+ {
+ target.displ.offset = 0xA;
+ target.size = 0x1;
+ buildimm(&target, FALSE);
+ }
+ else
+ getimmed(&target, 0x1);
+}
+
+/* INT */
+
+PUBLIC void mint()
+{
+ ++mcount;
+ getimmed(&target, 0x1);
+ if (!(immadr.data & (FORBIT | RELBIT | UNDBIT)) &&
+ (opcode_t) immadr.offset == 0x3)
+ {
+ immcount = 0x0;
+ opcode = 0xCC;
+ }
+}
+
+/* JCC */
+
+PUBLIC void mjcc()
+{
+ if (jumps_long && opcode < 0x80) /* above 0x80 means loop - not long */
+ mbcc();
+ else
+ mshort();
+}
+
+/* JCXZ, JECXZ */
+
+PUBLIC void mjcxz()
+{
+ if (opcode != defsize)
+ {
+ aprefix = 0x67;
+ ++mcount; /* quick fix - mshort() needs to know */
+ }
+ opcode = 0xE3;
+ mshort();
+ if (aprefix != 0x0)
+ --mcount; /* quick fix - main routine bumps it again */
+}
+
+/* LEA */
+
+PUBLIC void mlea()
+{
+ Gv(&source); /* back to front */
+ getcomma();
+ ++mcount;
+ getindirect(&target);
+ yes_samesize();
+ buildregular();
+}
+
+/* MOV */
+
+PUBLIC void mmov()
+{
+ getbinary();
+ if (segword >= SEGMOV)
+ {
+ oprefix = 0x0;
+ notimmed(&target); /* target is actually the source */
+ if (segword > SEGMOV) /* special reg */
+ notindirect(&target);
+ }
+ if (mcount != 0x0)
+ {
+ if (target.base == NOREG && target.index == NOREG &&
+ (source.base == ALREG || source.base == AXREG ||
+ source.base == EAXREG))
+ {
+ opcode = 0xA0 | (direction ^ TOREGBIT) | segword;
+ lastexp = target.displ;
+ if ((source.size = displsize(&target)) != defsize)
+ aprefix = 0x67;
+ mcount += source.size;
+ }
+ else if (source.base == NOREG)
+ {
+ if (target.indcount == 0x0)
+ opcode = 0xB0 | (segword << 0x3) | rm[target.base];
+ else
+ {
+ buildea(&target);
+ opcode = 0xC6 | segword;
+ }
+ buildimm(&source, FALSE);
+ }
+ else
+ {
+ if (isspecreg(source.base))
+ {
+ page = PAGE1_OPCODE;
+ ++mcount;
+ opcode = 0x0;
+ }
+ opcode |= direction | segword;
+ buildregular();
+ }
+ }
+}
+
+/* MOVSX, MOVZX */
+
+PUBLIC void mmovx()
+{
+ ++mcount;
+ Gv(&source);
+ getcomma();
+ Ex(&target);
+ if (target.size == 0x0)
+ kgerror(SIZE_UNK);
+ if (target.size > 0x2)
+ kgerror(ILL_SIZE);
+ oprefix = 0x0;
+ if (source.size != defsize)
+ oprefix = 0x66;
+ buildsegword(&target);
+ opcode |= segword;
+ buildregular();
+}
+
+/* NEG, NOT */
+
+PUBLIC void mnegnot()
+{
+ ++mcount;
+ Ex(&target);
+ buildsegword(&target);
+ buildunary(0xF6 | segword);
+}
+
+/* OUT */
+
+PUBLIC void mout()
+{
+ ++mcount;
+ if (opcode & WORDBIT) /* outw; outd not supported */
+ mnsize = 0x2;
+ if (sym == EOLSYM && mnsize != 0x0)
+ source.size = mnsize;
+ else
+ {
+ if (!getdxreg(&target))
+ {
+ getimmed(&target, 0x1);
+ opcode -= 0x8;
+ }
+ if (sym == COMMA)
+ {
+ getsym();
+ if (!getaccumreg(&source))
+ kgerror(AL_AX_EAX_EXP);
+ else if (mnsize != 0x0 && regsize[source.base] != mnsize)
+ error(MISMATCHED_SIZE);
+ }
+ else
+ source.size = regsize[source.base = mnsize < 0x2 ? ALREG : AXREG];
+ opcode |= regsegword[source.base];
+ }
+ if (source.size > 0x1 && source.size != defsize)
+ oprefix = 0x66;
+}
+
+/* POP, PUSH */
+
+PUBLIC void mpushpop()
+{
+ opcode_t oldopcode;
+
+ ++mcount;
+ getea(&target);
+ buildsegword(&target);
+ notbytesize(&target);
+ if ((oldopcode = opcode) == POP_OPCODE)
+ {
+ notimmed(&target);
+ if (target.base == CSREG)
+ kgerror(ILL_SEG_REG);
+ }
+ if (mcount != 0x0)
+ {
+ if (target.indcount == 0x0)
+ {
+ if (segword == SEGMOV)
+ {
+ switch (target.base)
+ {
+ case CSREG:
+ opcode = 0x0E;
+ break;
+ case DSREG:
+ opcode = 0x1E;
+ break;
+ case ESREG:
+ opcode = 0x06;
+ break;
+ case SSREG:
+ opcode = 0x16;
+ break;
+ case FSREG:
+ opcode = 0xA0;
+ page = PAGE1_OPCODE;
+ ++mcount;
+ break;
+ case GSREG:
+ opcode = 0xA8;
+ page = PAGE1_OPCODE;
+ ++mcount;
+ break;
+ }
+ if (oldopcode == POP_OPCODE)
+ ++opcode;
+ }
+ else if (target.base != NOREG)
+ {
+ opcode = 0x50 | rm[target.base];
+ if (oldopcode == POP_OPCODE)
+ opcode |= 0x8;
+ }
+ else
+ {
+ opcode = 0x68;
+ if (oldopcode == POP_OPCODE)
+ ++opcode;
+ buildimm(&target, TRUE);
+ }
+ }
+ else
+ {
+ buildea(&target);
+ if (oldopcode == PUSH_OPCODE)
+ postb |= 0x6 << REG_SHIFT;
+ }
+ }
+}
+
+/* RET, RETF */
+
+PUBLIC void mret()
+{
+ ++mcount;
+ if (sym != EOLSYM)
+ {
+ --opcode;
+ getimmed(&target, 0x2);
+ }
+}
+
+/* SEG CS/DS/ES/FS/GS/SS */
+
+PUBLIC void mseg()
+{
+ reg_pt reg;
+
+ if (regsegword[reg = regchk()] != SEGMOV)
+ error(SEG_REG_REQ);
+ else
+ {
+ getsym();
+ ++mcount;
+ opcode = (segoverride - CSREG)[reg];
+ }
+}
+
+/* SETCC */
+
+PUBLIC void msetcc()
+{
+ ++mcount;
+ Eb(&target);
+ if (mcount != 0x0)
+ buildea(&target);
+}
+
+/* SHLD, SHRD */
+
+PUBLIC void mshdouble()
+{
+ ++mcount;
+ Ev(&target);
+ getcomma();
+ Gv(&source);
+ yes_samesize();
+ buildregular();
+ getshift(&source2);
+ lastexp = target.displ; /* getshift() wiped it out */
+ if (mcount != 0x0)
+ {
+ if (source2.base == CLREG)
+ opcode |= 0x1;
+ else
+ {
+ source2.size = 0x1;
+ buildimm(&source2, FALSE);
+ }
+ }
+}
+
+/*
+ TEST
+ Similar to the regular group1 operators.
+ It does not allow the sign extended immediate byte forms
+ and does not use the relevant direction bit.
+*/
+
+PUBLIC void mtest()
+{
+ getbinary();
+ notsegorspecreg(&source);
+ if (source.base == NOREG)
+ {
+ if (mcount != 0x0)
+ {
+ if (target.indcount == 0x0
+ && (target.base == ALREG || target.base == AXREG
+ || target.base == EAXREG))
+ opcode = 0xA8 | segword;
+ else
+ {
+ buildea(&target);
+ opcode = 0xF6 | segword;
+ }
+ }
+ buildimm(&source, FALSE);
+ }
+ else
+ {
+ opcode |= segword;
+ buildregular();
+ }
+}
+
+/*
+ XCHG
+ Similar to the regular group1 operators.
+ It does not allow any of the immediate forms
+ and does not use the irrelevant direction bit.
+*/
+
+PUBLIC void mxchg()
+{
+ getbinary();
+ notimmed(&source);
+ notsegorspecreg(&source);
+ if (target.indcount == 0x0)
+ {
+ if (target.base == AXREG || target.base == EAXREG)
+ {
+ opcode = 0x90 + rm[source.base];
+ return;
+ }
+ if (source.base == AXREG || source.base == EAXREG)
+ {
+ opcode = 0x90 + rm[target.base];
+ return;
+ }
+ }
+ opcode |= segword;
+ buildregular();
+}
+
+PRIVATE void notbytesize(eap)
+register struct ea_s *eap;
+{
+ if (eap->size == 0x1)
+ kgerror(ILL_SIZE);
+}
+
+PRIVATE void notimmed(eap)
+register struct ea_s *eap;
+{
+ if (eap->indcount == 0x0 && eap->base == NOREG)
+ kgerror(ILL_IMM_MODE);
+}
+
+PRIVATE void notindirect(eap)
+register struct ea_s *eap;
+{
+ if (eap->indcount != 0x0)
+ kgerror(ILL_IND);
+}
+
+PRIVATE void notsegorspecreg(eap)
+register struct ea_s *eap;
+{
+ if (regsegword[eap->base] >= SEGMOV)
+ kgerror(ILLREG);
+}
+
+PRIVATE void yesimmed(eap)
+register struct ea_s *eap;
+{
+ if (eap->indcount == 0x1)
+ eap->indcount = 0x0;
+ if (eap->indcount != 0x0 || eap->base != NOREG)
+ kgerror(IMM_REQ);
+}
+
+PRIVATE void yes_samesize()
+{
+ if (target.size == 0x0)
+ target.size = source.size;
+ else if (source.size != 0x0 && target.size != source.size)
+ kgerror(MISMATCHED_SIZE);
+}
+
+#endif /* I80386 */
+
+#ifdef MC6809
+
+/* 6809 opcode constants */
+
+/* bits for indexed addressing */
+
+#define INDIRECTBIT 0x10
+#define INDEXBIT 0x80 /* except 5 bit offset */
+#define PCRELBIT 0x04 /* PC relative (in certain cases) */
+#define RRBITS 0x60 /* register select bits */
+
+PRIVATE opcode_t rrindex[] = /* register and index bits for indexed adr */
+{
+ 0x60 | INDEXBIT, /* S */
+ 0x40 | INDEXBIT, /* U */
+ 0x00 | INDEXBIT, /* X */
+ 0x20 | INDEXBIT, /* Y */
+ PCRELBIT | INDEXBIT, /* PC */
+};
+
+PRIVATE opcode_t pushpull[] = /* push/pull codes */
+{
+ 0x40, /* S */
+ 0x40, /* U */
+ 0x10, /* X */
+ 0x20, /* Y */
+ 0x80, /* PC */
+ 0x02, /* A */
+ 0x04, /* B */
+ 0x01, /* CC */
+ 0x08, /* DP */
+ 0x06, /* D */
+};
+
+PRIVATE opcode_t tfrexg1[] = /* transfer/exchange codes for source reg */
+{
+ 0x40, /* S */
+ 0x30, /* U */
+ 0x10, /* X */
+ 0x20, /* Y */
+ 0x50, /* PC */
+ 0x80, /* A */
+ 0x90, /* B */
+ 0xA0, /* CC */
+ 0xB0, /* DP */
+ 0x00, /* D */
+};
+
+PRIVATE opcode_t tfrexg2[] = /* transfer/exchange codes for target reg */
+{
+ 0x04, /* S */
+ 0x03, /* U */
+ 0x01, /* X */
+ 0x02, /* Y */
+ 0x05, /* PC */
+ 0x08, /* A */
+ 0x09, /* B */
+ 0x0A, /* CC */
+ 0x0B, /* DP */
+ 0x00, /* D */
+};
+
+FORWARD void checkpostinc P((void));
+FORWARD void doaltind P((void));
+FORWARD void do1altind P((void));
+FORWARD void fixupind P((void));
+FORWARD void getindexnopost P((void));
+FORWARD void inderror P((error_pt errnum));
+FORWARD reg_pt indreg P((reg_pt maxindex));
+FORWARD void predec1 P((void));
+FORWARD void sustack P((reg_pt stackreg));
+
+PRIVATE void checkpostinc()
+{
+ if (sym == ADDOP)
+ {
+ if (postb & INDIRECTBIT)
+ inderror(ILLMOD); /* single-inc indirect illegal */
+ else
+ {
+ lastexp.offset &= 0xFF00; /* for printing if postbyte is 0: ,X+ */
+ getsym();
+ }
+ }
+ else if (sym == POSTINCOP)
+ {
+ postb |= 0x1;
+ getsym();
+ }
+ else
+ postb |= 0x4;
+ fixupind();
+}
+
+/* common code for all-mode ops, alterable-mode ops, indexed ops */
+
+PRIVATE void doaltind()
+{
+ mcount += 0x2;
+ if (sym == LBRACKET)
+ {
+ postb = INDIRECTBIT;
+ getsym();
+ do1altind();
+ if (sym != RBRACKET)
+ error(RBEXP);
+ }
+ else
+ do1altind();
+}
+
+PRIVATE void do1altind()
+{
+ bool_t byteflag; /* set if direct or short indexed adr forced */
+ char *oldlineptr;
+ char *oldsymname;
+ reg_pt reg;
+ bool_t wordflag; /* set if extended or long indexed adr forced*/
+
+ if ((reg = regchk()) != NOREG)
+ {
+ switch (reg)
+ {
+ case AREG:
+ postb |= 0x86;
+ break;
+ case BREG:
+ postb |= 0x85;
+ break;
+ case DREG:
+ postb |= 0x8B;
+ break;
+ default:
+ if (indreg(MAXINDREG) != NOREG)
+ checkpostinc();
+ return;
+ }
+ getsym();
+ if (sym != COMMA)
+ inderror(COMEXP);
+ else
+ getindexnopost();
+ return;
+ }
+ else if (sym == SUBOP) /* could be -R or - in expression */
+ {
+ oldlineptr = lineptr; /* save state */
+ oldsymname = symname;
+ getsym();
+ reg = regchk();
+ lineptr = oldlineptr;
+ symname = oldsymname;
+ if (reg != NOREG)
+ {
+ predec1(); /* it's -R */
+ return;
+ }
+ sym = SUBOP;
+ }
+ else if (sym == COMMA)
+ {
+ postb |= INDEXBIT;
+ getsym();
+ if (sym == SUBOP)
+ {
+ predec1();
+ return;
+ }
+ else if (sym != PREDECOP)
+ {
+ if (indreg(MAXINDREG) != NOREG)
+ checkpostinc();
+ return;
+ }
+ }
+ if (sym == PREDECOP)
+ {
+ postb |= 0x83;
+ getindexnopost();
+ return;
+ }
+
+ /* should have expression */
+
+ wordflag = byteflag = FALSE;
+ if (sym == LESSTHAN)
+ {
+ /* context-sensitive, LESSTHAN means byte-sized here */
+ byteflag = TRUE;
+ getsym();
+ }
+ else if (sym == GREATERTHAN)
+ {
+ /* context-sensitive, GREATERTHAN means word-sized here */
+ wordflag = TRUE;
+ getsym();
+ }
+ expres();
+ if (sym == COMMA)
+ { /* offset from register */
+ getsym();
+ if ((reg = indreg(PCREG)) == NOREG)
+ return;
+ postb |= 0x8; /* default 8 bit offset */
+ if (reg == PCREG)
+ {
+ reldata();
+ if (!(lastexp.data & (RELBIT | UNDBIT)))
+ {
+ lastexp.offset = lastexp.offset - lc;
+ if (page != 0x0)
+ lastexp.offset -= 0x4; /* extra for instruction */
+ else
+ lastexp.offset -= 0x3; /* 3 byte instruction
+ assuming 8 bit offset */
+ }
+ }
+ if (byteflag)
+ {
+ if (!(lastexp.data & (RELBIT | UNDBIT)) &&
+ !is8bitsignedoffset(lastexp.offset))
+ error(ABOUNDS); /* forced short form is impossible */
+ ++mcount;
+ }
+ else if (wordflag || lastexp.data & (FORBIT | RELBIT | UNDBIT) ||
+ !is8bitsignedoffset(lastexp.offset))
+ { /* 16 bit offset */
+ if (postb & PCRELBIT && !(lastexp.data & RELBIT))
+ --lastexp.offset; /* instruction 1 longer than already
+ allowed */
+ postb |= 0x1;
+ mcount += 0x2;
+ }
+ else if (!(postb & PCRELBIT) &&
+ (offset_t) (lastexp.offset + 0x10) < 0x20 &&
+ !(postb & INDIRECTBIT && lastexp.offset != 0x0))
+ { /* 5 bit offset */
+ postb &= RRBITS | INDIRECTBIT;
+ if (lastexp.offset == 0x0)
+ postb |= 0x84; /* index with zero offset */
+ else
+ postb |= (lastexp.offset & 0x1F);
+ }
+ else /* 8 bit offset */
+ ++mcount;
+ fixupind();
+ }
+ else if (postb & INDIRECTBIT)
+ { /* extended indirect */
+ postb = 0x9F;
+ mcount += 0x2;
+ fixupind();
+ }
+ else if (postb & INDEXBIT)
+ inderror(ILLMOD); /* e.g. LEAX $10 */
+ else
+ {
+ if (byteflag || !wordflag && !(lastexp.data & (FORBIT | RELBIT)) &&
+ (lastexp.offset >> 0x8) == dirpag)
+ { /* direct addressing */
+ if (opcode >= 0x80)
+ opcode |= 0x10;
+ }
+ else /* extended addressing */
+ {
+ if (opcode < 0x80)
+ opcode |= 0x70;
+ else
+ opcode |= 0x30;
+ ++mcount;
+ if (pass2 && (opcode == JSR_OPCODE || opcode == JMP_OPCODE) &&
+ !(lastexp.data & IMPBIT) &&
+ lastexp.offset + (0x81 - 0x3) < 0x101)
+ /* JSR or JMP could be done with BSR or BRA */
+ error(SHORTB);
+ }
+ }
+}
+
+PRIVATE void fixupind()
+{
+ if ((opcode & 0x30) == 0x0) /* change all but LEA opcodes */
+ {
+ if (opcode < 0x80)
+ opcode |= 0x60;
+ else
+ opcode |= 0x20;
+ }
+}
+
+PRIVATE void getindexnopost()
+{
+ getsym();
+ if (indreg(MAXINDREG) != NOREG)
+ fixupind();
+}
+
+PRIVATE void inderror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ if (postb & INDIRECTBIT)
+ sym = RBRACKET; /* fake right bracket to kill further errors */
+ fixupind();
+}
+
+/* check current symbol is an index register (possibly excepting PC) */
+/* if so, modify postbyte RR and INDEXBIT for it, get next sym, return TRUE */
+/* otherwise generate error, return FALSE */
+
+PRIVATE reg_pt indreg(maxindex)
+reg_pt maxindex;
+{
+ reg_pt reg;
+
+ if ((reg = regchk()) == NOREG)
+ inderror(IREGEXP);
+ else if (reg > maxindex)
+ {
+ inderror(ILLREG);
+ reg = NOREG;
+ }
+ else
+ {
+ postb |= rrindex[reg];
+ getsym();
+ }
+ return reg;
+}
+
+/* all-mode ops */
+
+PUBLIC void mall()
+{
+ if (sym == IMMEDIATE)
+ mimmed();
+ else
+ malter();
+}
+
+/* alterable mode ops */
+
+PUBLIC void malter()
+{
+ postb = 0x0; /* not yet indexed or indirect */
+ doaltind();
+}
+
+/* indexed mode ops */
+
+PUBLIC void mindex()
+{
+ postb = INDEXBIT; /* indexed but not yet indirect */
+ doaltind();
+}
+
+/* immediate ops */
+
+PUBLIC void mimmed()
+{
+ opcode_t nybble;
+
+ mcount += 0x2;
+ if (sym != IMMEDIATE)
+ error(ILLMOD);
+ else
+ {
+ if (opcode >= 0x80 && ((nybble = opcode & 0xF) == 0x3 ||
+ nybble == 0xC || nybble >= 0xE))
+ ++mcount; /* magic for long immediate */
+ symexpres();
+ if (pass2 && mcount <= 0x2)
+ {
+ chkabs();
+ checkdatabounds();
+ }
+ }
+}
+
+/* long branches */
+
+PUBLIC void mlong()
+{
+ mcount += 0x3; /* may be 0x0 or 0x1 here */
+ expres();
+ if (pass2)
+ {
+ reldata();
+ if (!(lastexp.data & (RELBIT | UNDBIT)))
+ {
+ lastexp.offset = lastexp.offset - lc - lcjump;
+ if (!(lastexp.data & IMPBIT) &&
+ lastexp.offset + 0x81 < 0x101)
+ error(SHORTB); /* -0x81 to 0x7F, warning */
+ }
+ }
+}
+
+/* PSHS and PULS */
+
+PUBLIC void msstak()
+{
+ sustack(SREG);
+}
+
+/* TFR and EXG */
+
+PUBLIC void mswap()
+{
+ reg_pt reg;
+
+ mcount = 0x2;
+ if ((reg = regchk()) == NOREG)
+ error(REGEXP);
+ else
+ {
+ postb = tfrexg1[reg];
+ getsym();
+ if (sym != COMMA)
+ error(COMEXP);
+ else
+ {
+ getsym();
+ if ((reg = regchk()) == NOREG)
+ error(REGEXP);
+ else if ((postb |= tfrexg2[reg])
+ & 0x88 && (postb & 0x88) != 0x88)
+ error(ILLREG); /* registers not of same size */
+ }
+ }
+}
+
+/* PSHU and PULU */
+
+PUBLIC void mustak()
+{
+ sustack(UREG);
+}
+
+PRIVATE void predec1()
+{
+ if (postb & INDIRECTBIT)
+ inderror(ILLMOD); /* single-dec indirect illegal */
+ else
+ {
+ postb |= 0x82;
+ getindexnopost();
+ }
+}
+
+/* common routine for PSHS/PULS/PSHU/PULU */
+
+PRIVATE void sustack(stackreg)
+reg_pt stackreg;
+{
+ reg_pt reg;
+
+ mcount = 0x2;
+ while ((reg = regchk()) != NOREG)
+ {
+ if (reg == stackreg)
+ {
+ error(ILLREG); /* cannot stack self */
+ break;
+ }
+ postb |= pushpull[reg];
+ getsym();
+ if (sym != COMMA)
+ break;
+ getsym();
+ }
+}
+
+#endif /* MC6809 */
+
+/* routines common to all processors */
+
+PUBLIC void getcomma()
+{
+ if (sym != COMMA)
+ error(COMEXP);
+ else
+ getsym();
+}
+
+/* inherent ops */
+
+/* for I80386 */
+/* AAA, AAS, CLC, CLD, CLI, CLTS, CMC, CMPSB, DAA, DAS, HLT, INTO, INSB, */
+/* INVD, */
+/* LAHF, LEAVE, LOCK, LODSB, MOVSB, NOP, OUTSB, REP, REPE, REPNE, REPNZ, */
+/* REPZ, SAHF, SCASB, STC, STD, STI, STOSB, WAIT, WBINVD */
+
+PUBLIC void minher()
+{
+ ++mcount;
+}
+
+/* short branches */
+
+PUBLIC void mshort()
+{
+ nonimpexpres();
+ mshort2();
+}
+
+PRIVATE void mshort2()
+{
+ mcount += 0x2;
+ if (pass2)
+ {
+ reldata();
+ if (lastexp.data & RELBIT)
+ showrelbad();
+ else if (!(lastexp.data & UNDBIT))
+ {
+ lastexp.offset = lastexp.offset - lc - mcount;
+ if (!is8bitsignedoffset(lastexp.offset))
+ error(ABOUNDS);
+ }
+ }
+}
+
+/* check if current symbol is a register, return register number or NOREG */
+
+PRIVATE reg_pt regchk()
+{
+ register struct sym_s *symptr;
+
+ if (sym == IDENT)
+ {
+ if ((symptr = gsymptr)->type & MNREGBIT)
+ {
+ if (symptr->data & REGBIT)
+ {
+#ifdef I80386
+ if (symptr->value_reg_or_op.reg == ST0REG && !fpreg_allowed)
+ error(FP_REG_NOT_ALLOWED);
+#endif
+ return symptr->value_reg_or_op.reg;
+ }
+ }
+ else if (!(symptr->type & (LABIT | MACBIT | VARBIT)))
+ symptr->data |= FORBIT; /* show seen in advance */
+ }
+ return NOREG;
+}
+
+/* convert lastexp.data for PC relative */
+
+PRIVATE void reldata()
+{
+ if ((lastexp.data ^ lcdata) & (IMPBIT | RELBIT | SEGM))
+ {
+ if ((lastexp.data ^ lcdata) & RELBIT)
+ showrelbad(); /* rel - abs is weird, abs - rel is bad */
+ else
+ {
+ pcrflag = OBJ_R_MASK;
+ lastexp.data = (lcdata & ~SEGM) | lastexp.data | RELBIT;
+ /* segment is that of lastexp.data */
+ }
+ }
+ else /* same file, segment and relocation */
+ lastexp.data = (lastexp.data | lcdata) & ~(RELBIT | SEGM);
+}
diff --git a/as/obj1/calljmp.obj b/as/obj1/calljmp.obj
new file mode 100644
index 0000000..522d6f7
--- /dev/null
+++ b/as/obj1/calljmp.obj
Binary files differ
diff --git a/as/obj1/ea.obj b/as/obj1/ea.obj
new file mode 100644
index 0000000..6b53beb
--- /dev/null
+++ b/as/obj1/ea.obj
Binary files differ
diff --git a/as/obj1/each.obj b/as/obj1/each.obj
new file mode 100644
index 0000000..5426253
--- /dev/null
+++ b/as/obj1/each.obj
Binary files differ
diff --git a/as/obj1/f.obj b/as/obj1/f.obj
new file mode 100644
index 0000000..4dbe2d9
--- /dev/null
+++ b/as/obj1/f.obj
Binary files differ
diff --git a/as/obj1/fadd.obj b/as/obj1/fadd.obj
new file mode 100644
index 0000000..28b3dd4
--- /dev/null
+++ b/as/obj1/fadd.obj
Binary files differ
diff --git a/as/obj1/farcall.obj b/as/obj1/farcall.obj
new file mode 100644
index 0000000..259703c
--- /dev/null
+++ b/as/obj1/farcall.obj
Binary files differ
diff --git a/as/obj1/group1.obj b/as/obj1/group1.obj
new file mode 100644
index 0000000..26d4a8c
--- /dev/null
+++ b/as/obj1/group1.obj
Binary files differ
diff --git a/as/obj1/group6.obj b/as/obj1/group6.obj
new file mode 100644
index 0000000..27e81ae
--- /dev/null
+++ b/as/obj1/group6.obj
Binary files differ
diff --git a/as/obj1/group7.obj b/as/obj1/group7.obj
new file mode 100644
index 0000000..37af051
--- /dev/null
+++ b/as/obj1/group7.obj
Binary files differ
diff --git a/as/obj1/imul.obj b/as/obj1/imul.obj
new file mode 100644
index 0000000..34ef370
--- /dev/null
+++ b/as/obj1/imul.obj
Binary files differ
diff --git a/as/obj1/incdec.obj b/as/obj1/incdec.obj
new file mode 100644
index 0000000..03f583a
--- /dev/null
+++ b/as/obj1/incdec.obj
Binary files differ
diff --git a/as/obj1/inher.obj b/as/obj1/inher.obj
new file mode 100644
index 0000000..aaea0b9
--- /dev/null
+++ b/as/obj1/inher.obj
Binary files differ
diff --git a/as/obj1/inout.obj b/as/obj1/inout.obj
new file mode 100644
index 0000000..58aa820
--- /dev/null
+++ b/as/obj1/inout.obj
Binary files differ
diff --git a/as/obj1/movspec.obj b/as/obj1/movspec.obj
new file mode 100644
index 0000000..15eab78
--- /dev/null
+++ b/as/obj1/movspec.obj
Binary files differ
diff --git a/as/obj1/pushpop.obj b/as/obj1/pushpop.obj
new file mode 100644
index 0000000..2ff789e
--- /dev/null
+++ b/as/obj1/pushpop.obj
Binary files differ
diff --git a/as/obj1/seg.obj b/as/obj1/seg.obj
new file mode 100644
index 0000000..2ba948c
--- /dev/null
+++ b/as/obj1/seg.obj
Binary files differ
diff --git a/as/obj1/shdouble.obj b/as/obj1/shdouble.obj
new file mode 100644
index 0000000..ab75750
--- /dev/null
+++ b/as/obj1/shdouble.obj
Binary files differ
diff --git a/as/obj1/shift.obj b/as/obj1/shift.obj
new file mode 100644
index 0000000..520be81
--- /dev/null
+++ b/as/obj1/shift.obj
Binary files differ
diff --git a/as/obj1/xchg.obj b/as/obj1/xchg.obj
new file mode 100644
index 0000000..c39b703
--- /dev/null
+++ b/as/obj1/xchg.obj
Binary files differ
diff --git a/as/opcode.h b/as/opcode.h
new file mode 100644
index 0000000..385c096
--- /dev/null
+++ b/as/opcode.h
@@ -0,0 +1,157 @@
+/* opcode.h - routine numbers and special opcodes for assembler */
+
+enum
+{
+/* Pseudo-op routine numbers.
+ * Conditionals are first - this is used to test if op is a conditional.
+ */
+ ELSEOP,
+ ELSEIFOP,
+ ELSEIFCOP,
+ ENDIFOP,
+ IFOP,
+ IFCOP,
+
+#define MIN_NONCOND ALIGNOP
+ ALIGNOP,
+ ASCIZOP,
+ BLKWOP,
+ BLOCKOP,
+ BSSOP,
+ COMMOP,
+ COMMOP1,
+ DATAOP,
+ ENDBOP,
+ ENTEROP,
+ ENTRYOP,
+ EQUOP,
+ EVENOP,
+ EXPORTOP,
+ FAILOP,
+ FCBOP,
+ FCCOP,
+ FDBOP,
+ FQBOP,
+ GETOP,
+ GLOBLOP,
+ IDENTOP,
+ IMPORTOP,
+ LCOMMOP,
+ LCOMMOP1,
+ LISTOP,
+ LOCOP,
+ MACLISTOP,
+ MACROOP,
+ MAPOP,
+ ORGOP,
+ PROCEOFOP,
+ RMBOP,
+ SECTOP,
+ SETOP,
+ SETDPOP,
+ TEXTOP,
+#ifdef I80386
+ USE16OP,
+ USE32OP,
+#endif
+ WARNOP,
+
+/* Machine-op routine numbers. */
+#ifdef I80386
+ BCC,
+ BSWAP,
+ CALL,
+ CALLI,
+ DIVMUL,
+ ENTER,
+ EwGw,
+ ExGx,
+ F_INHER,
+ F_M,
+ F_M2,
+ F_M2_AX,
+ F_M2_M4,
+ F_M2_M4_M8,
+ F_M4_M8_OPTST,
+ F_M4_M8_ST,
+ F_M4_M8_STST,
+ F_M4_M8_M10_ST,
+ F_M10,
+ F_OPTST,
+ F_ST,
+ F_STST,
+ F_W_INHER,
+ F_W_M,
+ F_W_M2,
+ F_W_M2_AX,
+ GROUP1,
+ GROUP2,
+ GROUP6,
+ GROUP7,
+ GROUP8,
+ GvEv,
+ GvMa,
+ GvMp,
+ IMUL,
+ IN,
+ INCDEC,
+ INHER,
+ INHER16,
+ INHER32,
+ INHER_A,
+ INT,
+ JCC,
+ JCXZ,
+ LEA,
+ MOV,
+ MOVX,
+ NEGNOT,
+ OUT,
+ PUSHPOP,
+ RET,
+ SEG,
+ SETCC,
+ SH_DOUBLE,
+ TEST,
+ XCHG
+#endif /* I80386 */
+
+#ifdef MC6809
+ ALL, /* all address modes allowed, like LDA */
+ ALTER, /* all but immediate, like STA */
+ IMMED, /* immediate only (ANDCC, ORCC) */
+ INDEXD, /* indexed (LEA's) */
+ INHER, /* inherent, like CLC or CLRA */
+ LONG, /* long branches */
+ SHORT, /* short branches */
+ SSTAK, /* S-stack (PSHS, PULS) */
+ SWAP, /* TFR, EXG */
+ USTAK /* U-stack (PSHU,PULU) */
+#endif /* MC6809 */
+};
+
+/* Special opcodes. */
+#ifdef I80386
+# define CMP_OPCODE_BASE 0x38
+# define CMPSB_OPCODE 0xA6
+# define CMPSW_OPCODE 0xA7
+# define ESCAPE_OPCODE_BASE 0xD8
+# define FST_ENCODED 0x12
+# define FSTP_ENCODED 0x13
+# define JMP_OPCODE 0xE9
+# define JMP_SHORT_OPCODE 0xEB
+# define JSR_OPCODE 0xE8
+# define MOVSB_OPCODE 0xA4
+# define MOVSW_OPCODE 0xA5
+# define PAGE1_OPCODE 0x0F
+# define POP_OPCODE 0x8F
+# define PUSH_OPCODE 0xFF
+# define WAIT_OPCODE 0x9B
+#endif
+
+#ifdef MC6809
+# define JMP_OPCODE 0x7E
+# define JSR_OPCODE 0xBD
+# define PAGE1_OPCODE 0x10
+# define PAGE2_OPCODE 0x11
+#endif
diff --git a/as/pops.c b/as/pops.c
new file mode 100644
index 0000000..f7888d4
--- /dev/null
+++ b/as/pops.c
@@ -0,0 +1,1048 @@
+/* pops.c - handle pseudo-ops for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "address.h"
+#include "flag.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+
+PRIVATE bool_t elseflag; /* set if ELSE/ELSEIF are enabled */
+ /* depends on zero = FALSE init */
+PRIVATE bool_t lcommflag;
+
+FORWARD void bumpsem P((struct flags_s *flagptr));
+FORWARD void constdata P((unsigned size));
+FORWARD void docomm P((void));
+FORWARD void doelseif P((pfv func));
+FORWARD void doequset P((int labits));
+FORWARD void doentexp P((int entbits, int impbits));
+FORWARD void dofcc P((void));
+FORWARD void doif P((pfv func));
+FORWARD struct sym_s *needlabel P((void));
+FORWARD void showredefinedlabel P((void));
+FORWARD void setloc P((unsigned seg));
+
+PRIVATE void bumpsem(flagptr)
+register struct flags_s *flagptr;
+{
+ int newcount;
+
+ if (flagptr->global &&pass != 0)
+ {
+ /* bump semaphore count by an expression (default 1), */
+ /* then set currentflag iff semaphore count is plus */
+ if (sym == EOLSYM)
+ lastexp.offset = 1;
+ else
+ {
+ absexpres();
+ if (lastexp.data & UNDBIT)
+ return;
+ }
+ newcount = (int) lastexp.offset;
+#ifdef I80386 /* really sizeof (offset_t) != sizeof (int) */
+ if (newcount != lastexp.offset)
+ datatoobig();
+#endif
+ newcount += flagptr->semaphore;
+ if ((int) lastexp.offset >= 0)
+ {
+ if (newcount < flagptr->semaphore)
+ {
+ error(COUNTOV);
+ newcount = 0x7fff;
+ }
+ }
+ else if (newcount >= flagptr->semaphore)
+ {
+ error(COUNTUN);
+ newcount = -0x8000;
+ }
+ flagptr->semaphore = newcount;
+ flagptr->current = newcount >= 0;
+ }
+}
+
+/* check symbol is either undefined */
+/* or has the same segment & relocatability as lc */
+
+PUBLIC bool_pt checksegrel(symptr)
+register struct sym_s *symptr;
+{
+ if ((symptr->type & LABIT ||
+ (symptr->data & IMPBIT && !(symptr->data & UNDBIT))) &&
+ ((symptr->data ^ lcdata) & (RELBIT | SEGM)))
+ {
+ error(SEGREL);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* check address fits in 1 byte (possibly with sign truncated) */
+
+PUBLIC void checkdatabounds()
+{
+ if (!(lastexp.data & UNDBIT) &&
+ (offset_t) (lastexp.offset + 0x80) >= 0x180)
+ datatoobig();
+}
+
+/* allocate constant data (zero except for size 1), default zero for size 1 */
+
+PRIVATE void constdata(size)
+unsigned size;
+{
+ offset_t remaining;
+
+ absexpres();
+ if (!((lcdata |= lastexp.data) & UNDBIT))
+ {
+ lcjump = lastexp.offset * size;
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ if (size == 1 && sym == COMMA)
+ {
+ symabsexpres();
+ checkdatabounds();
+ for (remaining = lcjump; remaining != 0; --remaining)
+ {
+ putbin((opcode_pt) lastexp.offset); /* fill byte */
+ putabs((opcode_pt) lastexp.offset);
+ }
+ lastexp.offset = lcjump;
+ }
+ else
+ accumulate_rmb(lastexp.offset * size);
+ }
+}
+
+PUBLIC void datatoobig()
+{
+ error(DBOUNDS);
+}
+
+/* common routine for COMM/.COMM */
+
+PRIVATE void docomm()
+{
+ register struct sym_s *labptr;
+
+ absexpres(); /* if undefined, value 0 and size unchanged */
+ labptr = label;
+ if (checksegrel(labptr))
+ {
+ if (labptr->type & (EXPBIT | LABIT))
+ labelerror(ALREADY);
+ else
+ {
+ if (!(labptr->type & COMMBIT) ||
+ lastexp.offset > labptr->value_reg_or_op.value)
+ labptr->value_reg_or_op.value = lastexp.offset;
+ labptr->type |= COMMBIT;
+ if (lcommflag)
+ labptr->type |= REDBIT; /* kludge - COMMBIT | REDBIT => SA */
+ labptr->data = (lcdata & SEGM) | (FORBIT | IMPBIT | RELBIT);
+ showlabel();
+ }
+ }
+ lcommflag = FALSE;
+}
+
+/* common routine for ELSEIF/ELSEIFC */
+
+PRIVATE void doelseif(func)
+pfv func;
+{
+ if (iflevel == 0)
+ error(ELSEIFBAD);
+ else
+ {
+ ifflag = FALSE;
+ if (elseflag)
+ {
+ (*func) ();
+ if (!(lastexp.data & UNDBIT) && lastexp.offset != 0)
+ /* expression valid and TRUE, enable assembling */
+ {
+ ifflag = TRUE;
+ elseflag = FALSE;
+ }
+ }
+ }
+}
+
+/* common routine for EQU/SET */
+
+PRIVATE void doequset(labits)
+unsigned char labits;
+{
+ register struct sym_s *labptr;
+ unsigned char olddata;
+ unsigned char oldtype;
+
+ labptr = label;
+ /* set up new label flags in case labe isl used in expression */
+ labptr->type = (oldtype = labptr->type) | labits;
+ labptr->data = (olddata = labptr->data) & ~IMPBIT;
+ /* non-imported now */
+ nonimpexpres();
+ lastexp.data |= olddata & FORBIT; /* take all but FORBIT from
+ expression */
+ if (oldtype & LABIT && !(olddata & UNDBIT))
+ /* this is a previously defined label */
+
+ /*
+ redefinition only allowed if same relocatability, segment and
+ value
+ */
+ {
+ if ((olddata ^ lastexp.data) & (RELBIT | UNDBIT) ||
+ labptr->value_reg_or_op.value != lastexp.offset)
+ {
+ showredefinedlabel();
+ return;
+ }
+ }
+ labptr->data = lastexp.data;
+ labptr->value_reg_or_op.value = lastexp.offset;
+ showlabel();
+}
+
+/* common routine for ENTRY/EXPORT */
+
+PRIVATE void doentexp(entbits, impbits)
+unsigned char entbits;
+unsigned char impbits;
+{
+ struct sym_s *symptr;
+
+ while (TRUE)
+ {
+ if ((symptr = needlabel()) != NUL_PTR)
+ {
+ if (symptr->type & COMMBIT)
+ error(ALREADY);
+ else if (impbits != 0)
+ {
+ if (pass != 0)
+ ;
+ else if (symptr->type & (EXPBIT | LABIT))
+ symptr->type |= EXPBIT;
+ else
+ {
+ symptr->type |= REDBIT;
+ if (!(symptr->data & IMPBIT))
+ symptr->data |= IMPBIT | SEGM;
+ }
+ }
+ else
+ {
+ if (pass != 0)
+ {
+ if (!(symptr->type & LABIT))
+ error(UNLAB);
+ }
+ else
+ {
+ symptr->type |= entbits | EXPBIT;
+ symptr->data &= ~IMPBIT;
+ }
+ }
+ }
+ getsym();
+ if (sym != COMMA)
+ break;
+ getsym();
+ }
+}
+
+/* common routine for FCC (== .ASCII) and .ASCIZ */
+
+PRIVATE void dofcc()
+{
+ register char *bufptr;
+ char byte;
+ char delimiter;
+ register char *reglineptr;
+
+ bufptr = databuf.fcbuf;
+ reglineptr = symname;
+ if ((delimiter = *reglineptr) != EOLCHAR)
+ ++reglineptr;
+ while (TRUE)
+ {
+ if ((byte = *reglineptr) == EOLCHAR)
+ {
+ symname = reglineptr;
+ error(DELEXP);
+ break;
+ }
+ if (byte == delimiter)
+ {
+ if ((byte = *++reglineptr) != delimiter)
+ break;
+ }
+ else if (byte == '\\')
+ {
+ switch (byte = *++reglineptr)
+ {
+ case '"':
+ case '\'':
+ case '\\':
+ case '?':
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ byte -= '0';
+ if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8')
+ {
+ byte = 8 * byte + *++reglineptr - '0';
+ if (*(reglineptr + 1) >= '0' && *(reglineptr + 1) < '8')
+ byte = 8 * byte + *++reglineptr - '0';
+ }
+ break;
+ case 'a':
+ byte = 7;
+ break;
+ case 'b':
+ byte = 8;
+ break;
+ case 'f':
+ byte = 12;
+ break;
+ case 'n':
+ byte = 10;
+ break;
+ case 'r':
+ byte = 13;
+ break;
+ case 't':
+ byte = 9;
+ break;
+ case 'v':
+ byte = 11;
+ break;
+ case 'x':
+ byte = '0';
+ while (TRUE)
+ {
+ ++reglineptr;
+ if (*reglineptr >= '0' && *reglineptr <= '9')
+ byte = 16 * byte + *reglineptr - '0';
+ else if (*reglineptr >= 'F' && *reglineptr <= 'F')
+ byte = 16 * byte + *reglineptr - 'A';
+ else if (*reglineptr >= 'a' && *reglineptr <= 'f')
+ byte = 16 * byte + *reglineptr - 'F';
+ else
+ break;
+ }
+ --reglineptr;
+ break;
+ default:
+ symname = reglineptr;
+ error(UNKNOWN_ESCAPE_SEQUENCE);
+ break;
+ }
+ }
+ else if (byte < ' ' && byte >= 0)
+ {
+ symname = reglineptr;
+ error(CTLINS);
+ byte = ' ';
+ }
+ ++reglineptr;
+ *bufptr++ = byte;
+ }
+ lineptr = reglineptr;
+ getsym();
+ lastexp.offset = databuf.fcbuf[0]; /* show only 1st char (if any) */
+ mcount = bufptr - databuf.fcbuf;
+ /* won't overflow, line length limits it */
+ /* XXX - but now line length is unlimited */
+}
+
+/* common routine for IF/IFC */
+
+PRIVATE void doif(func)
+pfv func;
+{
+ if (iflevel >= MAXIF)
+ error(IFOV);
+ else
+ {
+ ++iflevel;
+ --ifstak;
+ ifstak->elseflag = elseflag;
+ elseflag = FALSE; /* prepare */
+ if ((ifstak->ifflag = ifflag) != FALSE)
+ /* else not assembling before, so not now & no ELSE's */
+ {
+ (*func) ();
+ if (!(lastexp.data & UNDBIT) && lastexp.offset == 0)
+ /* else expression invalid or FALSE, don't change flags */
+ {
+ ifflag = FALSE; /* not assembling */
+ elseflag = TRUE;/* but ELSE will change that */
+ }
+ }
+ }
+}
+
+PUBLIC void fatalerror(errnum)
+error_pt errnum;
+{
+ error(errnum);
+ skipline();
+ listline();
+ finishup();
+}
+
+/* swap position with label position, do error, put back posn */
+/* also clear label ptr */
+
+PUBLIC void labelerror(errnum)
+error_pt errnum;
+{
+ struct sym_s *oldgsymptr;
+ char *oldlineptr;
+ unsigned char oldsym;
+ char *oldsymname;
+
+ oldgsymptr = gsymptr;
+ oldlineptr = lineptr;
+ oldsym = sym;
+ oldsymname = symname;
+ lineptr = linebuf;
+ getsym(); /* 1st symbol is label or symbol after
+ * missing one */
+ error(errnum);
+ gsymptr = oldgsymptr;
+ lineptr = oldlineptr;
+ sym = oldsym;
+ symname = oldsymname;
+ label = NUL_PTR;
+}
+
+PRIVATE struct sym_s *needlabel()
+{
+ register struct sym_s *symptr;
+
+ if (sym != IDENT ||
+ (symptr = gsymptr)->type & (MACBIT | MNREGBIT | VARBIT))
+ {
+ error(LABEXP);
+ return NUL_PTR;
+ }
+ return symptr;
+}
+
+/* .ALIGN pseudo-op */
+
+PUBLIC void palign()
+{
+ absexpres();
+ if (!((lcdata |= lastexp.data) & UNDBIT))
+ {
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ if (lastexp.offset != 0 &&
+ (lcjump = lc % lastexp.offset) != 0)
+ accumulate_rmb(lcjump = lastexp.offset - lcjump);
+ }
+}
+
+/* .ASCIZ pseudo-op */
+
+PUBLIC void pasciz()
+{
+ dofcc();
+ databuf.fcbuf[mcount++] = 0;
+ fcflag = TRUE;
+ popflags = POPLO | POPLC;
+}
+
+/* .BLKW pseudo-op */
+
+PUBLIC void pblkw()
+{
+ constdata(2);
+}
+
+/* BLOCK pseudo-op */
+
+PUBLIC void pblock()
+{
+ if (blocklevel >= MAXBLOCK)
+ error(BLOCKOV);
+ else
+ {
+ register struct block_s *blockp;
+
+ ++blocklevel;
+ blockp = blockstak;
+ blockstak = --blockp;
+ blockp->data = lcdata;
+ blockp->dp = dirpag;
+ blockp->lc = lc;
+ porg(); /* same as ORG apart from stacking */
+ }
+}
+
+/* .BSS pseudo-op */
+
+PUBLIC void pbss()
+{
+ setloc(BSSLOC);
+}
+
+/* COMM pseudo-op */
+
+PUBLIC void pcomm()
+{
+ if (label == NUL_PTR)
+ labelerror(MISLAB);
+ else if (label->type & VARBIT)
+ labelerror(VARLAB); /* variable cannot be COMM'd */
+ else
+ docomm();
+}
+
+/* .COMM pseudo-op */
+
+PUBLIC void pcomm1()
+{
+ unsigned oldseg;
+
+ if (label != NUL_PTR)
+ labelerror(ILLAB);
+ oldseg = lcdata & SEGM;
+ setloc(BSSLOC);
+ if ((label = needlabel()) != NUL_PTR && checksegrel(label))
+ {
+ /* Like import. */
+ if (label->type & (EXPBIT | LABIT))
+ error(ALREADY);
+ else
+ label->data = lcdata | (FORBIT | IMPBIT | RELBIT);
+ getsym();
+ getcomma();
+ if (label->type & (EXPBIT | LABIT))
+ absexpres(); /* just to check it */
+ else
+ docomm();
+ }
+ setloc(oldseg);
+}
+
+/* .DATA pseudo-op */
+
+PUBLIC void pdata()
+{
+ setloc(DATALOC);
+}
+
+/* ELSE pseudo-op */
+
+PUBLIC void pelse()
+{
+ if (iflevel == 0)
+ error(ELSEBAD);
+ else
+ {
+ ifflag = FALSE; /* assume ELSE disabled */
+ if (elseflag)
+ {
+ ifflag = TRUE; /* ELSE enabled */
+ elseflag = FALSE;
+ }
+ }
+}
+
+/* ELSEIF pseudo-op */
+
+PUBLIC void pelseif()
+{
+ doelseif(absexpres);
+}
+
+/* ELSEIFC pseudo-op */
+
+PUBLIC void pelsifc()
+{
+ doelseif(scompare);
+}
+
+/* ENDB pseudo-op */
+
+PUBLIC void pendb()
+{
+ if (label != NUL_PTR)
+ labelerror(ILLAB);
+ if (blocklevel == 0)
+ error(ENDBBAD);
+ else
+ {
+ register struct block_s *blockp;
+
+ blockp = blockstak;
+ lcdata = blockp->data;
+ dirpag = blockp->dp;
+ accumulate_rmb(blockp->lc - lc);
+ lc = blockp->lc;
+ --blocklevel;
+ blockstak = blockp + 1;
+ }
+}
+
+/* ENDIF pseudo-op */
+
+PUBLIC void pendif()
+{
+ if (iflevel == 0)
+ error(ENDIFBAD);
+ else
+ {
+ ifflag = ifstak->ifflag;
+ elseflag = ifstak->elseflag;
+ ++ifstak;
+ --iflevel;
+ }
+}
+
+/* ENTER pseudo-op */
+
+PUBLIC void penter()
+{
+ if (!(pedata & UNDBIT))
+ error(REENTER);
+ else
+ {
+ if (!((pedata = (pedata & ~UNDBIT) | lcdata) & UNDBIT))
+ {
+ progent = lc;
+ popflags = POPLC;
+ }
+ }
+}
+
+/* ENTRY pseudo-op */
+
+PUBLIC void pentry()
+{
+ doentexp(ENTBIT, 0);
+}
+
+/* EQU pseudo-op */
+
+PUBLIC void pequ()
+{
+ register struct sym_s *labptr;
+
+ if ((labptr = label) == NUL_PTR)
+ labelerror(MISLAB);
+ else if (labptr->type & COMMBIT)
+ showredefinedlabel(); /* common cannot be EQU'd */
+ else if (labptr->type & VARBIT)
+ labelerror(VARLAB); /* variable cannot be EQU'd */
+ else
+ doequset(LABIT);
+}
+
+/* .EVEN pseudo-op */
+
+PUBLIC void peven()
+{
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ accumulate_rmb(lcjump = lastexp.data = lc & 1);
+}
+
+/* EXPORT pseudo-op */
+
+PUBLIC void pexport()
+{
+ doentexp(0, 0);
+}
+
+/* FAIL pseudo-op */
+
+PUBLIC void pfail()
+{
+ error(FAILERR);
+}
+
+/* FCB pseudo-op */
+
+PUBLIC void pfcb()
+{
+ char *bufptr;
+ offset_t firstbyte;
+
+ bufptr = databuf.fcbuf;
+ absexpres();
+ firstbyte = lastexp.offset;
+ while (TRUE)
+ {
+ checkdatabounds();
+ *bufptr++ = lastexp.offset;
+ ++mcount; /* won't overflow, line length limits it */
+ if (sym != COMMA)
+ break;
+ symabsexpres();
+ }
+ lastexp.offset = firstbyte;
+ popflags = POPLO | POPLC;
+ fcflag = TRUE;
+}
+
+/* FCC pseudo-op */
+
+PUBLIC void pfcc()
+{
+ dofcc();
+ if (mcount != 0)
+ {
+ fcflag = TRUE;
+ popflags = POPLO | POPLC;
+ }
+}
+
+/* FDB pseudo-op */
+
+PUBLIC void pfdb()
+{
+ struct address_s *adrptr;
+ unsigned firstdata;
+ offset_t firstword;
+
+ adrptr = databuf.fdbuf;
+ expres();
+ firstword = lastexp.offset;
+ firstdata = lastexp.data;
+ while (TRUE)
+ {
+ *adrptr++ = lastexp;
+ mcount += 2; /* won't overflow, line length limits it */
+ if (sym != COMMA)
+ break;
+ symexpres();
+ }
+ lastexp.offset = firstword;
+ lastexp.data = firstdata;
+ popflags = POPHI | POPLO | POPLC;
+ fdflag = TRUE;
+}
+
+#if SIZEOF_OFFSET_T > 2
+
+/* FQB pseudo-op */
+
+PUBLIC void pfqb()
+{
+ struct address_s *adrptr;
+ offset_t firstdata;
+ offset_t firstword;
+
+ adrptr = databuf.fqbuf;
+ expres();
+ firstword = lastexp.offset;
+ firstdata = lastexp.data;
+ while (TRUE)
+ {
+ *adrptr++ = lastexp;
+ mcount += 4; /* won't overflow, line length limits it */
+ if (sym != COMMA)
+ break;
+ symexpres();
+ }
+ lastexp.offset = firstword;
+ lastexp.data = firstdata;
+ popflags = POPLONG | POPHI | POPLO | POPLC;
+ fqflag = TRUE;
+}
+
+#endif /* SIZEOF_OFFSET_T > 2 */
+
+/* .GLOBL pseudo-op */
+
+PUBLIC void pglobl()
+{
+ if (binaryg)
+ error(NOIMPORT);
+ doentexp(0, IMPBIT);
+}
+
+/* IDENT pseudo-op (not complete) */
+
+PUBLIC void pident()
+{
+ if (sym != IDENT)
+ error(LABEXP);
+ else
+ getsym_nolookup(); /* should save ident string */
+}
+
+/* IF pseudo-op */
+
+PUBLIC void pif()
+{
+ doif(absexpres);
+}
+
+/* IFC pseudo-op */
+
+PUBLIC void pifc()
+{
+ doif(scompare);
+}
+
+/* IMPORT pseudo-op */
+
+PUBLIC void pimport()
+{
+ struct sym_s *symptr;
+
+ if (binaryg)
+ error(NOIMPORT);
+ while (TRUE)
+ {
+ if ((symptr = needlabel()) != NUL_PTR && checksegrel(symptr))
+ {
+ if (symptr->type & (COMMBIT | EXPBIT | LABIT))
+ /* IMPORT is null if label (to be) declared */
+ error(ALREADY);
+ else
+ /* get current segment from lcdata, no need to mask rest */
+ symptr->data = lcdata | (FORBIT | IMPBIT | RELBIT);
+ }
+ getsym();
+ if (sym != COMMA)
+ break;
+ getsym();
+ }
+}
+
+/* LCOMM pseudo-op */
+
+PUBLIC void plcomm()
+{
+ lcommflag = TRUE;
+ pcomm();
+}
+
+/* .LCOMM pseudo-op */
+
+PUBLIC void plcomm1()
+{
+ lcommflag = TRUE;
+ pcomm1();
+}
+
+/* .LIST pseudo-op */
+
+PUBLIC void plist()
+{
+ bumpsem(&list);
+}
+
+/* LOC pseudo-op */
+
+PUBLIC void ploc()
+{
+ if (label != NUL_PTR)
+ labelerror(ILLAB);
+ absexpres();
+ if (!(lastexp.data & UNDBIT))
+ {
+ if (lastexp.offset >= NLOC)
+ datatoobig();
+ else
+ setloc((unsigned) lastexp.offset);
+ }
+}
+
+/* .MACLIST pseudo-op */
+
+PUBLIC void pmaclist()
+{
+ bumpsem(&maclist);
+}
+
+/* .MAP pseudo-op */
+
+PUBLIC void pmap()
+{
+ absexpres();
+ if (!(lastexp.data & UNDBIT))
+ {
+ mapnum = lastexp.offset;
+ popflags = POPLO;
+ if (lastexp.offset >= 0x100)
+ datatoobig();
+ }
+}
+
+/* ORG pseudo-op */
+
+PUBLIC void porg()
+{
+ if (label != NUL_PTR)
+ labelerror(ILLAB);
+ absexpres();
+ if (!((lcdata = lastexp.data) & UNDBIT))
+ {
+ accumulate_rmb(lastexp.offset - lc);
+ binmbuf = lc = lastexp.offset;
+ popflags = POPLC;
+ }
+}
+
+/* RMB pseudo-op */
+
+PUBLIC void prmb()
+{
+ constdata(1);
+}
+
+/* .SECT pseudo-op */
+
+PUBLIC void psect()
+{
+ if (label != NUL_PTR)
+ labelerror(ILLAB);
+ while (sym == IDENT)
+ {
+ if (!(gsymptr->type & MNREGBIT))
+ error(ILL_SECTION);
+ else switch (gsymptr->value_reg_or_op.op.routine)
+ {
+ case BSSOP:
+ pbss();
+ break;
+ case DATAOP:
+ pdata();
+ break;
+ case TEXTOP:
+ ptext();
+ break;
+ default:
+ error(ILL_SECTION);
+ break;
+ }
+ getsym();
+ if (sym == COMMA)
+ getsym();
+ }
+}
+
+/* SET pseudo-op */
+
+PUBLIC void pset()
+{
+ register struct sym_s *labptr;
+
+ if ((labptr = label) == NUL_PTR)
+ labelerror(MISLAB);
+ else if (labptr->type & COMMBIT)
+ labelerror(RELAB); /* common cannot be SET'd */
+ else
+ doequset(labptr->type & LABIT ? 0 : VARBIT);
+}
+
+/* SETDP pseudo-op */
+
+PUBLIC void psetdp()
+{
+ absexpres();
+ if (!(lastexp.data & UNDBIT))
+ {
+ dirpag = lastexp.offset;
+ popflags = POPLO;
+ if (lastexp.offset >= 0x100)
+ datatoobig();
+ }
+}
+
+/* .TEXT pseudo-op */
+
+PUBLIC void ptext()
+{
+ setloc(TEXTLOC);
+}
+
+/* .WARN pseudo-op */
+
+PUBLIC void pwarn()
+{
+ bumpsem(&warn);
+}
+
+#ifdef I80386
+
+/* USE16 pseudo-op */
+
+PUBLIC void puse16()
+{
+ defsize = 2;
+}
+
+/* USE16 pseudo-op */
+
+PUBLIC void puse32()
+{
+ defsize = 4;
+}
+
+#endif
+
+/* show redefined label and error, and set REDBIT */
+
+PRIVATE void showredefinedlabel()
+{
+ register struct sym_s *labptr;
+
+ labptr = label; /* showlabel() will kill label prematurely */
+ showlabel();
+ if (!(labptr->type & REDBIT))
+ {
+ labptr->type |= REDBIT;
+ labelerror(RELAB);
+ }
+}
+
+PUBLIC void showlabel()
+{
+ register struct sym_s *labptr;
+
+ labptr = label;
+ lastexp.data = labptr->data;
+ lastexp.offset = labptr->value_reg_or_op.value;
+ popflags = POPLONG | POPHI | POPLO;
+ label = NUL_PTR; /* show handled by COMM, EQU or SET */
+}
+
+/* set location segment */
+
+PRIVATE void setloc(seg)
+unsigned seg;
+{
+ if (pass != 0 && seg != (lcdata & SEGM))
+ putobj((opcode_pt) (seg | OBJ_SET_SEG));
+ {
+ register struct lc_s *lcp;
+
+ lcp = lcptr;
+ lcp->data = lcdata;
+ lcp->lc = lc;
+ lcptr = lcp = lctab + (unsigned char) seg;
+ lcdata = (lcp->data & ~SEGM) | (unsigned char) seg;
+ binmbuf = lc = lcp->lc;
+ popflags = POPLC;
+ }
+}
diff --git a/as/proto.h b/as/proto.h
new file mode 100644
index 0000000..e348413
--- /dev/null
+++ b/as/proto.h
@@ -0,0 +1,218 @@
+/* extern functions */
+
+#if __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+/* as.c */
+int main P((int argc, char **argv));
+void as_abort P((char *message));
+void finishup P((void));
+void initp1p2 P((void));
+
+/* assemble.c */
+void assemble P((void));
+
+/* error.c */
+char *build_error_message P((error_pt errnum, char *buf));
+
+/* express.c */
+void absexpres P((void));
+void chkabs P((void));
+void nonimpexpres P((void));
+void showrelbad P((void));
+void symabsexpres P((void));
+void symexpres P((void));
+void expres P((void));
+void factor P((void));
+void scompare P((void));
+
+/* genbin.c */
+void binheader P((void));
+void bintrailer P((void));
+void genbin P((void));
+void initbin P((void));
+void putbin P((int ch));
+
+/* genlist.c */
+char *build_2hex_number P((unsigned num, char *where));
+char *build_number P((unsigned num, unsigned width, char *where));
+void error P((error_pt errnum));
+void listline P((void));
+void writec P((int ch));
+void writenl P((void));
+void writeoff P((offset_t offset));
+void writes P((char *s));
+void writesn P((char *s));
+void writew P((unsigned word));
+
+/* genobj.c */
+void accumulate_rmb P((offset_t offset));
+void flushobj P((void));
+void genobj P((void));
+void initobj P((void));
+void objheader P((void));
+void objtrailer P((void));
+void putabs P((opcode_pt ch));
+void putobj P((opcode_pt ch));
+
+/* gensym.c */
+void gensym P((void));
+
+/* macro.c */
+void entermac P((struct sym_s *symptr));
+void pmacro P((void));
+
+/* mops.c */
+#ifdef I80386
+void mbcc P((void));
+void mbswap P((void));
+void mcall P((void));
+void mcalli P((void));
+void mdivmul P((void));
+void menter P((void));
+void mEwGw P((void));
+void mExGx P((void));
+void mf_inher P((void));
+void mf_m P((void));
+void mf_m2 P((void));
+void mf_m2_ax P((void));
+void mf_m2_m4 P((void));
+void mf_m2_m4_m8 P((void));
+void mf_m4_m8_optst P((void));
+void mf_m4_m8_st P((void));
+void mf_m4_m8_stst P((void));
+void mf_m4_m8_m10_st P((void));
+void mf_m10 P((void));
+void mf_optst P((void));
+void mf_st P((void));
+void mf_stst P((void));
+void mf_w_inher P((void));
+void mf_w_m P((void));
+void mf_w_m2 P((void));
+void mf_w_m2_ax P((void));
+void mgroup1 P((void));
+void mgroup2 P((void));
+void mgroup6 P((void));
+void mgroup7 P((void));
+void mgroup8 P((void));
+void mGvEv P((void));
+void mGvMa P((void));
+void mGvMp P((void));
+void mimul P((void));
+void min P((void));
+void mincdec P((void));
+void minher P((void));
+void minher16 P((void));
+void minher32 P((void));
+void minhera P((void));
+void mint P((void));
+void mjcc P((void));
+void mjcxz P((void));
+void mlea P((void));
+void mmov P((void));
+void mmovx P((void));
+void mnegnot P((void));
+void mout P((void));
+void mpushpop P((void));
+void mret P((void));
+void mseg P((void));
+void msetcc P((void));
+void mshdouble P((void));
+void mtest P((void));
+void mxchg P((void));
+#endif /* I80386 */
+
+#ifdef MC6809
+void mall P((void));
+void malter P((void));
+void mimmed P((void));
+void mindex P((void));
+void minher P((void));
+void mlong P((void));
+void msstak P((void));
+void mswap P((void));
+void mustak P((void));
+#endif /* MC6809 */
+
+void getcomma P((void));
+void mshort P((void));
+
+/* pops.c */
+bool_pt checksegrel P((struct sym_s *symptr));
+void checkdatabounds P((void));
+void datatoobig P((void));
+void fatalerror P((error_pt errnum));
+void labelerror P((error_pt errnum));
+void palign P((void));
+void pasciz P((void));
+void pblkw P((void));
+void pblock P((void));
+void pbss P((void));
+void pcomm P((void));
+void pcomm1 P((void));
+void pdata P((void));
+void pelse P((void));
+void pelseif P((void));
+void pelsifc P((void));
+void pendb P((void));
+void pendif P((void));
+void penter P((void));
+void pentry P((void));
+void pequ P((void));
+void peven P((void));
+void pexport P((void));
+void pfail P((void));
+void pfcb P((void));
+void pfcc P((void));
+void pfdb P((void));
+void pfqb P((void));
+void pglobl P((void));
+void pident P((void));
+void pif P((void));
+void pifc P((void));
+void pimport P((void));
+void plcomm P((void));
+void plcomm1 P((void));
+void plist P((void));
+void ploc P((void));
+void pmaclist P((void));
+void pmap P((void));
+void porg P((void));
+void prmb P((void));
+void psect P((void));
+void pset P((void));
+void psetdp P((void));
+void ptext P((void));
+void puse16 P((void));
+void puse32 P((void));
+void pwarn P((void));
+void showlabel P((void));
+
+/* readsrc.c */
+void initsource P((void));
+fd_t open_input P((char *name));
+void pget P((void));
+void pproceof P((void));
+void readline P((void));
+void skipline P((void));
+
+/* scan.c */
+void context_hexconst P((void));
+void getsym P((void));
+void getsym_nolookup P((void));
+void initscan P((void));
+
+/* table.c */
+void inst_keywords P((void));
+struct sym_s *lookup P((void));
+void statistics P((void));
+
+/* type.c */
+void u2c2 P((char *buf, u16_pt offset));
+void u4c4 P((char *buf, u32_T offset));
+void u2cn P((char *buf, u16_pt offset, unsigned count));
+void u4cn P((char *buf, u32_T offset, unsigned count));
+bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian));
diff --git a/as/readsrc.c b/as/readsrc.c
new file mode 100644
index 0000000..f74db84
--- /dev/null
+++ b/as/readsrc.c
@@ -0,0 +1,340 @@
+#define MAXLINE 256 /* when this is made bigger, fix pfcc not
+ * to store the string length in a byte-
+ * sized variable */
+
+/* readsrc.c - read source files for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+#include "macro.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "source.h"
+
+#ifdef POSIX_HEADERS_MISSING
+#define O_RDONLY 0
+typedef long off_t;
+int close P((int fd));
+off_t lseek P((int fd, off_t offset, int whence));
+int open P((const char *path, int oflag, ...));
+int read P((int fd, void *buf, unsigned nbytes));
+#else
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+struct fcbstruct /* file control block structure */
+{
+ fd_t fd; /* file descriptor */
+ char *lineptr; /* current spot in line */
+ char *buf; /* start of buffer (after partial line) */
+ char *first; /* start of partial line before buf */
+ char *limit; /* end of used part of input buffer */
+ int blocksize; /* chars from last read and partial line flag */
+ struct fbufstruct *includer;/* buffer of file which included current one */
+};
+
+struct fbufstruct /* file buffer structure */
+{
+ struct fcbstruct fcb; /* status after opening an include sub-file */
+ char fpartline[MAXLINE + 1];/* buffer for partial line */
+ char fbuf[INBUFSIZE + 1]; /* buffer to read into */
+ char fname[1]; /* file name (variable length), 1 for null */
+};
+
+struct get_s /* to record included files */
+{
+ fd_t fd;
+ unsigned line;
+ off_t position;
+};
+
+PRIVATE char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */
+
+PRIVATE struct get_s hid_getstak[MAXGET]; /* GET stack */
+PRIVATE struct get_s *getstak; /* ptr */
+
+PRIVATE struct fcbstruct input; /* current input file control block */
+ /* input.lineptr is not kept up to date */
+ /* input.fd depends on zero init */
+PRIVATE struct fbufstruct xyz;
+PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */
+ /* its fcb only to date in includes */
+
+PRIVATE char hid_linebuf[LINLEN]; /* line buffer */
+PRIVATE char *maclinebuf;
+PRIVATE char *maclineptr;
+
+FORWARD void clearsource P((void));
+FORWARD void line_too_long P((void));
+
+PRIVATE void clearsource()
+{
+ input.includer = inputbuf;
+ inputbuf = &xyz;
+ input.first = input.limit = input.buf = inputbuf->fbuf;
+ *(lineptr = linebuf = input.first - 1) = EOLCHAR;
+ input.blocksize = 0;
+}
+
+PRIVATE void line_too_long()
+{
+ symname = linebuf + (LINLEN - 1); /* spot for the error */
+ error(LINLONG); /* so error is shown in column LINLEN - 1 */
+}
+
+/* initialise private variables */
+
+PUBLIC void initsource()
+{
+ filnamptr = hid_filnambuf;
+ getstak = hid_getstak + MAXGET;
+ clearsource(); /* sentinel to invoke blank skipping */
+}
+
+PUBLIC fd_t open_input(name)
+char *name;
+{
+ fd_t fd;
+
+ if ((unsigned) (fd = open(name, O_RDONLY)) > 255)
+ as_abort("error opening input file");
+ clearsource();
+ return fd;
+}
+
+/*
+ handle GET pseudo_op
+ stack state of current file, open new file and reset global state vars
+ file must be seekable for the buffer discard/restore method to work
+*/
+
+PUBLIC void pget()
+{
+#if OLD
+ if (infiln >= MAXGET)
+ error(GETOV);
+ else
+ {
+ skipline();
+ listline();
+ if (infiln != 0)
+ {
+ --getstak;
+ getstak->fd = infil;
+ getstak->line = linum;
+ getstak->position = lseek(infil, 0L, 1) - (inbufend - inbufptr);
+ ++infiln;
+ linum = 0;
+ infil = open_input(lineptr - 1);
+ }
+ }
+#else
+ as_abort("get/include pseudo-op not implemented");
+#endif
+}
+
+/* process end of file */
+/* close file, unstack old file if current one is included */
+/* otherwise switch pass 0 to pass 1 or exit on pass 2 */
+/* end of file may be from phyical end of file or an END statement */
+
+PUBLIC void pproceof()
+{
+ if (infiln != 0)
+ close(infil);
+ if (lineptr == linebuf)
+ list.current = FALSE; /* don't list line after last unless error */
+ if (infiln == infil0)
+ /* all conditionals must be closed before end of main file (not GETs) */
+ {
+ if (blocklevel != 0)
+ error(EOFBLOCK);
+ if (iflevel != 0)
+ error(EOFIF);
+ if (lcdata & UNDBIT)
+ error(EOFLC);
+ lcptr->data = lcdata;
+ lcptr->lc = lc;
+ }
+ /* macros must be closed before end of all files */
+ if (macload)
+ error(EOFMAC);
+ listline(); /* last line or line after last if error */
+ if (infiln != infil0)
+ {
+ infil = getstak->fd;
+ linum = getstak->line;
+ if (--infiln != 0)
+ lseek(infil, getstak->position, 0);
+ ++getstak;
+ }
+ else if (!pass)
+ {
+ pass = TRUE;
+ objheader(); /* while pass 1 data all valid */
+ binmbuf = 0; /* reset zero variables */
+ maclevel = iflevel = blocklevel =
+ totwarn = toterr = linum = macnum = 0;
+ initp1p2(); /* reset other varaiables */
+ binaryc = binaryg;
+#ifdef I80386
+ defsize = idefsize;
+#endif
+ list.current = list.global;
+ maclist.current = maclist.global;
+
+ warn.current = TRUE;
+ if (warn.semaphore < 0)
+ warn.current = FALSE;
+ if (infiln != 0)
+ infil = open_input(filnamptr);
+ binheader();
+ }
+ else
+ finishup();
+}
+
+/*
+ read 1 line of source.
+ Source line ends with '\n', line returned is null terminated without '\n'.
+ Control characters other than blank, tab and newline are discarded.
+ Long lines (length > LINLEN) are truncated, and an error is generated.
+ On EOF, calls pproceof(), and gets next line unless loading a macro.
+ This is where macro lines are recursively expanded.
+*/
+
+PUBLIC void readline()
+{
+ listpre = FALSE; /* not listed yet */
+ if (maclevel != 0)
+ {
+ register char *bufptr; /* hold *bufptr in a reg char variable */
+ register char *reglineptr; /* if possible (not done here) */
+ char *oldbufptr;
+ struct schain_s *parameters;
+ char paramnum;
+ unsigned int remaining; /* space remaining in line + 2 */
+ /* value 0 not used except for temp predec */
+ /* value 1 means error already gen */
+ /* values 1 and 2 mean no space */
+
+ for (; maclevel != 0;
+ macpar = macstak->parameters, ++macstak, --maclevel)
+ if (*(bufptr = macstak->text) != ETB)
+ /* nonempty macro, process it and return without continuing the for loop */
+ {
+ if (!macflag)
+ {
+ maclinebuf = linebuf;
+ maclineptr = lineptr;
+ macflag = TRUE;
+ }
+ remaining = LINLEN + 2;
+ lineptr = linebuf = reglineptr = hid_linebuf;
+ while (*bufptr++ != EOLCHAR)
+ {
+ if (bufptr[-1] == MACROCHAR && *bufptr >= '0' && *bufptr <= '9')
+ {
+ parameters = macstak->parameters;
+ for (paramnum = *bufptr++; paramnum-- != '0';)
+ if ((parameters = parameters->next) == NUL_PTR)
+ break;
+ if (parameters != NUL_PTR)
+ {
+ for (oldbufptr = bufptr, bufptr = parameters->string;
+ *bufptr++ != 0;)
+ {
+ if (--remaining <= 1)
+ {
+ if (remaining != 0)
+ line_too_long();
+ remaining = 1;
+ break; /* forget rest, param on 1 line */
+ }
+ *reglineptr++ = bufptr[-1];
+ }
+ bufptr = oldbufptr;
+ }
+ }
+ else
+ {
+ if (--remaining <= 1)
+ {
+ if (remaining != 0)
+ line_too_long();
+ remaining = 1;
+ }
+ else
+ *reglineptr++ = bufptr[-1];
+ }
+ }
+ macstak->text = bufptr;
+ *reglineptr = EOLCHAR;
+ return;
+ }
+ }
+ if (macflag)
+ {
+ linebuf = maclinebuf;
+ lineptr = maclineptr;
+ macflag = FALSE;
+ }
+again:
+ ++linum;
+ ++lineptr; /* if eof, this is input.limit + 1 */
+ if (input.blocksize != 0) /* and this routine just resets eof */
+ {
+ if (lineptr < input.limit) /* move back partial line */
+ {
+ register char *col;
+
+ col = input.buf;
+ while ((*--col = *--input.limit) != EOLCHAR)
+ ;
+ input.first = col + 1;
+ ++input.limit;
+ input.blocksize = 0;
+ }
+ else /* may be non-terminated line, don't stop */
+ lineptr = input.limit;
+ }
+ if (lineptr == input.limit)
+ {
+ lineptr = input.first;
+ input.blocksize = read(infil, input.buf, INBUFSIZE);
+ if (input.blocksize < 0)
+ as_abort("error reading input");
+ if (input.blocksize == 0)
+ {
+ clearsource();
+ pproceof();
+ if (macload)
+ {
+ symname = lineptr;
+ return; /* macro not allowed across eof */
+ }
+ goto again;
+ }
+ input.first = input.buf;
+ *(input.limit = input.buf + input.blocksize) = EOLCHAR;
+ }
+ linebuf = lineptr;
+ if (lineptr >= input.limit)
+ *(lineptr = input.limit = input.buf) = EOLCHAR;
+}
+
+PUBLIC void skipline()
+{
+ register char *reglineptr;
+
+ reglineptr = lineptr - 1;
+ while (*reglineptr != EOLCHAR)
+ ++reglineptr;
+ lineptr = reglineptr;
+}
diff --git a/as/scan.c b/as/scan.c
new file mode 100644
index 0000000..56c6bf3
--- /dev/null
+++ b/as/scan.c
@@ -0,0 +1,247 @@
+/* scan.c - lexical analyser for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#undef EXTERN
+#define EXTERN
+#include "scan.h"
+
+PRIVATE int numbase; /* base for number */
+
+PRIVATE char symofchar[256] = /* table to convert chars to their symbols */
+{
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, EOLSYM, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, EOLSYM, STRINGCONST, IMMEDIATE, /* !"# */
+ HEXCONST, BINCONST, ANDOP, CHARCONST, /* $%&' */
+ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */
+ COMMA, SUBOP, IDENT, SLASH, /* ,-./ */
+
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */
+ INTCONST, INTCONST, COLON, EOLSYM, /* 89:; */
+ LESSTHAN, EQOP, GREATERTHAN, MACROARG, /* <=>? */
+
+ INDIRECT, IDENT, IDENT, IDENT, /* @ABC */
+ IDENT, IDENT, IDENT, IDENT, /* DEFG */
+ IDENT, IDENT, IDENT, IDENT, /* HIJK */
+ IDENT, IDENT, IDENT, IDENT, /* LMNO */
+ IDENT, IDENT, IDENT, IDENT, /* PQRS */
+ IDENT, IDENT, IDENT, IDENT, /* TUVW */
+ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */
+ OTHERSYM, RBRACKET, OTHERSYM, IDENT, /* \]^_ */
+
+ OTHERSYM, IDENT, IDENT, IDENT, /* `abc */
+ IDENT, IDENT, IDENT, IDENT, /* defg */
+ IDENT, IDENT, IDENT, IDENT, /* hijk */
+ IDENT, IDENT, IDENT, IDENT, /* lmno */
+ IDENT, IDENT, IDENT, IDENT, /* pqrs */
+ IDENT, IDENT, IDENT, IDENT, /* tuvw */
+ IDENT, IDENT, IDENT, OTHERSYM, /* xyz{ */
+ OROP, OTHERSYM, NOTOP, OTHERSYM, /* |}~ */
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE,
+ WHITESPACE, WHITESPACE, WHITESPACE, WHITESPACE
+};
+
+FORWARD void intconst P((void));
+
+PUBLIC void context_hexconst()
+{
+ numbase = 16;
+ intconst();
+}
+
+PUBLIC void getsym()
+{
+ register char *reglineptr;
+
+ reglineptr = lineptr;
+advance:
+ symname = reglineptr;
+ switch (sym = symofchar[(unsigned char) *reglineptr++])
+ {
+ case WHITESPACE:
+ goto advance;
+ case ADDOP:
+ if (*reglineptr == '+')
+ {
+ sym = POSTINCOP;
+ ++reglineptr;
+ }
+ break;
+ case BINCONST:
+ numbase = 2;
+ lineptr = reglineptr;
+ intconst();
+ return;
+ case CHARCONST:
+ if ((number = *reglineptr) < ' ')
+ number = ' ';
+ if (*reglineptr != EOL)
+ ++reglineptr;
+ sym = INTCONST;
+ break;
+ case GREATERTHAN: /* context-sensitive */
+ if (*reglineptr == '>')
+ {
+ sym = SROP;
+ ++reglineptr;
+ }
+ break;
+ case HEXCONST:
+ numbase = 16;
+ lineptr = reglineptr;
+ intconst();
+ return;
+ case IDENT:
+ /* walk to end of identifier - magic INTCONST is max of INT, IDENT */
+ while (symofchar[(unsigned char) *reglineptr] <= INTCONST)
+ ++reglineptr;
+ lineptr = reglineptr;
+ gsymptr = lookup();
+ return;
+ case INTCONST:
+ if (*(reglineptr - 1) == '0')
+ {
+ if (*reglineptr != 'x' && *reglineptr != 'X')
+ numbase = 8;
+ else
+ {
+ numbase = 16;
+ ++reglineptr;
+ }
+ }
+ else
+ {
+ --reglineptr;
+ numbase = 10;
+ }
+ lineptr = reglineptr;
+ intconst();
+ return;
+ case LESSTHAN: /* context-sensitive */
+ if (*reglineptr == '<')
+ {
+ sym = SLOP;
+ ++reglineptr;
+ }
+ break;
+ case SUBOP:
+ if (*reglineptr == '-')
+ {
+ sym = PREDECOP;
+ ++reglineptr;
+ }
+ break;
+ }
+ lineptr = reglineptr;
+ return;
+}
+
+PUBLIC void getsym_nolookup()
+{
+ bool_t old_ifflag;
+
+ old_ifflag = ifflag;
+ ifflag = FALSE;
+ getsym();
+ ifflag = old_ifflag;
+}
+
+PRIVATE void intconst()
+{
+ register char *reglineptr;
+
+ number = 0;
+ reglineptr = lineptr;
+ for (; *reglineptr >= '0'; ++reglineptr)
+ {
+ if (*reglineptr > '9')
+ {
+ if (numbase != 16)
+ break;
+ if (*reglineptr >= 'a' && *reglineptr <= 'f')
+ {
+ if (number != 0)
+ number = numbase * number + (*reglineptr - 'a' + 10);
+ else
+ number = *reglineptr - 'a' + 10;
+ }
+ else if (*reglineptr >= 'A' && *reglineptr <= 'F')
+ {
+ if (number != 0)
+ number = numbase * number + (*reglineptr - 'A' + 10);
+ else
+ number = *reglineptr - 'A' + 10;
+ }
+ else
+ break;
+ }
+ else if (number != 0)
+ number = numbase * number + (*reglineptr - '0');
+ else
+ number = *reglineptr - '0';
+ }
+ if (*reglineptr == 'L' || *reglineptr == 'l')
+ ++reglineptr;
+ sym = INTCONST;
+ lineptr = reglineptr;
+}
+
+PUBLIC void initscan()
+{
+ if (asld_compatible)
+ {
+ lindirect = LPAREN;
+ rindexp = RPEXP;
+ rindirect = RPAREN;
+ }
+ else
+ {
+ lindirect = LBRACKET;
+ rindexp = RBEXP;
+ rindirect = RBRACKET;
+ }
+}
diff --git a/as/scan.h b/as/scan.h
new file mode 100644
index 0000000..22def98
--- /dev/null
+++ b/as/scan.h
@@ -0,0 +1,12 @@
+/* scan.h - global variables for scanner for assembler */
+
+#define EOLCHAR '\n'
+
+EXTERN struct sym_s *gsymptr; /* global symbol ptr */
+EXTERN char lindirect; /* left symbol for indirect addressing */
+EXTERN char *lineptr; /* current line position */
+EXTERN offset_t number; /* constant number */
+EXTERN int rindexp; /* error code for missing rindirect */
+EXTERN char rindirect; /* right symbol for indirect addressing */
+EXTERN char sym; /* current symbol */
+EXTERN char *symname; /* current symbol name */
diff --git a/as/source.h b/as/source.h
new file mode 100644
index 0000000..0181e54
--- /dev/null
+++ b/as/source.h
@@ -0,0 +1,4 @@
+/* source.h - global variables for source handlers for assembler */
+
+EXTERN unsigned linum; /* line # */
+EXTERN bool_t listpre; /* flag to show line has already been listed */
diff --git a/as/table.c b/as/table.c
new file mode 100644
index 0000000..528350b
--- /dev/null
+++ b/as/table.c
@@ -0,0 +1,944 @@
+/* table.c - keyword tables and symbol table lookup for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "opcode.h"
+#include "scan.h"
+
+#ifdef STDC_HEADERS_MISSING
+int memcmp P((const void *s1, const void *s2, unsigned n));
+#else
+#include <string.h>
+#endif
+
+#define hconv(ch) ((unsigned char) (ch) - 0x41) /* better form for hashing */
+
+#ifdef DEBUG
+unsigned nhash;
+unsigned nlookup;
+unsigned nsym;
+unsigned nx[30];
+FORWARD void printchain P((void));
+#endif
+
+/* --- start of keywords --- */
+
+/* registers */
+/* the register code (internal to assembler) is given in 1 byte */
+/* the "opcode" field is not used */
+
+PUBLIC char regs[] =
+{
+#ifdef I80386
+ 2, 'B', 'P', BPREG, 0,
+ 2, 'B', 'X', BXREG, 0,
+ 2, 'D', 'I', DIREG, 0,
+ 2, 'S', 'I', SIREG, 0,
+
+ 3, 'E', 'A', 'X', EAXREG, 0,
+ 3, 'E', 'B', 'P', EBPREG, 0,
+ 3, 'E', 'B', 'X', EBXREG, 0,
+ 3, 'E', 'C', 'X', ECXREG, 0,
+ 3, 'E', 'D', 'I', EDIREG, 0,
+ 3, 'E', 'D', 'X', EDXREG, 0,
+ 3, 'E', 'S', 'I', ESIREG, 0,
+ 3, 'E', 'S', 'P', ESPREG, 0,
+
+ 2, 'A', 'X', AXREG, 0,
+ 2, 'C', 'X', CXREG, 0,
+ 2, 'D', 'X', DXREG, 0,
+ 2, 'S', 'P', SPREG, 0,
+
+ 2, 'A', 'H', AHREG, 0,
+ 2, 'A', 'L', ALREG, 0,
+ 2, 'B', 'H', BHREG, 0,
+ 2, 'B', 'L', BLREG, 0,
+ 2, 'C', 'H', CHREG, 0,
+ 2, 'C', 'L', CLREG, 0,
+ 2, 'D', 'H', DHREG, 0,
+ 2, 'D', 'L', DLREG, 0,
+
+ 2, 'C', 'S', CSREG, 0,
+ 2, 'D', 'S', DSREG, 0,
+ 2, 'E', 'S', ESREG, 0,
+ 2, 'F', 'S', FSREG, 0,
+ 2, 'G', 'S', GSREG, 0,
+ 2, 'S', 'S', SSREG, 0,
+
+ 3, 'C', 'R', '0', CR0REG, 0,
+ 3, 'C', 'R', '2', CR2REG, 0,
+ 3, 'C', 'R', '3', CR3REG, 0,
+ 3, 'D', 'R', '0', DR0REG, 0,
+ 3, 'D', 'R', '1', DR1REG, 0,
+ 3, 'D', 'R', '2', DR2REG, 0,
+ 3, 'D', 'R', '3', DR3REG, 0,
+ 3, 'D', 'R', '6', DR6REG, 0,
+ 3, 'D', 'R', '7', DR7REG, 0,
+ 3, 'T', 'R', '3', TR3REG, 0,
+ 3, 'T', 'R', '4', TR4REG, 0,
+ 3, 'T', 'R', '5', TR5REG, 0,
+ 3, 'T', 'R', '6', TR6REG, 0,
+ 3, 'T', 'R', '7', TR7REG, 0,
+
+ 2, 'S', 'T', ST0REG, 0,
+#endif /* I80386 */
+
+#ifdef MC6809
+ 1, 'A', AREG, 0,
+ 1, 'B', BREG, 0,
+ 2, 'C', 'C', CCREG, 0,
+ 1, 'D', DREG, 0,
+ 2, 'D', 'P', DPREG, 0,
+ 2, 'P', 'C', PCREG, 0,
+ 3, 'P', 'C', 'R', PCREG, 0,
+ 1, 'S', SREG, 0,
+ 1, 'U', UREG, 0,
+ 1, 'X', XREG, 0,
+ 1, 'Y', YREG, 0,
+#endif
+ 0 /* end of register list */
+};
+
+#ifdef I80386
+
+/* type sizes */
+/* the "opcode" field gives the type size */
+
+PUBLIC char typesizes[] =
+{
+ 4, 'B', 'Y', 'T', 'E', BYTEOP, 1,
+ 5, 'D', 'W', 'O', 'R', 'D', DWORDOP, 4,
+ 5, 'F', 'W', 'O', 'R', 'D', FWORDOP, 6,
+ 3, 'F', 'A', 'R', FAROP, 0,
+ 3, 'P', 'T', 'R', PTROP, 0,
+ 5, 'P', 'W', 'O', 'R', 'D', PWORDOP, 6,
+ 5, 'Q', 'W', 'O', 'R', 'D', QWORDOP, 8,
+ 5, 'T', 'B', 'Y', 'T', 'E', TBYTEOP, 10,
+ 4, 'W', 'O', 'R', 'D', WORDOP, 2,
+ 0 /* end of typesize list */
+};
+
+#endif
+
+/* ops */
+/* the routine number is given in 1 byte */
+/* the opcode is given in 1 byte (it is not used for pseudo-ops) */
+
+PUBLIC char ops[] =
+{
+ /* pseudo-ops. The "opcode" field is unused and padded with a null byte */
+ /* conditionals - must be first */
+ 4, 'E', 'L', 'S', 'E', ELSEOP, 0,
+ 6, 'E', 'L', 'S', 'E', 'I', 'F', ELSEIFOP, 0,
+ 7, 'E', 'L', 'S', 'E', 'I', 'F', 'C', ELSEIFCOP, 0,
+ 5, 'E', 'N', 'D', 'I', 'F', ENDIFOP, 0,
+ 2, 'I', 'F', IFOP, 0,
+ 3, 'I', 'F', 'C', IFCOP, 0,
+
+ /* unconditionals */
+ 6, '.', 'A', 'L', 'I', 'G', 'N', ALIGNOP, 0,
+ 6, '.', 'A', 'S', 'C', 'I', 'I', FCCOP, 0,
+ 6, '.', 'A', 'S', 'C', 'I', 'Z', ASCIZOP, 0,
+ 5, '.', 'B', 'L', 'K', 'B', RMBOP, 0,
+ 5, '.', 'B', 'L', 'K', 'W', BLKWOP, 0,
+ 5, 'B', 'L', 'O', 'C', 'K', BLOCKOP, 0,
+ 4, '.', 'B', 'S', 'S', BSSOP, 0,
+ 5, '.', 'B', 'Y', 'T', 'E', FCBOP, 0,
+ 4, 'C', 'O', 'M', 'M', COMMOP, 0,
+ 5, '.', 'C', 'O', 'M', 'M', COMMOP1, 0,
+ 5, '.', 'D', 'A', 'T', 'A', DATAOP, 0,
+ 6, '.', 'D', 'A', 'T', 'A', '1', FCBOP, 0,
+ 6, '.', 'D', 'A', 'T', 'A', '2', FDBOP, 0,
+ 6, '.', 'D', 'A', 'T', 'A', '4', FQBOP, 0,
+ 2, 'D', 'B', FCBOP, 0,
+ 2, 'D', 'D', FQBOP, 0,
+ 7, '.', 'D', 'E', 'F', 'I', 'N', 'E', EXPORTOP, 0,
+ 2, 'D', 'W', FDBOP, 0,
+ 3, 'E', 'N', 'D', PROCEOFOP, 0,
+ 4, 'E', 'N', 'D', 'B', ENDBOP, 0,
+ 5, 'E', 'N', 'T', 'E', 'R', ENTEROP, 0,
+ 5, 'E', 'N', 'T', 'R', 'Y', ENTRYOP, 0,
+ 3, 'E', 'Q', 'U', EQUOP, 0,
+ 5, '.', 'E', 'V', 'E', 'N', EVENOP, 0,
+ 6, 'E', 'X', 'P', 'O', 'R', 'T', EXPORTOP, 0,
+ 6, 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0,
+ 7, '.', 'E', 'X', 'T', 'E', 'R', 'N', IMPORTOP, 0,
+ 5, 'E', 'X', 'T', 'R', 'N', IMPORTOP, 0,
+ 4, 'F', 'A', 'I', 'L', FAILOP, 0,
+ 5, '.', 'F', 'A', 'I', 'L', FAILOP, 0,
+ 3, 'F', 'C', 'B', FCBOP, 0,
+ 3, 'F', 'C', 'C', FCCOP, 0,
+ 3, 'F', 'D', 'B', FDBOP, 0,
+ 3, 'G', 'E', 'T', GETOP, 0,
+ 6, '.', 'G', 'L', 'O', 'B', 'L', GLOBLOP, 0,
+ 5, 'I', 'D', 'E', 'N', 'T', IDENTOP, 0,
+ 6, 'I', 'M', 'P', 'O', 'R', 'T', IMPORTOP, 0,
+ 7, 'I', 'N', 'C', 'L', 'U', 'D', 'E', GETOP, 0,
+ 5, 'L', 'C', 'O', 'M', 'M', LCOMMOP, 0,
+ 6, '.', 'L', 'C', 'O', 'M', 'M', LCOMMOP1, 0,
+ 5, '.', 'L', 'I', 'S', 'T', LISTOP, 0,
+ 3, 'L', 'O', 'C', LOCOP, 0,
+ 5, '.', 'L', 'O', 'N', 'G', FQBOP, 0,
+ 8, '.', 'M', 'A', 'C', 'L', 'I', 'S', 'T', MACLISTOP, 0,
+ 5, 'M', 'A', 'C', 'R', 'O', MACROOP, 0,
+ 4, '.', 'M', 'A', 'P', MAPOP, 0,
+ 3, 'O', 'R', 'G', ORGOP, 0,
+ 4, '.', 'O', 'R', 'G', ORGOP, 0,
+ 6, 'P', 'U', 'B', 'L', 'I', 'C', EXPORTOP, 0,
+ 3, 'R', 'M', 'B', RMBOP, 0,
+ 4, '.', 'R', 'O', 'M', DATAOP, 0,
+ 5, '.', 'S', 'E', 'C', 'T', SECTOP, 0,
+ 3, 'S', 'E', 'T', SETOP, 0,
+ 5, 'S', 'E', 'T', 'D', 'P', SETDPOP, 0,
+ 6, '.', 'S', 'H', 'O', 'R', 'T', FDBOP, 0,
+ 6, '.', 'S', 'P', 'A', 'C', 'E', RMBOP, 0,
+ 5, '.', 'T', 'E', 'X', 'T', TEXTOP, 0,
+ 5, 'U', 'S', 'E', '1', '6', USE16OP, 0,
+ 5, 'U', 'S', 'E', '3', '2', USE32OP, 0,
+ 5, '.', 'W', 'A', 'R', 'N', WARNOP, 0,
+ 5, '.', 'W', 'O', 'R', 'D', FDBOP, 0,
+ 6, '.', 'Z', 'E', 'R', 'O', 'W', BLKWOP, 0,
+
+ /* hardware ops. The opcode field is now used */
+#ifdef I80386
+ 3, 'A', 'A', 'A', INHER, 0x37,
+ 3, 'A', 'A', 'D', INHER_A, 0xD5,
+ 3, 'A', 'A', 'M', INHER_A, 0xD4,
+ 3, 'A', 'A', 'S', INHER, 0x3F,
+ 3, 'A', 'D', 'C', GROUP1, 0x10,
+ 3, 'A', 'D', 'D', GROUP1, 0x00,
+ 3, 'A', 'N', 'D', GROUP1, 0x20,
+ 4, 'A', 'R', 'P', 'L', EwGw, 0x63,
+ 3, 'B', 'C', 'C', BCC, 0x73,
+ 3, 'B', 'C', 'S', BCC, 0x72,
+ 3, 'B', 'E', 'Q', BCC, 0x74,
+ 3, 'B', 'G', 'E', BCC, 0x7D,
+ 3, 'B', 'G', 'T', BCC, 0x7F,
+ 3, 'B', 'H', 'I', BCC, 0x77,
+ 4, 'B', 'H', 'I', 'S', BCC, 0x73,
+ 3, 'B', 'L', 'E', BCC, 0x7E,
+ 3, 'B', 'L', 'O', BCC, 0x72,
+ 4, 'B', 'L', 'O', 'S', BCC, 0x76,
+ 3, 'B', 'L', 'T', BCC, 0x7C,
+ 3, 'B', 'M', 'I', BCC, 0x78,
+ 3, 'B', 'N', 'E', BCC, 0x75,
+ 5, 'B', 'O', 'U', 'N', 'D', GvMa, 0x62,
+ 3, 'B', 'P', 'C', BCC, 0x7B,
+ 3, 'B', 'P', 'L', BCC, 0x79,
+ 3, 'B', 'P', 'S', BCC, 0x7A,
+ 2, 'B', 'R', CALL, JMP_OPCODE,
+ 3, 'B', 'V', 'C', BCC, 0x71,
+ 3, 'B', 'V', 'S', BCC, 0x70,
+ 4, 'C', 'A', 'L', 'L', CALL, JSR_OPCODE,
+ 5, 'C', 'A', 'L', 'L', 'F', CALLI, 0x9A,
+ 5, 'C', 'A', 'L', 'L', 'I', CALLI, 0x9A,
+ 3, 'C', 'B', 'W', INHER16, 0x98,
+ 3, 'C', 'L', 'C', INHER, 0xF8,
+ 3, 'C', 'L', 'D', INHER, 0xFC,
+ 3, 'C', 'L', 'I', INHER, 0xFA,
+ 3, 'C', 'M', 'C', INHER, 0xF5,
+ 3, 'C', 'M', 'P', GROUP1, CMP_OPCODE_BASE,
+ 4, 'C', 'M', 'P', 'S', INHER, CMPSW_OPCODE,
+ 5, 'C', 'M', 'P', 'S', 'B', INHER, CMPSB_OPCODE,
+ 5, 'C', 'M', 'P', 'S', 'D', INHER32, CMPSW_OPCODE,
+ 5, 'C', 'M', 'P', 'S', 'W', INHER16, CMPSW_OPCODE,
+ 4, 'C', 'M', 'P', 'W', INHER16, CMPSW_OPCODE,
+ 4, 'C', 'S', 'E', 'G', INHER, 0x2E,
+ 3, 'C', 'W', 'D', INHER16, 0x99,
+ 4, 'C', 'W', 'D', 'E', INHER32, 0x98,
+ 3, 'C', 'D', 'Q', INHER32, 0x99,
+ 3, 'D', 'A', 'A', INHER, 0x27,
+ 3, 'D', 'A', 'S', INHER, 0x2F,
+ 4, 'D', 'S', 'E', 'G', INHER, 0x3E,
+ 3, 'D', 'E', 'C', INCDEC, 0x08,
+ 3, 'D', 'I', 'V', DIVMUL, 0x30,
+ 5, 'E', 'N', 'T', 'E', 'R', ENTER, 0xC8,
+ 4, 'E', 'S', 'E', 'G', INHER, 0x26,
+ 4, 'F', 'S', 'E', 'G', INHER, 0x64,
+ 4, 'G', 'S', 'E', 'G', INHER, 0x65,
+ 3, 'H', 'L', 'T', INHER, 0xF4,
+ 4, 'I', 'D', 'I', 'V', DIVMUL, 0x38,
+ 4, 'I', 'M', 'U', 'L', IMUL, 0x28,
+ 2, 'I', 'N', IN, 0xEC,
+ 3, 'I', 'N', 'C', INCDEC, 0x00,
+ 3, 'I', 'N', 'S', INHER, 0x6D,
+ 4, 'I', 'N', 'S', 'B', INHER, 0x6C,
+ 4, 'I', 'N', 'S', 'D', INHER32, 0x6D,
+ 4, 'I', 'N', 'S', 'W', INHER16, 0x6D,
+ 3, 'I', 'N', 'T', INT, 0xCD,
+ 4, 'I', 'N', 'T', 'O', INHER, 0xCE,
+ 3, 'I', 'N', 'W', IN, 0xED,
+ 4, 'I', 'R', 'E', 'T', INHER16, 0xCF,
+ 5, 'I', 'R', 'E', 'T', 'D', INHER32, 0xCF,
+ 1, 'J', CALL, JMP_SHORT_OPCODE,
+ 2, 'J', 'A', JCC, 0x77,
+ 3, 'J', 'A', 'E', JCC, 0x73,
+ 2, 'J', 'B', JCC, 0x72,
+ 3, 'J', 'B', 'E', JCC, 0x76,
+ 2, 'J', 'C', JCC, 0x72,
+ 4, 'J', 'C', 'X', 'E', JCXZ, 0x2,
+ 4, 'J', 'C', 'X', 'Z', JCXZ, 0x2,
+ 5, 'J', 'E', 'C', 'X', 'E', JCXZ, 0x4,
+ 5, 'J', 'E', 'C', 'X', 'Z', JCXZ, 0x4,
+ 2, 'J', 'E', JCC, 0x74,
+ 2, 'J', 'G', JCC, 0x7F,
+ 3, 'J', 'G', 'E', JCC, 0x7D,
+ 2, 'J', 'L', JCC, 0x7C,
+ 3, 'J', 'L', 'E', JCC, 0x7E,
+ 3, 'J', 'M', 'P', CALL, JMP_SHORT_OPCODE,
+ 4, 'J', 'M', 'P', 'F', CALLI, 0xEA,
+ 4, 'J', 'M', 'P', 'I', CALLI, 0xEA,
+ 3, 'J', 'N', 'A', JCC, 0x76,
+ 4, 'J', 'N', 'A', 'E', JCC, 0x72,
+ 3, 'J', 'N', 'B', JCC, 0x73,
+ 4, 'J', 'N', 'B', 'E', JCC, 0x77,
+ 3, 'J', 'N', 'C', JCC, 0x73,
+ 3, 'J', 'N', 'E', JCC, 0x75,
+ 3, 'J', 'N', 'G', JCC, 0x7E,
+ 4, 'J', 'N', 'G', 'E', JCC, 0x7C,
+ 3, 'J', 'N', 'L', JCC, 0x7D,
+ 4, 'J', 'N', 'L', 'E', JCC, 0x7F,
+ 3, 'J', 'N', 'O', JCC, 0x71,
+ 3, 'J', 'N', 'P', JCC, 0x7B,
+ 3, 'J', 'N', 'S', JCC, 0x79,
+ 3, 'J', 'N', 'Z', JCC, 0x75,
+ 2, 'J', 'O', JCC, 0x70,
+ 2, 'J', 'P', JCC, 0x7A,
+ 3, 'J', 'P', 'E', JCC, 0x7A,
+ 3, 'J', 'P', 'O', JCC, 0x7B,
+ 2, 'J', 'S', JCC, 0x78,
+ 2, 'J', 'Z', JCC, 0x74,
+ 4, 'L', 'A', 'H', 'F', INHER, 0x9F,
+ 3, 'L', 'D', 'S', GvMp, 0xC5,
+ 3, 'L', 'E', 'A', LEA, 0x8D,
+ 5, 'L', 'E', 'A', 'V', 'E', INHER, 0xC9,
+ 3, 'L', 'E', 'S', GvMp, 0xC4,
+ 4, 'L', 'O', 'C', 'K', INHER, 0xF0,
+ 4, 'L', 'O', 'D', 'B', INHER, 0xAC,
+ 4, 'L', 'O', 'D', 'S', INHER, 0xAD,
+ 5, 'L', 'O', 'D', 'S', 'B', INHER, 0xAC,
+ 5, 'L', 'O', 'D', 'S', 'D', INHER32, 0xAD,
+ 5, 'L', 'O', 'D', 'S', 'W', INHER16, 0xAD,
+ 4, 'L', 'O', 'D', 'W', INHER16, 0xAD,
+ 4, 'L', 'O', 'O', 'P', JCC, 0xE2,
+ 5, 'L', 'O', 'O', 'P', 'E', JCC, 0xE1,
+ 6, 'L', 'O', 'O', 'P', 'N', 'E', JCC, 0xE0,
+ 6, 'L', 'O', 'O', 'P', 'N', 'Z', JCC, 0xE0,
+ 5, 'L', 'O', 'O', 'P', 'Z', JCC, 0xE1,
+ 3, 'M', 'O', 'V', MOV, 0x88,
+ 4, 'M', 'O', 'V', 'S', INHER, MOVSW_OPCODE,
+ 5, 'M', 'O', 'V', 'S', 'B', INHER, MOVSB_OPCODE,
+ 5, 'M', 'O', 'V', 'S', 'D', INHER32, MOVSW_OPCODE,
+ 5, 'M', 'O', 'V', 'S', 'W', INHER16, MOVSW_OPCODE,
+ 4, 'M', 'O', 'V', 'W', INHER16, MOVSW_OPCODE,
+ 3, 'M', 'U', 'L', DIVMUL, 0x20,
+ 3, 'N', 'E', 'G', NEGNOT, 0x18,
+ 3, 'N', 'O', 'P', INHER, 0x90,
+ 3, 'N', 'O', 'T', NEGNOT, 0x10,
+ 2, 'O', 'R', GROUP1, 0x08,
+ 3, 'O', 'U', 'T', OUT, 0xEE,
+ 4, 'O', 'U', 'T', 'S', INHER, 0x6F,
+ 5, 'O', 'U', 'T', 'S', 'B', INHER, 0x6E,
+ 5, 'O', 'U', 'T', 'S', 'D', INHER32, 0x6F,
+ 5, 'O', 'U', 'T', 'S', 'W', INHER16, 0x6F,
+ 4, 'O', 'U', 'T', 'W', OUT, 0xEF,
+ 3, 'P', 'O', 'P', PUSHPOP, POP_OPCODE,
+ 4, 'P', 'O', 'P', 'A', INHER16, 0x61,
+ 5, 'P', 'O', 'P', 'A', 'D', INHER32, 0x61,
+ 4, 'P', 'O', 'P', 'F', INHER16, 0x9D,
+ 5, 'P', 'O', 'P', 'F', 'D', INHER32, 0x9D,
+ 4, 'P', 'U', 'S', 'H', PUSHPOP, PUSH_OPCODE,
+ 5, 'P', 'U', 'S', 'H', 'A', INHER16, 0x60,
+ 6, 'P', 'U', 'S', 'H', 'A', 'D', INHER32, 0x60,
+ 5, 'P', 'U', 'S', 'H', 'F', INHER16, 0x9C,
+ 6, 'P', 'U', 'S', 'H', 'F', 'D', INHER32, 0x9C,
+ 3, 'R', 'C', 'L', GROUP2, 0x10,
+ 3, 'R', 'C', 'R', GROUP2, 0x18,
+ 3, 'R', 'O', 'L', GROUP2, 0x00,
+ 3, 'R', 'O', 'R', GROUP2, 0x08,
+ 3, 'R', 'E', 'P', INHER, 0xF3,
+ 4, 'R', 'E', 'P', 'E', INHER, 0xF3,
+ 5, 'R', 'E', 'P', 'N', 'E', INHER, 0xF2,
+ 5, 'R', 'E', 'P', 'N', 'Z', INHER, 0xF2,
+ 4, 'R', 'E', 'P', 'Z', INHER, 0xF3,
+ 3, 'R', 'E', 'T', RET, 0xC3,
+ 4, 'R', 'E', 'T', 'F', RET, 0xCB,
+ 4, 'R', 'E', 'T', 'I', RET, 0xCB,
+ 4, 'S', 'A', 'H', 'F', INHER, 0x9E,
+ 3, 'S', 'A', 'L', GROUP2, 0x20,
+ 3, 'S', 'A', 'R', GROUP2, 0x38,
+ 3, 'S', 'B', 'B', GROUP1, 0x18,
+ 4, 'S', 'C', 'A', 'B', INHER, 0xAE,
+ 4, 'S', 'C', 'A', 'S', INHER, 0xAF,
+ 5, 'S', 'C', 'A', 'S', 'B', INHER, 0xAE,
+ 5, 'S', 'C', 'A', 'S', 'D', INHER32, 0xAF,
+ 5, 'S', 'C', 'A', 'S', 'W', INHER16, 0xAF,
+ 4, 'S', 'C', 'A', 'W', INHER16, 0xAF,
+ 3, 'S', 'E', 'G', SEG, 0x06,
+ 3, 'S', 'H', 'L', GROUP2, 0x20,
+ 3, 'S', 'H', 'R', GROUP2, 0x28,
+ 4, 'S', 'S', 'E', 'G', INHER, 0x36,
+ 3, 'S', 'T', 'C', INHER, 0xF9,
+ 3, 'S', 'T', 'D', INHER, 0xFD,
+ 3, 'S', 'T', 'I', INHER, 0xFB,
+ 4, 'S', 'T', 'O', 'B', INHER, 0xAA,
+ 4, 'S', 'T', 'O', 'S', INHER, 0xAB,
+ 5, 'S', 'T', 'O', 'S', 'B', INHER, 0xAA,
+ 5, 'S', 'T', 'O', 'S', 'D', INHER32, 0xAB,
+ 5, 'S', 'T', 'O', 'S', 'W', INHER16, 0xAB,
+ 4, 'S', 'T', 'O', 'W', INHER16, 0xAB,
+ 3, 'S', 'U', 'B', GROUP1, 0x28,
+ 4, 'T', 'E', 'S', 'T', TEST, 0x84,
+ 4, 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE,
+ 4, 'X', 'C', 'H', 'G', XCHG, 0x86,
+ 4, 'X', 'L', 'A', 'T', INHER, 0xD7,
+ 5, 'X', 'L', 'A', 'T', 'B', INHER, 0xD7,
+ 3, 'X', 'O', 'R', GROUP1, 0x30,
+
+ /* floating point */
+ 5, 'F', '2', 'X', 'M', '1', F_INHER, 0x70,
+ 4, 'F', 'A', 'B', 'S', F_INHER, 0x61,
+ 4, 'F', 'A', 'D', 'D', F_M4_M8_STST, 0x00,
+ 5, 'F', 'A', 'D', 'D', 'P', F_STST, 0x60,
+ 4, 'F', 'B', 'L', 'D', F_M10, 0x74,
+ 5, 'F', 'B', 'S', 'T', 'P', F_M10, 0x76,
+ 4, 'F', 'C', 'H', 'S', F_INHER, 0x60,
+ 5, 'F', 'C', 'L', 'E', 'X', F_W_INHER, 0xE2,
+ 4, 'F', 'C', 'O', 'M', F_M4_M8_OPTST, 0x02,
+ 5, 'F', 'C', 'O', 'M', 'P', F_M4_M8_OPTST, 0x03,
+ 6, 'F', 'C', 'O', 'M', 'P', 'P', F_INHER, 0x19,
+ 4, 'F', 'C', 'O', 'S', F_INHER, 0x7F,
+ 7, 'F', 'D', 'E', 'C', 'S', 'T', 'P', F_INHER, 0x76,
+ 5, 'F', 'D', 'I', 'S', 'I', F_W_INHER, 0xE1,
+ 4, 'F', 'D', 'I', 'V', F_M4_M8_STST, 0x06,
+ 5, 'F', 'D', 'I', 'V', 'P', F_STST, 0x67,
+ 5, 'F', 'D', 'I', 'V', 'R', F_M4_M8_STST, 0x07,
+ 6, 'F', 'D', 'I', 'V', 'R', 'P', F_STST, 0x66,
+ 4, 'F', 'E', 'N', 'I', F_W_INHER, 0xE0,
+ 5, 'F', 'F', 'R', 'E', 'E', F_ST, 0x50,
+ 5, 'F', 'I', 'A', 'D', 'D', F_M2_M4, 0x20,
+ 5, 'F', 'I', 'C', 'O', 'M', F_M2_M4, 0x22,
+ 6, 'F', 'I', 'C', 'O', 'M', 'P', F_M2_M4, 0x23,
+ 5, 'F', 'I', 'D', 'I', 'V', F_M2_M4, 0x26,
+ 6, 'F', 'I', 'D', 'I', 'V', 'R', F_M2_M4, 0x27,
+ 4, 'F', 'I', 'L', 'D', F_M2_M4_M8, 0x30,
+ 5, 'F', 'I', 'M', 'U', 'L', F_M2_M4, 0x21,
+ 7, 'F', 'I', 'N', 'C', 'S', 'T', 'P', F_INHER, 0x77,
+ 5, 'F', 'I', 'N', 'I', 'T', F_W_INHER, 0xE3,
+ 4, 'F', 'I', 'S', 'T', F_M2_M4, 0x32,
+ 5, 'F', 'I', 'S', 'T', 'P', F_M2_M4_M8, 0x33,
+ 5, 'F', 'I', 'S', 'U', 'B', F_M2_M4, 0x24,
+ 6, 'F', 'I', 'S', 'U', 'B', 'R', F_M2_M4, 0x25,
+ 3, 'F', 'L', 'D', F_M4_M8_M10_ST, 0x10,
+ 4, 'F', 'L', 'D', '1', F_INHER, 0x68,
+ 6, 'F', 'L', 'D', 'L', '2', 'E', F_INHER, 0x6A,
+ 6, 'F', 'L', 'D', 'L', '2', 'T', F_INHER, 0x69,
+ 5, 'F', 'L', 'D', 'C', 'W', F_M2, 0x15,
+ 6, 'F', 'L', 'D', 'E', 'N', 'V', F_M, 0x14,
+ 6, 'F', 'L', 'D', 'L', 'G', '2', F_INHER, 0x6C,
+ 6, 'F', 'L', 'D', 'L', 'N', '2', F_INHER, 0x6D,
+ 5, 'F', 'L', 'D', 'P', 'I', F_INHER, 0x6B,
+ 4, 'F', 'L', 'D', 'Z', F_INHER, 0x6E,
+ 4, 'F', 'M', 'U', 'L', F_M4_M8_STST, 0x01,
+ 5, 'F', 'M', 'U', 'L', 'P', F_STST, 0x61,
+ 6, 'F', 'N', 'C', 'L', 'E', 'X', F_INHER, 0xE2,
+ 6, 'F', 'N', 'D', 'I', 'S', 'I', F_INHER, 0xE1,
+ 5, 'F', 'N', 'E', 'N', 'I', F_INHER, 0xE0,
+ 6, 'F', 'N', 'I', 'N', 'I', 'T', F_INHER, 0xE3,
+ 4, 'F', 'N', 'O', 'P', F_INHER, 0x50,
+ 6, 'F', 'N', 'S', 'A', 'V', 'E', F_M, 0x56,
+ 6, 'F', 'N', 'S', 'T', 'C', 'W', F_M2, 0x17,
+ 7, 'F', 'N', 'S', 'T', 'E', 'N', 'V', F_M, 0x16,
+ 6, 'F', 'N', 'S', 'T', 'S', 'W', F_M2_AX, 0x57,
+ 6, 'F', 'P', 'A', 'T', 'A', 'N', F_INHER, 0x73,
+ 5, 'F', 'P', 'R', 'E', 'M', F_INHER, 0x78,
+ 6, 'F', 'P', 'R', 'E', 'M', '1', F_INHER, 0x75,
+ 5, 'F', 'P', 'T', 'A', 'N', F_INHER, 0x72,
+ 7, 'F', 'R', 'N', 'D', 'I', 'N', 'T', F_INHER, 0x7C,
+ 6, 'F', 'R', 'S', 'T', 'O', 'R', F_M, 0x54,
+ 5, 'F', 'S', 'A', 'V', 'E', F_W_M, 0x56,
+ 6, 'F', 'S', 'C', 'A', 'L', 'E', F_INHER, 0x7D,
+ 6, 'F', 'S', 'E', 'T', 'P', 'M', F_INHER, 0xE4,
+ 4, 'F', 'S', 'I', 'N', F_INHER, 0x7E,
+ 7, 'F', 'S', 'I', 'N', 'C', 'O', 'S', F_INHER, 0x7B,
+ 5, 'F', 'S', 'Q', 'R', 'T', F_INHER, 0x7A,
+ 3, 'F', 'S', 'T', F_M4_M8_ST, FST_ENCODED,
+ 5, 'F', 'S', 'T', 'C', 'W', F_W_M2, 0x17,
+ 6, 'F', 'S', 'T', 'E', 'N', 'V', F_W_M, 0x16,
+ 4, 'F', 'S', 'T', 'P', F_M4_M8_M10_ST, FSTP_ENCODED,
+ 5, 'F', 'S', 'T', 'S', 'W', F_W_M2_AX, 0x57,
+ 4, 'F', 'S', 'U', 'B', F_M4_M8_STST, 0x04,
+ 5, 'F', 'S', 'U', 'B', 'P', F_STST, 0x65,
+ 5, 'F', 'S', 'U', 'B', 'R', F_M4_M8_STST, 0x05,
+ 6, 'F', 'S', 'U', 'B', 'R', 'P', F_STST, 0x64,
+ 4, 'F', 'T', 'S', 'T', F_INHER, 0x64,
+ 5, 'F', 'U', 'C', 'O', 'M', F_OPTST, 0x54,
+ 6, 'F', 'U', 'C', 'O', 'M', 'P', F_OPTST, 0x55,
+ 7, 'F', 'U', 'C', 'O', 'M', 'P', 'P', F_INHER, 0xA9,
+ 5, 'F', 'W', 'A', 'I', 'T', INHER, WAIT_OPCODE,
+ 4, 'F', 'X', 'A', 'M', F_INHER, 0x65,
+ 4, 'F', 'X', 'C', 'H', F_OPTST, 0x11,
+ 7, 'F', 'X', 'T', 'R', 'A', 'C', 'T', F_INHER, 0x74,
+ 5, 'F', 'Y', 'L', '2', 'X', F_INHER, 0x71,
+ 7, 'F', 'Y', 'L', '2', 'X', 'P', '1', F_INHER, 0x79,
+#endif /* I80386 */
+
+#ifdef MC6809
+ 3, 'A', 'B', 'X', INHER, 0x3A,
+ 4, 'A', 'D', 'C', 'A', ALL, 0x89,
+ 4, 'A', 'D', 'C', 'B', ALL, 0xC9,
+ 4, 'A', 'D', 'D', 'A', ALL, 0x8B,
+ 4, 'A', 'D', 'D', 'B', ALL, 0xCB,
+ 4, 'A', 'D', 'D', 'D', ALL, 0xC3,
+ 4, 'A', 'N', 'D', 'A', ALL, 0x84,
+ 4, 'A', 'N', 'D', 'B', ALL, 0xC4,
+ 5, 'A', 'N', 'D', 'C', 'C', IMMED, 0x1C,
+ 3, 'A', 'S', 'L', ALTER, 0x08,
+ 4, 'A', 'S', 'L', 'A', INHER, 0x48,
+ 4, 'A', 'S', 'L', 'B', INHER, 0x58,
+ 3, 'A', 'S', 'R', ALTER, 0x07,
+ 4, 'A', 'S', 'R', 'A', INHER, 0x47,
+ 4, 'A', 'S', 'R', 'B', INHER, 0x57,
+ 3, 'B', 'C', 'C', SHORT, 0x24,
+ 3, 'B', 'C', 'S', SHORT, 0x25,
+ 3, 'B', 'E', 'Q', SHORT, 0x27,
+ 3, 'B', 'G', 'E', SHORT, 0x2C,
+ 3, 'B', 'G', 'T', SHORT, 0x2E,
+ 3, 'B', 'H', 'I', SHORT, 0x22,
+ 3, 'B', 'H', 'S', SHORT, 0x24,
+ 4, 'B', 'I', 'T', 'A', ALL, 0X85,
+ 4, 'B', 'I', 'T', 'B', ALL, 0XC5,
+ 3, 'B', 'L', 'E', SHORT, 0x2F,
+ 3, 'B', 'L', 'O', SHORT, 0x25,
+ 3, 'B', 'L', 'S', SHORT, 0x23,
+ 3, 'B', 'L', 'T', SHORT, 0x2D,
+ 3, 'B', 'M', 'I', SHORT, 0x2B,
+ 3, 'B', 'N', 'E', SHORT, 0x26,
+ 3, 'B', 'P', 'L', SHORT, 0x2A,
+ 3, 'B', 'R', 'A', SHORT, 0x20,
+ 4, 'L', 'B', 'R', 'A', LONG, 0x16,
+ 3, 'B', 'R', 'N', SHORT, 0x21,
+ 3, 'B', 'S', 'R', SHORT, 0x8D,
+ 4, 'L', 'B', 'S', 'R', LONG, 0x17,
+ 3, 'B', 'V', 'C', SHORT, 0x28,
+ 3, 'B', 'V', 'S', SHORT, 0x29,
+ 3, 'C', 'L', 'R', ALTER, 0x0F,
+ 4, 'C', 'L', 'R', 'A', INHER, 0x4F,
+ 4, 'C', 'L', 'R', 'B', INHER, 0x5F,
+ 4, 'C', 'M', 'P', 'A', ALL, 0x81,
+ 4, 'C', 'M', 'P', 'B', ALL, 0xC1,
+ 4, 'C', 'M', 'P', 'X', ALL, 0x8C,
+ 3, 'C', 'O', 'M', ALTER, 0x03,
+ 4, 'C', 'O', 'M', 'A', INHER, 0x43,
+ 4, 'C', 'O', 'M', 'B', INHER, 0x53,
+ 4, 'C', 'W', 'A', 'I', IMMED, 0x3C,
+ 3, 'D', 'A', 'A', INHER, 0x19,
+ 3, 'D', 'E', 'C', ALTER, 0x0A,
+ 4, 'D', 'E', 'C', 'A', INHER, 0x4A,
+ 4, 'D', 'E', 'C', 'B', INHER, 0x5A,
+ 4, 'E', 'O', 'R', 'A', ALL, 0x88,
+ 4, 'E', 'O', 'R', 'B', ALL, 0xC8,
+ 3, 'E', 'X', 'G', SWAP, 0x1E,
+ 3, 'I', 'N', 'C', ALTER, 0x0C,
+ 4, 'I', 'N', 'C', 'A', INHER, 0x4C,
+ 4, 'I', 'N', 'C', 'B', INHER, 0x5C,
+ 3, 'J', 'M', 'P', ALTER, 0x0E,
+ 3, 'J', 'S', 'R', ALTER, 0x8D,
+ 3, 'L', 'D', 'A', ALL, 0x86,
+ 3, 'L', 'D', 'B', ALL, 0xC6,
+ 3, 'L', 'D', 'D', ALL, 0xCC,
+ 3, 'L', 'D', 'U', ALL, 0xCE,
+ 3, 'L', 'D', 'X', ALL, 0x8E,
+ 4, 'L', 'E', 'A', 'S', INDEXD, 0x32,
+ 4, 'L', 'E', 'A', 'U', INDEXD, 0x33,
+ 4, 'L', 'E', 'A', 'X', INDEXD, 0x30,
+ 4, 'L', 'E', 'A', 'Y', INDEXD, 0x31,
+ 3, 'L', 'S', 'L', ALTER, 0x08,
+ 4, 'L', 'S', 'L', 'A', INHER, 0x48,
+ 4, 'L', 'S', 'L', 'B', INHER, 0x58,
+ 3, 'L', 'S', 'R', ALTER, 0x04,
+ 4, 'L', 'S', 'R', 'A', INHER, 0x44,
+ 4, 'L', 'S', 'R', 'B', INHER, 0x54,
+ 3, 'M', 'U', 'L', INHER, 0x3D,
+ 3, 'N', 'E', 'G', ALTER, 0x00,
+ 4, 'N', 'E', 'G', 'A', INHER, 0x40,
+ 4, 'N', 'E', 'G', 'B', INHER, 0x50,
+ 3, 'N', 'O', 'P', INHER, 0x12,
+ 3, 'O', 'R', 'A', ALL, 0x8A,
+ 3, 'O', 'R', 'B', ALL, 0xCA,
+ 4, 'O', 'R', 'C', 'C', IMMED, 0x1A,
+ 4, 'P', 'S', 'H', 'S', SSTAK, 0x34,
+ 4, 'P', 'S', 'H', 'U', USTAK, 0x36,
+ 4, 'P', 'U', 'L', 'S', SSTAK, 0x35,
+ 4, 'P', 'U', 'L', 'U', USTAK, 0x37,
+ 3, 'R', 'O', 'L', ALTER, 0x09,
+ 4, 'R', 'O', 'L', 'A', INHER, 0x49,
+ 4, 'R', 'O', 'L', 'B', INHER, 0x59,
+ 3, 'R', 'O', 'R', ALTER, 0x06,
+ 4, 'R', 'O', 'R', 'A', INHER, 0x46,
+ 4, 'R', 'O', 'R', 'B', INHER, 0x56,
+ 3, 'R', 'T', 'I', INHER, 0x3B,
+ 3, 'R', 'T', 'S', INHER, 0x39,
+ 4, 'S', 'B', 'C', 'A', ALL, 0x82,
+ 4, 'S', 'B', 'C', 'B', ALL, 0xC2,
+ 3, 'S', 'E', 'X', INHER, 0x1D,
+ 3, 'S', 'T', 'A', ALTER, 0x87,
+ 3, 'S', 'T', 'B', ALTER, 0xC7,
+ 3, 'S', 'T', 'D', ALTER, 0xCD,
+ 3, 'S', 'T', 'U', ALTER, 0xCF,
+ 3, 'S', 'T', 'X', ALTER, 0x8F,
+ 4, 'S', 'U', 'B', 'A', ALL, 0x80,
+ 4, 'S', 'U', 'B', 'B', ALL, 0xC0,
+ 4, 'S', 'U', 'B', 'D', ALL, 0x83,
+ 3, 'S', 'W', 'I', INHER, 0x3F,
+ 4, 'S', 'Y', 'N', 'C', INHER, 0x13,
+ 3, 'T', 'F', 'R', SWAP, 0x1F,
+ 3, 'T', 'S', 'T', ALTER, 0x0D,
+ 4, 'T', 'S', 'T', 'A', INHER, 0x4D,
+ 4, 'T', 'S', 'T', 'B', INHER, 0x5D,
+#endif /* MC6809 */
+ 0 /* end of ops */
+};
+
+PUBLIC char page1ops[] =
+{
+#ifdef I80386
+ 3, 'B', 'S', 'F', GvEv, 0xBC,
+ 3, 'B', 'S', 'R', GvEv, 0xBD,
+ 5, 'B', 'S', 'W', 'A', 'P', BSWAP, 0xC8,
+ 2, 'B', 'T', GROUP8, 0x20,
+ 3, 'B', 'T', 'C', GROUP8, 0x38,
+ 3, 'B', 'T', 'R', GROUP8, 0x30,
+ 3, 'B', 'T', 'S', GROUP8, 0x28,
+ 4, 'C', 'L', 'T', 'S', INHER, 0x06,
+ 7, 'C', 'M', 'P', 'X', 'C', 'H', 'G', ExGx, 0xA6,
+ 4, 'I', 'N', 'V', 'D', INHER, 0x08,
+ 6, 'I', 'N', 'V', 'L', 'P', 'G', GROUP7, 0x38,
+ 3, 'L', 'A', 'R', GvEv, 0x02,
+ 3, 'L', 'F', 'S', GvMp, 0xB4,
+ 4, 'L', 'G', 'D', 'T', GROUP7, 0x10,
+ 3, 'L', 'G', 'S', GvMp, 0xB5,
+ 4, 'L', 'I', 'D', 'T', GROUP7, 0x18,
+ 4, 'L', 'L', 'D', 'T', GROUP6, 0x10,
+ 4, 'L', 'M', 'S', 'W', GROUP7, 0x30,
+ 3, 'L', 'S', 'L', GvEv, 0x03,
+ 3, 'L', 'S', 'S', GvMp, 0xB2,
+ 3, 'L', 'T', 'R', GROUP6, 0x18,
+ 5, 'M', 'O', 'V', 'S', 'X', MOVX, 0xBE,
+ 5, 'M', 'O', 'V', 'Z', 'X', MOVX, 0xB6,
+ 4, 'S', 'E', 'T', 'A', SETCC, 0x97,
+ 5, 'S', 'E', 'T', 'A', 'E', SETCC, 0x93,
+ 4, 'S', 'E', 'T', 'B', SETCC, 0x92,
+ 5, 'S', 'E', 'T', 'B', 'E', SETCC, 0x96,
+ 4, 'S', 'E', 'T', 'C', SETCC, 0x92,
+ 4, 'S', 'E', 'T', 'E', SETCC, 0x94,
+ 4, 'S', 'E', 'T', 'G', SETCC, 0x9F,
+ 5, 'S', 'E', 'T', 'G', 'E', SETCC, 0x9D,
+ 4, 'S', 'E', 'T', 'L', SETCC, 0x9C,
+ 5, 'S', 'E', 'T', 'L', 'E', SETCC, 0x9E,
+ 5, 'S', 'E', 'T', 'N', 'A', SETCC, 0x96,
+ 6, 'S', 'E', 'T', 'N', 'A', 'E', SETCC, 0x92,
+ 5, 'S', 'E', 'T', 'N', 'B', SETCC, 0x93,
+ 6, 'S', 'E', 'T', 'N', 'B', 'E', SETCC, 0x97,
+ 5, 'S', 'E', 'T', 'N', 'C', SETCC, 0x93,
+ 5, 'S', 'E', 'T', 'N', 'E', SETCC, 0x95,
+ 5, 'S', 'E', 'T', 'N', 'G', SETCC, 0x9E,
+ 6, 'S', 'E', 'T', 'N', 'G', 'E', SETCC, 0x9C,
+ 5, 'S', 'E', 'T', 'N', 'L', SETCC, 0x9D,
+ 6, 'S', 'E', 'T', 'N', 'L', 'E', SETCC, 0x9F,
+ 5, 'S', 'E', 'T', 'N', 'O', SETCC, 0x91,
+ 5, 'S', 'E', 'T', 'N', 'P', SETCC, 0x9B,
+ 5, 'S', 'E', 'T', 'N', 'S', SETCC, 0x99,
+ 5, 'S', 'E', 'T', 'N', 'Z', SETCC, 0x95,
+ 4, 'S', 'E', 'T', 'O', SETCC, 0x90,
+ 4, 'S', 'E', 'T', 'P', SETCC, 0x9A,
+ 5, 'S', 'E', 'T', 'P', 'E', SETCC, 0x9A,
+ 5, 'S', 'E', 'T', 'P', 'O', SETCC, 0x9B,
+ 4, 'S', 'E', 'T', 'S', SETCC, 0x98,
+ 4, 'S', 'E', 'T', 'Z', SETCC, 0x94,
+ 4, 'S', 'G', 'D', 'T', GROUP7, 0x00,
+ 4, 'S', 'I', 'D', 'T', GROUP7, 0x08,
+ 4, 'S', 'H', 'L', 'D', SH_DOUBLE, 0xA4,
+ 4, 'S', 'H', 'R', 'D', SH_DOUBLE, 0xAC,
+ 4, 'S', 'L', 'D', 'T', GROUP6, 0x00,
+ 4, 'S', 'M', 'S', 'W', GROUP7, 0x20,
+ 3, 'S', 'T', 'R', GROUP6, 0x08,
+ 4, 'V', 'E', 'R', 'R', GROUP6, 0x20,
+ 4, 'V', 'E', 'R', 'W', GROUP6, 0x28,
+ 6, 'W', 'B', 'I', 'N', 'V', 'D', INHER, 0x09,
+ 4, 'X', 'A', 'D', 'D', ExGx, 0xC0,
+#endif /* I80386 */
+
+#ifdef MC6809
+ 4, 'L', 'B', 'C', 'C', LONG, 0x24,
+ 4, 'L', 'B', 'C', 'S', LONG, 0x25,
+ 4, 'L', 'B', 'E', 'Q', LONG, 0x27,
+ 4, 'L', 'B', 'G', 'E', LONG, 0x2C,
+ 4, 'L', 'B', 'G', 'T', LONG, 0x2E,
+ 4, 'L', 'B', 'H', 'I', LONG, 0x22,
+ 4, 'L', 'B', 'H', 'S', LONG, 0x24,
+ 4, 'L', 'B', 'L', 'E', LONG, 0x2F,
+ 4, 'L', 'B', 'L', 'O', LONG, 0x25,
+ 4, 'L', 'B', 'L', 'S', LONG, 0x23,
+ 4, 'L', 'B', 'L', 'T', LONG, 0x2D,
+ 4, 'L', 'B', 'M', 'I', LONG, 0x2B,
+ 4, 'L', 'B', 'N', 'E', LONG, 0x26,
+ 4, 'L', 'B', 'P', 'L', LONG, 0x2A,
+ 4, 'L', 'B', 'R', 'N', LONG, 0x21,
+ 4, 'L', 'B', 'V', 'C', LONG, 0x28,
+ 4, 'L', 'B', 'V', 'S', LONG, 0x29,
+ 4, 'C', 'M', 'P', 'D', ALL, 0x83,
+ 4, 'C', 'M', 'P', 'Y', ALL, 0x8C,
+ 3, 'L', 'D', 'S', ALL, 0xCE,
+ 3, 'L', 'D', 'Y', ALL, 0x8E,
+ 3, 'S', 'T', 'S', ALTER, 0xCF,
+ 3, 'S', 'T', 'Y', ALTER, 0x8F,
+ 4, 'S', 'W', 'I', '2', INHER, 0x3F,
+#endif /* MC6809 */
+ 0 /* end of page 1 ops */
+};
+
+PUBLIC char page2ops[] =
+{
+#ifdef MC6809
+ 4, 'C', 'M', 'P', 'S', ALL, 0x8C,
+ 4, 'C', 'M', 'P', 'U', ALL, 0x83,
+ 4, 'S', 'W', 'I', '3', INHER, 0x3F,
+#endif
+ 0 /* end of page 2 ops */
+};
+
+#ifdef I80386
+# ifdef MNSIZE
+PUBLIC char bytesizeops[] =
+{
+ 4, 'A', 'D', 'C', 'B', GROUP1, 0x10,
+ 4, 'A', 'D', 'D', 'B', GROUP1, 0x00,
+ 4, 'A', 'N', 'D', 'B', GROUP1, 0x20,
+ 4, 'C', 'M', 'P', 'B', GROUP1, CMP_OPCODE_BASE,
+ 4, 'D', 'E', 'C', 'b', INCDEC, 0x08,
+ 4, 'D', 'I', 'V', 'B', DIVMUL, 0x30,
+ 5, 'I', 'D', 'I', 'V', 'B', DIVMUL, 0x38,
+ 5, 'I', 'M', 'U', 'L', 'B', IMUL, 0x28,
+ 3, 'I', 'N', 'B', IN, 0xEC,
+ 4, 'I', 'N', 'C', 'B', INCDEC, 0x00,
+ 4, 'M', 'O', 'V', 'B', MOV, 0x88,
+ 4, 'M', 'U', 'L', 'B', DIVMUL, 0x20,
+ 4, 'N', 'E', 'G', 'B', NEGNOT, 0x18,
+ 4, 'N', 'O', 'T', 'B', NEGNOT, 0x10,
+ 3, 'O', 'R', 'B', GROUP1, 0x08,
+ 4, 'O', 'U', 'T', 'B', OUT, 0xEE,
+ 4, 'R', 'C', 'L', 'B', GROUP2, 0x10,
+ 4, 'R', 'C', 'R', 'B', GROUP2, 0x18,
+ 4, 'R', 'O', 'L', 'B', GROUP2, 0x00,
+ 4, 'R', 'O', 'R', 'B', GROUP2, 0x08,
+ 4, 'S', 'A', 'L', 'B', GROUP2, 0x20,
+ 4, 'S', 'A', 'R', 'B', GROUP2, 0x38,
+ 4, 'S', 'H', 'L', 'B', GROUP2, 0x20,
+ 4, 'S', 'H', 'R', 'B', GROUP2, 0x28,
+ 4, 'S', 'B', 'B', 'B', GROUP1, 0x18,
+ 4, 'S', 'U', 'B', 'B', GROUP1, 0x28,
+ 5, 'T', 'E', 'S', 'T', 'B', TEST, 0x84,
+ 5, 'X', 'C', 'H', 'G', 'B', XCHG, 0x86,
+ 4, 'X', 'O', 'R', 'B', GROUP1, 0x30,
+ 0 /* end of byte size ops */
+};
+# endif /* MNSIZE */
+#endif /* I80386 */
+
+/* --- end of keywords --- */
+
+FORWARD void install P((register char *keyptr, int data));
+
+PUBLIC void inst_keywords()
+{
+ install(regs, REGBIT);
+#ifdef I80386
+ install(typesizes, SIZEBIT);
+#endif
+ install(ops, 0);
+ install(page1ops, PAGE1);
+ install(page2ops, PAGE2);
+#ifdef I80386
+# ifdef MNSIZE
+ install(bytesizeops, PAGE1 | PAGE2);
+# endif
+#endif
+}
+
+PRIVATE void install(keyptr, data)
+register char *keyptr;
+unsigned char data;
+{
+ char lowcasebuf[20];
+ unsigned namelength;
+ char *nameptr;
+ char *namend;
+ register struct sym_s *symptr;
+
+ while (*keyptr != 0)
+ {
+ namelength = *keyptr++;
+ lineptr = (symname = keyptr) + namelength;
+ for (nameptr = lowcasebuf, namend = lowcasebuf + namelength;
+ nameptr < namend;)
+ {
+ if (*keyptr < 'A' || *keyptr > 'Z')
+ *nameptr++ = *keyptr++;
+ else
+ *nameptr++ = *keyptr++ + ('a' - 'A');
+ }
+ symptr = lookup();
+ symptr->type = MNREGBIT;
+ symptr->data = data;
+ symptr->value_reg_or_op.op.routine = *keyptr;
+ symptr->value_reg_or_op.op.opcode = keyptr[1];
+ lineptr = (symname = lowcasebuf) + namelength;
+ symptr = lookup();
+ symptr->type = MNREGBIT;
+ symptr->data = data;
+ symptr->value_reg_or_op.op.routine = *keyptr;
+ symptr->value_reg_or_op.op.opcode = keyptr[1];
+ keyptr += 2;
+ }
+}
+
+/* Lookup() searches symbol table for the string from symname to lineptr - 1.
+ * If string is not found and ifflag is TRUE, string is added to table, with
+ * type = 0
+ * data = inidata (RELBIT | UNDBIT, possibly with IMPBIT | SEGM)
+ * Returns pointer to symbol entry (NUL_PTR if not found and not installed)
+ * unless symbol table overflows, when routine aborts.
+ */
+
+PUBLIC struct sym_s *lookup()
+{
+ struct sym_s **hashptr;
+ register char *nameptr;
+ register struct sym_s *symptr;
+ register unsigned hashval;
+ register unsigned length;
+#ifdef DEBUG
+ int tries;
+
+ ++nlookup;
+ tries = 0;
+#endif
+
+ /* Hash function is a weighted xor of 1 to 4 chars in the string.
+ * This works seems to work better than looking at all the chars.
+ * It is important that the function be fast.
+ * The string comparision function should also be fast and it helps
+ * if it is optimized for mostly identical comparisions.
+ * The multiplication by MULTIPLIER should compile as a shift.
+ */
+
+#define MULTIPLIER (SPTSIZ / (1 << USEFUL_BITS_IN_ASCII))
+#define USEFUL_BITS_IN_ASCII 6
+
+ nameptr = lineptr;
+ length = nameptr - symname;
+ if (length <= 3)
+ {
+ if (length <= 2)
+ hashval = hconv(nameptr[-1]) * MULTIPLIER;
+ else
+ hashval = hconv(nameptr[-2]) * MULTIPLIER,
+ hashval ^= hconv(nameptr[-1]);
+ }
+ else
+ hashval = hconv(nameptr[-(length / 2)]) * MULTIPLIER,
+ hashval ^= hconv(nameptr[-2]) << 2,
+ hashval ^= hconv(nameptr[-1]);
+ nameptr = symname;
+ if ((symptr = *(hashptr = spt +
+ (hashval ^ (hconv(nameptr[0]) << 1)) % SPTSIZ))
+ != NUL_PTR)
+ {
+ do
+ {
+#ifdef DEBUG
+ if (tries != 0)
+ --nx[tries];
+ ++tries;
+ if (tries < sizeof nx / sizeof nx[0])
+ ++nx[tries];
+ if (tries >= 5)
+ printchain(hashptr - spt)
+#endif
+ if ((unsigned char) length != symptr->length)
+ continue;
+ if (memcmp(symptr->name, nameptr, length) == 0)
+ return symptr;
+ }
+ while ((symptr = symptr->next) != NUL_PTR);
+
+ /* Calculate last non-NUL_PTR hash ptr.
+ * This is faster than keeping hashptr up to date in previous loop
+ * since most lookups are successful and hash ptr is not needed.
+ */
+ do
+ {
+ symptr = *hashptr;
+ hashptr = &symptr->next;
+ }
+ while (symptr->next != NUL_PTR);
+ }
+ if (!ifflag)
+ return NUL_PTR;
+ align(heapptr);
+ if (heapptr >= heapend)
+ fatalerror(SYMOV);
+#ifdef DEBUG
+ ++nsym;
+ if (hashptr >= spt && hashptr < spt + SPTSIZ)
+ ++nhash;
+#endif
+ *hashptr = symptr = (struct sym_s *) heapptr;
+ symptr->type = 0;
+ symptr->data = inidata;
+ symptr->length = length;
+ symptr->value_reg_or_op.value = (unsigned) (symptr->next = NUL_PTR);
+ heapptr = symptr->name;
+ do
+ *heapptr++ = *nameptr++;
+ while (--length != 0);
+ *heapptr++ = 0;
+ return symptr;
+}
+
+#ifdef DEBUG
+
+static void printchain(hashval)
+unsigned hashval;
+{
+ register struct sym_s *symptr;
+
+ printf("%04x ", hashval);
+ for (symptr = spt[hashval]; symptr != NUL_PTR; symptr = symptr->next)
+ printf("%s ", symptr->name);
+ printf("\n");
+}
+
+#endif
+
+PUBLIC void statistics()
+{
+#ifdef DEBUG
+ int i;
+ int weight;
+
+ for (i = 0; i < SPTSIZ; ++i)
+ printchain(i);
+ printf("nhash = %d, nsym = %d, nlookup = %d nx =\n", nhash, nsym, nlookup);
+ weight = 0;
+ for (i = 0; i < 30; ++i)
+ {
+ printf("%5d", nx[i]);
+ weight += nx[i] * i;
+ }
+ printf("\n");
+ printf("weight = %d%d\n", w;
+#endif
+}
diff --git a/as/todo b/as/todo
new file mode 100644
index 0000000..e85cb6c
--- /dev/null
+++ b/as/todo
@@ -0,0 +1,14 @@
+Check why `chk' fails.
+
+Update 6809/const.h.
+
+Produce bsd symbol tables.
+
+Accept gas format.
+
+Decide how to choose between 8-bit and 32-bit branches. 16-bit branches in
+32-bit mode are unusable because top 16 bits of PC are messed up.
+
+Limit insns to specified processor (warn for 386 insns on 8086).
+
+Buffer for printing of listing.
diff --git a/as/type.h b/as/type.h
new file mode 100644
index 0000000..85e5240
--- /dev/null
+++ b/as/type.h
@@ -0,0 +1,167 @@
+/* type.h - types for assembler */
+
+/* redefine foo_t's because their use has become non-portable */
+
+#define bool_t bool_T
+#define count_t count_T
+#define fd_t fd_T
+#define indcount_t indcount_T
+#define offset_t offset_T
+#define opcode_t opcode_T
+#define opsize_t opsize_T
+#define scale_t scale_T
+#define sem_t sem_T
+#define smallcount_t smallcount_T
+#define soffset_t soffset_T
+
+typedef unsigned char bool_t;
+typedef int bool_pt;
+typedef unsigned count_t;
+typedef int error_pt;
+typedef int fd_t;
+typedef unsigned char indcount_t;
+#ifdef I80386
+typedef unsigned long offset_t;
+typedef long soffset_t;
+# define SIZEOF_OFFSET_T 4 /* non-portable */
+#endif
+#ifdef MC6809
+typedef unsigned offset_t;
+typedef int soffset_t;
+# define SIZEOF_OFFSET_T 2 /* but sizeof (offset_t) often breaks cpp */
+#endif
+typedef int opcode_pt;
+typedef unsigned char opcode_t;
+typedef int opsize_pt;
+typedef unsigned char opsize_t;
+typedef unsigned reg_pt;
+typedef unsigned char scale_t;
+typedef unsigned char smallcount_t;
+typedef /* signed */ char sem_t;
+typedef unsigned u16_pt;
+typedef unsigned short u16_T;
+typedef unsigned long u32_T;
+
+/* symbol table entry */
+
+struct sym_s
+{
+ struct sym_s *next; /* next symbol in hash chain (NUL_PTR if none) */
+ /* zero offset because it is accessed most */
+ unsigned char type;
+ unsigned char data; /* flags valid for expressions as well as syms*/
+ union
+ {
+ offset_t value; /* value, if sym is a label */
+ unsigned char reg; /* register code, if sym is a register */
+ struct
+ {
+ unsigned char routine; /* routine number */
+ opcode_t opcode; /* opcode, if sym is a hardware op */
+ }
+ op; /* if sym is pseudo-op or hardware op */
+ }
+ value_reg_or_op;
+ unsigned char length; /* length of symbol string */
+ char name[1]; /* string of variable length */
+};
+
+/* address */
+
+struct address_s
+{
+ offset_t offset;
+ unsigned char data;
+ struct sym_s *sym;
+};
+
+#ifdef I80386
+
+/* effective address */
+
+struct ea_s
+{
+ indcount_t indcount;
+ opsize_t size;
+ reg_pt base;
+ reg_pt index;
+ scale_t scale;
+ struct address_s displ;
+};
+
+#endif
+
+/* flags */
+
+struct flags_s
+{
+ bool_t global;
+ bool_t current;
+ int semaphore;
+};
+
+/* location counter */
+
+struct lc_s
+{
+ unsigned char data;
+ offset_t lc;
+};
+
+/* string chain */
+
+struct schain_s
+{
+ struct schain_s *next;
+ char string[2]; /* variable length */
+};
+
+/* block stack */
+
+struct block_s
+{
+ unsigned char data;
+ unsigned char dp;
+ offset_t lc;
+};
+
+/* if stack */
+
+struct if_s
+{
+ bool_t ifflag;
+ bool_t elseflag;
+};
+
+/* macro stack */
+
+struct macro_s
+{
+ char *text;
+ struct schain_s *parameters;
+};
+
+/* symbol listing format */
+
+struct sym_listing_s
+{
+ char name[SYMLIS_NAMELEN];
+ char zname[2];
+ char segm[1];
+ char pad1[1];
+ char value[4];
+ char pad2[1];
+ char ar[1];
+ char pad3[1];
+ char cein[1];
+ char pad4[1];
+ char nullterm;
+};
+
+#if __STDC__
+typedef void (*pfv)(void);
+#else
+typedef void (*pfv)();
+#endif
+
+#include "proto.h"
diff --git a/bcc/6809/const.h b/bcc/6809/const.h
new file mode 100644
index 0000000..559680c
--- /dev/null
+++ b/bcc/6809/const.h
@@ -0,0 +1,52 @@
+/* const.h - constants for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* switches for code generation */
+
+#define DEBUG /* generate compiler-debugging code */
+/*#define I8088*/ /* target processor is Intel 8088 thru 80386 */
+#define MC6809 /* target processor is Motorola 6809 */
+#define SELFTYPECHECK /* check calculated type = runtime type */
+
+#ifdef I8088
+# define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */
+# define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */
+# define HOLDSTRINGS /* hold strings for dumping at end
+ * since assembler has only 1 data seg */
+#endif
+
+#ifdef MC6809
+# define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */
+# define OP1 /* logical operators only use 1 byte */
+# define POSINDEPENDENT /* position indep code can (also) be gen */
+#endif
+
+/* switches for source and target operating system dependencies */
+
+/*#define SOS_EDOS*/ /* source O/S is EDOS */
+/*#define SOS_MSDOS*/ /* source O/S is MSDOS */
+#define TOS_EDOS /* target O/S is EDOS */
+
+/* switches for source machine dependencies */
+
+#ifndef SOS_EDOS
+# define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */
+#endif
+
+#ifndef SOS_MSDOS /* need portable alignment for large model */
+# define UNPORTABLE_ALIGNMENT
+#endif
+
+/* local style */
+
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
diff --git a/bcc/Makefile b/bcc/Makefile
new file mode 100644
index 0000000..eec2f83
--- /dev/null
+++ b/bcc/Makefile
@@ -0,0 +1,43 @@
+#
+# bcc Makefile
+# $Id$
+#
+BCCDEFS=-DLOCALPREFIX="\"/usr\"" -DDEFARCH=0
+
+ifneq ($(TOPDIR),)
+include $(TOPDIR)/Make.defs
+BCCDEFS=-DLOCALPREFIX="\"$(BCCHOME)\"" -DDEFARCH=0
+else
+CC=bcc
+LDFLAGS=-s
+endif
+
+OBJS = bcc-cc1.o codefrag.o debug.o declare.o express.o exptree.o floatop.o \
+ function.o gencode.o genloads.o glogcode.o hardop.o input.o label.o \
+ loadexp.o longop.o output.o preproc.o preserve.o scan.o softop.o \
+ state.o table.o type.o assign.o
+
+all: bcc bcc-cc1
+
+install: all
+ install -d $(LIBDIR)
+ install -m 755 bcc $(BINDIR)/bcc
+ install -m 755 bcc-cc1 $(LIBDIR)/bcc-cc1
+
+bcc: bcc.o
+ $(CC) -ansi $(LDFLAGS) bcc.o -o $@
+
+bcc.o: bcc.c
+ $(CC) -ansi $(CFLAGS) $(BCCDEFS) -c bcc.c
+
+bcc09: bcc.o
+ $(CC) -DMC6809 bcc.o $(LDFLAGS) -o $@
+
+ccc: bcc.o
+ $(CC) -DCCC bcc.o $(LDFLAGS) -o $@
+
+bcc-cc1: $(OBJS)
+ $(CC) $(LDFLAGS) $(OBJS) -o bcc-cc1
+
+clean:
+ rm -f bcc bcc-cc1 bcc09 ccc bcc.o $(OBJS)
diff --git a/bcc/align.h b/bcc/align.h
new file mode 100644
index 0000000..3c8971b
--- /dev/null
+++ b/bcc/align.h
@@ -0,0 +1,16 @@
+/* align.h - memory alignment requirements for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifndef S_ALIGNMENT
+# define align(x) (x)
+#else
+# ifdef UNPORTABLE_ALIGNMENT
+typedef unsigned pointerint_t;
+# define align(x) (((pointerint_t) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))
+# else
+# define align(x) ((char *) (x) + (- (int) (x) & (S_ALIGNMENT-1)))
+# endif
+#endif
+
+extern uoffset_t alignmask; /* general alignment mask */
diff --git a/bcc/assign.c b/bcc/assign.c
new file mode 100644
index 0000000..ebbc1fc
--- /dev/null
+++ b/bcc/assign.c
@@ -0,0 +1,387 @@
+/* assign.c - assignment and casting operations for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "sizes.h"
+#include "type.h"
+
+FORWARD void blockmove P((struct symstruct *source, struct symstruct *target));
+FORWARD void call3 P((char *funcname, struct symstruct *target,
+ struct symstruct *source, uoffset_t size));
+FORWARD void fconvert P((struct symstruct *source, struct typestruct *type));
+
+PUBLIC void assign(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt regpushed;
+ store_pt sourcereg;
+ scalar_t tscalar;
+
+ if (target->type->constructor & (ARRAY | FUNCTION) ||
+ target->flags == TEMP || target->flags == (LABELLED | STRING) ||
+ (target->indcount == 0 && target->flags != REGVAR))
+ {
+ bugerror("botched lvalue");
+ return;
+ }
+ if (source->storage != target->storage
+ || source->indcount != target->indcount
+ || source->level != target->level
+ || source->offset.offi != target->offset.offi /* kludge union cmp */
+ || source->type != target->type
+ || ((source->storage & (LOCAL | GLOBAL)
+ || source->level == OFFKLUDGELEVEL)
+ && ((source->flags ^ target->flags) & LABELLED
+ || (source->flags & LABELLED
+ && source->name.label != target->name.label)
+ || (!(source->flags & LABELLED)
+ && strcmp(source->name.namep, target->name.namep) != 0))))
+ {
+ tscalar = target->type->scalar;
+ if (tscalar & CHAR && source->storage == CONSTANT)
+ {
+ source->offset.offv &= CHMASKTO;
+ source->type = target->type;
+ }
+ regpushed = preslval(source, target);
+ if (!(tscalar & CHAR) || source->flags != TEMP ||
+ source->offset.offi != sp || source->type->typesize > itypesize)
+ cast(target->type, source);
+ if (tscalar & RSCALAR)
+ {
+ if (source->storage == CONSTANT && (!reguse & doubleregs))
+ load(source, doubleregs & ~DREG);
+ if (source->storage != CONSTANT && source->indcount == 0)
+ {
+ /* XXX - 386 only */
+ storereg(DREG, target);
+ if (tscalar & DOUBLE)
+ {
+ target->indcount = 1; /* XXX - outnnadr clobbers this */
+ target->offset.offi += accregsize;
+ storereg(doubleregs & ~DREG, target);
+ }
+ target->storage = source->storage;
+ target->offset.offi = 0;
+ }
+ else if (f_indirect(source) && tscalar & DOUBLE
+ && (!(reguse & OPREG) || target->storage == OPREG))
+ {
+ struct symstruct temptarg;
+
+ temptarg = *target;
+ pointat(&temptarg);
+ call("Fpull");
+ outntypechar(temptarg.type);
+ sp += dtypesize;
+ }
+ else
+ blockmove(source, target);
+ }
+ else if (target->type->constructor & STRUCTU)
+ blockmove(source, target);
+ else
+ {
+ if (tscalar & CHAR)
+ load(source, DREG);
+ else if (target->indcount == 0 && target->storage & regregs)
+ load(source, target->storage);
+ else
+ loadany(source);
+ if (tscalar & DLONG)
+ {
+ storereg(DREG, target);
+ target->indcount = 1;
+ target->offset.offi += accregsize;
+ }
+ if ((store_t) (sourcereg = source->storage) == DREG &&
+ target->type->scalar & CHAR)
+ sourcereg = BREG;
+ storereg(sourcereg, target);
+ if ((store_t) regpushed != 0)
+ {
+ /* DLONG */
+ target->indcount = 1;
+ target->offset.offi -= accregsize;
+ recovlist(regpushed);
+ }
+ else
+ {
+ target->storage = sourcereg;
+ target->offset.offi = 0;
+ if (target->level == OFFKLUDGELEVEL)
+ target->level = EXPRLEVEL;
+ }
+ }
+ }
+}
+
+/* block move assumes itypesize == accregsize && BREG size == 1 */
+
+PRIVATE void blockmove(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ struct symstruct oldtarget;
+ uoffset_t typesize;
+ struct symstruct worksource;
+
+ oldtarget = *target;
+ if ((typesize = target->type->typesize) >= 16 * itypesize ||
+ source->indcount + target->indcount != 2)
+ {
+ address(source);
+ address(target);
+ call3("_memcpy", target, source, typesize);
+ }
+ else
+ {
+ if (source->level == OFFKLUDGELEVEL)
+ addoffset(source); /* else kludge is lost and offsets big */
+ if (target->level == OFFKLUDGELEVEL)
+ addoffset(target);
+ worksource = *source;
+ for (; typesize >= itypesize; typesize -= itypesize)
+ {
+ loadreg(source, DREG);
+ worksource.offset.offi += itypesize;
+ *source = worksource;
+ storereg(DREG, target);
+ target->indcount = 1;
+ target->offset.offi += accregsize;
+ }
+ while (typesize-- != 0)
+ {
+ outload();
+ outregname(BREG);
+ outopsep();
+ outadr(source);
+ worksource.offset.offi += 1;
+ *source = worksource;
+ storereg(BREG, target);
+ target->indcount = 1;
+ target->offset.offi += 1;
+ }
+ }
+ *target = oldtarget;
+}
+
+PRIVATE void call3(funcname, target, source, size)
+char *funcname;
+struct symstruct *target;
+struct symstruct *source;
+uoffset_t size;
+{
+ store_pt regpushed;
+ offset_t spmark;
+ struct symstruct *length;
+
+ pushlist(regpushed = reguse & ~calleemask);
+ spmark = sp;
+ length = constsym((value_t) size);
+ length->type = uitype;
+ push(length);
+ push(source);
+ push(target);
+ call(funcname);
+ outnl();
+ if (regpushed)
+ {
+ modstk(spmark);
+ recovlist(regpushed);
+ }
+}
+
+PUBLIC void cast(type, target)
+struct typestruct *type;
+struct symstruct *target;
+{
+ scalar_t newscalar;
+ uoffset_t newsize;
+ scalar_t oldscalar;
+ uoffset_t oldsize;
+ store_pt targreg;
+
+ if (type->constructor & (ARRAY | FUNCTION)
+ || (type->constructor & STRUCTU && target->type != type))
+ {
+ bugerror("botched implicit cast");
+ return;
+ }
+ if (target->type == type)
+ return;
+ if (target->type->constructor == ARRAY)
+ oldsize = ptypesize;
+ else
+ oldsize = target->type->typesize;
+ newscalar = type->scalar;
+ oldscalar = target->type->scalar;
+ if ((newsize = type->typesize) == oldsize &&
+ !((newscalar | oldscalar) & RSCALAR))
+ ;
+ else if (newsize == ctypesize) /* char only */
+ {
+ if (oldscalar & RSCALAR)
+ fconvert(target, type);
+ else if (target->indcount == 1)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+# if BIG_ENDIAN
+ target->offset.offi += oldsize - ctypesize;
+# else
+ {
+ if (oldscalar & DLONG)
+ target->offset.offi += itypesize; /* discard msword */
+ }
+# endif
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+# if BIG_ENDIAN
+ target->offset.offi += ctypesize;
+# else
+ ;
+# endif
+#endif
+ }
+ else if (target->storage != CONSTANT)
+ {
+ load(target, DREG);
+ target->storage = BREG;
+ }
+ }
+ else if ((newscalar & (SHORT | INT | LONG) && !(newscalar & DLONG))
+ || type->constructor & POINTER)
+ {
+ if (oldscalar & RSCALAR)
+ fconvert(target, type);
+ else if (oldsize < newsize)
+ extend(target);
+ else if (target->indcount == 1)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ {
+ if (oldscalar & DLONG)
+ target->offset.offi += itypesize; /* discard msword */
+ }
+#endif
+ }
+ else
+ load(target, DREG);
+ }
+ else if (newscalar & DLONG)
+ {
+ if (oldscalar & RSCALAR)
+ fconvert(target, type);
+ else if (target->storage != CONSTANT)
+ {
+ extend(target);
+ load(target, DREG);
+ target->storage = targreg = getindexreg();
+ if (oldscalar & (UNSIGNED | CHAR) ||
+ target->type->constructor & (ARRAY | FUNCTION | POINTER))
+ uitol(targreg);
+ else
+ itol(targreg);
+ }
+ }
+ else if (newscalar & RSCALAR)
+ {
+ saveopreg(); /* XXX */
+ if (oldscalar & (ISCALAR | FLOAT))
+ fpush(target);
+ if (newscalar & FLOAT)
+ {
+ pointat(target);
+ call("dto");
+ outntypechar(type);
+ justpushed(target); /* XXX - sets dtype wrong (harmless) and
+ * wastes (dtypesize - ftypesize) stack */
+ }
+ restoreopreg();
+ }
+ target->type = type;
+}
+
+/* extend char or short to int (unsigned if from unsigned) */
+
+PUBLIC void extend(target)
+struct symstruct *target;
+{
+ scalar_t tscalar;
+
+ if ((tscalar = target->type->scalar) & (CHAR | SHORT))
+ {
+ if (target->storage != CONSTANT &&
+ target->type->typesize < itypesize)
+ {
+ load(target, DREG);
+ if (target->type == sctype)
+ sctoi();
+#ifdef I8088
+ else if (tscalar & SHORT)
+ {
+ if (tscalar & UNSIGNED)
+ ustoi();
+ else
+ stoi();
+ }
+#endif
+ else
+ ctoi();
+ target->storage = DREG;
+ }
+ if (tscalar & UNSIGNED)
+ target->type = uitype;
+ else
+ target->type = itype;
+ }
+}
+
+PRIVATE void fconvert(source, type)
+struct symstruct *source;
+struct typestruct *type;
+{
+ offset_t spmark;
+
+ pushlist(reguse & OPREG);
+ spmark = sp;
+ pointat(source);
+ if (source->type->scalar & DOUBLE)
+ call("dto");
+ else
+ call("fto");
+ if (type->scalar & UNSIGNED)
+ outbyte('u');
+ outntypechar(type);
+ if (type->scalar & DLONG)
+ {
+ if (reguse & OPREG)
+ bugerror("loading long into used reg");
+ source->storage = OPREG;
+ }
+ else if (type->scalar & CHAR)
+ source->storage = BREG;
+ else
+ source->storage = DREG;
+ source->offset.offi =
+ source->flags =
+ source->indcount = 0;
+ modstk(spmark); /* could adjust later (load instead of pop) */
+ poplist(reguse & OPREG);
+}
diff --git a/bcc/bcc-cc1.c b/bcc/bcc-cc1.c
new file mode 100644
index 0000000..d6fece3
--- /dev/null
+++ b/bcc/bcc-cc1.c
@@ -0,0 +1,25 @@
+/* bcc-cc1.c - "pass 1" for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ growheap(0); /* init order is important */
+ syminit();
+ etreeinit();
+ ifinit();
+ predefine();
+ openio(argc, argv);
+ codeinit();
+ typeinit();
+ program();
+ finishup();
+
+ /* NOTREACHED */
+ return 0;
+}
diff --git a/bcc/bcc.bugs b/bcc/bcc.bugs
new file mode 100644
index 0000000..52f6958
--- /dev/null
+++ b/bcc/bcc.bugs
@@ -0,0 +1,169 @@
+compiler limitations
+--------------------
+
+These are not implemented:
+
+a. bit fields
+ kludgily implemented (everything padded to char, int or long; can store
+ values wider than the specified field width)
+
+g. signed char type, other ANSI extensions
+
+compiler bugs
+-------------
+
+6. weird but doable casts are not always done for initializers
+
+15. calls to a (casted) absolute address produce an immediate prefix. as386
+ doesn't mind this but complains about the absolute address. as09 complains
+ about the prefix but can handle the absolute address
+
+23. char *f(); &f() is accepted as f() but produces botched nodetype
+ (calc char **).
+
+31. null byte in string initialiser should be ignored if it doesn't fit
+ Non-null bytes which don't fit should be ignored with a warning
+
+32. static char c = "xyz"; is allowed, and bad FCB is generated
+
+37. init of union will store multiple comma-separated entries
+
+38. arrays sizes larger than the amount of memory are accepted
+
+40. structure and union definitions are confused with each other. So
+ struct foo may be used in a declaration like "union foo bar;"
+
+42. pointer arithmetic is performed on pointers to undefined structures
+ (of unknown size). Size is taken as 0 although alignmask is set early
+
+59. preprocessor stuff (# lines or macro names) between the identifier for
+ a label and the colon for the label messes up the label
+
+60. some things involving switches are now broken for 6809 due to lack of
+ frame pointer
+
+61. assembler may get lost on lines of length exactly (?) 256
+
+65. expressions in emum lists or not properly checked for overflow. They
+ should fit in ints. The ordinal number is allowed to overflow
+
+66. sizeof has type int instead of size_t
+
+68. "return expr;" in a function returning a void is reported as a compiler
+ bug not as a semantic error
+
+69. an argument declared as float is (correctly) promoted to double, but
+ not demoted to float when it is used
+
+71. identifiers longer than 64 are botched (scanning of the identifier is
+ stopped but the remaining characters in the identifier are left to
+ mess up the input stream
+
+72. check for too many macro parameters is not working
+
+74. union { char a, b; } foo; gives the wrong offset for b. Unions work OK
+ if the declaration lists have length 1
+
+75. stack gets cleaned up too early in bee = foo ? bar : baz() where baz()
+ returns a struct although there is kludge to make plain bee = baz() work
+
+76. have reintroduced reduced-type bugs, so sizeof(1 ? 1 : 2) is 1
+
+78. fix to require comma in arg list may be half-baked
+
+79. compiler starts trying to load the void expression (i ? (void)0 : (void)0)
+
+80. (unsigned char *) - (char *) causes error and message is obscure
+
+81. 'defined' is a reserved word
+
+82. conditionals with voids don't work
+
+83. float = 1e100 gets overflow exception
+
+84. #endif seems to be seen in
+#if 1
+foo #endif bar
+
+85. line numbers from cpp are not quite right.
+
+bugs that may be fixed
+----------------------
+
+41. typedef's are not scoped properly
+
+nonstandard things that are not done quite right
+------------------------------------------------
+
+3. arguments declared as register are not being dumped by #asm, register
+ vars anyway not being passed to #asm
+
+26. should clear label ptrs when starting #asm
+
+things that have to be be done better
+-------------------------------------
+
+11. push order reversed in genloads.c (temp) - might try to get DP order right
+
+12. need to clean up handling of sc specs (maybe rename flags to sc)
+ And local statics and externs
+
+24. gvarsc is not returned properly for struct/union since the members
+ affect gvarsc (incorrectly). There should be a flag set when
+ inside a struct/union definition to disable sc specs. This could
+ replace the tests in abdeclarator and declselt
+ Best may be to carry the sc along with the type a bit more (in a
+ global symbol structure). Also, the symbol should record sc in a better
+ way than now
+
+25. need to check stack sometimes. Xenix cc does it when allocating >= 100
+ bytes locals and this is essential in Xenix as the stack is grown
+ dynamically
+
+68. overflow checking for constants
+
+things that could be done better
+--------------------------------
+
+4. install new 6809 code for branch patching (after redundancy checks)
+
+5. can improve code for compare with global adr in non-posindependent case
+
+6. char *s; long *pl;
+ code for *s += *pl is poor, for *s += (int) *pl is good
+
+7. most mov's from to ax would be faster and smaller done by xchg's
+
+7a. check ptr add/sub operations earlier
+
+8. tests for against 1 and -1 can sometimes be done with dec's and inc's
+
+9. __opreg is used unnec when the ptr is already in it
+
+9a. double indirect ptrs should maybe be made direct rather than singly
+ indirect by makelessindirect
+
+10. in cmpsmallconst(), the comparison constant should be incorporated in
+ the offset if the indcount is 0 and lea() called. It is harmless to
+ use the lea() trick for non-small constants
+
+20. when saved registers are popped in assign() they may overwrite the
+ expression value, anywhere else? May be fixed now
+
+27. better if loadexpression returned the register used
+
+28. better if source.c did not #include storage.h - it only references
+ DEFINITION, in some blank-skipping code which could be moved to
+ scan.c or preproc.c. preproc.c, scan.c and type.c also #include
+ storage.h, just to get at the DEFINITION and KEYWORD definitions
+
+29. need nodetype() to know about all optimisations in advance, including
+ int % small power of 2 (including 0, 1). Need to delete all type
+ assignments in final code gen, specially the one that convert short
+ to int
+
+30. overflow checking at runtime
+
+31. Use more than the first char from multiple character constants
+
+56. --i++ is not detected as an error in the parser
diff --git a/bcc/bcc.c b/bcc/bcc.c
new file mode 100644
index 0000000..810cbcb
--- /dev/null
+++ b/bcc/bcc.c
@@ -0,0 +1,961 @@
+/* bcc.c - driver for Bruce's C compiler (bcc) and for CvW's C compiler */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define _POSIX_SOURCE 1
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FALSE 0
+#define FORWARD static
+#define NUL_PTR ((void*)0)
+#define PRIVATE static
+#define PUBLIC
+#define TRUE 1
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+#define AS "as86"
+#define BAS86
+#define BCC86
+#define CC1 "bcc-cc1"
+#define CC1_MINUS_O_BROKEN FALSE
+#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */
+#define CPPFLAGS "-E"
+#define CRT0 "crt0.o"
+#define GCC "gcc"
+#define LD "ld86"
+#ifndef NO_ANSI_SUPPORT
+#define UNPROTO "unproto"
+#endif
+#define STANDARD_CRT0_0_PREFIX LOCALPREFIX "/lib/bcc/i86/"
+#define STANDARD_CRT0_3_PREFIX LOCALPREFIX "/lib/bcc/i386/"
+#define STANDARD_EXEC_PREFIX LOCALPREFIX "/lib/bcc/"
+#define STANDARD_EXEC_PREFIX_2 LOCALPREFIX "/bin/"
+#define DEFAULT_INCLUDE "-I" LOCALPREFIX "/include"
+#define DEFAULT_LIBDIR0 "-L" LOCALPREFIX "/lib/bcc/i86/"
+#define DEFAULT_LIBDIR3 "-L" LOCALPREFIX "/lib/bcc/i386/"
+
+#ifdef CCC
+#undef BCC86
+#undef CC1
+#define CC1 "c386"
+#undef CC1_MINUS_O_BROKEN
+#define CC1_MINUS_O_BROKEN TRUE
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#define STANDARD_CRT0_PREFIX "/usr/local/lib/i386/"
+#endif /* CCC */
+
+#ifdef MC6809
+#undef BAS86
+#undef BCC86
+#undef CRT0
+#undef GCC
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#undef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX "/usr/local/libexec/m09/bcc/"
+#endif /* MC6809 */
+
+#define ALLOC_UNIT 16 /* allocation unit for arg arrays */
+#define DIRCHAR '/'
+#define START_ARGS 4 /* number of reserved args */
+
+typedef unsigned char bool_T; /* boolean: TRUE if nonzero */
+
+struct arg_s
+{
+ char *prog;
+ bool_T minus_O_broken;
+ int argc;
+ char **argv;
+ unsigned nr_allocated;
+};
+
+struct prefix_s
+{
+ char *name;
+ struct prefix_s *next;
+};
+
+PRIVATE struct arg_s asargs = { AS, };
+PRIVATE struct arg_s ccargs = { CC1, CC1_MINUS_O_BROKEN, };
+PRIVATE struct arg_s cppargs = { CPP, };
+#ifndef NO_ANSI_SUPPORT
+PRIVATE struct arg_s unprotoargs = { UNPROTO, TRUE };
+#endif
+#ifdef STANDARD_CRT0_PREFIX
+PRIVATE struct prefix_s crt0_prefix = { STANDARD_CRT0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_0_PREFIX
+PRIVATE struct prefix_s crt0_0_prefix = { STANDARD_CRT0_0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_3_PREFIX
+PRIVATE struct prefix_s crt0_3_prefix = { STANDARD_CRT0_3_PREFIX, };
+#endif
+PRIVATE struct prefix_s exec_prefix;
+PRIVATE struct arg_s ldargs = { LD, };
+#ifdef BAS86
+PRIVATE struct arg_s ldrargs = { LD, };
+#endif
+PRIVATE char *progname;
+PRIVATE bool_T runerror; /* = FALSE */
+PRIVATE struct arg_s tmpargs; /* = empty */
+PRIVATE char *tmpdir;
+PRIVATE unsigned verbosity; /* = 0 */
+
+#ifdef REDECLARE_STDC_FUNCTIONS
+void exit P((int status));
+char *getenv P((const char *name));
+void *malloc P((size_t size));
+void *realloc P((void *ptr, size_t size));
+void (*signal P((int sig, void (*func) P((int sig))))) P((int sig));
+char *strcpy P((char *dest, const char *src));
+size_t strlen P((const char *s));
+char *strrchr P((const char *s, int c));
+#endif
+
+#ifdef REDECLARE_POSIX_FUNCTIONS
+int access P((const char *path, int amode));
+int execv P((const char *path, char * const *argv));
+pid_t fork P((void));
+pid_t getpid P((void));
+int unlink P((const char *path));
+pid_t wait P((int *status));
+ssize_t write P((int fd, const void *buf, size_t nbytes));
+#endif
+
+int main P((int argc, char **argv));
+
+FORWARD void addarg P((struct arg_s *argp, char *arg));
+FORWARD void addprefix P((struct prefix_s *prefix, char *name));
+FORWARD void fatal P((char *message));
+FORWARD char *fixpath P((char *path, struct prefix_s *prefix, int mode));
+FORWARD void killtemps P((void));
+FORWARD void *my_malloc P((unsigned size, char *where));
+FORWARD char *my_mktemp P((void));
+FORWARD void my_unlink P((char *name));
+FORWARD void outofmemory P((char *where));
+FORWARD int run P((char *in_name, char *out_name, struct arg_s *argp));
+FORWARD void set_trap P((void));
+FORWARD void show_who P((char *message));
+FORWARD void startarg P((struct arg_s *argp));
+FORWARD char *stralloc P((char *s));
+FORWARD char *stralloc2 P((char *s1, char *s2));
+FORWARD void trap P((int signum));
+FORWARD void unsupported P((char *option, char *message));
+FORWARD void writen P((void));
+FORWARD void writes P((char *s));
+FORWARD void writesn P((char *s));
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+ int add_default_inc = 1;
+ int add_default_lib = 1;
+ int argcount = argc;
+ bool_T *argdone = my_malloc((unsigned) argc * sizeof *argdone, "argdone");
+ bool_T as_only = FALSE;
+ char *basename;
+#ifdef BCC86
+#ifdef DEFARCH
+ bool_T bits32 = (DEFARCH != 0);
+#else
+ bool_T bits32 = sizeof (char *) >= 4;
+#endif
+ char *bits_arg;
+#endif
+ bool_T cc_only = FALSE;
+#ifndef NO_ANSI_SUPPORT
+ bool_T ansi_pass = FALSE;
+#endif
+#ifdef CCC
+ bool_T cpp_pass = TRUE;
+#else
+ bool_T cpp_pass = FALSE;
+#endif
+#ifdef BCC86
+ char *crt0;
+#endif
+ bool_T debug = FALSE;
+ bool_T echo = FALSE;
+ unsigned errcount = 0;
+ char ext;
+ char *f_out = NUL_PTR;
+ bool_T float_emulation = FALSE;
+#ifdef BAS86
+ bool_T gnu_objects = FALSE;
+#endif
+ char *in_name;
+ int length;
+ unsigned ncisfiles = 0;
+ unsigned nifiles = 0;
+ unsigned npass_specs;
+ bool_T optimize = FALSE;
+ char *out_name;
+ bool_T profile = FALSE;
+ bool_T prep_only = FALSE;
+ bool_T prep_line_numbers = FALSE;
+ int status;
+ char *temp;
+
+ progname = argv[0];
+ addarg(&cppargs, CPPFLAGS);
+#ifdef CCC
+ addarg(&asargs, "-j");
+#endif
+ addarg(&asargs, "-u");
+ addarg(&asargs, "-w");
+#ifdef BCC86
+ addarg(&ldargs, "-i");
+#endif
+#ifdef BAS86
+ addarg(&ldrargs, "-r");
+#endif
+
+ /* Pass 1 over argv to gather compile options. */
+ for (; --argc != 0;)
+ {
+ arg = *++argv;
+ *++argdone = TRUE;
+ if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0)
+ switch (arg[1])
+ {
+#ifdef BCC86
+ case '0':
+ bits32 = FALSE;
+ break;
+ case '3':
+ bits32 = TRUE;
+ break;
+#endif
+ case 'E':
+ prep_only = prep_line_numbers = cpp_pass = TRUE;
+ break;
+#ifdef BAS86
+ case 'G':
+ gnu_objects = TRUE;
+ break;
+#endif
+ case 'P':
+ prep_only = cpp_pass = TRUE;
+ prep_line_numbers = FALSE;
+ break;
+ case 'O':
+ optimize = TRUE; /* unsupported( arg, "optimize" ); */
+ break;
+ case 'S':
+ cc_only = TRUE;
+ break;
+ case 'V':
+ echo = TRUE;
+ break;
+ case 'c':
+ as_only = TRUE;
+ break;
+ case 'e':
+ cpp_pass = TRUE;
+ break;
+ case 'f':
+ float_emulation = TRUE;
+ ++errcount;
+ unsupported(arg, "float emulation");
+ break;
+ case 'g':
+ debug = TRUE; /* unsupported( arg, "debug" ); */
+ break;
+ case 'o':
+ if (--argc < 1)
+ {
+ ++errcount;
+ show_who("output file missing after -o\n");
+ }
+ else
+ {
+ if (f_out != NUL_PTR)
+ show_who("more than one output file\n");
+ f_out = *++argv;
+ *++argdone = TRUE;
+ }
+ break;
+ case 'p':
+ profile = TRUE;
+ ++errcount;
+ unsupported(arg, "profile");
+ break;
+ case 'v':
+ ++verbosity;
+ break;
+ case 'I':
+ add_default_inc = 0;
+ break;
+ case 'L':
+ add_default_lib = 0;
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else if (arg[0] == '-')
+ switch (arg[1])
+ {
+#ifndef NO_ANSI_SUPPORT
+ case 'a':
+ if (!strcmp(arg, "-ansi"))
+ {
+ ansi_pass=TRUE;
+ cpp_pass=TRUE;
+#ifndef CCC
+ /* NOTE I'm setting this to zero, this isn't a _real_ STDC */
+ addarg(&ccargs, "-D__STDC__=0");
+#endif
+ addarg(&cppargs, "-D__STDC__=0");
+#endif
+ }
+ break;
+ case 'A':
+ addarg(&asargs, arg + 2);
+ break;
+ case 'B':
+ addprefix(&exec_prefix, arg + 2);
+ break;
+ case 'C':
+ addarg(&ccargs, arg + 2);
+ break;
+ case 'D':
+ case 'I':
+ case 'U':
+#ifndef CCC
+ addarg(&ccargs, arg);
+#endif
+ addarg(&cppargs, arg);
+ break;
+ case 'X':
+ addarg(&ldargs, arg + 2);
+ break;
+ case 'L':
+ addarg(&ldargs, arg);
+ break;
+ case 'P':
+ addarg(&cppargs, arg + 2);
+ break;
+ case 'Q':
+ addarg(&ccargs, arg);
+ break;
+ case 'T':
+ tmpdir = arg + 2;
+ break;
+ case 't':
+ ++errcount;
+ unsupported(arg, "pass number");
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else
+ {
+ ++nifiles;
+ *argdone = FALSE;
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ ++ncisfiles;
+ }
+ }
+ npass_specs = prep_only + cc_only + as_only;
+ if (npass_specs != 0)
+ {
+ if (npass_specs > 1)
+ {
+ ++errcount;
+ show_who("more than 1 option from -E -P -S -c\n");
+ }
+ if (f_out != NUL_PTR && ncisfiles > 1)
+ {
+ ++errcount;
+ show_who("cannot have more than 1 input with non-linked output\n");
+ }
+ }
+ if (nifiles == 0)
+ {
+ ++errcount;
+ show_who("no input files\n");
+ }
+ if (errcount != 0)
+ exit(1);
+
+ if ((temp = getenv("BCC_EXEC_PREFIX")) != NUL_PTR)
+ addprefix(&exec_prefix, temp);
+ if( add_default_inc )
+ {
+#ifndef CCC
+ addarg(&ccargs, DEFAULT_INCLUDE);
+#endif
+ addarg(&cppargs, DEFAULT_INCLUDE);
+ }
+ if( add_default_lib )
+ {
+#ifdef BCC86
+ if( bits32 )
+ addarg(&ldargs, DEFAULT_LIBDIR3);
+ else
+#endif
+ addarg(&ldargs, DEFAULT_LIBDIR0);
+ }
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX);
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX_2);
+ cppargs.prog = fixpath(cppargs.prog, &exec_prefix, X_OK);
+ ccargs.prog = fixpath(ccargs.prog, &exec_prefix, X_OK);
+ asargs.prog = fixpath(asargs.prog, &exec_prefix, X_OK);
+ ldargs.prog = fixpath(ldargs.prog, &exec_prefix, X_OK);
+ ldrargs.prog = fixpath(ldrargs.prog, &exec_prefix, X_OK);
+#ifndef NO_ANSI_SUPPORT
+ unprotoargs.prog=fixpath(unprotoargs.prog, &exec_prefix, X_OK);
+#endif
+ if (tmpdir == NUL_PTR && (tmpdir = getenv("TMPDIR")) == NUL_PTR)
+ tmpdir = "/tmp";
+
+ if (prep_only && !prep_line_numbers)
+ addarg(&cppargs, "-P");
+#ifdef BCC86
+ if (bits32)
+ {
+ bits_arg = "-3";
+ crt0 = fixpath(CRT0, &crt0_3_prefix, R_OK);
+ }
+ else
+ {
+ bits_arg = "-0";
+ crt0 = fixpath(CRT0, &crt0_0_prefix, R_OK);
+ }
+ addarg(&ccargs, bits_arg);
+ addarg(&cppargs, bits_arg);
+ addarg(&asargs, bits_arg);
+#ifdef BAS86
+ if (!gnu_objects)
+ {
+ addarg(&ldargs, bits_arg);
+ addarg(&ldrargs, bits_arg);
+ /* addarg(&ldargs, crt0);*/
+ addarg(&ldargs, "-C0");
+ }
+#endif /* BAS86 */
+#endif /* BCC86 */
+#if defined(BAS86) && !defined(BCC86)
+ if (!gnu_objects)
+ addarg(&ldargs, fixpath(CRT0, &crt0_prefix, R_OK));
+#endif
+ set_trap();
+
+ /* Pass 2 over argv to compile and assemble .c, .i, .S and .s files and
+ * gather arguments for linker.
+ */
+ for (argv -= (argc = argcount) - 1, argdone -= argcount - 1; --argc != 0;)
+ {
+ arg = *++argv;
+ if (!*++argdone)
+ {
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ {
+ if (echo || verbosity != 0)
+ {
+ writes(arg);
+ writesn(":");
+ }
+ if ((basename = strrchr(arg, DIRCHAR)) == NUL_PTR)
+ basename = arg;
+ else
+ ++basename;
+ in_name = arg;
+ if (ext == 'c')
+ {
+ if (cpp_pass)
+ {
+#ifndef NO_ANSI_SUPPORT
+ if (prep_only && !ansi_pass)
+#else
+ if (prep_only)
+#endif
+ out_name = f_out;
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+#ifndef NO_ANSI_SUPPORT
+ if (ansi_pass)
+ {
+ if (prep_only)
+ out_name = f_out;
+ else
+ out_name = my_mktemp();
+
+ if (run(in_name, out_name, &unprotoargs) != 0)
+ continue;
+ in_name=out_name;
+ }
+#endif
+ }
+ ext = 'i';
+ }
+ if (ext == 'i')
+ {
+ if (prep_only)
+ continue;
+ if (cc_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &ccargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 'S')
+ {
+ if (prep_only)
+ out_name = f_out;
+ else if (cc_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 's')
+ {
+ if (prep_only || cc_only)
+ continue;
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ if (as_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ }
+ }
+ else
+ out_name = my_mktemp();
+ addarg(&asargs, "-n");
+ arg[length - 1] = 's';
+ addarg(&asargs, arg);
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ char *tmp_out_name;
+
+ tmp_out_name = my_mktemp();
+ status = run(in_name, tmp_out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ if (run(tmp_out_name, out_name, &ldrargs) != 0)
+ continue;
+ }
+ else
+#endif
+ {
+ status = run(in_name, out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ }
+ ext = 'o';
+ in_name = out_name;
+ }
+ if (ext == 'o')
+ {
+ if (prep_only || cc_only || as_only)
+ continue;
+ addarg(&ldargs, in_name);
+ }
+ }
+ else
+ addarg(&ldargs, arg);
+ }
+ }
+
+ if (!prep_only && !cc_only && !as_only && !runerror)
+ {
+ if (f_out == NUL_PTR)
+ f_out = "a.out";
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ /* Remove -i and -i-. */
+ for (argc = ldargs.argc - 1; argc >= START_ARGS; --argc)
+ {
+ arg = ldargs.argv[argc];
+ if (arg[0] == '-' && arg[1] == 'i'
+ && (arg[2] == 0 || (arg[2] == '-' && arg[3] == 0)))
+ {
+ --ldargs.argc;
+ memmove(ldargs.argv + argc, ldargs.argv + argc + 1,
+ (ldargs.argc - argc) * sizeof ldargs.argv[0]);
+ ldargs.argv[ldargs.argc] = NUL_PTR;
+ }
+ }
+
+ ldargs.prog = fixpath(GCC, &exec_prefix, X_OK);
+ run((char *) NUL_PTR, f_out, &ldargs);
+ }
+ else
+#endif
+ {
+ addarg(&ldargs, "-lc");
+ run((char *) NUL_PTR, f_out, &ldargs);
+ }
+ }
+ killtemps();
+ return runerror ? 1 : 0;
+}
+
+PRIVATE void addarg(argp, arg)
+register struct arg_s *argp;
+char *arg;
+{
+ int new_argc;
+ char **new_argv;
+
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ new_argc = argp->argc + 1;
+ if (new_argc >= argp->nr_allocated)
+ {
+ argp->nr_allocated += ALLOC_UNIT;
+ new_argv = realloc(argp->argv, argp->nr_allocated * sizeof *argp->argv);
+ if (new_argv == NUL_PTR)
+ outofmemory("addarg");
+ argp->argv = new_argv;
+ }
+ argp->argv[argp->argc] = arg;
+ argp->argv[argp->argc = new_argc] = NUL_PTR;
+}
+
+PRIVATE void addprefix(prefix, name)
+struct prefix_s *prefix;
+char *name;
+{
+ struct prefix_s *new_prefix;
+
+ if (prefix->name == NUL_PTR)
+ prefix->name = name;
+ else
+ {
+ new_prefix = my_malloc(sizeof *new_prefix, "addprefix");
+ new_prefix->name = name;
+ new_prefix->next = NUL_PTR;
+ while (prefix->next != NUL_PTR)
+ prefix = prefix->next;
+ prefix->next = new_prefix;
+ }
+}
+
+PRIVATE void fatal(message)
+char *message;
+{
+ writesn(message);
+ killtemps();
+ exit(1);
+}
+
+PRIVATE char *fixpath(path, prefix, mode)
+char *path;
+struct prefix_s *prefix;
+int mode;
+{
+ char *ppath;
+
+ for (; prefix != NUL_PTR; prefix = prefix->next)
+ {
+ if (verbosity > 2)
+ {
+ show_who("searching for ");
+ if (mode == R_OK)
+ writes("readable file ");
+ else
+ writes("executable file ");
+ writes(path);
+ writes(" in ");
+ writesn(prefix->name);
+ }
+ ppath = stralloc2(prefix->name, path);
+ if (access(ppath, mode) == 0)
+ return ppath;
+ free(ppath);
+ }
+ return path;
+}
+
+PRIVATE void killtemps()
+{
+ while (tmpargs.argc > START_ARGS)
+ my_unlink(tmpargs.argv[--tmpargs.argc]);
+}
+
+PRIVATE void *my_malloc(size, where)
+unsigned size;
+char *where;
+{
+ void *block;
+
+ if ((block = malloc(size)) == NUL_PTR)
+ outofmemory(where);
+ return block;
+}
+
+PRIVATE char *my_mktemp()
+{
+ char *p;
+ unsigned digit;
+ unsigned digits;
+ char *template;
+ static unsigned tmpnum;
+
+ p = template = stralloc2(tmpdir, "/bccYYYYXXXX");
+ p += strlen(p);
+
+ digits = getpid();
+ while (*--p == 'X')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p = digit + '0';
+ digits /= 16;
+ }
+ digits = tmpnum;
+ while (*p == 'Y')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p-- = digit + '0';
+ digits /= 16;
+ }
+ ++tmpnum;
+ addarg(&tmpargs, template);
+ return template;
+}
+
+PRIVATE void my_unlink(name)
+char *name;
+{
+ if (verbosity > 1)
+ {
+ show_who("unlinking ");
+ writesn(name);
+ }
+ if (unlink(name) < 0)
+ {
+ show_who("error unlinking ");
+ writesn(name);
+ }
+}
+
+PRIVATE void outofmemory(where)
+char *where;
+{
+ show_who("out of memory in ");
+ fatal(where);
+}
+
+PRIVATE int run(in_name, out_name, argp)
+char *in_name;
+char *out_name;
+struct arg_s *argp;
+{
+ int arg0;
+ int i;
+ int status;
+
+ arg0 = 0;
+ if (in_name == NUL_PTR)
+ ++arg0;
+ if (out_name == NUL_PTR)
+ arg0 += 2;
+ else if (argp->minus_O_broken)
+ ++arg0;
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ argp->argv[arg0] = argp->prog;
+ i = arg0 + 1;
+ if (in_name != NUL_PTR)
+ argp->argv[i++] = in_name;
+ if (out_name != NUL_PTR)
+ {
+ if (!argp->minus_O_broken)
+ argp->argv[i++] = "-o";
+ argp->argv[i++] = out_name;
+ }
+ if (verbosity != 0)
+ {
+ for (i = arg0; i < argp->argc; ++i)
+ {
+ writes(argp->argv[i]);
+ writes(" ");
+ }
+ writen();
+ }
+ switch (fork())
+ {
+ case -1:
+ show_who("fork failed");
+ fatal("");
+ case 0:
+ execv(argp->prog, argp->argv + arg0);
+ show_who("exec of ");
+ writes(argp->prog);
+ fatal(" failed");
+ default:
+ wait(&status);
+ for (i = tmpargs.argc - 1; i >= START_ARGS; --i)
+ if (in_name == tmpargs.argv[i])
+ {
+ my_unlink(in_name);
+ --tmpargs.argc;
+ memmove(tmpargs.argv + i, tmpargs.argv + i + 1,
+ (tmpargs.argc - i) * sizeof tmpargs.argv[0]);
+ tmpargs.argv[tmpargs.argc] = NUL_PTR;
+ break;
+ }
+ if (status != 0)
+ {
+ killtemps();
+ runerror = TRUE;
+ }
+ return status;
+ }
+}
+
+PRIVATE void set_trap()
+{
+#ifndef NORDB
+#ifdef SIGINT
+ signal(SIGINT, trap);
+#endif
+#ifdef SIGQUIT
+ signal(SIGQUIT, trap);
+#endif
+
+#else
+ /* This is being too trap happy! */
+#ifndef _NSIG
+#define _NSIG NSIG
+#endif
+ int signum;
+
+ for (signum = 0; signum <= _NSIG; ++signum)
+#ifdef SIGCHLD
+ if (signum != SIGCHLD)
+#endif
+ if (signal(signum, SIG_IGN) != SIG_IGN)
+ signal(signum, trap);
+#endif
+}
+
+PRIVATE void show_who(message)
+char *message;
+{
+ writes(progname);
+ writes(": ");
+ writes(message);
+}
+
+PRIVATE void startarg(argp)
+struct arg_s *argp;
+{
+ argp->argv = my_malloc((argp->nr_allocated = ALLOC_UNIT)
+ * sizeof *argp->argv, "startarg");
+ argp->argc = START_ARGS;
+ argp->argv[START_ARGS] = NUL_PTR;
+}
+
+PRIVATE char *stralloc(s)
+char *s;
+{
+ return strcpy(my_malloc(strlen(s) + 1, "stralloc"), s);
+}
+
+PRIVATE char *stralloc2(s1, s2)
+char *s1;
+char *s2;
+{
+ return strcat(strcpy(my_malloc(
+ strlen(s1) + strlen(s2) + 1, "stralloc2"), s1), s2);
+}
+
+PRIVATE void trap(signum)
+int signum;
+{
+ signal(signum, SIG_IGN);
+ show_who("caught signal");
+ fatal("");
+}
+
+PRIVATE void unsupported(option, message)
+char *option;
+char *message;
+{
+ show_who("compiler option ");
+ writes(option);
+ writes(" (");
+ writes(message);
+ writesn(") not supported yet");
+}
+
+PRIVATE void writen()
+{
+ writes("\n");
+}
+
+PRIVATE void writes(s)
+char *s;
+{
+ write(2, s, strlen(s));
+}
+
+PRIVATE void writesn(s)
+char *s;
+{
+ writes(s);
+ writen();
+}
diff --git a/bcc/bcc.c.gnu b/bcc/bcc.c.gnu
new file mode 100644
index 0000000..8491c97
--- /dev/null
+++ b/bcc/bcc.c.gnu
@@ -0,0 +1,983 @@
+/* bcc.c - driver for Bruce's C compiler (bcc) and for CvW's C compiler */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define _POSIX_SOURCE 1
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define FALSE 0
+#define FORWARD static
+#define NUL_PTR ((void*)0)
+#define PRIVATE static
+#define PUBLIC
+#define TRUE 1
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+#define AS "as86"
+#define BAS86
+#define BCC86
+#define CC1 "bcc-cc1"
+#define CC1_MINUS_O_BROKEN FALSE
+#define CPP "bcc-cc1" /* normally a link to /usr/bin/bcc-cc1 */
+#define CPPFLAGS "-E"
+#define CRT0 "crt0.o"
+#define GCC "gcc"
+#define LD "ld86"
+#ifdef ANSI_SUPPORT
+#define UNPROTO "unprotoize"
+#define CP "/bin/cp"
+#endif
+#define STANDARD_CRT0_0_PREFIX LOCALPREFIX "/lib/bcc/i86/"
+#define STANDARD_CRT0_3_PREFIX LOCALPREFIX "/lib/bcc/i386/"
+#define STANDARD_EXEC_PREFIX LOCALPREFIX "/lib/bcc/"
+#define STANDARD_EXEC_PREFIX_2 LOCALPREFIX "/bin/"
+#define DEFAULT_INCLUDE "-I" LOCALPREFIX "/include"
+#define DEFAULT_LIBDIR0 "-L" LOCALPREFIX "/lib/bcc/i86/"
+#define DEFAULT_LIBDIR3 "-L" LOCALPREFIX "/lib/bcc/i386/"
+
+#ifdef CCC
+#undef BCC86
+#undef CC1
+#define CC1 "c386"
+#undef CC1_MINUS_O_BROKEN
+#define CC1_MINUS_O_BROKEN TRUE
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#define STANDARD_CRT0_PREFIX "/usr/local/lib/i386/"
+#endif /* CCC */
+
+#ifdef MC6809
+#undef BAS86
+#undef BCC86
+#undef CRT0
+#undef GCC
+#undef STANDARD_CRT0_0_PREFIX
+#undef STANDARD_CRT0_3_PREFIX
+#undef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX "/usr/local/libexec/m09/bcc/"
+#endif /* MC6809 */
+
+#define ALLOC_UNIT 16 /* allocation unit for arg arrays */
+#define DIRCHAR '/'
+#define START_ARGS 4 /* number of reserved args */
+
+typedef unsigned char bool_T; /* boolean: TRUE if nonzero */
+
+struct arg_s
+{
+ char *prog;
+ bool_T minus_O_broken;
+ int argc;
+ char **argv;
+ unsigned nr_allocated;
+};
+
+struct prefix_s
+{
+ char *name;
+ struct prefix_s *next;
+};
+
+PRIVATE struct arg_s asargs = { AS, };
+PRIVATE struct arg_s ccargs = { CC1, CC1_MINUS_O_BROKEN, };
+PRIVATE struct arg_s cppargs = { CPP, };
+#ifdef ANSI_SUPPORT
+PRIVATE struct arg_s unprotoargs = { UNPROTO, };
+#endif
+#ifdef STANDARD_CRT0_PREFIX
+PRIVATE struct prefix_s crt0_prefix = { STANDARD_CRT0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_0_PREFIX
+PRIVATE struct prefix_s crt0_0_prefix = { STANDARD_CRT0_0_PREFIX, };
+#endif
+#ifdef STANDARD_CRT0_3_PREFIX
+PRIVATE struct prefix_s crt0_3_prefix = { STANDARD_CRT0_3_PREFIX, };
+#endif
+PRIVATE struct prefix_s exec_prefix;
+PRIVATE struct arg_s ldargs = { LD, };
+#ifdef BAS86
+PRIVATE struct arg_s ldrargs = { LD, };
+#endif
+PRIVATE char *progname;
+PRIVATE bool_T runerror; /* = FALSE */
+PRIVATE struct arg_s tmpargs; /* = empty */
+PRIVATE char *tmpdir;
+PRIVATE unsigned verbosity; /* = 0 */
+
+#ifndef DONT_REDECLARE_STDC_FUNCTIONS
+void exit P((int status));
+char *getenv P((const char *name));
+void *malloc P((size_t size));
+void *realloc P((void *ptr, size_t size));
+void (*signal P((int sig, void (*func) P((int sig))))) P((int sig));
+char *strcpy P((char *dest, const char *src));
+size_t strlen P((const char *s));
+char *strrchr P((const char *s, int c));
+#endif
+
+#ifndef DONT_REDECLARE_POSIX_FUNCTIONS
+int access P((const char *path, int amode));
+int execv P((const char *path, char * const *argv));
+pid_t fork P((void));
+pid_t getpid P((void));
+int unlink P((const char *path));
+pid_t wait P((int *status));
+ssize_t write P((int fd, const void *buf, size_t nbytes));
+#endif
+
+int main P((int argc, char **argv));
+
+FORWARD void addarg P((struct arg_s *argp, char *arg));
+FORWARD void addprefix P((struct prefix_s *prefix, char *name));
+FORWARD void fatal P((char *message));
+FORWARD char *fixpath P((char *path, struct prefix_s *prefix, int mode));
+FORWARD void killtemps P((void));
+FORWARD void *my_malloc P((unsigned size, char *where));
+FORWARD char *my_mktemp P((int c_extension));
+FORWARD void my_unlink P((char *name));
+FORWARD void outofmemory P((char *where));
+FORWARD int run P((char *in_name, char *out_name, struct arg_s *argp));
+FORWARD void set_trap P((void));
+FORWARD void show_who P((char *message));
+FORWARD void startarg P((struct arg_s *argp));
+FORWARD char *stralloc P((char *s));
+FORWARD char *stralloc2 P((char *s1, char *s2));
+FORWARD void trap P((int signum));
+FORWARD void unsupported P((char *option, char *message));
+FORWARD void writen P((void));
+FORWARD void writes P((char *s));
+FORWARD void writesn P((char *s));
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ char *arg;
+ int add_default_inc = 1;
+ int add_default_lib = 1;
+ int argcount = argc;
+ bool_T *argdone = my_malloc((unsigned) argc * sizeof *argdone, "argdone");
+ bool_T as_only = FALSE;
+ char *basename;
+#ifdef BCC86
+#ifdef DEFARCH
+ bool_T bits32 = (DEFARCH != 0);
+#else
+ bool_T bits32 = sizeof (char *) >= 4;
+#endif
+ char *bits_arg;
+#endif
+ bool_T cc_only = FALSE;
+#ifdef ANSI_SUPPORT
+ bool_T ansi_pass = FALSE;
+ bool_T quiet_ansi = TRUE;
+#endif
+#ifdef CCC
+ bool_T cpp_pass = TRUE;
+#else
+ bool_T cpp_pass = FALSE;
+#endif
+#ifdef BCC86
+ char *crt0;
+#endif
+ bool_T debug = FALSE;
+ bool_T echo = FALSE;
+ unsigned errcount = 0;
+ char ext;
+ char *f_out = NUL_PTR;
+ bool_T float_emulation = FALSE;
+#ifdef BAS86
+ bool_T gnu_objects = FALSE;
+#endif
+ char *in_name;
+ int length;
+ unsigned ncisfiles = 0;
+ unsigned nifiles = 0;
+ unsigned npass_specs;
+ bool_T optimize = FALSE;
+ char *out_name;
+ bool_T profile = FALSE;
+ bool_T prep_only = FALSE;
+ bool_T prep_line_numbers = FALSE;
+ int status;
+ char *temp;
+
+ progname = argv[0];
+ addarg(&cppargs, CPPFLAGS);
+#ifdef CCC
+ addarg(&asargs, "-j");
+#endif
+ addarg(&asargs, "-u");
+ addarg(&asargs, "-w");
+#ifdef BCC86
+ addarg(&ldargs, "-i");
+#endif
+#ifdef BAS86
+ addarg(&ldrargs, "-r");
+#endif
+
+ /* Pass 1 over argv to gather compile options. */
+ for (; --argc != 0;)
+ {
+ arg = *++argv;
+ *++argdone = TRUE;
+ if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0)
+ switch (arg[1])
+ {
+#ifdef BCC86
+ case '0':
+ bits32 = FALSE;
+ break;
+ case '3':
+ bits32 = TRUE;
+ break;
+#endif
+ case 'E':
+ prep_only = prep_line_numbers = cpp_pass = TRUE;
+ break;
+#ifdef BAS86
+ case 'G':
+ gnu_objects = TRUE;
+ break;
+#endif
+ case 'P':
+ prep_only = cpp_pass = TRUE;
+ prep_line_numbers = FALSE;
+ break;
+ case 'O':
+ optimize = TRUE; /* unsupported( arg, "optimize" ); */
+ break;
+ case 'S':
+ cc_only = TRUE;
+ break;
+ case 'V':
+ echo = TRUE;
+ break;
+ case 'c':
+ as_only = TRUE;
+ break;
+ case 'e':
+ cpp_pass = TRUE;
+ break;
+ case 'f':
+ float_emulation = TRUE;
+ ++errcount;
+ unsupported(arg, "float emulation");
+ break;
+ case 'g':
+ debug = TRUE; /* unsupported( arg, "debug" ); */
+ break;
+ case 'o':
+ if (--argc < 1)
+ {
+ ++errcount;
+ show_who("output file missing after -o\n");
+ }
+ else
+ {
+ if (f_out != NUL_PTR)
+ show_who("more than one output file\n");
+ f_out = *++argv;
+ *++argdone = TRUE;
+ }
+ break;
+ case 'p':
+ profile = TRUE;
+ ++errcount;
+ unsupported(arg, "profile");
+ break;
+ case 'v':
+ ++verbosity;
+#ifdef ANSI_SUPPORT
+ quiet_ansi=FALSE;
+#endif
+ break;
+ case 'I':
+ add_default_inc = 0;
+ break;
+ case 'L':
+ add_default_lib = 0;
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else if (arg[0] == '-')
+ switch (arg[1])
+ {
+#ifdef ANSI_SUPPORT
+ case 'a':
+ if (!strcmp(arg, "-ansi"))
+ {
+ ansi_pass=TRUE;
+#if 0
+#ifndef CCC
+ addarg(&ccargs, "-D__STDC__=1");
+#endif
+ addarg(&cppargs, "-D__STDC__=1");
+#endif
+ }
+ break;
+#endif
+ case 'A':
+ addarg(&asargs, arg + 2);
+ break;
+ case 'B':
+ addprefix(&exec_prefix, arg + 2);
+ break;
+ case 'C':
+ addarg(&ccargs, arg + 2);
+ break;
+ case 'D':
+ case 'I':
+ case 'U':
+#ifndef CCC
+ addarg(&ccargs, arg);
+#endif
+ addarg(&cppargs, arg);
+ break;
+ case 'X':
+ addarg(&ldargs, arg + 2);
+ break;
+ case 'L':
+ addarg(&ldargs, arg);
+ break;
+ case 'P':
+ addarg(&cppargs, arg + 2);
+ break;
+#ifdef CCC
+ case 'Q':
+ addarg(&ccargs, arg);
+ break;
+#endif
+ case 'T':
+ tmpdir = arg + 2;
+ break;
+ case 't':
+ ++errcount;
+ unsupported(arg, "pass number");
+ break;
+ default:
+ *argdone = FALSE;
+ break;
+ }
+ else
+ {
+ ++nifiles;
+ *argdone = FALSE;
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ ++ncisfiles;
+ }
+ }
+ npass_specs = prep_only + cc_only + as_only;
+ if (npass_specs != 0)
+ {
+ if (npass_specs > 1)
+ {
+ ++errcount;
+ show_who("more than 1 option from -E -P -S -c\n");
+ }
+ if (f_out != NUL_PTR && ncisfiles > 1)
+ {
+ ++errcount;
+ show_who("cannot have more than 1 input with non-linked output\n");
+ }
+ }
+ if (nifiles == 0)
+ {
+ ++errcount;
+ show_who("no input files\n");
+ }
+ if (errcount != 0)
+ exit(1);
+
+ if ((temp = getenv("BCC_EXEC_PREFIX")) != NUL_PTR)
+ addprefix(&exec_prefix, temp);
+ if( add_default_inc )
+ {
+#ifndef CCC
+ addarg(&ccargs, DEFAULT_INCLUDE);
+#endif
+ addarg(&cppargs, DEFAULT_INCLUDE);
+ }
+ if( add_default_lib )
+ {
+#ifdef BCC86
+ if( bits32 )
+ addarg(&ldargs, DEFAULT_LIBDIR3);
+ else
+#endif
+ addarg(&ldargs, DEFAULT_LIBDIR0);
+ }
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX);
+ addprefix(&exec_prefix, STANDARD_EXEC_PREFIX_2);
+ cppargs.prog = fixpath(cppargs.prog, &exec_prefix, X_OK);
+ ccargs.prog = fixpath(ccargs.prog, &exec_prefix, X_OK);
+ asargs.prog = fixpath(asargs.prog, &exec_prefix, X_OK);
+ ldargs.prog = fixpath(ldargs.prog, &exec_prefix, X_OK);
+ ldrargs.prog = fixpath(ldrargs.prog, &exec_prefix, X_OK);
+#ifdef ANSI_SUPPORT
+ unprotoargs.prog=fixpath(unprotoargs.prog, &exec_prefix, X_OK);
+#endif
+ if (tmpdir == NUL_PTR && (tmpdir = getenv("TMPDIR")) == NUL_PTR)
+ tmpdir = "/tmp";
+
+ if (prep_only && !prep_line_numbers)
+ addarg(&cppargs, "-P");
+#ifdef BCC86
+ if (bits32)
+ {
+ bits_arg = "-3";
+ crt0 = fixpath(CRT0, &crt0_3_prefix, R_OK);
+ }
+ else
+ {
+ bits_arg = "-0";
+ crt0 = fixpath(CRT0, &crt0_0_prefix, R_OK);
+ }
+ addarg(&ccargs, bits_arg);
+ addarg(&cppargs, bits_arg);
+ addarg(&asargs, bits_arg);
+#ifdef BAS86
+ if (!gnu_objects)
+ {
+ addarg(&ldargs, bits_arg);
+ addarg(&ldrargs, bits_arg);
+ /* addarg(&ldargs, crt0);*/
+ addarg(&ldargs, "-C0");
+ }
+#endif /* BAS86 */
+#endif /* BCC86 */
+#if defined(BAS86) && !defined(BCC86)
+ if (!gnu_objects)
+ addarg(&ldargs, fixpath(CRT0, &crt0_prefix, R_OK));
+#endif
+ set_trap();
+
+ /* Pass 2 over argv to compile and assemble .c, .i, .S and .s files and
+ * gather arguments for linker.
+ */
+ for (argv -= (argc = argcount) - 1, argdone -= argcount - 1; --argc != 0;)
+ {
+ arg = *++argv;
+ if (!*++argdone)
+ {
+ length = strlen(arg);
+ if (length >= 2 && arg[length - 2] == '.'
+ && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S'
+ || ext == 's'))
+ {
+ if (echo || verbosity != 0)
+ {
+ writes(arg);
+ writesn(":");
+ }
+ if ((basename = strrchr(arg, DIRCHAR)) == NUL_PTR)
+ basename = arg;
+ else
+ ++basename;
+ in_name = arg;
+ if (ext == 'c')
+ {
+#ifdef ANSI_SUPPORT
+ /* If this was done between CPP and CC1 then
+ * we could define __STDC__
+ */
+ if (ansi_pass)
+ {
+ char *old_tmpdir;
+ struct arg_s cpargs = { CP, TRUE, };
+
+ old_tmpdir=tmpdir;
+ tmpdir=".";
+ out_name=my_mktemp(TRUE);
+ tmpdir=old_tmpdir;
+ run(in_name, out_name, &cpargs);
+
+ addarg(&unprotoargs, out_name);
+ addarg(&unprotoargs, "-N");
+ if (quiet_ansi)
+ addarg(&unprotoargs, "-q");
+ run(NUL_PTR, NUL_PTR, &unprotoargs);
+ in_name=out_name;
+ }
+#endif
+ if (cpp_pass)
+ {
+ if (prep_only)
+ out_name = f_out;
+ else
+ out_name = my_mktemp(FALSE);
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+ }
+ ext = 'i';
+ }
+ if (ext == 'i')
+ {
+ if (prep_only)
+ continue;
+ if (cc_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp(FALSE);
+ if (run(in_name, out_name, &ccargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 'S')
+ {
+ if (prep_only)
+ out_name = f_out;
+ else if (cc_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 's';
+ }
+ }
+ else
+ out_name = my_mktemp(FALSE);
+ if (run(in_name, out_name, &cppargs) != 0)
+ continue;
+ in_name = out_name;
+ ext = 's';
+ }
+ if (ext == 's')
+ {
+ if (prep_only || cc_only)
+ continue;
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ if (as_only)
+ {
+ if (f_out != NUL_PTR)
+ out_name = f_out;
+ else
+ {
+ out_name = stralloc(basename);
+ out_name[strlen(out_name) - 1] = 'o';
+ }
+ }
+ else
+ out_name = my_mktemp(FALSE);
+ addarg(&asargs, "-n");
+ arg[length - 1] = 's';
+ addarg(&asargs, arg);
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ char *tmp_out_name;
+
+ tmp_out_name = my_mktemp(FALSE);
+ status = run(in_name, tmp_out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ if (run(tmp_out_name, out_name, &ldrargs) != 0)
+ continue;
+ }
+ else
+#endif
+ {
+ status = run(in_name, out_name, &asargs);
+ asargs.argc -= 2;
+ if (status != 0)
+ continue;
+ }
+ ext = 'o';
+ in_name = out_name;
+ }
+ if (ext == 'o')
+ {
+ if (prep_only || cc_only || as_only)
+ continue;
+ addarg(&ldargs, in_name);
+ }
+ }
+ else
+ addarg(&ldargs, arg);
+ }
+ }
+
+ if (!prep_only && !cc_only && !as_only && !runerror)
+ {
+ if (f_out == NUL_PTR)
+ f_out = "a.out";
+#ifdef BAS86
+ if (gnu_objects)
+ {
+ /* Remove -i and -i-. */
+ for (argc = ldargs.argc - 1; argc >= START_ARGS; --argc)
+ {
+ arg = ldargs.argv[argc];
+ if (arg[0] == '-' && arg[1] == 'i'
+ && (arg[2] == 0 || (arg[2] == '-' && arg[3] == 0)))
+ {
+ --ldargs.argc;
+ memmove(ldargs.argv + argc, ldargs.argv + argc + 1,
+ (ldargs.argc - argc) * sizeof ldargs.argv[0]);
+ ldargs.argv[ldargs.argc] = NUL_PTR;
+ }
+ }
+
+ ldargs.prog = fixpath(GCC, &exec_prefix, X_OK);
+ run((char *) NUL_PTR, f_out, &ldargs);
+ }
+ else
+#endif
+ {
+ addarg(&ldargs, "-lc");
+ run((char *) NUL_PTR, f_out, &ldargs);
+ }
+ }
+ killtemps();
+ return runerror ? 1 : 0;
+}
+
+PRIVATE void addarg(argp, arg)
+register struct arg_s *argp;
+char *arg;
+{
+ int new_argc;
+ char **new_argv;
+
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ new_argc = argp->argc + 1;
+ if (new_argc >= argp->nr_allocated)
+ {
+ argp->nr_allocated += ALLOC_UNIT;
+ new_argv = realloc(argp->argv, argp->nr_allocated * sizeof *argp->argv);
+ if (new_argv == NUL_PTR)
+ outofmemory("addarg");
+ argp->argv = new_argv;
+ }
+ argp->argv[argp->argc] = arg;
+ argp->argv[argp->argc = new_argc] = NUL_PTR;
+}
+
+PRIVATE void addprefix(prefix, name)
+struct prefix_s *prefix;
+char *name;
+{
+ struct prefix_s *new_prefix;
+
+ if (prefix->name == NUL_PTR)
+ prefix->name = name;
+ else
+ {
+ new_prefix = my_malloc(sizeof *new_prefix, "addprefix");
+ new_prefix->name = name;
+ new_prefix->next = NUL_PTR;
+ while (prefix->next != NUL_PTR)
+ prefix = prefix->next;
+ prefix->next = new_prefix;
+ }
+}
+
+PRIVATE void fatal(message)
+char *message;
+{
+ writesn(message);
+ killtemps();
+ exit(1);
+}
+
+PRIVATE char *fixpath(path, prefix, mode)
+char *path;
+struct prefix_s *prefix;
+int mode;
+{
+ char *ppath;
+
+ for (; prefix != NUL_PTR; prefix = prefix->next)
+ {
+ if (verbosity > 2)
+ {
+ show_who("searching for ");
+ if (mode == R_OK)
+ writes("readable file ");
+ else
+ writes("executable file ");
+ writes(path);
+ writes(" in ");
+ writesn(prefix->name);
+ }
+ ppath = stralloc2(prefix->name, path);
+ if (access(ppath, mode) == 0)
+ return ppath;
+ free(ppath);
+ }
+ return path;
+}
+
+PRIVATE void killtemps()
+{
+ while (tmpargs.argc > START_ARGS)
+ my_unlink(tmpargs.argv[--tmpargs.argc]);
+}
+
+PRIVATE void *my_malloc(size, where)
+unsigned size;
+char *where;
+{
+ void *block;
+
+ if ((block = malloc(size)) == NUL_PTR)
+ outofmemory(where);
+ return block;
+}
+
+PRIVATE char *my_mktemp(c_extension)
+int c_extension;
+{
+ char *p;
+ unsigned digit;
+ unsigned digits;
+ char *template;
+ static unsigned tmpnum;
+
+ if (c_extension)
+ {
+ p = template = stralloc2(tmpdir, "/bccYYYYXXXX.c");
+ p += strlen(p) - 2;
+ }
+ else
+ {
+ p = template = stralloc2(tmpdir, "/bccYYYYXXXX");
+ p += strlen(p);
+ }
+
+ digits = getpid();
+ while (*--p == 'X')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p = digit + '0';
+ digits /= 16;
+ }
+ digits = tmpnum;
+ while (*p == 'Y')
+ {
+ if ((digit = digits % 16) > 9)
+ digit += 'A' - ('9' + 1);
+ *p-- = digit + '0';
+ digits /= 16;
+ }
+ ++tmpnum;
+ addarg(&tmpargs, template);
+ return template;
+}
+
+PRIVATE void my_unlink(name)
+char *name;
+{
+ if (verbosity > 1)
+ {
+ show_who("unlinking ");
+ writesn(name);
+ }
+ if (unlink(name) < 0)
+ {
+ show_who("error unlinking ");
+ writesn(name);
+ }
+}
+
+PRIVATE void outofmemory(where)
+char *where;
+{
+ show_who("out of memory in ");
+ fatal(where);
+}
+
+PRIVATE int run(in_name, out_name, argp)
+char *in_name;
+char *out_name;
+struct arg_s *argp;
+{
+ int arg0;
+ int i;
+ int status;
+
+ arg0 = 0;
+ if (in_name == NUL_PTR)
+ ++arg0;
+ if (out_name == NUL_PTR)
+ arg0 += 2;
+ else if (argp->minus_O_broken)
+ ++arg0;
+ if (argp->nr_allocated == 0)
+ startarg(argp);
+ argp->argv[arg0] = argp->prog;
+ i = arg0 + 1;
+ if (in_name != NUL_PTR)
+ argp->argv[i++] = in_name;
+ if (out_name != NUL_PTR)
+ {
+ if (!argp->minus_O_broken)
+ argp->argv[i++] = "-o";
+ argp->argv[i++] = out_name;
+ }
+ if (verbosity != 0)
+ {
+ for (i = arg0; i < argp->argc; ++i)
+ {
+ writes(argp->argv[i]);
+ writes(" ");
+ }
+ writen();
+ }
+ switch (fork())
+ {
+ case -1:
+ show_who("fork failed");
+ fatal("");
+ case 0:
+ execv(argp->prog, argp->argv + arg0);
+ show_who("exec of ");
+ writes(argp->prog);
+ fatal(" failed");
+ default:
+ wait(&status);
+ for (i = tmpargs.argc - 1; i >= START_ARGS; --i)
+ if (in_name == tmpargs.argv[i])
+ {
+ my_unlink(in_name);
+ --tmpargs.argc;
+ memmove(tmpargs.argv + i, tmpargs.argv + i + 1,
+ (tmpargs.argc - i) * sizeof tmpargs.argv[0]);
+ tmpargs.argv[tmpargs.argc] = NUL_PTR;
+ break;
+ }
+ if (status != 0)
+ {
+ killtemps();
+ runerror = TRUE;
+ }
+ return status;
+ }
+}
+
+PRIVATE void set_trap()
+{
+#ifndef NORDB
+#ifdef SIGINT
+ signal(SIGINT, trap);
+#endif
+#ifdef SIGQUIT
+ signal(SIGQUIT, trap);
+#endif
+
+#else
+ /* This is being too trap happy! */
+#ifndef _NSIG
+#define _NSIG NSIG
+#endif
+ int signum;
+
+ for (signum = 0; signum <= _NSIG; ++signum)
+#ifdef SIGCHLD
+ if (signum != SIGCHLD)
+#endif
+ if (signal(signum, SIG_IGN) != SIG_IGN)
+ signal(signum, trap);
+#endif
+}
+
+PRIVATE void show_who(message)
+char *message;
+{
+ writes(progname);
+ writes(": ");
+ writes(message);
+}
+
+PRIVATE void startarg(argp)
+struct arg_s *argp;
+{
+ argp->argv = my_malloc((argp->nr_allocated = ALLOC_UNIT)
+ * sizeof *argp->argv, "startarg");
+ argp->argc = START_ARGS;
+ argp->argv[START_ARGS] = NUL_PTR;
+}
+
+PRIVATE char *stralloc(s)
+char *s;
+{
+ return strcpy(my_malloc(strlen(s) + 1, "stralloc"), s);
+}
+
+PRIVATE char *stralloc2(s1, s2)
+char *s1;
+char *s2;
+{
+ return strcat(strcpy(my_malloc(
+ strlen(s1) + strlen(s2) + 1, "stralloc2"), s1), s2);
+}
+
+PRIVATE void trap(signum)
+int signum;
+{
+ signal(signum, SIG_IGN);
+ show_who("caught signal");
+ fatal("");
+}
+
+PRIVATE void unsupported(option, message)
+char *option;
+char *message;
+{
+ show_who("compiler option ");
+ writes(option);
+ writes(" (");
+ writes(message);
+ writesn(") not supported yet");
+}
+
+PRIVATE void writen()
+{
+ writes("\n");
+}
+
+PRIVATE void writes(s)
+char *s;
+{
+ write(2, s, strlen(s));
+}
+
+PRIVATE void writesn(s)
+char *s;
+{
+ writes(s);
+ writen();
+}
diff --git a/bcc/bcc.doc b/bcc/bcc.doc
new file mode 100644
index 0000000..1c5e930
--- /dev/null
+++ b/bcc/bcc.doc
@@ -0,0 +1,177 @@
+bcc options
+-----------
+
+bcc [-03EGOPSVcegv] [-Aas_option] [-Bexecutable_prefix] [-Ccc1_option]
+ [-Ddefine] [-Iinclude_dir] [-Lld_option] [-Qc386_option] [-Ttmpdir]
+ [-Uundef] [-o outfile] [-fpt error] [ld_options] [infiles]
+
+The 6809 version does not support -0, -3 or -G.
+Only the c386 version supports -Q.
+
+defaults (off or none except for these):
+-03 native
+outfile stdout for preprocessor output
+ somewhere/file.[ci] -> file.s for compiler output
+ somewhere/file.[cis] -> file.o for assembler output
+ a.out for ld output
+
+-ansi Pass the source through '/usr/bin/unprotoize' first
+-0 8086 target (works even on 80386 host)
+-3 80386 target (works even on 8086 host)
+-A pass remainder of option to assembler (e.g. -A-l -Alistfile for a listing)
+-B prefix for executable search path (as usual; the search order is all paths
+ specified using -B, in order, then the path given in the environment
+ variable BCC_EXEC_PREFIX if that is set, then the compiled-in defaults
+ (something like /usr/libexec/i386/bcc/ followed by /usr/bin/))
+-C pass remainder of option to cc1 (e.g. -C-c for caller-saves)
+-D define (as usual)
+-E produce preprocessor output (as usual)
+-G produce gnu-Minix objects (link with gnu ld)
+-Ix include search path (as usual)
+-I don't add default include to search list
+-Lx add dir name x to the head of the list of library dirs searched
+-L don't add default library to search list
+-X pass remainder of option to linker
+-O optimize (does nothing)
+-P produce preprocessor output with no line numbers (as usual)
+-Q pass full option to c386
+-S produce assembler file (as usual)
+-T temporary directory (overrides previous value and default; default is
+ from the environment variable TMPDIR if that is set, otherwise /tmp)
+-U undefine (as usual)
+-V print names of files being compiled
+-c produce object file (as usual)
+-e run the preprocess pass separately. This takes less memory, and may help
+ or harm by giving more traditional semantics like token pasting with /**/.
+-f error (float emulation not supported)
+-g produce debugging info (does nothing)
+-o output file name follows (assembler, object or executable) (as usual)
+-p error (profiling not supported)
+-t error (substitution of some cc passes not supported)
+-v print names and args of subprocesses being run. Two or more -v's:
+ print names of files being unlinked. Three or more -v's:
+ print names of paths being searched.
+
+Other options are passed to the linker, in particular -i-, -lx, -M, -m, -s.
+The -i option is always passed to the linker but can be cancelled using -i-.
+
+This is supposed to match the V7 manual except for -0, -3, -A, -C, -G, -L,
+-T, -V, -e, -v and where not supported.
+
+cc1 options
+----------
+
+cc1 [-03EPcdfltw[-]] [-Ddefine] [-Iinclude_dir] [-Uundef] [-o outfile] [infile]
+
+The 6809 version does not support -0 or -3 but it supports -p.
+
+defaults (off or none except for these):
+-03 native
+-c on for 6809
+-f on for 6809
+outfile stdout
+infile stdin
+
+-0 8086 target (works even on 80386 host)
+-3 80386 target (works even on 8086 host)
+-D define (as usual)
+-E produce preprocessor output (as usual)
+-I include search path (as usual)
+-P produce preprocessor output with no line numbers (as usual)
+-c produce code with caller saving regs before function calls
+-d print debugging information in assembly output
+-f produce code with 1st argument passed in a register
+-l produce code for 2 3 1 0 long byte order (only works in 16-bit versions)
+-o assembler output file name follows
+-p produce (almost) position-independent code
+-t print source code in assemby output
+-w print what cc1 thinks is the location counter in assembly output
+
+All the options except -D, -I and -o may be turned off by following the
+option letter by a '-'. Options are processed left to right so the last
+setting has precedence.
+
+The following is defined before option processing:
+
+__BCC__ 1
+
+The following may be defined after option processing:
+
+__AS09__ 1 if 6809 version
+__AS386_16__ 1 if -0 option on 80*86
+__AS386_32__ 1 if -3 option on 80*86
+__CALLER_SAVES__ 1 if -c option
+__FIRST_ARG_IN_AX__ 1 if -f option on 80*86
+__FIRST_ARG_IN_X__ 1 if -f option on 6809
+__LONG_BIG_ENDIAN__ 1 if -l option
+__POS_INDEPENDENT__ 1 if -p option on 6809
+
+The following are standard builtins:
+
+__FILE__ stringized name of current input file
+__LINE__ current line number
+
+as options
+----------
+
+as [-03agjuw] [-b [bin]] [-lm [list]] [-n name] [-o obj] [-s sym] src
+
+The 6809 version does not support -0, -3, -a or -j.
+
+defaults (off or none except for these; no output is produced without a flag):
+-03 native
+list stdout (beware of clobbering next arg)
+name basename of the source name
+
+-0 start with 16-bit code segment
+-3 start with 32-bit code segment
+-a enable partial compatibility with asld
+-b produce binary file, filename may follow (obsolete)
+-g only put global symbols in object file
+-j force all jumps to be long
+-l produce list file, filename may follow
+-m print macro expansions in listing
+-n name of module follows (goes in object instead of source name)
+-o produce object file, filename follows
+-s produce symbol file, filename follows (obsolete)
+-u take undefined symbols as imported-with-unspecified segment
+-w don't print warnings
+
+The -u and -w options are perhaps back to front because they are needed for
+cc1 output and Minix's make does the wrong thing with .s files left around.
+However, all assembler code not written by compilers should assemble with
+them turned off.
+
+ld options
+----------
+
+ld [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]
+ [-Llibdir] [-Olibfile] [-T textaddr] infile...
+
+The version that produces old Minix a.out format does not support -r.
+
+The 6809 version does not support -i or -r.
+
+defaults (off or none except for these):
+-03 native
+-L/usr/local/lib/m/ (m is machine-dependent)
+outfile a.out
+
+-0 produce header with 16-bit magic and use library subdir i86 for -lx
+-3 produce header with 32-bit magic and use library subdir i386 for -lx
+-Cx add file libdir-from-search/crtx.o to list of files linked
+-Lx add dir name x to the head of the list of library dirs searched
+-M print symbols linked on stdout
+-Ox add library libdir-from-search/x to list of files linked
+-T text base address follows (in format suitable for strtoul)
+-i separate I&D output
+-lx add library libdir-from-search/libx.a to list of files linked
+-m print modules linked on stdout
+-o output file name follows
+-r produce output suitable for further relocation
+-s strip symbols
+-t trace modules being looked at on stdout
+-z produce "unmapped zero page" executables
+
+All the options not taking an argument may be turned off by following the
+option letter by a '-', as for cc1.
diff --git a/bcc/byteord.h b/bcc/byteord.h
new file mode 100644
index 0000000..e7b19e0
--- /dev/null
+++ b/bcc/byteord.h
@@ -0,0 +1,13 @@
+/* byteord.h - byte order dependencies for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef I8088
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 1 /* longs are back to front for Xenix */
+#endif
+
+#ifdef MC6809
+# define BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
diff --git a/bcc/codefrag.c b/bcc/codefrag.c
new file mode 100644
index 0000000..e42b05b
--- /dev/null
+++ b/bcc/codefrag.c
@@ -0,0 +1,1843 @@
+/* codefrag.c - code fragments for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "label.h"
+#include "output.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+
+#define DEFSTR_BYTEMAX 10
+#define DEFSTR_DELIMITER '"'
+#define DEFSTR_STRINGMAX 40
+#define EOS_TEXT '0'
+#define MAXPRINTCHAR '~'
+#define MINPRINTCHAR ' '
+
+/* segment numbers */
+
+#ifdef I8088
+# define CSEG 0
+# define outcseg() outop0str(".text\n")
+# define DSEG 1
+# define outdseg() outop0str(".data\n")
+# define BSSSEG 2
+# define outbssseg() outop0str(".bss\n")
+#endif
+
+#ifdef MC6809
+# define CSEG 0
+# define outcseg() outop0str("LOC\t0\n")
+# define DPSEG 2
+# define outdpseg() outop0str("LOC\t2\n")
+# define DSEG 3
+# define outdseg() outop0str("LOC\t3\n")
+# define STRSEG 1
+# define outstrseg() outop0str("LOC\t1\n")
+#endif
+
+#ifdef I8088
+FORWARD void adjcarry P((void));
+#endif
+FORWARD void clr P((store_pt reg));
+FORWARD bool_pt lowregisDreg P((void));
+#ifdef I8088
+FORWARD void outand P((void));
+FORWARD void outequate P((void));
+# ifdef XENIX_AS
+FORWARD void outexport P((void));
+# endif
+FORWARD void outmovsx P((void));
+FORWARD void outmovzx P((void));
+FORWARD void tfrhilo P((void));
+FORWARD void tfrlohi P((void));
+#endif
+#ifdef MC6809
+FORWARD void negBsbcA P((void));
+#endif
+FORWARD void outaccum P((void));
+FORWARD void outstackreg P((void));
+FORWARD void opregadr P((void));
+
+/* operator and miscellaneous strings */
+
+#ifdef I8088
+
+# define ACCHISTR "ah"
+# define ANDSTRING "and\t"
+# define DEFSTR_QUOTER '\\'
+# define EORSTRING "xor\t"
+# define MAX_INLINE_SHIFT 2 /* better 3 for 88, 1 for 186 and above */
+# define ORSTRING "or\t"
+# define TARGET_FIRST
+# define addfactor(reg) (outadd(), outregname(reg), outncregname(DXREG))
+# define defstorage() outop0str(".blkb\t")
+# define extBnegD() (ctoi(), negDreg())
+# define finishfactor() /* save/add/subfactor() ended already */
+# define outadc() outop3str("adc\t")
+# define outandac() (outand(), outaccum(), bumplc())
+# define outandlo() (outand(), outstr(acclostr))
+# define outbimmed() outbyte('*')
+# define outcommon() outop0str(".comm\t")
+# define outcwd() outnop1str("cwd")
+# define outdefstr() outop0str(".ascii\t\"")
+# define outexchange() outop1str("xchg\t")
+# define outglobl() outop0str(".globl\t")
+# ifdef XENIX_AS
+# define outimport() outexport()
+# else
+# define outexport() outop0str("export\t")
+# define outimport() outop0str("import\t")
+# endif
+# ifdef XENIX_AS
+# define outj1switch() outop3str("seg\tcs\nbr\t@");
+# else
+# define outj1switch() outop3str("seg\tcs\nbr\t");
+# endif
+# define outj2switch() \
+ (outindleft(), outstr(ireg0str), outindright(), bumplc2(), outnl())
+# define outlcommon() outop0str("\tlcomm\t")
+# define outlswitch() (outload(), outstr(ireg0str), outncregname(DREG))
+# define outnc1() outnstr(",*1")
+# define outsbc() outop3str("sbb\t")
+# define outset() outstr ("\tset\t")
+# define outsl() outop2str("shl\t")
+# define outsr() outop2str("sar\t")
+# define outtransfer() outload()
+# define outusr() outop2str("shr\t")
+# define outxor() outop2str(EORSTRING)
+# define reclaimfactor() /* factor in DXREG, DXREG now junk */
+# define savefactor(reg) regtransfer((reg), DXREG)
+# define smiDreg() (outcwd(), regexchange(DREG, DXREG))
+# define sr1() (outsr(), outaccum(), outnc1())
+# define subfactor(reg) (outsub(), outregname(reg), outncregname(DXREG))
+# define usr1() (outusr(), outaccum(), outnc1())
+PRIVATE void adjcarry()
+{
+ outop3str("rcl\t");
+ outregname(DXREG);
+ outncimmadr((offset_t) 9);
+ outand();
+ bumplc2();
+ bumplc2();
+ outregname(DXREG);
+ outncimmadr((offset_t) 0x100);
+}
+PUBLIC void clrBreg()
+{
+ outxor();
+ outstr(acclostr);
+ outncregname(BREG);
+}
+PUBLIC void comment()
+{
+ outstr("! ");
+}
+PUBLIC void ctoi()
+{
+ if (i386_32)
+ {
+ outmovzx();
+ outaccum();
+ outncregname(BREG);
+ }
+ else
+ {
+ outxor();
+ outhiaccum();
+ outcomma();
+ outhiaccum();
+ outnl();
+ }
+}
+PUBLIC void defbyte()
+{
+ outop0str(".byte\t");
+}
+#ifdef XENIX_AS
+PUBLIC void defword()
+{
+} /* don't have to print ".word\t" */
+#else
+PUBLIC void defword()
+{
+ outop0str(".word\t");
+}
+#endif
+PUBLIC void defdword()
+{
+ outop0str("dd\t");
+}
+PUBLIC void even()
+{
+ outop0str(".even\n");
+}
+PUBLIC void negDreg()
+{
+ outop2str("neg\t");
+ outnregname(DREG);
+}
+PUBLIC void comDreg()
+{
+ outop2str("not\t");
+ outnregname(DREG);
+}
+PUBLIC void outadd()
+{
+ outop2str("add\t");
+}
+PUBLIC void outaddsp()
+{
+ outadd();
+ outstackreg();
+ outcomma();
+ outimmed();
+ bumplc2();
+}
+PRIVATE void outand()
+{
+ outop2str(ANDSTRING);
+}
+#ifdef XENIX_AS
+PUBLIC void outcalladr()
+{
+ outop2str("call\t@");
+}
+#else
+PUBLIC void outcalladr()
+{
+ outop2str("call\t");
+}
+#endif
+PUBLIC void outcmp()
+{
+ outop2str("cmp\t");
+}
+PUBLIC void outdec()
+{
+ outop1str("dec\t");
+}
+PUBLIC void outdword()
+{
+ outstr("dword ");
+}
+PRIVATE void outequate()
+{
+ outop0str("\t=\t");
+}
+#ifdef XENIX_AS
+PRIVATE void outexport()
+{
+ outop0str(".globl\t");
+}
+#endif
+PUBLIC void outfail()
+{
+ outop0str(".fail\t");
+}
+PUBLIC void outinc()
+{
+ outop1str("inc\t");
+}
+#ifdef XENIX_AS
+PUBLIC void outindleft()
+{
+ outbyte('(');
+}
+PUBLIC void outindright()
+{
+ outbyte(')');
+}
+#else
+PUBLIC void outindleft()
+{
+ outbyte('[');
+}
+PUBLIC void outindright()
+{
+ outbyte(']');
+}
+#endif
+#ifndef FRAMEPOINTER
+PUBLIC void outindstackreg()
+{
+ outindleft();
+ outregname(STACKREG);
+ outindright();
+}
+#endif
+PUBLIC void outldaccum()
+{
+ outload();
+ outaccum();
+ outcomma();
+}
+PUBLIC void outldmulreg()
+{
+ outload();
+ outregname(MULREG);
+ outcomma();
+}
+PUBLIC void outlea()
+{
+ outop2str("lea\t");
+}
+PUBLIC void outleasp()
+{
+ outlea();
+ outstackreg();
+ outcomma();
+}
+PUBLIC void outload()
+{
+ outop2str("mov\t");
+}
+PRIVATE void outmovsx()
+{
+ outop3str("movsx\t");
+}
+PRIVATE void outmovzx()
+{
+ outop3str("movzx\t");
+}
+PUBLIC void outmulmulreg()
+{
+ outop2str("mul\t");
+ outnregname(MULREG);
+}
+PUBLIC void outopsep()
+{
+ outcomma();
+}
+PUBLIC void outpshs()
+{
+ outop1str("push");
+}
+PUBLIC void outpuls()
+{
+ outop1str("pop");
+}
+PUBLIC void outreturn()
+{
+ outnop1str("ret");
+}
+PUBLIC void outstore()
+{
+ outload();
+}
+PUBLIC void outsub()
+{
+ outop2str("sub\t");
+}
+PUBLIC void outtest()
+{
+ outop2str("test\t");
+}
+PUBLIC void outword()
+{
+ outstr("word ");
+}
+PUBLIC void sctoi()
+{
+ if (i386_32)
+ {
+ outmovsx();
+ outncregname(BREG);
+ }
+ else
+ outnop1str("cbw");
+}
+PUBLIC void stoi()
+{
+ outnop1str("cwde");
+}
+PRIVATE void tfrhilo()
+{
+ outload();
+ outstr(acclostr);
+ outcomma();
+ outhiaccum();
+ outnl();
+}
+PRIVATE void tfrlohi()
+{
+ outload();
+ outhiaccum();
+ outncregname(BREG);
+}
+PUBLIC void ustoi()
+{
+ outmovzx();
+ outaccum();
+ outcomma();
+ outshortregname(DREG);
+ outnl();
+}
+#endif /* I8088 */
+
+#ifdef MC6809
+
+# define ACCHISTR "A"
+# define ANDSTRING "AND"
+# define DEFSTR_QUOTER '"'
+# define EORSTRING "EOR"
+# define MAX_INLINE_SHIFT 16
+# define ORSTRING "OR"
+# define addfactor(reg) outop2str("ADDD\t,S")
+# define defstorage() outop0str("RMB\t")
+# define extBnegD() (ctoi(), negBsbcA())
+# define finishfactor() outnl()
+# define outadc() outop2str("ADC")
+# define outandhi() outop2str("ANDA")
+# define outandlo() outop2str("ANDB")
+# define outcommon() outop0str("\tCOMM\t")
+# define outdefstr() outop0str("FCC\t\"")
+# define outequate() outop0str("\tEQU\t")
+# define outexchange() outop2str("EXG\t")
+# define outexport() outop0str("EXPORT\t")
+# define outglobl() outop0str("GLOBL\t")
+# define outimport() outop0str("IMPORT\t")
+# define outjswitch() outnop2str("JMP\t[D,X]")
+# define outlcommon() outop0str("\tLCOMM\t")
+# define outlswitch() outop3str("LDX\t#")
+# define outpijswitch() outnop2str("JMP\tD,X")
+# define outpil1switch() outop3str("LEAX\t<")
+# define outpil2switch() outnop2str("LDD\tD,X")
+# define outrolhi() outnop1str("ROLA");
+# define outsbc() outop2str("SBC")
+# define outset() outstr ("\tSET\t")
+# define outsl() outop1str("LSL")
+# define outtransfer() outop2str("TFR\t")
+# define reclaimfactor() outnstr ("++") /* discard factor from stack */
+# define savefactor(reg) outop2str("PSHS\tD")
+# define smiDreg() (clrBreg(), outnop1str("ROLA"), \
+ outnop2str("SBCB\t#0"), sctoi())
+ /* this tricky sequence is twice as fast as TFR A,B; SEX; TFR A,B */
+ /* it gets the sign bit of A in the carry */
+ /* then subtracts it from 0 in D (effectively) */
+# define sr1() (outnop1str("ASRA"), outnop1str("RORB"))
+# define stackregstr "S"
+# define subfactor(reg) outop2str("SUBD\t,S")
+# define testhi() outnop1str("TSTA")
+# define tfrhilo() outnop2str("TFR\tA,B")
+# define tfrlohi() outnop2str("TFR\tB,A")
+# define usr1() (outnop1str("LSRA"), outnop1str("RORB"))
+PUBLIC void clrBreg()
+{
+ outnop1str("CLRB");
+}
+PUBLIC void comment()
+{
+ outstr("| ");
+}
+PUBLIC void defbyte()
+{
+ outop0str("FCB\t");
+}
+PUBLIC void defword()
+{
+ outop0str("FDB\t");
+}
+PUBLIC void negDreg()
+{
+ outnop1str("NEGA");
+ negBsbcA();
+}
+PRIVATE void negBsbcA()
+{
+ outnop1str("NEGB");
+ sbc0();
+}
+PUBLIC void comDreg()
+{
+ outnop1str("COMA");
+ outnop1str("COMB");
+}
+PUBLIC void outABX()
+{
+ outnop1str("ABX");
+}
+PUBLIC void outadd()
+{
+ outop2str("ADD");
+}
+PUBLIC void outaddsp()
+{
+ outleasp();
+ bumplc2();
+}
+PUBLIC void outcalladr()
+{
+ outop2str("JSR");
+}
+PUBLIC void outcmp()
+{
+ outop2str("CMP");
+}
+PUBLIC void outdec()
+{
+ outop1str("DEC");
+}
+PUBLIC void outdirectpage()
+{
+ outbyte('<');
+}
+PUBLIC void outextended()
+{
+ outbyte('>');
+}
+PUBLIC void outfail()
+{
+ outop0str("FAIL\t");
+}
+PUBLIC void outinc()
+{
+ outop1str("INC");
+}
+PUBLIC void outindleft()
+{
+ outbyte('[');
+}
+PUBLIC void outindright()
+{
+ outbyte(']');
+}
+PUBLIC void outldaccum()
+{
+ outload();
+ outaccum();
+}
+PUBLIC void outldmulreg()
+{
+ outop2str("LDA");
+}
+PUBLIC void outlea()
+{
+ outop2str("LEA");
+}
+PUBLIC void outleasp()
+{
+ outop2str("LEAS\t");
+}
+PUBLIC void outload()
+{
+ outop2str("LD");
+}
+PUBLIC void outmulmulreg()
+{
+ outnop1str("MUL");
+}
+PUBLIC void outncspregname()
+{
+ outcomma();
+ outstackreg();
+ outnl();
+}
+PUBLIC void outopsep()
+{
+} /* is tab, but already done by outadr() */
+PUBLIC void outpshs()
+{
+ outop2str("PSHS");
+}
+PUBLIC void outpuls()
+{
+ outop2str("PULS");
+}
+PUBLIC void outreturn()
+{
+ outnop1str("RTS");
+}
+PUBLIC void outstore()
+{
+ outop2str("ST");
+}
+PUBLIC void outsub()
+{
+ outop2str("SUB");
+}
+PUBLIC void outtest()
+{
+ outop1str("TST");
+}
+PUBLIC void sctoi()
+{
+ outnop1str("SEX");
+}
+PUBLIC void ctoi()
+{
+ outnop1str("CLRA");
+}
+#endif /* MC6809 */
+#ifdef FRAMEREG
+PUBLIC void outindframereg()
+{
+ outindleft();
+ outregname(FRAMEREG);
+ outindright();
+}
+#endif
+
+typedef fastin_t seg_t; /* range 0..3 */
+
+PRIVATE seg_t segment; /* current seg, depends on init to CSEG = 0 */
+
+/* add carry resulting from char addition */
+
+PUBLIC void adc0()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ adjcarry();
+ outadd();
+ outaccum();
+ outncregname(DXREG);
+ }
+ else
+#endif
+ {
+ outadc();
+ outhiaccum();
+ outncimmadr((offset_t) 0);
+ }
+}
+
+/* add constant to register */
+
+PUBLIC void addconst(offset, reg)
+offset_t offset;
+store_pt reg;
+{
+#ifdef I8088
+ if ((i386_32 && (uoffset_t) offset + 1 <= 2) /* do -1 to 1 by dec/inc */
+ || (!i386_32 && (uoffset_t) offset + 2 <= 4)) /* do -2 to 2 */
+ {
+ if (reg == ALREG)
+ reg = AXREG; /* shorter and faster */
+ do
+ {
+ if (offset < 0)
+ {
+ outdec();
+ ++offset;
+ }
+ else /* if offset == 0, do inc + dec */
+ {
+ outinc();
+ --offset; /* shouldn't happen and harmless */
+ }
+ outnregname(reg);
+ }
+ while (offset);
+ }
+ else
+#endif
+#ifdef MC6809
+ if (!(reg & ALLDATREGS))
+ lea(offset, reg, reg);
+ else if (reg == BREG && (offset == 1 || offset == -1))
+ {
+ if (offset < 0)
+ outdec();
+ else
+ outinc();
+ outnregname(reg);
+ }
+ else
+#endif
+ {
+ outadd();
+ outimadj(offset, reg);
+ }
+}
+
+/* adjust lc for signed offset */
+
+PUBLIC void adjlc(offset, reg)
+offset_t offset;
+store_pt reg;
+{
+ if (!(reg & CHARREGS))
+ {
+ bumplc();
+ if (!isbyteoffset(offset))
+ {
+#ifdef I8088
+ if ((store_t) reg != AXREG)
+#endif
+ bumplc();
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ }
+ }
+}
+
+/* adjust stack ptr by adding a labelled constant less current sp */
+
+PUBLIC void adjsp(label)
+label_t label;
+{
+ outaddsp();
+ outbyte(LOCALSTARTCHAR);
+ outlabel(label);
+ if (switchnow != NULL)
+ {
+ outminus();
+ outswstacklab();
+ }
+ else
+ {
+ outplus();
+ outhex((uoffset_t) - sp);
+ }
+#ifdef MC6809
+ outcregname(LOCAL);
+#endif
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ outnl();
+}
+
+/* and accumulator with constant */
+
+PUBLIC void andconst(offset)
+offset_t offset;
+{
+ char_t botbits;
+ uoffset_t topbits;
+
+ if ((topbits = offset & ~(uoffset_t) CHMASKTO & intmaskto) != 0 &&
+ topbits != (~(uoffset_t) CHMASKTO & intmaskto))
+ /* if topbits == 0, callers reduce the type */
+ {
+#ifdef OP1
+ outandhi();
+ outncimmadr((offset_t) (topbits >> (INT16BITSTO - CHBITSTO)));
+#else
+ outandac();
+ if (i386_32)
+ bumplc2();
+ outncimmadr(offset);
+ return;
+#endif
+ }
+ if ((botbits = (char_t) offset & CHMASKTO) == 0)
+ clrBreg();
+ else if (botbits != CHMASKTO)
+ {
+ outandlo();
+ outncimmadr((offset_t) botbits);
+ }
+}
+
+#ifdef I8088
+
+/* set bss segment */
+
+PUBLIC void bssseg()
+{
+ if (segment != BSSSEG)
+ {
+ segment = BSSSEG;
+ outbssseg();
+ }
+}
+
+#endif
+
+/* jump to case of switch */
+
+PUBLIC label_t casejump()
+{
+ label_t jtablelab;
+
+#ifdef I8088
+ outlswitch();
+ outj1switch();
+ outlabel(jtablelab = getlabel());
+ outj2switch();
+ if (i386_32)
+ bumplc2();
+#endif
+#ifdef MC6809
+ if (posindependent)
+ {
+ outpil1switch();
+ outlabel(jtablelab = getlabel());
+ outncregname(GLOBAL);
+ outpil2switch();
+ outpijswitch();
+ }
+ else
+ {
+ outlswitch();
+ outnlabel(jtablelab = getlabel());
+ outjswitch();
+ }
+#endif
+ return jtablelab;
+}
+
+/* clear register to 0 */
+
+PRIVATE void clr(reg)
+store_pt reg;
+{
+ loadconst((offset_t) 0, reg);
+}
+
+/* define common storage */
+
+PUBLIC void common(name)
+char *name;
+{
+#ifdef I8088
+ outcommon();
+ outccname(name);
+ outcomma();
+#endif
+#ifdef MC6809
+ outccname(name);
+ outcommon();
+#endif
+}
+
+/* set code segment */
+
+PUBLIC void cseg()
+{
+ if (segment != CSEG)
+ {
+ segment = CSEG;
+ outcseg();
+ }
+}
+
+/* define long */
+
+PUBLIC void deflong(value)
+uoffset_t value;
+{
+ uoffset_t longhigh;
+ uoffset_t longlow;
+
+ longlow = value & (uoffset_t) intmaskto;
+#ifdef I8088
+ if (i386_32)
+ defdword();
+ else
+#endif
+ {
+ longhigh = (value >> INT16BITSTO) & (uoffset_t) intmaskto;
+ defword();
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ outnhex(longhigh);
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ {
+ outnhex(longlow);
+ longlow = longhigh;
+ }
+#endif
+ defword();
+ }
+ outnhex(longlow);
+}
+
+/* define null storage */
+
+PUBLIC void defnulls(nullcount)
+uoffset_t nullcount;
+{
+ if (nullcount != 0)
+ {
+ defstorage();
+ outnhex(nullcount);
+ }
+}
+
+/* define string */
+
+PUBLIC label_t defstr(sptr, stop, dataflag)
+char *sptr;
+char *stop;
+bool_pt dataflag;
+{
+ int byte; /* promoted char for output */
+ label_t strlab;
+ seg_t oldsegment;
+ fastin_t count; /* range 0..max(DEFSTR_BYTEMAX,DEFSTR_STRMAX) */
+
+#ifdef HOLDSTRINGS
+ if (!(bool_t) dataflag)
+ return holdstr(sptr, stop);
+#endif
+ oldsegment = segment;
+#ifdef I8088
+ dseg();
+#endif
+#ifdef MC6809
+ if (dataflag)
+ dseg();
+ else
+ {
+ segment = STRSEG; /* could use dseg() */
+ outstrseg(); /* this brings strings together */
+ }
+#endif
+ outnlabel(strlab = getlabel());
+ byte = (unsigned char) *sptr++;
+ while (sptr <= stop)
+ {
+ if ((unsigned char) byte >= MINPRINTCHAR
+ && (unsigned char) byte <= MAXPRINTCHAR)
+ {
+ outdefstr();
+ count = DEFSTR_STRINGMAX;
+ while (count-- > 0 && (unsigned char) byte >= MINPRINTCHAR
+ && (unsigned char) byte <= MAXPRINTCHAR && sptr <= stop)
+ {
+#if DEFSTR_DELIMITER - DEFSTR_QUOTER
+ if ((unsigned char) byte == DEFSTR_DELIMITER
+ || (unsigned char) byte == DEFSTR_QUOTER)
+#else
+ if ((unsigned char) byte == DEFSTR_DELIMITER)
+#endif
+ outbyte(DEFSTR_QUOTER);
+ outbyte(byte);
+ byte = (unsigned char) *sptr++;
+ }
+ outnbyte(DEFSTR_DELIMITER);
+ }
+ else
+ {
+ defbyte();
+ count = DEFSTR_BYTEMAX;
+ while (count-- > 0 && ((unsigned char) byte < MINPRINTCHAR
+ || (unsigned char) byte > MAXPRINTCHAR) && sptr <= stop)
+ {
+ if (count < DEFSTR_BYTEMAX - 1)
+ outcomma(); /* byte separator */
+ outhex((uoffset_t) byte);
+ byte = (unsigned char) *sptr++;
+ }
+ outnl();
+ }
+ }
+ defbyte();
+ outnbyte(EOS_TEXT);
+ switch (oldsegment)
+ {
+ case CSEG:
+ cseg();
+ break;
+ case DSEG:
+ dseg();
+ break;
+#ifdef I8088
+ case BSSSEG:
+ bssseg();
+ break;
+#endif
+#ifdef MC6809
+ case DPSEG:
+ dpseg();
+ break;
+#endif
+ }
+ return strlab;
+}
+
+/* divide D register by a constant if it is easy to do with shifts */
+
+PUBLIC bool_pt diveasy(divisor, uflag)
+value_t divisor;
+bool_pt uflag;
+{
+ bool_t sign;
+
+ sign = FALSE;
+ if (divisor < 0 && !(bool_t) uflag)
+ {
+ sign = TRUE;
+ divisor = -divisor;
+ }
+ if (bitcount((uvalue_t) divisor) > 1)
+ return FALSE;
+ if (divisor == 0)
+ clr(DREG);
+ else
+ {
+ if (sign)
+ negDreg();
+ srconst((value_t) highbit((uvalue_t) divisor), uflag);
+ }
+ return TRUE;
+}
+
+#ifdef MC6809
+
+/* set direct page segment */
+
+PUBLIC void dpseg()
+{
+ if (segment != DPSEG)
+ {
+ segment = DPSEG;
+ outdpseg();
+ }
+}
+
+#endif
+
+/* set data segment */
+
+PUBLIC void dseg()
+{
+ if (segment != DSEG)
+ {
+ segment = DSEG;
+ outdseg();
+ }
+}
+
+/* equate a name to an EOL-terminated string */
+
+PUBLIC void equ(name, string)
+char *name;
+char *string;
+{
+ outstr(name);
+ outequate();
+ outline(string);
+}
+
+/* equate a local label to a value */
+
+PUBLIC void equlab(label, offset)
+label_t label;
+offset_t offset;
+{
+ outbyte(LOCALSTARTCHAR);
+ outlabel(label);
+ outequate();
+ outshex(offset);
+ outnl();
+}
+
+/* import or export a variable */
+
+PUBLIC void globl(name)
+char *name;
+{
+ outglobl();
+ outnccname(name);
+}
+
+/* import a variable */
+
+PUBLIC void import(name)
+char *name;
+{
+ outimport();
+ outnccname(name);
+}
+
+/* extend an int to a long */
+
+PUBLIC void itol(reg)
+store_pt reg;
+{
+#define TEMP_LABEL_FOR_REGRESSION_TESTS
+#ifdef TEMP_LABEL_FOR_REGRESSION_TESTS
+ getlabel();
+#endif
+
+ if (lowregisDreg())
+ {
+#ifdef I8088
+ outcwd();
+ regtransfer(DXREG, reg);
+#else
+ label_t exitlab;
+
+ clr(reg);
+ testhi();
+ sbranch(GE, exitlab = getlabel());
+ loadconst((offset_t) - 1, reg);
+ outnlabel(exitlab);
+#endif
+ }
+ else
+ {
+ regtransfer(DREG, reg);
+ smiDreg();
+ }
+}
+
+/* define local common storage */
+
+PUBLIC void lcommlab(label)
+label_t label;
+{
+ outlabel(label);
+ outlcommon();
+}
+
+PUBLIC void lcommon(name)
+char *name;
+{
+ outccname(name);
+ outlcommon();
+}
+
+#ifdef MC6809
+
+/* load effective address */
+
+PUBLIC void lea(offset, sourcereg, targreg)
+offset_t offset;
+store_pt sourcereg;
+store_pt targreg;
+{
+ outlea();
+ outregname(targreg);
+ outtab();
+ outshex(offset);
+ outncregname(sourcereg);
+}
+
+#endif
+
+/* load constant into given register */
+
+PUBLIC void loadconst(offset, reg)
+offset_t offset;
+store_pt reg;
+{
+#ifdef I8088
+ if (offset == 0)
+ {
+ outxor();
+ outregname(reg);
+ outncregname(reg);
+ }
+ else
+#endif
+#ifdef MC6809
+ if (offset == 0 && reg == BREG)
+ clrBreg();
+ else
+#endif
+ {
+ outload();
+ outregname(reg);
+#ifdef MC6809
+ if (reg == YREG)
+ bumplc2();
+ else
+#endif
+ if (reg != BREG)
+ {
+ bumplc();
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ }
+ outncimmadr(offset);
+ }
+}
+
+/* convert index half of long reg pair into low half of pair */
+
+PRIVATE bool_pt lowregisDreg()
+{
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ return FALSE;
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ return TRUE;
+#endif
+}
+
+/* partially long shift left register by a constant (negative = infinity) */
+
+PUBLIC int lslconst(shift, reg)
+value_t shift;
+store_pt reg;
+{
+ if ((uvalue_t) shift >= INT16BITSTO)
+ {
+ slconst(shift - INT16BITSTO, lowregisDreg() ? DREG : reg);
+ regexchange(reg, DREG);
+ clr(lowregisDreg() ? DREG : reg);
+ return 0;
+ }
+#ifdef I8088
+ if (shift >= CHBITSTO)
+ {
+ if (long_big_endian)
+ {
+ tfrlohi();
+ outnop2str("mov\tal,bh");
+ outnop2str("mov\tbh,bl");
+ outnop2str("sub\tbl,bl");
+ }
+ else
+ {
+ outnop2str("mov\tbh,bl");
+ outnop2str("mov\tbl,ah");
+ tfrlohi();
+ clrBreg();
+ }
+ return (int) shift - CHBITSTO;
+ }
+#endif
+ return (int) shift;
+}
+
+/* partially long shift right register by a constant (negative = infinity) */
+
+PUBLIC int lsrconst(shift, reg, uflag)
+value_t shift;
+store_pt reg;
+bool_pt uflag;
+{
+ if ((uvalue_t) shift >= INT16BITSTO)
+ {
+ if (lowregisDreg())
+ regexchange(reg, DREG);
+ srconst(shift - INT16BITSTO, uflag);
+ if ((bool_t) uflag)
+ uitol(reg);
+ else
+ itol(reg);
+ return 0;
+ }
+#ifdef I8088
+ if (shift >= CHBITSTO)
+ {
+ if (long_big_endian)
+ {
+ outnop2str("mov\tbl,bh");
+ outnop2str("mov\tbh,al");
+ tfrhilo();
+ if ((bool_t) uflag)
+ ctoi();
+ else
+ sctoi();
+ }
+ else
+ {
+ tfrhilo();
+ outnop2str("mov\tah,bl");
+ outnop2str("mov\tbl,bh");
+ if ((bool_t) uflag)
+ outnop2str("sub\tbh,bh");
+ else
+ {
+ regexchange(reg, DREG);
+ sctoi();
+ regexchange(reg, DREG);
+ }
+ }
+ return (int) shift - CHBITSTO;
+ }
+#endif
+ return (int) shift;
+}
+
+/* take D register modulo a constant if it is easy to do with a mask */
+
+PUBLIC bool_pt modeasy(divisor, uflag)
+value_t divisor;
+bool_pt uflag;
+{
+ bool_t sign;
+
+ sign = FALSE;
+ if (divisor < 0 && !(bool_t) uflag)
+ {
+ sign = TRUE;
+ divisor = -divisor;
+ }
+ if (bitcount((uvalue_t) divisor) > 1)
+ return FALSE;
+ if (--divisor == 0)
+ clrBreg(); /* original divisor 1 or -1 yields 0 */
+ else
+ {
+ if (sign)
+ negDreg();
+ andconst((offset_t) divisor); /* if original divisor 0, this is
+ null */
+ if (sign)
+ negDreg();
+ }
+ return TRUE;
+}
+
+/* multiply register by a constant if it is easy to do with shifts */
+
+PUBLIC bool_pt muleasy(factor, reg)
+uvalue_t factor;
+store_pt reg;
+{
+ int mulstack[MAXINTBITSTO / 2 + 1]; /* must be signed, not a fastin_t */
+ fastin_pt count;
+ fastin_t single1skip;
+ fastin_t lastcount;
+ fastin_t mulsp;
+ int stackentry; /* signed */
+
+ if (factor == 0)
+ {
+ clr(reg);
+ return TRUE;
+ }
+ single1skip = 0;
+ mulsp = -1; /* may be unsigned, but bumps to 0 */
+ while (factor != 0)
+ {
+ for (lastcount = single1skip; (factor & 1) == 0; factor >>= 1)
+ ++lastcount;
+ mulstack[(int)++mulsp] = lastcount;
+ /* first time bumps mulsp to 0 even if an unsigned char */
+ for (count = 0; (factor & 1) != 0; factor >>= 1)
+ ++count;
+ single1skip = 1;
+ if (count == 2 && factor == 0)
+ /* 3 = 2 + 1 better than 3 = 4 - 1 */
+ /* but rest of algorithm messed up unless factor now 0 */
+ mulstack[(int)++mulsp] = 1;
+ else if (count > 1)
+ {
+ single1skip = 0;
+ if (lastcount == 1 && mulsp != 0)
+ mulstack[(int)mulsp] = -1 - count;
+ else
+ mulstack[(int)++mulsp] = -count;
+ }
+ }
+ if (mulsp > 3)
+ return FALSE;
+ if (mulsp != 0)
+ {
+ savefactor(reg); /* on stack or in reg as nec */
+ do
+ {
+ finishfactor(); /* finish save/add/subfactor() if nec */
+ stackentry = mulstack[(int)mulsp--];
+ if (stackentry < 0)
+ {
+#ifdef I8088
+ if (stackentry == -INT32BITSTO)
+ clr(reg); /* shifting would do nothing */
+ else
+#endif
+ slconst((value_t) - stackentry, reg);
+ subfactor(reg); /* from wherever put by savefactor() */
+ }
+ else
+ {
+ slconst((value_t) stackentry, reg);
+ addfactor(reg); /* from wherever put by savefactor() */
+ }
+ }
+ while (mulsp != 0);
+ reclaimfactor(); /* reclaim storage if nec */
+ }
+ slconst((value_t) mulstack[0], reg);
+ return TRUE;
+}
+
+/* negate a register */
+
+PUBLIC void negreg(reg)
+store_pt reg;
+{
+ if ((store_t) reg == BREG)
+ extBnegD();
+ else
+ negDreg();
+}
+
+/* return string of operator */
+
+PUBLIC char *opstring(op)
+op_pt op;
+{
+ switch (op)
+ {
+ case ANDOP:
+ return ANDSTRING;
+ case EOROP:
+ return EORSTRING;
+ case OROP:
+ return ORSTRING;
+ }
+ return "badop";
+}
+
+/* print DREG (accumulator) */
+
+PRIVATE void outaccum()
+{
+ outstr(accumstr);
+}
+
+/* print a c compiler name with leading CCNAMEPREXFIX */
+
+PUBLIC void outccname(name)
+char *name;
+{
+ outbyte(CCNAMEPREFIX);
+ outstr(name);
+}
+
+/* print high byte of word accumulator */
+
+PUBLIC void outhiaccum()
+{
+ outstr(ACCHISTR);
+}
+
+/* print immediate address */
+
+PUBLIC void outimmadr(offset)
+offset_t offset;
+{
+#ifdef I8088
+ if (!isbyteoffset(offset))
+ outimmed();
+ else
+ outbimmed();
+#else
+ outimmed();
+#endif
+ outshex(offset);
+}
+
+/* print register, comma, immediate address and adjust lc */
+
+PUBLIC void outimadj(offset, targreg)
+offset_t offset;
+store_pt targreg;
+{
+ outregname(targreg);
+ adjlc(offset, targreg);
+ outncimmadr(offset);
+}
+
+/* print immediate address designator */
+
+PUBLIC void outimmed()
+{
+ outbyte('#');
+}
+
+PUBLIC void outjumpstring()
+{
+ outop3str(jumpstring);
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+/* print cc name, then newline */
+
+PUBLIC void outnccname(name)
+char *name;
+{
+ outccname(name);
+ outnl();
+}
+
+/* print separator, immediate address, newline */
+
+PUBLIC void outncimmadr(offset)
+offset_t offset;
+{
+#ifdef I8088
+ outcomma();
+#endif
+#ifdef MC6809
+ outtab();
+#endif
+ outimmadr(offset);
+ outnl();
+}
+
+/* print signed offset and adjust lc */
+
+PUBLIC void outoffset(offset)
+offset_t offset;
+{
+#ifdef MC6809
+ if (!is5bitoffset(offset))
+#endif
+ adjlc(offset, INDREG0);
+ outshex(offset);
+}
+
+/* print stack register */
+
+PRIVATE void outstackreg()
+{
+ outstr(stackregstr);
+}
+
+PUBLIC void public(name)
+char *name;
+{
+#ifndef AS09
+ outexport();
+ outnccname(name);
+#endif
+ outccname(name);
+ outnbyte(PUBLICENDCHAR);
+}
+
+/* print cc name as a private label */
+
+PUBLIC void private(name)
+char *name;
+{
+#ifdef LABELENDCHAR
+ outccname(name);
+ outnbyte(LABELENDCHAR);
+#else
+ outnccname(name);
+#endif
+}
+
+/* exchange registers */
+
+PUBLIC void regexchange(sourcereg, targreg)
+store_pt sourcereg;
+store_pt targreg;
+{
+ outexchange();
+ outregname(sourcereg);
+ outncregname(targreg);
+#ifdef I8088
+ if (!((sourcereg | targreg) & AXREG))
+ bumplc();
+#endif
+}
+
+/* transfer a register */
+
+PUBLIC void regtransfer(sourcereg, targreg)
+store_pt sourcereg;
+store_pt targreg;
+{
+ outtransfer();
+#ifdef TARGET_FIRST
+ outregname(targreg);
+ outncregname(sourcereg);
+#else
+ outregname(sourcereg);
+ outncregname(targreg);
+#endif
+}
+
+/* subtract carry resulting from char addition */
+
+PUBLIC void sbc0()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ adjcarry();
+ outsub();
+ outaccum();
+ outncregname(DXREG);
+ }
+ else
+#endif
+ {
+ outsbc();
+ outhiaccum();
+ outncimmadr((offset_t) 0);
+ }
+}
+
+/* set a name to a value */
+
+PUBLIC void set(name, value)
+char *name;
+offset_t value;
+{
+ outccname(funcname);
+ outbyte(LOCALSTARTCHAR);
+ outstr(name);
+ outset();
+ outshex(value);
+ outnl();
+}
+
+/* shift left register by 1 */
+
+PUBLIC void sl1(reg)
+store_pt reg;
+{
+ outsl();
+#ifdef I8088
+ outregname(reg);
+ outnc1();
+#endif
+#ifdef MC6809
+ outnregname(BREG);
+ outrolhi();
+#endif
+}
+
+/* shift left register by a constant (negative = infinity) */
+
+PUBLIC void slconst(shift, reg)
+value_t shift;
+store_pt reg;
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ if ((shift = (uvalue_t) shift % INT32BITSTO) != 0)
+ {
+ outsl();
+ if (shift != 1)
+ bumplc();
+ outregname(reg);
+ outncimmadr((offset_t) shift);
+ }
+ return;
+ }
+#endif
+ if ((uvalue_t) shift >= INT16BITSTO)
+ clr(reg);
+ else
+ {
+ if (shift >= CHBITSTO && reg == DREG)
+ {
+ tfrlohi();
+ clrBreg();
+ shift -= CHBITSTO;
+ }
+#ifdef I8088
+# if MAX_INLINE_SHIFT < INT16BITSTO
+ if (shift > MAX_INLINE_SHIFT)
+ {
+ outload();
+ outregname(SHIFTREG);
+ outcomma();
+ outimmadr((offset_t) shift);
+ outnl();
+ outsl();
+ outregname(reg);
+ outncregname(SHIFTREG);
+ }
+ else
+# endif
+#endif
+ while (shift--)
+ sl1(reg);
+ }
+}
+
+/* shift right D register by a constant (negative = infinity) */
+
+PUBLIC void srconst(shift, uflag)
+value_t shift;
+bool_pt uflag;
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ if ((shift = (uvalue_t) shift % INT32BITSTO) != 0)
+ {
+ if (uflag)
+ outusr();
+ else
+ outsr();
+ if (shift != 1)
+ bumplc();
+ outaccum();
+ outncimmadr((offset_t) shift);
+ }
+ return;
+ }
+#endif
+ if ((uvalue_t) shift >= INT16BITSTO) /* covers negatives too */
+ {
+ if ((bool_t) uflag)
+ clr(DREG);
+ else /* make D == 0 if D >= 0, else D == -1 */
+ smiDreg(); /* special case of 68020 Scc instruction */
+ }
+ else
+ {
+ if (shift >= CHBITSTO)
+ {
+ tfrhilo();
+ if ((bool_t) uflag)
+ ctoi();
+ else
+ sctoi();
+ shift -= CHBITSTO;
+ }
+#ifdef I8088
+# if MAX_INLINE_SHIFT < INT16BITSTO
+ if (shift > MAX_INLINE_SHIFT)
+ {
+ outload();
+ outregname(SHIFTREG);
+ outcomma();
+ outimmadr((offset_t) shift);
+ outnl();
+ if ((bool_t) uflag)
+ outusr();
+ else
+ outsr();
+ outaccum();
+ outncregname(SHIFTREG);
+ }
+ else
+# endif
+#endif
+ while (shift--)
+ {
+ if ((bool_t) uflag)
+ usr1();
+ else
+ sr1();
+ }
+ }
+}
+
+/* extend an unsigned in DREG to a long */
+
+PUBLIC void uitol(reg)
+store_pt reg;
+{
+ if (lowregisDreg())
+ clr(reg);
+ else
+ {
+ regexchange(DREG, reg);
+ clr(DREG);
+ }
+}
+
+PRIVATE char opregstr[] = "_opreg";
+
+/*-----------------------------------------------------------------------------
+ opregadr()
+ outputs address of variable opreg where OPREG is saved
+-----------------------------------------------------------------------------*/
+
+PRIVATE void opregadr()
+{
+#ifdef I8088
+ outindleft();
+ outccname(opregstr);
+ outindright();
+ bumplc2();
+ if (i386_32)
+ bumplc2();
+#endif
+#ifdef MC6809
+ outregname(OPREG);
+ outtab();
+ if (posindependent)
+ {
+ outccname(opregstr);
+ outncregname(GLOBAL);
+ bumplc();
+ }
+ else
+ {
+ outextended();
+ outnccname(opregstr);
+ }
+ bumplc();
+#endif
+}
+
+/*-----------------------------------------------------------------------------
+ restoreopreg()
+ restores register OPREG from static location >opreg if it is was use
+-----------------------------------------------------------------------------*/
+
+PUBLIC void restoreopreg()
+{
+ if (reguse & OPREG)
+ {
+#ifdef I8088
+ outload();
+ outregname(OPREG);
+ outopsep();
+ opregadr();
+ outnl();
+#endif
+#ifdef MC6809
+ outload();
+ opregadr();
+#endif
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ saveopreg()
+ saves register OPREG to static location >opreg if it is in use
+ this makes the flop routines non-reentrant. It is too messy to
+ push it because the flop routines leave results on the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC void saveopreg()
+{
+ if (reguse & OPREG)
+ {
+#ifdef I8088
+ bssseg();
+ common(opregstr);
+ outnhex(opregsize);
+ cseg();
+ outstore();
+ opregadr();
+ outncregname(OPREG);
+#endif
+#ifdef MC6809
+ dseg();
+ common(opregstr);
+ outnhex(opregsize);
+ cseg();
+ outstore();
+ opregadr();
+#endif
+ }
+}
diff --git a/bcc/condcode.h b/bcc/condcode.h
new file mode 100644
index 0000000..9b047df
--- /dev/null
+++ b/bcc/condcode.h
@@ -0,0 +1,16 @@
+/* condcode.h - condition codes for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define EQ 0
+#define NE 1
+#define RA 2
+#define RN 3
+#define LT 4
+#define GE 5
+#define LE 6
+#define GT 7
+#define LO 8
+#define HS 9
+#define LS 10
+#define HI 11
diff --git a/bcc/const.h b/bcc/const.h
new file mode 100644
index 0000000..8df8bcb
--- /dev/null
+++ b/bcc/const.h
@@ -0,0 +1,52 @@
+/* const.h - constants for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* switches for code generation */
+
+#define DEBUG /* generate compiler-debugging code */
+#define I8088 /* target processor is Intel 8088 thru 80386 */
+/*#define MC6809*/ /* target processor is Motorola 6809 */
+#define SELFTYPECHECK /* check calculated type = runtime type */
+
+#ifdef I8088
+# define DYNAMIC_LONG_ORDER 1 /* long word order spec. at compile time */
+# define FRAMEPOINTER /* index locals off frame ptr, not stack ptr */
+# define HOLDSTRINGS /* hold strings for dumping at end
+ * since assembler has only 1 data seg */
+#endif
+
+#ifdef MC6809
+# define DYNAMIC_LONG_ORDER 0 /* have to define it so it works in #if's */
+# define OP1 /* logical operators only use 1 byte */
+# define POSINDEPENDENT /* position indep code can (also) be gen */
+#endif
+
+/* switches for source and target operating system dependencies */
+
+/*#define SOS_EDOS*/ /* source O/S is EDOS */
+/*#define SOS_MSDOS*/ /* source O/S is MSDOS */
+/*#define TOS_EDOS*/ /* target O/S is EDOS */
+
+/* switches for source machine dependencies */
+
+#ifndef SOS_EDOS
+# define S_ALIGNMENT (sizeof(int)) /* source memory alignment, power of 2 */
+#endif
+
+#ifndef SOS_MSDOS /* need portable alignment for large model */
+# define UNPORTABLE_ALIGNMENT
+#endif
+
+/* local style */
+
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
diff --git a/bcc/debug.c b/bcc/debug.c
new file mode 100644
index 0000000..26f7bf8
--- /dev/null
+++ b/bcc/debug.c
@@ -0,0 +1,202 @@
+/* debug.c - print debug messages for operators for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+
+#ifdef DEBUG
+
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+PRIVATE char *opname[LASTOP - FIRSTOP + 1] = /* operator names */
+{ /* order must agree with op.h */
+ "cond?",
+ "or",
+ "eor",
+ "and",
+ "gt", "lt",
+ "add",
+ "div", "mod",
+ "lognot", "not",
+ "strucelt", "strucptr",
+ "eq",
+ "addab", "andab", "divab", "eorab", "modab", "mulab", "orab",
+ "slab", "srab", "subab",
+ "comma",
+ "cond:",
+ "logor",
+ "logand",
+ "logeq",
+ "ne",
+ "ge", "le",
+ "sl", "sr",
+ "sub",
+ "mul",
+ "address", "cast", "indirect", "neg",
+ "predec", "preinc", "postdec", "postinc",
+ "func", "list", "rootlist",
+ "leaf",
+ "ptraddab", "ptradd", "ptrsub",
+};
+
+FORWARD void outindchars P((int byte, indn_pt count));
+
+PUBLIC void dbitem(item)
+struct symstruct *item;
+{
+ dbtype(item->type);
+ if (item->storage == NOSTORAGE)
+ {
+ outbyte(' ');
+ outstr(item->name.namep + 2);
+ outstr(" (offset ");
+ outshex(item->offset.offi);
+ outbyte(')');
+ return;
+ }
+ if (item->storage == LOCAL)
+ {
+ outbyte(' ');
+ if (item->flags == TEMP)
+ outstr("(temp)");
+ else
+ outstr(item->name.namep);
+ }
+ outstr(" = ");
+ outindchars('[', item->indcount);
+ switch (item->storage)
+ {
+ case CONSTANT:
+ outstr("const ");
+ if (item->type->scalar & RSCALAR)
+ outstr("(whatever)");
+ else if (item->type->scalar & UNSIGNED)
+ outuvalue((uvalue_t) item->offset.offv);
+ else
+ outvalue(item->offset.offv);
+ break;
+ case BREG:
+ case DREG:
+ case INDREG0:
+ case INDREG1:
+ case INDREG2:
+#ifdef DATREG1
+ case DATREG1:
+#endif
+#ifdef DATREG2
+ case DATREG2:
+#endif
+ outregname(item->storage);
+ if (item->level == OFFKLUDGELEVEL)
+ {
+ outplus();
+ if (item->flags & LABELLED)
+ outlabel(item->name.label);
+ else
+ outccname(item->name.namep);
+ }
+ break;
+ case LOCAL:
+ outbyte('S');
+ if (sp <= 0)
+ outplus();
+ outshex(-sp);
+ break;
+ case GLOBAL:
+ if (item->flags & LABELLED)
+ outlabel(item->name.label);
+ else
+ outstr(item->name.namep);
+ break;
+ default:
+ outstr("bad storage (");
+ outhex((uoffset_t) item->storage);
+ outbyte(')');
+ outstr(" offset ");
+ }
+ if (item->storage != CONSTANT)
+ {
+ if (item->offset.offi >= 0)
+ outplus();
+ outshex(item->offset.offi);
+ }
+ outindchars(']', item->indcount);
+}
+
+PUBLIC void dbtype(type)
+struct typestruct *type;
+{
+ for ( ; type != NULL; type = type->nexttype)
+ {
+ outbyte(' ');
+ switch (type->constructor)
+ {
+ case ARRAY:
+ outbyte('[');
+ outhex(type->typesize / type->nexttype->typesize);
+ outbyte(']');
+ break;
+ case FUNCTION:
+ outstr("()");
+ break;
+ case POINTER:
+ outbyte('*');
+ break;
+ case STRUCTU:
+ outstr("struct ");
+ default:
+ if (type->scalar & UNSIGNED)
+ outstr("unsigned ");
+ outstr(type->tname);
+ break;
+ }
+ }
+}
+
+PUBLIC void debug(exp) /* sub-nodes must be leaves */
+struct nodestruct *exp;
+{
+ if (!debugon)
+ return;
+ comment();
+ if (exp->tag < FIRSTOP && exp->tag > LASTOP)
+ outstr("unknown op");
+ else
+ outstr(opname[exp->tag - FIRSTOP]);
+ if (exp->right != NULL && exp->tag != FUNCOP &&
+ exp->tag != LISTOP && exp->tag != ROOTLISTOP)
+ {
+ dbitem(exp->right->left.symptr);
+ outstr(" to");
+ }
+ dbitem(exp->left.nodeptr->left.symptr);
+ outstr(" (used reg = ");
+ if (reguse & INDREG0)
+ outregname(INDREG0);
+ if (reguse & INDREG1)
+ outregname(INDREG1);
+ if (reguse & INDREG2)
+ outregname(INDREG2);
+ outnstr(")");
+}
+
+PUBLIC void debugswap()
+{
+ if (debugon)
+ outnstr("* swapping");
+}
+
+PRIVATE void outindchars(byte, count)
+int byte;
+indn_pt count;
+{
+ while (count--)
+ outbyte(byte);
+}
+
+#endif /* DEBUG */
diff --git a/bcc/declare.c b/bcc/declare.c
new file mode 100644
index 0000000..1dd1314
--- /dev/null
+++ b/bcc/declare.c
@@ -0,0 +1,1124 @@
+/* declare.c - declaration routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "input.h" /* just for orig_cppmode */
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "parse.h"
+
+PRIVATE bool_t argsallowed; /* nonzero to allow args in declarator */
+PRIVATE sym_t gvarsc; /* sc flags of last identifier declared */
+PRIVATE char gvar2name[2 + NAMESIZE]; /* space for structure keys and .. */
+
+#define gvarname (gvar2name + 2) /* last identifier declared */
+PRIVATE struct typestruct *gvartype; /* type of last identifier declared */
+PRIVATE bool_t initlistflag; /* remembers whether initializer is a list */
+
+FORWARD struct typestruct *chainprefix P((struct typestruct *pretype,
+ struct typestruct *sufftype));
+FORWARD void declaf P((void));
+FORWARD void declarator P((void));
+FORWARD void declarg P((void));
+FORWARD struct typestruct *declenum P((void));
+FORWARD void declfunc P((void));
+FORWARD void declselt P((struct typestruct *structype, offset_t *psoffset,
+ struct typelist ** ptypelist));
+FORWARD bool_pt declspec P((void));
+FORWARD struct typestruct *declsu P((void));
+FORWARD void idecllist P((void));
+FORWARD void initarray P((struct typestruct *type));
+FORWARD void inititem P((struct typestruct *type));
+FORWARD void initstruct P((struct typestruct *type));
+FORWARD void lbrace P((void));
+FORWARD void multidecl P((char *sname));
+FORWARD void need P((int charneeded));
+FORWARD void rdeclarator P((void));
+FORWARD bool_pt regdecl P((void));
+
+PRIVATE struct typestruct *chainprefix(pretype, sufftype)
+struct typestruct *pretype;
+struct typestruct *sufftype;
+{
+ if (pretype->nexttype != NULL)
+ {
+ sufftype = chainprefix(pretype->nexttype, sufftype);
+ if (pretype->constructor != ARRAY)
+ return prefix(pretype->constructor, pretype->typesize, sufftype);
+ else
+ return prefix(ARRAY,
+ pretype->typesize / pretype->nexttype->typesize
+ * sufftype->typesize, sufftype);
+ }
+ return sufftype;
+}
+
+PUBLIC void colon()
+{
+ if (sym != COLON)
+ need(':');
+ else
+ nextsym();
+}
+
+/* decllist() - list of local declarations */
+/* this does the non-terminal symbols declaration-list, type-declaration */
+/* list and declaration */
+/* the different cases are and ";" at the end are decided by idecllist() */
+
+PUBLIC void decllist()
+{
+ while (declspec())
+ {
+ if (gvarsc == NULLDECL)
+ gvarsc = AUTODECL;
+ idecllist();
+ }
+}
+
+PRIVATE void declaf()
+{
+ uoffset_t asize;
+ bool_t levelnew;
+#ifdef TESTING_PROTOTYPES
+ char ogvarname[NAMESIZE];
+ sym_t ogvarsc;
+ struct symstruct *ogvarsymptr;
+ struct typestruct *ogvartype;
+#endif
+
+ if (sym == LPAREN) /* function */
+ {
+ nextsym();
+ if (argsallowed && level == GLBLEVEL)
+ {
+ newlevel();
+ levelnew = TRUE;
+ }
+ else
+ levelnew = FALSE;
+#ifdef TESTING_PROTOTYPES
+ strcpy(ogvarname, gvarname);
+ ogvarsc = gvarsc;
+ ogvarsymptr = gvarsymptr;
+ ogvartype = gvartype;
+ if (declspec())
+ {
+ if (level == ARGLEVEL)
+ outstr(gvarname);
+ outbyte('(');
+ do
+ {
+ declarator();
+ dbtype(gvartype);
+ outbyte(' ');
+#if 0
+ if (gvarname[0] != 0 && gsymptr != NULL
+ && gsymptr->level == level)
+ error("repeated argument");
+#endif
+ outstr(gvarname);
+ if (levelnew)
+ addloc(gsname, gvartype); /* adjust offsets later */
+ if (sym != COMMA)
+ break;
+ outcomma();
+ nextsym();
+ }
+ while (declspec());
+ if (sym == STRUCELTOP)
+ {
+ /* ... should be lexed. */
+ nextsym();
+ if (sym == STRUCELTOP)
+ {
+ nextsym();
+ if (sym == STRUCELTOP)
+ {
+ nextsym();
+ outstr(" ...");
+ }
+ }
+ }
+ outbyte(')');
+ if (level == ARGLEVEL)
+ outnl();
+ }
+ else
+ {
+#endif /* TESTING_PROTOTYPES */
+ while (sym == IDENT)
+ {
+ if (gsymptr != NULL && gsymptr->level == level)
+ error("repeated argument");
+ if (levelnew)
+ addloc(gsname, itype); /* adjust types and offsets later */
+ nextsym();
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+#ifdef TESTING_PROTOTYPES
+ }
+ strcpy(gvarname, ogvarname);
+ gvarsc = ogvarsc;
+ gvarsymptr = ogvarsymptr;
+ gvartype = ogvartype;
+#endif /* TESTING_PROTOTYPES */
+ rparen();
+ declaf();
+ switch (gvartype->constructor)
+ {
+ case ARRAY:
+ error("function returning array is illegal");
+ break;
+ case FUNCTION:
+ error("function returning function is illegal");
+ break;
+ }
+ gvartype = prefix(FUNCTION, ftypesize, gvartype);
+ }
+ else if (sym == LBRACKET)
+ {
+ nextsym();
+ if (sym == RBRACKET)
+ asize = 0;
+ else
+ asize = constexpression() & intmaskto; /* FIXME: warn overflow */
+ rbracket();
+ declaf();
+ if (gvartype->typesize == 0)
+ switch (gvartype->constructor)
+ {
+ case FUNCTION:
+ error("array of functions is illegal");
+ break;
+ case STRUCTU:
+ error("undefined structure");
+ break;
+ default: /* array */
+ error("null dimension");
+ gvartype->typesize = 1;
+ }
+ gvartype = prefix(ARRAY, asize * gvartype->typesize, gvartype);
+ }
+}
+
+PRIVATE void declarator()
+{
+ rdeclarator();
+ if (gvartype->constructor == STRUCTU && gvartype->typesize == 0 &&
+ gvarsc != TYPEDEFDECL && gvarsc != EXTERNDECL)
+ error("undefined structure");
+}
+
+PRIVATE void declarg()
+{
+ if (gvarsymptr->level != ARGLEVEL)
+ error2error(gvarname, " not in argument list");
+ else if (gvarsymptr->flags & INITIALIZED && gvarsymptr->type != gvartype)
+ multidecl(gvarname);
+ else
+ {
+ gvarsymptr->flags = INITIALIZED; /* flag otherwise unused for locals */
+ if (gvartype->constructor & (ARRAY | POINTER))
+ gvartype = pointype(gvartype->nexttype);
+ gvarsymptr->type = gvartype;
+ if (gvarsc == REGDECL && regdecl())
+ regarg = TRUE;
+ }
+}
+
+/*
+enum-specifier =
+ "enum" [identifier] "{" enumerator {, enumerator} "}"
+ | "enum" identifier.
+enumerator =
+ identifier
+ | identifier = constant-expression.
+*/
+
+PRIVATE struct typestruct *declenum()
+{
+ register struct symstruct *esymptr;
+ register struct typestruct *enumtype;
+ offset_t ordinal;
+
+ nextsym();
+ if (sym != IDENT && sym != TYPEDEFNAME)
+ enumtype = addstruct("");
+ else if ((esymptr = findstruct(gsname)) == NULL)
+ {
+ enumtype = addstruct(gsname);
+ nextsym();
+ }
+ else
+ {
+ nextsym();
+ enumtype = esymptr->type;
+ if (sym != LBRACE)
+ return enumtype;
+ if (esymptr->level != level)
+ enumtype = addstruct(esymptr->name.namea);
+ }
+ lbrace();
+ if (enumtype->typesize != 0)
+ multidecl(enumtype->tname);
+ else
+ {
+ enumtype->typesize = itypesize;
+ enumtype->alignmask = itype->alignmask;
+ }
+ if (sym != IDENT)
+ error("empty enumerator list");
+ ordinal = 0;
+ while (sym == IDENT)
+ {
+ if ((esymptr = gsymptr) != NULL && esymptr->level == level)
+ multidecl(gsname);
+ else
+ {
+ (esymptr = addlorg(gsname, itype))->storage = CONSTANT;
+ esymptr->indcount = 0;
+ }
+ nextsym();
+ if (sym == ASSIGNOP)
+ {
+ nextsym();
+ ordinal = constexpression() & intmaskto; /* FIXME: warn ovflo */
+ if (ordinal > maxintto)
+ ordinal -= (maxuintto + 1);
+ }
+ if (esymptr->storage == CONSTANT)
+ esymptr->offset.offv = ordinal++;
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+ rbrace();
+ return enumtype;
+}
+
+/* declselt - get list of declarations for a structure/union member */
+
+PRIVATE void declselt(structype, psoffset, ptypelist)
+struct typestruct *structype;
+offset_t *psoffset;
+struct typelist **ptypelist;
+{
+ struct typestruct *basetype;
+ value_t fieldwidth;
+ value_t fwidth;
+ offset_t offset;
+ scalar_t scalar=0;
+
+ offset = *psoffset;
+ declspec();
+ if (gvarsc != NULLDECL)
+ error("illegal type name");
+ basetype = gvartype;
+ while (sym != SEMICOLON && sym != EOFSYM)
+ {
+ gvartype = basetype;
+ declarator();
+ fieldwidth = -1;
+ if (sym == COLON)
+ {
+ scalar = gvartype->scalar;
+ if (!(scalar & ISCALAR))
+ error("bitfield has non-integral type");
+ nextsym();
+ fwidth = constexpression();
+ if (fwidth < 0)
+ error("bitfield has negative width");
+ else if (fwidth > INT32BITSTO) /* XXX */
+ error("bitfield is too wide");
+ else
+ fieldwidth = fwidth;
+ }
+ if (gvarname[0] == 0)
+ {
+ if (fieldwidth == 0)
+ offset = (offset + ~gvartype->alignmask) & gvartype->alignmask;
+ else
+ /* XXX - should really align to fieldwidth'th bit. */
+ offset = (offset + ~gvartype->alignmask) & gvartype->alignmask;
+ }
+ else
+ {
+ if (fieldwidth == 0)
+ error("bitfield has zero width");
+ else if (fieldwidth > 0 && scalar & ISCALAR)
+ {
+ if (fieldwidth <= CHBITSTO) /* XXX! */
+ gvartype = ctype;
+ else if (fieldwidth <= INT32BITSTO) /* XXX */
+ gvartype = itype;
+ else
+ gvartype = ltype;
+ if (scalar & UNSIGNED)
+ gvartype = tounsigned(gvartype);
+ }
+ gvar2name[0] = structype->structkey[0];
+ gvar2name[1] = structype->structkey[1];
+ /* key provides unique name space */
+ if (findlorg(gvar2name) != NULL)
+ multidecl(gvarname);
+ else
+ {
+ (gvarsymptr = addlorg(gvar2name, gvartype))->storage
+ = NOSTORAGE;
+ structype->alignmask &= gvartype->alignmask;
+ offset = (gvarsymptr->offset.offi =
+ (offset+ ~gvartype->alignmask) & gvartype->alignmask)
+ + gvartype->typesize;
+ {
+ register struct typelist *newtypelist;
+
+ newtypelist = qmalloc(sizeof *newtypelist);
+#ifdef TS
+++ts_n_newtypelist;
+ts_s_newtypelist += sizeof *newtypelist;
+#endif
+ newtypelist->tlnext = NULL;
+ newtypelist->tltype = gvartype;
+ if (*ptypelist == NULL)
+ structype->listtype = newtypelist;
+ else
+ (*ptypelist)->tlnext = newtypelist;
+ *ptypelist = newtypelist;
+ }
+ }
+ }
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+ semicolon();
+ *psoffset = offset;
+}
+
+PRIVATE bool_pt declspec()
+{
+ unsigned nsc;
+ unsigned ntype;
+ unsigned nunsigned;
+
+ gvarsc = NULLDECL;
+ gvartype = itype;
+ nunsigned = ntype = nsc = 0;
+ while (TRUE)
+ {
+ switch (sym)
+ {
+ case AUTODECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case ENUMDECL:
+ ++ntype;
+ declenum();
+ gvartype = itype; /* kludge - ignore type of enum */
+ break;
+ case EXTERNDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case REGDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case STATICDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case STRUCTDECL:
+ case UNIONDECL:
+ ++ntype;
+ gvartype = declsu();
+ break;
+ case TYPEDECL:
+ if (ntype == 1)
+ {
+ /* allow short int and long int */
+ if (gvartype == itype
+ && (gsymptr->type == stype || gsymptr->type == ltype))
+ ntype = 0;
+
+ /* allow int short and int long, blech */
+ if (gsymptr->type == itype
+ && (gvartype == stype || gvartype == ltype))
+ {
+ nextsym();
+ break;
+ }
+ }
+ ++ntype;
+ gvartype = gsymptr->type;
+ nextsym();
+ break;
+ case TYPEDEFDECL:
+ ++nsc;
+ gvarsc = sym;
+ nextsym();
+ break;
+ case TYPEDEFNAME:
+ if (ntype != 0)
+ goto break2;
+ ++ntype;
+ gvartype = gsymptr->type;
+ nextsym();
+ break;
+ case UNSIGNDECL:
+ ++nunsigned;
+ nextsym();
+ break;
+ default:
+ goto break2;
+ }
+ }
+break2:
+ if (nunsigned > 0)
+ {
+ if (ntype == 0)
+ {
+ gvartype = uitype;
+ ntype = 1;
+ }
+ gvartype = tounsigned(gvartype);
+ if (nunsigned > 1)
+ ntype = 2;
+ }
+ if (nsc > 0)
+ {
+ if (ntype == 0)
+ ntype = 1;
+ if (nsc > 1)
+ error("multiple storage classes in declaration");
+ }
+ if (ntype > 1)
+ error("multiple types in declaration");
+ return nsc > 0 || ntype > 0;
+}
+
+/* declsu - get structure or union name and/or declaration, return type */
+
+PRIVATE struct typestruct *declsu()
+{
+ sym_t ogvarsc;
+ offset_t soffset;
+ offset_t struclength;
+ sym_t susym;
+ struct typelist *typelist;
+ struct typestruct *structype;
+
+ susym = sym;
+ nextsym();
+ if (sym != IDENT && sym != TYPEDEFNAME)
+ structype = addstruct("");
+ else if ((gvarsymptr = findstruct(gsname)) == NULL)
+ {
+ structype = addstruct(gsname);
+ nextsym();
+ }
+ else
+ {
+ nextsym();
+ if (sym == LBRACE && gvarsymptr->level != level)
+ structype = addstruct(gvarsymptr->name.namea);
+ else
+ structype = gvarsymptr->type;
+ }
+ if (sym != LBRACE)
+ return structype;
+ if (structype->typesize != 0)
+ multidecl(structype->tname);
+ nextsym();
+ ogvarsc = gvarsc;
+ struclength = soffset = 0;
+ typelist = NULL;
+ while (sym != RBRACE && sym != EOFSYM)
+ {
+ declselt(structype, &soffset, &typelist);
+ if (susym == STRUCTDECL)
+ struclength = soffset;
+ else
+ {
+ if (struclength < soffset)
+ struclength = soffset;
+ soffset = 0;
+ }
+ }
+ structype->typesize = (struclength + ~structype->alignmask) &
+ structype->alignmask;
+ rbrace();
+ gvarsc = ogvarsc;
+ return structype;
+}
+
+/* declfunc() - function name and parameter list */
+
+PRIVATE void declfunc()
+{
+ offset_t argsp;
+ uoffset_t argsize;
+ struct symstruct *symptr;
+
+ strcpy(funcname, gvarname);
+ if (gvarsymptr == NULL)
+ gvarsymptr = addglb(gvarname, gvartype);
+ else if (gvarsymptr->type != gvartype ||
+ (gvarsymptr->flags & INITIALIZED))
+ multidecl(gvarname); /* different type or full declare */
+ gvarsymptr->flags = INITIALIZED; /* show full declare */
+ cseg();
+ if (gvarsc == STATICDECL)
+ private(gvarname); /* don't need to put STATIC in flags */
+ else
+ public(gvarname);
+ callee1mask = calleemask;
+#ifdef FRAMEPOINTER
+ frame1list = framelist;
+#endif
+ func1saveregsize = funcsaveregsize;
+#if 0
+ if ((returntype = gvartype->nexttype)->scalar & RSCALAR)
+#else
+ if ((returntype = gvartype->nexttype)->scalar & DOUBLE)
+#endif
+ {
+ callee1mask &= ~doublreturnregs;
+#ifdef FRAMEPOINTER
+ frame1list &= ~doublreturnregs;
+#endif
+ func1saveregsize = funcdsaveregsize;
+ }
+
+ arg1size = /* would already be 0 unless last function empty */
+#ifdef FRAMEPOINTER
+ framep =
+ stackarg =
+#endif
+ reguse = 0; /* would already be 0 unless last f had reg vars */
+ decllist();
+ argsp = returnadrsize;
+ if (returntype->constructor & STRUCTU)
+ argsp += ptypesize;
+ softsp = -func1saveregsize;
+ for (symptr = &locsyms[0];
+ symptr < locptr && symptr->flags != STRUCTNAME &&
+ *symptr->name.namea >= 'A';
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ {
+ /* convert arg sizes to offsets */
+ if (symptr->type == fltype)
+ symptr->type = dtype;
+ argsize = symptr->type->typesize;
+#ifdef FRAMEPOINTER
+ if (!arg1inreg || symptr != &locsyms[0] || symptr->flags != REGVAR)
+ stackarg = TRUE;
+#endif
+ if (arg1inreg && symptr == &locsyms[0] && symptr->flags != REGVAR)
+ {
+ if ((arg1size = argsize) < itypesize)
+ arg1size = itypesize;
+ argsp = softsp -= arg1size;
+ }
+#if BIG_ENDIAN
+ if (argsize < itypesize)
+ argsp += itypesize - argsize;
+ symptr->offset.offi = argsp;
+ argsp += argsize;
+#else
+ symptr->offset.offi = argsp;
+ if (argsize > itypesize)
+ argsp += argsize;
+ else
+ argsp += itypesize;
+#endif
+ if (arg1inreg && symptr == &locsyms[0])
+ argsp = returnadrsize; /* skip return adr after 1st arg */
+ }
+ lbrace();
+ compound();
+ clearfunclabels();
+}
+
+/* idecllist() - list of init-declarations with a given base type */
+/* this does the non-terminal symbols list( init-declarator ) ";" */
+/* and list( type-declaration ) ";" */
+/* and complete declarations of functions */
+
+PRIVATE void idecllist()
+{
+ struct typestruct *basetype;
+ struct typestruct *inittype;
+ scopelev_t levelmark;
+ uoffset_t newoffset;
+
+ argsallowed = level == GLBLEVEL;
+ levelmark = level;
+ basetype = gvartype;
+ while (sym != SEMICOLON)
+ {
+ gvartype = basetype;
+ declarator();
+ if (gvarname[0] == 0)
+ needvarname();
+ if (gvartype->constructor == FUNCTION)
+ {
+ if (sym != COMMA && sym != SEMICOLON)
+ {
+ if (level == ARGLEVEL && gvarsc != TYPEDEFDECL)
+ declfunc();
+ else
+ error("illegal non-external function");
+ if (level != levelmark)
+ {
+ oldlevel();
+ locptr = &locsyms[0];
+ }
+ argsallowed = FALSE;
+ return;
+ }
+ }
+ if (level != levelmark)
+ {
+ oldlevel();
+ locptr = &locsyms[0];
+ }
+ argsallowed = FALSE;
+ if (level == ARGLEVEL)
+ {
+ if (gvarsymptr == NULL)
+ gvarsymptr = addglb(gvarname, gvartype); /* error soon */
+ declarg();
+ }
+ else if (gvarsymptr != NULL && (gvarsymptr->level == level ||
+ gvartype->constructor == FUNCTION ||
+ (gvarsc == EXTERNDECL &&
+ gvarsymptr->level == GLBLEVEL)))
+ {
+ if (gvarsymptr->level != GLBLEVEL || gvarsymptr->flags == KEYWORD)
+ multidecl(gvarname);
+ else if (gvarsymptr->type != gvartype)
+ {
+ if (gvartype->constructor != ARRAY ||
+ gvarsymptr->type->constructor != ARRAY ||
+ gvartype->nexttype != gvarsymptr->type->nexttype ||
+ (gvartype->typesize != 0 &&
+ gvarsymptr->type->typesize != 0))
+ multidecl(gvarname);
+ else if (gvartype->typesize != 0)
+ gvarsymptr->type = gvartype;
+ }
+ if (gvarsc == NULLDECL)
+ gvarsymptr->flags &= ~EXTERNAL;
+ }
+ else if (level == GLBLEVEL || gvartype->constructor == FUNCTION ||
+ gvarsc == EXTERNDECL)
+ {
+ gvarsymptr = addglb(gvarname, gvartype);
+#ifdef DIRECTPAGE /* make all global scalar and pointer variables DIRECTPAGE */
+ if (!(gvartype->constructor & ~POINTER))
+ gvarsymptr->flags = DIRECTPAGE;
+#endif
+ if (gvarsc == EXTERNDECL)
+ gvarsymptr->flags |= EXTERNAL;
+ }
+ else
+ {
+ gvarsymptr = addloc(gvarname, gvartype);
+ if ((gvarsc != REGDECL || !regdecl()) &&
+ gvartype->constructor != FUNCTION && gvarsc != STATICDECL &&
+ gvarsc != TYPEDEFDECL)
+ gvarsymptr->offset.offi = softsp =
+ (softsp & gvartype->alignmask) - gvartype->typesize;
+ }
+ if (gvarsc == STATICDECL)
+ {
+ gvarsymptr->flags &= ~EXTERNAL;
+ gvarsymptr->flags |= STATIC;
+ if (gvarsymptr->level != GLBLEVEL)
+ {
+ gvarsymptr->storage = GLOBAL;
+ gvarsymptr->offset.offlabel = getlabel();
+ /* must leave gvarsymptr->name.label alone */
+ /* since name is required for findlorg() */
+ /* label is activated by expression() */
+ }
+ }
+ if (gvarsc == TYPEDEFDECL)
+ {
+ gvarsymptr->flags = KEYWORD;
+ gvarsymptr->offset.offsym = TYPEDEFNAME;
+ }
+ if (sym == ASSIGNOP)
+ {
+ if (gvarsymptr->flags & INITIALIZED)
+ multidecl(gvarname);
+ nextsym();
+ if (level == GLBLEVEL || gvarsc == STATICDECL)
+ {
+#ifndef DIRECTPAGE
+ dseg();
+#else
+ if (gvarsymptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ if ((inittype = gvartype)->constructor == ARRAY)
+ inittype = inittype->nexttype;
+ newoffset = (dataoffset + ~inittype->alignmask)
+ & inittype->alignmask;
+ defnulls(newoffset - dataoffset);
+ dataoffset = newoffset;
+ if (gvarsc == STATICDECL)
+ {
+ if (level == GLBLEVEL)
+ private(gvarname);
+ else
+ outnlabel(gvarsymptr->offset.offlabel);
+ }
+ else
+ public(gvarname);
+ initlistflag = TRUE;
+ if (sym != LBRACE)
+ initlistflag = FALSE;
+ inititem(gvartype);
+ dataoffset += (gvarsymptr->type = gvartype)->typesize;
+ if (gvarsymptr->level == GLBLEVEL)
+ gvarsymptr->flags |= INITIALIZED;
+ if (level != GLBLEVEL)
+ cseg();
+ }
+ else
+ {
+ if (gvarsc == EXTERNDECL)
+ error("initialization of externs is illegal");
+ switch (gvartype->constructor)
+ {
+ case ARRAY:
+ error("initialization of auto arrays is illegal");
+ break;
+ case FUNCTION:
+ error("initialization of functions is illegal");
+ break;
+ default:
+ initexpression(gvartype);
+ break;
+ }
+ }
+ }
+ else if (level != GLBLEVEL && gvarsc == STATICDECL &&
+ gvartype->constructor != FUNCTION)
+ {
+#ifndef DIRECTPAGE
+ bssseg();
+#else
+ if (gvarsymptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ lcommlab(gvarsymptr->offset.offlabel);
+ outnhex(gvartype->typesize);
+ cseg();
+ }
+ if (sym != COMMA)
+ break;
+ nextsym();
+ }
+ semicolon();
+ argsallowed = FALSE;
+}
+
+PRIVATE void initarray(type)
+struct typestruct *type;
+{
+ uoffset_t basesize;
+ struct typestruct *basetype;
+ uoffset_t dimension;
+ char *stringend;
+ uoffset_t stringlength;
+ uoffset_t remaining;
+
+ if ((basesize = (basetype = type->nexttype)->typesize) == 0)
+ dimension = remaining = 0;
+ else
+ dimension = remaining = type->typesize / basesize;
+ if (sym == STRINGCONST && (basetype->scalar & CHAR))
+ {
+ stringlength = (stringend = charptr) - constant.value.s;
+ if (remaining != 0 && stringlength >= remaining)
+ /* same dim should be allowed but defstr always nullterms */
+ {
+ error("string longer than dimension");
+ stringend = constant.value.s + (/* size_t */ unsigned)
+ (stringlength = remaining - 1);
+ }
+ defstr(constant.value.s, stringend, TRUE);
+ remaining -= (stringlength + 1);
+ nextsym();
+ }
+ else
+ do
+ inititem(basetype);
+ while (--remaining != 0 && sym == COMMA && initlistflag &&
+ (nextsym(), sym != RBRACE));
+ if (dimension == 0)
+ {
+ if (type == gvartype)
+ gvartype = prefix(ARRAY, -remaining * basesize, basetype);
+ }
+ else
+ defnulls(remaining * basesize);
+}
+
+PRIVATE void inititem(type)
+struct typestruct *type;
+{
+ sym_t startsym;
+
+ if ((startsym = sym) == LBRACE)
+ nextsym();
+ switch (type->constructor)
+ {
+ case ARRAY:
+ initarray(type);
+ break;
+ case STRUCTU:
+ initstruct(type);
+ break;
+ case FUNCTION:
+ error("initialization of functions is illegal");
+ break;
+ default:
+ initexpression(type);
+ }
+ if (startsym == LBRACE)
+ {
+ if (sym == COMMA)
+ {
+ nextsym();
+ if (sym != RBRACE)
+ error("too many initializers");
+ }
+ rbrace();
+ }
+}
+
+PRIVATE void initstruct(type)
+struct typestruct *type;
+{
+ struct typestruct *memtype;
+ uoffset_t newoffset;
+ uoffset_t offset;
+ struct typelist *typelist;
+
+ offset = 0;
+ if ((typelist = type->listtype) != NULL)
+ do
+ {
+ memtype = typelist->tltype;
+ newoffset = (offset + ~memtype->alignmask) & memtype->alignmask;
+ defnulls(newoffset - offset);
+ offset = newoffset + memtype->typesize;
+ inititem(memtype);
+ }
+ while ((typelist = typelist->tlnext) != NULL && sym == COMMA &&
+ initlistflag && (nextsym(), sym != RBRACE));
+ /* eof here will break next time */
+ defnulls(type->typesize - offset);
+}
+
+PRIVATE void lbrace()
+{
+ if (sym != LBRACE)
+ need('{');
+ else
+ nextsym();
+}
+
+PUBLIC void lparen()
+{
+ if (sym != LPAREN)
+ need('(');
+ else
+ nextsym();
+}
+
+PRIVATE void multidecl(sname)
+char *sname;
+{
+ error2error(sname, " already declared");
+}
+
+PRIVATE void need(charneeded)
+int charneeded;
+{
+ static char message[] = "need 'x'";
+
+ message[6] = charneeded;
+ error(message);
+}
+
+PUBLIC void needvarname()
+{
+ error("need variable name");
+ nextsym();
+}
+
+PUBLIC void program()
+{
+ if (orig_cppmode)
+ cppscan();
+ else
+ {
+ nextsym();
+ while (sym != EOFSYM)
+ {
+ declspec();
+ idecllist();
+ }
+ }
+}
+
+PUBLIC void rbrace()
+{
+ if (sym != RBRACE)
+ need('}');
+ else
+ nextsym();
+}
+
+PUBLIC void rbracket()
+{
+ if (sym != RBRACKET)
+ need(']');
+ else
+ nextsym();
+}
+
+PRIVATE void rdeclarator()
+{
+ while (sym == STAR)
+ {
+ nextsym();
+ gvartype = pointype(gvartype);
+ }
+ if (sym == LPAREN)
+ {
+ struct typestruct *pretype;
+ struct typestruct *sufftype;
+
+ nextsym();
+ sufftype = gvartype;
+ gvartype = ctype;
+ rdeclarator();
+ rparen();
+ pretype = gvartype;
+ gvartype = sufftype;
+ declaf();
+ gvartype = chainprefix(pretype, gvartype);
+ }
+ else if (sym == IDENT || sym == TYPEDEFNAME)
+ {
+ strcpy(gvarname, gsname);
+ gvarsymptr = gsymptr;
+ nextsym();
+ }
+ else
+ {
+ gvarname[0] = 0;
+ gvarsymptr = NULL;
+ }
+ declaf();
+}
+
+PRIVATE bool_pt regdecl()
+{
+ store_t regavail;
+
+#if !NOTFINISHED
+ if (gvarsymptr->type->constructor != POINTER)
+ return FALSE;
+#endif
+#ifdef MC6809
+ if (gvarsymptr->type->constructor != POINTER)
+ return FALSE;
+#endif
+ if (!(regavail = regregs & ~reguse))
+ return FALSE;
+ gvarsymptr->flags = REGVAR;
+ gvarsymptr->indcount = 0;
+#define LOWBITMASK(bits) (bits - (bits & (bits - 1))) /* & chops low bit */
+ reguse |= gvarsymptr->storage = LOWBITMASK(regavail);
+ return TRUE;
+}
+
+PUBLIC void rparen()
+{
+ if (sym != RPAREN)
+ need(')');
+ else
+ nextsym();
+}
+
+PUBLIC void semicolon()
+{
+ if (sym != SEMICOLON)
+ need(';');
+ else
+ nextsym();
+}
+
+PUBLIC struct typestruct *typename()
+{
+ char ogvarname[NAMESIZE];
+ sym_t ogvarsc;
+ struct symstruct *ogvarsymptr;
+ struct typestruct *ogvartype;
+ struct typestruct *type;
+
+ /* the global variable data must be preserved */
+ /* although this is only called for casts and sizeof, */
+ /* the casts can be in initialisers */
+ /* and the sizeof in an array size expression */
+ strcpy(ogvarname, gvarname);
+ ogvarsc = gvarsc;
+ ogvarsymptr = gvarsymptr;
+ ogvartype = gvartype;
+ if (declspec())
+ {
+ declarator();
+ if (gvarsc != NULLDECL || gvarname[0] != 0)
+ error("illegal type name");
+ type = gvartype;
+ }
+ else
+ type = NULL;
+ strcpy(gvarname, ogvarname);
+ gvarsc = ogvarsc;
+ gvarsymptr = ogvarsymptr;
+ gvartype = ogvartype;
+ return type;
+}
diff --git a/bcc/express.c b/bcc/express.c
new file mode 100644
index 0000000..e6ee64c
--- /dev/null
+++ b/bcc/express.c
@@ -0,0 +1,466 @@
+/* express.c - expression parsing routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "table.h" /* just for charptr for string constant */
+#include "type.h"
+
+PRIVATE unsigned insizeof; /* nest level for getsizeof */
+ /* used to avoid aborting undefined idents */
+ /* to 0 when they appear in a cpp expression */
+ /* under sizeof */
+
+/* names of expression functions are related to the 15 precedence levels */
+/* on p49 of K & R */
+
+FORWARD struct nodestruct *cast_exp P((void));
+FORWARD struct nodestruct *exp2 P((void));
+FORWARD struct nodestruct *exp3to12 P((fastin_pt lprecedence));
+FORWARD struct nodestruct *listargs P((void));
+FORWARD struct nodestruct *postfix_exp P((bool_pt seenlp));
+FORWARD struct nodestruct *primary_exp P((void));
+FORWARD struct nodestruct *unary_exp P((void));
+
+PRIVATE struct nodestruct *cast_exp()
+{
+ struct nodestruct *nodeptr;
+ scalar_t scalar;
+ struct typestruct *vartype;
+
+ if (sym != LPAREN)
+ return unary_exp();
+ nextsym();
+ if ((vartype = typename()) == NULL)
+ return postfix_exp(TRUE);
+ rparen();
+ scalar = (nodeptr = cast_exp())->nodetype->scalar;
+ if (vartype->scalar & INT && scalar & (CHAR | SHORT | INT)
+ && !((vartype->scalar ^ scalar) & UNSIGNED))
+ {
+ nodeptr->flags &= ~LVALUE;
+ return nodeptr; /* skip casts that are default promotions */
+ }
+ return castnode(vartype, nodeptr);
+}
+
+PUBLIC struct nodestruct *assignment_exp()
+{
+ struct nodestruct *lhs;
+ op_pt op;
+
+ lhs = exp2();
+ if (sym >= ASSIGNOP && sym <= SUBABOP) /* assign-op syms in order! */
+ {
+ op = sym;
+ nextsym();
+ lhs = node(op, lhs, assignment_exp());
+ }
+ return lhs;
+}
+
+PUBLIC struct nodestruct *expression()
+{
+ struct nodestruct *lhs;
+
+ lhs = assignment_exp();
+ while (sym == COMMA)
+ {
+ nextsym();
+ lhs = node(COMMAOP, lhs, assignment_exp());
+ }
+ return lhs;
+}
+
+PRIVATE struct nodestruct *exp2()
+{
+ struct nodestruct *lhs;
+ struct nodestruct *rhs;
+
+ lhs = exp3to12(0);
+ if (sym == CONDOP)
+ {
+ nextsym();
+ rhs = expression();
+ colon();
+ lhs = node(CONDOP, lhs, node(COLONOP, rhs, exp2()));
+ }
+ return lhs;
+}
+
+PRIVATE struct nodestruct *exp3to12(lprecedence)
+fastin_pt lprecedence;
+{
+ struct nodestruct *lhs;
+ op_pt op;
+ fastin_t rprecedence;
+
+ lhs = cast_exp();
+ while (TRUE)
+ {
+ rprecedence = 0;
+ switch (sym)
+ {
+ case LOGOROP:
+ if ((fastin_t) lprecedence <= 1)
+ rprecedence = 2;
+ break;
+ case LOGANDOP:
+ if ((fastin_t) lprecedence <= 3)
+ rprecedence = 4;
+ break;
+ case OROP:
+ if ((fastin_t) lprecedence <= 5)
+ rprecedence = 6;
+ break;
+ case EOROP:
+ if ((fastin_t) lprecedence <= 7)
+ rprecedence = 8;
+ break;
+ case AMPERSAND:
+ if ((fastin_t) lprecedence <= 9)
+ {
+ sym = ANDOP;
+ rprecedence = 10;
+ }
+ break;
+ case EQOP:
+ case NEOP:
+ if ((fastin_t) lprecedence <= 11)
+ rprecedence = 12;
+ break;
+ case GEOP:
+ case GTOP:
+ case LEOP:
+ case LTOP:
+ if ((fastin_t) lprecedence <= 13)
+ rprecedence = 14;
+ break;
+ case SLOP:
+ case SROP:
+ if ((fastin_t) lprecedence <= 15)
+ rprecedence = 16;
+ break;
+ case HYPHEN:
+ if ((fastin_t) lprecedence <= 17)
+ {
+ sym = SUBOP;
+ rprecedence = 18;
+ }
+ break;
+ case ADDOP:
+ if ((fastin_t) lprecedence <= 17)
+ rprecedence = 18;
+ break;
+ case STAR:
+ if ((fastin_t) lprecedence <= 19)
+ {
+ sym = MULOP;
+ rprecedence = 20;
+ }
+ break;
+ case DIVOP:
+ case MODOP:
+ if ((fastin_t) lprecedence <= 19)
+ rprecedence = 20;
+ break;
+ }
+ if (rprecedence == 0)
+ break;
+ op = sym;
+ nextsym();
+ lhs = node(op, lhs, exp3to12(rprecedence));
+ }
+ return lhs;
+}
+
+PRIVATE struct nodestruct *listargs()
+{
+ struct nodestruct *parent;
+ struct nodestruct *nextright;
+
+ if (sym == RPAREN)
+ {
+ nextsym();
+ return NULLNODE;
+ }
+ parent = node(arg1op, assignment_exp(), NULLNODE);
+ nextright = parent;
+ while (sym == COMMA)
+ {
+ nextsym();
+ nextright = nextright->right
+ = node(LISTOP, assignment_exp(), NULLNODE);
+ }
+ rparen();
+ return parent;
+}
+
+PRIVATE struct nodestruct *postfix_exp(seenlp)
+bool_pt seenlp;
+{
+ struct nodestruct *nodeptr;
+ struct symstruct *symptr;
+
+ if (seenlp)
+ {
+ nodeptr = expression();
+ rparen();
+ }
+ else
+ nodeptr = primary_exp();
+ while (TRUE)
+ {
+ switch (sym)
+ {
+ case DECSYM:
+ nextsym();
+ nodeptr = node(POSTDECOP, nodeptr, NULLNODE);
+ continue;
+ case INCSYM:
+ nextsym();
+ nodeptr = node(POSTINCOP, nodeptr, NULLNODE);
+ continue;
+ case LBRACKET:
+ nextsym();
+ nodeptr = node(INDIRECTOP, node(ADDOP, nodeptr, expression()),
+ NULLNODE);
+ rbracket();
+ continue;
+ case LPAREN:
+ nextsym();
+ nodeptr = node(FUNCOP, nodeptr, listargs());
+ {
+ register struct nodestruct *np;
+
+ for (np = nodeptr->right; np != NULL; np = np->right)
+ {
+ if (np->nodetype->scalar & RSCALAR)
+ {
+ np = nodeptr->left.nodeptr;
+ if (np->tag != LEAF)
+ printf_fp = TRUE;
+ else
+ {
+ unsigned len;
+ register char *name;
+
+ name = np->left.symptr->name.namep;
+ if ((len = strlen(name)) >= 6
+ && strcmp(name + len - 6, "printf") == 0)
+ printf_fp = TRUE;
+ }
+ break;
+ }
+ }
+ for (np = nodeptr->right; np != NULL; np = np->right)
+ {
+ if (np->nodetype->constructor & POINTER
+ && np->nodetype->nexttype->scalar & RSCALAR)
+ {
+ np = nodeptr->left.nodeptr;
+ if (np->tag != LEAF)
+ scanf_fp = TRUE;
+ else
+ {
+ unsigned len;
+ register char *name;
+
+ name = np->left.symptr->name.namep;
+ if ((len = strlen(name)) >= 5
+ && strcmp(name + len - 5, "scanf") == 0)
+ scanf_fp = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ continue;
+ case STRUCPTROP:
+ nodeptr = node(INDIRECTOP, nodeptr, NULLNODE);
+ case STRUCELTOP:
+ nextsym();
+ gs2name[0] = nodeptr->nodetype->structkey[0];
+ gs2name[1] = nodeptr->nodetype->structkey[1];
+ if ((gsymptr = findlorg(gs2name)) == NULL)
+ {
+ error("undefined structure element");
+ gsymptr = addglb(gs2name, itype);
+ }
+ symptr = exprsym(gsymptr);
+ nextsym();
+ nodeptr = node(STRUCELTOP, nodeptr, leafnode(symptr));
+ continue;
+ default:
+ return nodeptr;
+ }
+ }
+}
+
+PRIVATE struct nodestruct *primary_exp()
+{
+ bool_t isdefined;
+ struct nodestruct *nodeptr;
+ uoffset_t stringlen;
+ struct symstruct *symptr;
+ struct symstruct *symptr1;
+ bool_t waslparen;
+
+ switch (sym)
+ {
+ case IDENT:
+ if (incppexpr && !insizeof)
+ {
+cpp_ident:
+ nextsym();
+ return leafnode(constsym((value_t) 0));
+ }
+ if ((symptr = gsymptr) != NULL)
+ nextsym();
+ else
+ {
+ symptr = addglb(gsname, fitype);
+ nextsym();
+ if (sym != LPAREN)
+ {
+ error2error(symptr->name.namea, " undeclared");
+ symptr->indcount = 1;
+ symptr->type = itype;
+ }
+ }
+ symptr1 = exprsym(symptr);
+ if (symptr->flags & STATIC && symptr->level != GLBLEVEL)
+ {
+ symptr1->flags |= LABELLED;
+ symptr1->offset.offi = 0;
+ symptr1->name.label = symptr->offset.offlabel;
+ }
+ nodeptr = leafnode(symptr1);
+ if (!(nodeptr->nodetype->constructor & (ARRAY | FUNCTION | VOID)))
+ nodeptr->flags = LVALUE;
+ return nodeptr;
+ case TYPEDEFNAME:
+ if (incppexpr && !insizeof)
+ goto cpp_ident; /* else fall through */
+ default:
+ error("bad expression");
+ constant.value.v = 0;
+ constant.type = itype;
+ case CHARCONST:
+ case INTCONST: /* this includes enumeration-constants */
+ symptr = constsym(constant.value.v);
+ symptr->type = constant.type;
+ if (!(ltype->scalar & LONG))
+ {
+ if (symptr->type == ltype)
+ symptr->type = itype;
+ else if (symptr->type == ultype)
+ symptr->type = uitype;
+ }
+ nextsym();
+ return leafnode(symptr);
+ case DEFINEDSYM:
+ waslparen = isdefined = FALSE;
+ if (!blanksident())
+ {
+ nextsym();
+ if (sym != LPAREN)
+ lparen();
+ else
+ waslparen = TRUE;
+ }
+ if (waslparen && !blanksident())
+ needvarname();
+ else
+ {
+ if ((symptr = findlorg(gsname)) != NULL &&
+ symptr->flags == DEFINITION)
+ isdefined = TRUE;
+ nextsym();
+ }
+ if (waslparen)
+ rparen();
+ return leafnode(constsym((value_t) isdefined));
+ case FLOATCONST:
+ symptr = constsym((value_t) 0);
+ symptr->type = constant.type;
+ symptr->offset.offd = qmalloc(sizeof *symptr->offset.offd);
+ *symptr->offset.offd = constant.value.d;
+ nextsym();
+ return leafnode(symptr);
+ case LPAREN:
+ nextsym();
+ nodeptr = expression();
+ rparen();
+ return nodeptr;
+ case STRINGCONST:
+ symptr = constsym((value_t) 0);
+ symptr->storage = GLOBAL;
+ symptr->flags = LABELLED | STRING;
+ /* string length before defstr() or prefix() updates charptr */
+ stringlen = charptr - constant.value.s + 1;
+ symptr->name.label = defstr(constant.value.s, charptr, FALSE);
+ symptr->type = prefix(ARRAY, stringlen, ctype);
+ nextsym();
+ return leafnode(symptr);
+ }
+}
+
+PRIVATE struct nodestruct *unary_exp()
+{
+ value_t size;
+ struct typestruct *vartype;
+
+ switch (sym)
+ {
+ case ADDOP:
+ nextsym();
+ return cast_exp();
+ case AMPERSAND:
+ nextsym();
+ return node(ADDRESSOP, cast_exp(), NULLNODE); /* maybe unary_exp */
+ case DECSYM:
+ nextsym();
+ return node(PREDECOP, unary_exp(), NULLNODE);
+ case HYPHEN:
+ nextsym();
+ return node(NEGOP, cast_exp(), NULLNODE);
+ case INCSYM:
+ nextsym();
+ return node(PREINCOP, unary_exp(), NULLNODE);
+ case LOGNOTOP:
+ nextsym();
+ return node(LOGNOTOP, cast_exp(), NULLNODE);
+ case NOTOP:
+ nextsym();
+ return node(NOTOP, cast_exp(), NULLNODE);
+ case SIZEOFSYM:
+ nextsym();
+ ++insizeof;
+ if (sym != LPAREN)
+ size = unary_exp()->nodetype->typesize;
+ else
+ {
+ nextsym();
+ if ((vartype = typename()) != NULL)
+ {
+ rparen();
+ size = vartype->typesize;
+ }
+ else
+ size = postfix_exp(TRUE)->nodetype->typesize;
+ }
+ --insizeof;
+ return leafnode(constsym(size));
+ case STAR:
+ nextsym();
+ return node(INDIRECTOP, cast_exp(), NULLNODE); /* maybe unary_exp */
+ }
+ return postfix_exp(FALSE);
+}
diff --git a/bcc/exptree.c b/bcc/exptree.c
new file mode 100644
index 0000000..c4da1c4
--- /dev/null
+++ b/bcc/exptree.c
@@ -0,0 +1,1087 @@
+/* exptree.c - expression tree routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#define ETREESIZE 1200
+#define errtype itype
+#define redtype ctype
+#define uredtype uctype
+
+PRIVATE struct nodestruct etree[ETREESIZE]; /* expression tree */
+PRIVATE struct nodestruct *ettop;
+
+FORWARD void badlvalue P((struct nodestruct *nodeptr));
+FORWARD void binconvert P((struct nodestruct *nodeptr));
+FORWARD void castiright P((struct nodestruct *nodeptr));
+FORWARD void etreefull P((void));
+FORWARD void fixnode P((struct nodestruct *nodeptr));
+FORWARD bool_pt isconst0 P((struct nodestruct *nodeptr));
+FORWARD bool_pt isnodecharconst P((struct nodestruct *nodeptr));
+FORWARD void needint P((struct nodestruct *nodeptr));
+FORWARD void neednonstruct P((struct nodestruct *nodeptr));
+FORWARD void needscalar P((struct nodestruct *nodeptr));
+FORWARD void needspv P((struct nodestruct *nodeptr));
+FORWARD struct typestruct *nodetype P((struct nodestruct *nodeptr));
+FORWARD int redscalar P((struct nodestruct *nodeptr));
+FORWARD struct nodestruct *unconvert P((struct nodestruct *nodeptr));
+
+PRIVATE void badlvalue(nodeptr)
+struct nodestruct *nodeptr;
+{
+ error("invalid lvalue");
+ fixnode(nodeptr);
+}
+
+PRIVATE void binconvert(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ bool_t bothscalar;
+ value_t divisor;
+ scalar_t lscalar;
+ register struct nodestruct *right;
+ scalar_t rscalar;
+
+ rscalar = (right = nodeptr->right)->nodetype->scalar;
+ lscalar = nodeptr->left.nodeptr->nodetype->scalar;
+ if ((bothscalar = lscalar | rscalar) & RSCALAR)
+ {
+ nodeptr->nodetype = dtype;
+ if (!(lscalar & DOUBLE))
+ nodeptr->left.nodeptr = castnode(dtype, nodeptr->left.nodeptr);
+ if (!(rscalar & DOUBLE))
+ nodeptr->right = castnode(dtype, right);
+ }
+ else if (!(bothscalar & DLONG) && ((nodeptr->tag == ANDOP &&
+ (redscalar(nodeptr->left.nodeptr) | redscalar(right)) & CHAR) ||
+ ((nodeptr->tag == EOROP || nodeptr->tag == OROP) &&
+ redscalar(nodeptr->left.nodeptr) & redscalar(right) & CHAR) ||
+ (nodeptr->tag == MODOP && right->tag == LEAF &&
+ right->left.symptr->storage == CONSTANT &&
+ (divisor = right->left.symptr->offset.offv,
+ (uvalue_t) divisor <= MAXUCHTO + 1) &&
+ bitcount((uvalue_t) divisor) <= 1)))
+ {
+ /* result fits in char and extends correctly */
+ if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = uredtype;
+ else
+ nodeptr->nodetype = redtype;
+ }
+ else if (bothscalar & LONG)
+ {
+ nodeptr->nodetype = ltype;
+ if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = ultype;
+ if (bothscalar & (DLONG | SHORT | INT))
+ {
+ /* XXX - otherwise both are long, or one is long with the same
+ * size as int and the other is char, and we want the lower level
+ * routines to handle the char.
+ */
+ if (!(lscalar & LONG))
+ nodeptr->left.nodeptr = castnode(nodeptr->nodetype,
+ nodeptr->left.nodeptr);
+ if (!(rscalar & LONG))
+ nodeptr->right = castnode(nodeptr->nodetype, right);
+ }
+ }
+#ifdef I8088
+ else if (i386_32 && bothscalar & SHORT)
+ {
+ nodeptr->nodetype = itype;
+ if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = uitype;
+ if (lscalar & SHORT)
+ nodeptr->left.nodeptr = castnode(nodeptr->nodetype,
+ nodeptr->left.nodeptr);
+ if (rscalar & SHORT)
+ nodeptr->right = castnode(nodeptr->nodetype, right);
+ }
+#endif
+ else if (bothscalar & UNSIGNED)
+ nodeptr->nodetype = uitype;
+ else
+ nodeptr->nodetype = itype;
+}
+
+PRIVATE void castiright(nodeptr)
+struct nodestruct *nodeptr;
+{
+ nodeptr->right = castnode(itype, nodeptr->right);
+}
+
+PUBLIC struct nodestruct *castnode(type, nodeptr)
+struct typestruct *type;
+struct nodestruct *nodeptr;
+{
+ struct symstruct *symptr;
+
+ (symptr = constsym((value_t) 0))->type = type;
+ return node(CASTOP, nodeptr, leafnode(symptr));
+}
+
+PRIVATE void etreefull()
+{
+ limiterror("expression too complex (1201 nodes)");
+}
+
+PUBLIC void etreeinit()
+{
+ ettop = (etptr = etree) + ETREESIZE;
+}
+
+PRIVATE void fixnode(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ nodeptr->tag = LEAF;
+ nodeptr->flags = nodeptr->weight = 0;
+ nodeptr->left.symptr = constsym((value_t) 0); /* this has type errtype */
+ nodeptr->nodetype = errtype;
+}
+
+PRIVATE bool_pt isconst0(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ register struct symstruct *symptr;
+
+ return nodeptr->tag == LEAF &&
+ (symptr = nodeptr->left.symptr)->storage == CONSTANT &&
+ symptr->offset.offv == 0 &&
+ symptr->type->scalar & ISCALAR;
+}
+
+PRIVATE bool_pt isnodecharconst(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ register struct symstruct *symptr;
+
+ if (nodeptr->tag == LEAF &&
+ (symptr = nodeptr->left.symptr)->storage == CONSTANT &&
+ ischarconst(symptr->offset.offv) &&
+ symptr->type->scalar & ISCALAR)
+ return TRUE;
+ return FALSE;
+}
+
+PUBLIC struct nodestruct *leafnode(source)
+struct symstruct *source;
+{
+ register struct nodestruct *leafptr;
+
+ if ((leafptr = etptr++) >= ettop)
+ etreefull();
+ leafptr->tag = LEAF;
+ leafptr->flags = leafptr->weight = 0;
+ leafptr->nodetype = source->type;
+ leafptr->left.symptr = source;
+ leafptr->right = NULL;
+ return leafptr;
+}
+
+PRIVATE void needint(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (!(nodeptr->nodetype->scalar & ISCALAR))
+ {
+ error("need integral type");
+ fixnode(nodeptr);
+ }
+}
+
+PRIVATE void neednonstruct(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (nodeptr->nodetype->constructor & STRUCTU)
+ {
+ error("need non-structure type");
+ fixnode(nodeptr);
+ }
+}
+
+PRIVATE void needscalar(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (!nodeptr->nodetype->scalar)
+ {
+ error("need scalar");
+ fixnode(nodeptr);
+ }
+}
+
+PRIVATE void needspv(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION | STRUCTU))
+ {
+ error("need scalar or pointer or void");
+ fixnode(nodeptr);
+ }
+}
+
+PUBLIC struct nodestruct *node(t, p1, p2)
+op_pt t;
+struct nodestruct *p1;
+struct nodestruct *p2;
+{
+#if MAXREGS != 1
+ weight_t rightweight;
+#endif
+ double dsourceval = 0; /* for -Wall */
+ double dtargval = 0 ; /* for -Wall */
+ bool_t lflag;
+ scalar_t lscalar;
+ struct nodestruct *pswap;
+ struct symstruct *source = NULL; /* for -Wall */
+ value_t sourceval = 0 ; /* for -Wall */
+ struct symstruct *target;
+ offset_t targszdelta;
+ value_t targval = 0; /* for -Wall */
+ scalar_t rscalar = 0; /* for -Wall */
+ bool_t uflag;
+
+ switch ((op_t) t)
+ {
+ case ADDABOP:
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ t = PTRADDABOP;
+ break;
+ case ADDOP:
+ if (p2->nodetype->constructor & (ARRAY | POINTER))
+ {
+ pswap = p1;
+ p1 = p2;
+ p2 = pswap;
+ }
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ t = PTRADDOP;
+ break;
+ case CONDOP:
+ /* Change structs to struct pointers so condop() doesn't have to know
+ * about structs.
+ */
+ if (p2->nodetype->constructor & STRUCTU)
+ {
+ p2 = node(COLONOP, node(ADDRESSOP, p2->left.nodeptr, NULLNODE),
+ node(ADDRESSOP, p2->right, NULLNODE));
+ return node(INDIRECTOP, node(CONDOP, p1, p2), NULLNODE);
+ }
+ break;
+ case FUNCOP:
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ p1 = node(INDIRECTOP, p1, NULLNODE);
+ break;
+ case SUBABOP:
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ {
+ t = PTRADDABOP;
+ p2 = node(NEGOP, p2, NULLNODE);
+ break;
+ }
+ case SUBOP:
+#if 0
+ /* This works but sometimes pessimizes the code by converting small
+ * constants into large negative constants. It makes the most
+ * difference for longs by avoiding stack tangles. longop could be
+ * more careful. Only the case (regpair) - constant is naturally
+ * tangled.
+ */
+ if (p2->tag == LEAF && p2->nodetype->scalar
+ && (source = p2->left.symptr)->storage == CONSTANT)
+ {
+ if (source->type->scalar & RSCALAR)
+ *source->offset.offd = -*source->offset.offd;
+ else
+ source->offset.offv = -source->offset.offv;
+ return node((op_t) t == SUBOP ? ADDOP : ADDABOP, p1, p2);
+ }
+#endif
+ if (p1->nodetype->constructor & (ARRAY | POINTER))
+ {
+ if (p2->nodetype->nexttype == p1->nodetype->nexttype)
+ t = PTRSUBOP;
+ else
+ {
+ t = PTRADDOP;
+ p2 = node(NEGOP, p2, NULLNODE);
+ }
+ }
+ break;
+ }
+ if (((op_t) t == PTRADDABOP || (op_t) t == PTRADDOP) &&
+ p1->nodetype->nexttype->constructor & (FUNCTION | VOID))
+ error("arithmetic on pointer to function or void");
+ if (p1->tag != LEAF)
+ goto node1;
+ target = p1->left.symptr;
+ switch ((op_t) t)
+ {
+ case ADDRESSOP:
+ if (target->indcount == 0 && target->flags == REGVAR)
+ error("register variable addressed");
+ else if (target->type->constructor & ARRAY)
+ {
+ if (target->indcount != 0)
+ bugerror("botched array indirection count");
+ target->type = pointype(target->type);
+ }
+ else if (!(p1->flags & LVALUE))
+ badlvalue(p1);
+ else
+ {
+ address(target); /* change p1, no code generated */
+ if (target->indcount == 2) /* XXX - MAXINDIRECT? */
+ /* just became direct enough */
+ p1->weight = 1;
+ }
+ p1->flags &= ~LVALUE;
+ p1->nodetype = target->type;
+ return p1;
+ case CASTOP:
+ needspv(p2);
+ if (p1->nodetype == p2->nodetype)
+ {
+ p1->flags &= ~LVALUE;
+ return p1;
+ }
+ if ((rscalar = p2->nodetype->scalar) & ISCALAR)
+ neednonstruct(p1);
+ else if (rscalar & RSCALAR)
+ needscalar(p1);
+ else /* POINTER */
+ neednonstruct(p1); /* H & S say functions & arrays must match */
+ if (((lscalar = p1->nodetype->scalar) | rscalar) & RSCALAR)
+ {
+ if (target->storage != CONSTANT)
+ goto node1;
+ if (lscalar & RSCALAR && !(rscalar & RSCALAR))
+ {
+ double val;
+ static double MAXULONG = (double)0xFFFFFFFFL +1;
+
+ val = *target->offset.offd;
+ if (val > maxlongto)
+ val -= MAXULONG;
+ target->offset.offv = (value_t) val;
+ }
+ if (!(lscalar & RSCALAR) && rscalar & RSCALAR)
+ {
+ value_t val;
+
+ val = target->offset.offv;
+ target->offset.offd = qmalloc(sizeof *target->offset.offd);
+ if (lscalar & UNSIGNED)
+ *target->offset.offd = (uvalue_t) val;
+ else
+ *target->offset.offd = val;
+ }
+ }
+ if (target->storage == CONSTANT)
+ {
+ if (rscalar & CHAR)
+ target->offset.offv &= CHMASKTO;
+ else if (rscalar & SHORT)
+ {
+ target->offset.offv &= shortmaskto;
+ if (!(rscalar & UNSIGNED) && target->offset.offv > maxshortto)
+ target->offset.offv -= (maxushortto + 1);
+ }
+ else if (rscalar & INT)
+ {
+ target->offset.offv &= intmaskto;
+ if (!(rscalar & UNSIGNED) && target->offset.offv > maxintto)
+ target->offset.offv -= (maxuintto + 1);
+ }
+ else if (rscalar & FLOAT)
+ *target->offset.offd = (float) *target->offset.offd;
+ }
+ else if ((targszdelta =
+ ((p1->nodetype->constructor & (ARRAY | POINTER)) ?
+ ptypesize : p1->nodetype->typesize) -
+ p2->nodetype->typesize) == 0)
+ ;
+ else if (target->indcount == 1 && targszdelta > 0 &&
+ target->flags != REGVAR)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+# if BIG_ENDIAN
+ target->offset.offi += targszdelta;
+# else
+ {
+ if (lscalar & DLONG)
+ target->offset.offi += itypesize; /* discard msword */
+ }
+# endif
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+# if BIG_ENDIAN
+ {
+ if (rscalar & CHAR)
+ target->offset.offi += ctypesize;
+ }
+# else
+ ;
+# endif
+#endif
+ }
+ else
+ goto node1;
+ p1->flags &= ~LVALUE;
+ p1->nodetype = target->type = p2->nodetype;
+ return p1;
+ case INDIRECTOP:
+ if (!(target->type->constructor & (ARRAY | POINTER)))
+ error("illegal indirection");
+ else
+ {
+ indirec(target);
+ if (target->indcount == 3) /* XXX - MAXINDIRECT + 1? */
+ /* just became too indirect */
+ p1->weight = 1;
+ p1->flags |= LVALUE;
+ p1->nodetype = target->type;
+ }
+ return p1;
+ case STRUCELTOP: /* p2 known leaf */
+ if (target->indcount != 1)
+ break; /* struc() would generate code */
+ struc(p2->left.symptr, target);
+ p1->flags |= LVALUE;
+ p1->nodetype = target->type;
+ return p1;
+ }
+ if (target->indcount != 0)
+ goto node1;
+ lscalar = target->type->scalar;
+ if (target->storage == CONSTANT)
+ {
+ if (lscalar & RSCALAR)
+ dtargval = *target->offset.offd;
+ else
+ targval = target->offset.offv;
+ switch ((op_t) t)
+ {
+ case COMMAOP:
+ return p2;
+ case CONDOP:
+ if ((lscalar & RSCALAR && dtargval != FALSE)
+ || (!(lscalar & RSCALAR) && targval != FALSE))
+ {
+ p2->left.nodeptr->nodetype = p2->nodetype;
+ return p2->left.nodeptr;
+ }
+ p2->right->nodetype = p2->nodetype;
+ return p2->right;
+ case LOGANDOP:
+ if ((lscalar & RSCALAR && dtargval != FALSE)
+ || (!(lscalar & RSCALAR) && targval != FALSE))
+ break;
+ p1->nodetype = target->type = itype;
+ return p1;
+ case LOGOROP:
+ if ((lscalar & RSCALAR && dtargval == FALSE)
+ || (!(lscalar & RSCALAR) && targval == FALSE))
+ break;
+ target->offset.offv = TRUE;
+ p1->nodetype = target->type = itype;
+ return p1;
+ }
+ }
+ switch ((op_t) t)
+ {
+ case COLONOP:
+ case FUNCOP:
+ case LISTOP:
+ case ROOTLISTOP:
+ goto node1;
+ case PTRADDOP:
+ if (p2->tag == LEAF &&
+ (source = p2->left.symptr)->storage == CONSTANT &&
+ source->type->scalar & ISCALAR)
+ {
+ indexadr(source, target);
+ p1->flags &= ~LVALUE;
+ p1->nodetype = target->type;
+ return p1;
+ }
+ }
+ if (target->storage != CONSTANT ||
+ !((lscalar & (ISCALAR | RSCALAR)) && (op_t) t != PTRSUBOP) ||
+ (p2 != NULL &&
+ (p2->tag != LEAF || (source = p2->left.symptr)->storage != CONSTANT ||
+ (!((rscalar = source->type->scalar) & (ISCALAR | RSCALAR))
+ && (op_t) t != PTRSUBOP))))
+ goto node1;
+ lflag = lscalar & LONG;
+ uflag = lscalar & UNSIGNED;
+ if (p2 != NULL)
+ {
+ if (rscalar & RSCALAR)
+ dsourceval = *source->offset.offd;
+ else
+ {
+ sourceval = source->offset.offv;
+ lflag |= rscalar & LONG;
+ uflag |= rscalar & UNSIGNED;
+ }
+ }
+ if (lscalar & RSCALAR || (p2 != NULL && rscalar & RSCALAR))
+ {
+ if (!(lscalar & RSCALAR))
+ {
+ if (uflag)
+ dtargval = (uvalue_t) targval;
+ else
+ dtargval = targval;
+ }
+ if (p2 != NULL && !(rscalar & RSCALAR))
+ {
+ if (rscalar & UNSIGNED)
+ dsourceval = (uvalue_t) sourceval;
+ else
+ dsourceval = sourceval;
+ }
+ switch ((op_t) t)
+ {
+ case ADDOP:
+ dtargval += dsourceval;
+ break;
+ case DIVOP:
+ if (dsourceval == 0)
+ {
+ error("divison by 0");
+ dsourceval = 1;
+ }
+ dtargval /= dsourceval;
+ break;
+ case EQOP:
+ targval = dtargval == dsourceval;
+ goto intconst;
+ case GEOP:
+ targval = dtargval >= dsourceval;
+ goto intconst;
+ case GTOP:
+ targval = dtargval > dsourceval;
+ goto intconst;
+ case LEOP:
+ targval = dtargval <= dsourceval;
+ goto intconst;
+ case LOGANDOP:
+ targval = dtargval && dsourceval;
+ goto intconst;
+ case LOGNOTOP:
+ targval = !dtargval;
+ goto intconst;
+ case LOGOROP:
+ targval = dtargval || dsourceval;
+ goto intconst;
+ case LTOP:
+ targval = dtargval < dsourceval;
+ goto intconst;
+ case MULOP:
+ dtargval *= dsourceval;
+ break;
+ case NEGOP:
+ dtargval = -dtargval;
+ break;
+ case NEOP:
+ targval = dtargval != dsourceval;
+ goto intconst;
+ case SUBOP:
+ dtargval -= dsourceval;
+ break;
+ }
+ /* XXX - leaks memory */
+ target->offset.offd = qmalloc(sizeof *target->offset.offd);
+ *target->offset.offd = dtargval;
+ p1->nodetype = target->type = dtype;
+ return p1;
+ }
+ switch ((op_t) t)
+ {
+ case ADDOP:
+ targval += sourceval;
+ break;
+ case ANDOP:
+ targval &= sourceval;
+ break;
+ case DIVOP:
+ if (sourceval == 0)
+ {
+ error("divison by 0");
+ sourceval = 1;
+ }
+ if (uflag)
+ targval = (uvalue_t) targval / sourceval;
+ else
+ targval /= sourceval;
+ break;
+ case EOROP:
+ targval ^= sourceval;
+ break;
+ case EQOP:
+ targval = targval == sourceval;
+ break;
+ case GEOP:
+ if (uflag)
+ targval = (uvalue_t) targval >= sourceval;
+ else
+ targval = targval >= sourceval;
+ goto intconst;
+ case GTOP:
+ if (uflag)
+ targval = (uvalue_t) targval > sourceval;
+ else
+ targval = targval > sourceval;
+ goto intconst;
+ case LEOP:
+ if (uflag)
+ targval = (uvalue_t) targval <= sourceval;
+ else
+ targval = targval <= sourceval;
+ goto intconst;
+ case LOGANDOP:
+ targval = targval && sourceval;
+ goto intconst;
+ case LOGNOTOP:
+ targval = !targval;
+ goto intconst;
+ case LOGOROP:
+ targval = targval || sourceval;
+ goto intconst;
+ case LTOP:
+ if (uflag)
+ targval = (uvalue_t) targval < sourceval;
+ else
+ targval = targval < sourceval;
+ goto intconst;
+ break;
+ case MODOP:
+ if (sourceval == 0)
+ {
+ error("modulo by 0");
+ sourceval = 1;
+ }
+ if (uflag)
+ targval = (uvalue_t) targval % sourceval;
+ else
+ targval %= sourceval;
+ break;
+ case MULOP:
+ targval *= sourceval;
+ break;
+ case NEGOP:
+ targval = -targval;
+ break;
+ case NEOP:
+ targval = targval != sourceval;
+ goto intconst;
+ case NOTOP:
+ targval = ~targval;
+ break;
+ case OROP:
+ targval |= sourceval;
+ break;
+ case PTRSUBOP:
+ if (targval < sourceval)
+ targval = -((uvalue_t) (sourceval - targval) /
+ target->type->nexttype->typesize);
+ else
+ targval = (uvalue_t) (targval - sourceval) /
+ target->type->nexttype->typesize;
+ uflag = FALSE;
+ break;
+ case SLOP:
+ targval <<= sourceval; /* assume shiftcount treated as unsigned */
+ lflag = lscalar & LONG;
+ uflag = lscalar & UNSIGNED;
+ break;
+ case SROP:
+ if (uflag)
+ targval = (uvalue_t) targval >> sourceval;
+ else
+ targval >>= sourceval;
+ lflag = lscalar & LONG;
+ uflag = lscalar & UNSIGNED;
+ break;
+ case SUBOP:
+ targval -= sourceval;
+ break;
+ }
+ if (lflag)
+ {
+ target->type = ltype;
+ if (uflag)
+ target->type = ultype;
+ }
+ else
+ {
+ targval &= intmaskto;
+ if (uflag)
+ target->type = uitype;
+ else
+ {
+ target->type = itype;
+ if (targval > maxintto)
+ targval -= (maxuintto + 1);
+ }
+ }
+ target->offset.offv = targval;
+ p1->nodetype = target->type;
+ return p1;
+
+intconst:
+ target->offset.offv = targval;
+ p1->nodetype = target->type = itype;
+ return p1;
+
+node1:
+ {
+ register struct nodestruct *nodeptr;
+ register struct nodestruct *regp2;
+
+ if ((nodeptr = etptr++) >= ettop)
+ etreefull();
+ regp2 = p2;
+ nodeptr->tag = t;
+ nodeptr->left.nodeptr = p1;
+ nodeptr->right = regp2;
+ if ((op_t) t == FUNCOP)
+ nodeptr->weight = MAXREGS + 1;
+ else
+ {
+#if MAXREGS == 1
+ if ((nodeptr->weight = p1->weight) <= MAXREGS &&
+ (regp2 == NULL ||
+ (nodeptr->weight = regp2->weight) < MAXREGS))
+ nodeptr->weight = MAXREGS;
+#else
+ nodeptr->weight = p1->weight;
+ if (regp2 == NULL)
+ rightweight = 1; /* could do POST-ops with 0 */
+ else /* 0 more approp for LIST-ops but 1 OK */
+ rightweight = regp2->weight;
+ if (nodeptr->weight < rightweight)
+ nodeptr->weight = rightweight;
+ else if (nodeptr->weight == rightweight &&
+ nodeptr->weight < MAXREGS)
+ ++nodeptr->weight;
+#endif
+ }
+ nodeptr->nodetype = nodetype(nodeptr);
+ return nodeptr;
+ }
+}
+
+PRIVATE struct typestruct *nodetype(nodeptr)
+struct nodestruct *nodeptr;
+{
+ scalar_t bothscalar;
+ scalar_t lscalar;
+ scalar_t rscalar;
+ struct nodestruct *left;
+ struct nodestruct *right;
+ struct typestruct *targtype;
+
+ if (nodeptr->tag == LEAF)
+ return nodeptr->left.symptr->type;
+ targtype = (left = nodeptr->left.nodeptr)->nodetype;
+ right = nodeptr->right;
+ switch (nodeptr->tag)
+ {
+ case FUNCOP:
+ if (!(targtype->constructor & FUNCTION))
+ {
+ error("call of non-function");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ return targtype->nexttype;
+ case INDIRECTOP:
+ if (!(targtype->constructor & (ARRAY | POINTER)))
+ {
+ error("illegal indirection");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ nodeptr->flags |= LVALUE;
+ return targtype->nexttype;
+ case LISTOP:
+ case ROOTLISTOP:
+ nodeptr->left.nodeptr = unconvert(left);
+ return promote(targtype);
+ case CASTOP:
+ needspv(right);
+ case COMMAOP:
+ case CONDOP:
+ return right->nodetype;
+
+ case STRUCELTOP:
+ nodeptr->flags |= LVALUE;
+ return right->nodetype;
+
+ case ADDRESSOP:
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ return pointype(targtype);
+ case LOGNOTOP:
+ neednonstruct(left);
+ return redtype;
+ case NEGOP:
+ needscalar(left);
+ return promote(left->nodetype);
+ case NOTOP:
+ needint(left);
+ return promote(left->nodetype);
+ case PREDECOP:
+ case PREINCOP:
+ case POSTDECOP:
+ case POSTINCOP:
+ neednonstruct(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ break;
+
+ case ANDOP:
+ case EOROP:
+ case MODOP:
+ case OROP:
+ needint(left);
+ needint(right);
+ /* fall through to redundant check and code to cast to same types */
+ case ADDOP:
+ case DIVOP:
+ case MULOP:
+ case SUBOP:
+ needscalar(left);
+ needscalar(right);
+ binconvert(nodeptr);
+ return nodeptr->nodetype;
+
+ case PTRADDABOP:
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ case PTRADDOP: /* right type conversion to same size as ptr */
+ needint(right);
+ if (right->nodetype->scalar & LONG)
+ castiright(nodeptr);
+ break;
+ case PTRSUBOP: /* already checked */
+ return itype;
+ case SLOP: /* right type conversion always to int */
+ case SROP: /* ulong strictly to unsigned but no matter */
+ needint(left);
+ needint(right);
+ if (right->nodetype->scalar & LONG)
+ castiright(nodeptr);
+ return promote(left->nodetype);
+
+ case LTOP:
+ case LEOP:
+ case GTOP:
+ case GEOP:
+ case EQOP:
+ case LOGOROP:
+ case LOGANDOP:
+ case NEOP:
+ neednonstruct(left);
+ neednonstruct(right);
+ nodeptr->left.nodeptr = left = unconvert(left);
+ nodeptr->right = right = unconvert(right);
+#ifdef MAYBE_DO_LATER /* OK if pointers fit in uitype */
+ if (left->nodetype->constructor & POINTER)
+ nodeptr->left.nodeptr = left = castnode(uitype, left);
+ if (right->nodetype->constructor & POINTER)
+ nodeptr->right = right = castnode(uitype, right);
+#endif
+ binconvert(nodeptr);
+ return redtype;
+
+ case COLONOP:
+ if (isnodecharconst(left) && isnodecharconst(right))
+ {
+ targtype = (targtype->scalar | right->nodetype->scalar) & UNSIGNED
+ ? uctype : ctype;
+ left = castnode(targtype, left);
+ right = castnode(targtype, right);
+ }
+ nodeptr->left.nodeptr = left = unconvert(left);
+ nodeptr->right = right = unconvert(right);
+ if ((targtype = left->nodetype) == right->nodetype)
+ return targtype; /* XXX - reduced from promote(targtype) */
+ if ((lscalar = targtype->scalar) != 0 &&
+ (rscalar = right->nodetype->scalar) != 0)
+ {
+ /* promote minimally without using binconvert for char/short */
+ if ((bothscalar = lscalar | rscalar) & (LONG | RSCALAR))
+ {
+ binconvert(nodeptr);
+ return nodeptr->nodetype;
+ }
+ if (bothscalar & INT || (lscalar ^ rscalar) & UNSIGNED)
+ targtype = itype;
+ else if (bothscalar & SHORT)
+ targtype = stype;
+ else
+ targtype = ctype;
+ if (bothscalar & UNSIGNED)
+ targtype = tounsigned(targtype);
+ if ((!(bothscalar & INT) || (left->tag == LEAF && lscalar & INT)) ||
+ (right->tag == LEAF && rscalar & INT))
+ {
+ /* this is correct even when the if fails (the casts have to */
+ /* be considered at a lower level) but gives worse code */
+ if (left->nodetype != targtype)
+ nodeptr->left.nodeptr = castnode(targtype, left);
+ if (right->nodetype != targtype)
+ nodeptr->right = castnode(targtype, right);
+ }
+ return targtype; /* XXX - reduced from promote(targtype) */
+ }
+ if (targtype->constructor & POINTER &&
+ (isconst0(right) || (right->nodetype->constructor & POINTER &&
+ right->nodetype->nexttype->constructor & VOID)))
+ return targtype;
+ if (right->nodetype->constructor & POINTER &&
+ (isconst0(left) || (targtype->constructor & POINTER &&
+ targtype->nexttype->constructor & VOID)))
+ return right->nodetype;
+ error("mismatched types");
+ fixnode(left); /* XXX - better to fix the CONDOP */
+ fixnode(right);
+ return errtype;
+
+ case ASSIGNOP:
+ if (right->nodetype->constructor & VOID)
+ {
+ error("assignment of void");
+ fixnode(right);
+ }
+ if (targtype->constructor & (ARRAY | FUNCTION | VOID))
+ {
+ error("assignment to array, function or void");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ if ((targtype->constructor | right->nodetype->constructor)
+ & STRUCTU && targtype != right->nodetype)
+ {
+ error("assignment to/from struct/union of a different type");
+ fixnode(nodeptr);
+ return errtype;
+ }
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+#if 0
+ /* XXX - this is done at the lowest levels, with too many chances for
+ * errors.
+ */
+ if (targtype != right->nodetype)
+ nodeptr->right = castnode(left->nodetype, right);
+#endif
+ break;
+ case ANDABOP:
+ case EORABOP:
+ case MODABOP:
+ case ORABOP:
+ needint(right);
+ needint(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ /* fall through to redundant check and code to cast to same types */
+ case ADDABOP:
+ case SUBABOP:
+ case DIVABOP:
+ case MULABOP:
+ needscalar(right);
+ needscalar(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ rscalar = right->nodetype->scalar;
+ if ((lscalar = (targtype = left->nodetype)->scalar) & RSCALAR)
+ {
+ if (!(rscalar & DOUBLE))
+ nodeptr->right = castnode(dtype, right);
+ }
+ else if (lscalar & LONG)
+ {
+ if (!(rscalar & LONG))
+ nodeptr->right = castnode(rscalar & UNSIGNED
+ ? ultype : targtype, right);
+ }
+#ifdef I8088
+ else if (i386_32 && lscalar & INT)
+ {
+ if (rscalar & SHORT)
+ nodeptr->right = castnode(rscalar & UNSIGNED
+ ? uitype : targtype, right);
+ }
+#endif
+ break;
+ case SLABOP:
+ case SRABOP:
+ needint(right);
+ needint(left);
+ if (!(left->flags & LVALUE))
+ {
+ badlvalue(nodeptr);
+ return errtype;
+ }
+ if (!(right->nodetype->scalar & INT))
+ castiright(nodeptr);
+ break;
+ }
+ return left->nodetype;
+}
+
+PRIVATE int redscalar(nodeptr)
+register struct nodestruct *nodeptr;
+{
+ if (isnodecharconst(nodeptr))
+ return CHAR;
+ return nodeptr->nodetype->scalar;
+}
+
+PRIVATE struct nodestruct *unconvert(nodeptr)
+struct nodestruct *nodeptr;
+{
+ if (nodeptr->nodetype->constructor & (ARRAY | FUNCTION))
+ return castnode(pointype(nodeptr->nodetype->constructor & ARRAY ?
+ nodeptr->nodetype->nexttype :
+ nodeptr->nodetype), nodeptr);
+ return nodeptr;
+}
diff --git a/bcc/floatop.c b/bcc/floatop.c
new file mode 100644
index 0000000..fb9c54d
--- /dev/null
+++ b/bcc/floatop.c
@@ -0,0 +1,173 @@
+/* floatop.c - software operations on floats and doubles for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ f_indirect(target leaf)
+ make the float or double target indirect if it is not already
+ return nonzero iff the result is a temp double on the base of the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC bool_pt f_indirect(target)
+struct symstruct *target;
+{
+ if (target->indcount == 0)
+ {
+ if (target->storage == CONSTANT)
+ {
+ /* XXX - more for non-386 */
+ if (target->type->scalar & FLOAT)
+ {
+ float val;
+
+ val = *target->offset.offd;
+ push(constsym(((value_t *) &val)[0]));
+ }
+ else
+ {
+ push(constsym(((value_t *) target->offset.offd)[1]));
+ push(constsym(((value_t *) target->offset.offd)[0]));
+ }
+ }
+ else if (target->type->scalar & FLOAT)
+ pushlist(target->storage); /* XXX - floatregs */
+ else
+ pushlist(doubleregs);
+ onstack(target);
+ }
+ return target->flags == TEMP && target->type->scalar & DOUBLE
+ && target->offset.offi == sp;
+}
+
+/*-----------------------------------------------------------------------------
+ float1op(operation code, source leaf)
+ handles all flop unary operations except inc/dec
+ result is double on stack (or in condition codes for EQOP)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void float1op(op, source)
+op_pt op;
+struct symstruct *source;
+{
+ saveopreg();
+ pointat(source);
+ if ((op_t) op == NEGOP)
+ call("Fneg");
+ else /* op == EQOP */
+ call("Ftst");
+ outntypechar(source->type);
+ if ((op_t) op != EQOP)
+ justpushed(source);
+ restoreopreg();
+}
+
+/*-----------------------------------------------------------------------------
+ floatop(operation code, source leaf, target leaf)
+ handles all flop binary operations
+ result is double on stack (or in condition codes for EQOP)
+----------------------------------------------------------------------------*/
+
+PUBLIC void floatop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regmark;
+ bool_t sflag;
+
+ regmark = reguse;
+ saveopreg();
+ (void) f_indirect(source);
+ if (!(reguse & OPREG) && (source->storage == OPREG))
+ {
+ reguse |= source->storage;
+ saveopreg();
+ }
+ fpush(target);
+ sflag = TRUE;
+ if (source->flags != TEMP || source->offset.offi != sp + dtypesize)
+ {
+ sflag = FALSE;
+ if (source->storage == OPREG)
+ restoreopreg();
+ pointat(source);
+ }
+ switch ((op_t) op)
+ {
+ case ADDOP:
+ call("Fadd");
+ break;
+ case DIVOP:
+ call("Fdiv");
+ break;
+ case EQOP:
+ call("Fcomp");
+ sp += dtypesize; /* target is popped */
+ break; /* target symbol now invalid but is not used */
+ case MULOP:
+ call("Fmul");
+ break;
+ case SUBOP:
+ call("Fsub");
+ break;
+ }
+ if (sflag)
+ {
+ outnl();
+ sp += dtypesize; /* source is popped */
+ }
+ else
+ outntypechar(source->type);
+ onstack(target);
+ reguse = regmark; /* early so opreg is not reloaded if source */
+ restoreopreg();
+}
+
+/*-----------------------------------------------------------------------------
+ fpush(source leaf of scalar type)
+ converts source to double and pushes it to stack
+ OPREG must be free
+-----------------------------------------------------------------------------*/
+
+PUBLIC void fpush(source)
+struct symstruct *source;
+{
+ scalar_t scalar;
+
+ if ((scalar = source->type->scalar) & RSCALAR)
+ {
+ if (f_indirect(source))
+ return;
+ pointat(source);
+ }
+ else if (scalar & DLONG)
+ load(source, OPREG);
+ else
+ load(source, DREG);
+ call("Fpush");
+ if (scalar & UNSIGNED)
+ outbyte('u');
+ outntypechar(source->type);
+ justpushed(source);
+}
+
+/*-----------------------------------------------------------------------------
+ justpushed(target leaf)
+ records that target has just been pushed to a double on the stack
+-----------------------------------------------------------------------------*/
+
+PUBLIC void justpushed(target)
+struct symstruct *target;
+{
+ sp -= dtypesize;
+ onstack(target);
+ target->type = dtype;
+}
diff --git a/bcc/function.c b/bcc/function.c
new file mode 100644
index 0000000..1d48a19
--- /dev/null
+++ b/bcc/function.c
@@ -0,0 +1,413 @@
+/* function.c - function call protocol for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "table.h"
+#include "type.h"
+
+#ifdef I8088
+# define ADJUSTLONGRETURN
+# define CANHANDLENOFRAME
+# undef CANHANDLENOFRAME
+# define STUPIDFRAME
+#endif
+
+FORWARD void out_callstring P((void));
+
+/* call a named (assembly interface) procedure, don't print newline after */
+
+PUBLIC void call(name)
+char *name;
+{
+ out_callstring();
+ outstr(name);
+}
+
+PUBLIC void function(source)
+struct symstruct *source;
+{
+ if (source->indcount == 0 && source->storage == GLOBAL &&
+ !(source->flags & LABELLED) && *source->name.namep != 0)
+ {
+ out_callstring();
+ outnccname(source->name.namep);
+ }
+ else
+ {
+#ifdef XENIX_AS
+ if (source->indcount == 0) /* fix call fixed address */
+ out_callstring();
+ else
+#endif
+ outcalladr();
+#ifdef MC6809
+ if (source->indcount == 1)
+ ++source->indcount; /* fake for outadr */
+#endif
+ outadr(source);
+ }
+ source->type = source->type->nexttype;
+#ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
+ if (source->type->scalar & DLONG)
+ {
+# ifdef ADJUSTLONGRETURN
+# if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ {
+ regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2);
+ regexchange(LONGREG2, DXREG);
+ }
+# endif
+# if DYNAMIC_LONG_ORDER
+ else
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ regtransfer(DXREG, LONGRETURNREGS & ~LONGREG2);
+# endif
+# endif
+ source->storage = LONGRETURNREGS & ~LONGREG2;
+ }
+ else
+#endif
+ if (source->type->scalar & CHAR)
+ {
+#if RETURNREG != DREG
+ transfer(source, DREG);
+#endif
+ source->storage = BREG;
+ }
+ else if (source->type->scalar & DOUBLE)
+ source->storage = doublreturnregs & ~DREG;
+#if 0
+ else if (source->type->scalar & FLOAT)
+ source->storage = floatreturnregs /* XXX? & ~DREG */;
+#endif
+ else
+ source->storage = RETURNREG;
+ source->offset.offi = source->indcount = 0;
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ if (source->type->constructor & STRUCTU)
+ {
+ transfer(source, getindexreg()); /* so it can be indirected
+ * and/or preserved in blockmove() */
+ source->indcount = 1;
+ source->flags = TEMP; /* kludge so blockpush can be avoided */
+ }
+}
+
+PUBLIC void ldregargs()
+{
+ register struct symstruct *symptr;
+ store_pt targreg;
+ struct symstruct temptarg;
+
+ for (symptr = &locsyms[0]; symptr < locptr && symptr->level == ARGLEVEL;
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ {
+ if ((store_t) (targreg = symptr->storage) & allregs)
+ {
+
+ /* load() is designed to work on expression symbols, so don't
+ * trust it on reg variables although it almost works.
+ */
+ temptarg = *symptr;
+ if (arg1inreg && symptr == &locsyms[0])
+ {
+ temptarg.storage = ARGREG;
+ temptarg.offset.offi = 0;
+ }
+ else
+ {
+ temptarg.storage = LOCAL;
+ temptarg.indcount = 1;
+ }
+ load(&temptarg, targreg);
+ symptr->offset.offi = 0;
+ }
+ }
+ regarg = FALSE;
+}
+
+PUBLIC void loadretexpression()
+{
+ if (returntype->constructor & STRUCTU)
+ {
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+ struct symstruct *structarg;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ exp = expression();
+ makeleaf(exp);
+ structarg = constsym((value_t) 0);
+ structarg->type = pointype(returntype);
+ onstack(structarg);
+ indirec(structarg);
+ structarg->flags = 0; /* assign() doesn't like TEMP even for indir */
+ structarg->offset.offi = returnadrsize;
+ assign(exp->left.symptr, structarg);
+ etptr = etmark;
+ exprptr = exprmark;
+ }
+#ifdef LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
+ else if (returntype->scalar & DLONG)
+ {
+ loadexpression(LONGRETURNREGS & ~LONGREG2, returntype);
+# ifdef ADJUSTLONGRETURN
+# if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ {
+ regexchange(LONGREG2, DXREG);
+ regexchange(LONGREG2, LONGRETURNREGS & ~LONGREG2);
+ }
+# endif
+# if DYNAMIC_LONG_ORDER
+ else
+# endif
+# if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ regtransfer(LONGRETURNREGS & ~LONGREG2, DXREG);
+# endif
+# endif
+ }
+ else
+#endif
+ if (returntype->scalar & DOUBLE)
+ loadexpression(doublreturnregs & ~DREG, returntype);
+#if 0
+ else if (returntype->scalar & FLOAT)
+ loadexpression(floatreturnregs /* XXX? & ~DREG */, returntype);
+#endif
+ else
+ loadexpression(RETURNREG, returntype);
+}
+
+PUBLIC void listo(target, lastargsp)
+struct symstruct *target;
+offset_t lastargsp;
+{
+ extend(target);
+ push(target);
+ if (lastargsp != 0 && sp != lastargsp - target->type->typesize)
+ {
+ loadany(target);
+ modstk(lastargsp);
+ push(target);
+ if (sp != lastargsp - target->type->typesize)
+ {
+ bugerror("botched push of arg");
+#ifdef DEBUG
+ outstr("arg type is ");
+ dbtype(target->type);
+ outnl();
+#endif
+ }
+ }
+}
+
+PUBLIC void listroot(target)
+struct symstruct *target;
+{
+ extend(target);
+ /* necessary regs are free since they were saved for function */
+ if (target->type->scalar & DLONG)
+ load(target, LONGARGREGS & ~LONGREG2);
+ else
+ load(target, ARGREG);
+}
+
+PRIVATE void out_callstring()
+{
+ outop3str(callstring);
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+#ifdef FRAMEPOINTER
+
+PUBLIC void popframe()
+{
+ poplist(frame1list);
+}
+
+#endif
+
+/* reserve storage for locals if necessary */
+/* also push 1st function arg and load register args if necessary */
+
+PUBLIC void reslocals()
+{
+#ifdef FRAMEPOINTER
+# ifndef STUPIDFRAME
+ bool_t loadframe = FALSE;
+
+# endif
+#endif
+
+ if (switchnow != NULL)
+ {
+#ifdef FRAMEPOINTER
+ if (framep == 0 && softsp != sp)
+ bugerror("local variables in switch statement messed up, sorry");
+#else
+ if (sp != softsp)
+ bugerror("local variables in switch statement don't work, sorry");
+#endif
+ if (lowsp > softsp)
+ lowsp = softsp;
+ sp = softsp;
+ return;
+ }
+#ifdef FRAMEPOINTER
+ if (framep == 0)
+ {
+# ifdef STUPIDFRAME
+ pushreg(FRAMEREG);
+ regtransfer(STACKREG, FRAMEREG);
+ framep = sp;
+ pushlist(callee1mask);
+# else /* not STUPIDFRAME */
+# ifdef CANHANDLENOFRAME
+ if (stackarg || softsp != -frameregsize) /* args or locals */
+# endif
+ {
+ pushlist(frame1list);
+ loadframe = TRUE;
+ }
+# endif /* not STUPIDFRAME */
+ }
+#else
+ if (sp == 0)
+ pushlist(callee1mask);
+#endif /* FRAMEPOINTER */
+ if (arg1size)
+ {
+ switch ((fastin_t) arg1size)
+ {
+ case 8:
+ pushlist(doubleargregs);
+ break;
+ case 4:
+# ifdef I8088
+ if (!i386_32)
+# endif
+ {
+ pushlist(LONGARGREGS);
+ break;
+ }
+ case 2:
+# ifdef I8088
+ pushlist(ARGREG);
+# endif
+# ifdef MC6809
+ switch (sp - softsp)
+ {
+ case 3:
+ pushlist(LOC1REGS | ARGREG);
+ break;
+ case 4:
+ pushlist(LOC2REGS | ARGREG);
+ break;
+ case 5:
+ pushlist(LOC3REGS | ARGREG);
+ break;
+ case 6:
+ pushlist(LOC4REGS | ARGREG);
+ break;
+ default:
+ pushlist(ARGREG);
+ break;
+ }
+# endif /* MC6809 */
+ }
+ arg1size = 0; /* show 1st arg allocated */
+ }
+#ifdef FRAMEPOINTER
+# ifndef STUPIDFRAME /* else this moved above for compat with Xenix cc frame */
+ if (loadframe || softsp != -frameregsize)
+ modstk(softsp);
+ /* else avoid modstk() because softsp holds space for frame pointer only) */
+ /* but pointer has not been pushed (must keep softsp for later levels) */
+ if (loadframe)
+ {
+ regtransfer(STACKREG, FRAMEREG);
+ framep = sp;
+ }
+# else /* STUPIDFRAME */
+ modstk(softsp);
+# endif /* STUPIDFRAME */
+#else /* no FRAMEPOINTER */
+ modstk(softsp);
+#endif /* FRAMEPOINTER */
+ if (regarg)
+ ldregargs();
+}
+
+/* clean up stack and return from a function */
+
+PUBLIC void ret()
+{
+#ifdef FRAMEPOINTER
+ offset_t newsp;
+
+ if (framep != 0)
+ {
+ newsp = -(offset_t) func1saveregsize;
+ if (switchnow != NULL || newsp - sp >= 0x80)
+ changesp(newsp, TRUE);
+ else
+ modstk(newsp);
+ popframe();
+ }
+ outreturn();
+#else /* no FRAMEPOINTER */
+# ifdef MC6809
+ store_pt reglist;
+
+ switch (sp)
+ {
+ case -1:
+ reglist = JUNK1REGS | PCREG;
+ break;
+ case -2:
+ reglist = JUNK2REGS | PCREG;
+ break;
+ case -3:
+ reglist = JUNK3REGS | PCREG;
+ break;
+ case -4:
+ reglist = JUNK4REGS | PCREG;
+ break;
+ default:
+ modstk(0);
+ outreturn();
+ return;
+ }
+ poplist(reglist);
+#else
+ if (sp != 0)
+ {
+ modstk(-(offset_t) func1saveregsize);
+ poplist(callee1mask);
+ }
+ outreturn();
+# endif /* no MC6809 */
+#endif /* no FRAMEPOINTER */
+}
diff --git a/bcc/gencode.c b/bcc/gencode.c
new file mode 100644
index 0000000..fa098ea
--- /dev/null
+++ b/bcc/gencode.c
@@ -0,0 +1,736 @@
+/* gencode.c - generate code for an expression tree for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define islvalop(op) \
+ (((op) >= ASSIGNOP && (op) <= SUBABOP) || (op) == PTRADDABOP)
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "condcode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "gencode.h"
+#include "sizes.h"
+
+#define FIRSTOPDATA GTOP
+
+#if MAXINDIRECT <= 1
+# define istooindirect(t) ((t)->indcount > MAXINDIRECT)
+#else
+# define istooindirect(t) ((t)->indcount >= MAXINDIRECT && \
+ ((t)->indcount > MAXINDIRECT || \
+ (t)->type->typesize > maxregsize || \
+ (t)->type->constructor & FUNCTION))
+#endif
+
+#ifdef I8088
+#if NOTFINISHED
+PUBLIC store_pt allregs = BREG | DREG | DATREG1 | DATREG2
+ | INDREG0 | INDREG1 | INDREG2;
+#else
+PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2;
+#endif
+PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2;
+PUBLIC uoffset_t alignmask = ~(uoffset_t) 0x0001;
+PUBLIC bool_t arg1inreg = FALSE;
+PUBLIC store_pt calleemask = INDREG1 | INDREG2;
+PUBLIC bool_t callersaves = FALSE;
+PUBLIC char *callstring = "call\t";
+PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC offset_t jcclonger = 3;
+PUBLIC offset_t jmplonger = 1;
+PUBLIC char *jumpstring = "br \t";
+PUBLIC char *regpulllist = "f2ax2ax2bx2si2di2bp2qx2qx2cx2dx2";
+PUBLIC char *regpushlist = "dx2cx2qx2qx2bp2di2si2bx2ax2ax2f2";
+#if NOTFINISHED
+PUBLIC store_pt regregs = INDREG1 | INDREG2 | DATREG1 | DATREG2;
+#else
+PUBLIC store_pt regregs = INDREG1 | INDREG2;
+#endif
+
+PUBLIC char *acclostr = "al";
+PUBLIC char *accumstr = "ax";
+PUBLIC char *badregstr = "qx";
+PUBLIC char *dreg1str = "cx";
+PUBLIC char *dreg1bstr = "cl";
+PUBLIC char *dreg2str = "dx";
+PUBLIC char *ireg0str = "bx";
+PUBLIC char *ireg1str = "si";
+PUBLIC char *ireg2str = "di";
+#ifdef FRAMEPOINTER
+PUBLIC char *localregstr = "bp";
+#else
+PUBLIC char *localregstr = "sp";
+#endif
+PUBLIC char *stackregstr = "sp";
+#endif
+
+#ifdef MC6809
+PUBLIC store_pt allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt allindregs = INDREG0 | INDREG1 | INDREG2;
+PUBLIC uoffset_t alignmask = ~(uoffset_t) 0x0000;
+PUBLIC bool_t arg1inreg = TRUE;
+PUBLIC store_pt calleemask = INDREG1 | INDREG2;
+PUBLIC bool_t callersaves = TRUE;
+PUBLIC char *callstring = "JSR\t>";
+PUBLIC store_pt doubleargregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doubleregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC store_pt doublreturnregs = DREG | INDREG0 | INDREG1 | INDREG2;
+PUBLIC offset_t jcclonger = 2;
+PUBLIC offset_t jmplonger = 1;
+PUBLIC char *jumpstring = "JMP\t>";
+PUBLIC char *regpulllist = "CC1B1D2X2U2Y2DP1PC2";
+PUBLIC char *regpushlist = "PC2DP1Y2U2X2D2B1CC1";
+PUBLIC store_pt regregs = INDREG1 | INDREG2;
+
+PUBLIC char *acclostr = "B";
+PUBLIC char *accumstr = "D";
+PUBLIC char *badregstr = "Q";
+PUBLIC char *ireg0str = "X";
+PUBLIC char *ireg1str = "U";
+PUBLIC char *ireg2str = "Y";
+PUBLIC char *localregstr = "S";
+#endif
+
+PUBLIC uoffset_t accregsize = 2;
+#ifdef FRAMEPOINTER
+PUBLIC uoffset_t frameregsize = 2;
+#endif
+PUBLIC uoffset_t maxregsize = 2;
+PUBLIC uoffset_t opregsize = 2;
+PUBLIC uoffset_t pshregsize = 2;
+PUBLIC uoffset_t returnadrsize = 2;
+
+#ifndef MC6809
+PUBLIC uvalue_t intmaskto = 0xFFFFL;
+PUBLIC uvalue_t maxintto = 0x7FFFL;
+PUBLIC uvalue_t maxlongto = 0x7FFFFFFFL;
+PUBLIC uvalue_t maxoffsetto = 0x7FFFL;
+PUBLIC uvalue_t maxshortto = 0x7FFFL;
+PUBLIC uvalue_t maxuintto = 0xFFFFL;
+PUBLIC uvalue_t maxushortto = 0xFFFFL;
+PUBLIC uvalue_t shortmaskto = 0xFFFFL;
+#endif
+
+PRIVATE store_pt callermask;
+PRIVATE offset_t lastargsp;
+
+PRIVATE smalin_t opdata[] =
+{
+/* GTOP, LTOP, ADDOP, DIVOP, */
+ GT, LT, 0, 0,
+/* MODOP, LOGNOTOP, NOTOP, STRUCELTOP, */
+ 0, 0, 0, 0,
+/* STRUCPTROP, ASSIGNOP, ADDABOP, ANDABOP, */
+ 0, 0, 0, ANDOP,
+/* DIVABOP, EORABOP, MODABOP, MULABOP, */
+ DIVOP, EOROP, MODOP, MULOP,
+/* ORABOP, SLABOP, SRABOP, SUBABOP, */
+ OROP, SLOP, SROP, 0,
+/* COMMAOP, COLONOP, LOGOROP, LOGANDOP, */
+ 0, 0, 0, 0,
+/* EQOP, NEOP, GEOP, LEOP, */
+ EQ, NE, GE, LE,
+};
+
+FORWARD void abop P((op_pt op, struct symstruct *source,
+ struct symstruct *target));
+FORWARD void smakeleaf P((struct nodestruct *exp));
+FORWARD void tcheck P((struct nodestruct *exp));
+
+PRIVATE void abop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt regmark;
+ store_pt regpushed;
+ store_pt regtemp;
+ struct symstruct temptarg;
+
+ regpushed = preslval(source, target);
+ temptarg = *target;
+ if ((source->type->scalar ^ target->type->scalar) & (DLONG | RSCALAR)
+ && op != SLABOP && op != SRABOP) /* XXX - perhaps not float */
+ {
+ pres2(target, source);
+ cast(source->type, &temptarg);
+ }
+ switch (op)
+ {
+ case ADDABOP:
+ add(source, &temptarg);
+ break;
+ case ANDABOP:
+ case EORABOP:
+ case ORABOP:
+ op1((opdata - FIRSTOPDATA)[op], source, &temptarg);
+ break;
+ case DIVABOP:
+ case MODABOP:
+ case MULABOP:
+ case SLABOP:
+ case SRABOP:
+ softop((opdata - FIRSTOPDATA)[op], source, &temptarg);
+ break;
+ case PTRADDABOP:
+ regtemp = 0;
+ if ((reguse & allindregs) == allindregs)
+ {
+ /* free a temporary index not used for source or target */
+
+ regmark = reguse;
+ reguse = source->storage | temptarg.storage;
+ pushreg(regtemp = getindexreg());
+ reguse = regmark & ~regtemp;
+ }
+ indexadr(source, &temptarg);
+ if (regtemp)
+ {
+ load(&temptarg, DREG);
+ recovlist(regtemp);
+ }
+ break;
+ case SUBABOP:
+ sub(source, &temptarg);
+ break;
+ }
+ assign(&temptarg, target);
+ recovlist(regpushed);
+}
+
+PUBLIC void bileaf(exp)
+struct nodestruct *exp;
+{
+ bool_t commutop;
+ bool_t tookaddress;
+ store_t regmark;
+ struct nodestruct *indchase;
+ struct nodestruct *left;
+ struct nodestruct *right;
+ struct symstruct *source;
+ struct symstruct *target;
+
+ left = exp->left.nodeptr;
+ if ((right = exp->right) == NULL)
+ {
+ makeleaf(left);
+#ifdef DEBUG
+ debug(exp);
+#endif
+ return;
+ }
+ switch (exp->tag)
+ {
+ case ADDOP:
+ case ANDOP:
+ case EOROP:
+ case OROP:
+ case EQOP:
+ case NEOP:
+ case MULOP:
+ commutop = TRUE;
+ break;
+ case FUNCOP:
+ makeleaf(left);
+ if ((target = left->left.symptr)->storage & allregs
+ && right->tag != LEAF && target->flags != REGVAR)
+ {
+ if (target->indcount == 0)
+ push(target);
+ else
+ {
+ --target->indcount;
+ push(target);
+ ++target->indcount;
+ }
+ }
+ default:
+ commutop = FALSE;
+ break;
+ }
+ regmark = reguse;
+ if (right->tag != LEAF)
+ {
+ if (left->tag != LEAF && commutop && left->weight > right->weight)
+ {
+ exp->left.nodeptr = right;
+ right = exp->right = left;
+ left = exp->left.nodeptr;
+#ifdef DEBUG
+ debugswap();
+#endif
+ }
+ makeleaf(right);
+ }
+ else if (left->tag != LEAF)
+ makeleaf(left);
+ source = right->left.symptr;
+ if (left->tag != LEAF)
+ {
+ for (indchase = left;
+ indchase->tag == INDIRECTOP || indchase->tag == STRUCELTOP;
+ indchase = indchase->left.nodeptr)
+ ;
+ tookaddress = FALSE;
+ if (source->storage & allindregs || indchase->tag != LEAF)
+ {
+ if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP)
+ {
+ address(source);
+ tookaddress = TRUE;
+ }
+ if (source->storage & allindregs && source->indcount == 0 &&
+ (source->type->scalar & (DLONG | RSCALAR) ||
+ (left->tag == FUNCOP && source->flags != REGVAR)))
+ push(source); /* XXX - perhaps not float */
+ else
+ preserve(source);
+ }
+ makeleaf(left);
+ if (tookaddress)
+ indirec(source);
+ }
+ target = left->left.symptr;
+ if (istooindirect(source))
+ {
+ /* want to makelessindirect(source) */
+ /* this uses source->storage if that is a free index */
+ /* otherwise, must preserve target if that is an index */
+
+ tookaddress = FALSE;
+ if (!(source->storage & ~reguse & allindregs) &&
+ target->storage & allindregs)
+ {
+ /* want to pres2(source, target) */
+ /* this requires target to be < MAXINDIRECT indirect */
+ /* it is safe to makelessindirect(target) */
+ /* since source is not a free index */
+
+ if (islvalop(exp->tag) && target->indcount != 0)
+ {
+ address(target);
+ tookaddress = TRUE;
+ }
+ if (istooindirect(target))
+ makelessindirect(target);
+ pres2(source, target);
+ }
+ makelessindirect(source);
+ if (tookaddress)
+ indirec(target);
+ }
+ if (istooindirect(target))
+ {
+ tookaddress = FALSE;
+ if (!(target->storage & ~reguse & allindregs) &&
+ source->storage & allindregs)
+ {
+ if (exp->nodetype->constructor & STRUCTU && exp->tag == ASSIGNOP)
+ {
+ address(source);
+ tookaddress = TRUE;
+ }
+ pres2(target, source);
+ }
+ makelessindirect(target);
+ if (tookaddress)
+ indirec(source);
+ }
+ reguse = regmark;
+#ifdef DEBUG
+ debug(exp);
+#endif
+ if (commutop
+ && ((target->storage == CONSTANT
+ && !(target->type->scalar & (DLONG | RSCALAR)))
+ || source->storage & ALLDATREGS
+ || (source->type->scalar & (DLONG | RSCALAR)
+ && source->indcount == 0 && target->indcount != 0)))
+ {
+ exp->left.nodeptr = right;
+ exp->right = left;
+#ifdef DEBUG
+ debugswap();
+#endif
+ }
+}
+
+PUBLIC fastin_pt bitcount(number)
+register uvalue_t number;
+{
+ register fastin_pt count;
+
+ for (count = 0; number != 0; number >>= 1)
+ if (number & 1)
+ ++count;
+ return count;
+}
+
+PUBLIC void codeinit()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ /* Need DATREG2 for doubles although handling of extra data regs is
+ * not finished.
+ * XXX - might need more regs for 16-bit mode doubles or floats.
+ */
+ allregs = BREG | DREG | INDREG0 | INDREG1 | INDREG2
+ | DATREG1 | DATREG1B | DATREG2;
+#if NOTFINISHED
+ allindregs = INDREG0 | INDREG1 | INDREG2 | DATREG1 | DATREG2;
+#else
+ allindregs = INDREG0 | INDREG1 | INDREG2;
+#endif
+ alignmask = ~(uoffset_t) 0x00000003;
+ calleemask = INDREG0 | INDREG1 | INDREG2;
+ doubleargregs = DREG | DATREG2;
+ doubleregs = DREG | DATREG2;
+ doublreturnregs = DREG | DATREG2;
+ jcclonger = 4;
+ jmplonger = 3;
+ regpulllist = "fd4eax4eax4ebx4esi4edi4ebp4qx4qx4ecx4edx4";
+ regpushlist = "edx4ecx4qx4qx4ebp4edi4esi4ebx4eax4eax4fd4";
+
+ accumstr = "eax";
+ dreg1str = "ecx";
+ dreg2str = "edx";
+ ireg0str = "ebx";
+ ireg1str = "esi";
+ ireg2str = "edi";
+#ifdef FRAMEPOINTER
+ localregstr = "ebp";
+#else
+ localregstr = "esp";
+#endif
+ stackregstr = "esp";
+
+ opregsize =
+ returnadrsize =
+ pshregsize =
+ maxregsize =
+#ifdef FRAMEPOINTER
+ frameregsize =
+#endif
+ accregsize = 4;
+
+ intmaskto = (unsigned long) 0xFFFFFFFFL;
+ maxintto = 0x7FFFFFFFL;
+ maxoffsetto = 0x7FFFFFFFL;
+ maxuintto = (unsigned long) 0xFFFFFFFFL;
+ }
+#endif
+#ifdef POSINDEPENDENT
+ if (posindependent)
+ {
+# ifdef MC6809
+ callstring = "LBSR\t";
+ jumpstring = "LBRA\t";
+# endif
+ }
+#endif
+ if (callersaves)
+ calleemask = 0;
+ callermask = ~calleemask;
+#ifdef FRAMEPOINTER
+ funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize
+ + frameregsize;
+ funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs)
+ * maxregsize + frameregsize;
+ framelist = FRAMEREG | calleemask;
+#else
+ funcsaveregsize = bitcount((uvalue_t) calleemask) * maxregsize;
+ funcdsaveregsize = bitcount((uvalue_t) calleemask & ~doubleregs)
+ * maxregsize;
+#endif
+}
+
+PUBLIC fastin_pt highbit(number)
+register uvalue_t number;
+{
+ register fastin_pt bit;
+
+ for (bit = -1; number != 0; number >>= 1)
+ ++bit;
+ return bit;
+}
+
+PUBLIC void makeleaf(exp)
+struct nodestruct *exp;
+{
+ ccode_t condtrue;
+ op_pt op;
+ store_t regmark;
+ offset_t saveargsp = 0; /* for -Wall */
+ store_t savelist = 0; /* for -Wall */
+ offset_t saveoffset = 0; /* for -Wall */
+ struct symstruct *source;
+ offset_t spmark;
+ struct symstruct *structarg = 0; /* for -Wall */
+ struct symstruct *target;
+
+ if ((op_t) (op = exp->tag) == LEAF)
+ {
+ target = exp->left.symptr;
+ if (istooindirect(target))
+ makelessindirect(target);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == INDIRECTOP || (op_t) op == STRUCELTOP)
+ {
+ smakeleaf(exp);
+ target = exp->left.symptr;
+ if (istooindirect(target))
+ makelessindirect(target);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == COMMAOP)
+ {
+ spmark = sp;
+ makeleaf(exp->left.nodeptr);
+ modstk(spmark);
+ makeleaf(exp->right);
+ exp->tag = LEAF;
+ exp->left.symptr = exp->right->left.symptr;
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == CONDOP)
+ {
+ condop(exp);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ if ((op_t) op == LOGANDOP || (op_t) op == LOGNOTOP
+ || (op_t) op == LOGOROP)
+ {
+ logop(exp);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+ return;
+ }
+ regmark = reguse;
+ if ((op_t) op == FUNCOP)
+ {
+ saveargsp = lastargsp;
+ lastargsp = savelist = 0;
+ if (exp->nodetype->constructor & STRUCTU)
+ {
+ modstk(sp - (offset_t) exp->nodetype->typesize);
+ onstack(structarg = constsym((value_t) 0));
+ }
+ else
+ {
+ if (exp->nodetype->scalar & DOUBLE)
+ {
+ if (regmark & doublreturnregs)
+ savelist = doublreturnregs;
+ }
+ else if (regmark & RETURNREG)
+ savelist = exp->nodetype->scalar & DLONG
+ ? LONGRETURNREGS : RETURNREG;
+ if (savelist != 0)
+ modstk(saveoffset = sp - exp->nodetype->typesize);
+ }
+ pushlist(regmark & callermask);
+ }
+ spmark = sp;
+ bileaf(exp);
+ if (exp->right != NULL)
+ source = exp->right->left.symptr;
+ else
+ source = NULL;
+ target = exp->left.nodeptr->left.symptr;
+ switch ((op_t) op)
+ {
+ case ADDABOP:
+ case ANDABOP:
+ case DIVABOP:
+ case EORABOP:
+ case SUBABOP:
+ case MODABOP:
+ case MULABOP:
+ case ORABOP:
+ case PTRADDABOP:
+ case SLABOP:
+ case SRABOP:
+ abop(op, source, target);
+ break;
+ case ADDOP:
+ add(source, target);
+ break;
+ case ADDRESSOP:
+ address(target);
+ break;
+ case ANDOP:
+ case EOROP:
+ case OROP:
+ op1(op, source, target);
+ break;
+ case ASSIGNOP:
+ assign(source, target);
+ break;
+ case CASTOP:
+ cast(source->type, target);
+ break;
+ case DIVOP:
+ case MODOP:
+ case MULOP:
+ case SLOP:
+ case SROP:
+ softop(op, source, target);
+ break;
+ case EQOP:
+ case GEOP:
+ case GTOP:
+ case LEOP:
+ case LTOP:
+ case NEOP:
+ condtrue = (opdata - FIRSTOPDATA)[op];
+ cmp(source, target, &condtrue);
+ break;
+ case FUNCOP:
+ /* kludge update pushed regs */
+ /* may only work for si, di */
+ /* -2 skips for ax and bx */
+ /* need dirtymask to mostly avoid this */
+ savereturn(regmark & callermask & regregs,
+ spmark - 2 * (offset_t) pshregsize);
+ if (exp->nodetype->constructor & STRUCTU)
+ {
+ address(structarg);
+ push(structarg);
+ }
+ function(target);
+ break;
+ case INDIRECTOP:
+ indirec(target);
+ break;
+ case LISTOP:
+ listo(target, lastargsp);
+ lastargsp = sp;
+ break;
+ case NEGOP:
+ neg(target);
+ break;
+ case NOTOP:
+ not(target);
+ break;
+ case POSTDECOP:
+ case POSTINCOP:
+ case PREDECOP:
+ case PREINCOP:
+ incdec(op, target);
+ break;
+ case PTRADDOP:
+ indexadr(source, target);
+ break;
+ case PTRSUBOP:
+ ptrsub(source, target);
+ break;
+ case ROOTLISTOP:
+ listroot(target);
+ lastargsp = sp;
+ break;
+ case STRUCELTOP:
+ struc(source, target);
+ break;
+ case SUBOP:
+ sub(source, target);
+ break;
+ }
+ if (target->storage == LOCAL && target->offset.offi < spmark &&
+ target->flags == TEMP)
+ spmark = target->offset.offi;
+#if 1 /* XXX - why does sp get changed without this? */
+ if ((op_t) op != ROOTLISTOP)
+#endif
+ modstk(spmark);
+ if ((op_t) op == FUNCOP)
+ {
+ lastargsp = saveargsp;
+ if (savelist != 0)
+ {
+ savereturn(savelist, saveoffset);
+ onstack(target);
+ target->offset.offi = saveoffset;
+ }
+ recovlist(regmark & callermask);
+ }
+ reguse = regmark;
+ exp->tag = LEAF;
+ exp->left.symptr = target;
+ if (istooindirect(target))
+ makelessindirect(target);
+#ifdef SELFTYPECHECK
+ tcheck(exp);
+#endif
+}
+
+PRIVATE void smakeleaf(exp)
+struct nodestruct *exp;
+{
+ struct nodestruct *left;
+
+ left = exp->left.nodeptr;
+ if (left->tag == INDIRECTOP || left->tag == STRUCELTOP)
+ smakeleaf(left);
+ else if (left->tag != LEAF)
+ makeleaf(left);
+ if (exp->tag == INDIRECTOP)
+ indirec(left->left.symptr);
+ else
+ {
+ if (left->left.symptr->indcount > MAXINDIRECT + 1)
+ makelessindirect(left->left.symptr);
+ struc(exp->right->left.symptr, left->left.symptr);
+ }
+ exp->tag = LEAF;
+ exp->left.symptr = left->left.symptr;
+}
+
+#ifdef SELFTYPECHECK
+
+PRIVATE void tcheck(exp)
+register struct nodestruct *exp;
+{
+ register struct symstruct *target;
+
+ if (exp->nodetype != (target = exp->left.symptr)->type)
+ {
+ {
+ bugerror("botched nodetype calculation");
+#ifdef DEBUG
+ comment();
+ outstr("runtime type is ");
+ dbtype(target->type);
+ outstr(", calculated type is ");
+ dbtype(exp->nodetype);
+ outnl();
+#endif
+ }
+ }
+}
+
+#endif /* SELFTYPECHECK */
diff --git a/bcc/gencode.h b/bcc/gencode.h
new file mode 100644
index 0000000..370817a
--- /dev/null
+++ b/bcc/gencode.h
@@ -0,0 +1,101 @@
+/* gencode.h - code generation for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef MC6809
+# define CANABXCUTOFF 7 /* favour ABX over MUL before this */
+#endif
+#define EXPRLEVEL 126 /* level for symbols in exptree, > real levs */
+#define OFFKLUDGELEVEL 127 /* level for expr sym with offset from name */
+#define OPERANDSEPARATOR ',' /* char separating operands */
+#define OPSEPARATOR '\t' /* char separating op string and operand */
+
+EXTERN uoffset_t arg1size; /* size of 1st arg to function */
+ /* zero after allocation of 1st arg */
+EXTERN store_pt callee1mask; /* calleemask with doubleregs masked if nec */
+EXTERN uoffset_t dataoffset; /* amount of initialized data so far */
+#ifdef DEBUG
+EXTERN bool_t debugon; /* nonzero to print debugging messages */
+ /* depends on zero init */
+#endif
+#ifdef FRAMEPOINTER
+EXTERN store_pt framelist; /* bit pattern for frame and saved regs */
+EXTERN store_pt frame1list; /* framelist with doubleregs masked if nec */
+EXTERN offset_t framep; /* hardware relative frame ptr */
+#endif
+EXTERN uoffset_t func1saveregsize; /* choice of next two values */
+EXTERN uoffset_t funcdsaveregsize; /* funcsaveregsize adjusted for doubles */
+EXTERN uoffset_t funcsaveregsize; /* tot size of framelist/calleemask regs */
+#ifdef I8088
+EXTERN bool_t i386_32; /* nonzero to generate 386 32 bit code */
+ /* depends on zero init */
+#endif
+#ifdef DYNAMIC_LONG_ORDER
+EXTERN bool_t long_big_endian; /* nonzero if high long word is first */
+ /* depends on zero init */
+#endif
+EXTERN offset_t lowsp; /* low water sp (collects locals in switch) */
+#ifdef POSINDEPENDENT
+EXTERN bool_t posindependent; /* nonzero to generate pos-independent code */
+ /* depends on zero init */
+#endif
+EXTERN bool_t printf_fp; /* nonzero if *printf called with FP arg */
+EXTERN bool_t regarg; /* nonzero to show unloaded register arg */
+ /* depends on zero init */
+EXTERN store_t reguse; /* registers in use */
+EXTERN bool_t scanf_fp; /* nonzero if *scanf called with ptr-to-FP */
+EXTERN offset_t softsp; /* software sp (leads sp during declares) */
+EXTERN offset_t sp; /* hardware relative stack ptr */
+ /* depends on zero init */
+#ifdef FRAMEPOINTER
+EXTERN bool_t stackarg; /* nonzero to show function has arg on stack */
+#endif
+EXTERN struct switchstruct *switchnow; /* currently active switch */
+ /* depends on NULL init */
+
+/* variables to be initialised to nonzero */
+
+extern store_pt allindregs; /* mask (in) for index registers */
+extern store_pt allregs; /* mask (in) for registers */
+extern bool_t arg1inreg; /* nonzero to pass 1st arg in reg */
+extern store_pt calleemask; /* mask (in) for regs to be saved by callee */
+extern bool_t callersaves; /* nonzero to make caller save regs */
+extern char *callstring; /* opcode string for call */
+extern store_pt doubleargregs; /* mask (in) for regs for 1st arg if double */
+extern store_pt doubleregs; /* mask (in) for regs to temp contain double */
+extern store_pt doublreturnregs; /* mask (in) for regs for returning double */
+extern offset_t jcclonger; /* amount jcc long jumps are longer */
+extern offset_t jmplonger; /* amount long jumps is longer */
+extern char *jumpstring; /* opcode string for jump */
+extern char *regpulllist; /* reg names and sizes (0 store_t bit first) */
+extern char *regpushlist; /* reg names and sizes (0 store_t bit last) */
+extern store_pt regregs; /* mask (in) for regs which can be reg vars */
+
+/* register names */
+
+extern char *acclostr;
+extern char *accumstr;
+extern char *badregstr;
+#ifdef I8088
+extern char *dreg1str;
+extern char *dreg1bstr;
+extern char *dreg2str;
+#endif
+extern char *ireg0str;
+extern char *ireg1str;
+extern char *ireg2str;
+extern char *localregstr;
+#ifdef I8088
+extern char *stackregstr;
+#endif
+
+/* register sizes */
+
+extern uoffset_t accregsize;
+#ifdef FRAMEPOINTER
+extern uoffset_t frameregsize;
+#endif
+extern uoffset_t maxregsize;
+extern uoffset_t opregsize;
+extern uoffset_t pshregsize;
+extern uoffset_t returnadrsize;
diff --git a/bcc/genloads.c b/bcc/genloads.c
new file mode 100644
index 0000000..2056cb7
--- /dev/null
+++ b/bcc/genloads.c
@@ -0,0 +1,1255 @@
+/* genloads.c - generate loads of registers and memory for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+FORWARD void badaddress P((void));
+FORWARD void blockpush P((struct symstruct *source));
+FORWARD void loadadr P((struct symstruct *source, store_pt targreg));
+FORWARD void loadlongindirect P((struct symstruct *source, store_pt targreg));
+FORWARD void outnamoffset P((struct symstruct *adr));
+FORWARD void outnnadr P((struct symstruct *adr));
+FORWARD fastin_pt pushpull P((store_pt reglist, bool_pt pushflag));
+
+PUBLIC void addoffset(source)
+struct symstruct *source;
+{
+#ifdef I8088
+ if (source->level == OFFKLUDGELEVEL)
+ {
+ outadd();
+ outregname(source->storage);
+ outcomma();
+ outnamoffset(source);
+ outnl();
+ if (source->storage & (AXREG | ALREG))
+ unbumplc();
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ source->offset.offi = 0;
+ }
+ else
+#endif
+ if (source->offset.offi != 0)
+ {
+ addconst(source->offset.offi, source->storage);
+ source->offset.offi = 0;
+ }
+}
+
+PUBLIC void address(source)
+struct symstruct *source;
+{
+ if (source->indcount == 0)
+ bugerror("taking address of non-lvalue");
+ else
+ {
+ if (source->type->constructor & (ARRAY | FUNCTION))
+ bugerror("botched indirect array or function");
+ else if (--source->indcount == 0 && source->storage == GLOBAL &&
+ !(source->flags & LABELLED) && *source->name.namep == 0)
+ source->storage = CONSTANT;
+ source->type = pointype(source->type);
+ }
+}
+
+PRIVATE void badaddress()
+{
+ bugerror("bad address");
+}
+
+PRIVATE void blockpush(source)
+struct symstruct *source;
+{
+ struct symstruct *length;
+ offset_t spmark;
+ uoffset_t typesize;
+
+ typesize = source->type->typesize;
+ length = constsym((value_t) typesize);
+ length->type = uitype;
+ address(source);
+ modstk(spmark = sp - (offset_t) typesize);
+#ifdef STACKREG
+ regtransfer(STACKREG, DREG);
+#else
+#ifdef MC6809 /* XXX ? */
+ regtransfer(LOCAL, DREG);
+#else
+#include "need STACKREG and stackregstr"
+#endif
+#endif
+ push(length);
+ push(source);
+ pushreg(DREG);
+ call("_memcpy");
+ outnl();
+ modstk(spmark);
+ indirec(source);
+}
+
+PUBLIC void exchange(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t tempreg;
+
+ regexchange(source->storage, target->storage);
+ tempreg = target->storage;
+ target->storage = source->storage;
+ source->storage = tempreg;
+}
+
+/*-----------------------------------------------------------------------------
+ getindexreg()
+ returns the "best" available index register
+-----------------------------------------------------------------------------*/
+
+PUBLIC store_pt getindexreg()
+{
+ if (!(reguse & INDREG0))
+ return INDREG0;
+ if (!(reguse & INDREG1))
+ return INDREG1;
+ if (!(reguse & INDREG2))
+ return INDREG2;
+#if NOTFINISHED
+#ifdef I8088
+ if (i386_32)
+ {
+ if (!(reguse & DATREG1))
+ return DATREG1;
+ if (!(reguse & DATREG2))
+ return DATREG2;
+ }
+#endif
+#endif
+ bugerror("out of index regs");
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ indexadr(index leaf, pointer leaf)
+ is used by the index and add and subtract (pointer) routines
+ it handles expressions like
+ pointer + index
+ &array[index]
+ the target becomes register direct with offset
+ (except for index = 0, when nothing is changed)
+ constant indexes are optimised by leaving them as offsets
+ register direct pointers are optimised by leaving the offset alone
+ (except for PC register direct, since there is no LEAX D,PC)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void indexadr(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+#ifdef MC6809
+ bool_t canABX;
+#endif
+ uoffset_t size;
+ store_pt sourcereg;
+ struct typestruct *targtype;
+ store_pt targreg;
+
+ if (!(target->type->constructor & (ARRAY | POINTER)))
+ {
+ bugerror("cannot index");
+ return;
+ }
+ size = target->type->nexttype->typesize;
+ if (source->storage == CONSTANT)
+ {
+ if (source->offset.offv != 0)
+ {
+ if (target->indcount != 0)
+ loadany(target);
+ target->offset.offi += source->offset.offv * size;
+ }
+ return;
+ }
+ if (target->storage & ALLDATREGS)
+ push(target);
+ if ((store_t) (sourcereg = target->storage) & ~reguse & allindregs)
+ targreg = sourcereg;
+ else
+ targreg = getindexreg();
+#ifdef I8088
+ if ((store_t) sourcereg == GLOBAL && target->indcount == 0 &&
+ !(source->type->scalar & CHAR) && source->storage != DREG)
+ load(source, targreg);
+ else
+#endif
+ load(source, DREG);
+
+#ifdef I8088
+ softop(MULOP, constsym((value_t) size), source);
+#endif
+#ifdef MC6809
+
+/*-----------------------------------------------------------------------------
+ do some calculations in advance to decide if index can be done with ABX
+-----------------------------------------------------------------------------*/
+
+ if ((store_t) targreg == XREG && source->type->scalar & CHAR &&
+ size < CANABXCUTOFF)
+ canABX = TRUE;
+ else
+ {
+ canABX = FALSE;
+ softop(MULOP, constsym((value_t) size), source);
+ }
+
+#endif
+
+/*-----------------------------------------------------------------------------
+ deal with constant target - constant becomes offset, result in DREG
+-----------------------------------------------------------------------------*/
+
+ if (target->storage == CONSTANT)
+ {
+ target->storage = DREG;
+ return;
+ }
+
+/*-----------------------------------------------------------------------------
+ load target if it is indirect or GLOBAL or canABX so D or B can be added
+ otherwise, it is register direct (maybe S register, maybe with offset)
+ and the offset can be left after adding DREG
+-----------------------------------------------------------------------------*/
+
+#ifdef I8088
+ if (target->indcount != 0)
+ {
+ targtype = target->type;
+ target->type = itype;
+ add(source, target);
+ target->type = targtype;
+ return;
+ }
+ if ((store_t) sourcereg == GLOBAL)
+ {
+ target->storage = source->storage;
+ target->level = OFFKLUDGELEVEL;
+ return;
+ }
+#endif
+#ifdef MC6809
+ if (canABX || (store_t) sourcereg == GLOBAL)
+ {
+ load(target, targreg);
+ sourcereg = targreg;
+ }
+ else if (target->indcount != 0)
+ {
+ targtype = target->type;
+ target->type = itype;
+ add(source, target);
+ target->type = targtype;
+ return;
+ }
+ if (canABX)
+ while (size--)
+ outABX();
+ else
+#endif
+ {
+#ifdef I8088
+ if ((store_t) targreg != (store_t) sourcereg)
+ regtransfer(sourcereg, targreg);
+ outadd();
+ outregname(targreg);
+ outncregname(DREG);
+#endif
+#ifdef MC6809
+ outlea();
+ outregname(targreg);
+ outtab();
+ outregname(DREG);
+ outncregname(sourcereg);
+#endif
+ }
+ if ((store_t) sourcereg == LOCAL)
+#ifdef FRAMEPOINTER
+ target->offset.offi -= framep;
+#else
+ target->offset.offi -= sp;
+#endif
+ target->storage = targreg;
+}
+
+PUBLIC void indirec(source)
+struct symstruct *source;
+{
+ if (!(source->type->constructor & (ARRAY | POINTER)))
+ bugerror("illegal indirection");
+ else if (source->indcount == (indn_t) - 1)
+ limiterror("too many indirections (256)");
+ else
+ {
+ if (source->storage & ALLDATREGS)
+ transfer(source, getindexreg());
+ if (!((source->type = source->type->nexttype)->constructor &
+ (ARRAY | FUNCTION)))
+ ++source->indcount;
+ if (source->storage == CONSTANT)
+ source->storage = GLOBAL;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ load(source leaf, target register)
+ loads the specified register without changing any others (except CC)
+ if the type is long or float, DREG is paired with the target register
+ the result has no offset
+-----------------------------------------------------------------------------*/
+
+PUBLIC void load(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ if (source->type->scalar & DLONG)
+ {
+ if (source->storage == CONSTANT)
+ loadreg(source, targreg);
+ else if (source->indcount == 0)
+ {
+#if DYNAMIC_LONG_ORDER
+ if (!long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ {
+ if ((store_t) targreg == DREG)
+ source->storage = DREG;
+ }
+#endif
+ if (source->storage != (store_t) targreg)
+ transfer(source, targreg);
+ if (source->offset.offi != 0)
+ bugerror("loading direct long with offset not implemented");
+ }
+ else
+ loadlongindirect(source, targreg);
+ }
+ else if (source->type->scalar & DOUBLE)
+ {
+ if (source->storage == targreg && source->indcount == 0)
+ return;
+ if (source->storage == CONSTANT)
+ {
+ /* XXX - more for non-386 */
+ loadconst(((offset_t *) source->offset.offd)[0], DREG);
+ loadconst(((offset_t *) source->offset.offd)[1], targreg);
+ }
+ else
+ {
+ push(source);
+ poplist(targreg | DREG); /* actually it's the full reg list */
+ }
+ source->storage = targreg; /* XXX - multi for non-386 */
+ source->indcount = 0;
+ source->flags = 0;
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ source->offset.offi = 0;
+ }
+ else if (source->type->scalar & FLOAT && source->storage == CONSTANT)
+ {
+ float val;
+
+ val = *source->offset.offd;
+ loadconst(((offset_t *) &val)[0], targreg);
+ }
+ else if (source->indcount == 0 && source->storage != CONSTANT)
+ loadadr(source, targreg);
+ else if (source->type->scalar ||
+ source->type->constructor & (ARRAY | POINTER))
+ loadreg(source, targreg);
+ else
+ bugerror("attempting to load non-scalar non-pointer");
+}
+
+PRIVATE void loadadr(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ if ((store_t) targreg & ALLDATREGS)
+ {
+ if (source->storage == GLOBAL)
+ {
+#ifdef MC6809
+ if (posindependent)
+ {
+ pushreg(INDREG0);
+ loadreg(source, INDREG0);
+ transfer(source, DREG);
+ recovlist(INDREG0);
+ }
+ else
+#endif
+ loadreg(source, targreg);
+ }
+ if (source->storage == LOCAL)
+#ifdef FRAMEPOINTER
+ source->offset.offi -= framep;
+#else
+ source->offset.offi -= sp;
+#endif
+ if (source->type->scalar & CHAR)
+ targreg = BREG;
+#ifdef I8088
+ if (source->storage == DREG)
+ addoffset(source);
+#endif
+ if (source->storage != (store_t) targreg)
+ transfer(source, targreg);
+ addoffset(source);
+ }
+ else if (source->storage & ALLDATREGS)
+ {
+ addoffset(source);
+ transfer(source, targreg);
+ }
+ else if (source->storage != (store_t) targreg ||
+ source->offset.offi != 0 || source->level == OFFKLUDGELEVEL)
+ loadreg(source, targreg);
+}
+
+PUBLIC void loadany(source)
+struct symstruct *source;
+{
+ if (source->indcount != 0 || source->offset.offi != 0 || /* kludge u cmp */
+ source->level == OFFKLUDGELEVEL || !(source->storage & allregs))
+ {
+ if (source->type->scalar & RSCALAR)
+ load(source, doubleregs & ~DREG);
+ else if ((source->storage == CONSTANT &&
+ !(source->type->scalar & DLONG))
+ || source->type->scalar & CHAR)
+ load(source, DREG);
+ else if (source->storage & ~reguse & allregs)
+ load(source, source->storage);
+ else if (((reguse & allindregs) == allindregs ||
+ ((!(source->type->constructor & (ARRAY | POINTER)) &&
+ source->indcount != 0) &&
+ !(source->type->scalar & DLONG))))
+ load(source, DREG);
+ else
+ load(source, getindexreg());
+ }
+}
+
+PRIVATE void loadlongindirect(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ sc_t flags;
+ offset_t offset;
+ store_t reg;
+ struct typestruct *type;
+
+ if (source->level == OFFKLUDGELEVEL)
+ addoffset(source); /* else kludge is lost and offsets big */
+ flags = source->flags;
+ offset = source->offset.offi;
+ reg = source->storage;
+ type = source->type;
+ source->type = itype;
+ loadreg(source, DREG);
+ source->flags = flags;
+ source->storage = reg;
+ source->indcount = 1;
+ source->offset.offi = offset + accregsize;
+ loadreg(source, targreg);
+ source->type = type;
+}
+
+PUBLIC void loadreg(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ offset_t longhigh;
+ offset_t longlow;
+
+ if (source->storage == CONSTANT)
+ {
+ if (source->type->scalar & CHAR && (store_t) targreg & ALLDATREGS)
+ targreg = BREG;
+ longlow = (offset_t) source->offset.offv;
+ if (source->type->scalar & DLONG)
+ {
+ longlow &= (offset_t) intmaskto;
+ longhigh = (offset_t) (source->offset.offv >> INT16BITSTO)
+ & (offset_t) intmaskto;
+ if ((store_t) targreg != LONGREG2) /* loading the whole long */
+ {
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ loadconst(longhigh, DREG);
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ {
+ loadconst(longlow, DREG);
+ longlow = longhigh;
+ }
+#endif
+ }
+ }
+ loadconst(longlow, targreg);
+ source->storage = targreg;
+ source->offset.offi = 0;
+ }
+ else
+ {
+#ifdef I8088
+ if (source->indcount == 0 && source->storage != GLOBAL &&
+ (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL))
+ {
+ if ((store_t) targreg == source->storage)
+ {
+ addoffset(source);
+ return;
+ }
+ source->indcount = 1; /* fake for outadr() to produce "()" */
+ outlea();
+ }
+ else
+ {
+ outload();
+ if (source->storage == GLOBAL && source->indcount != 0 &&
+ (store_t) targreg & (AXREG | ALREG))
+ unbumplc();
+ }
+#endif
+#ifdef MC6809
+ if (source->indcount == 0 &&
+ (source->storage != GLOBAL || posindependent))
+ outlea();
+ else
+ {
+ outload();
+ if ((store_t) targreg == YREG)
+ bumplc();
+ }
+#endif
+ movereg(source, targreg);
+ }
+}
+
+PUBLIC void makelessindirect(source)
+struct symstruct *source;
+{
+ store_pt lreg;
+
+ if (!((store_t) (lreg = source->storage) & ~reguse & allindregs))
+ lreg = getindexreg();
+ while (source->indcount > MAXINDIRECT)
+ loadreg(source, lreg);
+#if MAXINDIRECT > 1
+ if (source->indcount == MAXINDIRECT &&
+ (source->type->typesize > maxregsize ||
+ source->type->constructor & FUNCTION))
+ {
+ source->indcount = 1;
+ loadreg(source, lreg);
+ source->indcount = 1;
+ }
+#endif
+}
+
+PUBLIC void movereg(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ if ((store_t) targreg & ALLDATREGS && source->type->scalar & CHAR)
+ targreg = BREG;
+#ifdef I8088
+ if (i386_32 && source->type->scalar & SHORT &&
+ source->indcount <= 1)
+ {
+ outshortregname(targreg);
+ bumplc();
+ }
+ else
+#endif
+ outregname(targreg);
+ if (source->storage == CONSTANT)
+ adjlc((offset_t) source->offset.offv, targreg);
+#ifdef I8088
+ outcomma();
+#endif
+ outadr(source);
+ source->storage = targreg; /* in register for further use */
+ source->flags = 0;
+ if (source->level == OFFKLUDGELEVEL)
+ source->level = EXPRLEVEL;
+ source->offset.offi = 0; /* indcount was adjusted by outadr */
+}
+
+PUBLIC void onstack(target)
+register struct symstruct *target;
+{
+ target->storage = LOCAL;
+ target->flags = TEMP;
+ if (target->level == OFFKLUDGELEVEL)
+ target->level = EXPRLEVEL;
+ target->indcount = 1;
+ target->offset.offi = sp;
+}
+
+PUBLIC void outadr(adr)
+struct symstruct *adr;
+{
+ outnnadr(adr);
+ outnl();
+}
+
+PUBLIC void outcregname(reg)
+store_pt reg;
+{
+ outcomma();
+ outregname(reg);
+}
+
+PRIVATE void outnamoffset(adr)
+struct symstruct *adr;
+{
+ outimmed();
+ if (adr->flags & LABELLED)
+ outlabel(adr->name.label);
+ else
+ outccname(adr->name.namep);
+ if (adr->offset.offi != 0)
+ {
+ if (adr->offset.offi > 0)
+ outplus();
+ outshex(adr->offset.offi);
+ }
+ bumplc2();
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+/* print comma, then register name, then newline */
+
+PUBLIC void outncregname(reg)
+store_pt reg;
+{
+ outcomma();
+ outnregname(reg);
+}
+
+PRIVATE void outnnadr(adr)
+struct symstruct *adr;
+{
+ bool_t indflag;
+
+ indflag = FALSE;
+#ifdef I8088
+ if (adr->indcount >= MAXINDIRECT)
+ indflag = TRUE;
+#endif
+#ifdef MC6809
+ outtab();
+ if (adr->indcount >= MAXINDIRECT && (adr->indcount & 1) == 0)
+ {
+ indflag = TRUE; /* indirection means double indirect */
+ outindleft();
+ }
+#endif
+ switch (adr->storage)
+ {
+ case CONSTANT:
+ outimmadr((offset_t) adr->offset.offv);
+ break;
+#ifdef I8088
+ case DREG:
+ if (indflag || adr->offset.offi != 0 || adr->level == OFFKLUDGELEVEL)
+ badaddress();
+ else
+ outregname(DREG);
+ break;
+#endif
+#ifdef I8088
+ case DATREG1:
+ case DATREG2:
+ if (indflag && !i386_32)
+ {
+ outnl();
+ badaddress();
+ break;
+ }
+#endif
+ case INDREG0:
+ case INDREG1:
+ case INDREG2:
+ if (adr->level == OFFKLUDGELEVEL)
+ outnamoffset(adr);
+#ifndef MC6809
+ else if (adr->offset.offi != 0)
+#endif
+ outoffset(adr->offset.offi);
+#ifdef I8088
+ if (indflag)
+ outindleft();
+ outregname(adr->storage);
+# ifdef XENIX_AS
+ if (indflag)
+ outindright();
+# endif
+#endif
+#ifdef MC6809
+ if (indflag && adr->offset.offi != 0 && is5bitoffset(adr->offset.offi))
+ bumplc();
+ outcregname(adr->storage);
+#endif
+ break;
+ case LOCAL:
+#ifdef I8088
+# ifdef FRAMEPOINTER
+ if (framep == 0)
+ bugerror("no frame pointer");
+ if (indflag)
+ {
+ if (adr->offset.offi == framep)
+ bumplc();
+ else
+ {
+ if (switchnow != NULL && adr->flags == TEMP)
+ outswoffset(adr->offset.offi);
+ else
+ outoffset(adr->offset.offi - framep);
+ }
+ outindleft();
+ }
+ else if (adr->offset.offi != framep)
+ badaddress();
+ outregname(LOCAL);
+# else
+ if (indflag)
+ {
+ bumplc();
+ if (adr->offset.offi != sp)
+ outoffset(adr->offset.offi - sp);
+ outindleft();
+ }
+ else if (adr->offset.offi != sp)
+ badaddress();
+ outregname(LOCAL);
+# endif /* FRAMEPOINTER */
+# ifdef XENIX_AS
+ if (indflag)
+ outindright();
+# endif
+#endif /* I8088 */
+#ifdef MC6809
+ if (adr->flags == TEMP && adr->offset.offi == sp &&
+ adr->indcount == 1)
+ {
+ outcregname(LOCAL);
+ outplus();
+ ++sp;
+ if (adr->type->typesize != 1)
+ {
+ outplus();
+ ++sp;
+ }
+ break;
+ }
+ outoffset(adr->offset.offi - sp);
+ if (indflag && adr->offset.offi != sp &&
+ is5bitoffset(adr->offset.offi - sp))
+ bumplc();
+ outcregname(LOCAL);
+#endif /* MC6809 */
+ break;
+ case GLOBAL:
+#ifdef I8088
+ bumplc();
+ if (i386_32)
+ bumplc2();
+ if (!indflag)
+ outimmed();
+ else
+ {
+# ifndef XENIX_AS
+ outindleft();
+# endif
+ bumplc();
+ }
+#endif
+#ifdef MC6809
+ if (!posindependent)
+ {
+ if (adr->indcount == 0)
+ {
+ outimmed();
+ bumplc();
+ }
+ else if (indflag)
+ {
+ outextended();
+ bumplc2();
+ }
+ else if (adr->flags & DIRECTPAGE)
+ outdirectpage();
+ else
+ {
+ outextended();
+ bumplc();
+ }
+ }
+#endif
+ if (adr->flags & LABELLED)
+ outlabel(adr->name.label);
+ else if (*adr->name.namep == 0) /* constant address */
+ {
+ outhex((uoffset_t) adr->offset.offi);
+ break;
+ }
+ else
+ outccname(adr->name.namep);
+ if (adr->offset.offi != 0)
+ {
+ if (adr->offset.offi > 0)
+ outplus();
+ outshex(adr->offset.offi);
+ }
+#ifdef MC6809
+ if (posindependent)
+ {
+ outcregname(GLOBAL);
+ bumplc2();
+ }
+#endif
+ break;
+ default:
+ outnl();
+ badaddress();
+ break;
+ }
+#ifdef I8088
+ if (indflag)
+ {
+ --adr->indcount;
+# ifndef XENIX_AS
+ outindright();
+# endif
+ }
+#endif
+#ifdef MC6809
+ if (indflag)
+ {
+ outindright();
+ adr->indcount -= MAXINDIRECT;
+ }
+ else if (adr->indcount != 0)
+ --adr->indcount;
+#endif
+}
+
+/* print register name, then newline */
+
+PUBLIC void outnregname(reg)
+store_pt reg;
+{
+ outregname(reg);
+ outnl();
+}
+
+/* print register name */
+
+PUBLIC void outregname(reg)
+store_pt reg;
+{
+ switch ((store_t) reg)
+ {
+ case BREG:
+ outstr(acclostr);
+ break;
+ case DREG:
+ outstr(accumstr);
+ break;
+#ifdef MC6809
+ case GLOBAL:
+ outstr("PC");
+ break;
+#endif
+ case INDREG0:
+ outstr(ireg0str);
+ break;
+ case INDREG1:
+ outstr(ireg1str);
+ break;
+ case INDREG2:
+ outstr(ireg2str);
+ break;
+ case LOCAL:
+ outstr(localregstr);
+ break;
+#ifdef STACKREG
+ case STACKREG:
+ outstr(stackregstr);
+ break;
+#endif
+#ifdef DATREG1
+ case DATREG1:
+ outstr(dreg1str);
+ break;
+#endif
+#ifdef DATREG1B
+ case DATREG1B:
+ outstr(dreg1bstr);
+ break;
+#endif
+#ifdef DATREG2
+ case DATREG2:
+ outstr(dreg2str);
+ break;
+#endif
+ default:
+ outstr(badregstr);
+ break;
+ }
+}
+
+#ifdef I8088
+/* print register name for short type */
+
+PUBLIC void outshortregname(reg)
+store_pt reg;
+{
+ switch ((store_t) reg)
+ {
+ case DREG:
+ outstr(accumstr + 1);
+ break;
+ case INDREG0:
+ outstr(ireg0str + 1);
+ break;
+ case INDREG1:
+ outstr(ireg1str + 1);
+ break;
+ case INDREG2:
+ outstr(ireg2str + 1);
+ break;
+ case DATREG1:
+ outstr(dreg1str + 1);
+ break;
+ case DATREG2:
+ outstr(dreg2str + 1);
+ break;
+ default:
+ outstr(badregstr);
+ break;
+ }
+}
+
+#endif
+
+/*-----------------------------------------------------------------------------
+ pointat(target leaf)
+ point OPREG at target
+ target must be singly indirect or float or double
+-----------------------------------------------------------------------------*/
+
+PUBLIC void pointat(target)
+struct symstruct *target;
+{
+ if (target->type->scalar & RSCALAR)
+ (void) f_indirect(target);
+ address(target);
+ load(target, OPREG);
+ target->type = target->type->nexttype;
+}
+
+PUBLIC void poplist(reglist)
+store_pt reglist;
+{
+ if (reglist)
+ sp += pushpull(reglist, FALSE);
+}
+
+PUBLIC void push(source)
+struct symstruct *source;
+{
+ store_t reg;
+#ifdef I8088
+ uoffset_t size;
+#endif
+ scalar_t sscalar;
+
+ if (source->type->constructor & STRUCTU)
+ {
+ if (source->flags != TEMP) /* TEMP must be from last function */
+ blockpush(source);
+ }
+ else if ((sscalar = source->type->scalar) & RSCALAR)
+ {
+ if (!f_indirect(source))
+ {
+ saveopreg();
+ fpush(source);
+ restoreopreg();
+ }
+ }
+#ifdef I8088
+ else if ((source->indcount == 1 &&
+ (sscalar & (SHORT | INT | LONG | FLOAT) ||
+ source->type->constructor & POINTER)) ||
+ (source->storage == CONSTANT && i386_32))
+ {
+ size = source->type->typesize;
+ if (size == 1)
+ size = 2;
+ if (sscalar & DLONG)
+ {
+ source->offset.offi += itypesize;
+ outpshs();
+ bumplc();
+ outtab();
+ outadr(source);
+ source->indcount = 1;
+ source->offset.offi -= itypesize;
+ }
+ outpshs();
+ bumplc();
+ outtab();
+ if (i386_32)
+ {
+ if (source->storage == CONSTANT)
+ {
+ unbumplc();
+ adjlc((offset_t) source->offset.offv, INDREG0);
+ }
+ if (size == 2)
+ {
+ outword();
+ bumplc();
+ }
+ else
+ outdword();
+ }
+ outadr(source);
+ sp -= size;
+ }
+#endif
+ else
+ {
+ reg = source->storage;
+ loadany(source);
+ if (sscalar & DLONG)
+ pushlist(DREG | source->storage);
+ else if (sscalar & CHAR)
+ pushchar();
+ else
+ pushreg(source->storage);
+ if (source->flags != REGVAR)
+ reguse &= ~(reg | source->storage);
+ }
+ onstack(source);
+}
+
+PUBLIC void pushlist(reglist)
+store_pt reglist;
+{
+ if ((store_t) reglist)
+ sp -= pushpull(reglist, TRUE);
+}
+
+PRIVATE fastin_pt pushpull(reglist, pushflag)
+store_pt reglist;
+bool_pt pushflag;
+{
+ store_pt lastregbit;
+ void (*ppfunc) P((void));
+ char *regptr;
+
+#ifdef MC6809
+ int separator; /* promoted char for output */
+
+#endif
+ fastin_t bytespushed;
+ store_pt regbit;
+
+ if ((bool_t) pushflag)
+ {
+ ppfunc = outpshs;
+#ifdef I8088
+ regbit = 1 << 10;
+#else
+ regbit = 1 << 7;
+#endif
+ regptr = regpushlist;
+ lastregbit = 1;
+ }
+ else
+ {
+ ppfunc = outpuls;
+ regbit = 1;
+ regptr = regpulllist;
+#ifdef I8088
+ lastregbit = 1 << 10;
+#else
+ lastregbit = 1 << 7;
+#endif
+ }
+#ifdef MC6809 /* temp use pull strings to keep old order */
+ regbit = 1;
+ regptr = regpulllist;
+ lastregbit = 1 << 7;
+#endif
+#ifdef MC6809
+ separator = OPSEPARATOR;
+ (*ppfunc) ();
+#endif
+ bytespushed = 0;
+ while (TRUE)
+ {
+ if (regbit & reglist)
+ {
+#ifdef I8088
+ (*ppfunc)();
+ if (*regptr != FLAGSREGCHAR)
+ outtab();
+#endif
+#ifdef MC6809
+ outbyte(separator);
+#endif
+ do
+ outbyte(*regptr++);
+ while (*regptr >= MINREGCHAR);
+ bytespushed += *regptr++ - '0';
+#ifdef I8088
+ outnl();
+#endif
+#ifdef MC6809
+ separator = OPERANDSEPARATOR;
+#endif
+ }
+ else
+ do
+ ;
+ while (*regptr++ >= MINREGCHAR);
+ if (regbit == lastregbit)
+ break;
+#ifdef MC6809 /* temp use pull strings to keep old order */
+ regbit <<= 1;
+#else /* this should normally be unconditional */
+ if ((bool_t) pushflag)
+ regbit >>= 1;
+ else
+ regbit <<= 1;
+#endif
+ }
+#ifdef MC6809
+ outnl();
+#endif
+ return bytespushed;
+}
+
+PUBLIC void pushreg(reg)
+store_pt reg;
+{
+ outpshs();
+ outtab();
+ outnregname(reg);
+ sp -= pshregsize;
+}
+
+PUBLIC void storereg(sourcereg, target)
+store_pt sourcereg;
+struct symstruct *target;
+{
+ store_pt targreg;
+
+ if (target->indcount == 0)
+ {
+ if (target->offset.offi != 0 || target->level == OFFKLUDGELEVEL ||
+ !(target->storage & allregs) || target->storage & CHARREGS)
+ bugerror("bad register store");
+ else if ((store_t) (targreg = target->storage) != (store_t) sourcereg)
+ {
+ target->storage = sourcereg;
+ loadadr(target, targreg); /* do LEA or TFR */
+ }
+ }
+ else
+ {
+ outstore();
+#ifdef I8088
+ if (target->storage == GLOBAL && (store_t) sourcereg & (AXREG | ALREG))
+ unbumplc();
+ outnnadr(target);
+ outcomma();
+#ifdef I8088
+ if (i386_32 && target->type->scalar & SHORT)
+ {
+ outshortregname(sourcereg);
+ bumplc();
+ outnl();
+ }
+ else
+#endif
+ outnregname(sourcereg);
+#endif
+#ifdef MC6809
+ if ((store_t) sourcereg == YREG)
+ bumplc();
+ outregname(sourcereg);
+ outadr(target);
+#endif
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ struc(element leaf, structure leaf)
+ evaluates the expression
+ structure.element
+-----------------------------------------------------------------------------*/
+
+PUBLIC void struc(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ address(target);
+ if (source->offset.offi != 0 || source->level == OFFKLUDGELEVEL)
+ {
+ if (target->indcount != 0 || target->level == OFFKLUDGELEVEL)
+ load(target, getindexreg());
+ target->offset.offi += source->offset.offi;
+ }
+ if (source->indcount == 0)
+ target->type = source->type;
+ else
+ {
+ target->type = pointype(source->type); /* lost by = */
+ indirec(target);
+ }
+}
+
+PUBLIC void transfer(source, targreg)
+struct symstruct *source;
+store_pt targreg;
+{
+ regtransfer(source->storage, targreg);
+ source->storage = targreg;
+}
diff --git a/bcc/glogcode.c b/bcc/glogcode.c
new file mode 100644
index 0000000..e2d086b
--- /dev/null
+++ b/bcc/glogcode.c
@@ -0,0 +1,560 @@
+/* glogcode.c - generate code for logical expressions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#define cc_signed(cc) ((cc) >= 4 && (cc) < 8)
+
+PRIVATE char oppcc[] = /* opposite condition codes LT --> GE etc */
+/* EQ, NE, RA, RN, LT, GE, LE, GT, LO, HS, LS, HI, indices */
+{
+ NE, EQ, RN, RA, GE, LT, GT, LE, HS, LO, HI, LS,
+};
+
+PRIVATE char reverscc[] = /* reverse condition codes LT --> GT etc */
+{
+ EQ, NE, RN, RA, GT, LE, GE, LT, HI, LS, HS, LO,
+};
+
+PRIVATE char testcc[] = /* test condition codes LS --> EQ etc */
+{
+ EQ, NE, RA, RN, LT, GE, LE, GT, RN, RA, EQ, NE,
+};
+
+PRIVATE char unsigncc[] = /* unsigned condition codes LT --> LO etc */
+{
+ EQ, NE, RA, RN, LO, HS, LS, HI, LO, HS, LS, HI,
+};
+
+FORWARD void cmplocal P((struct symstruct *source, struct symstruct *target,
+ ccode_t *pcondtrue));
+#ifdef MC6809
+FORWARD void cmporsub P((struct symstruct *target));
+FORWARD bool_pt cmpsmallconst P((value_t intconst, struct symstruct *target,
+ ccode_t *pcondtrue));
+#endif
+FORWARD void comparecond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void jumpcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void loadlogical P((struct symstruct *source, label_t falselab));
+FORWARD void logandcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void logorcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+FORWARD void reduceconst P((struct symstruct *source));
+FORWARD void test P((struct symstruct *target, ccode_t *pcondtrue));
+FORWARD void testcond P((struct nodestruct *exp, label_t truelab,
+ label_t falselab, bool_pt nojump));
+
+PUBLIC void cmp(source, target, pcondtrue)
+struct symstruct *source;
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+ label_t falselab;
+
+ cmplocal(source, target, pcondtrue);
+#if 0
+#ifdef I8088
+ if (i386_32)
+ {
+ if (*pcondtrue == LO)
+ {
+ getlabel();
+ getlabel();
+ outnop2str("sbb\teax,eax");
+ outnop1str("inc eax");
+ target->storage = BREG;
+ target->type = ctype;
+ return;
+ }
+ if (*pcondtrue == HS)
+ {
+ getlabel();
+ getlabel();
+ outnop2str("sbb\teax,eax");
+ outnop2str("neg eax");
+ target->storage = BREG;
+ target->type = ctype;
+ return;
+ }
+ }
+#endif
+#endif
+ sbranch(oppcc[(int)*pcondtrue], falselab = getlabel());
+ loadlogical(target, falselab);
+}
+
+PRIVATE void cmplocal(source, target, pcondtrue)
+struct symstruct *source;
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+ scalar_t sscalar;
+ scalar_t tempscalar;
+ scalar_t tscalar;
+
+ reduceconst(source);
+ reduceconst(target);
+ sscalar = source->type->scalar;
+ tscalar = target->type->scalar;
+ if ((source->storage != CONSTANT &&
+ (target->storage == CONSTANT ||
+ (sscalar & CHAR && !(tscalar & CHAR)) ||
+ ((sscalar & CHAR || !(tscalar & CHAR)) &&
+ source->indcount == 0 && target->indcount != 0))) ||
+ (tscalar & DLONG && target->indcount != 0))
+ {
+ swapsym(target, source);
+ *pcondtrue = reverscc[(int)*pcondtrue];
+ tempscalar = sscalar;
+ sscalar = tscalar;
+ tscalar = tempscalar;
+ }
+ if ((sscalar & CHAR && tscalar & CHAR &&
+ (source->type != sctype || target->type != sctype)) ||
+ (sscalar | tscalar) & UNSIGNED ||
+ (source->type->constructor | target->type->constructor) &
+ (ARRAY | POINTER))
+ *pcondtrue = unsigncc[(int)*pcondtrue];
+ if (source->type->scalar & DLONG)
+ {
+ longop(EQOP, source, target);
+ return;
+ }
+ if (source->type->scalar & RSCALAR)
+ {
+ floatop(EQOP, source, target);
+ return;
+ }
+ if (source->storage == CONSTANT)
+ {
+ if (sscalar & CHAR)
+ {
+ if (tscalar & CHAR)
+ *pcondtrue = unsigncc[(int)*pcondtrue];
+ else
+ {
+ source->type = iscalartotype(sscalar);
+ sscalar = source->type->scalar;
+ }
+ }
+ if (source->offset.offv == 0)
+ {
+ test(target, pcondtrue);
+ return;
+ }
+#ifdef MC6809
+ if (cmpsmallconst(source->offset.offv, target, pcondtrue))
+ return;
+#endif
+ }
+ if (!(sscalar & CHAR) && tscalar & CHAR)
+ {
+ loadpres(target, source);
+ extend(target);
+ }
+#ifndef MC6809
+# define posindependent 0
+#endif
+ if (source->indcount == 0 && source->storage != CONSTANT &&
+ (posindependent || source->storage != GLOBAL))
+ {
+ loadpres(source, target);
+#ifdef MC6809
+ push(source);
+#endif
+ }
+ loadpres(target, source);
+#ifdef MC6809
+ cmporsub(target);
+#else
+ outcmp();
+#endif
+#ifdef I8088
+ if (source->storage == GLOBAL && source->indcount == 0 &&
+ !(target->storage & (AXREG | ALREG)))
+ bumplc();
+#endif
+ movereg(source, target->storage);
+}
+
+#ifdef MC6809
+
+PRIVATE void cmporsub(target)
+struct symstruct *target;
+{
+ if (target->storage & ALLDATREGS)
+ outsub();
+ else
+ {
+ outcmp();
+ if (target->storage != XREG)
+ bumplc();
+ }
+}
+
+PRIVATE bool_pt cmpsmallconst(intconst, target, pcondtrue)
+value_t intconst;
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+ store_pt targreg;
+
+ if ((*pcondtrue == EQ || *pcondtrue == NE) &&
+ !(target->storage & ALLDATREGS) && !(target->type->scalar & CHAR) &&
+ isnegbyteoffset(intconst) &&
+ (reguse & (XREG | YREG)) != (XREG | YREG))
+ {
+ targreg = XREG;
+ if (reguse & XREG)
+ targreg = YREG;
+ if (target->indcount != 0)
+ load(target, targreg);
+ target->offset.offi -= (offset_t) intconst;
+ loadreg(target, targreg);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#endif
+
+PRIVATE void comparecond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ ccode_t condtrue;
+ store_t regmark;
+ struct symstruct *source;
+ offset_t spmark;
+ struct symstruct *target;
+
+ regmark = reguse;
+ spmark = sp;
+ bileaf(exp);
+ target = exp->left.nodeptr->left.symptr;
+ source = exp->right->left.symptr; /* exp->right != NULL since cond */
+ switch (exp->tag)
+ {
+ case GEOP:
+ condtrue = GE;
+ break;
+ case GTOP:
+ condtrue = GT;
+ break;
+ case LEOP:
+ condtrue = LE;
+ break;
+ case EQOP:
+ condtrue = EQ;
+ break;
+ case LTOP:
+ condtrue = LT;
+ break;
+ case NEOP:
+ condtrue = NE;
+ break;
+ }
+ cmplocal(source, target, &condtrue);
+ changesp(spmark, FALSE);
+ reguse = regmark;
+ if ((bool_t) nojump)
+ lbranch(oppcc[(int)condtrue], falselab);
+ else
+ lbranch(condtrue, truelab);
+}
+
+PUBLIC void condop(exp)
+struct nodestruct *exp;
+{
+ label_t exitlab;
+ label_t falselab;
+ struct nodestruct *falsenode;
+ struct symstruct *falsesym;
+ label_t truelab;
+ struct nodestruct *truenode;
+ struct symstruct *truesym;
+
+ jumpcond(exp->left.nodeptr, truelab = getlabel(),
+ falselab = getlabel(), ~0);
+ deflabel(truelab);
+ makeleaf(truenode = exp->right->left.nodeptr);
+ loadany(truesym = truenode->left.symptr);
+ if (truesym->storage & reguse)
+ {
+ /* This can happen if truesym was a reg variable. */
+ if (truesym->type->scalar & RSCALAR)
+ /* XXX - always happens for non-386 with 2 regs vars assigned. */
+ bugerror("loaded float or double into used reg");
+ load(truesym, DREG);
+ }
+ falsenode = exp->right->right;
+ if (/* falsenode->tag != LEAF || XXX */
+ truesym->type != falsenode->left.symptr->type)
+ cast(truenode->nodetype == falsenode->nodetype ?
+ truenode->nodetype : exp->nodetype, truesym);
+ jump(exitlab = getlabel());
+ deflabel(falselab);
+ makeleaf(falsenode);
+ falsesym = falsenode->left.symptr;
+ if (falsesym->type != truesym->type)
+ cast(truesym->type, falsesym);
+ load(falsesym, truesym->storage);
+ deflabel(exitlab);
+ exp->tag = LEAF;
+ exp->left.symptr = truesym;
+}
+
+PRIVATE void jumpcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ switch (exp->tag)
+ {
+ case GEOP:
+ case GTOP:
+ case LEOP:
+ case EQOP:
+ case LTOP:
+ case NEOP:
+ comparecond(exp, truelab, falselab, nojump);
+ break;
+ case LOGANDOP:
+ logandcond(exp, truelab, falselab, nojump);
+ break;
+ case LOGNOTOP:
+ jumpcond(exp->left.nodeptr, falselab, truelab, ~nojump);
+ break;
+ case LOGOROP:
+ logorcond(exp, truelab, falselab, nojump);
+ break;
+ default:
+ testcond(exp, truelab, falselab, nojump);
+ break;
+ }
+}
+
+PUBLIC void jumpfalse(exp, label)
+struct nodestruct *exp;
+label_t label;
+{
+ label_t truelab;
+
+ jumpcond(exp, truelab = getlabel(), label, ~0);
+ deflabel(truelab);
+}
+
+PUBLIC void jumptrue(exp, label)
+struct nodestruct *exp;
+label_t label;
+{
+ label_t falselab;
+
+ jumpcond(exp, label, falselab = getlabel(), 0);
+ deflabel(falselab);
+}
+
+PRIVATE void loadlogical(source, falselab)
+struct symstruct *source;
+label_t falselab;
+{
+ label_t exitlab;
+ struct symstruct *target;
+
+ target = constsym((value_t) TRUE);
+ target->type = ctype;
+ loadreg(target, DREG);
+ sbranch(RA, exitlab = getlabel());
+ deflabel(falselab);
+ target = constsym((value_t) FALSE);
+ target->type = ctype;
+ *source = *target;
+ loadreg(source, DREG);
+ outnlabel(exitlab);
+}
+
+PRIVATE void logandcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ label_t andlab;
+
+ andlab = getlabel();
+ jumpcond(exp->left.nodeptr, andlab, falselab, ~0);
+ deflabel(andlab);
+ jumpcond(exp->right, truelab, falselab, nojump);
+}
+
+PUBLIC void logop(exp)
+struct nodestruct *exp;
+{
+ label_t falselab;
+ struct symstruct *target;
+ label_t truelab;
+
+ jumpcond(exp, truelab = getlabel(), falselab = getlabel(), ~0);
+ deflabel(truelab);
+ target = constsym((value_t) 0); /* anything, loadlogical makes B reg */
+ target->type = ctype;
+ loadlogical(target, falselab);
+ exp->tag = LEAF;
+ exp->left.symptr = target;
+}
+
+PRIVATE void logorcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ label_t orlab;
+
+ orlab = getlabel();
+ jumpcond(exp->left.nodeptr, truelab, orlab, 0);
+ deflabel(orlab);
+ jumpcond(exp->right, truelab, falselab, nojump);
+}
+
+PRIVATE void reduceconst(source)
+struct symstruct *source;
+{
+ if (source->storage == CONSTANT && ischarconst(source->offset.offv) &&
+ (source->type->scalar & (CHAR | SHORT | INT | DLONG)) != DLONG)
+ {
+ if (source->type->scalar & UNSIGNED)
+ source->type = uctype;
+ else
+ source->type = ctype;
+ }
+}
+
+PRIVATE void test(target, pcondtrue)
+struct symstruct *target;
+ccode_t *pcondtrue;
+{
+#ifdef I8088
+ store_t targreg;
+#endif
+
+ *pcondtrue = testcc[(int)*pcondtrue];
+ if (target->type->scalar & DLONG)
+ {
+ long1op(EQOP, target);
+ return;
+ }
+ if (target->type->scalar & RSCALAR)
+ {
+ float1op(EQOP, target);
+ return;
+ }
+#ifdef I8088
+ if (target->indcount != 0 ||
+ (target->storage == LOCAL && target->offset.offi != sp))
+ load(target, DREG);
+ if (target->storage == GLOBAL)
+ load(target, getindexreg());
+ if (target->type->scalar & CHAR)
+ load(target, DREG);
+ targreg = target->storage;
+ if (target->offset.offi != 0 && cc_signed(*pcondtrue))
+ load(target, targreg);
+
+ /* Extension was not done in exptree for the == 0 case, to allow
+ * optimization here - which we don't do for shorts. (foo--) is
+ * newfoo == -1 here and used to be missed.
+ */
+ if (i386_32 && target->type->scalar & SHORT)
+ extend(target);
+
+ if (target->offset.offi == 0)
+ {
+ outtest();
+ outregname(targreg);
+ outcomma();
+ outnregname(targreg);
+ return;
+ }
+ outcmp();
+ outimadj(-target->offset.offi, targreg);
+#endif
+#ifdef MC6809
+ if (target->indcount != 0 ||
+ target->storage == LOCAL && target->offset.offi != sp)
+ {
+ load(target, DREG);
+ return;
+ }
+ if (cmpsmallconst(0, target, pcondtrue))
+ return;
+ if (target->storage == GLOBAL)
+ load(target, getindexreg());
+ if (target->type->scalar & CHAR)
+ load(target, DREG);
+ if (target->offset.offi != 0 && cc_signed(*pcondtrue))
+ load(target, target->storage);
+ if (target->type->scalar & CHAR)
+ {
+ if (target->offset.offi == 0)
+ {
+ outtest();
+ outnregname(BREG);
+ return;
+ }
+ outcmp();
+ outimadj(-target->offset.offi, BREG);
+ }
+ else
+ {
+ cmporsub(target);
+ outimadj(-target->offset.offi, target->storage);
+ }
+#endif
+}
+
+/* test expression and jump depending on NE/EQ */
+
+PRIVATE void testcond(exp, truelab, falselab, nojump)
+struct nodestruct *exp;
+label_t truelab;
+label_t falselab;
+bool_pt nojump; /* NB if nonzero, is ~0 so complement is 0 */
+{
+ ccode_t condtrue;
+ struct symstruct *source;
+
+ makeleaf(exp);
+ source = exp->left.symptr;
+ reduceconst(source);
+ if (source->storage != CONSTANT)
+ {
+ condtrue = NE;
+ test(source, &condtrue);
+ if ((bool_t) nojump)
+ lbranch(oppcc[(int)condtrue], falselab);
+ else
+ lbranch(condtrue, truelab);
+ }
+ else if (source->offset.offi == 0)
+ {
+ if ((bool_t) nojump)
+ jump(falselab);
+ }
+ else if (!(bool_t) nojump)
+ jump(truelab);
+}
diff --git a/bcc/hardop.c b/bcc/hardop.c
new file mode 100644
index 0000000..098d22b
--- /dev/null
+++ b/bcc/hardop.c
@@ -0,0 +1,510 @@
+/* hardop.c - hardware operations for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+FORWARD void sub1 P((struct symstruct *source, struct symstruct *target));
+
+PUBLIC void add(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ scalar_t sscalar;
+
+ if (source->indcount == 0 && source->storage != CONSTANT &&
+ (target->indcount != 0 || target->storage & ALLDATREGS))
+ swapsym(target, source);
+ if ((sscalar = source->type->scalar) & DLONG)
+ {
+ longop(ADDOP, source, target);
+ return;
+ }
+ if (sscalar & RSCALAR)
+ {
+ floatop(ADDOP, source, target);
+ return;
+ }
+ if (source->storage == CONSTANT)
+ {
+ extend(target);
+ if (target->indcount != 0 || target->storage & reguse)
+ loadany(target);
+ target->offset.offi += (offset_t) source->offset.offv;
+ }
+ else if (source->indcount == 0)
+ {
+ /* target is also direct */
+ sscalar |= target->type->scalar; /* remember if unsigned/long */
+ target->type = pctype; /* fake to use indexadr() */
+ indexadr(source, target);
+ }
+ else
+ {
+ /* source is indirect and not DREG */
+ extend(target);
+ load(target, DREG);
+ outadd();
+ movereg(source, DREG);
+ if (source->type->scalar & CHAR)
+ adc0();
+ }
+ target->type = iscalartotype(target->type->scalar | sscalar);
+}
+
+PUBLIC void incdec(op, source)
+op_pt op;
+struct symstruct *source;
+{
+ offset_t bump;
+ bool_t postflag;
+ store_t regmark;
+ struct symstruct *target;
+ struct symstruct targ;
+#ifdef MC6809
+ store_pt targreg;
+#endif
+
+ *(target = &targ) = *source;
+ bump = 1;
+ if (targ.type->constructor & POINTER)
+ bump = targ.type->nexttype->typesize;
+ if (op == PREDECOP || op == POSTDECOP)
+ bump = -bump;
+ postflag = FALSE;
+ if (op == POSTDECOP || op == POSTINCOP)
+ postflag = TRUE;
+ reguse |= targ.storage;
+ if (targ.type->scalar & DLONG) /* cannot be direct */
+ {
+ if (postflag)
+ {
+ regmark = reguse;
+ if (((reguse |= OPREG) & allindregs) == allindregs)
+ {
+ saveopreg();
+ load(source, OPREG);
+ pushreg(source->storage);
+ restoreopreg();
+ }
+ else
+ {
+ loadany(source);
+ reguse = regmark | source->storage;
+ saveopreg();
+ }
+ }
+ else
+ saveopreg();
+ pointat(target);
+ switch (op)
+ {
+ case PREDECOP:
+ case POSTDECOP:
+ call("ldec");
+ break;
+ case PREINCOP:
+ case POSTINCOP:
+ call("linc");
+ break;
+ }
+ outlongendian();
+ restoreopreg();
+ if (postflag && source->storage == OPREG)
+ poplist(OPREG);
+ return;
+ }
+ if (targ.type->scalar & RSCALAR)
+ {
+ saveopreg();
+ pointat(target);
+ switch (op)
+ {
+ case PREDECOP:
+ call("Fpredec");
+ break;
+ case PREINCOP:
+ call("Fpreinc");
+ break;
+ case POSTDECOP:
+ call("Fpostdec");
+ break;
+ case POSTINCOP:
+ call("Fpostinc");
+ break;
+ }
+ outntypechar(targ.type);
+ restoreopreg();
+ if (postflag)
+ {
+ justpushed(source);
+ source->type = targ.type;
+ }
+ return;
+ }
+ loadany(source);
+#ifdef MC6809
+ if (postflag && targ.flags != REGVAR &&
+ !(source->storage & ALLDATREGS) &&
+ ((reguse |= source->storage) & allindregs) != allindregs)
+ {
+ targreg = getindexreg();
+ outlea();
+ outregname(targreg);
+ outtab();
+ outshex(bump);
+ outncregname(source->storage);
+ }
+ else
+ {
+ addconst(bump, targreg = source->storage);
+ if (postflag)
+ source->offset.offi = -bump;
+ }
+ storereg(targreg, target);
+ target->storage = targreg;
+ target->offset.offi = 0;
+#else
+ addconst(bump, source->storage);
+ if (postflag)
+ source->offset.offi = -bump;
+ storereg(source->storage, target);
+ target->storage = source->storage;
+ target->offset.offi = 0;
+#endif
+}
+
+PUBLIC void neg(target)
+struct symstruct *target;
+{
+ scalar_t scalar;
+ struct symstruct *source;
+
+ if ((scalar = target->type->scalar) & DLONG)
+ long1op(NEGOP, target);
+ else if (scalar & RSCALAR)
+ float1op(NEGOP, target);
+ else
+ {
+ if (scalar & SHORT)
+ extend(target);
+ if (!(target->storage & ALLDATREGS))
+ {
+ /* load 0, subtract is shorter than load, negate */
+ /* if no hardware integer negate; about the same if there is */
+ sub1(target, source = constsym((value_t) 0));
+ *target = *source;
+ }
+ else
+ {
+ load(target, DREG);
+ negreg(target->storage);
+ target->storage = DREG;
+ }
+ target->type = iscalartotype(scalar);
+ }
+}
+
+PUBLIC void not(target)
+struct symstruct *target;
+{
+ if (target->type->scalar & DLONG)
+ long1op(NOTOP, target);
+ else
+ {
+ extend(target);
+ load(target, DREG);
+ comDreg();
+ }
+}
+
+/* 1-byte ops like AND acting on integers (not both constant) */
+
+PUBLIC void op1(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ char *opstr;
+#ifdef OP1
+# if MAXINDIRECT > 1
+ indn_t indcount;
+# endif
+#endif
+ bool_t resultchar;
+ scalar_t resultscalar;
+ scalar_t sscalar;
+ scalar_t tscalar;
+
+ if ((sscalar = source->type->scalar) & DLONG)
+ {
+ longop(op, source, target);
+ return;
+ }
+ /* Emergency fix. The types of constants should be reduced here and in
+ * other low-level routines anyway, and not in exptree.c and table.c,
+ * and for the 80386 and maybe the 8086 they would be better not
+ * reduced.
+ */
+ if (source->storage == CONSTANT && ischarconst(source->offset.offv))
+ {
+ if (sscalar & UNSIGNED)
+ source->type = uctype;
+ else
+ source->type = ctype;
+ sscalar = source->type->scalar;
+ }
+ tscalar = target->type->scalar;
+ if (target->storage == CONSTANT && ischarconst(target->offset.offv))
+ {
+ if (sscalar & UNSIGNED)
+ target->type = uctype;
+ else
+ target->type = ctype;
+ tscalar = target->type->scalar;
+ }
+ resultscalar = sscalar | tscalar;
+ if (op != ANDOP)
+ resultchar = sscalar & tscalar & CHAR;
+ else if ((resultchar = (sscalar | tscalar) & CHAR) != 0 &&
+ source->storage == CONSTANT)
+ {
+ source->offset.offv &= CHMASKTO;
+ if (sscalar & UNSIGNED)
+ source->type = uctype;
+ else
+ source->type = ctype;
+ sscalar = source->type->scalar;
+ }
+ if (target->indcount != 0 &&
+ ((tscalar & CHAR && !(sscalar & CHAR) &&
+ op != ANDOP) || (source->indcount == 0 && source->storage != CONSTANT)))
+ {
+ swapsym(target, source);
+ sscalar = tscalar;
+ tscalar = target->type->scalar;
+ }
+ if (source->indcount == 0 && source->storage != CONSTANT)
+ {
+ loadpres(source, target);
+ push(source);
+ }
+#if MAXINDIRECT > 1
+ else if (source->indcount >= MAXINDIRECT && !(sscalar & CHAR))
+ {
+ address(source);
+ if (!(target->storage & ALLDATREGS))
+ preserve(target);
+ load(source, getindexreg());
+ indirec(source);
+ }
+#endif
+ if (!(tscalar & CHAR) &&
+ op == ANDOP && sscalar & CHAR && target->indcount == 1)
+ cast(ctype, target);
+ if (!(target->storage & ALLDATREGS) || target->indcount != 0)
+ pres2(target, source);
+ load(target, DREG);
+ opstr = opstring(op);
+ if (source->storage == CONSTANT && op == ANDOP)
+ andconst((offset_t) source->offset.offv);
+#ifdef OP1
+ else if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP)
+ outload();
+ else
+ outop2str(opstr);
+#else /* OP1 */
+ else
+ {
+ if (tscalar & CHAR && !(sscalar & CHAR) && op != ANDOP)
+ extend(target);
+ outop2str(opstr);
+ }
+#endif /* OP1 */
+ if (source->storage == CONSTANT)
+ {
+ if (op != ANDOP)
+ {
+#ifdef OP1
+ if (!(sscalar & CHAR))
+ {
+ outhiaccum();
+ outncimmadr((offset_t) ((uoffset_t) source->offset.offv
+ >> (INT16BITSTO - CHBITSTO)));
+ outop2str(opstr);
+ }
+ outregname(BREG);
+ outncimmadr((offset_t) source->offset.offv & CHMASKTO);
+#else /* OP1 */
+ if (!(sscalar & CHAR))
+ {
+ outregname(DREG);
+ bumplc();
+ }
+ else
+ outregname(BREG);
+# ifdef I8088
+ if (i386_32 && !(sscalar & CHAR))
+ bumplc2();
+# endif
+ outncimmadr((offset_t) source->offset.offv);
+
+#endif /* OP1 */
+ }
+ }
+ else if (sscalar & CHAR)
+ {
+ outregname(BREG);
+ outopsep();
+ outadr(source);
+ }
+ else
+ {
+#ifdef MC6809
+ source->type = ctype; /* fool outadr to avoid ,S++ */
+#endif
+#ifdef OP1
+ if (!(tscalar & CHAR) || op != ANDOP)
+ {
+ outhiaccum();
+# if MAXINDIRECT > 1
+ indcount = source->indcount;
+# endif
+ outopsep();
+# if BIG_ENDIAN == 0
+ ++source->offset.offi;
+# endif
+ outadr(source);
+# if BIG_ENDIAN == 0
+ --source->offset.offi;
+# endif
+# if MAXINDIRECT > 1
+ source->indcount = indcount;
+# else
+ source->indcount = 1;
+# endif
+ outop2str(opstr);
+ }
+ outregname(BREG);
+ outopsep();
+# if BIG_ENDIAN
+ ++source->offset.offi;
+# endif
+ outadr(source);
+ }
+#else /* OP1 */
+ if (!(tscalar & CHAR) || op != ANDOP)
+ outregname(DREG);
+ else
+ outregname(BREG);
+ outopsep();
+ outadr(source);
+ }
+#endif /* OP1 */
+ if (resultchar)
+ {
+ target->storage = BREG;
+ if (resultscalar & UNSIGNED)
+ target->type = uctype;
+ else
+ target->type = ctype;
+ }
+ else
+ {
+ target->storage = DREG;
+ target->type = iscalartotype(resultscalar);
+ }
+}
+
+PUBLIC void ptrsub(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ label_t exitlab;
+ uoffset_t factor;
+ label_t usignlab;
+
+ if (source->indcount == 0 && source->storage != CONSTANT)
+ {
+ loadpres(source, target);
+ push(source);
+ }
+ if (target->indcount == 0)
+ {
+ pres2(target, source);
+ load(target, DREG);
+ }
+ factor = target->type->nexttype->typesize;
+ source->type = target->type = itype;
+ sub1(source, target);
+ if (factor != 1)
+ {
+ pushlist(CCREG);
+ sbranch(HS, usignlab = getlabel()); /* HS == no carry */
+ negDreg();
+ outnlabel(usignlab);
+ target->type = uitype;
+ softop(DIVOP, constsym((value_t) factor), target);
+ target->type = itype;
+ poplist(CCREG);
+ sbranch(HS, exitlab = getlabel());
+ negDreg();
+ outnlabel(exitlab);
+ }
+}
+
+PUBLIC void sub(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ scalar_t sscalar;
+
+ if ((sscalar = source->type->scalar) & DLONG)
+ {
+ longop(SUBOP, source, target);
+ return;
+ }
+ if (sscalar & RSCALAR)
+ {
+ floatop(SUBOP, source, target);
+ return;
+ }
+ if (source->storage == CONSTANT)
+ {
+ extend(target);
+ if (target->indcount != 0 || target->storage & reguse)
+ loadany(target);
+ target->offset.offi -= (offset_t) source->offset.offv;
+ }
+ else
+ sub1(source, target);
+ target->type = iscalartotype(target->type->scalar | sscalar);
+}
+
+PRIVATE void sub1(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ if (source->storage == CONSTANT)
+ source->type = itype;
+ else if (source->indcount == 0)
+ {
+ loadpres(source, target);
+ push(source);
+ }
+ extend(target);
+ load(target, DREG);
+ outsub();
+ movereg(source, DREG);
+ if (source->type->scalar & CHAR)
+ sbc0();
+}
diff --git a/bcc/input.c b/bcc/input.c
new file mode 100644
index 0000000..4cf699a
--- /dev/null
+++ b/bcc/input.c
@@ -0,0 +1,771 @@
+/* input.c - input for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define ARBITRARY_BACKSLASH_NEWLINES_NOT
+#define INSERT_BACKSLASH_NEWLINES_NOT
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "output.h"
+#include "os.h"
+#include "sc.h"
+#include "scan.h"
+#include "table.h"
+
+#undef EXTERN
+#define EXTERN
+#include "input.h"
+
+#define INBUFSIZE 2048
+
+struct fbufstruct /* file buffer structure */
+{
+ struct fcbstruct fcb; /* status after opening an include sub-file */
+ char *fname; /* file name */
+ bool_t fname_malloced; /* nonzero if fname was malloced */
+ char pushback[3]; /* allows pushback to 2 before start of fbuf
+ * XXX 3 chars before?
+ * XXX should do everything in fbuf */
+ char fbuf[INBUFSIZE + 1]; /* buffer to read into */
+};
+
+struct inclist /* list of include file directories */
+{
+ char *incdirname;
+ struct inclist *incnext;
+};
+
+PRIVATE char filemacro[] = "__FILE__";
+PRIVATE struct inclist incabsolute; /* dummy list for absolute names */
+ /* depends on zero (NULL) init */
+PRIVATE struct inclist incfirst;
+ /* begin include searches here for "" */
+ /* at next in list for <> */
+ /* -I directories are put in list */
+ /* between first and last */
+PRIVATE struct inclist inclast =
+{
+#ifdef DEFAULT_INCLUDE_DIR
+ DEFAULT_INCLUDE_DIR,
+#endif
+ NULL,
+};
+PRIVATE fastin_t inclevel; /* nest level of include files */
+ /* depends on zero init */
+PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */
+ /* its fcb only to date in includes */
+ /* depends on zero (NULL) init */
+PRIVATE bool_t suppress_line_numbers;
+
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+FORWARD void backslash P((void));
+#endif
+FORWARD void definefile P((char *fname));
+FORWARD void inputinit P((char *fname, fd_t fd));
+FORWARD void leaveinclude P((void));
+FORWARD void usage P((void));
+
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+PRIVATE void backslash()
+{
+ static unsigned nbackslash;
+
+ if (nbackslash != 0)
+ --nbackslash;
+more:
+ ++nbackslash;
+ while (*(lineptr + 1) == '\\')
+ {
+ ++nbackslash;
+ ++lineptr;
+ }
+ if (*(lineptr + 1) != EOL)
+ {
+ if (--nbackslash != 0)
+ *--lineptr = '\\'; /* force look at current backslash again */
+ return;
+ }
+ ch = *++lineptr;
+more1:
+ if (!eof && lineptr >= input.limit)
+ skipeol();
+ if (ch == EOL)
+ {
+ --nbackslash;
+ if (eof)
+ eofin("backslash-newline");
+ else
+ {
+ skipeol();
+ if (ch == EOL && !eof && lineptr >= input.limit)
+ skipeol();
+#ifdef COEOL /* XXX - this should go through specialchar() */
+ if (ch == COEOL)
+ {
+ ch = *++lineptr;
+ if (ch == EOL && !eof && lineptr >= input.limit)
+ skipeol();
+ }
+#endif
+ }
+ if (ch == '\\')
+ goto more;
+ if (nbackslash != 0 && ch == EOL && !eof)
+ goto more1;
+ if (nbackslash != 0)
+ {
+ ch = *--lineptr = '\\';
+ if (--nbackslash != 0)
+ ch = *--lineptr = '\\';
+ }
+ return;
+ }
+ if (ch == '\\')
+ goto more;
+ if (ch == EOL && !eof)
+ goto more1;
+ ch = *--lineptr = '\\'; /* pushback */
+ if (--nbackslash != 0)
+ ch = *--lineptr = '\\';
+}
+#endif
+
+PUBLIC void closein()
+{
+#ifdef FAKE_INBUFSIZE_1
+ fclose(input.fp);
+#else
+ close(input.fd);
+#endif
+ while (inclevel != 0)
+ leaveinclude();
+}
+
+PRIVATE void definefile(fname)
+char *fname;
+{
+ char *def;
+
+ def = ourmalloc(sizeof filemacro - 1 + 2 + strlen(fname) + 1 + 1);
+ strcpy(def, filemacro);
+ strcat(def, "=\"");
+ strcat(def, fname);
+ strcat(def, "\"");
+ definestring(def);
+ ourfree(def);
+}
+
+PUBLIC void errorloc()
+{
+ register struct fbufstruct *infbuf;
+
+ if ((infbuf = inputbuf) == NULL)
+ return;
+ outstr(infbuf->fname);
+ outbyte(':');
+ if (eof)
+ outstr("eof");
+ else
+ {
+ outudec(input.linenumber);
+ outbyte('.');
+ if (maclevel == 0)
+ outudec((unsigned) (lineptr - inputbuf->fbuf) - input.lineoffset);
+ else
+ {
+ outudec((unsigned) (savedlineptr() - inputbuf->fbuf)
+ - input.lineoffset);
+ outstr(" (macro level ");
+ outudec((unsigned) maclevel);
+ outbyte(')');
+ }
+ }
+ infbuf->fcb.includer = input.includer;
+ while ((infbuf = infbuf->fcb.includer) != NULL)
+ {
+ outstr(" (from ");
+ outstr(infbuf->fname);
+ outbyte(':');
+ outudec(infbuf->fcb.linenumber);
+ outbyte(')');
+ }
+ outstr(": ");
+}
+
+/* gch1() - get next char, advance ptr (only works on current line) */
+
+PUBLIC void gch1()
+{
+ if (SYMOFCHAR(ch = *++lineptr) != SPECIALCHAR)
+ return;
+ specialchar();
+}
+
+/* process #include */
+
+PUBLIC void include()
+{
+ char *dirnameptr;
+ char *dirnamend;
+ unsigned dirnamelen;
+ fd_t fd;
+ char *fnameptr;
+ char *fullnameptr;
+ struct inclist *incptr;
+ char terminator;
+
+ while (blanksident())
+ {
+ if ((gsymptr = findlorg(gsname)) == NULL ||
+ gsymptr->flags != DEFINITION)
+ break;
+ entermac();
+ }
+ if ((terminator = ch) == '<')
+ terminator = '>';
+ else if (terminator != '"')
+ {
+ error("bad file name");
+ return;
+ }
+ gch1();
+ fnameptr = charptr;
+ while (TRUE)
+ {
+ if (ch == EOL) /* no escapes in file names */
+ break;
+ if (ch == terminator)
+ {
+ gch1();
+ break;
+ }
+ if (charptr >= chartop)
+ fnameptr = growobject(fnameptr, 1);
+#ifdef TS
+++ts_n_filename;
+++ts_s_filename;
+++ts_s_filename_tot;
+#endif
+ *charptr++ = ch;
+ gch1();
+ }
+ if (charptr >= chartop)
+ fnameptr = growobject(fnameptr, 1);
+#ifdef TS
+++ts_n_filename_term;
+++ts_s_filename_term;
+++ts_s_filename_tot;
+#endif
+ *charptr++ = 0;
+ dirnamend = NULL;
+ if (isabspath(fnameptr, &ch))
+ incptr = &incabsolute;
+ else
+ {
+ incptr = &incfirst;
+ if (terminator == '>')
+ incptr = incptr->incnext;
+ else
+ {
+ dirnameptr = inputbuf->fname;
+ if ((dirnamend = strrchr(dirnameptr, DIRCHAR)) == NULL)
+ incptr->incdirname = NULL;
+ else
+ {
+ *dirnamend = 0;
+ incptr->incdirname = dirnameptr;
+ }
+ }
+ }
+ do
+ {
+ if (incptr->incdirname == NULL)
+ {
+ fullnameptr = ourmalloc(strlen(fnameptr) + 1);
+#ifdef TS
+++ts_n_pathname;
+ts_s_pathname += strlen(fnameptr) + 1;
+ts_s_pathname_tot += strlen(fnameptr) + 1;
+#endif
+ strcpy(fullnameptr, fnameptr);
+ }
+ else
+ {
+ dirnamelen = strlen(incptr->incdirname);
+ fullnameptr = ourmalloc(dirnamelen + (int) (charptr - fnameptr)
+ + 2);
+ /* 2 extra for null and maybe DIRCHAR */
+#ifdef TS
+++ts_n_pathname;
+ts_s_pathname += dirnamelen + (charptr - fnameptr) + 2;
+ts_s_pathname_tot += dirnamelen + (charptr - fnameptr) + 2;
+#endif
+ dirnameptr = fullnameptr + dirnamelen;
+ strcpy(fullnameptr, incptr->incdirname);
+ if (*fullnameptr != 0 && *(dirnameptr - 1) != DIRCHAR)
+ strcat(fullnameptr, DIRSTRING);
+ strcat(fullnameptr, fnameptr);
+ if (dirnamend != NULL)
+ {
+ *dirnamend = DIRCHAR;
+ dirnamend = NULL;
+ }
+ }
+ fd = open(fullnameptr, 0);
+ if (fd >= 0)
+ {
+#ifdef TS
+ts_s_filename_tot -= charptr - fnameptr;
+#endif
+ charptr = fnameptr;
+ input.lineptr = lineptr;
+ inputbuf->fcb = input;
+ ++inclevel; /* XXX - will run out of memory before overflow */
+ inputinit(fullnameptr, fd);
+ inputbuf->fname_malloced = TRUE;
+ return;
+ }
+#ifdef TS
+ts_s_pathname_tot -= strlen(fullnameptr) + 1;
+#endif
+ ourfree(fullnameptr);
+ }
+ while ((incptr = incptr->incnext) != NULL);
+
+ fullnameptr = ourmalloc(strlen(fnameptr) + 40);
+ strcpy(fullnameptr, "cannot find include file ");
+ strcat(fullnameptr, fnameptr);
+ error(fullnameptr);
+ ourfree(fullnameptr);
+
+#ifdef TS
+ts_s_filename_tot -= charptr - fnameptr;
+#endif
+ charptr = fnameptr;
+}
+
+/* initialise current input file */
+
+PRIVATE void inputinit(fname, fd)
+char *fname;
+fd_t fd;
+{
+ register struct fbufstruct *newinputbuf;
+
+ /* don't allocate after saying input.includer = inputbuf (to save a reg)
+ * or an error in the alloc would cycle trying to print the include list
+ */
+ newinputbuf = (struct fbufstruct *) ourmalloc(sizeof *inputbuf);
+#ifdef TS
+++ts_n_inputbuf;
+ts_s_inputbuf += sizeof *inputbuf;
+ts_s_inputbuf_tot += sizeof *inputbuf;
+#endif
+ input.fd = fd;
+#ifdef FAKE_INBUFSIZE_1
+ input.fp = fdopen(fd, "r");
+#endif
+ input.linenumber = 0;
+ input.lineoffset = 0;
+ input.includer = inputbuf;
+ inputbuf = newinputbuf;
+ newinputbuf->fname = fname;
+ newinputbuf->fname_malloced = FALSE;
+ undefinestring(filemacro);
+ definefile(fname);
+ if (orig_cppmode && !suppress_line_numbers)
+ outcpplinenumber(1, fname, input.includer == NULL ? "" : " 1");
+ *(input.limit = newinputbuf->fbuf) = EOL;
+
+ /* dummy line so #include processing can start with skipline() */
+ ch = *(lineptr = newinputbuf->fbuf - 1) = EOL;
+}
+
+PUBLIC void linecontol()
+{
+static char linename[32];
+ char * ptr;
+ int i=0;
+
+ blanks();
+ input.linenumber = atoi(lineptr)-1;
+ while( SYMOFCHAR(ch) == INTCONST ) gch1();
+ blanks();
+ if( ch != '"' ) return;
+ for(ptr=lineptr+1; *ptr
+ && *ptr != EOL
+ && *ptr != '"'
+ && i<sizeof(linename)-1; i++, ptr++)
+ linename[i] = *ptr;
+ linename[i] = '\0';
+
+ if (inputbuf->fname_malloced)
+{
+#ifdef TS
+ts_s_pathname_tot -= strlen(inputbuf->fname) + 1;
+#endif
+ ourfree(inputbuf->fname);
+}
+ inputbuf->fname_malloced = FALSE;
+ inputbuf->fname = linename;
+
+ ptr=lineptr;
+ undefinestring(filemacro);
+ definefile(inputbuf->fname);
+ ch = *(lineptr = ptr);
+}
+
+/* switch from include file to file which included it */
+
+PRIVATE void leaveinclude()
+{
+ --inclevel;
+ if (inputbuf->fname_malloced)
+{
+#ifdef TS
+ts_s_pathname_tot -= strlen(inputbuf->fname) + 1;
+#endif
+ ourfree(inputbuf->fname);
+}
+#ifdef TS
+ts_s_inputbuf_tot -= sizeof *inputbuf;
+#endif
+ ourfree((char *) inputbuf);
+ close(input.fd);
+#ifdef FAKE_INBUFSIZE_1
+ fclose(input.fp);
+#endif
+ inputbuf = input.includer;
+ input = inputbuf->fcb;
+ undefinestring(filemacro);
+ definefile(inputbuf->fname);
+ ch = *(lineptr = input.lineptr);
+ skipline();
+ if (orig_cppmode && !suppress_line_numbers)
+ outcpplinenumber(input.linenumber, inputbuf->fname, " 2");
+}
+
+/* open input and output files and get options */
+
+PUBLIC void openio(argc, argv)
+int argc;
+char *argv[];
+{
+ register char *arg;
+ int argn;
+ fd_t fd;
+ char *fname;
+ struct inclist *incnew;
+ struct inclist *incptr;
+ bool_t flag[128];
+
+#if 0
+ lineptr = "\n"; /* empty line in case error message */
+#endif
+ fd = 0; /* standard input */
+ memset(flag, 0, sizeof flag);
+ flag['3'] = sizeof (int) >= 4;
+ fname = "stdin";
+ (incptr = &incfirst)->incnext = &inclast;
+ initout();
+ for (argn = 1; argn < argc; ++argn)
+ {
+ arg = argv[argn];
+ if (*arg != '-')
+ {
+ if (fd != 0)
+ fatalerror("more than one input file");
+ fname = arg;
+ if ((fd = open(arg, 0)) < 0)
+ fatalerror("cannot open input");
+ }
+ else
+ switch (arg[1])
+ {
+#ifdef I8088
+ case '0': /* generate 16-bit code */
+ case '3': /* generate 32-bit code */
+#endif
+ case 'c': /* caller saves */
+#ifdef DEBUG
+ case 'd': /* print debugging information in asm output */
+#endif
+ case 'E': /* acting as cpp */
+ case 'f': /* pass first argument in register */
+#ifdef DYNAMIC_LONG_ORDER
+ case 'l': /* long big-endian */
+#endif
+ case 'P': /* if acting as cpp, suppress line numbers */
+#ifdef POSINDEPENDENT
+ case 'p': /* generate almost-position-independent code */
+#endif
+ case 't': /* print source code in asm output */
+ case 'w': /* watch location counter */
+ if (arg[2] == 0)
+ flag[(int)arg[1]] = TRUE;
+ else if (arg[2] == '-' && arg[3] == 0)
+ flag[(int)arg[1]] = FALSE;
+ else
+ usage();
+ if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
+ flag['3'] = TRUE + FALSE - flag['0'];
+ break;
+ case 'D':
+ definestring(arg + 2);
+ break;
+ case 'I':
+ (incnew = (struct inclist *) ourmalloc(sizeof *incnew))
+ ->incdirname = arg + 2;
+#ifdef TS
+++ts_n_includelist;
+ts_s_includelist += sizeof *incnew;
+#endif
+ incnew->incnext = incptr->incnext;
+ incptr = incptr->incnext = incnew;
+ break;
+ case 'U':
+ undefinestring(arg + 2);
+ break;
+ case 'o':
+ if (arg[2] != 0 || ++argn >= argc)
+ usage();
+ openout(argv[argn]);
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+#ifdef I8088
+ if (flag['3'])
+ {
+ i386_32 = TRUE;
+ definestring("__AS386_32__");
+ }
+ else
+ definestring("__AS386_16__");
+#endif
+#ifdef MC6809
+ definestring("__AS09__");
+#endif
+ if (flag['c'])
+ {
+ callersaves = TRUE;
+ definestring("__CALLER_SAVES__");
+ }
+#ifdef DEBUG
+ debugon = flag['d'];
+#endif
+ orig_cppmode = cppmode = flag['E'];
+ if (flag['f'])
+ {
+ arg1inreg = TRUE;
+#ifdef I8088
+ definestring("__FIRST_ARG_IN_AX__");
+#endif
+#ifdef MC6808
+ definestring("__FIRST_ARG_IN_X__");
+#endif
+ }
+ arg1op = arg1inreg ? ROOTLISTOP : LISTOP;
+#ifdef DYNAMIC_LONG_ORDER
+ if (flag['l'])
+ {
+ long_big_endian = TRUE;
+ definestring("__LONG_BIG_ENDIAN__");
+ }
+#endif
+ suppress_line_numbers = flag['P'];
+#ifdef POSINDEPENDENT
+ if (flag['p'])
+ {
+ posindependent = TRUE;
+ definestring("__POS_INDEPENDENT__");
+ }
+#endif
+ ctext = flag['t'];
+ watchlc = flag['w'];
+ setoutbufs();
+ inputinit(fname, fd);
+}
+
+/* advance over EOL sentinel to new line */
+
+PUBLIC void skipeol()
+{
+#ifdef FAKE_INBUFSIZE_1
+ static int ich;
+#endif
+#ifdef INSERT_BACKSLASH_NEWLINES
+ static int bs_state;
+ static bool_t skip_printing_nl;
+#endif
+ int nread;
+
+ if (eof)
+ return;
+ if (lineptr < input.limit)
+ {
+ ++input.linenumber;
+ ch = *++lineptr;
+ if (ctext && !asmmode)
+ {
+ comment();
+ outudec(input.linenumber);
+ outbyte(' ');
+ outline(lineptr);
+ }
+ if (orig_cppmode && !asmmode)
+#ifdef INSERT_BACKSLASH_NEWLINES
+ if (!skip_printing_nl)
+#endif
+
+ outbyte('\n');
+#ifdef INSERT_BACKSLASH_NEWLINES
+ if (bs_state == 1 && *(lineptr - 1) == EOL)
+#endif
+ input.lineoffset = (int) (lineptr - inputbuf->fbuf);
+ return;
+ }
+ input.lineoffset -= (int) (lineptr - inputbuf->fbuf);
+#ifdef FAKE_INBUFSIZE_1
+ lineptr = inputbuf->fbuf;
+#ifdef INSERT_BACKSLASH_NEWLINES
+ switch (bs_state)
+ {
+case0:
+ case 0:
+ bs_state = nread = (ich = getc(input.fp)) == EOF ? 0 : 1;
+ skip_printing_nl = FALSE;
+ break;
+ case 1:
+ if (ich == '\\')
+ goto case0; /* avoid chance of splitting \EOL */
+ ich = '\\';
+ nread = 1;
+ bs_state = 2;
+ ++input.lineoffset;
+ break;
+ case 2:
+ ich = EOL;
+ nread = 1;
+ bs_state = 0;
+ skip_printing_nl = TRUE;
+ ++input.lineoffset;
+ --input.linenumber;
+ break;
+ }
+#else
+ nread = (ich = getc(input.fp)) == EOF ? 0 : 1;
+#endif
+ *lineptr = ich;
+#else
+ nread = read(input.fd, lineptr = inputbuf->fbuf, INBUFSIZE);
+#endif
+ if (nread < 0)
+ fatalerror("input error");
+ *(input.limit = lineptr + nread) = EOL;
+ ch = *lineptr;
+ if (nread == 0)
+ {
+ if (inclevel == 0)
+ {
+ eof = TRUE;
+ checknotinif();
+ }
+ else
+ {
+ leaveinclude();
+ skipeol();
+ }
+ return;
+ }
+ if (ctext && !asmmode)
+ {
+ comment();
+ outudec(input.linenumber);
+ outbyte(' ');
+ outline(lineptr);
+ }
+}
+
+PUBLIC void specialchar()
+{
+ if (maclevel != 0)
+ {
+ if (ch == EOL) /* it might also be backslash or COEOL */
+ leavemac();
+ if (ch != EOL)
+ return;
+ }
+more:
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+ if (ch == '\\')
+ backslash();
+#endif
+ if (!eof && lineptr >= input.limit)
+ {
+ skipeol();
+#ifdef ARBITRARY_BACKSLASH_NEWLINES
+ if (ch == '\\')
+ backslash();
+#endif
+ }
+#ifndef ARBITRARY_BACKSLASH_NEWLINES
+ if (ch == '\\')
+ {
+ if (*(lineptr + 1) == EOL)
+ {
+ if (lineptr + 1 >= input.limit)
+ {
+ ++lineptr;
+ skipeol();
+ ch = *--lineptr = '\\'; /* pushback */
+ }
+ if (*(lineptr + 1) == EOL)
+ {
+ if (eof)
+ eofin("backslash-newline");
+ else
+ {
+ ++lineptr;
+ skipeol();
+ if (SYMOFCHAR(ch) == SPECIALCHAR)
+ {
+#ifdef COEOL
+ if (ch != COEOL
+ || SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR)
+#endif
+ goto more;
+ }
+ }
+ }
+ }
+#endif
+ }
+#ifdef COEOL
+ if (ch == EOL && !eof)
+ {
+ if (*(lineptr + 1) == EOL && lineptr + 1 >= input.limit)
+ {
+ ++lineptr;
+ skipeol(); /* refill buffer */
+ ch = *--lineptr = EOL; /* pushback */
+ }
+ if (*(lineptr + 1) == COEOL)
+ *++lineptr = EOL; /* discard COEOL */
+ }
+#endif
+}
+
+PRIVATE void usage()
+{
+ fatalerror(
+#ifdef MC6809
+"usage: cc1 [-cdfptw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]");
+#else
+"usage: cc1 [-03cdfltw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]");
+#endif
+}
diff --git a/bcc/input.h b/bcc/input.h
new file mode 100644
index 0000000..0563059
--- /dev/null
+++ b/bcc/input.h
@@ -0,0 +1,37 @@
+/* input.h - input for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define FAKE_INBUFSIZE_1_NOT
+
+#ifdef FAKE_INBUFSIZE_1
+#include <stdio.h>
+FILE *fdopen();
+#endif
+
+struct fcbstruct /* file control block structure */
+{
+ fd_t fd; /* file descriptor */
+#ifdef FAKE_INBUFSIZE_1
+ FILE *fp;
+#endif
+ unsigned linenumber; /* current line in file */
+ int lineoffset; /* offset to start of current line in buf */
+ char *lineptr; /* current spot in line */
+ char *limit; /* end of used part of input buffer */
+ struct fbufstruct *includer;
+ /* buffer of file which included current one */
+};
+
+EXTERN bool_t asmmode; /* nonzero when processing assembler code */
+ /* depends on zero init */
+EXTERN char ch; /* current char */
+EXTERN bool_t cppmode; /* nonzero if acting as cpp not as compiler */
+EXTERN bool_t eof; /* nonzero after end of main file reached */
+ /* depends on zero init */
+EXTERN struct fcbstruct input; /* current input file control block */
+ /* input.lineptr is not kept up to date */
+EXTERN char *lineptr; /* ptr to current char */
+EXTERN maclev_t maclevel; /* nest level of #defined identifiers */
+ /* depends on zero init */
+EXTERN bool_t orig_cppmode; /* same as cppmode ex. not varied while in # */
diff --git a/bcc/label.c b/bcc/label.c
new file mode 100644
index 0000000..5b07af9
--- /dev/null
+++ b/bcc/label.c
@@ -0,0 +1,429 @@
+/* label.c - label handling routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "label.h"
+#include "output.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#ifdef I8088
+# define outlbranch() outop3str( "b")
+# define outsbranch() outop2str( "j")
+#endif
+#ifdef MC6809
+# define outlbranch() outop3str( "LB")
+# define outsbranch() outop2str( "B")
+#endif
+
+#define MAXVISLAB 32
+
+struct labdatstruct
+{
+ label_t labnum; /* 0 if not active */
+ offset_t lablc; /* location counter for branch or label */
+ char *labpatch; /* buffer ptr for branch, NULL for label */
+ ccode_t labcond; /* condition code for branch */
+};
+
+#ifdef I8088
+PRIVATE char lcondnames[][2] = /* names of long condition codes */
+{
+ { 'e', 'q', }, { 'n', 'e', }, { 'r', ' ', }, { 'r', 'n', },
+ { 'l', 't', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', 't', },
+ { 'l', 'o', }, { 'h', 'i', }, { 'l', 'o', }, { 'h', 'i' },
+};
+PRIVATE char scondnames[][2] = /* names of short condition codes */
+{
+ { 'e', ' ', }, { 'n', 'e', }, { 'm', 'p', }, { 'n', 0, },
+ { 'l', ' ', }, { 'g', 'e', }, { 'l', 'e', }, { 'g', ' ', },
+ { 'b', ' ', }, { 'a', 'e', }, { 'b', 'e', }, { 'a', ' ', },
+};
+#endif
+
+#ifdef MC6809
+PRIVATE char condnames[][2] = /* names of condition codes */
+{
+ { 'E', 'Q', }, { 'N', 'E', }, { 'R', 'A', }, { 'R', 'N', },
+ { 'L', 'T', }, { 'G', 'E', }, { 'L', 'E', }, { 'G', 'T', },
+ { 'L', 'O', }, { 'H', 'S', }, { 'L', 'S', }, { 'H', 'I', },
+};
+#endif
+
+PRIVATE label_t lasthighlab = 0xFFFF+1; /* temp & temp init so labels fixed */
+ /* lint */
+PRIVATE label_t lastlab; /* bss init to 0 */
+PRIVATE offset_t lc; /* bss init to 0 */
+
+PRIVATE struct labdatstruct vislab[MAXVISLAB]; /* bss, all labnum's init 0 */
+PRIVATE smalin_t nextvislab; /* bss init to NULL */
+PRIVATE struct symstruct *namedfirst; /* bss init to NULL */
+PRIVATE struct symstruct *namedlast; /* bss init to NULL */
+
+FORWARD void addlabel P((ccode_pt cond, label_t label, char *patch));
+FORWARD struct labdatstruct *findlabel P((label_t label));
+
+/* add label to circular list */
+
+PRIVATE void addlabel(cond, label, patch)
+ccode_pt cond;
+label_t label;
+char *patch;
+{
+ register struct labdatstruct *labptr;
+
+ labptr = &vislab[(int)nextvislab];
+ labptr->labcond = cond;
+ labptr->labnum = label;
+ labptr->lablc = lc;
+ labptr->labpatch = patch;
+ if (++nextvislab == MAXVISLAB)
+ nextvislab = 0;
+}
+
+/* bump location counter */
+
+PUBLIC void bumplc()
+{
+ ++lc;
+}
+
+/* bump location counter by 2 */
+
+PUBLIC void bumplc2()
+{
+ lc += 2;
+}
+
+/* bump location counter by 3 */
+
+PUBLIC void bumplc3()
+{
+ lc += 3;
+}
+
+/* clear out labels in function */
+
+PUBLIC void clearfunclabels()
+{
+ register struct symstruct *symptr;
+ register struct symstruct *tmp;
+
+ for (symptr = namedfirst; symptr != NULL;)
+ {
+ if (symptr->indcount == 2)
+ error("undefined label");
+ symptr->indcount = 0;
+ tmp = symptr;
+ symptr = (struct symstruct *) symptr->type;
+ tmp->type = NULL;
+ }
+ namedlast = namedfirst = NULL;
+}
+
+/* clear out labels no longer in buffer */
+
+PUBLIC void clearlabels(patchbuf, patchtop)
+char *patchbuf;
+char *patchtop;
+{
+ register struct labdatstruct *labptr;
+ struct labdatstruct *labtop;
+ register char *labpatch;
+
+ for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
+ labptr < labtop; ++labptr)
+ if ((labpatch = labptr->labpatch) >= patchbuf && labpatch < patchtop)
+ labptr->labnum = 0;
+}
+
+/* clear out labels in switch statement */
+
+PUBLIC void clearswitchlabels()
+{
+ register struct symstruct *symptr;
+
+ for (symptr = namedfirst; symptr != NULL;
+ symptr = (struct symstruct *) symptr->type)
+ if (symptr->indcount == 3)
+ {
+ equlab(symptr->offset.offlabel, lowsp);
+ symptr->indcount = 4;
+ }
+}
+
+/* return location counter */
+
+PUBLIC uoffset_t getlc()
+{
+ return (uoffset_t) lc;
+}
+
+/* define location of label and backpatch references to it */
+
+PUBLIC void deflabel(label)
+label_t label;
+{
+ char *cnameptr;
+ struct labdatstruct *labmin;
+ struct labdatstruct *labmax;
+ struct labdatstruct *labmid;
+ struct labdatstruct *labptrsave;
+ offset_t nlonger;
+
+ outnlabel(label);
+ {
+ register struct labdatstruct *labptr;
+ register char *labpatch;
+
+ labmin = &vislab[0];
+ labmax = &vislab[MAXVISLAB];
+ labptr = labmid = &vislab[(int)nextvislab];
+ if (!watchlc)
+ do
+ {
+ if (labptr == labmin)
+ labptr = &vislab[MAXVISLAB];
+ --labptr;
+ if (labptr->labnum == label)
+ {
+ if ((labpatch = labptr->labpatch) != NULL &&
+ isshortbranch(lc - labptr->lablc))
+ {
+#ifdef I8088 /* patch "bcc(c) to j(c)(c)( ) */
+ *labpatch = 'j';
+ *(labpatch + 1) =
+ *(cnameptr = scondnames[(int)labptr->labcond]);
+#endif
+#ifdef MC6809
+# ifdef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
+ *labpatch = 'B';
+ *(labpatch + 4) = '\t'; /* redundant unless JMP */
+ *(labpatch + 1) =
+ *(cnameptr = condnames[labptr->labcond]);
+# else
+ if (labptr->labcond == RA)
+ strncpy(labpatch, "BRA\t\t", 5);
+ else
+ *labpatch = '\t';
+ goto over;
+# endif
+#endif
+ *(labpatch + 2) = *(cnameptr + 1);
+ *(labpatch + 3) = ' ';
+#ifdef MC6809
+# ifndef NEW_MC6809 /* patch JMP\t> or LBCC\t to BCC \t */
+ over: ; /* temp regression test kludge */
+# endif
+#endif
+ nlonger = jcclonger;
+ if (labptr->labcond == RA)
+ nlonger = jmplonger;
+ lc -= nlonger;
+ labptrsave = labptr;
+ while (++labptr != labmid)
+ if (labptr == labmax)
+ labptr = &vislab[-1];
+ else
+ labptr->lablc -= nlonger;
+ labptr = labptrsave;
+ }
+ }
+ }
+ while (labptr != labmid);
+ }
+ addlabel((ccode_pt) 0, label, (char *) NULL);
+}
+
+PRIVATE struct labdatstruct *findlabel(label)
+label_t label;
+{
+ register struct labdatstruct *labptr;
+ struct labdatstruct *labtop;
+
+ for (labptr = &vislab[0], labtop = &vislab[MAXVISLAB];
+ labptr < labtop; ++labptr)
+ if (labptr->labnum == label)
+ {
+ if (labptr->labpatch != 0)
+ break;
+ return labptr;
+ }
+ return (struct labdatstruct *) NULL;
+}
+
+/* reserve a new label, from top down to temp avoid renumbering low labels */
+
+PUBLIC label_t gethighlabel()
+{
+ return --lasthighlab;
+}
+
+/* reserve a new label */
+
+PUBLIC label_t getlabel()
+{
+ return ++lastlab;
+}
+
+/* jump to label */
+
+PUBLIC void jump(label)
+label_t label;
+{
+ lbranch(RA, label);
+}
+
+/* long branch on condition to label */
+
+PUBLIC void lbranch(cond, label)
+ccode_pt cond;
+label_t label;
+{
+#ifdef I8088
+ char *cnameptr;
+
+#endif
+ struct labdatstruct *labptr;
+ char *oldoutptr;
+
+ if ((ccode_t) cond == RN)
+ return;
+ if ((labptr = findlabel(label)) != NULL &&
+ isshortbranch(lc - labptr->lablc + 2))
+ {
+ sbranch(cond, label);
+ return;
+ }
+ oldoutptr = outbufptr;
+ if (cond == RA)
+ outjumpstring();
+ else
+ {
+ outlbranch();
+#ifdef I8088
+ outbyte(*(cnameptr = lcondnames[(int) cond]));
+ outbyte(*(cnameptr + 1));
+ if ((ccode_t) cond == LS || (ccode_t) cond == HS)
+ outbyte('s'); /* "blos" or "bhis" */
+ else
+ outbyte(' ');
+ outtab();
+ bumplc2();
+ if (i386_32)
+ bumplc();
+#endif
+#ifdef MC6809
+ outcond(cond);
+ bumplc();
+#endif
+ }
+ outlabel(label);
+ outnl();
+ if (labptr == NULL && oldoutptr < outbufptr) /* no wrap-around */
+ addlabel(cond, label, oldoutptr);
+}
+
+/* look up the name gsname in label space, install it if new */
+
+PUBLIC struct symstruct *namedlabel()
+{
+ struct symstruct *symptr;
+
+ gs2name[1] = 0xFF;
+ if ((symptr = findlorg(gs2name + 1)) == NULL)
+ {
+ symptr = addglb(gs2name + 1, vtype);
+ symptr->flags = LABELLED;
+ }
+ if (symptr->indcount < 2)
+ {
+ symptr->indcount = 2;
+ symptr->offset.offlabel = gethighlabel();
+ if (namedfirst == NULL)
+ namedfirst = symptr;
+ else
+ namedlast->type = (struct typestruct *) symptr;
+ namedlast = symptr;
+ symptr->type = NULL;
+ }
+ return symptr;
+}
+
+#ifdef MC6809
+
+/* print condition code name */
+
+PUBLIC void outcond(cond)
+ccode_pt cond;
+{
+ char *cnameptr;
+
+ outbyte(*(cnameptr = condnames[(ccode_t) cond]));
+ outbyte(*(cnameptr + 1));
+ outtab();
+}
+
+#endif
+
+/* print label */
+
+PUBLIC void outlabel(label)
+label_t label;
+{
+ outbyte(LABELSTARTCHAR);
+ outhexdigs((uoffset_t) label);
+}
+
+/* print label and newline */
+
+PUBLIC void outnlabel(label)
+label_t label;
+{
+ outlabel(label);
+#ifdef LABELENDCHAR
+ outnbyte(LABELENDCHAR);
+#else
+ outnl();
+#endif
+}
+
+/* short branch on condition to label */
+
+PUBLIC void sbranch(cond, label)
+ccode_pt cond;
+label_t label;
+{
+#ifdef I8088
+ char *cnameptr;
+
+ if ((ccode_t) cond != RN)
+ {
+ outsbranch();
+ outbyte(*(cnameptr = scondnames[(int) cond]));
+ outbyte(*(cnameptr + 1));
+ outtab();
+ outlabel(label);
+ outnl();
+ }
+#endif
+#ifdef MC6809
+ outsbranch();
+ outcond(cond);
+ outlabel(label);
+ outnl();
+#endif
+}
+
+/* reverse bump location counter */
+
+PUBLIC void unbumplc()
+{
+ --lc;
+}
diff --git a/bcc/label.h b/bcc/label.h
new file mode 100644
index 0000000..89c83d7
--- /dev/null
+++ b/bcc/label.h
@@ -0,0 +1,24 @@
+/* label.h - assembler-specific label characters for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* defaults */
+
+#define CCNAMEPREFIX '_'
+# define LABELENDCHAR ':' /* last char of ALL labels */
+#define LABELSTARTCHAR '.' /* first char of names of generated labels */
+#define LOCALSTARTCHAR '.' /* first char of local names */
+#define PUBLICENDCHAR ':'
+
+/* adjustments for other assemblers */
+
+#ifdef AS09
+# undef LABELENDCHAR
+#endif
+
+#ifdef XENIX_AS
+# undef LABELSTARTCHAR
+# define LABELSTARTCHAR 'L'
+# undef LOCALSTARTCHAR
+# define LOCALSTARTCHAR 'L'
+#endif
diff --git a/bcc/loadexp.c b/bcc/loadexp.c
new file mode 100644
index 0000000..632c2ad
--- /dev/null
+++ b/bcc/loadexp.c
@@ -0,0 +1,180 @@
+/* loadexp.c - load expressions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+PUBLIC value_t constexpression()
+{
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+ struct symstruct *symptr;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ exp = assignment_exp();
+ etptr = etmark;
+ exprptr = exprmark;
+ if (exp->tag == LEAF && (symptr = exp->left.symptr)->storage == CONSTANT
+ && symptr->type->scalar & ISCALAR)
+ return symptr->offset.offv;
+ error("constant expression required");
+ return 1;
+}
+
+PUBLIC void initexpression(type)
+struct typestruct *type;
+{
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+ struct nodestruct *lhs;
+ struct symstruct *symptr;
+ uoffset_t value;
+
+ if (gvarsymptr->storage != GLOBAL)
+ reslocals();
+ exprmark = exprptr;
+ etmark = etptr;
+ exp = assignment_exp();
+ if (gvarsymptr->storage != GLOBAL)
+ {
+ lhs = leafnode(exprsym(gvarsymptr));
+ if (!(lhs->nodetype->constructor & (ARRAY | FUNCTION | VOID)))
+ lhs->flags = LVALUE;
+ makeleaf(node(ASSIGNOP, lhs, exp));
+ }
+ else if (exp->tag != LEAF ||
+ ((symptr = exp->left.symptr)->storage != CONSTANT &&
+ (symptr->storage != GLOBAL || symptr->indcount != 0 ||
+ type->scalar & DLONG)) ||
+ (type->constructor | (symptr->type->constructor & ~FUNCTION)) &
+ ~(ARRAY | POINTER))
+ error("initializer too complicated");
+ else
+ {
+ if ((symptr->type->scalar | type->scalar) & RSCALAR)
+ {
+ /* Can only afford castnode if result known constant. */
+ exp = castnode(type, exp);
+ symptr = exp->left.symptr;
+ }
+ if (type->scalar & RSCALAR)
+ {
+ if (type->scalar & FLOAT)
+ {
+ float val;
+
+ val = *symptr->offset.offd;
+ deflong(((uoffset_t *) &val)[0]);
+ }
+ else
+ {
+ deflong(((uoffset_t *) symptr->offset.offd)[0]);
+ deflong(((uoffset_t *) symptr->offset.offd)[1]);
+ }
+ etptr = etmark; /* XXX - stuff from end of function */
+ exprptr = exprmark;
+ return;
+ }
+ if (type->typesize == 1)
+ defbyte();
+ else if (type->typesize == 2)
+ defword();
+#ifdef I8088
+ else if (!(type->scalar & DLONG))
+ defdword();
+#endif
+ switch (symptr->storage)
+ {
+ case CONSTANT:
+ value = (uoffset_t) symptr->offset.offv;
+ if (type->scalar & DLONG)
+ {
+ deflong(value);
+ break;
+ }
+ /* XXX - put sizes in type struct to avoid tests */
+ if (type->scalar & CHAR)
+ value &= CHMASKTO;
+ else if (type->scalar & SHORT)
+ value &= shortmaskto;
+ else if (type->scalar & INT)
+ value &= intmaskto;
+ /* XXX - no longmaskto */
+ outnhex(value);
+ break;
+ case GLOBAL:
+ if (symptr->flags & LABELLED)
+ {
+ outlabel(symptr->name.label);
+ outplus();
+ outnhex((uoffset_t) symptr->offset.offi);
+ break;
+ }
+ if (*symptr->name.namep == 0) /* constant address */
+ {
+ outnhex((uoffset_t) symptr->offset.offi);
+ break;
+ }
+ outccname(symptr->name.namep);
+ if (symptr->offset.offi != 0)
+ {
+ if (symptr->offset.offi > 0)
+ outplus();
+ outshex(symptr->offset.offi);
+ }
+ outnl();
+ break;
+ }
+ }
+ etptr = etmark;
+ exprptr = exprmark;
+}
+
+PUBLIC struct typestruct *loadexpression(targreg, targtype)
+store_pt targreg;
+struct typestruct *targtype;
+{
+ struct nodestruct *etmark;
+ struct nodestruct *exp;
+ struct symstruct *exprmark;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ exp = expression();
+ if (targtype != NULL)
+ exp = castnode(targtype, exp);
+ makeleaf(exp);
+ if (targtype == NULL) /* this is for a switch */
+ {
+ targtype = exp->left.symptr->type;
+ if (!(targtype->scalar & (CHAR | INT))
+ && (targtype->scalar & (LONG | DLONG)) != LONG)
+ {
+ if (targtype->scalar & SHORT)
+ targtype = promote(targtype);
+ else
+ {
+ error("non-integral selector in switch");
+ targtype = itype;
+ }
+ makeleaf(exp = castnode(targtype, exp));
+ }
+ }
+ load(exp->left.symptr, targreg); /* resets stack if value was there */
+ etptr = etmark;
+ exprptr = exprmark;
+ return exp->left.symptr->type;
+}
diff --git a/bcc/longop.c b/bcc/longop.c
new file mode 100644
index 0000000..f678e11
--- /dev/null
+++ b/bcc/longop.c
@@ -0,0 +1,169 @@
+/* longop.c - software operations on longs for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "byteord.h"
+#include "gencode.h"
+#include "reg.h"
+#include "scan.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ longop(operation code, source leaf, target leaf)
+ handles all binary operations on longs
+ source and target must already have been converted to long,
+ (except source is int for shifts) and not more than singly indirect
+ hence they must be direct (in an index reg paired with DREG),
+ or singly indirect (local, global, or from an index reg)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void longop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt reglist;
+ store_t regmark;
+ bool_t shiftflag;
+ scalar_t scalar;
+ offset_t spmark;
+
+ pushlist(reglist = (regmark = reguse) & (OPREG | OPWORKREG));
+ reguse &= ~reglist;
+ spmark = sp;
+ shiftflag = FALSE;
+ scalar = target->type->scalar;
+ if ((op_t) op == SLOP || (op_t) op == SROP)
+ shiftflag = TRUE;
+ else
+ scalar |= source->type->scalar;
+ if ((source->indcount == 0 && !shiftflag) ||
+ source->storage & (DREG | OPREG | OPWORKREG))
+ {
+ pres2(source, target);
+ push(source);
+ }
+ if (!shiftflag)
+ address(source);
+ load(target, OPREG);
+ if (source->storage == CONSTANT && shiftflag)
+ {
+ if (scalar & UNSIGNED)
+ target->type = ultype;
+ if ((op_t) op == SLOP)
+ source->offset.offv = lslconst(source->offset.offv,
+ target->storage);
+ else
+ source->offset.offv = lsrconst(source->offset.offv,
+ target->storage, scalar & UNSIGNED);
+ if (source->offset.offv == 0)
+ goto shiftdone;
+ }
+ load(source, OPWORKREG);
+ switch ((op_t) op)
+ {
+ case ADDOP:
+ call("ladd");
+ break;
+ case ANDOP:
+ call("land");
+ break;
+ case DIVOP:
+ call("ldiv");
+ break;
+ case EOROP:
+ call("leor");
+ break;
+ case EQOP:
+ call("lcmp");
+ break;
+ case MODOP:
+ call("lmod");
+ break;
+ case MULOP:
+ call("lmul");
+ break;
+ case OROP:
+ call("lor");
+ break;
+ case SLOP:
+ call("lsl");
+ break;
+ case SROP:
+ call("lsr");
+ break;
+ case SUBOP:
+ call("lsub");
+ break;
+ }
+ if (scalar & UNSIGNED)
+ {
+ outbyte('u');
+ target->type = ultype;
+ }
+ outlongendian();
+
+shiftdone:
+ if ((reguse = regmark) & OPREG && op != EQOP)
+ load(target, getindexreg());
+ if (reglist)
+ {
+#ifdef I8088
+ if (op == EQOP)
+ changesp(spmark, FALSE);
+ else
+#endif
+ modstk(spmark);
+ poplist(reglist);
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ long1op(operation code, target leaf)
+ handles all unary operations on longs except inc/dec
+ target must be not more than singly indirect
+ hence it must be direct (in an index reg paired with DREG),
+ or singly indirect (local, global, or from an index reg)
+-----------------------------------------------------------------------------*/
+
+PUBLIC void long1op(op, target)
+op_pt op;
+struct symstruct *target;
+{
+ pushlist(reguse & OPREG);
+ load(target, OPREG);
+ if (op == NOTOP)
+ call("lcom");
+ else if (op == NEGOP)
+ call("lneg");
+ else
+ call("ltst");
+ outlongendian();
+ if (reguse & OPREG)
+ {
+ if (op != EQOP)
+ load(target, getindexreg());
+ poplist(reguse & OPREG);
+ }
+}
+
+PUBLIC void outlongendian()
+{
+#ifdef MC6809
+ outbyte('_');
+#endif
+#if DYNAMIC_LONG_ORDER
+ if (long_big_endian)
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN
+ outnbyte('b');
+#endif
+#if DYNAMIC_LONG_ORDER
+ else
+#endif
+#if DYNAMIC_LONG_ORDER || LONG_BIG_ENDIAN == 0
+ outnbyte('l');
+#endif
+}
diff --git a/bcc/misc/sformat b/bcc/misc/sformat
new file mode 100644
index 0000000..3dcb0c4
--- /dev/null
+++ b/bcc/misc/sformat
@@ -0,0 +1,56 @@
+int x;
+.comm _x,2
+
+int x = 1;
+.global _x
+.data
+_x:
+1
+
+static int x;
+.bss
+_x:
+.=.+2
+
+static int x = 1;
+.bss | implicit
+.data
+_x:
+1
+
+char x[10];
+.comm _x,12
+
+char x[10] = "1";
+.globl _x
+.data
+_x:
+.byte 61,0
+.=.+10
+
+static char x[10];
+.bss;
+_cc:
+.=.+12
+
+static char x[10] = "1";
+.data
+_x:
+.byte 61,0
+.=.+10
+
+test()
+.globl _test
+.text
+_test:
+
+{
+static int x;
+.bss
+L3:
+.=.+2
+
+static int x = 1;
+.bss
+.data
+L5:1
diff --git a/bcc/misc/test/8queens.pas b/bcc/misc/test/8queens.pas
new file mode 100644
index 0000000..f4f1b47
--- /dev/null
+++ b/bcc/misc/test/8queens.pas
@@ -0,0 +1,33 @@
+program eightqueens;
+
+var i: integer;
+ a: array[ 1..8 ] of boolean;
+ b: array[ 2..16] of boolean;
+ c: array[-7..7 ] of boolean;
+ x: array[ 1..8 ] of integer;
+
+procedure print;
+var k: integer;
+begin
+ for k:= 1 to 8 do write(x[k]:4);
+ writeln;
+end;
+
+procedure try(i: integer);
+var j: integer;
+begin
+ for j:= 1 to 8 do if a[j] and b[i+j] and c[i-j] then
+ begin
+ x[i]:= j;
+ a[j]:= false; b[i+j]:= false; c[i-j]:= false;
+ if i < 8 then try(i+1) else print;
+ a[j]:= true; b[i+j]:= true; c[i-j]:= true;
+ end;
+end;
+
+begin
+ for i:= 1 to 8 do a[i]:= true;
+ for i:= 2 to 16 do b[i]:= true;
+ for i:= -7 to 7 do c[i]:= true;
+ try(1);
+end.
diff --git a/bcc/misc/test/8queens.t b/bcc/misc/test/8queens.t
new file mode 100644
index 0000000..8d20a4d
--- /dev/null
+++ b/bcc/misc/test/8queens.t
@@ -0,0 +1,74 @@
+/* 8queens - straightforward translation of pascal version */
+
+#define TRUE 1
+#define FALSE 0
+
+int i;
+char a[8],b[15],c[15],x[8];
+
+main()
+{
+ for (i=0;i<8;i++)
+ a[i]=TRUE;
+ for (i=0;i<15;i++)
+ b[i]=TRUE;
+ for (i=0;i<15;i++)
+ c[i]=TRUE;
+ try(0);
+}
+
+print()
+{
+ int k;
+
+ for (k=0;k<8;k++)
+ write(x[k]);
+ writeln();
+}
+
+write(i)
+int i;
+{
+ {
+#asm
+ LDA #$20
+ JSR $E820
+ LDD .i,S
+ JSR $C682
+#endasm
+ }
+}
+
+writeln()
+{
+ {
+#asm
+ LDA #13
+ JSR $E820
+ LDA #10
+ JSR $E820
+#endasm
+ }
+}
+
+try(i)
+int i;
+{
+ int j;
+
+ for(j=0;j<8;j++)
+ if (a[j] && b[i+j] && c[7+i-j])
+ {
+ x[i]=j;
+ a[j]=FALSE;
+ b[i+j]=FALSE;
+ c[7+i-j]=FALSE;
+ if (i<7)
+ try(i+1);
+ else
+ print();
+ a[j]=TRUE;
+ b[i+j]=TRUE;
+ c[7+i-j]=TRUE;
+ }
+}
diff --git a/bcc/misc/test/atol.t b/bcc/misc/test/atol.t
new file mode 100644
index 0000000..79c78b7
--- /dev/null
+++ b/bcc/misc/test/atol.t
@@ -0,0 +1,29 @@
+/* atol.c - long atol( char *s ) */
+
+/* atol converts s to a long */
+/* leading spaces and tabs are ignored, an optional sign is recognised, */
+/* and the digits (0 to 9) following determine the long */
+
+long atol( s )
+register char *s;
+{
+ char signflag;
+ long number;
+
+ while ( *s == ' ' || *s == '\t')
+ s++;
+ signflag = 0;
+ if ( *s == '+' )
+ s++;
+ else if ( *s == '-' )
+ {
+ signflag = 1;
+ s++;
+ }
+ number = 0;
+ while ( *s >= '0' && *s <= '9' )
+ number = 10 * number + *s++ - '0';
+ if ( signflag )
+ return -number;
+ return number;
+}
diff --git a/bcc/misc/test/bigsievec.t b/bcc/misc/test/bigsievec.t
new file mode 100644
index 0000000..f3f76b2
--- /dev/null
+++ b/bcc/misc/test/bigsievec.t
@@ -0,0 +1,29 @@
+#define TRUE 1
+#define FALSE 0
+#define NITER 10
+#define SIZE 100000
+
+char flags[SIZE+1];
+
+main()
+{
+ int i,prime,k,count,iter;
+
+ for (iter=0;iter<NITER;iter++)
+ {
+ count=0;
+ for (i=0;i<=SIZE;i++)
+ flags[i]=TRUE;
+ for (i=0;i<=SIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ for (k=i+prime;k<=SIZE;k=k+prime)
+ flags[k]=FALSE;
+ count++;
+ }
+ }
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc/misc/test/bt.t b/bcc/misc/test/bt.t
new file mode 100644
index 0000000..b88836c
--- /dev/null
+++ b/bcc/misc/test/bt.t
@@ -0,0 +1,373 @@
+/* bt.t - bug tests */
+
+test1()
+{
+ char *p, *q;
+
+ q += *p++;
+}
+
+test2()
+{
+ int i,j,k,a[2],b[2],c[2];
+
+ i = a[i] + b[j] + c[k];
+}
+
+test3()
+{
+ int *p, *q;
+ int i;
+
+ i = p - q;
+}
+
+test4()
+{
+ int a[2];
+ int *p;
+
+ p = a;
+ test4(a);
+}
+
+test5()
+{
+ char c;
+
+ test4(c);
+}
+
+test6(a,b)
+int b,a;
+{
+ int i;
+
+ i = b;
+ i = a;
+}
+
+test7()
+{
+ int a[2];
+ int *p;
+
+ p = a + 1;
+}
+
+int *test8();
+
+int *test8()
+{
+ int i;
+
+ if ( test8() == i )
+ ;
+ i = *test8();
+}
+
+test9()
+{
+ int i,j,k,n;
+
+ if ((i < 0 || j > 100) && (k < 0 || n > 50))
+ i = 1;
+}
+
+struct complex
+{
+ int re;
+ int im;
+}
+ znum, *zptr, zarr[10], *zptrarr[10];
+
+test10()
+{
+ int i;
+
+ znum.re = i;
+ znum.im = 1;
+ zptr -> re = 1;
+ zptr -> im = i;
+ zarr[3].im = i;
+ zptrarr[4] -> im = 1;
+}
+
+test11()
+{
+ char symtab[100];
+
+ char *p;
+
+ if (p > symtab)
+ ;
+}
+
+test12()
+{
+char symtab[100];
+
+ char *p;
+
+ p = symtab - 21;
+}
+
+test13()
+{
+ char a[10];
+ int i;
+
+ i = a - 1;
+}
+
+test14()
+{
+ int i, **pi;
+
+ **pi = i;
+}
+
+test15()
+{
+ int i, j;
+
+ if ( (i = j ) == 2 )
+ test();
+}
+
+test16()
+{
+ struct cx3
+ {
+ int re3;
+ char im3;
+ }
+ z[10], *pz, *pz1;
+ int i;
+
+ i = z[i].re3;
+ i = pz1 - pz;
+}
+
+test17()
+{
+ int i;
+ char c;
+
+ c &= ~i;
+}
+
+test18()
+{
+ typedef int (*PFI)();
+ PFI h();
+
+ (*h())( 0 );
+}
+
+test19()
+{
+ register int *p, *q;
+ int ***z,i,a[10];
+
+ test(***z + a[i]);
+}
+
+char a[2][3][5];
+
+char *p = a;
+char *q = a[1];
+char *r = a[1][2];
+
+char test20();
+char (*test21)();
+
+test22()
+{
+ char i,k;
+ char *p;
+
+ p = a;
+ p = a[1];
+ p = a[1][2];
+ p = a[k];
+ p = a[k][k];
+ i = sizeof a;
+ i = sizeof a[k];
+ i = sizeof a[k][k];
+ i = sizeof test20;
+ i = sizeof test21;
+ i = sizeof test20();
+ i = sizeof (*test21)();
+}
+
+test23()
+{
+ long *pl;
+ int i;
+ char *s;
+
+ *pl += i;
+ *s += *pl;
+}
+
+test24()
+{
+ float f;
+ double *dp1(), *dp2();
+
+ f = *dp1()++; /* illegal */
+ f = *++dp1(); /* illegal */
+ f = *dp1() + *dp2(); /* bad code (pushes ptr to doubly indirect) */
+}
+
+test25()
+{
+ test25( "2"[1] ); /* added 1 to label number, not label address */
+}
+
+struct stat
+{
+ int st_dev;
+};
+
+test26( buf )
+struct stat buf; /* wrong declare, s.b. struct stat *buf */
+{
+ buf->st_dev = 1; /* error caused null pointer to be dereferenced */
+}
+
+union
+{
+ long l;
+}
+ test27;
+
+test28()
+{
+ test27.l = test27.l + 1; /* produced poor code */
+}
+
+int test29 = (char) 1; /* cast was clobbering the global symptr */
+
+struct { int i; } test30;
+
+test31()
+{
+ return test30; /* a structure cannot be returned (yet) */
+}
+
+int *test32, test33() {} /* this is illegal */
+
+test35()
+{
+ char a[1];
+ char b[1];
+ int i;
+
+ i = i == 1 ? a : b; /* arrays were not converted to ptrs */
+}
+
+test36()
+{
+ struct fp
+ {
+ struct filp *fp_filp[1];
+ };
+ struct filp
+ {
+ int filp_int;
+ long filp_long;
+ };
+ int i;
+ register char *junk;
+ register struct fp *cp;
+
+ cp->fp_filp[i]->filp_int++; /* used to push lvalue */
+ cp->fp_filp[i]->filp_long++; /* used to push lvalue */
+ cp->fp_filp[i]->filp_int += 1; /* was OK */
+ cp->fp_filp[i]->filp_long += 1; /* used to load long into DREG:DREG */
+}
+
+test37()
+{
+ unsigned u;
+
+ u = -u; /* used to give botched nodetype */
+}
+
+test38()
+{
+ char c;
+ int i;
+
+ i = -c; /* did i = (char) -c for a time */
+}
+
+test39()
+{
+ int i;
+
+ i = (char) 1000; /* the constant wasn't being truncated */
+}
+
+#define test40(x) (x)
+
+test41()
+{
+ int i;
+ int j;
+ int k;
+
+ i = test40( j + /* was confused by EOL in macro argument */
+ k );
+}
+
+test42()
+{
+ register char *junk1;
+ register char *junk2;
+ long *longptr;
+ long longfn();
+
+ *longptr = longfn(); /* used to run out of index regs */
+}
+
+test43()
+{
+ register char *jnk1, *junk2;
+ unsigned char *bp;
+ struct FILE_BUF
+ {
+ char *bufp;
+ } *op;
+
+ *op->bufp++ = *bp; /* used to push lvalue */
+}
+
+test44()
+{
+ register char *x, *y;
+ int i;
+ char a[2];
+ char **p;
+
+ a[**p] = **p; /* used to push lvalue */
+}
+
+struct test45
+{
+ int i;
+ int j;
+} test45[10];
+
+test46()
+{
+ register char *p, *q;
+ int i;
+ int j;
+
+ test45[i] = test45[j]; /* used to push lvalue */
+}
+
+int (*test100( x )() {} /* this is legal, keep last avoid swallowing */
diff --git a/bcc/misc/test/cast.t b/bcc/misc/test/cast.t
new file mode 100644
index 0000000..554cb93
--- /dev/null
+++ b/bcc/misc/test/cast.t
@@ -0,0 +1,144 @@
+/* cast.t */
+
+char c;
+unsigned char uc;
+short s;
+unsigned short us;
+int i;
+unsigned int ui;
+long l;
+unsigned long ul;
+float f;
+double d;
+int *p;
+
+cast()
+{
+ c = (char) c;
+ uc = (unsigned char) c;
+ s = (short) c;
+ us = (unsigned short) c;
+ i = (int) c;
+ ui = (unsigned int) c;
+ l = (long) c;
+ ul = (unsigned long) c;
+ f = (float) c;
+ d = (double) c;
+ p = (int *) c;
+
+ c = (char) uc;
+ uc = (unsigned char) uc;
+ s = (short) uc;
+ us = (unsigned short) uc;
+ i = (int) uc;
+ ui = (unsigned int) uc;
+ l = (long) uc;
+ ul = (unsigned long) uc;
+ f = (float) uc;
+ d = (double) uc;
+ p = (int *) uc;
+
+ c = (char) s;
+ uc = (unsigned char) s;
+ s = (short) s;
+ us = (unsigned short) s;
+ i = (int) s;
+ ui = (unsigned int) s;
+ l = (long) s;
+ ul = (unsigned long) s;
+ f = (float) s;
+ d = (double) s;
+ p = (int *) s;
+
+ c = (char) us;
+ uc = (unsigned char) us;
+ s = (short) us;
+ us = (unsigned short) us;
+ i = (int) us;
+ ui = (unsigned int) us;
+ l = (long) us;
+ ul = (unsigned long) us;
+ f = (float) us;
+ d = (double) us;
+ p = (int *) us;
+
+ c = (char) i;
+ uc = (unsigned char) i;
+ s = (short) i;
+ us = (unsigned short) i;
+ i = (int) i;
+ ui = (unsigned int) i;
+ l = (long) i;
+ ul = (unsigned long) i;
+ f = (float) i;
+ d = (double) i;
+ p = (int *) i;
+
+ c = (char) ui;
+ uc = (unsigned char) ui;
+ s = (short) ui;
+ us = (unsigned short) ui;
+ i = (int) ui;
+ ui = (unsigned int) ui;
+ l = (long) ui;
+ ul = (unsigned long) ui;
+ f = (float) ui;
+ d = (double) ui;
+ p = (int *) ui;
+
+ c = (char) l;
+ uc = (unsigned char) l;
+ s = (short) l;
+ us = (unsigned short) l;
+ i = (int) l;
+ ui = (unsigned int) l;
+ l = (long) l;
+ ul = (unsigned long) l;
+ f = (float) l;
+ d = (double) l;
+ p = (int *) l;
+
+ c = (char) ul;
+ uc = (unsigned char) ul;
+ s = (short) ul;
+ us = (unsigned short) ul;
+ i = (int) ul;
+ ui = (unsigned int) ul;
+ l = (long) ul;
+ ul = (unsigned long) ul;
+ f = (float) ul;
+ d = (double) ul;
+ p = (int *) ul;
+
+ c = (char) f;
+ uc = (unsigned char) f;
+ s = (short) f;
+ us = (unsigned short) f;
+ i = (int) f;
+ ui = (unsigned int) f;
+ l = (long) f;
+ ul = (unsigned long) f;
+ f = (float) f;
+ d = (double) f;
+
+ c = (char) d;
+ uc = (unsigned char) d;
+ s = (short) d;
+ us = (unsigned short) d;
+ i = (int) d;
+ ui = (unsigned int) d;
+ l = (long) d;
+ ul = (unsigned long) d;
+ f = (float) d;
+ d = (double) d;
+
+ c = (char) p;
+ uc = (unsigned char) p;
+ s = (short) p;
+ us = (unsigned short) p;
+ i = (int) p;
+ ui = (unsigned int) p;
+ l = (long) p;
+ ul = (unsigned long) p;
+ p = (int *) p;
+}
diff --git a/bcc/misc/test/cast1.t b/bcc/misc/test/cast1.t
new file mode 100644
index 0000000..a4c15d5
--- /dev/null
+++ b/bcc/misc/test/cast1.t
@@ -0,0 +1,144 @@
+/* cast1.t */
+
+char c;
+unsigned char uc;
+short s;
+unsigned short us;
+int i;
+unsigned int ui;
+long l;
+unsigned long ul;
+float f;
+double d;
+int *p;
+
+cast()
+{
+ c = c;
+ uc = c;
+ s = c;
+ us = c;
+ i = c;
+ ui = c;
+ l = c;
+ ul = c;
+ f = c;
+ d = c;
+ p = c;
+
+ c = uc;
+ uc = uc;
+ s = uc;
+ us = uc;
+ i = uc;
+ ui = uc;
+ l = uc;
+ ul = uc;
+ f = uc;
+ d = uc;
+ p = uc;
+
+ c = s;
+ uc = s;
+ s = s;
+ us = s;
+ i = s;
+ ui = s;
+ l = s;
+ ul = s;
+ f = s;
+ d = s;
+ p = s;
+
+ c = us;
+ uc = us;
+ s = us;
+ us = us;
+ i = us;
+ ui = us;
+ l = us;
+ ul = us;
+ f = us;
+ d = us;
+ p = us;
+
+ c = i;
+ uc = i;
+ s = i;
+ us = i;
+ i = i;
+ ui = i;
+ l = i;
+ ul = i;
+ f = i;
+ d = i;
+ p = i;
+
+ c = ui;
+ uc = ui;
+ s = ui;
+ us = ui;
+ i = ui;
+ ui = ui;
+ l = ui;
+ ul = ui;
+ f = ui;
+ d = ui;
+ p = ui;
+
+ c = l;
+ uc = l;
+ s = l;
+ us = l;
+ i = l;
+ ui = l;
+ l = l;
+ ul = l;
+ f = l;
+ d = l;
+ p = l;
+
+ c = ul;
+ uc = ul;
+ s = ul;
+ us = ul;
+ i = ul;
+ ui = ul;
+ l = ul;
+ ul = ul;
+ f = ul;
+ d = ul;
+ p = ul;
+
+ c = f;
+ uc = f;
+ s = f;
+ us = f;
+ i = f;
+ ui = f;
+ l = f;
+ ul = f;
+ f = f;
+ d = f;
+
+ c = d;
+ uc = d;
+ s = d;
+ us = d;
+ i = d;
+ ui = d;
+ l = d;
+ ul = d;
+ f = d;
+ d = d;
+
+ c = p;
+ uc = p;
+ s = p;
+ us = p;
+ i = p;
+ ui = p;
+ l = p;
+ ul = p;
+ p = p;
+}
diff --git a/bcc/misc/test/castest.t b/bcc/misc/test/castest.t
new file mode 100644
index 0000000..ae27f7b
--- /dev/null
+++ b/bcc/misc/test/castest.t
@@ -0,0 +1,74 @@
+/* castest.c */
+
+/*
+#define signedchar
+#define bigints
+*/
+#define unsigchar
+#define unsigshort
+#define unsiglong
+
+#define TEST(u,c) if ( (u) != (c) )\
+ { printf( "u != c\n" ); ++bad; } ++possible
+
+main()
+{
+ int bad;
+ int possible;
+ char c;
+#ifdef signedchar
+ signed char sc;
+#endif
+#ifdef unsigchar
+ unsigned char uc;
+#endif
+ short s;
+#ifdef unsigshort
+ unsigned short us;
+#endif
+ int i;
+ unsigned u;
+ long l;
+#ifdef unsiglong
+ unsigned long ul;
+#endif
+
+ bad = possible = 0;
+ u = 0x1ff;
+ c = (char) u;
+ if ( c < 0 )
+ printf( "characters are signed\n" );
+ TEST((char)u,c);
+ i = (int)(char) u;
+ TEST(i,(int)c);
+ TEST((int)(char)u,i);
+
+#ifdef signedchar
+ sc = (signed char) u;
+ if ( sc >= 0 )
+ printf( "??? signed char not signed\n" );
+ TEST((signed char)u,sc);
+ TEST((int)(signed char)u,(int)sc);
+ i = (int) sc;
+ TEST((int)(signed char)u,i);
+#endif
+
+#ifdef bigints
+ u = 0x1ffff;
+ s = (short) u;
+ TEST((short)u,s);
+ TEST((int)(short)u,(int)s);
+ i = (int) s;
+ TEST((int)(short)u,i);
+
+#ifdef unsigshort
+ us = (unsigned short) u;
+ TEST((unsigned short)u,us);
+ TEST((int)(unsigned short)u,(int)us);
+ i = (int) us;
+ TEST((int)(unsigned short)u,i);
+#endif
+#endif
+
+ printf( "%d bad out of a possible %d\n", bad, possible );
+}
diff --git a/bcc/misc/test/ctype.t b/bcc/misc/test/ctype.t
new file mode 100644
index 0000000..93b3e4f
--- /dev/null
+++ b/bcc/misc/test/ctype.t
@@ -0,0 +1,38 @@
+/* ctype.h */
+
+#define _C 1 /* control */
+#define _D 2 /* digit */
+#define _L 4 /* lower */
+#define _P 8 /* punctuation */
+#define _S 16 /* space */
+#define _U 32 /* upper */
+#define _UN 64 /* underline */
+#define _X '\200' /* hex digit, not digit */
+
+extern char _ctype_[];
+
+#define _ct1_ (_ctype_+1)
+
+#define isalnum(c) (_ct1_[c]&(_U|_L|_D))
+#define isalpha(c) (_ct1_[c]&(_U|_L))
+#define isascii(i) ((unsigned)(i)<=0x7f)
+#define isalpha(c) (_ct1_[c]&(_U|_L))
+#define iscntrl(c) (_ct1_[c]&_C)
+#define iscsym(c) (_ct1_[c]&(_U|_L|_D|_UN))
+#define iscsymf(c) (_ct1_[c]&(_U|_L|_UN))
+#define isdigit(c) (_ct1_[c]&_D)
+#define isgraph(c) (_ct1_[c]&(_U|_L|_D|_P))
+#define islower(c) (_ct1_[c]&_L)
+/* isodigit(i) is a function */
+/* isprint(i) is a function */
+#define ispunct(c) (_ct1_[c]&_P)
+#define isspace(c) (_ct1_[c]&_S)
+#define isupper(c) (_ct1_[c]&_U)
+#define isxdigit(c) (_ct1_[c]&(_D|_X))
+
+#define toascii(i) ((i)&0x7f)
+/* toint(i) is a function */
+/* tolower(i) is a function */
+#define _tolower(c) ((c)+('a'-'A'))
+/* toupper(i) is a function */
+#define _toupper(c) ((c)+('A'-'a'))
diff --git a/bcc/misc/test/error.t b/bcc/misc/test/error.t
new file mode 100644
index 0000000..24e302a
--- /dev/null
+++ b/bcc/misc/test/error.t
@@ -0,0 +1,78 @@
+static char *errorstring[] =
+{
+ "# in a macro: not preprocessed",
+ "already declared",
+ "array of functions is illegal",
+ "bad address",
+ "bad case label",
+ "bad character constant",
+ "bad character",
+ "bad control",
+ "bad default label",
+ "bad expression",
+ "bad file name",
+ "bad indirection count",
+ "bad initializer address",
+ "bad register store",
+ "call of non-function",
+ "can't continue in switch",
+ "can't index",
+ "can't load char to index reg",
+ "can't open",
+ "can't open input",
+ "can't open output",
+ "case can't be reached with char switch",
+ "constant expression expected",
+ "else without if",
+ "end of file in #asm",
+ "end of file in #define",
+ "end of file in comment",
+ "end of file in failed #if",
+ "end of file in macro parameter expansion",
+ "end of file in string constant",
+ "end of line in string constant",
+ "endif without if",
+ "function returning array is illegal",
+ "function returning function is illegal",
+ "function returning structure is illegal",
+ "if stack overflow",
+ "illegal indirection",
+ "illegal macro name",
+ "illegal non-external function",
+ "illegal symbol name",
+ "illegal type conversion",
+ "illegal type name",
+ "initializer too complicated",
+ "input error",
+ "load of long constants not implemented",
+ "loading direct long with offset not implemented",
+ "local symbol table overflow",
+ "macro stack overflow",
+ "missing '('",
+ "missing while at end of do-while",
+ "need '",
+ "need int or char",
+ "need lvalue",
+ "need scalar or ptr type",
+ "need structure",
+ "no active fors, switches or whiles",
+ "not in a compound statement",
+ "null dimension",
+ "out of index registers",
+ "redefined macro",
+ "repeated argument",
+ "repeated default label",
+ "repeated parameter",
+ "table full",
+ "too few macro parameters",
+ "too many active whiles",
+ "too many cases",
+ "too many macro parameters",
+ "too many open compound statements",
+ "too many parameters",
+ "undeclared variable",
+ "undefined structure element",
+ "undefined structure",
+ "unsigned ints only",
+ "variable not in argument list"
+};
diff --git a/bcc/misc/test/extern.t b/bcc/misc/test/extern.t
new file mode 100644
index 0000000..dac5f5c
--- /dev/null
+++ b/bcc/misc/test/extern.t
@@ -0,0 +1,236 @@
+/* extern.c - external declarations (K & R p218-9) */
+
+#include "def.h"
+#include "globvar.h"
+#include "symbol.h"
+
+struct typestruct *declarator();
+struct typestruct *extypespec();
+int paramlist();
+struct typestruct *typespec();
+
+/*=============================================================================
+ -- notation is 1st attempt at EBNF (see Modula-2 book)
+ program = { type-definition | function-or-data-definition }.
+ type-definition = "typedef" type-definition-list.
+=============================================================================*/
+
+program()
+{
+ nextsym();
+ while ( sym != EOFSYM )
+ {
+ if ( sym = TYPEDEFDECL )
+ deftypes();
+ else
+ functordata();
+ }
+}
+
+/*=============================================================================
+ type-definition-list. -- not implemented
+=============================================================================*/
+
+deftypes()
+{}
+
+/*=============================================================================
+ function-or-data-definition = external-type-specification
+ ( function-definition | init-declarators ).
+ function-definition = "(" parameter-list ")" arg-list compound-statement.
+ -- this is different from K & R who omit typedefs and static functions
+=============================================================================*/
+
+functordata()
+{
+ struct typestruct *type;
+ int nargs;
+
+ type = extypespec();
+ if ( sym == LPAREN )
+ {
+ nextsym();
+ nargs = paramlist();
+ need( RPAREN );
+ arglist( nargs );
+ need( LBRACE );
+ compound( 1 + locptr-pstartloc );/* 1 = function flag, rest = nargs */
+ oldlevel();
+ }
+ else
+ initdecl( type );
+}
+
+/*=============================================================================
+ external-type-specification = extern-sc type-specifier declarator.
+ extern-sc = [ extern | static ].
+=============================================================================*/
+
+struct typestruct *extypespec()
+{
+ int sc;
+
+ switch( sym )
+ {
+ case EXTERNDECL:
+ case STATICDECL:
+ sc = sym; nextsym(); break;
+ default:
+ sc = EXTERNDECL; break;
+ }
+ return declarator( typespec() );
+}
+
+/*=============================================================================
+ parameter-list = [identifier { "," identifier }].
+=============================================================================*/
+
+int paramlist()
+{
+ int nargs;
+
+ locptr = pstartloc;
+ newlevel();
+ nargs = 0;
+ while ( sym == IDENT )
+ {
+ addloc( gsname, itype, 0 ); /* fix up types and offsets later */
+ nextsym();
+ ++nargs;
+ if ( sym != COMMA )
+ break;
+ nextsym();
+ }
+ return nargs;
+}
+
+/*=============================================================================
+ arg-list =
+=============================================================================*/
+
+arglist( nargs )
+int nargs;
+{
+ struct symstruct *symptr;
+ int argsize, argsp;
+ int lastsym;
+ struct typestruct *basetype;
+ char declflag;
+
+ declflag = TRUE;
+ do
+ {
+ switch( sym )
+ {
+ case TYPEDECL:
+ basetype = gsymptr->type;
+ nextsym();
+ getarg1( basetype );
+ break;
+ case STRUCTDECL:
+ case UNIONDECL:
+ lastsym = sym;
+ nextsym();
+ getarg( declsu( lastsym ) );
+ break;
+ case AUTODECL:
+ case EXTERNDECL:
+ case REGDECL:
+ case STATICDECL:
+ case SEMICOLON:
+ nextsym();
+ break;
+ default:
+ declflag = FALSE;
+ break;
+ }
+ }
+ while ( declflag );
+ argsp = -2;
+ symptr = pstartloc;
+ while ( nargs && symptr < locptr ) /* convert arg sizes to offsets */
+ {
+ argsize = symptr->offset;
+ if ( symptr->type == ctype )
+ {
+ ++argsp;
+ --argsize;
+ }
+ symptr->offset = argsp;
+ argsp += argsize;
+ if ( symptr == pstartloc )
+ argsp += 2;
+ --nargs;
+ ++symptr;
+ }
+ if ( nargs )
+ error( "arguments not all declared" );
+}
+
+/* getarg( basetype ) - fill in argument types and sizes */
+
+getarg1( basetype )
+struct typestruct *basetype;
+{
+ char sname[NAMESIZE];
+ struct typestruct *type;
+ int size;
+ struct symstruct *symptr;
+
+ if ( sym != SEMICOLON )
+ while ( TRUE )
+ {
+ type = basetype;
+ size = getvar( sname, &type );
+ if ( (symptr = findlorg( sname )) == NULL || symptr->level != ARGLEVEL )
+ error( "variable not in argument list" );
+ else if ( symptr->offset != 0 ) /* already in arg list */
+ multidecl( sname, type, symptr );
+ else
+ {
+ if ( size < 2 || type->typeop == ATYPEOP )
+ size = 2;
+ symptr->offset = size;
+ symptr->type = type;
+ }
+ if ( sym == COMMA )
+ nextsym();
+ else
+ break;
+ }
+ ns();
+}
+
+struct typestruct *declarator( basetype )
+struct typestruct *basetype;
+{
+ char sname[NAMESIZE];
+ int size;
+ struct symstruct *multi;
+
+ size = getvar( sname, &type );
+ if ( multi = findlorg( sname ) )
+ multidecl( sname, type, multi );
+ else
+ addglb( sname, type, size );
+ nextsym();
+}
+
+struct typestruct *typespec()
+{
+ int lastsym;
+
+ switch( sym )
+ {
+ case TYPEDECL:
+ nextsym();
+ return gsymptr->type;
+ case STRUCTDECL:
+ case UNIONDECL:
+ lastsym = sym;
+ nextsym();
+ return declsu( lastsym );
+ default:
+ return itype;
+ }
+}
diff --git a/bcc/misc/test/hilbert.t b/bcc/misc/test/hilbert.t
new file mode 100644
index 0000000..e18dc63
--- /dev/null
+++ b/bcc/misc/test/hilbert.t
@@ -0,0 +1,169 @@
+/* hilbert.c */
+
+/* S1 stuff
+
+#define PIFBUF ( *(struct IFBUF **) 0xf010 )
+#define PSET 2
+
+struct IFBUF
+{
+ char ERR;
+ char COMMAND;
+ char COLOR;
+ char PLOTOPTION;
+ int LINESTYLE;
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char BFFLAG;
+};
+end of S1 stuff */
+
+/* L3 stuff */
+
+#define PIFBUF ( (struct IFBUF *) 0xa1 )
+#define PSET 1
+
+struct IFBUF
+{
+ char PLOTOPTION;
+ char junk1[0xa8-0xa2];
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char junk2[0xf0-0xb0];
+ char ERR; /* this to BFFLAG are dummies to keep S1 code */
+ char COMMAND;
+ int LINESTYLE;
+ char BFFLAG;
+ char junk3[0x3ea-0xf5];
+ char COLOR;
+};
+
+#define H0 512 /* square size */
+#define XOFFS 80 /* offset to centre square */
+#define XNUM 15 /* scale 512 * 15/16 = 480 */
+#define XDENOM 16
+#define YNUM 25 /* scale 512 * 25/64 = 200 */
+#define YDENOM 64 /* to give max height, dot ratio 480/200 = 2.4 */
+
+int h, x, y;
+
+main()
+{
+ int i, x0, y0;
+ char color;
+
+ PIFBUF->PLOTOPTION = PSET;
+ PIFBUF->LINESTYLE = /* normal */
+ PIFBUF->COMMAND = /* ?? */
+ PIFBUF->BFFLAG = 0; /* not a box */
+ color = i = 0;
+ x0 = y0 = (h = H0)/2;
+ while ( h > 1 )
+ {
+ ++i;
+ h = h/2;
+ if ( ++color > 7 )
+ color = 1;
+ gcolor( color );
+ x = x0 += h/2;
+ y = y0 += h/2;
+ glocate();
+ a( i );
+ }
+}
+
+a( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ d( i ); x -= h; plot();
+ a( i ); y -= h; plot();
+ a( i ); x += h; plot();
+ b( i );
+ }
+}
+
+b( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ c( i ); y += h; plot();
+ b( i ); x += h; plot();
+ b( i ); y -= h; plot();
+ a( i );
+ }
+}
+
+c( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ b( i ); x += h; plot();
+ c( i ); y += h; plot();
+ c( i ); x -= h; plot();
+ d( i );
+ }
+}
+
+d( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ a( i ); y -= h; plot();
+ d( i ); x -= h; plot();
+ d( i ); y += h; plot();
+ c( i );
+ }
+}
+
+glocate()
+{
+ PIFBUF->X2 = x - x * (XDENOM - XNUM) / XDENOM + XOFFS;
+ PIFBUF->Y2 = (y * YNUM) / YDENOM;
+}
+
+/* S1 gcolor and plot
+
+gcolor( color )
+int color;
+{
+ PIFBUF->COLOR = color;
+}
+
+plot()
+{
+ PIFBUF->X1 = PIFBUF->X2;
+ PIFBUF->Y1 = PIFBUF->Y2;
+ glocate();
+#asm
+ SWI2
+ FDB $4201 call LINEMA
+#endasm
+}
+
+end S1 plot */
+
+gcolor( color )
+int color;
+{
+ PIFBUF->COLOR = color | 0x10;
+}
+
+plot()
+{
+ PIFBUF->X1 = PIFBUF->X2;
+ PIFBUF->Y1 = PIFBUF->Y2;
+ glocate();
+#asm
+ JSR $D709
+ JSR $D79A
+#endasm
+}
diff --git a/bcc/misc/test/longtest.c b/bcc/misc/test/longtest.c
new file mode 100644
index 0000000..0c0bfe0
--- /dev/null
+++ b/bcc/misc/test/longtest.c
@@ -0,0 +1,24 @@
+int i,j;
+long m,n;
+
+main()
+{
+ while ( 1 )
+ {
+ if ( scanf( "%ld %ld", &m, &n ) <= 0 )
+ exit( 0 );
+ printf( "m = %ld n = %ld m + n = %ld m - n = %ld m * n = %ld\n",
+ m, n, m + n, m - n, m * n );
+ printf( "m = %ld n = %ld m / n = %ld m %% n = %ld\n",
+ m, n, m / n, m % n );
+ printf( "m = %ld n = %ld m&n = %ld m | n = %ld m^n = %ld\n",
+ m, n, m & n, m | n, m ^ n );
+ printf( "m = %ld n = %ld m << n = %ld m >> n = %ld\n",
+ m, n, m << (int) n, m >> (int) n );
+ printf(
+ "m = %ld n = %ld m < n is %d m == n is %d m > n is %d m == 0 is %d\n",
+ m, n, m < n, m == n, m > n, m == 0 );
+ printf( "m = %ld n = %ld -m = %ld ~m = %ld ++m = %ld --n = %ld\n",
+ m, n, -m, ~m, ++m, --n );
+ }
+}
diff --git a/bcc/misc/test/longtest.dat b/bcc/misc/test/longtest.dat
new file mode 100644
index 0000000..a1c7998
--- /dev/null
+++ b/bcc/misc/test/longtest.dat
@@ -0,0 +1,15 @@
+1 1
+-1 1
+1 -1
+-1 -1
+2 3
+4 5
+234234 34554
+4534534 34535
+345324523 3245325
+345435345 319755
+34534 345
+-352351235 23535
+533512351 -3535345
+-351351313 -12235
+123456789 987654321
diff --git a/bcc/misc/test/longtest.mak b/bcc/misc/test/longtest.mak
new file mode 100755
index 0000000..454a4e8
--- /dev/null
+++ b/bcc/misc/test/longtest.mak
@@ -0,0 +1,3 @@
+cc -o cclongtest longtest.c
+sc longtest.c sclongtest.s
+cc -o sclongtest sclongtest.s $HOME/lib/libcb.a $HOME/lib/liblb.a
diff --git a/bcc/misc/test/longtest.sh b/bcc/misc/test/longtest.sh
new file mode 100755
index 0000000..e76f98a
--- /dev/null
+++ b/bcc/misc/test/longtest.sh
@@ -0,0 +1,4 @@
+./sclongtest < longtest.dat >scl.out
+./cclongtest < longtest.dat >ccl.out
+diff scl.out ccl.out >longtest.diff
+cat longtest.diff
diff --git a/bcc/misc/test/miniltest.t b/bcc/misc/test/miniltest.t
new file mode 100644
index 0000000..78097d4
--- /dev/null
+++ b/bcc/misc/test/miniltest.t
@@ -0,0 +1,72 @@
+long x;
+int i;
+unsigned u;
+
+long test1(x)
+long x;
+{
+ return x;
+}
+
+long test2(x)
+int x;
+{
+ return x;
+}
+
+main()
+{
+ printlong( "x=1 is ", x = 1 );
+ printlong( "test1(x) is ", test1(x) );
+ printlong( "test1(1L) is ", test1(1L) );
+ printlong( "x = test1(1L) is ", x = test1(1L) );
+ printlong( "x = test1(x=1) is ", x = test1(x=1) );
+ printlong( "i=1 is ", (long) (i = 1) );
+ printlong( "test2(i) is ", test2(i) );
+ printlong( "test2(1) is ", test2(1) );
+ printlong( "i = test2(1) is ", (long) (i = test2(1)) );
+ printlong( "i = test2(i=1) is ", (long) (i = test2(i=1)) );
+ printlong( "(long) (i = -1) is ", (long) (i=-1) );
+ printlong( "(long) (u = -1) is ", (long) (u=-1) );
+ printlong( "x = -1 is ", x = -1 );
+}
+
+printlong( s, x )
+char *s;
+long x;
+{
+ printf( "%s", s );
+ if ( x & 0x80000000 )
+ {
+ putchar( '-' );
+ x = -x;
+ }
+ printf( "%08lx", (x >> 16) + (x << 16) );
+ putchar( '\n' );
+}
+
+outulhex( pnum )
+char *pnum;
+{
+ int i;
+
+ for ( i = 3; i >=0; --i )
+ p2( pnum[i] );
+}
+
+p2(i)
+int i;
+{
+ p1(i>>4);
+ p1(i);
+}
+
+p1(num)
+int num;
+{
+ int digit;
+
+ if ( (digit = num & 0xf) >= 10 )
+ digit += 'A' - ('9' + 1);
+ putchar( digit + '0' );
+}
diff --git a/bcc/misc/test/op1.t b/bcc/misc/test/op1.t
new file mode 100644
index 0000000..614e093
--- /dev/null
+++ b/bcc/misc/test/op1.t
@@ -0,0 +1,120 @@
+/* op1.t - test and, or (eor same as or ) */
+
+char cfn();
+int ifn();
+
+char *op1()
+{
+ char c, *pc, **ppc;
+ int i, *pi, **ppi;
+
+ i = c & 1;
+ i = 1 & c;
+ i = i & 1;
+ i = 1 & i;
+
+ i = c & 500;
+ i = 500 & c;
+ i = i & 500;
+ i = 500 & i;
+
+ i = c | 1;
+ i = 1 | c;
+ i = i | 1;
+ i = 1 | i;
+
+ i = c | 500;
+ i = 500 | c;
+ i = i | 500;
+ i = 500 | i;
+
+ i = c & c;
+ i = c & i;
+ i = i & c;
+ i = i & i;
+
+ i = c | c;
+ i = c | i;
+ i = i | c;
+ i = i | i;
+
+ i = c & c++;
+ i = c & i++;
+ i = i & c++;
+ i = i & i++;
+
+ i = c++ & c;
+ i = i++ & c;
+ i = c++ & i;
+ i = i++ & i;
+
+ i = c | c++;
+ i = c | i++;
+ i = i | c++;
+ i = i | i++;
+
+ i = c++ | c;
+ i = i++ | c;
+ i = c++ | i;
+ i = i++ | i;
+
+ i = c & cfn();
+ i = c & ifn();
+ i = i & cfn();
+ i = i & ifn();
+
+ i = cfn() & c;
+ i = ifn() & c;
+ i = cfn() & i;
+ i = ifn() & i;
+
+ i = c | cfn();
+ i = c | ifn();
+ i = i | cfn();
+ i = i | ifn();
+
+ i = cfn() | c;
+ i = ifn() | c;
+ i = cfn() | i;
+ i = ifn() | i;
+
+ i = *pc & c++;
+ i = *pc & i++;
+ i = *pi & c++;
+ i = *pi & i++;
+
+ i = c++ & *pc;
+ i = i++ & *pc;
+ i = c++ & *pi;
+ i = i++ & *pi;
+
+ i = *pc | c++;
+ i = *pc | i++;
+ i = *pi | c++;
+ i = *pi | i++;
+
+ i = c++ | *pc;
+ i = i++ | *pc;
+ i = c++ | *pi;
+ i = i++ | *pi;
+
+ i = **ppc & c++;
+ i = **ppc & i++;
+ i = **ppi & c++;
+ i = **ppi & i++;
+
+ i = c++ & **ppc;
+ i = i++ & **ppc;
+ i = c++ & **ppi;
+ i = i++ & **ppi;
+
+ i = **ppc | c++;
+ i = **ppc | i++;
+ i = **ppi | c++;
+ i = **ppi | i++;
+
+ i = c++ | **ppc;
+ i = i++ | **ppc;
+ i = c++ | **ppi;
+ i = i++ | **ppi;
+}
diff --git a/bcc/misc/test/opcmp.t b/bcc/misc/test/opcmp.t
new file mode 100644
index 0000000..28bd1a2
--- /dev/null
+++ b/bcc/misc/test/opcmp.t
@@ -0,0 +1,106 @@
+/* opcmp.t - test logical compare operations */
+
+/* only doing chars, shorts, ints and unsigneds */
+/* not doing longs, floats or doubles */
+
+/* short = int, so only a few examples */
+/* unsigned like int, so only a few examples */
+/* all examples < */
+
+op1()
+{
+ char c, *pc, **ppc, cfn();
+ short s, *ps, **pps, sfn();
+ int i, *pi, **ppi, ifn();
+ unsigned u, *pu, **ppu, ufn();
+
+ c < 0;
+ 0 < c;
+ i < 0;
+ 0 < i;
+
+ s < 0;
+ 0 < s;
+
+ 0 < u;
+ u < 0;
+ 1 < u;
+ u < 1;
+
+ c < 1;
+ 1 < c;
+ c < 500;
+ 500 < c;
+
+ c < c;
+ c < i;
+ i < c;
+ i < i;
+
+ s < c;
+ i < u;
+
+ c < c++;
+ c < i++;
+ i < c++;
+ i < i++;
+
+ s < i++;
+ c < u++;
+
+ c++ < c;
+ i++ < c;
+ c++ < i;
+ i++ < i;
+
+ s++ < c;
+ i++ < u;
+
+ c < cfn();
+ c < ifn();
+ i < cfn();
+ i < ifn();
+
+ s < cfn();
+ c < ufn();
+
+ cfn() < c;
+ ifn() < c;
+ cfn() < i;
+ ifn() < i;
+
+ sfn() < c;
+ ifn() < u;
+
+ *pc < c++;
+ *pc < i++;
+ *pi < c++;
+ *pi < i++;
+
+ *ps < c++;
+ *pi < u++;
+
+ c++ < *pc;
+ i++ < *pc;
+ c++ < *pi;
+ i++ < *pi;
+
+ s++ < *pc;
+ i++ < *pu;
+
+ **ppc < c++;
+ **ppc < i++;
+ **ppi < c++;
+ **ppi < i++;
+
+ **pps < c++;
+ **ppi < u++;
+
+ c++ < **ppc;
+ i++ < **ppc;
+ c++ < **ppi;
+ i++ < **ppi;
+
+ s++ < **ppc;
+ i++ < **ppu;
+}
diff --git a/bcc/misc/test/oplong.t b/bcc/misc/test/oplong.t
new file mode 100644
index 0000000..b452243
--- /dev/null
+++ b/bcc/misc/test/oplong.t
@@ -0,0 +1,264 @@
+/* oplong.t - test long operations */
+
+/* this is just opsoft.t with int defined as long */
+
+#define int long
+#define UNSIGNED unsigned long
+
+/* only doing chars, shorts, ints and unsigneds */
+/* not doing longs, floats or doubles */
+
+/* short = int, so only a few examples */
+/* unsigned like int, so only a few examples */
+/* most examples for DIVOP */
+/* only (all) special cases of MULOP, MODOP, SLOP and SROP are tried */
+
+op1()
+{
+ char c, *pc, **ppc, cfn();
+ short s, *ps, **pps, sfn();
+ int i, *pi, **ppi, ifn();
+ UNSIGNED u, *pu, **ppu, ufn();
+
+ i = c / 0;
+ i = 0 / c;
+ i = i / 0;
+ i = 0 / i;
+
+ i = s / 0;
+ i = 0 / u;
+
+ i = c / 1;
+ i = 1 / c;
+ i = i / 1;
+ i = 1 / i;
+
+ i = s / 1;
+ i = 1 / u;
+
+ i = c / 2;
+ i = 2 / c;
+ i = i / 2;
+ i = 2 / i;
+
+ i = s / 2;
+ i = 2 / u;
+
+ i = c / 500;
+ i = 500 / c;
+ i = i / 500;
+ i = 500 / i;
+
+ i = s / 500;
+ i = 500 / u;
+
+ i = c / c;
+ i = c / i;
+ i = i / c;
+ i = i / i;
+
+ i = s / c;
+ i = i / u;
+
+ i = c / c++;
+ i = c / i++;
+ i = i / c++;
+ i = i / i++;
+
+ i = s / i++;
+ i = c / u++;
+
+ i = c++ / c;
+ i = i++ / c;
+ i = c++ / i;
+ i = i++ / i;
+
+ i = s++ / c;
+ i = i++ / u;
+
+ i = c / cfn();
+ i = c / ifn();
+ i = i / cfn();
+ i = i / ifn();
+
+ i = s / cfn();
+ i = c / ufn();
+
+ i = cfn() / c;
+ i = ifn() / c;
+ i = cfn() / i;
+ i = ifn() / i;
+
+ i = sfn() / c;
+ i = ifn() / u;
+
+ i = *pc / c++;
+ i = *pc / i++;
+ i = *pi / c++;
+ i = *pi / i++;
+
+ i = *ps / c++;
+ i = *pi / u++;
+
+ i = c++ / *pc;
+ i = i++ / *pc;
+ i = c++ / *pi;
+ i = i++ / *pi;
+
+ i = s++ / *pc;
+ i = i++ / *pu;
+
+ i = **ppc / c++;
+ i = **ppc / i++;
+ i = **ppi / c++;
+ i = **ppi / i++;
+
+ i = **pps / c++;
+ i = **ppi / u++;
+
+ i = c++ / **ppc;
+ i = i++ / **ppc;
+ i = c++ / **ppi;
+ i = i++ / **ppi;
+
+ i = s++ / **ppc;
+ i = i++ / **ppu;
+
+ i = c * 0;
+ i = 0 * c;
+ i = i * 0;
+ i = 0 * i;
+
+ i = s * 0;
+ i = 0 * u;
+
+ i = c * 1;
+ i = 1 * c;
+ i = i * 1;
+ i = 1 * i;
+
+ i = s * 1;
+ i = 1 * u;
+
+ i = c * 2;
+ i = 2 * c;
+ i = i * 2;
+ i = 2 * i;
+
+ i = s * 2;
+ i = 2 * u;
+
+ i = c * 500;
+ i = 500 * c;
+ i = i * 500;
+ i = 500 * i;
+
+ i = s * 500;
+ i = 500 * u;
+
+ i = c * c;
+ i = c * c++;
+ i = c++ * c;
+ i = c * cfn();
+ i = cfn() * c;
+ i = *pc * c++;
+ i = c++ * *pc;
+ i = **ppc * c++;
+ i = c++ * **ppc;
+
+ i = c % 0;
+ i = 0 % c;
+ i = i % 0;
+ i = 0 % i;
+
+ i = s % 0;
+ i = 0 % u;
+
+ i = c % 1;
+ i = 1 % c;
+ i = i % 1;
+ i = 1 % i;
+
+ i = s % 1;
+ i = 1 % u;
+
+ i = c % 2;
+ i = 2 % c;
+ i = i % 2;
+ i = 2 % i;
+
+ i = s % 2;
+ i = 2 % u;
+
+ i = c % 500;
+ i = 500 % c;
+ i = i % 500;
+ i = 500 % i;
+
+ i = s % 500;
+ i = 500 % u;
+
+ i = c << 0;
+ i = 0 << c;
+ i = i << 0;
+ i = 0 << i;
+
+ i = s << 0;
+ i = 0 << u;
+
+ i = c << 1;
+ i = 1 << c;
+ i = i << 1;
+ i = 1 << i;
+
+ i = s << 1;
+ i = 1 << u;
+
+ i = c << 8;
+ i = 8 << c;
+ i = i << 8;
+ i = 8 << i;
+
+ i = s << 8;
+ i = 8 << u;
+
+ i = c << 9;
+ i = 9 << c;
+ i = i << 9;
+ i = 9 << i;
+
+ i = s << 9;
+ i = 9 << u;
+
+ i = c >> 0;
+ i = 0 >> c;
+ i = i >> 0;
+ i = 0 >> i;
+
+ i = s >> 0;
+ i = 0 >> u;
+
+ i = c >> 1;
+ i = 1 >> c;
+ i = i >> 1;
+ i = 1 >> i;
+
+ i = s >> 1;
+ i = 1 >> u;
+
+ i = c >> 8;
+ i = 8 >> c;
+ i = i >> 8;
+ i = 8 >> i;
+
+ i = s >> 8;
+ i = 8 >> u;
+
+ i = c >> 9;
+ i = 9 >> c;
+ i = i >> 9;
+ i = 9 >> i;
+
+ i = s >> 9;
+ i = 9 >> u;
+}
diff --git a/bcc/misc/test/opplus.t b/bcc/misc/test/opplus.t
new file mode 100644
index 0000000..88e31e9
--- /dev/null
+++ b/bcc/misc/test/opplus.t
@@ -0,0 +1,122 @@
+/* op+-.t - test plus, minus operators */
+
+/* only doing chars and ints, not shorts, longs, floats, doubles */
+/* not doing pointer arithmetic */
+
+op1()
+{
+ char cfn();
+ int ifn();
+ char c, *pc, **ppc;
+ int i, *pi, **ppi;
+
+ i = c + 1;
+ i = 1 + c;
+ i = i + 1;
+ i = 1 + i;
+
+ i = c + 500;
+ i = 500 + c;
+ i = i + 500;
+ i = 500 + i;
+
+ i = c - 1;
+ i = 1 - c;
+ i = i - 1;
+ i = 1 - i;
+
+ i = c - 500;
+ i = 500 - c;
+ i = i - 500;
+ i = 500 - i;
+
+ i = c + c;
+ i = c + i;
+ i = i + c; /* -2 cycles, +1 byte different from c + i, lhs loaded 1st */
+ i = i + i;
+
+ i = c - c;
+ i = c - i;
+ i = i - c;
+ i = i - i;
+
+ i = c + c++;
+ i = c + i++;
+ i = i + c++;
+ i = i + i++;
+
+ i = c++ + c;
+ i = i++ + c;
+ i = c++ + i;
+ i = i++ + i;
+
+ i = c - c++;
+ i = c - i++;
+ i = i - c++;
+ i = i - i++;
+
+ i = c++ - c;
+ i = i++ - c;
+ i = c++ - i;
+ i = i++ - i;
+
+ i = c + cfn();
+ i = c + ifn();
+ i = i + cfn();
+ i = i + ifn();
+
+ i = cfn() + c;
+ i = ifn() + c;
+ i = cfn() + i;
+ i = ifn() + i;
+
+ i = c - cfn();
+ i = c - ifn();
+ i = i - cfn();
+ i = i - ifn();
+
+ i = cfn() - c;
+ i = ifn() - c;
+ i = cfn() - i;
+ i = ifn() - i;
+
+ i = *pc + c++;
+ i = *pc + i++;
+ i = *pi + c++;
+ i = *pi + i++;
+
+ i = c++ + *pc;
+ i = i++ + *pc;
+ i = c++ + *pi;
+ i = i++ + *pi;
+
+ i = *pc - c++;
+ i = *pc - i++;
+ i = *pi - c++;
+ i = *pi - i++;
+
+ i = c++ - *pc;
+ i = i++ - *pc;
+ i = c++ - *pi;
+ i = i++ - *pi;
+
+ i = **ppc + c++;
+ i = **ppc + i++;
+ i = **ppi + c++;
+ i = **ppi + i++;
+
+ i = c++ + **ppc;
+ i = i++ + **ppc;
+ i = c++ + **ppi;
+ i = i++ + **ppi;
+
+ i = **ppc - c++;
+ i = **ppc - i++;
+ i = **ppi - c++;
+ i = **ppi - i++;
+
+ i = c++ - **ppc;
+ i = i++ - **ppc;
+ i = c++ - **ppi;
+ i = i++ - **ppi;
+}
diff --git a/bcc/misc/test/opsoft.t b/bcc/misc/test/opsoft.t
new file mode 100644
index 0000000..346df4d
--- /dev/null
+++ b/bcc/misc/test/opsoft.t
@@ -0,0 +1,259 @@
+/* opsoft.t - test software operations */
+
+/* only doing chars, shorts, ints and unsigneds */
+/* not doing longs, floats or doubles */
+
+/* short = int, so only a few examples */
+/* unsigned like int, so only a few examples */
+/* most examples for DIVOP */
+/* only (all) special cases of MULOP, MODOP, SLOP and SROP are tried */
+
+op1()
+{
+ char c, *pc, **ppc, cfn();
+ short s, *ps, **pps, sfn();
+ int i, *pi, **ppi, ifn();
+ unsigned u, *pu, **ppu, ufn();
+
+ i = c / 0;
+ i = 0 / c;
+ i = i / 0;
+ i = 0 / i;
+
+ i = s / 0;
+ i = 0 / u;
+
+ i = c / 1;
+ i = 1 / c;
+ i = i / 1;
+ i = 1 / i;
+
+ i = s / 1;
+ i = 1 / u;
+
+ i = c / 2;
+ i = 2 / c;
+ i = i / 2;
+ i = 2 / i;
+
+ i = s / 2;
+ i = 2 / u;
+
+ i = c / 500;
+ i = 500 / c;
+ i = i / 500;
+ i = 500 / i;
+
+ i = s / 500;
+ i = 500 / u;
+
+ i = c / c;
+ i = c / i;
+ i = i / c;
+ i = i / i;
+
+ i = s / c;
+ i = i / u;
+
+ i = c / c++;
+ i = c / i++;
+ i = i / c++;
+ i = i / i++;
+
+ i = s / i++;
+ i = c / u++;
+
+ i = c++ / c;
+ i = i++ / c;
+ i = c++ / i;
+ i = i++ / i;
+
+ i = s++ / c;
+ i = i++ / u;
+
+ i = c / cfn();
+ i = c / ifn();
+ i = i / cfn();
+ i = i / ifn();
+
+ i = s / cfn();
+ i = c / ufn();
+
+ i = cfn() / c;
+ i = ifn() / c;
+ i = cfn() / i;
+ i = ifn() / i;
+
+ i = sfn() / c;
+ i = ifn() / u;
+
+ i = *pc / c++;
+ i = *pc / i++;
+ i = *pi / c++;
+ i = *pi / i++;
+
+ i = *ps / c++;
+ i = *pi / u++;
+
+ i = c++ / *pc;
+ i = i++ / *pc;
+ i = c++ / *pi;
+ i = i++ / *pi;
+
+ i = s++ / *pc;
+ i = i++ / *pu;
+
+ i = **ppc / c++;
+ i = **ppc / i++;
+ i = **ppi / c++;
+ i = **ppi / i++;
+
+ i = **pps / c++;
+ i = **ppi / u++;
+
+ i = c++ / **ppc;
+ i = i++ / **ppc;
+ i = c++ / **ppi;
+ i = i++ / **ppi;
+
+ i = s++ / **ppc;
+ i = i++ / **ppu;
+
+ i = c * 0;
+ i = 0 * c;
+ i = i * 0;
+ i = 0 * i;
+
+ i = s * 0;
+ i = 0 * u;
+
+ i = c * 1;
+ i = 1 * c;
+ i = i * 1;
+ i = 1 * i;
+
+ i = s * 1;
+ i = 1 * u;
+
+ i = c * 2;
+ i = 2 * c;
+ i = i * 2;
+ i = 2 * i;
+
+ i = s * 2;
+ i = 2 * u;
+
+ i = c * 500;
+ i = 500 * c;
+ i = i * 500;
+ i = 500 * i;
+
+ i = s * 500;
+ i = 500 * u;
+
+ i = c * c;
+ i = c * c++;
+ i = c++ * c;
+ i = c * cfn();
+ i = cfn() * c;
+ i = *pc * c++;
+ i = c++ * *pc;
+ i = **ppc * c++;
+ i = c++ * **ppc;
+
+ i = c % 0;
+ i = 0 % c;
+ i = i % 0;
+ i = 0 % i;
+
+ i = s % 0;
+ i = 0 % u;
+
+ i = c % 1;
+ i = 1 % c;
+ i = i % 1;
+ i = 1 % i;
+
+ i = s % 1;
+ i = 1 % u;
+
+ i = c % 2;
+ i = 2 % c;
+ i = i % 2;
+ i = 2 % i;
+
+ i = s % 2;
+ i = 2 % u;
+
+ i = c % 500;
+ i = 500 % c;
+ i = i % 500;
+ i = 500 % i;
+
+ i = s % 500;
+ i = 500 % u;
+
+ i = c << 0;
+ i = 0 << c;
+ i = i << 0;
+ i = 0 << i;
+
+ i = s << 0;
+ i = 0 << u;
+
+ i = c << 1;
+ i = 1 << c;
+ i = i << 1;
+ i = 1 << i;
+
+ i = s << 1;
+ i = 1 << u;
+
+ i = c << 8;
+ i = 8 << c;
+ i = i << 8;
+ i = 8 << i;
+
+ i = s << 8;
+ i = 8 << u;
+
+ i = c << 9;
+ i = 9 << c;
+ i = i << 9;
+ i = 9 << i;
+
+ i = s << 9;
+ i = 9 << u;
+
+ i = c >> 0;
+ i = 0 >> c;
+ i = i >> 0;
+ i = 0 >> i;
+
+ i = s >> 0;
+ i = 0 >> u;
+
+ i = c >> 1;
+ i = 1 >> c;
+ i = i >> 1;
+ i = 1 >> i;
+
+ i = s >> 1;
+ i = 1 >> u;
+
+ i = c >> 8;
+ i = 8 >> c;
+ i = i >> 8;
+ i = 8 >> i;
+
+ i = s >> 8;
+ i = 8 >> u;
+
+ i = c >> 9;
+ i = 9 >> c;
+ i = i >> 9;
+ i = 9 >> i;
+
+ i = s >> 9;
+ i = 9 >> u;
+}
diff --git a/bcc/misc/test/puzzle.t b/bcc/misc/test/puzzle.t
new file mode 100644
index 0000000..9d2c4ab
--- /dev/null
+++ b/bcc/misc/test/puzzle.t
@@ -0,0 +1,178 @@
+/* puzzle.t - from C puzzle book */
+
+#define puzzle(which) ( puts( "-----which-----\n" ), which() )
+
+main()
+{
+ puzzle( op1 );
+ puzzle( op2 );
+ puzzle( op3 );
+ puzzle( op4 );
+ puzzle( op5 );
+ puzzle( op6 );
+ puzzle( prep1 );
+ puzzle( prep2 );
+}
+
+op1()
+{
+ int x;
+
+ x = - 3 + 4 * 5 - 6; printf("%d\n",x);
+ x = 3 + 4 % 5 - 6; printf("%d\n",x);
+ x = - 3 * 4 % - 6 / 5; printf("%d\n",x);
+ x = ( 7 + 6 ) % 5 /2; printf("%d\n",x);
+}
+
+#define PRINTX printf( "%d\n", x )
+
+op2()
+{
+ int x, y, z;
+
+ x = 2;
+ x *= 3 + 2; PRINTX;
+ x *= y = z = 4; PRINTX;
+ x = y == z; PRINTX;
+ x == (y == z); PRINTX;
+}
+
+#define PRINT(int) printf( "int = %d\n", int )
+
+op3()
+{
+ int x, y, z;
+
+ x = 2; y = 1; z = 0;
+ x = x && y || z; PRINT(x);
+ PRINT( x || ! y && z );
+
+ x = y = 1;
+ z = x ++ - 1; PRINT(x); PRINT(z);
+ z += - x ++ + ++ y;PRINT(x);PRINT(z);
+ z = x / ++ x; PRINT(z);
+}
+
+op4()
+{
+ int x, y, z;
+
+ x = 03; y = 02; z = 01;
+ PRINT( x | y & z );
+ PRINT( x | y & ~ z );
+ PRINT( x ^ y & ~ z );
+ PRINT( x & y && z );
+
+ x = 1; y = -1;
+ PRINT( ! x | x );
+ PRINT( ~ x | x );
+ PRINT( x ^ x );
+ x <<= 3; PRINT(x);
+ y <<= 3; PRINT(y);
+ y >>= 3; PRINT(y);
+}
+
+op5()
+{
+ int x, y, z;
+
+ x = 1; y = 1; z = 1;
+
+ x += y += z;
+ PRINT( x < y ? y : x );
+
+ PRINT( x < y ? x ++ : y ++ );
+ PRINT(x); PRINT(y);
+
+ PRINT( z += x < y ? x ++ : y ++ );
+ PRINT(y); PRINT(z);
+
+ x = 3; y=z=4;
+ PRINT( (z >= y >= x) ? 1 : 0 );
+ PRINT( z >= y && y >= x );
+}
+
+#define PRINT3(x,y,z) printf("x=%d\ty=%d\tz=%d\n",x,y,z)
+
+op6()
+{
+ int x, y, z;
+
+ x = y = z = 1;
+ ++x || ++y && ++z; PRINT3(x,y,z);
+
+ x = y = z = 1;
+ ++x && ++y || ++z; PRINT3(x,y,z);
+
+ x = y = z = 1;
+ ++x && ++y && ++z; PRINT3(x,y,z);
+
+ x = y = z = -1;
+ ++x && ++y || ++z; PRINT3(x,y,z);
+
+ x = y = z = -1;
+ ++x || ++y && ++z; PRINT3(x,y,z);
+
+ x = y = z = -1;
+ ++x && ++y && ++z; PRINT3(x,y,z);
+}
+
+#define FUDGE(k) k+3
+#define PR(a) printf("a= %d\t",(int)(a))
+#define PRINTNEW(a) PR(a); putchar( '\n' );
+#define PRINT2(a,b) PR(a); PRINT(b)
+#define PRINT3NEW(a,b,c) PR(a); PRINT2(b,c)
+#define MAX(a,b) (a<b ? b : a )
+
+prep1()
+{
+ {
+ int x;
+ x = 2;
+ PRINTNEW( x*FUDGE(2) );
+ }
+ {
+ int cel;
+ for( cel=0; cel<=100; cel+=50 )
+ PRINT2( cel, 9/5*cel+32 );
+ }
+ {
+ int x, y;
+ x=1; y=2;
+ PRINT3NEW( MAX(x++,y),x,y );
+ PRINT3NEW( MAX(x++,y),x,y );
+ }
+}
+
+#define NEG(a)-a
+#define weeks(mins) (days(mins)/7)
+#define days(mins) (hours(mins)/24)
+#define hours(mins) (mins/60)
+#define mins(secs) (secs/60)
+#define TAB(c,i,oi,tx) if(c=='\t')\
+ for(tx=8-(i-oi-1)%8,oi=i; tx; tx--)\
+ putchar(' ')
+
+static char *input = "\twhich\tif?";
+
+prep2()
+{
+ {
+ int x;
+ x=1;
+ PRINT( -NEG(x) );
+ }
+ {
+ PRINT( weeks(10080) );
+ PRINT( days(mins(86400)) );
+ }
+ {
+ char c;
+ int i, oldi, temp;
+
+ for( oldi= -1,i=0; (c=input[i])!='\0'; i++ )
+ if( c<' ' ) TAB(c,i,oldi,temp);
+ else putchar(c);
+ putchar('\n');
+ }
+}
diff --git a/bcc/misc/test/sierpin.t b/bcc/misc/test/sierpin.t
new file mode 100644
index 0000000..79016f7
--- /dev/null
+++ b/bcc/misc/test/sierpin.t
@@ -0,0 +1,123 @@
+/* sierpin.t */
+
+#define PPIFBUF 0xf010 /* address of ptr to IFBUF */
+#define PSET 2 /* use this plot option */
+
+struct IFBUF
+{
+ char ERR;
+ char COMMAND;
+ char COLOR;
+ char PLOTOPTION;
+ int LINESTYLE;
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char BFFLAG;
+};
+
+#define H0 512 /* square size */
+#define XOFFS 80 /* offset to centre square */
+#define XNUM 15 /* scale 512 * 15/16 = 480 */
+#define XDENOM 16
+#define YNUM 25 /* scale 512 * 25/64 = 200 */
+#define YDENOM 64 /* to give max height, dot ratio 480/200 = 2.4 */
+
+struct IFBUF *pifbuf;
+int h, x, y;
+
+main()
+{
+ struct IFBUF **ppifbuf; /* required since no casts */
+ int i, x0, y0;
+ char color;
+
+ pifbuf = *(ppifbuf = PPIFBUF); /* pifbuf = *(struct IFBUF **)PPIFBUF; */
+ pifbuf->PLOTOPTION = PSET;
+ pifbuf->LINESTYLE = /* normal */
+ pifbuf->COMMAND = /* ?? */
+ pifbuf->BFFLAG = 0; /* not a box */
+ color = i = 0;
+ x0 = 2 * (h = H0/4);
+ y0 = 3 * (H0/4);
+ while ( h > 1 )
+ {
+ ++i;
+ if ( ++color > 7 )
+ color = 1;
+ pifbuf->COLOR = color;
+ x = x0 -= h;
+ y = y0 += h /= 2;
+ glocate();
+ a( i ); x += h; y -= h; plot();
+ b( i ); x -= h; y -= h; plot();
+ c( i ); x -= h; y += h; plot();
+ d( i ); x += h; y += h; plot();
+ }
+}
+
+a( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ a( i ); x += h; y -=h; plot();
+ b( i ); x += 2*h; plot();
+ d( i ); x += h; y += h; plot();
+ a( i );
+ }
+}
+
+b( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ b( i ); x -= h; y -=h; plot();
+ c( i ); y -= 2*h; plot();
+ a( i ); x += h; y -= h; plot();
+ b( i );
+ }
+}
+
+c( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ c( i ); x -= h; y +=h; plot();
+ d( i ); x -= 2*h; plot();
+ b( i ); x -= h; y -= h; plot();
+ c( i );
+ }
+}
+
+d( i )
+int i;
+{
+ if ( --i >= 0 )
+ {
+ d( i ); x += h; y +=h; plot();
+ a( i ); y += 2*h; plot();
+ c( i ); x -= h; y += h; plot();
+ d( i );
+ }
+}
+
+glocate()
+{
+ pifbuf->X2 = x - x * (XDENOM - XNUM) / XDENOM + XOFFS;
+ pifbuf->Y2 = (y * YNUM) / YDENOM;
+}
+
+plot()
+{
+ pifbuf->X1 = pifbuf->X2;
+ pifbuf->Y1 = pifbuf->Y2;
+ glocate();
+#asm
+ SWI2
+ FDB $4201 call LINEMA
+#endasm
+}
diff --git a/bcc/misc/test/sievec.t b/bcc/misc/test/sievec.t
new file mode 100644
index 0000000..1b51fdb
--- /dev/null
+++ b/bcc/misc/test/sievec.t
@@ -0,0 +1,28 @@
+#define TRUE 1
+#define FALSE 0
+#define SIZE 8190
+
+char flags[SIZE+1];
+
+main()
+{
+ int i,prime,k,count,iter;
+
+ for (iter=0;iter<10;iter++)
+ {
+ count=0;
+ for (i=0;i<=SIZE;i++)
+ flags[i]=TRUE;
+ for (i=0;i<=SIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ for (k=i+prime;k<=SIZE;k=k+prime)
+ flags[k]=FALSE;
+ count++;
+ }
+ }
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc/misc/test/sievecp.t b/bcc/misc/test/sievecp.t
new file mode 100644
index 0000000..185b031
--- /dev/null
+++ b/bcc/misc/test/sievecp.t
@@ -0,0 +1,45 @@
+/* sieve using pointers */
+
+#define TRUE 1
+#define FALSE 0
+#define NITER 100
+#define SIZE 8191 /* last prime <= 2*this+3 */
+#define SQRSIZE 63 /* last divisor tested = 2*this+3 */
+
+char flags[SIZE+2*SQRSIZE+3]; /* avoid ptr+=prime overflowing */
+
+main()
+{
+ int i,count,iter;
+ register char *ptr;
+ char *endptr;
+ int prime;
+
+ for (iter=0;iter<NITER;iter++)
+ {
+ count=0;
+ ptr=flags;
+ endptr=flags+SIZE;
+ while (ptr<endptr)
+ *ptr++=TRUE;
+ for (i=0;i<SQRSIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ ptr=flags+i+prime; /* ptr<endptr since i<SQRSIZE */
+ while (ptr<endptr)
+ {
+ *ptr=FALSE;
+ ptr+=prime; /* does not overflow since in flags */
+ }
+ count++;
+ }
+ }
+ ptr=flags+SQRSIZE;
+ while (ptr<endptr)
+ if (*ptr++)
+ count++;
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc/misc/test/sievei.t b/bcc/misc/test/sievei.t
new file mode 100644
index 0000000..d4910dc
--- /dev/null
+++ b/bcc/misc/test/sievei.t
@@ -0,0 +1,28 @@
+#define TRUE 1
+#define FALSE 0
+#define SIZE 8190
+
+int flags[SIZE+1];
+
+main()
+{
+ int i,prime,k,count,iter;
+
+ for (iter=0;iter<10;iter++)
+ {
+ count=0;
+ for (i=0;i<=SIZE;i++)
+ flags[i]=TRUE;
+ for (i=0;i<=SIZE;i++)
+ {
+ if (flags[i])
+ {
+ prime=i+i+3;
+ for (k=i+prime;k<=SIZE;k=k+prime)
+ flags[k]=FALSE;
+ count++;
+ }
+ }
+ }
+ printf( "%d primes\n", count );
+}
diff --git a/bcc/misc/test/sort.t b/bcc/misc/test/sort.t
new file mode 100644
index 0000000..34bcb9e
--- /dev/null
+++ b/bcc/misc/test/sort.t
@@ -0,0 +1,104 @@
+unsigned t[10000];
+unsigned s[10000];
+unsigned size,repet;
+unsigned comp=0,swap=0; /* s.b. long */
+
+main(argc)
+{
+ int i,zz;
+
+/*
+ printf("size?");
+ scanf("%d",&size);
+ printf("repet?");
+ scanf("%d",&repet);
+*/
+ if ( argc > 20 )
+ {
+ printf( "usage: sort [args], where 500*argc is the array size\n" );
+ exit( 1 );
+ }
+ size = 500 * argc;
+ repet = 1;
+ for (i = 0; i < size; i++)
+ s[i] = size-i;
+ printf("\npress key to begin shell sorting\n");
+ getchar();
+ for (zz=0;zz<repet;zz++)
+ {
+ comp=swap=0;
+ for (i=0;i<size;i++)
+ t[i]=s[i];
+ sort();
+ }
+ printf("\nsorted\n");
+ printf("\ncompares = %d, swaps = %d\n",comp,swap);
+ printf("\npress key to begin quick sorting\n");
+ getchar();
+ for (zz=0;zz<repet;zz++)
+ {
+ comp=swap=0;
+ for (i=0;i<size;i++)
+ t[i]=s[i];
+ qqsort();
+ }
+ printf("\nsorted\n");
+ printf("\ncompares = %d, swaps = %d\n",comp,swap);
+}
+
+sort()
+{
+ int i,j,h,temp;
+
+ h=1;
+ while (9*h+4<size)
+ h=3*h+1;
+ while (h>0)
+ {
+ for (j=h; j<size; j++)
+ for (i=j-h; i>=0; i-=h)
+ {
+ ++comp;
+ if (t[i]<=t[i+h])
+ break;
+ ++swap;
+ temp=t[i];
+ t[i]=t[i+h];
+ t[i+h]=temp;
+ }
+ h=(h-1)/3;
+ }
+}
+
+qqsort()
+{
+ qsort(0,size-1);
+}
+
+qsort(l,r)
+int l,r;
+{
+ int i,j;
+ unsigned x,w;
+
+ i=l;j=r;
+ x=t[(l+r)>>1];
+ do
+ {
+ while (t[i] < x)
+ {
+ ++comp;
+ i++;
+ }
+ while (x < t[j]) {--j;}
+ if (i<=j)
+ {
+ ++swap;
+ w=t[i];t[i]=t[j];t[j]=w;
+ i++;j--;
+ }
+ }
+ while (i<=j);
+ if (l<j) qsort(l,j);
+ if (i<r) qsort(i,r);
+}
diff --git a/bcc/misc/test/stdio.t b/bcc/misc/test/stdio.t
new file mode 100644
index 0000000..e7e174d
--- /dev/null
+++ b/bcc/misc/test/stdio.t
@@ -0,0 +1,87 @@
+/* stdio.h */
+
+#asm
+
+#define BUFSIZ 512
+#define _NFILE 20
+
+#define _IOREAD 1
+#define _IOWRITE 2
+#define _IODIRTY 4
+#define _IOEOF 8
+#define _IOERR 16
+#define _IOMYBUF 32 /* says if stream routines allocated buffer */
+#define _IOUNBUF 64
+
+#define EOF (-1)
+#define NULL 0
+
+#endasm
+
+#define stdin (&_iob[0])
+#define stdout (&_iob[1])
+#define stderr (&_iob[2])
+
+#define FILE struct _iobuf
+
+struct _iobuf
+{
+ char *_ptr;
+ char *_base;
+ char *_rtop;
+ char *_wtop;
+ char _flags;
+ char _fd;
+}
+ _iob[_NFILE];
+
+#define clearerr(fp) ((fp)->flags&=~_IOERR)
+#define getchar() getc(stdin)
+#define feof(fp) ((fp)->_flags&_IOEOF)
+#define ferror(fp) ((fp)->_flags&_IOERR)
+#define fileno(fp) ((fp)->_fd)
+#define putchar(c) putc((c),stdout)
+
+#define void int
+
+FILE *fdopen();
+char *fgets();
+FILE *fopen();
+FILE *freopen();
+long ftell();
+
+long lseek();
+unsigned read();
+unsigned write();
+
+char *malloc();
+char *realloc();
+char *sbrk();
+
+char *index();
+char *rindex();
+char *strcat();
+char *strcpy();
+char *strncat();
+char *strncpy();
+
+#asm
+
+BLANK EQU 32
+COEOL EQU 10
+EOL EQU 13
+MAXCONTROL EQU 31
+
+* struct _iobuf translated into offsets
+
+ BLOCK 0
+PTR RMB 2
+BASE RMB 2
+RTOP RMB 2
+WTOP RMB 2
+FLAGS RMB 1
+FD RMB 1
+IOB.SIZE
+ ENDB
+
+#endasm
diff --git a/bcc/os.h b/bcc/os.h
new file mode 100644
index 0000000..71dfcef
--- /dev/null
+++ b/bcc/os.h
@@ -0,0 +1,78 @@
+/* os.h - source/target operating system dependencies for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ must have unix-near-compatible creat, open, read, write and close
+
+ source O/S's supported:
+ default:
+ *IX
+ special:
+ EDOS (#define SOS_EDOS if required)
+ MSDOS (#define SOS_MSDOS)
+ target O/S's supported:
+ default:
+ *IX
+ MSDOS
+ special:
+ EDOS (#define TOS_EDOS)
+*/
+
+/* defaults */
+
+#define CREATPERMS 0666 /* permissions for creat */
+#define EOL 10 /* source newline */
+#define EOLTO 10 /* target newline */
+#define DIRCHAR '/'
+#define DIRSTRING "/"
+#define isabspath(fnameptr, tempcptr) \
+ ((*(tempcptr) = *(fnameptr)) == DIRCHAR)
+
+/* special */
+
+#ifdef SOS_EDOS
+# undef DEFAULT_INCLUDE_DIR
+# define DEFAULT_INCLUDE_DIR "3"
+# undef DIRCHAR
+# define DIRCHAR ':'
+# undef DIRSTRING
+# define DIRSTRING ":"
+# define AS09
+# undef EOL
+# define EOL 13
+# undef isabspath
+# define isabspath(fnameptr, tempcptr) \
+ ((*(tempcptr) = *(fnameptr)) >= '0' && *(tempcptr) <= '9' && \
+ (fnameptr)[1] == DIRCHAR)
+#endif
+
+#ifdef SOS_MSDOS
+# define COEOL 10
+# undef DEFAULT_INCLUDE_DIR
+# define DEFAULT_INCLUDE_DIR "\\usr\\include"
+# undef DIRCHAR
+# define DIRCHAR '\\'
+# undef DIRSTRING
+# define DIRSTRING "\\"
+# undef EOL
+# define EOL 13
+/*
+ Problems with newline on MSDOS (as usual).
+ Defining EOL as 10 (LF) handles LF-terminated lines as well as
+ CRLF-terminated lines, but escaped CRLF's do not work. The compiler
+ should handle the escapes better. (Perhaps it does now.)
+ Defining EOL as 13 (CR) handles CRLF-terminated lines but fails on
+ LF-terminated lines.
+*/
+#endif
+
+#ifdef TOS_EDOS
+# undef EOLTO
+# define EOLTO 13
+#endif
+
+/* don't let names dealt with here affect anything outside this file */
+
+#undef SOS_EDOS
+#undef SOS_MSDOS
diff --git a/bcc/output.c b/bcc/output.c
new file mode 100644
index 0000000..c44ea3f
--- /dev/null
+++ b/bcc/output.c
@@ -0,0 +1,813 @@
+/* output.c - output and error handling for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "input.h"
+#include "os.h"
+#include "sizes.h"
+#include "table.h"
+
+#undef EXTERN
+#define EXTERN
+#include "output.h"
+
+#ifdef XENIX_AS
+# define HEXSTARTCHAR '/'
+#else
+# define HEXSTARTCHAR '$'
+#endif
+#define OUTBUFSIZE 2048
+#define opcodeleadin() /* outtab() for fussy assemblers */
+
+PRIVATE unsigned errcount; /* # errors in compilation */
+ /* depends on zero init */
+PRIVATE char hexdigits[] = "0123456789ABCDEF";
+PRIVATE char *outbuf;
+EXTERN char *outbufend; /* end of pair of output buffers */
+PRIVATE char *outbufmid;
+PRIVATE fd_t output;
+PRIVATE fastin_t outstage; /* depends on zero init */
+
+FORWARD void errorsummary P((void));
+FORWARD void errsum1 P((void));
+#ifdef MC6809
+#ifdef DEBUG
+FORWARD void outvaldigs P((uvalue_t num));
+#endif
+#endif
+
+PUBLIC void bugerror(message)
+char *message;
+{
+ error2error("compiler bug - ", message);
+}
+
+PUBLIC void closeout()
+{
+ char *saveoutptr;
+
+ if (outstage == 3)
+ {
+ saveoutptr = outbufptr;
+ flushout(); /* buffer from last stage */
+ outbufptr = saveoutptr;
+ }
+ outstage = 0; /* flush from top to current ptr */
+ flushout();
+ close(output);
+}
+
+/* error handler */
+
+PUBLIC void error(message)
+char *message;
+{
+ error2error(message, "");
+}
+
+/* error handler - concatenate 2 messages */
+
+PUBLIC void error2error(message1, message2)
+char *message1;
+char *message2;
+{
+ char *warning;
+
+ if (message1[0] == '%' && message1[1] == 'w')
+ {
+ message1 += 2;
+ warning = "warning: ";
+ }
+ else
+ {
+ ++errcount;
+ warning = "error: ";
+ }
+ if (output != 1)
+ {
+ char *old_outbuf;
+ char *old_outbufptr;
+ char *old_outbuftop;
+ fd_t old_output;
+ fastin_t old_outstage;
+ char smallbuf[81]; /* don't use heap - might be full or busy */
+
+ old_outbuf = outbuf;
+ old_outbufptr = outbufptr;
+ old_outbuftop = outbuftop;
+ old_output = output;
+ old_outstage = outstage;
+
+ outbufptr = outbuf = &smallbuf[0];
+ outbuftop = &smallbuf[sizeof smallbuf];
+ output = 1;
+ outstage = 0;
+ errorloc();
+ outstr(warning);
+ outstr(message1);
+ outstr(message2);
+ outnl();
+ flushout();
+
+ outbuf = old_outbuf;
+ outbufptr = old_outbufptr;
+ outbuftop = old_outbuftop;
+ output = old_output;
+ outstage = old_outstage;
+ }
+ comment();
+ errorloc();
+ outstr(warning);
+ outstr(message1);
+ outstr(message2);
+ outnl();
+}
+
+/* summarise errors */
+
+PRIVATE void errorsummary()
+{
+ if (errcount != 0)
+ {
+ outfail();
+ errsum1();
+ }
+ outnl();
+ comment();
+ errsum1();
+}
+
+PRIVATE void errsum1()
+{
+ outudec(errcount);
+ outnstr(" errors detected");
+}
+
+/* fatal error, exit early */
+
+PUBLIC void fatalerror(message)
+char *message;
+{
+ error(message);
+ finishup();
+}
+
+/* finish up compile */
+
+PUBLIC void finishup()
+{
+ if (!cppmode)
+ {
+ if (watchlc)
+ {
+ cseg();
+ outop0str("if *-.program.start-");
+ outnhex(getlc());
+ outfail();
+ outnstr("phase error");
+ outop0str("endif\n");
+ }
+#ifdef HOLDSTRINGS
+ dumpstrings();
+#endif
+ dumpglbs();
+ errorsummary();
+ }
+ closein();
+ closeout();
+ exit(errcount == 0 ? 0 : 1);
+}
+
+/* flush output file */
+
+PUBLIC void flushout()
+{
+ unsigned nbytes;
+
+ switch (outstage)
+ {
+ case 0:
+ nbytes = (unsigned) (outbufptr - outbuf);
+ outbufptr = outbuf;
+ break;
+ case 2:
+ nbytes = OUTBUFSIZE;
+ outbufptr = outbuf;
+ outbuftop = outbufmid;
+ outstage = 3;
+ break;
+ default:
+ nbytes = OUTBUFSIZE;
+ if (outstage == 1)
+ nbytes = 0;
+ outbufptr = outbufmid;
+ outbuftop = outbufend;
+ outstage = 2;
+ break;
+ }
+ if (nbytes != 0)
+ {
+ if (!orig_cppmode)
+ clearlabels(outbufptr, outbufptr + nbytes);
+ if (write(output, outbufptr, nbytes) != nbytes)
+ {
+ write(2, "output file error\n", 18);
+ closein();
+ close(output);
+ exit(1);
+ }
+ }
+}
+
+PUBLIC void initout()
+{
+ static char smallbuf[1];
+
+ outbufend = outbuftop = (outbuf = outbufptr = smallbuf) + sizeof smallbuf;
+ output = 1; /* standard output */
+}
+
+PUBLIC void limiterror(message)
+char *message;
+{
+ error2error("compiler limit exceeded - ", message);
+ finishup();
+}
+
+PUBLIC void openout(oname)
+char *oname;
+{
+ if (output != 1)
+ fatalerror("more than one output file");
+ if ((output = creat(oname, CREATPERMS)) < 0)
+ {
+ output = 1;
+ fatalerror("cannot open output");
+ }
+}
+
+/* print character */
+
+PUBLIC void outbyte(c)
+int c;
+{
+#if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1
+ register char *outp;
+
+ outp = outbufptr;
+ *outp++ = c;
+ outbufptr = outp;
+ if (outp >= outbuftop)
+ flushout();
+#else /* !C_CODE etc */
+
+#if __AS09__
+# asm
+ TFR X,D
+ LDX _outbufptr,PC
+ STB ,X+
+ STX _outbufptr,PC
+ CMPX _outbuftop,PC
+ LBHS CALL.FLUSHOUT
+# endasm
+#endif /* __AS09__ */
+
+#if __AS386_16__
+# asm
+# if !__FIRST_ARG_IN_AX__
+ pop dx
+ pop ax
+ dec sp
+ dec sp
+# else
+# if ARGREG != DREG
+ xchg ax,bx
+# endif
+# endif
+ mov bx,[_outbufptr]
+ mov [bx],al
+ inc bx
+ mov [_outbufptr],bx
+ cmp bx,[_outbuftop]
+ jae OUTBYTE.FLUSH
+# if !__FIRST_ARG_IN_AX__
+ jmp dx
+# else
+ ret
+# endif
+
+OUTBYTE.FLUSH:
+# if !__FIRST_ARG_IN_AX__
+ push dx
+# endif
+ br _flushout
+# endasm
+#endif /* __AS386_16__ */
+
+#if __AS386_32__
+# asm
+# if !__FIRST_ARG_IN_AX__
+ mov eax,_outbyte.c[esp]
+# else
+# if ARGREG != DREG
+ xchg eax,ebx
+# endif
+# endif
+ mov ecx,[_outbufptr]
+ mov [ecx],al
+ inc ecx
+ mov [_outbufptr],ecx
+ cmp ecx,[_outbuftop]
+ jae OUTBYTE.FLUSH
+ ret
+
+OUTBYTE.FLUSH:
+ br _flushout
+# endasm
+#endif /* __AS386_32__ */
+#endif /* C_CODE etc */
+}
+
+/* print comma */
+
+PUBLIC void outcomma()
+{
+ outbyte(',');
+}
+
+/* print line number in format ("# %u \"%s\"%s", nr, fname, str) */
+
+PUBLIC void outcpplinenumber(nr, fname, str)
+unsigned nr;
+char *fname;
+char *str;
+{
+ outstr("# ");
+ outudec(nr);
+ outstr(" \"");
+ outstr(fname);
+ outstr("\"");
+ outnstr(str);
+}
+
+/* print unsigned offset, hex format */
+
+PUBLIC void outhex(num)
+uoffset_t num;
+{
+#ifdef HEXSTARTCHAR
+ if (num >= 10)
+ outbyte(HEXSTARTCHAR);
+#endif
+ outhexdigs(num);
+#ifdef HEXENDCHAR
+ if (num >= 10)
+ outbyte(HEXENDCHAR);
+#endif
+}
+
+/* print unsigned offset, hex format with digits only (no hex designator) */
+
+PUBLIC void outhexdigs(num)
+register uoffset_t num;
+{
+ if (num >= 0x10)
+ {
+ outhexdigs(num / 0x10);
+ num %= 0x10;
+ }
+ outbyte(hexdigits[(int) num]);
+}
+
+/* print string terminated by EOL */
+
+PUBLIC void outline(s)
+char *s;
+{
+ register char *outp;
+ register char *rs;
+
+ outp = outbufptr;
+ rs = s;
+#ifdef COEOL
+ if (*rs == COEOL)
+ ++rs;
+#endif
+ do
+ {
+ *outp++ = *rs;
+ if (outp >= outbuftop)
+ {
+ outbufptr = outp;
+ flushout();
+ outp = outbufptr;
+ }
+ }
+ while (*rs++ != EOL);
+ outbufptr = outp;
+#ifdef COEOL
+ if (*rs == COEOL)
+ outbyte(COEOL);
+#endif
+}
+
+/* print minus sign */
+
+PUBLIC void outminus()
+{
+ outbyte('-');
+}
+
+/* print character, then newline */
+
+PUBLIC void outnbyte(byte)
+int byte;
+{
+ outbyte(byte);
+ outnl();
+}
+
+/* print unsigned offset, hex format, then newline */
+
+PUBLIC void outnhex(num)
+uoffset_t num;
+{
+ outhex(num);
+ outnl();
+}
+
+/* print newline */
+
+PUBLIC void outnl()
+{
+ if (watchlc)
+ {
+ outtab();
+ comment();
+ outhex(getlc());
+ }
+ outbyte('\n');
+}
+
+/* print opcode and newline, bump lc by 1 */
+
+PUBLIC void outnop1str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc();
+ outnl();
+}
+
+/* print opcode and newline, bump lc by 2 */
+
+PUBLIC void outnop2str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc2();
+ outnl();
+}
+
+/* print string, then newline */
+
+PUBLIC void outnstr(s)
+char *s;
+{
+ outstr(s);
+ outnl();
+}
+
+/* print opcode */
+
+PUBLIC void outop0str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+}
+
+/* print opcode, bump lc by 1 */
+
+PUBLIC void outop1str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc();
+}
+
+/* print opcode, bump lc by 2 */
+
+PUBLIC void outop2str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc2();
+}
+
+/* print opcode, bump lc by 3 */
+
+PUBLIC void outop3str(s)
+char *s;
+{
+ opcodeleadin();
+ outstr(s);
+ bumplc3();
+}
+
+/* print plus sign */
+
+PUBLIC void outplus()
+{
+ outbyte('+');
+}
+
+/* print signed offset, hex format */
+
+PUBLIC void outshex(num)
+offset_t num;
+{
+ if (num >= -(maxoffsetto + 1))
+ {
+ outminus();
+ num = -num;
+ }
+ outhex((uoffset_t) num);
+}
+
+/* print string */
+
+PUBLIC void outstr(s)
+char *s;
+{
+#if C_CODE || __AS09__ + __AS386_16__ + __AS386_32__ != 1
+ register char *outp;
+ register char *rs;
+
+ outp = outbufptr;
+ rs = s;
+ while (*rs)
+ {
+ *outp++ = *rs++;
+ if (outp >= outbuftop)
+ {
+ outbufptr = outp;
+ flushout();
+ outp = outbufptr;
+ }
+ }
+ outbufptr = outp;
+#else /* !C_CODE etc */
+
+#if __AS09__
+# asm
+ LEAU ,X
+ LDX _outbuftop,PC
+ PSHS X
+ LDX _outbufptr,PC
+ BRA OUTSTR.NEXT
+
+CALL.FLUSHOUT
+ PSHS U,B
+ STX _outbufptr,PC
+ LBSR _flushout
+ LDX _outbufptr,PC
+ LDY _outbuftop,PC
+ PULS B,U,PC
+
+OUTSTR.LOOP
+ STB ,X+
+ CMPX ,S
+ BLO OUTSTR.NEXT
+ BSR CALL.FLUSHOUT
+ STY ,S
+OUTSTR.NEXT
+ LDB ,U+
+ BNE OUTSTR.LOOP
+ STX _outbufptr,PC
+ LEAS 2,S
+# endasm
+#endif /* __AS09__ */
+
+#if __AS386_16__
+# asm
+# if !__CALLER_SAVES__
+ mov dx,di
+ mov cx,si
+# endif
+# if !__FIRST_ARG_IN_AX__
+ pop ax
+ pop si
+ dec sp
+ dec sp
+ push ax
+# else
+# if ARGREG == DREG
+ xchg si,ax
+# else
+ mov si,bx
+# endif
+# endif
+ mov di,[_outbufptr]
+ mov bx,[_outbuftop]
+ br OUTSTR.NEXT
+
+CALL.FLUSHOUT:
+ push si
+# if !__CALLER_SAVES__
+ push dx
+ push cx
+# endif
+ push ax
+ mov [_outbufptr],di
+ call _flushout
+ mov di,[_outbufptr]
+ mov bx,[_outbuftop]
+ pop ax
+# if !__CALLER_SAVES__
+ pop cx
+ pop dx
+#endif
+ pop si
+ ret
+
+OUTSTR.LOOP:
+ stosb
+ cmp di,bx
+ jb OUTSTR.NEXT
+ call CALL.FLUSHOUT
+OUTSTR.NEXT:
+ lodsb
+ test al,al
+ jne OUTSTR.LOOP
+ mov [_outbufptr],di
+# if !__CALLER_SAVES__
+ mov si,cx
+ mov di,dx
+# endif
+# endasm
+#endif /* __AS386_16__ */
+
+#if __AS386_32__
+# asm
+# if !__CALLER_SAVES__
+ mov edx,edi
+ push esi
+# define TEMPS 4
+# else
+# define TEMPS 0
+# endif
+# if !__FIRST_ARG_IN_AX__
+ mov esi,TEMPS+_outstr.s[esp]
+# else
+# if ARGREG == DREG
+ xchg esi,eax
+# else
+ mov esi,ebx
+# endif
+# endif
+ mov edi,[_outbufptr]
+ mov ecx,[_outbuftop]
+ br OUTSTR.NEXT
+
+CALL.FLUSHOUT:
+ push esi
+# if !__CALLER_SAVES__
+ push edx
+# endif
+ push eax
+ mov [_outbufptr],edi
+ call _flushout
+ mov edi,[_outbufptr]
+ mov ecx,[_outbuftop]
+ pop eax
+# if !__CALLER_SAVES__
+ pop edx
+# endif
+ pop esi
+ ret
+
+OUTSTR.LOOP:
+ stosb
+ cmp edi,ecx
+ jb OUTSTR.NEXT
+ call CALL.FLUSHOUT
+OUTSTR.NEXT:
+ lodsb
+ test al,al
+ jne OUTSTR.LOOP
+ mov [_outbufptr],edi
+# if !__CALLER_SAVES__
+ pop esi
+ mov edi,edx
+# endif
+# endasm
+#endif /* __AS386_32__ */
+#endif /* C_CODE etc */
+}
+
+/* print tab */
+
+PUBLIC void outtab()
+{
+ outbyte('\t');
+}
+
+/* print unsigned, decimal format */
+
+PUBLIC void outudec(num)
+unsigned num;
+{
+ char str[10 + 1];
+
+ str[sizeof str - 1] = 0;
+ outstr(pushudec(str + sizeof str - 1, num));
+}
+
+#ifdef MC6809
+#ifdef DEBUG
+
+/* print unsigned value, hex format (like outhex except value_t is larger) */
+
+PUBLIC void outuvalue(num)
+uvalue_t num;
+{
+#ifdef HEXSTARTCHAR
+ if (num >= 10)
+ outbyte(HEXSTARTCHAR);
+#endif
+ outvaldigs(num);
+#ifdef HEXENDCHAR
+ if (num >= 10)
+ outbyte(HEXENDCHAR);
+#endif
+}
+
+/* print unsigned value, hex format with digits only (no hex designator) */
+
+PRIVATE void outvaldigs(num)
+register uvalue_t num;
+{
+ if (num >= 0x10)
+ {
+ outvaldigs(num / 0x10);
+ num %= 0x10;
+ }
+ outbyte(hexdigits[(fastin_t) num]);
+}
+
+/* print signed value, hex format (like outshex except value_t is larger) */
+
+PUBLIC void outvalue(num)
+register value_t num;
+{
+ if (num < 0)
+ {
+ outminus();
+ num = -num;
+ }
+ outuvalue((uoffset_t) num);
+}
+
+#endif /* DEBUG */
+#endif /* MC6809 */
+
+/* push decimal digits of an unsigned onto a stack of chars */
+
+PUBLIC char *pushudec(s, num)
+register char *s;
+register unsigned num;
+{
+ register unsigned reduction;
+
+ while (num >= 10)
+ {
+ reduction = num / 10;
+ *--s = num - 10 * reduction + '0';
+ num = reduction;
+ }
+ *--s = num + '0';
+ return s;
+}
+
+PUBLIC void setoutbufs()
+{
+ if (!isatty(output))
+ {
+ outbufptr = outbuf = ourmalloc(2 * OUTBUFSIZE);
+#ifdef TS
+ts_s_outputbuf += 2 * OUTBUFSIZE;
+#endif
+ outbufmid = outbuftop = outbufptr + OUTBUFSIZE;
+ outbufend = outbufmid + OUTBUFSIZE;
+ outstage = 1;
+ }
+ if (watchlc)
+ outnstr(".program.start:\n"); /* kludge temp label */
+}
diff --git a/bcc/output.h b/bcc/output.h
new file mode 100644
index 0000000..6dc9cf1
--- /dev/null
+++ b/bcc/output.h
@@ -0,0 +1,14 @@
+/* output.h - output for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define OUTBYTE(ch) \
+ do {register char *outp = outbufptr; *outp++ = (ch); \
+ outbufptr = outp; if (outp >= outbuftop) flushout(); } while (0)
+
+EXTERN bool_t ctext; /* nonzero to intermix C source */
+ /* depends on zero init */
+EXTERN char *outbufptr; /* current spot in output buffer */
+EXTERN char *outbuftop; /* top of current output buffer */
+EXTERN bool_t watchlc; /* nonzero to print lc after every line */
+ /* depends on zero init */
diff --git a/bcc/parse.h b/bcc/parse.h
new file mode 100644
index 0000000..ab67f6c
--- /dev/null
+++ b/bcc/parse.h
@@ -0,0 +1,19 @@
+/* parse.h - parser for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* possible scope levels */
+
+#define ARGLEVEL 1
+#define GLBLEVEL 0
+#define MAXLEVEL 125
+#define MINLOCLEVEL 1
+
+/* possible node flags */
+
+#define LVALUE (1 << 0)
+
+EXTERN struct nodestruct *etptr; /* ptr to next entry in expression tree */
+EXTERN struct symstruct *gvarsymptr; /* gsymptr for last identifier declared */
+EXTERN scopelev_t level; /* scope level */
+ /* depends on zero init */
diff --git a/bcc/preproc.c b/bcc/preproc.c
new file mode 100644
index 0000000..90f5a8c
--- /dev/null
+++ b/bcc/preproc.c
@@ -0,0 +1,944 @@
+/* preprocessor routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "input.h"
+#include "os.h"
+#include "output.h"
+#include "parse.h"
+#include "sc.h"
+#include "scan.h"
+#include "table.h"
+#include "type.h"
+
+#define MAX_IF 32
+#define MAX__LINE__ 10 /* enough for 32-bit source unsigneds */
+#define MAX_MACRO 32
+#define MAX_PARAM 127 /* max char with no sign on all machines */
+
+/* Definition types. These are kept in the 'storage' member of struct
+ * symstruct and must be distinct from 'LOCAL' because dumplocs() doesn't
+ * check.
+ */
+enum
+{
+ DEF_LINE, /* __LINE__ keyword */
+ DEF_NONE /* nothing special */
+};
+
+struct ifstruct
+{
+ bool_t elseflag;
+ bool_t ifflag;
+};
+
+struct macroposition
+{
+ char *maclineptr;
+ char **paramlist;
+ char *paramspot;
+ bool_t inparam;
+ indn_t nparam;
+};
+
+PRIVATE char dummyparam[] = { EOL, 0 };
+PRIVATE fastin_t iflevel; /* depends on zero init */
+PRIVATE struct ifstruct ifstate;
+ /* elseflag depends on zero init */
+PRIVATE struct ifstruct ifstack[MAX_IF];
+
+PRIVATE struct macroposition macrostack[MAX_MACRO];
+
+FORWARD void asmcontrol P((void));
+FORWARD void control P((void));
+FORWARD void defineorundefinestring P((char *str, bool_pt defineflag));
+FORWARD void elsecontrol P((void));
+FORWARD void endif P((void));
+FORWARD fastin_pt getparnames P((void));
+FORWARD void ifcontrol P((sym_pt ifcase));
+FORWARD void undef P((void));
+
+/* asmcontrol() - process #asm */
+
+PRIVATE void asmcontrol()
+{
+ char treasure; /* to save at least one leading blank */
+
+ asmmode = TRUE;
+ if (orig_cppmode)
+ outstr("#asm\n");
+ else
+ dumplocs();
+ while (TRUE)
+ {
+ skipline();
+ skipeol();
+ if (eof)
+ {
+ eofin("#asm");
+ break;
+ }
+ if (SYMOFCHAR(ch) == SPECIALCHAR)
+ specialchar();
+ treasure = 0;
+ if (SYMOFCHAR(ch) == WHITESPACE)
+ treasure = ch;
+ blanks();
+ if (ch == '#')
+ {
+ if (ctext)
+ {
+ register char *lptr;
+
+ comment();
+ if (treasure != 0)
+ outbyte(treasure);
+ lptr = lineptr;
+ while (*lptr++ != EOL) /* XXX - handle COEOL too */
+ outbyte(ch);
+ outnl();
+ }
+ gch1();
+ docontrol();
+ if (!asmmode)
+ break;
+ }
+ else
+ {
+ if (treasure != 0)
+ outbyte(treasure);
+ while (ch != EOL) /* XXX - handle COEOL too */
+ {
+ outbyte(ch);
+ gch1();
+ }
+ outnl();
+ }
+ }
+ if (orig_cppmode)
+ outstr("#endasm"); /* nl is done by skipeol */
+}
+
+/* blanksident() - return nonzero if at blanks followed by an identifier */
+
+PUBLIC bool_pt blanksident()
+{
+ blanks();
+ return isident();
+}
+
+PUBLIC void checknotinif()
+{
+ while (iflevel != 0)
+ {
+ if (ifstate.ifflag)
+ eofin("true #conditional");
+ else
+ eofin("false #conditional");
+ endif();
+ }
+}
+
+/* control() - select and switch to control statement */
+
+PRIVATE void control()
+{
+ char sname[NAMESIZE + 1];
+ sym_t ctlcase;
+ struct symstruct *symptr;
+
+ sname[0] = '#'; /* prepare for bad control */
+ sname[1] = 0;
+ while (blanksident())
+ {
+ if ((gsymptr = findlorg(gsname)) == NULL ||
+ gsymptr->flags != DEFINITION)
+ {
+ strcat(sname, gsname);
+ break;
+ }
+ entermac();
+ }
+ if (sname[1] == 0 && ch == EOL)
+ return;
+ if (SYMOFCHAR(ch) == INTCONST)
+ { linecontol(); return; }
+ if ((symptr = findlorg(sname)) == NULL)
+ {
+ if (ifstate.ifflag)
+ error(" bad control");
+ return;
+ }
+ ctlcase = symptr->offset.offsym;
+ if (ifstate.ifflag == FALSE &&
+ (ctlcase < ELSECNTL || ctlcase > IFNDEFCNTL))
+ return;
+ switch (ctlcase)
+ {
+ case ASMCNTL:
+ asmcontrol();
+ break;
+ case DEFINECNTL:
+ define();
+ break;
+ case ELSECNTL:
+ elsecontrol();
+ break;
+ case ENDASMCNTL:
+ asmmode = FALSE;
+ break;
+ case ENDIFCNTL:
+ endif();
+ break;
+ case IFCNTL:
+ case IFDEFCNTL:
+ case IFNDEFCNTL:
+ ifcontrol(symptr->offset.offsym);
+ break;
+ case INCLUDECNTL:
+ include();
+ break;
+ case LINECNTL:
+ { linecontol(); break; }
+ case UNDEFCNTL:
+ undef();
+ break;
+ }
+}
+
+/* define() - process #define */
+
+/*
+ MACRO storage.
+ A symbol recording the macro name is added to the symbol table.
+ This overrides all current scopes of the name (put at head of hash chain).
+ The flags are set to DEFINITION.
+ The indcount is 0 if no parameters, else 1 + number of parameters.
+ The offset field points to the macro string.
+ The macro string is null-terminated but EOL-sentineled.
+ It consists of EOL-terminated substrings followed by parameter numbers,
+ e.g., junk(x,y)=-x+y is stored as '-', EOL, 1, '+', EOL, 2, EOL, 0.
+ Here 1 is for the 1st parameter (start at 1 so 0 can terminate).
+ EOL acts as a sentinel for the scanner.
+ This choice works well because EOL cannot occur in a macro string.
+*/
+
+PUBLIC void define()
+{
+ char sname[NAMESIZE];
+ char quote;
+ struct symstruct **hashptr;
+ struct symstruct *locmark = NULL; /* for -Wall */
+ char *macstring;
+ fastin_t nparnames;
+ char *oldstring;
+ struct symstruct *symptr;
+
+ if (!blanksident())
+ {
+ error("illegal macro name");
+ return;
+ }
+ strcpy(sname, gsname); /* will overwrite gsname if parameters */
+ if (ch == '(')
+ {
+ locmark = locptr;
+ newlevel(); /* temp storage for parameter names */
+ nparnames = getparnames() + 1;
+ }
+ else
+ nparnames = 0;
+ blanks();
+ macstring = charptr;
+ quote = 0;
+ while (ch != EOL)
+ {
+ if (charptr >= char1top) /* check room for char and end of string */
+ macstring = growobject(macstring, 2);
+ if (nparnames && isident())
+ {
+ if ((symptr = findlorg(gsname)) != NULL &&
+ symptr->level == level)
+ {
+#ifdef TS
+++ts_n_macstring_param;
+ts_s_macstring += 2;
+#endif
+ *charptr++ = EOL; /* end current string */
+ *charptr++ = symptr->indcount; /* param to insert */
+ }
+ else
+ {
+ if (charptr + strlen(gsname) >= chartop) /* null too */
+ macstring = growobject(macstring, strlen(gsname) + 1);
+#ifdef TS
+++ts_n_macstring_ident;
+ts_s_macstring += strlen(gsname);;
+#endif
+ strcpy(charptr, gsname);
+ charptr += strlen(gsname); /* discard null */
+ }
+ continue;
+ }
+ if (ch == '\\')
+ {
+ gch1();
+ *charptr = '\\';
+ *(charptr + 1) = ch;
+#ifdef TS
+++ts_n_macstring_quoted;
+ts_s_macstring += 2;
+#endif
+ charptr += 2;
+ gch1();
+ continue;
+ }
+ if (quote)
+ {
+ if (ch == quote)
+ quote = 0;
+ }
+ else if (ch == '"' || ch == '\'')
+ quote = ch;
+ else if (ch == '/')
+ {
+ if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR)
+ {
+ gch1();
+ ch = *--lineptr = '/'; /* pushback */
+ }
+ if (*(lineptr + 1) == '*')
+ {
+ gch1();
+ skipcomment();
+ ch = *--lineptr = ' '; /* comment is space in modern cpp's */
+ }
+ }
+#ifdef TS
+++ts_n_macstring_ordinary;
+++ts_s_macstring;
+#endif
+ *charptr++ = ch;
+ gch1();
+ }
+ {
+ register char *rcp;
+
+ /* strip trailing blanks, but watch out for parameters */
+ for (rcp = charptr;
+ rcp > macstring && SYMOFCHAR(*(rcp - 1)) == WHITESPACE
+ && (--rcp == macstring || *(rcp - 1) != EOL); )
+ charptr = rcp;
+ }
+ if (charptr >= char1top)
+ macstring = growobject(macstring, 2);
+#ifdef TS
+++ts_n_macstring_term;
+ts_s_macstring += 2;
+#endif
+ *charptr++ = EOL;
+ *charptr++ = 0;
+ if (nparnames)
+ {
+ oldlevel();
+ locptr = locmark;
+ }
+ if (asmmode)
+ equ(sname, macstring);
+
+ if ((symptr = findlorg(sname)) != NULL && symptr->flags == DEFINITION)
+ {
+ if (strcmp(macstring, oldstring = symptr->offset.offp) != 0)
+ error("%wredefined macro");
+ if (strlen(macstring) > strlen(oldstring = symptr->offset.offp))
+ symptr->offset.offp = macstring;
+ else
+ {
+ strcpy(oldstring, macstring); /* copy if == to avoid test */
+ charptr = macstring;
+ }
+ return;
+ }
+ symptr = qmalloc(sizeof (struct symstruct) + strlen(sname));
+#ifdef TS
+++ts_n_defines;
+ts_s_defines += sizeof (struct symstruct) + strlen(sname);
+#endif
+ addsym(sname, vtype, symptr);
+ symptr->storage = DEF_NONE;
+ symptr->indcount = nparnames;
+ symptr->flags = DEFINITION;
+ symptr->level = GLBLEVEL;
+ symptr->offset.offp = macstring;
+ if (*(hashptr = gethashptr(sname)) != NULL)
+ {
+ symptr->next = *hashptr;
+ symptr->next->prev = &symptr->next;
+ }
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+}
+
+PRIVATE void defineorundefinestring(str, defineflag)
+char *str; /* "name[=def]" or "name def" */
+bool_pt defineflag;
+{
+ char *fakeline;
+ unsigned len;
+ bool_t old_eof;
+
+ len = strlen(str);
+ strcpy(fakeline = (char *) ourmalloc(3 + len + 2 + 2) + 3, str);
+ /* 3 pushback, 2 + 2 guards */
+#ifdef TS
+ts_s_fakeline += 3 + len + 2 + 2;
+ts_s_fakeline_tot += 3 + len + 2 + 2;
+#endif
+ {
+ register char *endfakeline;
+
+ endfakeline = fakeline + len;
+ endfakeline[0] = EOL; /* guards any trailing backslash */
+ endfakeline[1] = EOL; /* line ends here or before */
+ }
+ old_eof = eof;
+ eof = TRUE; /* valid after first EOL */
+ ch = *(lineptr = fakeline);
+ if (defineflag)
+ {
+ if (blanksident()) /* if not, let define() produce error */
+ {
+ blanks();
+ if (ch == '=')
+ *lineptr = ' ';
+ else if (ch == EOL)
+ {
+ register char *lptr;
+
+ lptr = lineptr;
+ lptr[0] = ' ';
+ lptr[1] = '1'; /* 2 extra were allocated for this & EOL */
+ lptr[2] = EOL;
+ }
+ }
+ ch = *(lineptr = fakeline);
+ define();
+ }
+ else
+ undef();
+ eof = old_eof;
+#ifdef TS
+ts_s_fakeline_tot -= len + 2 + 2;
+#endif
+ ourfree(fakeline - 3);
+}
+
+PUBLIC void definestring(str)
+char *str; /* "name[=def]" or "name def" */
+{
+ defineorundefinestring(str, TRUE);
+}
+
+/* docontrol() - process control statement, loop till "#if" is true */
+
+PUBLIC void docontrol()
+{
+ while (TRUE)
+ {
+ control();
+ skipline();
+ if (ifstate.ifflag)
+ return;
+ while (TRUE)
+ {
+ skipeol();
+ if (eof)
+ return;
+ blanks();
+ if (ch == '#')
+ {
+ gch1();
+ break;
+ }
+ skipline();
+ }
+ }
+}
+
+/* elsecontrol() - process #else */
+
+PRIVATE void elsecontrol()
+{
+ if (iflevel == 0)
+ {
+ error("else without if");
+ return;
+ }
+ ifstate.ifflag = ifstate.elseflag;
+ ifstate.elseflag = FALSE;
+}
+
+/* endif() - process #endif */
+
+PRIVATE void endif()
+{
+ if (iflevel == 0)
+ {
+ error("endif without if");
+ return;
+ }
+ {
+ register struct ifstruct *ifptr;
+
+ ifptr = &ifstack[(int)--iflevel];
+ ifstate.elseflag = ifptr->elseflag;
+ ifstate.ifflag = ifptr->ifflag;
+ }
+}
+
+/* entermac() - switch line ptr to macro string */
+
+PUBLIC void entermac()
+{
+ char quote;
+ struct symstruct *symptr;
+ char **paramhead;
+ char **paramlist;
+ int ngoodparams;
+ int nparleft;
+ int lpcount;
+
+ if (maclevel >= MAX_MACRO)
+ {
+ limiterror("macros nested too deeply (33 levels)");
+ return;
+ }
+ symptr = gsymptr;
+ ngoodparams = 0;
+ paramhead = NULL;
+ if (symptr->indcount != 0)
+ {
+ nparleft = symptr->indcount - 1;
+ if (nparleft == 0)
+ paramhead = NULL;
+ else
+ paramhead = ourmalloc(sizeof *paramlist * nparleft);
+ paramlist = paramhead;
+#ifdef TS
+++ts_n_macparam;
+ts_s_macparam += sizeof *paramlist * nparleft;
+ts_s_macparam_tot += sizeof *paramlist * nparleft;
+#endif
+ blanks();
+ while (ch == EOL && !eof)
+ {
+ skipeol();
+ blanks();
+ }
+ if (ch != '(')
+ error("missing '('");
+ else
+ {
+ gch1();
+ while (nparleft)
+ {
+ --nparleft;
+ ++ngoodparams;
+ *(paramlist++) = charptr;
+ quote = 0;
+ lpcount = 1;
+ while (TRUE)
+ {
+ if (ch == '\\')
+ {
+ gch1();
+ if (charptr >= char1top)
+ *(paramlist - 1) = growobject(*(paramlist - 1), 2);
+#ifdef TS
+++ts_n_macparam_string_quoted;
+++ts_s_macparam_string;
+++ts_s_macparam_string_tot;
+#endif
+ *charptr++ = '\\';
+ }
+ else if (quote)
+ {
+ if (ch == quote)
+ quote = 0;
+ }
+ else if (ch == '"' || ch == '\'')
+ quote = ch;
+ else if (ch == '/')
+ {
+ if (SYMOFCHAR(*(lineptr + 1)) == SPECIALCHAR)
+ {
+ gch1();
+ ch = *--lineptr = '/'; /* pushback */
+ }
+ if (*(lineptr + 1) == '*')
+ {
+ gch1();
+ skipcomment();
+ ch = *--lineptr = ' '; /* pushback */
+ }
+ }
+ else if (ch == '(')
+ ++lpcount;
+ else if ((ch == ')' && --lpcount == 0) ||
+ (ch == ',' && lpcount == 1))
+ break;
+ if (ch == EOL)
+ ch = ' ';
+ if (charptr >= char1top)
+ *(paramlist - 1) = growobject(*(paramlist - 1), 2);
+#ifdef TS
+++ts_n_macparam_string_ordinary;
+++ts_s_macparam_string;
+++ts_s_macparam_string_tot;
+#endif
+ *charptr++ = ch;
+ if (*lineptr == EOL)
+ {
+ skipeol(); /* macro case disposed of already */
+ if (SYMOFCHAR(ch) == SPECIALCHAR)
+ specialchar();
+ if (eof)
+ break;
+ }
+ else
+ gch1();
+ }
+#ifdef TS
+++ts_n_macparam_string_term;
+++ts_s_macparam_string;
+++ts_s_macparam_string_tot;
+#endif
+ *charptr++ = EOL;
+ {
+ register char *newparam;
+ register char *oldparam;
+ unsigned size;
+
+ oldparam = *(paramlist - 1);
+ size = (/* size_t */ unsigned) (charptr - oldparam);
+ newparam = ourmalloc(size);
+#ifdef TS
+ts_s_macparam_string_alloced += size;
+ts_s_macparam_string_alloced_tot += size;
+#endif
+ memcpy(newparam, oldparam, size);
+ *(paramlist - 1) = newparam;
+#ifdef TS
+ts_s_macparam_string_tot -= charptr - oldparam;
+#endif
+ charptr = oldparam;
+ }
+ if (ch == ',')
+ gch1();
+ else
+ break;
+ }
+ }
+ blanks();
+ while (ch == EOL && !eof)
+ {
+ skipeol();
+ blanks();
+ }
+ if (eof)
+ eofin("macro parameter expansion");
+ if (nparleft)
+ {
+ error("too few macro parameters");
+ do
+ *(paramlist++) = dummyparam;
+ while (--nparleft);
+ }
+ if (ch == ')')
+ gch1();
+ else if (ch == ',')
+ {
+ error("too many macro parameters");
+
+ /* XXX - should read and discard extra parameters. Also check
+ * for eof at end.
+ */
+ while (ch != ')')
+ {
+ if (ch == EOL)
+ {
+ skipeol();
+ if (eof)
+ break;
+ continue;
+ }
+ gch1();
+ }
+ }
+ else
+ error("missing ')'");
+ }
+
+ if (symptr->storage == DEF_LINE)
+ {
+ char *str;
+
+ str = pushudec(symptr->offset.offp + MAX__LINE__, input.linenumber);
+ memcpy(symptr->offset.offp, str, /* size_t */
+ (unsigned) (symptr->offset.offp + MAX__LINE__ + 1 + 1 - str));
+ }
+
+ {
+ register struct macroposition *mpptr;
+
+ mpptr = &macrostack[maclevel];
+ mpptr->paramlist = paramhead;
+ mpptr->maclineptr = lineptr;
+ ch = *(lineptr = symptr->offset.offp);
+ mpptr->inparam = FALSE;
+ mpptr->nparam = ngoodparams;
+ ++maclevel;
+ }
+/*
+ comment();
+ outstr("MACRO (level ");
+ outudec((unsigned) maclevel);
+ outstr(") ");
+ outline(lineptr);
+*/
+}
+
+/* getparnames() - get parameter names during macro definition, return count */
+
+PRIVATE fastin_pt getparnames()
+{
+ fastin_t nparnames;
+ struct symstruct *symptr;
+
+ nparnames = 0;
+ gch1();
+ while (blanksident())
+ {
+ if ((symptr = findlorg(gsname)) != NULL &&
+ symptr->level == level)
+ error("repeated parameter");
+ symptr = addloc(gsname, itype);
+ if (nparnames >= MAX_PARAM)
+ limiterror("too many macro parameters (128)");
+ else
+ ++nparnames; /* number params from 1 */
+ symptr->indcount = nparnames; /* param number */
+ blanks();
+ if (ch == ',')
+ gch1();
+ }
+ if (ch != ')')
+ error("missing ')'");
+ else
+ gch1();
+ return nparnames;
+}
+
+/* ifcontrol - process #if, #ifdef, #ifndef */
+
+PRIVATE void ifcontrol(ifcase)
+sym_pt ifcase;
+{
+ bool_t iftrue;
+ struct symstruct *symptr;
+
+ if (iflevel >= MAX_IF)
+ {
+ limiterror("#if's nested too deeply (33 levels)");
+ return;
+ }
+ {
+ register struct ifstruct *ifptr;
+
+ ifptr = &ifstack[(int)iflevel++];
+ ifptr->elseflag = ifstate.elseflag;
+ ifptr->ifflag = ifstate.ifflag;
+ ifstate.elseflag = FALSE; /* prepare for !(if now)||(if future)*/
+ }
+ if (ifstate.ifflag)
+ {
+ if ((sym_t) ifcase != IFCNTL)
+ {
+ iftrue = FALSE;
+ if (blanksident() && (symptr = findlorg(gsname)) != NULL &&
+ symptr->flags == DEFINITION)
+ iftrue = TRUE;
+ }
+ else
+ {
+ incppexpr = TRUE;
+ nextsym();
+ iftrue = constexpression() != 0;
+ incppexpr = FALSE;
+ }
+ if ((!iftrue && (sym_t) ifcase != IFNDEFCNTL) ||
+ (iftrue && (sym_t) ifcase == IFNDEFCNTL))
+ {
+ ifstate.elseflag = TRUE;
+ ifstate.ifflag = FALSE;
+ }
+ }
+}
+
+/* ifinit() - initialise if state */
+
+PUBLIC void ifinit()
+{
+ ifstate.ifflag = TRUE;
+}
+
+/* leavemac() - leave current and further macro substrings till not at end */
+
+PUBLIC void leavemac()
+{
+ register struct macroposition *mpptr;
+
+ do
+ {
+ mpptr = &macrostack[maclevel - 1];
+ if (mpptr->inparam)
+ {
+ lineptr = ++mpptr->paramspot;
+ mpptr->inparam = FALSE;
+ }
+ else
+ {
+ ch = *++lineptr; /* gch1() would mess up next param == EOL-1 */
+ if (ch != 0)
+ {
+ mpptr->paramspot = lineptr;
+ lineptr = mpptr->paramlist[ch - 1];
+ mpptr->inparam = TRUE;
+ }
+ else
+ {
+ lineptr = mpptr->maclineptr;
+ if (mpptr->nparam != 0)
+ {
+ register char **paramlist;
+
+#ifdef TS
+ts_s_macparam_tot -= sizeof *paramlist * mpptr->nparam;
+#endif
+ paramlist = mpptr->paramlist;
+ do
+{
+#ifdef TS
+ts_s_macparam_string_alloced_tot -= strchr(*paramlist, EOL) - *paramlist + 1;
+#endif
+ ourfree(*paramlist++);
+}
+ while (--mpptr->nparam != 0);
+ ourfree(mpptr->paramlist);
+ }
+ --maclevel;
+ }
+ }
+ }
+ while ((ch = *lineptr) == EOL && maclevel != 0);
+}
+
+PUBLIC void predefine()
+{
+ definestring("__BCC__ 1");
+ definestring("__LINE__ 0123456789"); /* MAX__LINE__ digits */
+ findlorg("__LINE__")->storage = DEF_LINE;
+}
+
+PUBLIC char *savedlineptr()
+{
+ return macrostack[0].maclineptr;
+}
+
+PUBLIC void skipcomment()
+{
+/* Skip current char, then everything up to '*' '/' or eof. */
+
+ gch1();
+ do
+ {
+ while (TRUE)
+ {
+ {
+ register char *reglineptr;
+
+ reglineptr = lineptr;
+ symofchar['*'] = SPECIALCHAR;
+ while (SYMOFCHAR(*reglineptr) != SPECIALCHAR)
+ ++reglineptr;
+ symofchar['*'] = STAR;
+ lineptr = reglineptr;
+ if (*reglineptr == '*')
+ break;
+ ch = *reglineptr;
+ }
+ specialchar();
+ if (ch == EOL)
+ {
+ skipeol();
+ if (eof)
+ break;
+ }
+ else if (ch != '*')
+ gch1();
+ }
+ gch1();
+ if (eof)
+ {
+ eofin("comment");
+ return;
+ }
+ }
+ while (ch != '/');
+ gch1();
+}
+
+/* skipline() - skip rest of line */
+
+PUBLIC void skipline()
+{
+ while (TRUE)
+ {
+ blanks();
+ if (ch == EOL)
+ return;
+ if (ch == '\\')
+ {
+ gch1();
+ if (ch == EOL) /* XXX - I think blanks() eats \EOL */
+ return;
+ gch1(); /* XXX - escape() better? */
+ }
+ else if (ch == '"' || ch == '\'')
+ {
+ stringorcharconst();
+ charptr = constant.value.s;
+ }
+ else
+ gch1();
+ }
+}
+
+/* undef() - process #undef */
+
+PRIVATE void undef()
+{
+ struct symstruct *symptr;
+
+ if (blanksident() && (symptr = findlorg(gsname)) != NULL &&
+ symptr->flags == DEFINITION)
+ delsym(symptr);
+}
+
+PUBLIC void undefinestring(str)
+char *str;
+{
+ defineorundefinestring(str, FALSE);
+}
diff --git a/bcc/preserve.c b/bcc/preserve.c
new file mode 100644
index 0000000..74b0f34
--- /dev/null
+++ b/bcc/preserve.c
@@ -0,0 +1,216 @@
+/* preserve.c - preserve opererands or registers in use for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "type.h"
+
+/* change stack ptr without changing condition codes */
+
+PUBLIC void changesp(newsp, absflag)
+offset_t newsp;
+bool_pt absflag;
+{
+ if (newsp != sp || ((bool_t) absflag && switchnow != NULL))
+ {
+#ifdef FRAMEPOINTER
+ if (newsp != framep || (!(bool_t) absflag && switchnow != NULL))
+ {
+ outleasp();
+ if (!(bool_t) absflag && switchnow != NULL)
+ outswoffset(newsp);
+ else
+ outoffset(newsp - framep);
+ outindframereg();
+ outnl();
+ }
+ else
+ regtransfer(FRAMEREG, STACKREG);
+ sp = newsp;
+ if (framep == 0)
+ bugerror("no frame pointer");
+#else
+# ifdef I8088
+ outleasp();
+ outoffset(newsp - sp);
+ outindstackreg();
+ outnl();
+# else
+ modstk(newsp); /* this should preserve CC */
+# endif
+#endif /* FRAMEPOINTER */
+ }
+}
+
+/* load source to any while preserving target */
+
+PUBLIC void loadpres(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regmark;
+
+ if (target->storage & ALLDATREGS)
+ {
+ if (source->type->scalar & CHAR)
+ {
+ push(target);
+ load(source, DREG);
+ }
+ else
+ load(source, getindexreg());
+ }
+ else
+ {
+ regmark = reguse;
+ reguse |= target->storage;
+ loadany(source);
+ reguse = regmark;
+ }
+}
+
+/* change stack ptr */
+
+PUBLIC void modstk(newsp)
+offset_t newsp;
+{
+ if (newsp != sp)
+ {
+#ifdef FRAMEPOINTER
+ if (newsp != framep || framep == 0 || switchnow != NULL)
+ addconst(newsp - sp, STACKREG);
+ else
+ regtransfer(FRAMEREG, STACKREG);
+#else
+# ifdef I8088
+ addconst(newsp - sp, STACKREG);
+# else
+ outleasp();
+ outoffset(newsp - sp);
+ outncspregname();
+# endif
+#endif
+ sp = newsp;
+ }
+}
+
+/* preserve target without changing source */
+
+PUBLIC void pres2(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ if (target->storage & allregs)
+ {
+ if (target->storage & (allregs - allindregs) /* XXX */ ||
+ (target->indcount == 0 &&
+ target->type->scalar & (DLONG | RSCALAR)))
+ push(target); /* XXX - perhaps not float */
+ else if (((target->storage | reguse) & allindregs) == allindregs)
+ {
+ loadpres(target, source);
+ push(target);
+ }
+ else
+ reguse |= target->storage;
+ }
+}
+
+/* preserve source */
+
+PUBLIC void preserve(source)
+struct symstruct *source;
+{
+ if (source->storage & allregs)
+ {
+ if (source->storage & (allregs - allindregs) /* XXX */ ||
+ ((source->storage | reguse) & allindregs) == allindregs)
+ push(source);
+ else
+ reguse |= source->storage;
+ }
+}
+
+/* preserve lvalue target without changing source or target */
+
+PUBLIC store_pt preslval(source, target)
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_pt regpushed;
+
+ if (target->indcount == 0)
+ reguse &= ~target->storage;
+ else
+ reguse = (target->storage | reguse) & allindregs;
+ if (!((source->type->scalar | target->type->scalar) & (DLONG | RSCALAR))
+ || reguse != allindregs)
+ return 0; /* XXX - perhaps not float */
+ reguse = source->storage | target->storage; /* free one other than s/t */
+ pushreg(regpushed = getindexreg());
+ reguse = ~(store_t) regpushed & allindregs;
+ return regpushed;
+}
+
+PUBLIC void recovlist(reglist)
+store_pt reglist;
+{
+ poplist(reglist);
+ reguse |= (store_t) reglist;
+}
+
+#ifdef I8088
+PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5};
+ /* CONSTANT, BREG, ax = DREG, bx = INDREG0, si = INDREG1, di = INDREG2 */
+ /* LOCAL, GLOBAL, STACKREG, cx = DATREG1, dx = DATREG2 */
+#endif
+#ifdef MC6809
+PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 3, 2};
+ /* CONSTANT, BREG, DREG, XREG = INDREG0, UREG = INDREG1, YREG = INDREG2 */
+#endif
+
+PUBLIC void savereturn(savelist, saveoffset)
+store_pt savelist;
+offset_t saveoffset;
+{
+ store_t reg;
+ smalin_t *regoffptr;
+ offset_t spoffset;
+
+ if (savelist == 0)
+ return;
+#ifdef MC6809 /* must check this */
+ if (savelist == XREG || savelist == INDREG1)
+ saveoffset -= accregsize; /* patch for DREG/YREG not saved */
+#endif
+ for (reg = 1, regoffptr = regoffset; reg != 0; ++regoffptr, reg <<= 1)
+ if (reg & savelist)
+ {
+ outstore();
+ spoffset = saveoffset + *regoffptr * maxregsize;
+#ifdef I8088
+# ifdef FRAMEPOINTER
+ if (switchnow != NULL)
+ outswoffset(spoffset);
+ else
+ outoffset(spoffset - framep);
+ outindframereg();
+# else
+ outoffset(spoffset - sp);
+ outindstackreg();
+# endif
+ outncregname(reg);
+#endif
+#ifdef MC6809
+ if (reg == YREG)
+ bumplc();
+ outregname(reg);
+ outtab();
+ outoffset(spoffset - sp);
+ outncspregname();
+#endif
+ }
+}
diff --git a/bcc/proto.h b/bcc/proto.h
new file mode 100644
index 0000000..0c04044
--- /dev/null
+++ b/bcc/proto.h
@@ -0,0 +1,397 @@
+/* proto.h - extern functions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#include <malloc.h>
+
+/* assign.c */
+void assign P((struct symstruct *source, struct symstruct *target));
+void cast P((struct typestruct *type, struct symstruct *target));
+void extend P((struct symstruct *target));
+
+/* codefrag.c */
+void adjsp P((label_t label));
+void clrBreg P((void));
+void comment P((void));
+void ctoi P((void));
+void defbyte P((void));
+void deflong P((uoffset_t value));
+void defword P((void));
+void defdword P((void));
+void even P((void));
+void negDreg P((void));
+void comDreg P((void));
+void outadd P((void));
+void outaddsp P((void));
+void outcalladr P((void));
+void outcmp P((void));
+void outdec P((void));
+void outdword P((void));
+void outfail P((void));
+void outinc P((void));
+void outindleft P((void));
+void outindright P((void));
+void outindstackreg P((void));
+void outldaccum P((void));
+void outldmulreg P((void));
+void outlea P((void));
+void outleasp P((void));
+void outload P((void));
+void outmulmulreg P((void));
+void outopsep P((void));
+void outpshs P((void));
+void outpuls P((void));
+void outreturn P((void));
+void outstore P((void));
+void outsub P((void));
+void outtest P((void));
+void outword P((void));
+void sctoi P((void));
+void stoi P((void));
+void ustoi P((void));
+void outABX P((void));
+void outdirectpage P((void));
+void outextended P((void));
+void outncspregname P((void));
+void outindframereg P((void));
+void adc0 P((void));
+void addconst P((offset_t offset, store_pt reg));
+void adjlc P((offset_t offset, store_pt reg));
+void andconst P((offset_t offset));
+void bssseg P((void));
+label_t casejump P((void));
+void common P((char *name));
+void cseg P((void));
+void defnulls P((uoffset_t nullcount));
+label_t defstr P((char *sptr, char *stop, bool_pt dataflag));
+bool_pt diveasy P((value_t divisor, bool_pt uflag));
+void dpseg P((void));
+void dseg P((void));
+void equ P((char *name, char *string));
+void equlab P((label_t label, offset_t offset));
+void globl P((char *name));
+void import P((char *name));
+void itol P((store_pt reg));
+void lcommlab P((label_t label));
+void lcommon P((char *name));
+void lea P((offset_t offset, store_pt sourcereg, store_pt targreg));
+void loadconst P((offset_t offset, store_pt reg));
+int lslconst P((value_t shift, store_pt reg));
+int lsrconst P((value_t shift, store_pt reg, bool_pt uflag));
+bool_pt modeasy P((value_t divisor, bool_pt uflag));
+bool_pt muleasy P((uvalue_t factor, store_pt reg));
+void negreg P((store_pt reg));
+char *opstring P((op_pt op));
+void outccname P((char *name));
+void outhiaccum P((void));
+void outimmadr P((offset_t offset));
+void outimadj P((offset_t offset, store_pt targreg));
+void outimmed P((void));
+void outjumpstring P((void));
+void outnccname P((char *name));
+void outncimmadr P((offset_t offset));
+void outoffset P((offset_t offset));
+void public P((char *name));
+void private P((char *name));
+void regexchange P((store_pt sourcereg, store_pt targreg));
+void regtransfer P((store_pt sourcereg, store_pt targreg));
+void sbc0 P((void));
+void set P((char *name, offset_t value));
+void sl1 P((store_pt reg));
+void slconst P((value_t shift, store_pt reg));
+void srconst P((value_t shift, bool_pt uflag));
+void uitol P((store_pt reg));
+void restoreopreg P((void));
+void saveopreg P((void));
+
+/* debug.c */
+void dbitem P((struct symstruct *item));
+void dbtype P((struct typestruct *type));
+void debug P((struct nodestruct *exp));
+void debugswap P((void));
+
+/* declare.c */
+void colon P((void));
+void decllist P((void));
+void lparen P((void));
+void needvarname P((void));
+void program P((void));
+void rbrace P((void));
+void rbracket P((void));
+void rparen P((void));
+void semicolon P((void));
+struct typestruct *typename P((void));
+
+/* express.c */
+struct nodestruct *assignment_exp P((void));
+struct nodestruct *expression P((void));
+
+/* exptree.c */
+struct nodestruct *castnode P((struct typestruct *type,
+ struct nodestruct *nodeptr));
+void etreeinit P((void));
+struct nodestruct *leafnode P((struct symstruct *source));
+struct nodestruct *node P((op_pt t, struct nodestruct *p1,
+ struct nodestruct *p2));
+
+/* floatop.c */
+bool_pt f_indirect P((struct symstruct *target));
+void float1op P((op_pt op, struct symstruct *source));
+void floatop P((op_pt op, struct symstruct *source, struct symstruct *target));
+void fpush P((struct symstruct *source));
+void justpushed P((struct symstruct *target));
+
+/* function.c */
+void call P((char *name));
+void function P((struct symstruct *source));
+void ldregargs P((void));
+void loadretexpression P((void));
+void listo P((struct symstruct *target, offset_t lastargsp));
+void listroot P((struct symstruct *target));
+void popframe P((void));
+void reslocals P((void));
+void ret P((void));
+
+/* gencode.c */
+void bileaf P((struct nodestruct *exp));
+fastin_pt bitcount P((uvalue_t number));
+void codeinit P((void));
+fastin_pt highbit P((uvalue_t number));
+void makeleaf P((struct nodestruct *exp));
+
+/* genloads.c */
+void addoffset P((struct symstruct *source));
+void address P((struct symstruct *source));
+void exchange P((struct symstruct *source, struct symstruct *target));
+store_pt getindexreg P((void));
+void indexadr P((struct symstruct *source, struct symstruct *target));
+void indirec P((struct symstruct *source));
+void load P((struct symstruct *source, store_pt targreg));
+void loadany P((struct symstruct *source));
+void loadreg P((struct symstruct *source, store_pt targreg));
+void makelessindirect P((struct symstruct *source));
+void movereg P((struct symstruct *source, store_pt targreg));
+void onstack P((struct symstruct *target));
+void outadr P((struct symstruct *adr));
+void outcregname P((store_pt reg));
+void outncregname P((store_pt reg));
+void outnregname P((store_pt reg));
+void outregname P((store_pt reg));
+void outshortregname P((store_pt reg));
+void pointat P((struct symstruct *target));
+void poplist P((store_pt reglist));
+void push P((struct symstruct *source));
+void pushlist P((store_pt reglist));
+void pushreg P((store_pt reg));
+void storereg P((store_pt sourcereg, struct symstruct *target));
+void struc P((struct symstruct *source, struct symstruct *target));
+void transfer P((struct symstruct *source, store_pt targreg));
+
+/* glogcode.c */
+void cmp P((struct symstruct *source, struct symstruct *target,
+ ccode_t *pcondtrue));
+void condop P((struct nodestruct *exp));
+void jumpfalse P((struct nodestruct *exp, label_t label));
+void jumptrue P((struct nodestruct *exp, label_t label));
+void logop P((struct nodestruct *exp));
+
+/* hardop.c */
+void add P((struct symstruct *source, struct symstruct *target));
+void incdec P((op_pt op, struct symstruct *source));
+void neg P((struct symstruct *target));
+void not P((struct symstruct *target));
+void op1 P((op_pt op, struct symstruct *source, struct symstruct *target));
+void ptrsub P((struct symstruct *source, struct symstruct *target));
+void sub P((struct symstruct *source, struct symstruct *target));
+
+/* input.c */
+void closein P((void));
+void errorloc P((void));
+void gch1 P((void));
+void include P((void));
+void openio P((int argc, char **argv));
+void skipeol P((void));
+void specialchar P((void));
+
+/* label.c */
+void bumplc P((void));
+void bumplc2 P((void));
+void bumplc3 P((void));
+void clearfunclabels P((void));
+void clearlabels P((char *patchbuf, char *patchtop));
+void clearswitchlabels P((void));
+uoffset_t getlc P((void));
+void deflabel P((label_t label));
+label_t gethighlabel P((void));
+label_t getlabel P((void));
+void jump P((label_t label));
+void lbranch P((ccode_pt cond, label_t label));
+struct symstruct *namedlabel P((void));
+void outcond P((ccode_pt cond));
+void outlabel P((label_t label));
+void outnlabel P((label_t label));
+void sbranch P((ccode_pt cond, label_t label));
+void unbumplc P((void));
+
+/* loadexp.c */
+value_t constexpression P((void));
+void initexpression P((struct typestruct *type));
+struct typestruct *loadexpression P((store_pt targreg,
+ struct typestruct *targtype));
+
+/* longop.c */
+void longop P((op_pt op, struct symstruct *source, struct symstruct *target));
+void long1op P((op_pt op, struct symstruct *target));
+void outlongendian P((void));
+
+/* output.c */
+void bugerror P((char *message));
+void closeout P((void));
+void error P((char *message));
+void error2error P((char *message1, char *message2));
+void fatalerror P((char *message));
+void finishup P((void));
+void flushout P((void));
+void limiterror P((char *message));
+void initout P((void));
+void openout P((char *oname));
+void outbyte P((int ch));
+void outcomma P((void));
+void outcpplinenumber P((unsigned nr, char *fname, char *str));
+void outhex P((uoffset_t num));
+void outhexdigs P((uoffset_t num));
+void outline P((char *s));
+void outminus P((void));
+void outnl P((void));
+void outnbyte P((int byte));
+void outnhex P((uoffset_t num));
+void outnop1str P((char *s));
+void outnop2str P((char *s));
+void outnstr P((char *s));
+void outop0str P((char *s));
+void outop1str P((char *s));
+void outop2str P((char *s));
+void outop3str P((char *s));
+void outplus P((void));
+void outshex P((offset_t num));
+void outstr P((char *s));
+void outtab P((void));
+void outudec P((unsigned num));
+void outuvalue P((uvalue_t num));
+void outvalue P((value_t num));
+char *pushudec P((char *s, unsigned num));
+void setoutbufs P((void));
+
+/* preproc.c */
+void blanks P((void));
+bool_pt blanksident P((void));
+void checknotinif P((void));
+void define P((void));
+void definestring P((char *str));
+void docontrol P((void));
+void entermac P((void));
+void ifinit P((void));
+void leavemac P((void));
+void predefine P((void));
+char *savedlineptr P((void));
+void skipcomment P((void));
+void skipline P((void));
+void undefinestring P((char *str));
+
+/* preserve.c */
+void changesp P((offset_t newsp, bool_pt absflag));
+void loadpres P((struct symstruct *source, struct symstruct *target));
+void modstk P((offset_t newsp));
+void pres2 P((struct symstruct *source, struct symstruct *target));
+void preserve P((struct symstruct *source));
+store_pt preslval P((struct symstruct *source, struct symstruct *target));
+void recovlist P((store_pt reglist));
+void savereturn P((store_pt savelist, offset_t saveoffset));
+
+/* sc.c */
+int main P((int argc, char **argv));
+
+/* scan.c */
+void cppscan P((void));
+void eofin P((char *message));
+bool_pt isident P((void));
+void nextsym P((void));
+void stringorcharconst P((void));
+
+/* softop.c */
+void softop P((op_pt op, struct symstruct *source, struct symstruct *target));
+
+/* state.c */
+void compound P((void));
+void outswoffset P((offset_t offset));
+void outswstacklab P((void));
+
+/* table.c */
+struct symstruct *addglb P((char *name, struct typestruct *type));
+struct symstruct *addloc P((char *name, struct typestruct *type));
+struct symstruct *addlorg P((char *name, struct typestruct *type));
+void addsym P((char *name, struct typestruct *type,
+ struct symstruct *symptr));
+struct symstruct *constsym P((value_t intconst));
+void delsym P((struct symstruct *symptr));
+void dumpglbs P((void));
+void dumplocs P((void));
+void dumpstrings P((void));
+struct symstruct *exprsym P((struct symstruct *symptr));
+struct symstruct *findlorg P((char *name));
+struct symstruct *findstruct P((char *name));
+struct symstruct **gethashptr P((char *sname));
+void growheap P((unsigned size));
+void *growobject P((void *object, unsigned extra));
+label_t holdstr P((char *sptr, char *stop));
+void newlevel P((void));
+void oldlevel P((void));
+void ourfree P((void *ptr));
+void *ourmalloc P((unsigned nbytes));
+void outofmemoryerror P((char *message));
+void *qmalloc P((unsigned size));
+void swapsym P((struct symstruct *sym1, struct symstruct *sym2));
+void syminit P((void));
+
+/* type.c */
+struct typestruct *addstruct P((char *structname));
+struct typestruct *iscalartotype P((scalar_pt scalar));
+struct typestruct *newtype P((void));
+void outntypechar P((struct typestruct *type));
+struct typestruct *pointype P((struct typestruct *type));
+struct typestruct *prefix P((constr_pt constructor, uoffset_t size,
+ struct typestruct *type));
+struct typestruct *promote P((struct typestruct *type));
+struct typestruct *tounsigned P((struct typestruct *type));
+void typeinit P((void));
+
+/* library - fcntl.h */
+int creat P((const char *_path, int _mode));
+int open P((const char *_path, int _oflag, ...));
+
+/* library - stdlib.h */
+double atof P((const char *_str));
+void exit P((int _status));
+
+/* library - string.h */
+void *memcpy P((void *_t, const void *_s, unsigned _length));
+void *memset P((void *_s, int _c, unsigned _nbytes));
+char *strcat P((char *_target, const char *_source));
+char *strchr P((const char *_s, int _ch));
+int strcmp P((const char *_s1, const char *_s2));
+char *strcpy P((char *_target, const char *_source));
+unsigned strlen P((const char *_s));
+char *strncpy P((char *_target, const char *_source, unsigned _maxlength));
+char *strrchr P((const char *_s, int _ch));
+
+/* library - unistd.h */
+int close P((int _fd));
+int isatty P((int _fd));
+long lseek P((int _fd, long _offset, int _whence));
+int read P((int _fd, char *_buf, unsigned _nbytes));
+int write P((int _fd, char *_buf, unsigned _nbytes));
diff --git a/bcc/reg.h b/bcc/reg.h
new file mode 100644
index 0000000..822bda7
--- /dev/null
+++ b/bcc/reg.h
@@ -0,0 +1,139 @@
+/* reg.h - registers for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ The compiler generates "addresses" of the form
+ indirect(indcount) (rx + offset)
+ where
+ rx is a machine register (possibly null)
+ n is the indirection count (possibly 0)
+ offset is a constant.
+ It does not support more complicated formats like
+ indirect(indcount) (rx + index * scale + offset).
+
+ The register is coded as bit flag in the storage component of
+ the symbol structure. This allows groups of registers to be tested
+ using bitwise "&". Throughout the compiler, the group of these bit
+ flags has the type reg_t. If there are only a few registers, reg_t
+ can be an unsigned char. It must be unsigned if the high bit is
+ used, to avoid sign extension problems. For bootstrapping the compiler
+ from a compiler with no unsigned char, the unsigned type should be
+ used instead (with a signifigant waste of storage).
+
+ The bit flags should really be defined as ((reg_t) whatever) but
+ then they would not (necessarily) be constant expressions and couldn't
+ be used in switch selectors or (worse) preprocessor expressions.
+
+ The CONSTANT and GLOBAL (non-) register bits are almost
+ equivalent. A constant with nonzero indirection is marked as a
+ GLOBAL and not a CONSTANT. This makes it easier to test for a constant
+ CONSTANT. Globals which are formed in this way are converted to
+ constants if their indirection count is reset to 0 (by & operator).
+*/
+
+/* register bit flags */
+
+#define NOSTORAGE 0x000 /* structure/union member offsets */
+#define CONSTANT 0x001 /* offsets are values */
+#define BREG 0x002
+#define DREG 0x004
+#define INDREG0 0x008
+#define INDREG1 0x010
+#define INDREG2 0x020
+#define LOCAL 0x040
+#define GLOBAL 0x080 /* offsets from storage name or 0 */
+#define CCREG CONSTANT /* arg to PSHS/PULS functions only */
+#ifdef I8088
+# ifdef FRAMEPOINTER
+# define FRAMEREG LOCAL
+# endif
+# define STACKREG 0x100
+# define DATREG1 0x200
+# define DATREG2 0x400
+# define DATREG1B 0x800
+#endif
+#ifdef MC6809
+# define DPREG LOCAL /* arg to PSHS/PULS functions only */
+# define PCREG GLOBAL /* arg to PSHS/PULS functions only */
+#endif
+
+/* data for pushing and pulling registers */
+
+#define MINREGCHAR 'A'
+#ifdef I8088
+# define FLAGSREGCHAR 'f'
+# define pushchar() pushlist(AXREG)
+#endif
+#ifdef MC6809
+# define pushchar() pushlist(BREG)
+#endif
+
+/* special registers */
+
+#ifdef I8088
+# define ALREG BREG
+# define AXREG DREG
+# define DXREG DATREG2
+# define MULREG DATREG1B
+# define SHIFTREG DATREG1B
+#endif
+#ifdef MC6809
+# define XREG INDREG0 /* XREG is special for ABX in index & switch */
+# define YREG INDREG2 /* XREG and YREG allow LEA (Z test) in cmp() */
+#endif
+
+/* groups of registers */
+
+#define ALLDATREGS (BREG|DREG)
+#define CHARREGS BREG
+#define MAXREGS 1 /* number of data registers */
+#define WORKDATREGS (BREG|DREG)
+
+/* function call and return registers */
+
+#define ARGREG RETURNREG /* for (1st) argument */
+#define LONGARGREGS LONGRETURNREGS /* for long or float arg */
+#define LONGRETURNREGS (INDREG0|LONGREG2)
+#define LONGREG2 DREG
+#ifdef I8088
+# define LONGRETSPECIAL /* LONGRETURNREGS!=RETURNREG && RETURNREG==LONGREG2 */
+# define RETURNREG DREG
+#endif
+#ifdef MC6809
+# define RETURNREG INDREG0
+#endif
+
+/* registers which can be pulled as a group with the program counter */
+/* to perform an efficient function return */
+
+#ifdef MC6809
+#define JUNK1REGS BREG /* 1 bytes locals to discard */
+#define JUNK2REGS INDREG2
+#define JUNK3REGS (BREG|INDREG2)
+#define JUNK4REGS (INDREG1|INDREG2)
+#endif
+
+/* registers which can be pushed as a group with the first argument */
+/* to perform an efficient function startup */
+
+#ifdef MC6809
+# define LOC1REGS CCREG /* 1 bytes local to allocate */
+# define LOC2REGS DREG
+# define LOC3REGS (CCREG|DREG)
+# define LOC4REGS (CCREG|DREG|DPREG)
+# endif
+
+/* registers to be used by software operations */
+
+#define OPREG INDREG0 /* 2nd reg for software ops (1st is DREG) */
+#define OPWORKREG INDREG2 /* 3rd register for software ops */
+
+/* maximum indirection count for 1 instruction */
+
+#ifdef I8088
+# define MAXINDIRECT 1
+#endif
+#ifdef MC6809
+# define MAXINDIRECT 2
+#endif
diff --git a/bcc/sc.h b/bcc/sc.h
new file mode 100644
index 0000000..c17536a
--- /dev/null
+++ b/bcc/sc.h
@@ -0,0 +1,27 @@
+/* sc.h - storage classes for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#ifdef MC6809
+#define DIRECTPAGE 0x01 /* modifier on global to show in dpseg */
+#endif
+#define EXTERNAL 0x02 /* external */
+#define STATIC 0x04
+
+/* symbols with flags above the 1st initialised value are not to be dumped */
+
+#define MAXDUMPFLAG 0x07
+#define INITIALIZED 0x08 /* modifier on global to show initialized */
+#define LABELLED 0x10 /* modifier on static to show labelled */
+ /* and on STRING to show labelled */
+
+/* remaining "flags" are numbers, not flags */
+/* they are disjoint from all combinations of flags above */
+/* except STRING => LABELLED (and no other flags) */
+
+#define DEFINITION 0x20 /* #defined name */
+#define KEYWORD 0x40 /* reserved word for C */
+#define STRUCTNAME 0x60 /* struct/union name or member name */
+#define REGVAR 0x80 /* register variable */
+#define TEMP 0xa0 /* temporary on stack expression eval */
+#define STRING 0xc0 /* string constant (=> LABELLED) */
diff --git a/bcc/scan.c b/bcc/scan.c
new file mode 100644
index 0000000..0baecf8
--- /dev/null
+++ b/bcc/scan.c
@@ -0,0 +1,806 @@
+/* scan.c - lexical analyser for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define GCH1() do { if (SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) specialchar(); } while (0)
+
+#include "const.h"
+#include "types.h"
+#include "input.h"
+#include "os.h"
+#include "output.h"
+#include "sc.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "scan.h"
+
+PUBLIC sym_t symofchar[256] =
+{
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, WHITESPACE, SPECIALCHAR, BADCHAR,
+ WHITESPACE, SPECIALCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ WHITESPACE, LOGNOTOP, STRINGCONST, CONTROL, /* !"# */
+ BADCHAR, MODOP, AMPERSAND, CHARCONST, /* $%&' */
+ LPAREN, RPAREN, STAR, ADDOP, /* ()*+ */
+ COMMA, HYPHEN, FLOATCONST, SLASH, /* ,-./ */
+
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 0123 */
+ INTCONST, INTCONST, INTCONST, INTCONST, /* 4567 */
+ INTCONST, INTCONST, COLON, SEMICOLON, /* 89:; */
+ LTOP, ASSIGNOP, GTOP, CONDOP, /* <=>? */
+
+ BADCHAR, IDENT, IDENT, IDENT, /* @ABC */
+ IDENT, IDENT, IDENT, IDENT, /* DEFG */
+ IDENT, IDENT, IDENT, IDENT, /* HIJK */
+ IDENT, IDENT, IDENT, IDENT, /* LMNO */
+ IDENT, IDENT, IDENT, IDENT, /* PQRS */
+ IDENT, IDENT, IDENT, IDENT, /* TUVW */
+ IDENT, IDENT, IDENT, LBRACKET, /* XYZ[ */
+ SPECIALCHAR, RBRACKET, EOROP, IDENT, /* \]^_ */
+
+ BADCHAR, IDENT, IDENT, IDENT, /* `abc */
+ IDENT, IDENT, IDENT, IDENT, /* defg */
+ IDENT, IDENT, IDENT, IDENT, /* hijk */
+ IDENT, IDENT, IDENT, IDENT, /* lmno */
+ IDENT, IDENT, IDENT, IDENT, /* pqrs */
+ IDENT, IDENT, IDENT, IDENT, /* tuvw */
+ IDENT, IDENT, IDENT, LBRACE, /* xyz{ */
+ OROP, RBRACE, NOTOP, BADCHAR, /* |}~ */
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR,
+ BADCHAR, BADCHAR, BADCHAR, BADCHAR
+};
+
+FORWARD void getident P((void));
+FORWARD void intconst P((void));
+FORWARD void ppnumber P((void));
+PRIVATE void newstringorcharconst P((void));
+
+/* skip white space up to end of line (skip EOL's if in comments) */
+
+PUBLIC void blanks()
+{
+ register char *reglineptr;
+
+ while (TRUE)
+ {
+ reglineptr = lineptr;
+ while (SYMOFCHAR(*reglineptr) == WHITESPACE)
+ ++reglineptr;
+ lineptr = reglineptr;
+ if (SYMOFCHAR(ch = *reglineptr) == SPECIALCHAR)
+ {
+ specialchar();
+ if (ch == EOL)
+ return;
+ if (SYMOFCHAR(ch) == WHITESPACE)
+ continue;
+ reglineptr = lineptr;
+ }
+ if (*reglineptr != '/')
+ return;
+ if (SYMOFCHAR(*(reglineptr + 1)) == SPECIALCHAR)
+ {
+ ch = *(lineptr = reglineptr + 1);
+ specialchar();
+ ch = *(reglineptr = --lineptr) = '/'; /* pushback */
+ }
+ if (*(reglineptr + 1) != '*')
+ return;
+ gch1();
+ skipcomment();
+ }
+}
+
+PUBLIC void cppscan()
+{
+ while (TRUE)
+ {
+ switch (SYMOFCHAR(ch))
+ {
+ case CHARCONST:
+ case STRINGCONST:
+ stringorcharconst();
+ *charptr = 0; /* room reserved */
+ outstr(constant.value.s); /* XXX - embedded null would kill it */
+ charptr = constant.value.s;
+ break;
+ case CONTROL:
+ gch1();
+ if (maclevel != 0)
+ {
+ error("# in a macro: not preprocessed"); /* XXX? */
+ break;
+ }
+ else
+ {
+ cppmode = FALSE;
+ docontrol();
+ cppmode = TRUE;
+ break;
+ }
+ case SLASH:
+ gch1();
+ if (ch == '*')
+ {
+ skipcomment();
+ break;
+ }
+ outbyte('/');
+ break;
+ case FLOATCONST:
+ gch1();
+ if (SYMOFCHAR(ch) == INTCONST)
+ {
+ --lineptr;
+ ch = '.'; /* pushback */
+ ppnumber();
+ outstr(constant.value.s);
+ charptr = constant.value.s;
+ }
+ else
+ outbyte('.');
+ break;
+ case IDENT:
+ getident();
+ if ((gsymptr = findlorg(gsname)) != NULL)
+ {
+ if (gsymptr->flags == DEFINITION)
+ {
+ entermac();
+ break;
+ }
+ }
+ outstr(gsname);
+ break;
+ case INTCONST:
+ ppnumber();
+ outstr(constant.value.s);
+ charptr = constant.value.s;
+ break;
+ case SPECIALCHAR:
+ specialchar(); /* XXX - this is necessary because entermac
+ * and skipeol can leave lineptr at a special
+ * char although GCH1 cannot. entermac would
+ * be easy to fix, but too many places already
+ * have to handle the extra work after skipeol
+ * for other reasons.
+ */
+ if (ch == EOL)
+ {
+ skipeol();
+ if (eof)
+ return;
+ break;
+ }
+#ifdef COEOL
+ if (ch == COEOL)
+ {
+ gch1();
+ break;
+ }
+#endif
+ if (SYMOFCHAR(ch) != SPECIALCHAR)
+ break; /* specialchar advanced the input */
+ /* must be '\\' */
+ default:
+ OUTBYTE(ch);
+ GCH1();
+ break;
+ }
+ }
+}
+
+PUBLIC void eofin(message)
+char *message;
+{
+ error2error("end of file in ", message);
+}
+
+/* get identifier in gsname == gs2name + 2 */
+
+PRIVATE void getident()
+{
+ register int c;
+ register char *idptr;
+ register int length;
+ register char *reglineptr;
+
+ idptr = gsname;
+ length = NAMESIZE;
+ reglineptr = lineptr;
+ c = ch;
+more:
+ do
+ {
+ *idptr++ = c;
+ c = (unsigned char) *++reglineptr;
+ }
+ while (symofchar[c] <= MAXIDSYM && --length != 0);
+ ch = c;
+ *idptr = 0;
+ lineptr = reglineptr;
+ if (symofchar[c] == SPECIALCHAR)
+ {
+ specialchar();
+ if (SYMOFCHAR(ch) <= MAXIDSYM && length != 0)
+ {
+ reglineptr = lineptr;
+ c = ch;
+ goto more;
+ }
+ }
+}
+
+/* return nonzero if at an identifier */
+
+PUBLIC bool_pt isident()
+{
+ if (SYMOFCHAR(ch) != IDENT)
+ return FALSE;
+ getident();
+ return TRUE;
+}
+
+PRIVATE void intconst()
+{
+ fastin_t base;
+ fastin_t digit;
+ register char *digptr;
+ fastin_t lcount;
+ fastin_t ucount;
+ bool_t dflag;
+
+ ppnumber();
+ digptr = charptr = constant.value.s;
+ if (*digptr == '0')
+ {
+ if (digptr[1] != 'x' && digptr[1] != 'X')
+ base = 8;
+ else
+ {
+ base = 16;
+ digptr += 2;
+ }
+ }
+ else
+ base = 10;
+ dflag = FALSE;
+ if (*digptr == 0)
+ error("constant has no digits");
+ if (base != 16)
+ {
+ while (SYMOFCHAR(*digptr) == INTCONST)
+ ++digptr;
+ if (*digptr == '.')
+ {
+ dflag = TRUE;
+ ++digptr;
+ while (SYMOFCHAR(*digptr) == INTCONST)
+ ++digptr;
+ }
+ if (*digptr == 'E' || *digptr == 'e')
+ {
+ dflag = TRUE;
+ ++digptr;
+ if (*digptr == '+' || *digptr == '-')
+ ++digptr;
+ if (SYMOFCHAR(*digptr) != INTCONST)
+ error("exponent has no digits");
+ while (SYMOFCHAR(*digptr) == INTCONST)
+ ++digptr;
+ }
+ }
+ if (dflag)
+ {
+ constant.type = dtype;
+ digit = *digptr;
+ *digptr = 0;
+ constant.value.d = atof(constant.value.s);
+ *digptr = digit;
+ if (digit == 'F' || digit == 'f')
+ {
+ ++digptr;
+ constant.type = fltype;
+ constant.value.d = (float) constant.value.d;
+ }
+ sym = FLOATCONST;
+ if (*digptr != 0)
+ error("junk at end of floating point constant");
+ return;
+ }
+ if (base != 16)
+ digptr = constant.value.s;
+ constant.value.v = 0;
+ while (*digptr >= '0')
+ {
+ digit = *digptr;
+ if (digit > '9')
+ {
+ if (base != 16)
+ break;
+ if (digit >= 'a' && digit <= 'f')
+ digit = digit + (-'a' + '0' + 10);
+ else if (digit >= 'A' && digit <= 'F')
+ digit = digit + (-'A' + '0' + 10);
+ else
+ break;
+ }
+ constant.value.v = base * constant.value.v + (digit - '0');
+ ++digptr;
+ }
+ ucount = lcount = 0;
+ while (TRUE)
+ {
+ if (*digptr == 'L' || *digptr == 'l')
+ ++lcount;
+ else if (*digptr == 'U' || *digptr == 'u')
+ ++ucount;
+ else
+ break;
+ ++digptr;
+ }
+ if (lcount > 1)
+ error("more than one 'L' in integer constant");
+ if (ucount > 1)
+ error("more than one 'U' in integer constant");
+ if (constant.value.v <= maxintto && lcount == 0 && ucount == 0)
+ constant.type = itype;
+ else if (constant.value.v <= maxuintto && lcount == 0
+ && (base != 10 || ucount != 0))
+ constant.type = uitype;
+ else if (constant.value.v <= maxlongto && ucount == 0)
+ constant.type = ltype;
+ else
+ constant.type = ultype;
+ if (*digptr != 0)
+ error("junk at end of integer constant");
+}
+
+PUBLIC void nextsym()
+{
+ static char lastch;
+ register char *reglineptr;
+
+ while (TRUE) /* exit with short, fast returns */
+ {
+ reglineptr = lineptr;
+ while ((sym = SYMOFCHAR(*reglineptr)) == WHITESPACE)
+ ++reglineptr;
+ lastch = *reglineptr;
+ if (SYMOFCHAR(ch = *(lineptr = reglineptr + 1)) == SPECIALCHAR
+ && sym != SPECIALCHAR)
+ specialchar();
+ switch (sym)
+ {
+ case CHARCONST:
+ --lineptr;
+ ch = lastch; /* pushback */
+ stringorcharconst();
+ newstringorcharconst();
+ if (charptr == constant.value.s)
+ {
+ charptr = constant.value.s;
+ error("empty character constant");
+ constant.value.v = 0;
+ }
+ else
+ {
+ if (charptr != constant.value.s + 1)
+ error("character constant too long");
+ charptr = constant.value.s;
+ constant.value.v = *constant.value.s & CHMASKTO;
+ }
+ constant.type = itype;
+ return;
+ case CONTROL:
+ if (maclevel != 0)
+ {
+ error("# in a macro: not preprocessed"); /* XXX? */
+ return;
+ }
+ else
+ {
+ docontrol();
+ break;
+ }
+ case FLOATCONST:
+ if (SYMOFCHAR(ch) == INTCONST)
+ {
+ --lineptr;
+ ch = lastch;
+ intconst();
+ }
+ else
+ sym = STRUCELTOP;
+ return;
+ case IDENT:
+ --lineptr;
+ ch = lastch;
+ getident();
+ if ((gsymptr = findlorg(gsname)) != NULL)
+ {
+ if (gsymptr->flags == DEFINITION)
+ {
+ entermac();
+ break;
+ }
+ if (gsymptr->flags == KEYWORD)
+ sym = gsymptr->offset.offsym;
+ }
+ return;
+ case INTCONST:
+ --lineptr;
+ ch = lastch;
+ intconst();
+ return;
+ case SPECIALCHAR:
+ ch = *(lineptr = reglineptr);
+ specialchar();
+ if (ch == EOL)
+ {
+ if (incppexpr)
+ {
+ sym = SEMICOLON;
+ return;
+ }
+ skipeol();
+ if (eof)
+ {
+ sym = EOFSYM;
+ return;
+ }
+ break;
+ }
+ if (SYMOFCHAR(ch) != SPECIALCHAR)
+ break;
+ gch1();
+ /* fall through to BADCHAR case */
+ case BADCHAR:
+ error("illegal character");
+ break;
+ case STRINGCONST:
+ --lineptr;
+ ch = lastch; /* pushback */
+ stringorcharconst();
+ newstringorcharconst();
+#ifdef TS
+ ts_n_string += charptr - constant.value.s;
+#endif
+ return;
+ case COLON: /* could be COLONOP or in label */
+ case COMMA: /* could be COMMAOP or in list */
+ case CONDOP:
+ case LBRACE:
+ case LBRACKET:
+ case LPAREN:
+ case NOTOP:
+ case RBRACE:
+ case RBRACKET:
+ case RPAREN:
+ case SEMICOLON:
+ return;
+ case ASSIGNOP:
+ if (ch == '=')
+ {
+ sym = EQOP;
+ gch1();
+ }
+ return;
+ case ADDOP:
+ if (ch == '+')
+ {
+ sym = INCSYM; /* PREINCOP or POSINCOP */
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = ADDABOP;
+ gch1();
+ }
+ return;
+ case HYPHEN: /* NEGOP or SUBOP or decoded below */
+ if (ch == '-')
+ {
+ sym = DECSYM; /* PREDECOP or POSTDECOP */
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = SUBABOP;
+ gch1();
+ }
+ else if (ch == '>')
+ {
+ sym = STRUCPTROP;
+ gch1();
+ }
+ return;
+ case STAR: /* INDIRECTOP or MULOP or as below */
+ if (ch == '=')
+ {
+ sym = MULABOP;
+ gch1();
+ }
+ return;
+ case SLASH:
+ if (ch == '*')
+ {
+ skipcomment();
+ break;
+ }
+ if (ch == '=')
+ {
+ sym = DIVABOP;
+ gch1();
+ }
+ else
+ sym = DIVOP;
+ return;
+ case MODOP:
+ if (ch == '=')
+ {
+ sym = MODABOP;
+ gch1();
+ }
+ return;
+ case LTOP:
+ if (ch == '=')
+ {
+ sym = LEOP;
+ gch1();
+ }
+ else if (ch == '<')
+ {
+ gch1();
+ if (ch == '=')
+ {
+ sym = SLABOP;
+ gch1();
+ }
+ else
+ {
+ sym = SLOP;
+ }
+ }
+ return;
+ case GTOP:
+ if (ch == '=')
+ {
+ sym = GEOP;
+ gch1();
+ }
+ else if (ch == '>')
+ {
+ gch1();
+ if (ch == '=')
+ {
+ sym = SRABOP;
+ gch1();
+ }
+ else
+ {
+ sym = SROP;
+ }
+ }
+ return;
+ case AMPERSAND: /* ADDRESSOP or ANDOP or as below */
+ if (ch == '&')
+ {
+ sym = LOGANDOP;
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = ANDABOP;
+ gch1();
+ }
+ return;
+ case EOROP:
+ if (ch == '=')
+ {
+ sym = EORABOP;
+ gch1();
+ }
+ return;
+ case OROP:
+ if (ch == '|')
+ {
+ sym = LOGOROP;
+ gch1();
+ }
+ else if (ch == '=')
+ {
+ sym = ORABOP;
+ gch1();
+ }
+ return;
+ case LOGNOTOP:
+ if (ch == '=')
+ {
+ sym = NEOP;
+ gch1();
+ }
+ return;
+ }
+ }
+}
+
+PRIVATE void ppnumber()
+{
+ constant.value.s = charptr;
+ while (TRUE)
+ {
+ if (charptr >= char1top)
+ constant.value.s = growobject(constant.value.s, 2);
+ *charptr++ = ch;
+ if (ch == 'E' || ch == 'e')
+ {
+ gch1();
+ if (ch == '+' || ch == '-')
+ continue;
+ }
+ else
+ GCH1();
+ if (SYMOFCHAR(ch) > MAXPPNUMSYM)
+ break;
+ }
+ *charptr = 0;
+}
+
+PUBLIC void stringorcharconst()
+{
+ char terminator;
+
+ constant.value.s = charptr;
+ terminator = ch;
+ while (TRUE)
+ {
+ if (charptr >= char3top)
+ constant.value.s = growobject(constant.value.s, 4);
+ *charptr++ = ch;
+ if (ch == '\\')
+ {
+ gch1();
+ if (ch == EOL)
+ {
+ if (!orig_cppmode)
+ eofin("escape sequence");
+ break;
+ }
+ *charptr++ = ch;
+ }
+ GCH1();
+ if (ch == EOL)
+ {
+ if (!orig_cppmode)
+ error(terminator == '"' ? "end of line in string constant"
+ : "end of line in character constant");
+ break;
+ }
+ if (ch == terminator)
+ {
+ *charptr++ = terminator;
+ gch1();
+ break;
+ }
+ }
+}
+
+PRIVATE void newstringorcharconst()
+{
+ char *endinptr;
+ int escvalue;
+ fastin_t maxdigits;
+ register char *inptr;
+ register char *outptr;
+
+ outptr = constant.value.s;
+ inptr = charptr - 1;
+ if (inptr == outptr || *inptr != *outptr)
+ endinptr = charptr; /* not properly terminated */
+ else
+ endinptr = inptr;
+ inptr = outptr + 1;
+ while (inptr != endinptr)
+ {
+ if (*inptr == '\\')
+ {
+ if (++inptr == endinptr)
+ break; /* error reported already */
+ if (*inptr >= '0' && *inptr < '8')
+ {
+ escvalue = 0;
+ maxdigits = 3;
+ do
+ {
+ escvalue = 8 * escvalue + *inptr - '0';
+ ++inptr;
+ }
+ while (--maxdigits != 0 && *inptr >= '0' && *inptr < '8');
+ --inptr;
+ *outptr++ = escvalue;
+ }
+ else switch (*inptr)
+ {
+ case '"':
+ case '\'':
+ case '\\':
+ *outptr++ = *inptr;
+ break;
+ case 'a':
+ *outptr++ = 7;
+ break;
+ case 'b':
+ *outptr++ = 8;
+ break;
+ case 'f':
+ *outptr++ = 12;
+ break;
+ case 'n':
+ *outptr++ = EOLTO;
+ break;
+ case 'r':
+ *outptr++ = 13;
+ break;
+ case 't':
+ *outptr++ = 9;
+ break;
+ case 'v':
+ *outptr++ = 11;
+ break;
+ default:
+ error("%wnonstandard escape sequence");
+ *outptr++ = *inptr;
+ break;
+ }
+ }
+ else
+ *outptr++ = *inptr;
+ ++inptr;
+ }
+ charptr = outptr;
+}
diff --git a/bcc/scan.h b/bcc/scan.h
new file mode 100644
index 0000000..5333e96
--- /dev/null
+++ b/bcc/scan.h
@@ -0,0 +1,201 @@
+/* scan.h - scanner for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#define NAMESIZE 64 /* limit on identifier lengths */
+#define SYMOFCHAR(ch) (symofchar[(unsigned char) (ch)])
+
+/* scanner codes */
+
+enum
+{
+/* The first group of entries consists of all the values that occur in the
+ switch for cppscan().
+*/
+ IDENT,
+ INTCONST,
+#define MAXIDSYM INTCONST /* IDENT and INTCONST must be the only
+ * symofchar[] entries below this */
+ FLOATCONST,
+#define MAXPPNUMSYM FLOATCONST /* IDENT, INTCONST and FLOATCONST must be the
+ * only symofchar[] entries below this */
+ CHARCONST,
+ CONTROL,
+ SLASH,
+ SPECIALCHAR,
+ STRINGCONST,
+
+/* The next group of entries are all the rest of the values that occur in
+ symofchar[] and so in the switch for nextsym().
+*/
+ AMPERSAND, /* ADDRESSOP or ANDOP */
+ BADCHAR,
+ COLON, /* also COLONOP */
+ COMMA, /* also COMMAOP */
+ DECSYM, /* PREDECOP or POSTDECOP */
+ EOFSYM,
+ HYPHEN, /* NEGOP or SUBOP */
+ INCSYM, /* PREINCOP or POSTINCOP */
+ LBRACE,
+ LBRACKET,
+ LPAREN,
+ RBRACE,
+ RBRACKET,
+ RPAREN,
+ SEMICOLON,
+ STAR, /* INDIRECTOP or MULOP */
+ WHITESPACE,
+
+/* The next group of entries consists of all operator codes. These codes must
+ be contiguous so they can be used as (offsetted) array indexes. The group
+ is ordered by operator-precedence (this is not necessary). The first part
+ of it overlaps the previous group.
+*/
+
+/* Assign-abops (level 1) belong here but are at end to improve switch. */
+
+#define FIRSTOP CONDOP
+ CONDOP, /* level 2 */
+
+ OROP, /* level 5 */
+
+ EOROP, /* level 6 */
+
+ ANDOP, /* level 7 */
+
+ GTOP, /* level 9 */
+ LTOP,
+
+ ADDOP, /* level 11 */
+
+ DIVOP, /* level 12 */
+ MODOP,
+
+ LOGNOTOP, /* level 13 */
+ NOTOP,
+
+ STRUCELTOP, /* level 14 */
+ STRUCPTROP,
+
+/* End of symbols that appear in symofchar[]. */
+
+ ASSIGNOP, /* level 1 - assign ops must be contiguous */
+ ADDABOP,
+ ANDABOP,
+ DIVABOP,
+ EORABOP,
+ MODABOP,
+ MULABOP,
+ ORABOP,
+ SLABOP,
+ SRABOP,
+ SUBABOP,
+
+ COMMAOP, /* level 0 */
+
+ COLONOP, /* level 2 */
+
+ LOGOROP, /* level 3 */
+
+ LOGANDOP, /* level 4 */
+
+ EQOP, /* level 8 */
+ NEOP,
+
+ GEOP, /* level 9 */
+ LEOP,
+
+ SLOP, /* level 10 */
+ SROP,
+
+ SUBOP, /* level 11 */
+
+ MULOP, /* level 12 */
+
+ ADDRESSOP, /* level 13 */
+ CASTOP,
+ INDIRECTOP,
+ NEGOP,
+ PREDECOP,
+ PREINCOP,
+ POSTDECOP,
+ POSTINCOP,
+
+ FUNCOP, /* level 14 */
+ LISTOP,
+ ROOTLISTOP,
+
+ LEAF, /* special */
+ PTRADDABOP,
+ PTRADDOP,
+ PTRSUBOP,
+
+/* end of operator codes (they must stay contiguous) */
+
+#define LASTOP PTRSUBOP
+
+ ENUMDECL,
+ NULLDECL,
+ STRUCTDECL,
+ TYPEDECL,
+ TYPEDEFNAME,
+ UNIONDECL,
+ UNSIGNDECL,
+
+ AUTODECL,
+ EXTERNDECL,
+ REGDECL,
+ STATICDECL,
+ TYPEDEFDECL,
+
+ BREAKSYM,
+ CASESYM,
+ CONTSYM,
+ DEFAULTSYM,
+ DEFINEDSYM,
+ DOSYM,
+ ELSESYM,
+ FORSYM,
+ GOTOSYM,
+ IFSYM,
+ RETURNSYM,
+ SIZEOFSYM,
+ SWITCHSYM,
+ WHILESYM,
+
+ ASMCNTL,
+ DEFINECNTL,
+ ENDASMCNTL,
+ INCLUDECNTL,
+ LINECNTL,
+ UNDEFCNTL,
+
+ ELIFCNTL, /* "IF" controls must be contiguous */
+ ELSECNTL,
+ ENDIFCNTL,
+ IFCNTL,
+ IFDEFCNTL,
+ IFNDEFCNTL
+};
+
+EXTERN op_pt arg1op; /* LISTOP, or ROOTLISTOP if arg1inreg */
+EXTERN struct
+{
+ union
+ {
+ char *s;
+ value_t v;
+ double d;
+ }
+ value;
+ struct typestruct *type;
+}
+ constant; /* value of last constant scanned */
+ /* sym tells type */
+EXTERN char funcname[NAMESIZE]; /* name of current function for unique labels */
+EXTERN char gs2name[2 + NAMESIZE]; /* 2 reserved for namespace keys */
+#define gsname (gs2name + 2) /* before last identifier */
+EXTERN struct symstruct *gsymptr; /* symbol ptr for last identifier */
+EXTERN bool_t incppexpr; /* nonzero while scanning cpp expression */
+EXTERN sym_t sym; /* current symbol */
+extern sym_t symofchar[]; /* table to convert chars to their symbols */
diff --git a/bcc/sizes.h b/bcc/sizes.h
new file mode 100644
index 0000000..df0d141
--- /dev/null
+++ b/bcc/sizes.h
@@ -0,0 +1,50 @@
+/* sizes.h - target scalar type sizes for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ the compiler is not very portable in this area
+ it only directly supports I8088-I80386 and MC6809
+ it assumes
+ sizeof(source long) >= sizeof(target long)
+ usual register size = int
+ long = 2 int sizes
+*/
+
+#define CHBITSTO 8 /* bits in a character */
+#define CHMASKTO 0xFF /* mask to reduce SOURCE int to TARGET uchar */
+#define INT16BITSTO 16 /* not accessed in non-16 bit case */
+#define INT32BITSTO 32 /* not accessed in non-32 bit case */
+#define MAXINTBITSTO 32 /* max bits in an integer (var processors) */
+#define MAXSCHTO 127 /* maximum signed character */
+#define MAXUCHTO 255 /* maximum unsigned character */
+#define MINSCHTO (-128) /* minimum signed character */
+
+#ifdef MC6809
+# define is5bitoffset(n) ((uoffset_t) (n) + 0x10 < 0x20)
+#endif
+#define isbyteoffset(n) ((uoffset_t) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO)
+#define ischarconst(n) ((uvalue_t) (n) <= MAXUCHTO)
+#define isnegbyteoffset(n) ((uvalue_t) (n) + MAXSCHTO <= MAXSCHTO - MINSCHTO)
+#define isshortbranch(n) ((uoffset_t) (n) - MINSCHTO <= MAXSCHTO - MINSCHTO)
+
+#ifdef MC6809
+/* Hack to reduce number of direct page variables. */
+#define intmaskto ((uvalue_t) 0xFFFFL)
+#define maxintto ((uvalue_t) 0x7FFFL)
+#define maxlongto ((uvalue_t) 0x7FFFFFFFL)
+#define maxoffsetto ((uvalue_t) 0x7FFFL)
+#define maxshortto ((uvalue_t) 0x7FFFL)
+#define maxuintto ((uvalue_t) 0xFFFFL)
+#define maxushortto ((uvalue_t) 0xFFFFL)
+#define shortmaskto ((uvalue_t) 0xFFFFL)
+#else
+extern uvalue_t intmaskto; /* mask for ints */
+extern uvalue_t maxintto; /* maximum int */
+extern uvalue_t maxlongto; /* maximum long */
+extern uvalue_t maxoffsetto; /* maximum offset */
+extern uvalue_t maxshortto; /* maximum short */
+extern uvalue_t maxuintto; /* maximum unsigned */
+extern uvalue_t maxushortto; /* maximum unsigned short */
+extern uvalue_t shortmaskto; /* mask for shorts */
+#endif
diff --git a/bcc/softop.c b/bcc/softop.c
new file mode 100644
index 0000000..369ad96
--- /dev/null
+++ b/bcc/softop.c
@@ -0,0 +1,225 @@
+/* softop.c - software operations for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "gencode.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+/*-----------------------------------------------------------------------------
+ softop(operation code, source leaf, target leaf)
+ handles binary operations which are not done in hardware
+ if the result type is (unsigned) long, float or double, all the work
+ is immediately passed on to routines in other files. Otherwise:
+ source and target may be either char, int or unsigned int
+ they are not cast to ints or unsigneds before they get here
+ considerable effort goes into avoiding unnecessary pushes
+-----------------------------------------------------------------------------*/
+
+PUBLIC void softop(op, source, target)
+op_pt op;
+struct symstruct *source;
+struct symstruct *target;
+{
+ store_t regpushed;
+ store_t regmark;
+ scalar_t resultscalar;
+ scalar_t sscalar;
+ scalar_t tscalar;
+ value_t sourceval;
+ bool_t uflag;
+ store_t workreg;
+
+ if ((tscalar = target->type->scalar) & DLONG)
+ {
+ longop(op, source, target);
+ return;
+ }
+ if (tscalar & RSCALAR)
+ {
+ floatop(op, source, target);
+ return;
+ }
+ sscalar = source->type->scalar;
+ resultscalar = tscalar;
+ uflag = tscalar & UNSIGNED;
+ if (op != SLOP && op != SROP)
+ {
+ resultscalar |= sscalar;
+ uflag |= sscalar & UNSIGNED;
+ }
+#ifdef MC6809
+ if ((op_t) op == MULOP && sscalar & CHAR && tscalar & CHAR &&
+ (source->storage != CONSTANT || (uvalue_t) source->offset.offv > 2))
+ {
+ if (source->storage & WORKDATREGS)
+ push(source);
+ load(target, DREG);
+ outldmulreg();
+ outadr(source);
+ outmulmulreg();
+ target->storage = DREG;
+ target->type = iscalartotype(resultscalar);
+ return;
+ }
+#endif
+ if (source->storage == CONSTANT)
+ {
+ extend(target);
+#ifdef I8088
+ if (op == MULOP || op == SLOP)
+ loadany(target);
+ else
+#endif
+ load(target, DREG);
+ target->type = iscalartotype(resultscalar);
+ sourceval = source->offset.offv;
+ switch ((op_t) op)
+ {
+ case DIVOP:
+ if (diveasy(sourceval, uflag))
+ return;
+ break;
+ case MODOP:
+ if (modeasy(sourceval, uflag))
+ {
+ if ((uvalue_t) sourceval <= MAXUCHTO + 1)
+ {
+ target->storage = BREG;
+ target->type = ctype;
+ if (uflag)
+ target->type = uctype;
+ }
+ return;
+ }
+ break;
+ case MULOP:
+ if (muleasy((uvalue_t) sourceval, target->storage))
+ return;
+ load(target, DREG);
+ break;
+ case SLOP:
+ slconst(sourceval, target->storage);
+ return;
+ case SROP:
+ srconst(sourceval, uflag);
+ return;
+ }
+ sscalar = (source->type = iscalartotype(resultscalar))->scalar;
+ }
+
+/* to load source first if it is CHAR: */
+/* need work register if target is in WORKDATREGS */
+/* use OPREG unless it will become overloaded later */
+
+/* to preserve source while target is loaded: */
+/* if source is in WORKDATREGS, put it in OPREG, */
+/* unless target is OPREG-indirect */
+/* otherwise, if source is in WORKDATREGS, put it in work reg not OPREG */
+/* also assign a work reg if source is already in OPREG and target needs one */
+
+ regpushed = (regmark = reguse) & OPREG;
+ workreg = OPREG;
+ if ((sscalar & CHAR && target->storage & WORKDATREGS &&
+ source->storage == OPREG && source->indcount != 0) ||
+ ((sscalar & CHAR || source->storage & WORKDATREGS) &&
+ target->storage == OPREG && target->indcount != 0) ||
+#ifdef MC6809 /* for -Wall */
+ (
+#endif
+ (source->storage == OPREG &&
+ target->storage == GLOBAL && target->indcount == 0)
+#ifdef MC6809
+ && posindependent)
+#endif
+ )
+ {
+ if ((regmark | OPREG) == allindregs)
+ regpushed |= (workreg = OPWORKREG);
+ else
+ {
+ reguse |= OPREG;
+ workreg = getindexreg();
+ }
+ }
+ pushlist(regpushed); /* no more pushes */
+ reguse = allindregs; /* error if another reg unexpectedly needed */
+
+ if (sscalar & CHAR)
+ {
+ if (target->storage & WORKDATREGS)
+ {
+ extend(target);
+ if (source->storage == workreg)
+ exchange(source, target);
+ else
+ transfer(target, workreg);
+ }
+ extend(source);
+ if (target->storage != OPREG &&
+ (target->storage != GLOBAL || target->indcount != 0
+#ifdef MC6809
+ || !posindependent
+#endif
+ ))
+ workreg = OPREG;
+ }
+ if (source->storage & WORKDATREGS)
+ {
+ if (target->storage == OPREG && target->indcount == 0)
+ exchange(source, target);
+ else
+ {
+ transfer(source, workreg);
+ workreg = OPREG;
+ }
+ }
+ if (target->storage == GLOBAL && target->indcount == 0
+#ifdef MC6809
+ && posindependent
+#endif
+ )
+ load(target, workreg);
+
+/* source and target now in position to be loaded without any more registers */
+
+ extend(target);
+ load(target, DREG);
+ load(source, OPREG);
+ switch ((op_t) op)
+ {
+ case DIVOP:
+#ifdef I8088
+ call("idiv_");
+#else
+ call("idiv");
+#endif
+ break;
+ case MODOP:
+ call("imod");
+ break;
+ case MULOP:
+#ifdef I8088
+ call("imul_");
+#else
+ call("imul");
+#endif
+ break;
+ case SLOP:
+ call("isl");
+ break;
+ case SROP:
+ call("isr");
+ break;
+ }
+ if (uflag)
+ outbyte('u');
+ outnl();
+ target->type = iscalartotype(resultscalar);
+ poplist(regpushed);
+ reguse = regmark;
+}
diff --git a/bcc/state.c b/bcc/state.c
new file mode 100644
index 0000000..cc821e3
--- /dev/null
+++ b/bcc/state.c
@@ -0,0 +1,793 @@
+/* state.c - statement routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "condcode.h"
+#include "gencode.h"
+#include "input.h" /* just for ch and eof for label check */
+#include "label.h"
+#include "os.h" /* just for EOL */
+#include "parse.h"
+#include "reg.h"
+#include "scan.h"
+#include "sizes.h"
+#include "table.h"
+#include "type.h"
+
+#define COLONCHAR ':' /* for label */
+#define GROWCASES 64 /* extra cases for growth of switch struct */
+#define INITIALCASES 16 /* initial cases in switch structure */
+
+struct loopstruct
+{
+ label_t breaklab; /* destination for break */
+ label_t contlab; /* destination for continue */
+ struct nodestruct *etmark; /* expression tree built during loop */
+ struct symstruct *exprmark; /* expression symbols built during loop */
+ struct symstruct *locmark; /* local variables built during loop */
+ struct loopstruct *prevloop; /* previous active for, switch or while */
+ offset_t spmark; /* stack value for continue and break */
+};
+
+struct switchstruct
+{
+ struct casestruct *caseptr; /* current spot in caselist */
+ struct casestruct *casetop; /* last in caselist + 1 */
+ bool_t charselector; /* tells if case selector is char */
+ label_t dfaultlab; /* destination for default case (0 if none) */
+ struct switchstruct *prevswitch; /* previous active switch */
+ struct casestruct
+ {
+ value_t casevalue; /* value giving this case */
+ label_t caselabel; /* corresponding label */
+ }
+ caselist[INITIALCASES]; /* perhaps larger */
+};
+
+PRIVATE struct loopstruct *loopnow; /* currently active for/switch/while */
+ /* depends on NULL init */
+PRIVATE bool_t returnflag; /* set if last effective statement */
+ /* was a return */
+PRIVATE label_t swstacklab; /* label giving stack for switch statement */
+
+FORWARD void addloop P((struct loopstruct *newloop));
+FORWARD void badloop P((void));
+FORWARD void deleteloop P((void));
+FORWARD void evalexpression P((struct nodestruct *exp));
+FORWARD void exprstatement P((void));
+FORWARD bool_pt isforever P((struct nodestruct *exp));
+FORWARD void sort P((struct casestruct *caselist, int count));
+FORWARD void dobreak P((void));
+FORWARD void docase P((void));
+FORWARD void docont P((void));
+FORWARD void dodefault P((void));
+FORWARD void dodowhile P((void));
+FORWARD void dofor P((void));
+FORWARD void dogoto P((void));
+FORWARD void doif P((void));
+FORWARD void doreturn P((void));
+FORWARD void doswitch P((void));
+FORWARD void dowhile P((void));
+FORWARD void jumptocases P((void));
+FORWARD void statement P((void));
+
+/* --- utility routines --- */
+
+PRIVATE void addloop(newloop)
+struct loopstruct *newloop;
+{
+ newloop->breaklab = getlabel();
+ newloop->contlab = getlabel();
+ newloop->etmark = etptr;
+ newloop->exprmark = exprptr;
+ newloop->locmark = locptr;
+ newloop->prevloop = loopnow;
+ newloop->spmark = sp;
+ loopnow = newloop;
+}
+
+PRIVATE void badloop()
+{
+ error(" no active fors, switches or whiles");
+}
+
+PRIVATE void deleteloop()
+{
+ etptr = loopnow->etmark;
+ exprptr = loopnow->exprmark;
+ locptr = loopnow->locmark;
+ loopnow = loopnow->prevloop;
+}
+
+PRIVATE void evalexpression(exp)
+struct nodestruct *exp;
+{
+ offset_t spmark;
+
+ spmark = sp;
+ makeleaf(exp);
+ modstk(spmark);
+}
+
+PRIVATE void exprstatement()
+{
+ struct nodestruct *etmark;
+ struct symstruct *exprmark;
+
+ etmark = etptr;
+ exprmark = exprptr;
+ evalexpression(expression());
+ etptr = etmark;
+ exprptr = exprmark;
+}
+
+PRIVATE bool_pt isforever(exp)
+register struct nodestruct *exp;
+{
+ return exp == NULL ||
+ (exp->tag == LEAF && exp->left.symptr->storage == CONSTANT &&
+ exp->left.symptr->offset.offv != 0);
+}
+
+PRIVATE void sort(caselist, count) /* shell sort */
+struct casestruct *caselist;
+int count;
+{
+ register int gap;
+ register int i;
+ int j;
+ struct casestruct swaptemp;
+
+ gap = 1;
+ do
+ gap = 3 * gap + 1;
+ while (gap <= count);
+ while (gap != 1)
+ {
+ gap /= 3;
+ for (j = gap; j < count; ++j)
+ for (i = j - gap;
+ i >= 0 && caselist[i].casevalue > caselist[i + gap].casevalue;
+ i -= gap)
+ {
+ swaptemp = caselist[i];
+ caselist[i] = caselist[i + gap];
+ caselist[i + gap] = swaptemp;
+ }
+ }
+}
+
+/* --- syntax routines --- */
+
+/* ----------------------------------------------------------------------------
+ compound-statement:
+ "{" <declaration-list> <statement-list> "}"
+---------------------------------------------------------------------------- */
+
+PUBLIC void compound() /* have just seen "{" */
+{
+ struct symstruct *locmark;
+ store_t regmark;
+#ifdef FRAMEPOINTER
+ offset_t framepmark;
+ offset_t softspmark;
+#else
+ /* softsp == sp here unless level == ARGLEVEL so mark is unnec */
+ /* this is also true if funcsaveregsize != 0 but the tests are too messy */
+#endif
+ offset_t spmark;
+
+ locmark = locptr;
+ regmark = reguse;
+#ifdef FRAMEPOINTER
+ softspmark = softsp;
+ framepmark = framep;
+#endif
+ spmark = sp;
+ newlevel();
+ decllist();
+ softsp &= alignmask;
+ if (sym != RBRACE) /* no need for locals if empty compound */
+ reslocals();
+ returnflag = FALSE;
+ while (sym != RBRACE && sym != EOFSYM)
+ statement();
+ oldlevel();
+ if (!returnflag)
+ {
+ if (level != ARGLEVEL)
+ {
+ if (switchnow == NULL)
+ {
+#ifdef FRAMEPOINTER
+ if (framep != 0)
+ {
+ /* some args or locals, maybe at lower levels */
+ modstk(softspmark);
+ if (framep != framepmark)
+ /* frame was just set up */
+ popframe();
+ }
+#else
+ modstk(spmark);
+#endif
+ }
+ }
+ else
+ ret();
+ }
+#ifdef FRAMEPOINTER
+ framep = framepmark;
+ sp = spmark;
+ softsp = softspmark;
+#else
+ softsp = sp = spmark;
+#endif
+ reguse = regmark;
+ locptr = locmark;
+ rbrace();
+}
+
+PRIVATE void dobreak()
+{
+ offset_t spmark;
+
+ if (loopnow == NULL)
+ badloop();
+ else
+ {
+ if (switchnow == NULL)
+ {
+ spmark = sp;
+ modstk(loopnow->spmark);
+ sp = spmark;
+ }
+ jump(loopnow->breaklab);
+ }
+}
+
+PRIVATE void docase()
+{
+ value_t caseval;
+
+ caseval = constexpression() & intmaskto; /* FIXME: warn overflow */
+ if (caseval > maxintto)
+ caseval -= (maxuintto + 1);
+ colon();
+ if (switchnow == NULL)
+ error("case not in switch");
+ else
+ {
+ if (switchnow->charselector && (caseval < 0 || caseval > 255))
+ error("%wcase cannot be reached with char switch");
+ else
+ {
+ if (switchnow->caseptr >= switchnow->casetop)
+ {
+ int ncases;
+
+ ncases = (/* ptrdiff_t */ int)
+ (switchnow->caseptr - &switchnow->caselist[0]);
+ switchnow = realloc(switchnow,
+ (/* size_t */ unsigned)
+ ((char *) switchnow->caseptr
+ - (char *) switchnow)
+ + GROWCASES * sizeof (struct casestruct));
+#ifdef TS
+++ts_n_case_realloc;
+ts_s_case += GROWCASES * sizeof (struct casestruct);
+ts_s_case_tot += GROWCASES * sizeof (struct casestruct);
+#endif
+ if (switchnow == NULL)
+ outofmemoryerror("");
+ switchnow->caseptr = &switchnow->caselist[ncases];
+ switchnow->casetop = switchnow->caseptr + GROWCASES;
+ }
+ switchnow->caseptr->casevalue = caseval;
+ deflabel(switchnow->caseptr->caselabel = getlabel());
+ ++switchnow->caseptr;
+ }
+ }
+}
+
+PRIVATE void docont()
+{
+ struct loopstruct *contloop;
+ offset_t spmark;
+ struct switchstruct *switchthen;
+
+ for (contloop = loopnow, switchthen = switchnow; ;
+ contloop = contloop->prevloop, switchthen = switchthen->prevswitch)
+ {
+ if (contloop == NULL)
+ {
+ badloop();
+ return;
+ }
+ if (contloop->contlab != 0)
+ break;
+ }
+ if (switchnow == NULL)
+ {
+ spmark = sp;
+ modstk(contloop->spmark);
+ sp = spmark;
+ }
+ else if (switchthen == NULL)
+ {
+ outaddsp();
+ outshex(contloop->spmark);
+ outminus();
+ outswstacklab();
+#ifdef MC6809
+ outcregname(LOCAL);
+#endif
+#ifdef I8088
+ if (i386_32)
+ bumplc2();
+#endif
+ outnl();
+ }
+ jump(contloop->contlab);
+}
+
+PRIVATE void dodefault()
+{
+ colon();
+ if (switchnow == NULL)
+ error("default not in switch");
+ else if (switchnow->dfaultlab != 0)
+ error("multiple defaults");
+ else
+ deflabel(switchnow->dfaultlab = getlabel());
+}
+
+PRIVATE void dodowhile()
+{
+ struct loopstruct dwhileloop;
+ label_t dolab;
+
+ addloop(&dwhileloop);
+ deflabel(dolab = getlabel());
+ statement();
+ if (sym == WHILESYM)
+ nextsym();
+ else
+ error("missing while at end of do-while");
+ deflabel(dwhileloop.contlab);
+ lparen();
+ jumptrue(expression(), dolab);
+ rparen();
+ semicolon();
+ deflabel(dwhileloop.breaklab);
+ deleteloop();
+}
+
+PRIVATE void dofor()
+{
+ struct loopstruct forloop;
+ label_t forstatlab;
+ label_t fortestlab = 0; /* for -Wall */
+ struct nodestruct *testexp;
+ struct nodestruct *loopexp;
+
+ lparen();
+ if (sym != SEMICOLON)
+ exprstatement();
+ semicolon();
+ addloop(&forloop);
+ if (sym == SEMICOLON)
+ testexp = NULL;
+ else
+ testexp = expression(); /* remember test expression */
+ semicolon();
+ if (sym == RPAREN)
+ loopexp = NULL;
+ else
+ loopexp = expression(); /* remember loop expression */
+ rparen();
+ if (!isforever(testexp))
+ jump(fortestlab = getlabel()); /* test at bottom */
+ deflabel(forstatlab = getlabel()); /* back here if test succeeds */
+ statement();
+ deflabel(forloop.contlab);
+ if (loopexp != NULL)
+ evalexpression(loopexp);
+ if (isforever(testexp))
+ jump(forstatlab);
+ else
+ {
+ deflabel(fortestlab); /* test label */
+ jumptrue(testexp, forstatlab);
+ }
+ deflabel(forloop.breaklab);
+ deleteloop();
+}
+
+PRIVATE void dogoto()
+{
+ struct symstruct *symptr;
+
+ if (sym == IDENT || sym == TYPEDEFNAME)
+ {
+ symptr = namedlabel();
+/*
+ if (symptr->indcount == 4)
+ modstk(
+ else
+*/
+ adjsp(symptr->offset.offlabel);
+ jump(symptr->offset.offlabel);
+ nextsym();
+ }
+ else
+ error("need identifier");
+}
+
+PRIVATE void doif()
+{
+ struct nodestruct *etmark;
+ label_t elselab;
+ label_t exitlab;
+ struct symstruct *exprmark;
+
+ lparen();
+ etmark = etptr;
+ exprmark = exprptr;
+ jumpfalse(expression(), elselab = getlabel());
+ etptr = etmark;
+ exprptr = exprmark;
+ rparen();
+ statement(); /* true, do a statement */
+ if (sym == ELSESYM) /* "if .. else" statement */
+ {
+ nextsym();
+ jump(exitlab = getlabel()); /* over "else" label and code */
+ deflabel(elselab);
+ statement();
+ deflabel(exitlab);
+ }
+ else
+ deflabel(elselab);
+}
+
+PRIVATE void doreturn()
+{
+ offset_t spmark;
+
+ spmark = sp;
+ if (sym != SEMICOLON) /* returning expression */
+ loadretexpression();
+ ret(); /* clean up stack and return */
+ sp = spmark; /* restore stack for rest of function */
+}
+
+PRIVATE void doswitch()
+{
+ struct switchstruct *sw;
+ struct loopstruct switchloop;
+ offset_t spmark = 0; /* for -Wall */
+ label_t sdecidelab;
+
+ sw = (struct switchstruct *) ourmalloc(sizeof *sw);
+#ifdef TS
+++ts_n_case;
+ts_s_case += sizeof *sw;
+ts_s_case_tot += sizeof *sw;
+#endif
+ lparen();
+ sw->charselector = loadexpression(DREG, NULLTYPE)->scalar & CHAR;
+ rparen();
+ if (switchnow == NULL)
+ spmark = lowsp = sp;
+ addloop(&switchloop);
+ sw->dfaultlab = switchloop.contlab = 0; /* kill to show this is a switch */
+ sw->casetop = (sw->caseptr = sw->caselist) + INITIALCASES;
+ sw->prevswitch = switchnow;
+ jump(sdecidelab = getlabel()); /* to case decision label */
+ if (switchnow == NULL)
+ swstacklab = gethighlabel();
+ switchnow = sw;
+ statement(); /* cases */
+ sw = switchnow;
+ jump(switchloop.breaklab); /* over case decision to break label */
+ deflabel(sdecidelab);
+ if (sw->prevswitch == NULL)
+ modstk(lowsp);
+ jumptocases();
+ deflabel(switchloop.breaklab);
+ if ((switchnow = sw->prevswitch) == NULL)
+ {
+ equlab(swstacklab, lowsp);
+ clearswitchlabels();
+ modstk(spmark);
+ }
+ deleteloop();
+#ifdef TS
+ts_s_case_tot -= (char *) sw->casetop - (char *) sw;
+#endif
+ ourfree(sw);
+}
+
+PRIVATE void dowhile()
+{
+ struct loopstruct whileloop;
+ struct nodestruct *testexp;
+ label_t wstatlab;
+
+ lparen();
+ addloop(&whileloop);
+ testexp = expression();
+ rparen();
+ if (!isforever(testexp))
+ jump(whileloop.contlab); /* test at bottom */
+ deflabel(wstatlab = getlabel()); /* back here if test succeeds */
+ statement();
+ deflabel(whileloop.contlab);
+ jumptrue(testexp, wstatlab);
+ deflabel(whileloop.breaklab);
+ deleteloop();
+}
+
+PRIVATE void jumptocases()
+{
+ value_t basevalue;
+ struct casestruct *case1ptr;
+ struct casestruct *caseptr;
+ struct casestruct *casetop;
+ value_t caseval;
+ bool_t charselector;
+ bool_t dfaultflag;
+ label_t dfaultlab;
+ label_t jtablelab;
+ ccode_t lowcondition;
+ store_pt targreg;
+ label_t zjtablelab;
+
+ caseptr = switchnow->caselist;
+ casetop = switchnow->caseptr;
+ sort(caseptr, (/* ptrdiff_t */ int) (casetop - caseptr));
+ basevalue = 0;
+ if ((charselector = switchnow->charselector) != 0)
+ {
+ targreg = BREG;
+ lowcondition = LO;
+ }
+ else
+ {
+ targreg = DREG;
+ lowcondition = LT;
+ }
+ dfaultflag = TRUE;
+ if ((dfaultlab = switchnow->dfaultlab) == 0)
+ {
+ dfaultflag = FALSE;
+ dfaultlab = loopnow->breaklab;
+ }
+ --casetop;
+ for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr)
+ if (case1ptr->casevalue == (case1ptr + 1)->casevalue)
+ error("duplicate case in switch");
+ while (caseptr <= casetop)
+ {
+ outsub();
+ outimadj((offset_t) (caseptr->casevalue - basevalue), targreg);
+ basevalue = caseptr->casevalue;
+ for (case1ptr = caseptr; case1ptr < casetop; ++case1ptr)
+ if (case1ptr->casevalue < (case1ptr + 1)->casevalue - 10)
+ break;
+ if (case1ptr < caseptr + 5)
+ {
+ lbranch(EQ, caseptr->caselabel);
+ ++caseptr;
+ }
+ else
+ {
+ lbranch(lowcondition, dfaultlab);
+ outcmp();
+ outimadj((offset_t) (case1ptr->casevalue - basevalue), targreg);
+ lbranch(HI, zjtablelab = getlabel());
+ if (charselector)
+ ctoi();
+#ifdef MC6809
+ else
+ bumplc(); /* extra for CMPD */
+#endif
+ slconst((value_t) (ptypesize / 2), DREG);
+ /* really log ptypesize */
+ deflabel(jtablelab = casejump());
+#ifdef I8088
+ jtablelab = jtablelab; /* not used, allocated for regress */
+#endif
+ for (caseval = caseptr->casevalue; caseval <= case1ptr->casevalue;
+ ++caseval)
+ {
+#ifdef I8088
+ if (ptypesize > 2)
+ defdword();
+ else
+#endif
+ defword();
+ if (caseval != caseptr->casevalue)
+ outlabel(dfaultlab);
+ else
+ {
+ outlabel(caseptr->caselabel);
+ ++caseptr;
+ }
+#ifdef MC6809
+ if (posindependent)
+ {
+ outminus();
+ outlabel(jtablelab);
+ }
+#endif
+ bumplc2();
+#ifdef I8088
+ if (ptypesize > 2)
+ bumplc2();
+#endif
+ outnl();
+ }
+ deflabel(zjtablelab);
+ }
+ lowcondition = LO; /* 1st subtraction makes rest unsigned */
+ }
+ if (dfaultflag)
+ jump(dfaultlab);
+}
+
+PUBLIC void outswoffset (offset)
+offset_t offset;
+{
+#ifdef FRAMEPOINTER
+ outoffset(offset - softsp - framep);
+#else
+ outoffset(offset - softsp - sp);
+#endif
+ outplus();
+ outswstacklab();
+#ifdef I8088
+ bumplc();
+ if (i386_32)
+ bumplc2();
+#endif
+}
+
+PUBLIC void outswstacklab()
+{
+ outbyte(LOCALSTARTCHAR);
+ outlabel(swstacklab);
+}
+
+/* ----------------------------------------------------------------------------
+ statement:
+ <compound-statement>
+ <if-statement>
+ <while-statement>
+ <do-statement>
+ <for-statement>
+ <switch-statement>
+ <case-statement>
+ <default-statement>
+ <break-statement>
+ <continue-statement>
+ <return-statement>
+ <goto-statement>
+ <labelled-statement>
+ <null-statement>
+ <expression> ;
+---------------------------------------------------------------------------- */
+
+PRIVATE void statement()
+{
+#if 1
+ struct symstruct *symptr;
+#endif
+
+more:
+ switch (sym)
+ {
+ case LBRACE:
+ nextsym();
+ compound();
+ return;
+ case IFSYM:
+ nextsym();
+ doif();
+ break;
+ case WHILESYM:
+ nextsym();
+ dowhile();
+ break;
+ case FORSYM:
+ nextsym();
+ dofor();
+ break;
+ case RETURNSYM:
+ nextsym();
+ doreturn();
+ semicolon();
+ returnflag = TRUE;
+ return;
+ case SWITCHSYM:
+ nextsym();
+ doswitch();
+ break;
+ case BREAKSYM:
+ nextsym();
+ dobreak();
+ semicolon();
+ break;
+ case CASESYM:
+ nextsym();
+ docase();
+ goto more;
+ case DEFAULTSYM:
+ nextsym();
+ dodefault();
+ goto more;
+ case DOSYM:
+ nextsym();
+ dodowhile();
+ break;
+ case CONTSYM:
+ nextsym();
+ docont();
+ semicolon();
+ break;
+ case GOTOSYM:
+ nextsym();
+ dogoto();
+ semicolon();
+ break;
+ case SEMICOLON:
+ nextsym();
+ return;
+ case IDENT:
+ case TYPEDEFNAME:
+ blanks(); /* cannot afford nextsym() */
+ while (ch == EOL && !eof)
+ {
+ /* this now fails only on #controls and macros giving ':' */
+ skipeol();
+ blanks();
+ }
+ if (ch == COLONCHAR)
+ {
+#if 0
+ struct symstruct *symptr;
+#endif
+ symptr = namedlabel();
+ if (symptr->indcount != 2)
+ error("redefined label");
+ else
+ {
+ deflabel(symptr->offset.offlabel);
+ if (switchnow != NULL)
+ symptr->indcount = 3;
+ else
+ {
+ symptr->indcount = 4;
+ outbyte(LOCALSTARTCHAR);
+ outlabel(symptr->offset.offlabel);
+ outop0str("\t=\t");
+ outshex(sp);
+ outnl();
+ }
+ }
+ nextsym();
+ nextsym();
+ goto more;
+ }
+ /* else fall into default */
+ default:
+ exprstatement();
+ semicolon();
+ break;
+ }
+ returnflag = FALSE;
+}
diff --git a/bcc/table.c b/bcc/table.c
new file mode 100644
index 0000000..5a5c34e
--- /dev/null
+++ b/bcc/table.c
@@ -0,0 +1,668 @@
+/* table.c - table handler for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/* Can I now get rid of EXPRLEVEL? Yes, except expression symbols must
+ * usually be set to some level different from OFFKLUDGELEVEL.
+ */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "gencode.h"
+#include "os.h"
+#include "parse.h"
+#include "reg.h"
+#include "sc.h"
+#include "scan.h"
+#include "sizes.h"
+#include "type.h"
+
+#undef EXTERN
+#define EXTERN
+#include "table.h"
+
+#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */
+#define HASHTABSIZE 256
+#define MARKER ((unsigned) 0x18C396A5L) /* lint everywhere it is used */
+#define MAXEXPR 500
+#define MAXLOCAL 100
+#define NKEYWORDS 34
+#define NSCALTYPES 12
+#define STACKSPACE 256 /* punt for normal recursions - switch extra */
+
+struct keywordstruct
+{
+ char *kwname;
+ sym_t kwcode;
+};
+
+#ifdef HOLDSTRINGS
+struct string
+{
+ struct string *snext;
+ char *sptr;
+ char *stop;
+ label_t slabel;
+};
+#endif
+
+struct typedatastruct
+{
+ char *tdname;
+ bool_t tdkeyscalar;
+ scalar_t tdscalar;
+ smalin_t tdsize;
+ struct typestruct **tdtypeptr;
+};
+
+PRIVATE struct symstruct exprsyms[MAXEXPR];
+PRIVATE struct symstruct *hashtab[HASHTABSIZE];
+ /* depends on zero init */
+#ifdef HOLDSTRINGS
+PRIVATE struct string *laststring; /* last in list of strings */
+ /* depends on NULL init */
+#endif
+PUBLIC struct symstruct locsyms[MAXLOCAL];
+
+PRIVATE struct symstruct constemplate =
+{
+ CONSTANT, /* storage */
+ 0, /* indcount */
+ 0, /* flags */
+ EXPRLEVEL, /* level */
+ NULL, /* next */
+ NULL, /* prev */
+ NULL, /* type, init later to itype */
+ /* offset is a union, set every time constemplate is used */
+ /* name is a union, namea member is constant "\0" */
+};
+
+PRIVATE struct keywordstruct keywords[NKEYWORDS] =
+{
+ { "enum", ENUMDECL, },
+ { "struct", STRUCTDECL, },
+ { "union", UNIONDECL, },
+ { "unsigned", UNSIGNDECL, },
+
+ { "auto", AUTODECL, },
+ { "extern", EXTERNDECL, },
+ { "register", REGDECL, },
+ { "static", STATICDECL, },
+
+ { "typedef", TYPEDEFDECL, },
+
+ { "break", BREAKSYM, },
+ { "case", CASESYM, },
+ { "continue", CONTSYM, },
+ { "default", DEFAULTSYM, },
+ { "do", DOSYM, },
+ { "else", ELSESYM, },
+ { "for", FORSYM, },
+ { "goto", GOTOSYM, },
+ { "if", IFSYM, },
+ { "return", RETURNSYM, },
+ { "sizeof", SIZEOFSYM, },
+ { "switch", SWITCHSYM, },
+ { "while", WHILESYM, },
+
+ { "#asm", ASMCNTL, },
+ { "#define", DEFINECNTL, },
+ { "#else", ELSECNTL, },
+ { "#endasm", ENDASMCNTL, },
+ { "#endif", ENDIFCNTL, },
+ { "#if", IFCNTL, },
+ { "#ifdef", IFDEFCNTL, },
+ { "#include", INCLUDECNTL, },
+ { "#ifndef", IFNDEFCNTL, },
+ { "#line", LINECNTL, },
+ { "#undef", UNDEFCNTL, },
+
+ { "defined", DEFINEDSYM, }, /* should be deactivated except in #if's */
+};
+
+PRIVATE struct typedatastruct scaltypes[NSCALTYPES] =
+{
+ { "void", TRUE, 0, 0, &vtype, }, /* first - addkeyword uses vtype */
+ { "char", TRUE, CHAR, 1, &ctype, },
+ { "char", FALSE, UNSIGNED | CHAR, 1, &uctype, },
+ { "char", FALSE, CHAR, 1, &sctype, },
+ { "short", TRUE, SHORT, 2, &stype, },
+ { "short", FALSE, UNSIGNED | SHORT, 2, &ustype, },
+ { "int", TRUE, INT, 2, &itype, },
+ { "int", FALSE, UNSIGNED | INT, 2, &uitype, },
+ { "long", TRUE, LONG | DLONG, 4, &ltype, },
+ { "long", FALSE, UNSIGNED | LONG | DLONG, 4, &ultype, },
+ { "float", TRUE, FLOAT, 4, &fltype, },
+ { "double", TRUE, DOUBLE, 8, &dtype, },
+};
+
+FORWARD struct symstruct *addkeyword P((char *name, sym_pt code));
+FORWARD void heapcorrupterror P((void));
+
+PUBLIC struct symstruct *addglb(name, type)
+char *name;
+struct typestruct *type;
+{
+ struct symstruct **hashptr;
+ struct symstruct *oldsymptr = NULL; /* for -Wall */
+ register struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ {
+ oldsymptr = symptr;
+ symptr = symptr->next;
+ }
+ symptr = qmalloc(sizeof (struct symstruct) + strlen(name));
+#ifdef TS
+++ts_n_global;
+ts_size_global += sizeof (struct symstruct) + strlen(name);
+#endif
+ addsym(name, type, symptr);
+ symptr->storage = GLOBAL;
+ symptr->level = GLBLEVEL;
+ if (*hashptr == NULL)
+ {
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+ }
+ else
+ {
+ oldsymptr->next = symptr;
+ symptr->prev = &oldsymptr->next;
+ }
+ return symptr;
+}
+
+PRIVATE struct symstruct *addkeyword(name, code)
+char *name;
+sym_pt code;
+{
+ struct symstruct *symptr;
+
+ (symptr = addglb(name, vtype))->flags = KEYWORD;
+ symptr->offset.offsym = code;
+ return symptr;
+}
+
+PUBLIC struct symstruct *addloc(name, type)
+char *name;
+struct typestruct *type;
+{
+ struct symstruct **hashptr;
+ register struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ symptr = symptr->next;
+ symptr = locptr;
+ locptr = (struct symstruct *) align(&symptr->name.namea[strlen(name) + 1]);
+ if (locptr >= &locsyms[MAXLOCAL])
+ limiterror("too many local symbols (101)");
+ addsym(name, type, symptr);
+ if (type->constructor == FUNCTION)
+ symptr->storage = GLOBAL;
+ else
+ symptr->storage = LOCAL;
+ symptr->level = level;
+ if (*hashptr != NULL)
+ {
+ symptr->next = *hashptr;
+ symptr->next->prev = &symptr->next;
+ }
+ *hashptr = symptr;
+ symptr->prev = hashptr;
+ return symptr;
+}
+
+PUBLIC struct symstruct *addlorg(name, type)
+char *name;
+struct typestruct *type;
+{
+ if (level != GLBLEVEL)
+ return addloc(name, type);
+ return addglb(name, type);
+}
+
+PUBLIC void addsym(name, type, symptr)
+char *name;
+struct typestruct *type;
+register struct symstruct *symptr;
+{
+ if (type->constructor & (ARRAY | FUNCTION))
+ symptr->indcount = 0;
+ else
+ symptr->indcount = 1;
+ symptr->flags = 0;
+ symptr->next = NULL;
+ symptr->type = type;
+ symptr->offset.offi = 0;
+ strcpy(symptr->name.namea, name);
+}
+
+PUBLIC struct symstruct *constsym(longconst)
+value_t longconst;
+{
+ register struct symstruct *symptr;
+
+ symptr = exprsym(&constemplate);
+ symptr->offset.offv = longconst;
+ return symptr;
+}
+
+PUBLIC void delsym(symptr)
+register struct symstruct *symptr;
+{
+ if ((*(symptr->prev) = symptr->next) != NULL)
+ symptr->next->prev = symptr->prev;
+}
+
+/* dumpglbs() - define locations of globals and reserve space for them */
+
+PUBLIC void dumpglbs()
+{
+ int i;
+ register struct symstruct *symptr;
+ register struct typestruct *type;
+
+#ifdef TS
+extern char *brksize;
+struct ts
+{
+ char *what;
+ uvalue_t *where;
+};
+static struct ts ts[] =
+{
+ "ts_n_newtypelist ", &ts_n_newtypelist,
+ "ts_s_newtypelist ", &ts_s_newtypelist,
+ "ts_n_filename_term ", &ts_n_filename_term,
+ "ts_s_filename_term ", &ts_s_filename_term,
+ "ts_n_filename ", &ts_n_filename,
+ "ts_s_filename ", &ts_s_filename,
+ "ts_s_filename_tot ", &ts_s_filename_tot,
+ "ts_n_pathname ", &ts_n_pathname,
+ "ts_s_pathname ", &ts_s_pathname,
+ "ts_s_pathname_tot ", &ts_s_pathname_tot,
+ "ts_n_inputbuf ", &ts_n_inputbuf,
+ "ts_s_inputbuf ", &ts_s_inputbuf,
+ "ts_s_inputbuf_tot ", &ts_s_inputbuf_tot,
+ "ts_n_includelist ", &ts_n_includelist,
+ "ts_s_includelist ", &ts_s_includelist,
+ "ts_s_outputbuf ", &ts_s_outputbuf,
+ "ts_n_macstring_ident ", &ts_n_macstring_ident,
+ "ts_n_macstring_ordinary ", &ts_n_macstring_ordinary,
+ "ts_n_macstring_param ", &ts_n_macstring_param,
+ "ts_n_macstring_quoted ", &ts_n_macstring_quoted,
+ "ts_n_macstring_term ", &ts_n_macstring_term,
+ "ts_s_macstring ", &ts_s_macstring,
+ "ts_n_defines ", &ts_n_defines,
+ "ts_s_defines ", &ts_s_defines,
+ "ts_n_macparam ", &ts_n_macparam,
+ "ts_s_macparam ", &ts_s_macparam,
+ "ts_s_macparam_tot ", &ts_s_macparam_tot,
+ "ts_n_macparam_string_ordinary ", &ts_n_macparam_string_ordinary,
+ "ts_n_macparam_string_quoted ", &ts_n_macparam_string_quoted,
+ "ts_n_macparam_string_term ", &ts_n_macparam_string_term,
+ "ts_s_macparam_string ", &ts_s_macparam_string,
+ "ts_s_macparam_string_tot ", &ts_s_macparam_string_tot,
+ "ts_s_macparam_string_alloced ", &ts_s_macparam_string_alloced,
+ "ts_s_macparam_string_alloced_tot ", &ts_s_macparam_string_alloced_tot,
+ "ts_s_fakeline ", &ts_s_fakeline,
+ "ts_s_fakeline_tot ", &ts_s_fakeline_tot,
+ "ts_n_string ", &ts_n_string,
+ "ts_n_case ", &ts_n_case,
+ "ts_n_case_realloc ", &ts_n_case_realloc,
+ "ts_s_case ", &ts_s_case,
+ "ts_s_case_tot ", &ts_s_case_tot,
+ "ts_n_structname ", &ts_n_structname,
+ "ts_s_structname ", &ts_s_structname,
+ "ts_n_type ", &ts_n_type,
+ "ts_s_type ", &ts_s_type,
+ "ts_n_global ", &ts_n_global,
+ "ts_size_global ", &ts_size_global,
+ "ts_n_holdstr ", &ts_n_holdstr,
+ "ts_size_holdstr ", &ts_size_holdstr,
+ "ts_n_growobj ", &ts_n_growobj,
+ "ts_size_growobj_wasted ", &ts_size_growobj_wasted,
+ "ts_n_growheap ", &ts_n_growheap,
+ "ts_s_growheap ", &ts_s_growheap,
+};
+struct ts *tp;
+
+for (tp = &ts[0]; tp < &ts[sizeof ts / sizeof ts[0]]; ++tp)
+{
+ comment();
+ outstr(tp->what);
+ outstr("");
+ outuvalue(*tp->where);
+ outnl();
+}
+comment();
+outstr("brksize ");
+outhex((uvalue_t) brksize);
+outnl();
+#endif
+
+#ifndef DIRECTPAGE
+ bssseg();
+#endif
+ for (i = 0; i < HASHTABSIZE; ++i)
+ for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next)
+ if (symptr->storage == GLOBAL && !(symptr->flags & EXTERNAL)
+ && *symptr->name.namea >= 'A' && symptr->flags <= MAXDUMPFLAG
+ /* Don't access type unless flags <= MAXDUMPFLAG, because
+ * type is punned to a symbol pointer for the label chain
+ * and might be null.
+ */
+ && symptr->type->constructor != FUNCTION)
+ {
+#ifdef DIRECTPAGE
+ if (symptr->flags & DIRECTPAGE)
+ dpseg();
+ else
+ dseg();
+#endif
+ type = symptr->type;
+ if (symptr->flags & STATIC)
+ lcommon(symptr->name.namea);
+ else
+ common(symptr->name.namea);
+ outnhex(type->typesize);
+ }
+ if (printf_fp)
+ globl("__xfpcvt");
+ if (scanf_fp)
+ globl("__xfptvc");
+}
+
+/* dumplocs() - define offsets of current locals */
+
+PUBLIC void dumplocs()
+{
+ register struct symstruct *symptr;
+ int i;
+
+ for (i = 0; i < HASHTABSIZE; ++i)
+ for (symptr = hashtab[i]; symptr != NULL; symptr = symptr->next)
+ if (symptr->storage == LOCAL)
+ set(symptr->name.namea, symptr->offset.offi - sp);
+}
+
+#ifdef HOLDSTRINGS
+
+/* dumpstrings() - dump held-up strings */
+
+PUBLIC void dumpstrings()
+{
+ struct string *stringp;
+
+ dseg();
+ for (stringp = laststring; stringp != NULL; stringp = stringp->snext)
+ {
+ outnlabel(stringp->slabel);
+ defstr(stringp->sptr, stringp->stop, TRUE);
+ dataoffset += stringp->stop - stringp->sptr + 1;
+ }
+}
+
+#endif
+
+PUBLIC struct symstruct *exprsym(symptr)
+struct symstruct *symptr;
+{
+ register struct symstruct *newsymptr;
+
+ newsymptr = exprptr++;
+ if (exprptr >= &exprsyms[MAXEXPR])
+ limiterror("expression too complex (501 symbols)");
+ *newsymptr = *symptr;
+ newsymptr->level = EXPRLEVEL;
+ newsymptr->name.namep = symptr->name.namea;
+ return newsymptr;
+}
+
+PUBLIC struct symstruct *findlorg(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (strcmp(symptr->name.namea, name) != 0 ||
+ symptr->flags == STRUCTNAME))
+ symptr = symptr->next;
+ return symptr;
+}
+
+PUBLIC struct symstruct *findstruct(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (symptr->flags != STRUCTNAME ||
+ strcmp(symptr->name.namea, name) != 0))
+ symptr = symptr->next;
+ return symptr;
+}
+
+/* convert name to a hash table ptr */
+
+PUBLIC struct symstruct **gethashptr(sname)
+char *sname;
+{
+ register int hashval;
+ register char *rsname;
+
+ hashval = 0;
+ rsname = sname;
+#if 1
+ while (*rsname)
+ hashval = hashval * 2 + *rsname++;
+#else
+ hashval = rsname[0];
+ if (rsname[1] != 0)
+ hashval = (rsname[2] << 2) ^ rsname[1] ^ (rsname[0] << 1);
+ else
+ hashval = rsname[0];
+#endif
+ return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1));
+}
+
+PRIVATE void heapcorrupterror()
+{
+ outofmemoryerror(" (heap corrupt - stack overflow?)");
+}
+
+#ifdef HOLDSTRINGS
+
+/* hold string for dumping at end, to avoid mixing it with other data */
+
+PUBLIC label_t holdstr(sptr, stop)
+char *sptr;
+char *stop;
+{
+ register struct string *stringp;
+
+ stringp = qmalloc(sizeof *stringp);
+#ifdef TS
+++ts_n_holdstr;
+ts_size_holdstr += sizeof *stringp;
+#endif
+ stringp->snext = laststring;
+ stringp->sptr = sptr;
+ stringp->stop = stop;
+ laststring = stringp;
+ return stringp->slabel = getlabel();
+}
+
+#endif /* HOLDSTRINGS */
+
+PUBLIC void newlevel()
+{
+ if (*(unsigned *) chartop != MARKER)
+ heapcorrupterror();
+ if (level >= MAXLEVEL)
+ limiterror("compound statements nested too deeply (126 levels)");
+ else
+ ++level;
+}
+
+PUBLIC void oldlevel()
+{
+ register struct symstruct *symptr;
+
+ if (*(unsigned *) chartop != MARKER)
+ heapcorrupterror();
+ if (level == 0)
+ bugerror("not in a compound statement");
+ else
+ --level;
+ for (symptr = &locsyms[0]; symptr < locptr;
+ symptr = (struct symstruct *)
+ align(&symptr->name.namea[strlen(symptr->name.namea) + 1]))
+ if (symptr->level > level)
+ delsym(symptr);
+}
+
+PUBLIC void ourfree(ptr)
+void *ptr;
+{
+ free(ptr);
+}
+
+PUBLIC void *ourmalloc(nbytes)
+unsigned nbytes;
+{
+ void *ptr;
+
+ if ((ptr = malloc(nbytes)) == NULL)
+ outofmemoryerror("");
+ return ptr;
+}
+
+PUBLIC void outofmemoryerror(message)
+char *message;
+{
+ error2error("compiler out of memory", message);
+
+#if defined(DEBUG) && 0
+ {
+ unsigned size;
+ char *ptr;
+
+ for (size = 0x1000; size != 0; --size)
+ if ((ptr = malloc(size)) != NULL)
+ {
+ outstr("found free memory at ");
+ outuvalue((uvalue_t) ptr);
+ outstr(" size ");
+ outuvalue((uvalue_t) size);
+ outnl();
+ }
+ }
+#endif
+
+ finishup();
+}
+
+PUBLIC void *growobject(object, extra)
+void *object;
+unsigned extra;
+{
+ /* size_t */ unsigned oblength;
+
+ /* It would be nice to realloc the previous memory if it can be left in
+ * the same place. Since a realloc that moves the memory can almost be
+ * relied on to mess up pointers before *obptr, and since malloc(extra)
+ * would be unlikely to produce memory adjoining chartop, it is not
+ * clear how to do this.
+ */
+#ifdef TS
+ts_size_growobj_wasted += chartop - (char *) object;
+#endif
+ oblength = (/* size_t */ unsigned) (charptr - (char *) object);
+ growheap(oblength + extra);
+#ifdef TS
+++ts_n_growobj;
+#endif
+ memcpy(charptr, object, oblength);
+ object = charptr;
+ charptr += oblength;
+ return object;
+}
+
+#define ALLOC_UNIT ((unsigned) 0x400)
+#ifdef S_ALIGNMENT
+#define ALLOC_OVERHEAD (S_ALIGNMENT - 1 + sizeof (unsigned))
+#else
+#define ALLOC_OVERHEAD (sizeof (unsigned))
+#endif
+
+PUBLIC void growheap(size)
+unsigned size;
+{
+ register char *newptr;
+
+ if ((newptr = malloc(size += ALLOC_UNIT + ALLOC_OVERHEAD)) == NULL
+ && (newptr = malloc(size -= ALLOC_UNIT)) == NULL)
+ outofmemoryerror("");
+#ifdef TS
+++ts_n_growheap;
+ts_s_growheap += size;
+#endif
+ charptr = newptr;
+ newptr = (char *) align(newptr + size - ALLOC_OVERHEAD);
+ chartop = newptr;
+ char1top = newptr - 1;
+ char3top = newptr - 3;
+ *(unsigned *) newptr = MARKER;
+}
+
+PUBLIC void *qmalloc(size)
+unsigned size;
+{
+ register char *ptr;
+
+ if ((charptr = (char *) align(charptr)) + size > chartop)
+ growheap(size);
+ ptr = charptr;
+ charptr += size;
+ return ptr;
+}
+
+PUBLIC void swapsym(sym1, sym2)
+struct symstruct *sym1;
+struct symstruct *sym2;
+{
+ struct symstruct swaptemp;
+
+ swaptemp = *sym1;
+ *sym1 = *sym2;
+ *sym2 = swaptemp;
+}
+
+PUBLIC void syminit()
+{
+ struct keywordstruct *kwptr;
+ struct typedatastruct *tdptr;
+ struct typestruct *type;
+
+ exprptr = exprsyms;
+ locptr = locsyms;
+ for (tdptr = scaltypes; tdptr < scaltypes + NSCALTYPES; ++tdptr)
+ {
+ (*tdptr->tdtypeptr = type = newtype())->scalar = tdptr->tdscalar;
+ type->alignmask = ~((type->typesize = tdptr->tdsize) - 1) |
+ alignmask;
+ type->tname = tdptr->tdname;
+ if (tdptr->tdkeyscalar)
+ addkeyword(tdptr->tdname, TYPEDECL)->type = type;
+ }
+ for (kwptr = keywords; kwptr < keywords + NKEYWORDS; ++kwptr)
+ addkeyword(kwptr->kwname, kwptr->kwcode);
+ constemplate.type = itype;
+}
diff --git a/bcc/table.h b/bcc/table.h
new file mode 100644
index 0000000..f9b2f38
--- /dev/null
+++ b/bcc/table.h
@@ -0,0 +1,71 @@
+/* table.h - table handler for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+EXTERN char *charptr; /* next free spot in catchall table */
+EXTERN char *chartop; /* spot after last in table */
+EXTERN char *char1top; /* last character spot in table */
+EXTERN char *char3top; /* third last character spot in table */
+EXTERN struct symstruct *exprptr;
+ /* next entry in expression symbol table */
+EXTERN struct symstruct *locptr;
+ /* next entry in local symbol table */
+extern struct symstruct locsyms[];
+ /* local symbol table */
+
+#define TS1
+#ifdef TS
+uvalue_t ts_n_newtypelist;
+uvalue_t ts_s_newtypelist;
+uvalue_t ts_n_filename_term;
+uvalue_t ts_s_filename_term;
+uvalue_t ts_n_filename;
+uvalue_t ts_s_filename;
+uvalue_t ts_s_filename_tot;
+uvalue_t ts_n_pathname;
+uvalue_t ts_s_pathname;
+uvalue_t ts_s_pathname_tot;
+uvalue_t ts_n_inputbuf;
+uvalue_t ts_s_inputbuf;
+uvalue_t ts_s_inputbuf_tot;
+uvalue_t ts_n_includelist;
+uvalue_t ts_s_includelist;
+uvalue_t ts_s_outputbuf;
+uvalue_t ts_n_macstring_ident;
+uvalue_t ts_n_macstring_ordinary;
+uvalue_t ts_n_macstring_param;
+uvalue_t ts_n_macstring_quoted;
+uvalue_t ts_n_macstring_term;
+uvalue_t ts_s_macstring;
+uvalue_t ts_n_defines;
+uvalue_t ts_s_defines;
+uvalue_t ts_n_macparam;
+uvalue_t ts_s_macparam;
+uvalue_t ts_s_macparam_tot;
+uvalue_t ts_n_macparam_string_ordinary;
+uvalue_t ts_n_macparam_string_quoted;
+uvalue_t ts_n_macparam_string_term;
+uvalue_t ts_s_macparam_string;
+uvalue_t ts_s_macparam_string_tot;
+uvalue_t ts_s_macparam_string_alloced;
+uvalue_t ts_s_macparam_string_alloced_tot;
+uvalue_t ts_s_fakeline;
+uvalue_t ts_s_fakeline_tot;
+uvalue_t ts_n_string;
+uvalue_t ts_n_case;
+uvalue_t ts_n_case_realloc;
+uvalue_t ts_s_case;
+uvalue_t ts_s_case_tot;
+uvalue_t ts_n_structname;
+uvalue_t ts_s_structname;
+uvalue_t ts_n_type;
+uvalue_t ts_s_type;
+uvalue_t ts_n_global;
+uvalue_t ts_size_global;
+uvalue_t ts_n_holdstr;
+uvalue_t ts_size_holdstr;
+uvalue_t ts_n_growobj;
+uvalue_t ts_size_growobj_wasted;
+uvalue_t ts_n_growheap;
+uvalue_t ts_s_growheap;
+#endif
diff --git a/bcc/tags b/bcc/tags
new file mode 100644
index 0000000..c0babfc
--- /dev/null
+++ b/bcc/tags
@@ -0,0 +1,341 @@
+adc0 codefrag.c /^PUBLIC void adc0()$/
+add hardop.c /^PUBLIC void add(source, target)$/
+addconst codefrag.c /^PUBLIC void addconst(offset, reg)$/
+addglb table.c /^PUBLIC struct symstruct *addglb(name, type)$/
+addloc table.c /^PUBLIC struct symstruct *addloc(name, type)$/
+addlorg table.c /^PUBLIC struct symstruct *addlorg(name, type)$/
+addoffset genloads.c /^PUBLIC void addoffset(source)$/
+address genloads.c /^PUBLIC void address(source)$/
+addstruct type.c /^PUBLIC struct typestruct *addstruct(structname)$/
+addsym table.c /^PUBLIC void addsym(name, type, symptr)$/
+adjlc codefrag.c /^PUBLIC void adjlc(offset, reg)$/
+adjsp codefrag.c /^PUBLIC void adjsp(label)$/
+andconst codefrag.c /^PUBLIC void andconst(offset)$/
+assign assign.c /^PUBLIC void assign(source, target)$/
+assignment_exp express.c /^PUBLIC struct nodestruct *assignment_exp()$/
+bileaf gencode.c /^PUBLIC void bileaf(exp)$/
+bitcount gencode.c /^PUBLIC fastin_pt bitcount(number)$/
+blanks scan.c /^PUBLIC void blanks()$/
+blanksident preproc.c /^PUBLIC bool_pt blanksident()$/
+bssseg codefrag.c /^PUBLIC void bssseg()$/
+bugerror output.c /^PUBLIC void bugerror(message)$/
+bumplc label.c /^PUBLIC void bumplc()$/
+bumplc2 label.c /^PUBLIC void bumplc2()$/
+bumplc3 label.c /^PUBLIC void bumplc3()$/
+call function.c /^PUBLIC void call(name)$/
+casejump codefrag.c /^PUBLIC label_t casejump()$/
+cast assign.c /^PUBLIC void cast(type, target)$/
+castnode exptree.c /^PUBLIC struct nodestruct *castnode(type, nodeptr)$/
+changesp preserve.c /^PUBLIC void changesp(newsp, absflag)$/
+checknotinif preproc.c /^PUBLIC void checknotinif()$/
+clearfunclabels label.c /^PUBLIC void clearfunclabels()$/
+clearlabels label.c /^PUBLIC void clearlabels(patchbuf, patchtop)$/
+clearswitchlabels label.c /^PUBLIC void clearswitchlabels()$/
+closein input.c /^PUBLIC void closein()$/
+closeout output.c /^PUBLIC void closeout()$/
+clrBreg codefrag.c /^PUBLIC void clrBreg()$/
+clrBreg codefrag.c /^PUBLIC void clrBreg()$/
+cmp glogcode.c /^PUBLIC void cmp(source, target, pcondtrue)$/
+codeinit gencode.c /^PUBLIC void codeinit()$/
+colon declare.c /^PUBLIC void colon()$/
+comDreg codefrag.c /^PUBLIC void comDreg()$/
+comDreg codefrag.c /^PUBLIC void comDreg()$/
+comment codefrag.c /^PUBLIC void comment()$/
+comment codefrag.c /^PUBLIC void comment()$/
+common codefrag.c /^PUBLIC void common(name)$/
+compound state.c /^PUBLIC void compound() /* have just seen "{" */$/
+condop glogcode.c /^PUBLIC void condop(exp)$/
+constexpression loadexp.c /^PUBLIC value_t constexpression()$/
+constsym table.c /^PUBLIC struct symstruct *constsym(longconst)$/
+cppscan scan.c /^PUBLIC void cppscan()$/
+cseg codefrag.c /^PUBLIC void cseg()$/
+ctoi codefrag.c /^PUBLIC void ctoi()$/
+ctoi codefrag.c /^PUBLIC void ctoi()$/
+dbitem debug.c /^PUBLIC void dbitem(item)$/
+dbtype debug.c /^PUBLIC void dbtype(type)$/
+debug debug.c /^PUBLIC void debug(exp) /* sub-nodes must be leaves */$/
+debugswap debug.c /^PUBLIC void debugswap()$/
+decllist declare.c /^PUBLIC void decllist()$/
+defbyte codefrag.c /^PUBLIC void defbyte()$/
+defbyte codefrag.c /^PUBLIC void defbyte()$/
+defdword codefrag.c /^PUBLIC void defdword()$/
+define preproc.c /^PUBLIC void define()$/
+definestring preproc.c /^PUBLIC void definestring(str)$/
+deflabel label.c /^PUBLIC void deflabel(label)$/
+deflong codefrag.c /^PUBLIC void deflong(value)$/
+defnulls codefrag.c /^PUBLIC void defnulls(nullcount)$/
+defstr codefrag.c /^PUBLIC label_t defstr(sptr, stop, dataflag)$/
+defword codefrag.c /^PUBLIC void defword()$/
+defword codefrag.c /^PUBLIC void defword()$/
+defword codefrag.c /^PUBLIC void defword()$/
+delsym table.c /^PUBLIC void delsym(symptr)$/
+diveasy codefrag.c /^PUBLIC bool_pt diveasy(divisor, uflag)$/
+docontrol preproc.c /^PUBLIC void docontrol()$/
+dpseg codefrag.c /^PUBLIC void dpseg()$/
+dseg codefrag.c /^PUBLIC void dseg()$/
+dumpglbs table.c /^PUBLIC void dumpglbs()$/
+dumplocs table.c /^PUBLIC void dumplocs()$/
+dumpstrings table.c /^PUBLIC void dumpstrings()$/
+entermac preproc.c /^PUBLIC void entermac()$/
+eofin scan.c /^PUBLIC void eofin(message)$/
+equ codefrag.c /^PUBLIC void equ(name, string)$/
+equlab codefrag.c /^PUBLIC void equlab(label, offset)$/
+error output.c /^PUBLIC void error(message)$/
+error2error output.c /^PUBLIC void error2error(message1, message2)$/
+errorloc input.c /^PUBLIC void errorloc()$/
+etreeinit exptree.c /^PUBLIC void etreeinit()$/
+even codefrag.c /^PUBLIC void even()$/
+exchange genloads.c /^PUBLIC void exchange(source, target)$/
+expression express.c /^PUBLIC struct nodestruct *expression()$/
+exprsym table.c /^PUBLIC struct symstruct *exprsym(symptr)$/
+extend assign.c /^PUBLIC void extend(target)$/
+f_indirect floatop.c /^PUBLIC bool_pt f_indirect(target)$/
+fatalerror output.c /^PUBLIC void fatalerror(message)$/
+findlorg table.c /^PUBLIC struct symstruct *findlorg(name)$/
+findstruct table.c /^PUBLIC struct symstruct *findstruct(name)$/
+finishup output.c /^PUBLIC void finishup()$/
+float1op floatop.c /^PUBLIC void float1op(op, source)$/
+floatop floatop.c /^PUBLIC void floatop(op, source, target)$/
+flushout output.c /^PUBLIC void flushout()$/
+for table.c /^ for (i = 0; i < HASHTABSIZE; ++i)$/
+for table.c /^for (tp = &ts[0]; tp < &ts[sizeof ts / sizeof ts[0]]; ++tp)$/
+fpush floatop.c /^PUBLIC void fpush(source)$/
+function function.c /^PUBLIC void function(source)$/
+gch1 input.c /^PUBLIC void gch1()$/
+gethashptr table.c /^PUBLIC struct symstruct **gethashptr(sname)$/
+gethighlabel label.c /^PUBLIC label_t gethighlabel()$/
+getindexreg genloads.c /^PUBLIC store_pt getindexreg()$/
+getlabel label.c /^PUBLIC label_t getlabel()$/
+getlc label.c /^PUBLIC uoffset_t getlc()$/
+globl codefrag.c /^PUBLIC void globl(name)$/
+growheap table.c /^PUBLIC void growheap(size)$/
+growobject table.c /^PUBLIC void *growobject(object, extra)$/
+highbit gencode.c /^PUBLIC fastin_pt highbit(number)$/
+holdstr table.c /^PUBLIC label_t holdstr(sptr, stop)$/
+ifinit preproc.c /^PUBLIC void ifinit()$/
+import codefrag.c /^PUBLIC void import(name)$/
+incdec hardop.c /^PUBLIC void incdec(op, source)$/
+include input.c /^PUBLIC void include()$/
+indexadr genloads.c /^PUBLIC void indexadr(source, target)$/
+indirec genloads.c /^PUBLIC void indirec(source)$/
+initexpression loadexp.c /^PUBLIC void initexpression(type)$/
+initout output.c /^PUBLIC void initout()$/
+iscalartotype type.c /^PUBLIC struct typestruct *iscalartotype(scalar)$/
+isident scan.c /^PUBLIC bool_pt isident()$/
+itol codefrag.c /^PUBLIC void itol(reg)$/
+jump label.c /^PUBLIC void jump(label)$/
+jumpfalse glogcode.c /^PUBLIC void jumpfalse(exp, label)$/
+jumptrue glogcode.c /^PUBLIC void jumptrue(exp, label)$/
+justpushed floatop.c /^PUBLIC void justpushed(target)$/
+lbranch label.c /^PUBLIC void lbranch(cond, label)$/
+lcommlab codefrag.c /^PUBLIC void lcommlab(label)$/
+lcommon codefrag.c /^PUBLIC void lcommon(name)$/
+ldregargs function.c /^PUBLIC void ldregargs()$/
+lea codefrag.c /^PUBLIC void lea(offset, sourcereg, targreg)$/
+leafnode exptree.c /^PUBLIC struct nodestruct *leafnode(source)$/
+leavemac preproc.c /^PUBLIC void leavemac()$/
+limiterror output.c /^PUBLIC void limiterror(message)$/
+listo function.c /^PUBLIC void listo(target, lastargsp)$/
+listroot function.c /^PUBLIC void listroot(target)$/
+load genloads.c /^PUBLIC void load(source, targreg)$/
+loadany genloads.c /^PUBLIC void loadany(source)$/
+loadconst codefrag.c /^PUBLIC void loadconst(offset, reg)$/
+loadexpression loadexp.c /^PUBLIC struct typestruct *loadexpression(targreg, targtype)$/
+loadpres preserve.c /^PUBLIC void loadpres(source, target)$/
+loadreg genloads.c /^PUBLIC void loadreg(source, targreg)$/
+loadretexpression function.c /^PUBLIC void loadretexpression()$/
+logop glogcode.c /^PUBLIC void logop(exp)$/
+long1op longop.c /^PUBLIC void long1op(op, target)$/
+longop longop.c /^PUBLIC void longop(op, source, target)$/
+lparen declare.c /^PUBLIC void lparen()$/
+lslconst codefrag.c /^PUBLIC int lslconst(shift, reg)$/
+lsrconst codefrag.c /^PUBLIC int lsrconst(shift, reg, uflag)$/
+main bcc-cc1.c /^PUBLIC int main(argc, argv)$/
+main bcc.c /^PUBLIC int main(argc, argv)$/
+makeleaf gencode.c /^PUBLIC void makeleaf(exp)$/
+makelessindirect genloads.c /^PUBLIC void makelessindirect(source)$/
+modeasy codefrag.c /^PUBLIC bool_pt modeasy(divisor, uflag)$/
+modstk preserve.c /^PUBLIC void modstk(newsp)$/
+movereg genloads.c /^PUBLIC void movereg(source, targreg)$/
+muleasy codefrag.c /^PUBLIC bool_pt muleasy(factor, reg)$/
+namedlabel label.c /^PUBLIC struct symstruct *namedlabel()$/
+needvarname declare.c /^PUBLIC void needvarname()$/
+neg hardop.c /^PUBLIC void neg(target)$/
+negDreg codefrag.c /^PUBLIC void negDreg()$/
+negDreg codefrag.c /^PUBLIC void negDreg()$/
+negreg codefrag.c /^PUBLIC void negreg(reg)$/
+newlevel table.c /^PUBLIC void newlevel()$/
+newtype type.c /^PUBLIC struct typestruct *newtype()$/
+nextsym scan.c /^PUBLIC void nextsym()$/
+node exptree.c /^PUBLIC struct nodestruct *node(t, p1, p2)$/
+not hardop.c /^PUBLIC void not(target)$/
+oldlevel table.c /^PUBLIC void oldlevel()$/
+onstack genloads.c /^PUBLIC void onstack(target)$/
+op1 hardop.c /^PUBLIC void op1(op, source, target)$/
+openio input.c /^PUBLIC void openio(argc, argv)$/
+openout output.c /^PUBLIC void openout(oname)$/
+opstring codefrag.c /^PUBLIC char *opstring(op)$/
+ourfree table.c /^PUBLIC void ourfree(ptr)$/
+ourmalloc table.c /^PUBLIC void *ourmalloc(nbytes)$/
+outABX codefrag.c /^PUBLIC void outABX()$/
+outadd codefrag.c /^PUBLIC void outadd()$/
+outadd codefrag.c /^PUBLIC void outadd()$/
+outaddsp codefrag.c /^PUBLIC void outaddsp()$/
+outaddsp codefrag.c /^PUBLIC void outaddsp()$/
+outadr genloads.c /^PUBLIC void outadr(adr)$/
+outbyte output.c /^PUBLIC void outbyte(c)$/
+outcalladr codefrag.c /^PUBLIC void outcalladr()$/
+outcalladr codefrag.c /^PUBLIC void outcalladr()$/
+outcalladr codefrag.c /^PUBLIC void outcalladr()$/
+outccname codefrag.c /^PUBLIC void outccname(name)$/
+outcmp codefrag.c /^PUBLIC void outcmp()$/
+outcmp codefrag.c /^PUBLIC void outcmp()$/
+outcomma output.c /^PUBLIC void outcomma()$/
+outcond label.c /^PUBLIC void outcond(cond)$/
+outcpplinenumber output.c /^PUBLIC void outcpplinenumber(nr, fname, str)$/
+outcregname genloads.c /^PUBLIC void outcregname(reg)$/
+outdec codefrag.c /^PUBLIC void outdec()$/
+outdec codefrag.c /^PUBLIC void outdec()$/
+outdirectpage codefrag.c /^PUBLIC void outdirectpage()$/
+outdword codefrag.c /^PUBLIC void outdword()$/
+outextended codefrag.c /^PUBLIC void outextended()$/
+outfail codefrag.c /^PUBLIC void outfail()$/
+outfail codefrag.c /^PUBLIC void outfail()$/
+outhex output.c /^PUBLIC void outhex(num)$/
+outhexdigs output.c /^PUBLIC void outhexdigs(num)$/
+outhiaccum codefrag.c /^PUBLIC void outhiaccum()$/
+outimadj codefrag.c /^PUBLIC void outimadj(offset, targreg)$/
+outimmadr codefrag.c /^PUBLIC void outimmadr(offset)$/
+outimmed codefrag.c /^PUBLIC void outimmed()$/
+outinc codefrag.c /^PUBLIC void outinc()$/
+outinc codefrag.c /^PUBLIC void outinc()$/
+outindframereg codefrag.c /^PUBLIC void outindframereg()$/
+outindleft codefrag.c /^PUBLIC void outindleft()$/
+outindleft codefrag.c /^PUBLIC void outindleft()$/
+outindleft codefrag.c /^PUBLIC void outindleft()$/
+outindright codefrag.c /^PUBLIC void outindright()$/
+outindright codefrag.c /^PUBLIC void outindright()$/
+outindright codefrag.c /^PUBLIC void outindright()$/
+outindstackreg codefrag.c /^PUBLIC void outindstackreg()$/
+outjumpstring codefrag.c /^PUBLIC void outjumpstring()$/
+outlabel label.c /^PUBLIC void outlabel(label)$/
+outldaccum codefrag.c /^PUBLIC void outldaccum()$/
+outldaccum codefrag.c /^PUBLIC void outldaccum()$/
+outldmulreg codefrag.c /^PUBLIC void outldmulreg()$/
+outldmulreg codefrag.c /^PUBLIC void outldmulreg()$/
+outlea codefrag.c /^PUBLIC void outlea()$/
+outlea codefrag.c /^PUBLIC void outlea()$/
+outleasp codefrag.c /^PUBLIC void outleasp()$/
+outleasp codefrag.c /^PUBLIC void outleasp()$/
+outline output.c /^PUBLIC void outline(s)$/
+outload codefrag.c /^PUBLIC void outload()$/
+outload codefrag.c /^PUBLIC void outload()$/
+outlongendian longop.c /^PUBLIC void outlongendian()$/
+outminus output.c /^PUBLIC void outminus()$/
+outmulmulreg codefrag.c /^PUBLIC void outmulmulreg()$/
+outmulmulreg codefrag.c /^PUBLIC void outmulmulreg()$/
+outnbyte output.c /^PUBLIC void outnbyte(byte)$/
+outnccname codefrag.c /^PUBLIC void outnccname(name)$/
+outncimmadr codefrag.c /^PUBLIC void outncimmadr(offset)$/
+outncregname genloads.c /^PUBLIC void outncregname(reg)$/
+outncspregname codefrag.c /^PUBLIC void outncspregname()$/
+outnhex output.c /^PUBLIC void outnhex(num)$/
+outnl output.c /^PUBLIC void outnl()$/
+outnlabel label.c /^PUBLIC void outnlabel(label)$/
+outnop1str output.c /^PUBLIC void outnop1str(s)$/
+outnop2str output.c /^PUBLIC void outnop2str(s)$/
+outnregname genloads.c /^PUBLIC void outnregname(reg)$/
+outnstr output.c /^PUBLIC void outnstr(s)$/
+outntypechar type.c /^PUBLIC void outntypechar(type)$/
+outoffset codefrag.c /^PUBLIC void outoffset(offset)$/
+outofmemoryerror table.c /^PUBLIC void outofmemoryerror(message)$/
+outop0str output.c /^PUBLIC void outop0str(s)$/
+outop1str output.c /^PUBLIC void outop1str(s)$/
+outop2str output.c /^PUBLIC void outop2str(s)$/
+outop3str output.c /^PUBLIC void outop3str(s)$/
+outopsep codefrag.c /^PUBLIC void outopsep()$/
+outopsep codefrag.c /^PUBLIC void outopsep()$/
+outplus output.c /^PUBLIC void outplus()$/
+outpshs codefrag.c /^PUBLIC void outpshs()$/
+outpshs codefrag.c /^PUBLIC void outpshs()$/
+outpuls codefrag.c /^PUBLIC void outpuls()$/
+outpuls codefrag.c /^PUBLIC void outpuls()$/
+outregname genloads.c /^PUBLIC void outregname(reg)$/
+outreturn codefrag.c /^PUBLIC void outreturn()$/
+outreturn codefrag.c /^PUBLIC void outreturn()$/
+outshex output.c /^PUBLIC void outshex(num)$/
+outshortregname genloads.c /^PUBLIC void outshortregname(reg)$/
+outstore codefrag.c /^PUBLIC void outstore()$/
+outstore codefrag.c /^PUBLIC void outstore()$/
+outstr output.c /^PUBLIC void outstr(s)$/
+outsub codefrag.c /^PUBLIC void outsub()$/
+outsub codefrag.c /^PUBLIC void outsub()$/
+outswoffset state.c /^PUBLIC void outswoffset (offset)$/
+outswstacklab state.c /^PUBLIC void outswstacklab()$/
+outtab output.c /^PUBLIC void outtab()$/
+outtest codefrag.c /^PUBLIC void outtest()$/
+outtest codefrag.c /^PUBLIC void outtest()$/
+outudec output.c /^PUBLIC void outudec(num)$/
+outuvalue output.c /^PUBLIC void outuvalue(num)$/
+outvalue output.c /^PUBLIC void outvalue(num)$/
+outword codefrag.c /^PUBLIC void outword()$/
+pointat genloads.c /^PUBLIC void pointat(target)$/
+pointype type.c /^PUBLIC struct typestruct *pointype(type)$/
+popframe function.c /^PUBLIC void popframe()$/
+poplist genloads.c /^PUBLIC void poplist(reglist)$/
+predefine preproc.c /^PUBLIC void predefine()$/
+prefix type.c /^PUBLIC struct typestruct *prefix(constructor, size, type)$/
+pres2 preserve.c /^PUBLIC void pres2(source, target)$/
+preserve preserve.c /^PUBLIC void preserve(source)$/
+preslval preserve.c /^PUBLIC store_pt preslval(source, target)$/
+program declare.c /^PUBLIC void program()$/
+promote type.c /^PUBLIC struct typestruct *promote(type)$/
+ptrsub hardop.c /^PUBLIC void ptrsub(source, target)$/
+public codefrag.c /^PUBLIC void public(name)$/
+push genloads.c /^PUBLIC void push(source)$/
+pushlist genloads.c /^PUBLIC void pushlist(reglist)$/
+pushreg genloads.c /^PUBLIC void pushreg(reg)$/
+pushudec output.c /^PUBLIC char *pushudec(s, num)$/
+qmalloc table.c /^PUBLIC void *qmalloc(size)$/
+rbrace declare.c /^PUBLIC void rbrace()$/
+rbracket declare.c /^PUBLIC void rbracket()$/
+recovlist preserve.c /^PUBLIC void recovlist(reglist)$/
+regexchange codefrag.c /^PUBLIC void regexchange(sourcereg, targreg)$/
+regtransfer codefrag.c /^PUBLIC void regtransfer(sourcereg, targreg)$/
+reslocals function.c /^PUBLIC void reslocals()$/
+restoreopreg codefrag.c /^PUBLIC void restoreopreg()$/
+ret function.c /^PUBLIC void ret()$/
+rparen declare.c /^PUBLIC void rparen()$/
+savedlineptr preproc.c /^PUBLIC char *savedlineptr()$/
+saveopreg codefrag.c /^PUBLIC void saveopreg()$/
+savereturn preserve.c /^PUBLIC void savereturn(savelist, saveoffset)$/
+sbc0 codefrag.c /^PUBLIC void sbc0()$/
+sbranch label.c /^PUBLIC void sbranch(cond, label)$/
+sctoi codefrag.c /^PUBLIC void sctoi()$/
+sctoi codefrag.c /^PUBLIC void sctoi()$/
+semicolon declare.c /^PUBLIC void semicolon()$/
+set codefrag.c /^PUBLIC void set(name, value)$/
+setoutbufs output.c /^PUBLIC void setoutbufs()$/
+skipcomment preproc.c /^PUBLIC void skipcomment()$/
+skipeol input.c /^PUBLIC void skipeol()$/
+skipline preproc.c /^PUBLIC void skipline()$/
+sl1 codefrag.c /^PUBLIC void sl1(reg)$/
+slconst codefrag.c /^PUBLIC void slconst(shift, reg)$/
+softop softop.c /^PUBLIC void softop(op, source, target)$/
+specialchar input.c /^PUBLIC void specialchar()$/
+srconst codefrag.c /^PUBLIC void srconst(shift, uflag)$/
+stoi codefrag.c /^PUBLIC void stoi()$/
+storereg genloads.c /^PUBLIC void storereg(sourcereg, target)$/
+stringorcharconst scan.c /^PUBLIC void stringorcharconst()$/
+struc genloads.c /^PUBLIC void struc(source, target)$/
+sub hardop.c /^PUBLIC void sub(source, target)$/
+swapsym table.c /^PUBLIC void swapsym(sym1, sym2)$/
+syminit table.c /^PUBLIC void syminit()$/
+tounsigned type.c /^PUBLIC struct typestruct *tounsigned(type)$/
+transfer genloads.c /^PUBLIC void transfer(source, targreg)$/
+typeinit type.c /^PUBLIC void typeinit()$/
+typename declare.c /^PUBLIC struct typestruct *typename()$/
+uitol codefrag.c /^PUBLIC void uitol(reg)$/
+unbumplc label.c /^PUBLIC void unbumplc()$/
+undefinestring preproc.c /^PUBLIC void undefinestring(str)$/
+ustoi codefrag.c /^PUBLIC void ustoi()$/
diff --git a/bcc/type.c b/bcc/type.c
new file mode 100644
index 0000000..4852c9d
--- /dev/null
+++ b/bcc/type.c
@@ -0,0 +1,203 @@
+/* type.c - type and storage-class routines for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+#include "const.h"
+#include "types.h"
+#include "align.h"
+#include "gencode.h" /* s.b. switches.h */
+#include "sc.h"
+#include "scan.h"
+#include "table.h"
+
+#undef EXTERN
+#define EXTERN
+#include "type.h"
+
+PUBLIC uoffset_t ctypesize = 1;
+PUBLIC uoffset_t dtypesize = 8;
+PUBLIC uoffset_t ftypesize = 0;
+PUBLIC uoffset_t itypesize = 2;
+PUBLIC uoffset_t ptypesize = 2;
+PUBLIC uoffset_t stypesize = 2;
+
+PRIVATE char skey0;
+PRIVATE char skey1;
+
+PUBLIC struct typestruct *addstruct(structname)
+char *structname;
+{
+ unsigned namelength;
+ struct symstruct *symptr;
+ struct typestruct *structype;
+
+ (structype = newtype())->constructor = STRUCTU;
+ structype->alignmask = ctype->alignmask;
+ if (++skey1 == 0)
+ {
+ ++skey1; /* must be nonzero or key string would end */
+ ++skey0; /* will never reach 'A' to be an identifier */
+ }
+ structype->structkey[0] = skey0;
+ structype->structkey[1] = skey1;
+ if (*structname != 0)
+ {
+ symptr = addlorg(structname, structype);
+ symptr->storage = 0;
+ symptr->flags = STRUCTNAME;
+ if (charptr + (namelength = strlen(structname)) >= chartop)
+ growheap(namelength + 1);
+#ifdef TS
+++ts_n_structname;
+ts_s_structname += namelength + 1;
+#endif
+ structype->tname = strcpy(charptr, structname);
+ charptr += namelength + 1;
+ }
+ return structype;
+}
+
+PUBLIC struct typestruct *iscalartotype(scalar)
+scalar_pt scalar;
+{
+ if (scalar & LONG)
+ {
+ if (scalar & UNSIGNED)
+ return ultype;
+ return ltype;
+ }
+ if (scalar & UNSIGNED)
+ return uitype;
+ return itype;
+}
+
+PUBLIC struct typestruct *newtype()
+{
+ register struct typestruct *type;
+
+ type = qmalloc(sizeof *type);
+#ifdef TS
+++ts_n_type;
+ts_s_type += sizeof *type;
+#endif
+ type->typesize = /* (uoffset_t) */
+ type->scalar = /* (scalar_t) */
+ type->constructor = /* (constr_t) */
+ type->structkey[0] = 0;
+ type->nexttype =
+ type->prevtype =
+ type->sidetype = NULL;
+ type->listtype = NULL;
+ type->tname = "";
+ return type;
+}
+
+PUBLIC void outntypechar(type)
+struct typestruct *type;
+{
+ outnbyte(*type->tname);
+}
+
+PUBLIC struct typestruct *pointype(type)
+struct typestruct *type;
+{
+ return prefix(POINTER, ptypesize, type);
+}
+
+PUBLIC struct typestruct *prefix(constructor, size, type)
+constr_pt constructor;
+uoffset_t size;
+struct typestruct *type;
+{
+ register struct typestruct *searchtype;
+
+ for (searchtype = type->prevtype; searchtype != NULL;
+ searchtype = searchtype->sidetype)
+ if (searchtype->constructor == (constr_t) constructor &&
+ searchtype->typesize == size)
+ return searchtype;
+ switch ((searchtype = newtype())->constructor = constructor)
+ {
+ case ARRAY:
+ searchtype->alignmask = type->alignmask;
+ break;
+ case FUNCTION:
+ searchtype->alignmask = ~(uoffset_t) 0;
+ break;
+ case POINTER:
+ searchtype->alignmask = ~(ptypesize - 1) | alignmask;
+ break;
+ case STRUCTU:
+ bugerror("prefixing structure/union");
+ searchtype->alignmask = alignmask;
+ break;
+ }
+ searchtype->typesize = size;
+ searchtype->nexttype = type;
+ searchtype->sidetype = type->prevtype;
+ return type->prevtype = searchtype;
+}
+
+PUBLIC struct typestruct *promote(type)
+struct typestruct *type;
+{
+ scalar_t scalar;
+
+ if ((scalar = type->scalar) & (CHAR | SHORT))
+ {
+ if (scalar & UNSIGNED)
+ return uitype;
+ return itype;
+ }
+ if (scalar & FLOAT)
+ return dtype;
+ if (type->constructor & ARRAY)
+ return pointype(type->nexttype);
+ if (type->constructor & FUNCTION)
+ return pointype(type);
+ return type;
+}
+
+PUBLIC struct typestruct *tounsigned(type)
+struct typestruct *type;
+{
+ switch (type->scalar & ~(UNSIGNED | DLONG))
+ {
+ case CHAR:
+ return uctype;
+ case SHORT:
+ return ustype;
+ case INT:
+ return uitype;
+ case LONG:
+ return ultype;
+ default:
+ error("unsigned only applies to integral types");
+ return type;
+ }
+}
+
+PUBLIC void typeinit()
+{
+#ifdef I8088
+ if (i386_32)
+ {
+ uitype->typesize =
+ itype->typesize =
+ ptypesize =
+ itypesize = 4;
+ dtype->alignmask =
+ fltype->alignmask =
+ uitype->alignmask =
+ ltype->alignmask =
+ ultype->alignmask =
+ itype->alignmask = ~(uoffset_t) (4 - 1);
+ ltype->scalar = LONG; /* not DLONG */
+ ultype->scalar = UNSIGNED | LONG;
+ }
+#endif
+ fitype = prefix(FUNCTION, ftypesize, itype);
+ pctype = pointype(ctype);
+ skey0 = 1;
+ vtype->constructor = VOID;
+}
diff --git a/bcc/type.h b/bcc/type.h
new file mode 100644
index 0000000..c451283
--- /dev/null
+++ b/bcc/type.h
@@ -0,0 +1,98 @@
+/* type.h - types for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ A type is essentially a "constructor", a size, and a list of pointers
+ leading to a scalar type.
+ The type constructors are codes for the scalar types and (), [], *,
+ struct and union.
+ The scalar types are char, short, int, long, float and double.
+ The type lists are triply linked.
+
+ Part of the type structure might look like
+
+ int (int)
+ =
+ func <-------> int (int ())
+ | =
+ --> ptr <--> int (int *)
+
+ (the exact structure depends on the order of declarations).
+ This layout results from the pre-declared (int) and (int ()) followed by
+ a declaration using (int *).
+ The sideways link (from func to ptr here) allows all types leading to a
+ given type to be found.
+ This allows different declarations of (int *) to be recognised as the same.
+ Type equivalence is equality of type pointers.
+*/
+
+/*
+ flags for scalar types
+ up to 3 of the flags may be set (none for constructed types)
+ the 2nd and third flags can only be UNSIGNED or DLONG
+ UNSIGNED only applies to integral types
+ DLONG only applies to long and unsigned long types and says that these
+ are actually longer than an int
+*/
+
+#define CHAR 0x01
+#define SHORT 0x02
+#define INT 0x04
+#define LONG 0x08
+#define FLOAT 0x10
+#define DOUBLE 0x20
+#define UNSIGNED 0x40
+#define DLONG 0x80
+
+#define ISCALAR (CHAR | SHORT | INT | LONG)
+#define RSCALAR (FLOAT | DOUBLE)
+
+/*
+ flags for type constructor
+ at most 1 of the flags may be set (none for scalar types)
+ flags are used for fast testing for array/pointer
+*/
+
+#define ARRAY 1
+#define FUNCTION 2
+#define POINTER 4
+#define STRUCTU 8
+#define VOID 0x10
+
+/* type sizes */
+/* default sizes and long and float sizes are hard-coded into type data */
+
+extern uoffset_t ctypesize;
+extern uoffset_t dtypesize;
+extern uoffset_t ftypesize;
+extern uoffset_t itypesize;
+extern uoffset_t ptypesize;
+extern uoffset_t stypesize;
+
+/* basic scalar types */
+
+EXTERN struct typestruct *dtype;
+EXTERN struct typestruct *fltype;
+EXTERN struct typestruct *itype;
+EXTERN struct typestruct *ltype;
+EXTERN struct typestruct *sctype;
+EXTERN struct typestruct *stype;
+EXTERN struct typestruct *uctype;
+EXTERN struct typestruct *uitype;
+EXTERN struct typestruct *ultype;
+EXTERN struct typestruct *ustype;
+EXTERN struct typestruct *vtype;
+
+/* working type */
+
+EXTERN struct typestruct *ctype;
+
+/* constructed types */
+
+EXTERN struct typestruct *fitype;
+EXTERN struct typestruct *pctype;
+
+/* return type of current function */
+
+EXTERN struct typestruct *returntype;
diff --git a/bcc/types.h b/bcc/types.h
new file mode 100644
index 0000000..755b8b1
--- /dev/null
+++ b/bcc/types.h
@@ -0,0 +1,206 @@
+/* types.h - type definitions for bcc */
+
+/* Copyright (C) 1992 Bruce Evans */
+
+/*
+ source types big enough to handle target quantities
+ these have to be match the source compiler and target machine
+ this is impossible if the source long type is too small
+*/
+
+typedef unsigned char char_t; /* target char */
+typedef long value_t; /* target ints, longs and offsets */
+typedef unsigned long uvalue_t; /* target unsigned ints, longs and offsets */
+
+#ifdef I8088
+typedef long offset_t; /* target machine offset */
+typedef unsigned long uoffset_t; /* target unsigned machine offset */
+#define outuvalue outhex
+#define outvalue outshex
+#endif
+#ifdef MC6809
+typedef int offset_t;
+typedef unsigned uoffset_t;
+#endif
+
+
+/*
+ storage class type must hold all the flags defined elsewhere
+ it must have a few more bits than the target has registers
+*/
+
+#ifdef I8088
+typedef unsigned store_pt; /* promoted store_t */
+typedef unsigned store_t; /* storage class flags */
+#endif
+#ifdef MC6809
+#ifdef __STDC__
+typedef int store_pt;
+# else
+typedef unsigned store_pt;
+# endif
+typedef unsigned char store_t;
+#endif
+
+
+/*
+ types for library routines
+*/
+
+typedef int fd_t; /* file descriptor */
+
+
+/*
+ basic scalar types - may be tuned to suit machine
+*/
+
+typedef int fastin_pt; /* promoted fastin_t */
+ /* always an int - use to show that the */
+ /* value may be accessed as a fastin_t */
+typedef char fastin_t; /* fast int - a small integer value */
+ /* on some machines, chars can be accessed */
+ /* more efficiently than ints for arithmetic */
+ /* such as comparing and masking which */
+ /* does not requiring promotion */
+ /* change to int if chars are inefficient */
+ /* or if char has < 8 bits */
+typedef int smalin_pt; /* promoted smalin_t */
+typedef char smalin_t; /* small int - a small integer value */
+ /* on most machines, chars are stored in */
+ /* less space than any other type */
+ /* change to fastin_t if this is not true */
+ /* or if char has < 8 bits */
+ /* or if space is not a limiting factor */
+#ifdef __STDC__
+typedef int smalu_pt;
+#else
+typedef unsigned smalu_pt;
+#endif
+typedef unsigned char smalu_t;
+
+
+/*
+ derived scalar types
+ the types containing bit flags fit in an 8 bit smalin_t
+*/
+
+typedef fastin_pt bool_pt; /* promoted bool_t */
+typedef fastin_t bool_t; /* boolean: TRUE if nonzero */
+typedef fastin_pt ccode_pt; /* promoted ccode_t */
+typedef fastin_t ccode_t; /* condition code code */
+typedef smalu_pt constr_pt; /* promoted constr_t */
+typedef smalu_t constr_t; /* type constructor flags */
+typedef smalu_pt indn_pt; /* promoted indn_t */
+typedef smalu_t indn_t; /* storage indirection count */
+typedef unsigned label_t; /* label number */
+typedef smalu_t maclev_t; /* macro expansion level */
+typedef smalin_pt op_pt; /* promoted op_t */
+typedef smalin_t op_t; /* operator code */
+typedef smalu_t sc_t; /* storage class flags */
+typedef smalu_pt scalar_pt; /* promoted scalar_t */
+typedef smalu_t scalar_t; /* type scalar flags */
+typedef smalu_t scopelev_t; /* scope level */
+typedef fastin_pt sym_pt; /* promoted sym_t */
+typedef fastin_t sym_t; /* symbol code from scanner */
+typedef smalu_t weight_t; /* expression tree node weight */
+
+
+/*
+ derived structure types
+ the fields are ordered in a way that is most space-efficient
+ when smalin_t is char and smalu_t is unsigned char
+ the first element of the structures is the one most frequently accessed
+*/
+
+/*
+ expression table entry format
+*/
+
+struct nodestruct
+{
+ op_t tag;
+ weight_t weight;
+ smalu_t flags;
+ struct typestruct *nodetype;
+ union nodeunion
+ {
+ struct nodestruct *nodeptr;
+ struct symstruct *symptr;
+ } left;
+ struct nodestruct *right;
+};
+
+/*
+ symbol table entry format
+*/
+
+struct symstruct
+{
+ store_t storage;
+ indn_t indcount;
+ sc_t flags;
+ scopelev_t level;
+ struct symstruct *next;
+ struct symstruct **prev;
+ struct typestruct *type;
+ union
+ {
+ double *offd; /* value for double constants */
+ offset_t offi; /* offset for register or global storage */
+ label_t offlabel; /* label number for strings */
+ char *offp; /* to string for macro definitions */
+ sym_pt offsym; /* symbol code for keywords */
+ value_t offv; /* value for integral constants */
+ }
+ offset;
+ union
+ {
+ label_t label; /* label number for strings */
+ char namea[1]; /* variable length array for declarations */
+ char *namep; /* to constant storage for exprs */
+ }
+ name;
+};
+
+/*
+ type table entry format
+*/
+
+struct typestruct
+{
+ scalar_t scalar; /* scalar type flags u d f l i s c */
+ constr_t constructor; /* constructed type flags a f p s/u */
+ char structkey[2]; /* unique prefix for member names */
+ /* ranges from "\001\001" to "@\377" */
+ /* avoiding nulls */
+ uoffset_t alignmask; /* alignment mask, typesize - 1 for scalars */
+ uoffset_t typesize; /* size of this type */
+ char *tname; /* name of scalar type or constructor */
+ struct typelist *listtype; /* list of member types */
+ struct typestruct *nexttype;
+ /* next in list */
+ struct typestruct *prevtype;
+ /* previous in list */
+ struct typestruct *sidetype;
+ /* next in sideways list */
+};
+
+/*
+ list of type structures
+*/
+
+struct typelist
+{
+ struct typelist *tlnext;
+ struct typestruct *tltype;
+};
+
+
+/*
+ definitions to avoid passing raw NULLs to functions
+*/
+
+#define NULLNODE ((struct nodestruct *) NULL)
+#define NULLTYPE ((struct typestruct *) NULL)
+
+#include "proto.h"
diff --git a/dis88/Makefile b/dis88/Makefile
new file mode 100644
index 0000000..692326f
--- /dev/null
+++ b/dis88/Makefile
@@ -0,0 +1,51 @@
+# Makefile for dis
+
+# @(#) Makefile, Ver. 2.1 created 00:00:00 87/09/01
+# Makefile for 8088 symbolic disassembler
+
+# Copyright (C) 1987 G. M. Harding, all rights reserved.
+# Permission to copy and redistribute is hereby granted,
+# provided full source code, with all copyright notices,
+# accompanies any redistribution.
+
+# This Makefile automates the process of compiling and linking
+# a symbolic object-file disassembler program for the Intel
+# 8088 CPU. Relatively machine-independent code is contained in
+# the file dismain.c; lookup tables and handler routines, which
+# are by their nature machine-specific, are contained in two
+# files named distabs.c and dishand.c, respectively. (A third
+# machine-specific file, disfp.c, contains handler routines for
+# floating-point coprocessor opcodes.) A header file, dis.h,
+# attempts to mediate between the machine-specific and machine-
+# independent portions of the code. An attempt has been made to
+# isolate machine dependencies and to deal with them in fairly
+# straightforward ways. Thus, it should be possible to target a
+# different CPU by rewriting the handler routines and changing
+# the initialization data in the lookup tables. It should not
+# be necessary to alter the formats of the tables.
+
+CC=bcc
+CFLAGS=-O
+LDFLAGS=
+
+OBJ = disrel.o dismain.o distabs.o dishand.o disfp.o
+
+all: dis88
+
+dis88: $(OBJ)
+ $(CC) $(LDFLAGS) -o dis88 $(OBJ)
+
+install: /usr/bin/dis88
+
+/usr/bin/dis88: dis88
+ install -cs -o bin dis88 $@
+
+disrel.o: disrel.c
+dismain.o: dismain.c dis.h
+distabs.o: distabs.c dis.h
+dishand.o: dishand.c dis.h
+disfp.o: disfp.c dis.h
+
+
+clean:
+ rm -f *.bak *.o core dis88
diff --git a/dis88/README b/dis88/README
new file mode 100644
index 0000000..efc5ad9
--- /dev/null
+++ b/dis88/README
@@ -0,0 +1,90 @@
+ dis88
+ Beta Release
+ 87/09/01
+ ---
+ G. M. HARDING
+ POB 4142
+ Santa Clara CA 95054-0142
+
+
+ "Dis88" is a symbolic disassembler for the Intel 8088 CPU,
+ designed to run under the PC/IX operating system on an IBM XT
+ or fully-compatible clone. Its output is in the format of, and
+ is completely compatible with, the PC/IX assembler, "as". The
+ program is copyrighted by its author, but may be copied and re-
+ distributed freely provided that complete source code, with all
+ copyright notices, accompanies any distribution. This provision
+ also applies to any modifications you may make. You are urged
+ to comment such changes, giving, as a miminum, your name and
+ complete address.
+
+ This release of the program is a beta release, which means
+ that it has been extensively, but not exhaustively, tested.
+ User comments, recommendations, and bug fixes are welcome. The
+ principal features of the current release are:
+
+ (a) The ability to disassemble any file in PC/IX object
+ format, making full use of symbol and relocation information if
+ it is present, regardless of whether the file is executable or
+ linkable, and regardless of whether it has continuous or split
+ I/D space;
+
+ (b) Automatic generation of synthetic labels when no sym-
+ bol table is available; and
+
+ (c) Optional output of address and object-code informa-
+ tion as assembler comment text.
+
+ Limitations of the current release are:
+
+ (a) Numeric co-processor (i.e., 8087) mnemonics are not
+ supported. Instructions for the co-processor are disassembled
+ as CPU escape sequences, or as interrupts, depending on how
+ they were assembled in the first place. This limitation will be
+ addressed in a future release.
+
+ (b) Symbolic references within the object file's data
+ segment are not supported. Thus, for example, if a data segment
+ location is initialized to point to a text segment address, no
+ reference to a text segment symbol will be detected. This limi-
+ tation is likely to remain in future releases, because object
+ code does not, in most cases, contain sufficient information to
+ allow meaningful interpretation of pure data. (Note, however,
+ that symbolic references to the data segment from within the
+ text segment are always supported.)
+
+ As a final caveat, be aware that the PC/IX assembler does
+ not recognize the "esc" mnemonic, even though it refers to a
+ completely valid CPU operation which is documented in all the
+ Intel literature. Thus, the corresponding opcodes (0xd8 through
+ 0xdf) are disassembled as .byte directives. For reference, how-
+ ever, the syntactically-correct "esc" instruction is output as
+ a comment.
+
+ To build the disassembler program, transfer all the source
+ files, together with the Makefile, to a suitable (preferably
+ empty) PC/IX directory. Then, simply type "make".
+
+ To use dis88, place it in a directory which appears in
+ your $PATH list. It may then be invoked by name from whatever
+ directory you happen to be in. As a minimum, the program must
+ be invoked with one command-line argument: the name of the ob-
+ ject file to be disassembled. (Dis88 will complain if the file
+ specified is not an object file.) Optionally, you may specify
+ an output file; stdout is the default. One command-line switch
+ is available: "-o", which makes the program display addresses
+ and object code along with its mnemonic disassembly.
+
+ The "-o" option is useful primarily for verifying the cor-
+ rectness of the program's output. In particular, it may be used
+ to check the accuracy of local relative jump opcodes. These
+ jumps often target local labels, which are lost at assembly
+ time; thus, the disassembly may contain cryptic instructions
+ like "jnz .+39". As a user convenience, all relative jump and
+ call opcodes are output with a comment which identifies the
+ physical target address.
+
+ By convention, the release level of the program as a whole
+ is the SID of the file disrel.c, and this SID string appears in
+ each disassembly. Release 2.1 of the program is the first beta
+ release to be distributed on Usenet.
diff --git a/dis88/a.out.h b/dis88/a.out.h
new file mode 120000
index 0000000..ccbf4b5
--- /dev/null
+++ b/dis88/a.out.h
@@ -0,0 +1 @@
+../libc/include/a.out.h \ No newline at end of file
diff --git a/dis88/ansi.h b/dis88/ansi.h
new file mode 100644
index 0000000..825b4a6
--- /dev/null
+++ b/dis88/ansi.h
@@ -0,0 +1,58 @@
+/* The <ansi.h> header attempts to decide whether the compiler has enough
+ * conformance to Standard C for Minix to take advantage of. If so, the
+ * symbol _ANSI is defined (as 31415). Otherwise _ANSI is not defined
+ * here, but it may be defined by applications that want to bend the rules.
+ * The magic number in the definition is to inhibit unnecessary bending
+ * of the rules. (For consistency with the new '#ifdef _ANSI" tests in
+ * the headers, _ANSI should really be defined as nothing, but that would
+ * break many library routines that use "#if _ANSI".)
+
+ * If _ANSI ends up being defined, a macro
+ *
+ * _PROTOTYPE(function, params)
+ *
+ * is defined. This macro expands in different ways, generating either
+ * ANSI Standard C prototypes or old-style K&R (Kernighan & Ritchie)
+ * prototypes, as needed. Finally, some programs use _CONST, _VOIDSTAR etc
+ * in such a way that they are portable over both ANSI and K&R compilers.
+ * The appropriate macros are defined here.
+ */
+
+#ifndef _ANSI_H
+#define _ANSI_H
+
+#if __STDC__ == 1
+#define _ANSI 31459 /* compiler claims full ANSI conformance */
+#endif
+
+#ifdef __GNUC__
+#define _ANSI 31459 /* gcc conforms enough even in non-ANSI mode */
+#endif
+
+#ifdef _ANSI
+
+/* Keep everything for ANSI prototypes. */
+#define _PROTOTYPE(function, params) function params
+#define _ARGS(params) params
+
+#define _VOIDSTAR void *
+#define _VOID void
+#define _CONST const
+#define _VOLATILE volatile
+#define _SIZET size_t
+
+#else
+
+/* Throw away the parameters for K&R prototypes. */
+#define _PROTOTYPE(function, params) function()
+#define _ARGS(params) ()
+
+#define _VOIDSTAR void *
+#define _VOID void
+#define _CONST
+#define _VOLATILE
+#define _SIZET int
+
+#endif /* _ANSI */
+
+#endif /* ANSI_H */
diff --git a/dis.h b/dis88/dis.h
index d8fc245..7815e06 100644
--- a/dis.h
+++ b/dis88/dis.h
@@ -25,14 +25,15 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <sys/types.h>
-#include <a.out.h> /* Object file format definitions */
#include <fcntl.h> /* System file-control definitions */
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h> /* System standard I/O definitions */
+#include "a.out.h" /* Object file format definitions */
+#include "ansi.h"
-#define MAXSYM 1500 /* Maximum entries in symbol table */
+#define MAXSYM 800 /* Maximum entries in symbol table */
extern struct nlist /* Array to hold the symbol table */
symtab[MAXSYM];
@@ -123,7 +124,9 @@ extern struct exec HDR; /* Holds the object file's header */
#define TR_SEG 8
/* Macro for byte input primitive */
-#define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p
+/* #define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p */
+static int _F_;
+#define FETCH(p) (p)=_F_ = Fetch(); if(_F_<0) {printf("???\n"); return; }
/* disfp.c */
diff --git a/dis88/dis88.1 b/dis88/dis88.1
new file mode 100644
index 0000000..c991ad7
--- /dev/null
+++ b/dis88/dis88.1
@@ -0,0 +1,147 @@
+.TH dis88 1 LOCAL
+.SH "NAME"
+dis88 \- 8088 symbolic disassembler
+.SH "SYNOPSIS"
+\fBdis88\fP [ -o ] ifile [ ofile ]
+.SH "DESCRIPTION"
+Dis88 reads ifile, which must be in PC/IX a.out format.
+It interprets the binary opcodes and data locations, and
+writes corresponding assembler source code to stdout, or
+to ofile if specified. The program's output is in the
+format of, and fully compatible with, the PC/IX assembler,
+as(1). If a symbol table is present in ifile, labels and
+references will be symbolic in the output. If the input
+file lacks a symbol table, the fact will be noted, and the
+disassembly will proceed, with the disassembler generating
+synthetic labels as needed. If the input file has split
+I/D space, or if it is executable, the disassembler will
+make all necessary adjustments in address-reference calculations.
+.PP
+If the "-o" option appears, object code will be included
+in comments during disassembly of the text segment. This
+feature is used primarily for debugging the disassembler
+itself, but may provide information of passing interest
+to users.
+.PP
+The program always outputs the current machine address
+before disassembling an opcode. If a symbol table is
+present, this address is output as an assembler comment;
+otherwise, it is incorporated into the synthetic label
+which is generated internally. Since relative jumps,
+especially short ones, may target unlabelled locations,
+the program always outputs the physical target address
+as a comment, to assist the user in following the code.
+.PP
+The text segment of an object file is always padded to
+an even machine address. In addition, if the file has
+split I/D space, the text segment will be padded to a
+paragraph boundary (i.e., an address divisible by 16).
+As a result of this padding, the disassembler may produce
+a few spurious, but harmless, instructions at the
+end of the text segment.
+.PP
+Disassembly of the data segment is a difficult matter.
+The information to which initialized data refers cannot
+be inferred from context, except in the special case
+of an external data or address reference, which will be
+reflected in the relocation table. Internal data and
+address references will already be resolved in the object file,
+and cannot be recreated. Therefore, the data
+segment is disassembled as a byte stream, with long
+stretches of null data represented by an appropriate
+".zerow" pseudo-op. This limitation notwithstanding,
+labels (as opposed to symbolic references) are always
+output at appropriate points within the data segment.
+.PP
+If disassembly of the data segment is difficult, disassembly of the
+bss segment is quite easy, because uninitialized data is all
+zero by definition. No data
+is output in the bss segment, but symbolic labels are
+output as appropriate.
+.PP
+For each opcode which takes an operand, a particular
+symbol type (text, data, or bss) is appropriate. This
+tidy correspondence is complicated somewhat, however,
+by the existence of assembler symbolic constants and
+segment override opcodes. Therefore, the disassembler's
+symbol lookup routine attempts to apply a certain amount
+of intelligence when it is asked to find a symbol. If
+it cannot match on a symbol of the preferred type, it
+may return a symbol of some other type, depending on
+preassigned (and somewhat arbitrary) rankings within
+each type. Finally, if all else fails, it returns a
+string containing the address sought as a hex constant;
+this behavior allows calling routines to use the output
+of the lookup function regardless of the success of its
+search.
+.PP
+It is worth noting, at this point, that the symbol lookup
+routine operates linearly, and has not been optimized in
+any way. Execution time is thus likely to increase
+geometrically with input file size. The disassembler is
+internally limited to 1500 symbol table entries and 1500
+relocation table entries; while these limits are generous
+(/unix, itself, has fewer than 800 symbols), they are not
+guaranteed to be adequate in all cases. If the symbol
+table or the relocation table overflows, the disassembly
+aborts.
+.PP
+Finally, users should be aware of a bug in the assembler,
+which causes it not to parse the "esc" mnemonic, even
+though "esc" is a completely legitimate opcode which is
+documented in all the Intel literature. To accommodate
+this deficiency, the disassembler translates opcodes of
+the "esc" family to .byte directives, but notes the
+correct mnemonic in a comment for reference.
+.PP
+In all cases, it should be possible to submit the output
+of the disassembler program to the assembler, and assemble
+it without error. In most cases, the resulting object
+code will be identical to the original; in any event, it
+will be functionally equivalent.
+.SH "SEE ALSO"
+adb(1), as(1), cc(1), ld(1).
+.br
+"Assembler Reference Manual" in the PC/IX Programmer's
+Guide.
+.SH "DIAGNOSTICS"
+"can't access input file" if the input file cannot be
+found, opened, or read.
+.sp
+"can't open output file" if the output file cannot be
+created.
+.sp
+"warning: host/cpu clash" if the program is run on a
+machine with a different CPU.
+.sp
+"input file not in object format" if the magic number
+does not correspond to that of a PC/IX object file.
+.sp
+"not an 8086/8088 object file" if the CPU ID of the
+file header is incorrect.
+.sp
+"reloc table overflow" if there are more than 1500
+entries in the relocation table.
+.sp
+"symbol table overflow" if there are more than 1500
+entries in the symbol table.
+.sp
+"lseek error" if the input file is corrupted (should
+never happen).
+.sp
+"warning: no symbols" if the symbol table is missing.
+.sp
+"can't reopen input file" if the input file is removed
+or altered during program execution (should never happen).
+.SH "BUGS"
+Numeric co-processor (i.e., 8087) mnemonics are not currently supported.
+Instructions for the co-processor are
+disassembled as CPU escape sequences, or as interrupts,
+depending on how they were assembled in the first place.
+.sp
+Despite the program's best efforts, a symbol retrieved
+from the symbol table may sometimes be different from
+the symbol used in the original assembly.
+.sp
+The disassembler's internal tables are of fixed size,
+and the program aborts if they overflow.
diff --git a/disfp.c b/dis88/disfp.c
index c6dc0da..c6dc0da 100644
--- a/disfp.c
+++ b/dis88/disfp.c
diff --git a/dishand.c b/dis88/dishand.c
index 56c6321..5983972 100644
--- a/dishand.c
+++ b/dis88/dishand.c
@@ -162,7 +162,7 @@ aohand(j)
register int k;
int m, n;
- char b[64];
+ char b[80];
objini(j);
@@ -541,7 +541,7 @@ mihand(j)
register int k;
int m, n;
- char b[64];
+ char b[80];
objini(j);
@@ -622,7 +622,7 @@ tqhand(j)
register int m, n;
int k;
- char b[64];
+ char b[80];
objini(j);
@@ -702,7 +702,7 @@ mmhand(j)
char *a;
register int k;
- char b[64];
+ char b[80];
objini(j);
@@ -898,7 +898,7 @@ mahand(j)
char *a;
register int k;
- char b[64];
+ char b[80];
objini(j);
diff --git a/dismain.c b/dis88/dismain.c
index d317f00..f9ec6c5 100644
--- a/dismain.c
+++ b/dis88/dismain.c
@@ -75,7 +75,7 @@ static void
fatal(s,t)
register char *s, *t;
{
- fprintf(stderr,"\07%s: %s\n",s,t);
+ fprintf(stderr,"%s: %s\n",s,t);
exit(-1);
}
@@ -200,7 +200,7 @@ register int type;
{/* * * * * * * * * * START OF getlab() * * * * * * * * * */
register int k;
- static char b[32], c[10];
+ static char b[48], c[32];
if (symptr < 0)
if ((type == N_TEXT)
@@ -245,6 +245,8 @@ prolog()
register int j, flag;
+ fflush(stdout);
+
if (symptr < 0)
return;
@@ -279,6 +281,7 @@ prolog()
if (flag)
putchar('\n');
+ fflush(stdout);
for (j = flag = 0; j <= relptr; ++j)
if (relo[j].r_symndx < S_BSS)
@@ -294,6 +297,7 @@ prolog()
if (flag)
putchar('\n');
+ fflush(stdout);
for (j = flag = 0; j <= symptr; ++j)
if ((symtab[j].n_sclass & N_SECT) == N_ABS)
@@ -313,6 +317,7 @@ prolog()
if (flag)
putchar('\n');
+ fflush(stdout);
}/* * * * * * * * * * * END OF prolog() * * * * * * * * * * */
@@ -359,6 +364,7 @@ distext()
printf("\t.text\t\t\t| loc = %05.5lx, size = %05.5lx\n\n",
PC,HDR.a_text);
+ fflush(stdout);
segflg = 0;
@@ -374,10 +380,23 @@ distext()
printf("%s",c);
f = optab[j].func;
(*f)(j);
+ fflush(stdout);
}
}/* * * * * * * * * * END OF distext() * * * * * * * * * */
+Fetch()
+{
+ int p;
+ ++PC;
+ if( symptr>=0 && getlab(N_TEXT) != NULL ) { --PC; return -1; }
+
+/* #define FETCH(p) ++PC; p = getchar() & 0xff; objbuf[objptr++] = p */
+ p = getchar() & 0xff;
+ objbuf[objptr++] = p;
+ return p;
+}
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This function handles the object file's data segment. *
@@ -548,7 +567,7 @@ main(argc,argv)
}
if ( ! cpuid )
- fprintf(stderr,"\07%s: warning: host/cpu clash\n",PRG);
+ fprintf(stderr,"%s: warning: host/cpu clash\n",PRG);
read(fd, (char *) &HDR,sizeof(struct exec));
@@ -610,7 +629,7 @@ main(argc,argv)
symptr--;
}
else
- fprintf(stderr,"\07%s: warning: no symbols\n",PRG);
+ fprintf(stderr,"%s: warning: no symbols\n",PRG);
close(fd);
diff --git a/disrel.c b/dis88/disrel.c
index 37f3221..37f3221 100644
--- a/disrel.c
+++ b/dis88/disrel.c
diff --git a/distabs.c b/dis88/distabs.c
index 6390cec..283fe42 100644
--- a/distabs.c
+++ b/dis88/distabs.c
@@ -365,9 +365,9 @@ getnam(k)
{/* * * * * * * * * * START OF getnam() * * * * * * * * * */
register int j;
- static char a[9];
+ static char a[sizeof(symtab->n_name)+1];
- for (j = 0; j < 8; ++j)
+ for (j = 0; j < sizeof(symtab[k].n_name); ++j)
if ( ! symtab[k].n_name[j] )
break;
else
@@ -411,7 +411,7 @@ lookext(off,loc,buf)
{/* * * * * * * * * * START OF lookext() * * * * * * * * * */
register int k;
- char c[16];
+ char c[32];
if ((loc != -1L) && (relptr >= 0))
for (k = 0; k <= relptr; ++k)
@@ -477,7 +477,7 @@ lookup(addr,type,kind,ext)
{/* * * * * * * * * * START OF lookup() * * * * * * * * * */
register int j, k;
- static char b[64];
+ static char b[80];
struct
{
diff --git a/dis88/old_a.out.h b/dis88/old_a.out.h
new file mode 100644
index 0000000..1a36dfb
--- /dev/null
+++ b/dis88/old_a.out.h
@@ -0,0 +1,117 @@
+/* The <a.out> header file describes the format of executable files. */
+
+#ifndef _AOUT_H
+#define _AOUT_H
+
+struct exec { /* a.out header */
+ unsigned char a_magic[2]; /* magic number */
+ unsigned char a_flags; /* flags, see below */
+ unsigned char a_cpu; /* cpu id */
+ unsigned char a_hdrlen; /* length of header */
+ unsigned char a_unused; /* reserved for future use */
+ unsigned short a_version; /* version stamp (not used at present) */
+ long a_text; /* size of text segement in bytes */
+ long a_data; /* size of data segment in bytes */
+ long a_bss; /* size of bss segment in bytes */
+ long a_entry; /* entry point */
+ long a_total; /* total memory allocated */
+ long a_syms; /* size of symbol table */
+
+ /* SHORT FORM ENDS HERE */
+ long a_trsize; /* text relocation size */
+ long a_drsize; /* data relocation size */
+ long a_tbase; /* text relocation base */
+ long a_dbase; /* data relocation base */
+};
+
+#define A_MAGIC0 (unsigned char) 0x01
+#define A_MAGIC1 (unsigned char) 0x03
+#define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1)
+
+/* CPU Id of TARGET machine (byte order coded in low order two bits) */
+#define A_NONE 0x00 /* unknown */
+#define A_I8086 0x04 /* intel i8086/8088 */
+#define A_M68K 0x0B /* motorola m68000 */
+#define A_NS16K 0x0C /* national semiconductor 16032 */
+#define A_I80386 0x10 /* intel i80386 */
+#define A_SPARC 0x17 /* Sun SPARC */
+
+#define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */
+#define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */
+
+/* Flags. */
+#define A_UZP 0x01 /* unmapped zero page (pages) */
+#define A_PAL 0x02 /* page aligned executable */
+#define A_NSYM 0x04 /* new style symbol table */
+#define A_EXEC 0x10 /* executable */
+#define A_SEP 0x20 /* separate I/D */
+#define A_PURE 0x40 /* pure text */ /* not used */
+#define A_TOVLY 0x80 /* text overlay */ /* not used */
+
+/* Offsets of various things. */
+#define A_MINHDR 32
+#define A_TEXTPOS(X) ((long)(X).a_hdrlen)
+#define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text)
+#define A_HASRELS(X) ((X).a_hdrlen > (unsigned char) A_MINHDR)
+#define A_HASEXT(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 8))
+#define A_HASLNS(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 16))
+#define A_HASTOFF(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 24))
+#define A_TRELPOS(X) (A_DATAPOS(X) + (X).a_data)
+#define A_DRELPOS(X) (A_TRELPOS(X) + (X).a_trsize)
+#define A_SYMPOS(X) (A_TRELPOS(X) + (A_HASRELS(X) ? \
+ ((X).a_trsize + (X).a_drsize) : 0))
+
+struct reloc {
+ long r_vaddr; /* virtual address of reference */
+ unsigned short r_symndx; /* internal segnum or extern symbol num */
+ unsigned short r_type; /* relocation type */
+};
+
+/* r_tyep values: */
+#define R_ABBS 0
+#define R_RELLBYTE 2
+#define R_PCRBYTE 3
+#define R_RELWORD 4
+#define R_PCRWORD 5
+#define R_RELLONG 6
+#define R_PCRLONG 7
+#define R_REL3BYTE 8
+#define R_KBRANCHE 9
+
+/* r_symndx for internal segments */
+#define S_ABS ((unsigned short)-1)
+#define S_TEXT ((unsigned short)-2)
+#define S_DATA ((unsigned short)-3)
+#define S_BSS ((unsigned short)-4)
+
+struct nlist { /* symbol table entry */
+ char n_name[8]; /* symbol name */
+ long n_value; /* value */
+ unsigned char n_sclass; /* storage class */
+ unsigned char n_numaux; /* number of auxiliary entries (not used) */
+ unsigned short n_type; /* language base and derived type (not used) */
+};
+
+/* Low bits of storage class (section). */
+#define N_SECT 07 /* section mask */
+#define N_UNDF 00 /* undefined */
+#define N_ABS 01 /* absolute */
+#define N_TEXT 02 /* text */
+#define N_DATA 03 /* data */
+#define N_BSS 04 /* bss */
+#define N_COMM 05 /* (common) */
+
+/* High bits of storage class. */
+#define N_CLASS 0370 /* storage class mask */
+#define C_NULL
+#define C_EXT 0020 /* external symbol */
+#define C_STAT 0030 /* static */
+
+/* Function prototypes. */
+#ifndef _ANSI_H
+#include "ansi.h"
+#endif
+
+_PROTOTYPE( int nlist, (char *_file, struct nlist *_nl) );
+
+#endif /* _AOUT_H */
diff --git a/elksemu/Kernel_patch b/elksemu/Kernel_patch
new file mode 100644
index 0000000..451455f
--- /dev/null
+++ b/elksemu/Kernel_patch
@@ -0,0 +1,19 @@
+
+This kernel patch allows you to run Linux-8086 executables transparently
+on a Linux-i386 system. It requires V0.0.2 of elksemu in "/lib/elksemu".
+
+--- orig-13/fs/exec.c Sun Sep 24 13:22:37 1995
++++ linux/fs/exec.c Sun Feb 11 20:11:47 1996
+@@ -615,6 +615,12 @@
+ set_fs(old_fs);
+ if (retval < 0)
+ goto exec_error2;
++#ifndef NO_ELKSEMU
++ /* What a horrible hack! :-) */
++ if ((bprm.buf[0] == 1) && (bprm.buf[1] == 3) &&
++ (bprm.buf[2] == 0x20) && (bprm.buf[3] == 4))
++ memcpy(bprm.buf, "#!/lib/elksemu\n", 16);
++#endif
+ if ((bprm.buf[0] == '#') && (bprm.buf[1] == '!') && (!sh_bang)) {
+ /*
+ * This section does the #! interpretation.
diff --git a/elksemu/Makefile b/elksemu/Makefile
new file mode 100644
index 0000000..cee13ac
--- /dev/null
+++ b/elksemu/Makefile
@@ -0,0 +1,29 @@
+#
+# Makefile for elksemu.
+#
+
+CFLAGS=-O2 -fno-strength-reduce -Wall
+# If you need an a.out exe. NB The program _does_ now work as ELF
+# CFLAGS=-O2 -fno-strength-reduce -b i486-linuxaout -N -s -static
+
+OBJ=elks.o elks_sys.o elks_signal.o
+
+elksemu: $(OBJ)
+ $(CC) $(CFLAGS) -o elksemu $(OBJ)
+
+$(OBJ): elks.h
+elks_sys.o: call_tab.v
+
+call_tab.v: dummy
+ -cp -p ../libc/syscall/call_tab.v . 2>/dev/null
+ -cp -p ../libc/syscall/defn_tab.v . 2>/dev/null
+
+dummy:
+
+# The kernel patch _requires_ this location.
+install: elksemu
+ install -s -m 755 elksemu /lib/elksemu
+ tar cvf V-files.tar call_tab.v defn_tab.v
+
+clean:
+ rm -f $(OBJ) elksemu call_tab.v defn_tab.v
diff --git a/elksemu/V-files.tar b/elksemu/V-files.tar
new file mode 100644
index 0000000..c5e6082
--- /dev/null
+++ b/elksemu/V-files.tar
Binary files differ
diff --git a/elksemu/Version b/elksemu/Version
new file mode 100644
index 0000000..38a680f
--- /dev/null
+++ b/elksemu/Version
@@ -0,0 +1 @@
+Version elksemu-0.0.4
diff --git a/elksemu/elks.c b/elksemu/elks.c
new file mode 100644
index 0000000..f84c994
--- /dev/null
+++ b/elksemu/elks.c
@@ -0,0 +1,258 @@
+/*
+ * ELKSEMU An emulator for Linux8086 binaries.
+ *
+ * VM86 is used to process all the 8086 mode code.
+ * We trap up to 386 mode for system call emulation and naughties.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/vm86.h>
+#include <sys/mman.h>
+#include "elks.h"
+
+volatile struct vm86_struct elks_cpu;
+unsigned char *elks_base; /* Paragraph aligned */
+
+#define dbprintf(x) db_printf x
+/**/
+
+static void elks_init()
+{
+ elks_cpu.screen_bitmap=0;
+ elks_cpu.cpu_type = CPU_286;
+ /*
+ * All INT xx calls are trapped.
+ */
+ memset((void *)&elks_cpu.int_revectored,0xFF, sizeof(elks_cpu.int_revectored));
+}
+
+static void elks_take_interrupt(int arg)
+{
+ if(arg!=0x80)
+ {
+ dbprintf(("Took an int %d\n", arg));
+ fflush(stderr);
+ kill(getpid(), SIGILL);
+ return;
+ }
+
+ dbprintf(("syscall AX=%X BX=%X CX=%X DX=%x\n",
+ (unsigned short)elks_cpu.regs.eax,
+ (unsigned short)elks_cpu.regs.ebx,
+ (unsigned short)elks_cpu.regs.ecx,
+ (unsigned short)elks_cpu.regs.edx));
+
+ elks_cpu.regs.eax = elks_syscall();
+ dbprintf(("elks syscall returned %d\n", elks_cpu.regs.eax));
+ /* Finally return to vm86 state */
+}
+
+
+static int load_elks(int fd)
+{
+ /* Load the elks binary image and set it up in a suitable VM86 segment. Load CS and DS/SS
+ according to image type. chmem is ignored we always use 64K segments */
+ struct elks_exec_hdr mh;
+ unsigned char *dsp;
+ if(read(fd, &mh,sizeof(mh))!=sizeof(mh))
+ return -ENOEXEC;
+ if(mh.hlen!=EXEC_HEADER_SIZE)
+ return -ENOEXEC;
+ if(mh.type!=ELKS_COMBID&&mh.type!=ELKS_SPLITID)
+ return -ENOEXEC;
+#if 0
+ fprintf(stderr,"Linux-86 binary - %lX. tseg=%ld dseg=%ld bss=%ld\n",
+ mh.type,mh.tseg,mh.dseg,mh.bseg);
+#endif
+ if(read(fd,elks_base,mh.tseg)!=mh.tseg)
+ return -ENOEXEC;
+ if(mh.type==ELKS_COMBID)
+ dsp=elks_base+mh.tseg;
+ else
+ dsp=elks_base+65536;
+ if(read(fd,dsp,mh.dseg)!=mh.dseg)
+ return -ENOEXEC;
+ memset(dsp+mh.dseg,0, mh.bseg);
+ /*
+ * Load the VM86 registers
+ */
+
+/* if(mh.type==ELKS_COMBID)
+ dsp=elks_base;*/
+ elks_cpu.regs.ds=PARAGRAPH(dsp);
+ elks_cpu.regs.es=PARAGRAPH(dsp);
+ elks_cpu.regs.ss=PARAGRAPH(dsp);
+ elks_cpu.regs.esp=65536; /* Args stacked later */
+ elks_cpu.regs.cs=PARAGRAPH(elks_base);
+ elks_cpu.regs.eip=0; /* Run from 0 */
+
+ /*
+ * Loaded, check for sanity.
+ */
+ if( dsp != ELKS_PTR(unsigned char, 0) )
+ {
+ printf("Error VM86 problem %lx!=%lx (Is DS > 16 bits ?)\n",
+ (long)dsp, (long)ELKS_PTR(char, 0));
+ exit(0);
+ }
+
+ return 0;
+}
+
+
+void run_elks()
+{
+ /*
+ * Execute 8086 code for a while.
+ */
+ int err=vm86((struct vm86_struct*)&elks_cpu);
+ switch(VM86_TYPE(err))
+ {
+ /*
+ * Signals are just re-starts of emulation (yes the
+ * handler might alter elks_cpu)
+ */
+ case VM86_SIGNAL:
+ break;
+ case VM86_UNKNOWN:
+ fprintf(stderr, "VM86_UNKNOWN returned\n");
+ exit(1);
+ case VM86_INTx:
+ elks_take_interrupt(VM86_ARG(err));
+ break;
+ case VM86_STI:
+ fprintf(stderr, "VM86_STI returned\n");
+ break; /* Shouldnt be seen */
+ }
+}
+
+void build_stack(char ** argv, char ** envp)
+{
+ char **p;
+ int argv_len=0, argv_count=0;
+ int envp_len=0, envp_count=0;
+ int stack_bytes;
+ unsigned short * pip;
+ unsigned short pcp;
+
+ /* How much space for argv */
+ for(p=argv; *p; p++)
+ {
+ argv_count++; argv_len += strlen(*p)+1;
+ }
+
+ /* How much space for envp */
+ for(p=envp; *p; p++)
+ {
+ envp_count++; envp_len += strlen(*p)+1;
+ }
+
+ /* tot it all up */
+ stack_bytes = 2 /* argc */
+ + argv_count * 2 + 2 /* argv */
+ + argv_len
+ + envp_count * 2 + 2 /* envp */
+ + envp_len;
+
+ /* Allocate it */
+ elks_cpu.regs.esp -= stack_bytes;
+
+/* Sanity check
+ printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n",
+ argv_count, argv_len, envp_count, envp_len, stack_bytes);
+*/
+
+ /* Now copy in the strings */
+ pip=ELKS_PTR(unsigned short, elks_cpu.regs.esp);
+ pcp=elks_cpu.regs.esp+2*(1+argv_count+1+envp_count+1);
+
+ *pip++ = argv_count;
+ for(p=argv; *p; p++)
+ {
+ *pip++ = pcp;
+ strcpy(ELKS_PTR(char, pcp), *p);
+ pcp += strlen(*p)+1;
+ }
+ *pip++ = 0;
+
+ for(p=envp; *p; p++)
+ {
+ *pip++ = pcp;
+ strcpy(ELKS_PTR(char, pcp), *p);
+ pcp += strlen(*p)+1;
+ }
+ *pip++ = 0;
+}
+
+void main(int argc, char *argv[], char *envp[])
+{
+ int fd;
+ dbprintf(("ELKSEMU 0.01 Alpha\n"));
+ if(argc==1)
+ {
+ fprintf(stderr,"elksemu cmd args.....\n");
+ exit(1);
+ }
+ elks_init();
+
+ /* The Linux vm will deal with not allocating the unused pages */
+#if __AOUT__
+ /* GNU malloc will align to 4k with large chunks */
+ elks_base = malloc(0x20000);
+#else
+ /* For ELF first 128M is unmapped, it needs to be mapped manually */
+ elks_base = mmap((void*)0x10000, 0x20000,
+ PROT_EXEC|PROT_READ|PROT_WRITE,
+ MAP_ANON|MAP_PRIVATE|MAP_FIXED,
+ 0, 0);
+#endif
+ if( (long)elks_base < 0 || (long)elks_base >= 0xE0000 )
+ {
+ fprintf(stderr, "Elks memory is at an illegal address\n");
+ exit(255);
+ }
+ fd=open(argv[1], O_RDONLY);
+ if(fd==-1)
+ {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ if(load_elks(fd) < 0)
+ {
+ fprintf(stderr,"Not a elks binary.\n");
+ exit(1);
+ }
+
+ close(fd);
+
+ build_stack(argv+1, envp);
+
+ while(1)
+ run_elks();
+}
+
+void db_printf(const char * fmt, ...)
+{
+static FILE * db_fd = 0;
+ va_list ptr;
+ int rv;
+ if( db_fd == 0 )
+ {
+ db_fd = fopen("/tmp/ELKS_log", "a");
+ if( db_fd == 0 ) db_fd = stderr;
+ setbuf(db_fd, 0);
+ }
+ fprintf(db_fd, "%d: ", getpid());
+ va_start(ptr, fmt);
+ rv = vfprintf(db_fd,fmt,ptr);
+ va_end(ptr);
+}
diff --git a/elksemu/elks.h b/elksemu/elks.h
new file mode 100644
index 0000000..6d52470
--- /dev/null
+++ b/elksemu/elks.h
@@ -0,0 +1,96 @@
+/*
+ * Definitions for emulating ELKS
+ */
+
+#define ELKS_CS_OFFSET 0
+#define ELKS_DS_OFFSET 0 /* For split I/D */
+
+#define HZ 100
+
+#define ELKS_SIG_IGN (-1)
+#define ELKS_SIG_DFL 0
+
+#define WRITE_USPACE 0
+#define READ_USPACE 1
+
+#if !__ELF__
+#define __AOUT__ 1
+#endif
+
+/*
+ * Minix view of stat(). We have to squash a bit here and give
+ * wrong values with inode >65535 etc
+ */
+
+struct elks_stat
+{
+ unsigned short st_dev;
+ unsigned short st_inode;
+ unsigned short st_mode;
+ unsigned short st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned short st_rdev;
+ int st_size;
+ int st_atime;
+ int st_mtime;
+ int st_ctime;
+};
+
+
+/*
+ * Minix ioctl list
+ */
+
+#define ELKS_TIOCGETP (('t'<<8)|8)
+#define ELKS_TIOCSETP (('t'<<8)|9)
+#define ELKS_TIOCGETC (('t'<<8)|18)
+#define ELKS_TIOCSETC (('t'<<8)|17)
+#define ELKS_TIOCFLUSH (('t'<<8)|16)
+
+/*
+ * fcntl list
+ */
+
+#define ELKS_F_DUPFD 0
+#define ELKS_F_GETFD 1
+#define ELKS_F_SETFD 2
+#define ELKS_F_GETFL 3
+#define ELKS_F_SETFL 4
+#define ELKS_F_GETLK 5
+#define ELKS_F_SETLK 6
+#define ELKS_F_SETLKW 7
+
+/*
+ * Elks binary formats
+ */
+
+#define EXEC_HEADER_SIZE 32
+
+struct elks_exec_hdr
+{
+ unsigned long type;
+#define ELKS_COMBID 0x04100301L
+#define ELKS_SPLITID 0x04200301L
+ unsigned long hlen;
+ unsigned long tseg;
+ unsigned long dseg;
+ unsigned long bseg;
+ unsigned long unused;
+ unsigned long chmem;
+ unsigned long unused2;
+};
+
+#define PARAGRAPH(x) (((unsigned long)(x))>>4)
+#define ELKS_DSEG(x) ((unsigned char *)(((x)&0xFFFF)+(elks_cpu.regs.ds<<4)))
+
+#define ELKS_PTR(_t,x) ((_t *) ((elks_cpu.regs.ds<<4)+((x)&0xFFFF)) )
+#define ELKS_PEEK(_t,x) (*((_t *) ((elks_cpu.regs.ds<<4)+((x)&0xFFFF)) ))
+#define ELKS_POKE(_t,x,_v) \
+ (*((_t *) ((elks_cpu.regs.ds<<4)+((x)&0xFFFF)) ) = (_v))
+
+extern unsigned char * elks_base;
+extern volatile struct vm86_struct elks_cpu;
+
+void db_printf(const char *, ...);
+int elks_syscall(void);
diff --git a/elksemu/elks_signal.c b/elksemu/elks_signal.c
new file mode 100644
index 0000000..2bf1e55
--- /dev/null
+++ b/elksemu/elks_signal.c
@@ -0,0 +1,36 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/vm86.h>
+#include "elks.h"
+
+static int elks_sigtrap= -1;
+
+void sig_trap(int signo)
+{
+ elks_cpu.regs.esp -= 2;
+ ELKS_POKE(unsigned short, elks_cpu.regs.esp, signo);
+ elks_cpu.regs.esp -= 2;
+ ELKS_POKE(unsigned short, elks_cpu.regs.esp, elks_cpu.regs.eip);
+ elks_cpu.regs.eip = elks_sigtrap;
+}
+
+int elks_signal(int bx,int cx,int dx,int di,int si)
+{
+ int rv;
+ if( bx < 0 || bx >= NSIG ) { errno = EINVAL; return -1; }
+ if( cx == 0 ) rv = (signal(bx, SIG_DFL) == SIG_ERR);
+ else if( cx == 1 ) rv = (signal(bx, SIG_IGN) == SIG_ERR);
+ else
+ {
+ elks_sigtrap = cx;
+ rv = (signal(bx, sig_trap) == SIG_ERR);
+ }
+
+ return -rv;
+}
diff --git a/elksemu/elks_sys.c b/elksemu/elks_sys.c
new file mode 100644
index 0000000..7ca946c
--- /dev/null
+++ b/elksemu/elks_sys.c
@@ -0,0 +1,723 @@
+/*
+ * System calls are mostly pretty easy as the emulator is tightly bound to
+ * the elks task.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/vm86.h>
+#include <sys/times.h>
+#include <utime.h>
+#include <termios.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <dirent.h>
+#include "elks.h"
+
+#define dbprintf(x) db_printf x
+
+#define sys_signal elks_signal
+extern int elks_signal(int bx,int cx,int dx,int di,int si);
+
+/* Forward refs */
+static int elks_termios(int bx,int cx,int dx,int di,int si);
+static int elks_enosys(int bx,int cx,int dx,int di,int si);
+
+#define DIRCOUNT 20
+DIR * dirtab[DIRCOUNT];
+int diropen = 0;
+static int elks_opendir(char * dname);
+static int elks_readdir(int bx, int cx, int dx);
+static int elks_closedir(int bx);
+
+/*
+ * Compress a host stat into a elks one. Lose upper bits with wild
+ * abandon. For SYS5.3 this isn't a problem, but machines with 32
+ * bit inodes (BSD, SYS5 with veritas, newest SCO) you lose the top
+ * bits which can confuse a few programs which use inode numbers
+ * (eg gnu tar).
+ */
+
+static void squash_stat(struct stat *s, int bx)
+{
+#if 1 /* Can't use elks_stat, shot in the foot by alignment */
+
+ ELKS_POKE(short, bx+0, s->st_dev);
+ ELKS_POKE(short, bx+2, s->st_ino ^ (s->st_ino>>16));
+ ELKS_POKE(short, bx+4, s->st_mode);
+ ELKS_POKE(short, bx+6, s->st_nlink);
+ ELKS_POKE(short, bx+8, s->st_uid);
+ ELKS_POKE(short, bx+10, s->st_gid);
+ ELKS_POKE(short, bx+12, s->st_rdev);
+ ELKS_POKE(long, bx+14, s->st_size);
+ ELKS_POKE(long, bx+18, s->st_atime);
+ ELKS_POKE(long, bx+22, s->st_mtime);
+ ELKS_POKE(long, bx+26, s->st_ctime);
+#else
+ struct elks_stat * ms = ELKS_PTR(struct elks_stat, bx);
+ ms->st_dev=s->st_dev;
+ ms->st_inode=(unsigned short)s->st_ino; /* Bits lost */
+ ms->st_mode=s->st_mode;
+ ms->st_nlink=s->st_nlink;
+ ms->st_uid=s->st_uid;
+ ms->st_gid=s->st_gid;
+ ms->st_rdev=s->st_rdev;
+ ms->st_size=s->st_size;
+ ms->st_atime=s->st_atime;
+ ms->st_mtime=s->st_mtime;
+ ms->st_ctime=s->st_ctime;
+#endif
+}
+
+/*
+ * Implementation of ELKS syscalls.
+ */
+
+
+#define sys_exit elks_exit
+static int elks_exit(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("exit(%d)\n",bx));
+ exit(bx);
+}
+
+#define sys_vfork elks_fork
+#define sys_fork elks_fork
+static int elks_fork(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("fork()\n"));
+ /* This is fun 8) - fork the emulator (its easier that way) */
+ return fork();
+}
+
+#define sys_read elks_read
+static int elks_read(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("read(%d, %d, %d)\n",
+ bx,cx,dx));
+ if( bx >= 10000 && bx < 10000+DIRCOUNT)
+ return elks_readdir(bx, cx, dx);
+ return read(bx, ELKS_PTR(void, cx), dx);
+}
+
+#define sys_write elks_write
+static int elks_write(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("write(%d, %d, %d)\n",bx,cx,dx));
+ return write(bx,ELKS_PTR(void, cx),dx);
+}
+
+#define sys_open elks_open
+static int elks_open(int bx,int cx,int dx,int di,int si)
+{
+ struct stat s;
+
+ /* Assumes _all_ flags are the same */
+ char *dp=ELKS_PTR(char, bx);
+ dbprintf(("open(%s, %d, %d)\n",
+ dp,cx,dx));
+
+ if( cx == O_RDONLY )
+ {
+ if(stat(dp,&s)==-1)
+ return -1;
+ if( S_ISDIR(s.st_mode) )
+ return elks_opendir(dp);
+ }
+
+ return open(dp,cx,dx);
+}
+
+#define sys_close elks_close
+static int elks_close(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("close(%d)\n",bx));
+ if( bx >= 10000 && bx < 10000+DIRCOUNT)
+ return elks_closedir(bx);
+ return close(bx);
+}
+
+#define sys_wait4 elks_wait4
+static int elks_wait4(int bx,int cx,int dx,int di,int si)
+{
+ int status;
+ unsigned short *tp=ELKS_PTR(unsigned short, cx);
+ int r;
+ struct rusage use;
+
+ dbprintf(("wait4(%d, %d, %d, %d)\n", bx, cx, dx, di));
+ r=wait4((int)(short)bx, &status, dx, &use );
+
+ *tp=status;
+ if( di ) memcpy(ELKS_PTR(void, di), &use, sizeof(use));
+ return r;
+}
+
+#define sys_link elks_link
+static int elks_link(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("link(%s,%s)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx)));
+ return link(ELKS_PTR(char, bx),ELKS_PTR(char, cx));
+}
+
+#define sys_unlink elks_unlink
+static int elks_unlink(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("unlink(%s)\n",ELKS_PTR(char, bx)));
+ return unlink(ELKS_PTR(char, bx));
+}
+
+#define sys_chdir elks_chdir
+static int elks_chdir(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("chdir(%s)\n",ELKS_PTR(char, bx)));
+ return chdir(ELKS_PTR(char, bx));
+}
+
+#define sys_mknod elks_mknod
+static int elks_mknod(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("mknod(%s,%d,%d)\n", ELKS_PTR(char, bx),cx,dx));
+ return mknod(ELKS_PTR(char, bx),cx,dx);
+}
+
+#define sys_chmod elks_chmod
+static int elks_chmod(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("chmod(%s,%d)\n", ELKS_PTR(char, bx),cx));
+ return chmod(ELKS_PTR(char, bx), cx);
+}
+
+#define sys_chown elks_chown
+static int elks_chown(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("chown(%s,%d,%d)\n", ELKS_PTR(char, bx),cx,dx));
+ return chown(ELKS_PTR(char, bx),cx,dx);
+}
+
+#define sys_brk elks_brk
+static int elks_brk(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("brk(%d)\n",bx));
+ if(bx>=elks_cpu.regs.esp)
+ {
+ errno= 1; /* Really return -1 */
+ return -1;
+ }
+ return 0; /* Can't return bx, 0xBAD1 is an error */
+}
+
+#define sys_stat elks_stat
+static int elks_stat(int bx,int cx,int dx,int di,int si)
+{
+ struct stat s;
+ dbprintf(("stat(%s,%d)\n", ELKS_PTR(char, bx), cx));
+ if(stat(ELKS_PTR(char, bx),&s)==-1)
+ return -1;
+ squash_stat(&s,cx);
+ return 0;
+}
+
+#define sys_lstat elks_lstat
+static int elks_lstat(int bx,int cx,int dx,int di,int si)
+{
+ struct stat s;
+ dbprintf(("lstat(%s,%d)\n", ELKS_PTR(char, bx), cx));
+ if(lstat(ELKS_PTR(char, bx),&s)==-1)
+ return -1;
+ squash_stat(&s,cx);
+ return 0;
+}
+
+#define sys_lseek elks_lseek
+static int elks_lseek(int bx,int cx,int dx,int di,int si)
+{
+ long l=ELKS_PEEK(long, cx);
+
+ dbprintf(("lseek(%d,%ld,%d)\n",bx,l,dx));
+ l = lseek(bx,l,dx);
+ if( l < 0 ) return -1;
+ ELKS_POKE(long, cx, l);
+ return 0;
+}
+
+#define sys_getpid elks_getpid
+static int elks_getpid(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("getpid/getppid()\n"));
+ ELKS_POKE(unsigned short, bx, getppid());
+ return getpid();
+}
+
+#define sys_setuid elks_setuid
+static int elks_setuid(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("setuid(%d)\n",bx));
+ return setuid(bx);
+}
+
+#define sys_getuid elks_getuid
+static int elks_getuid(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("get[e]uid()\n"));
+ ELKS_POKE(unsigned short, bx, geteuid());
+ return getuid();
+}
+
+#define sys_alarm elks_alarm
+static int elks_alarm(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("alarm(%d)\n",bx<<16|cx));
+ return alarm(bx<<16|cx);
+}
+
+#define sys_fstat elks_fstat
+static int elks_fstat(int bx,int cx,int dx,int di,int si)
+{
+ struct stat s;
+ int err;
+ dbprintf(("fstat(%d,%d)\n",bx,cx));
+ err=fstat(bx,&s);
+ squash_stat(&s,cx);
+ return err;
+}
+
+#define sys_pause elks_pause
+static int elks_pause(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("pause()\n"));
+ return pause();
+}
+
+#define sys_utime elks_utime
+static int elks_utime(int bx,int cx,int dx,int di,int si)
+{
+ unsigned long *up=ELKS_PTR(long, cx);
+ struct utimbuf u;
+ u.actime=*up++;
+ u.modtime=*up;
+ return utime(ELKS_PTR(char, bx), &u);
+}
+
+#define sys_access elks_access
+static int elks_access(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("access(%s,%d)\n",ELKS_PTR(char, bx),cx));
+ return access(ELKS_PTR(char, bx),cx);
+}
+
+#define sys_sync elks_sync
+static int elks_sync(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("sync()\n"));
+ sync();
+ return 0;
+}
+
+#define sys_kill elks_kill
+static int elks_kill(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("kill(%d,%d)\n",bx,cx));
+ return kill(bx,cx);
+}
+
+#define sys_pipe elks_pipe
+static int elks_pipe(int bx,int cx,int dx,int di,int si)
+{
+ unsigned short *dp=ELKS_PTR(unsigned short, bx);
+ int p[2];
+ int err=pipe(p);
+ if(err==-1)
+ return err;
+ *dp++=p[0];
+ *dp=p[1];
+ return 0;
+}
+
+#define sys_times elks_times
+static int elks_times(int bx,int cx,int dx,int di,int si)
+{
+ struct tms t;
+ long clock_ticks=times(&t);
+ long *tp=ELKS_PTR(long, bx);
+ *tp++=t.tms_utime;
+ *tp++=t.tms_stime;
+ *tp++=t.tms_cutime;
+ *tp=t.tms_cstime;
+ return 0; /* Should be clock_ticks */
+}
+
+#define sys_setgid elks_setgid
+static int elks_setgid(int bx,int cx,int dx,int di,int si)
+{
+ return setgid(bx);
+}
+
+#define sys_getgid elks_getgid
+static int elks_getgid(int bx,int cx,int dx,int di,int si)
+{
+ ELKS_POKE(unsigned short, bx, getegid());
+ return getgid();
+}
+
+/*
+ * Exec is fun. The Minix user library builds a complete elks stack image.
+ * Great except that we need to unpack it all again and do a real exec. If
+ * its another elks image then our kernel side binary loader will load
+ * elksemu again and we'll take the Unix args and turn them back into a
+ * elks stack image.
+ *
+ * For now we run elksemu ourselves and do token attempts at binary checking.
+ *
+ * Of course with the Patch in the Linux kernel we could just run the exe.
+ */
+#define sys_exec elks_exec
+static int elks_exec(int bx,int cx,int dx,int di,int si)
+{
+ int fd;
+ int arg_ct,env_ct;
+ int ct;
+ char **argp, **envp;
+ unsigned short *bp;
+ unsigned char *base;
+ unsigned short *tmp;
+ struct elks_exec_hdr mh;
+ int is_elks = 1;
+
+ dbprintf(("exec(%s,%d,%d)\n",ELKS_PTR(char, bx), cx, dx));
+
+ base=ELKS_PTR(unsigned char, cx);
+ bp=ELKS_PTR(unsigned short, cx+2);
+ tmp=bp;
+
+ fd=open(ELKS_PTR(char, bx),O_RDONLY);
+ if(fd==-1)
+ { errno = ENOENT; return -1; }
+ if(read(fd, &mh, sizeof(mh))!=sizeof(mh))
+ {
+ close(fd);
+ errno = ENOEXEC;
+ return -1;
+ }
+ close(fd);
+ if(mh.hlen!=EXEC_HEADER_SIZE
+ || (mh.type!=ELKS_COMBID && mh.type!=ELKS_SPLITID))
+ is_elks = 0;
+
+ arg_ct = env_ct = 0;
+ while(*tmp++)
+ arg_ct++;
+ while(*tmp++)
+ env_ct++;
+ arg_ct+=2; /* elksemu-path progname arg0...argn */
+ argp=malloc(sizeof(char *)*(arg_ct+1));
+ envp=malloc(sizeof(char *)*(env_ct+1));
+ if(!argp||!envp) { errno = ENOMEM; return -1; }
+ ct=0;
+ if( is_elks )
+ {
+ argp[0]="/lib/elksemu";
+ argp[1]=ELKS_PTR(char, bx);
+ ct=2;
+ }
+ while(*bp)
+ argp[ct++]=ELKS_PTR(char, cx+ *bp++);
+ argp[ct]=0;
+ bp++;
+ ct=0;
+ while(*bp)
+ envp[ct++]=ELKS_PTR(char, cx+ *bp++);
+ envp[ct]=0;
+ if( is_elks )
+ execve(argp[0],argp,envp);
+ else
+ execve(ELKS_PTR(char, bx),argp,envp);
+ if( errno == ENOEXEC || errno == EACCES ) return -1;
+ perror("elksemu");
+ exit(1);
+}
+
+#define sys_umask elks_umask
+static int elks_umask(int bx,int cx,int dx,int di,int si)
+{
+ return umask(bx);
+}
+
+#define sys_chroot elks_chroot
+static int elks_chroot(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("chroot(%s)\n", ELKS_PTR(char, bx)));
+ return chroot(ELKS_PTR(char, bx));
+}
+
+
+#define sys_fcntl elks_fcntl
+static int elks_fcntl(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("fcntl(%d,%d,%d)\n", bx,cx,dx));
+ switch(cx)
+ {
+ case ELKS_F_GETFD:
+ return fcntl(bx,F_GETFD,0);
+ case ELKS_F_GETFL:
+ return fcntl(bx,F_GETFL,0);
+ case ELKS_F_DUPFD:
+ return fcntl(bx,F_DUPFD,dx);
+ case ELKS_F_SETFD:
+ return fcntl(bx,F_SETFD,dx);
+ case ELKS_F_SETFL:
+ return fcntl(bx,F_SETFL,dx);
+ /*
+ * Fixme: Unpack and process elks file locks
+ */
+ case ELKS_F_GETLK:
+ case ELKS_F_SETLK:
+ case ELKS_F_SETLKW:
+ errno = EINVAL;
+ return -1;
+ }
+ errno = EINVAL;
+ return -1;
+}
+
+#define sys_rename elks_rename
+static int elks_rename(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("rename(%s,%s)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx)));
+ return rename(ELKS_PTR(char, bx), ELKS_PTR(char, cx));
+}
+
+#define sys_mkdir elks_mkdir
+static int elks_mkdir(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("mkdir(%s,%d)\n", ELKS_PTR(char, bx),cx));
+ return mkdir(ELKS_PTR(char, bx),cx);
+}
+
+#define sys_rmdir elks_rmdir
+static int elks_rmdir(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("rmdir(%s)\n", ELKS_PTR(char, bx)));
+ return rmdir(ELKS_PTR(char, bx));
+}
+
+#define sys_gettimeofday elks_gettimeofday
+static int elks_gettimeofday(int bx,int cx,int dx,int di,int si)
+{
+ struct timeval tv;
+ struct timezone tz;
+ int ax;
+ dbprintf(("gettimeofday(%d,%d)\n",bx,cx));
+
+ ax = gettimeofday(&tv, &tz);
+
+ if( ax == 0 && bx )
+ {
+ ELKS_POKE(long, bx, tv.tv_sec);
+ ELKS_POKE(long, bx+4, tv.tv_usec);
+ }
+ if( ax == 0 && cx )
+ {
+ ELKS_POKE(short, cx, tz.tz_minuteswest);
+ ELKS_POKE(short, cx+2, tz.tz_dsttime);
+ }
+ return ax?-1:0;
+}
+
+#define sys_settimeofday elks_settimeofday
+static int elks_settimeofday(int bx,int cx,int dx,int di,int si)
+{
+ struct timeval tv, *pv = 0;
+ struct timezone tz, *pz = 0;
+ int ax;
+ dbprintf(("settimeofday(%d,%d)\n",bx,cx));
+
+ if( bx )
+ {
+ pv = &tv;
+ tv.tv_sec = ELKS_PEEK(long, bx);
+ tv.tv_usec = ELKS_PEEK(long, bx+4);
+ }
+ if( cx )
+ {
+ pz = &tz;
+ tz.tz_minuteswest = ELKS_PEEK(short, cx);
+ tz.tz_dsttime = ELKS_PEEK(short, cx+2);
+ }
+
+ ax = settimeofday(pv, pz);
+ return ax?-1:0;
+}
+
+#define sys_nice elks_nice
+static int elks_nice(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("nice(%d)\n",bx));
+ return nice(bx);
+}
+
+#define sys_symlink elks_symlink
+static int elks_symlink(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("symlink(%s,%s)\n", ELKS_PTR(char, bx), ELKS_PTR(char, cx)));
+ return symlink(ELKS_PTR(char, bx), ELKS_PTR(char, cx));
+}
+
+#define sys_readlink elks_readlink
+static int elks_readlink(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("readlink(%s,%s,%d)\n",
+ ELKS_PTR(char, bx),
+ ELKS_PTR(char, cx),
+ dx));
+ return readlink(ELKS_PTR(char, bx), ELKS_PTR(char, cx), dx);
+}
+
+#define sys_ioctl elks_ioctl
+static int elks_ioctl(int bx,int cx,int dx,int di,int si)
+{
+ dbprintf(("ioctl(%d,0x%04x,0x%04x)\n", bx,cx,dx));
+ switch((cx>>8)&0xFF)
+ {
+ case 'T': return elks_termios(bx,cx,dx,di,si);
+ default: return elks_enosys(bx,cx,dx,di,si);
+ }
+}
+
+#define sys_reboot elks_reboot
+static int elks_reboot(int bx,int cx,int dx,int di,int si)
+{
+ errno = EINVAL;
+ if( bx != 0xfee1 || cx != 0xdead ) return -1;
+
+ switch(dx)
+ {
+ /* graceful shutdown, C-A-D off, kill -? 1 */
+ case 0: return reboot(0xfee1dead, 672274793, 0);
+ /* Enable C-A-D */
+ case 0xCAD: return reboot(0xfee1dead, 672274793, 0x89abcdef);
+ /* Time to die! */
+ case 0xD1E: return reboot(0xfee1dead, 672274793, 0x1234567);
+ }
+ return -1;
+}
+
+/****************************************************************************/
+
+static int
+elks_opendir(char * dname)
+{
+ DIR * d;
+ int rv;
+ for(rv=0; rv<DIRCOUNT; rv++)
+ if( dirtab[rv] == 0 )
+ break;
+ if( rv >= DIRCOUNT ) { errno=ENOMEM; return -1; }
+ d = opendir(dname);
+ if( d == 0 ) return -1;
+ dirtab[rv] = d;
+ return 10000+rv;
+}
+
+static int
+elks_readdir(int bx, int cx, int dx)
+{
+ struct dirent * ent;
+
+ /* Only read _ONE_ _WHOLE_ dirent at a time */
+ if( dx != 266 )
+ {
+ errno=EINVAL; return -1;
+ }
+ errno = 0;
+ ent = readdir(dirtab[bx-10000]);
+ if( ent == 0 ) { if( errno ) { return -1; } else return 0; }
+
+ memcpy(ELKS_PTR(char, cx+10), ent->d_name, ent->d_reclen+1);
+ ELKS_POKE(long, cx, ent->d_ino);
+ ELKS_POKE(short, cx+8, ent->d_reclen);
+ return dx;
+}
+
+static int
+elks_closedir(int bx)
+{
+ bx-=10000;
+ if( dirtab[bx] ) closedir(dirtab[bx]);
+ dirtab[bx] = 0;
+ return 0;
+}
+
+/****************************************************************************/
+
+static int elks_termios(int bx,int cx,int dx,int di,int si)
+{
+ int rv = 0;
+ switch(cx&0xFF)
+ {
+ case 0x01: rv = ioctl(bx, TCGETS, ELKS_PTR(void, dx)); break;
+ case 0x02: rv = ioctl(bx, TCSETS, ELKS_PTR(void, dx)); break;
+ case 0x03: rv = ioctl(bx, TCSETSW, ELKS_PTR(void, dx)); break;
+ case 0x04: rv = ioctl(bx, TCSETSF, ELKS_PTR(void, dx)); break;
+
+ case 0x09: rv = ioctl(bx, TCSBRK, dx); break;
+ case 0x0A: rv = ioctl(bx, TCXONC, dx); break;
+ case 0x0B: rv = ioctl(bx, TCFLSH, dx); break;
+
+ default: rv = -1; errno = EINVAL; break;
+ }
+ return rv;
+}
+
+/****************************************************************************/
+/* */
+/****************************************************************************/
+#define sys_enosys elks_enosys
+static int elks_enosys(int bx,int cx,int dx,int di,int si)
+{
+ fprintf(stderr, "Function number %d called (%d,%d,%d)\n",
+ (int)(0xFFFF&elks_cpu.regs.eax),
+ bx, cx, dx);
+ errno = ENOSYS;
+ return -1;
+}
+
+#include "defn_tab.v"
+/* * */
+
+typedef int (*funcp)(int, int, int, int, int);
+
+static funcp jump_tbl[] = {
+#include "call_tab.v"
+ elks_enosys
+};
+
+int elks_syscall(void)
+{
+ int r, n;
+ int bx=elks_cpu.regs.ebx&0xFFFF;
+ int cx=elks_cpu.regs.ecx&0xFFFF;
+ int dx=elks_cpu.regs.edx&0xFFFF;
+ int di=elks_cpu.regs.edi&0xFFFF;
+ int si=elks_cpu.regs.esi&0xFFFF;
+
+ errno=0;
+ n = (elks_cpu.regs.eax&0xFFFF);
+ if( n>= 0 && n< sizeof(jump_tbl)/sizeof(funcp) )
+ r = (*(jump_tbl[n]))(bx, cx, dx, di, si);
+ else
+ return -ENOSYS;
+
+ if(r>=0)
+ return r;
+ else
+ return -errno;
+}
diff --git a/ld/6809/config.h b/ld/6809/config.h
new file mode 100644
index 0000000..dc5fed4
--- /dev/null
+++ b/ld/6809/config.h
@@ -0,0 +1,28 @@
+/* config.h - configuration for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/* one of these target processors must be defined */
+
+#undef I8086 /* Intel 8086 */
+#undef I80386 /* Intel 80386 */
+#define MC6809 /* Motorola 6809 */
+
+/* one of these target operating systems must be defined */
+
+#define EDOS /* generate EDOS executable */
+#undef MINIX /* generate Minix executable */
+
+/* these may need to be defined to suit the source processor */
+
+#define HOST_8BIT /* enable some 8-bit optimizations */
+
+/* #define S_ALIGNMENT 4 */ /* source memory alignment, power of 2 */
+ /* don't use for 8 bit processors */
+ /* don't use even for 80386 - overhead for */
+ /* alignment cancels improved access */
+
+/* these must be defined to suit the source libraries */
+
+#define CREAT_PERMS 0666 /* permissions for creat() */
+#define EXEC_PERMS 0111 /* extra permissions to set for executable */
diff --git a/ld/Makefile b/ld/Makefile
new file mode 100644
index 0000000..d93579a
--- /dev/null
+++ b/ld/Makefile
@@ -0,0 +1,29 @@
+
+ifneq ($(TOPDIR),)
+include $(TOPDIR)/Make.defs
+else
+CC=bcc
+LDFLAGS=-s
+endif
+
+OBJS =dumps.o io.o ld.o readobj.o table.o typeconv.o writebin.o
+
+all: ld86
+
+ld86: $(OBJS)
+ $(CC) $(LDFLAGS) $(OBJS) -o $@
+
+install: ld86
+ install -d $(LIBDIR)
+ install -m 755 ld86 $(LIBDIR)
+
+clean:
+ rm -f $(OBJS) ld86
+
+dumps.o: dumps.c const.h config.h obj.h type.h globvar.h
+io.o: io.c const.h config.h obj.h type.h globvar.h
+ld.o: ld.c const.h config.h byteord.h type.h globvar.h
+readobj.o: readobj.c const.h config.h byteord.h obj.h type.h globvar.h
+table.o: table.c const.h config.h align.h obj.h type.h globvar.h
+typeconv.o: typeconv.c const.h config.h type.h globvar.h
+writebin.o: writebin.c const.h config.h obj.h type.h globvar.h
diff --git a/ld/README.1994 b/ld/README.1994
new file mode 100644
index 0000000..669c8a8
--- /dev/null
+++ b/ld/README.1994
@@ -0,0 +1,17 @@
+The `bcc' and `ld' parts of the bin86 distribution are now covered by the
+GNU GPL. The next release of the `as' part will be covered by the GPL.
+The `a.out.h' part is no longer used and should be deleted. The `bccfp'
+belongs in another package and may be deleted.
+
+`ld' is now correctly ported to linux. It now defaults to the target
+a.out format for output. However, it still requires its own special
+format for input. It is best used as a post-processor for `as' to
+produce objects in a.out format. Then the target ld can be used to
+link the objects. The post-processing step is:
+
+ ld86 -r -o tmpfile.o file.o && mv tmpfile.o file.o
+
+This can be handled more simply by using the `bcc' compiler driver as
+the assembler and never calling as86 or ld86 directly:
+
+ AS86="bcc -G -0 -c"
diff --git a/ld/a.out.h b/ld/a.out.h
new file mode 100644
index 0000000..f6a7b94
--- /dev/null
+++ b/ld/a.out.h
@@ -0,0 +1,115 @@
+/* Copyright (C) 1990-1996
+ * This file is part of the ld86 command for Linux-86
+ * It is distributed under the GNU Library General Public License.
+ *
+ * - This may actually be BSD or Minix code, can someone clarify please. -RDB
+ */
+
+#ifndef __AOUT_H
+#define __AOUT_H
+
+struct exec { /* a.out header */
+ unsigned char a_magic[2]; /* magic number */
+ unsigned char a_flags; /* flags, see below */
+ unsigned char a_cpu; /* cpu id */
+ unsigned char a_hdrlen; /* length of header */
+ unsigned char a_unused; /* reserved for future use */
+ unsigned short a_version; /* version stamp (not used at present) */
+ long a_text; /* size of text segement in bytes */
+ long a_data; /* size of data segment in bytes */
+ long a_bss; /* size of bss segment in bytes */
+ long a_entry; /* entry point */
+ long a_total; /* total memory allocated */
+ long a_syms; /* size of symbol table */
+
+ /* SHORT FORM ENDS HERE */
+ long a_trsize; /* text relocation size */
+ long a_drsize; /* data relocation size */
+ long a_tbase; /* text relocation base */
+ long a_dbase; /* data relocation base */
+};
+
+#define A_MAGIC0 (unsigned char) 0x01
+#define A_MAGIC1 (unsigned char) 0x03
+#define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1)
+
+/* CPU Id of TARGET machine (byte order coded in low order two bits) */
+#define A_NONE 0x00 /* unknown */
+#define A_I8086 0x04 /* intel i8086/8088 */
+#define A_M68K 0x0B /* motorola m68000 */
+#define A_NS16K 0x0C /* national semiconductor 16032 */
+#define A_I80386 0x10 /* intel i80386 */
+#define A_SPARC 0x17 /* Sun SPARC */
+
+#define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */
+#define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */
+
+/* Flags. */
+#define A_UZP 0x01 /* unmapped zero page (pages) */
+#define A_PAL 0x02 /* page aligned executable */
+#define A_NSYM 0x04 /* new style symbol table */
+#define A_EXEC 0x10 /* executable */
+#define A_SEP 0x20 /* separate I/D */
+#define A_PURE 0x40 /* pure text */
+#define A_TOVLY 0x80 /* text overlay */
+
+/* Offsets of various things. */
+#define A_MINHDR 32
+#define A_TEXTPOS(X) ((long)(X).a_hdrlen)
+#define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text)
+#define A_HASRELS(X) ((X).a_hdrlen > (unsigned char) A_MINHDR)
+#define A_HASEXT(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 8))
+#define A_HASLNS(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 16))
+#define A_HASTOFF(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 24))
+#define A_TRELPOS(X) (A_DATAPOS(X) + (X).a_data)
+#define A_DRELPOS(X) (A_TRELPOS(X) + (X).a_trsize)
+#define A_SYMPOS(X) (A_TRELPOS(X) + (A_HASRELS(X) ? \
+ ((X).a_trsize + (X).a_drsize) : 0))
+
+struct reloc {
+ long r_vaddr; /* virtual address of reference */
+ unsigned short r_symndx; /* internal segnum or extern symbol num */
+ unsigned short r_type; /* relocation type */
+};
+
+/* r_tyep values: */
+#define R_ABBS 0
+#define R_RELLBYTE 2
+#define R_PCRBYTE 3
+#define R_RELWORD 4
+#define R_PCRWORD 5
+#define R_RELLONG 6
+#define R_PCRLONG 7
+#define R_REL3BYTE 8
+#define R_KBRANCHE 9
+
+/* r_symndx for internal segments */
+#define S_ABS ((unsigned short)-1)
+#define S_TEXT ((unsigned short)-2)
+#define S_DATA ((unsigned short)-3)
+#define S_BSS ((unsigned short)-4)
+
+struct nlist { /* symbol table entry */
+ char n_name[24]; /* symbol name */
+ long n_value; /* value */
+ unsigned char n_sclass; /* storage class */
+ unsigned char n_numaux; /* number of auxiliary entries (not used) */
+ unsigned short n_type; /* language base and derived type (not used) */
+};
+
+/* Low bits of storage class (section). */
+#define N_SECT 07 /* section mask */
+#define N_UNDF 00 /* undefined */
+#define N_ABS 01 /* absolute */
+#define N_TEXT 02 /* text */
+#define N_DATA 03 /* data */
+#define N_BSS 04 /* bss */
+#define N_COMM 05 /* (common) */
+
+/* High bits of storage class. */
+#define N_CLASS 0370 /* storage class mask */
+#define C_NULL
+#define C_EXT 0020 /* external symbol */
+#define C_STAT 0030 /* static */
+
+#endif /* _AOUT_H */
diff --git a/ld/align.h b/ld/align.h
new file mode 100644
index 0000000..ba33fb8
--- /dev/null
+++ b/ld/align.h
@@ -0,0 +1,10 @@
+/* align.h - memory alignment requirements for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#ifndef S_ALIGNMENT
+# define align(x)
+#else
+# define align(x) ((x) = ((int) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))
+ /* assumes sizeof(int) == sizeof(char *) */
+#endif
diff --git a/ld/bugs b/ld/bugs
new file mode 100644
index 0000000..b671f30
--- /dev/null
+++ b/ld/bugs
@@ -0,0 +1,17 @@
+1. Should cause error when an address which requires > 16 bits is referenced
+ using 16 bits.
+
+TODO:
+ integrate byteord.h with compiler as well as assembler
+
+TODO:
+ integrate align.h with compiler and assembler
+ use alignment for *86 like compiler - use more portable macro
+ ((x) + (-(int) (x) & MASK)) when it is either necessary or
+ faster
+
+TODO:
+ do malloc stuff better, as in compiler
+
+2. Error message about "foo.a is not an object file" is confusing - should
+ name archive member.
diff --git a/ld/byteord.h b/ld/byteord.h
new file mode 100644
index 0000000..57d17b9
--- /dev/null
+++ b/ld/byteord.h
@@ -0,0 +1,20 @@
+/* byteord.h - byte order dependencies for C compiler, assembler, linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/* These are for the targets of everything and for linker source too. */
+
+#ifdef I8086
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */
+#endif
+
+#ifdef I80386
+# define BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0
+#endif
+
+#ifdef MC6809
+# define BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
diff --git a/ld/config.h b/ld/config.h
new file mode 100644
index 0000000..201c153
--- /dev/null
+++ b/ld/config.h
@@ -0,0 +1,28 @@
+/* config.h - configuration for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/* one of these target processors must be defined */
+
+#undef I8086 /* Intel 8086 */
+#define I80386 /* Intel 80386 */
+#undef MC6809 /* Motorola 6809 */
+
+/* one of these target operating systems must be defined */
+
+#undef EDOS /* generate EDOS executable */
+#define MINIX /* generate Minix executable */
+
+/* these may need to be defined to suit the source processor */
+
+#undef HOST_8BIT /* enable some 8-bit optimizations */
+
+/* #define S_ALIGNMENT 4 */ /* source memory alignment, power of 2 */
+ /* don't use for 8 bit processors */
+ /* don't use even for 80386 - overhead for */
+ /* alignment cancels improved access */
+
+/* these must be defined to suit the source libraries */
+
+#define CREAT_PERMS 0666 /* permissions for creat() */
+#define EXEC_PERMS 0111 /* extra permissions to set for executable */
diff --git a/ld/const.h b/ld/const.h
new file mode 100644
index 0000000..04d6330
--- /dev/null
+++ b/ld/const.h
@@ -0,0 +1,14 @@
+/* const.h - constants for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#define FALSE 0
+#define NUL_PTR ((void*)0)
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+
+#include "config.h"
diff --git a/ld/dumps.c b/ld/dumps.c
new file mode 100644
index 0000000..c9a40d4
--- /dev/null
+++ b/ld/dumps.c
@@ -0,0 +1,68 @@
+/* dumps.c - print data about symbols and modules for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+/* print list of modules and whether they are loaded */
+
+PUBLIC void dumpmods()
+{
+ struct modstruct *modptr;
+
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ {
+ putstr(modptr->loadflag ? "L " : " ");
+ putbstr(20, modptr->modname);
+ putbyte('\n');
+ }
+}
+
+/* print data about symbols (in loaded modules only) */
+
+PUBLIC void dumpsyms()
+{
+ flags_t flags;
+ struct modstruct *modptr;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+ char uflag;
+
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr)
+ {
+ uflag = FALSE;
+ if (((flags = symptr->flags) & (C_MASK | I_MASK)) == I_MASK)
+ uflag = TRUE;
+ putbstr(20, uflag ? "" : modptr->modname);
+ putstr(" ");
+ putbstr(20, symptr->name);
+ putstr(" ");
+ putbyte(hexdigit[flags & SEGM_MASK]);
+ putstr(" ");
+ if (uflag)
+ putstr(" ");
+ else
+#ifdef LONG_OFFSETS
+ put08lx(symptr->value);
+#else
+ put08x(symptr->value);
+#endif
+ putstr(flags & A_MASK ? " A" : " R");
+ if (uflag)
+ putstr(" U");
+ if (flags & C_MASK)
+ putstr(" C");
+ if (flags & N_MASK)
+ putstr(" N");
+ putbyte('\n');
+ }
+ }
+}
diff --git a/ld/globvar.h b/ld/globvar.h
new file mode 100644
index 0000000..0351a6b
--- /dev/null
+++ b/ld/globvar.h
@@ -0,0 +1,14 @@
+/* globvar.h - global variables for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#ifdef EXTERN
+EXTERN char hexdigit[];
+#else
+#define EXTERN
+PUBLIC char hexdigit[] = "0123456789abcdef";
+#endif
+EXTERN unsigned errcount; /* count of errors */
+EXTERN struct entrylist *entryfirst; /* first on list of entry symbols */
+EXTERN struct modstruct *modfirst; /* data for 1st module */
+EXTERN struct redlist *redfirst; /* first on list of redefined symbols */
diff --git a/ld/include/fcntl.h b/ld/include/fcntl.h
new file mode 100644
index 0000000..8c1ec8b
--- /dev/null
+++ b/ld/include/fcntl.h
@@ -0,0 +1,2 @@
+#define O_RDONLY 0
+#define O_WRONLY 1
diff --git a/ld/io.c b/ld/io.c
new file mode 100644
index 0000000..c1829c8
--- /dev/null
+++ b/ld/io.c
@@ -0,0 +1,607 @@
+/* io.c - input/output and error modules for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "const.h"
+#include "obj.h" /* needed for LONG_OFFSETS and offset_t */
+#include "type.h"
+#include "globvar.h"
+#include <fcntl.h>
+
+#ifdef STDC_HEADERS_MISSING
+void exit P((int status));
+void *malloc P((unsigned size));
+#else
+#include <stdlib.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+#define SEEK_SET 0
+#define STDOUT_FILENO 0
+#include <sys/types.h>
+#include <sys/stat.h>
+#define mode_t unsigned short
+#define off_t long
+int chmod P((const char *path, int mode));
+int close P((int fd));
+int creat P((const char *path, int mode));
+int fstat P((int fd, struct stat *statbuf));
+off_t lseek P((int fd, off_t offset, int whence));
+int open P((const char *path, int oflag, ...));
+int read P((int fd, void *buf, unsigned nbytes));
+mode_t umask P((int oldmask));
+int write P((int fd, const void *buf, unsigned nbytes));
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+#define DRELBUFSIZE 3072
+#define ERR (-1)
+#define ERRBUFSIZE 1024
+#define INBUFSIZE 1024
+#define OUTBUFSIZE 2048
+#define TRELBUFSIZE 1024
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifdef BSD_A_OUT
+PRIVATE char *drelbuf; /* extra output buffer for data relocations */
+PRIVATE char *drelbufptr; /* data relocation output buffer ptr */
+PRIVATE char *drelbuftop; /* data relocation output buffer top */
+#endif
+PRIVATE char *errbuf; /* error buffer (actually uses STDOUT) */
+PRIVATE char *errbufptr; /* error buffer ptr */
+PRIVATE char *errbuftop; /* error buffer top */
+PRIVATE char *inbuf; /* input buffer */
+PRIVATE char *inbufend; /* input buffer top */
+PRIVATE char *inbufptr; /* end of input in input buffer */
+PRIVATE int infd; /* input file descriptor */
+PRIVATE char *inputname; /* name of current input file */
+PRIVATE char *outbuf; /* output buffer */
+PRIVATE char *outbufptr; /* output buffer ptr */
+PRIVATE char *outbuftop; /* output buffer top */
+PRIVATE int outfd; /* output file descriptor */
+PRIVATE mode_t outputperms; /* permissions of output file */
+PRIVATE char *outputname; /* name of output file */
+PRIVATE char *refname; /* name of program for error reference */
+#ifdef BSD_A_OUT
+PRIVATE char *trelbuf; /* extra output buffer for text relocations */
+PRIVATE char *trelbufptr; /* text relocation output buffer ptr */
+PRIVATE char *trelbuftop; /* text relocation output buffer top */
+PRIVATE int trelfd; /* text relocation output file descriptor */
+#endif
+PRIVATE unsigned warncount; /* count of warnings */
+
+FORWARD void errexit P((char *message));
+FORWARD void flushout P((void));
+#ifdef BSD_A_OUT
+FORWARD void flushtrel P((void));
+#endif
+FORWARD void outhexdigs P((offset_t num));
+FORWARD void outputerror P((char *message));
+FORWARD void put04x P((unsigned num));
+FORWARD void putstrn P((char *message));
+FORWARD void refer P((void));
+
+PUBLIC void ioinit(progname)
+char *progname;
+{
+ infd = ERR;
+ if (*progname)
+ refname = progname; /* name must be static (is argv[0]) */
+ else
+ refname = "link";
+#ifdef BSD_A_OUT
+ drelbuf = malloc(DRELBUFSIZE);
+ drelbuftop = drelbuf + DRELBUFSIZE;
+#endif
+ errbuf = malloc(ERRBUFSIZE);
+ errbufptr = errbuf;
+ errbuftop = errbuf + ERRBUFSIZE;
+ inbuf = malloc(INBUFSIZE);
+ outbuf = malloc(OUTBUFSIZE);/* outbuf invalid if this fails but then */
+ /* will not be used - tableinit() aborts */
+ outbuftop = outbuf + OUTBUFSIZE;
+#ifdef BSD_A_OUT
+ trelbuf = malloc(TRELBUFSIZE);
+ trelbuftop = trelbuf + TRELBUFSIZE;
+#endif
+}
+
+PUBLIC void closein()
+{
+ if (infd != ERR && close(infd) < 0)
+ inputerror("cannot close");
+ infd = ERR;
+}
+
+PUBLIC void closeout()
+{
+#ifdef BSD_A_OUT
+ unsigned nbytes;
+#endif
+
+ flushout();
+#ifdef BSD_A_OUT
+ flushtrel();
+ nbytes = drelbufptr - drelbuf;
+ if (write(trelfd, drelbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+#endif
+ if (close(outfd) == ERR)
+ outputerror("cannot close");
+#ifdef BSD_A_OUT
+ if (close(trelfd) == ERR)
+ outputerror("cannot close");
+#endif
+}
+
+PUBLIC void errtrace(name, level)
+char *name;
+int level;
+{
+ while (level-- > 0)
+ putbyte(' ');
+ putstrn(name);
+}
+
+PUBLIC void executable()
+{
+ mode_t oldmask;
+
+ if (errcount == 0)
+ {
+ oldmask = umask(0);
+ umask(oldmask);
+ chmod(outputname, outputperms | (EXEC_PERMS & ~oldmask));
+ }
+}
+
+PUBLIC void flusherr()
+{
+ write(STDOUT_FILENO, errbuf, (unsigned) (errbufptr - errbuf));
+ errbufptr = errbuf;
+}
+
+PRIVATE void flushout()
+{
+ unsigned nbytes;
+
+ nbytes = outbufptr - outbuf;
+ if (write(outfd, outbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+ outbufptr = outbuf;
+}
+
+#ifdef BSD_A_OUT
+PRIVATE void flushtrel()
+{
+ unsigned nbytes;
+
+ nbytes = trelbufptr - trelbuf;
+ if (write(trelfd, trelbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+ trelbufptr = trelbuf;
+}
+#endif
+
+PUBLIC void openin(filename)
+char *filename;
+{
+#if 0 /* XXX - this probably won't work with constructed lib names? */
+ if (infd == ERR || strcmp(inputname, filename) != 0)
+#endif
+ {
+ closein();
+ inputname = filename; /* this relies on filename being static */
+ if ((infd = open(filename, O_BINARY|O_RDONLY)) < 0)
+ inputerror("cannot open");
+ inbufptr = inbufend = inbuf;
+ }
+}
+
+PUBLIC void openout(filename)
+char *filename;
+{
+ struct stat statbuf;
+
+ outputname = filename;
+ if ((outfd = open(filename, O_BINARY|O_RDWR|O_CREAT|O_TRUNC, CREAT_PERMS)) == ERR)
+ outputerror("cannot open");
+ if (fstat(outfd, &statbuf) != 0)
+ outputerror("cannot stat");
+ outputperms = statbuf.st_mode;
+ chmod(filename, outputperms & ~EXEC_PERMS);
+#ifdef BSD_A_OUT
+ drelbufptr = drelbuf;
+#endif
+ outbufptr = outbuf;
+#ifdef BSD_A_OUT
+ if ((trelfd = open(filename, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, CREAT_PERMS)) == ERR)
+ outputerror("cannot reopen");
+ trelbufptr = trelbuf;
+#endif
+}
+
+PRIVATE void outhexdigs(num)
+register offset_t num;
+{
+ if (num >= 0x10)
+ {
+ outhexdigs(num / 0x10);
+ num %= 0x10;
+ }
+ putbyte(hexdigit[num]);
+}
+
+PRIVATE void put04x(num)
+register unsigned num;
+{
+ putbyte(hexdigit[num / 0x1000]);
+ putbyte(hexdigit[(num / 0x100) & 0x0F]);
+ putbyte(hexdigit[(num / 0x10) & 0x0F]);
+ putbyte(hexdigit[num & 0x0F]);
+}
+
+#ifdef LONG_OFFSETS
+
+PUBLIC void put08lx(num)
+register offset_t num;
+{
+ put04x(num / 0x10000);
+ put04x(num % 0x10000);
+}
+
+#else /* not LONG_OFFSETS */
+
+PUBLIC void put08x(num)
+register offset_t num;
+{
+ putstr("0000");
+ put04x(num);
+}
+
+#endif /* not LONG_OFFSETS */
+
+PUBLIC void putbstr(width, str)
+unsigned width;
+char *str;
+{
+ unsigned length;
+
+ for (length = strlen(str); length < width; ++length)
+ putbyte(' ');
+ putstr(str);
+}
+
+PUBLIC void putbyte(ch)
+int ch;
+{
+ register char *ebuf;
+
+ ebuf = errbufptr;
+ if (ebuf >= errbuftop)
+ {
+ flusherr();
+ ebuf = errbufptr;
+ }
+ *ebuf++ = ch;
+ errbufptr = ebuf;
+}
+
+PUBLIC void putstr(message)
+char *message;
+{
+ while (*message != 0)
+ putbyte(*message++);
+}
+
+PRIVATE void putstrn(message)
+char *message;
+{
+ putstr(message);
+ putbyte('\n');
+ flusherr();
+}
+
+PUBLIC int readchar()
+{
+ int ch;
+
+ register char *ibuf;
+ int nread;
+
+ ibuf = inbufptr;
+ if (ibuf >= inbufend)
+ {
+ ibuf = inbufptr = inbuf;
+ nread = read(infd, ibuf, INBUFSIZE);
+ if (nread <= 0)
+ {
+ inbufend = ibuf;
+ return ERR;
+ }
+ inbufend = ibuf + nread;
+ }
+ ch = (unsigned char) *ibuf++;
+ inbufptr = ibuf;
+ return ch;
+}
+
+PUBLIC void readin(buf, count)
+char *buf;
+unsigned count;
+{
+ int ch;
+
+ while (count--)
+ {
+ if ((ch = readchar()) < 0)
+ prematureeof();
+ *buf++ = ch;
+ }
+}
+
+PUBLIC bool_pt readineofok(buf, count)
+char *buf;
+unsigned count;
+{
+ int ch;
+
+ while (count--)
+ {
+ if ((ch = readchar()) < 0)
+ return TRUE;
+ *buf++ = ch;
+ }
+ return FALSE;
+}
+
+PUBLIC void seekin(offset)
+unsigned long offset;
+{
+ inbufptr = inbufend = inbuf;
+ if (lseek(infd, (off_t) offset, SEEK_SET) != offset)
+ prematureeof();
+}
+
+PUBLIC void seekout(offset)
+unsigned long offset;
+{
+ flushout();
+ if (lseek(outfd, (off_t) offset, SEEK_SET) != offset)
+ outputerror("cannot seek in");
+}
+
+#ifdef BSD_A_OUT
+PUBLIC void seektrel(offset)
+unsigned long offset;
+{
+ flushtrel();
+ if (lseek(trelfd, (off_t) offset, SEEK_SET) != offset)
+ outputerror("cannot seek in");
+}
+#endif
+
+PUBLIC void writechar(ch)
+int ch;
+{
+ register char *obuf;
+
+ obuf = outbufptr;
+ if (obuf >= outbuftop)
+ {
+ flushout();
+ obuf = outbufptr;
+ }
+ *obuf++ = ch;
+ outbufptr = obuf;
+}
+
+#ifdef BSD_A_OUT
+PUBLIC void writedrel(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *rbuf;
+
+ rbuf = drelbufptr;
+ while (count--)
+ {
+ if (rbuf >= drelbuftop)
+ inputerror("data relocation buffer full while processing");
+ *rbuf++ = *buf++;
+ }
+ drelbufptr = rbuf;
+}
+#endif
+
+PUBLIC void writeout(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *obuf;
+
+ obuf = outbufptr;
+ while (count--)
+ {
+ if (obuf >= outbuftop)
+ {
+ outbufptr = obuf;
+ flushout();
+ obuf = outbufptr;
+ }
+ *obuf++ = *buf++;
+ }
+ outbufptr = obuf;
+}
+
+#ifdef BSD_A_OUT
+PUBLIC void writetrel(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *rbuf;
+
+ rbuf = trelbufptr;
+ while (count--)
+ {
+ if (rbuf >= trelbuftop)
+ {
+ trelbufptr = rbuf;
+ flushtrel();
+ rbuf = trelbufptr;
+ }
+ *rbuf++ = *buf++;
+ }
+ trelbufptr = rbuf;
+}
+#endif
+
+/* error module */
+
+PRIVATE void errexit(message)
+char *message;
+{
+ putstrn(message);
+ exit(2);
+}
+
+PUBLIC void fatalerror(message)
+char *message;
+{
+ refer();
+ errexit(message);
+}
+
+PUBLIC void inputerror(message)
+char *message;
+{
+ refer();
+ putstr(message);
+ putstr(" input file ");
+ errexit(inputname);
+}
+
+PUBLIC void input1error(message)
+char *message;
+{
+ refer();
+ putstr(inputname);
+ errexit(message);
+}
+
+PRIVATE void outputerror(message)
+char *message;
+{
+ refer();
+ putstr(message);
+ putstr(" output file ");
+ errexit(outputname);
+}
+
+PUBLIC void outofmemory()
+{
+ inputerror("out of memory while processing");
+}
+
+PUBLIC void prematureeof()
+{
+ inputerror("premature end of");
+}
+
+PUBLIC void redefined(name, message, archentry, deffilename, defarchentry)
+char *name;
+char *message;
+char *archentry;
+char *deffilename;
+char *defarchentry;
+{
+ ++warncount;
+ refer();
+ putstr("warning: ");
+ putstr(name);
+ putstr(" redefined");
+ putstr(message);
+ putstr(" in file ");
+ putstr(inputname);
+ if (archentry != NUL_PTR)
+ {
+ putbyte('(');
+ putstr(archentry);
+ putbyte(')');
+ }
+ putstr("; using definition in ");
+ putstr(deffilename);
+ if (defarchentry != NUL_PTR)
+ {
+ putbyte('(');
+ putstr(defarchentry);
+ putbyte(')');
+ }
+ putbyte('\n');
+}
+
+PRIVATE void refer()
+{
+ putstr(refname);
+ putstr(": ");
+}
+
+PUBLIC void reserved(name)
+char *name;
+{
+ ++errcount;
+ putstr("incorrect use of reserved symbol: ");
+ putstrn(name);
+}
+
+PUBLIC void size_error(seg, count, size)
+int seg;
+offset_t count;
+offset_t size;
+{
+ refer();
+ putstr("seg ");
+ outhexdigs((offset_t) seg);
+ putstr(" has wrong size ");
+ outhexdigs(count);
+ putstr(", supposed to be ");
+ outhexdigs(size);
+ errexit("\n");
+}
+
+PUBLIC void undefined(name)
+char *name;
+{
+ ++errcount;
+ putstr("undefined symbol: ");
+ putstrn(name);
+}
+
+PUBLIC void usage()
+{
+ putstr("usage: ");
+ putstr(refname);
+#ifdef BSD_A_OUT
+ errexit("\
+ [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-Llibdir] [-Olibfile] [-T textaddr] infile...");
+#else
+ errexit("\
+ [-03Mimstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-Llibdir] [-Olibfile] [-T textaddr] infile...");
+#endif
+}
+
+PUBLIC void use_error(message)
+char *message;
+{
+ refer();
+ putstrn(message);
+ usage();
+}
diff --git a/ld/ld.c b/ld/ld.c
new file mode 100644
index 0000000..a333f04
--- /dev/null
+++ b/ld/ld.c
@@ -0,0 +1,191 @@
+/* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "const.h"
+#include "byteord.h"
+#include "type.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+extern int errno;
+char *strcat P((char *dest, const char *src));
+unsigned long strtoul P((const char *s, char **endptr, int base));
+#else
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#ifdef POSIX_HEADERS_MISSING
+#define R_OK 0
+int access P((const char *path, int amode));
+#else
+#include <unistd.h>
+#endif
+
+#define MAX_LIBS (NR_STDLIBS + 5)
+#ifdef MC6809
+#define NR_STDLIBS 1
+#else
+#define NR_STDLIBS 0
+#endif
+
+PUBLIC long text_base_address; /* XXX */
+PUBLIC int doscomfile = 0;
+
+PRIVATE bool_t flag[128];
+PRIVATE char *libs[MAX_LIBS] = {
+#ifdef MC6809
+ "/usr/local/lib/m09/",
+#endif
+ 0
+};
+PRIVATE int lastlib = NR_STDLIBS;
+
+FORWARD char *buildname P((char *pre, char *mid, char *suf));
+FORWARD char *expandlib P((char *fn));
+
+PRIVATE char *buildname(pre, mid, suf)
+char *pre;
+char *mid;
+char *suf;
+{
+ char *name;
+
+ name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1);
+ strcpy(name, pre);
+ strcat(name, mid);
+ strcat(name, suf);
+ return name;
+}
+
+PRIVATE char *expandlib(fn)
+char *fn;
+{
+ char *path;
+ int i;
+
+ for (i = lastlib - 1; i >= 0; --i)
+ {
+ path = ourmalloc(strlen(libs[i]) + strlen(fn) + 1);
+ strcpy(path, libs[i]);
+ strcat(path, fn);
+ if (access(path, R_OK) == 0)
+ return path;
+ ourfree(path);
+ }
+ return NUL_PTR;
+}
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ register char *arg;
+ int argn;
+ static char crtprefix[] = "crt";
+ static char crtsuffix[] = ".o";
+ char *infilename;
+ static char libprefix[] = "lib";
+ static char libsuffix[] = ".a";
+ char *outfilename;
+ char *tfn;
+
+ ioinit(argv[0]);
+ objinit();
+ syminit();
+ typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN);
+#ifndef MC6809
+ flag['z'] = flag['3'] = sizeof(char *) >= 4;
+#endif
+ outfilename = NUL_PTR;
+ for (argn = 1; argn < argc; ++argn)
+ {
+ arg = argv[argn];
+ if (*arg != '-')
+ readsyms(arg, flag['t']);
+ else
+ switch (arg[1])
+ {
+ case '0': /* use 16-bit libraries */
+ case '3': /* use 32-bit libraries */
+ case 'M': /* print symbols linked */
+ case 'i': /* separate I & D output */
+ case 'm': /* print modules linked */
+#ifdef BSD_A_OUT
+ case 'r': /* relocatable output */
+#endif
+ case 's': /* strip symbols */
+ case 't': /* trace modules linked */
+ case 'z': /* unmapped zero page */
+ if (arg[2] == 0)
+ flag[(int) arg[1]] = TRUE;
+ else if (arg[2] == '-' && arg[3] == 0)
+ flag[(int) arg[1]] = FALSE;
+ else
+ usage();
+ if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
+ flag['3'] = !flag['0'];
+ break;
+ case 'd': /* Make DOS com file */
+ flag['3'] = FALSE;
+ flag['z'] = FALSE;
+ flag['0'] = TRUE;
+ flag['s'] = TRUE;
+ flag['d'] = TRUE;
+ text_base_address = 0x100;
+ break;
+ case 'C': /* startfile name */
+ tfn = buildname(crtprefix, arg + 2, crtsuffix);
+ if ((infilename = expandlib(tfn)) == NUL_PTR)
+ fatalerror(tfn); /* XXX - need to describe failure */
+ readsyms(infilename, flag['t']);
+ break;
+ case 'L': /* library path */
+ if (lastlib < MAX_LIBS)
+ libs[lastlib++] = arg + 2;
+ else
+ fatalerror("too many library paths");
+ break;
+ case 'O': /* library file name */
+ if ((infilename = expandlib(arg + 2)) == NUL_PTR)
+ fatalerror(arg); /* XXX */
+ readsyms(infilename, flag['t']);
+ break;
+ case 'T': /* text base address */
+ if (arg[2] != 0 || ++argn >= argc)
+ usage();
+ errno = 0;
+ text_base_address = strtoul(argv[argn], (char **) NUL_PTR, 16);
+ if (errno != 0)
+ use_error("invalid text address");
+ break;
+ case 'l': /* library name */
+ tfn = buildname(libprefix, arg + 2, libsuffix);
+ if ((infilename = expandlib(tfn)) == NUL_PTR)
+ fatalerror(tfn); /* XXX */
+ readsyms(infilename, flag['t']);
+ break;
+ case 'o': /* output file name */
+ if (arg[2] != 0 || ++argn >= argc || outfilename != NUL_PTR)
+ usage();
+ outfilename = argv[argn];
+ break;
+ default:
+ usage();
+ }
+ }
+ doscomfile = flag['d'];
+ linksyms(flag['r']);
+ if (outfilename == NUL_PTR)
+ outfilename = "a.out";
+ writebin(outfilename, flag['i'], flag['3'], flag['s'],
+ flag['z'] & flag['3']);
+ if (flag['m'])
+ dumpmods();
+ if (flag['M'])
+ dumpsyms();
+ flusherr();
+ return errcount ? 1 : 0;
+}
diff --git a/ld/obj.h b/ld/obj.h
new file mode 100644
index 0000000..e0a52dc
--- /dev/null
+++ b/ld/obj.h
@@ -0,0 +1,54 @@
+/* obj.h - constants for Introl object modules */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#define OBJ_H
+
+#ifdef I80386
+# define LONG_OFFSETS /* others can use this, but wasteful */
+#endif
+
+#ifndef OMAGIC
+# ifdef I80386
+# define OMAGIC 0x86A3
+# endif
+
+# ifdef I8086
+# define OMAGIC 0x86A0
+# endif
+
+# ifdef MC6809
+# define OMAGIC 0x5331
+# endif
+#endif
+
+#ifdef LONG_OFFSETS
+# define cntooffset cnu4
+# define offtocn u4cn
+#else
+# define cntooffset cnu2
+# define offtocn u2cn
+#endif
+
+#ifdef MC6809 /* temp don't support alignment at all */
+# define roundup( num, boundary, type ) (num)
+#else
+# define roundup( num, boundary, type ) \
+ (((num) + ((boundary) - 1)) & (type) ~((boundary) - 1))
+#endif
+
+#define MAX_OFFSET_SIZE 4
+#define NSEG 16
+
+/* flag values |SZ|LXXXX|N|E|I|R|A|SEGM|, X not used */
+
+#define A_MASK 0x0010 /* absolute */
+#define C_MASK 0x0020 /* common (internal only) */
+#define E_MASK 0x0080 /* exported */
+#define I_MASK 0x0040 /* imported */
+#define N_MASK 0x0100 /* entry point */
+#define R_MASK 0x0020 /* relative (in text only) */
+#define SEGM_MASK 0x000F /* segment (if not absolute) */
+#define SA_MASK 0x2000 /* offset is storage allocation */
+#define SZ_MASK 0xC000 /* size descriptor for value */
+#define SZ_SHIFT 14
diff --git a/ld/readobj.c b/ld/readobj.c
new file mode 100644
index 0000000..bb6a6b5
--- /dev/null
+++ b/ld/readobj.c
@@ -0,0 +1,373 @@
+/* readobj.c - read object file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "ar.h" /* maybe local copy of <ar.h> for cross-link */
+#include "const.h"
+#include "byteord.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+int strncmp P((const char *s1, const char *s2, unsigned n));
+char *strncpy P((char *dest, const char *src, unsigned n));
+unsigned long strtoul P((const char *s, char **endptr, int base));
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+/*
+ Linking takes 2 passes. The 1st pass reads through all files specified
+in the command line, and all libraries. All public symbols are extracted
+and stored in a chained hash table. For each module, its file and header
+data recorded, and the resulting structures are chained together
+(interleaved with the symbols).
+
+ The symbol descriptors are separated from the symbol names, so we must
+record all the descriptors of a module before putting the symbols in the
+symbol table (poor design). The descriptors are stored in the symbol
+table, then moved to the top of the table to make room for the symols.
+The symbols referred to in a given module are linked together by a chain
+beginning in the module descriptor.
+*/
+
+PRIVATE unsigned convertsize[NSEG / 4] = {0, 1, 2, 4};
+PRIVATE struct entrylist *entrylast; /* last on list of entry symbols */
+PRIVATE struct redlist *redlast; /* last on list of redefined symbols */
+PRIVATE struct modstruct *modlast; /* data for last module */
+
+FORWARD long readarheader P((char **parchentry));
+FORWARD unsigned readfileheader P((void));
+FORWARD void readmodule P((char *filename, char *archentry));
+FORWARD void reedmodheader P((void));
+FORWARD bool_pt redsym P((struct symstruct *symptr, offset_t value));
+FORWARD unsigned checksum P((char *string, unsigned length));
+FORWARD unsigned segbits P((unsigned seg, char *sizedesc));
+
+/* initialise object file handler */
+
+PUBLIC void objinit()
+{
+ modfirst = modlast = NUL_PTR;
+ entryfirst = entrylast = NUL_PTR;
+ redfirst = redlast = NUL_PTR;
+}
+
+/* read all symbol definitions in an object file */
+
+PUBLIC void readsyms(filename, trace)
+char *filename;
+bool_pt trace;
+{
+ char *archentry;
+ long filelength;
+ char filemagic[SARMAG];
+ unsigned long filepos;
+ unsigned modcount;
+
+ if (trace)
+ errtrace(filename, 0);
+ openin(filename); /* input is not open, so position is start */
+ switch ((unsigned) readsize(2))
+ {
+ case OMAGIC:
+ seekin((unsigned long) 0);
+ for (modcount = readfileheader(); modcount-- != 0;)
+ readmodule(filename, (char *) NUL_PTR);
+ break;
+ default:
+ seekin((unsigned long) 0);
+ readin(filemagic, sizeof filemagic);
+ if (strncmp(filemagic, ARMAG, sizeof filemagic) != 0)
+ input1error(" has bad magic number");
+ filepos = SARMAG;
+ while ((filelength = readarheader(&archentry)) > 0)
+ {
+ if (trace)
+ errtrace(archentry, 2);
+ filepos += sizeof(struct ar_hdr);
+ for (modcount = readfileheader(); modcount-- != 0;)
+ {
+ readmodule(stralloc(filename), archentry);
+ modlast->textoffset += filepos;
+ }
+ seekin(filepos += roundup(filelength, 2, long));
+ }
+ break;
+ }
+ closein();
+}
+
+/* read archive header and return length */
+
+PRIVATE long readarheader(parchentry)
+char **parchentry;
+{
+ struct ar_hdr arheader;
+ char *endptr;
+ char *nameptr;
+
+ if (readineofok((char *) &arheader, sizeof arheader))
+ return 0;
+ strncpy (*parchentry = nameptr = ourmalloc(sizeof arheader.ar_name + 1),
+ arheader.ar_name, sizeof arheader.ar_name);
+ endptr = nameptr + sizeof arheader.ar_name;
+ do
+ *endptr = 0;
+ while (endptr > nameptr && *--endptr == ' ');
+ return strtoul(arheader.ar_size, (char **) NUL_PTR, 0);
+}
+
+/* read and check file header of the object file just opened */
+
+PRIVATE unsigned readfileheader()
+{
+ struct
+ {
+ char magic[2];
+ char count[2]; /* really an int */
+ }
+ fileheader;
+ char filechecksum; /* part of fileheader but would unalign */
+
+ readin((char *) &fileheader, sizeof fileheader);
+ readin(&filechecksum, sizeof filechecksum);
+ if (filechecksum != checksum((char *) &fileheader, sizeof fileheader))
+ input1error(" is not an object file");
+ return c2u2(fileheader.count);
+}
+
+/* read the next module */
+
+PRIVATE void readmodule(filename, archentry)
+char *filename;
+char *archentry;
+{
+ struct symdstruct /* to save parts of symbol before name known */
+ {
+ offset_t dvalue;
+ flags_t dflags;
+ };
+ struct symdstruct *endsymdptr;
+ flags_t flags;
+ unsigned nsymbol;
+ struct symdstruct *symdptr;
+ char *symname;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+
+ reedmodheader();
+ modlast->filename = filename;
+ modlast->archentry = archentry;
+ nsymbol = readsize(2);
+ symdptr = (struct symdstruct *)
+ ourmalloc(nsymbol * sizeof(struct symdstruct));
+ for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; ++symdptr)
+ {
+ readsize(2); /* discard string offset, assume strings seq */
+ symdptr->dflags = flags = readsize(2);
+ symdptr->dvalue = readconvsize((flags & SZ_MASK) >> SZ_SHIFT);
+ /* NB unsigned flags to give logical shift */
+ /* bug in Xenix 2.5 cc causes (int) of the */
+ /* argument to turn flags into an int */
+ }
+ symdptr = (struct symdstruct *)
+ moveup(nsymbol * sizeof(struct symdstruct));
+ modlast->symparray = symparray = (struct symstruct **)
+ ourmalloc((nsymbol + 1) * sizeof(struct symstruct *));
+ symname = readstring(); /* module name */
+ modlast->modname = stralloc(symname); /* likely OK overlapped copy */
+ for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr;
+ *symparray++ = symptr, release((char *) ++symdptr))
+ {
+ symname = readstring();
+ if ((flags = symdptr->dflags) & (E_MASK | I_MASK) &&
+ (symptr = findsym(symname)) != NUL_PTR)
+ {
+ /*
+ weaken segment-checking by letting the maximum segment
+ (SEGM_MASK) mean any segment
+ */
+ if ((symptr->flags & SEGM_MASK) == SEGM_MASK)
+ symptr->flags &= ~(flags_t) SEGM_MASK | (flags & SEGM_MASK);
+ else if ((flags & SEGM_MASK) == SEGM_MASK)
+ flags &= ~(flags_t) SEGM_MASK | (symptr->flags & SEGM_MASK);
+ if ((flags ^ symptr->flags) & (N_MASK | A_MASK | SEGM_MASK))
+ {
+ redefined(symname, " with different segment or relocatability",
+ archentry, symptr->modptr->filename,
+ symptr->modptr->archentry);
+ continue;
+ }
+ if (symptr->flags & E_MASK)
+ {
+ if (flags & E_MASK && redsym(symptr, symdptr->dvalue))
+ redefined(symname, "", archentry, symptr->modptr->filename,
+ symptr->modptr->archentry);
+ continue;
+ }
+ if (flags & I_MASK && symdptr->dvalue <= symptr->value)
+ continue;
+ }
+ else
+ symptr = addsym(symname);
+ symptr->modptr = modlast;
+ symptr->value = symdptr->dvalue;
+ symptr->flags = flags;
+ if (flags & N_MASK)
+ entrysym(symptr);
+ }
+ *symparray = NUL_PTR;
+}
+
+/* put symbol on entry symbol list if it is not already */
+
+PUBLIC void entrysym(symptr)
+struct symstruct *symptr;
+{
+ register struct entrylist *elptr;
+
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ if (symptr == elptr->elsymptr)
+ return;
+ elptr = (struct entrylist *) ourmalloc(sizeof(struct entrylist));
+ elptr->elnext = NUL_PTR;
+ elptr->elsymptr = symptr;
+ if (entryfirst == NUL_PTR)
+ entryfirst = elptr;
+ else
+ entrylast->elnext = elptr;
+ entrylast = elptr;
+}
+
+/* read the header of the next module */
+
+PRIVATE void reedmodheader()
+{
+ struct
+ {
+ char htextoffset[4]; /* offset to module text in file */
+ char htextsize[4]; /* size of text (may be 0 for last mod) */
+ char stringssize[2]; /* size of string area */
+ char hclass; /* module class */
+ char revision; /* module revision */
+ }
+ modheader;
+ unsigned seg;
+ unsigned count;
+ char *cptr;
+ struct modstruct *modptr;
+
+ readin((char *) &modheader, sizeof modheader);
+ modptr = (struct modstruct *) ourmalloc(sizeof(struct modstruct));
+ modptr->modnext = NUL_PTR;
+ modptr->textoffset = c4u4(modheader.htextoffset);
+ modptr->class = modheader.hclass;
+ readin(modptr->segmaxsize, sizeof modptr->segmaxsize);
+ readin(modptr->segsizedesc, sizeof modptr->segsizedesc);
+ cptr = modptr->segsize;
+ for (seg = 0; seg < NSEG; ++seg)
+ {
+ if ((count = segsizecount(seg, modptr)) != 0)
+ {
+ if (cptr == modptr->segsize)
+ ourmalloc(count - 1); /* 1st byte reserved in struct */
+ else
+ ourmalloc(count);
+ readin(cptr, count);
+ cptr += count;
+ }
+ }
+ if (modfirst == NUL_PTR)
+ modfirst = modptr;
+ else
+ modlast->modnext = modptr;
+ modlast = modptr;
+}
+
+PRIVATE bool_pt redsym(symptr, value)
+register struct symstruct *symptr;
+offset_t value;
+{
+ register struct redlist *rlptr;
+ char class;
+
+ if (symptr->modptr->class != (class = modlast->class))
+ for (rlptr = redfirst;; rlptr = rlptr->rlnext)
+ {
+ if (rlptr == NUL_PTR)
+ {
+ rlptr = (struct redlist *)
+ ourmalloc(sizeof(struct redlist));
+ rlptr->rlnext = NUL_PTR;
+ rlptr->rlsymptr = symptr;
+ if (symptr->modptr->class < class)
+ /* prefer lower class - put other on redlist */
+ {
+ rlptr->rlmodptr = modlast;
+ rlptr->rlvalue = value;
+ }
+ else
+ {
+ rlptr->rlmodptr = symptr->modptr;
+ symptr->modptr = modlast;
+ rlptr->rlvalue = symptr->value;
+ symptr->value = value;
+ }
+ if (redfirst == NUL_PTR)
+ redfirst = rlptr;
+ else
+ redlast->rlnext = rlptr;
+ redlast = rlptr;
+ return FALSE;
+ }
+ if (symptr == rlptr->rlsymptr && class == rlptr->rlmodptr->class)
+ break;
+ }
+ return TRUE;
+}
+
+PRIVATE unsigned checksum(string, length)
+char *string;
+unsigned length;
+{
+ unsigned char sum; /* this is a 1-byte checksum */
+
+ for (sum = 0; length-- != 0;)
+ sum += *string++ & 0xFF;
+ return sum;
+}
+
+PUBLIC offset_t readconvsize(countindex)
+unsigned countindex;
+{
+ return readsize(convertsize[countindex]);
+}
+
+PUBLIC offset_t readsize(count)
+unsigned count;
+{
+ char buf[MAX_OFFSET_SIZE];
+
+ if (count == 0)
+ return 0;
+ readin(buf, count);
+ return cntooffset(buf, count);
+}
+
+PRIVATE unsigned segbits(seg, sizedesc)
+unsigned seg;
+char *sizedesc;
+{
+ return 3 & ((unsigned) sizedesc[((NSEG - 1) - seg) / 4] >> (2 * (seg % 4)));
+ /* unsigned to give logical shift */
+}
+
+PUBLIC unsigned segsizecount(seg, modptr)
+unsigned seg;
+struct modstruct *modptr;
+{
+ return convertsize[segbits(seg, modptr->segsizedesc)];
+}
diff --git a/ld/table.c b/ld/table.c
new file mode 100644
index 0000000..cbe4217
--- /dev/null
+++ b/ld/table.c
@@ -0,0 +1,206 @@
+/* table.c - table-handler module for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "const.h"
+#include "align.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void *malloc P((unsigned size));
+char * strcpy P((char* dest, char* src));
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */
+#define HASHTABSIZE 256
+
+PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* hash table */
+PRIVATE char *tableptr; /* next free spot in catchall table */
+PRIVATE char *tableend; /* ptr to spot after last in table */
+
+FORWARD struct symstruct **gethashptr P((char *name));
+
+/* initialise symbol table */
+
+PUBLIC void syminit()
+{
+ unsigned i;
+
+ for (i = sizeof(int) <= 2 ? 0xE000 : (unsigned) 0x38000;
+ i != 0; i -= 512)
+ if ((tableptr = malloc(i)) != NUL_PTR)
+ break;
+ if (tableptr == NUL_PTR)
+ outofmemory();
+ tableend = tableptr + i;
+ for (i = 0; i < HASHTABSIZE; i++)
+ hashtab[i] = NUL_PTR;
+}
+
+/* add named symbol to end of table - initialise only name and next fields */
+/* caller must not duplicate names of externals for findsym() to work */
+
+PUBLIC struct symstruct *addsym(name)
+char *name;
+{
+ struct symstruct **hashptr;
+ struct symstruct *oldsymptr = 0;
+ struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NUL_PTR)
+ {
+ oldsymptr = symptr;
+ symptr = symptr->next;
+ }
+ align(tableptr);
+ symptr = (struct symstruct *) tableptr;
+ if ((tableptr = symptr->name + (strlen(name) + 1)) > tableend)
+ outofmemory();
+ symptr->modptr = NUL_PTR;
+ symptr->next = NUL_PTR;
+ if (name != symptr->name)
+ strcpy(symptr->name, name); /* should't happen */
+ if (*hashptr == NUL_PTR)
+ *hashptr = symptr;
+ else
+ oldsymptr->next = symptr;
+ return symptr;
+}
+
+/* lookup named symbol */
+
+PUBLIC struct symstruct *findsym(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NUL_PTR && (!(symptr->flags & (E_MASK | I_MASK)) ||
+ strcmp(symptr->name, name) != 0))
+ symptr = symptr->next;
+ return symptr;
+}
+
+/* convert name to a hash table ptr */
+
+PRIVATE struct symstruct **gethashptr(name)
+register char *name;
+{
+ register unsigned hashval;
+
+ hashval = 0;
+ while (*name)
+ hashval = hashval * 2 + *name++;
+ return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1));
+
+/*
+
+#asm
+
+GOLDEN EQU 157
+HASHTABSIZE EQU 256
+
+ CLRB can build value here since HASHTABSIZE <= 256
+ LDA ,X
+ BEQ HASHVAL.EXIT
+HASHVAL.LOOP
+ ADDB ,X+
+ LSLB
+ LDA ,X
+ BNE HASHVAL.LOOP
+ RORB
+ LDA #GOLDEN
+ MUL
+HASHVAL.EXIT
+HASHVAL.EXIT
+ LDX #_hashtab
+ ABX discard A - same as taking mod HASHTABSIZE
+ ABX
+#endasm
+
+*/
+
+}
+
+/* move symbol descriptor entries to top of table (no error checking) */
+
+PUBLIC char *moveup(nbytes)
+unsigned nbytes;
+{
+ register char *source;
+ register char *target;
+
+ source = tableptr;
+ target = tableend;
+ while (nbytes--)
+ *--target = *--source;
+ tableptr = source;
+ return tableend = target;
+}
+
+/* our version of malloc */
+
+PUBLIC char *ourmalloc(nbytes)
+unsigned nbytes;
+{
+ char *allocptr;
+
+ align(tableptr);
+ allocptr = tableptr;
+ if ((tableptr += nbytes) > tableend)
+ outofmemory();
+ return allocptr;
+}
+
+/* our version of free (release from bottom of table) */
+
+PUBLIC void ourfree(cptr)
+char *cptr;
+{
+ tableptr = cptr;
+}
+
+/* read string from file into table at offset suitable for next symbol */
+
+PUBLIC char *readstring()
+{
+ int c;
+ char *s;
+ char *start;
+
+ align(tableptr);
+ start = s = ((struct symstruct *) tableptr)->name;
+ while (TRUE)
+ {
+ if (s >= tableend)
+ outofmemory();
+ if ((c = readchar()) < 0)
+ prematureeof();
+ if ((*s++ = c) == 0)
+ return start;
+ }
+ /* NOTREACHED */
+}
+
+/* release from top of table */
+
+PUBLIC void release(cptr)
+char *cptr;
+{
+ tableend = cptr;
+}
+
+/* allocate space for string */
+
+PUBLIC char *stralloc(s)
+char *s;
+{
+ return strcpy(ourmalloc((unsigned) strlen(s) + 1), s);
+}
diff --git a/ld/type.h b/ld/type.h
new file mode 100644
index 0000000..142ea53
--- /dev/null
+++ b/ld/type.h
@@ -0,0 +1,163 @@
+/* type.h - types for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+typedef int bool_pt;
+typedef unsigned char bool_t;
+
+typedef unsigned short u2_t;
+typedef unsigned u2_pt;
+typedef unsigned long u4_t;
+typedef unsigned long u4_pt;
+
+#ifdef HOST_8BIT
+typedef char fastin_t;
+#else
+typedef int fastin_t;
+#endif
+typedef int fastin_pt;
+
+#ifdef OBJ_H /* obj.h is included */
+
+typedef unsigned flags_t; /* unsigned makes shifts logical */
+
+#ifdef LONG_OFFSETS
+typedef unsigned long offset_t;
+#else
+typedef unsigned offset_t;
+#endif
+
+struct entrylist /* list of entry symbols */
+{
+ struct entrylist *elnext; /* next on list */
+ struct symstruct *elsymptr; /* entry on list */
+};
+
+struct modstruct /* module table entry format */
+{
+ char *filename; /* file containing this module */
+ char *archentry; /* name of component file for archives */
+ char *modname; /* name of module */
+ unsigned long textoffset; /* offset to module text in file */
+ char class; /* class of module */
+ char loadflag; /* set if module to be loaded */
+ char segmaxsize[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for seg max size */
+ /* 00 = 1, 01 = 2, 10 = 3, 11 = 4 */
+ char segsizedesc[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for #bytes for size */
+ /* 00 = 0, 01 = 1, 10 = 2, 11 = 4 */
+ struct symstruct **symparray; /* ^array of ptrs to referenced syms */
+ struct modstruct *modnext; /* next module in order of initial reading */
+ char segsize[1]; /* up to 64 size bytes begin here */
+}; /* careful with sizeof( struct modstruct )!! */
+
+struct redlist /* list of redefined (exported) symbols */
+{
+ struct redlist *rlnext; /* next on list */
+ struct symstruct *rlsymptr; /* to symbol with same name, flags */
+ struct modstruct *rlmodptr; /* module for this redefinition */
+ offset_t rlvalue; /* value for this redefinition */
+};
+
+struct symstruct /* symbol table entry format */
+{
+ struct modstruct *modptr; /* module where symbol is defined */
+ offset_t value; /* value of symbol */
+ flags_t flags; /* see below (unsigned makes shifts logical) */
+ struct symstruct *next; /* next symbol with same hash value */
+ char name[1]; /* name is any string beginning here */
+}; /* don't use sizeof( struct symstruct )!! */
+
+#endif /* obj.h is included */
+
+/* prototypes */
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+/* dump.c */
+void dumpmods P((void));
+void dumpsyms P((void));
+
+/* io.c */
+void ioinit P((char *progname));
+void closein P((void));
+void closeout P((void));
+void errtrace P((char *name, int level));
+void executable P((void));
+void flusherr P((void));
+void openin P((char *filename));
+void openout P((char *filename));
+void putstr P((char *message));
+#ifdef OBJ_H
+void put08x P((offset_t num));
+void put08lx P((offset_t num));
+#endif
+void putbstr P((unsigned width, char *str));
+void putbyte P((int ch));
+int readchar P((void));
+void readin P((char *buf, unsigned count));
+bool_pt readineofok P((char *buf, unsigned count));
+void seekin P((unsigned long offset));
+void seekout P((unsigned long offset));
+void seektrel P((unsigned long offset));
+void writechar P((int c));
+void writedrel P((char *buf, unsigned count));
+void writeout P((char *buf, unsigned count));
+void writetrel P((char *buf, unsigned count));
+void fatalerror P((char *message));
+void inputerror P((char *message));
+void input1error P((char *message));
+void outofmemory P((void));
+void prematureeof P((void));
+void redefined P((char *name, char *message, char *archentry,
+ char *deffilename, char *defarchentry));
+void reserved P((char *name));
+#ifdef OBJ_H
+void size_error P((int seg, offset_t count, offset_t size));
+#endif
+void undefined P((char *name));
+void usage P((void));
+void use_error P((char *message));
+
+/* ld.c */
+int main P((int argc, char **argv));
+
+/* readobj.c */
+void objinit P((void));
+void readsyms P((char *filename, bool_pt trace));
+#ifdef OBJ_H
+void entrysym P((struct symstruct *symptr));
+offset_t readconvsize P((unsigned countindex));
+offset_t readsize P((unsigned count));
+unsigned segsizecount P((unsigned seg, struct modstruct *modptr));
+#endif
+
+/* table.c */
+void syminit P((void));
+struct symstruct *addsym P((char *name));
+struct symstruct *findsym P((char *name));
+char *moveup P((unsigned nbytes));
+char *ourmalloc P((unsigned nbytes));
+void ourfree P((char *cptr));
+char *readstring P((void));
+void release P((char *cptr));
+char *stralloc P((char *s));
+
+/* typeconvert.c */
+u2_pt c2u2 P((char *buf));
+u4_t c4u4 P((char *buf));
+u2_pt cnu2 P((char *buf, unsigned count));
+u4_t cnu4 P((char *buf, unsigned count));
+void u2c2 P((char *buf, u2_pt offset));
+void u4c4 P((char *buf, u4_t offset));
+void u2cn P((char *buf, u2_pt offset, unsigned count));
+void u4cn P((char *buf, u4_t offset, unsigned count));
+bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian));
+
+/* writebin.c */
+void writebin P((char *outfilename, bool_pt argsepid, bool_pt argbits32,
+ bool_pt argstripflag, bool_pt arguzp));
+void linksyms P((bool_pt argreloc_output));
diff --git a/ld/typeconv.c b/ld/typeconv.c
new file mode 100644
index 0000000..82dafdd
--- /dev/null
+++ b/ld/typeconv.c
@@ -0,0 +1,536 @@
+/* typeconv.c - convert between char arrays and unsigneds */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/*
+ c2u2(): 2 byte array to 2 byte unsigned
+ c4u4(): 4 byte array to 4 byte unsigned
+ cnu2(): n byte array to 2 byte unsigned
+ cnu4(): n byte array to 4 byte unsigned
+ u2c2(): 2 byte unsigned to 2 byte array
+ u2cn(): 2 byte unsigned to n byte array
+ u4c4(): 4 byte unsigned to 4 byte array
+ u4cn(): 4 byte unsigned to n byte array
+ typeconv_init: (re)initialise for given byte order.
+ Default is no swapping, but the initialisation should be done
+ anyway to provide some validity checks (returns FALSE if error).
+
+ Not provided:
+ c2u4(), c4u2(), u2c4(), u4c2().
+ Each of these is best done by truncating or extending a return value
+ or argument to the appropiate fixed-count function.
+ c4u2() has too many cases to do in-line conveniently, and the others
+ are hardly more efficient when done in-line.
+
+ 4 byte orderings for both char arrays and unsigneds are supported:
+ 0123 - little-endian
+ 3210 - big-endian
+ 2301 - little-endian with long words big-endian (pdp11)
+ 1032 - big-endian with long words little_endian (who knows?)
+
+ The unsigned's byte order is that of the machine on which these
+ routines are running.
+ It is determined at run time initialisation since the compiler/
+ preprocessor is too dumb to tell us at compile time.
+*/
+
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+
+FORWARD u2_pt c2u2_00 P((char *buf));
+FORWARD u4_pt c4u4_00 P((char *buf));
+FORWARD u2_pt c2u2_ss P((char *buf));
+FORWARD u4_pt c4u4_ss P((char *buf));
+FORWARD u4_pt c4u4_s0 P((char *buf));
+FORWARD u4_pt c4u4_0s P((char *buf));
+FORWARD void u2c2_00 P((char *buf, u2_pt offset));
+FORWARD void u4c4_00 P((char *buf, u4_t offset));
+FORWARD void u2c2_ss P((char *buf, u2_pt offset));
+FORWARD void u4c4_ss P((char *buf, u4_t offset));
+FORWARD void u4c4_s0 P((char *buf, u4_t offset));
+FORWARD void u4c4_0s P((char *buf, u4_t offset));
+
+PRIVATE u2_pt (*pc2u2) P((char *buf)) = c2u2_00;
+PRIVATE u4_pt (*pc4u4) P((char *buf)) = c4u4_00;
+PRIVATE void (*pu2c2) P((char *buf, u2_pt offset)) = u2c2_00;
+PRIVATE void (*pu4c4) P((char *buf, u4_t offset)) = u4c4_00;
+
+/* === char arrays to unsigneds === */
+
+/* no bytes swapped, longwinded to avoid alignment problems */
+
+PRIVATE u2_pt c2u2_00(buf)
+register char *buf;
+{
+ u2_t offset;
+
+ ((char *) &offset)[0] = buf[0];
+ ((char *) &offset)[1] = buf[1];
+ return offset;
+}
+
+PRIVATE u4_pt c4u4_00(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[0];
+ ((char *) &offset)[1] = buf[1];
+ ((char *) &offset)[2] = buf[2];
+ ((char *) &offset)[3] = buf[3];
+ return offset;
+}
+
+/* straight swapping for little-endian to big-endian and vice versa */
+
+PRIVATE u2_pt c2u2_ss(buf)
+register char *buf;
+{
+ u2_t offset;
+
+ ((char *) &offset)[0] = buf[1];
+ ((char *) &offset)[1] = buf[0];
+ return offset;
+}
+
+PRIVATE u4_pt c4u4_ss(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[3];
+ ((char *) &offset)[1] = buf[2];
+ ((char *) &offset)[2] = buf[1];
+ ((char *) &offset)[3] = buf[0];
+ return offset;
+}
+
+/* wierd swapping for different-endian u2's, same-endian u4's */
+
+PRIVATE u4_pt c4u4_s0(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[1];
+ ((char *) &offset)[1] = buf[0];
+ ((char *) &offset)[2] = buf[3];
+ ((char *) &offset)[3] = buf[2];
+ return offset;
+}
+
+/* very wierd swapping for same-endian u2's, different-endian u4's */
+
+PRIVATE u4_pt c4u4_0s(buf)
+register char *buf;
+{
+ u4_t offset;
+
+ ((char *) &offset)[0] = buf[2];
+ ((char *) &offset)[1] = buf[3];
+ ((char *) &offset)[2] = buf[0];
+ ((char *) &offset)[3] = buf[1];
+ return offset;
+}
+
+/* === entry points === */
+
+PUBLIC u2_pt c2u2(buf)
+char *buf;
+{
+ return (*pc2u2) (buf);
+}
+
+PUBLIC u4_t c4u4(buf)
+char *buf;
+{
+ return (*pc4u4) (buf);
+}
+
+PUBLIC u2_pt cnu2(buf, count)
+char *buf;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ return buf[0] & 0xFF;
+ case 2:
+ return (*pc2u2) (buf);
+ case 4:
+ return (u2_pt) (*pc4u4) (buf);
+ default:
+ return 0;
+ }
+}
+
+PUBLIC u4_t cnu4(buf, count)
+char *buf;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ return buf[0] & 0xFF;
+ case 2:
+ return (*pc2u2) (buf);
+ case 4:
+ return (*pc4u4) (buf);
+ default:
+ return 0;
+ }
+}
+
+/* === unsigneds to char arrays === */
+
+/* no bytes swapped, longwinded to avoid alignment problems */
+
+PRIVATE void u2c2_00(buf, offset)
+register char *buf;
+u2_pt offset;
+{
+
+ buf[0] = ((char *) &offset)[0];
+ buf[1] = ((char *) &offset)[1];
+}
+
+PRIVATE void u4c4_00(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[0];
+ buf[1] = ((char *) &offset)[1];
+ buf[2] = ((char *) &offset)[2];
+ buf[3] = ((char *) &offset)[3];
+}
+
+/* straight swapping for little-endian to big-endian and vice versa */
+
+PRIVATE void u2c2_ss(buf, offset)
+register char *buf;
+u2_pt offset;
+{
+ u2_t offset2;
+
+ offset2 = offset;
+ buf[0] = ((char *) &offset2)[1];
+ buf[1] = ((char *) &offset2)[0];
+}
+
+PRIVATE void u4c4_ss(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[3];
+ buf[1] = ((char *) &offset)[2];
+ buf[2] = ((char *) &offset)[1];
+ buf[3] = ((char *) &offset)[0];
+}
+
+/* wierd swapping for different-endian u2's, same-endian u4's */
+
+PRIVATE void u4c4_s0(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[1];
+ buf[1] = ((char *) &offset)[0];
+ buf[2] = ((char *) &offset)[3];
+ buf[3] = ((char *) &offset)[2];
+}
+
+/* very wierd swapping for same-endian u2's, different-endian u4's */
+
+PRIVATE void u4c4_0s(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ buf[0] = ((char *) &offset)[2];
+ buf[1] = ((char *) &offset)[3];
+ buf[2] = ((char *) &offset)[0];
+ buf[3] = ((char *) &offset)[1];
+}
+
+/* === entry points === */
+
+PUBLIC void u2c2(buf, offset)
+register char *buf;
+u2_pt offset;
+{
+ (*pu2c2) (buf, offset);
+}
+
+PUBLIC void u4c4(buf, offset)
+register char *buf;
+u4_t offset;
+{
+ (*pu4c4) (buf, offset);
+}
+
+PUBLIC void u2cn(buf, offset, count)
+register char *buf;
+u2_pt offset;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ buf[0] = (char) offset;
+ return;
+ case 2:
+ (*pu2c2) (buf, offset);
+ return;
+ case 4:
+ (*pu4c4) (buf, (u4_t) offset);
+ return;
+ }
+}
+
+PUBLIC void u4cn(buf, offset, count)
+register char *buf;
+u4_t offset;
+unsigned count;
+{
+ switch (count)
+ {
+ case 1:
+ buf[0] = (char) offset;
+ return;
+ case 2:
+ (*pu2c2) (buf, (u2_pt) (u2_t) offset);
+ return;
+ case 4:
+ (*pu4c4) (buf, offset);
+ return;
+ }
+}
+
+/* initialise type conversion, return FALSE if it cannot be handled */
+
+PUBLIC bool_pt typeconv_init(big_endian, long_big_endian)
+bool_pt big_endian;
+bool_pt long_big_endian;
+{
+ u2_pt conv2;
+ u4_pt conv4;
+ char *conv2ptr;
+ char *conv4ptr;
+
+ if (sizeof(u2_t) != 2 || sizeof(u4_t) != 4)
+ /* dumb preprocessor's don't accept sizeof in #if expressions */
+ return FALSE;
+
+ if (big_endian)
+ {
+ conv2ptr = (conv4ptr = "\1\2\3\4") + 2;
+ if (!long_big_endian)
+ conv4ptr = "\3\4\1\2";
+ }
+ else
+ {
+ conv2ptr = conv4ptr = "\4\3\2\1";
+ if (long_big_endian)
+ conv4ptr = "\2\1\4\3";
+ }
+ conv2 = c2u2_00(conv2ptr);
+ conv4 = c4u4_00(conv4ptr);
+ if (conv2 == 0x0304)
+ {
+ pc2u2 = c2u2_00;
+ pc4u4 = c4u4_00;
+ pu2c2 = u2c2_00;
+ pu4c4 = u4c4_00;
+ if (conv4 == 0x03040102L)
+ {
+ pc4u4 = c4u4_0s;
+ pu4c4 = u4c4_0s;
+ }
+ else if (conv4 != 0x01020304L)
+ return FALSE;
+ }
+ else if (conv2 == 0x0403)
+ {
+ pc2u2 = c2u2_ss;
+ pc4u4 = c4u4_ss;
+ pu2c2 = u2c2_ss;
+ pu4c4 = u4c4_ss;
+ if (conv4 == 0x02010403L)
+ {
+ pc4u4 = c4u4_s0;
+ pu4c4 = u4c4_s0;
+ }
+ else if (conv4 != 0x04030201L)
+ return FALSE;
+ }
+ else
+ return FALSE;
+ return TRUE;
+}
+
+#ifdef DEBUG_TYPECONV
+
+main()
+{
+ char *source;
+ char target[4];
+ u2_t u2;
+ u2_t u2a;
+ u4_t u4;
+ u4_t u4a;
+
+ printf("%u\n", typeconv_init(FALSE, FALSE));
+ printf("%u\n", typeconv_init(FALSE, TRUE));
+ printf("%u\n", typeconv_init(TRUE, FALSE));
+ printf("%u\n", typeconv_init(TRUE, TRUE));
+
+ typeconv_init(FALSE, FALSE);
+ source = "\4\3\2\1";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source, target, 2))
+ printf("oops9\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source, target, 2))
+ printf("oops10\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\4\3\0\0", 4))
+ printf("oops11\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops12\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+
+ typeconv_init(FALSE, TRUE);
+ source = "\2\1\4\3";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source + 2, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops13\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source + 2, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops14\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\0\0\4\3", 4))
+ printf("oops15\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops16\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+
+ typeconv_init(TRUE, FALSE);
+ source = "\3\4\1\2";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source, target, 2))
+ printf("oops5\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source, target, 2))
+ printf("oops6\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\3\4\0\0", 4))
+ printf("oops7\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops8\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+
+ typeconv_init(TRUE, TRUE);
+ source = "\1\2\3\4";
+
+ target[0] = 0;
+ target[1] = 0;
+ u2 = cnu2(source + 2, 2);
+ u2cn(target, u2, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops1\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ u4a = cnu4(source + 2, 2);
+ u4cn(target, u4a, 2);
+ if (strncmp(source + 2, target, 2))
+ printf("oops2\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u2a = cnu2(source, 4);
+ u2cn(target, u2a, 4);
+ if (strncmp(target, "\0\0\3\4", 4))
+ printf("oops3\n");
+
+ target[0] = 0;
+ target[1] = 0;
+ target[2] = 0;
+ target[3] = 0;
+ u4 = cnu4(source, 4);
+ u4cn(target, u4, 4);
+ if (strncmp(source, target, 4))
+ printf("oops4\n");
+
+ printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a);
+}
+
+#endif /* DEBUG_TYPECONV */
diff --git a/ld/writebin.c b/ld/writebin.c
new file mode 100644
index 0000000..3e7602d
--- /dev/null
+++ b/ld/writebin.c
@@ -0,0 +1,997 @@
+extern long text_base_address;
+#define btextoffset text_base_address
+static long bdataoffset;
+#define page_size() 4096
+
+/* writebin.c - write binary file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#ifdef A_OUT_H
+# include A_OUT_H
+#else
+# ifdef BSD_A_OUT
+# ifdef STANDARD_GNU_A_OUT
+# include <a.out.h>
+# define RELOC_INFO_SIZE 8 /* unportable bitfields - bcc doesn't pack */
+# else
+# include "bsd-a.out.h"
+# define RELOC_INFO_SIZE (sizeof (struct relocation_info))
+# endif
+# define C_EXT N_EXT
+# define C_STAT 0
+# define n_was_name n_un.n_name
+# define n_was_numaux n_other
+# define n_was_other n_numaux
+# define n_was_sclass n_type
+# define n_was_strx n_un.n_strx
+# define n_was_type n_desc
+# else /* not BSD_A_OUT */
+# ifdef MSDOS
+# include "a_out.h"
+# else
+# include "a.out.h" /* maybe local copy of <a.out.h> for X-link */
+# endif
+# define n_was_name n_name
+# define n_was_numaux n_numaux
+# define n_was_other n_other
+# define n_was_sclass n_sclass
+# define n_was_strx n_value
+# define n_was_type n_type
+# endif /* BSD_A_OUT */
+#endif
+
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#undef EXTERN
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void *memset P((void *s, int c, unsigned n));
+#else
+#include <string.h>
+#endif
+
+#ifdef EDOS
+# define FILEHEADERLENGTH 0
+#endif
+#ifdef MINIX
+# ifdef BSD_A_OUT
+# ifdef STANDARD_GNU_A_OUT
+# define FILEHEADERLENGTH 32
+# else
+# define FILEHEADERLENGTH (doscomfile?0:48)
+# endif
+# else
+# define FILEHEADERLENGTH (doscomfile?0:A_MINHDR)
+ /* part of header not counted in offsets */
+# endif
+#endif
+#define DPSEG 2
+
+#define CM_MASK 0xC0
+#define MODIFY_MASK 0x3F
+#define S_MASK 0x04
+#define OF_MASK 0x03
+
+#define CM_SPECIAL 0
+#define CM_ABSOLUTE 0x40
+#define CM_OFFSET_RELOC 0x80
+#define CM_SYMBOL_RELOC 0xC0
+
+#define CM_EOT 0
+#define CM_BYTE_SIZE 1
+#define CM_WORD_SIZE 2
+#define CM_LONG_SIZE 3
+#define CM_1_SKIP 17
+#define CM_2_SKIP 18
+#define CM_4_SKIP 19
+#define CM_0_SEG 32
+
+#define ABS_TEXT_MAX 64
+
+#define offsetof(struc, mem) ((int) &((struc *) 0)->mem)
+#define memsizeof(struc, mem) sizeof(((struc *) 0)->mem)
+
+PRIVATE bool_t bits32; /* nonzero for 32-bit executable */
+PRIVATE offset_t combase[NSEG]; /* bases of common parts of segments */
+PRIVATE offset_t comsz[NSEG]; /* sizes of common parts of segments */
+PRIVATE fastin_t curseg; /* current segment, 0 to $F */
+PRIVATE offset_t edataoffset; /* end of data */
+PRIVATE offset_t endoffset; /* end of bss */
+PRIVATE offset_t etextoffset; /* end of text */
+PRIVATE offset_t etextpadoff; /* end of padded text */
+#ifdef BSD_A_OUT
+PRIVATE unsigned ndreloc; /* number of data relocations */
+#endif
+PRIVATE unsigned nsym; /* number of symbols written */
+#ifdef BSD_A_OUT
+PRIVATE unsigned ntreloc; /* number of text relocations */
+PRIVATE bool_t reloc_output; /* nonzero to leave reloc info in output */
+#endif
+PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */
+PRIVATE offset_t segadj[NSEG]; /* adjusts (file offset - seg offset) */
+ /* depends on zero init */
+PRIVATE offset_t segbase[NSEG]; /* bases of data parts of segments */
+PRIVATE char segboundary[9] = "__seg0DH";
+ /* name of seg boundary __seg0DL to __segfCH */
+PRIVATE offset_t segpos[NSEG]; /* segment positions for current module */
+PRIVATE offset_t segsz[NSEG]; /* sizes of data parts of segments */
+ /* depends on zero init */
+PRIVATE bool_t sepid; /* nonzero for separate I & D */
+PRIVATE bool_t stripflag; /* nonzero to strip symbols */
+PRIVATE offset_t spos; /* position in current seg */
+PRIVATE bool_t uzp; /* nonzero for unmapped zero page */
+
+#ifdef EDOS
+FORWARD unsigned binheaderlength P((char *commandname));
+FORWARD char *idconvert P((struct entrylist *elptr, char *commandname));
+#endif
+FORWARD void linkmod P((struct modstruct *modptr));
+FORWARD void linkrefs P((struct modstruct *modptr));
+FORWARD void padmod P((struct modstruct *modptr));
+FORWARD void setsym P((char *name, offset_t value));
+FORWARD void symres P((char *name));
+FORWARD void setseg P((fastin_pt newseg));
+FORWARD void skip P((unsigned countsize));
+#ifdef EDOS
+FORWARD void writeheader P((char *commandname));
+#else
+FORWARD void writeheader P((void));
+#endif
+FORWARD void writenulls P((offset_t count));
+
+extern int doscomfile;
+
+/* link all symbols connected to entry symbols */
+
+PUBLIC void linksyms(argreloc_output)
+bool_pt argreloc_output;
+{
+ char needlink;
+ struct entrylist *elptr;
+ struct modstruct *modptr;
+ struct symstruct *symptr;
+
+#ifdef BSD_A_OUT
+ reloc_output = argreloc_output;
+ if (argreloc_output)
+ {
+ if (modfirst->modnext != NUL_PTR)
+ fatalerror("relocatable output only works for one input file");
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ modptr->loadflag = TRUE;
+ return;
+ }
+#endif
+ if ((symptr = findsym("_main")) != NUL_PTR)
+ entrysym(symptr);
+ do
+ {
+ if ((elptr = entryfirst) == NUL_PTR)
+ fatalerror("no start symbol");
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ modptr->loadflag = FALSE;
+ for (; elptr != NUL_PTR; elptr = elptr->elnext)
+ linkrefs(elptr->elsymptr->modptr);
+ if ((symptr = findsym("start")) != NUL_PTR)
+ linkrefs(symptr->modptr);
+ needlink = FALSE;
+ {
+ struct redlist *prlptr = 0;
+ struct redlist *rlptr;
+
+ for (rlptr = redfirst; rlptr != NUL_PTR;
+ rlptr = (prlptr = rlptr)->rlnext)
+ if (rlptr->rlmodptr->loadflag &&
+ rlptr->rlmodptr->class > rlptr->rlsymptr->modptr->class)
+ {
+ rlptr->rlsymptr->modptr = rlptr->rlmodptr;
+ rlptr->rlsymptr->value = rlptr->rlvalue;
+ if (rlptr == redfirst)
+ redfirst = rlptr->rlnext;
+ else
+ prlptr->rlnext = rlptr->rlnext;
+ needlink = TRUE;
+ }
+ }
+ }
+ while (needlink);
+}
+
+/* write binary file */
+
+PUBLIC void writebin(outfilename, argsepid, argbits32, argstripflag, arguzp)
+char *outfilename;
+bool_pt argsepid;
+bool_pt argbits32;
+bool_pt argstripflag;
+bool_pt arguzp;
+{
+ char buf4[4];
+#ifdef EDOS
+ char *commandname;
+#endif
+ char *cptr;
+ struct nlist extsym;
+ flags_t flags;
+ struct modstruct *modptr;
+ fastin_t seg;
+ unsigned sizecount;
+ offset_t tempoffset;
+
+ sepid = argsepid;
+ bits32 = argbits32;
+ stripflag = argstripflag;
+#ifdef BSD_A_OUT
+ uzp = arguzp && !reloc_output;
+#else
+ uzp = arguzp;
+#endif
+ if (uzp)
+ {
+ if (btextoffset == 0)
+ btextoffset = page_size();
+ if (bdataoffset == 0 && sepid)
+ bdataoffset = page_size();
+ }
+#ifdef EDOS
+ commandname = stralloc(outfilename);
+ if ((cptr = strchr(commandname, ':')) != NUL_PTR)
+ commandname = cptr + 1;
+ if ((cptr = strrchr(commandname, '.')) != NUL_PTR)
+ *cptr = 0;
+#endif
+
+ /* reserve special symbols use curseg to pass parameter to symres() */
+ for (curseg = 0; curseg < NSEG; ++curseg)
+ {
+ segboundary[5] = hexdigit[curseg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ symres(segboundary); /* __segXDH */
+ segboundary[7] = 'L';
+ symres(segboundary); /* __segXDL */
+ segboundary[6] = 'C';
+ symres(segboundary); /* __segXCL */
+ segboundary[7] = 'H';
+ symres(segboundary); /* __segXCH */
+ }
+#ifdef EDOS
+ curseg = 0; /* data seg, s.b. variable */
+#else
+ curseg = 3;
+#endif
+ symres("__edata");
+ symres("__end");
+ curseg = 0; /* text seg, s.b. variable */
+ symres("__etext");
+ symres("__segoff");
+
+ /* calculate segment and common sizes (sum over loaded modules) */
+ /* use zero init of segsz[] */
+ /* also relocate symbols relative to starts of their segments */
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (!(symptr->flags & (I_MASK | SA_MASK)))
+ {
+ /* relocate by offset of module in segment later */
+ /* relocate by offset of segment in memory special */
+ /* symbols get relocated improperly */
+ symptr->value += segsz[symptr->flags & SEGM_MASK];
+ }
+ else if (symptr->value == 0)
+ {
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ undefined(symptr->name);
+ }
+ else
+ {
+#ifdef BSD_A_OUT
+#if 0
+ if (!reloc_output)
+#else
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+#endif
+ {
+ tempoffset = roundup(symptr->value, 4, offset_t);
+ /* temp kludge quad alignment for 386 */
+ symptr->value = comsz[seg = symptr->flags & SEGM_MASK];
+ comsz[seg] += tempoffset;
+ }
+ if (!(symptr->flags & SA_MASK))
+ symptr->flags |= C_MASK;
+ }
+ }
+ for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ segsz[seg] += cntooffset(cptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+#ifndef EDOS
+
+ /* adjust sizes to even to get quad boundaries */
+ /* this should be specifiable dynamically */
+ segsz[seg] = roundup(segsz[seg], 4, offset_t);
+ comsz[seg] = roundup(comsz[seg], 4, offset_t);
+#endif
+ cptr += sizecount;
+ }
+ }
+
+ /* calculate seg positions now their sizes are known */
+ /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */
+ /* assume seg 0 is text and rest are data */
+#ifdef EDOS
+ if (btextoffset == 0)
+ btextoffset = binheaderlength(commandname);
+#endif
+ segpos[0] = segbase[0] = spos = btextoffset;
+ combase[0] = segbase[0] + segsz[0];
+ segadj[1] = segadj[0] = -btextoffset;
+ etextpadoff = etextoffset = combase[0] + comsz[0];
+ if (sepid)
+ {
+ etextpadoff = roundup(etextoffset, 0x10, offset_t);
+ segadj[1] += etextpadoff - bdataoffset;
+ }
+ else if (bdataoffset == 0)
+ bdataoffset = etextpadoff;
+ segpos[1] = segbase[1] = edataoffset = bdataoffset;
+ combase[1] = segbase[1] + segsz[1];
+ for (seg = 2; seg < NSEG; ++seg)
+ {
+ segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1];
+ if (seg == DPSEG)
+ {
+ /* temporarily have fixed DP seg */
+ /* adjust if nec so it only spans 1 page */
+ tempoffset = segsz[seg] + comsz[seg];
+ if (tempoffset > 0x100)
+ fatalerror("direct page segment too large");
+ if ((((segbase[seg] + tempoffset) ^ segbase[seg])
+ & ~(offset_t) 0xFF) != 0)
+ segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF)
+ & ~(offset_t) 0xFF;
+ }
+ combase[seg] = segbase[seg] + segsz[seg];
+ segadj[seg] = segadj[seg - 1];
+ }
+
+ /* relocate symbols by offsets of segments in memory */
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (symptr->flags & (C_MASK | SA_MASK))
+ {
+#ifdef BSD_A_OUT
+#if 0
+ if (!reloc_output)
+#else
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+#endif
+ symptr->value += combase[symptr->flags & SEGM_MASK];
+ }
+ else
+#ifdef BSD_A_OUT
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+ symptr->value += segbase[symptr->flags & SEGM_MASK];
+ }
+ }
+
+ /* adjust special symbols */
+ for (seg = 0; seg < NSEG; ++seg)
+ {
+ if (segsz[seg] != 0)
+ /* only count data of nonzero length */
+ edataoffset = segbase[seg] + segsz[seg];
+ segboundary[5] = hexdigit[seg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]);
+ /* __segXDH */
+ segboundary[7] = 'L';
+ setsym(segboundary, tempoffset); /* __segXDL */
+ segboundary[6] = 'C';
+ setsym(segboundary, tempoffset = combase[seg]);
+ /* __segXCL */
+ segboundary[7] = 'H';
+ setsym(segboundary, tempoffset + comsz[seg]);
+ /* __segXCH */
+ }
+ setsym("__etext", etextoffset);
+ setsym("__edata", edataoffset);
+ setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]);
+ setsym("__segoff", (offset_t)(segadj[1]-segadj[0])/0x10);
+
+ openout(outfilename);
+#ifdef BSD_A_OUT
+ if (reloc_output)
+ seektrel(FILEHEADERLENGTH
+ + (unsigned long) (etextpadoff - btextoffset)
+ + (unsigned long) (edataoffset - bdataoffset));
+#endif
+#ifdef EDOS
+ writeheader(commandname);
+#else
+ writeheader();
+#endif
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ linkmod(modptr);
+ padmod(modptr);
+ }
+
+ /* dump symbol table */
+#ifdef MINIX
+ if (!stripflag)
+ {
+#ifdef BSD_A_OUT
+ unsigned stringoff;
+#endif
+
+ seekout(FILEHEADERLENGTH
+ + (unsigned long) (etextpadoff - btextoffset)
+ + (unsigned long) (edataoffset - bdataoffset)
+#ifdef BSD_A_OUT
+ + ((unsigned long) ndreloc + ntreloc) * RELOC_INFO_SIZE
+#endif
+ );
+ extsym.n_was_numaux = extsym.n_was_type = 0;
+#ifdef BSD_A_OUT
+ stringoff = 4;
+#endif
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr)
+ {
+#ifdef BSD_A_OUT
+ offtocn((char *) &extsym.n_was_strx,
+ (offset_t) stringoff, 4);
+#else
+ strncpy((char *) extsym.n_was_name, symptr->name,
+ sizeof extsym.n_was_name);
+#endif
+ u4cn((char *) &extsym.n_value, (u4_t) symptr->value,
+ sizeof extsym.n_value);
+ if ((flags = symptr->flags) & A_MASK)
+ extsym.n_was_sclass = N_ABS;
+ else if (flags & (E_MASK | I_MASK))
+ extsym.n_was_sclass = C_EXT;
+ else
+ extsym.n_was_sclass = C_STAT;
+ if (!(flags & I_MASK) ||
+#ifdef BSD_A_OUT
+ !reloc_output &&
+#endif
+ flags & C_MASK)
+ switch (flags & (A_MASK | SEGM_MASK))
+ {
+ case 0:
+ extsym.n_was_sclass |= N_TEXT;
+ case A_MASK:
+ break;
+ default:
+ if (flags & (C_MASK | SA_MASK))
+ extsym.n_was_sclass |= N_BSS;
+ else
+ extsym.n_was_sclass |= N_DATA;
+ break;
+ }
+ writeout((char *) &extsym, sizeof extsym);
+ ++nsym;
+#ifdef BSD_A_OUT
+ stringoff += strlen(symptr->name) + 1;
+#endif
+ }
+ }
+#ifdef BSD_A_OUT
+ offtocn((char *) &extsym.n_was_strx, (offset_t) stringoff, 4);
+ writeout((char *) &extsym.n_was_strx, 4);
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr)
+ writeout(symptr->name, strlen(symptr->name) + 1);
+ }
+#endif
+ seekout((unsigned long) offsetof(struct exec, a_syms));
+ u4cn(buf4, (u4_t) nsym * sizeof extsym,
+ memsizeof(struct exec, a_syms));
+ writeout(buf4, memsizeof(struct exec, a_syms));
+#ifdef BSD_A_OUT
+ seekout((unsigned long) offsetof(struct exec, a_trsize));
+ u4cn(buf4, (u4_t) ntreloc * RELOC_INFO_SIZE,
+ memsizeof(struct exec, a_trsize));
+ writeout(buf4, memsizeof(struct exec, a_trsize));
+ seekout((unsigned long) offsetof(struct exec, a_drsize));
+ u4cn(buf4, (u4_t) ndreloc * RELOC_INFO_SIZE,
+ memsizeof(struct exec, a_drsize));
+ writeout(buf4, memsizeof(struct exec, a_drsize));
+#endif
+ }
+#endif /* MINIX */
+ closeout();
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ executable();
+}
+
+#ifdef EDOS
+
+PRIVATE unsigned binheaderlength(commandname)
+char *commandname;
+{
+ unsigned count;
+ char *name;
+ struct entrylist *elptr;
+ struct symstruct *startptr;
+
+ count = 2 + 2 + 1; /* len len nul */
+ startptr = findsym("start");
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ {
+ name = idconvert(elptr, commandname);
+ count += strlen(name) + 1 + 2 + 1; /* nul off flg */
+ ourfree(name);
+ if (startptr != NUL_PTR)
+ count += 6; /* LBSR $xxxx and LBRA $xxxx */
+ }
+ return count;
+}
+
+/* convert name of symbol (entry) list element to a Basic identifier */
+/* new name is built in storage obtained from stralloc() */
+/* the special name _main is converted to the command name first */
+/* copy upper case and numerals, convert lower case to upper, ignore rest */
+
+PRIVATE char *idconvert(elptr, commandname)
+struct entrylist *elptr;
+char *commandname;
+{
+ char *name;
+ char *newname;
+
+ if (strcmp(name = elptr->elsymptr->name, "_main") == 0)
+ name = commandname;
+ newname = stralloc(name);
+ {
+ register char *t;
+ register char *s;
+
+ t = newname;
+ s = name;
+ do
+ {
+ if (*s >= '0' && *s <= '9' || *s >= 'A' && *s <= 'Z')
+ *t++ = *s;
+ if (*s >= 'a' && *s <= 'z')
+ *t++ = *s + ('A' - 'a');
+ }
+ while (*s++);
+ *t = 0;
+ }
+ if (*newname < 'A') /* numeral or null */
+ fatalerror("bad entry name");
+ return newname;
+}
+
+#endif /* EDOS */
+
+PRIVATE void linkmod(modptr)
+struct modstruct *modptr;
+{
+ char buf[ABS_TEXT_MAX];
+ int command;
+ unsigned char modify;
+ offset_t offset;
+ int symbolnum;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+
+ setseg(0);
+ relocsize = 2;
+ symparray = modptr->symparray;
+ openin(modptr->filename); /* does nothing if already open */
+ seekin(modptr->textoffset);
+ while (TRUE)
+ {
+ if ((command = readchar()) < 0)
+ prematureeof();
+ modify = command & MODIFY_MASK;
+ switch (command & CM_MASK)
+ {
+ case CM_SPECIAL:
+ switch (modify)
+ {
+ case CM_EOT:
+ segpos[curseg] = spos;
+ return;
+ case CM_BYTE_SIZE:
+ relocsize = 1;
+ break;
+ case CM_WORD_SIZE:
+ relocsize = 2;
+ break;
+ case CM_LONG_SIZE:
+#ifdef LONG_OFFSETS
+ relocsize = 4;
+ break;
+#else
+ fatalerror("relocation by long offsets not implemented");
+#endif
+ case CM_1_SKIP:
+ skip(1);
+ break;
+ case CM_2_SKIP:
+ skip(2);
+ break;
+ case CM_4_SKIP:
+ skip(4);
+ break;
+ default:
+ if ((modify -= CM_0_SEG) >= NSEG)
+ inputerror("bad data in");
+ setseg(modify);
+ break;
+ }
+ break;
+ case CM_ABSOLUTE:
+ if (modify == 0)
+ modify = ABS_TEXT_MAX;
+ readin(buf, (unsigned) modify);
+ writeout(buf, (unsigned) modify);
+ spos += (int) modify;
+ break;
+ case CM_OFFSET_RELOC:
+ offset = readsize(relocsize);
+ if (modify & R_MASK)
+ offset -= (spos + relocsize);
+ offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize);
+ writeout(buf, relocsize);
+#ifdef BSD_A_OUT
+ if (reloc_output)
+ {
+ u4_t bitfield;
+
+ if (curseg == 0)
+ {
+ ++ntreloc;
+ offtocn(buf, spos, 4);
+ writetrel(buf, 4);
+ }
+ else
+ {
+ ++ndreloc;
+ offtocn(buf, spos - segbase[1], 4);
+ writedrel(buf, 4);
+ }
+ if ((modify & SEGM_MASK) == 0)
+ bitfield = N_TEXT;
+ else
+ bitfield = N_DATA;
+ if (modify & R_MASK)
+ bitfield |= 1L << 24;
+ if (relocsize == 2)
+ bitfield |= 1L << 25;
+ else if (relocsize == 4)
+ bitfield |= 1L << 26;
+ u4cn(buf, bitfield, 4);
+ if (curseg == 0)
+ writetrel(buf, 4);
+ else
+ writedrel(buf, 4);
+ }
+#endif /* BSD_A_OUT */
+ spos += relocsize;
+ break;
+ case CM_SYMBOL_RELOC:
+ symptr = symparray[symbolnum = readconvsize((unsigned)
+ (modify & S_MASK ? 2 : 1))];
+ offset = readconvsize((unsigned) modify & OF_MASK);
+ if (modify & R_MASK)
+ offset -= (spos + relocsize);
+#ifdef BSD_A_OUT
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+ offset += symptr->value;
+ offtocn(buf, offset, relocsize);
+ writeout(buf, relocsize);
+#ifdef BSD_A_OUT
+ if (reloc_output)
+ {
+ u4_t bitfield;
+
+ if (curseg == 0)
+ {
+ ++ntreloc;
+ offtocn(buf, spos, 4);
+ writetrel(buf, 4);
+ }
+ else
+ {
+ ++ndreloc;
+ offtocn(buf, spos - segbase[1], 4);
+ writedrel(buf, 4);
+ }
+ if (symptr->flags & I_MASK)
+ bitfield = (1L << 27) | symbolnum;
+ else if ((symptr->flags & SEGM_MASK) == 0)
+ bitfield = N_TEXT;
+ else if (symptr->flags & (C_MASK | SA_MASK))
+ bitfield = N_BSS;
+ else
+ bitfield = N_DATA;
+ if (modify & R_MASK)
+ bitfield |= 1L << 24;
+ if (relocsize == 2)
+ bitfield |= 1L << 25;
+ else if (relocsize == 4)
+ bitfield |= 1L << 26;
+ u4cn(buf, bitfield, 4);
+ if (curseg == 0)
+ writetrel(buf, 4);
+ else
+ writedrel(buf, 4);
+ }
+#endif /* BSD_A_OUT */
+ spos += relocsize;
+ }
+ }
+}
+
+PRIVATE void linkrefs(modptr)
+struct modstruct *modptr;
+{
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ modptr->loadflag = TRUE;
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr->loadflag == FALSE)
+ linkrefs(symptr->modptr);
+}
+
+PRIVATE void padmod(modptr)
+struct modstruct *modptr;
+{
+ offset_t count;
+ fastin_t seg;
+ offset_t size;
+ unsigned sizecount;
+ char *sizeptr;
+
+ for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ size = cntooffset(sizeptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+ sizeptr += sizecount;
+ if ((count = segpos[seg] - segbase[seg]) != size)
+ size_error(seg, count, size);
+
+ /* pad to quad boundary */
+ /* not padding in-between common areas which sometimes get into file */
+ if ((size = roundup(segpos[seg], 4, offset_t) - segpos[seg]) != 0)
+ {
+ setseg(seg);
+ writenulls(size);
+ segpos[seg] = spos;
+ }
+ segbase[seg] = segpos[seg];
+ }
+}
+
+PRIVATE void setsym(name, value)
+char *name;
+offset_t value;
+{
+ struct symstruct *symptr;
+
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ if ((symptr = findsym(name)) != NUL_PTR)
+ symptr->value = value;
+}
+
+PRIVATE void symres(name)
+register char *name;
+{
+ register struct symstruct *symptr;
+
+ if ((symptr = findsym(name)) != NUL_PTR)
+ {
+ if ((symptr->flags & SEGM_MASK) == SEGM_MASK)
+ symptr->flags &= ~SEGM_MASK | curseg;
+ if (symptr->flags != (I_MASK | curseg) || symptr->value != 0)
+ reserved(name);
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ symptr->flags = E_MASK | curseg; /* show defined, not common */
+ }
+}
+
+/* set new segment */
+
+PRIVATE void setseg(newseg)
+fastin_pt newseg;
+{
+ if (newseg != curseg)
+ {
+ segpos[curseg] = spos;
+ spos = segpos[curseg = newseg];
+ seekout(FILEHEADERLENGTH + (unsigned long) spos
+ + (unsigned long) segadj[curseg]);
+ }
+}
+
+PRIVATE void skip(countsize)
+unsigned countsize;
+{
+ writenulls((offset_t) readsize(countsize));
+}
+
+#ifdef EDOS
+
+PRIVATE void writeheader(commandname)
+char *commandname;
+{
+ char buf[MAX_OFFSET_SIZE];
+ offset_t offset;
+ unsigned headlength;
+ char *name;
+ struct entrylist *elptr;
+ struct symstruct *startptr;
+
+ headlength = binheaderlength(commandname);
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ headlength -= 6;
+ offset = headlength;
+ startptr = findsym("start");
+ offtocn(buf, edataoffset, 2);
+ writeout(buf, 2);
+ writechar(0xFF); /* dummy data length 0xFFFF takes everything */
+ writechar(0xFF);
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ {
+ name = idconvert(elptr, commandname);
+ writeout(name, (unsigned) strlen(name) + 1);
+ ourfree(name);
+ offtocn(buf, startptr == NUL_PTR ? elptr->elsymptr->value : offset, 2);
+ writeout(buf, 2);
+ writechar(0x82); /* 8 = set flags from here, 2 = cmd line */
+ offset += 6; /* LBSR $xxxx and LBRA $xxxx */
+ }
+ writechar(0);
+ if (startptr != NUL_PTR)
+ {
+ offset = headlength + 3; /* over 1st LBSR */
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ {
+ writechar(0x17); /* LBSR */
+ offtocn(buf, startptr->value - offset, 2);
+ writeout(buf, 2);
+ writechar(0x16); /* LBRA */
+ offtocn(buf, elptr->elsymptr->value - offset - 3, 2);
+ writeout(buf, 2);
+ offset += 6;
+ }
+ }
+}
+
+#endif /* EDOS */
+
+#ifdef MINIX
+
+PRIVATE void writeheader()
+{
+ struct exec header;
+
+ memset(&header, 0, sizeof header);
+#ifdef STANDARD_GNU_A_OUT
+#ifdef N_SET_MAGIC
+ N_SET_MAGIC(header, OMAGIC);
+#else
+ *(unsigned short *) &header.a_magic = OMAGIC; /* XXX - works for 386BSD */
+#endif
+#else
+ header.a_magic[0] = A_MAGIC0;
+ header.a_magic[1] = A_MAGIC1;
+#endif
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ {
+#ifdef STANDARD_GNU_A_OUT
+#ifdef N_SET_FLAGS
+ N_SET_FLAGS(header, 0);
+#else
+ /* XXX - works for 386BSD */
+#endif
+#else
+ header.a_flags = sepid ? A_SEP : A_EXEC;
+ if (uzp)
+ header.a_flags |= A_UZP;
+#endif
+ }
+#ifdef BSD_A_OUT
+#ifdef STANDARD_GNU_A_OUT
+#ifdef N_SET_FLAGS
+ N_SET_MACHTYPE(header, M_386);
+#else
+ /* XXX - works for 386BSD which doesn't define its own machtype :-( */
+#endif
+#else
+ header.a_cpu = (bits32 || reloc_output) ? A_I80386 : A_I8086;
+#endif
+#else
+ header.a_cpu = bits32 ? A_I80386 : A_I8086;
+#endif
+#ifndef STANDARD_GNU_A_OUT
+ header.a_hdrlen = FILEHEADERLENGTH;
+#endif
+ offtocn((char *) &header.a_text, etextpadoff - btextoffset,
+ sizeof header.a_text);
+ offtocn((char *) &header.a_data, edataoffset - bdataoffset,
+ sizeof header.a_data);
+ offtocn((char *) &header.a_bss, endoffset - edataoffset,
+ sizeof header.a_bss);
+#ifdef BSD_A_OUT
+ if (!reloc_output)
+#endif
+ {
+ if (uzp)
+ offtocn((char *) &header.a_entry, page_size(),
+ sizeof header.a_entry);
+#ifndef STANDARD_GNU_A_OUT
+ offtocn((char *) &header.a_total, (offset_t)
+ (endoffset < 0x00010000L ? 0x00010000L : endoffset + 0x0008000L),
+ sizeof header.a_total);
+#endif
+ }
+ if( FILEHEADERLENGTH )
+ writeout((char *) &header, FILEHEADERLENGTH);
+}
+
+#endif /* MINIX */
+
+PRIVATE void writenulls(count)
+offset_t count;
+{
+ spos += count;
+ while (count--)
+ writechar(0);
+}
diff --git a/libc-0.0.4/COPYING b/libc-0.0.4/COPYING
new file mode 100644
index 0000000..eb685a5
--- /dev/null
+++ b/libc-0.0.4/COPYING
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/libc-0.0.4/Changes b/libc-0.0.4/Changes
new file mode 100644
index 0000000..8cd0a84
--- /dev/null
+++ b/libc-0.0.4/Changes
@@ -0,0 +1,127 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library which is distributed
+# under the GNU Library General Public License.
+
+If you make any changes please put a little note here. -RDB
+
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+----- Mar 18 '96 - RDB
+Re-written to wetware storage "Robert must remember to fill in changes!"
+Ok, there's now some makefiles in the directory above for creating an
+environment with cleanup of bcc/as/ld makefiles and new home for bcc files.
+My version of a standard I/O package has been added, I've split the
+output libs for Linux-86 and MSDOS.
+(Now need small mod to bcc to accept '-d' as '-d -D__MSDOS__ -ldos')
+A couple of functions (including reboot) added to elksemu.
+----- Mar 3 '96 - RDB
+open/close in doselks
+----- Feb 25 '96 - RDB
+iota.c - oops -ve numbers give infinite loop
+altered a.out.h changed size of n_name from 8 to 24, ld needs recompile,
+dis88 bombed (bad malloc), nm etc will need to know.
+added popen, pclose, system
+----- Feb 24 '96 - RDB
+Problem with __lseek syscall, was trying to return a long - no way jose
+Little change to malloc1/* if you #define __MINI_MALLOC__ (used in LIB)
+a _much_ smaller but more limited version of malloc is used.
+Added assert.h - no __assert() in lib yet.
+Added in printf c/o Steven Huang <sthuang@hns.com>.
+ELKSemu; added -Wall, cleaned up mess.
+----- Feb 23 '96 - RDB
+Release 0.0.3, bump version to 0.0.4
+----- Feb 18 '96 - RDB
+ELKSemu signals now seem to be working.
+ELKSemu; Added symlinks
+ELKSemu; Added opendir support
+ELKSemu; now runs as ELF executable
+Added exec* functions except exec*p ones
+Small cleanup of doselks.
+Start final checks for 0.0.3
+----- Feb 16 '96 - RDB
+I do _NOT_ believe this - sbrk() yet again!! RIGHT! This time it WILL work!!
+Groan! There was no problem with sbrk, it was elksemu :-( fixed!
+----- Feb 12 '96 - RDB
+Yet another problem with sbrk() return val wrong! - FIXed
+Alter elksemu change in way *_tab.v files work.
+----- Feb 11 '96 - RDB
+Fix on strchr (asm86) - SI not saved
+First cut at opendir/readdir/closedir
+Move in ar.h
+add in 'make config' - (split malloc's and options for stdio packages)
+Merge in Nat's grp and other pieces.
+ELKSemu; Little i386 kernel patch, i8086 programs now run transparently :-)
+----- Feb 10 '96 - RDB
+Found a _nasty_ bug with atexit; the actual problem was in cstartup but ...
+----- Feb 4 '96 - RDB
+Corrected minor problem in atexit/on_exit
+----- Jan 28 '96 - RDB
+Debug, execve in libc _and_ elksemu
+perror added
+----- Jan 27 '96 - RDB
+Debug pwd, pw_fd was static
+Started modifing syscall.dat, adjusting elksemu to match.
+----- Jan 21 '96 - RDB
+Altered fflush to test return status. Corrected porting bug in printf.c
+----- Jan 20 '96 - RDB
+Imported printf from the 'DLibs' library, I've now found the rest of the
+Dlibs stdio, it appears to be very ST specific tho :-(
+NB: This is not in the dist, still sending out Joel's
+----- Jan 19 '96 - RDB
+Making some test alterations to stdio.
+Made ungetc into function, removed ungetc specific structure items
+Altered putc() to micro-macro.
+----- Jan 16 '96 - RDB
+Added in patches from Nat, corrected minor oops in misc/alias.c
+----- Jan 11 '96 - RDB
+Final checks, release version 0.0.2
+----- Jan 9 '96 - RDB
+Added 'signal' function.
+Added 'setjmp' Is it right for SI & DI to be saved ?
+----- Jan 8 '96 - RDB
+Added various MS-DOS functions, COM files are now starting to be able to
+do something useful.
+----- Jan 7 '96 - RDB
+Added the 'New_subdir' script.
+Now YOU (Yes I mean you reading this!) can use it :-)
+----- Jan 6 '96 - RDB
+Problem with sbrk() shown up by Joel's malloc, the error checks failed if
+you were allocating big blocks, fixed.
+----- Jan 6 '96 - RDB
+Added in Joel's malloc routine after a solid hack to actually debug it
+it seems to work now but I haven't really tested it; I can't do it under
+x386 Linux as something tried to link in 'realloc' too.
+----- Jan 5 '96 - RDB
+Ok, I've messed around and joined in Joel's stdio.h routines
+----- Jan 3 '96 - RDB
+(This is a good idea, dates, Always overlook the little things, ho hum!)
+----- - RDB
+Added 'movedata' function like MSC version to string/string.h
+----- - RDB
+Added support for the -C-f and -C-c options of BCC. BUT note for the moment
+the string functions degenerate to the C versions for -C-f
+----- - RDB
+Added getenv/putenv
+----- - RDB
+Changed crt0.c. It now only jmps to ___cstartup. This is so the same crt0
+can be used for both DOS and Linux, only the libc needs to be changed.
+Cost is 4 bytes at the start of the exe.
+----- - RDB
+Added support for automatic calling of functions before main. (See Pre_main)
+Added support for atexit() and onexit() functions.
+----- - RDB
+Added fast strchr
+Altered strstr to use strchr.
+----- - RDB
+Added cputype function - CPU detector.
+----- - RDB
+Dec 12 95
+Just completed a working debugged malloc set _including_ a 'fake' alloca
+function. (The assembler version will not work for BCC) It's a classical
+algorthm so may be slow in some cases. I had a look at the GNU malloc ...
+erm ... I _think_ I see what they're doing! :-)
+----- - RDB
+Added tiny printf, to be replaced by Joel.
+Added HP-UX long->ascii function.
+----- - RDB
+Split off brk/sbrk etc into own file. Asm alloca not compiled.
diff --git a/libc-0.0.4/Contributors b/libc-0.0.4/Contributors
new file mode 100644
index 0000000..d96193d
--- /dev/null
+++ b/libc-0.0.4/Contributors
@@ -0,0 +1,8 @@
+Alan Cox <alan@cymru.net>
+Bruce Evans <bde@FreeBSD.org>
+Chad Page <page0588@sundance.sjsu.edu>
+Dale Schumacher <dal@syntel.UUCP>
+Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+Nat Friedman <ndf@aleph1.mit.edu>
+Robert de Bath <rdebath@cix.compulink.co.uk>
+Steven Huang <sthuang@hns.com>
diff --git a/libc-0.0.4/KERNEL b/libc-0.0.4/KERNEL
new file mode 100644
index 0000000..6f83f90
--- /dev/null
+++ b/libc-0.0.4/KERNEL
@@ -0,0 +1,37 @@
+
+KERNEL SYSTEM CALL INTERFACE:
+The kernel system calls are all done through interrupt 0x80
+All parameters are passed in the 'AX,BX,CX,DX,DI,SI' registers.
+The AX register contains the system call number.
+The BX,CX,DX,DI,SI registers contain the first 5 arguments from the stack.
+(NB If the syscall is know to have less than 5 args the rest are not loaded)
+On return from the syscall AX has the return value.
+If AX is -ve then errno= -AX and return val = -1;
+
+The system calls are named in syscall/syscall.dat.
+There is a script syscall/mksyscall which generates the assembler for the
+system calls, near the top there is a line:
+ COMPACT=1
+If this is changed to
+ COMPACT=0
+the code generated will be slightly faster and larger.
+
+-RDB
+
+KERNEL SIGNAL INTERFACE:
+ It is assumed the kernel will never pass a signal to the userspace
+ routine unless it's _explicitly_ asked for!
+
+The Kernel need only save space for _one_ function pointer
+(to system_signal) and must deal with SIG_DFL and SIG_IGN
+in kernel space.
+
+When a signal is required the kernel must set all the registers as if
+returning from a interrupt normally then push the number of the signal
+to be generated, push the current pc value, then set the pc to the
+address of the 'system_signal' function.
+
+This is in syscall/signal.c
+
+-RDB
+
diff --git a/libc-0.0.4/MAGIC b/libc-0.0.4/MAGIC
new file mode 100644
index 0000000..69c9c2d
--- /dev/null
+++ b/libc-0.0.4/MAGIC
@@ -0,0 +1,23 @@
+Useful bits for /etc/magic:
+
+#------------------------------------------------------------------------------
+# Localstuff: file(1) magic for locally observed files
+#
+# $Id: Localstuff,v 1.3 1995/01/21 21:09:00 christos Exp $
+# Add any locally observed files here. Remember:
+# text if readable, executable if runnable binary, data if unreadable.
+#
+0 string \01\03\020\04 Linux-8086 impure executable
+>16 long !0 not stripped
+0 string \01\03\040\04 Linux-8086 executable
+>16 long !0 not stripped
+#
+0 string \243\206\001\0 Linux-8086 object file
+# There is _no_ difference between 16 and 32 bit .o files
+#
+0 string \01\03\020\20 Minix-386 impure executable
+>16 long !0 not stripped
+0 string \01\03\040\20 Minix-386 executable
+>16 long !0 not stripped
+#
+#------------------------------------------------------------------------------
diff --git a/libc-0.0.4/Make.defs b/libc-0.0.4/Make.defs
new file mode 100644
index 0000000..b960852
--- /dev/null
+++ b/libc-0.0.4/Make.defs
@@ -0,0 +1,64 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+# Set PLATFORM to i386-Linux to build for Linux/386 and to i86-ELKS to
+# build for ELKS. This doesn't quite work yet, though, because of some of
+# the platform and/or compiler-specific code flying around here.
+# Eventually, compiler-specificity won't be an issue, and we can put
+# platform-specific code in i86/ and i386/. -Nat
+
+# Define enviroment var for others.
+ifeq ($(PLATFORM),)
+PLATFORM=i86-ELKS
+#PLATFORM=i86-DOS
+#PLATFORM=i386-Linux
+endif
+
+VERMAJOR=0
+VERMINOR=0
+VERPATCH=4
+VER=$(VERMAJOR).$(VERMINOR).$(VERPATCH)
+
+LIBDEFS=-D__LIBC__
+LIBC=libc.a
+
+ifneq ($(PLATFORM),i386-Linux)
+
+# Normal standard 8086 code
+ifeq ($(PLATFORM),i86-ELKS)
+ARCH=-0
+
+# 8086 elks code With "Caller saves" and "First arg in AX"
+# ARCH=-0 -C-c -C-f
+endif
+
+# MSDOS COM file (msdos libs don't support "First arg in AX")
+ifeq ($(PLATFORM),i86-DOS)
+ARCH=-0 -d -D__MSDOS__
+LIBC=libdos.a
+endif
+
+# BCC 386.
+ifeq ($(PLATFORM),i386-BCC)
+ARCH=-3
+endif
+
+CC=bcc $(ARCH)
+CCFLAGS=-O -I -I$(TOP)/include
+LKFLAGS=-L -L$(TOP)/ -s
+
+else # ifeq ($(PLATFORM),i386-Linux)
+
+CC=gcc $(ARCH)
+# ARCH=-b i486-linuxaout
+LKFLAGS=-static -N
+CCFLAGS=-O6 -fomit-frame-pointer -I- -I$(TOP)/include -I. -fno-builtin
+WALL= -ansi -pedantic -Wwrite-strings -Wpointer-arith -Wcast-qual \
+ -Wcast-align -Wtraditional -Wstrict-prototypes -Wmissing-prototypes \
+ -Wnested-externs -Winline -Wshadow
+
+endif # ifeq ($(PLATFORM),i386-Linux)
+
+CFLAGS=$(CCFLAGS) $(LIBDEFS)
+LDFLAGS=$(LKFLAGS)
diff --git a/libc-0.0.4/Makefile b/libc-0.0.4/Makefile
new file mode 100644
index 0000000..7b233bd
--- /dev/null
+++ b/libc-0.0.4/Makefile
@@ -0,0 +1,71 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=.
+include $(TOP)/Make.defs
+
+SRC=crt0.c
+OBJ=crt0.o
+
+TARGETS=$(OBJ) $(LIBC)
+TXT=COPYING Changes Contributors MAGIC \
+ Make.defs Makefile New_subdir Pre_main README TODO KERNEL
+
+all: $(TARGETS)
+
+install: all
+ install -d $(BCCHOME)
+ rm -rf $(BCCHOME)/include
+ ln -s $(TOPDIR)/libc/include $(BCCHOME)/include
+ install -d $(LIBDIR)/i86
+ install -m 644 crt0.o $(LIBDIR)/i86
+ install -m 644 $(LIBC) $(LIBDIR)/i86
+ -install -m 644 error/liberror.txt /usr/lib
+
+tests: dummy
+ make -C tests
+
+$(LIBC): transfer
+ for i in */Makefile ; do \
+ make -C `dirname $$i` $@ || exit 1 ; \
+ done
+
+realclean: clean
+ rm -f $(OBJ) $(LIBC) libc-$(VER)
+ @for i in */makefile ; do \
+ grep -q '^clean:' $$i && make -C `dirname $$i` clean ; \
+ done ; echo -n
+
+clean: dummy
+ for i in */Makefile ; do \
+ make -C `dirname $$i` $@ || exit 1 ; \
+ done
+
+config:
+ sh Config.sh
+ @for i in */Makefile ; do \
+ [ -f `dirname $$i`/Config.sh ] && \
+ sh `dirname $$i`/Config.sh ] ; \
+ done ; echo -n
+
+dist: clean
+ tar cf temp.tar \
+ $(TXT) $(TARGETS) $(SRC) include \
+ `for i in */Makefile */Config; do dirname $$i; done | sort -u`
+ rm -rf libc-$(VER)
+ mkdir libc-$(VER) ; cd libc-$(VER) ; tar xf ../temp.tar
+ tar czf libc-8086-$(VER).tar.gz libc-$(VER)
+ rm -rf libc-$(VER) temp.tar
+
+dist_ver: dist
+ mv libc-8086-$(VER).tar.gz ..
+ echo $(VER) > ../Libc_version
+
+transfer: dummy
+ @echo Checking for transfers
+ @for i in */Makefile ; do \
+ grep -q '^transfer' $$i && make -C `dirname $$i` $@ ; \
+ done ; echo -n
+
+dummy:
diff --git a/libc-0.0.4/New_subdir b/libc-0.0.4/New_subdir
new file mode 100755
index 0000000..a10ccf7
--- /dev/null
+++ b/libc-0.0.4/New_subdir
@@ -0,0 +1,67 @@
+#!/bin/sh -
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+cat <<!
+This is a shell script to create the bare bones for a new part of the
+libc package. To use it you just invoke it with the directory name
+you want to create as it's argument, it'll then create that directory
+and put a few files in it.
+
+!
+if [ "$1" = "" ] ; then exit 1 ; fi
+if [ -e "$1" ]
+then echo "There is already something called '$1' in the current directory"
+ echo "You'll have to remove it or rename it first"
+ exit 1
+fi
+
+YEAR=`date +%Y`
+NAME="`finger -s $LOGNAME | head -2 | tail -1 | cut -b10-30 | sed 's/ *$//'`"
+EMAIL="$LOGNAME@`hostname -f`"
+FNAME="`echo $NAME | cut -d\ -f1`"
+
+mkdir $1
+cat <<! > $1/Makefile
+# Copyright (C) $YEAR $NAME <$EMAIL>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include \$(TOP)/Make.defs
+
+OBJ=$1.o
+
+all: \$(OBJ)
+
+libc.a: \$(OBJ)
+ ar r ../libc.a \$(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f \$(OBJ) libc.a
+!
+cat <<! > $1/README
+Copyright (C) $YEAR $NAME <$EMAIL>
+This file is part of the Linux-8086 C library and is distributed
+under the GNU Library General Public License.
+
+There's currently nothing special about $1.
+
+-$FNAME
+!
+cat <<! > $1/$1.c
+/* Copyright (C) $YEAR $NAME <$EMAIL>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+$1()
+{
+ /* FIXME :-) */
+}
+!
+
+echo "Ok, the directory $1 has now been created ..."
+exit 0
diff --git a/libc-0.0.4/Pre_main b/libc-0.0.4/Pre_main
new file mode 100644
index 0000000..e3793f1
--- /dev/null
+++ b/libc-0.0.4/Pre_main
@@ -0,0 +1,55 @@
+
+There is now support for calling functions before main and from inside the
+exit() function.
+
+The exit processing uses the standard 'atexit' and 'on_exit' functions
+see the normal man pages.
+
+Execution of code before main is Linux-8086 specific; the method
+is similar to this:
+
+/**********************/
+int global_var_that_needs_init;
+
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word _init_vars ! Pointer to the autorun function
+ .word no_op ! Space filler cause segs are padded to 4 bytes.
+ .text ! So the function after is also in the correct seg.
+#endasm
+
+static void init_vars()
+{
+ global_var_that_needs_init = getuid();
+}
+/**********************/
+
+The most important part is that the asm code _MUST_ be compiled into the
+same object file as the variable that is being initialised.
+
+If this is not so the init_vars function will not be linked in and will
+not be executed.
+
+Also do note that the init functions are called in essentially random order
+(It's actually the order that they appear in the executable) so you must be
+careful not to call any routines tht have their own autostart from inside
+your autostart. Nevertheless you should try to ensure that your routines
+will fail gracefully if they are called before the initilisation routine.
+
+If you do not know if a routine has an autostart create a test program
+calling the routine and compile with:
+
+ bcc -0 [other_stuff] -M test.c | sort +2 | more
+
+Look down the list for lines like this:
+
+ crt0 ZP_safety 1 00000000 R
+ crt0 auto_start 1 00000008 R
+ objname auto_func 1 00000008 R <<****
+ crt0 data_start 2 00000010 R
+ crt0 _environ 3 00000010 R
+
+The line marked is an autostart function call.
+
+Robert.
diff --git a/libc-0.0.4/README b/libc-0.0.4/README
new file mode 100644
index 0000000..f8160ba
--- /dev/null
+++ b/libc-0.0.4/README
@@ -0,0 +1,70 @@
+
+This is the README for libc-8086-0.0.3.tar.gz
+Robert de Bath, 22/Feb/96, rdebath@cix.compulink.co.uk
+
+The lib is starting to look a lot fatter, it can now be compiled five
+different ways for Linux-8086 standard, Linux-8086 with 'First arg in AX',
+MS-DOS, BCC-386 or for GNU-386. At the moment the 386 versions are
+missing some _very_ important bits.
+
+THE COMPILER
+ You should use the newest version of the bcc/bcc-cc1/as86/ld86 tools these
+ contain patches to ease operating in a cross-compiling enviroment and
+ the arguments to BCC have changed slightly.
+
+ The standard ld86 can't generate MSDOS COM files by itself.
+ If you need to change search paths they can all be done from the command
+ line or by recompiling _only_ bcc.c.
+ These tools also contain Nat's 'clean' and 'ansi' patches.
+
+Main Subdirectories.
+
+include Some include files, some new others Glib or Glib hacked.
+ (They are a _real_ mess ATM and very light on the ground)
+
+bcc Lots of BCC helper functions
+malloc1 My malloc routines
+malloc2 Joel's malloc routines
+misc Various larger functions
+msdos This is the equlivent of the syscall directory for msdos.
+string The functions for string.h
+syscall All the system call functions, and a few tied lib ones.
+stdio Joel's standard I/O functions - as yet rather incomplete
+pwd Routines for /etc/passwd, from Nat
+grp Routines for /etc/group, from Nat
+regexp Standard regular expression parser
+tests Various C programs used to test the lib.
+
+Directory structure:
+
+ The top Makefile will try to call any "Makefile" it finds in a
+ subdirectory, so to add a new chunk to "libc.a" just drop in
+ the directory a Makefile that understands "make clean" and
+ "make libc.a" (Which must also update ../libc.a)
+ There's now a tiny script (New_subdir) that'll do this.
+
+ Make config will look in all subdirectories for a file 'Config'
+ any it finds will be displayed and can be used to switch a directory
+ on or off by renaming Makefile<->makefile.
+ (This seemed like a good idea, I'm not so sure now ...)
+
+ The exit(rv) function is already defined. It will call the contents
+ of the function pointer (*__cleanup)() before it calls _exit();
+ This pointer should be used through the 'atexit' or 'on_exit' lib
+ functions. (See standard man pages)
+
+ If you need to call something before main see the file 'Pre_main'.
+
+There are symlinks in the archive, they assume a layout something like:
+
+ Linux_8086
+ Linux_8086/libc This Libc
+ Linux_8086/linuxmt The Elks Kernel
+ Linux_8086/ELKSemu The Elks Emulator
+ Linux_8086/bcc Compiler src
+ Linux_8086/as Assembler
+ Linux_8086/ld Linker
+
+-Robert
+
+-=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=- -=*=-
diff --git a/libc-0.0.4/TODO b/libc-0.0.4/TODO
new file mode 100644
index 0000000..a65fac7
--- /dev/null
+++ b/libc-0.0.4/TODO
@@ -0,0 +1,54 @@
+Here's a short list of bits that are required. If you want to do one of
+these it's probably best to post to the list <linux-8086@vger.rutgers.edu>.
+
+Add more to this todo list!
+
+
+TODO for libc-8086:
+Item Notes
+---------------------------------------------------------------------------
+Floating Point - BUT note there may need to be kernel support. Also,
+ BCC doesn't do it properly right now...
+Header Files - This will take some time, also some files should
+ be kernel.
+Stdio - Joel is on this. (stdio1) (RDB stdio2)
+dirent &co - Directory listing - Partial.
+getgrent &co - Nat -Done
+getpwent &co - Nat -Done
+utmp/wtmp - Nat -Done
+hsearch &co -
+tsearch &co -
+locale processing - multi national, unicode (string stuff has a couple
+ of stubs)
+login - getpass and friends - [I'll just dump the tiny-login
+ getpass code in -Nat]
+rpc -
+setjmp - Done, Rob
+syslog &co - make stubs to splatter to console.
+time calcs - mktime gmtime localtime etc
+timezone - Probably V simplistic, List of UTC's
+ offsets & STDvDST
+shadow password - Do we need ? Do we want :-) [No! Ick! ;) -Nat]
+termcap - and curses; what does ncurses need ? (150kb!!)
+crypt - glibc/crypt ? Use TEA?
+signal stuff - Got a basic 'signal' appears to work correctly.
+getenv/setenv - Done
+bsearch - Grabbed (Public Domain)
+lsearch - Grabbed (Public Domain)
+random numbers - Got ZX81 version (better than some) (And 2nd now)
+math - Until BCC can handle 16 bit FP properly, this is
+ probably on hold..
+dual-platform build
+environment - This will be a gradual process, I imagine.
+
+Other projects:
+Project Notes
+---------------------------------------------------------------------------
+Optimiser for BCC - A lot of work, but lucrative.
+Tiny vi editor - Use 'ae' ?
+Shells: Bourne, Csh,
+menu, silly - ash with proper compile-time options. . . ?
+Tiny Perl - :-) :-) You first ;)
+User commands - Everything in /bin /usr/bin - will existing PD/GPL
+ compile in 16 bit ? Or do smaller ones exist,
+ need to written ?
diff --git a/libc-0.0.4/bcc/Config b/libc-0.0.4/bcc/Config
new file mode 100644
index 0000000..0bfed09
--- /dev/null
+++ b/libc-0.0.4/bcc/Config
@@ -0,0 +1,2 @@
+
+bcclib: Library of bcc helper functions
diff --git a/libc-0.0.4/bcc/Makefile b/libc-0.0.4/bcc/Makefile
new file mode 100644
index 0000000..b5019a5
--- /dev/null
+++ b/libc-0.0.4/bcc/Makefile
@@ -0,0 +1,58 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+# Support for integer arithmetic
+IOBJ=__idiv.o __idivu.o __imod.o __imodu.o __imul.o __isl.o __isr.o __isru.o
+ISRC=bcc_int.c
+
+# Support for long arithmetic on little-endian (normal) longs
+LSRC=bcc_long.c
+LOBJ=__laddl.o __landl.o __lcmpl.o __lcoml.o __ldecl.o __ldivl.o __ldivul.o \
+ __leorl.o __lincl.o __lmodl.o __lmodul.o __lmull.o __lnegl.o __lorl.o \
+ __lsll.o __lsrl.o __lsrul.o __lsubl.o __ltstl.o
+
+# Memory allocation primitives
+AOBJ=errno.o __brk_addr.o sbrk.o brk.o
+ASRC=heap.c
+
+# Support for long arithmetic on big-endian (words-swapped) longs
+RSRC=bcc_bsw.c
+ROBJ=__laddb.o __landb.o __lcmpb.o __lcomb.o __ldecb.o __ldivb.o __ldivub.o \
+ __leorb.o __lincb.o __lmodb.o __lmodub.o __lmulb.o __lnegb.o __lorb.o \
+ __lslb.o __lsrb.o __lsrub.o __lsubb.o __ltstb.o
+
+# Miscellaneous I/O and far access junk
+PSRC=bcc_io.c
+POBJ=__inport.o __inportb.o __outport.o __outportb.o __peekb.o __peekw.o \
+ __pokeb.o __pokew.o
+
+OBJ=__ldivmod.o $(IOBJ) $(LOBJ) $(AOBJ)
+OLDOBJ=$(ROBJ) $(POBJ)
+
+all: $(OBJ)
+
+$(IOBJ): $(ISRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ISRC)
+
+$(LOBJ): $(LSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(LSRC)
+
+$(AOBJ): $(ASRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ASRC)
+
+$(ROBJ): $(RSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(RSRC)
+
+$(POBJ): $(PSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(PSRC)
+
+$(LIBC): $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f $(OBJ) libc.a
diff --git a/libc-0.0.4/bcc/__ldivmod.c b/libc-0.0.4/bcc/__ldivmod.c
new file mode 100644
index 0000000..4cb6d77
--- /dev/null
+++ b/libc-0.0.4/bcc/__ldivmod.c
@@ -0,0 +1,195 @@
+/************************************************************************/
+/* This file contains the BCC compiler helper functions */
+/* Function ldivmod */
+
+#ifdef __AS386_16__
+#asm
+ .text
+ .even
+
+| ldivmod.s - 32 over 32 to 32 bit division and remainder for 8086
+
+| ldivmod( dividend bx:ax, divisor di:cx ) [ signed quot di:cx, rem bx:ax ]
+| ludivmod( dividend bx:ax, divisor di:cx ) [ unsigned quot di:cx, rem bx:ax ]
+
+| dx is not preserved
+
+
+| NB negatives are handled correctly, unlike by the processor
+| divison by zero does not trap
+
+
+| let dividend = a, divisor = b, quotient = q, remainder = r
+| a = b * q + r mod 2^32
+| where:
+
+| if b = 0, q = 0 and r = a
+
+| otherwise, q and r are uniquely determined by the requirements:
+| r has the same sign as b and absolute value smaller than that of b, i.e.
+| if b > 0, then 0 <= r < b
+| if b < 0, then 0 >= r > b
+| (the absoulute value and its comparison depend on signed/unsigned)
+
+| the rule for the sign of r means that the quotient is truncated towards
+| negative infinity in the usual case of a positive divisor
+
+| if the divisor is negative, the division is done by negating a and b,
+| doing the division, then negating q and r
+
+
+ .globl ldivmod
+
+ldivmod:
+ mov dx,di ! sign byte of b in dh
+ mov dl,bh ! sign byte of a in dl
+ test di,di
+ jns set_asign
+ neg di
+ neg cx
+ sbb di,*0
+set_asign:
+ test bx,bx
+ jns got_signs ! leave r = a positive
+ neg bx
+ neg ax
+ sbb bx,*0
+ j got_signs
+
+ .globl ludivmod
+ .even
+
+ludivmod:
+ xor dx,dx ! both sign bytes 0
+got_signs:
+ push bp
+ push si
+ mov bp,sp
+ push di ! remember b
+ push cx
+b0 = -4
+b16 = -2
+
+ test di,di
+ jne divlarge
+ test cx,cx
+ je divzero
+ cmp bx,cx
+ jae divlarge ! would overflow
+ xchg dx,bx ! a in dx:ax, signs in bx
+ div cx
+ xchg cx,ax ! q in di:cx, junk in ax
+ xchg ax,bx ! signs in ax, junk in bx
+ xchg ax,dx ! r in ax, signs back in dx
+ mov bx,di ! r in bx:ax
+ j zdivu1
+
+divzero: ! return q = 0 and r = a
+ test dl,dl
+ jns return
+ j negr ! a initially minus, restore it
+
+divlarge:
+ push dx ! remember sign bytes
+ mov si,di ! w in si:dx, initially b from di:cx
+ mov dx,cx
+ xor cx,cx ! q in di:cx, initially 0
+ mov di,cx
+ ! r in bx:ax, initially a
+ ! use di:cx rather than dx:cx in order to
+ ! have dx free for a byte pair later
+ cmp si,bx
+ jb loop1
+ ja zdivu ! finished if b > r
+ cmp dx,ax
+ ja zdivu
+
+| rotate w (= b) to greatest dyadic multiple of b <= r
+
+loop1:
+ shl dx,*1 ! w = 2*w
+ rcl si,*1
+ jc loop1_exit ! w was > r counting overflow (unsigned)
+ cmp si,bx ! while w <= r (unsigned)
+ jb loop1
+ ja loop1_exit
+ cmp dx,ax
+ jbe loop1 ! else exit with carry clear for rcr
+loop1_exit:
+ rcr si,*1
+ rcr dx,*1
+loop2:
+ shl cx,*1 ! q = 2*q
+ rcl di,*1
+ cmp si,bx ! if w <= r
+ jb loop2_over
+ ja loop2_test
+ cmp dx,ax
+ ja loop2_test
+loop2_over:
+ add cx,*1 ! q++
+ adc di,*0
+ sub ax,dx ! r = r-w
+ sbb bx,si
+loop2_test:
+ shr si,*1 ! w = w/2
+ rcr dx,*1
+ cmp si,b16[bp] ! while w >= b
+ ja loop2
+ jb zdivu
+ cmp dx,b0[bp]
+ jae loop2
+
+zdivu:
+ pop dx ! sign bytes
+zdivu1:
+ test dh,dh
+ js zbminus
+ test dl,dl
+ jns return ! else a initially minus, b plus
+ mov dx,ax ! -a = b * q + r ==> a = b * (-q) + (-r)
+ or dx,bx
+ je negq ! use if r = 0
+ sub ax,b0[bp] ! use a = b * (-1 - q) + (b - r)
+ sbb bx,b16[bp]
+ not cx ! q = -1 - q (same as complement)
+ not di
+negr:
+ neg bx
+ neg ax
+ sbb bx,*0
+return:
+ mov sp,bp
+ pop si
+ pop bp
+ ret
+
+ .even
+
+zbminus:
+ test dl,dl ! (-a) = (-b) * q + r ==> a = b * q + (-r)
+ js negr ! use if initial a was minus
+ mov dx,ax ! a = (-b) * q + r ==> a = b * (-q) + r
+ or dx,bx
+ je negq ! use if r = 0
+ sub ax,b0[bp] ! use a = b * (-1 - q) + (b + r) (b is now -b)
+ sbb bx,b16[bp]
+ not cx
+ not di
+ mov sp,bp
+ pop si
+ pop bp
+ ret
+
+ .even
+
+negq:
+ neg di
+ neg cx
+ sbb di,*0
+ mov sp,bp
+ pop si
+ pop bp
+ ret
+#endasm
+#endif
diff --git a/libc-0.0.4/bcc/alloca.c b/libc-0.0.4/bcc/alloca.c
new file mode 100644
index 0000000..4f85047
--- /dev/null
+++ b/libc-0.0.4/bcc/alloca.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/* Alloca is a nice interesting function */
+/* Needs change to BCC to work, as BCC doesn't use 'mov sp,bp:pop bp' */
+/* The only other way to do it is to use malloc and the emacs alloca */
+
+#if 0
+THIS IS BROKEN!!!
+
+#asm
+export _alloca
+ .text
+_alloca:
+ pop cx ! The program counter
+ pop ax ! The argument (>1 arg == snafu)
+ inc ax
+ and al,$FE ! Round up to even
+
+ test ax,ax
+ jz too_big ! Well _I_ think it means 64k ! :-) (ANSI too IIUC)
+
+ mov bx,sp
+ sub bx,ax ! Calc new SP
+ jb too_big ! SP wrapped, snafu!
+
+ mov ax,[brk_addr]
+ add ax,#64 ! Check if brk has allocated the memory first but
+ cmp bx,ax ! leave a little bit of space before we collide!
+ jb too_big
+
+ xchg bx,sp ! Put it in place, may need the old SP for other args
+ mov ax,sp ! The bottom of the area allocated
+
+ ! This is needed if si/di popped before mov sp,bp
+ !push [bx+4] ! This copies the saved register vars and possibly a temp
+ !push [bx+2] ! value, beware snafu if called within complex expression!
+ !push [bx] !
+
+ push ax ! Anything really, it will be deallocated by the caller
+ jmp cx ! Return
+
+too_big:
+ xor ax,ax ! Sorry not enough stack
+ push ax ! More junk
+ jmp cx ! Return
+#endasm
+#endif
diff --git a/libc-0.0.4/bcc/bcc_bsw.c b/libc-0.0.4/bcc/bcc_bsw.c
new file mode 100644
index 0000000..4dd0d11
--- /dev/null
+++ b/libc-0.0.4/bcc/bcc_bsw.c
@@ -0,0 +1,487 @@
+/************************************************************************/
+/* This file contains the BCC compiler helper functions */
+/* Support for long arithmetic on big-endian (words-swapped) longs
+ * __laddb.o __landb.o __lcmpb.o __lcomb.o __ldecb.o __ldivb.o __ldivub.o
+ * __leorb.o __lincb.o __lmodb.o __lmodub.o __lmulb.o __lnegb.o __lorb.o
+ * __lslb.o __lsrb.o __lsrub.o __lsubb.o __ltstb.o
+ */
+#ifdef __AS386_16__
+#asm
+ .text ! This is common to all.
+ .even
+#endasm
+
+/************************************************************************/
+/* Function laddb */
+
+#ifdef L___laddb
+#asm
+
+| laddb.s
+
+ .globl laddb
+ .globl laddub
+
+laddb:
+laddub:
+ add bx,2(di)
+ adc ax,(di)
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function landb */
+
+#ifdef L___landb
+#asm
+
+| landb.s
+
+ .globl landb
+ .globl landub
+
+landb:
+landub:
+ and ax,(di)
+ and bx,2(di)
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lcmpb */
+
+#ifdef L___lcmpb
+#asm
+
+| lcmpb.s
+| lcmpb, lcmpub don`t preserve ax
+
+ .globl lcmpb
+ .globl lcmpub
+
+lcmpb:
+lcmpub:
+ sub ax,(di) | don`t need to preserve ax
+ je LCMP_NOT_SURE
+ ret
+
+ .even
+
+LCMP_NOT_SURE:
+ cmp bx,2(di)
+ jb LCMP_B_AND_LT | b (below) becomes lt (less than) as well
+ jge LCMP_EXIT | ge and already ae
+ | else make gt as well as a (above)
+ inc ax | clear ov and mi, set ne for greater than
+LCMP_EXIT:
+ ret
+
+ .even
+
+LCMP_B_AND_LT:
+ dec ax | clear ov, set mi and ne for less than
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lcomb */
+
+#ifdef L___lcomb
+#asm
+
+| lcomb.s
+
+ .globl lcomb
+ .globl lcomub
+
+lcomb:
+lcomub:
+ not ax
+ not bx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function ldecb */
+
+#ifdef L___ldecb
+#asm
+
+| ldecb.s
+
+ .globl ldecb
+ .globl ldecub
+
+ldecb:
+ldecub:
+ cmp 2(bx),*0
+ je LDEC_BOTH
+ dec 2(bx)
+ ret
+
+ .even
+
+LDEC_BOTH:
+ dec 2(bx)
+ dec (bx)
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function ldivb */
+
+#ifdef L___ldivb
+#asm
+
+| ldivb.s
+| ax:bx / (di):2(di), quotient ax:bx, remainder cx:di, dx not preserved
+
+ .globl ldivb
+ .extern ldivmod
+
+ldivb:
+ xchg ax,bx
+ mov cx,2(di)
+ mov di,(di)
+ call ldivmod | bx:ax / di:cx, quot di:cx, rem bx:ax
+ xchg ax,di
+ xchg bx,cx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function ldivub */
+
+#ifdef L___ldivub
+#asm
+
+| ldivub.s
+| unsigned ax:bx / (di):2(di), quotient ax:bx,remainder cx:di, dx not preserved
+
+ .globl ldivub
+ .extern ludivmod
+
+ldivub:
+ xchg ax,bx
+ mov cx,2(di)
+ mov di,(di)
+ call ludivmod | unsigned bx:ax / di:cx, quot di:cx, rem bx:ax
+ xchg ax,di
+ xchg bx,cx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function leorb */
+
+#ifdef L___leorb
+#asm
+
+| leorb.s
+
+ .globl leorb
+ .globl leorub
+
+leorb:
+leorub:
+ xor ax,(di)
+ xor bx,2(di)
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lincb */
+
+#ifdef L___lincb
+#asm
+
+| lincb.s
+
+ .globl lincb
+ .globl lincub
+
+lincb:
+lincub:
+ inc 2(bx)
+ je LINC_HIGH_WORD
+ ret
+
+ .even
+
+LINC_HIGH_WORD:
+ inc (bx)
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lmodb */
+
+#ifdef L___lmodb
+#asm
+
+| lmodb.s
+| ax:bx % (di):2(di), remainder ax:bx, quotient cx:di, dx not preserved
+
+ .globl lmodb
+ .extern ldivmod
+
+lmodb:
+ xchg ax,bx
+ mov cx,2(di)
+ mov di,(di)
+ call ldivmod | bx:ax / di:cx, quot di:cx, rem bx:ax
+ xchg ax,bx
+ xchg cx,di
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lmodub */
+
+#ifdef L___lmodub
+#asm
+
+| lmodub.s
+| unsigned ax:bx / (di):2(di), remainder ax:bx,quotient cx:di, dx not preserved
+
+ .globl lmodub
+ .extern ludivmod
+
+lmodub:
+ xchg ax,bx
+ mov cx,2(di)
+ mov di,(di)
+ call ludivmod | unsigned bx:ax / di:cx, quot di:cx, rem bx:ax
+ xchg ax,bx
+ xchg cx,di
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lmulb */
+
+#ifdef L___lmulb
+#asm
+
+| lmulb.s
+| lmulb, lmulub don`t preserve cx, dx
+
+ .globl lmulb
+ .globl lmulub
+
+lmulb:
+lmulub:
+ mul 2(di)
+ xchg ax,bx
+ mov cx,ax
+ mul (di)
+ add bx,ax
+ mov ax,2(di)
+ mul cx
+ add bx,dx
+ xchg ax,bx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lnegb */
+
+#ifdef L___lnegb
+#asm
+
+| lnegb.s
+
+ .globl lnegb
+ .globl lnegub
+
+lnegb:
+lnegub:
+ neg ax
+ neg bx
+ sbb ax,*0
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lorb */
+
+#ifdef L___lorb
+#asm
+
+| lorb.s
+
+ .globl lorb
+ .globl lorub
+
+lorb:
+lorub:
+ or ax,(di)
+ or bx,2(di)
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lslb */
+
+#ifdef L___lslb
+#asm
+
+| lslb.s
+| lslb, lslub don`t preserve cx
+
+ .globl lslb
+ .globl lslub
+
+lslb:
+lslub:
+ mov cx,di
+ jcxz LSL_EXIT
+ cmp cx,*32
+ jae LSL_ZERO
+LSL_LOOP:
+ shl bx,*1
+ rcl ax,*1
+ loop LSL_LOOP
+LSL_EXIT:
+ ret
+
+ .even
+
+LSL_ZERO:
+ xor ax,ax
+ mov bx,ax
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lsrb */
+
+#ifdef L___lsrb
+#asm
+
+| lsrb.s
+| lsrb doesn`t preserve cx
+
+ .globl lsrb
+
+lsrb:
+ mov cx,di
+ jcxz LSR_EXIT
+ cmp cx,*32
+ jae LSR_SIGNBIT
+LSR_LOOP:
+ sar ax,*1
+ rcr bx,*1
+ loop LSR_LOOP
+LSR_EXIT:
+ ret
+
+ .even
+
+LSR_SIGNBIT:
+ mov cx,*32 | equivalent to +infinity in this context
+ j LSR_LOOP
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lsrub */
+
+#ifdef L___lsrub
+#asm
+
+| lsrub.s
+| lsrub doesn`t preserve cx
+
+ .globl lsrub
+
+lsrub:
+ mov cx,di
+ jcxz LSRU_EXIT
+ cmp cx,*32
+ jae LSRU_ZERO
+LSRU_LOOP:
+ shr ax,*1
+ rcr bx,*1
+ loop LSRU_LOOP
+LSRU_EXIT:
+ ret
+
+ .even
+
+LSRU_ZERO:
+ xor ax,ax
+ mov bx,ax
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lsubb */
+
+#ifdef L___lsubb
+#asm
+
+| lsubb.s
+
+ .globl lsubb
+ .globl lsubub
+
+lsubb:
+lsubub:
+ sub bx,2(di)
+ sbb ax,(di)
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function ltstb */
+
+#ifdef L___ltstb
+#asm
+
+| ltstb.s
+| ltstb, ltstub don`t preserve ax
+
+ .globl ltstb
+ .globl ltstub
+
+ltstb:
+ltstub:
+ test ax,ax
+ je LTST_NOT_SURE
+ ret
+
+ .even
+
+LTST_NOT_SURE:
+ test bx,bx
+ js LTST_FIX_SIGN
+ ret
+
+ .even
+
+LTST_FIX_SIGN:
+ inc ax | clear ov and mi, set ne for greater than
+ ret
+#endasm
+#endif
+
+#endif
+
diff --git a/libc-0.0.4/bcc/bcc_int.c b/libc-0.0.4/bcc/bcc_int.c
new file mode 100644
index 0000000..abdb7b4
--- /dev/null
+++ b/libc-0.0.4/bcc/bcc_int.c
@@ -0,0 +1,162 @@
+/************************************************************************/
+/* This file contains the BCC compiler helper functions */
+/* Support for integer arithmetic
+ * __idiv.o __idivu.o __imod.o __imodu.o __imul.o __isl.o __isr.o __isru.o
+ */
+
+#ifdef __AS386_16__
+#asm
+ .text ! This is common to all.
+ .even
+#endasm
+
+/************************************************************************/
+/* Function idiv */
+
+#ifdef L___idiv
+#asm
+
+| idiv.s
+| idiv_ doesn`t preserve dx (returns remainder in it)
+
+ .globl idiv_
+
+idiv_:
+ cwd
+ idiv bx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function idivu */
+
+#ifdef L___idivu
+#asm
+
+| idivu.s
+| idiv_u doesn`t preserve dx (returns remainder in it)
+
+ .globl idiv_u
+
+idiv_u:
+ xor dx,dx
+ div bx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function imod */
+
+#ifdef L___imod
+#asm
+
+| imod.s
+| imod doesn`t preserve dx (returns quotient in it)
+
+ .globl imod
+
+imod:
+ cwd
+ idiv bx
+ mov ax,dx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function imodu */
+
+#ifdef L___imodu
+#asm
+
+| imodu.s
+| imodu doesn`t preserve dx (returns quotient in it)
+
+ .globl imodu
+
+imodu:
+ xor dx,dx
+ div bx
+ mov ax,dx ! instruction queue full so xchg slower
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function imul */
+
+#ifdef L___imul
+#asm
+
+| imul.s
+| imul_, imul_u don`t preserve dx
+
+ .globl imul_
+ .globl imul_u
+
+imul_:
+imul_u:
+ imul bx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function isl */
+
+#ifdef L___isl
+#asm
+
+| isl.s
+| isl, islu don`t preserve cl
+
+ .globl isl
+ .globl islu
+
+isl:
+islu:
+ mov cl,bl
+ shl ax,cl
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function isr */
+
+#ifdef L___isr
+#asm
+
+| isr.s
+| isr doesn`t preserve cl
+
+ .globl isr
+
+isr:
+ mov cl,bl
+ sar ax,cl
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function isru */
+
+#ifdef L___isru
+#asm
+
+| isru.s
+| isru doesn`t preserve cl
+
+ .globl isru
+
+isru:
+ mov cl,bl
+ shr ax,cl
+ ret
+#endasm
+#endif
+
+#endif
diff --git a/libc-0.0.4/bcc/bcc_io.c b/libc-0.0.4/bcc/bcc_io.c
new file mode 100644
index 0000000..af5dfd2
--- /dev/null
+++ b/libc-0.0.4/bcc/bcc_io.c
@@ -0,0 +1,189 @@
+/************************************************************************/
+/* This file contains the BCC compiler helper functions */
+/* Miscellaneous obsolete junk
+ * __inport.o __inportb.o __outport.o __outportb.o __peekb.o __peekw.o
+ * __pokeb.o __pokew.o
+ */
+
+#ifdef __AS368_16__
+#if !__FIRST_ARG_IN_AX__
+#asm
+ .text ! This is common to all.
+ .even
+#endasm
+
+/************************************************************************/
+/* Function inport */
+
+#ifdef L___inport
+#asm
+
+| int inport( int port );
+| reads a word from the i/o port port and returns it
+
+ .globl _inport
+_inport:
+ pop bx
+ pop dx
+ dec sp
+ dec sp
+ inw
+ jmp bx
+#endasm
+#endif
+
+/************************************************************************/
+/* Function inportb */
+
+#ifdef L___inportb
+#asm
+
+| int inportb( int port );
+| reads a byte from the i/o port port and returns it
+
+ .globl _inportb
+_inportb:
+ pop bx
+ pop dx
+ dec sp
+ dec sp
+ in
+ sub ah,ah
+ jmp bx
+#endasm
+#endif
+
+/************************************************************************/
+/* Function outport */
+
+#ifdef L___outport
+#asm
+
+| void outport( int port, int value );
+| writes the word value to the i/o port port
+
+ .globl _outport
+_outport:
+ pop bx
+ pop dx
+ pop ax
+ sub sp,*4
+ outw
+ jmp bx
+#endasm
+#endif
+
+/************************************************************************/
+/* Function outportb */
+
+#ifdef L___outportb
+#asm
+
+| void oportb( int port, char value );
+| writes the byte value to the i/o port port
+| this would be outportb except for feeble linkers
+
+ .globl _oportb
+_oportb:
+ pop bx
+ pop dx
+ pop ax
+ sub sp,*4
+ out
+ jmp bx
+#endasm
+#endif
+
+/************************************************************************/
+/* Function peekb */
+
+#ifdef L___peekb
+#asm
+
+| int peekb( unsigned segment, char *offset );
+| returns the (unsigned) byte at the far pointer segment:offset
+
+ .define _peekb
+_peekb:
+ mov cx,ds
+ pop dx
+ pop ds
+ pop bx
+ sub sp,*4
+ movb al,(bx)
+ subb ah,ah
+ mov ds,cx
+ jmp dx
+#endasm
+#endif
+
+/************************************************************************/
+/* Function peekw */
+
+#ifdef L___peekw
+#asm
+
+| int peekw( unsigned segment, int *offset );
+| returns the word at the far pointer segment:offset
+
+ .define _peekw
+_peekw:
+ mov cx,ds
+ pop dx
+ pop ds
+ pop bx
+ sub sp,*4
+ mov ax,(bx)
+ mov ds,cx
+ jmp dx
+#endasm
+#endif
+
+/************************************************************************/
+/* Function pokeb */
+
+#ifdef L___pokeb
+#asm
+
+| void pokeb( unsigned segment, char *offset, char value );
+| writes the byte value at the far pointer segment:offset
+
+ .define _pokeb
+_pokeb:
+ mov cx,ds
+ pop dx
+ pop ds
+ pop bx
+ pop ax
+ sub sp,*6
+ movb (bx),al
+ mov ds,cx
+ jmp dx
+#endasm
+#endif
+
+/************************************************************************/
+/* Function pokew */
+
+#ifdef L___pokew
+#asm
+
+| void pokew( unsigned segment, int *offset, int value );
+| writes the word value at the far pointer segment:offset
+
+ .define _pokew
+_pokew:
+ mov cx,ds
+ pop dx
+ pop ds
+ pop bx
+ pop ax
+ sub sp,*6
+ mov (bx),ax
+ mov ds,cx
+ jmp dx
+#endasm
+#endif
+
+#endif /* !__FIRST_ARG_IN_AX__ */
+#endif
diff --git a/libc-0.0.4/bcc/bcc_long.c b/libc-0.0.4/bcc/bcc_long.c
new file mode 100644
index 0000000..4b6ceae
--- /dev/null
+++ b/libc-0.0.4/bcc/bcc_long.c
@@ -0,0 +1,479 @@
+/************************************************************************/
+/* This file contains the BCC compiler helper functions */
+/* Support for long arithmetic on little-endian (normal) longs
+ * __laddl.o __landl.o __lcmpl.o __lcoml.o __ldecl.o __ldivl.o __ldivul.o
+ * __leorl.o __lincl.o __lmodl.o __lmodul.o __lmull.o __lnegl.o __lorl.o
+ * __lsll.o __lsrl.o __lsrul.o __lsubl.o __ltstl.o
+ */
+
+#ifdef __AS386_16__
+#asm
+ .text ! This is common to all.
+ .even
+#endasm
+
+/************************************************************************/
+/* Function laddl */
+
+#ifdef L___laddl
+#asm
+
+| laddl.s
+
+ .globl laddl
+ .globl laddul
+
+laddl:
+laddul:
+ add ax,[di]
+ adc bx,2[di]
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function landl */
+
+#ifdef L___landl
+#asm
+
+| landl.s
+
+ .globl landl
+ .globl landul
+
+landl:
+landul:
+ and ax,[di]
+ and bx,2[di]
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lcmpl */
+
+#ifdef L___lcmpl
+#asm
+
+| lcmpl.s
+| lcmpl, lcmpul don`t preserve bx
+
+ .globl lcmpl
+ .globl lcmpul
+
+lcmpl:
+lcmpul:
+ sub bx,2[di]
+ je LCMP_NOT_SURE
+ ret
+
+ .even
+
+LCMP_NOT_SURE:
+ cmp ax,[di]
+ jb LCMP_B_AND_LT
+ jge LCMP_EXIT
+
+ inc bx
+LCMP_EXIT:
+ ret
+
+ .even
+
+LCMP_B_AND_LT:
+ dec bx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lcoml */
+
+#ifdef L___lcoml
+#asm
+
+| lcoml.s
+
+ .globl lcoml
+ .globl lcomul
+
+lcoml:
+lcomul:
+ not ax
+ not bx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function ldecl */
+
+#ifdef L___ldecl
+#asm
+
+| ldecl.s
+
+ .globl ldecl
+ .globl ldecul
+
+ldecl:
+ldecul:
+ cmp word ptr [bx],*0
+ je LDEC_BOTH
+ dec word ptr [bx]
+ ret
+
+ .even
+
+LDEC_BOTH:
+ dec word ptr [bx]
+ dec word ptr 2[bx]
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function ldivl */
+
+#ifdef L___ldivl
+#asm
+
+| ldivl.s
+| bx:ax / 2(di):(di), quotient bx:ax, remainder di:cx, dx not preserved
+
+ .globl ldivl
+ .extern ldivmod
+
+ldivl:
+ mov cx,[di]
+ mov di,2[di]
+ call ldivmod
+ xchg ax,cx
+ xchg bx,di
+ ret
+
+#endasm
+#endif
+
+/************************************************************************/
+/* Function ldivul */
+
+#ifdef L___ldivul
+#asm
+
+| ldivul.s
+| unsigned bx:ax / 2(di):(di), quotient bx:ax,remainder di:cx, dx not preserved
+
+ .globl ldivul
+ .extern ludivmod
+
+ldivul:
+ mov cx,[di]
+ mov di,2[di]
+ call ludivmod
+ xchg ax,cx
+ xchg bx,di
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function leorl */
+
+#ifdef L___leorl
+#asm
+
+| leorl.s
+
+ .globl leorl
+ .globl leorul
+
+leorl:
+leorul:
+ xor ax,[di]
+ xor bx,2[di]
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lincl */
+
+#ifdef L___lincl
+#asm
+
+| lincl.s
+
+ .globl lincl
+ .globl lincul
+
+lincl:
+lincul:
+ inc word ptr [bx]
+ je LINC_HIGH_WORD
+ ret
+
+ .even
+
+LINC_HIGH_WORD:
+ inc word ptr 2[bx]
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lmodl */
+
+#ifdef L___lmodl
+#asm
+
+| lmodl.s
+| bx:ax % 2(di):(di), remainder bx:ax, quotient di:cx, dx not preserved
+
+ .globl lmodl
+ .extern ldivmod
+
+lmodl:
+ mov cx,[di]
+ mov di,2[di]
+ call ldivmod
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lmodul */
+
+#ifdef L___lmodul
+#asm
+
+| lmodul.s
+| unsigned bx:ax / 2(di):(di), remainder bx:ax,quotient di:cx, dx not preserved
+
+ .globl lmodul
+ .extern ludivmod
+
+lmodul:
+ mov cx,[di]
+ mov di,2[di]
+ call ludivmod
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lmull */
+
+#ifdef L___lmull
+#asm
+
+| lmull.s
+| lmull, lmulul don`t preserve cx, dx
+
+ .globl lmull
+ .globl lmulul
+
+lmull:
+lmulul:
+ mov cx,ax
+ mul word ptr 2[di]
+ xchg ax,bx
+ mul word ptr [di]
+ add bx,ax
+ mov ax,ptr [di]
+ mul cx
+ add bx,dx
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lnegl */
+
+#ifdef L___lnegl
+#asm
+
+| lnegl.s
+
+ .globl lnegl
+ .globl lnegul
+
+lnegl:
+lnegul:
+ neg bx
+ neg ax
+ sbb bx,*0
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lorl */
+
+#ifdef L___lorl
+#asm
+
+| lorl.s
+
+ .globl lorl
+ .globl lorul
+
+lorl:
+lorul:
+ or ax,[di]
+ or bx,2[di]
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lsll */
+
+#ifdef L___lsll
+#asm
+
+| lsll.s
+| lsll, lslul don`t preserve cx
+
+ .globl lsll
+ .globl lslul
+
+lsll:
+lslul:
+ mov cx,di
+ jcxz LSL_EXIT
+ cmp cx,*32
+ jae LSL_ZERO
+LSL_LOOP:
+ shl ax,*1
+ rcl bx,*1
+ loop LSL_LOOP
+LSL_EXIT:
+ ret
+
+ .even
+
+LSL_ZERO:
+ xor ax,ax
+ mov bx,ax
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lsrl */
+
+#ifdef L___lsrl
+#asm
+
+| lsrl.s
+| lsrl doesn`t preserve cx
+
+ .globl lsrl
+
+lsrl:
+ mov cx,di
+ jcxz LSR_EXIT
+ cmp cx,*32
+ jae LSR_SIGNBIT
+LSR_LOOP:
+ sar bx,*1
+ rcr ax,*1
+ loop LSR_LOOP
+LSR_EXIT:
+ ret
+
+ .even
+
+LSR_SIGNBIT:
+ mov cx,*32
+ j LSR_LOOP
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lsrul */
+
+#ifdef L___lsrul
+#asm
+
+| lsrul.s
+| lsrul doesn`t preserve cx
+
+ .globl lsrul
+
+lsrul:
+ mov cx,di
+ jcxz LSRU_EXIT
+ cmp cx,*32
+ jae LSRU_ZERO
+LSRU_LOOP:
+ shr bx,*1
+ rcr ax,*1
+ loop LSRU_LOOP
+LSRU_EXIT:
+ ret
+
+ .even
+
+LSRU_ZERO:
+ xor ax,ax
+ mov bx,ax
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function lsubl */
+
+#ifdef L___lsubl
+#asm
+
+| lsubl.s
+
+ .globl lsubl
+ .globl lsubul
+
+lsubl:
+lsubul:
+ sub ax,[di]
+ sbb bx,2[di]
+ ret
+#endasm
+#endif
+
+/************************************************************************/
+/* Function ltstl */
+
+#ifdef L___ltstl
+#asm
+
+| ltstl.s
+| ltstl, ltstul don`t preserve bx
+
+ .globl ltstl
+ .globl ltstul
+
+ltstl:
+ltstul:
+ test bx,bx
+ je LTST_NOT_SURE
+ ret
+
+ .even
+
+LTST_NOT_SURE:
+ test ax,ax
+ js LTST_FIX_SIGN
+ ret
+
+ .even
+
+LTST_FIX_SIGN:
+ inc bx
+ ret
+#endasm
+#endif
+
+#endif
diff --git a/libc-0.0.4/bcc/heap.c b/libc-0.0.4/bcc/heap.c
new file mode 100644
index 0000000..af4e898
--- /dev/null
+++ b/libc-0.0.4/bcc/heap.c
@@ -0,0 +1,116 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/****************************************************************************/
+
+#ifdef L_errno
+int errno = 0; /* libc error value */
+#endif
+
+/****************************************************************************/
+
+#ifdef L___brk_addr
+#ifdef __AS386_16__
+#asm
+.data
+export brk_addr
+brk_addr: .word __end ! This holds the current return for sbrk(0)
+.text
+#endasm
+#endif
+#endif
+
+/****************************************************************************/
+
+#ifdef L_sbrk
+#ifdef __AS386_16__
+int sbrk(brk_off)
+unsigned int brk_off;
+{
+#asm
+ mov bx,sp
+#if !__FIRST_ARG_IN_AX__
+ mov ax,[bx+2] ! Fetch the requested value
+#endif
+ test ax,ax
+ jnz has_change
+ mov ax,[brk_addr] ! Simple one; read current - can`t fail.
+ jmp eof
+
+has_change:
+ js go_down
+ add ax,[brk_addr] ! Goin up!
+ jc Enomem
+ sub bx,#64 ! Safety space
+ cmp bx,ax ! Too close ?
+ jb Enomem
+
+sbrk_ok:
+#ifndef __MSDOS__
+ push ax ! MSDOS `kernel` doesn`t care
+ call ___brk ! Tell the kernel
+ test ax,ax
+ pop ax ! ASSUME ___brk doesn`t alter stack!
+ jnz Enomem ! Ugh! kernel didn`t like the idea!
+#endif
+ xchg [brk_addr],ax ! Save away new val
+ jmp eof ! Return it
+go_down:
+ add ax,[brk_addr]
+ jnc Enomem
+ cmp ax,#__end
+ jae sbrk_ok
+
+Enomem:
+ mov ax,#12 ! This should be ENOMEM not a magic.
+ mov [_errno],ax
+ mov ax,#-1
+eof:
+#endasm
+}
+#endif
+#endif
+
+/****************************************************************************/
+
+#ifdef L_brk
+#ifdef __AS386_16__
+int
+brk(new_brk)
+void * new_brk;
+{
+#asm
+ mov bx,sp
+#if !__FIRST_ARG_IN_AX__
+ mov ax,[bx+2] ! Fetch the requested value
+#endif
+ sub bx,#64 ! Safety space
+ cmp bx,ax ! Too close ?
+ jb Enomem
+ cmp ax,#__end
+ jae brk_ok
+Enomem:
+ mov ax,#12 ! This should be ENOMEM not a magic.
+ mov [_errno],ax
+ mov ax,#-1
+ ret
+brk_ok:
+#ifndef __MSDOS__
+ push ax
+ call ___brk ! Tell the kernel
+ test ax,ax
+ pop bx ! ASSUME ___brk doesn`t alter stack!
+ jnz Enomem ! Ugh! kernel didn`t like the idea!
+ mov [brk_addr],bx ! Save away new val
+#else
+ mov [brk_addr],ax ! MSDOS `kernel` doesn`t care
+ mov ax,#0
+#endif
+#endasm
+}
+#endif
+#endif
+
+/****************************************************************************/
diff --git a/libc-0.0.4/crt0.c b/libc-0.0.4/crt0.c
new file mode 100644
index 0000000..71ca6bc
--- /dev/null
+++ b/libc-0.0.4/crt0.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#if defined(__AS386_16__) || defined(__AS386_32__)
+#define CRT0_OK
+/*
+ * Change of aim here, to allow easy alteration for generation of COM files
+ * this code has been moved into libc. This means only the linker needs to
+ * to be told to fetch a different libc the crt0 is unaltered.
+ *
+ * This also allows us to deal with __FIRST_ARG_IN_AX__ and __CALLER_SAVES__
+ * in the same way.
+ */
+
+#asm
+.text
+entry startup ! Crt0 startup
+startup:
+ br ___cstartup
+export no_op
+no_op: ! Generic no operation call (the byte was free :-) )
+ ret
+
+ loc 1 ! Segment 1 is where the pointers to the autostart
+ZP_safety: ! functions are stored.
+ .word 0 ! But first some zeros to avoid null pointer writes.
+ .word 0
+ .word 0
+ .word 0
+export auto_start
+auto_start:
+
+#endasm
+#endif /* __AS386_16__ or __AS386_32__ */
+
+#if defined(__GNUC__) && defined(__i386__)
+#define CRT0_OK
+
+#ifdef __ELF__
+__asm__(".globl __startup\n__startup:");
+__asm__("jmp __cstartup");
+__asm__(".globl __no_op\n__no_op:");
+__asm__("ret");
+#else
+__asm__(".globl startup\nstartup:");
+__asm__("jmp ___cstartup");
+__asm__(".globl no_op\nno_op:");
+__asm__("ret");
+#endif
+
+#endif /* defined(__GNUC__) && defined(__i386__) */
+
+#ifndef CRT0_OK
+#error You are not going to get far without crt0.o!
+#endif
diff --git a/libc-0.0.4/crt0.o b/libc-0.0.4/crt0.o
new file mode 100644
index 0000000..e43705b
--- /dev/null
+++ b/libc-0.0.4/crt0.o
Binary files differ
diff --git a/libc-0.0.4/error/Config b/libc-0.0.4/error/Config
new file mode 100644
index 0000000..1f384b7
--- /dev/null
+++ b/libc-0.0.4/error/Config
@@ -0,0 +1,2 @@
+
+error: Unix error functions
diff --git a/libc-0.0.4/error/Makefile b/libc-0.0.4/error/Makefile
new file mode 100644
index 0000000..885f2b8
--- /dev/null
+++ b/libc-0.0.4/error/Makefile
@@ -0,0 +1,17 @@
+# Copyright (C) 1996 Robert de Bath <robert@debath.thenet.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+OBJ=error.o sys_errlist.o perror.o sys_siglist.o __assert.o
+
+all: $(OBJ)
+
+$(LIBC): $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f $(OBJ) libc.a
diff --git a/libc-0.0.4/error/README b/libc-0.0.4/error/README
new file mode 100644
index 0000000..02c123f
--- /dev/null
+++ b/libc-0.0.4/error/README
@@ -0,0 +1,10 @@
+Copyright (C) 1996 Robert de Bath <robert@debath.thenet.co.uk>
+This file is part of the Linux-8086 C library and is distributed
+under the GNU Library General Public License.
+
+These routines assume the existance of a file /usr/lib/liberror.txt,
+this file contains the actual error messages. One useful feature,
+the language of the error messages can be easily changed.
+
+
+-Robert
diff --git a/libc-0.0.4/error/__assert.c b/libc-0.0.4/error/__assert.c
new file mode 100644
index 0000000..bcf04e8
--- /dev/null
+++ b/libc-0.0.4/error/__assert.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <unistd.h>
+
+static void errput(str)
+const char * str;
+{
+ write(2, str, strlen(str));
+}
+
+void
+__assert(assertion, filename, linenumber)
+const char * assertion;
+const char * filename;
+int linenumber;
+{
+ errput("Failed assertion '");
+ errput(assertion);
+ errput("' in file ");
+ errput(filename);
+ errput(" at line ");
+ errput(itoa(linenumber));
+ errput(".\n");
+ abort();
+}
diff --git a/libc-0.0.4/error/error.c b/libc-0.0.4/error/error.c
new file mode 100644
index 0000000..3695719
--- /dev/null
+++ b/libc-0.0.4/error/error.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 1996 Robert de Bath <robert@debath.thenet.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+#include <string.h>
+
+char **__sys_errlist =0;
+int __sys_nerr = 0;
+
+char *
+strerror(err)
+int err;
+{
+ int fd;
+ static char retbuf[80];
+ char inbuf[256];
+ int cc;
+ int bufoff = 0;
+
+ if( __sys_nerr )
+ {
+ if( err < 0 || err >= __sys_nerr ) goto unknown;
+ return __sys_errlist[err];
+ }
+
+ if( err <= 0 ) goto unknown; /* NB the <= allows comments in the file */
+ fd = open("/usr/lib/liberror.txt", 0);
+ if( fd < 0 ) goto unknown;
+
+ while( (cc=read(fd, inbuf, sizeof(inbuf))) > 0 )
+ {
+ int i;
+ for(i=0; i<cc; i++)
+ {
+ if( inbuf[i] == '\n' )
+ {
+ retbuf[bufoff] = '\0';
+ if( err == atoi(retbuf) )
+ {
+ char * p = strchr(retbuf, ' ');
+ if( p == 0 ) goto unknown;
+ while(*p == ' ') p++;
+ close(fd);
+ return p;
+ }
+ bufoff = 0;
+ }
+ else if( bufoff < sizeof(retbuf)-1 )
+ retbuf[bufoff++] = inbuf[i];
+ }
+ }
+unknown:;
+ if( fd >= 0 ) close(fd);
+ strcpy(retbuf, "Unknown error ");
+ strcpy(retbuf+14, itoa(err));
+ return retbuf;
+}
diff --git a/libc-0.0.4/error/liberror.txt b/libc-0.0.4/error/liberror.txt
new file mode 100644
index 0000000..2b510bd
--- /dev/null
+++ b/libc-0.0.4/error/liberror.txt
@@ -0,0 +1,121 @@
+1 Operation not permitted
+2 No such file or directory
+3 No such process
+4 Interrupted system call
+5 I/O error
+6 No such device or address
+7 Arg list too long
+8 Exec format error
+9 Bad file number
+10 No child processes
+11 Try again
+12 Out of memory
+13 Permission denied
+14 Bad address
+15 Block device required
+16 Device or resource busy
+17 File exists
+18 Cross-device link
+19 No such device
+20 Not a directory
+21 Is a directory
+22 Invalid argument
+23 File table overflow
+24 Too many open files
+25 Not a typewriter
+26 Text file busy
+27 File too large
+28 No space left on device
+29 Illegal seek
+30 Read-only file system
+31 Too many links
+32 Broken pipe
+33 Math argument out of domain of func
+34 Math result not representable
+35 Resource deadlock would occur
+36 File name too long
+37 No record locks available
+38 Function not implemented
+39 Directory not empty
+40 Too many symbolic links encountered
+41 Operation would block
+42 No message of desired type
+43 Identifier removed
+44 Channel number out of range
+45 Level 2 not synchronized
+46 Level 3 halted
+47 Level 3 reset
+48 Link number out of range
+49 Protocol driver not attached
+50 No CSI structure available
+51 Level 2 halted
+52 Invalid exchange
+53 Invalid request descriptor
+54 Exchange full
+55 No anode
+56 Invalid request code
+57 Invalid slot
+58 File locking deadlock error
+59 Bad font file format
+60 Device not a stream
+61 No data available
+62 Timer expired
+63 Out of streams resources
+64 Machine is not on the network
+65 Package not installed
+66 Object is remote
+67 Link has been severed
+68 Advertise error
+69 Srmount error
+70 Communication error on send
+71 Protocol error
+72 Multihop attempted
+73 RFS specific error
+74 Not a data message
+75 Value too large for defined data type
+76 Name not unique on network
+77 File descriptor in bad state
+78 Remote address changed
+79 Can not access a needed shared library
+80 Accessing a corrupted shared library
+81 .lib section in a.out corrupted
+82 Attempting to link in too many shared libraries
+83 Cannot exec a shared library directly
+84 Illegal byte sequence
+85 Interrupted system call should be restarted
+86 Streams pipe error
+87 Too many users
+88 Socket operation on non-socket
+89 Destination address required
+90 Message too long
+91 Protocol wrong type for socket
+92 Protocol not available
+93 Protocol not supported
+94 Socket type not supported
+95 Operation not supported on transport endpoint
+96 Protocol family not supported
+97 Address family not supported by protocol
+98 Address already in use
+99 Cannot assign requested address
+100 Network is down
+101 Network is unreachable
+102 Network dropped connection because of reset
+103 Software caused connection abort
+104 Connection reset by peer
+105 No buffer space available
+106 Transport endpoint is already connected
+107 Transport endpoint is not connected
+108 Cannot send after transport endpoint shutdown
+109 Too many references: cannot splice
+110 Connection timed out
+111 Connection refused
+112 Host is down
+113 No route to host
+114 Operation already in progress
+115 Operation now in progress
+116 Stale NFS file handle
+117 Structure needs cleaning
+118 Not a XENIX named type file
+119 No XENIX semaphores available
+120 Is a named type file
+121 Remote I/O error
diff --git a/libc-0.0.4/error/perror.c b/libc-0.0.4/error/perror.c
new file mode 100644
index 0000000..f9b0965
--- /dev/null
+++ b/libc-0.0.4/error/perror.c
@@ -0,0 +1,19 @@
+
+#include <errno.h>
+
+void
+perror(str)
+__const char * str;
+{
+ register char * ptr;
+ if(str)
+ {
+ write(2, str, strlen(str));
+ write(2, ": ", 2);
+ }
+ else write(2, "perror: ", 8);
+
+ ptr = strerror(errno);
+ write(2, ptr, strlen(ptr));
+ write(2, "\n", 1);
+}
diff --git a/libc-0.0.4/error/sys_errlist.c b/libc-0.0.4/error/sys_errlist.c
new file mode 100644
index 0000000..1d9e65b
--- /dev/null
+++ b/libc-0.0.4/error/sys_errlist.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 1996 Robert de Bath <robert@debath.thenet.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/* This is a flash way of auto-initing the error array from an external file
+ * I wouldn't be surprised tho if it's a lot better just to hard code the
+ * error messages into the array.
+ *
+ * Of course the best of all is to use strerror().
+ */
+
+#ifdef __AS386_16__
+#define NR_ERRORS 128
+
+extern char **__sys_errlist;
+extern int __sys_nerr;
+
+char *sys_errlist[NR_ERRORS];
+int sys_nerr = NR_ERRORS;
+
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word _init_vars ! Pointer to the autorun function
+ .word no_op ! Space filler cause segs are padded to 4 bytes.
+ .text ! So the function after is also in the correct seg.
+#endasm
+
+static void init_vars()
+{
+ char inbuf[256];
+ char errbuf[80];
+ int i, cc, fd, err, len, bufoff=0;
+ char * ptr;
+
+ fd = open("/usr/lib/liberror.txt", 0);
+ if( fd < 0 ) return;
+
+ for(i=0; i<NR_ERRORS; i++) sys_errlist[i] = "Unknown error";
+
+ while( (cc=read(fd, inbuf, sizeof(inbuf))) > 0 )
+ {
+ for(i=0; i<cc; i++)
+ {
+ if( inbuf[i] == '\n' )
+ {
+ errbuf[bufoff] = '\0';
+ err = atoi(errbuf);
+ ptr = strchr(errbuf, ' ');
+ if( ptr && err > 0 && err < NR_ERRORS )
+ {
+ while(*ptr == ' ') ptr++;
+ len = strlen(ptr)+1;
+ sys_errlist[err] = (void*)sbrk(len);
+ if( (int)sys_errlist[err] == -1 )
+ {
+ sys_errlist[err] == "";
+ break;
+ }
+ memcpy(sys_errlist[err], ptr, len);
+ }
+ bufoff = 0;
+ }
+ else if( bufoff < sizeof(errbuf)-1 )
+ errbuf[bufoff++] = inbuf[i];
+ }
+ }
+ close(fd);
+
+ __sys_errlist = sys_errlist;
+ __sys_nerr = sys_nerr = NR_ERRORS;
+}
+
+#endif /* __AS386_16__ */
diff --git a/libc-0.0.4/error/sys_siglist.c b/libc-0.0.4/error/sys_siglist.c
new file mode 100644
index 0000000..8f502f6
--- /dev/null
+++ b/libc-0.0.4/error/sys_siglist.c
@@ -0,0 +1,38 @@
+
+#include <signal.h>
+
+__const char * __const sys_siglist[NSIG] =
+{
+ "Unknown signal",
+ "Hangup",
+ "Interrupt",
+ "Quit",
+ "Illegal instruction",
+ "Trace/breakpoint trap",
+ "IOT trap/Abort",
+ "Bus error",
+ "Floating point exception",
+ "Killed",
+ "User defined signal 1",
+ "Segmentation fault",
+ "User defined signal 2",
+ "Broken pipe",
+ "Alarm clock",
+ "Terminated",
+ "Stack fault",
+ "Child exited",
+ "Continued",
+ "Stopped (signal)",
+ "Stopped",
+ "Stopped (tty input)",
+ "Stopped (tty output)",
+ "Possible I/O",
+ "CPU time limit exceeded",
+ "File size limit exceeded",
+ "Virtual time alarm",
+ "Profile signal",
+ "Window size changed",
+ "File lock lost",
+ "Power failure",
+ "Unused signal"
+};
diff --git a/libc-0.0.4/grp/Makefile b/libc-0.0.4/grp/Makefile
new file mode 100644
index 0000000..9c01e23
--- /dev/null
+++ b/libc-0.0.4/grp/Makefile
@@ -0,0 +1,41 @@
+# Copyright (C) 1996 Nat Friedman <ndf@aleph1.mit.edu>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+ifeq ($(PLATFORM),i386-Linux)
+CFLAGS+=$(WALL)
+else # ifeq ($(PLATFORM),i86-ELKS)
+CFLAGS=$(CCFLAGS) $(LIBDEFS) -ansi
+endif
+
+GSRC=__getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c initgroups.c \
+ config-grp.h
+GOBJ=__getgrent.o grent.o getgrnam.o getgrgid.o fgetgrent.o initgroups.o
+
+all: $(GOBJ)
+
+%.o: %.c config-grp.h
+ $(CC) $(CFLAGS) -o $@ $< -c
+
+$(LIBC): $(GOBJ)
+ ar r ../$(LIBC) $(GOBJ)
+ @touch libc.a
+
+test: test_grp.c libgrp.a
+ $(CC) $(CFLAGS) test_grp.c -o test_grp -L -lgrp # -static
+
+libgrp: libgrp.a
+
+libgrp.a: $(GOBJ)
+ ar r libgrp.a $(GOBJ)
+ ranlib libgrp.a
+
+clean:
+ rm -f $(GOBJ) libc.a libgrp.a
+
+
+
+
diff --git a/libc-0.0.4/grp/__getgrent.c b/libc-0.0.4/grp/__getgrent.c
new file mode 100644
index 0000000..ed46163
--- /dev/null
+++ b/libc-0.0.4/grp/__getgrent.c
@@ -0,0 +1,168 @@
+/*
+ * __getgrent.c - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <grp.h>
+#include "config-grp.h"
+
+/*
+ * This is the core group-file read function. It behaves exactly like
+ * getgrent() except that it is passed a file descriptor, and getgrent()
+ * is just a wrapper for this function.
+ */
+struct group *
+__getgrent(int grp_fd)
+{
+#ifndef GR_SCALE_DYNAMIC
+ static char line_buff[GR_MAX_LINE_LEN];
+ static char * members[GR_MAX_MEMBERS];
+#else
+ static char * line_buff = NULL;
+ static char ** members = NULL;
+#endif
+ static struct group group;
+ register char * ptr;
+ char * field_begin;
+ char * endptr;
+ short member_num;
+ short line_index;
+
+
+ /* We use the restart label to handle malformatted lines */
+restart:
+ line_index=0;
+
+#ifndef GR_SCALE_DYNAMIC
+ *line_buff='\0';
+ /* Read the line into the static buffer */
+ while (1)
+ {
+ if (read(grp_fd, &line_buff[line_index], 1)<=0)
+ return NULL;
+ if (*line_buff=='#' || *line_buff==' ' || *line_buff=='\n' ||
+ *line_buff=='\t')
+ {
+ while (line_buff[line_index]!='\n' &&
+ read(grp_fd, &line_buff[line_index], 1)==1);
+ goto restart;
+ }
+ if (line_buff[line_index]=='\n')
+ {
+ line_buff[line_index]='\0';
+ break;
+ }
+ line_index++;
+ if (line_index==GR_MAX_LINE_LEN)
+ {
+ while (line_buff[line_index]!='\n' &&
+ read(grp_fd, &line_buff[line_index], 1)==1);
+ return NULL;
+ }
+ }
+
+#else /* !GR_SCALE_DYNAMIC */
+ line_buff=realloc(line_buff, 1);
+ while (1)
+ {
+ if (read(grp_fd, &line_buff[line_index], 1)<=0)
+ return NULL;
+ if (*line_buff=='#' || *line_buff==' ' || *line_buff=='\n' ||
+ *line_buff=='\t')
+ {
+ while (line_buff[line_index]!='\n' &&
+ read(grp_fd, &line_buff[line_index], 1)==1);
+ goto restart;
+ }
+ if (line_buff[line_index]=='\n')
+ {
+ line_buff[line_index]='\0';
+ break;
+ }
+ line_index++;
+ line_buff=realloc(line_buff, line_index+1);
+ }
+#endif /* GR_SCALE_DYNAMIC */
+
+ /* Now parse the line */
+ group.gr_name=line_buff;
+ ptr=strchr(line_buff, ':');
+ if (ptr==NULL) goto restart;
+ *ptr++='\0';
+
+ group.gr_passwd=ptr;
+ ptr=strchr(ptr, ':');
+ if (ptr==NULL) goto restart;
+ *ptr++='\0';
+
+ field_begin=ptr;
+ ptr=strchr(ptr, ':');
+ if (ptr==NULL) goto restart;
+ *ptr++='\0';
+
+ group.gr_gid=(gid_t) strtoul(field_begin, &endptr, 10);
+ if (*endptr!='\0') goto restart;
+
+ member_num=0;
+ field_begin=ptr;
+
+#ifndef GR_SCALE_DYNAMIC
+ while ((ptr=strchr(ptr, ','))!=NULL)
+ {
+ *ptr='\0';
+ ptr++;
+ members[member_num]=field_begin;
+ field_begin=ptr;
+ member_num++;
+ }
+ if (*field_begin=='\0')
+ members[member_num]=NULL;
+ else
+ {
+ members[member_num]=field_begin;
+ members[member_num+1]=NULL;
+ }
+#else /* !GR_SCALE_DYNAMIC */
+ if (members!=NULL)
+ free (members);
+ members=(char **) malloc(1*sizeof(char *));
+ while ((ptr=strchr(ptr, ','))!=NULL)
+ {
+ *ptr='\0';
+ ptr++;
+ members[member_num]=field_begin;
+ field_begin=ptr;
+ member_num++;
+ members=(char **)realloc((void *)members, (member_num+1)*sizeof(char *));
+ }
+ if (*field_begin=='\0')
+ members[member_num]=NULL;
+ else
+ {
+ members[member_num]=field_begin;
+ members[member_num+1]=NULL;
+ }
+#endif /* GR_SCALE_DYNAMIC */
+
+ group.gr_mem=members;
+ return &group;
+}
diff --git a/libc-0.0.4/grp/config-grp.h b/libc-0.0.4/grp/config-grp.h
new file mode 100644
index 0000000..337d54b
--- /dev/null
+++ b/libc-0.0.4/grp/config-grp.h
@@ -0,0 +1,65 @@
+/*
+ * config-grp.h - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#ifndef _CONFIG_GRP_H
+#define _CONFIG_GRP_H
+
+/*
+ * Define GR_SCALE_DYNAMIC if you want grp to dynamically scale its read buffer
+ * so that lines of any length can be used. On very very small systems,
+ * you may want to leave this undefined becasue it will make the grp functions
+ * somewhat larger (because of the inclusion of malloc and the code necessary).
+ * On larger systems, you will want to define this, because grp will _not_
+ * deal with long lines gracefully (they will be skipped).
+ */
+#define GR_SCALE_DYNAMIC
+
+#ifndef GR_SCALE_DYNAMIC
+/*
+ * If scaling is not dynamic, the buffers will be statically allocated, and
+ * maximums must be chosen. GR_MAX_LINE_LEN is the maximum number of
+ * characters per line in the group file. GR_MAX_MEMBERS is the maximum
+ * number of members of any given group.
+ */
+#define GR_MAX_LINE_LEN 128
+/* GR_MAX_MEMBERS = (GR_MAX_LINE_LEN-(24+3+6))/9 */
+#define GR_MAX_MEMBERS 11
+
+#endif /* !GR_SCALE_DYNAMIC */
+
+
+/*
+ * Define GR_DYNAMIC_GROUP_LIST to make initgroups() dynamically allocate
+ * space for it's GID array before calling setgroups(). This is probably
+ * unnecessary scalage, so it's undefined by default.
+ */
+#undef GR_DYNAMIC_GROUP_LIST
+
+#ifndef GR_DYNAMIC_GROUP_LIST
+/*
+ * GR_MAX_GROUPS is the size of the static array initgroups() uses for
+ * its static GID array if GR_DYNAMIC_GROUP_LIST isn't defined.
+ */
+#define GR_MAX_GROUPS 64
+
+#endif /* !GR_DYNAMIC_GROUP_LIST */
+
+#endif /* !_CONFIG_GRP_H */
diff --git a/libc-0.0.4/grp/fgetgrent.c b/libc-0.0.4/grp/fgetgrent.c
new file mode 100644
index 0000000..800236f
--- /dev/null
+++ b/libc-0.0.4/grp/fgetgrent.c
@@ -0,0 +1,35 @@
+/*
+ * fgetgrent.c - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <grp.h>
+
+struct group *
+fgetgrent(FILE * file)
+{
+ if (file==NULL)
+ {
+ errno=EINTR;
+ return NULL;
+ }
+
+ return __getgrent(fileno(file));
+}
diff --git a/libc-0.0.4/grp/getgrgid.c b/libc-0.0.4/grp/getgrgid.c
new file mode 100644
index 0000000..c1dd20e
--- /dev/null
+++ b/libc-0.0.4/grp/getgrgid.c
@@ -0,0 +1,48 @@
+/*
+ * getgrgid.c - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <grp.h>
+
+struct group *
+getgrgid(const gid_t gid)
+{
+ struct group * group;
+ int grp_fd;
+
+ if ((grp_fd=open("/etc/group", O_RDONLY))<0)
+ return NULL;
+
+ while ((group=__getgrent(grp_fd))!=NULL)
+ if (group->gr_gid==gid)
+ {
+ close(grp_fd);
+ return group;
+ }
+
+ close(grp_fd);
+ return NULL;
+}
+
+
+
+
diff --git a/libc-0.0.4/grp/getgrnam.c b/libc-0.0.4/grp/getgrnam.c
new file mode 100644
index 0000000..e6c27fc
--- /dev/null
+++ b/libc-0.0.4/grp/getgrnam.c
@@ -0,0 +1,51 @@
+/*
+ * getgrnam.c - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+
+struct group *
+getgrnam(const char * name)
+{
+ int grp_fd;
+ struct group * group;
+
+ if (name==NULL)
+ {
+ errno=EINVAL;
+ return NULL;
+ }
+
+ if ((grp_fd=open("/etc/group", O_RDONLY))<0)
+ return NULL;
+
+ while ((group=__getgrent(grp_fd))!=NULL)
+ if (!strcmp(group->gr_name, name))
+ {
+ close(grp_fd);
+ return group;
+ }
+
+ close(grp_fd);
+ return NULL;
+}
diff --git a/libc-0.0.4/grp/grent.c b/libc-0.0.4/grp/grent.c
new file mode 100644
index 0000000..19d618b
--- /dev/null
+++ b/libc-0.0.4/grp/grent.c
@@ -0,0 +1,57 @@
+/*
+ * grent.c - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * setgrent(), endgrent(), and getgrent() are mutually-dependent functions,
+ * so they are all included in the same object file, and thus all linked
+ * in together.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <grp.h>
+
+static int grp_fd=-1;
+
+void
+setgrent(void)
+{
+ if (grp_fd!=-1)
+ close(grp_fd);
+ grp_fd=open("/etc/group", O_RDONLY);
+}
+
+void
+endgrent(void)
+{
+ if (grp_fd!=-1)
+ close(grp_fd);
+ grp_fd=-1;
+}
+
+struct group *
+getgrent(void)
+{
+ if (grp_fd==-1)
+ return NULL;
+ return __getgrent(grp_fd);
+}
+
+
diff --git a/libc-0.0.4/grp/initgroups.c b/libc-0.0.4/grp/initgroups.c
new file mode 100644
index 0000000..df3ffa8
--- /dev/null
+++ b/libc-0.0.4/grp/initgroups.c
@@ -0,0 +1,80 @@
+/*
+ * initgroups.c - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <grp.h>
+#include "config-grp.h"
+
+int
+initgroups(__const char * user, gid_t gid)
+{
+ register struct group * group;
+#ifndef GR_DYNAMIC_GROUP_LIST
+ gid_t group_list[GR_MAX_GROUPS];
+#else
+ gid_t * group_list=NULL;
+#endif
+ register char ** tmp_mem;
+ int num_groups;
+ int grp_fd;
+
+
+ if ((grp_fd=open("/etc/group", O_RDONLY))<0)
+ return -1;
+
+ num_groups=0;
+#ifdef GR_DYNAMIC_GROUP_LIST
+ group_list=(gid_t *) realloc(group_list, 1);
+#endif
+ group_list[num_groups]=gid;
+#ifndef GR_DYNAMIC_GROUP_LIST
+ while (num_groups<GR_MAX_GROUPS &&
+ (group=__getgrent(grp_fd))!=NULL)
+#else
+ while ((group=__getgrent(grp_fd))!=NULL)
+#endif
+ {
+ if (group->gr_gid!=gid);
+ {
+ tmp_mem=group->gr_mem;
+ while(*tmp_mem!=NULL)
+ {
+ if (!strcmp(*tmp_mem, user))
+ {
+ num_groups++;
+#ifdef GR_DYNAMIC_GROUP_LIST
+ group_list=(gid_t *)realloc(group_list,
+ num_groups*sizeof(gid_t *));
+#endif
+ group_list[num_groups]=group->gr_gid;
+ }
+ tmp_mem++;
+ }
+ }
+ }
+ close(grp_fd);
+ return setgroups(num_groups, group_list);
+}
+
+
+
+
diff --git a/libc-0.0.4/grp/test_grp.c b/libc-0.0.4/grp/test_grp.c
new file mode 100644
index 0000000..b5ecd36
--- /dev/null
+++ b/libc-0.0.4/grp/test_grp.c
@@ -0,0 +1,107 @@
+/*
+ * test_grp.c - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <grp.h>
+
+int
+main(int argc, char ** argv)
+{
+ struct group * group;
+ char ** tmp_mem;
+ int test_gid;
+
+ fprintf(stderr, "Beginning test of libc/grp...\n");
+
+ fprintf(stderr, "=> Testing setgrent(), getgrent(), endgrent()...\n");
+ fprintf(stderr, "-> setgrent()...\n");
+ setgrent();
+ fprintf(stderr, "-> getgrent()...\n");
+ printf("********************************************************************************\n");
+ while ((group=getgrent())!=NULL)
+ {
+ printf("gr_name\t\t: %s\n", group->gr_name);
+ printf("gr_passwd\t: %s\n", group->gr_passwd);
+ printf("gr_gid\t\t: %d\n", (int) group->gr_gid);
+ printf("gr_mem\t\t: ");
+ fflush(stdout);
+ tmp_mem=group->gr_mem;
+ while(*tmp_mem!=NULL)
+ {
+ printf("%s, ", *tmp_mem);
+ tmp_mem++;
+ }
+ printf("\n********************************************************************************\n");
+ }
+ fprintf(stderr, "-> endgrent()...\n");
+ endgrent();
+ fprintf(stderr, "=> Test of setgrent(), getgrent(), endgrent() complete.\n");
+ fprintf(stderr, "=> Testing getgrid(), getgrnam()...\n");
+ fprintf(stderr, "-> getgrgid()...\n");
+ printf("********************************************************************************\n");
+ for(test_gid=0;test_gid<100;test_gid++)
+ {
+ fprintf(stderr, "-> getgrgid(%d)...\n", test_gid);
+ group=getgrgid((gid_t) test_gid);
+ if (group!=NULL)
+ {
+ printf("gr_name\t: %s\n", group->gr_name);
+ printf("gr_passwd\t: %s\n", group->gr_passwd);
+ printf("gr_gid\t: %d\n", (int) group->gr_gid);
+ printf("gr_mem\t\t: ");
+ fflush(stdout);
+ tmp_mem=group->gr_mem;
+ while(*tmp_mem!=NULL)
+ {
+ printf("%s, ", *tmp_mem);
+ tmp_mem++;
+ }
+ }
+ printf("\n********************************************************************************\n");
+ }
+ fprintf(stderr, "-> getgrnam()...\n");
+ group=getgrnam("root");
+ if (group==NULL)
+ {
+ printf(">NULL<\n");
+ }
+ else
+ {
+ printf("gr_name\t: %s\n", group->gr_name);
+ printf("gr_passwd\t: %s\n", group->gr_passwd);
+ printf("gr_gid\t: %d\n", (int) group->gr_gid);
+ printf("gr_mem\t\t: ");
+ fflush(stdout);
+ tmp_mem=group->gr_mem;
+ while(*tmp_mem!=NULL)
+ {
+ printf("%s, ", *tmp_mem);
+ tmp_mem++;
+ }
+ printf("\n");
+ }
+
+
+ return 0;
+}
+
+
diff --git a/libc-0.0.4/include/a.out.h b/libc-0.0.4/include/a.out.h
new file mode 100644
index 0000000..f6a7b94
--- /dev/null
+++ b/libc-0.0.4/include/a.out.h
@@ -0,0 +1,115 @@
+/* Copyright (C) 1990-1996
+ * This file is part of the ld86 command for Linux-86
+ * It is distributed under the GNU Library General Public License.
+ *
+ * - This may actually be BSD or Minix code, can someone clarify please. -RDB
+ */
+
+#ifndef __AOUT_H
+#define __AOUT_H
+
+struct exec { /* a.out header */
+ unsigned char a_magic[2]; /* magic number */
+ unsigned char a_flags; /* flags, see below */
+ unsigned char a_cpu; /* cpu id */
+ unsigned char a_hdrlen; /* length of header */
+ unsigned char a_unused; /* reserved for future use */
+ unsigned short a_version; /* version stamp (not used at present) */
+ long a_text; /* size of text segement in bytes */
+ long a_data; /* size of data segment in bytes */
+ long a_bss; /* size of bss segment in bytes */
+ long a_entry; /* entry point */
+ long a_total; /* total memory allocated */
+ long a_syms; /* size of symbol table */
+
+ /* SHORT FORM ENDS HERE */
+ long a_trsize; /* text relocation size */
+ long a_drsize; /* data relocation size */
+ long a_tbase; /* text relocation base */
+ long a_dbase; /* data relocation base */
+};
+
+#define A_MAGIC0 (unsigned char) 0x01
+#define A_MAGIC1 (unsigned char) 0x03
+#define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1)
+
+/* CPU Id of TARGET machine (byte order coded in low order two bits) */
+#define A_NONE 0x00 /* unknown */
+#define A_I8086 0x04 /* intel i8086/8088 */
+#define A_M68K 0x0B /* motorola m68000 */
+#define A_NS16K 0x0C /* national semiconductor 16032 */
+#define A_I80386 0x10 /* intel i80386 */
+#define A_SPARC 0x17 /* Sun SPARC */
+
+#define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */
+#define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */
+
+/* Flags. */
+#define A_UZP 0x01 /* unmapped zero page (pages) */
+#define A_PAL 0x02 /* page aligned executable */
+#define A_NSYM 0x04 /* new style symbol table */
+#define A_EXEC 0x10 /* executable */
+#define A_SEP 0x20 /* separate I/D */
+#define A_PURE 0x40 /* pure text */
+#define A_TOVLY 0x80 /* text overlay */
+
+/* Offsets of various things. */
+#define A_MINHDR 32
+#define A_TEXTPOS(X) ((long)(X).a_hdrlen)
+#define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text)
+#define A_HASRELS(X) ((X).a_hdrlen > (unsigned char) A_MINHDR)
+#define A_HASEXT(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 8))
+#define A_HASLNS(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 16))
+#define A_HASTOFF(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 24))
+#define A_TRELPOS(X) (A_DATAPOS(X) + (X).a_data)
+#define A_DRELPOS(X) (A_TRELPOS(X) + (X).a_trsize)
+#define A_SYMPOS(X) (A_TRELPOS(X) + (A_HASRELS(X) ? \
+ ((X).a_trsize + (X).a_drsize) : 0))
+
+struct reloc {
+ long r_vaddr; /* virtual address of reference */
+ unsigned short r_symndx; /* internal segnum or extern symbol num */
+ unsigned short r_type; /* relocation type */
+};
+
+/* r_tyep values: */
+#define R_ABBS 0
+#define R_RELLBYTE 2
+#define R_PCRBYTE 3
+#define R_RELWORD 4
+#define R_PCRWORD 5
+#define R_RELLONG 6
+#define R_PCRLONG 7
+#define R_REL3BYTE 8
+#define R_KBRANCHE 9
+
+/* r_symndx for internal segments */
+#define S_ABS ((unsigned short)-1)
+#define S_TEXT ((unsigned short)-2)
+#define S_DATA ((unsigned short)-3)
+#define S_BSS ((unsigned short)-4)
+
+struct nlist { /* symbol table entry */
+ char n_name[24]; /* symbol name */
+ long n_value; /* value */
+ unsigned char n_sclass; /* storage class */
+ unsigned char n_numaux; /* number of auxiliary entries (not used) */
+ unsigned short n_type; /* language base and derived type (not used) */
+};
+
+/* Low bits of storage class (section). */
+#define N_SECT 07 /* section mask */
+#define N_UNDF 00 /* undefined */
+#define N_ABS 01 /* absolute */
+#define N_TEXT 02 /* text */
+#define N_DATA 03 /* data */
+#define N_BSS 04 /* bss */
+#define N_COMM 05 /* (common) */
+
+/* High bits of storage class. */
+#define N_CLASS 0370 /* storage class mask */
+#define C_NULL
+#define C_EXT 0020 /* external symbol */
+#define C_STAT 0030 /* static */
+
+#endif /* _AOUT_H */
diff --git a/libc-0.0.4/include/ar.h b/libc-0.0.4/include/ar.h
new file mode 100644
index 0000000..c608371
--- /dev/null
+++ b/libc-0.0.4/include/ar.h
@@ -0,0 +1,18 @@
+#ifndef __AR_H
+#define __AR_H
+
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+struct ar_hdr {
+ char ar_name[16],
+ ar_date[12],
+ ar_uid[6],
+ ar_gid[6],
+ ar_mode[8],
+ ar_size[10],
+ ar_fmag[2];
+};
+
+#endif /* __AR_H */
diff --git a/libc-0.0.4/include/assert.h b/libc-0.0.4/include/assert.h
new file mode 100644
index 0000000..c58c57f
--- /dev/null
+++ b/libc-0.0.4/include/assert.h
@@ -0,0 +1,23 @@
+#ifdef __ASSERT_H
+#define __ASSERT_H
+#include <features.h>
+
+/* If NDEBUG is defined, do nothing.
+ If not, and EXPRESSION is zero, print an error message and abort. */
+
+#ifdef NDEBUG
+
+#define assert(expr) ((void) 0)
+
+#else /* Not NDEBUG. */
+
+extern void __assert __P((const char *, const char *, int));
+
+#define assert(expr) \
+ ((void) ((expr) || \
+ (__assert (__STRING(expr), \
+ __FILE__, __LINE__), 0)))
+
+#endif /* NDEBUG. */
+
+#endif /* __ASSERT_H */
diff --git a/libc-0.0.4/include/ctype.h b/libc-0.0.4/include/ctype.h
new file mode 100644
index 0000000..038659f
--- /dev/null
+++ b/libc-0.0.4/include/ctype.h
@@ -0,0 +1,37 @@
+/*
+ * ctype.h Character classification and conversion
+ */
+
+#ifndef __CTYPE_H
+#define __CTYPE_H
+
+extern unsigned char _ctype[];
+
+#define __CT_d 0x01 /* numeric digit */
+#define __CT_u 0x02 /* upper case */
+#define __CT_l 0x04 /* lower case */
+#define __CT_c 0x08 /* control character */
+#define __CT_s 0x10 /* whitespace */
+#define __CT_p 0x20 /* punctuation */
+#define __CT_x 0x40 /* hexadecimal */
+
+#define toupper(c) (islower(c) ? (c)^0x20 : (c))
+#define tolower(c) (isupper(c) ? (c)^0x20 : (c))
+#define _toupper(c) ((c)^0x20)
+#define _tolower(c) ((c)^0x20)
+#define toascii(c) ((c)&0x7F)
+
+#define isalnum(c) (_ctype[(int) c]&(__CT_u|__CT_l|__CT_d))
+#define isalpha(c) (_ctype[(int) c]&(__CT_u|__CT_l))
+#define isascii(c) !((c)&~0x7F)
+#define iscntrl(c) (_ctype[(int) c]&__CT_c)
+#define isdigit(c) (_ctype[(int) c]&__CT_d)
+#define isgraph(c) !(_ctype[(int) c]&(__CT_c|__CT_s))
+#define islower(c) (_ctype[(int) c]&__CT_l)
+#define isprint(c) !(_ctype[(int) c]&__CT_c)
+#define ispunct(c) (_ctype[(int) c]&__CT_p)
+#define isspace(c) (_ctype[(int) c]&__CT_s)
+#define isupper(c) (_ctype[(int) c]&__CT_u)
+#define isxdigit(c) (_ctype[(int) c]&__CT_x)
+
+#endif /* __CTYPE_H */
diff --git a/libc-0.0.4/include/dirent.h b/libc-0.0.4/include/dirent.h
new file mode 100644
index 0000000..0a931b9
--- /dev/null
+++ b/libc-0.0.4/include/dirent.h
@@ -0,0 +1,45 @@
+
+#ifndef __DIRENT_H
+#define __DIRENT_H
+
+#include <features.h>
+#include <sys/types.h>
+
+#ifndef MAXNAMLEN
+#define MAXNAMLEN 255
+#endif
+
+/* Directory stream type. */
+typedef struct {
+ int dd_fd; /* file descriptor */
+ int dd_loc; /* offset in buffer */
+ int dd_size; /* # of valid entries in buffer */
+ struct dirent *dd_buf; /* -> directory buffer */
+} DIR; /* stream data from opendir() */
+
+struct dirent {
+ long d_ino;
+ off_t d_off;
+ unsigned short d_reclen;
+ char d_name[MAXNAMLEN+1];
+};
+
+extern DIR *opendir __P ((__const char *__name));
+extern int closedir __P ((DIR * __dirp));
+extern struct dirent *readdir __P ((DIR * __dirp));
+extern void rewinddir __P ((DIR * __dirp));
+
+extern void seekdir __P ((DIR * __dirp, __off_t __pos));
+extern off_t telldir __P ((DIR * __dirp));
+
+/* Scan the directory DIR, calling SELECT on each directory entry.
+ Entries for which SELECT returns nonzero are individually malloc'd,
+ sorted using qsort with CMP, and collected in a malloc'd array in
+ *NAMELIST. Returns the number of entries selected, or -1 on error. */
+extern int scandir __P ((__const char *__dir,
+ struct dirent ***__namelist,
+ __dir_select_fn_t __select,
+ __dir_compar_fn_t __compar));
+
+#endif /* dirent.h */
+
diff --git a/libc-0.0.4/include/dos.h b/libc-0.0.4/include/dos.h
new file mode 100644
index 0000000..28575b4
--- /dev/null
+++ b/libc-0.0.4/include/dos.h
@@ -0,0 +1,34 @@
+
+#ifndef __DOS_H
+#define __DOS_H
+#include <features.h>
+
+union REGS
+{
+ struct { unsigned int ax, bx, cx, dx, si, di, cflag; } x;
+ struct { unsigned char al, ah, bl, bh, cl, ch, dl, dh; } h;
+};
+
+struct SREGS
+{
+ unsigned int es, cs, ss, ds;
+};
+
+extern unsigned int __envseg;
+extern unsigned int __psp;
+char * __fconv __P((char * fname));
+
+unsigned int __segalloc __P((unsigned int paracount));
+void __setvect __P((int i, long j));
+long __getvect __P((int vecno));
+
+unsigned int __get_ds __P((void));
+unsigned int __get_es __P((void));
+void __set_es __P((unsigned int seg));
+int __peek_es __P((unsigned int off));
+int __deek_es __P((unsigned int off));
+
+#define movedata __movedata
+
+#endif
+
diff --git a/libc-0.0.4/include/errno.h b/libc-0.0.4/include/errno.h
new file mode 100644
index 0000000..c8d2002
--- /dev/null
+++ b/libc-0.0.4/include/errno.h
@@ -0,0 +1,25 @@
+#ifndef __ERRNO_H
+#define __ERRNO_H
+
+#include <features.h>
+#include <linuxmt/errno.h>
+
+#ifdef __USE_BSD
+extern int sys_nerr;
+extern char *sys_errlist[];
+#endif
+#ifdef __USE_GNU
+extern int _sys_nerr;
+extern char *_sys_errlist[];
+#endif
+
+extern int errno;
+
+__BEGIN_DECLS
+
+extern void perror __P ((__const char* __s));
+extern char* strerror __P ((int __errno));
+
+__END_DECLS
+
+#endif
diff --git a/libc-0.0.4/include/fcntl.h b/libc-0.0.4/include/fcntl.h
new file mode 100644
index 0000000..ddd9afc
--- /dev/null
+++ b/libc-0.0.4/include/fcntl.h
@@ -0,0 +1,20 @@
+#ifndef __FCNTL_H
+#define __FCNTL_H
+
+#include <features.h>
+#include <sys/types.h>
+#include <linuxmt/fcntl.h>
+
+#ifndef FNDELAY
+#define FNDELAY O_NDELAY
+#endif
+
+__BEGIN_DECLS
+
+extern int creat __P ((__const char * __filename, mode_t __mode));
+extern int fcntl __P ((int __fildes,int __cmd, ...));
+extern int open __P ((__const char * __filename, int __flags, ...));
+
+__END_DECLS
+
+#endif
diff --git a/libc-0.0.4/include/features.h b/libc-0.0.4/include/features.h
new file mode 100644
index 0000000..11eb610
--- /dev/null
+++ b/libc-0.0.4/include/features.h
@@ -0,0 +1,36 @@
+
+#ifndef __FEATURES_H
+#define __FEATURES_H
+
+#ifdef __STDC__
+
+#define __P(x) x
+#define __const const
+
+/* Almost ansi */
+#if __STDC__ != 1
+#define const
+#define volatile
+#endif
+
+#else /* K&R */
+
+#define __P(x) ()
+#define __const
+#define const
+#define volatile
+
+#endif
+
+/* No C++ */
+#define __BEGIN_DECLS
+#define __END_DECLS
+
+/* GNUish things */
+#define __CONSTVALUE
+#define __CONSTVALUE2
+
+#include <sys/cdefs.h>
+
+#endif
+
diff --git a/libc-0.0.4/include/getopt.h b/libc-0.0.4/include/getopt.h
new file mode 100644
index 0000000..0d71ff6
--- /dev/null
+++ b/libc-0.0.4/include/getopt.h
@@ -0,0 +1,17 @@
+/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#ifndef __GETOPT_H
+#define __GETOPT_H
+
+#include <features.h>
+
+extern char *optarg;
+extern int opterr;
+extern int optind;
+
+extern int getopt __P((int argc, char *const *argv, const char *shortopts));
+
+#endif /* __GETOPT_H */
diff --git a/libc-0.0.4/include/grp.h b/libc-0.0.4/include/grp.h
new file mode 100644
index 0000000..96b2b4b
--- /dev/null
+++ b/libc-0.0.4/include/grp.h
@@ -0,0 +1,37 @@
+#ifndef __GRP_H
+#define __GRP_H
+
+#include <sys/types.h>
+#include <features.h>
+#include <stdio.h>
+
+/* The group structure */
+struct group
+{
+ char *gr_name; /* Group name. */
+ char *gr_passwd; /* Password. */
+ gid_t gr_gid; /* Group ID. */
+ char **gr_mem; /* Member list. */
+};
+
+extern void setgrent __P ((void));
+extern void endgrent __P ((void));
+extern struct group * getgrent __P ((void));
+
+extern struct group * getgrgid __P ((__const gid_t gid));
+extern struct group * getgrnam __P ((__const char * name));
+
+extern struct group * fgetgrent __P ((FILE * file));
+
+extern int setgroups __P ((size_t n, __const gid_t * groups));
+extern int initgroups __P ((__const char * user, gid_t gid));
+
+
+#ifdef __LIBC__
+extern struct group * __getgrent __P ((int grp_fd));
+#endif
+
+#endif /* _GRP_H */
+
+
+
diff --git a/libc-0.0.4/include/limits.h b/libc-0.0.4/include/limits.h
new file mode 100644
index 0000000..579287e
--- /dev/null
+++ b/libc-0.0.4/include/limits.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#ifndef __LIMITS_H
+#define __LIMITS_H
+
+#if __AS386_16__
+#define MB_LEN_MAX 1 /* Longest multi-byte character */
+#define CHAR_MAX 127 /* maximum char value */
+#define CHAR_MIN (-127) /* mimimum char value */
+#define SCHAR_MAX 127 /* maximum signed char value */
+#define SCHAR_MIN (-127) /* minimum signed char value */
+#define CHAR_BIT 8 /* number of bits in a char */
+#define SHRT_MAX 32767 /* maximum (signed) short value */
+#define SHRT_MIN (-32767) /* minimum (signed) short value */
+#define INT_MAX 32767 /* maximum (signed) int value */
+#define INT_MIN (-32767) /* minimum (signed) int value */
+#define LONG_MAX 2147483647 /* maximum (signed) long value */
+#define LONG_MIN (-2147483647) /* minimum (signed) long value */
+#define UCHAR_MAX 255 /* maximum unsigned char value */
+#define USHRT_MAX 0xffff /* maximum unsigned short value */
+#define UINT_MAX 0xffff /* maximum unsigned int value */
+#define ULONG_MAX 0xffffffff /* maximum unsigned long value */
+#ifndef RAND_MAX
+#define RAND_MAX INT_MAX
+#endif
+#else
+#error "Limits.h not implemented"
+#endif
+
+#endif
diff --git a/libc-0.0.4/include/linuxmt b/libc-0.0.4/include/linuxmt
new file mode 120000
index 0000000..45fae66
--- /dev/null
+++ b/libc-0.0.4/include/linuxmt
@@ -0,0 +1 @@
+../kinclude/linuxmt \ No newline at end of file
diff --git a/libc-0.0.4/include/malloc.h b/libc-0.0.4/include/malloc.h
new file mode 100644
index 0000000..c00fa21
--- /dev/null
+++ b/libc-0.0.4/include/malloc.h
@@ -0,0 +1,29 @@
+
+#ifndef __MALLOC_H
+#define __MALLOC_H
+#include <features.h>
+
+/*
+ * Mini malloc allows you to use a less efficient but smaller malloc the
+ * cost is about 100 bytes of code in free but malloc (700bytes) doesn't
+ * have to be linked. Unfortunatly memory can only be reused if everything
+ * above it has been freed
+ *
+ */
+
+void free __P((void *));
+void *malloc __P((unsigned int));
+void *realloc __P((void *, unsigned int));
+void *alloca __P((unsigned int));
+
+extern void *(*__alloca_alloc) __P((unsigned int));
+
+#ifdef __LIBC__
+#define __MINI_MALLOC__
+#endif
+
+#ifdef __MINI_MALLOC__
+#define malloc(x) ((*__alloca_alloc)(x))
+#endif
+
+#endif
diff --git a/libc-0.0.4/include/memory.h b/libc-0.0.4/include/memory.h
new file mode 100644
index 0000000..3b2f590
--- /dev/null
+++ b/libc-0.0.4/include/memory.h
@@ -0,0 +1 @@
+#include <string.h>
diff --git a/libc-0.0.4/include/paths.h b/libc-0.0.4/include/paths.h
new file mode 100644
index 0000000..58bade7
--- /dev/null
+++ b/libc-0.0.4/include/paths.h
@@ -0,0 +1,20 @@
+/* paths.h <ndf@linux.mit.edu> */
+
+#ifndef ___PATHS_H
+#define ___PATHS_H
+
+
+#define _PATH_CONSOLE "/dev/console"
+#define _PATH_TTY "/dev/tty"
+#define _PATH_NOLOGIN "/etc/nologin"
+#define _PATH_LOGIN "/bin/login"
+#define _PATH_BSHELL "/bin/sh"
+#define _PATH_UTMP "/var/run/utmp"
+#define _PATH_WTMP "/var/log/wtmp"
+#define _PATH_DEFPATH "/bin:/usr/bin:/usr/local/bin:."
+#define _PATH_DEV "/dev/"
+#define _PATH_TMP "/tmp/"
+#define _PATH_LASTLOG "/var/log/lastlog"
+#define _PATH_LOCALE "/usr/lib/locale"
+
+#endif /* __PATHS_H */
diff --git a/libc-0.0.4/include/pwd.h b/libc-0.0.4/include/pwd.h
new file mode 100644
index 0000000..1b48c6a
--- /dev/null
+++ b/libc-0.0.4/include/pwd.h
@@ -0,0 +1,40 @@
+#ifndef __PWD_H
+#define __PWD_H
+
+#include <sys/types.h>
+#include <features.h>
+#include <stdio.h>
+
+/* The passwd structure. */
+struct passwd
+{
+ char *pw_name; /* Username. */
+ char *pw_passwd; /* Password. */
+ uid_t pw_uid; /* User ID. */
+ gid_t pw_gid; /* Group ID. */
+ char *pw_gecos; /* Real name. */
+ char *pw_dir; /* Home directory. */
+ char *pw_shell; /* Shell program. */
+};
+
+
+extern void setpwent __P ((void));
+extern void endpwent __P ((void));
+extern struct passwd * getpwent __P ((void));
+
+extern int putpwent __P ((__const struct passwd * __p, FILE * __f));
+extern int getpw __P ((uid_t uid, char *buf));
+
+extern struct passwd * fgetpwent __P ((FILE * file));
+
+extern struct passwd * getpwuid __P ((__const uid_t));
+extern struct passwd * getpwnam __P ((__const char *));
+
+#ifdef __LIBC__
+extern struct passwd * __getpwent __P ((__const int passwd_fd));
+#endif
+
+#endif /* pwd.h */
+
+
+
diff --git a/libc-0.0.4/include/regexp.h b/libc-0.0.4/include/regexp.h
new file mode 100644
index 0000000..73d6bf4
--- /dev/null
+++ b/libc-0.0.4/include/regexp.h
@@ -0,0 +1,21 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+#define NSUBEXP 10
+typedef struct regexp {
+ char *startp[NSUBEXP];
+ char *endp[NSUBEXP];
+ char regstart; /* Internal use only. */
+ char reganch; /* Internal use only. */
+ char *regmust; /* Internal use only. */
+ int regmlen; /* Internal use only. */
+ char program[1]; /* Unwarranted chumminess with compiler. */
+} regexp;
+
+extern regexp *regcomp();
+extern int regexec();
+extern void regsub();
+extern void regerror();
diff --git a/libc-0.0.4/include/regmagic.h b/libc-0.0.4/include/regmagic.h
new file mode 100644
index 0000000..5acf447
--- /dev/null
+++ b/libc-0.0.4/include/regmagic.h
@@ -0,0 +1,5 @@
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define MAGIC 0234
diff --git a/libc-0.0.4/include/search.h b/libc-0.0.4/include/search.h
new file mode 100644
index 0000000..b9c8a17
--- /dev/null
+++ b/libc-0.0.4/include/search.h
@@ -0,0 +1,94 @@
+/* Copyright (C) 1993 Ulrich Drepper
+
+This file is intended to be included in the GNU C Library and the
+Linux C Library. So the copyright notice will be:
+
+
+Copyright (C) 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.
+
+
+For now the file can be distributed under the LGPL. */
+
+#ifndef _SEARCH_H
+#define _SEARCH_H
+
+#include <features.h>
+
+#define __need_size_t
+#define __need_NULL
+#include <stddef.h>
+
+__BEGIN_DECLS
+
+#ifndef __COMPAR_FN_T
+#define __COMPAR_FN_T
+typedef int (*__compar_fn_t) __P ((__const __ptr_t, __const __ptr_t));
+#endif
+
+/* for use with hsearch(3) */
+
+typedef struct entry { char *key; char *data; } ENTRY;
+typedef enum { FIND, ENTER } ACTION;
+
+extern ENTRY * hsearch __P((ENTRY __item, ACTION __action));
+extern int hcreate __P((unsigned __nel));
+extern void hdestroy __P((void));
+
+
+/* The tsearch routines are very interesting. They make many
+ * assumptions about the compiler. It assumpts that the first field
+ * in node must be the "key" field, which points to the datum.
+ * Everything depends on that. It is a very tricky stuff. H.J.
+ */
+/* For tsearch */
+typedef enum { preorder, postorder, endorder, leaf } VISIT;
+
+extern void *tsearch __P((__const void * __key, void **__rootp,
+ __compar_fn_t compar));
+
+extern void *tfind __P((__const void * __key, __const void ** __rootp,
+ __compar_fn_t compar));
+
+extern void *tdelete __P((__const void * __key, void ** __rootp,
+ __compar_fn_t compar));
+
+#ifndef __ACTION_FN_T
+#define __ACTION_FN_T
+/* FYI, the first argument should be a pointer to "key".
+ * Please read the man page for details.
+ */
+typedef void (*__action_fn_t) __P((__const void *__nodep,
+ __const VISIT __value,
+ __const int __level));
+#endif
+
+extern void twalk __P((__const void * __root, __action_fn_t action));
+
+
+extern void * lfind __P((__const void * __key, __const void * __base,
+ size_t * __nmemb, size_t __size,
+ __compar_fn_t __compar));
+
+extern void * lsearch __P((__const void * __key, __const void * __base,
+ size_t * __nmemb, size_t __size,
+ __compar_fn_t __compar));
+
+__END_DECLS
+
+#endif /* search.h */
diff --git a/libc-0.0.4/include/setjmp.h b/libc-0.0.4/include/setjmp.h
new file mode 100644
index 0000000..c2bfadb
--- /dev/null
+++ b/libc-0.0.4/include/setjmp.h
@@ -0,0 +1,26 @@
+
+#ifndef __SETJMP_H
+#define __SETJMP_H
+
+#include <features.h>
+
+/*
+ * I know most systems use an array of ints here, but I prefer this - RDB
+ */
+
+typedef struct
+{
+ unsigned int pc;
+ unsigned int sp;
+ unsigned int bp;
+ unsigned int si;
+ unsigned int di;
+} jmp_buf[1];
+
+int setjmp __P((jmp_buf env));
+void longjmp __P((jmp_buf env, int rv));
+
+/* LATER: Seems GNU beat me to it, must be OK then :-)
+ * Humm, what's this about setjmp being a macro !?
+ */
+#endif
diff --git a/libc-0.0.4/include/sgtty.h b/libc-0.0.4/include/sgtty.h
new file mode 100644
index 0000000..9e26956
--- /dev/null
+++ b/libc-0.0.4/include/sgtty.h
@@ -0,0 +1 @@
+#include <termios.h>
diff --git a/libc-0.0.4/include/signal.h b/libc-0.0.4/include/signal.h
new file mode 100644
index 0000000..1d54fc3
--- /dev/null
+++ b/libc-0.0.4/include/signal.h
@@ -0,0 +1,85 @@
+
+#ifndef __SIGNAL_H
+#define __SIGNAL_H
+#include <features.h>
+
+typedef unsigned long sigset_t; /* at least 32 bits */
+
+#define _NSIG 32
+#define NSIG _NSIG
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGSTKFLT 16
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGTSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGURG 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGIO 29
+#define SIGPOLL SIGIO
+/*
+#define SIGLOST 29
+*/
+#define SIGPWR 30
+#define SIGUNUSED 31
+
+/*
+ * sa_flags values: SA_STACK is not currently supported, but will allow the
+ * usage of signal stacks by using the (now obsolete) sa_restorer field in
+ * the sigaction structure as a stack pointer. This is now possible due to
+ * the changes in signal handling. LBT 010493.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ */
+#define SA_NOCLDSTOP 1
+#define SA_STACK 0x08000000
+#define SA_RESTART 0x10000000
+#define SA_INTERRUPT 0x20000000
+#define SA_NOMASK 0x40000000
+#define SA_ONESHOT 0x80000000
+
+#define SIG_BLOCK 0 /* for blocking signals */
+#define SIG_UNBLOCK 1 /* for unblocking signals */
+#define SIG_SETMASK 2 /* for setting the signal mask */
+
+/* Type of a signal handler. */
+typedef void (*__sighandler_t)(/* int */);
+
+#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
+#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
+#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
+
+struct sigaction {
+ __sighandler_t sa_handler;
+ sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)( /*void*/ );
+};
+
+/* BSDisms */
+extern __const char * __const sys_siglist[];
+#define sig_t __sighandler_t
+
+#endif
diff --git a/libc-0.0.4/include/stdarg.h b/libc-0.0.4/include/stdarg.h
new file mode 100644
index 0000000..978529b
--- /dev/null
+++ b/libc-0.0.4/include/stdarg.h
@@ -0,0 +1,38 @@
+ /*
+ * @(#) stdarg.h 1.2 91/11/30 21:10:39
+ *
+ * Sample stdarg.h file for use with the unproto filter.
+ *
+ * This file serves two purposes.
+ *
+ * 1 - As an include file for use with ANSI-style C source that implements
+ * variadic functions.
+ *
+ * 2 - To configure the unproto filter itself. If the _VA_ALIST_ macro is
+ * defined, its value will appear in the place of the "..." in argument
+ * lists of variadic function *definitions* (not declarations).
+ *
+ * Compilers that pass arguments via the stack can use the default code at the
+ * end of this file (this usually applies for the VAX, MC68k and 80*86
+ * architectures).
+ *
+ * RISC-based systems often need special tricks. An example of the latter is
+ * given for the SPARC architecture. Read your /usr/include/varargs.h for
+ * more information.
+ *
+ * You can use the varargs.c program provided with the unproto package to
+ * verify that the stdarg.h file has been set up correctly.
+ */
+
+#ifdef sparc
+# define _VA_ALIST_ "__builtin_va_alist"
+ typedef char *va_list;
+# define va_start(ap, p) (ap = (char *) &__builtin_va_alist)
+# define va_arg(ap, type) ((type *) __builtin_va_arg_incr((type *) ap))[0]
+# define va_end(ap)
+#else /* vax, mc68k, 80*86 */
+ typedef char *va_list;
+# define va_start(ap, p) (ap = (char *) (&(p)+1))
+# define va_arg(ap, type) ((type *) (ap += sizeof(type)))[-1]
+# define va_end(ap)
+#endif
diff --git a/libc-0.0.4/include/stddef.h b/libc-0.0.4/include/stddef.h
new file mode 100644
index 0000000..112c18f
--- /dev/null
+++ b/libc-0.0.4/include/stddef.h
@@ -0,0 +1,26 @@
+/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+/* We don't care, ignore GCC's __need hackery */
+
+#undef __need_wchar_t
+#undef __need_size_t
+#undef __need_ptrdiff_t
+#undef __need_NULL
+
+#if __AS386_16__ /* Only for 8086 */
+#ifndef __STDDEF_H
+#define __STDDEF_H
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#endif
+#endif
diff --git a/libc-0.0.4/include/stdio.h b/libc-0.0.4/include/stdio.h
new file mode 100644
index 0000000..ba70b1d
--- /dev/null
+++ b/libc-0.0.4/include/stdio.h
@@ -0,0 +1,125 @@
+
+#ifndef __STDIO_H
+#define __STDIO_H
+
+#include <features.h>
+#include <sys/types.h>
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#define _IOFBF 0x00 /* full buffering */
+#define _IOLBF 0x01 /* line buffering */
+#define _IONBF 0x02 /* no buffering */
+#define __MODE_BUF 0x03 /* Modal buffering dependent on isatty */
+
+#define __MODE_FREEBUF 0x04 /* Buffer allocated with malloc, can free */
+#define __MODE_FREEFIL 0x08 /* FILE allocated with malloc, can free */
+
+#define __MODE_READ 0x10 /* Opened in read only */
+#define __MODE_WRITE 0x20 /* Opened in write only */
+#define __MODE_RDWR 0x30 /* Opened in read/write */
+
+#define __MODE_READING 0x40 /* Buffer has pending read data */
+#define __MODE_WRITING 0x80 /* Buffer has pending write data */
+
+#define __MODE_EOF 0x100 /* EOF status */
+#define __MODE_ERR 0x200 /* Error status */
+#define __MODE_UNGOT 0x400 /* Buffer has been polluted by ungetc */
+
+#ifdef __MSDOS__
+#define __MODE_IOTRAN 0x1000 /* MSDOS nl <-> cr,nl translation */
+#else
+#define __MODE_IOTRAN 0
+#endif
+
+/* when you add or change fields here, be sure to change the initialization
+ * in stdio_init and fopen */
+struct __stdio_file {
+ unsigned char *bufpos; /* the next byte to write to or read from */
+ unsigned char *bufread; /* the end of data returned by last read() */
+ unsigned char *bufwrite; /* highest address writable by macro */
+ unsigned char *bufstart; /* the start of the buffer */
+ unsigned char *bufend; /* the end of the buffer; ie the byte after the last
+ malloc()ed byte */
+
+ int fd; /* the file descriptor associated with the stream */
+ int mode;
+
+ char unbuf[8]; /* The buffer for 'unbuffered' streams */
+
+ struct __stdio_file * next;
+};
+
+#define EOF (-1)
+#ifndef NULL
+#define NULL (0)
+#endif
+
+typedef struct __stdio_file FILE;
+
+#define BUFSIZ (256)
+
+extern FILE stdin[1];
+extern FILE stdout[1];
+extern FILE stderr[1];
+
+#ifdef __MSDOS__
+#define putc(c, fp) fputc(c, fp)
+#define getc(fp) fgetc(fp)
+#else
+#define putc(c, stream) \
+ (((stream)->bufpos >= (stream)->bufwrite) ? fputc((c), (stream)) \
+ : (unsigned char) (*(stream)->bufpos++ = (c)) )
+
+#define getc(stream) \
+ (((stream)->bufpos >= (stream)->bufread) ? fgetc(stream): \
+ (*(stream)->bufpos++))
+#endif
+
+#define putchar(c) putc((c), stdout)
+#define getchar() getc(stdin)
+
+#define ferror(fp) (((fp)->mode&__MODE_ERR) != 0)
+#define feof(fp) (((fp)->mode&__MODE_EOF) != 0)
+#define clearerr(fp) ((fp)->mode &= ~(__MODE_EOF|__MODE_ERR),0)
+#define fileno(fp) ((fp)->fd)
+
+/* declare functions; not like it makes much difference without ANSI */
+/* RDB: The return values _are_ important, especially if we ever use
+ 8086 'large' model
+ */
+
+/* These two call malloc */
+#define setlinebuf(__fp) setvbuf((__fp), (char*)0, _IOLBF, 0)
+extern int setvbuf __P((FILE*, char*, int, size_t));
+
+/* These don't */
+#define setbuf(__fp, __buf) setbuffer((__fp), (__buf), BUFSIZ)
+extern void setbuffer __P((FILE*, char*, int));
+
+extern int fgetc __P((FILE*));
+extern int fputc __P((int, FILE*));
+
+extern int fclose __P((FILE*));
+extern int fflush __P((FILE*));
+extern char *fgets __P((char*, size_t, FILE*));
+extern FILE *__fopen __P((char*, int, FILE*, char*));
+
+#define fopen(__file, __mode) __fopen((__file), -1, (FILE*)0, (__mode))
+#define freopen(__file, __mode, __fp) __fopen((__file), -1, (__fp), (__mode))
+#define fdopen(__file, __mode) __fopen((char*)0, (__file), (FILE*)0, (__mode))
+
+extern int fputs __P((char*, FILE*));
+extern int puts __P((char*));
+
+extern int printf __P ((__const char*, ...));
+extern int fprintf __P ((FILE*, __const char*, ...));
+extern int sprintf __P ((char*, __const char*, ...));
+
+#define stdio_pending(fp) ((fp)->bufread>(fp)->bufpos)
+
+#endif /* __STDIO_H */
diff --git a/libc-0.0.4/include/stdlib.h b/libc-0.0.4/include/stdlib.h
new file mode 100644
index 0000000..9f235d8
--- /dev/null
+++ b/libc-0.0.4/include/stdlib.h
@@ -0,0 +1,30 @@
+/* stdlib.h <ndf@linux.mit.edu> */
+#include <features.h>
+#include <sys/types.h>
+
+#ifndef __STDLIB_H
+#define __STDLIB_H
+
+/* Don't overwrite user definitions of NULL */
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+/* For program termination */
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+
+extern void * malloc __P ((size_t size));
+extern void * calloc __P ((size_t nmemb, size_t size));
+extern void free __P ((void * ptr));
+extern void * realloc __P ((void * ptr, size_t size));
+
+extern int rand __P ((void));
+extern void srand __P ((unsigned int seed));
+
+extern long strtol __P ((const char * nptr, char ** endptr, int base));
+extern unsigned long strtoul __P ((const char * nptr,
+ char ** endptr, int base));
+extern double strtod __P ((const char * nptr, char ** endptr));
+
+#endif /* __STDLIB_H */
diff --git a/libc-0.0.4/include/string.h b/libc-0.0.4/include/string.h
new file mode 100644
index 0000000..8be8eff
--- /dev/null
+++ b/libc-0.0.4/include/string.h
@@ -0,0 +1,52 @@
+
+#ifndef __STRING_H
+#define __STRING_H
+#include <features.h>
+#include <stddef.h>
+
+/* Basic string functions */
+extern size_t strlen __P ((__const char* __str));
+
+extern char * strcat __P ((char*, __const char*));
+extern char * strcpy __P ((char*, __const char*));
+extern int strcmp __P ((__const char*, __const char*));
+
+extern char * strncat __P ((char*, char*, size_t));
+extern char * strncpy __P ((char*, char*, size_t));
+extern int strncmp __P ((__const char*, __const char*, size_t));
+
+extern char * strchr __P ((char*, int));
+extern char * strrchr __P ((char*, int));
+extern char * strdup __P ((char*));
+
+/* Basic mem functions */
+extern void * memcpy __P ((void*, __const void*, size_t));
+extern void * memccpy __P ((void*, void*, int, size_t));
+extern void * memchr __P ((__const void*, __const int, size_t));
+extern void * memset __P ((void*, int, size_t));
+extern int memcmp __P ((__const void*, __const void*, size_t));
+
+extern void * memmove __P ((void*, void*, size_t));
+
+/* Minimal (very!) locale support */
+#define strcoll strcmp
+#define strxfrm strncpy
+
+/* BSDisms */
+#define index strchr
+#define rindex strrchr
+
+/* Other common BSD functions */
+extern int strcasecmp __P ((char*, char*));
+extern int strncasecmp __P ((char*, char*, size_t));
+char *strpbrk __P ((char *, char *));
+char *strsep __P ((char **, char *));
+char *strstr __P ((char *, char *));
+char *strtok __P ((char *, char *));
+size_t strcspn __P ((char *, char *));
+size_t strspn __P ((char *, char *));
+
+/* Linux silly hour */
+char *strfry __P ((char *));
+
+#endif
diff --git a/libc-0.0.4/include/strings.h b/libc-0.0.4/include/strings.h
new file mode 100644
index 0000000..3b2f590
--- /dev/null
+++ b/libc-0.0.4/include/strings.h
@@ -0,0 +1 @@
+#include <string.h>
diff --git a/libc-0.0.4/include/sys/cdefs.h b/libc-0.0.4/include/sys/cdefs.h
new file mode 100644
index 0000000..366b0c6
--- /dev/null
+++ b/libc-0.0.4/include/sys/cdefs.h
@@ -0,0 +1,33 @@
+
+#ifndef __SYS_CDEFS_H
+#define __SYS_CDEFS_H
+#include <features.h>
+
+#if defined (__STDC__) && __STDC__
+
+#define __CONCAT(x,y) x ## y
+#define __STRING(x) #x
+
+/* This is not a typedef so `const __ptr_t' does the right thing. */
+#define __ptr_t void *
+typedef long double __long_double_t;
+
+#else
+
+#define __CONCAT(x,y) x/**/y
+#define __STRING(x) "x"
+
+#define __ptr_t char *
+typedef double __long_double_t;
+
+#endif
+
+/* No C++ */
+#define __BEGIN_DECLS
+#define __END_DECLS
+
+/* GNUish things */
+#define __CONSTVALUE
+#define __CONSTVALUE2
+
+#endif
diff --git a/libc-0.0.4/include/sys/errno.h b/libc-0.0.4/include/sys/errno.h
new file mode 100644
index 0000000..339f4fc
--- /dev/null
+++ b/libc-0.0.4/include/sys/errno.h
@@ -0,0 +1 @@
+#include <errno.h>
diff --git a/libc-0.0.4/include/sys/fcntl.h b/libc-0.0.4/include/sys/fcntl.h
new file mode 100644
index 0000000..cd30455
--- /dev/null
+++ b/libc-0.0.4/include/sys/fcntl.h
@@ -0,0 +1 @@
+#include <fcntl.h>
diff --git a/libc-0.0.4/include/sys/file.h b/libc-0.0.4/include/sys/file.h
new file mode 100644
index 0000000..2401b15
--- /dev/null
+++ b/libc-0.0.4/include/sys/file.h
@@ -0,0 +1,35 @@
+#ifndef _SYS_FILE_H
+#define _SYS_FILE_H
+
+#include <features.h>
+#include <fcntl.h>
+
+#ifndef L_SET
+
+#define L_SET 0 /* absolute offset */
+#define L_INCR 1 /* relative to current offset */
+#define L_XTND 2 /* relative to end of file */
+
+#endif
+
+#ifndef LOCK_SH
+
+/* Operations for the `flock' call. */
+#define LOCK_SH 1 /* Shared lock. */
+#define LOCK_EX 2 /* Exclusive lock. */
+#define LOCK_UN 8 /* Unlock. */
+
+/* Can be OR'd in to one of the above. */
+#define LOCK_NB 4 /* Don't block when locking. */
+
+#endif
+
+__BEGIN_DECLS
+
+/* Apply or remove an advisory lock, according to OPERATION,
+ on the file FD refers to. */
+extern int flock __P ((int __fd, int __operation));
+
+__END_DECLS
+
+#endif
diff --git a/libc-0.0.4/include/sys/ioctl.h b/libc-0.0.4/include/sys/ioctl.h
new file mode 100644
index 0000000..55e5882
--- /dev/null
+++ b/libc-0.0.4/include/sys/ioctl.h
@@ -0,0 +1,9 @@
+
+#ifndef _SYS_IOCTL_H
+#define _SYS_IOCTL_H
+#include <features.h>
+#include <linuxmt/ioctl.h>
+
+extern int ioctl __P((int __fildes, int __cmd, ...));
+
+#endif
diff --git a/libc-0.0.4/include/sys/param.h b/libc-0.0.4/include/sys/param.h
new file mode 100644
index 0000000..1a31d1f
--- /dev/null
+++ b/libc-0.0.4/include/sys/param.h
@@ -0,0 +1,18 @@
+/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#ifndef _PARAM_H
+#define _PARAM_H
+
+#include <limits.h>
+
+#ifndef NR_OPEN
+#define NR_OPEN 32
+#endif
+#ifndef NR_FILE
+#define NR_FILE 32
+#endif
+
+#endif
diff --git a/libc-0.0.4/include/sys/signal.h b/libc-0.0.4/include/sys/signal.h
new file mode 100644
index 0000000..2e602da
--- /dev/null
+++ b/libc-0.0.4/include/sys/signal.h
@@ -0,0 +1 @@
+#include <signal.h>
diff --git a/libc-0.0.4/include/sys/stat.h b/libc-0.0.4/include/sys/stat.h
new file mode 100644
index 0000000..4a4bdbd
--- /dev/null
+++ b/libc-0.0.4/include/sys/stat.h
@@ -0,0 +1,27 @@
+#ifndef _SYS_STAT_H
+#define _SYS_STAT_H
+
+#include <linuxmt/stat.h>
+#include <sys/types.h>
+#include <features.h>
+
+struct stat
+{
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size;
+ time_t st_atime;
+ time_t st_mtime;
+ time_t st_ctime;
+};
+
+int stat __P((__const char * __path, struct stat * __statbuf));
+int lstat __P((__const char * __path, struct stat * __statbuf));
+int fstat __P((int __fd, struct stat * __statbuf));
+
+#endif
diff --git a/libc-0.0.4/include/sys/types.h b/libc-0.0.4/include/sys/types.h
new file mode 100644
index 0000000..7b7de09
--- /dev/null
+++ b/libc-0.0.4/include/sys/types.h
@@ -0,0 +1,2 @@
+#include <stddef.h>
+#include <linuxmt/types.h>
diff --git a/libc-0.0.4/include/sys/wait.h b/libc-0.0.4/include/sys/wait.h
new file mode 100644
index 0000000..70a0e4a
--- /dev/null
+++ b/libc-0.0.4/include/sys/wait.h
@@ -0,0 +1,2 @@
+
+/** FIXME **/
diff --git a/libc-0.0.4/include/termcap.h b/libc-0.0.4/include/termcap.h
new file mode 100644
index 0000000..a7ae37b
--- /dev/null
+++ b/libc-0.0.4/include/termcap.h
@@ -0,0 +1,21 @@
+
+#ifndef _TERMCAP_H
+#define _TERMCAP_H
+
+#include <features.h>
+#include <sys/types.h>
+
+extern char PC;
+extern char *UP;
+extern char *BC;
+extern int ospeed;
+
+extern int tgetent __P((char *, const char *));
+extern int tgetflag __P((const char *));
+extern int tgetnum __P((const char *));
+extern char *tgetstr __P((const char *, char **));
+
+extern int tputs __P((const char *, int, int (*)(int)));
+extern char *tgoto __P((const char *, int, int));
+
+#endif /* _TERMCAP_H */
diff --git a/libc-0.0.4/include/termio.h b/libc-0.0.4/include/termio.h
new file mode 100644
index 0000000..9e26956
--- /dev/null
+++ b/libc-0.0.4/include/termio.h
@@ -0,0 +1 @@
+#include <termios.h>
diff --git a/libc-0.0.4/include/termios.h b/libc-0.0.4/include/termios.h
new file mode 100644
index 0000000..4ca1ec8
--- /dev/null
+++ b/libc-0.0.4/include/termios.h
@@ -0,0 +1,24 @@
+#ifndef __TERMIOS_H
+#define __TERMIOS_H
+
+#include <features.h>
+#include <sys/types.h>
+#include <linuxmt/termios.h>
+
+extern int cfgetispeed __P ((struct termios *__termios_p));
+extern int cfgetospeed __P ((struct termios *__termios_p));
+extern int cfsetispeed __P ((struct termios *__termios_p, speed_t __speed));
+extern int cfsetospeed __P ((struct termios *__termios_p, speed_t __speed));
+
+extern void cfmakeraw __P ((struct termios *__t));
+
+extern int tcsetattr __P ((int __fd, int __opt, struct termios *__termios_p));
+extern int tcgetattr __P ((int __fildes, struct termios *__termios_p));
+extern int tcdrain __P ((int __fildes));
+extern int tcflow __P ((int __fildes, int __action));
+extern int tcflush __P ((int __fildes, int __queue_selector));
+extern int tcsendbreak __P ((int __fildes, int __duration));
+extern pid_t tcgetpgrp __P ((int __fildes));
+extern int tcsetpgrp __P ((int __fildes, pid_t __pgrp_id));
+
+#endif
diff --git a/libc-0.0.4/include/time.h b/libc-0.0.4/include/time.h
new file mode 100644
index 0000000..b9eb87c
--- /dev/null
+++ b/libc-0.0.4/include/time.h
@@ -0,0 +1,61 @@
+#ifndef __TIME_H
+#define __TIME_H
+
+#include <features.h>
+#include <sys/types.h>
+#include <stddef.h>
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef long clock_t;
+#endif
+
+#define CLOCKS_PER_SEC 100
+#define CLK_TCK 100 /* That must be the same as HZ ???? */
+
+struct timeval {
+ long tv_sec;
+ long tv_usec;
+};
+
+struct tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+};
+
+#define __isleap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+extern char *tzname[2];
+extern int daylight;
+extern long int timezone;
+
+__BEGIN_DECLS
+
+extern int stime __P ((time_t* __tptr));
+
+extern clock_t clock __P ((void));
+extern time_t time __P ((time_t * __tp));
+extern __CONSTVALUE double difftime __P ((time_t __time2,
+ time_t __time1)) __CONSTVALUE2;
+extern time_t mktime __P ((struct tm * __tp));
+
+extern char * asctime __P ((__const struct tm * __tp));
+extern char * ctime __P ((__const time_t * __tp));
+extern size_t strftime __P ((char * __s, size_t __smax,
+ __const char * __fmt, __const struct tm * __tp));
+extern void tzset __P ((void));
+
+extern struct tm* gmtime __P ((__const time_t *__tp));
+extern struct tm* localtime __P ((__const time_t * __tp));
+
+__END_DECLS
+
+#endif
diff --git a/libc-0.0.4/include/unistd.h b/libc-0.0.4/include/unistd.h
new file mode 100644
index 0000000..c283a38
--- /dev/null
+++ b/libc-0.0.4/include/unistd.h
@@ -0,0 +1,34 @@
+/* unistd.h <ndf@linux.mit.edu> */
+#include <features.h>
+#include <sys/types.h>
+
+#ifndef __UNISTD_H
+#define __UNISTD_H
+
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+extern int close __P ((int));
+extern size_t read __P ((int __fd, char * __buf, size_t __nbytes));
+extern size_t write __P ((int __fd, __const char * __buf, size_t __n));
+extern off_t lseek __P ((int __fd, off_t __n, int __whence));
+extern int pipe __P ((int __pipedes[2]));
+extern unsigned int alarm __P ((unsigned int __seconds));
+extern unsigned int sleep __P ((unsigned int __seconds));
+extern int pause __P ((void));
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#ifndef R_OK
+#define R_OK 4 /* Test for read permission. */
+#define W_OK 2 /* Test for write permission. */
+#define X_OK 1 /* Test for execute permission. */
+#define F_OK 0 /* Test for existence. */
+#endif
+
+#endif /* __UNISTD_H */
diff --git a/libc-0.0.4/include/utime.h b/libc-0.0.4/include/utime.h
new file mode 100644
index 0000000..7f82b9f
--- /dev/null
+++ b/libc-0.0.4/include/utime.h
@@ -0,0 +1,15 @@
+#ifndef __UTIME_H
+#define __UTIME_H
+
+#include <features.h>
+#include <sys/types.h>
+
+struct utimbuf {
+ time_t actime;
+ time_t modtime;
+};
+
+extern int utime __P ((char *__filename, struct utimbuf *__utimebuf));
+
+#endif
+
diff --git a/libc-0.0.4/include/utmp.h b/libc-0.0.4/include/utmp.h
new file mode 100644
index 0000000..ca630a3
--- /dev/null
+++ b/libc-0.0.4/include/utmp.h
@@ -0,0 +1,48 @@
+/* utmp.h <ndf@linux.mit.edu> */
+
+#ifndef __UTMP_H
+#define __UTMP_H
+
+#include <features.h>
+#include <sys/types.h>
+#include <paths.h>
+#include <time.h>
+
+#define UT_UNKNOWN 0
+#define UT_LINESIZE 12
+#define UT_NAMESIZE 8
+#define UT_HOSTSIZE 16
+
+#define RUN_LVL 1
+#define BOOT_TIME 2
+#define NEW_TIME 3
+#define OLD_TIME 4
+
+#define INIT_PROCESS 5
+#define LOGIN_PROCESS 6
+#define USER_PROCESS 7
+#define DEAD_PROCESS 8
+
+struct utmp
+{
+ short ut_type; /* type of login */
+ pid_t ut_pid; /* pid of login-process */
+ char ut_line[UT_LINESIZE]; /* devicename of tty -"/dev/", null-term */
+ char ut_id[2]; /* abbrev. ttyname, as 01, s1 etc. */
+ time_t ut_time; /* logintime */
+ char ut_user[UT_NAMESIZE]; /* username, not null-term */
+ char ut_host[UT_HOSTSIZE]; /* hostname for remote login... */
+ long ut_addr; /* IP addr of remote host */
+
+};
+
+extern void setutent __P ((void));
+extern void utmpname __P ((__const char *));
+extern struct utmp *getutent __P ((void));
+extern struct utmp *getutid __P ((struct utmp *));
+extern struct utmp *getutline __P ((struct utmp *));
+extern void pututline __P ((struct utmp *));
+extern struct utmp *_getutline __P ((struct utmp *));
+extern void endutent __P ((void));
+
+#endif /* __UTMP_H */
diff --git a/libc-0.0.4/include/varargs.h b/libc-0.0.4/include/varargs.h
new file mode 100644
index 0000000..b5c647f
--- /dev/null
+++ b/libc-0.0.4/include/varargs.h
@@ -0,0 +1,12 @@
+
+#ifndef __VARARGS_H
+#define __VARARGS_H
+
+typedef char *va_list;
+
+#define va_dcl va_list va_alist;
+#define va_start(ap) ap = (va_list)&va_alist
+#define va_arg(ap,t) ((t *)(ap += sizeof(t)))[-1]
+#define va_end(ap) ap = NULL
+
+#endif
diff --git a/libc-0.0.4/kinclude/Config b/libc-0.0.4/kinclude/Config
new file mode 100644
index 0000000..f3d064f
--- /dev/null
+++ b/libc-0.0.4/kinclude/Config
@@ -0,0 +1 @@
+kinc: The kernel include files
diff --git a/libc-0.0.4/kinclude/arch/errno.h b/libc-0.0.4/kinclude/arch/errno.h
new file mode 100644
index 0000000..ee3fcab
--- /dev/null
+++ b/libc-0.0.4/kinclude/arch/errno.h
@@ -0,0 +1,127 @@
+#ifndef _I86_ERRNO_H
+#define _I86_ERRNO_H
+
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Arg list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+#define EDEADLK 35 /* Resource deadlock would occur */
+#define ENAMETOOLONG 36 /* File name too long */
+#define ENOLCK 37 /* No record locks available */
+#define ENOSYS 38 /* Function not implemented */
+#define ENOTEMPTY 39 /* Directory not empty */
+#define ELOOP 40 /* Too many symbolic links encountered */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+#define ENOMSG 42 /* No message of desired type */
+#define EIDRM 43 /* Identifier removed */
+#define ECHRNG 44 /* Channel number out of range */
+#define EL2NSYNC 45 /* Level 2 not synchronized */
+#define EL3HLT 46 /* Level 3 halted */
+#define EL3RST 47 /* Level 3 reset */
+#define ELNRNG 48 /* Link number out of range */
+#define EUNATCH 49 /* Protocol driver not attached */
+#define ENOCSI 50 /* No CSI structure available */
+#define EL2HLT 51 /* Level 2 halted */
+#define EBADE 52 /* Invalid exchange */
+#define EBADR 53 /* Invalid request descriptor */
+#define EXFULL 54 /* Exchange full */
+#define ENOANO 55 /* No anode */
+#define EBADRQC 56 /* Invalid request code */
+#define EBADSLT 57 /* Invalid slot */
+#define EDEADLOCK 58 /* File locking deadlock error */
+#define EBFONT 59 /* Bad font file format */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data available */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* Object is remote */
+#define ENOLINK 67 /* Link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 72 /* Multihop attempted */
+#define EDOTDOT 73 /* RFS specific error */
+#define EBADMSG 74 /* Not a data message */
+#define EOVERFLOW 75 /* Value too large for defined data type */
+#define ENOTUNIQ 76 /* Name not unique on network */
+#define EBADFD 77 /* File descriptor in bad state */
+#define EREMCHG 78 /* Remote address changed */
+#define ELIBACC 79 /* Can not access a needed shared library */
+#define ELIBBAD 80 /* Accessing a corrupted shared library */
+#define ELIBSCN 81 /* .lib section in a.out corrupted */
+#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
+#define ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define EILSEQ 84 /* Illegal byte sequence */
+#define ERESTART 85 /* Interrupted system call should be restarted */
+#define ESTRPIPE 86 /* Streams pipe error */
+#define EUSERS 87 /* Too many users */
+#define ENOTSOCK 88 /* Socket operation on non-socket */
+#define EDESTADDRREQ 89 /* Destination address required */
+#define EMSGSIZE 90 /* Message too long */
+#define EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define ENOPROTOOPT 92 /* Protocol not available */
+#define EPROTONOSUPPORT 93 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
+#define EADDRINUSE 98 /* Address already in use */
+#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define ENETDOWN 100 /* Network is down */
+#define ENETUNREACH 101 /* Network is unreachable */
+#define ENETRESET 102 /* Network dropped connection because of reset */
+#define ECONNABORTED 103 /* Software caused connection abort */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EISCONN 106 /* Transport endpoint is already connected */
+#define ENOTCONN 107 /* Transport endpoint is not connected */
+#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define ETIMEDOUT 110 /* Connection timed out */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EHOSTDOWN 112 /* Host is down */
+#define EHOSTUNREACH 113 /* No route to host */
+#define EALREADY 114 /* Operation already in progress */
+#define EINPROGRESS 115 /* Operation now in progress */
+#define ESTALE 116 /* Stale NFS file handle */
+#define EUCLEAN 117 /* Structure needs cleaning */
+#define ENOTNAM 118 /* Not a XENIX named type file */
+#define ENAVAIL 119 /* No XENIX semaphores available */
+#define EISNAM 120 /* Is a named type file */
+#define EREMOTEIO 121 /* Remote I/O error */
+#define EDQUOT 122 /* Quota exceeded */
+
+#endif
diff --git a/libc-0.0.4/kinclude/arch/ioctl.h b/libc-0.0.4/kinclude/arch/ioctl.h
new file mode 100644
index 0000000..55b276b
--- /dev/null
+++ b/libc-0.0.4/kinclude/arch/ioctl.h
@@ -0,0 +1,9 @@
+/*
+ * Nothing here yet.
+ */
+
+#ifndef _ASMI86_IOCTL_H
+#define _ASMI86_IOCTL_H
+
+
+#endif /* _ASMI86_IOCTL_H */
diff --git a/libc-0.0.4/kinclude/arch/types.h b/libc-0.0.4/kinclude/arch/types.h
new file mode 100644
index 0000000..d6690d1
--- /dev/null
+++ b/libc-0.0.4/kinclude/arch/types.h
@@ -0,0 +1,48 @@
+/* arch/i86/include/asm/types.h - Basic Linux/MT data types. */
+
+#ifndef LINUXMT_8086_TYPES
+#define LINUXMT_8086_TYPES
+
+/* First we define all of the __u and __s types...*/
+
+typedef unsigned char __u8;
+typedef unsigned char * __pu8;
+typedef char __s8;
+typedef char * __ps8;
+
+typedef unsigned int __u16;
+typedef unsigned int * __pu16;
+typedef int __s16;
+typedef int * __ps16;
+
+typedef unsigned long __u32;
+typedef unsigned long * __pu32;
+typedef long __s32;
+typedef long * __ps32;
+
+/* __uint == 16bit here */
+
+typedef unsigned int __uint;
+typedef int __sint;
+typedef unsigned int * __puint;
+typedef int * __psint;
+
+/* Then we define registers, etc... */
+
+struct _registers {
+ __u16 ksp, sp, ss, ax, bx, cx, dx, di, si, ds, es, bp, ip, cs, flags;
+};
+
+typedef struct _registers __registers;
+typedef struct _registers * __pregisters;
+
+typedef __u32 __pptr;
+
+struct _mminit {
+ __u16 cs, endcs, ds, endds, ss, endss, lowss;
+};
+
+typedef struct _mminit __arch_mminit;
+typedef struct _mminit * __parch_mminit;
+
+#endif
diff --git a/libc-0.0.4/kinclude/linuxmt/errno.h b/libc-0.0.4/kinclude/linuxmt/errno.h
new file mode 100644
index 0000000..b4c07a3
--- /dev/null
+++ b/libc-0.0.4/kinclude/linuxmt/errno.h
@@ -0,0 +1 @@
+#include "../arch/errno.h"
diff --git a/libc-0.0.4/kinclude/linuxmt/fcntl.h b/libc-0.0.4/kinclude/linuxmt/fcntl.h
new file mode 100644
index 0000000..d9188a1
--- /dev/null
+++ b/libc-0.0.4/kinclude/linuxmt/fcntl.h
@@ -0,0 +1,70 @@
+#ifndef __LINUXMT_FCNTL_H
+#define __LINUXMT_FCNTL_H
+
+/*
+ * Definitions taken from the i386 Linux kernel.
+ */
+
+/* open/fcntl */
+
+#define O_ACCMODE 0003
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 0100 /* not fcntl */
+#define O_EXCL 0200 /* not fcntl */
+#define O_NOCTTY 0400 /* not fcntl */
+#define O_TRUNC 01000 /* not fcntl */
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_NDELAY O_NONBLOCK
+#if 0
+#define O_SYNC 010000 /* Not supported */
+#define FASYNC 020000 /* Not supported */
+#endif
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get f_flags */
+#define F_SETFD 2 /* set f_flags */
+#define F_GETFL 3 /* more flags (cloexec) */
+#define F_SETFL 4
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+
+#define F_SETOWN 8 /* for sockets. */
+#define F_GETOWN 9 /* for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#ifdef __KERNEL__
+#define F_POSIX 1
+#define F_FLOCK 2
+#endif /* __KERNEL__ */
+
+struct flock {
+ short l_type;
+ short l_whence;
+ off_t l_start;
+ off_t l_len;
+ pid_t l_pid;
+};
+
+#endif
diff --git a/libc-0.0.4/kinclude/linuxmt/ioctl.h b/libc-0.0.4/kinclude/linuxmt/ioctl.h
new file mode 100644
index 0000000..20f5ac6
--- /dev/null
+++ b/libc-0.0.4/kinclude/linuxmt/ioctl.h
@@ -0,0 +1 @@
+#include "../arch/ioctl.h"
diff --git a/libc-0.0.4/kinclude/linuxmt/stat.h b/libc-0.0.4/kinclude/linuxmt/stat.h
new file mode 100644
index 0000000..0eb1c0e
--- /dev/null
+++ b/libc-0.0.4/kinclude/linuxmt/stat.h
@@ -0,0 +1,55 @@
+#ifndef _LINUX_STAT_H
+#define _LINUX_STAT_H
+
+#ifdef __KERNEL__
+
+#include "../arch/stat.h"
+
+#endif
+
+#define S_IFMT 00170000
+#ifdef __LINUXMT_NETWORK__
+#define S_IFSOCK 0140000
+#endif
+#define S_IFLNK 0120000
+#define S_IFREG 0100000
+#define S_IFBLK 0060000
+#define S_IFDIR 0040000
+#define S_IFCHR 0020000
+#define S_IFIFO 0010000
+#define S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
+
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+
+#define S_IRWXU 00700
+#define S_IRUSR 00400
+#define S_IWUSR 00200
+#define S_IXUSR 00100
+
+#define S_IRWXG 00070
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+
+#define S_IRWXO 00007
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+
+#ifdef __KERNEL__
+#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
+#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
+#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
+#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
+#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
+#endif
+
+#endif
diff --git a/libc-0.0.4/kinclude/linuxmt/termios.h b/libc-0.0.4/kinclude/linuxmt/termios.h
new file mode 100644
index 0000000..52bde9a
--- /dev/null
+++ b/libc-0.0.4/kinclude/linuxmt/termios.h
@@ -0,0 +1,258 @@
+#ifndef _LINUXMT_TERMIOS_H
+#define _LINUXMT_TERMIOS_H
+#include <linuxmt/types.h>
+
+/* This is just a magic number to make these relatively unique ('T') */
+#define __TERMIOS_MAJ ('T'<<8)
+
+#define TCGETS (__TERMIOS_MAJ+0x01)
+#define TCSETS (__TERMIOS_MAJ+0x02)
+#define TCSETSW (__TERMIOS_MAJ+0x03)
+#define TCSETSF (__TERMIOS_MAJ+0x04)
+#define TCGETA (__TERMIOS_MAJ+0x05)
+#define TCSETA (__TERMIOS_MAJ+0x06)
+#define TCSETAW (__TERMIOS_MAJ+0x07)
+#define TCSETAF (__TERMIOS_MAJ+0x08)
+#define TCSBRK (__TERMIOS_MAJ+0x09)
+#define TCXONC (__TERMIOS_MAJ+0x0A)
+#define TCFLSH (__TERMIOS_MAJ+0x0B)
+#define TIOCEXCL (__TERMIOS_MAJ+0x0C)
+#define TIOCNXCL (__TERMIOS_MAJ+0x0D)
+#define TIOCSCTTY (__TERMIOS_MAJ+0x0E)
+#define TIOCGPGRP (__TERMIOS_MAJ+0x0F)
+#define TIOCSPGRP (__TERMIOS_MAJ+0x10)
+#define TIOCOUTQ (__TERMIOS_MAJ+0x11)
+#define TIOCSTI (__TERMIOS_MAJ+0x12)
+#define TIOCGWINSZ (__TERMIOS_MAJ+0x13)
+#define TIOCSWINSZ (__TERMIOS_MAJ+0x14)
+#define TIOCMGET (__TERMIOS_MAJ+0x15)
+#define TIOCMBIS (__TERMIOS_MAJ+0x16)
+#define TIOCMBIC (__TERMIOS_MAJ+0x17)
+#define TIOCMSET (__TERMIOS_MAJ+0x18)
+#define TIOCGSOFTCAR (__TERMIOS_MAJ+0x19)
+#define TIOCSSOFTCAR (__TERMIOS_MAJ+0x1A)
+#define FIONREAD (__TERMIOS_MAJ+0x1B)
+#define TIOCINQ FIONREAD
+#define TIOCLINUX (__TERMIOS_MAJ+0x1C)
+#define TIOCCONS (__TERMIOS_MAJ+0x1D)
+#define TIOCGSERIAL (__TERMIOS_MAJ+0x1E)
+#define TIOCSSERIAL (__TERMIOS_MAJ+0x1F)
+#define TIOCPKT (__TERMIOS_MAJ+0x20)
+#define FIONBIO (__TERMIOS_MAJ+0x21)
+#define TIOCNOTTY (__TERMIOS_MAJ+0x22)
+#define TIOCSETD (__TERMIOS_MAJ+0x23)
+#define TIOCGETD (__TERMIOS_MAJ+0x24)
+#define TCSBRKP (__TERMIOS_MAJ+0x25) /* Needed for POSIX tcsendbreak */
+#define TIOCTTYGSTRUCT (__TERMIOS_MAJ+0x26) /* For debugging only */
+#define FIONCLEX (__TERMIOS_MAJ+0x50) /* these numbers need to be adjusted. */
+#define FIOCLEX (__TERMIOS_MAJ+0x51)
+#define FIOASYNC (__TERMIOS_MAJ+0x52)
+#define TIOCSERCONFIG (__TERMIOS_MAJ+0x53)
+#define TIOCSERGWILD (__TERMIOS_MAJ+0x54)
+#define TIOCSERSWILD (__TERMIOS_MAJ+0x55)
+#define TIOCGLCKTRMIOS (__TERMIOS_MAJ+0x56)
+#define TIOCSLCKTRMIOS (__TERMIOS_MAJ+0x57)
+#define TIOCSERGSTRUCT (__TERMIOS_MAJ+0x58) /* For debugging only */
+#define TIOCSERGETLSR (__TERMIOS_MAJ+0x59) /* Get line status register */
+#define TIOCSERGETMULTI (__TERMIOS_MAJ+0x5A) /* Get multiport config */
+#define TIOCSERSETMULTI (__TERMIOS_MAJ+0x5B) /* Set multiport config */
+
+/* Used for packet mode */
+#define TIOCPKT_DATA 0
+#define TIOCPKT_FLUSHREAD 1
+#define TIOCPKT_FLUSHWRITE 2
+#define TIOCPKT_STOP 4
+#define TIOCPKT_START 8
+#define TIOCPKT_NOSTOP 16
+#define TIOCPKT_DOSTOP 32
+
+struct winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+ unsigned short ws_xpixel;
+ unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+ unsigned short c_iflag; /* input mode flags */
+ unsigned short c_oflag; /* output mode flags */
+ unsigned short c_cflag; /* control mode flags */
+ unsigned short c_lflag; /* local mode flags */
+ unsigned char c_line; /* line discipline */
+ unsigned char c_cc[NCC]; /* control characters */
+};
+
+#define NCCS 19
+struct termios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK 0000020
+#define ISTRIP 0000040
+#define INLCR 0000100
+#define IGNCR 0000200
+#define ICRNL 0000400
+#define IUCLC 0001000
+#define IXON 0002000
+#define IXANY 0004000
+#define IXOFF 0010000
+#define IMAXBEL 0020000
+
+/* c_oflag bits */
+#define OPOST 0000001
+#define OLCUC 0000002
+#define ONLCR 0000004
+#define OCRNL 0000010
+#define ONOCR 0000020
+#define ONLRET 0000040
+#define OFILL 0000100
+#define OFDEL 0000200
+#define NLDLY 0000400
+#define NL0 0000000
+#define NL1 0000400
+#define CRDLY 0003000
+#define CR0 0000000
+#define CR1 0001000
+#define CR2 0002000
+#define CR3 0003000
+#define TABDLY 0014000
+#define TAB0 0000000
+#define TAB1 0004000
+#define TAB2 0010000
+#define TAB3 0014000
+#define XTABS 0014000
+#define BSDLY 0020000
+#define BS0 0000000
+#define BS1 0020000
+#define VTDLY 0040000
+#define VT0 0000000
+#define VT1 0040000
+#define FFDLY 0100000
+#define FF0 0000000
+#define FF1 0100000
+
+/* c_cflag bit meaning */
+#define CBAUD 0010017
+#define B0 0000000 /* hang up */
+#define B50 0000001
+#define B75 0000002
+#define B110 0000003
+#define B134 0000004
+#define B150 0000005
+#define B200 0000006
+#define B300 0000007
+#define B600 0000010
+#define B1200 0000011
+#define B1800 0000012
+#define B2400 0000013
+#define B4800 0000014
+#define B9600 0000015
+#define B19200 0000016
+#define B38400 0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE 0000060
+#define CS5 0000000
+#define CS6 0000020
+#define CS7 0000040
+#define CS8 0000060
+#define CSTOPB 0000100
+#define CREAD 0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL 0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CRTSCTS 020000000000 /* flow control */
+
+/* c_lflag bits */
+#define ISIG 0000001
+#define ICANON 0000002
+#define XCASE 0000004
+#define ECHO 0000010
+#define ECHOE 0000020
+#define ECHOK 0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL 0001000
+#define ECHOPRT 0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+
+/* modem lines */
+#define TIOCM_LE 0x001
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_ST 0x008
+#define TIOCM_SR 0x010
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RNG 0x080
+#define TIOCM_DSR 0x100
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RI TIOCM_RNG
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+
+
+/* tcflow() and TCXONC use these */
+#define TCOOFF 0
+#define TCOON 1
+#define TCIOFF 2
+#define TCION 3
+
+/* tcflush() and TCFLSH use these */
+#define TCIFLUSH 0
+#define TCOFLUSH 1
+#define TCIOFLUSH 2
+
+/* tcsetattr uses these */
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+/* line disciplines */
+#define N_TTY 0
+#define N_SLIP 1
+#define N_MOUSE 2
+#define N_PPP 3
+
+#endif /* _LINUXMT_TERMIOS_H */
diff --git a/libc-0.0.4/kinclude/linuxmt/types.h b/libc-0.0.4/kinclude/linuxmt/types.h
new file mode 100644
index 0000000..b38f81c
--- /dev/null
+++ b/libc-0.0.4/kinclude/linuxmt/types.h
@@ -0,0 +1,31 @@
+#ifndef __LINUXMT_TYPES_H
+#define __LINUXMT_TYPES_H
+
+#include "../arch/types.h"
+
+/* Throw away _FUNCTION parameters - the syntax is ripped off of Minix's
+ _PROTOTYPE. Considering Borland did the same thing to MFC on a bigger
+ scale, I don't think PH will mind :) */
+
+/* Yes, this should be in arch/types.h too */
+
+#define _FUNCTION(function, params) function()
+#define _VFUNCTION(functiom, params) (*function) ()
+
+typedef __u32 off_t;
+typedef __u16 pid_t;
+typedef __u16 uid_t;
+typedef __u16 gid_t;
+typedef __u32 time_t;
+typedef __u16 umode_t;
+typedef __u16 nlink_t;
+typedef __u16 mode_t;
+typedef __u32 loff_t;
+
+typedef __u16 dev_t;
+typedef __u16 ino_t;
+typedef __u32 tcflag_t;
+typedef __u8 cc_t;
+
+#endif
+
diff --git a/libc-0.0.4/libc.a b/libc-0.0.4/libc.a
new file mode 100644
index 0000000..a02a759
--- /dev/null
+++ b/libc-0.0.4/libc.a
Binary files differ
diff --git a/libc-0.0.4/malloc1/Config b/libc-0.0.4/malloc1/Config
new file mode 100644
index 0000000..4404398
--- /dev/null
+++ b/libc-0.0.4/malloc1/Config
@@ -0,0 +1 @@
+malloc: Robert's malloc routines
diff --git a/libc-0.0.4/malloc1/Makefile b/libc-0.0.4/malloc1/Makefile
new file mode 100644
index 0000000..d4aa9cf
--- /dev/null
+++ b/libc-0.0.4/malloc1/Makefile
@@ -0,0 +1,24 @@
+
+TOP=..
+include $(TOP)/Make.defs
+
+ASRC=malloc.c
+AOBJ=malloc.o alloca.o free.o calloc.o realloc.o
+
+OBJ=$(AOBJ)
+
+all: $(OBJ)
+
+$(LIBC): $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f $(OBJ) libc.a
+
+$(AOBJ): $(ASRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ASRC)
+
+transfer:
+ -@rm ../include/malloc.h
+ cp -p malloc.h ../include/.
diff --git a/libc-0.0.4/malloc1/README b/libc-0.0.4/malloc1/README
new file mode 100644
index 0000000..95f5928
--- /dev/null
+++ b/libc-0.0.4/malloc1/README
@@ -0,0 +1,9 @@
+Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+This file is part of the Linux-8086 C library and is distributed
+under the GNU Library General Public License.
+
+This is a combined alloca/malloc package. It uses a classic algorithm
+and so may be seen to be quite slow compared to more modern routines
+with 'nasty' distributions of allocation.
+
+-Robert
diff --git a/libc-0.0.4/malloc1/malloc.c b/libc-0.0.4/malloc1/malloc.c
new file mode 100644
index 0000000..687a84b
--- /dev/null
+++ b/libc-0.0.4/malloc1/malloc.c
@@ -0,0 +1,540 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/*
+ * This is a combined alloca/malloc package. It uses a classic algorithm
+ * and so may be seen to be quite slow compared to more modern routines
+ * with 'nasty' distributions.
+ */
+
+#include <malloc.h>
+#include <errno.h>
+
+#define MCHUNK 2048 /* Allocation unit in 'mem' elements */
+#define XLAZY_FREE /* If set frees can be infinitly defered */
+#define XMINALLOC 32 /* Smallest chunk to alloc in 'mem's */
+#define XVERBOSE /* Lots of noise, debuging ? */
+
+#undef malloc
+#define MAX_INT ((int)(((unsigned)-1)>>1))
+
+#ifdef VERBOSE
+#define noise __noise
+#else
+#define noise(y,x)
+#endif
+
+typedef union mem_cell
+{
+ union mem_cell *next; /* A pointer to the next mem */
+ unsigned int size; /* An int >= sizeof pointer */
+ char *depth; /* For the alloca hack */
+}
+mem;
+
+#define m_size(p) ((p) [0].size) /* For malloc */
+#define m_next(p) ((p) [1].next) /* For malloc and alloca */
+#define m_deep(p) ((p) [0].depth) /* For alloca */
+
+extern void *__mini_malloc __P ((unsigned int));
+extern void *(*__alloca_alloc) __P ((unsigned int));
+extern mem *__freed_list;
+
+#ifdef L_free
+/* Start the alloca with just the dumb version of malloc */
+
+void *(*__alloca_alloc) __P ((unsigned int)) = __mini_malloc;
+mem *__freed_list = 0;
+
+#ifdef VERBOSE
+/* NB: Careful here, stdio may use malloc - so we can't */
+static
+phex(val)
+{
+ static char hex[] = "0123456789ABCDEF";
+ int i;
+ for (i = sizeof(int)*8-4; i >= 0; i -= 4)
+ write(2, hex + ((val >> i) & 0xF), 1);
+}
+
+noise(y, x)
+char *y;
+mem *x;
+{
+ write(2, "Malloc ", 7);
+ phex(x);
+ write(2, " sz ", 4);
+ if(x) phex(m_size(x)); else phex(0);
+ write(2, " nxt ", 5);
+ if(x) phex(m_next(x)); else phex(0);
+ write(2, " is ", 4);
+ write(2, y, strlen(y));
+ write(2, "\n", 1);
+}
+#endif
+
+#endif
+
+#ifdef L_alloca
+static mem *alloca_stack = 0;
+
+void *
+alloca(size)
+unsigned size;
+{
+ auto char probe; /* Probes stack depth: */
+ register mem *hp;
+
+ /*
+ * Reclaim garbage, defined as all alloca'd storage that was allocated
+ * from deeper in the stack than currently.
+ */
+
+ for (hp = alloca_stack; hp != 0;)
+ if (m_deep(hp) < &probe)
+ {
+ register mem *np = m_next(hp);
+ free((void *) hp); /* Collect garbage. */
+ hp = np; /* -> next header. */
+ }
+ else
+ break; /* Rest are not deeper. */
+
+ alloca_stack = hp; /* -> last valid storage. */
+ if (size == 0)
+ return 0; /* No allocation required. */
+
+ hp = (mem *) (*__alloca_alloc) (sizeof(mem) + size);
+ if (hp == 0)
+ return hp;
+
+ m_next(hp) = alloca_stack;
+ m_deep(hp) = &probe;
+ alloca_stack = hp;
+
+ /* User storage begins just after header. */
+ return (void *) (hp + 2);
+}
+#endif /* L_alloca */
+
+#ifdef L_free
+void
+free(ptr)
+void *ptr;
+{
+ register mem *top;
+ register mem *chk = (mem *) ptr;
+
+ if (chk == 0)
+ return; /* free(NULL) - be nice */
+ chk--;
+
+ try_this:;
+ top = (mem *) sbrk(0);
+ if (chk + m_size(chk) == top)
+ {
+ noise("FREE sbrk", chk);
+ sbrk(-m_size(chk) * sizeof(mem));
+ /*
+ * Adding this code allow free to release blocks in any order; they
+ * can still only be allocated from the top of the heap tho.
+ */
+#ifdef __MINI_MALLOC__
+ if (__alloca_alloc == __mini_malloc && __freed_list)
+ {
+ mem *prev, *curr;
+ chk = __freed_list;
+ __freed_list = m_next(__freed_list);
+ goto try_this;
+ }
+#endif
+ }
+ else
+ { /* Nope, not sure where this goes, leave
+ * it for malloc to deal with */
+#ifdef __MINI_MALLOC__
+ if( __freed_list || chk > __freed_list )
+ { m_next(chk) = __freed_list; __freed_list = chk; }
+ else
+ {
+ register mem *prev;
+ prev=__freed_list;
+ for(top=__freed_list; top && top > chk; prev=top, top=m_next(top))
+ ;
+ m_next(chk) = top;
+ m_next(prev) = chk;
+ }
+#else
+ m_next(chk) = __freed_list;
+ __freed_list = chk;
+#endif
+ noise("ADD LIST", chk);
+ }
+}
+
+void *
+__mini_malloc(size)
+unsigned int size;
+{
+ register mem *ptr;
+ register unsigned int sz;
+
+ /* First time round this _might_ be odd, But we won't do that! */
+ sz = (unsigned int) sbrk(0);
+ if (sz & (sizeof(mem) - 1))
+ sbrk(4 - (sz & (sizeof(mem) - 1)));
+
+ if (size <= 0)
+ return 0;
+ /* Minor oops here, sbrk has a signed argument */
+ if( size > (((unsigned)-1)>>1)-sizeof(mem)*3 )
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ size += sizeof(mem) * 2 - 1; /* Round up and leave space for size field */
+ size /= sizeof(mem);
+
+ ptr = (mem *) sbrk(size * sizeof(mem));
+ if ((int) ptr == -1)
+ return 0;
+
+ m_size(ptr) = size;
+ noise("CREATE", ptr);
+ return ptr + 1;
+}
+#endif /* L_free */
+
+#ifdef L_malloc
+
+/*
+ * The chunk_list pointer is either NULL or points to a chunk in a
+ * circular list of all the free blocks in memory
+ */
+
+static mem *chunk_list = 0;
+static void insert_chunk();
+static mem *search_chunk();
+
+void *
+malloc(size)
+unsigned int size;
+{
+ register mem *ptr = 0;
+ register unsigned int sz;
+
+ if (size == 0)
+ return 0; /* ANSI STD */
+
+ sz = size + sizeof(mem) * 2 - 1;
+ sz /= sizeof(mem);
+
+#ifdef MINALLOC
+ if (sz < MINALLOC)
+ sz = MINALLOC;
+#endif
+
+#ifdef VERBOSE
+ {
+ static mem arr[2];
+ m_size(arr) = sz;
+ noise("WANTED", arr);
+ }
+#endif
+
+ __alloca_alloc = malloc; /* We'll be messing with the heap now TVM */
+
+#ifdef LAZY_FREE
+ ptr = search_chunk(sz);
+ if (ptr == 0)
+ {
+#endif
+
+ /* First deal with the freed list */
+ if (__freed_list)
+ {
+ while (__freed_list)
+ {
+ ptr = __freed_list;
+ __freed_list = m_next(__freed_list);
+
+ if (m_size(ptr) == sz) /* Oh! Well that's lucky ain't it
+ * :-) */
+ {
+ noise("LUCKY MALLOC", ptr);
+ return ptr + 1;
+ }
+
+ insert_chunk(ptr);
+ }
+ ptr = m_next(chunk_list);
+ if (m_size(ptr) < (MAX_INT/sizeof(mem))
+ && ptr + m_size(ptr) == (void *) sbrk(0))
+ {
+ /* Time to free for real */
+ m_next(chunk_list) = m_next(ptr);
+ if (ptr == m_next(ptr))
+ chunk_list = 0;
+ free(ptr + 1);
+ }
+#ifdef LAZY_FREE
+ ptr = search_chunk(sz);
+#endif
+ }
+#ifndef LAZY_FREE
+ ptr = search_chunk(sz);
+#endif
+ if (ptr == 0)
+ {
+#ifdef MCHUNK
+ unsigned int alloc;
+ alloc = sizeof(mem) * (MCHUNK * ((sz + MCHUNK - 1) / MCHUNK) - 1);
+ ptr = __mini_malloc(alloc);
+ if (ptr)
+ insert_chunk(ptr - 1);
+ else /* Oooo, near end of RAM */
+ {
+ for(alloc/=2; alloc>256; )
+ {
+ ptr = __mini_malloc(alloc);
+ if (ptr) insert_chunk(ptr - 1);
+ else alloc/=2;
+ }
+ }
+ ptr = search_chunk(sz);
+ if (ptr == 0)
+#endif
+ {
+#ifndef MCHUNK
+ ptr = __mini_malloc(size);
+#endif
+#ifdef VERBOSE
+ if( ptr == 0 )
+ noise("MALLOC FAIL", 0);
+ else
+ noise("MALLOC NOW", ptr - 1);
+#endif
+ return ptr;
+ }
+ }
+#ifdef LAZY_FREE
+ }
+#endif
+
+#ifdef VERBOSE
+ ptr[1].size = 0x55555555;
+#endif
+ noise("MALLOC RET", ptr);
+ return ptr + 1;
+}
+
+/*
+ * This function takes a pointer to a block of memory and inserts it into
+ * the chain of memory chunks
+ */
+
+static void
+insert_chunk(mem_chunk)
+mem *mem_chunk;
+{
+ register mem *p1, *p2;
+ if (chunk_list == 0) /* Simple case first */
+ {
+ m_next(mem_chunk) = chunk_list = mem_chunk;
+ noise("FIRST CHUNK", mem_chunk);
+ return;
+ }
+ p1 = mem_chunk;
+ p2 = chunk_list;
+
+ do
+ {
+ if (p1 > p2)
+ {
+ if (m_next(p2) <= p2)
+ { /* We're at the top of the chain, p1 is
+ * higher */
+
+ if (p2 + m_size(p2) == p1)
+ { /* Good, stick 'em together */
+ noise("INSERT CHUNK", mem_chunk);
+ m_size(p2) += m_size(p1);
+ noise("JOIN 1", p2);
+ }
+ else
+ {
+ m_next(p1) = m_next(p2);
+ m_next(p2) = p1;
+ noise("INSERT CHUNK", mem_chunk);
+ noise("FROM", p2);
+ }
+ return;
+ }
+ if (m_next(p2) > p1)
+ {
+ /* In chain, p1 between p2 and next */
+
+ m_next(p1) = m_next(p2);
+ m_next(p2) = p1;
+ noise("INSERT CHUNK", mem_chunk);
+ noise("FROM", p2);
+
+ /* Try to join above */
+ if (p1 + m_size(p1) == m_next(p1))
+ {
+ m_size(p1) += m_size(m_next(p1));
+ m_next(p1) = m_next(m_next(p1));
+ noise("JOIN 2", p1);
+ }
+ /* Try to join below */
+ if (p2 + m_size(p2) == p1)
+ {
+ m_size(p2) += m_size(p1);
+ m_next(p2) = m_next(p1);
+ noise("JOIN 3", p2);
+ }
+ chunk_list = p2; /* Make sure it's valid */
+ return;
+ }
+ }
+ else if (p1 < p2)
+ {
+ if (m_next(p2) <= p2 && p1 < m_next(p2))
+ {
+ /* At top of chain, next is bottom of chain, p1 is below next */
+
+ m_next(p1) = m_next(p2);
+ m_next(p2) = p1;
+ noise("INSERT CHUNK", mem_chunk);
+ noise("FROM", p2);
+ chunk_list = p2;
+
+ if (p1 + m_size(p1) == m_next(p1))
+ {
+ if (p2 == m_next(p1))
+ chunk_list = p1;
+ m_size(p1) += m_size(m_next(p1));
+ m_next(p1) = m_next(m_next(p1));
+ noise("JOIN 4", p1);
+ }
+ return;
+ }
+ }
+ chunk_list = p2; /* Save for search */
+ p2 = m_next(p2);
+ }
+ while (p2 != chunk_list);
+
+ /* If we get here we have a problem, ignore it, maybe it'll go away */
+ noise("DROPPED CHUNK", mem_chunk);
+}
+
+/*
+ * This function will search for a chunk in memory of at least 'mem_size'
+ * when found, if the chunk is too big it'll be split, and pointer to the
+ * chunk returned. If none is found NULL is returned.
+ */
+
+static mem *
+search_chunk(mem_size)
+unsigned int mem_size;
+{
+ register mem *p1, *p2;
+ if (chunk_list == 0) /* Simple case first */
+ return 0;
+
+ /* Search for a block >= the size we want */
+ p1 = m_next(chunk_list);
+ p2 = chunk_list;
+ do
+ {
+ noise("CHECKED", p1);
+ if (m_size(p1) >= mem_size)
+ break;
+
+ p2 = p1;
+ p1 = m_next(p1);
+ }
+ while (p2 != chunk_list);
+
+ /* None found, exit */
+ if (m_size(p1) < mem_size)
+ return 0;
+
+ /* If it's exactly right remove it */
+ if (m_size(p1) < mem_size + 2)
+ {
+ noise("FOUND RIGHT", p1);
+ chunk_list = m_next(p2) = m_next(p1);
+ if (chunk_list == p1)
+ chunk_list = 0;
+ return p1;
+ }
+
+ noise("SPLIT", p1);
+ /* Otherwise split it */
+ m_next(p2) = p1 + mem_size;
+ chunk_list = p2;
+
+ p2 = m_next(p2);
+ m_size(p2) = m_size(p1) - mem_size;
+ m_next(p2) = m_next(p1);
+ m_size(p1) = mem_size;
+ if (chunk_list == p1)
+ chunk_list = p2;
+#ifdef VERBOSE
+ p1[1].size = 0xAAAAAAAA;
+#endif
+ noise("INSERT CHUNK", p2);
+ noise("FOUND CHUNK", p1);
+ noise("LIST IS", chunk_list);
+ return p1;
+}
+
+#endif /* L_malloc */
+
+#ifdef L_calloc
+void *
+calloc(elm, sz)
+unsigned int elm, sz;
+{
+ register unsigned int v;
+ register void *ptr;
+ ptr = malloc(v = elm * sz);
+ if (ptr)
+ memset(ptr, 0, v);
+ return ptr;
+}
+#endif /* L_calloc */
+
+#ifdef L_realloc
+void *
+realloc(ptr, size)
+void *ptr;
+unsigned int size;
+{
+ void *nptr;
+ unsigned int osize;
+ if (ptr == 0)
+ return malloc(size);
+
+ osize = (m_size(((mem *) ptr) - 1) - 1) * sizeof(mem);
+ if (size <= osize)
+ {
+ return ptr;
+ }
+
+ nptr = malloc(size);
+
+ if (nptr == 0)
+ return 0;
+
+ memcpy(nptr, ptr, osize);
+ free(ptr);
+
+ return nptr;
+}
+#endif /* L_realloc */
diff --git a/libc-0.0.4/malloc1/malloc.h b/libc-0.0.4/malloc1/malloc.h
new file mode 100644
index 0000000..c00fa21
--- /dev/null
+++ b/libc-0.0.4/malloc1/malloc.h
@@ -0,0 +1,29 @@
+
+#ifndef __MALLOC_H
+#define __MALLOC_H
+#include <features.h>
+
+/*
+ * Mini malloc allows you to use a less efficient but smaller malloc the
+ * cost is about 100 bytes of code in free but malloc (700bytes) doesn't
+ * have to be linked. Unfortunatly memory can only be reused if everything
+ * above it has been freed
+ *
+ */
+
+void free __P((void *));
+void *malloc __P((unsigned int));
+void *realloc __P((void *, unsigned int));
+void *alloca __P((unsigned int));
+
+extern void *(*__alloca_alloc) __P((unsigned int));
+
+#ifdef __LIBC__
+#define __MINI_MALLOC__
+#endif
+
+#ifdef __MINI_MALLOC__
+#define malloc(x) ((*__alloca_alloc)(x))
+#endif
+
+#endif
diff --git a/libc-0.0.4/malloc2/Config b/libc-0.0.4/malloc2/Config
new file mode 100644
index 0000000..11c476d
--- /dev/null
+++ b/libc-0.0.4/malloc2/Config
@@ -0,0 +1 @@
+malloc: Joel's malloc functions
diff --git a/libc-0.0.4/malloc2/README b/libc-0.0.4/malloc2/README
new file mode 100644
index 0000000..ecf3fd2
--- /dev/null
+++ b/libc-0.0.4/malloc2/README
@@ -0,0 +1,19 @@
+This is just the malloc for libc. It is untested; it won't even compile
+right now. In particular, __malloc_init needs some bug fixing!
+
+Apparently, there is another malloc that Robert Debath wrote which probably
+works by now. However, I honestly think that my malloc may be just as
+good when it's finished.
+
+In about six months, you'll probably see something like this:
+
+
+Linux/less-than-32-bit installation program
+Do you want
+ 1. Chad Page's kernel
+ 2. Alan Cox's kernel
+Enter your chioce --> 2
+Do you want
+ 1. Robert Debath's malloc
+ 2. Joel Weber's malloc
+[more choices for compilers, filetools, etc]
diff --git a/libc-0.0.4/malloc2/makefile b/libc-0.0.4/malloc2/makefile
new file mode 100644
index 0000000..8678d62
--- /dev/null
+++ b/libc-0.0.4/malloc2/makefile
@@ -0,0 +1,23 @@
+
+TOP=..
+include $(TOP)/Make.defs
+
+MOBJ=malloc.o stack.o
+
+OBJ=$(MOBJ)
+
+all: $(OBJ)
+
+libc.a: $(OBJ)
+ ar r ../libc.a $(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f $(OBJ) libc.a
+
+$(AOBJ): $(ASRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ASRC)
+
+transfer:
+ -@rm ../include/malloc.h
+ cp -p malloc.h ../include/.
diff --git a/libc-0.0.4/malloc2/malloc.c b/libc-0.0.4/malloc2/malloc.c
new file mode 100644
index 0000000..143d324
--- /dev/null
+++ b/libc-0.0.4/malloc2/malloc.c
@@ -0,0 +1,127 @@
+/* simplified linux malloc.h
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <malloc.h>
+
+typedef struct __malloc_struct malloc_struct;
+
+typedef union __malloc_union
+{
+ char *c;
+ malloc_struct *m;
+} malloc_union;
+
+
+struct __malloc_struct
+{
+ unsigned char status;
+#define ALLOC 0x53
+#define FREE 0x55
+#define END_OF_WORLD 0x57
+ malloc_union next;
+} *malloc_start;
+
+extern int __STACKSIZE;
+
+/* WARNING: this init will only work if there is a hard limit on the
+ amount of RAM that can be allocated.
+ */
+
+#ifdef __AS386_16__
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word _malloc_init ! Pointer to the autorun function
+ .word no_op ! Space filler cause segs are padded to 4 bytes.
+ .text ! So the function after is also in the correct seg.
+#endasm
+#endif
+
+malloc_init()
+{
+ extern unsigned int sbrk();
+
+ unsigned int ptr, sz, count;
+
+ malloc_start = (malloc_struct*) ((sbrk(16)+1)&~1);
+ malloc_start->status = FREE;
+
+ count=254;
+ for(sz=16384; sz>64; )
+ {
+ ptr= sbrk(sz);
+ if( ptr == (unsigned)-1 ) sz>>=1;
+ else count+=sz;
+ }
+ if( __STACKSIZE > count || __STACKSIZE <= 0 ) __STACKSIZE = ((count>>1)&-2);
+ ptr = sbrk(-__STACKSIZE);
+
+ malloc_start->next.m = ((malloc_struct*)ptr) - 1;
+
+ malloc_start->next.m->status = END_OF_WORLD;
+}
+
+char *malloc(size)
+size_t size;
+{
+ register malloc_union tmp, tmp2;
+
+ /* Make sure we don't lose the alignment */
+ size = (size+sizeof(malloc_struct)-1)/sizeof(malloc_struct);
+
+ tmp.m = malloc_start;
+ while ( ( tmp.m->next.m - tmp.m - 2 ) < size
+ || ( tmp.m->status == ALLOC ))
+ tmp.m = tmp.m->next.m;
+
+ if (tmp.m->status == FREE){
+ tmp2.m = size + tmp.m + 1;
+ tmp2.m->status = FREE;
+ tmp2.m->next.c = tmp.m->next.c;
+ tmp.m->status = ALLOC;
+ tmp.m->next.c = tmp2.c;
+ }
+ else return 0;
+ tmp.m++;
+ return tmp.c;
+}
+
+__malloc_cleanup() /* finds consecutive free blocks and joins them */
+{
+ malloc_struct *tmp;
+
+ tmp = malloc_start;
+ while ((tmp->status != END_OF_WORLD)&&(tmp->next.m->status != END_OF_WORLD)){
+ if ((tmp->status==FREE)&&(tmp->next.m->status==FREE))
+ tmp->next.m = tmp->next.m->next.m;
+ else tmp = tmp->next.m;
+ }
+}
+
+free(what)
+char *what;
+{
+ malloc_union tmp;
+
+ tmp.c = what; tmp.m--;
+ if( tmp.m->status == ALLOC )
+ {
+ tmp.m->status = FREE;
+ __malloc_cleanup;
+ }
+}
diff --git a/libc-0.0.4/malloc2/malloc.h b/libc-0.0.4/malloc2/malloc.h
new file mode 100644
index 0000000..ffcb3a4
--- /dev/null
+++ b/libc-0.0.4/malloc2/malloc.h
@@ -0,0 +1,21 @@
+/* simplified linux malloc.h
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+char *malloc(size);
+void free(what);
+char *realloc(what, size);
diff --git a/libc-0.0.4/malloc2/stack.c b/libc-0.0.4/malloc2/stack.c
new file mode 100644
index 0000000..5f33e21
--- /dev/null
+++ b/libc-0.0.4/malloc2/stack.c
@@ -0,0 +1,10 @@
+
+/*
+ * Under Linux 8086 the stack and heap areas are at the top and bottom
+ * of the same area of memory, this version of malloc requires that the
+ * malloc area is of a fixed size this means that there must also be a
+ * specific amount of stack space reserved outside of this. The number
+ * of bytes to be reserved is specified below.
+ */
+
+int __STACKSIZE = 2048;
diff --git a/libc-0.0.4/misc/Config b/libc-0.0.4/misc/Config
new file mode 100644
index 0000000..9ede0c2
--- /dev/null
+++ b/libc-0.0.4/misc/Config
@@ -0,0 +1 @@
+misc: Various unix lib functions
diff --git a/libc-0.0.4/misc/Makefile b/libc-0.0.4/misc/Makefile
new file mode 100644
index 0000000..b136fc4
--- /dev/null
+++ b/libc-0.0.4/misc/Makefile
@@ -0,0 +1,45 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+MSRC=aliases.c
+MOBJ=abs.o raise.o bcopy.o bzero.o bcmp.o index.o rindex.o remove.o creat.o
+
+ESRC=atexit.c
+EOBJ=on_exit.o atexit.o __do_exit.o
+
+OBJ=$(MOBJ) $(EOBJ) \
+ atoi.o atol.o ltoa.o ltostr.o \
+ ctype.o qsort.o bsearch.o rand.o lsearch.o getopt.o \
+ getenv.o putenv.o itoa.o cputype.o \
+ strtol.o popen.o system.o
+
+# No ELKS strtod() until BCC does 16 bit FP...
+ifeq ($(PLATFORM),i386-Linux)
+OBJ+=strtod.o
+endif
+
+all: $(OBJ)
+
+$(LIBC): $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f $(OBJ) libc.a
+
+$(MOBJ): $(MSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(MSRC)
+
+$(EOBJ): $(ESRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ESRC)
+
+strto%.o: strto%.c
+ifeq ($(PLATFORM),i386-Linux)
+ $(CC) $(CFLAGS) $< -c -o $@ $(WALL)
+else
+ $(CC) $(CFLAGS) $< -c -o $@ -ansi
+endif
diff --git a/libc-0.0.4/misc/aliases.c b/libc-0.0.4/misc/aliases.c
new file mode 100644
index 0000000..466cb74
--- /dev/null
+++ b/libc-0.0.4/misc/aliases.c
@@ -0,0 +1,109 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+#include <string.h>
+#include <sys/types.h>
+
+#ifdef L_abs
+int
+abs(arg1)
+int arg1;
+{
+ return arg1>0?arg1:-arg1;
+}
+#endif
+
+#ifdef L_raise
+int
+raise(signo)
+int signo;
+{
+ return kill(getpid(), signo);
+}
+#endif
+
+#ifdef L_bcopy
+#undef bcopy
+void
+bcopy(src, dest, len)
+void * src, *dest;
+unsigned int len;
+{
+ (void) memcpy(dest, src, len);
+}
+#endif
+
+#ifdef L_bzero
+#undef bzero
+void
+bzero(dest, len)
+void *dest;
+unsigned int len;
+{
+ (void) memset(dest, '\0', len);
+}
+#endif
+
+#ifdef L_bcmp
+#undef bcmp
+int
+bcmp(dest, src, len)
+void * src, *dest;
+unsigned int len;
+{
+ return memcmp(dest, src, len);
+}
+#endif
+
+#ifdef L_index
+#undef index
+char *
+index(src, chr)
+char *src;
+int chr;
+{
+ return strchr(src, chr);
+}
+#endif
+
+#ifdef L_rindex
+#undef rindex
+char *
+rindex(src, chr)
+char *src;
+int chr;
+{
+ return strrchr(src, chr);
+}
+#endif
+
+#ifdef L_remove
+#include <errno.h>
+
+int
+remove(src)
+char *src;
+{
+ extern int errno;
+ int er = errno;
+ int rv = unlink(src);
+ if( rv < 0 && errno == EISDIR )
+ rv = rmdir(src);
+ if( rv >= 0 ) errno = er;
+ return rv;
+}
+#endif
+
+#ifdef L_creat
+#include <fcntl.h>
+
+int
+creat(file, mode)
+__const char * file;
+mode_t mode;
+{
+ return open(file, O_TRUNC|O_CREAT|O_WRONLY, mode);
+}
+#endif
+
diff --git a/libc-0.0.4/misc/atexit.c b/libc-0.0.4/misc/atexit.c
new file mode 100644
index 0000000..6e8e45b
--- /dev/null
+++ b/libc-0.0.4/misc/atexit.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/*
+ * This deals with both the atexit and on_exit function calls
+ *
+ * Note calls installed with atexit are called with the same args as on_exit
+ * fuctions; the void* is given the NULL value.
+ *
+ */
+
+#include <errno.h>
+
+/* ATEXIT.H */
+#define MAXONEXIT 20 /* AIUI Posix requires 10 */
+
+typedef void (*vfuncp) ();
+
+extern vfuncp __cleanup;
+extern void __do_exit();
+
+extern struct exit_table
+{
+ vfuncp called;
+ void *argument;
+}
+__on_exit_table[MAXONEXIT];
+
+extern int __on_exit_count;
+
+/* End ATEXIT.H */
+
+#ifdef L_atexit
+int
+atexit(ptr)
+vfuncp ptr;
+{
+ if( __on_exit_count < 0 || __on_exit_count >= MAXONEXIT)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ __cleanup = __do_exit;
+ if( ptr )
+ {
+ __on_exit_table[__on_exit_count].called = ptr;
+ __on_exit_table[__on_exit_count].argument = 0;
+ __on_exit_count++;
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef L_on_exit
+int
+on_exit(ptr, arg)
+vfuncp ptr;
+void *arg;
+{
+ if( __on_exit_count < 0 || __on_exit_count >= MAXONEXIT)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ __cleanup = __do_exit;
+ if( ptr )
+ {
+ __on_exit_table[__on_exit_count].called = ptr;
+ __on_exit_table[__on_exit_count].argument = arg;
+ __on_exit_count++;
+ }
+ return 0;
+}
+
+#endif
+
+#ifdef L___do_exit
+
+int __on_exit_count = 0;
+struct exit_table __on_exit_table[MAXONEXIT];
+
+void
+__do_exit(rv)
+int rv;
+{
+ register int count = __on_exit_count-1;
+ register vfuncp ptr;
+ __on_exit_count = -1; /* ensure no more will be added */
+ __cleanup = 0; /* Calling exit won't re-do this */
+
+ /* In reverse order */
+ for (; count >= 0; count--)
+ {
+ ptr = __on_exit_table[count].called;
+ (*ptr) (rv, __on_exit_table[count].argument);
+ }
+}
+
+#endif
diff --git a/libc-0.0.4/misc/atoi.c b/libc-0.0.4/misc/atoi.c
new file mode 100644
index 0000000..5272646
--- /dev/null
+++ b/libc-0.0.4/misc/atoi.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+int
+atoi(number)
+register char *number;
+{
+ register int n = 0, neg = 0;
+
+ while (*number <= ' ' && *number > 0)
+ ++number;
+ if (*number == '-')
+ {
+ neg = 1;
+ ++number;
+ }
+ else if (*number == '+')
+ ++number;
+ while (*number>='0' && *number<='9')
+ n = (n * 10) + ((*number++) - '0');
+ return (neg ? -n : n);
+}
diff --git a/libc-0.0.4/misc/atol.c b/libc-0.0.4/misc/atol.c
new file mode 100644
index 0000000..901dfe2
--- /dev/null
+++ b/libc-0.0.4/misc/atol.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+long
+atol(number)
+register char *number;
+{
+ register long n = 0, neg = 0;
+
+ while (*number <= ' ' && *number > 0)
+ ++number;
+ if (*number == '-')
+ {
+ neg = 1;
+ ++number;
+ }
+ else if (*number == '+')
+ ++number;
+ while (*number>='0' && *number<='9')
+ n = (n * 10) + ((*number++) - '0');
+ return (neg ? -n : n);
+}
diff --git a/libc-0.0.4/misc/bsearch.c b/libc-0.0.4/misc/bsearch.c
new file mode 100644
index 0000000..9898667
--- /dev/null
+++ b/libc-0.0.4/misc/bsearch.c
@@ -0,0 +1,46 @@
+
+/*
+ * This file lifted in toto from 'Dlibs' on the atari ST (RdeBath)
+ *
+ *
+ * Dale Schumacher 399 Beacon Ave.
+ * (alias: Dalnefre') St. Paul, MN 55104
+ * dal@syntel.UUCP United States of America
+ * "It's not reality that's important, but how you perceive things."
+ */
+#include <stdio.h>
+
+static int _bsearch; /* index of element found, or where to
+ * insert */
+
+char *
+bsearch(key, base, num, size, cmp)
+register char *key; /* item to search for */
+register char *base; /* base address */
+int num; /* number of elements */
+register int size; /* element size in bytes */
+register int (*cmp) (); /* comparison function */
+{
+ register int a, b, c, dir;
+
+ a = 0;
+ b = num - 1;
+ while (a <= b)
+ {
+ c = (a + b) >> 1; /* == ((a + b) / 2) */
+ if (dir = (*cmp) ((base + (c * size)), key))
+ {
+ if (dir > 0)
+ b = c - 1;
+ else /* (dir < 0) */
+ a = c + 1;
+ }
+ else
+ {
+ _bsearch = c;
+ return (base + (c * size));
+ }
+ }
+ _bsearch = b;
+ return (NULL);
+}
diff --git a/libc-0.0.4/misc/cputype.c b/libc-0.0.4/misc/cputype.c
new file mode 100644
index 0000000..642edf6
--- /dev/null
+++ b/libc-0.0.4/misc/cputype.c
@@ -0,0 +1,344 @@
+/*
+ * This does a determination of the cpu type that is actually being used.
+ * It can determine the CPU on anything upto and including a 386 accuratly
+ * whatever mode the CPU is in (This is 16 bit code)
+ * An MSDOS compiled version is available.
+ *
+ * For Post 386 interpretation the argument must be set to 1, if this is done
+ * an attempt to determine the CPU type will be made using MSDOS calls and
+ * potentially Illegal instructions.
+ *
+ * If STANDALONE is defined this will decode and print the output from cputype
+ *
+ * $ cputype # Call cputype(0) and interpret
+ * $ cputype + # Call cputype(1) get a SIGILL (or perhaps interpret)
+ *
+ * NOTE: This code is COPYRIGHT and not under the GNU Lib copyright, this
+ * may be distributed freely as source or as a standalone binary
+ * compiled from this unmodified source.
+ *
+ * You may use the cputype() function in your own personal code.
+ * You may distribute a binary version of code containing the
+ * cputype() function if either you distribute this source with
+ * the binary version or distribute a clear reference to a freely
+ * available copy of this source code and the source code to the
+ * rest of your package with the binary version of the package.
+ *
+ * (C) Copyright R de Bath 1989-1995
+ */
+
+#ifdef STANDALONE
+
+#include <stdio.h>
+#include <signal.h>
+
+char * name_808x[] = {
+"8088", "8086", "80C88", "80C86", "NEC V20", "NEC V30", "808x Clone"
+};
+
+char * name_8018x[] = {
+"80188", "80186", "8018x Clone"
+};
+
+void
+main(argc, argv)
+int argc; char **argv;
+{
+ int c, major, flg, fpu;
+#ifdef SIGFPE
+ signal(SIGFPE, SIG_IGN);
+#endif
+
+ printf("Cpu identifier - (C) R de Bath <rdebath@cix.compulink.co.uk>\n");
+
+ c = cputype(argc!=1);
+ fpu = (c<0); major = ((c>>8)&0x1F); c &= 0xFF;
+
+ if( major == 0 )
+ {
+ if( c > 6 ) c = 6;
+ printf("Cpu is an %s\n", name_808x[c]);
+ }
+ else if( major == 1 )
+ {
+ if( c > 3 ) c = 3;
+ printf("Cpu is an %s\n", name_8018x[c]);
+ }
+ else
+ {
+ printf("Cpu is an 80%x86%s", major&0xF, major>15?"+":"");
+ if(c&0x01) printf( " in protected mode");
+ printf(" MSW= ");
+ if( c&0x10 ) printf("ET,"); else printf("--,");
+ if( c&0x08 ) printf("TS,"); else printf("--,");
+ if( c&0x04 ) printf("EM,"); else printf("--,");
+ if( c&0x02 ) printf("MP,"); else printf("--,");
+ if( c&0x01 ) printf("PE\n"); else printf("--\n");
+
+ if( !fpu && ( c&0x06) )
+ printf("An FPU appears to exist but it is unavailable\n");
+ else
+ {
+ if( c&0x02 ) printf("Math processor requires WAIT\n");
+ if( c&0x04 ) printf("Emulated math present\n");
+ if( c&0x08 ) printf("Math processor belongs to a different process\n");
+ /* if( c&0x10 ) printf("Humm\n"); */
+ }
+ }
+ if( fpu ) printf("FPU available for use\n");
+
+ exit(0);
+}
+#endif
+
+/*
+ * The assembler for CPU determination.
+ *
+ * Improvements and additional CPUs are solicited.
+ */
+
+#ifdef __AS386_16__
+#asm
+ .text
+export _cputype
+_cputype:
+ ; First save everything ...
+ push bp
+ mov bp,sp
+ push ds
+ push es
+ push bx
+ push cx
+ push dx
+ pushf
+#if __FIRST_ARG_IN_AX__
+ mov cx, ax ; Collect the flag
+#else
+ mov cx, [bp+4] ; Collect the flag
+#endif
+
+ ; Tiny mode code ...
+ mov ax, cs
+ mov es, ax
+ mov ds, ax
+ mov bx, #0 ; Init to 8086
+
+ ; First easy check is it a 286 or better ...
+ push sp
+ pop ax
+ cmp ax, sp
+ jz ge286
+ br pre286
+
+ ; Come here when we`re done (286+)
+cpu_prot:
+ ; .286P
+ smsw ax ; Fetch 5 LSB of MSW (PE,MP,EP,...)
+ and al,#31
+ mov bl,al
+
+ ; Check for FPU
+ fninit
+ xor ax,ax
+ push ax
+ mov bp,sp
+ fnstcw word ptr [bp]
+ pop ax
+ cmp ah,#3
+ jne cpuend
+ or bh,#$80
+
+ ; Another check for FPU *BUT* I think this only get`s 287+
+; finit
+; fstsw ax
+; or al,al
+; jnz cpuend
+; or bh,#$80
+
+ ; .8086
+cpuend:
+ mov ax, bx
+ popf
+ pop dx
+ pop cx
+ pop bx
+ pop es
+ pop ds
+ pop bp
+ ret
+
+ge286: ; .286P
+ ; Does the caller want the exact CPU
+ cmp cx,#0
+ jne try_486
+
+; Simple test for a 286 ...
+
+ mov bh,#2 ; Major CPU type >= 80286
+ ; What`s the contents of the GDT pointer
+ sub sp,#6
+ mov bp,sp
+ sgdt [bp]
+ add sp,#4
+ pop ax ; 286 == FFFF, 386+ anything else
+ inc ax
+ jz cpu_prot
+ mov bh,#$13 ; Major CPU type >= 80386
+
+; smsw ax
+; ror ax,#1
+; jnc try_486 ; If in real mode and running MSDOS
+
+ jmp cpu_prot ; Assume 486 test will NOT work in prot mode
+
+ ; This is an alternate way of finding a 386 ...
+ ; But it *can* be hidden by V86 mode.
+; pushf
+; mov ax,#$7000
+; push ax
+; popf
+; pushf
+; pop ax
+; popf
+; and ax,#$7000
+; jz cpu_prot ; It`s id`ed as a 286 we already know
+ ; different but it`s probably a bad idea
+ ; to try for a 486.
+
+try_486:
+ ; This trys to trap undefined instructions
+ ; it may not work if the CPU is in protected mode
+ ; Note: This does actually re-test 286 v 386
+ cli
+ push bp
+ mov bp, sp
+ mov ax,#$3506
+ int #$21 ; WARNING - DOS DOS DOS DOS DOS !!!!!
+ mov [vector+2], es
+ mov [vector], bx
+ mov ax,#$2506
+ lea dx, [int6]
+ int #$21
+ mov bh,#2 ; 286
+
+ ; .486
+test386:
+ mov ebx,#$00040300 ; 386 or 486
+test486:
+ bswap ebx ; Byte twiddle now 486
+
+ mov ax,#1
+do_cpuid:
+ db $0F ; CPUID instruction
+ db $A2
+ and ah,#15 ; Select family number
+ mov bh,ah ; put it where we want it
+
+ ; .286P
+fail386:
+ mov ax, #$2506
+ mov dx, [vector]
+ mov ds, [vector+2]
+ int #$21
+ pop bp
+ sti
+ br cpu_prot
+
+
+ ; Tests for processors before the 80286 ...
+ ; .8086
+pre286:
+ ; Is it an 8018x ? These mask shifts to less that 32 bits
+ mov cl,#32
+ mov ax, #$0100
+ shl ax,cl
+ mov bx, ax
+ jnz test8
+
+ ; Try for an NEC V20/30
+ mov ax, #$0208
+ db $D5
+ db 16 ; Only the 8088 actually checks the arg to AAD
+ cmp al, #$28 ; as intel ran out of microcode space
+ jz cmos
+ mov bx,#4 ; NEC V20
+ jmp test8
+
+ ; The CMOS 8088/6 had the bug with rep lods repaired.
+cmos: push si
+ sti
+ mov cx, #$FFFF
+ rep
+ lodsb
+ pop si
+ or cx,cx
+ jne test8
+ mov bx,#2 ; Intel 80C88
+
+ ; This tests the prefetch of the CPU, 8 bit ones have 4 bytes
+ ; 16 bit cpus have a queue of 6 bytes.
+test8: push di
+ push bx
+ mov dx,#0
+ mov bx,#4
+ std
+ mov al,#$90
+
+retest: lea di,[_nop]
+ cli
+ mov cx,#3
+ rep
+ stosb
+ nop
+ nop
+ nop
+ nop
+_inc: inc dx
+ nop
+_nop: nop
+ sti
+ mov byte ptr [_inc], #$42
+ dec bx
+ jnz retest
+ pop bx
+ cmp dx,#0
+ jz done8
+ inc bx
+done8: pop di
+ cld
+
+ br cpuend
+
+
+ ; Function called by the illegal instruction trap
+int6:
+ mov sp, bp
+ jmp fail386
+;;
+ push bp
+ mov bp, sp
+ push ax
+ mov ax,cs
+ cmp 4[bp],ax
+ pop ax
+ jnz pass
+ cmp bh,#2
+ je move23
+ cmp bh,#3
+ je move34
+ add [bp+2], #(fail386 - do_cpuid)
+ jmp return
+move34: add [bp+2], #(fail386 - test486)
+ jmp return
+move23: add [bp+2], #(fail386 - test386)
+return: pop bp
+ iret
+
+pass: pop bp
+ jmp [vector]
+
+vector: dd 0
+
+#endasm
+
+#endif
diff --git a/libc-0.0.4/misc/ctype.c b/libc-0.0.4/misc/ctype.c
new file mode 100644
index 0000000..1514668
--- /dev/null
+++ b/libc-0.0.4/misc/ctype.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/*
+ * CTYPE.C Character classification and conversion
+ */
+
+#include <ctype.h>
+
+#undef toupper
+#undef tolower
+
+unsigned char _ctype[128] =
+{
+ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x00..0x03 */
+ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x04..0x07 */
+ __CT_c, __CT_c|__CT_s, __CT_c|__CT_s, __CT_c|__CT_s, /* 0x08..0x0B */
+ __CT_c|__CT_s, __CT_c|__CT_s, __CT_c, __CT_c, /* 0x0C..0x0F */
+
+ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x10..0x13 */
+ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x14..0x17 */
+ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x18..0x1B */
+ __CT_c, __CT_c, __CT_c, __CT_c, /* 0x1C..0x1F */
+
+ __CT_s, __CT_p, __CT_p, __CT_p, /* 0x20..0x23 */
+ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x24..0x27 */
+ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x28..0x2B */
+ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x2C..0x2F */
+
+ __CT_d|__CT_x, __CT_d|__CT_x, __CT_d|__CT_x, __CT_d|__CT_x,/* 0x30..0x33 */
+ __CT_d|__CT_x, __CT_d|__CT_x, __CT_d|__CT_x, __CT_d|__CT_x,/* 0x34..0x37 */
+ __CT_d|__CT_x, __CT_d|__CT_x, __CT_p, __CT_p, /* 0x38..0x3B */
+ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x3C..0x3F */
+
+ __CT_p, __CT_u|__CT_x, __CT_u|__CT_x, __CT_u|__CT_x, /* 0x40..0x43 */
+ __CT_u|__CT_x, __CT_u|__CT_x, __CT_u|__CT_x, __CT_u, /* 0x44..0x47 */
+ __CT_u, __CT_u, __CT_u, __CT_u, /* 0x48..0x4B */
+ __CT_u, __CT_u, __CT_u, __CT_u, /* 0x4C..0x4F */
+
+ __CT_u, __CT_u, __CT_u, __CT_u, /* 0x50..0x53 */
+ __CT_u, __CT_u, __CT_u, __CT_u, /* 0x54..0x57 */
+ __CT_u, __CT_u, __CT_u, __CT_p, /* 0x58..0x5B */
+ __CT_p, __CT_p, __CT_p, __CT_p, /* 0x5C..0x5F */
+
+ __CT_p, __CT_l|__CT_x, __CT_l|__CT_x, __CT_l|__CT_x, /* 0x60..0x63 */
+ __CT_l|__CT_x, __CT_l|__CT_x, __CT_l|__CT_x, __CT_l, /* 0x64..0x67 */
+ __CT_l, __CT_l, __CT_l, __CT_l, /* 0x68..0x6B */
+ __CT_l, __CT_l, __CT_l, __CT_l, /* 0x6C..0x6F */
+
+ __CT_l, __CT_l, __CT_l, __CT_l, /* 0x70..0x73 */
+ __CT_l, __CT_l, __CT_l, __CT_l, /* 0x74..0x77 */
+ __CT_l, __CT_l, __CT_l, __CT_p, /* 0x78..0x7B */
+ __CT_p, __CT_p, __CT_p, __CT_c /* 0x7C..0x7F */
+};
+
+int toupper(c)
+int c;
+{
+ return(islower(c) ? (c ^ 0x20) : (c));
+}
+
+int tolower(c)
+int c;
+{
+ return(isupper(c) ? (c ^ 0x20) : (c));
+}
diff --git a/libc-0.0.4/misc/getenv.c b/libc-0.0.4/misc/getenv.c
new file mode 100644
index 0000000..45d072e
--- /dev/null
+++ b/libc-0.0.4/misc/getenv.c
@@ -0,0 +1,26 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+extern char ** environ;
+
+char *
+getenv(name)
+char * name;
+{
+ register int l;
+ register char ** ep = environ;
+ l = strlen(name);
+
+ if( ep == 0 || l == 0 ) return 0;
+
+ while(*ep)
+ {
+ if( **ep == *name && memcmp(name, *ep, l) == 0 && (*ep)[l] == '=' )
+ return *ep+l+1;
+ ep++;
+ }
+ return 0;
+}
+
diff --git a/libc-0.0.4/misc/getopt.c b/libc-0.0.4/misc/getopt.c
new file mode 100644
index 0000000..d951214
--- /dev/null
+++ b/libc-0.0.4/misc/getopt.c
@@ -0,0 +1,122 @@
+
+/*
+ * From: gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) Newsgroups: net.sources
+ * Subject: getopt library routine Date: 30 Mar 85 04:45:33 GMT
+ */
+/*
+ * getopt -- public domain version of standard System V routine
+ *
+ * Strictly enforces the System V Command Syntax Standard; provided by D A
+ * Gwyn of BRL for generic ANSI C implementations
+ *
+ * #define STRICT to prevent acceptance of clustered options with arguments
+ * and ommision of whitespace between option and arg.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+int opterr = 1; /* error => print message */
+int optind = 1; /* next argv[] index */
+char *optarg = NULL; /* option parameter if any */
+
+static int
+Err(name, mess, c) /* returns '?' */
+char *name; /* program name argv[0] */
+char *mess; /* specific message */
+int c; /* defective option letter */
+{
+ if (opterr)
+ {
+ (void) fprintf(stderr,
+ "%s: %s -- %c\n",
+ name, mess, c
+ );
+ }
+
+ return '?'; /* erroneous-option marker */
+}
+
+int
+getopt(argc, argv, optstring) /* returns letter, '?', EOF */
+int argc; /* argument count from main */
+char *argv[]; /* argument vector from main */
+char *optstring; /* allowed args, e.g. "ab:c" */
+{
+ static int sp = 1; /* position within argument */
+ register int osp; /* saved `sp' for param test */
+#ifndef STRICT
+ register int oind; /* saved `optind' for param test */
+#endif
+ register int c; /* option letter */
+ register char *cp; /* -> option in `optstring' */
+
+ optarg = NULL;
+
+ if (sp == 1) /* fresh argument */
+ if (optind >= argc /* no more arguments */
+ || argv[optind][0] != '-' /* no more options */
+ || argv[optind][1] == '\0' /* not option; stdin */
+ )
+ return EOF;
+ else if (strcmp(argv[optind], "--") == 0)
+ {
+ ++optind; /* skip over "--" */
+ return EOF; /* "--" marks end of options */
+ }
+
+ c = argv[optind][sp]; /* option letter */
+ osp = sp++; /* get ready for next letter */
+
+#ifndef STRICT
+ oind = optind; /* save optind for param test */
+#endif
+ if (argv[optind][sp] == '\0')/* end of argument */
+ {
+ ++optind; /* get ready for next try */
+ sp = 1; /* beginning of next argument */
+ }
+
+ if (c == ':' || c == '?' /* optstring syntax conflict */
+ || (cp = strchr(optstring, c)) == NULL /* not found */
+ )
+ return Err(argv[0], "illegal option", c);
+
+ if (cp[1] == ':') /* option takes parameter */
+ {
+#ifdef STRICT
+ if (osp != 1)
+ return Err(argv[0],
+ "option must not be clustered",
+ c
+ );
+
+ if (sp != 1) /* reset by end of argument */
+ return Err(argv[0],
+ "option must be followed by white space",
+ c
+ );
+
+#else
+ if (oind == optind) /* argument w/o whitespace */
+ {
+ optarg = &argv[optind][sp];
+ sp = 1; /* beginning of next argument */
+ }
+
+ else
+#endif
+ if (optind >= argc)
+ return Err(argv[0],
+ "option requires an argument",
+ c
+ );
+
+ else /* argument w/ whitespace */
+ optarg = argv[optind];
+
+ ++optind; /* skip over parameter */
+ }
+
+ return c;
+}
diff --git a/libc-0.0.4/misc/itoa.c b/libc-0.0.4/misc/itoa.c
new file mode 100644
index 0000000..0822cfc
--- /dev/null
+++ b/libc-0.0.4/misc/itoa.c
@@ -0,0 +1,24 @@
+/* itoa.c <ndf@linux.mit.edu> */
+#define __MAX_INT_CHARS 7
+
+char *
+itoa(i)
+int i;
+{
+ static char a[__MAX_INT_CHARS];
+ char *b = a + sizeof(a) - 1;
+ int sign = (i < 0);
+
+ if (sign)
+ i = -i;
+ *b = 0;
+ do
+ {
+ *--b = '0' + (i % 10);
+ i /= 10;
+ }
+ while (i);
+ if (sign)
+ *--b = '-';
+ return b;
+}
diff --git a/libc-0.0.4/misc/lsearch.c b/libc-0.0.4/misc/lsearch.c
new file mode 100644
index 0000000..f3253e9
--- /dev/null
+++ b/libc-0.0.4/misc/lsearch.c
@@ -0,0 +1,47 @@
+/*
+ * This file lifted in toto from 'Dlibs' on the atari ST (RdeBath)
+ *
+ *
+ * Dale Schumacher 399 Beacon Ave.
+ * (alias: Dalnefre') St. Paul, MN 55104
+ * dal@syntel.UUCP United States of America
+ * "It's not reality that's important, but how you perceive things."
+ */
+
+#include <stdio.h>
+
+char *
+lfind(key, base, num, size, cmp)
+register char *key, *base;
+unsigned int *num;
+register unsigned int size;
+register int (*cmp) ();
+{
+ register int n = *num;
+
+ while (n--)
+ {
+ if ((*cmp) (base, key) == 0)
+ return (base);
+ base += size;
+ }
+ return (NULL);
+}
+
+char *
+lsearch(key, base, num, size, cmp)
+char *key, *base;
+register unsigned int *num;
+register unsigned int size;
+int (*cmp) ();
+{
+ register char *p;
+ char *memcpy();
+
+ if ((p = lfind(key, base, num, size, cmp)) == NULL)
+ {
+ p = memcpy((base + (size * (*num))), key, size);
+ ++(*num);
+ }
+ return (p);
+}
diff --git a/libc-0.0.4/misc/ltoa.c b/libc-0.0.4/misc/ltoa.c
new file mode 100644
index 0000000..be1c7e2
--- /dev/null
+++ b/libc-0.0.4/misc/ltoa.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+static char buf[12];
+
+extern char * ultoa();
+
+char * ltoa(val)
+long val;
+{
+ char *p;
+ int flg = 0;
+ if( val < 0 ) { flg++; val= -val; }
+ p = ultoa(val);
+ if(flg) *--p = '-';
+ return p;
+}
+
+char * ultoa(val)
+unsigned long val;
+{
+ char *p;
+
+ p = buf+sizeof(buf);
+ *--p = '\0';
+
+ do
+ {
+ *--p = '0' + val%10;
+ val/=10;
+ }
+ while(val);
+ return p;
+}
+
diff --git a/libc-0.0.4/misc/ltostr.c b/libc-0.0.4/misc/ltostr.c
new file mode 100644
index 0000000..c8966d9
--- /dev/null
+++ b/libc-0.0.4/misc/ltostr.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+static char buf[34];
+
+extern char * ultostr();
+
+char * ltostr(val, radix)
+long val;
+int radix;
+{
+ char *p;
+ int flg = 0;
+ if( val < 0 ) { flg++; val= -val; }
+ p = ultostr(val, radix);
+ if(p && flg) *--p = '-';
+ return p;
+}
+
+char * ultostr(val, radix)
+unsigned long val;
+int radix;
+{
+ register char *p;
+ register int c;
+
+ if( radix > 36 || radix < 2 ) return 0;
+
+ p = buf+sizeof(buf);
+ *--p = '\0';
+
+ do
+ {
+ c = val%radix;
+ val/=radix;
+ if( c > 9 ) *--p = 'a'-10+c; else *--p = '0'+c;
+ }
+ while(val);
+ return p;
+}
+
diff --git a/libc-0.0.4/misc/popen.c b/libc-0.0.4/misc/popen.c
new file mode 100644
index 0000000..c848ca4
--- /dev/null
+++ b/libc-0.0.4/misc/popen.c
@@ -0,0 +1,42 @@
+
+#include <stdio.h>
+
+
+FILE * popen(command, rw)
+char * command;
+char * rw;
+{
+ int pipe_fd[2];
+ int pid, reading;
+
+ if( pipe(pipe_fd) < 0 ) return NULL;
+ reading = (rw[0] == 'r');
+
+ pid = vfork();
+ if( pid < 0 ) { close(pipe_fd[0]); close(pipe_fd[1]); return NULL; }
+ if( pid == 0 )
+ {
+ close(pipe_fd[!reading]);
+ close(reading);
+ if( pipe_fd[reading] != reading )
+ {
+ dup2(pipe_fd[reading], reading);
+ close(pipe_fd[reading]);
+ }
+
+ execl("/bin/sh", "sh", "-c", command, (char*)0);
+ _exit(255);
+ }
+
+ close(pipe_fd[reading]);
+ return fdopen(pipe_fd[!reading], rw);
+}
+
+int pclose(fd)
+FILE *fd;
+{
+ int waitstat;
+ if( fclose(fd) != 0 ) return EOF;
+ wait(&waitstat);
+}
+
diff --git a/libc-0.0.4/misc/putenv.c b/libc-0.0.4/misc/putenv.c
new file mode 100644
index 0000000..09a68d6
--- /dev/null
+++ b/libc-0.0.4/misc/putenv.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+extern char ** environ;
+#define ADD_NUM 4
+
+int
+putenv(var)
+char * var;
+{
+static char ** mall_env = 0;
+static int extras = 0;
+ char **p, **d;
+ char * r;
+ int len;
+
+ r = strchr(var, '=');
+ if( r == 0 ) len = strlen(var);
+ else len = r-var;
+
+ for(p=environ; *p; p++)
+ {
+ if( memcmp(var, *p, len) == 0 && (*p)[len] == '=' )
+ {
+ while( p[0] = p[1] ) p++;
+ extras++;
+ break;
+ }
+ }
+ if( r == 0 ) return 0;
+ if( extras <= 0 ) /* Need more space */
+ {
+ d = malloc((p-environ+1+ADD_NUM)*sizeof(char*));
+ if( d == 0 ) return -1;
+
+ memcpy((void*) d, (void*) environ, (p-environ+1)*sizeof(char*));
+ p = d + (p-environ);
+ extras=ADD_NUM;
+
+ if( mall_env ) free(mall_env);
+ environ = d;
+ mall_env = d;
+ }
+ *p++ = var;
+ *p = '\0';
+ extras--;
+
+ return 0;
+}
+
+
diff --git a/libc-0.0.4/misc/qsort.c b/libc-0.0.4/misc/qsort.c
new file mode 100644
index 0000000..cee53c3
--- /dev/null
+++ b/libc-0.0.4/misc/qsort.c
@@ -0,0 +1,166 @@
+/*
+ * This file lifted in toto from 'Dlibs' on the atari ST (RdeBath)
+ *
+ *
+ * Dale Schumacher 399 Beacon Ave.
+ * (alias: Dalnefre') St. Paul, MN 55104
+ * dal@syntel.UUCP United States of America
+ * "It's not reality that's important, but how you perceive things."
+ */
+#include <string.h>
+
+char *_qbuf = 0; /* pointer to storage for qsort() */
+
+#define PIVOT ((i+j)>>1)
+#define moveitem(dst,src,size) if(dst != src) memcpy(dst, src, size)
+
+static
+_wqsort(base, lo, hi, cmp)
+register int *base;
+register int lo;
+register int hi;
+register int (*cmp) ();
+{
+ int k;
+ register int i, j, t;
+ register int *p = &k;
+
+ while (hi > lo)
+ {
+ i = lo;
+ j = hi;
+ t = PIVOT;
+ *p = base[t];
+ base[t] = base[i];
+ base[i] = *p;
+ while (i < j)
+ {
+ while (((*cmp) ((base + j), p)) > 0)
+ --j;
+ base[i] = base[j];
+ while ((i < j) && (((*cmp) ((base + i), p)) <= 0))
+ ++i;
+ base[j] = base[i];
+ }
+ base[i] = *p;
+ if ((i - lo) < (hi - i))
+ {
+ _wqsort(base, lo, (i - 1), cmp);
+ lo = i + 1;
+ }
+ else
+ {
+ _wqsort(base, (i + 1), hi, cmp);
+ hi = i - 1;
+ }
+ }
+}
+
+static
+_lqsort(base, lo, hi, cmp)
+register long *base;
+register int lo;
+register int hi;
+register int (*cmp) ();
+{
+ long k;
+ register int i, j, t;
+ register long *p = &k;
+
+ while (hi > lo)
+ {
+ i = lo;
+ j = hi;
+ t = PIVOT;
+ *p = base[t];
+ base[t] = base[i];
+ base[i] = *p;
+ while (i < j)
+ {
+ while (((*cmp) ((base + j), p)) > 0)
+ --j;
+ base[i] = base[j];
+ while ((i < j) && (((*cmp) ((base + i), p)) <= 0))
+ ++i;
+ base[j] = base[i];
+ }
+ base[i] = *p;
+ if ((i - lo) < (hi - i))
+ {
+ _lqsort(base, lo, (i - 1), cmp);
+ lo = i + 1;
+ }
+ else
+ {
+ _lqsort(base, (i + 1), hi, cmp);
+ hi = i - 1;
+ }
+ }
+}
+
+static
+_nqsort(base, lo, hi, size, cmp)
+register char *base;
+register int lo;
+register int hi;
+register int size;
+register int (*cmp) ();
+{
+ register int i, j;
+ register char *p = _qbuf;
+
+ while (hi > lo)
+ {
+ i = lo;
+ j = hi;
+ p = (base + size * PIVOT);
+ moveitem(_qbuf, p, size);
+ moveitem(p, (base + size * i), size);
+ moveitem((base + size * i), _qbuf, size);
+ p = _qbuf;
+ while (i < j)
+ {
+ while (((*cmp) ((base + size * j), p)) > 0)
+ --j;
+ moveitem((base + size * i), (base + size * j), size);
+ while ((i < j) && (((*cmp) ((base + size * i), p)) <= 0))
+ ++i;
+ moveitem((base + size * j), (base + size * i), size);
+ }
+ moveitem((base + size * i), p, size);
+ if ((i - lo) < (hi - i))
+ {
+ _nqsort(base, lo, (i - 1), size, cmp);
+ lo = i + 1;
+ }
+ else
+ {
+ _nqsort(base, (i + 1), hi, size, cmp);
+ hi = i - 1;
+ }
+ }
+}
+
+qsort(base, num, size, cmp)
+char *base;
+int num;
+int size;
+int (*cmp) ();
+{
+ char _qtemp[128];
+
+ if (_qbuf == 0)
+ {
+ if (size > sizeof(_qtemp))/* records too large! */
+ return;
+ _qbuf = _qtemp;
+ }
+ if (size == 2)
+ _wqsort(base, 0, num - 1, cmp);
+ else if (size == 4)
+ _lqsort(base, 0, num - 1, cmp);
+ else
+ _nqsort(base, 0, num - 1, size, cmp);
+ if (_qbuf == _qtemp)
+ _qbuf = 0;
+}
diff --git a/libc-0.0.4/misc/rand.c b/libc-0.0.4/misc/rand.c
new file mode 100644
index 0000000..4eb0789
--- /dev/null
+++ b/libc-0.0.4/misc/rand.c
@@ -0,0 +1,61 @@
+#ifdef ZX81_RNG
+/*
+ * This is my favorite tiny RNG, If you had a ZX81 you may recognise it :-)
+ * (RdeBath)
+ */
+
+#include <stdlib.h>
+
+#define MAXINT (((unsigned)-1)>>1)
+
+static unsigned int sseed = 0;
+
+int rand()
+{
+ return ( sseed = (((sseed+1L)*75L)%65537L)-1 ) & MAXINT;
+}
+
+void srand(seed)
+unsigned int seed;
+{
+ sseed=seed;
+}
+
+#else
+
+/*
+ * This generator is a combination of three linear congruential generators
+ * with periods or 2^15-405, 2^15-1041 and 2^15-1111. It has a period that
+ * is the product of these three numbers.
+ */
+
+static int seed1 = 1;
+static int seed2 = 1;
+static int seed3 = 1;
+#define MAXINT (((unsigned)-1)>>1)
+
+#define CRANK(a,b,c,m,s) \
+ q = s/a; \
+ s = b*(s-a*q) - c*q; \
+ if(s<0) s+=m;
+
+int rand()
+{
+ register int q, z;
+ CRANK(206, 157, 31, 32363, seed1);
+ CRANK(217, 146, 45, 31727, seed2);
+ CRANK(222, 142, 133, 31657, seed3);
+
+ return seed1^seed2^seed3;
+}
+
+void srand(seed)
+unsigned int seed;
+{
+ seed &= MAXINT;
+ seed1= seed%32362 + 1;
+ seed2= seed%31726 + 1;
+ seed3= seed%31656 + 1;
+}
+
+#endif
diff --git a/libc-0.0.4/misc/strtod.c b/libc-0.0.4/misc/strtod.c
new file mode 100644
index 0000000..8acb423
--- /dev/null
+++ b/libc-0.0.4/misc/strtod.c
@@ -0,0 +1,96 @@
+/*
+ * strtod.c - This file is part of the libc-8086 package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <stdlib.h>
+#include <ctype.h>
+
+double
+strtod(const char *nptr, char ** endptr)
+{
+ unsigned short negative;
+ double number;
+ double fp_part;
+ int exponent;
+ unsigned short exp_negative;
+
+ /* advance beyond any leading whitespace */
+ while (isspace(*nptr))
+ nptr++;
+
+ /* check for optional '+' or '-' */
+ negative=0;
+ if (*nptr=='-')
+ {
+ negative=1;
+ nptr++;
+ }
+ else
+ if (*nptr=='+')
+ nptr++;
+
+ number=0;
+ while (isdigit(*nptr))
+ {
+ number=number*10+(*nptr-'0');
+ nptr++;
+ }
+
+ if (*nptr=='.')
+ {
+ nptr++;
+ fp_part=0;
+ while (isdigit(*nptr))
+ {
+ fp_part=fp_part/10.0 + (*nptr-'0')/10.0;
+ nptr++;
+ }
+ number+=fp_part;
+ }
+
+ if (*nptr=='e' || *nptr=='E')
+ {
+ nptr++;
+ exp_negative=0;
+ if (*nptr=='-')
+ {
+ exp_negative=1;
+ nptr++;
+ }
+ else
+ if (*nptr=='+')
+ nptr++;
+
+ exponent=0;
+ while (isdigit(*nptr))
+ {
+ exponent=exponent*10+(*nptr-'0');
+ exponent++;
+ }
+ }
+
+ while (exponent)
+ {
+ if (exp_negative)
+ number/=10;
+ else
+ number*=10;
+ exponent--;
+ }
+ return (negative ? -number:number);
+}
diff --git a/libc-0.0.4/misc/strtol.c b/libc-0.0.4/misc/strtol.c
new file mode 100644
index 0000000..bcd3334
--- /dev/null
+++ b/libc-0.0.4/misc/strtol.c
@@ -0,0 +1,106 @@
+/*
+ * strtol.c - This file is part of the libc-8086 package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+
+long int
+strtol(const char *nptr, char **endptr, int base)
+{
+ const char * ptr;
+ unsigned short negative;
+ long int number;
+
+ ptr=nptr;
+
+ while (isspace(*ptr))
+ ptr++;
+
+ negative=0;
+ if (*ptr=='-')
+ negative=1;
+
+ number=(long int)strtoul(nptr, endptr, base);
+
+ return (negative ? -number:number);
+}
+
+unsigned long int
+strtoul(const char *nptr, char **endptr, int base)
+{
+ unsigned long int number;
+
+ /* Sanity check the arguments */
+ if (base==1 || base>36 || base<0)
+ base=0;
+
+ /* advance beyond any leading whitespace */
+ while (isspace(*nptr))
+ nptr++;
+
+ /* check for optional '+' or '-' */
+ if (*nptr=='-')
+ nptr++;
+ else
+ if (*nptr=='+')
+ nptr++;
+
+ /* If base==0 and the string begins with "0x" then we're supposed
+ to assume that it's hexadecimal (base 16). */
+ else
+ if (base==0 && *nptr=='0')
+ if (toupper(*(nptr+1))=='X')
+ {
+ base=16;
+ nptr+=2;
+ }
+ /* If base==0 and the string begins with "0" but not "0x",
+ then we're supposed to assume that it's octal (base 8). */
+ else
+ {
+ base=8;
+ nptr++;
+ }
+
+
+ /* If base is still 0 (it was 0 to begin with and the string didn't begin
+ with "0"), then we are supposed to assume that it's base 10 */
+ if (base==0)
+ base=10;
+
+ number=0;
+ while (isalnum(*nptr))
+ {
+ number= (number*base)+((isalpha(*nptr) ? toupper(*nptr) : *nptr)
+ - (isdigit(*nptr) ? '0' : 'A' + 9));
+ nptr++;
+ if (*nptr>'0'+base)
+ break;
+ }
+
+ /* Some code is simply _impossible_ to write with -Wcast-qual .. :-\ */
+ if (endptr!=NULL)
+ *endptr=(char *)nptr;
+
+ /* All done */
+ return number;
+}
+
+
diff --git a/libc-0.0.4/misc/system.c b/libc-0.0.4/misc/system.c
new file mode 100644
index 0000000..f48f68d
--- /dev/null
+++ b/libc-0.0.4/misc/system.c
@@ -0,0 +1,49 @@
+
+#include <stddef.h>
+#include <signal.h>
+
+int
+system(command)
+char * command;
+{
+ int wait_val, wait_ret, pid;
+ __sighandler_t save_quit;
+ __sighandler_t save_int;
+
+ if( command == 0 ) return 1;
+
+ save_quit = signal(SIGQUIT, SIG_IGN);
+ save_int = signal(SIGINT, SIG_IGN);
+
+ if( (pid=vfork()) < 0 )
+ {
+ signal(SIGQUIT, save_quit);
+ signal(SIGINT, save_int);
+ return -1;
+ }
+ if( pid == 0 )
+ {
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+
+ execl("/bin/sh", "sh", "-c", command, (char*)0);
+ _exit(127);
+ }
+ /* Signals are not absolutly guarenteed with vfork */
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+
+ do
+ {
+ if( (wait_ret = wait(&wait_val)) == -1 )
+ {
+ wait_val = -1;
+ break;
+ }
+ }
+ while( wait_ret != pid );
+
+ signal(SIGQUIT, save_quit);
+ signal(SIGINT, save_int);
+ return wait_val;
+}
diff --git a/libc-0.0.4/msdos/Config b/libc-0.0.4/msdos/Config
new file mode 100644
index 0000000..ec28084
--- /dev/null
+++ b/libc-0.0.4/msdos/Config
@@ -0,0 +1 @@
+msdos: Msdos system calls
diff --git a/libc-0.0.4/msdos/Makefile b/libc-0.0.4/msdos/Makefile
new file mode 100644
index 0000000..d94d733
--- /dev/null
+++ b/libc-0.0.4/msdos/Makefile
@@ -0,0 +1,36 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+ASRC=msdos.c
+AOBJ= dos_start.o __mkargv.o dos__fconv.o dos_read.o dos_write.o \
+ dos_open.o dos_close.o dos_unlink.o dos_lseek.o \
+ dos_segalloc.o dos_setvect.o dos_getvect.o dos_isatty.o
+
+BSRC=i86.c
+BOBJ= __set_es.o __peek_es.o __poke_es.o __deek_es.o __strchr_es.o
+
+OBJ=$(AOBJ) $(BOBJ)
+
+all: $(OBJ)
+
+libc.a: $(BOBJ)
+ ar r ../$(LIBC) $(BOBJ)
+ @touch libc.a
+
+libdos.a: $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f $(OBJ) libc.a
+
+$(AOBJ): $(ASRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ASRC)
+
+$(BOBJ): $(BSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(BSRC)
+
diff --git a/libc-0.0.4/msdos/TODO b/libc-0.0.4/msdos/TODO
new file mode 100644
index 0000000..b775dff
--- /dev/null
+++ b/libc-0.0.4/msdos/TODO
@@ -0,0 +1,8 @@
+This is currently a very cutdown version of the syslib.
+
+This also currently does nothing about the difference between 'TEXT' and
+'BINARY' modes but I think that this level of operation should be pure
+binary, the 'TEXT' mode is more suited to stdio where an "fopen(f, "rb")"
+is more reasonable and probably won't break on other OSs.
+
+-Robert.
diff --git a/libc-0.0.4/msdos/i86.c b/libc-0.0.4/msdos/i86.c
new file mode 100644
index 0000000..0613756
--- /dev/null
+++ b/libc-0.0.4/msdos/i86.c
@@ -0,0 +1,163 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+/*
+ * These functions will not normally be useful for Linux-8086. But they
+ * can be used and may be useful in the kernel.
+ */
+
+#ifdef __AS386_16__
+
+#ifdef L___set_es
+unsigned int
+__get_ds()
+{
+#asm
+ mov ax,ds
+#endasm
+}
+
+unsigned int
+__get_es()
+{
+#asm
+ mov ax,es
+#endasm
+}
+
+void
+__set_es(seg)
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov es,ax
+#else
+ mov bx,sp
+ mov es,[bx+2]
+#endif
+#endasm
+}
+#endif
+
+#ifdef L___peek_es
+int
+__peek_es(off)
+unsigned int off;
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax
+#else
+ mov bx,sp
+ mov bx,[bx+2]
+#endif
+ seg es
+ mov al,[bx]
+ xor ah,ah
+#endasm
+}
+#endif
+
+#ifdef L___poke_es
+int
+__poke_es(off, value)
+unsigned int off;
+int value;
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,sp
+ mov bx,[bx+2]
+ xchg ax,bx
+#else
+ mov bx,sp
+ mov ax,[bx+4]
+ mov bx,[bx+2]
+#endif
+ seg es
+ mov [bx],al
+ xor ah,ah
+#endasm
+}
+#endif
+
+#ifdef L___deek_es
+int
+__deek_es(off)
+unsigned int off;
+{
+#asm
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax
+#else
+ mov bx,sp
+ mov bx,[bx+2]
+#endif
+ seg es
+ mov ax,[bx]
+#endasm
+}
+#endif
+
+#ifdef L___strchr_es
+char *
+__strchr_es(s, c)
+char * s;
+int c;
+{
+#asm
+ mov bx,sp
+ push si
+#if __FIRST_ARG_IN_AX__
+ mov bx,[bx+2]
+ mov si,ax
+#else
+ mov si,[bx+2]
+ mov bx,[bx+4]
+#endif
+ xor ax,ax
+
+#ifdef PARANOID
+ cld
+#endif
+ push ds
+ push es
+ pop ds
+
+in_loop:
+ lodsb
+ cmp al,bl
+ jz got_it
+ or al,al
+ jnz in_loop
+ pop ds
+ pop si
+ ret
+got_it:
+ lea ax,[si-1]
+ pop ds
+ pop si
+
+#endasm
+}
+#endif
+
+#ifdef L___strchr_es
+char *
+__strnget_es(d, s, c)
+char *d, *s;
+int c;
+{
+ int ds, es;
+ char *p = __strchr_es(s, '\0');
+ if(p != 0 && p-s < c)
+ c = p-s+1;
+ ds = __get_ds();
+ es = __get_es();
+
+ __movedata(es, s, ds, d, c);
+}
+#endif
+
+#endif /* __AS386_16__ */
diff --git a/libc-0.0.4/msdos/msdos.c b/libc-0.0.4/msdos/msdos.c
new file mode 100644
index 0000000..02c35db
--- /dev/null
+++ b/libc-0.0.4/msdos/msdos.c
@@ -0,0 +1,540 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#if !__FIRST_ARG_IN_AX__
+#ifdef __AS386_16__
+#ifdef __MSDOS__
+
+#include <dos.h>
+#include <fcntl.h>
+#include <errno.h>
+int errno;
+
+#ifdef L_dos_start
+
+static char * argdef[2] = { "C" };
+char ** __argv =argdef;
+char ** environ =argdef+1;
+
+int __argc =1;
+void (*__cleanup)() = 0;
+
+#asm
+ .data
+export ___envseg
+___envseg:
+ .word 0
+
+export ___psp
+___psp:
+ .word 0
+
+ .text
+
+export _exit
+export __exit
+_exit: ! exit(rv) function
+ mov bx,sp
+ push [bx+2] ! Copy the `rv` for the exit fuctions.
+ mov bx,[___cleanup] ! Call exit, normally this is `__do_exit`
+ test bx,bx
+ je no_clean ! But it`s default is null
+ call bx
+no_clean:
+ inc sp
+ inc sp
+__exit: ! _exit(rv)
+ mov bx,sp
+ mov ax,[bx+2]
+ mov ah,#$4c
+ int #$21
+dos_1_exit:
+ int #$20
+
+ .text
+export ___cstartup ! Crt0 startup
+___cstartup:
+ mov ax,#$3000 ! Get DOS version
+ int $21
+ cmp al,#2 ! DOS 2+ is Ok
+ jb dos_1_exit
+
+ mov dx,cs ! Current CS
+ add dx,#__segoff ! This var generated by the linker
+ mov ds,dx ! Correct DS
+
+ mov [___psp],es ! PSP segment
+ seg es
+ mov ax,[$2c]
+ mov [___envseg],ax ! Enviroment Segment
+
+ ! Now need to free some RAM
+ seg es
+ mov bx,[2] ! Top of Ram
+ mov ax,ds
+ add ax,#4096 ! Top of 64k data seg
+ jc use_tor ! Oops, wrapped
+ cmp ax,bx
+ jnc use_tor ! Bigger than tor
+ mov bx,ax
+use_tor:
+ mov ax,cs ! Work out how big the memseg is needed
+ sub bx,ax
+ mov ah,#$4A ! Set it
+ int $21
+ jnc set_stack ! Good.
+ ! Ooops, problem..
+ ! BX is now how big it can be so set that.
+ ! FIXME should check for BSS v Stack overlap
+ mov ah,#$4A
+ int $21
+
+set_stack: ! Now set SS to the same as DS
+ sub bx,#__segoff ! And SP to the top of available memory.
+ mov cl,#4
+ shl bx,cl
+ sub bx,#2
+ mov ss,dx
+ mov sp,bx
+
+zap_bss: ! Clear the BSS
+ mov es,dx ! ES now data seg
+ mov di,#__edata
+ mov cx,#__end
+ sub cx,di
+ xor ax,ax
+ cld
+ rep
+ stosb
+
+ call ___mkargv ! Fetch the arguments and enviroment
+ push [_environ]
+ push [___argv]
+ push [___argc]
+
+ mov si,#auto_start ! Pointer to first autostart function
+auto_run:
+ call [si] ! Call the function
+ inc si ! SI at next
+ inc si
+ jmp auto_run ! And round for the next.
+
+call_exit: ! Last item called by above.
+ pop bx ! Be tidy.
+ push ax ! At the end the last called was main() push it`s
+ call _exit ! return val and call exit();
+bad_exit:
+ jmp bad_exit ! Exit returned !!
+
+ loc 2
+ .word _main ! Segment 2 is the trailing pointers, main and the
+ .word call_exit ! routine to call exit.
+data_start:
+
+ .text
+
+#endasm
+
+__E_nosys()
+{
+#asm
+ .text
+
+export sys_call5
+export sys_call4
+export sys_call3
+export sys_call2
+export sys_call1
+export sys_call0
+sys_call5: ! Trap the unemulated Linux86 syscalls
+sys_call4:
+sys_call3:
+sys_call2:
+sys_call1:
+sys_call0:
+
+#endasm
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+#ifdef L___mkargv
+
+extern char ** environ;
+extern char ** __argv;
+extern int __argc;
+
+__mkargv()
+{
+ int length, i, argc=1, s=0;
+ char *ptr, *p;
+ __set_es(__psp); /* Pointer to the args */
+ length = __peek_es(0x80); /* Length of cmd line */
+ if( length > 0 )
+ {
+ ptr = (char*) sbrk(length+1); /* Allocate some space */
+
+ for(i=0; i<length; i++) /* Copy it in. */
+ {
+ ptr[i] = __peek_es(0x81+i);
+ if( ptr[i] != ' ' && s == 0 ) { argc++; s=1; }
+ if( ptr[i] == ' ' && s == 1 ) s=0;
+ }
+ ptr[length]=0;
+
+ p= __argv[0];
+ __argv = (char**) sbrk((argc+1)*sizeof(char*));
+ __argv[0] = p; /* FIXME: The real command can be found */
+ __argc=argc;
+
+ argc=1; s=0;
+ for(i=0; i<length; i++)
+ {
+ if( ptr[i] != ' ' && s == 0 ) { __argv[argc++] = ptr+i; s=1; }
+ if( ptr[i] == ' ' && s == 1 ) { ptr[i] = '\0'; s=0; }
+ }
+ __argv[argc] = 0;
+ }
+}
+#endif
+
+#ifdef L_dos__fconv
+/* This function converts filenames from unix like to DOS. */
+char *
+__fconv(fname)
+char * fname;
+{
+static char buf1[66], buf2[66], *str = 0;
+ register char *p, ch;
+ int dot = 0;
+
+ if( strcmp("/dev/tty", fname) == 0 ) return "CON:";
+
+ if( str == buf1 ) str = buf2; else str = buf1;
+
+ p = str;
+ if( strncmp("/mnt/", fname, 5) == 0 )
+ {
+ strcpy(p, "A:"); p+=2; fname+=4;
+ }
+ /*
+ * POSS:
+ * open("/name/*", ...); looks for an environ var PATH_name=c:\x\y\z
+ */
+
+ while((ch = *fname++) && p < str+65)
+ {
+ if( ( ch >= 'a' && ch <= 'z' )
+ || ( ch >= '0' && ch <= '9' )
+ || ch == ':' || ch == '%' || ch == '-' || ch == '$' )
+ ;
+ else if( ch >= 'A' && ch <= 'Z' )
+ ch = ch-'A'+'a';
+ else if( ch == '.' && dot == 0 )
+ dot = 1;
+ else if( ch == '/' || ch == '\\' )
+ {
+ dot = 0; ch = '\\';
+ }
+ else ch = '_';
+
+ *p++ = ch;
+ }
+ *p++ = '\0';
+ return str;
+}
+#endif
+
+#ifdef L_dos_read
+int
+read(fd, ptr, len)
+int fd;
+char *ptr;
+unsigned len;
+{
+#asm
+ mov bx,sp
+ mov cx,[bx+6]
+ mov dx,[bx+4]
+ mov bx,[bx+2]
+ mov ah,#$3f
+ int #$21
+ jnc readok
+ mov ax,#-1
+readok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_write
+int
+write(fd, ptr, len)
+int fd;
+char *ptr;
+unsigned len;
+{
+#asm
+ mov bx,sp
+ mov cx,[bx+6]
+ mov dx,[bx+4]
+ mov bx,[bx+2]
+ mov ah,#$40
+ int #$21
+ jnc writeok
+ mov ax,#-1
+writeok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_open
+int
+open(fname, type, cmode)
+char * fname;
+int type;
+int cmode;
+{
+ register char * nname = __fconv(fname);
+ int creat_mode = 0;
+ int rv;
+
+ if( (cmode & 0222) == 0 ) creat_mode = 1;
+
+ /* BzzzT. Assume these flags both mean the merge of them */
+ /* BzzzT. Also ignore O_EXCL */
+ if( type & (O_TRUNC|O_CREAT) )
+ rv = __dos_creat(nname, creat_mode);
+
+ else
+ /* Warn, this assumes the standard vals for O_RDWR, O_RDONLY, O_WRONLY */
+ rv = __dos_open(nname, type&O_ACCMODE);
+ if( rv < 0 ) errno=ENOENT;
+ return rv;
+}
+
+__dos_open(fname, mode)
+{
+#asm
+ mov bx,sp
+ mov dx,[bx+2] ;ds:dx points to source string
+ mov al,[bx+4] ;access code
+ mov ah,#$3d ;ask for a open
+ int #$21
+ jnc openok ;return handle if no error
+ mov ax,#-1 ;return -1 if error
+openok:
+#endasm
+}
+
+__dos_creat(fname)
+char * fname;
+{
+#asm
+ mov bx,sp
+ mov dx,[bx+2] ;ds:dx points to source string
+ xor cx,cx ;normal attributes
+ mov ah,#$3c ;ask for a create
+ int #$21
+ jnc creok ;return handle if no error
+ mov ax,#-1 ;return -1 if error
+creok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_close
+close(fd)
+{
+#asm
+ mov bx,sp
+ mov bx,[bx+2] ;file handle
+ mov ah,#$3e ;ask for a close
+ int #$21
+ mov ax,0 ;return 0 if no error
+ jnc closeok
+ mov ax,#-1 ;return -1 if error
+closeok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_unlink
+unlink(fname)
+char * fname;
+{
+#asm
+ mov bx,sp
+ push [bx+2]
+ call ___fconv
+ inc sp
+ inc sp
+ mov dx,ax ;ds:dx points to source string
+ mov ah,#$41 ;ask for a unlink
+ int #$21
+ mov ax,0 ;assume no errors
+ jnc unlok
+ mov ax,#-1 ;return -1 if error
+unlok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_lseek
+long
+lseek(fd, offset, mode)
+int fd, mode;
+long offset;
+{
+#asm
+ mov bx,sp
+ mov al,[bx+8] ;mode of seek (0 to 2)
+ mov dx,[bx+4] ;cx:dx is long offset
+ mov cx,[bx+6]
+ mov bx,[bx+2] ;file handle
+ mov ah,#$42
+ int #$21 ;do the lseek
+ jnc seekok
+ mov ax,#-1 ;return -1 if error
+ mov dx,ax
+seekok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_segalloc
+unsigned int
+__segalloc(paracount)
+unsigned int paracount;
+{
+#asm
+ mov bx,sp
+ mov bx,[bx+2]
+ mov ah,#$48
+ int $21
+ jnc ok
+ mov ax,#0
+ok:
+#endasm
+}
+#endif
+
+#ifdef L_dos_setvect
+void
+__setvect(i,j)
+int i;
+long j;
+{
+#asm
+ mov bx,sp
+ mov ax,[bx+2]
+ mov dx,[bx+4]
+ mov bx,[bx+6]
+ push ds
+ test bx,bx
+ jnz got_seg
+ mov bx,cs
+got_seg:
+ mov ds,bx
+ mov ah,#$25
+ int $21
+ pop ds
+#endasm
+}
+#endif
+
+#ifdef L_dos_getvect
+long
+__getvect(vecno)
+int vecno;
+{
+#asm
+ mov bx,sp
+ mov ax,[bx+2]
+ mov ah,#$35
+ push es
+ int #$21
+ mov dx,es
+ mov ax,bx
+ pop es
+#endasm
+}
+#endif
+
+#ifdef L_dos_isatty
+isatty(fd)
+int fd;
+{
+#asm
+ mov bx,sp
+ mov bx,[bx+2]
+ mov ah,#$44
+ mov al,#0
+ int #$21
+ xor ax,ax
+ test dx,#$80
+ jz not_tty
+ inc ax
+not_tty:
+#endasm
+}
+#endif
+
+#endif /* __MSDOS__ */
+#endif /* __AS386_16__ */
+#endif /* !__FIRST_ARG_IN_AX__ */
+
+/*
+# Name No Args Flag, comment
+CHDIR 12 1
+TIME 13 1 * No long return val, arg _must_ exist.
+MKNOD 14 3
+CHMOD 15 2
+CHOWN 16 3
+BRK 17 1 * This is only to tell the system
+STAT 18 2
+GETPID 20 1 * This gets both pid & ppid
+MOUNT 21 3 * Need more args & no ELKS
+UMOUNT 22 1 . No ELKS
+SETUID 23 1
+GETUID 24 1 * This gets both uid and euid
+STIME 25 2 . No ELKS should be 1 LONG arg
+PTRACE 26 X +
+ALARM 27 2 ? No unused return.
+FSTAT 28 2
+PAUSE 29 0
+UTIME 30 2
+STTY 31 2 . ELKS ain't got this and it'll probably change
+GTTY 32 2 . ELKS ain't got this and it'll probably change
+ACCESS 33 2
+NICE 34 1
+FTIME 35 1 . ELKS ain't got this.
+SYNC 36 0
+KILL 37 2
+RENAME 38 2
+MKDIR 39 2
+RMDIR 40 1
+DUP 41 X - Using nasty fcntl function
+PIPE 42 1
+TIMES 43 1
+PROF 44 X +
+SETGID 46 1
+GETGID 47 1 * This gets both gid and egid
+SIGNAL 48 2 +
+ACCT 51 X +
+PLOCK 53 X +
+IOCTL 54 3
+FCNTL 55 3
+EXEC 59 2 ?
+UMASK 60 1
+CHROOT 61 1
+SIGACTION 71 X
+SIGSUSPEND 72 X
+SIGPENDING 73 X
+SIGPROCMASK 74 X
+SIGRETURN 75 X
+REBOOT 76 3 . No ELKS and the magic number will be diff.
+*/
+
diff --git a/libc-0.0.4/pwd/Config b/libc-0.0.4/pwd/Config
new file mode 100644
index 0000000..b5aaad0
--- /dev/null
+++ b/libc-0.0.4/pwd/Config
@@ -0,0 +1 @@
+pwd: /etc/passwd managment
diff --git a/libc-0.0.4/pwd/Makefile b/libc-0.0.4/pwd/Makefile
new file mode 100644
index 0000000..df90f89
--- /dev/null
+++ b/libc-0.0.4/pwd/Makefile
@@ -0,0 +1,40 @@
+# Copyright (C) 1996 Nat Friedman <ndf@aleph1.mit.edu>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+ifeq ($(PLATFORM),i386-Linux)
+CFLAGS+=$(WALL)
+else # ifeq ($(PLATFORM),i86-ELKS)
+CFLAGS=$(CCFLAGS) $(LIBDEFS) -ansi
+endif
+
+PSRC=__getpwent.c pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c fgetpwent.c
+POBJ=__getpwent.o pwent.o getpwnam.o getpwuid.o putpwent.o getpw.o fgetpwent.o
+
+all: $(POBJ)
+
+%.o: %.c
+ $(CC) $(CFLAGS) -o $@ $< -c
+
+$(LIBC): $(POBJ)
+ ar r ../$(LIBC) $(POBJ)
+ @touch libc.a
+
+test: test_pwd.c libpwd.a
+ $(CC) $(CFLAGS) test_pwd.c -o test_pwd -L. -lpwd
+
+libpwd.a: $(POBJ)
+ ar r libpwd.a $(POBJ)
+ ranlib libpwd.a
+
+libpwd: libpwd.a
+
+clean:
+ rm -f $(POBJ) libc.a libpwd.a
+
+
+
+
diff --git a/libc-0.0.4/pwd/__getpwent.c b/libc-0.0.4/pwd/__getpwent.c
new file mode 100644
index 0000000..1dfc87e
--- /dev/null
+++ b/libc-0.0.4/pwd/__getpwent.c
@@ -0,0 +1,152 @@
+/*
+ * __getpwent.c - This file is part of the libc-8086/pwd package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pwd.h>
+
+#define __PWD_LINE_BUFFER_SIZE 256
+
+struct passwd *
+__getpwent(int passwd_fd)
+{
+ static char pwd_line[__PWD_LINE_BUFFER_SIZE];
+ unsigned short curr_index;
+
+ /* field_num is the current field number, 0 through 6 */
+ unsigned short field_num;
+
+ /* field_length is the length of the current field */
+ unsigned short field_length;
+
+ /* field_begin is a pointer to the first character of the current field */
+ char * field_begin;
+
+ /* endptr is used to error-check the call to strtol() */
+ char * endptr;
+
+ /* the only static passwd structure. we return a pointer to it */
+ static struct passwd passwd;
+
+ /* Gross, but small... */
+ goto readline_start;
+
+readline_restart:
+ /* Advance to the end of the line */
+ while (pwd_line[curr_index]!='\n' &&
+ read(passwd_fd, &pwd_line[curr_index], 1)==1);
+
+readline_start:
+ /* Initialize ourselves at the beginning of the line */
+ curr_index=field_num=field_length=0;
+ field_begin=pwd_line;
+ while (read(passwd_fd, &pwd_line[curr_index], 1)==1)
+ {
+ if (curr_index==0)
+ if (*pwd_line=='#' || *pwd_line==' ' || *pwd_line=='\n' ||
+ *pwd_line=='\t')
+ goto readline_restart;
+
+ field_length++;
+ if (pwd_line[curr_index]==':' || pwd_line[curr_index]=='\n')
+ {
+ pwd_line[curr_index]='\0';
+ switch (field_num)
+ {
+ case 0: /* login */
+ passwd.pw_name=field_begin;
+ break;
+ case 1: /* passwd */
+ passwd.pw_passwd=field_begin;
+ break;
+ case 2: /* GID */
+ case 3: /* UID */
+ if (field_num==2)
+ passwd.pw_uid=strtol(field_begin, &endptr, 10);
+ else
+ passwd.pw_gid=strtol(field_begin, &endptr, 10);
+ if (endptr!=(pwd_line+curr_index)) /* there were invalid
+ characters */
+ goto readline_restart;
+
+ curr_index-=field_length;
+ break;
+ case 4: /* GECOS field */
+ passwd.pw_gecos=field_begin;
+ break;
+ case 5: /* home directory */
+ passwd.pw_dir=field_begin;
+ break;
+ case 6: /* shell */
+ passwd.pw_shell=field_begin;
+ return &passwd;
+ break;
+ default: /* too many fields -- invalid line */
+ goto readline_restart;
+ }
+ if (field_num!=2 && field_num!=3)
+ field_begin=pwd_line+curr_index+1;
+ field_num++;
+ field_length=0;
+ }
+ curr_index++;
+ if (curr_index>=__PWD_LINE_BUFFER_SIZE)
+ {
+ if (field_num<=3)
+ goto readline_start;
+
+ if (*passwd.pw_gecos)
+ {
+ if (field_num==4) /* gecos.. least important */
+ {
+ /* erase this field */
+ curr_index-=field_length;
+ field_num++;
+ passwd.pw_gecos=field_begin-1;
+ /* read until the next delimiter */
+ while ((read(passwd_fd, &pwd_line[curr_index], 1)==1) &&
+ pwd_line[curr_index]!=':');
+
+ }
+ else if (field_num>4) /* move everything back to the gecos... */
+ {
+ unsigned short shift;
+ if (field_num==5)
+ passwd.pw_dir=field_begin;
+
+ shift=passwd.pw_dir-passwd.pw_gecos;
+ memcpy(passwd.pw_gecos,
+ passwd.pw_dir, pwd_line+curr_index-passwd.pw_dir);
+ passwd.pw_gecos--;
+ passwd.pw_dir=passwd.pw_gecos;
+ field_begin-=shift;
+ passwd.pw_shell-=shift;
+ curr_index-=shift;
+ }
+ }
+ else
+ goto readline_restart;
+ }
+ }
+ return NULL;
+}
+
diff --git a/libc-0.0.4/pwd/fgetpwent.c b/libc-0.0.4/pwd/fgetpwent.c
new file mode 100644
index 0000000..e12b890
--- /dev/null
+++ b/libc-0.0.4/pwd/fgetpwent.c
@@ -0,0 +1,35 @@
+/*
+ * fgetpwent.c - This file is part of the libc-8086/pwd package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <pwd.h>
+
+struct passwd *
+fgetpwent(FILE * file)
+{
+ if (file==NULL)
+ {
+ errno=EINTR;
+ return NULL;
+ }
+
+ return __getpwent(fileno(file));
+}
diff --git a/libc-0.0.4/pwd/getpw.c b/libc-0.0.4/pwd/getpw.c
new file mode 100644
index 0000000..4f4e390
--- /dev/null
+++ b/libc-0.0.4/pwd/getpw.c
@@ -0,0 +1,51 @@
+/*
+ * getpw.c - This file is part of the libc-8086/pwd package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <pwd.h>
+
+int
+getpw(uid_t uid, char *buf)
+{
+ struct passwd * passwd;
+
+ if (buf==NULL)
+ {
+ errno=EINVAL;
+ return -1;
+ }
+ if ((passwd=getpwuid(uid))==NULL)
+ return -1;
+
+ if (sprintf(buf, "%s:%s:%u:%u:%s:%s:%s", passwd->pw_name, passwd->pw_passwd,
+ passwd->pw_gid, passwd->pw_uid, passwd->pw_gecos,
+ passwd->pw_dir, passwd->pw_shell)<0)
+ {
+ errno=ENOBUFS;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
diff --git a/libc-0.0.4/pwd/getpwnam.c b/libc-0.0.4/pwd/getpwnam.c
new file mode 100644
index 0000000..85dbc8e
--- /dev/null
+++ b/libc-0.0.4/pwd/getpwnam.c
@@ -0,0 +1,52 @@
+/*
+ * getpwnam.c - This file is part of the libc-8086/pwd package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+
+
+struct passwd *
+getpwnam(const char * name)
+{
+ int passwd_fd;
+ struct passwd * passwd;
+
+ if (name==NULL)
+ {
+ errno=EINVAL;
+ return NULL;
+ }
+
+ if ((passwd_fd=open("/etc/passwd", O_RDONLY))<0)
+ return NULL;
+
+ while ((passwd=__getpwent(passwd_fd))!=NULL)
+ if (!strcmp(passwd->pw_name, name))
+ {
+ close(passwd_fd);
+ return passwd;
+ }
+
+ close(passwd_fd);
+ return NULL;
+}
diff --git a/libc-0.0.4/pwd/getpwuid.c b/libc-0.0.4/pwd/getpwuid.c
new file mode 100644
index 0000000..ffd58c1
--- /dev/null
+++ b/libc-0.0.4/pwd/getpwuid.c
@@ -0,0 +1,44 @@
+/*
+ * getpwuid.c - This file is part of the libc-8086/pwd package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+
+struct passwd *
+getpwuid(uid_t uid)
+{
+ int passwd_fd;
+ struct passwd * passwd;
+
+ if ((passwd_fd=open("/etc/passwd", O_RDONLY))<0)
+ return NULL;
+
+ while ((passwd=__getpwent(passwd_fd))!=NULL)
+ if (passwd->pw_uid==uid)
+ {
+ close(passwd_fd);
+ return passwd;
+ }
+
+ close (passwd_fd);
+ return NULL;
+}
diff --git a/libc-0.0.4/pwd/putpwent.c b/libc-0.0.4/pwd/putpwent.c
new file mode 100644
index 0000000..a0035ea
--- /dev/null
+++ b/libc-0.0.4/pwd/putpwent.c
@@ -0,0 +1,39 @@
+/*
+ * putpwent.c - This file is part of the libc-8086/pwd package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <pwd.h>
+
+int
+putpwent(const struct passwd * passwd, FILE * f)
+{
+ if (passwd == NULL || f == NULL)
+ {
+ errno=EINVAL;
+ return -1;
+ }
+ if (fprintf(f, "%s:%s:%u:%u:%s:%s:%s\n", passwd->pw_name, passwd->pw_passwd,
+ passwd->pw_gid, passwd->pw_uid, passwd->pw_gecos,
+ passwd->pw_dir, passwd->pw_shell)<0)
+ return -1;
+
+ return 0;
+}
diff --git a/libc-0.0.4/pwd/pwent.c b/libc-0.0.4/pwd/pwent.c
new file mode 100644
index 0000000..dc40a08
--- /dev/null
+++ b/libc-0.0.4/pwd/pwent.c
@@ -0,0 +1,62 @@
+/*
+ * pwent.c - This file is part of the libc-8086/pwd package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pwd.h>
+#include <fcntl.h>
+
+/*
+ * setpwent(), endpwent(), and getpwent() are included in the same object
+ * file, since one cannot be used without the other two, so it makes sense to
+ * link them all in together.
+ */
+
+/* file descriptor for the password file currently open */
+static int pw_fd;
+
+void
+setpwent(void)
+{
+ if (pw_fd!=-1)
+ close(pw_fd);
+
+ pw_fd=open("/etc/passwd", O_RDONLY);
+}
+
+void
+endpwent(void)
+{
+ if (pw_fd!=-1)
+ close(pw_fd);
+ pw_fd=-1;
+}
+
+struct passwd *
+getpwent(void)
+{
+ if (pw_fd!=-1)
+ return __getpwent(pw_fd);
+ return NULL;
+}
+
+
+
diff --git a/libc-0.0.4/pwd/test_pwd b/libc-0.0.4/pwd/test_pwd
new file mode 100755
index 0000000..bac2f1e
--- /dev/null
+++ b/libc-0.0.4/pwd/test_pwd
Binary files differ
diff --git a/libc-0.0.4/pwd/test_pwd.c b/libc-0.0.4/pwd/test_pwd.c
new file mode 100644
index 0000000..3279fb2
--- /dev/null
+++ b/libc-0.0.4/pwd/test_pwd.c
@@ -0,0 +1,91 @@
+/*
+ * test_pwd.c - This file is part of the libc-8086/pwd package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman <ndf@linux.mit.edu>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <pwd.h>
+
+int
+main(int argc, char ** argv)
+{
+ struct passwd * passwd;
+ int test_uid;
+
+ fprintf(stderr, "Beginning test of libc/pwd...\n");
+
+ fprintf(stderr, "=> Testing setpwent(), getpwent(), endpwent()...\n");
+ fprintf(stderr, "-> setpwent()...\n");
+ setpwent();
+ fprintf(stderr, "-> getpwent()...\n");
+ printf("********************************************************************************\n");
+ while ((passwd=getpwent())!=NULL)
+ {
+ printf("pw_name\t\t: %s\n", passwd->pw_name);
+ printf("pw_passwd\t: %s\n", passwd->pw_passwd);
+ printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid);
+ printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid);
+ printf("pw_gecos\t: %s\n", passwd->pw_gecos);
+ printf("pw_dir\t\t: %s\n", passwd->pw_dir);
+ printf("pw_shell\t: %s\n", passwd->pw_shell);
+ printf("********************************************************************************\n");
+ }
+ fprintf(stderr, "-> endpwent()...\n");
+ endpwent();
+ fprintf(stderr, "=> Test of setpwent(), getpwent(), endpwent() complete.\n");
+ fprintf(stderr, "=> Testing getpwuid(), getpwnam()...\n");
+ fprintf(stderr, "-> getpwuid()...\n");
+ printf("********************************************************************************\n");
+ for(test_uid=0;test_uid<100;test_uid++)
+ {
+ fprintf(stderr, "-> getpwuid(%d)...\n", test_uid);
+ passwd=getpwuid((uid_t) test_uid);
+ if (passwd!=NULL)
+ {
+ printf("pw_name\t\t: %s\n", passwd->pw_name);
+ printf("pw_passwd\t: %s\n", passwd->pw_passwd);
+ printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid);
+ printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid);
+ printf("pw_gecos\t: %s\n", passwd->pw_gecos);
+ printf("pw_dir\t\t: %s\n", passwd->pw_dir);
+ printf("pw_shell\t: %s\n", passwd->pw_shell);
+ }
+ printf("********************************************************************************\n");
+ }
+ fprintf(stderr, "-> getpwnam()...\n");
+ passwd=getpwnam("root");
+ if (passwd==NULL)
+ {
+ printf(">NULL<\n");
+ }
+ else
+ {
+ printf("pw_name\t\t: %s\n", passwd->pw_name);
+ printf("pw_passwd\t: %s\n", passwd->pw_passwd);
+ printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid);
+ printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid);
+ printf("pw_gecos\t: %s\n", passwd->pw_gecos);
+ printf("pw_dir\t\t: %s\n", passwd->pw_dir);
+ printf("pw_shell\t: %s\n", passwd->pw_shell);
+ }
+ return 0;
+}
+
+
diff --git a/libc-0.0.4/regexp/Config b/libc-0.0.4/regexp/Config
new file mode 100644
index 0000000..bd644a6
--- /dev/null
+++ b/libc-0.0.4/regexp/Config
@@ -0,0 +1 @@
+regexp: Regular expression lib
diff --git a/libc-0.0.4/regexp/Makefile b/libc-0.0.4/regexp/Makefile
new file mode 100644
index 0000000..b330451
--- /dev/null
+++ b/libc-0.0.4/regexp/Makefile
@@ -0,0 +1,28 @@
+
+TOP=..
+include $(TOP)/Make.defs
+
+OBJ=regexp.o regsub.o
+LSRC=regexp.c regsub.c regerror.c
+
+try: try.o $(OBJ)
+ $(CC) $(CFLAGS) try.o $(OBJ) -o try
+
+# Regression test.
+test: try tests
+ @echo 'No news is good news...'
+ try <tests
+
+$(LIBC): $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+transfer:
+ -@rm -f ../include/regexp.h ../include/regmagic.h
+ cp -p regexp.h regmagic.h ../include/.
+
+regexp.o: regexp.c regexp.h regmagic.h
+regsub.o: regsub.c regexp.h regmagic.h
+
+clean:
+ rm -f libc.a *.o core mon.out timer.t.h dMakefile dtr try timer
diff --git a/libc-0.0.4/regexp/Makefile.org b/libc-0.0.4/regexp/Makefile.org
new file mode 100644
index 0000000..a8be06e
--- /dev/null
+++ b/libc-0.0.4/regexp/Makefile.org
@@ -0,0 +1,63 @@
+# Things you might want to put in ENV and LENV:
+# -Dvoid=int compilers that don't do void
+# -DCHARBITS=0377 compilers that don't do unsigned char
+# -DSTATIC=extern compilers that don't like "static foo();" as forward decl
+# -DSTRCSPN library does not have strcspn()
+# -Dstrchr=index library does not have strchr()
+# -DERRAVAIL have utzoo-compatible error() function and friends
+# ENV=-DCHARBITS=0377
+# LENV=-DCHARBITS=0377
+
+# Things you might want to put in TEST:
+# -DDEBUG debugging hooks
+# -I. regexp.h from current directory, not /usr/include
+TEST=-I.
+
+# Things you might want to put in PROF:
+# -Dstatic='/* */' make everything global so profiler can see it.
+# -p profiler
+PROF=
+
+CFLAGS=-O $(ENV) $(TEST) $(PROF)
+LINTFLAGS=$(LENV) $(TEST) -ha
+LDFLAGS=-i
+
+OBJ=regexp.o regsub.o
+LSRC=regexp.c regsub.c regerror.c
+DTR=README dMakefile regexp.3 regexp.h regexp.c regsub.c regerror.c \
+ regmagic.h try.c timer.c tests
+
+try: try.o $(OBJ)
+ cc $(LDFLAGS) try.o $(OBJ) -o try
+
+# Making timer will probably require putting stuff in $(PROF) and then
+# recompiling everything; the following is just the final stage.
+timer: timer.o $(OBJ)
+ cc $(LDFLAGS) $(PROF) timer.o $(OBJ) -o timer
+
+timer.o: timer.c timer.t.h
+
+timer.t.h: tests
+ sed 's/ /","/g;s/\\/&&/g;s/.*/{"&"},/' tests >timer.t.h
+
+# Regression test.
+r: try tests
+ @echo 'No news is good news...'
+ try <tests
+
+lint: timer.t.h
+ @echo 'Complaints about multiply-declared regerror() are legit.'
+ lint $(LINTFLAGS) $(LSRC) try.c
+ lint $(LINTFLAGS) $(LSRC) timer.c
+
+regexp.o: regexp.c regexp.h regmagic.h
+regsub.o: regsub.c regexp.h regmagic.h
+
+clean:
+ rm -f *.o core mon.out timer.t.h dMakefile dtr try timer
+
+dtr: r makedtr $(DTR)
+ makedtr $(DTR) >dtr
+
+dMakefile: Makefile
+ sed '/^L*ENV=/s/ *-DERRAVAIL//' Makefile >dMakefile
diff --git a/libc-0.0.4/regexp/README b/libc-0.0.4/regexp/README
new file mode 100644
index 0000000..37d6f51
--- /dev/null
+++ b/libc-0.0.4/regexp/README
@@ -0,0 +1,84 @@
+This is a nearly-public-domain reimplementation of the V8 regexp(3) package.
+It gives C programs the ability to use egrep-style regular expressions, and
+does it in a much cleaner fashion than the analogous routines in SysV.
+
+ Copyright (c) 1986 by University of Toronto.
+ Written by Henry Spencer. Not derived from licensed software.
+
+ Permission is granted to anyone to use this software for any
+ purpose on any computer system, and to redistribute it freely,
+ subject to the following restrictions:
+
+ 1. The author is not responsible for the consequences of use of
+ this software, no matter how awful, even if they arise
+ from defects in it.
+
+ 2. The origin of this software must not be misrepresented, either
+ by explicit claim or by omission.
+
+ 3. Altered versions must be plainly marked as such, and must not
+ be misrepresented as being the original software.
+
+Barring a couple of small items in the BUGS list, this implementation is
+believed 100% compatible with V8. It should even be binary-compatible,
+sort of, since the only fields in a "struct regexp" that other people have
+any business touching are declared in exactly the same way at the same
+location in the struct (the beginning).
+
+This implementation is *NOT* AT&T/Bell code, and is not derived from licensed
+software. Even though U of T is a V8 licensee. This software is based on
+a V8 manual page sent to me by Dennis Ritchie (the manual page enclosed
+here is a complete rewrite and hence is not covered by AT&T copyright).
+The software was nearly complete at the time of arrival of our V8 tape.
+I haven't even looked at V8 yet, although a friend elsewhere at U of T has
+been kind enough to run a few test programs using the V8 regexp(3) to resolve
+a few fine points. I admit to some familiarity with regular-expression
+implementations of the past, but the only one that this code traces any
+ancestry to is the one published in Kernighan & Plauger (from which this
+one draws ideas but not code).
+
+Simplistically: put this stuff into a source directory, copy regexp.h into
+/usr/include, inspect Makefile for compilation options that need changing
+to suit your local environment, and then do "make r". This compiles the
+regexp(3) functions, compiles a test program, and runs a large set of
+regression tests. If there are no complaints, then put regexp.o, regsub.o,
+and regerror.o into your C library, and regexp.3 into your manual-pages
+directory.
+
+Note that if you don't put regexp.h into /usr/include *before* compiling,
+you'll have to add "-I." to CFLAGS before compiling.
+
+The files are:
+
+Makefile instructions to make everything
+regexp.3 manual page
+regexp.h header file, for /usr/include
+regexp.c source for regcomp() and regexec()
+regsub.c source for regsub()
+regerror.c source for default regerror()
+regmagic.h internal header file
+try.c source for test program
+timer.c source for timing program
+tests test list for try and timer
+
+This implementation uses nondeterministic automata rather than the
+deterministic ones found in some other implementations, which makes it
+simpler, smaller, and faster at compiling regular expressions, but slower
+at executing them. In theory, anyway. This implementation does employ
+some special-case optimizations to make the simpler cases (which do make
+up the bulk of regular expressions actually used) run quickly. In general,
+if you want blazing speed you're in the wrong place. Replacing the insides
+of egrep with this stuff is probably a mistake; if you want your own egrep
+you're going to have to do a lot more work. But if you want to use regular
+expressions a little bit in something else, you're in luck. Note that many
+existing text editors use nondeterministic regular-expression implementations,
+so you're in good company.
+
+This stuff should be pretty portable, given appropriate option settings.
+If your chars have less than 8 bits, you're going to have to change the
+internal representation of the automaton, although knowledge of the details
+of this is fairly localized. There are no "reserved" char values except for
+NUL, and no special significance is attached to the top bit of chars.
+The string(3) functions are used a fair bit, on the grounds that they are
+probably faster than coding the operations in line. Some attempts at code
+tuning have been made, but this is invariably a bit machine-specific.
diff --git a/libc-0.0.4/regexp/README.rdb b/libc-0.0.4/regexp/README.rdb
new file mode 100644
index 0000000..1c3bba6
--- /dev/null
+++ b/libc-0.0.4/regexp/README.rdb
@@ -0,0 +1,6 @@
+
+I've applied the four bugfix patches I've found and made a couple of
+very small changes (added malloc.h) and put in a new Makefile.
+Otherwise this is as it was posted on by Henry Spencer to mod.sources.
+
+-Robert
diff --git a/libc-0.0.4/regexp/patch.1 b/libc-0.0.4/regexp/patch.1
new file mode 100644
index 0000000..6126592
--- /dev/null
+++ b/libc-0.0.4/regexp/patch.1
@@ -0,0 +1,32 @@
+Subject: bug in regexp(3), and fix
+Newsgroups: mod.sources
+Approved: jpn@panda.UUCP
+
+Mod.sources: Volume 3, Issue 105
+Submitted by: genrad!decvax!utzoo!henry
+
+Drat! Chris Siebenmann at CSRI just found a bug in my regexp(3) routines.
+The problem is that the code for character classes does not check properly
+for the possibility that it might be looking at the end of the string. By
+simple bad luck none of my test cases hit this. To fix it, make the
+following two changes to regexp.c:
+
+848c848
+< if (strchr(OPERAND(scan), *reginput) == NULL)
+---
+> if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
+853c853
+< if (strchr(OPERAND(scan), *reginput) != NULL)
+---
+> if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
+
+and recompile. Also, add the following line to the "tests" file:
+
+[k] ab n - -
+
+My thanks to Chris for finding this.
+
+ Henry Spencer @ U of Toronto Zoology
+ {allegra,ihnp4,linus,decvax}!utzoo!henry
+
+
diff --git a/libc-0.0.4/regexp/patch.2 b/libc-0.0.4/regexp/patch.2
new file mode 100644
index 0000000..fcf4778
--- /dev/null
+++ b/libc-0.0.4/regexp/patch.2
@@ -0,0 +1,27 @@
+Subject: 2nd bug fix for regexp(3), in regsub()
+Newsgroups: mod.sources
+Approved: jpn@panda.UUCP
+
+Mod.sources: Volume 4, Issue 33
+Submitted by: genrad!decvax!utzoo!henry
+
+I cringe with embarrassment! Another bug in regexp! In regsub.c, the
+following line (line 72 in the original distribution):
+
+ if (*(dst-1) == '\0') { /* strncpy hit NUL. */
+
+should read
+
+ if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */
+
+This shows up as an occasional spurious complaint from regsub about
+"damaged match string"... *if* the program invoking it, and the compiler
+compiling it, happen to interact just right. It didn't show in any of
+my tests because mine don't.
+
+My thanks to H}vard Eidnes for finding this.
+
+ Henry Spencer @ U of Toronto Zoology
+ {allegra,ihnp4,linus,decvax}!utzoo!henry
+
+
diff --git a/libc-0.0.4/regexp/patch.3 b/libc-0.0.4/regexp/patch.3
new file mode 100644
index 0000000..36bafd4
--- /dev/null
+++ b/libc-0.0.4/regexp/patch.3
@@ -0,0 +1,46 @@
+Subject: regexp(3) improvement
+Newsgroups: mod.sources
+Approved: jpn@panda.UUCP
+
+Mod.sources: Volume 4, Issue 49
+Submitted by: utzoo!henry (Henry Spencer)
+
+One flaw of my regexp(3) as distributed is that there is no way to get
+a literal `&' or '\n' (n a digit) past regsub(). The V8 manual page
+made no mention of an escape convention. It turns out that this is a
+deficiency in the documentation rather than the software. Accordingly,
+the following update should be applied to my regexp(3) to preserve full
+compatibility and to add this useful facility.
+
+In regsub.c, change the following (line numbers approximate only):
+
+67,69c67,71
+< if (no < 0) /* Ordinary character. */
+< *dst++ = c;
+< else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
+---
+> if (no < 0) { /* Ordinary character. */
+> if (c == '\\' && (*src == '\\' || *src == '&'))
+> c = *src++;
+> *dst++ = c;
+> } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
+
+In regexp.3, add the following sentence to the end of the paragraph
+describing regsub:
+
+To get a literal `&' or `\e\fIn\fR' into \fIdest\fR, prefix it with `\e';
+to get a literal `\e' preceding `&' or `\e\fIn\fR', prefix it with
+another `\e'.
+
+And add the following two lines to the "tests" file:
+
+abcd abcd y &-\&-\\& abcd-&-\abcd
+a(bc)d abcd y \1-\\1-\\\1 bc-\1-\bc
+
+My thanks to Mike Lutz at Rochester Institute of Technology for noticing
+this issue and alerting me to it.
+
+ Henry Spencer @ U of Toronto Zoology
+ {allegra,ihnp4,decvax,pyramid}!utzoo!henry
+
+
diff --git a/libc-0.0.4/regexp/patch.4 b/libc-0.0.4/regexp/patch.4
new file mode 100644
index 0000000..4d8ea3a
--- /dev/null
+++ b/libc-0.0.4/regexp/patch.4
@@ -0,0 +1,65 @@
+Path: uunet!rs
+From: rs@uunet.UU.NET (Rich Salz)
+Newsgroups: comp.sources.unix
+Subject: v10i097: Bug-fix for regexp() library
+Message-ID: <789@uunet.UU.NET>
+Date: 7 Aug 87 11:20:15 GMT
+Organization: UUNET Communications Services, Arlington, VA
+Lines: 46
+Approved: rs@uunet.UU.NET
+
+Submitted-by: seismo!ai.toronto.edu!utzoo!henry
+Posting-number: Volume 10, Issue 97
+Archive-name: regexp.pch
+
+FURTHER NOTE by Rich $alz on Tue Apr 26 20:02:59 EDT 1988:
+ This is a patch for Henry's regexp posting that appeared in
+ volume 3 (first patch was volume3/regexp2; the naming
+ convention used by my predecessor). There is another
+ regexp library in volume 7 -- they're unreleated.
+
+ The "fastgrep" posting appeards in volume 9. It also includes
+ Henry's volume3 posting and both sets of patches.
+
+[ Regexp was published by itself in volume 6, and also as part of the
+ "fastest grep around" earlier in this volume. --r$ ]
+
+Jeff Mc Carrell at Berkeley has found (gasp! choke! the horror! the horror!)
+another bug in my regexp functions. One thing my test set did not include
+was very large regular expressions. The bug is in the NEXT macro, which
+digs out the offset to the next node of the regexp: a parenthesization
+botch makes trouble if the offset is ever larger than 255. How humiliating.
+Here is the fix to regexp.c:
+
+116c116
+< #define NEXT(p) (((*((p)+1)&0377)<<8) + *((p)+2)&0377)
+---
+> #define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+
+and here are some more lines for the "tests" file:
+
+[ -~]* abc y & abc
+[ -~ -~]* abc y & abc
+[ -~ -~ -~]* abc y & abc
+[ -~ -~ -~ -~]* abc y & abc
+[ -~ -~ -~ -~ -~]* abc y & abc
+[ -~ -~ -~ -~ -~ -~]* abc y & abc
+[ -~ -~ -~ -~ -~ -~ -~]* abc y & abc
+
+
+Just to let people know: there is some prospect of me coming out with
+a second edition of my regexp stuff, including a number of improvements
+that various people have suggested/contributed. However, it will not be
+soon, because I'm very busy right now. I can't spare the time to sort
+it all out, decide what belongs and what doesn't, write the missing bits
+of code, and integrate it all. Sometime later this year, maybe.
+
+ Henry Spencer @ U of Toronto Zoology
+ {allegra,ihnp4,decvax,pyramid}!utzoo!henry
+
+
+--
+
+Rich $alz "Anger is an energy"
+Cronus Project, BBN Labs rsalz@bbn.com
+Moderator, comp.sources.unix sources@uunet.uu.net
diff --git a/libc-0.0.4/regexp/regerror.c b/libc-0.0.4/regexp/regerror.c
new file mode 100644
index 0000000..63864c7
--- /dev/null
+++ b/libc-0.0.4/regexp/regerror.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+void
+regerror(s)
+char *s;
+{
+#ifdef ERRAVAIL
+ error("regexp: %s", s);
+#else
+ fprintf(stderr, "regexp(3): %s", s);
+ exit(1);
+#endif
+ /* NOTREACHED */
+}
diff --git a/libc-0.0.4/regexp/regexp.3 b/libc-0.0.4/regexp/regexp.3
new file mode 100644
index 0000000..c0e29ea
--- /dev/null
+++ b/libc-0.0.4/regexp/regexp.3
@@ -0,0 +1,176 @@
+.TH REGEXP 3 local
+.DA 30 Nov 1985
+.SH NAME
+regcomp, regexec, regsub, regerror \- regular expression handler
+.SH SYNOPSIS
+.ft B
+.nf
+#include <regexp.h>
+
+regexp *regcomp(exp)
+char *exp;
+
+int regexec(prog, string)
+regexp *prog;
+char *string;
+
+regsub(prog, source, dest)
+regexp *prog;
+char *source;
+char *dest;
+
+regerror(msg)
+char *msg;
+.SH DESCRIPTION
+These functions implement
+.IR egrep (1)-style
+regular expressions and supporting facilities.
+.PP
+.I Regcomp
+compiles a regular expression into a structure of type
+.IR regexp ,
+and returns a pointer to it.
+The space has been allocated using
+.IR malloc (3)
+and may be released by
+.IR free .
+.PP
+.I Regexec
+matches a NUL-terminated \fIstring\fR against the compiled regular expression
+in \fIprog\fR.
+It returns 1 for success and 0 for failure, and adjusts the contents of
+\fIprog\fR's \fIstartp\fR and \fIendp\fR (see below) accordingly.
+.PP
+The members of a
+.I regexp
+structure include at least the following (not necessarily in order):
+.PP
+.RS
+char *startp[NSUBEXP];
+.br
+char *endp[NSUBEXP];
+.RE
+.PP
+where
+.I NSUBEXP
+is defined (as 10) in the header file.
+Once a successful \fIregexec\fR has been done using the \fIregexp\fR,
+each \fIstartp\fR-\fIendp\fR pair describes one substring
+within the \fIstring\fR,
+with the \fIstartp\fR pointing to the first character of the substring and
+the \fIendp\fR pointing to the first character following the substring.
+The 0th substring is the substring of \fIstring\fR that matched the whole
+regular expression.
+The others are those substrings that matched parenthesized expressions
+within the regular expression, with parenthesized expressions numbered
+in left-to-right order of their opening parentheses.
+.PP
+.I Regsub
+copies \fIsource\fR to \fIdest\fR, making substitutions according to the
+most recent \fIregexec\fR performed using \fIprog\fR.
+Each instance of `&' in \fIsource\fR is replaced by the substring
+indicated by \fIstartp\fR[\fI0\fR] and
+\fIendp\fR[\fI0\fR].
+Each instance of `\e\fIn\fR', where \fIn\fR is a digit, is replaced by
+the substring indicated by
+\fIstartp\fR[\fIn\fR] and
+\fIendp\fR[\fIn\fR].
+.PP
+.I Regerror
+is called whenever an error is detected in \fIregcomp\fR, \fIregexec\fR,
+or \fIregsub\fR.
+The default \fIregerror\fR writes the string \fImsg\fR,
+with a suitable indicator of origin,
+on the standard
+error output
+and invokes \fIexit\fR(2).
+.I Regerror
+can be replaced by the user if other actions are desirable.
+.SH "REGULAR EXPRESSION SYNTAX"
+A regular expression is zero or more \fIbranches\fR, separated by `|'.
+It matches anything that matches one of the branches.
+.PP
+A branch is zero or more \fIpieces\fR, concatenated.
+It matches a match for the first, followed by a match for the second, etc.
+.PP
+A piece is an \fIatom\fR possibly followed by `*', `+', or `?'.
+An atom followed by `*' matches a sequence of 0 or more matches of the atom.
+An atom followed by `+' matches a sequence of 1 or more matches of the atom.
+An atom followed by `?' matches a match of the atom, or the null string.
+.PP
+An atom is a regular expression in parentheses (matching a match for the
+regular expression), a \fIrange\fR (see below), `.'
+(matching any single character), `^' (matching the null string at the
+beginning of the input string), `$' (matching the null string at the
+end of the input string), a `\e' followed by a single character (matching
+that character), or a single character with no other significance
+(matching that character).
+.PP
+A \fIrange\fR is a sequence of characters enclosed in `[]'.
+It normally matches any single character from the sequence.
+If the sequence begins with `^',
+it matches any single character \fInot\fR from the rest of the sequence.
+If two characters in the sequence are separated by `\-', this is shorthand
+for the full list of ASCII characters between them
+(e.g. `[0-9]' matches any decimal digit).
+To include a literal `]' in the sequence, make it the first character
+(following a possible `^').
+To include a literal `\-', make it the first or last character.
+.SH AMBIGUITY
+If a regular expression could match two different parts of the input string,
+it will match the one which begins earliest.
+If both begin in the same place but match different lengths, or match
+the same length in different ways, life gets messier, as follows.
+.PP
+In general, the possibilities in a list of branches are considered in
+left-to-right order, the possibilities for `*', `+', and `?' are
+considered longest-first, nested constructs are considered from the
+outermost in, and concatenated constructs are considered leftmost-first.
+The match that will be chosen is the one that uses the earliest
+possibility in the first choice that has to be made.
+If there is more than one choice, the next will be made in the same manner
+(earliest possibility) subject to the decision on the first choice.
+And so forth.
+.PP
+For example, `(ab|a)b*c' could match `abc' in one of two ways.
+The first choice is between `ab' and `a'; since `ab' is earlier, and does
+lead to a successful overall match, it is chosen.
+Since the `b' is already spoken for,
+the `b*' must match its last possibility\(emthe empty string\(emsince
+it must respect the earlier choice.
+.PP
+In the particular case where no `|'s are present and there is only one
+`*', `+', or `?', the net effect is that the longest possible
+match will be chosen.
+So `ab*', presented with `xabbbby', will match `abbbb'.
+Note that if `ab*' is tried against `xabyabbbz', it
+will match `ab' just after `x', due to the begins-earliest rule.
+(In effect, the decision on where to start the match is the first choice
+to be made, hence subsequent choices must respect it even if this leads them
+to less-preferred alternatives.)
+.SH SEE ALSO
+egrep(1), expr(1)
+.SH DIAGNOSTICS
+\fIRegcomp\fR returns NULL for a failure
+(\fIregerror\fR permitting),
+where failures are syntax errors, exceeding implementation limits,
+or applying `+' or `*' to a possibly-null operand.
+.SH HISTORY
+Both code and manual page were
+written at U of T.
+They are intended to be compatible with the Bell V8 \fIregexp\fR(3),
+but are not derived from Bell code.
+.SH BUGS
+Empty branches and empty regular expressions are not portable to V8.
+.PP
+The restriction against
+applying `*' or `+' to a possibly-null operand is an artifact of the
+simplistic implementation.
+.PP
+Does not support \fIegrep\fR's newline-separated branches;
+neither does the V8 \fIregexp\fR(3), though.
+.PP
+Due to emphasis on
+compactness and simplicity,
+it's not strikingly fast.
+It does give special attention to handling simple cases quickly.
diff --git a/libc-0.0.4/regexp/regexp.c b/libc-0.0.4/regexp/regexp.c
new file mode 100644
index 0000000..860b485
--- /dev/null
+++ b/libc-0.0.4/regexp/regexp.c
@@ -0,0 +1,1213 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions. Serious changes in
+ * regular-expression syntax might require a total rethink.
+ */
+#include <stdio.h>
+#include <regexp.h>
+#include <malloc.h>
+#include <string.h>
+#include "regmagic.h"
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases. They are:
+ *
+ * regstart char that must begin a match; '\0' if none obvious
+ * reganch is the match anchored (at beginning-of-line only)?
+ * regmust string (pointer into program) that match must include, or NULL
+ * regmlen length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot. Regmust permits fast rejection
+ * of lines that cannot possibly match. The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup). Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program". This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology). Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives. (Here we
+ * have one of the subtle syntax dependencies: an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.) The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM. In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure: the tail of the branch connects
+ * to the thing following the set of BRANCHes.) The opcodes are:
+ */
+
+/* definition number opnd? meaning */
+#define END 0 /* no End of program. */
+#define BOL 1 /* no Match "" at beginning of line. */
+#define EOL 2 /* no Match "" at end of line. */
+#define ANY 3 /* no Match any one character. */
+#define ANYOF 4 /* str Match any character in this string. */
+#define ANYBUT 5 /* str Match any character not in this string. */
+#define BRANCH 6 /* node Match this alternative, or the next... */
+#define BACK 7 /* no Match "", "next" ptr points backward. */
+#define EXACTLY 8 /* str Match this string. */
+#define NOTHING 9 /* no Match empty string. */
+#define STAR 10 /* node Match this (simple) thing 0 or more times. */
+#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
+#define OPEN 20 /* no Mark this point in input as start of #n. */
+ /* OPEN+1 is number 1, etc. */
+#define CLOSE 30 /* no Analogous to OPEN. */
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH The set of branches constituting a single choice are hooked
+ * together with their "next" pointers, since precedence prevents
+ * anything being concatenated to any individual branch. The
+ * "next" pointer of the last BRANCH in a choice points to the
+ * thing following the whole choice. This is also where the
+ * final "next" pointer of each individual branch points; each
+ * branch starts with the operand node of a BRANCH node.
+ *
+ * BACK Normal "next" pointers all implicitly point forward; BACK
+ * exists to make loop structures possible.
+ *
+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
+ * BRANCH structures using BACK. Simple cases (one character
+ * per match) are implemented with STAR and PLUS for speed
+ * and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE ...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first. The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node. (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define OP(p) (*(p))
+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define OPERAND(p) ((p) + 3)
+
+/*
+ * See regmagic.h for one further detail of program structure.
+ */
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define UCHARAT(p) ((int)*(unsigned char *)(p))
+#else
+#define UCHARAT(p) ((int)*(p)&CHARBITS)
+#endif
+
+#define FAIL(m) { regerror(m); return(NULL); }
+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
+#define META "^$.[()|?+*\\"
+
+/*
+ * Flags to be passed up and down.
+ */
+#define HASWIDTH 01 /* Known never to match null string. */
+#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
+#define SPSTART 04 /* Starts with * or +. */
+#define WORST 0 /* Worst case. */
+
+/*
+ * Global work variables for regcomp().
+ */
+static char *regparse; /* Input-scan pointer. */
+static int regnpar; /* () count. */
+static char regdummy;
+static char *regcode; /* Code-emit pointer; &regdummy = don't. */
+static long regsize; /* Code size. */
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+#ifndef STATIC
+#define STATIC static
+#endif
+STATIC char *reg();
+STATIC char *regbranch();
+STATIC char *regpiece();
+STATIC char *regatom();
+STATIC char *regnode();
+STATIC char *regnext();
+STATIC void regc();
+STATIC void reginsert();
+STATIC void regtail();
+STATIC void regoptail();
+#ifdef STRCSPN
+STATIC int strcspn();
+#endif
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code. So we cheat: we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it. (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp(exp)
+char *exp;
+{
+ register regexp *r;
+ register char *scan;
+ register char *longest;
+ register int len;
+ int flags;
+
+ if (exp == NULL)
+ FAIL("NULL argument");
+
+ /* First pass: determine size, legality. */
+ regparse = exp;
+ regnpar = 1;
+ regsize = 0L;
+ regcode = &regdummy;
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Small enough for pointer-storage convention? */
+ if (regsize >= 32767L) /* Probably could be 65535L. */
+ FAIL("regexp too big");
+
+ /* Allocate space. */
+ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
+ if (r == NULL)
+ FAIL("out of space");
+
+ /* Second pass: emit code. */
+ regparse = exp;
+ regnpar = 1;
+ regcode = r->program;
+ regc(MAGIC);
+ if (reg(0, &flags) == NULL)
+ return(NULL);
+
+ /* Dig out information for optimizations. */
+ r->regstart = '\0'; /* Worst-case defaults. */
+ r->reganch = 0;
+ r->regmust = NULL;
+ r->regmlen = 0;
+ scan = r->program+1; /* First BRANCH. */
+ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
+ scan = OPERAND(scan);
+
+ /* Starting-point info. */
+ if (OP(scan) == EXACTLY)
+ r->regstart = *OPERAND(scan);
+ else if (OP(scan) == BOL)
+ r->reganch++;
+
+ /*
+ * If there's something expensive in the r.e., find the
+ * longest literal string that must appear and make it the
+ * regmust. Resolve ties in favor of later strings, since
+ * the regstart check works with the beginning of the r.e.
+ * and avoiding duplication strengthens checking. Not a
+ * strong reason, but sufficient in the absence of others.
+ */
+ if (flags&SPSTART) {
+ longest = NULL;
+ len = 0;
+ for (; scan != NULL; scan = regnext(scan))
+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+ longest = OPERAND(scan);
+ len = strlen(OPERAND(scan));
+ }
+ r->regmust = longest;
+ r->regmlen = len;
+ }
+ }
+
+ return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char *
+reg(paren, flagp)
+int paren; /* Parenthesized? */
+int *flagp;
+{
+ register char *ret;
+ register char *br;
+ register char *ender;
+ register int parno;
+ int flags;
+
+ *flagp = HASWIDTH; /* Tentatively. */
+
+ /* Make an OPEN node, if parenthesized. */
+ if (paren) {
+ if (regnpar >= NSUBEXP)
+ FAIL("too many ()");
+ parno = regnpar;
+ regnpar++;
+ ret = regnode(OPEN+parno);
+ } else
+ ret = NULL;
+
+ /* Pick up the branches, linking them together. */
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ if (ret != NULL)
+ regtail(ret, br); /* OPEN -> first. */
+ else
+ ret = br;
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ while (*regparse == '|') {
+ regparse++;
+ br = regbranch(&flags);
+ if (br == NULL)
+ return(NULL);
+ regtail(ret, br); /* BRANCH -> BRANCH. */
+ if (!(flags&HASWIDTH))
+ *flagp &= ~HASWIDTH;
+ *flagp |= flags&SPSTART;
+ }
+
+ /* Make a closing node, and hook it on the end. */
+ ender = regnode((paren) ? CLOSE+parno : END);
+ regtail(ret, ender);
+
+ /* Hook the tails of the branches to the closing node. */
+ for (br = ret; br != NULL; br = regnext(br))
+ regoptail(br, ender);
+
+ /* Check for proper termination. */
+ if (paren && *regparse++ != ')') {
+ FAIL("unmatched ()");
+ } else if (!paren && *regparse != '\0') {
+ if (*regparse == ')') {
+ FAIL("unmatched ()");
+ } else
+ FAIL("junk on end"); /* "Can't happen". */
+ /* NOTREACHED */
+ }
+
+ return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char *
+regbranch(flagp)
+int *flagp;
+{
+ register char *ret;
+ register char *chain;
+ register char *latest;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ ret = regnode(BRANCH);
+ chain = NULL;
+ while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
+ latest = regpiece(&flags);
+ if (latest == NULL)
+ return(NULL);
+ *flagp |= flags&HASWIDTH;
+ if (chain == NULL) /* First piece. */
+ *flagp |= flags&SPSTART;
+ else
+ regtail(chain, latest);
+ chain = latest;
+ }
+ if (chain == NULL) /* Loop ran zero times. */
+ (void) regnode(NOTHING);
+
+ return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized: they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char *
+regpiece(flagp)
+int *flagp;
+{
+ register char *ret;
+ register char op;
+ register char *next;
+ int flags;
+
+ ret = regatom(&flags);
+ if (ret == NULL)
+ return(NULL);
+
+ op = *regparse;
+ if (!ISMULT(op)) {
+ *flagp = flags;
+ return(ret);
+ }
+
+ if (!(flags&HASWIDTH) && op != '?')
+ FAIL("*+ operand could be empty");
+ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+ if (op == '*' && (flags&SIMPLE))
+ reginsert(STAR, ret);
+ else if (op == '*') {
+ /* Emit x* as (x&|), where & means "self". */
+ reginsert(BRANCH, ret); /* Either x */
+ regoptail(ret, regnode(BACK)); /* and loop */
+ regoptail(ret, ret); /* back */
+ regtail(ret, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '+' && (flags&SIMPLE))
+ reginsert(PLUS, ret);
+ else if (op == '+') {
+ /* Emit x+ as x(&|), where & means "self". */
+ next = regnode(BRANCH); /* Either */
+ regtail(ret, next);
+ regtail(regnode(BACK), ret); /* loop back */
+ regtail(next, regnode(BRANCH)); /* or */
+ regtail(ret, regnode(NOTHING)); /* null. */
+ } else if (op == '?') {
+ /* Emit x? as (x|) */
+ reginsert(BRANCH, ret); /* Either x */
+ regtail(ret, regnode(BRANCH)); /* or */
+ next = regnode(NOTHING); /* null. */
+ regtail(ret, next);
+ regoptail(ret, next);
+ }
+ regparse++;
+ if (ISMULT(*regparse))
+ FAIL("nested *?+");
+
+ return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization: gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run. Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char *
+regatom(flagp)
+int *flagp;
+{
+ register char *ret;
+ int flags;
+
+ *flagp = WORST; /* Tentatively. */
+
+ switch (*regparse++) {
+ case '^':
+ ret = regnode(BOL);
+ break;
+ case '$':
+ ret = regnode(EOL);
+ break;
+ case '.':
+ ret = regnode(ANY);
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ case '[': {
+ register int class;
+ register int classend;
+
+ if (*regparse == '^') { /* Complement of range. */
+ ret = regnode(ANYBUT);
+ regparse++;
+ } else
+ ret = regnode(ANYOF);
+ if (*regparse == ']' || *regparse == '-')
+ regc(*regparse++);
+ while (*regparse != '\0' && *regparse != ']') {
+ if (*regparse == '-') {
+ regparse++;
+ if (*regparse == ']' || *regparse == '\0')
+ regc('-');
+ else {
+ class = UCHARAT(regparse-2)+1;
+ classend = UCHARAT(regparse);
+ if (class > classend+1)
+ FAIL("invalid [] range");
+ for (; class <= classend; class++)
+ regc(class);
+ regparse++;
+ }
+ } else
+ regc(*regparse++);
+ }
+ regc('\0');
+ if (*regparse != ']')
+ FAIL("unmatched []");
+ regparse++;
+ *flagp |= HASWIDTH|SIMPLE;
+ }
+ break;
+ case '(':
+ ret = reg(1, &flags);
+ if (ret == NULL)
+ return(NULL);
+ *flagp |= flags&(HASWIDTH|SPSTART);
+ break;
+ case '\0':
+ case '|':
+ case ')':
+ FAIL("internal urp"); /* Supposed to be caught earlier. */
+ break;
+ case '?':
+ case '+':
+ case '*':
+ FAIL("?+* follows nothing");
+ break;
+ case '\\':
+ if (*regparse == '\0')
+ FAIL("trailing \\");
+ ret = regnode(EXACTLY);
+ regc(*regparse++);
+ regc('\0');
+ *flagp |= HASWIDTH|SIMPLE;
+ break;
+ default: {
+ register int len;
+ register char ender;
+
+ regparse--;
+ len = strcspn(regparse, META);
+ if (len <= 0)
+ FAIL("internal disaster");
+ ender = *(regparse+len);
+ if (len > 1 && ISMULT(ender))
+ len--; /* Back off clear of ?+* operand. */
+ *flagp |= HASWIDTH;
+ if (len == 1)
+ *flagp |= SIMPLE;
+ ret = regnode(EXACTLY);
+ while (len > 0) {
+ regc(*regparse++);
+ len--;
+ }
+ regc('\0');
+ }
+ break;
+ }
+
+ return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+static char * /* Location. */
+regnode(op)
+char op;
+{
+ register char *ret;
+ register char *ptr;
+
+ ret = regcode;
+ if (ret == &regdummy) {
+ regsize += 3;
+ return(ret);
+ }
+
+ ptr = ret;
+ *ptr++ = op;
+ *ptr++ = '\0'; /* Null "next" pointer. */
+ *ptr++ = '\0';
+ regcode = ptr;
+
+ return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void
+regc(b)
+char b;
+{
+ if (regcode != &regdummy)
+ *regcode++ = b;
+ else
+ regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void
+reginsert(op, opnd)
+char op;
+char *opnd;
+{
+ register char *src;
+ register char *dst;
+ register char *place;
+
+ if (regcode == &regdummy) {
+ regsize += 3;
+ return;
+ }
+
+ src = regcode;
+ regcode += 3;
+ dst = regcode;
+ while (src > opnd)
+ *--dst = *--src;
+
+ place = opnd; /* Op node, where operand used to be. */
+ *place++ = op;
+ *place++ = '\0';
+ *place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void
+regtail(p, val)
+char *p;
+char *val;
+{
+ register char *scan;
+ register char *temp;
+ register int offset;
+
+ if (p == &regdummy)
+ return;
+
+ /* Find last node. */
+ scan = p;
+ for (;;) {
+ temp = regnext(scan);
+ if (temp == NULL)
+ break;
+ scan = temp;
+ }
+
+ if (OP(scan) == BACK)
+ offset = scan - val;
+ else
+ offset = val - scan;
+ *(scan+1) = (offset>>8)&0377;
+ *(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+static void
+regoptail(p, val)
+char *p;
+char *val;
+{
+ /* "Operandless" and "op != BRANCH" are synonymous in practice. */
+ if (p == NULL || p == &regdummy || OP(p) != BRANCH)
+ return;
+ regtail(OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+/*
+ * Global work variables for regexec().
+ */
+static char *reginput; /* String-input pointer. */
+static char *regbol; /* Beginning of input, for ^ check. */
+static char **regstartp; /* Pointer to startp array. */
+static char **regendp; /* Ditto for endp. */
+
+/*
+ * Forwards.
+ */
+STATIC int regtry();
+STATIC int regmatch();
+STATIC int regrepeat();
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC char *regprop();
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(prog, string)
+register regexp *prog;
+register char *string;
+{
+ register char *s;
+
+ /* Be paranoid... */
+ if (prog == NULL || string == NULL) {
+ regerror("NULL parameter");
+ return(0);
+ }
+
+ /* Check validity of program. */
+ if (UCHARAT(prog->program) != MAGIC) {
+ regerror("corrupted program");
+ return(0);
+ }
+
+ /* If there is a "must appear" string, look for it. */
+ if (prog->regmust != NULL) {
+ s = string;
+ while ((s = strchr(s, prog->regmust[0])) != NULL) {
+ if (strncmp(s, prog->regmust, prog->regmlen) == 0)
+ break; /* Found it. */
+ s++;
+ }
+ if (s == NULL) /* Not present. */
+ return(0);
+ }
+
+ /* Mark beginning of line for ^ . */
+ regbol = string;
+
+ /* Simplest case: anchored match need be tried only once. */
+ if (prog->reganch)
+ return(regtry(prog, string));
+
+ /* Messy cases: unanchored match. */
+ s = string;
+ if (prog->regstart != '\0')
+ /* We know what char it must start with. */
+ while ((s = strchr(s, prog->regstart)) != NULL) {
+ if (regtry(prog, s))
+ return(1);
+ s++;
+ }
+ else
+ /* We don't -- general case. */
+ do {
+ if (regtry(prog, s))
+ return(1);
+ } while (*s++ != '\0');
+
+ /* Failure. */
+ return(0);
+}
+
+/*
+ - regtry - try match at specific point
+ */
+static int /* 0 failure, 1 success */
+regtry(prog, string)
+regexp *prog;
+char *string;
+{
+ register int i;
+ register char **sp;
+ register char **ep;
+
+ reginput = string;
+ regstartp = prog->startp;
+ regendp = prog->endp;
+
+ sp = prog->startp;
+ ep = prog->endp;
+ for (i = NSUBEXP; i > 0; i--) {
+ *sp++ = NULL;
+ *ep++ = NULL;
+ }
+ if (regmatch(prog->program + 1)) {
+ prog->startp[0] = string;
+ prog->endp[0] = reginput;
+ return(1);
+ } else
+ return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple: check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly. In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+static int /* 0 failure, 1 success */
+regmatch(prog)
+char *prog;
+{
+ register char *scan; /* Current node. */
+ char *next; /* Next node. */
+ extern char *strchr();
+
+ scan = prog;
+#ifdef DEBUG
+ if (scan != NULL && regnarrate)
+ fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+ while (scan != NULL) {
+#ifdef DEBUG
+ if (regnarrate)
+ fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+ next = regnext(scan);
+
+ switch (OP(scan)) {
+ case BOL:
+ if (reginput != regbol)
+ return(0);
+ break;
+ case EOL:
+ if (*reginput != '\0')
+ return(0);
+ break;
+ case ANY:
+ if (*reginput == '\0')
+ return(0);
+ reginput++;
+ break;
+ case EXACTLY: {
+ register int len;
+ register char *opnd;
+
+ opnd = OPERAND(scan);
+ /* Inline the first character, for speed. */
+ if (*opnd != *reginput)
+ return(0);
+ len = strlen(opnd);
+ if (len > 1 && strncmp(opnd, reginput, len) != 0)
+ return(0);
+ reginput += len;
+ }
+ break;
+ case ANYOF:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
+ return(0);
+ reginput++;
+ break;
+ case ANYBUT:
+ if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
+ return(0);
+ reginput++;
+ break;
+ case NOTHING:
+ break;
+ case BACK:
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9: {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - OPEN;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set startp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regstartp[no] == NULL)
+ regstartp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9: {
+ register int no;
+ register char *save;
+
+ no = OP(scan) - CLOSE;
+ save = reginput;
+
+ if (regmatch(next)) {
+ /*
+ * Don't set endp if some later
+ * invocation of the same parentheses
+ * already has.
+ */
+ if (regendp[no] == NULL)
+ regendp[no] = save;
+ return(1);
+ } else
+ return(0);
+ }
+ break;
+ case BRANCH: {
+ register char *save;
+
+ if (OP(next) != BRANCH) /* No choice. */
+ next = OPERAND(scan); /* Avoid recursion. */
+ else {
+ do {
+ save = reginput;
+ if (regmatch(OPERAND(scan)))
+ return(1);
+ reginput = save;
+ scan = regnext(scan);
+ } while (scan != NULL && OP(scan) == BRANCH);
+ return(0);
+ /* NOTREACHED */
+ }
+ }
+ break;
+ case STAR:
+ case PLUS: {
+ register char nextch;
+ register int no;
+ register char *save;
+ register int min;
+
+ /*
+ * Lookahead to avoid useless match attempts
+ * when we know what character comes next.
+ */
+ nextch = '\0';
+ if (OP(next) == EXACTLY)
+ nextch = *OPERAND(next);
+ min = (OP(scan) == STAR) ? 0 : 1;
+ save = reginput;
+ no = regrepeat(OPERAND(scan));
+ while (no >= min) {
+ /* If it could work, try it. */
+ if (nextch == '\0' || *reginput == nextch)
+ if (regmatch(next))
+ return(1);
+ /* Couldn't or didn't -- back up. */
+ no--;
+ reginput = save + no;
+ }
+ return(0);
+ }
+ break;
+ case END:
+ return(1); /* Success! */
+ break;
+ default:
+ regerror("memory corruption");
+ return(0);
+ break;
+ }
+
+ scan = next;
+ }
+
+ /*
+ * We get here only if there's trouble -- normally "case END" is
+ * the terminating point.
+ */
+ regerror("corrupted pointers");
+ return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int
+regrepeat(p)
+char *p;
+{
+ register int count = 0;
+ register char *scan;
+ register char *opnd;
+
+ scan = reginput;
+ opnd = OPERAND(p);
+ switch (OP(p)) {
+ case ANY:
+ count = strlen(scan);
+ scan += count;
+ break;
+ case EXACTLY:
+ while (*opnd == *scan) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYOF:
+ while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
+ count++;
+ scan++;
+ }
+ break;
+ case ANYBUT:
+ while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
+ count++;
+ scan++;
+ }
+ break;
+ default: /* Oh dear. Called inappropriately. */
+ regerror("internal foulup");
+ count = 0; /* Best compromise. */
+ break;
+ }
+ reginput = scan;
+
+ return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static char *
+regnext(p)
+register char *p;
+{
+ register int offset;
+
+ if (p == &regdummy)
+ return(NULL);
+
+ offset = NEXT(p);
+ if (offset == 0)
+ return(NULL);
+
+ if (OP(p) == BACK)
+ return(p-offset);
+ else
+ return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump(r)
+regexp *r;
+{
+ register char *s;
+ register char op = EXACTLY; /* Arbitrary non-END op. */
+ register char *next;
+ extern char *strchr();
+
+
+ s = r->program + 1;
+ while (op != END) { /* While that wasn't END last time... */
+ op = OP(s);
+ printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
+ next = regnext(s);
+ if (next == NULL) /* Next ptr. */
+ printf("(0)");
+ else
+ printf("(%d)", (s-r->program)+(next-s));
+ s += 3;
+ if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+ /* Literal string, where present. */
+ while (*s != '\0') {
+ putchar(*s);
+ s++;
+ }
+ s++;
+ }
+ putchar('\n');
+ }
+
+ /* Header fields of interest. */
+ if (r->regstart != '\0')
+ printf("start `%c' ", r->regstart);
+ if (r->reganch)
+ printf("anchored ");
+ if (r->regmust != NULL)
+ printf("must have \"%s\"", r->regmust);
+ printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *
+regprop(op)
+char *op;
+{
+ register char *p;
+ static char buf[50];
+
+ (void) strcpy(buf, ":");
+
+ switch (OP(op)) {
+ case BOL:
+ p = "BOL";
+ break;
+ case EOL:
+ p = "EOL";
+ break;
+ case ANY:
+ p = "ANY";
+ break;
+ case ANYOF:
+ p = "ANYOF";
+ break;
+ case ANYBUT:
+ p = "ANYBUT";
+ break;
+ case BRANCH:
+ p = "BRANCH";
+ break;
+ case EXACTLY:
+ p = "EXACTLY";
+ break;
+ case NOTHING:
+ p = "NOTHING";
+ break;
+ case BACK:
+ p = "BACK";
+ break;
+ case END:
+ p = "END";
+ break;
+ case OPEN+1:
+ case OPEN+2:
+ case OPEN+3:
+ case OPEN+4:
+ case OPEN+5:
+ case OPEN+6:
+ case OPEN+7:
+ case OPEN+8:
+ case OPEN+9:
+ sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
+ p = NULL;
+ break;
+ case CLOSE+1:
+ case CLOSE+2:
+ case CLOSE+3:
+ case CLOSE+4:
+ case CLOSE+5:
+ case CLOSE+6:
+ case CLOSE+7:
+ case CLOSE+8:
+ case CLOSE+9:
+ sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+ p = NULL;
+ break;
+ case STAR:
+ p = "STAR";
+ break;
+ case PLUS:
+ p = "PLUS";
+ break;
+ default:
+ regerror("corrupted opcode");
+ break;
+ }
+ if (p != NULL)
+ (void) strcat(buf, p);
+ return(buf);
+}
+#endif
+
+/*
+ * The following is provided for those people who do not have strcspn() in
+ * their C libraries. They should get off their butts and do something
+ * about it; at least one public-domain implementation of those (highly
+ * useful) string routines has been published on Usenet.
+ */
+#ifdef STRCSPN
+/*
+ * strcspn - find length of initial segment of s1 consisting entirely
+ * of characters not from s2
+ */
+
+static int
+strcspn(s1, s2)
+char *s1;
+char *s2;
+{
+ register char *scan1;
+ register char *scan2;
+ register int count;
+
+ count = 0;
+ for (scan1 = s1; *scan1 != '\0'; scan1++) {
+ for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */
+ if (*scan1 == *scan2++)
+ return(count);
+ count++;
+ }
+ return(count);
+}
+#endif
diff --git a/libc-0.0.4/regexp/regexp.h b/libc-0.0.4/regexp/regexp.h
new file mode 100644
index 0000000..73d6bf4
--- /dev/null
+++ b/libc-0.0.4/regexp/regexp.h
@@ -0,0 +1,21 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+#define NSUBEXP 10
+typedef struct regexp {
+ char *startp[NSUBEXP];
+ char *endp[NSUBEXP];
+ char regstart; /* Internal use only. */
+ char reganch; /* Internal use only. */
+ char *regmust; /* Internal use only. */
+ int regmlen; /* Internal use only. */
+ char program[1]; /* Unwarranted chumminess with compiler. */
+} regexp;
+
+extern regexp *regcomp();
+extern int regexec();
+extern void regsub();
+extern void regerror();
diff --git a/libc-0.0.4/regexp/regmagic.h b/libc-0.0.4/regexp/regmagic.h
new file mode 100644
index 0000000..5acf447
--- /dev/null
+++ b/libc-0.0.4/regexp/regmagic.h
@@ -0,0 +1,5 @@
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define MAGIC 0234
diff --git a/libc-0.0.4/regexp/regsub.c b/libc-0.0.4/regexp/regsub.c
new file mode 100644
index 0000000..5ca5676
--- /dev/null
+++ b/libc-0.0.4/regexp/regsub.c
@@ -0,0 +1,82 @@
+/*
+ * regsub
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ */
+#include <stdio.h>
+#include <regexp.h>
+#include "regmagic.h"
+
+#ifndef CHARBITS
+#define UCHARAT(p) ((int)*(unsigned char *)(p))
+#else
+#define UCHARAT(p) ((int)*(p)&CHARBITS)
+#endif
+
+/*
+ - regsub - perform substitutions after a regexp match
+ */
+void
+regsub(prog, source, dest)
+regexp *prog;
+char *source;
+char *dest;
+{
+ register char *src;
+ register char *dst;
+ register char c;
+ register int no;
+ register int len;
+ extern char *strncpy();
+
+ if (prog == NULL || source == NULL || dest == NULL) {
+ regerror("NULL parm to regsub");
+ return;
+ }
+ if (UCHARAT(prog->program) != MAGIC) {
+ regerror("damaged regexp fed to regsub");
+ return;
+ }
+
+ src = source;
+ dst = dest;
+ while ((c = *src++) != '\0') {
+ if (c == '&')
+ no = 0;
+ else if (c == '\\' && '0' <= *src && *src <= '9')
+ no = *src++ - '0';
+ else
+ no = -1;
+
+ if (no < 0) { /* Ordinary character. */
+ if (c == '\\' && (*src == '\\' || *src == '&'))
+ c = *src++;
+ *dst++ = c;
+ } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
+ len = prog->endp[no] - prog->startp[no];
+ (void) strncpy(dst, prog->startp[no], len);
+ dst += len;
+ if (len != 0 && *(dst-1) == '\0') {
+ /* strncpy hit NUL. */
+ regerror("damaged match string");
+ return;
+ }
+ }
+ }
+ *dst++ = '\0';
+}
diff --git a/libc-0.0.4/regexp/tests b/libc-0.0.4/regexp/tests
new file mode 100644
index 0000000..e5bc16d
--- /dev/null
+++ b/libc-0.0.4/regexp/tests
@@ -0,0 +1,127 @@
+abc abc y & abc
+abc xbc n - -
+abc axc n - -
+abc abx n - -
+abc xabcy y & abc
+abc ababc y & abc
+ab*c abc y & abc
+ab*bc abc y & abc
+ab*bc abbc y & abbc
+ab*bc abbbbc y & abbbbc
+ab+bc abbc y & abbc
+ab+bc abc n - -
+ab+bc abq n - -
+ab+bc abbbbc y & abbbbc
+ab?bc abbc y & abbc
+ab?bc abc y & abc
+ab?bc abbbbc n - -
+ab?c abc y & abc
+^abc$ abc y & abc
+^abc$ abcc n - -
+^abc abcc y & abc
+^abc$ aabc n - -
+abc$ aabc y & abc
+^ abc y &
+$ abc y &
+a.c abc y & abc
+a.c axc y & axc
+a.*c axyzc y & axyzc
+a.*c axyzd n - -
+a[bc]d abc n - -
+a[bc]d abd y & abd
+a[b-d]e abd n - -
+a[b-d]e ace y & ace
+a[b-d] aac y & ac
+a[-b] a- y & a-
+a[b-] a- y & a-
+a[b-a] - c - -
+a[]b - c - -
+a[ - c - -
+a] a] y & a]
+a[]]b a]b y & a]b
+a[^bc]d aed y & aed
+a[^bc]d abd n - -
+a[^-b]c adc y & adc
+a[^-b]c a-c n - -
+a[^]b]c a]c n - -
+a[^]b]c adc y & adc
+ab|cd abc y & ab
+ab|cd abcd y & ab
+()ef def y &-\1 ef-
+()* - c - -
+*a - c - -
+^* - c - -
+$* - c - -
+(*)b - c - -
+$b b n - -
+a\ - c - -
+a\(b a(b y &-\1 a(b-
+a\(*b ab y & ab
+a\(*b a((b y & a((b
+a\\b a\b y & a\b
+abc) - c - -
+(abc - c - -
+((a)) abc y &-\1-\2 a-a-a
+(a)b(c) abc y &-\1-\2 abc-a-c
+a+b+c aabbabc y & abc
+a** - c - -
+a*? - c - -
+(a*)* - c - -
+(a*)+ - c - -
+(a|)* - c - -
+(a*|b)* - c - -
+(a+|b)* ab y &-\1 ab-b
+(a+|b)+ ab y &-\1 ab-b
+(a+|b)? ab y &-\1 a-a
+[^ab]* cde y & cde
+(^)* - c - -
+(ab|)* - c - -
+)( - c - -
+ abc y &
+abc n - -
+a* y &
+([abc])*d abbbcd y &-\1 abbbcd-c
+([abc])*bcd abcd y &-\1 abcd-a
+a|b|c|d|e e y & e
+(a|b|c|d|e)f ef y &-\1 ef-e
+((a*|b))* - c - -
+abcd*efg abcdefg y & abcdefg
+ab* xabyabbbz y & ab
+ab* xayabbbz y & a
+(ab|cd)e abcde y &-\1 cde-cd
+[abhgefdc]ij hij y & hij
+^(ab|cd)e abcde n x\1y xy
+(abc|)ef abcdef y &-\1 ef-
+(a|b)c*d abcd y &-\1 bcd-b
+(ab|ab*)bc abc y &-\1 abc-a
+a([bc]*)c* abc y &-\1 abc-bc
+a([bc]*)(c*d) abcd y &-\1-\2 abcd-bc-d
+a([bc]+)(c*d) abcd y &-\1-\2 abcd-bc-d
+a([bc]*)(c+d) abcd y &-\1-\2 abcd-b-cd
+a[bcd]*dcdcde adcdcde y & adcdcde
+a[bcd]+dcdcde adcdcde n - -
+(ab|a)b*c abc y &-\1 abc-ab
+((a)(b)c)(d) abcd y \1-\2-\3-\4 abc-a-b-d
+[a-zA-Z_][a-zA-Z0-9_]* alpha y & alpha
+^a(bc+|b[eh])g|.h$ abh y &-\1 bh-
+(bc+d$|ef*g.|h?i(j|k)) effgz y &-\1-\2 effgz-effgz-
+(bc+d$|ef*g.|h?i(j|k)) ij y &-\1-\2 ij-ij-j
+(bc+d$|ef*g.|h?i(j|k)) effg n - -
+(bc+d$|ef*g.|h?i(j|k)) bcdd n - -
+(bc+d$|ef*g.|h?i(j|k)) reffgz y &-\1-\2 effgz-effgz-
+((((((((((a)))))))))) - c - -
+(((((((((a))))))))) a y & a
+multiple words of text uh-uh n - -
+multiple words multiple words, yeah y & multiple words
+(.*)c(.*) abcde y &-\1-\2 abcde-ab-de
+\((.*), (.*)\) (a, b) y (\2, \1) (b, a)
+[k] ab n - -
+abcd abcd y &-\&-\\& abcd-&-\abcd
+a(bc)d abcd y \1-\\1-\\\1 bc-\1-\bc
+[ -~]* abc y & abc
+[ -~ -~]* abc y & abc
+[ -~ -~ -~]* abc y & abc
+[ -~ -~ -~ -~]* abc y & abc
+[ -~ -~ -~ -~ -~]* abc y & abc
+[ -~ -~ -~ -~ -~ -~]* abc y & abc
+[ -~ -~ -~ -~ -~ -~ -~]* abc y & abc
diff --git a/libc-0.0.4/regexp/timer.c b/libc-0.0.4/regexp/timer.c
new file mode 100644
index 0000000..2d84a12
--- /dev/null
+++ b/libc-0.0.4/regexp/timer.c
@@ -0,0 +1,182 @@
+/*
+ * Simple timing program for regcomp().
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * Usage: timer ncomp nexec nsub
+ * or
+ * timer ncomp nexec nsub regexp string [ answer [ sub ] ]
+ *
+ * The second form is for timing repetitions of a single test case.
+ * The first form's test data is a compiled-in copy of the "tests" file.
+ * Ncomp, nexec, nsub are how many times to do each regcomp, regexec,
+ * and regsub. The way to time an operation individually is to do something
+ * like "timer 1 50 1".
+ */
+#include <stdio.h>
+
+struct try {
+ char *re, *str, *ans, *src, *dst;
+} tests[] = {
+#include "timer.t.h"
+{ NULL, NULL, NULL, NULL, NULL }
+};
+
+#include <regexp.h>
+
+int errreport = 0; /* Report errors via errseen? */
+char *errseen = NULL; /* Error message. */
+
+char *progname;
+
+/* ARGSUSED */
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int ncomp, nexec, nsub;
+ struct try one;
+ char dummy[512];
+
+ if (argc < 4) {
+ ncomp = 1;
+ nexec = 1;
+ nsub = 1;
+ } else {
+ ncomp = atoi(argv[1]);
+ nexec = atoi(argv[2]);
+ nsub = atoi(argv[3]);
+ }
+
+ progname = argv[0];
+ if (argc > 5) {
+ one.re = argv[4];
+ one.str = argv[5];
+ if (argc > 6)
+ one.ans = argv[6];
+ else
+ one.ans = "y";
+ if (argc > 7) {
+ one.src = argv[7];
+ one.dst = "xxx";
+ } else {
+ one.src = "x";
+ one.dst = "x";
+ }
+ errreport = 1;
+ try(one, ncomp, nexec, nsub);
+ } else
+ multiple(ncomp, nexec, nsub);
+ exit(0);
+}
+
+void
+regerror(s)
+char *s;
+{
+ if (errreport)
+ errseen = s;
+ else
+ error(s, "");
+}
+
+#ifndef ERRAVAIL
+error(s1, s2)
+char *s1;
+char *s2;
+{
+ fprintf(stderr, "regexp: ");
+ fprintf(stderr, s1, s2);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+#endif
+
+int lineno = 0;
+
+multiple(ncomp, nexec, nsub)
+int ncomp, nexec, nsub;
+{
+ register int i;
+ extern char *strchr();
+
+ errreport = 1;
+ for (i = 0; tests[i].re != NULL; i++) {
+ lineno++;
+ try(tests[i], ncomp, nexec, nsub);
+ }
+}
+
+try(fields, ncomp, nexec, nsub)
+struct try fields;
+int ncomp, nexec, nsub;
+{
+ regexp *r;
+ char dbuf[BUFSIZ];
+ register int i;
+
+ errseen = NULL;
+ r = regcomp(fields.re);
+ if (r == NULL) {
+ if (*fields.ans != 'c')
+ complain("regcomp failure in `%s'", fields.re);
+ return;
+ }
+ if (*fields.ans == 'c') {
+ complain("unexpected regcomp success in `%s'", fields.re);
+ free((char *)r);
+ return;
+ }
+ for (i = ncomp-1; i > 0; i--) {
+ free((char *)r);
+ r = regcomp(fields.re);
+ }
+ if (!regexec(r, fields.str)) {
+ if (*fields.ans != 'n')
+ complain("regexec failure in `%s'", "");
+ free((char *)r);
+ return;
+ }
+ if (*fields.ans == 'n') {
+ complain("unexpected regexec success", "");
+ free((char *)r);
+ return;
+ }
+ for (i = nexec-1; i > 0; i--)
+ (void) regexec(r, fields.str);
+ errseen = NULL;
+ for (i = nsub; i > 0; i--)
+ regsub(r, fields.src, dbuf);
+ if (errseen != NULL) {
+ complain("regsub complaint", "");
+ free((char *)r);
+ return;
+ }
+ if (strcmp(dbuf, fields.dst) != 0)
+ complain("regsub result `%s' wrong", dbuf);
+ free((char *)r);
+}
+
+complain(s1, s2)
+char *s1;
+char *s2;
+{
+ fprintf(stderr, "try: %d: ", lineno);
+ fprintf(stderr, s1, s2);
+ fprintf(stderr, " (%s)\n", (errseen != NULL) ? errseen : "");
+}
diff --git a/libc-0.0.4/regexp/try.c b/libc-0.0.4/regexp/try.c
new file mode 100644
index 0000000..71620c2
--- /dev/null
+++ b/libc-0.0.4/regexp/try.c
@@ -0,0 +1,238 @@
+/*
+ * Simple test program for regexp(3) stuff. Knows about debugging hooks.
+ *
+ * Copyright (c) 1986 by University of Toronto.
+ * Written by Henry Spencer. Not derived from licensed software.
+ *
+ * Permission is granted to anyone to use this software for any
+ * purpose on any computer system, and to redistribute it freely,
+ * subject to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of
+ * this software, no matter how awful, even if they arise
+ * from defects in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either
+ * by explicit claim or by omission.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * Usage: try re [string [output [-]]]
+ * The re is compiled and dumped, regexeced against the string, the result
+ * is applied to output using regsub(). The - triggers a running narrative
+ * from regexec(). Dumping and narrative don't happen unless DEBUG.
+ *
+ * If there are no arguments, stdin is assumed to be a stream of lines with
+ * five fields: a r.e., a string to match it against, a result code, a
+ * source string for regsub, and the proper result. Result codes are 'c'
+ * for compile failure, 'y' for match success, 'n' for match failure.
+ * Field separator is tab.
+ */
+#include <stdio.h>
+#include <regexp.h>
+
+#ifdef ERRAVAIL
+char *progname;
+extern char *mkprogname();
+#endif
+
+#ifdef DEBUG
+extern int regnarrate;
+#endif
+
+char buf[BUFSIZ];
+
+int errreport = 0; /* Report errors via errseen? */
+char *errseen = NULL; /* Error message. */
+int status = 0; /* Exit status. */
+
+/* ARGSUSED */
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ regexp *r;
+ int i;
+
+#ifdef ERRAVAIL
+ progname = mkprogname(argv[0]);
+#endif
+
+ if (argc == 1) {
+ multiple();
+ exit(status);
+ }
+
+ r = regcomp(argv[1]);
+ if (r == NULL)
+ error("regcomp failure", "");
+#ifdef DEBUG
+ regdump(r);
+ if (argc > 4)
+ regnarrate++;
+#endif
+ if (argc > 2) {
+ i = regexec(r, argv[2]);
+ printf("%d", i);
+ for (i = 1; i < NSUBEXP; i++)
+ if (r->startp[i] != NULL && r->endp[i] != NULL)
+ printf(" \\%d", i);
+ printf("\n");
+ }
+ if (argc > 3) {
+ regsub(r, argv[3], buf);
+ printf("%s\n", buf);
+ }
+ exit(status);
+}
+
+void
+regerror(s)
+char *s;
+{
+ if (errreport)
+ errseen = s;
+ else
+ error(s, "");
+}
+
+#ifndef ERRAVAIL
+error(s1, s2)
+char *s1;
+char *s2;
+{
+ fprintf(stderr, "regexp: ");
+ fprintf(stderr, s1, s2);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+#endif
+
+int lineno;
+
+regexp badregexp; /* Implicit init to 0. */
+
+multiple()
+{
+ char rbuf[BUFSIZ];
+ char *field[5];
+ char *scan;
+ int i;
+ regexp *r;
+ extern char *strchr();
+
+ errreport = 1;
+ lineno = 0;
+ while (fgets(rbuf, sizeof(rbuf), stdin) != NULL) {
+ rbuf[strlen(rbuf)-1] = '\0'; /* Dispense with \n. */
+ lineno++;
+ scan = rbuf;
+ for (i = 0; i < 5; i++) {
+ field[i] = scan;
+ if (field[i] == NULL) {
+ complain("bad testfile format", "");
+ exit(1);
+ }
+ scan = strchr(scan, '\t');
+ if (scan != NULL)
+ *scan++ = '\0';
+ }
+ try(field);
+ }
+
+ /* And finish up with some internal testing... */
+ lineno = 9990;
+ errseen = NULL;
+ if (regcomp((char *)NULL) != NULL || errseen == NULL)
+ complain("regcomp(NULL) doesn't complain", "");
+ lineno = 9991;
+ errseen = NULL;
+ if (regexec((regexp *)NULL, "foo") || errseen == NULL)
+ complain("regexec(NULL, ...) doesn't complain", "");
+ lineno = 9992;
+ r = regcomp("foo");
+ if (r == NULL) {
+ complain("regcomp(\"foo\") fails", "");
+ return;
+ }
+ lineno = 9993;
+ errseen = NULL;
+ if (regexec(r, (char *)NULL) || errseen == NULL)
+ complain("regexec(..., NULL) doesn't complain", "");
+ lineno = 9994;
+ errseen = NULL;
+ regsub((regexp *)NULL, "foo", rbuf);
+ if (errseen == NULL)
+ complain("regsub(NULL, ..., ...) doesn't complain", "");
+ lineno = 9995;
+ errseen = NULL;
+ regsub(r, (char *)NULL, rbuf);
+ if (errseen == NULL)
+ complain("regsub(..., NULL, ...) doesn't complain", "");
+ lineno = 9996;
+ errseen = NULL;
+ regsub(r, "foo", (char *)NULL);
+ if (errseen == NULL)
+ complain("regsub(..., ..., NULL) doesn't complain", "");
+ lineno = 9997;
+ errseen = NULL;
+ if (regexec(&badregexp, "foo") || errseen == NULL)
+ complain("regexec(nonsense, ...) doesn't complain", "");
+ lineno = 9998;
+ errseen = NULL;
+ regsub(&badregexp, "foo", rbuf);
+ if (errseen == NULL)
+ complain("regsub(nonsense, ..., ...) doesn't complain", "");
+}
+
+try(fields)
+char **fields;
+{
+ regexp *r;
+ char dbuf[BUFSIZ];
+
+ errseen = NULL;
+ r = regcomp(fields[0]);
+ if (r == NULL) {
+ if (*fields[2] != 'c')
+ complain("regcomp failure in `%s'", fields[0]);
+ return;
+ }
+ if (*fields[2] == 'c') {
+ complain("unexpected regcomp success in `%s'", fields[0]);
+ free((char *)r);
+ return;
+ }
+ if (!regexec(r, fields[1])) {
+ if (*fields[2] != 'n')
+ complain("regexec failure in `%s'", "");
+ free((char *)r);
+ return;
+ }
+ if (*fields[2] == 'n') {
+ complain("unexpected regexec success", "");
+ free((char *)r);
+ return;
+ }
+ errseen = NULL;
+ regsub(r, fields[3], dbuf);
+ if (errseen != NULL) {
+ complain("regsub complaint", "");
+ free((char *)r);
+ return;
+ }
+ if (strcmp(dbuf, fields[4]) != 0)
+ complain("regsub result `%s' wrong", dbuf);
+ free((char *)r);
+}
+
+complain(s1, s2)
+char *s1;
+char *s2;
+{
+ fprintf(stderr, "try: %d: ", lineno);
+ fprintf(stderr, s1, s2);
+ fprintf(stderr, " (%s)\n", (errseen != NULL) ? errseen : "");
+ status = 1;
+}
diff --git a/libc-0.0.4/stdio1/BUGS b/libc-0.0.4/stdio1/BUGS
new file mode 100644
index 0000000..0e8e0db
--- /dev/null
+++ b/libc-0.0.4/stdio1/BUGS
@@ -0,0 +1,15 @@
+Error checking is known to be wanting. However the author just wants to
+get it working right now.
+
+fread() and fwrite() are not supported. open(), read(), write(), and close()
+work very well for binary data.
+
+fopen() is the only way to open a file. None of the temp stuff is supported,
+and frepon() is unsupported.
+
+GNU extensions are unsupported.
+
+Some printf specifications may not work. Read the code for details of what
+IS supported.
+
+Other than that, this should be a perfectly normal stdio lib when it's finished.
diff --git a/libc-0.0.4/stdio1/Config b/libc-0.0.4/stdio1/Config
new file mode 100644
index 0000000..3b3b35f
--- /dev/null
+++ b/libc-0.0.4/stdio1/Config
@@ -0,0 +1,3 @@
+
+
+stdio: Joel's stdio package altered by Nat
diff --git a/libc-0.0.4/stdio1/NOTICE b/libc-0.0.4/stdio1/NOTICE
new file mode 100644
index 0000000..25ca5b6
--- /dev/null
+++ b/libc-0.0.4/stdio1/NOTICE
@@ -0,0 +1,17 @@
+/*
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
diff --git a/libc-0.0.4/stdio1/README b/libc-0.0.4/stdio1/README
new file mode 100644
index 0000000..5dc59aa
--- /dev/null
+++ b/libc-0.0.4/stdio1/README
@@ -0,0 +1,13 @@
+I found that it was helpful to have the extern stuff actually defined in
+one file as not external...
+
+Still trying to find the other problems
+
+Whether it is desireable to list stdio.h as a dependency is debateable
+
+-Joel
+
+I've made a horrible number of changes here, look in 'Reverse_Patch' for
+how to go back ...
+
+-Robert
diff --git a/libc-0.0.4/stdio1/TODO b/libc-0.0.4/stdio1/TODO
new file mode 100644
index 0000000..481f6d9
--- /dev/null
+++ b/libc-0.0.4/stdio1/TODO
@@ -0,0 +1,33 @@
+Sun Jan 21 18:16:03 EST 1996 -- Nat Friedman
+============================================
+I've made a load of changes to this code, but there's still a lot to be done.
+- scanf, fscanf
+
+
+
+
+input, file positioning, eof, declarations of functions, printf
+
+look for unsigned char references
+
+specifically
+fix printf and figure out what's going on in there.
+write idealgetline, scanf, other stuff
+then deal with above stuff...
+
+
+LATEST LIST:
+printf, fprintf
+scanf, fscanf
+feof
+seek support
+error handling (not too hard since system calls only in a few places)
+atexit stuff (close files; will need to add a linked list of files)
+setvbuf if desired
+check that fopen() and stdio_init() fill in ALL the fields
+testing!
+
+rm NOTICE
+
+
+
diff --git a/libc-0.0.4/stdio1/__ffillbuf.c b/libc-0.0.4/stdio1/__ffillbuf.c
new file mode 100644
index 0000000..e705cbf
--- /dev/null
+++ b/libc-0.0.4/stdio1/__ffillbuf.c
@@ -0,0 +1,55 @@
+/* simplified linux __ffillbuf.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <unistd.h>
+#include "stdio.h"
+
+/* this function makes the mistake of assuming the buffer really DOES
+need to be filled. */
+
+/* RDB:
+ * Added simple processing for EOF and errors
+ * As this is _only_ called from getc() the memory footprint is smaller
+ * if it pretends to be getc in the complex case.
+ */
+
+int
+__ffillbuf(stream)
+FILE *stream;
+{
+ int stat;
+
+ if( stream->fd < 0 || ferror(stream) ) return EOF;
+
+ stat = read(stream->fd, (char *) stream->bufstart, stream->bufend - stream->bufstart);
+ if( stat > 0 )
+ stream->bufread = stream->bufstart + stat;
+ else if( stat == 0 )
+ {
+ stream->fc_eof = 1;
+ return EOF;
+ }
+ else
+ {
+ stream->fc_err = 1;
+ return EOF;
+ }
+
+ stream->bufpos = stream->bufstart;
+
+ return getc(stream);
+}
diff --git a/libc-0.0.4/stdio1/__stdio_init.c b/libc-0.0.4/stdio1/__stdio_init.c
new file mode 100644
index 0000000..b49bb28
--- /dev/null
+++ b/libc-0.0.4/stdio1/__stdio_init.c
@@ -0,0 +1,66 @@
+/* simplified linux __stdio_init.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "stdio.h"
+
+/*
+ OK, Complete hackup here, I've removed the need for the init function.
+ Not also I've make the types into 'unsigned char' this is so it doesn't
+ return EOF when it really means '\377'
+ */
+
+static unsigned char __stdinbuf[BUFSIZ], __stdoutbuf[BUFSIZ], __stderrbuf[80];
+
+static FILE __the_stdin = {
+ 0,
+ __stdinbuf,
+ __stdinbuf,
+ __stdinbuf,
+ __stdinbuf+sizeof(__stdinbuf),
+ _IOLBF,
+ _MODE_READ,
+ 0, 0,
+ 0, 0, 1
+};
+
+static FILE __the_stdout = {
+ 1,
+ __stdoutbuf,
+ __stdoutbuf,
+ __stdoutbuf,
+ __stdoutbuf+sizeof(__stdoutbuf),
+ _IOLBF,
+ _MODE_WRITE,
+ 0, 0,
+ 0, 0, 1
+};
+
+static FILE __the_stderr = {
+ 2,
+ __stderrbuf,
+ __stderrbuf,
+ __stderrbuf,
+ __stderrbuf+sizeof(__stderrbuf),
+ _IOLBF,
+ _MODE_WRITE,
+ 0, 0,
+ 0, 0, 1
+};
+
+FILE *stdin = &__the_stdin,
+ *stdout = &__the_stdout,
+ *stderr = &__the_stderr;
diff --git a/libc-0.0.4/stdio1/fclose.c b/libc-0.0.4/stdio1/fclose.c
new file mode 100644
index 0000000..7ec233e
--- /dev/null
+++ b/libc-0.0.4/stdio1/fclose.c
@@ -0,0 +1,41 @@
+/* simplified linux fclose.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <unistd.h>
+#include "stdio.h"
+
+int fclose (stream)
+FILE *stream;
+{
+ /* only allow fclose() on what was fopen()ed. */
+ /*
+ This isn't right, there's nothing wrong with fclosing stdin
+ but the next fopen/open will be given fd 0 and so become stdin
+ Of course you do have to be a little careful :-)
+ RDB
+ */
+
+ if ((stream == stdin) || (stream == stdout) || (stream == stderr)) return EOF;
+
+ if (fflush(stream)) return EOF;
+
+ if (close(stream->fd)) return EOF;
+
+ free(stream->bufstart);
+ free(stream);
+ return 0;
+}
diff --git a/libc-0.0.4/stdio1/fcntl.h b/libc-0.0.4/stdio1/fcntl.h
new file mode 100644
index 0000000..69fdb90
--- /dev/null
+++ b/libc-0.0.4/stdio1/fcntl.h
@@ -0,0 +1,72 @@
+#ifndef __FCNTL_H
+#define __FCNTL_H
+
+/*
+ * Definitions taken from the i386 Linux kernel.
+ */
+
+/* open/fcntl */
+
+#define O_ACCMODE 0003
+#define O_RDONLY 00
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 0100 /* not fcntl */
+#define O_EXCL 0200 /* not fcntl */
+#define O_NOCTTY 0400 /* not fcntl */
+#define O_TRUNC 01000 /* not fcntl */
+#define O_APPEND 02000
+#define O_NONBLOCK 04000
+#define O_NDELAY O_NONBLOCK
+#if 0
+#define O_SYNC 010000 /* Not supported */
+#define FASYNC 020000 /* Not supported */
+#endif
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get f_flags */
+#define F_SETFD 2 /* set f_flags */
+#define F_GETFL 3 /* more flags (cloexec) */
+#define F_SETFL 4
+#define F_GETLK 5
+#define F_SETLK 6
+#define F_SETLKW 7
+
+#define F_SETOWN 8 /* for sockets. */
+#define F_GETOWN 9 /* for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#ifdef __KERNEL__
+#define F_POSIX 1
+#define F_FLOCK 2
+#endif /* __KERNEL__ */
+
+#if 0
+struct flock {
+ short l_type;
+ short l_whence;
+ off_t l_start;
+ off_t l_len;
+ pid_t l_pid;
+};
+#endif
+
+#endif
diff --git a/libc-0.0.4/stdio1/fflush.c b/libc-0.0.4/stdio1/fflush.c
new file mode 100644
index 0000000..c9cdac7
--- /dev/null
+++ b/libc-0.0.4/stdio1/fflush.c
@@ -0,0 +1,36 @@
+/* simplified linux fflush.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <unistd.h>
+#include "stdio.h"
+
+int fflush(stream)
+FILE *stream;
+{
+ if (stream == 0) return 0;
+ if ((stream->file_mode == _MODE_WRITE)
+ ||(stream->file_mode == (_MODE_WRITE & _MODE_RDWR))){
+ write(stream->fd, (char *) stream->bufstart,
+ stream->bufpos - stream->bufstart);
+ stream->bufpos = stream->bufstart;
+ }
+ return 0;
+}
+/* TODO: return EOF or 0; support NULL stream */
+/* The only place an error can come from is the write; you're not checking RDB
+ */
diff --git a/libc-0.0.4/stdio1/fgetc.c b/libc-0.0.4/stdio1/fgetc.c
new file mode 100644
index 0000000..2c41062
--- /dev/null
+++ b/libc-0.0.4/stdio1/fgetc.c
@@ -0,0 +1,39 @@
+/*
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "stdio.h"
+
+/*
+ * Make this not dependent on getc() then we can:
+ #define getc(fp) fgetc(fp)
+ * if memory is _really_ tight.
+ */
+
+int fgetc(stream)
+FILE *stream;
+{
+ if( stream->ungetted )
+ {
+ stream->ungetted = 0;
+ return stream->ungetchar;
+ }
+ if( stream->bufpos == stream->bufread )
+ return __ffillbuf(stream);
+ else
+ return *stream->bufpos++;
+}
diff --git a/libc-0.0.4/stdio1/fgets.c b/libc-0.0.4/stdio1/fgets.c
new file mode 100644
index 0000000..c085970
--- /dev/null
+++ b/libc-0.0.4/stdio1/fgets.c
@@ -0,0 +1,50 @@
+/* fgets.c for limited linux stdio
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "stdio.h"
+
+/*
+ RDB BZZZT! This should only read upto and including any newline!
+*/
+
+char *fgets(s, count, f)
+char *s;
+size_t count;
+FILE *f;
+{
+ char *ret;
+ register size_t i;
+ register int ch;
+
+ ret = s;
+ for(i=count; i>0; i--)
+ {
+ ch = getc(f);
+ if( ch == EOF )
+ {
+ if(s==ret) return 0;
+ break;
+ }
+ *s++ = (char) ch;
+ if( ch == '\n' ) break;
+ }
+ *s = 0;
+
+ if( ferror(f) ) return 0;
+ return ret;
+}
diff --git a/libc-0.0.4/stdio1/fopen.c b/libc-0.0.4/stdio1/fopen.c
new file mode 100644
index 0000000..1265ff5
--- /dev/null
+++ b/libc-0.0.4/stdio1/fopen.c
@@ -0,0 +1,80 @@
+/* simplified linux fopen.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "stdio.h"
+#include <malloc.h>
+
+FILE * fopen(name, openmode)
+char *name;
+char *openmode;
+{
+ FILE *new;
+ int openplus=0;
+ char basemode;
+
+ basemode = openmode[0];
+ while (openmode[0] != 0){
+ switch(openmode[0]){
+ case '+': openplus=1; break;
+ }
+ openmode++;
+ }
+
+ new = malloc(sizeof(new));
+ if( new == 0 ) return 0;
+ new->bufread = new->bufpos = new->bufstart = malloc(BUFSIZ);
+ if( new->bufstart == 0 ) { free(new) ; return 0; }
+
+ new->bufend = new->bufstart + BUFSIZ;
+ new->buffer_mode = _IOFBF;
+ new->iotrans = 0;
+ new->fd = -1;
+ if (openplus){
+ new->file_mode = _MODE_RDWR;
+ switch (basemode){
+ case 'a':
+ new->fd = open(name, O_RDWR | O_APPEND | O_CREAT);
+ break;
+ case 'r':
+ new->fd = open(name, O_RDWR);
+ break;
+ case 'w':
+ new->fd = open(name, O_RDWR | O_TRUNC | O_CREAT);
+ break;
+ }
+ } else switch (basemode){
+ case 'a':
+ new->fd = open(name, O_WRONLY | O_APPEND | O_CREAT);
+ new->file_mode = _MODE_WRITE;
+ break;
+ case 'r':
+ new->fd = open(name, O_RDONLY);
+ new->file_mode = _MODE_READ;
+ break;
+ case 'w':
+ new->fd = open(name, O_WRONLY | O_TRUNC | O_CREAT);
+ new->file_mode = _MODE_WRITE;
+ break;
+ }
+ if( new->fd < 0 )
+ {
+ free(new->bufstart);
+ free(new);
+ return 0;
+ }
+ return new;
+}
diff --git a/libc-0.0.4/stdio1/fputc.c b/libc-0.0.4/stdio1/fputc.c
new file mode 100644
index 0000000..939a721
--- /dev/null
+++ b/libc-0.0.4/stdio1/fputc.c
@@ -0,0 +1,53 @@
+/* simplified linux fputc.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "stdio.h"
+
+/*
+ * Make this not dependent on putc() then we can:
+ #define putc(c, fp) fputc(c, fp)
+ * if memory is _really_ tight.
+ */
+
+#undef putc
+#define putc(c, stream) \
+ (((stream)->bufpos[0] = (c)), \
+ ((stream)->bufpos++), \
+ ((((stream)->bufpos == (stream)->bufend) \
+ ||((stream)->buffer_mode == _IONBF) \
+ ||(((stream)->buffer_mode == _IOLBF) \
+ && ((stream)->bufpos != (stream)->bufstart) \
+ && ((stream)->bufpos[-1] == '\n'))) \
+ ? fflush(stream):0))
+
+#define new_putc(c, stream) \
+ ((unsigned char)( \
+ ((stream)->bufpos>=(stream)->bufread) ? fputc((c), (stream)) \
+ : *(stream)->bufpos++ = (c) \
+ ))
+
+int
+fputc(int c, FILE * stream)
+{
+#ifdef __MSDOS__
+ if( c == '\n' && stream->iotrans ) fputc('\r', stream);
+#endif
+ return putc(c, stream);
+}
+
+
+
diff --git a/libc-0.0.4/stdio1/fputs.c b/libc-0.0.4/stdio1/fputs.c
new file mode 100644
index 0000000..41e2998
--- /dev/null
+++ b/libc-0.0.4/stdio1/fputs.c
@@ -0,0 +1,32 @@
+/* simplified linux fputs.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <unistd.h>
+#include <string.h>
+#include "stdio.h"
+
+int
+fputs(__const char * string, FILE * stream)
+{
+ if (stream->buffer_mode != _IONBF){
+ while (string[0] != 0){
+ putc(string[0], stream);
+ string++;
+ }
+ } else write(stream->fd, string, strlen(string));
+ return 0;
+}
diff --git a/libc-0.0.4/stdio1/idealgetline.c b/libc-0.0.4/stdio1/idealgetline.c
new file mode 100644
index 0000000..7eacc9e
--- /dev/null
+++ b/libc-0.0.4/stdio1/idealgetline.c
@@ -0,0 +1,67 @@
+/* idealgetline.c -- my idea of an ideal getline function for stdio
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* I actually intend to use this in 32 bit programs, unlike the other stuff
+ in this lib. IMHO GNU getline is broken. It is too hard to use.
+
+ Just pass this function a FILE * and it will retrieve a line for you using
+ getc(). It will realloc() exactly the amount of memory needed, and will
+ generate error messages for non-ascii characters on stderr.
+
+ This may not be your ideal. It probably generates far too many errors.
+ It doesn't work well for those who don't use English (but since
+ Linux-less-than-32 libc and kernels are each being produced by one
+ person in the US and one in the UK, this isn't a problem). It probably
+ is not what you (or I) want for interactive input.
+
+ You're welcome to modify this routine to meet your needs. However, if
+ you change the semantics significantly, please change the name.
+
+ (Maybe I should have put my own name on it so there will be no confusion
+ about who thought it was ideal). */
+
+#include <stdio.h>
+#include <malloc.h>
+
+char *idealgetline(f)
+FILE *f;
+{
+ char c;
+ char *ret;
+ int size = 0, bufsize = 256;
+
+ ret = malloc(256);
+ c = getc(f);
+ while ((c != EOF) && (c != '\n')){
+ if ((c >= ' ') && (c <= 126)){
+ ret[size] = c;
+ size++;
+ if (size == bufsize){
+ bufsize += 256;
+ ret = realloc(ret, bufsize);
+ }
+ } else {
+ fprintf(stderr, "Unexpected character 0x%x encountered in input", c);
+ free(ret);
+ return 0;
+ }
+ }
+ ret[size] = '\0';
+ size++;
+ return realloc(ret, size);
+}
diff --git a/libc-0.0.4/stdio1/libc.a b/libc-0.0.4/stdio1/libc.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libc-0.0.4/stdio1/libc.a
diff --git a/libc-0.0.4/stdio1/makefile b/libc-0.0.4/stdio1/makefile
new file mode 100644
index 0000000..0723b97
--- /dev/null
+++ b/libc-0.0.4/stdio1/makefile
@@ -0,0 +1,36 @@
+TOP=..
+include $(TOP)/Make.defs
+OBJ = __ffillbuf.o __stdio_init.o fflush.o fgetc.o fgets.o \
+ fputc.o fputs.o puts.o printf.o fopen.o fclose.o scanf.o
+
+#missing functions from above: printf etc, scanf etc, idealgetline
+#seek
+
+#fopen.c, fclose.c removed because of malloc() use
+
+CFLAGS+=$(WALL)
+
+ifeq ($(PLATFORM),i86-ELKS)
+CFLAGS=$(CCFLAGS) $(DEFS) -ansi
+endif
+
+all: $(OBJ)
+
+libc.a: $(OBJ)
+ ar r ../libc.a $(OBJ)
+ @touch libc.a
+
+$(OBJ): stdio.h
+
+test: test.o $(OBJ)
+ $(CC) -o test test.o $(OBJ)
+
+%.o: %.c
+ $(CC) $(CFLAGS) -o $@ $< -c
+
+clean:
+ rm -f *.o test
+
+transfer:
+ -@rm -f ../include/stdio.h
+ cp -p stdio.h ../include/.
diff --git a/libc-0.0.4/stdio1/old_printf.c b/libc-0.0.4/stdio1/old_printf.c
new file mode 100644
index 0000000..81d62ac
--- /dev/null
+++ b/libc-0.0.4/stdio1/old_printf.c
@@ -0,0 +1,230 @@
+/* fprintf.c for limited Linux libc
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* Thanks Alan for writing the hard routine for me :-)
+ * Alan said that this works "most of the time". Something tells me I'm making
+ * it even worse! */
+/* The basic idea here is to make fprintf the core routine. printf obviously
+ can just call fprintf with stdout followed by all of its arguments.
+ sprintf() works using the fake file &the_sprintf. It's marked as fully
+ buffered, so that it will only write(2) when &the_sprintf->bufpos ==
+ &the_sprintf->bufend, which I doubt will happen since &the_sprintf->bufend
+ = 0. The trick is that sprintf must set &the_sprintf->bufstart =
+ &the_sprintf->bufpos = its first argument. Not as orthagonal (is that
+ the right word?) as glibc's facilities for non-files, but this isn't a
+ library for people who have unlimited RAM budgets. (not like the libc
+ I use on linux/i586 enjoys an unlimited RAM budget either; I only have
+ 8 MB
+
+ I'm not sure what the "correct" way to pass the variable arguments
+ from one function to the next is. Rather than pass the arguments
+ themselves, I'm passing a pointer to them. However, the following
+ explaination from Alan is probably a polite way of saying it will not
+ work on a 386 anyway.
+ Joel Weber
+
+ [ I've migrated all of this code over to the ELKS stdarg that I wrote.
+ The accepted way to do it is for the wrapper function to accept a
+ variable number of arguments, use stdarg to make an argument pointer,
+ and then pass the argument pointer on to the core function, as I've
+ done here. This should definitely work on a 386, as the arguments
+ are still passed in the stack, and stack order is maintained. -Nat ]
+ */
+
+/*
+ * This is NOT stunningly portable, but works
+ * for pretty dumb non ANSI compilers and is
+ * tight. Adjust the sizes to taste.
+ *
+ * Illegal format strings will break it. Only the
+ * following simple subset is supported
+ *
+ * %x - hex
+ * %d - decimal
+ * %s - string
+ * %c - char
+ *
+ * And the h/l length specifiers for %d/%x
+ *
+ * Alan Cox.
+ */
+
+#include <stdarg.h>
+#include "stdio.h"
+
+/* 17 to make sure that there's room for the trailing newline.
+ I'm not really sure if this is ideal... */
+static char nstring[17]="0123456789ABCDEF";
+
+static unsigned char *
+__numout(long i, int base)
+{
+ static unsigned char out[16];
+ int n;
+ int flg = 0;
+ unsigned long val;
+
+ if (i<0 && base==10)
+ {
+ flg = 1;
+ i = -i;
+ }
+ val = i;
+
+ for (n = 0; n < 15; n++)
+ out[n] = ' ';
+ out[15] = '\0';
+ n = 14;
+ do{
+ out[n] = nstring[val % base];
+ n--;
+ val /= base;
+ }
+ while(val);
+ if(flg) out[n--] = '-';
+ return &out[n+1];
+}
+
+static int
+internal_fprintf(FILE * stream, __const char * fmt, va_list ap)
+{
+ register int c;
+ int count = 0;
+ int type, base;
+
+ while(c=*fmt++)
+ {
+ if(c!='%')
+ {
+ putc(c, stream);
+ count++;
+ }
+ else
+ {
+ type=1;
+ do { c=*fmt++; } while( c=='.' || (c>='0' && c<='9'));
+ if( c == 0 ) break;
+ if(c=='h')
+ {
+ c=*fmt++;
+ type = 0;
+ }
+ else if(c=='l')
+ {
+ c=*fmt++;
+ type = 2;
+ }
+
+ switch(c)
+ {
+ case 'x':
+ case 'o':
+ case 'd':
+ if (c=='x') base=16;
+ if (c=='o') base=8;
+ if (c=='d') base=10;
+ {
+ long val=0;
+ switch(type)
+ {
+ case 0:
+ val=va_arg(ap, short);
+ break;
+ case 1:
+ val=va_arg(ap, int);
+ break;
+ case 2:
+ val=va_arg(ap, long);
+ break;
+ }
+ fputs((__const char *)__numout(val,base),stream);
+ }
+ break;
+ case 's':
+ {
+ char *cp;
+ cp=va_arg(ap, char *);
+ while(*cp)
+ putc(*cp++, stream);
+ break;
+ }
+ case 'c':
+ putc(va_arg(ap, int), stream);
+ break;
+ default:
+ putc(c, stream);
+ }
+ }
+ }
+ return count;
+}
+
+
+int
+fprintf(FILE * stream, __const char * fmt, ...)
+{
+ va_list ap;
+ int retval;
+ va_start(ap, fmt);
+ retval=internal_fprintf(stream, fmt, ap);
+ va_end(ap);
+ return(retval);
+}
+
+int
+printf(__const char * fmt, ...)
+{
+ va_list ap;
+ int retval;
+ va_start(ap, fmt);
+ retval=internal_fprintf(stdout, fmt, ap);
+ va_end(ap);
+ return(retval);
+}
+
+/* This is a strange way of doing sprintf, but it should work */
+int sprintf(char * s, __const char * fmt, ...)
+{
+ static FILE the_sprintf = {
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ _IOFBF,
+ _MODE_WRITE,
+ 0, 0,
+ 0, 0};
+ va_list ap;
+ int retval;
+
+ va_start(ap, fmt);
+ the_sprintf.bufstart = the_sprintf.bufpos = (unsigned char *) s;
+ the_sprintf.fc_err = 0;
+
+ retval = internal_fprintf(&the_sprintf, fmt, ap);
+ /* null-terminate the string */
+ putc('\0', &the_sprintf);
+
+ va_end(ap);
+ return retval;
+}
+
+
+
+
+
diff --git a/libc-0.0.4/stdio1/printf.c b/libc-0.0.4/stdio1/printf.c
new file mode 100644
index 0000000..f2a39bd
--- /dev/null
+++ b/libc-0.0.4/stdio1/printf.c
@@ -0,0 +1,649 @@
+/* fprintf.c for limited Linux libc
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* Thanks Alan for writing the hard routine for me :-)
+ * Alan said that this works "most of the time". Something tells me I'm making
+ * it even worse! */
+/* The basic idea here is to make fprintf the core routine. printf obviously
+ can just call fprintf with stdout followed by all of its arguments.
+ sprintf() works using the fake file &the_sprintf. It's marked as fully
+ buffered, so that it will only write(2) when &the_sprintf->bufpos ==
+ &the_sprintf->bufend, which I doubt will happen since &the_sprintf->bufend
+ = 0. The trick is that sprintf must set &the_sprintf->bufstart =
+ &the_sprintf->bufpos = its first argument. Not as orthagonal (is that
+ the right word?) as glibc's facilities for non-files, but this isn't a
+ library for people who have unlimited RAM budgets. (not like the libc
+ I use on linux/i586 enjoys an unlimited RAM budget either; I only have
+ 8 MB
+
+ I'm not sure what the "correct" way to pass the variable arguments
+ from one function to the next is. Rather than pass the arguments
+ themselves, I'm passing a pointer to them. However, the following
+ explaination from Alan is probably a polite way of saying it will not
+ work on a 386 anyway.
+ Joel Weber
+
+ [ I've migrated all of this code over to the ELKS stdarg that I wrote.
+ The accepted way to do it is for the wrapper function to accept a
+ variable number of arguments, use stdarg to make an argument pointer,
+ and then pass the argument pointer on to the core function, as I've
+ done here. This should definitely work on a 386, as the arguments
+ are still passed in the stack, and stack order is maintained. -Nat ]
+ */
+
+/*
+ * This is NOT stunningly portable, but works
+ * for pretty dumb non ANSI compilers and is
+ * tight. Adjust the sizes to taste.
+ *
+ * Illegal format strings will break it. Only the
+ * following simple subset is supported
+ *
+ * %x - hex
+ * %d - decimal
+ * %s - string
+ * %c - char
+ *
+ * And the h/l length specifiers for %d/%x
+ *
+ * Alan Cox.
+ */
+
+#include <stdarg.h>
+#include "stdio.h"
+
+/* 17 to make sure that there's room for the trailing newline.
+ I'm not really sure if this is ideal... */
+static char nstring[17]="0123456789ABCDEF";
+
+static unsigned char *
+__numout(long i, int base)
+{
+ static unsigned char out[16];
+ int n;
+ int flg = 0;
+ unsigned long val;
+
+ if (i<0 && base==10)
+ {
+ flg = 1;
+ i = -i;
+ }
+ val = i;
+
+ for (n = 0; n < 15; n++)
+ out[n] = ' ';
+ out[15] = '\0';
+ n = 14;
+ do{
+ out[n] = nstring[val % base];
+ n--;
+ val /= base;
+ }
+ while(val);
+ if(flg) out[n--] = '-';
+ return &out[n+1];
+}
+
+int
+fprintf(FILE * stream, __const char * fmt, ...)
+{
+ va_list ap;
+ int retval;
+ va_start(ap, fmt);
+ retval=internal_fprintf(stream, fmt, ap);
+ va_end(ap);
+ return(retval);
+}
+
+int
+printf(__const char * fmt, ...)
+{
+ va_list ap;
+ int retval;
+ va_start(ap, fmt);
+ retval=internal_fprintf(stdout, fmt, ap);
+ va_end(ap);
+ return(retval);
+}
+
+/* This is a strange way of doing sprintf, but it should work */
+int sprintf(char * s, __const char * fmt, ...)
+{
+ static FILE the_sprintf = {
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ _IOFBF,
+ _MODE_WRITE,
+ 0, 0,
+ 0, 0};
+ va_list ap;
+ int retval;
+
+ va_start(ap, fmt);
+ the_sprintf.bufstart = the_sprintf.bufpos = (unsigned char *) s;
+ the_sprintf.fc_err = 0;
+
+ retval = internal_fprintf(&the_sprintf, fmt, ap);
+ /* null-terminate the string */
+ putc('\0', &the_sprintf);
+
+ va_end(ap);
+ return retval;
+}
+
+
+
+
+
+/*
+ * printf.c - This is the more complete fprintf() replacement for libc8086
+ * Copyright (C) 1996 Steven Huang <sthuang@hns.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+/*
+ * This decides if the little test main program gets included
+ */
+#undef TEST
+/*
+ * This decides if printf() should act like standard. When undefined,
+ * - prints out "(err)" if a bad format is encountered
+ * - supports the %b (binary) format
+ */
+#define STANDARD
+
+/*
+ * Shut bcc up about 'const', which doesn't seem to be handled right
+ * by unproto.
+ */
+#ifdef __BCC__
+#define const
+#endif
+
+#define BUF_SIZE 128
+#define OUTC(c) { putc(c, stream); n++; }
+#define max(a, b) ((a > b) ? a : b)
+/*
+ * if you change the ff, you need to change the order of characters in
+ * the string 'flagstr' defined in _printf()
+ */
+#define FLAG_PADZERO (1<<0)
+#define FLAG_LEFTJUST (1<<1)
+#define FLAG_SIGNED (1<<2)
+#define FLAG_ALT (1<<3)
+#define FLAG_SPACE (1<<4)
+
+static char *utoa(unsigned int val, char *buf, int radix)
+/*
+ * Converts an integer to a variable-radix string representation
+ *
+ * Note:
+ * Does not perform sanity checking for 'radix'
+ * Assumes 'buf' has memory allocated to it
+ */
+{
+ int divisor;
+ char *p = buf;
+ const char *digitstr = "0123456789abcdef";
+
+ for (divisor = 1; val / divisor >= radix; divisor *= radix);
+ do {
+ *p++ = digitstr[val / divisor];
+ val %= divisor;
+ divisor /= radix;
+ } while (divisor >= 1);
+ *p = '\0';
+ return(buf);
+}
+
+static
+internal_fprintf(FILE * stream, const char * fmt, char *args)
+
+/* static int _printf(FILE *stream, const char *fmt, char *args) */
+/*
+ * The one that does all the work.
+ * This is a fairly complete implementation of printf(), supporting
+ * everything EXCEPT:
+ * - floating point (eEDOUfg formats)
+ * - pointers (realizes them but doesn't understand how to print them)
+ * - short and long (h/l) modifiers (dunno what to do about them)
+ * It's even slightly faster than gcc's printf() on Linux. Can't beat
+ * HP-UX's printf() though ;)
+ *
+ * Supports:
+ * d, signed integer
+ * i
+ * o unsigned octal integer
+ * u unsigned integer
+ * x unsigned hex lowercase a-f
+ * X unsigned hex uppercase A-F
+ * c character
+ * s string (character pointer)
+ * p void pointer (ignores it)
+ * % % character
+ * n number of characters output so far
+ *
+ * Special feature: (no really, it's not a bug =) )
+ * b prints an integer in binary form (i think this might come
+ * in handy *somewhere*)
+ *
+ * # alternate format for octal (leading 0) and hex (0x/0X)
+ * 0 leading zeroes for d, i, o, u, x, and X
+ * - left justify, overrides '0'
+ * ' ' (space) force a blank in front of positive numbers
+ * + force a sign in front of any number
+ *
+ * width.precision, including support for '*' (reads value from
+ * the parameter list (MUST BE INT))
+ *
+ * h, short/long modifiers, recognized but ignored.
+ * l
+ *
+ * Warning:
+ * The way varargs is implemented in libc is evil. Don't think
+ * there's a better way, but misaligned or wrong parameters
+ * passed to printf() can break a lot of things. I've tried my
+ * best to handle errors in the format string, though.
+ *
+ * Each %something field cannot exceed 'BUF_SIZE' characters,
+ * which I set to 128 right now. %s fields are not subject to
+ * this limit.
+ *
+ * Note:
+ * The semicolon -looks- missing in a few places but that's
+ * because of the macro def of 'OUTC'. did it that way to
+ * save a few lines of source ;)
+ *
+ * Expects a 'char *' as varargs parameter, unlike libc8086's
+ * printf(), which takes a 'int *' then casts it to a 'char *'.
+ * Either has to change, but it should be trivial.
+ *
+ * This function aborts whenever it scans an illegal format, unlike
+ * gcc's libc which prints out the illegal format as if it's -not-
+ * a format string. The 'STANDARD' preprocessor flag controls if
+ * if just aborts (when defined) or prints out "(err)" (when undefined).
+ */
+{
+ /*
+ * the "0-+# " and "dcs..." strings are listed in my idea of their
+ * frequency of use, with the most popular in front. not terribly
+ * important but strchr() might have an easier time that way.
+ * if you change the ordering of 'flagstr', make sure you update
+ * the #define FLAG_* stuff on top of this file too.
+ */
+ char c, *s, *f;
+ const char *flagstr = "0-+# ",
+#ifdef STANDARD
+ *typestr = "dcsixXuop";
+#else
+ *typestr = "dcsixXuopb";
+#endif
+ int n = 0, flags, width, actwidth, prec, bad = 0, neg, i;
+ static char buf[BUF_SIZE];
+
+ for (c = *fmt++; c && !bad;) {
+ if (c != '%') { /* just copy */
+ OUTC(c);
+ c = *fmt++;
+ }
+ else {
+ c = *fmt++; /* chew the % sign */
+ flags = width = prec = 0;
+ /*
+ * Parse the "0-+# " flags
+ */
+ while ((f = strchr(flagstr, c)) != NULL) {
+ flags |= 1 << (f - flagstr);
+ c = *fmt++;
+ }
+ /*
+ * The '*' parameter says fetch width value from varargs
+ */
+ if (c == '*') {
+ width = *(int *) args;
+ args += sizeof(int);
+ if (width < 0) {
+ width = abs(width);
+ flags |= FLAG_LEFTJUST; /* set '-' flag */
+ }
+ c = *fmt++;
+ }
+ else
+ /*
+ * scan and convert the width parameter
+ */
+ if (isdigit(c))
+ while (isdigit(c)) {
+ width *= 10;
+ width += c - '0';
+ c = *fmt++;
+ }
+ /*
+ * a '.' means there may be a precision parameter
+ */
+ if (c == '.') {
+ c = *fmt++;
+ /*
+ * fetch precision value from varargs
+ */
+ if (c == '*') {
+ prec = *(int *) args;
+ if (prec < 0)
+ prec = 0;
+ args += sizeof(int);
+ c = *fmt++;
+ }
+ else
+ /*
+ * scan and convert precision field
+ */
+ if (isdigit(c))
+ while (isdigit(c)) {
+ prec *= 10;
+ prec += c - '0';
+ c = *fmt++;
+ }
+ }
+ /*
+ * short and long modifiers. ignored for the moment
+ */
+ if (c == 'h') {
+ c = *fmt++;
+ }
+ else
+ if (c == 'l') {
+ c = *fmt++;
+ }
+ /*
+ * check if it's a valid type "dioux..."
+ */
+ if (strchr(typestr, c) != NULL) {
+ neg = 0;
+ switch (c) {
+ case 'd':
+ case 'i': {
+ int val = *(int *) args;
+ args += sizeof(int);
+ neg = (val < 0);
+ val = abs(val);
+ actwidth = strlen(utoa(val, buf, 10)); }
+ /*
+ * if negative or '+'/' ' flags set
+ */
+ if (neg || (flags & FLAG_SIGNED) || (flags & FLAG_SPACE))
+ actwidth++;
+ break;
+ case 'u': {
+ unsigned int uval = *(unsigned int *) args;
+ args += sizeof(unsigned int);
+ actwidth = strlen(utoa(uval, buf, 10)); }
+ /*
+ * if '+'/' ' flags set
+ */
+ if ((flags & FLAG_SIGNED) || (flags & FLAG_SPACE))
+ actwidth++;
+ break;
+ case 'x':
+ case 'X': {
+ int val = *(int *) args;
+ args += sizeof(int);
+ actwidth = strlen(utoa(val, buf, 16)); }
+ if (flags & FLAG_ALT)
+ actwidth += 2;
+ break;
+ case 'o': {
+ int val = *(int *) args;
+ args += sizeof(int);
+ actwidth = strlen(utoa(val, buf, 8)); }
+ if (flags & FLAG_ALT)
+ actwidth++;
+ break;
+ case 's':
+ s = *(char **) args;
+ args += sizeof(char *);
+ actwidth = strlen(s);
+ break;
+ case 'c':
+ buf[0] = *(char *) args;
+ buf[1] = '\0';
+ args += sizeof(char);
+ actwidth = 1;
+ break;
+ /*
+ * dunno how to handle pointers - what's the format of
+ * linux86 pointers?! right now just prints "(ptr)"
+ */
+ case 'p':
+ strcpy(buf, "(ptr)");
+ args += sizeof(void *);
+ actwidth = strlen(buf);
+ s = buf; /* pretend we're a string */
+ c = 's';
+ break;
+#ifndef STANDARD
+ case 'b': {
+ int val = *(int *) args;
+ args += sizeof(int);
+ actwidth = strlen(utoa(val, buf, 2)); }
+ break;
+#endif
+ }
+ /*
+ * strings behave differently to the width.precision
+ * parameters, so handle separately. besides, we avoid
+ * an extra 'memcpy' to 'buf'
+ */
+ if (c == 's') {
+ if (prec == 0)
+ prec = actwidth;
+ width = max(width, prec);
+ /*
+ * pad to the left if not left justified
+ */
+ if (!(flags & FLAG_LEFTJUST)) {
+ for (i = width; i > prec; i--)
+ OUTC(' ');
+ }
+ /*
+ * print out entire string if no precision specified, otherwise
+ * that's our upper limit
+ */
+ if (prec == 0)
+ for (; *s; s++)
+ OUTC(*s) /* no semicolon here */
+ else
+ for (i = 0; i < prec; i++)
+ OUTC(s[i]);
+ }
+ else {
+ /*
+ * precision is as wide as width if it's not specified and
+ * the leading zero '0' flag is set, and left-justify is
+ * -not- set. c standard says left justify overrides the
+ * leading 0.
+ */
+ if (prec == 0 && (flags & FLAG_PADZERO) && !(flags & FLAG_LEFTJUST))
+ prec = width;
+ /*
+ * expand width.precision to fit the actual width. printf
+ * width specifies the -minimum-, and aside from the
+ * precision of %s fields, there's no way to specify maximum
+ */
+ prec = max(prec, actwidth);
+ width = max(width, prec);
+ /*
+ * pad to the left if we're not left justified
+ */
+ if (!(flags & FLAG_LEFTJUST)) {
+ for (i = width; i > prec; i--)
+ OUTC(' ');
+ }
+ /*
+ * check if we might need to print the sign
+ */
+ if (strchr("diu", c) != NULL) {
+ if (neg) /* print if negative */
+ OUTC('-') /* yes, no ';' here =) */
+ else
+ if (flags & FLAG_SIGNED) /* or '+' specified */
+ OUTC('+') /* nor here */
+ else
+ if (flags & FLAG_SPACE) /* or ' ' specified */
+ OUTC(' ') /* nor here */
+ }
+ /*
+ * the alternate '#' flag is set. doesn't affect all though
+ */
+ if (flags & FLAG_ALT) {
+ switch (c) {
+ case 'o':
+ OUTC('0'); /* leading zero for octals */
+ break;
+ case 'x':
+ case 'X': /* prints 0x or 0X */
+ OUTC('0');
+ OUTC(c);
+ break;
+ }
+ }
+ /*
+ * fill the precision field with either spaces or zeroes,
+ * depending if we're printing numbers
+ */
+ if (strchr("diuxXo", c) != NULL)
+ for (i = prec; i > actwidth; i--)
+ OUTC('0')
+ else
+ for (i = prec; i > actwidth; i--)
+ OUTC(' ');
+ /*
+ * print the field, except for 'X', which we convert to caps
+ */
+ if (c != 'X')
+ for (f = buf; *f; f++)
+ OUTC(*f) /* none here either */
+ else
+ for (f = buf; *f; f++)
+ OUTC(toupper(*f));
+ }
+ /*
+ * if we're left justified, we now need to pad spaces to the
+ * right so that width will be correct
+ */
+ if (flags & FLAG_LEFTJUST)
+ for (i = width; i > prec; i--)
+ OUTC(' ');
+ }
+ else {
+ /*
+ * miscellaneous %thingies
+ */
+ switch (c) {
+ case '%': /* %% -> % */
+ OUTC('%');
+ break;
+ case 'n': /* %n writes current output count */
+ *(*(int **) args) = n;
+ args += sizeof(int *);
+ break;
+ default: /* oops, got a bad %thingy */
+ bad = 1;
+ }
+ }
+ c = *fmt++;
+ }
+ }
+#ifndef STANDARD
+ /*
+ * dunno what the standard wants if the format string is badly
+ * formed, so i print (err) if the debug flag is set
+ */
+ if (bad) {
+ OUTC('(');
+ OUTC('e');
+ OUTC('r');
+ OUTC('r');
+ OUTC(')');
+ }
+#endif
+ return(n);
+}
+
+#ifdef TEST
+
+#include <time.h>
+
+int main()
+{
+ static unsigned char xbuf[128], *x;
+ char *fmt = "%s, %s %d, %.*d:%.*d\n";
+ int rv1, rv2, i, dt1, dt2;
+ clock_t t1, t2;
+
+ x = xbuf;
+ *(char **) x = "Sun";
+ x += sizeof(char *);
+ *(char **) x = "Feb";
+ x += sizeof(char *);
+ *(int *) x = 18;
+ x += sizeof(int);
+ *(int *) x = 2;
+ x += sizeof(int);
+ *(int *) x = 10;
+ x += sizeof(int);
+ *(int *) x = 2;
+ x += sizeof(int);
+ *(int *) x = 56;
+ x += sizeof(int);
+ t1 = clock();
+ for (i = 0; i < 1000; i++)
+ rv1 = _printf(stdout, fmt, xbuf);
+ t2 = clock();
+ dt1 = t2 - t1;
+
+ t1 = clock();
+ for (i = 0; i < 1000; i++)
+ rv2 = printf(fmt, "Sun", "Feb", 18, 2, 10, 2, 56);
+ t2 = clock();
+ dt2 = t2 - t1;
+
+ printf("\nrv1: %d, rv2: %d, dt1: %d, dt2: %d\n", rv1, rv2, dt1, dt2);
+ return(0);
+}
+
+#endif
diff --git a/libc-0.0.4/stdio1/puts.c b/libc-0.0.4/stdio1/puts.c
new file mode 100644
index 0000000..d9bb8d0
--- /dev/null
+++ b/libc-0.0.4/stdio1/puts.c
@@ -0,0 +1,26 @@
+/* simplified linux puts.c
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "stdio.h"
+
+int puts (string)
+char *string;
+{
+ fputs(string, stdout);
+ putc('\n', stdout);
+ return 0;
+}
diff --git a/libc-0.0.4/stdio1/scanf.c b/libc-0.0.4/stdio1/scanf.c
new file mode 100644
index 0000000..81900a1
--- /dev/null
+++ b/libc-0.0.4/stdio1/scanf.c
@@ -0,0 +1,151 @@
+/* scanf.c for limited Linux libc
+ Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* This scanf code was derived from my printf code, which in turn was
+ * derived from Alan Cox's printk. It was tested by [no one so far...]
+ */
+
+/* Disclaimer: I haven't even THOUGHT about testing this. If you do decide
+ * to be brave and test it, and it doesn't work, you have the following
+ * options:
+ * o Send me mail telling me it doesn't work, which I will ignore
+ * since I already knew that.
+ * o Fix it yourself
+ * o isolate the problem and send it to the list, and maybe
+ * I'll fix it
+ */
+
+/* BTW, the above comment may be destroyed once this has been tested. It's
+ * not nessisary for my great great grandchildren to see it when they
+ * take Ancient Linux History...
+ */
+
+/* Incidentally, if it doesn't work, it may well be because I never bothered
+ * to learn how to use scanf()...I briefly tried it for the usaco qualification
+ * round, but had some wierd problems...ask me after mid February...BTW the
+ * problems had nothing to do with scanf(); it was still broken (hopelessly)
+ * when I went to getchar().
+ */
+
+/* Note, too that the current version probably assumes some things with
+ * variable argument handling that it shouldn't. Don't expect this to
+ * work on a 386 in 32 bit mode, don't expect this to work on a Z80,
+ * or anything other than an 8086. In fact, don't expect it to even
+ * work on an 8086 ;-)
+ */
+
+/* One of these days the headers will work painlessly... */
+/* #include <linuxmt/types.h> */
+/* #include <linuxmt/fcntl.h> */
+#include "stdio.h"
+
+/* note that we assume base == 10... */
+static int numin(int *num, int base, FILE *stream, int c)
+{
+ if ((c < '0') || (c > '9')) return 0;
+ *num = 0;
+ while ((c >= '0') && (c <= '9')) {
+ *num = *num * base + c - '0';
+ c = getc(stream);
+ }
+ ungetc(c, stream);
+}
+
+/* currently, the h/l specifications are ignored */
+static int internal_scanf(stream,fmt,a1)
+FILE *stream;
+char *fmt;
+int *a1;
+{
+ unsigned char *p=(char *)a1;
+ char c;
+ int inc;
+ int count = 0;
+
+ while(c=*fmt++)
+ {
+ do {
+ inc = getc(stream);
+ } while ((inc == ' ') || (inc == '\t') || (inc == '\n'));
+
+ if ((c == '\n') || (c == '\t') || (c == ' '))
+ ;
+ else if (c!='%') {
+ if (c != inc) {
+ ungetc(inc, stream);
+ return count;
+ }
+ } else {
+ int len=2;
+ c=*fmt++;
+ if(c=='h') c=*fmt++;
+ else if(c=='l') c=*fmt++;
+
+ switch(c)
+ {
+ case 'x':
+ if (numin(p, 16, stream, inc)) count++;
+ else return count;
+ p+=2;
+ break;
+ case 'd':
+ if (numin(p, 10, stream, inc)) count++;
+ else return count;
+ p+=2;
+ break;
+ case 's':
+ {
+ char *cp=*((char **)p);
+ p+=sizeof(char *);
+ while(*cp)
+ putc(cp++, stream);
+ while ((inc != ' ') && (inc != '\t')
+ && (inc != '\n') && (inc != EOF)) {
+ *cp++ = inc;
+ inc = getc(stream);
+ }
+ ungetc(inc, stream);
+ break;
+ }
+ case 'c':
+ *p++ = inc;
+ p++;
+ break;
+ default:
+ putc('?', stream);
+ }
+ }
+ }
+ return count;
+}
+
+
+int fscanf(stream,fmt,a1)
+FILE *stream;
+char *fmt;
+int a1;
+{
+ return internal_fscanf(stream,fmt,&a1);
+}
+
+int scanf(fmt,a1)
+char *fmt;
+int a1;
+{
+ return internal_fscanf(stdout,fmt,&a1);
+}
diff --git a/libc-0.0.4/stdio1/stdio.h b/libc-0.0.4/stdio1/stdio.h
new file mode 100644
index 0000000..4bd1989
--- /dev/null
+++ b/libc-0.0.4/stdio1/stdio.h
@@ -0,0 +1,135 @@
+/* simplified linux stdio.h
+ Copyright (C) 1995 Joel N. Weber II
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <malloc.h>
+
+#ifndef __STDIO_H
+#define __STDIO_H
+
+/* when you add or change fields here, be sure to change the initialization
+ * in stdio_init and fopen */
+struct __stdio_file {
+ int fd; /* the file descriptor associated with the stream */
+ unsigned char *bufstart; /* the start of the buffer */
+ unsigned char *bufpos; /* the next byte to write to or read from */
+ unsigned char *bufread; /* the end of data returned by last read() */
+ unsigned char *bufend; /* the end of the buffer; ie the byte after the last
+ malloc()ed byte */
+ int buffer_mode;
+#define _IONBF 0xB111 /* no buffering */
+#define _IOLBF 0xB112 /* line buffering */
+#define _IOFBF 0xB113 /* full buffering */
+ int file_mode;
+#define _MODE_READ 0xB121
+#define _MODE_WRITE 0xB122
+#define _MODE_RDWR 0xB124 /* used when a file is readwrite and is ord with
+ what's in the buffer now */
+ unsigned char ungetted, ungetchar;
+ /* ungetted = 1 if there's data unread; else 0
+ ungetchar contains the character */
+ int fc_eof:1;
+ int fc_err:1; /* eof and error conditions */
+ int iotrans:1; /* Translate \n -> \r\n on MSDOS */
+};
+
+#define EOF (-1)
+
+typedef struct __stdio_file FILE;
+
+#define BUFSIZ 256
+
+extern FILE *stdin, *stdout, *stderr, *__stdsprintf;
+
+/* The following macros are used for all access to the buffers. If you
+ * know the file is unbuffered, however, you may write to it directly, as
+ * fputs.c does. However, be aware that sprintf assumes that by setting
+ * bufend to 0, no file writing will occur. Also, since NO streams use
+ * unbuffered mode by default and the function to change this behavior is
+ * not implemented yet, I'm considering disallowing raw access at the cost
+ * of having each byte of a string written individually. However, that
+ * IS what you're asking for with non-buffered mode.
+ *
+ * RDB: It's considered very bad form to use the raw read() & write()
+ * calls on the same files you use the stdio functions.
+ */
+#ifdef __MSDOS__
+#define putc(c, fp) fputc(c, fp)
+#define getc(fp) fgetc(fp)
+#else
+#define putc(c, stream) \
+ (((stream)->bufpos[0] = (c)), \
+ ((stream)->bufpos++), \
+ ((((stream)->bufpos == (stream)->bufend) \
+ ||((stream)->buffer_mode == _IONBF) \
+ ||(((stream)->buffer_mode == _IOLBF) \
+ && ((stream)->bufpos != (stream)->bufstart) \
+ && ((stream)->bufpos[-1] == '\n'))) \
+ ? fflush(stream):0))
+
+#define getc(stream) \
+ ((stream)->ungetted ? (((stream)->ungetted = 0), ((stream)->ungetchar)) : \
+ (((stream)->bufpos == (stream)->bufread)?__ffillbuf(stream): \
+ (*(stream)->bufpos++)))
+
+#endif
+
+#define putchar(c) putc((c), stdout)
+#define getchar() getc(stdin)
+#define ungetc(c, stream) (((stream)->ungetted = 1), ((stream)->ungetchar = c))
+
+#define ferror(fp) ((fp)->fc_err)
+#define feof(fp) ((fp)->fc_eof)
+
+#define fileno(fp) ((fp)->fd)
+/* declare functions; not like it makes much difference without ANSI */
+/* RDB: The return values _are_ important, especially if we ever use
+ 8086 'large' model
+ */
+
+#ifndef __P
+#define __P(x) ()
+#endif
+
+int setvbuf __P((FILE*, char*, int, size_t));
+int __ffillbuf __P((FILE*));
+void __stdio_init __P((void));
+int fclose __P((FILE*));
+int fflush __P((FILE*));
+int fgetc __P((FILE*));
+char *fgets __P((char*, size_t, FILE*));
+FILE *fopen __P((char*, char*));
+
+int fputc __P((int, FILE*));
+int fputs __P((__const char*, FILE*));
+char *idealgetline __P((FILE*));
+int puts __P((char*));
+
+int printf __P ((__const char *, ...));
+int fprintf __P ((FILE *, __const char *, ...));
+int sprintf __P ((char *, __const char *, ...));
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#endif /* __STDIO_H */
+/* TODO: add scanf, fscanf */
diff --git a/libc-0.0.4/stdio1/test.sh b/libc-0.0.4/stdio1/test.sh
new file mode 100755
index 0000000..9d872dc
--- /dev/null
+++ b/libc-0.0.4/stdio1/test.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+echo 'rm -f *.o test *.a'
+rm -f *.o test *.a
+echo 'make'
+make
+echo 'ar r libnat.a *.o'
+ar r libnat.a *.o
+echo 'ranlib libnat.a'
+ranlib libnat.a
+echo 'gcc test.c -I- -I../include -fno-builtin -o test.o -L./ -lnat'
+gcc test.c -I- -I../include -fno-builtin -o test.o -L./ -lnat
diff --git a/libc-0.0.4/stdio2/Config b/libc-0.0.4/stdio2/Config
new file mode 100644
index 0000000..665045f
--- /dev/null
+++ b/libc-0.0.4/stdio2/Config
@@ -0,0 +1,4 @@
+#
+
+stdio: Robert's stdio package
+
diff --git a/libc-0.0.4/stdio2/Funcs b/libc-0.0.4/stdio2/Funcs
new file mode 100644
index 0000000..a177893
--- /dev/null
+++ b/libc-0.0.4/stdio2/Funcs
@@ -0,0 +1,43 @@
++clearerr Stdio
++fclose Stdio
++fdopen Stdio
++feof Stdio
++ferror Stdio
++fflush Stdio
++fgetc Stdio
++fgets Stdio
++fileno Stdio
++fopen Stdio
++fprintf Stdio
++fputc Stdio
++fputs Stdio
++fread Stdio
++freopen Stdio
++fscanf Stdio
++fseek Stdio
++ftell Stdio
++fwrite Stdio
++getc Stdio
++getchar Stdio
++gets Stdio
++pclose Stdio Popen
++popen Stdio Popen
++printf Stdio
++putc Stdio
++putchar Stdio
++puts Stdio
++rewind Stdio
++scanf Stdio
++setbuf Stdio
++setbuffer Stdio
++sprintf Stdio
++sscanf Stdio
++ungetc Stdio
++vfprintf Stdio
++vfscanf Stdio
++vprintf Stdio
++vscanf Stdio
++vsprintf Stdio
++vsscanf Stdio
+setlinebuf Stdio
+setvbuf Stdio
diff --git a/libc-0.0.4/stdio2/Makefile b/libc-0.0.4/stdio2/Makefile
new file mode 100644
index 0000000..51c48c1
--- /dev/null
+++ b/libc-0.0.4/stdio2/Makefile
@@ -0,0 +1,39 @@
+
+TOP=..
+include $(TOP)/Make.defs
+
+ASRC=stdio.c
+AOBJ=_stdio_init.o fputc.o fgetc.o fflush.o fgets.o gets.o fputs.o \
+ puts.o fread.o fwrite.o fopen.o fclose.o fseek.o rewind.o ftell.o \
+ setbuffer.o ungetc.o
+
+PSRC=printf.c
+POBJ=printf.o sprintf.o fprintf.o vprintf.o vsprintf.o vfprintf.o
+
+SSRC=scanf.c
+SOBJ=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o
+
+OBJ= $(AOBJ) $(POBJ) $(SOBJ)
+
+all: $(OBJ)
+
+$(LIBC): $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+transfer:
+ -@rm -f ../include/stdio.h
+ cp -p stdio.h ../include/.
+
+clean:
+ rm -f $(OBJ) libc.a
+
+$(AOBJ): $(ASRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ASRC)
+
+$(POBJ): $(PSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(PSRC)
+
+$(SOBJ): $(SSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(SSRC)
+
diff --git a/libc-0.0.4/stdio2/printf.c b/libc-0.0.4/stdio2/printf.c
new file mode 100644
index 0000000..0d107a4
--- /dev/null
+++ b/libc-0.0.4/stdio2/printf.c
@@ -0,0 +1,362 @@
+/*
+ * This file based on printf.c from 'Dlibs' on the atari ST (RdeBath)
+ *
+ *
+ * Dale Schumacher 399 Beacon Ave.
+ * (alias: Dalnefre') St. Paul, MN 55104
+ * dal@syntel.UUCP United States of America
+ * "It's not reality that's important, but how you perceive things."
+ */
+
+/* Altered to use stdarg, made the core function vfprintf.
+ * Hooked into the stdio package using 'inside information'
+ * Altered sizeof() assumptions, now assumes all integers except chars
+ * will be either
+ * sizeof(xxx) == sizeof(long) or sizeof(xxx) == sizeof(short)
+ *
+ * -RDB
+ */
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "stdio.h"
+
+#ifdef L_printf
+
+#ifdef __STDC__
+int printf(const char * fmt, ...)
+#else
+int printf(fmt)
+__const char *fmt;
+#endif
+{
+ va_list ptr;
+ int rv;
+ va_start(ptr, fmt);
+ rv = vfprintf(stdout,fmt,ptr);
+ va_end(ptr);
+ return rv;
+}
+#endif
+
+#ifdef L_sprintf
+#ifdef __STDC__
+int sprintf(char * sp, const char * fmt, ...)
+#else
+int sprintf(sp, fmt)
+char * sp;
+__const char *fmt;
+#endif
+{
+static FILE string[1] =
+{
+ {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1,
+ _IOFBF | __MODE_WRITE}
+};
+
+ va_list ptr;
+ int rv;
+ va_start(ptr, fmt);
+ string->bufpos = sp;
+ rv = vfprintf(string,fmt,ptr);
+ va_end(ptr);
+ *(string->bufpos) = 0;
+ return rv;
+}
+#endif
+
+#ifdef L_fprintf
+#ifdef __STDC__
+int fprintf(FILE * fp, const char * fmt, ...)
+#else
+int fprintf(fp, fmt)
+FILE * fp;
+__const char *fmt;
+#endif
+{
+ va_list ptr;
+ int rv;
+ va_start(ptr, fmt);
+ rv = vfprintf(fp,fmt,ptr);
+ va_end(ptr);
+ return rv;
+}
+#endif
+
+#ifdef L_vprintf
+int vprintf(fmt, ap)
+__const char *fmt;
+va_list ap;
+{
+ return vfprintf(stdout,fmt,ap);
+}
+#endif
+
+#ifdef L_vsprintf
+int vsprintf(sp, fmt, ap)
+char * sp;
+__const char *fmt;
+va_list ap;
+{
+static FILE string[1] =
+{
+ {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1,
+ _IOFBF | __MODE_WRITE}
+};
+
+ int rv;
+ string->bufpos = sp;
+ rv = vfprintf(string,fmt,ap);
+ *(string->bufpos) = 0;
+ return rv;
+}
+#endif
+
+#ifdef L_vfprintf
+static int
+prtfld(op, buf, ljustf, sign, pad, width, preci, buffer_mode)
+register FILE *op;
+register unsigned char *buf;
+int ljustf;
+register char sign;
+char pad;
+register int width;
+int preci;
+int buffer_mode;
+/*
+ * Output the given field in the manner specified by the arguments. Return
+ * the number of characters output.
+ */
+{
+ register int cnt = 0, len;
+ register unsigned char ch;
+
+ len = strlen(buf);
+
+ if (*buf == '-')
+ sign = *buf++;
+ else if (sign)
+ len++;
+
+ if ((preci != -1) && (len > preci)) /* limit max data width */
+ len = preci;
+
+ if (width < len) /* flexible field width or width overflow */
+ width = len;
+
+ /*
+ * at this point: width = total field width len = actual data width
+ * (including possible sign character)
+ */
+ cnt = width;
+ width -= len;
+
+ while (width || len)
+ {
+ if (!ljustf && width) /* left padding */
+ {
+ if (len && sign && (pad == '0'))
+ goto showsign;
+ ch = pad;
+ --width;
+ }
+ else if (len)
+ {
+ if (sign)
+ {
+ showsign:ch = sign; /* sign */
+ sign = '\0';
+ }
+ else
+ ch = *buf++; /* main field */
+ --len;
+ }
+ else
+ {
+ ch = pad; /* right padding */
+ --width;
+ }
+ putc(ch, op);
+ if( ch == '\n' && buffer_mode == _IOLBF ) fflush(op);
+ }
+
+ return (cnt);
+}
+
+int
+vfprintf(op, fmt, ap)
+FILE *op;
+register __const char *fmt;
+register va_list ap;
+{
+ register int i, cnt = 0, ljustf, lval;
+ int preci, dpoint, width;
+ char pad, sign, radix, hash;
+ register char *ptmp;
+ char tmp[64], *ltostr(), *ultostr();
+ int buffer_mode;
+#if FLOATS
+ double fx;
+#endif
+
+ /* This speeds things up a bit for unbuffered */
+ buffer_mode = (op->mode&__MODE_BUF);
+ op->mode &= (~__MODE_BUF);
+
+ while (*fmt)
+ {
+ if (*fmt == '%')
+ {
+ if( buffer_mode == _IONBF ) fflush(op);
+ ljustf = 0; /* left justify flag */
+ sign = '\0'; /* sign char & status */
+ pad = ' '; /* justification padding char */
+ width = -1; /* min field width */
+ dpoint = 0; /* found decimal point */
+ preci = -1; /* max data width */
+ radix = 10; /* number base */
+ ptmp = tmp; /* pointer to area to print */
+ hash = 0;
+ lval = (sizeof(int)==sizeof(long)); /* long value flaged */
+ fmtnxt:
+ i = 0;
+ for(;;)
+ {
+ ++fmt;
+ if(*fmt < '0' || *fmt > '9' ) break;
+ i = (i * 10) + (*fmt - '0');
+ if (dpoint)
+ preci = i;
+ else if (!i && (pad == ' '))
+ {
+ pad = '0';
+ goto fmtnxt;
+ }
+ else
+ width = i;
+ }
+
+ switch (*fmt)
+ {
+ case '\0': /* early EOS */
+ --fmt;
+ goto charout;
+
+ case '-': /* left justification */
+ ljustf = 1;
+ goto fmtnxt;
+
+ case ' ':
+ case '+': /* leading sign flag */
+ sign = *fmt;
+ goto fmtnxt;
+
+ case '*': /* parameter width value */
+ i = va_arg(ap, int);
+ if (dpoint)
+ preci = i;
+ else
+ width = i;
+ goto fmtnxt;
+
+ case '.': /* secondary width field */
+ dpoint = 1;
+ goto fmtnxt;
+
+ case 'l': /* long data */
+ lval = 1;
+ goto fmtnxt;
+
+ case 'h': /* short data */
+ lval = 0;
+ goto fmtnxt;
+
+ case 'd': /* Signed decimal */
+ case 'i':
+ ptmp = ltostr((long) ((lval)
+ ? va_arg(ap, long)
+ : va_arg(ap, short)),
+ 10);
+ goto printit;
+
+ case 'b': /* Unsigned binary */
+ radix = 2;
+ goto usproc;
+
+ case 'o': /* Unsigned octal */
+ radix = 8;
+ goto usproc;
+
+ case 'p': /* Pointer */
+ lval = (sizeof(char*) == sizeof(long));
+ pad = '0';
+ width = 6;
+ preci = 8;
+ /* fall thru */
+
+ case 'x': /* Unsigned hexadecimal */
+ case 'X':
+ radix = 16;
+ /* fall thru */
+
+ case 'u': /* Unsigned decimal */
+ usproc:
+ ptmp = ultostr((unsigned long) ((lval)
+ ? va_arg(ap, unsigned long)
+ : va_arg(ap, unsigned short)),
+ radix);
+ if( hash && radix == 8 ) { width = strlen(ptmp)+1; pad='0'; }
+ goto printit;
+
+ case '#':
+ hash=1;
+ goto fmtnxt;
+
+#if FLOATS
+ case 'e': /* float */
+ case 'f':
+ case 'g':
+ case 'E':
+ case 'G':
+ fx = va_arg(ap, double);
+ fp_print(fx, *fmt, preci, ptmp);
+ preci = -1;
+ goto printit;
+#endif
+
+ case 'c': /* Character */
+ ptmp[0] = va_arg(ap, int);
+ ptmp[1] = '\0';
+ goto nopad;
+
+ case 's': /* String */
+ ptmp = va_arg(ap, char*);
+ nopad:
+ sign = '\0';
+ pad = ' ';
+ printit:
+ cnt += prtfld(op, ptmp, ljustf,
+ sign, pad, width, preci, buffer_mode);
+ break;
+
+ default: /* unknown character */
+ goto charout;
+ }
+ }
+ else
+ {
+ charout:
+ putc(*fmt, op); /* normal char out */
+ ++cnt;
+ if( *fmt == '\n' && buffer_mode == _IOLBF ) fflush(op);
+ }
+ ++fmt;
+ }
+ op->mode |= buffer_mode;
+ if( buffer_mode == _IONBF ) fflush(op);
+ if( buffer_mode == _IOLBF ) op->bufwrite = op->bufstart;
+ return (cnt);
+}
+#endif
diff --git a/libc-0.0.4/stdio2/scanf.c b/libc-0.0.4/stdio2/scanf.c
new file mode 100644
index 0000000..c43320d
--- /dev/null
+++ b/libc-0.0.4/stdio2/scanf.c
@@ -0,0 +1,511 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+
+#ifdef L_scanf
+#ifdef __STDC__
+int scanf(const char * fmt, ...)
+#else
+int scanf(fmt)
+__const char *fmt;
+#endif
+{
+ va_list ptr;
+ int rv;
+ va_start(ptr, fmt);
+ rv = vfscanf(stdin,fmt,ptr);
+ va_end(ptr);
+ return rv;
+}
+#endif
+
+#ifdef L_sscanf
+#ifdef __STDC__
+int sscanf(char * sp, const char * fmt, ...)
+#else
+int sscanf(sp, fmt)
+char * sp;
+__const char *fmt;
+#endif
+{
+static FILE string[1] =
+{
+ {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1,
+ _IOFBF | __MODE_READ}
+};
+
+ va_list ptr;
+ int rv;
+ va_start(ptr, fmt);
+ string->bufpos = sp;
+ rv = vfscanf(string,fmt,ptr);
+ va_end(ptr);
+ return rv;
+}
+#endif
+
+#ifdef L_fscanf
+#ifdef __STDC__
+int fscanf(FILE * fp, const char * fmt, ...)
+#else
+int fscanf(fp, fmt)
+FILE * fp;
+__const char *fmt;
+#endif
+{
+ va_list ptr;
+ int rv;
+ va_start(ptr, fmt);
+ rv = vfscanf(fp,fmt,ptr);
+ va_end(ptr);
+ return rv;
+}
+#endif
+
+#ifdef L_vscanf
+int vscanf(fmt, ap)
+__const char *fmt;
+va_list ap;
+{
+ return vfscanf(stdin,fmt,ap);
+}
+#endif
+
+#ifdef L_vsscanf
+int vsscanf(sp, fmt, ap)
+char * sp;
+__const char *fmt;
+{
+static FILE string[1] =
+{
+ {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1,
+ _IOFBF | __MODE_READ}
+};
+
+ string->bufpos = sp;
+ return vfscanf(string,fmt,ap);
+}
+#endif
+
+#ifdef L_vfscanf
+/* #define skip() do{c=getc(fp); if (c<1) goto done;}while(isspace(c))*/
+
+#define skip() while(isspace(c)) { if ((c=getc(fp))<1) goto done; }
+
+#if FLOATS
+/* fp scan actions */
+#define F_NADA 0 /* just change state */
+#define F_SIGN 1 /* set sign */
+#define F_ESIGN 2 /* set exponent's sign */
+#define F_INT 3 /* adjust integer part */
+#define F_FRAC 4 /* adjust fraction part */
+#define F_EXP 5 /* adjust exponent part */
+#define F_QUIT 6
+
+#define NSTATE 8
+#define FS_INIT 0 /* initial state */
+#define FS_SIGNED 1 /* saw sign */
+#define FS_DIGS 2 /* saw digits, no . */
+#define FS_DOT 3 /* saw ., no digits */
+#define FS_DD 4 /* saw digits and . */
+#define FS_E 5 /* saw 'e' */
+#define FS_ESIGN 6 /* saw exp's sign */
+#define FS_EDIGS 7 /* saw exp's digits */
+
+#define FC_DIG 0
+#define FC_DOT 1
+#define FC_E 2
+#define FC_SIGN 3
+
+/* given transition,state do what action? */
+int fp_do[][NSTATE] = {
+ {F_INT,F_INT,F_INT,
+ F_FRAC,F_FRAC,
+ F_EXP,F_EXP,F_EXP}, /* see digit */
+ {F_NADA,F_NADA,F_NADA,
+ F_QUIT,F_QUIT,F_QUIT,F_QUIT,F_QUIT}, /* see '.' */
+ {F_QUIT,F_QUIT,
+ F_NADA,F_QUIT,F_NADA,
+ F_QUIT,F_QUIT,F_QUIT}, /* see e/E */
+ {F_SIGN,F_QUIT,F_QUIT,F_QUIT,F_QUIT,
+ F_ESIGN,F_QUIT,F_QUIT}, /* see sign */
+};
+/* given transition,state what is new state? */
+int fp_ns[][NSTATE] = {
+ {FS_DIGS,FS_DIGS,FS_DIGS,
+ FS_DD,FS_DD,
+ FS_EDIGS,FS_EDIGS,FS_EDIGS}, /* see digit */
+ {FS_DOT,FS_DOT,FS_DD,
+ }, /* see '.' */
+ {0,0,
+ FS_E,0,FS_E,
+ }, /* see e/E */
+ {FS_SIGNED,0,0,0,0,
+ FS_ESIGN,0,0}, /* see sign */
+};
+/* which states are valid terminators? */
+int fp_sval[NSTATE] = {
+ 0,0,1,0,1,0,0,1
+};
+#endif
+
+vfscanf(fp, fmt, ap)
+register FILE *fp;
+register char *fmt;
+va_list ap;
+
+{
+ register long n;
+ register int c, width, lval, cnt = 0;
+ int store, neg, base, wide1, endnull, rngflag, c2;
+ register unsigned char *p;
+ unsigned char delim[128], digits[17], *q;
+#if FLOATS
+ long frac, expo;
+ int eneg, fraclen, fstate, trans;
+ double fx, fp_scan();
+#endif
+
+ if (!*fmt)
+ return (0);
+
+ c = getc(fp);
+ while (c > 0)
+ {
+ store = 0;
+ if (*fmt == '%')
+ {
+ n = 0;
+ width = -1;
+ wide1 = 1;
+ base = 10;
+ lval = (sizeof(long) == sizeof(int));
+ store = 1;
+ endnull = 1;
+ neg = -1;
+
+ strcpy(delim, "\011\012\013\014\015 ");
+ strcpy(digits, "0123456789ABCDEF");
+
+ if (fmt[1] == '*')
+ {
+ endnull = store = 0;
+ ++fmt;
+ }
+
+ while (isdigit(*++fmt))/* width digit(s) */
+ {
+ if (width == -1)
+ width = 0;
+ wide1 = width = (width * 10) + (*fmt - '0');
+ }
+ --fmt;
+ fmtnxt:
+ ++fmt;
+ switch (tolower(*fmt)) /* tolower() is a MACRO! */
+ {
+ case '*':
+ endnull = store = 0;
+ goto fmtnxt;
+
+ case 'l': /* long data */
+ lval = 1;
+ goto fmtnxt;
+ case 'h': /* short data */
+ lval = 0;
+ goto fmtnxt;
+
+ case 'i': /* any-base numeric */
+ base = 0;
+ goto numfmt;
+
+ case 'b': /* unsigned binary */
+ base = 2;
+ goto numfmt;
+
+ case 'o': /* unsigned octal */
+ base = 8;
+ goto numfmt;
+
+ case 'x': /* unsigned hexadecimal */
+ base = 16;
+ goto numfmt;
+
+ case 'd': /* SIGNED decimal */
+ neg = 0;
+ /* FALL-THRU */
+
+ case 'u': /* unsigned decimal */
+ numfmt:skip();
+
+ if (isupper(*fmt))
+ lval = 1;
+
+ if (!base)
+ {
+ base = 10;
+ neg = 0;
+ if (c == '%')
+ {
+ base = 2;
+ goto skip1;
+ }
+ else if (c == '0')
+ {
+ c = getc(fp);
+ if (c < 1)
+ goto savnum;
+ if ((c != 'x')
+ && (c != 'X'))
+ {
+ base = 8;
+ digits[8] = '\0';
+ goto zeroin;
+ }
+ base = 16;
+ goto skip1;
+ }
+ }
+
+ if ((neg == 0) && (base == 10)
+ && ((neg = (c == '-')) || (c == '+')))
+ {
+ skip1:
+ c = getc(fp);
+ if (c < 1)
+ goto done;
+ }
+
+ digits[base] = '\0';
+ p = ((unsigned char *)
+ strchr(digits, toupper(c)));
+
+ if ((!c || !p) && width)
+ goto done;
+
+ while (p && width-- && c)
+ {
+ n = (n * base) + (p - digits);
+ c = getc(fp);
+ zeroin:
+ p = ((unsigned char *)
+ strchr(digits, toupper(c)));
+ }
+ savnum:
+ if (store)
+ {
+ if (neg == 1)
+ n = -n;
+ if (lval)
+ *va_arg(ap, long*) = n;
+ else
+ *va_arg(ap, short*) = n;
+ ++cnt;
+ }
+ break;
+
+#if FLOATS
+ case 'e': /* float */
+ case 'f':
+ case 'g':
+ skip();
+
+ if (isupper(*fmt))
+ lval = 1;
+
+ fstate = FS_INIT;
+ neg = 0;
+ eneg = 0;
+ n = 0;
+ frac = 0;
+ expo = 0;
+ fraclen = 0;
+
+ while (c && width--)
+ {
+ if (c >= '0' && c <= '9')
+ trans = FC_DIG;
+ else if (c == '.')
+ trans = FC_DOT;
+ else if (c == '+' || c == '-')
+ trans = FC_SIGN;
+ else if (tolower(c) == 'e')
+ trans = FC_E;
+ else
+ goto fdone;
+
+ switch (fp_do[trans][fstate])
+ {
+ case F_SIGN:
+ neg = (c == '-');
+ break;
+ case F_ESIGN:
+ eneg = (c == '-');
+ break;
+ case F_INT:
+ n = 10 * n + (c - '0');
+ break;
+ case F_FRAC:
+ frac = 10 * frac + (c - '0');
+ fraclen++;
+ break;
+ case F_EXP:
+ expo = 10 * expo + (c - '0');
+ break;
+ case F_QUIT:
+ goto fdone;
+ }
+ fstate = fp_ns[trans][fstate];
+ c = getc(fp);
+ }
+
+ fdone:
+ if (!fp_sval[fstate])
+ goto done;
+ if (store)
+ {
+ fx = fp_scan(neg, eneg, n, frac, expo, fraclen);
+ if (lval)
+ *va_arg(ap, double *) = fx;
+ else
+ *va_arg(ap, float *) = fx;
+ ++cnt;
+ }
+ break;
+#endif
+
+ case 'c': /* character data */
+ width = wide1;
+ lval = endnull = 0;
+ delim[0] = '\0';
+ goto strproc;
+
+ case '[': /* string w/ delimiter set */
+
+ /* get delimiters */
+ p = delim;
+
+ if (*++fmt == '^')
+ {
+ fmt++;
+ lval = 0;
+ }
+ else
+ lval = 1;
+
+ rngflag = 2;
+ if ((*fmt == ']') || (*fmt == '-'))
+ {
+ *p++ = *fmt++;
+ rngflag = 0;
+ }
+
+ while (*fmt != ']')
+ {
+ if (*fmt == '\0')
+ goto done;
+ switch (rngflag)
+ {
+ case 1:
+ c2 = *(p - 2);
+ if (c2 <= *fmt)
+ {
+ p -= 2;
+ while (c2 < *fmt)
+ *p++ = c2++;
+ rngflag = 2;
+ break;
+ }
+ /* fall thru intentional */
+
+ case 0:
+ rngflag = (*fmt == '-');
+ break;
+
+ case 2:
+ rngflag = 0;
+ }
+
+ *p++ = *fmt++;
+ }
+
+ *p = '\0';
+ goto strproc;
+
+ case 's': /* string data */
+ lval = 0;
+ skip();
+ strproc:
+ /* process string */
+ p = va_arg(ap, unsigned char *);
+
+ /* if the 1st char fails, match fails */
+ if (width)
+ {
+ q = ((unsigned char *)
+ strchr(delim, c));
+ if ((c < 1) || lval == (q==0))
+ {
+ if (endnull)
+ *p = '\0';
+ goto done;
+ }
+ }
+
+ for (;;) /* FOREVER */
+ {
+ if (store)
+ *p++ = c;
+ if (((c = getc(fp)) < 1) ||
+ (--width == 0))
+ break;
+
+ q = ((unsigned char *)
+ strchr(delim, c));
+ if (lval == (q==0))
+ break;
+ }
+
+ if (store)
+ {
+ if (endnull)
+ *p = '\0';
+ ++cnt;
+ }
+ break;
+
+ case '\0': /* early EOS */
+ --fmt;
+ /* FALL THRU */
+
+ default:
+ goto cmatch;
+ }
+ }
+ else if (isspace(*fmt)) /* skip whitespace */
+ {
+ skip();
+ }
+ else
+ { /* normal match char */
+ cmatch:
+ if (c != *fmt)
+ break;
+ c = getc(fp);
+ }
+
+ if (!*++fmt)
+ break;
+ }
+
+ done: /* end of scan */
+ if ((c == EOF) && (cnt == 0))
+ return (EOF);
+
+ if( c != EOF )
+ ungetc(c, fp);
+ return (cnt);
+}
+
+#endif
diff --git a/libc-0.0.4/stdio2/stdio.c b/libc-0.0.4/stdio2/stdio.c
new file mode 100644
index 0000000..575a8f9
--- /dev/null
+++ b/libc-0.0.4/stdio2/stdio.c
@@ -0,0 +1,738 @@
+/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/* This is an implementation of the C standard IO package.
+ */
+
+#include <stdio.h>
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <malloc.h>
+#include <errno.h>
+
+extern FILE *__IO_list; /* For fflush at exit */
+
+#ifndef __AS386_16__
+#define Inline_init __io_init_vars()
+#else
+#define Inline_init
+#endif
+
+#ifdef L__stdio_init
+
+FILE *__IO_list = 0; /* For fflush at exit */
+
+static char bufin[BUFSIZ];
+static char bufout[BUFSIZ];
+
+#define buferr (stderr->unbuf) /* Stderr is unbuffered */
+
+FILE stdin[1] =
+{
+ {bufin, bufin, bufin, bufin, bufin + sizeof(bufin),
+ 0, _IOFBF | __MODE_READ | __MODE_IOTRAN}
+};
+
+FILE stdout[1] =
+{
+ {bufout, bufout, bufout, bufout, bufout + sizeof(bufout),
+ 1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN}
+};
+
+FILE stderr[1] =
+{
+ {buferr, buferr, buferr, buferr, buferr + sizeof(buferr),
+ 2, _IONBF | __MODE_WRITE | __MODE_IOTRAN}
+};
+
+/* Call the stdio initiliser; it's main job it to call atexit */
+
+#ifndef __AS386_16__
+#define STATIC
+#else
+#define STATIC static
+
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word ___io_init_vars ! Pointer to the autorun function
+ .word no_op ! Space filler cause segs are padded to 4 bytes.
+ .text ! So the function after is also in the correct seg.
+#endasm
+#endif
+
+STATIC int
+__stdio_close_all()
+{
+ FILE *fp;
+ fflush(stdout);
+ fflush(stderr);
+ for (fp = __IO_list; fp; fp = fp->next)
+ {
+ fflush(fp);
+ close(fp->fd);
+ /* Note we're not de-allocating the memory */
+ /* There doesn't seem to be much point :-) */
+ fp->fd = -1;
+ }
+}
+
+STATIC void
+__io_init_vars()
+{
+#ifndef __AS386_16__
+ static int first_time = 1;
+ if( !first_time ) return ; first_time = 1;
+#endif
+ if (isatty(1))
+ stdout->mode |= _IOLBF;
+ atexit(__stdio_close_all);
+}
+#endif
+
+#ifdef L_fputc
+int
+fputc(ch, fp)
+int ch;
+FILE *fp;
+{
+ register int v;
+ Inline_init;
+
+ v = fp->mode;
+ /* If last op was a read ... */
+ if ((v & __MODE_READING) && fflush(fp))
+ return EOF;
+
+ /* Can't write or there's been an EOF or error then return EOF */
+ if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE)
+ return EOF;
+
+ /* In MSDOS translation mode */
+#if __MODE_IOTRAN
+ if (ch == '\n' && (v & __MODE_IOTRAN) && fputc('\r', fp) == EOF)
+ return EOF;
+#endif
+
+ /* Buffer is full */
+ if (fp->bufpos >= fp->bufend && fflush(fp))
+ return EOF;
+
+ /* Right! Do it! */
+ *(fp->bufpos++) = ch;
+ fp->mode |= __MODE_WRITING;
+
+ /* Unbuffered or Line buffered and end of line */
+ if (((ch == '\n' && (v & _IOLBF)) || (v & _IONBF))
+ && fflush(fp))
+ return EOF;
+
+ /* Can the macro handle this by itself ? */
+ if (v & (__MODE_IOTRAN | _IOLBF | _IONBF))
+ fp->bufwrite = fp->bufstart; /* Nope */
+ else
+ fp->bufwrite = fp->bufend; /* Yup */
+
+ /* Correct return val */
+ return (unsigned char) ch;
+}
+#endif
+
+#ifdef L_fgetc
+int
+fgetc(fp)
+FILE *fp;
+{
+ int ch;
+
+ if (fp->mode & __MODE_WRITING)
+ fflush(fp);
+
+ try_again:
+ /* Can't read or there's been an EOF or error then return EOF */
+ if ((fp->mode & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ)
+ return EOF;
+
+ /* Nothing in the buffer - fill it up */
+ if (fp->bufpos >= fp->bufread)
+ {
+ fp->bufpos = fp->bufread = fp->bufstart;
+ ch = fread(fp->bufpos, 1, fp->bufend - fp->bufstart, fp);
+ if (ch == 0)
+ return EOF;
+ fp->bufread += ch;
+ fp->mode |= __MODE_READING;
+ fp->mode &= ~__MODE_UNGOT;
+ }
+ ch = *(fp->bufpos++);
+
+#if __MODE_IOTRAN
+ /* In MSDOS translation mode; WARN: Doesn't work with UNIX macro */
+ if (ch == '\r' && (fp->mode & __MODE_IOTRAN))
+ goto try_again;
+#endif
+
+ return ch;
+}
+#endif
+
+#ifdef L_fflush
+int
+fflush(fp)
+FILE *fp;
+{
+ int len, cc;
+ if (fp == NULL) /* On NULL flush the lot. */
+ {
+ if (fflush(stdin))
+ return EOF;
+ if (fflush(stdout))
+ return EOF;
+ if (fflush(stderr))
+ return EOF;
+
+ for (fp = __IO_list; fp; fp = fp->next)
+ if (fflush(fp))
+ return EOF;
+
+ return 0;
+ }
+
+ /* If there's output data pending */
+ if (fp->mode & __MODE_WRITING)
+ {
+ len = fp->bufpos - fp->bufstart;
+
+ if (len)
+ {
+ /*
+ * The loop is so we don't get upset by signals
+ */
+ do
+ {
+ cc = write(fp->fd, fp->bufstart, len);
+ }
+ while (cc == -1 && errno == EINTR);
+ /*
+ * I think the following test is _too_ stringent, but it's not
+ * serious If it is found to be a problem then if cc>0 we can do
+ * a memcpy to put the buffer in a state for a retry. Or even do
+ * the retry ourselves.
+ */
+ if (cc != len)
+ {
+ fp->mode |= __MODE_ERR;
+ return EOF;
+ }
+ }
+ }
+ /* If there's data in the buffer sychronise the file positions */
+ else if (fp->mode & __MODE_READING)
+ {
+ /* Humm, I think this means sync the file like fpurge() ... */
+ /* Anyway the user isn't supposed to call this function when reading */
+
+ len = fp->bufread - fp->bufpos; /* Bytes buffered but unread */
+ /* If it's a file, make it good */
+ if (len > 0 && lseek(fp->fd, -len, 1) < 0)
+ {
+ /* Hummm - Not certain here, I don't think this is reported */
+ /*
+ * fp->mode |= __MODE_ERR; return EOF;
+ */
+ }
+ }
+
+ /* All done, no problem */
+ fp->mode &= (~(__MODE_READING|__MODE_WRITING|__MODE_EOF|__MODE_UNGOT));
+ fp->bufread = fp->bufwrite = fp->bufpos = fp->bufstart;
+ return 0;
+}
+#endif
+
+#ifdef L_fgets
+/* Nothing special here ... */
+char *
+fgets(s, count, f)
+char *s;
+size_t count;
+FILE *f;
+{
+ char *ret;
+ register size_t i;
+ register int ch;
+
+ ret = s;
+ for (i = count; i > 0; i--)
+ {
+ ch = getc(f);
+ if (ch == EOF)
+ {
+ if (s == ret)
+ return 0;
+ break;
+ }
+ *s++ = (char) ch;
+ if (ch == '\n')
+ break;
+ }
+ *s = 0;
+
+ if (ferror(f))
+ return 0;
+ return ret;
+}
+#endif
+
+#ifdef L_gets
+char *
+gets(str) /* BAD function; DON'T use it! */
+char *str;
+{
+ /* Auwlright it will work but of course _your_ program will crash */
+ /* if it's given a too long line */
+ register char *p = str;
+ register int c;
+
+ while (((c = getc(stdin)) != EOF) && (c != '\n'))
+ *p++ = c;
+ *p = '\0';
+ return (((c == EOF) && (p == str)) ? NULL : str); /* NULL == EOF */
+}
+#endif
+
+#ifdef L_fputs
+int
+fputs(str, fp)
+char *str;
+FILE *fp;
+{
+ register int n = 0;
+ while (*str)
+ {
+ if (putc(*str++, fp) == EOF)
+ return (EOF);
+ ++n;
+ }
+ return (n);
+}
+#endif
+
+#ifdef L_puts
+int
+puts(str)
+char *str;
+{
+ register int n;
+
+ if (((n = fputs(str, stdout)) == EOF)
+ || (putc('\n', stdout) == EOF))
+ return (EOF);
+ return (++n);
+}
+#endif
+
+#ifdef L_fread
+/*
+ * fread will often be used to read in large chunks of data calling read()
+ * directly can be a big win in this case. Beware also fgetc calls this
+ * function to fill the buffer.
+ *
+ * This ignores __MODE__IOTRAN; probably exactly what you want. (It _is_ what
+ * fgetc wants)
+ */
+int
+fread(buf, size, nelm, fp)
+char *buf;
+int size;
+int nelm;
+FILE *fp;
+{
+ int len, v;
+ unsigned bytes, got = 0;
+ Inline_init;
+
+ v = fp->mode;
+
+ /* Want to do this to bring the file pointer up to date */
+ if (v & __MODE_WRITING)
+ fflush(fp);
+
+ /* Can't read or there's been an EOF or error then return zero */
+ if ((v & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ)
+ return 0;
+
+ /* This could be long, doesn't seem much point tho */
+ bytes = size * nelm;
+
+ len = fp->bufread - fp->bufpos;
+ if (len >= bytes) /* Enough buffered */
+ {
+ memcpy(buf, fp->bufpos, (unsigned) bytes);
+ fp->bufpos += bytes;
+ return bytes;
+ }
+ else if (len > 0) /* Some buffered */
+ {
+ memcpy(buf, fp->bufpos, len);
+ got = len;
+ }
+
+ /* Need more; do it with a direct read */
+ len = read(fp->fd, buf + got, (unsigned) (bytes - got));
+
+ /* Possibly for now _or_ later */
+ if (len < 0)
+ {
+ fp->mode |= __MODE_ERR;
+ len = 0;
+ }
+ else if (len == 0)
+ fp->mode |= __MODE_EOF;
+
+ return (got + len) / size;
+}
+#endif
+
+#ifdef L_fwrite
+/*
+ * Like fread, fwrite will often be used to write out large chunks of
+ * data; calling write() directly can be a big win in this case.
+ *
+ * But first we check to see if there's space in the buffer.
+ *
+ * Again this ignores __MODE__IOTRAN.
+ */
+int
+fwrite(buf, size, nelm, fp)
+char *buf;
+int size;
+int nelm;
+FILE *fp;
+{
+ register int v;
+ int len;
+ unsigned bytes, put;
+
+ v = fp->mode;
+ /* If last op was a read ... */
+ if ((v & __MODE_READING) && fflush(fp))
+ return 0;
+
+ /* Can't write or there's been an EOF or error then return 0 */
+ if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE)
+ return 0;
+
+ /* This could be long, doesn't seem much point tho */
+ bytes = size * nelm;
+
+ len = fp->bufend - fp->bufpos;
+
+ /* Flush the buffer if not enough room */
+ if (bytes > len)
+ if (fflush(fp))
+ return 0;
+
+ len = fp->bufend - fp->bufpos;
+ if (bytes <= len) /* It'll fit in the buffer ? */
+ {
+ fp->mode |= __MODE_WRITING;
+ memcpy(fp->bufpos, buf, bytes);
+ fp->bufpos += bytes;
+
+ /* If we're not fully buffered */
+ if (v & (_IOLBF | _IONBF))
+ fflush(fp);
+
+ return nelm;
+ }
+ else
+ /* Too big for the buffer */
+ {
+ put = write(fp->fd, buf, bytes);
+ if (put < 0)
+ {
+ fp->mode |= __MODE_ERR;
+ put = 0;
+ }
+ }
+
+ return put / size;
+}
+#endif
+
+#ifdef L_rewind
+void
+rewind(fp)
+FILE * fp;
+{
+ fseek(fp, (long)0, 0);
+ clearerr(fp);
+}
+#endif
+
+#ifdef L_fseek
+int
+fseek(fp, offset, ref)
+FILE *fp;
+long offset;
+int ref;
+{
+ /* Use fflush to sync the pointers */
+ /*
+ * TODO: if __MODE_READING and no ungetc ever done can just move
+ * pointer
+ */
+
+ if (fflush(fp) == EOF)
+ return EOF;
+ if (lseek(fp->fd, offset, ref) < 0)
+ return EOF;
+ return 0;
+}
+#endif
+
+#ifdef L_ftell
+long ftell(fp)
+FILE * fp;
+{
+ long rv;
+ if (fflush(fp) == EOF)
+ return EOF;
+ return lseek(fp->fd, 0L, SEEK_CUR);
+}
+#endif
+
+#ifdef L_fopen
+/*
+ * This Fopen is all three of fopen, fdopen and freopen. The macros in
+ * stdio.h show the other names.
+ */
+FILE *
+__fopen(fname, fd, fp, mode)
+char *fname;
+int fd;
+FILE *fp;
+char *mode;
+{
+ int open_mode = 0;
+#if __MODE_IOTRAN
+ int do_iosense = 1;
+#endif
+ int fopen_mode = 0;
+ FILE *nfp = 0;
+
+ /* If we've got an fp close the old one (freopen) */
+ if (fp)
+ {
+ /* Careful, don't de-allocate it */
+ fopen_mode |= (fp->mode & (__MODE_BUF | __MODE_FREEFIL | __MODE_FREEBUF));
+ fp->mode &= ~(__MODE_FREEFIL | __MODE_FREEBUF);
+ fclose(fp);
+ }
+
+ /* decode the new open mode */
+ while (*mode)
+ switch (*mode++)
+ {
+ case 'r':
+ fopen_mode |= __MODE_READ;
+ break;
+ case 'w':
+ fopen_mode |= __MODE_WRITE;
+ open_mode = (O_CREAT | O_TRUNC);
+ break;
+ case 'a':
+ fopen_mode |= __MODE_WRITE;
+ open_mode = (O_CREAT | O_APPEND);
+ break;
+ case '+':
+ fopen_mode |= __MODE_RDWR;
+ break;
+#if __MODE_IOTRAN
+ case 'b': /* Binary */
+ fopen_mode &= ~__MODE_IOTRAN;
+ do_iosense=0;
+ break;
+ case 't': /* Text */
+ fopen_mode |= __MODE_IOTRAN;
+ do_iosense=0;
+ break;
+#endif
+ }
+
+ /* Add in the read/write options to mode for open() */
+ switch (fopen_mode & (__MODE_READ | __MODE_WRITE))
+ {
+ case 0:
+ return 0;
+ case __MODE_READ:
+ open_mode |= O_RDONLY;
+ break;
+ case __MODE_WRITE:
+ open_mode |= O_WRONLY;
+ break;
+ default:
+ open_mode |= O_RDWR;
+ break;
+ }
+
+ /* Allocate the (FILE) before we do anything irreversable */
+ if (fp == 0)
+ {
+ nfp = malloc(sizeof(FILE));
+ if (nfp == 0)
+ return 0;
+ }
+
+ /* Open the file itself */
+ if (fname)
+ fd = open(fname, open_mode, 0666);
+ if (fd < 0) /* Grrrr */
+ {
+ if (nfp)
+ free(nfp);
+ return 0;
+ }
+
+ /* If this isn't freopen create a (FILE) and buffer for it */
+ if (fp == 0)
+ {
+ fp = nfp;
+ fp->next = __IO_list;
+ __IO_list = fp;
+
+ fp->mode = __MODE_FREEFIL;
+ if( isatty(fd) )
+ {
+ fp->mode |= _IOLBF;
+#if __MODE_IOTRAN
+ if( do_iosense ) fopen_mode |= __MODE_IOTRAN;
+#endif
+ }
+ else
+ fp->mode |= _IOFBF;
+ fp->bufstart = malloc(BUFSIZ);
+ if (fp->bufstart == 0) /* Oops, no mem */
+ { /* Humm, full buffering with a two(!) byte
+ * buffer. */
+ fp->bufstart = fp->unbuf;
+ fp->bufend = fp->unbuf + sizeof(fp->unbuf);
+ }
+ else
+ {
+ fp->bufend = fp->bufstart + BUFSIZ;
+ fp->mode |= __MODE_FREEBUF;
+ }
+ }
+
+ /* Ok, file's ready clear the buffer and save important bits */
+ fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
+ fp->mode |= fopen_mode;
+ fp->fd = fd;
+
+ return fp;
+}
+#endif
+
+#ifdef L_fclose
+int
+fclose(fp)
+FILE *fp;
+{
+ int rv = 0;
+
+ if (fp == 0)
+ {
+ errno = EINVAL;
+ return EOF;
+ }
+ if (fflush(fp))
+ return EOF;
+
+ if (close(fp->fd))
+ rv = EOF;
+ fp->fd = -1;
+
+ if (fp->mode & __MODE_FREEBUF)
+ {
+ free(fp->bufstart);
+ fp->mode &= ~__MODE_FREEBUF;
+ fp->bufstart = fp->bufend = 0;
+ }
+
+ if (fp->mode & __MODE_FREEFIL)
+ {
+ FILE *prev = 0, *ptr;
+ fp->mode = 0;
+
+ for (ptr = __IO_list; ptr && ptr != fp; ptr = ptr->next)
+ ;
+ if (ptr == fp)
+ {
+ if (prev == 0)
+ __IO_list = fp->next;
+ else
+ prev->next = fp->next;
+ }
+ free(fp);
+ }
+ else
+ fp->mode = 0;
+
+ return rv;
+}
+#endif
+
+#ifdef L_setbuffer
+void
+setbuffer(fp, buf, size)
+FILE * fp;
+char * buf;
+int size;
+{
+ fflush(fp);
+ if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart);
+ fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);
+
+ if( buf == 0 )
+ {
+ fp->bufstart = fp->unbuf;
+ fp->bufend = fp->unbuf + sizeof(fp->unbuf);
+ fp->mode |= _IONBF;
+ }
+ else
+ {
+ fp->bufstart = buf;
+ fp->bufend = buf+size;
+ fp->mode |= _IOFBF;
+ }
+ fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
+}
+#endif
+
+#ifdef L_ungetc
+int
+ungetc(c, fp)
+int c;
+FILE *fp;
+{
+ if (fp->mode & __MODE_WRITING)
+ fflush(fp);
+
+ /* Can't read or there's been an error then return EOF */
+ if ((fp->mode & (__MODE_READ | __MODE_ERR)) != __MODE_READ)
+ return EOF;
+
+ if( fp->bufpos > fp->bufstart )
+ return *--fp->bufpos = (unsigned char) c;
+ else if( fp->bufread == fp->bufstart )
+ return *fp->bufread++ = (unsigned char) c;
+ else
+ return EOF;
+}
+#endif
+
diff --git a/libc-0.0.4/stdio2/stdio.c.old b/libc-0.0.4/stdio2/stdio.c.old
new file mode 100644
index 0000000..2c06b8d
--- /dev/null
+++ b/libc-0.0.4/stdio2/stdio.c.old
@@ -0,0 +1,730 @@
+/* Copyright (C) 1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+/* This is an implementation of the C standard IO package.
+ */
+
+#include <stdio.h>
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <malloc.h>
+#include <errno.h>
+
+extern FILE *__IO_list; /* For fflush at exit */
+
+#ifndef __AS386_16__
+#define Inline_init __io_init_vars()
+#else
+#define Inline_init
+#endif
+
+#ifdef L__stdio_init
+
+FILE *__IO_list = 0; /* For fflush at exit */
+
+static char bufin[BUFSIZ];
+static char bufout[BUFSIZ];
+
+#define buferr (stderr->unbuf) /* Stderr is unbuffered */
+
+FILE stdin[1] =
+{
+ {bufin, bufin, bufin, bufin, bufin + sizeof(bufin),
+ 0, _IOFBF | __MODE_READ | __MODE_IOTRAN}
+};
+
+FILE stdout[1] =
+{
+ {bufout, bufout, bufout, bufout, bufout + sizeof(bufout),
+ 1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN}
+};
+
+FILE stderr[1] =
+{
+ {buferr, buferr, buferr, buferr, buferr + sizeof(buferr),
+ 2, _IONBF | __MODE_WRITE | __MODE_IOTRAN}
+};
+
+/* Call the stdio initiliser; it's main job it to call atexit */
+
+#ifndef __AS386_16__
+#define STATIC
+#else
+#define STATIC static
+
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word ___io_init_vars ! Pointer to the autorun function
+ .word no_op ! Space filler cause segs are padded to 4 bytes.
+ .text ! So the function after is also in the correct seg.
+#endasm
+#endif
+
+STATIC int
+__stdio_close_all()
+{
+ FILE *fp;
+ fflush(stdout);
+ fflush(stderr);
+ for (fp = __IO_list; fp; fp = fp->next)
+ {
+ fflush(fp);
+ close(fp->fd);
+ /* Note we're not de-allocating the memory */
+ /* There doesn't seem to be much point :-) */
+ fp->fd = -1;
+ }
+}
+
+STATIC void
+__io_init_vars()
+{
+#ifndef __AS386_16__
+ static int first_time = 1;
+ if( !first_time ) return ; first_time = 1;
+#endif
+ if (isatty(1))
+ stdout->mode |= _IOLBF;
+ atexit(__stdio_close_all);
+}
+#endif
+
+#ifdef L_fputc
+int
+fputc(ch, fp)
+int ch;
+FILE *fp;
+{
+ register int v;
+ Inline_init;
+
+ v = fp->mode;
+ /* If last op was a read ... */
+ if ((v & __MODE_READING) && fflush(fp))
+ return EOF;
+
+ /* Can't write or there's been an EOF or error then return EOF */
+ if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE)
+ return EOF;
+
+ /* In MSDOS translation mode */
+#if __MODE_IOTRAN
+ if (ch == '\n' && (v & __MODE_IOTRAN) && fputc('\r', fp) == EOF)
+ return EOF;
+#endif
+
+ /* Buffer is full */
+ if (fp->bufpos >= fp->bufend && fflush(fp))
+ return EOF;
+
+ /* Right! Do it! */
+ *(fp->bufpos++) = ch;
+ fp->mode |= __MODE_WRITING;
+
+ /* Unbuffered or Line buffered and end of line */
+ if (((ch == '\n' && (v & _IOLBF)) || (v & _IONBF))
+ && fflush(fp))
+ return EOF;
+
+ /* Can the macro handle this by itself ? */
+ if (v & (__MODE_IOTRAN | _IOLBF | _IONBF))
+ fp->bufwrite = fp->bufstart; /* Nope */
+ else
+ fp->bufwrite = fp->bufend; /* Yup */
+
+ /* Correct return val */
+ return (unsigned char) ch;
+}
+#endif
+
+#ifdef L_fgetc
+int
+fgetc(fp)
+FILE *fp;
+{
+ int ch;
+
+ if (fp->mode & __MODE_WRITING)
+ fflush(fp);
+
+ try_again:
+ /* Can't read or there's been an EOF or error then return EOF */
+ if ((fp->mode & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ)
+ return EOF;
+
+ /* Nothing in the buffer - fill it up */
+ if (fp->bufpos >= fp->bufread)
+ {
+ fp->bufpos = fp->bufread = fp->bufstart;
+ ch = fread(fp->bufpos, 1, fp->bufend - fp->bufstart, fp);
+ if (ch == 0)
+ return EOF;
+ fp->bufread += ch;
+ fp->mode |= __MODE_READING;
+ fp->mode &= ~__MODE_UNGOT;
+ }
+ ch = *(fp->bufpos++);
+
+#if __MODE_IOTRAN
+ /* In MSDOS translation mode; WARN: Doesn't work with UNIX macro */
+ if (ch == '\r' && (fp->mode & __MODE_IOTRAN))
+ goto try_again;
+#endif
+
+ return ch;
+}
+#endif
+
+#ifdef L_fflush
+int
+fflush(fp)
+FILE *fp;
+{
+ int len, cc;
+ if (fp == NULL) /* On NULL flush the lot. */
+ {
+ if (fflush(stdin))
+ return EOF;
+ if (fflush(stdout))
+ return EOF;
+ if (fflush(stderr))
+ return EOF;
+
+ for (fp = __IO_list; fp; fp = fp->next)
+ if (fflush(fp))
+ return EOF;
+
+ return 0;
+ }
+
+ /* If there's output data pending */
+ if (fp->mode & __MODE_WRITING)
+ {
+ len = fp->bufpos - fp->bufstart;
+
+ if (len)
+ {
+ /*
+ * The loop is so we don't get upset by signals
+ */
+ do
+ {
+ cc = write(fp->fd, fp->bufstart, len);
+ }
+ while (cc == -1 && errno == EINTR);
+ /*
+ * I think the following test is _too_ stringent, but it's not
+ * serious If it is found to be a problem then if cc>0 we can do
+ * a memcpy to put the buffer in a state for a retry. Or even do
+ * the retry ourselves.
+ */
+ if (cc != len)
+ {
+ fp->mode |= __MODE_ERR;
+ return EOF;
+ }
+ }
+ }
+ /* If there's data in the buffer sychronise the file positions */
+ else if (fp->mode & __MODE_READING)
+ {
+ /* Humm, I think this means sync the file like fpurge() ... */
+ /* Anyway the user isn't supposed to call this function when reading */
+
+ len = fp->bufread - fp->bufpos; /* Bytes buffered but unread */
+ /* If it's a file, make it good */
+ if (len > 0 && lseek(fp->fd, -len, 1) < 0)
+ {
+ /* Hummm - Not certain here, I don't think this is reported */
+ /*
+ * fp->mode |= __MODE_ERR; return EOF;
+ */
+ }
+ }
+
+ /* All done, no problem */
+ fp->mode &= (~(__MODE_READING|__MODE_WRITING|__MODE_EOF|__MODE_UNGOT));
+ fp->bufread = fp->bufwrite = fp->bufpos = fp->bufstart;
+ return 0;
+}
+#endif
+
+#ifdef L_fgets
+/* Nothing special here ... */
+char *
+fgets(s, count, f)
+char *s;
+size_t count;
+FILE *f;
+{
+ char *ret;
+ register size_t i;
+ register int ch;
+
+ ret = s;
+ for (i = count; i > 0; i--)
+ {
+ ch = getc(f);
+ if (ch == EOF)
+ {
+ if (s == ret)
+ return 0;
+ break;
+ }
+ *s++ = (char) ch;
+ if (ch == '\n')
+ break;
+ }
+ *s = 0;
+
+ if (ferror(f))
+ return 0;
+ return ret;
+}
+#endif
+
+#ifdef L_gets
+char *
+gets(str) /* BAD function; DON'T use it! */
+char *str;
+{
+ /* Auwlright it will work but of course _your_ program will crash */
+ /* if it's given a too long line */
+ register char *p = str;
+ register int c;
+
+ while (((c = getc(stdin)) != EOF) && (c != '\n'))
+ *p++ = c;
+ *p = '\0';
+ return (((c == EOF) && (p == str)) ? NULL : str); /* NULL == EOF */
+}
+#endif
+
+#ifdef L_fputs
+int
+fputs(str, fp)
+char *str;
+FILE *fp;
+{
+ register int n = 0;
+ while (*str)
+ {
+ if (putc(*str++, fp) == EOF)
+ return (EOF);
+ ++n;
+ }
+ return (n);
+}
+#endif
+
+#ifdef L_puts
+int
+puts(str)
+char *str;
+{
+ register int n;
+
+ if (((n = fputs(str, stdout)) == EOF)
+ || (putc('\n', stdout) == EOF))
+ return (EOF);
+ return (++n);
+}
+#endif
+
+#ifdef L_fread
+/*
+ * fread will often be used to read in large chunks of data calling read()
+ * directly can be a big win in this case. Beware also fgetc calls this
+ * function to fill the buffer.
+ *
+ * This ignores __MODE__IOTRAN; probably exactly what you want. (It _is_ what
+ * fgetc wants)
+ */
+int
+fread(buf, size, nelm, fp)
+char *buf;
+int size;
+int nelm;
+FILE *fp;
+{
+ int len, v;
+ unsigned bytes, got = 0;
+ Inline_init;
+
+ v = fp->mode;
+
+ /* Want to do this to bring the file pointer up to date */
+ if (v & __MODE_WRITING)
+ fflush(fp);
+
+ /* Can't read or there's been an EOF or error then return zero */
+ if ((v & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ)
+ return 0;
+
+ /* This could be long, doesn't seem much point tho */
+ bytes = size * nelm;
+
+ len = fp->bufread - fp->bufpos;
+ if (len >= bytes) /* Enough buffered */
+ {
+ memcpy(buf, fp->bufpos, (unsigned) bytes);
+ fp->bufpos += bytes;
+ return bytes;
+ }
+ else if (len > 0) /* Some buffered */
+ {
+ memcpy(buf, fp->bufpos, len);
+ got = len;
+ }
+
+ /* Need more; do it with a direct read */
+ len = read(fp->fd, buf + got, (unsigned) (bytes - got));
+
+ /* Possibly for now _or_ later */
+ if (len < 0)
+ {
+ fp->mode |= __MODE_ERR;
+ len = 0;
+ }
+ else if (len == 0)
+ fp->mode |= __MODE_EOF;
+
+ return (got + len) / size;
+}
+#endif
+
+#ifdef L_fwrite
+/*
+ * Like fread, fwrite will often be used to write out large chunks of
+ * data; calling write() directly can be a big win in this case.
+ *
+ * But first we check to see if there's space in the buffer.
+ *
+ * Again this ignores __MODE__IOTRAN.
+ */
+int
+fwrite(buf, size, nelm, fp)
+char *buf;
+int size;
+int nelm;
+FILE *fp;
+{
+ register int v;
+ int len;
+ unsigned bytes, put;
+
+ v = fp->mode;
+ /* If last op was a read ... */
+ if ((v & __MODE_READING) && fflush(fp))
+ return 0;
+
+ /* Can't write or there's been an EOF or error then return 0 */
+ if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE)
+ return 0;
+
+ /* This could be long, doesn't seem much point tho */
+ bytes = size * nelm;
+
+ len = fp->bufend - fp->bufpos;
+
+ /* Flush the buffer if not enough room */
+ if (bytes > len)
+ if (fflush(fp))
+ return 0;
+
+ len = fp->bufend - fp->bufpos;
+ if (bytes <= len) /* It'll fit in the buffer ? */
+ {
+ fp->mode |= __MODE_WRITING;
+ memcpy(fp->bufpos, buf, bytes);
+ fp->bufpos += bytes;
+
+ /* If we're not fully buffered */
+ if (v & (_IOLBF | _IONBF))
+ fflush(fp);
+
+ return nelm;
+ }
+ else
+ /* Too big for the buffer */
+ {
+ put = write(fp->fd, buf, bytes);
+ if (put < 0)
+ {
+ fp->mode |= __MODE_ERR;
+ put = 0;
+ }
+ }
+
+ return put / size;
+}
+#endif
+
+#ifdef L_rewind
+void
+rewind(fp)
+FILE * fp;
+{
+ fseek(fp, (long)0, 0);
+ clearerr(fp);
+}
+#endif
+
+#ifdef L_fseek
+int
+fseek(fp, offset, ref)
+FILE *fp;
+long offset;
+int ref;
+{
+ /* Use fflush to sync the pointers */
+ /*
+ * TODO: if __MODE_READING and no ungetc ever done can just move
+ * pointer
+ */
+
+ if (fflush(fp) == EOF)
+ return EOF;
+ if (lseek(fp->fd, offset, ref) < 0)
+ return EOF;
+ return 0;
+}
+#endif
+
+#ifdef L_ftell
+long ftell(fp)
+FILE * fp;
+{
+ long rv;
+ if (fflush(fp) == EOF)
+ return EOF;
+ return lseek(fp->fd, 0L, SEEK_CUR);
+}
+#endif
+
+#ifdef L_fopen
+/*
+ * This Fopen is all three of fopen, fdopen and freopen. The macros in
+ * stdio.h show the other names.
+ */
+FILE *
+__fopen(fname, fd, fp, mode)
+char *fname;
+int fd;
+FILE *fp;
+char *mode;
+{
+ int open_mode = 0;
+#ifdef __MSDOS__
+ int fopen_mode = __MODE_IOTRAN; /* default to 'text' file on DOS */
+#else
+ int fopen_mode = 0;
+#endif
+ int nfd = -1;
+ FILE *nfp = 0;
+
+ /* If we've got an fp close the old one (freopen) */
+ if (fp)
+ {
+ /* Careful, don't de-allocate it */
+ fopen_mode |= (fp->mode & (__MODE_BUF | __MODE_FREEFIL | __MODE_FREEBUF));
+ fp->mode &= ~(__MODE_FREEFIL | __MODE_FREEBUF);
+ fclose(fp);
+ }
+
+ /* decode the new open mode */
+ while (*mode)
+ switch (*mode++)
+ {
+ case 'r':
+ fopen_mode |= __MODE_READ;
+ break;
+ case 'w':
+ fopen_mode |= __MODE_WRITE;
+ open_mode = (O_CREAT | O_TRUNC);
+ break;
+ case 'a':
+ fopen_mode |= __MODE_WRITE;
+ open_mode = (O_CREAT | O_APPEND);
+ break;
+ case '+':
+ fopen_mode |= __MODE_RDWR;
+ break;
+#if __MODE_IOTRAN
+ case 'b': /* Binary */
+ fopen_mode &= ~__MODE_IOTRAN;
+ break;
+ case 't': /* Text */
+ fopen_mode |= __MODE_IOTRAN;
+ break;
+#endif
+ }
+
+ /* Add in the read/write options to mode for open() */
+ switch (fopen_mode & (__MODE_READ | __MODE_WRITE))
+ {
+ case 0:
+ return 0;
+ case __MODE_READ:
+ open_mode |= O_RDONLY;
+ break;
+ case __MODE_WRITE:
+ open_mode |= O_WRONLY;
+ break;
+ default:
+ open_mode |= O_RDWR;
+ break;
+ }
+
+ /* Allocate the (FILE) before we do anything irreversable */
+ if (fp == 0)
+ {
+ nfp = malloc(sizeof(FILE));
+ if (nfp == 0)
+ return 0;
+ }
+
+ /* Open the file itself */
+ if (fname)
+ nfd = fd = open(fname, open_mode, 0666);
+ if (fd < 0) /* Grrrr */
+ {
+ if (nfp)
+ free(nfp);
+ return 0;
+ }
+
+ /* If this isn't freopen create a (FILE) and buffer for it */
+ if (fp == 0)
+ {
+ fp = nfp;
+ fp->next = __IO_list;
+ __IO_list = fp;
+
+ fp->mode = __MODE_FREEFIL;
+ fp->bufstart = malloc(BUFSIZ);
+ if (fp->bufstart == 0) /* Oops, no mem */
+ { /* Humm, full buffering with a two(!) byte
+ * buffer. */
+ fp->bufstart = fp->unbuf;
+ fp->bufend = fp->unbuf + sizeof(fp->unbuf);
+ fp->mode |= _IOFBF;
+ }
+ else
+ {
+ fp->bufend = fp->bufstart + BUFSIZ;
+ fp->mode |= (__MODE_FREEBUF | _IOFBF);
+ }
+ }
+
+ /* Ok, file's ready clear the buffer and save important bits */
+ fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
+ fp->mode |= fopen_mode;
+ fp->fd = fd;
+
+ return fp;
+}
+#endif
+
+#ifdef L_fclose
+int
+fclose(fp)
+FILE *fp;
+{
+ int rv = 0;
+
+ if (fp == 0)
+ {
+ errno = EINVAL;
+ return EOF;
+ }
+ if (fflush(fp))
+ return EOF;
+
+ if (close(fp->fd))
+ rv = EOF;
+ fp->fd = -1;
+
+ if (fp->mode & __MODE_FREEBUF)
+ {
+ free(fp->bufstart);
+ fp->mode &= ~__MODE_FREEBUF;
+ fp->bufstart = fp->bufend = 0;
+ }
+
+ if (fp->mode & __MODE_FREEFIL)
+ {
+ FILE *prev = 0, *ptr;
+ fp->mode = 0;
+
+ for (ptr = __IO_list; ptr && ptr != fp; ptr = ptr->next)
+ ;
+ if (ptr == fp)
+ {
+ if (prev == 0)
+ __IO_list = fp->next;
+ else
+ prev->next = fp->next;
+ }
+ free(fp);
+ }
+ else
+ fp->mode = 0;
+
+ return rv;
+}
+#endif
+
+#ifdef L_setbuffer
+void
+setbuffer(fp, buf, size)
+FILE * fp;
+char * buf;
+int size;
+{
+ fflush(fp);
+ if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart);
+ fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF);
+
+ if( buf == 0 )
+ {
+ fp->bufstart = fp->unbuf;
+ fp->bufend = fp->unbuf + sizeof(fp->unbuf);
+ fp->mode |= _IONBF;
+ }
+ else
+ {
+ fp->bufstart = buf;
+ fp->bufend = buf+size;
+ fp->mode |= _IOFBF;
+ }
+ fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
+}
+#endif
+
+#ifdef L_ungetc
+int
+ungetc(c, fp)
+int c;
+FILE *fp;
+{
+ if (fp->mode & __MODE_WRITING)
+ fflush(fp);
+
+ /* Can't read or there's been an error then return EOF */
+ if ((fp->mode & (__MODE_READ | __MODE_ERR)) != __MODE_READ)
+ return EOF;
+
+ if( fp->bufpos > fp->bufstart )
+ return *--fp->bufpos = (unsigned char) c;
+ else if( fp->bufread == fp->bufstart )
+ return *fp->bufread++ = (unsigned char) c;
+ else
+ return EOF;
+}
+#endif
+
diff --git a/libc-0.0.4/stdio2/stdio.h b/libc-0.0.4/stdio2/stdio.h
new file mode 100644
index 0000000..ba70b1d
--- /dev/null
+++ b/libc-0.0.4/stdio2/stdio.h
@@ -0,0 +1,125 @@
+
+#ifndef __STDIO_H
+#define __STDIO_H
+
+#include <features.h>
+#include <sys/types.h>
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#define _IOFBF 0x00 /* full buffering */
+#define _IOLBF 0x01 /* line buffering */
+#define _IONBF 0x02 /* no buffering */
+#define __MODE_BUF 0x03 /* Modal buffering dependent on isatty */
+
+#define __MODE_FREEBUF 0x04 /* Buffer allocated with malloc, can free */
+#define __MODE_FREEFIL 0x08 /* FILE allocated with malloc, can free */
+
+#define __MODE_READ 0x10 /* Opened in read only */
+#define __MODE_WRITE 0x20 /* Opened in write only */
+#define __MODE_RDWR 0x30 /* Opened in read/write */
+
+#define __MODE_READING 0x40 /* Buffer has pending read data */
+#define __MODE_WRITING 0x80 /* Buffer has pending write data */
+
+#define __MODE_EOF 0x100 /* EOF status */
+#define __MODE_ERR 0x200 /* Error status */
+#define __MODE_UNGOT 0x400 /* Buffer has been polluted by ungetc */
+
+#ifdef __MSDOS__
+#define __MODE_IOTRAN 0x1000 /* MSDOS nl <-> cr,nl translation */
+#else
+#define __MODE_IOTRAN 0
+#endif
+
+/* when you add or change fields here, be sure to change the initialization
+ * in stdio_init and fopen */
+struct __stdio_file {
+ unsigned char *bufpos; /* the next byte to write to or read from */
+ unsigned char *bufread; /* the end of data returned by last read() */
+ unsigned char *bufwrite; /* highest address writable by macro */
+ unsigned char *bufstart; /* the start of the buffer */
+ unsigned char *bufend; /* the end of the buffer; ie the byte after the last
+ malloc()ed byte */
+
+ int fd; /* the file descriptor associated with the stream */
+ int mode;
+
+ char unbuf[8]; /* The buffer for 'unbuffered' streams */
+
+ struct __stdio_file * next;
+};
+
+#define EOF (-1)
+#ifndef NULL
+#define NULL (0)
+#endif
+
+typedef struct __stdio_file FILE;
+
+#define BUFSIZ (256)
+
+extern FILE stdin[1];
+extern FILE stdout[1];
+extern FILE stderr[1];
+
+#ifdef __MSDOS__
+#define putc(c, fp) fputc(c, fp)
+#define getc(fp) fgetc(fp)
+#else
+#define putc(c, stream) \
+ (((stream)->bufpos >= (stream)->bufwrite) ? fputc((c), (stream)) \
+ : (unsigned char) (*(stream)->bufpos++ = (c)) )
+
+#define getc(stream) \
+ (((stream)->bufpos >= (stream)->bufread) ? fgetc(stream): \
+ (*(stream)->bufpos++))
+#endif
+
+#define putchar(c) putc((c), stdout)
+#define getchar() getc(stdin)
+
+#define ferror(fp) (((fp)->mode&__MODE_ERR) != 0)
+#define feof(fp) (((fp)->mode&__MODE_EOF) != 0)
+#define clearerr(fp) ((fp)->mode &= ~(__MODE_EOF|__MODE_ERR),0)
+#define fileno(fp) ((fp)->fd)
+
+/* declare functions; not like it makes much difference without ANSI */
+/* RDB: The return values _are_ important, especially if we ever use
+ 8086 'large' model
+ */
+
+/* These two call malloc */
+#define setlinebuf(__fp) setvbuf((__fp), (char*)0, _IOLBF, 0)
+extern int setvbuf __P((FILE*, char*, int, size_t));
+
+/* These don't */
+#define setbuf(__fp, __buf) setbuffer((__fp), (__buf), BUFSIZ)
+extern void setbuffer __P((FILE*, char*, int));
+
+extern int fgetc __P((FILE*));
+extern int fputc __P((int, FILE*));
+
+extern int fclose __P((FILE*));
+extern int fflush __P((FILE*));
+extern char *fgets __P((char*, size_t, FILE*));
+extern FILE *__fopen __P((char*, int, FILE*, char*));
+
+#define fopen(__file, __mode) __fopen((__file), -1, (FILE*)0, (__mode))
+#define freopen(__file, __mode, __fp) __fopen((__file), -1, (__fp), (__mode))
+#define fdopen(__file, __mode) __fopen((char*)0, (__file), (FILE*)0, (__mode))
+
+extern int fputs __P((char*, FILE*));
+extern int puts __P((char*));
+
+extern int printf __P ((__const char*, ...));
+extern int fprintf __P ((FILE*, __const char*, ...));
+extern int sprintf __P ((char*, __const char*, ...));
+
+#define stdio_pending(fp) ((fp)->bufread>(fp)->bufpos)
+
+#endif /* __STDIO_H */
diff --git a/libc-0.0.4/string/Config b/libc-0.0.4/string/Config
new file mode 100644
index 0000000..b712dcf
--- /dev/null
+++ b/libc-0.0.4/string/Config
@@ -0,0 +1 @@
+string: String and memory manipulation
diff --git a/libc-0.0.4/string/Makefile b/libc-0.0.4/string/Makefile
new file mode 100644
index 0000000..d9c1f46
--- /dev/null
+++ b/libc-0.0.4/string/Makefile
@@ -0,0 +1,31 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+SSRC=string.c
+SOBJ=strlen.o strcat.o strcpy.o strcmp.o strncat.o strncpy.o strncmp.o \
+ strchr.o strrchr.o strdup.o memcpy.o memccpy.o memchr.o memset.o \
+ memcmp.o memmove.o movedata.o
+
+OBJ=$(SOBJ) strpbrk.o strsep.o strstr.o strtok.o strcspn.o \
+ strspn.o strcasecmp.o strncasecmp.o
+
+all: $(OBJ)
+
+$(LIBC): $(OBJ)
+ ar r ../$(LIBC) $(OBJ)
+ @touch libc.a
+
+transfer:
+ -@rm -f ../include/string.h
+ cp -p string.h ../include/.
+
+clean:
+ rm -f $(OBJ) libc.a
+
+$(SOBJ): $(SSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(SSRC)
+
diff --git a/libc-0.0.4/string/strcasecmp.c b/libc-0.0.4/string/strcasecmp.c
new file mode 100644
index 0000000..0e7b038
--- /dev/null
+++ b/libc-0.0.4/string/strcasecmp.c
@@ -0,0 +1,26 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <string.h>
+#include <ctype.h>
+
+int
+strcasecmp(s, d)
+char *s;
+char *d;
+{
+ for(;;)
+ {
+ if( *s != *d )
+ {
+ if( tolower(*s) != tolower(*d) )
+ return *s - *d;
+ }
+ else if( *s == '\0' ) break;
+ s++; d++;
+ }
+ return 0;
+}
+
diff --git a/libc-0.0.4/string/strcspn.c b/libc-0.0.4/string/strcspn.c
new file mode 100644
index 0000000..619c8be
--- /dev/null
+++ b/libc-0.0.4/string/strcspn.c
@@ -0,0 +1,32 @@
+/* strcspn.c */
+
+/* from Schumacher's Atari library, improved */
+
+#include <string.h>
+
+size_t strcspn(string, set)
+register char *string;
+char *set;
+/*
+ * Return the length of the sub-string of <string> that consists
+ * entirely of characters not found in <set>. The terminating '\0'
+ * in <set> is not considered part of the match set. If the first
+ * character if <string> is in <set>, 0 is returned.
+ */
+{
+ register char *setptr;
+ char *start;
+
+ start = string;
+ while (*string)
+ {
+ setptr = set;
+ do
+ if (*setptr == *string)
+ goto break2;
+ while (*setptr++);
+ ++string;
+ }
+break2:
+ return string - start;
+}
diff --git a/libc-0.0.4/string/string.c b/libc-0.0.4/string/string.c
new file mode 100644
index 0000000..fad6690
--- /dev/null
+++ b/libc-0.0.4/string/string.c
@@ -0,0 +1,667 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <string.h>
+#include <malloc.h>
+
+#ifdef __AS386_16__
+#if __FIRST_ARG_IN_AX__
+#define BCC_AX_ASM /* BCC Assembler that can cope with arg in AX */
+#else
+#define BCC_AX_ASM
+#define BCC_ASM /* Use 16 bit BCC assembler */
+#endif
+
+#define PARANOID /* Include extra code for cld and ES register */
+#endif
+
+/* This is a basic string package; it includes the most used functions
+
+ strlen strcat strcpy strcmp strncat strncpy strncmp strchr strrchr strdup
+ memcpy memccpy memchr memset memcmp memmove
+
+ These functions are in seperate files.
+ strpbrk.o strsep.o strstr.o strtok.o strcspn.o
+ strspn.o strcasecmp.o strncasecmp.o
+ */
+
+/********************** Function strlen ************************************/
+
+#ifdef L_strlen
+size_t strlen(str)
+const char * str;
+{
+#ifdef BCC_AX_ASM
+#asm
+#if !__FIRST_ARG_IN_AX__
+ mov bx,sp
+#endif
+ push di
+
+#ifdef PARANOID
+ push es
+ push ds ; Im not sure if this is needed, so just in case.
+ pop es
+ cld
+#endif ! This is almost the same as memchr, but it can
+ ! stay as a special.
+
+#if __FIRST_ARG_IN_AX__
+ mov di,ax
+#else
+ mov di,[bx+2]
+#endif
+ mov cx,#-1
+ xor ax,ax
+ repne
+ scasb
+ not cx
+ dec cx
+ mov ax,cx
+
+#ifdef PARANOID
+ pop es
+#endif
+ pop di
+#endasm
+#else
+ register char * p =(char *) str;
+ while(*p) p++;
+ return p-str;
+#endif /* ifdef BCC_AX_ASM */
+}
+#endif
+
+/********************** Function strcat ************************************/
+
+#ifdef L_strcat
+char * strcat(d, s)
+char *d;
+const char * s;
+{
+ (void) strcpy(d+strlen(d), s);
+ return d;
+}
+#endif
+
+/********************** Function strcpy ************************************/
+
+#ifdef L_strcpy
+char * strcpy(d, s)
+char *d;
+const char * s;
+{
+ /* This is probably the quickest on an 8086 but a CPU with a cache will
+ * prefer to do this in one pass */
+ return memcpy(d, s, strlen(s)+1);
+}
+#endif
+
+/********************** Function strcmp ************************************/
+
+#ifdef L_strcmp
+int strcmp(d, s)
+const char *d;
+const char * s;
+{
+ /* There are a number of ways to do this and it really does depend on the
+ types of strings given as to which is better, nevertheless the Glib
+ method is quite reasonable so we'll take that */
+
+#ifdef BCC_AX_ASM
+#asm
+ mov bx,sp
+ push di
+ push si
+
+#ifdef PARANOID
+ push es
+ push ds ; Im not sure if this is needed, so just in case.
+ pop es
+#endif
+
+#if __FIRST_ARG_IN_AX__
+ mov di,ax ; dest
+ mov si,[bx+2] ; source
+#else
+ mov di,[bx+2] ; dest
+ mov si,[bx+4] ; source
+#endif
+sc_1:
+ lodsb
+ scasb
+ jne sc_2 ; If bytes are diff skip out.
+ testb al,al
+ jne sc_1 ; If this byte in str1 is nul the strings are equal
+ xor ax,ax ; so return zero
+ jmp sc_3
+sc_2:
+ sbb ax,ax ; Collect correct val (-1,1).
+ orb al,#1
+sc_3:
+
+#ifdef PARANOID
+ pop es
+#endif
+ pop si
+ pop di
+#endasm
+#else /* ifdef BCC_AX_ASM */
+ register char *s1=(char *)d, *s2=(char *)s, c1,c2;
+ while((c1= *s1++) == (c2= *s2++) && c1 );
+ return c1 - c2;
+#endif /* ifdef BCC_AX_ASM */
+}
+#endif
+
+/********************** Function strncat ************************************/
+
+#ifdef L_strncat
+char * strncat(d, s, l)
+char *d, *s;
+size_t l;
+{
+ register char *s1=d+strlen(d), *s2;
+
+ s2 = memchr(s, l, 0);
+ if( s2 )
+ memcpy(s1, s, s2-s+1);
+ else
+ {
+ memcpy(s1, s, l);
+ s1[l] = '\0';
+ }
+ return d;
+}
+#endif
+
+/********************** Function strncpy ************************************/
+
+#ifdef L_strncpy
+char * strncpy(d, s, l) /* FIXME need the fast version of this */
+char *d, *s;
+size_t l;
+{
+ register char *s1=d, *s2=s;
+ while(l > 0)
+ {
+ l--;
+ if( (*s1++ = *s2++) == '\0')
+ break;
+ }
+
+ /* This _is_ correct strncpy is supposed to zap */
+ for(; l>0; l--) *s1++ = '\0';
+ return d;
+}
+#endif
+
+/********************** Function strncmp ************************************/
+
+#ifdef L_strncmp
+int strncmp(d, s, l)
+const char *d, *s;
+size_t l;
+{
+#ifdef BCC_AX_ASM
+#asm
+ mov bx,sp
+ push si
+ push di
+
+#ifdef PARANOID
+ push es
+ push ds ! Im not sure if this is needed, so just in case.
+ pop es
+ cld
+#endif
+
+#if __FIRST_ARG_IN_AX__
+ mov si,ax
+ mov di,[bx+2]
+ mov cx,[bx+4]
+#else
+ mov si,[bx+2] ! Fetch
+ mov di,[bx+4]
+ mov cx,[bx+6]
+#endif
+
+ inc cx
+lp1:
+ dec cx
+ je lp2
+ lodsb
+ scasb
+ jne lp3
+ testb al,al
+ jne lp1
+lp2:
+ xor ax,ax
+ jmp lp4
+lp3:
+ sbb ax,ax
+ or al,#1
+lp4:
+
+#ifdef PARANOID
+ pop es
+#endif
+ pop di
+ pop si
+#endasm
+#else
+ register char c1=0, c2=0;
+ while(l-- >0)
+ if( (c1= *d++) != (c2= *s++) || c1 == '\0' )
+ break;
+ return c1-c2;
+#endif
+}
+#endif
+
+/********************** Function strchr ************************************/
+
+#ifdef L_strchr
+char *
+strchr(s, c)
+char * s;
+int c;
+{
+#ifdef BCC_AX_ASM
+#asm
+ mov bx,sp
+ push si
+#if __FIRST_ARG_IN_AX__
+ mov bx,[bx+2]
+ mov si,ax
+#else
+ mov si,[bx+2]
+ mov bx,[bx+4]
+#endif
+ xor ax,ax
+
+#ifdef PARANOID
+ cld
+#endif
+
+in_loop:
+ lodsb
+ cmp al,bl
+ jz got_it
+ or al,al
+ jnz in_loop
+ pop si
+ ret
+got_it:
+ lea ax,[si-1]
+ pop si
+
+#endasm
+#else /* ifdef BCC_AX_ASM */
+ register char ch;
+ for(;;)
+ {
+ if( (ch= *s) == c ) return s;
+ if( ch == 0 ) return 0;
+ s++;
+ }
+#endif /* ifdef BCC_AX_ASM */
+}
+#endif
+
+/********************** Function strrchr ************************************/
+
+#ifdef L_strrchr
+char * strrchr(s, c)
+char * s;
+int c;
+{
+ register char * prev = 0;
+ register char * p = s;
+ /* For null it's just like strlen */
+ if( c == '\0' ) return p+strlen(p);
+
+ /* everything else just step along the string. */
+ while( (p=strchr(p, c)) != 0 )
+ {
+ prev = p; p++;
+ }
+ return prev;
+}
+#endif
+
+/********************** Function strdup ************************************/
+
+#ifdef L_strdup
+char * strdup(s)
+char * s;
+{
+ register size_t len;
+ register char * p;
+
+ len = strlen(s)+1;
+ p = (char *) malloc(s);
+ if(p) memcpy(p, s, len); /* Faster than strcpy */
+ return p;
+}
+#endif
+
+/********************** Function memcpy ************************************/
+
+#ifdef L_memcpy
+void *
+memcpy(d, s, l)
+void *d;
+const void *s;
+size_t l;
+{
+#ifdef BCC_AX_ASM
+#asm
+ mov bx,sp
+ push di
+ push si
+
+#ifdef PARANOID
+ push es
+ push ds ; Im not sure if this is needed, so just in case.
+ pop es
+#endif
+
+#if __FIRST_ARG_IN_AX__
+ mov di,ax ; dest
+ mov si,[bx+2] ; source
+ mov cx,[bx+4] ; count
+#else
+ mov di,[bx+2] ; dest
+ mov si,[bx+4] ; source
+ mov cx,[bx+6] ; count
+
+ mov ax,di
+#endif
+ ; If di is odd mov 1 byte before doing word move
+ ; this will speed slightly but
+ ; NB 8086 has no problem with mis-aligned access.
+
+ shr cx,#1 ; Do this faster by doing a mov word
+ rep
+ movsw
+ adc cx,cx ; Retrieve the leftover 1 bit from cflag.
+ rep
+ movsb
+
+#ifdef PARANOID
+ pop es
+#endif
+ pop si
+ pop di
+#endasm
+#else /* ifdef BCC_AX_ASM */
+ register char *s1=d, *s2=(char *)s;
+ for( ; l>0; l--) *((unsigned char*)s1++) = *((unsigned char*)s2++);
+ return d;
+#endif /* ifdef BCC_AX_ASM */
+}
+#endif
+
+/********************** Function memccpy ************************************/
+
+#ifdef L_memccpy
+void * memccpy(d, s, c, l) /* Do we need a fast one ? */
+void *s, *d;
+int c;
+size_t l;
+{
+ register char *s1=d, *s2=s;
+ while(l-- > 0)
+ if((*s1++ = *s2++) == c )
+ return s1;
+ return 0;
+}
+#endif
+
+/********************** Function memchr ************************************/
+
+#ifdef L_memchr
+void * memchr(str, c, l)
+const void * str;
+int c;
+size_t l;
+{
+#ifdef BCC_ASM
+#asm
+ mov bx,sp
+ push di
+
+#ifdef PARANOID
+ push es
+ push ds ; Im not sure if this is needed, so just in case.
+ pop es
+ cld
+#endif
+
+ mov di,[bx+2]
+ mov ax,[bx+4]
+ mov cx,[bx+6]
+ test cx,cx
+ je is_z ! Zero length, do not find.
+
+ repne ! Scan
+ scasb
+ jne is_z ! Not found, ret zero
+ dec di ! Adjust ptr
+ mov ax,di ! return
+ jmp xit
+is_z:
+ xor ax,ax
+xit:
+
+#ifdef PARANOID
+ pop es
+#endif
+ pop di
+#endasm
+#else /* ifdef BCC_ASM */
+ register char *p=(char *)str;
+ while(l-- > 0)
+ {
+ if(*p == c) return p;
+ p++;
+ }
+ return 0;
+#endif /* ifdef BCC_ASM */
+}
+#endif
+
+/********************** Function memset ************************************/
+
+#ifdef L_memset
+void * memset(str, c, l)
+void * str;
+int c;
+size_t l;
+{
+#ifdef BCC_AX_ASM
+#asm
+ mov bx,sp
+ push di
+
+#ifdef PARANOID
+ push es
+ push ds ; Im not sure if this is needed, so just in case.
+ pop es
+ cld
+#endif
+
+#if __FIRST_ARG_IN_AX__
+ mov di,ax ; Fetch
+ mov ax,[bx+2]
+ mov cx,[bx+4]
+#else
+ mov di,[bx+2] ; Fetch
+ mov ax,[bx+4]
+ mov cx,[bx+6]
+#endif
+
+; How much difference does this alignment make ?
+; I don`t think it`s significant cause most will already be aligned.
+
+; test cx,cx ; Zero size - skip
+; je xit
+;
+; test di,#1 ; Line it up
+; je s_1
+; stosb
+; dec cx
+;s_1:
+
+ mov ah,al ; Replicate byte
+ shr cx,#1 ; Do this faster by doing a sto word
+ rep ; Bzzzzz ...
+ stosw
+ adc cx,cx ; Retrieve the leftover 1 bit from cflag.
+
+ rep ; ... z
+ stosb
+
+xit:
+ mov ax,[bx+2]
+#ifdef PARANOID
+ pop es
+#endif
+ pop di
+#endasm
+#else /* ifdef BCC_AX_ASM */
+ register char *s1=str;
+ while(l-->0) *s1++ = c;
+ return str;
+#endif /* ifdef BCC_AX_ASM */
+}
+#endif
+
+/********************** Function memcmp ************************************/
+
+#ifdef L_memcmp
+int memcmp(s, d, l)
+const void *s, *d;
+size_t l;
+{
+#ifdef BCC_ASM
+#asm
+ mov bx,sp
+ push di
+ push si
+
+#ifdef PARANOID
+ push es
+ push ds ! Im not sure if this is needed, so just in case.
+ pop es
+ cld
+#endif
+
+ mov si,[bx+2] ! Fetch
+ mov di,[bx+4]
+ mov cx,[bx+6]
+ xor ax,ax
+
+ rep ! Bzzzzz
+ cmpsb
+ je xit ! All the same!
+ sbb ax,ax
+ sbb ax,#-1 ! choose +/-1
+xit:
+#ifdef PARANOID
+ pop es
+#endif
+ pop si
+ pop di
+#endasm
+#else /* ifdef BCC_ASM */
+ register const char *s1=d, *s2=s;
+ register char c1=0, c2=0;
+ while(l-- > 0)
+ if( (c1= *s1++) != (c2= *s2++) )
+ break;
+ return c1-c2;
+#endif /* ifdef BCC_ASM */
+}
+#endif
+
+/********************** Function memmove ************************************/
+
+#ifdef L_memmove
+void *
+memmove(d, s, l)
+void *d, *s;
+size_t l;
+{
+ register char *s1=d, *s2=s;
+ /* This bit of sneakyness c/o Glibc, it assumes the test is unsigned */
+ if( s1-s2 >= l ) return memcpy(d,s,l);
+
+ /* This reverse copy only used if we absolutly have to */
+ s1+=l; s2+=l;
+ while(l-- >0)
+ *(--s1) = *(--s2);
+ return d;
+}
+#endif
+
+/********************** Function movedata ***********************************/
+
+#ifdef L_movedata
+
+/* NB There isn't any C version of this function ... */
+
+#ifdef BCC_AX_ASM
+void
+__movedata(srcseg, srcoff, destseg, destoff, len)
+unsigned int srcseg, srcoff, destseg, destoff, len;
+{
+#asm
+ push bp
+ mov bp,sp
+ push si
+ push di
+ push ds
+#ifdef PARANOID
+ push es
+ cld
+#endif
+
+ ! sei ! Are we _really_ paranoid ?
+
+#if !__FIRST_ARG_IN_AX__
+ mov ds,[bp+4] ! Careful, [bp+xx] is SS based.
+ mov si,[bp+6]
+ mov es,[bp+8]
+ mov di,[bp+10]
+ mov cx,[bp+12]
+#else
+ mov ds,ax
+ mov si,[bp+4]
+ mov es,[bp+6]
+ mov di,[bp+8]
+ mov cx,[bp+10]
+#endif
+ rep
+ movsb
+
+ ! cli ! Are we _really_ paranoid ?
+
+#ifdef PARANOID
+ pop es
+#endif
+ pop ds
+ pop di
+ pop si
+ pop bp
+#endasm
+}
+#endif
+
+#endif
+
+/********************** THE END ********************************************/
+
diff --git a/libc-0.0.4/string/string.h b/libc-0.0.4/string/string.h
new file mode 100644
index 0000000..8be8eff
--- /dev/null
+++ b/libc-0.0.4/string/string.h
@@ -0,0 +1,52 @@
+
+#ifndef __STRING_H
+#define __STRING_H
+#include <features.h>
+#include <stddef.h>
+
+/* Basic string functions */
+extern size_t strlen __P ((__const char* __str));
+
+extern char * strcat __P ((char*, __const char*));
+extern char * strcpy __P ((char*, __const char*));
+extern int strcmp __P ((__const char*, __const char*));
+
+extern char * strncat __P ((char*, char*, size_t));
+extern char * strncpy __P ((char*, char*, size_t));
+extern int strncmp __P ((__const char*, __const char*, size_t));
+
+extern char * strchr __P ((char*, int));
+extern char * strrchr __P ((char*, int));
+extern char * strdup __P ((char*));
+
+/* Basic mem functions */
+extern void * memcpy __P ((void*, __const void*, size_t));
+extern void * memccpy __P ((void*, void*, int, size_t));
+extern void * memchr __P ((__const void*, __const int, size_t));
+extern void * memset __P ((void*, int, size_t));
+extern int memcmp __P ((__const void*, __const void*, size_t));
+
+extern void * memmove __P ((void*, void*, size_t));
+
+/* Minimal (very!) locale support */
+#define strcoll strcmp
+#define strxfrm strncpy
+
+/* BSDisms */
+#define index strchr
+#define rindex strrchr
+
+/* Other common BSD functions */
+extern int strcasecmp __P ((char*, char*));
+extern int strncasecmp __P ((char*, char*, size_t));
+char *strpbrk __P ((char *, char *));
+char *strsep __P ((char **, char *));
+char *strstr __P ((char *, char *));
+char *strtok __P ((char *, char *));
+size_t strcspn __P ((char *, char *));
+size_t strspn __P ((char *, char *));
+
+/* Linux silly hour */
+char *strfry __P ((char *));
+
+#endif
diff --git a/libc-0.0.4/string/strncasecmp.c b/libc-0.0.4/string/strncasecmp.c
new file mode 100644
index 0000000..561f72a
--- /dev/null
+++ b/libc-0.0.4/string/strncasecmp.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <string.h>
+#include <ctype.h>
+
+int
+strncasecmp(s, d, l)
+char *s;
+char *d;
+size_t l;
+{
+ while(l>0)
+ {
+ if( *s != *d )
+ {
+ if( tolower(*s) != tolower(*d) )
+ return *s - *d;
+ }
+ else
+ if( *s == '\0' ) return 0;
+ s++; d++; l--;
+ }
+ return 0;
+}
+
diff --git a/libc-0.0.4/string/strpbrk.c b/libc-0.0.4/string/strpbrk.c
new file mode 100644
index 0000000..3fc27ec
--- /dev/null
+++ b/libc-0.0.4/string/strpbrk.c
@@ -0,0 +1,21 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <string.h>
+
+/* This uses strchr, strchr should be in assembler */
+
+char *strpbrk(str, set)
+register char *str;
+char *set;
+{
+ while (*str != '\0')
+ if (strchr(set, *str) == 0)
+ ++str;
+ else
+ return (char *) str;
+
+ return 0;
+}
diff --git a/libc-0.0.4/string/strsep.c b/libc-0.0.4/string/strsep.c
new file mode 100644
index 0000000..21aa1bb
--- /dev/null
+++ b/libc-0.0.4/string/strsep.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <string.h>
+
+char *
+strsep(pp, delim)
+char **pp;
+char *delim;
+{
+ char *p, *q;
+
+ if (!(p = *pp))
+ return 0;
+ if (q = strpbrk (p, delim))
+ {
+ *pp = q + 1;
+ *q = '\0';
+ }
+ else
+ *pp = 0;
+ return p;
+}
diff --git a/libc-0.0.4/string/strspn.c b/libc-0.0.4/string/strspn.c
new file mode 100644
index 0000000..2094caa
--- /dev/null
+++ b/libc-0.0.4/string/strspn.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <string.h>
+
+/* Return the length of the maximum initial segment
+ of S which contains only characters in ACCEPT. */
+size_t
+strspn(s, accept)
+char *s;
+char *accept;
+{
+ register char *p;
+ register char *a;
+ register size_t count = 0;
+
+ for (p = s; *p != '\0'; ++p)
+ {
+ for (a = accept; *a != '\0'; ++a)
+ if (*p == *a)
+ break;
+ if (*a == '\0')
+ return count;
+ else
+ ++count;
+ }
+
+ return count;
+}
diff --git a/libc-0.0.4/string/strstr.c b/libc-0.0.4/string/strstr.c
new file mode 100644
index 0000000..aafcaf9
--- /dev/null
+++ b/libc-0.0.4/string/strstr.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <string.h>
+
+#if 1
+/* We've now got a nice fast strchr and memcmp use them */
+
+char *
+strstr(s1, s2)
+char *s1; char *s2;
+{
+ register int l = strlen(s2);
+ register char * p = s1;
+
+ if( l==0 ) return p;
+
+ while (p = strchr(p, *s2))
+ {
+ if( memcmp(p, s2, l) == 0 )
+ return p;
+ p++;
+ }
+ return (char *) 0;
+}
+
+#else
+/* This is a nice simple self contained strstr,
+ now go and work out why the GNU one is faster :-) */
+
+char *strstr(str1, str2)
+char *str1, *str2;
+{
+ register char *Sptr, *Tptr;
+ int len = strlen(str1) -strlen(str2) + 1;
+
+ if (*str2)
+ for (; len > 0; len--, str1++){
+ if (*str1 != *str2)
+ continue;
+
+ for (Sptr = str1, Tptr = str2; *Tptr != '\0'; Sptr++, Tptr++)
+ if (*Sptr != *Tptr)
+ break;
+
+ if (*Tptr == '\0')
+ return (char*) str1;
+ }
+
+ return (char*)0;
+}
+#endif
diff --git a/libc-0.0.4/string/strtok.c b/libc-0.0.4/string/strtok.c
new file mode 100644
index 0000000..27d8f25
--- /dev/null
+++ b/libc-0.0.4/string/strtok.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <string.h>
+
+
+static char *olds = 0;
+
+/* Parse S into tokens separated by characters in DELIM.
+ If S is NULL, the last string strtok() was called with is
+ used. For example:
+ char s[] = "-abc=-def";
+ x = strtok(s, "-"); // x = "abc"
+ x = strtok(NULL, "=-"); // x = "def"
+ x = strtok(NULL, "="); // x = NULL
+ // s = "abc\0-def\0"
+*/
+char *
+strtok(s, delim)
+register char *s;
+register char *delim;
+{
+ char *token;
+
+ if (s == 0)
+ {
+ if (olds == 0)
+ {
+ return 0;
+ }
+ else
+ s = olds;
+ }
+
+ /* Scan leading delimiters. */
+ s += strspn(s, delim);
+ if (*s == '\0')
+ {
+ olds = 0;
+ return 0;
+ }
+
+ /* Find the end of the token. */
+ token = s;
+ s = strpbrk(token, delim);
+ if (s == 0)
+ /* This token finishes the string. */
+ olds = 0;
+ else
+ {
+ /* Terminate the token and make OLDS point past it. */
+ *s = '\0';
+ olds = s + 1;
+ }
+ return token;
+}
diff --git a/libc-0.0.4/syscall/Config b/libc-0.0.4/syscall/Config
new file mode 100644
index 0000000..472e74b
--- /dev/null
+++ b/libc-0.0.4/syscall/Config
@@ -0,0 +1 @@
+syscall: Linux-8086 system call routines
diff --git a/libc-0.0.4/syscall/Makefile b/libc-0.0.4/syscall/Makefile
new file mode 100644
index 0000000..6a2b9bb
--- /dev/null
+++ b/libc-0.0.4/syscall/Makefile
@@ -0,0 +1,45 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+LSRC=syslibc.c
+LOBJ=__cstartup.o time.o lseek.o getpid.o getppid.o \
+ getuid.o geteuid.o getgid.o getegid.o \
+ dup2.o dup.o abort.o wait.o waitpid.o sleep.o
+
+ESRC=execve.c
+EOBJ=execve.o execl.o execv.o execle.o
+
+DSRC=dirent.c
+DOBJ=opendir.o closedir.o readdir.o
+
+OBJ=$(LOBJ) $(DOBJ) $(EOBJ) signal.o setjmp.o execve.o
+
+all: mksyscall syscall.dat $(OBJ)
+ sh mksyscall
+
+clean:
+ sh mksyscall clean
+ rm -f libc.a syscall.c syscall.mak call_tab.v defn_tab.v $(OBJ)
+
+libdos.a: setjmp.o
+ ar r ../libc.a setjmp.o
+ @touch libc.a
+
+libc.a: mksyscall syscall.dat $(OBJ)
+ sh mksyscall libc.a
+ ar r ../libc.a $(OBJ)
+ @touch libc.a
+
+$(LOBJ): $(LSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(LSRC)
+
+$(DOBJ): $(DSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(DSRC)
+
+$(EOBJ): $(ESRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(ESRC)
+
diff --git a/libc-0.0.4/syscall/TODO b/libc-0.0.4/syscall/TODO
new file mode 100644
index 0000000..90085d9
--- /dev/null
+++ b/libc-0.0.4/syscall/TODO
@@ -0,0 +1,7 @@
+It appears that a 386 version of the syscall libs is also wanted ...
+
+SYSV IPC, there's and __ipc syscall and the hardware can manage messages and
+semaphores.
+
+Idea, for RPC syscall, seperate all the FD related calls from the system ones
+IIRC all the single FD related ones have the FD in arg0
diff --git a/libc-0.0.4/syscall/dirent.c b/libc-0.0.4/syscall/dirent.c
new file mode 100644
index 0000000..c484956
--- /dev/null
+++ b/libc-0.0.4/syscall/dirent.c
@@ -0,0 +1,84 @@
+
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <malloc.h>
+
+#ifdef L_opendir
+DIR *
+opendir(dname)
+char *dname;
+{
+ struct stat st;
+ int fd;
+ DIR *p;
+
+ if (stat(dname, &st) < 0)
+ return 0;
+
+ if (!S_ISDIR(st.st_mode))
+ {
+ errno = ENOTDIR;
+ return 0;
+ }
+ if ((fd = open(dname, O_RDONLY)) < 0)
+ return 0;
+
+ p = malloc(sizeof(DIR));
+ if (p == 0)
+ {
+ close(fd);
+ return 0;
+ }
+
+ p->dd_buf = malloc(sizeof(struct dirent));
+ if (p->dd_buf == 0)
+ {
+ free(p);
+ close(fd);
+ return 0;
+ }
+ p->dd_fd = fd;
+ p->dd_loc = p->dd_size = 0;
+
+ return p;
+}
+#endif
+
+#ifdef L_closedir
+int
+closedir(dirp)
+DIR *dirp;
+{
+ int fd;
+ fd = dirp->dd_fd;
+ free(dirp->dd_buf);
+ free(dirp);
+ return close(fd);
+}
+#endif
+
+#ifdef L_readdir
+/*
+ * This currently assumes we see a v. simple diectory structure, it's
+ * probably faked!
+ */
+struct dirent *
+readdir(dirp)
+DIR *dirp;
+{
+ int cc;
+ cc = read(dirp->dd_fd, dirp->dd_buf, sizeof(struct dirent));
+
+ if (cc <= 0)
+ return 0;
+ if (cc != sizeof(struct dirent))
+ {
+ errno = EBADF;
+ return 0;
+ }
+ return dirp->dd_buf;
+}
+#endif
diff --git a/libc-0.0.4/syscall/execve.c b/libc-0.0.4/syscall/execve.c
new file mode 100644
index 0000000..aee7182
--- /dev/null
+++ b/libc-0.0.4/syscall/execve.c
@@ -0,0 +1,114 @@
+
+#include <errno.h>
+
+extern char ** environ;
+
+#ifdef L_execl
+int
+execl(fname, arg0)
+char * fname, *arg0;
+{
+ return execve(fname, &arg0, environ);
+}
+#endif
+
+#ifdef L_execv
+int
+execv(fname, argv)
+char * fname, **argv;
+{
+ return execve(fname, argv, environ);
+}
+#endif
+
+#ifdef L_execle
+int
+execle(fname, arg0)
+char *fname, *arg0;
+{
+ char ** envp = &arg0;
+ while(*envp) envp++;
+ return execve(fname, &arg0, envp+1);
+}
+#endif
+
+#ifdef L_execve
+int
+execve(fname, argv, envp)
+char * fname;
+char ** argv;
+char ** envp;
+{
+ char **p;
+ int argv_len=0, argv_count=0;
+ int envp_len=0, envp_count=0;
+ int stack_bytes;
+ unsigned short * pip;
+ char * pcp, * stk_ptr, *baseoff;
+ int rv;
+
+ /* How much space for argv */
+ for(p=argv; p && *p && argv_len >= 0; p++)
+ {
+ argv_count++; argv_len += strlen(*p)+1;
+ }
+
+ /* How much space for envp */
+ for(p=envp; p && *p && envp_len >= 0; p++)
+ {
+ envp_count++; envp_len += strlen(*p)+1;
+ }
+
+ /* tot it all up */
+ stack_bytes = 2 /* argc */
+ + argv_count * 2 + 2 /* argv */
+ + argv_len
+ + envp_count * 2 + 2 /* envp */
+ + envp_len;
+
+ /* Allocate it */
+ if( argv_len < 0 || envp_len < 0 || stack_bytes <= 0
+ || (int)(stk_ptr = (char*)sbrk(stack_bytes)) == -1)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+/* Sanity check
+ printf("Argv = (%d,%d), Envp=(%d,%d), stack=%d\n",
+ argv_count, argv_len, envp_count, envp_len, stack_bytes);
+*/
+
+ /* Now copy in the strings */
+ pip=(unsigned short *) stk_ptr;
+ pcp=stk_ptr+2*(1+argv_count+1+envp_count+1);
+
+ /* baseoff = stk_ptr + stack_bytes; */
+ baseoff = stk_ptr;
+ *pip++ = argv_count;
+ for(p=argv; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ *pip++ = 0;
+
+ for(p=envp; p && *p; p++)
+ {
+ int l;
+ *pip++ = pcp-baseoff;
+ l = strlen(*p)+1;
+ memcpy(pcp, *p, l);
+ pcp += l;
+ }
+ *pip++ = 0;
+
+ rv = __exec(fname, stk_ptr, stack_bytes);
+ /* FIXME: This will probably have to interpret '#!' style exe's */
+ sbrk(-stack_bytes);
+ return rv;
+}
+#endif
diff --git a/libc-0.0.4/syscall/getinfo.c b/libc-0.0.4/syscall/getinfo.c
new file mode 100644
index 0000000..a5ab89a
--- /dev/null
+++ b/libc-0.0.4/syscall/getinfo.c
@@ -0,0 +1,32 @@
+
+#define PERM_GETINFO 0x100
+#define PERM_GETGROUP 0x200
+
+struct {
+ int pid;
+ int ppid;
+ int uid;
+ int gid;
+ int euid;
+ int egid;
+}
+ __info_safe;
+
+getgroups(count, locn)
+int count;
+void * locn;
+{
+ if( count < 0 ) {errno = EINVAL; return -1; }
+ return __permissions(PERM_GETGROUP, count, locn);
+}
+
+getpid()
+{
+ __permissions(PERM_GETINFO, 6, &__info_safe);
+ return __info_safe.pid;
+}
+
+getppid()
+{
+ return __permissions(PERM_GETITEM(1) /*, 0, 0 */);
+}
diff --git a/libc-0.0.4/syscall/mksyscall b/libc-0.0.4/syscall/mksyscall
new file mode 100644
index 0000000..1d2b27e
--- /dev/null
+++ b/libc-0.0.4/syscall/mksyscall
@@ -0,0 +1,303 @@
+# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+#
+# This script generates the 'simple' system calls.
+#
+# Each call is put into it's own object file, if the semantics of the
+# call are not correct UNIX then the 4th field in the dat file has a
+# marker and the function is generated with a __ prefix.
+#
+#
+# Different levels of squeeze
+# 0 = each is complete
+# 1 = Short codes calling common function
+
+COMPACT=1
+
+rm -f syscall.c syscall.mak call_tab.v defn_tab.v
+
+tr '[A-Z]' '[a-z]' < syscall.dat | \
+awk -v COMPACT=$COMPACT 'BEGIN{
+ print "# Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>" > "syscall.mak";
+ print "# This file is part of the Linux-8086 C library and is distributed" > "syscall.mak";
+ print "# under the GNU Library General Public License." > "syscall.mak";
+ print "# " > "syscall.mak";
+ print "# This file is automatically generated\n" > "syscall.mak"
+
+ print "/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>";
+ print " * This file is part of the Linux-8086 C library and is distributed";
+ print " * under the GNU Library General Public License.";
+ print " * ";
+ print " * This file is automatically generated */\n"
+ obj="OBJ=";
+
+ print "/* Standard start */\n\n"
+ printf("#ifndef __MSDOS__\n");
+ printf("#ifdef __AS386_16__\n");
+ printf("#asm\n");
+ printf(" .text\n");
+ printf(" .even\n");
+ printf("#endasm\n\n");
+
+ {
+ obj=obj "__syscall.o __syscall4.o ";
+ print "/* Shared system call code */\n"
+ printf("#ifdef L___syscall\n", funcname);
+ printf("#asm\n");
+ printf("#if __FIRST_ARG_IN_AX__\n");
+
+ printf("export sys_call3\nsys_call3:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov cx,[bx+2]\n");
+ printf(" mov bx,[bx+4]\n");
+ # ax=arg1 bx=arg3 cx=arg2 dx=arg0
+ printf(" xchg ax,bx\n");
+ # ax=arg3 bx=arg1 cx=arg2 dx=arg0
+ printf(" xchg ax,dx\n");
+ # ax=arg0 bx=arg1 cx=arg2 dx=arg3
+ printf(" jmp sys_call0\n\n");
+
+ printf("export sys_call2\nsys_call2:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov cx,[bx+2]\n");
+ printf(" mov bx,ax\n");
+ printf(" mov ax,dx\n");
+ printf(" jmp sys_call0\n\n");
+
+ printf("export sys_call1\nsys_call1:\n");
+ printf(" mov bx,ax\n");
+ printf(" mov ax,dx\n");
+ printf("#else\n");
+ printf("export sys_call3\nsys_call3:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov dx,[bx+6]\n");
+ printf(" mov cx,[bx+4]\n");
+ printf(" mov bx,[bx+2]\n");
+ printf(" jmp sys_call0\n\n");
+
+ printf("export sys_call2\nsys_call2:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov cx,[bx+4]\n");
+ printf(" mov bx,[bx+2]\n");
+ printf(" jmp sys_call0\n\n");
+
+ printf("export sys_call1\nsys_call1:\n");
+ printf(" mov bx,sp\n");
+ printf(" mov bx,[bx+2]\n");
+ printf("#endif\n\n");
+
+ printf("export sys_call0\nsys_call0:\n");
+ printf(" int $80\n");
+ printf(" test ax,ax\n");
+ printf(" jge syscall_ok\n");
+ printf(" neg ax\n");
+ printf(" mov [_errno],ax\n");
+ printf(" mov ax,#-1\n");
+ printf("syscall_ok:\n");
+ printf(" ret\n");
+ printf("#endasm\n");
+ printf("#endif\n\n");
+
+ print "/* Shared system call code, syscalls with 4/5 args */\n"
+ printf("#ifdef L___syscall4\n", funcname);
+ printf("#asm\n");
+ printf("#if __FIRST_ARG_IN_AX__\n");
+
+ printf("export sys_call4\nsys_call4:\n");
+ printf("export sys_call5\nsys_call5:\n");
+ printf(" mov bx,sp\n");
+ printf(" push si\n");
+ printf(" mov si,[bx+8]\n");
+ printf(" push di\n");
+ printf(" mov di,[bx+6]\n");
+ printf(" mov cx,[bx+2]\n");
+ printf(" mov bx,[bx+4]\n");
+ # ax=arg1 bx=arg3 cx=arg2 dx=arg0
+ printf(" xchg ax,bx\n");
+ # ax=arg3 bx=arg1 cx=arg2 dx=arg0
+ printf(" xchg ax,dx\n");
+ # ax=arg0 bx=arg1 cx=arg2 dx=arg3
+ printf("#else\n");
+ printf("export sys_call4\nsys_call4:\n");
+ printf("export sys_call5\nsys_call5:\n");
+ printf(" mov bx,sp\n");
+ printf(" push si\n");
+ printf(" mov si,[bx+10]\n");
+ printf(" push di\n");
+ printf(" mov di,[bx+8]\n");
+ printf(" mov dx,[bx+6]\n");
+ printf(" mov cx,[bx+4]\n");
+ printf(" mov bx,[bx+2]\n");
+ printf("#endif\n\n");
+
+ printf(" int $80\n");
+ printf(" pop di\n");
+ printf(" pop si\n");
+ printf(" test ax,ax\n");
+ printf(" jge syscall_ok\n");
+ printf(" neg ax\n");
+ printf(" mov [_errno],ax\n");
+ printf(" mov ax,#-1\n");
+ printf("syscall_ok:\n");
+ printf(" ret\n");
+ printf("#endasm\n");
+ printf("#endif\n\n");
+ }
+}
+/^[ ]*#/ { next; }
+/^[ ]*$/ { next; }
+{
+ if( $2 > max_call ) max_call = $2;
+ if( !($2 in calltab) )
+ callwas[$2] = " /* " $1 " */";
+
+ if( $3 == "x" || $3 == "" ) next;
+ else if( $4 == "-" ) next;
+ else if( $4 == "*" ) funcname="__" $1;
+ else funcname=$1;
+
+ calltab[$2] = $1;
+
+ if( length(obj) > 60 )
+ {
+ printf("%s\t\\\n", obj) > "syscall.mak";
+ obj=" ";
+ }
+ obj=obj funcname ".o ";
+
+ printf "/* CALL %s */\n\n", $0;
+
+ printf("#ifdef L_%s\n", funcname);
+ printf("#asm\n", funcname);
+ printf("export _%s\n", funcname);
+ printf("_%s:\n", funcname);
+
+ # Inline assembler max to 5 args (10 bytes)
+ if( $3 != 4 && $3 != 5 && ( COMPACT || $3 > 5 ))
+ {
+ if( $3 == 0 )
+ {
+ printf(" mov ax,#%d\n", $2);
+ }
+ else
+ {
+ printf("#if __FIRST_ARG_IN_AX__\n");
+ printf(" mov dx,#%d\n", $2);
+ printf("#else\n");
+ printf(" mov ax,#%d\n", $2);
+ printf("#endif\n");
+ }
+ printf(" br sys_call%d\n", $3);
+ }
+ else
+ {
+ if( $3 >= 1 )
+ printf("#if __FIRST_ARG_IN_AX__\n");
+ if( $3 >= 2 )
+ printf(" mov bx,sp\n");
+ if( $3 >= 5 )
+ printf(" push si\n");
+ if( $3 >= 5 )
+ printf(" mov si,[bx+8]\n");
+ if( $3 >= 4 )
+ printf(" push di\n");
+ if( $3 >= 4 )
+ printf(" mov di,[bx+6]\n");
+ if( $3 >= 3 )
+ printf(" mov dx,[bx+4]\n");
+ if( $3 >= 2 )
+ printf(" mov cx,[bx+2]\n");
+ if( $3 >= 1 )
+ printf(" mov bx,ax\n");
+ if( $3 >= 1 )
+ printf("#else\n");
+ if( $3 >= 1 )
+ printf(" mov bx,sp\n");
+ if( $3 >= 5 )
+ printf(" push si\n");
+ if( $3 >= 5 )
+ printf(" mov si,[bx+10]\n");
+ if( $3 >= 4 )
+ printf(" push di\n");
+ if( $3 >= 4 )
+ printf(" mov di,[bx+8]\n");
+ if( $3 >= 3 )
+ printf(" mov dx,[bx+6]\n");
+ if( $3 >= 2 )
+ printf(" mov cx,[bx+4]\n");
+ if( $3 >= 1 )
+ printf(" mov bx,[bx+2]\n");
+ if( $3 >= 1 )
+ printf("#endif\n");
+
+ printf(" mov ax,#%d\n", $2);
+
+ printf(" int $80\n");
+
+ if( $3 >= 4 )
+ printf(" pop di\n");
+ if( $3 >= 5 )
+ printf(" pop si\n");
+
+ printf(" test ax,ax\n");
+ printf(" jl syscall_err\n");
+ printf(" ret\n");
+ printf("syscall_err:\n");
+ printf(" neg ax\n");
+ printf(" mov [_errno],ax\n");
+ printf(" mov ax,#-1\n");
+ printf(" ret\n");
+ }
+ printf("#endasm\n");
+ printf("#endif\n\n");
+}
+END{
+
+ for(i=0; i<=max_call; i++)
+ if( i in calltab )
+ {
+ printf("#ifndef sys_%s\n", calltab[i]) > "defn_tab.v";
+ printf("#define sys_%s sys_enosys\n", calltab[i]) > "defn_tab.v";
+ printf("#endif\n\n") > "defn_tab.v";
+ }
+
+ for(i=0; i<=max_call; i++)
+ if( i in calltab )
+ printf("/* %3d */ sys_%s,\n", i, calltab[i]) > "call_tab.v";
+ else
+ printf("/* %3d */ sys_enosys,%s\n", i, callwas[i]) > "call_tab.v";
+
+ printf("#endif /* __AS386_16__ */\n\n");
+ printf("#endif /* __MSDOS__ */\n\n");
+ printf("%s\n", obj) > "syscall.mak";
+ printf "\n" > "syscall.mak";
+
+}' > syscall.c
+
+cat >> syscall.mak <<\!
+
+TOP=..
+include $(TOP)/Make.defs
+
+all: $(OBJ)
+
+libc.a: $(OBJ)
+ ar r ../libc.a $(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f $(OBJ) libc.a
+
+$(OBJ): syscall.dat mksyscall
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ syscall.c
+!
+
+rv=$?
+if [ "$rv" != 0 ]
+then exit $rv
+fi
+
+export MAKELEVEL
+MAKELEVEL=0
+exec make -f syscall.mak $1
diff --git a/libc-0.0.4/syscall/setjmp.c b/libc-0.0.4/syscall/setjmp.c
new file mode 100644
index 0000000..52c3ff1
--- /dev/null
+++ b/libc-0.0.4/syscall/setjmp.c
@@ -0,0 +1,50 @@
+
+#include <setjmp.h>
+
+#if __AS386_16__
+
+int
+setjmp(env)
+jmp_buf env;
+{
+#asm
+ pop cx ! PC
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax
+#else
+ mov bx,sp
+ mov bx,[bx] ! TOS is prt -> env
+#endif
+ mov [bx+0],cx ! PC
+ mov [bx+2],sp ! This registers are all that may be constant.
+ mov [bx+4],bp
+ mov [bx+6],si ! Is saving these the "right thing" ?
+ mov [bx+8],di
+ xor ax,ax
+ jmp cx
+#endasm
+}
+
+void
+longjmp(env, rv)
+jmp_buf env;
+int rv;
+{
+#asm
+ pop cx ! pc
+#if __FIRST_ARG_IN_AX__
+ mov bx,ax ! env->
+#else
+ pop bx ! env->
+#endif
+ pop ax ! rv
+ mov cx,[bx+0] ! PC
+ mov sp,[bx+2]
+ mov bp,[bx+4]
+ mov si,[bx+6]
+ mov di,[bx+8]
+ jmp cx
+#endasm
+}
+
+#endif
diff --git a/libc-0.0.4/syscall/signal.c b/libc-0.0.4/syscall/signal.c
new file mode 100644
index 0000000..dbeac4a
--- /dev/null
+++ b/libc-0.0.4/syscall/signal.c
@@ -0,0 +1,94 @@
+
+#ifndef __MSDOS__
+#ifdef __AS386_16__
+
+#include <errno.h>
+#include <signal.h>
+
+typedef __sighandler_t Sig;
+
+extern int __signal __P((int, __sighandler_t));
+static Sig system_signal();
+
+Sig __sigtable[_NSIG-1];
+
+/*
+ * Signal handler.
+ *
+ */
+
+/*
+ * KERNEL INTERFACE:
+ * It is assumed the kernel will never give us a signal we haven't
+ * _explicitly_ asked for!
+ *
+ * The Kernel need only save space for _one_ function pointer
+ * (to system_signal) and must deal with SIG_DFL and SIG_IGN
+ * in kernel space.
+ *
+ * When a signal is required the kernel must set all the registers as if
+ * returning from a interrupt normally then push the number of the signal
+ * to be generated, push the current pc value, then set the pc to the
+ * address of the 'system_signal' function.
+ */
+
+Sig
+signal(number, pointer)
+int number;
+Sig pointer;
+{
+ Sig old_sig;
+ int rv;
+ if( number < 1 || number >= _NSIG ) { errno=EINVAL; return SIG_ERR; }
+
+ if( pointer == SIG_DFL || pointer == SIG_IGN )
+ rv = __signal(number, pointer);
+ else
+ rv = __signal(number, (__sighandler_t) system_signal);
+
+ if( rv < 0 ) return SIG_ERR;
+
+ old_sig = __sigtable[number-1];
+ __sigtable[number-1] = pointer;
+
+ return old_sig;
+}
+
+#asm
+ .text
+_system_signal: ! When this is called by the kernel the stack contains
+ pushf ! in order:
+ push ax !
+ push bx ! The signal number, (NOS)
+ push cx ! The program counter, (TOS)
+ push dx !
+ push si ! It does NOT contain the CS register or the flags.
+ push di ! This means it cannot be unraveled by an iret.
+ push bp
+ push es ! Note also only ES segment register is saved.
+ mov bx,sp ! Unlike minix the rv from a system call is in AX.
+ mov bx,[bx+20]
+#if __FIRST_ARG_IN_AX__
+ mov ax,bx
+#else
+ push bx ! NB this is _unchecked_, do we want to ?
+#endif
+ add bx,bx
+ mov bx,[bx+___sigtable-2] ! Offset by 2 cause no entry for signal 0
+ call bx ! Do we want to check BX for 0 or 1 ?
+ inc sp
+ inc sp
+ pop es
+ pop bp
+ pop di
+ pop si
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ popf
+ ret #2 ! Get rid of the signum too.
+#endasm
+
+#endif /* __AS386_16__ */
+#endif /* __MSDOS__ */
diff --git a/libc-0.0.4/syscall/syscall.dat b/libc-0.0.4/syscall/syscall.dat
new file mode 100644
index 0000000..397616f
--- /dev/null
+++ b/libc-0.0.4/syscall/syscall.dat
@@ -0,0 +1,148 @@
+#
+# Name No Args Flag, comment
+#
+# . = Ok, with comment
+# * = Needs libc code (Prefix __)
+# - = Obsolete/not required
+#
+# WARNING!
+# This file is used to generate includes for ELKSemu too.
+# This file is continually changing, when you upgrade you _MUST_ ensure
+# that ELKSemu is of a matching build!
+#
+# Calls that use one fd
+READ 3 3
+WRITE 4 3
+CLOSE 6 1
+LSEEK 19 3 * NB 2nd arg is a ptr to long not a long.
+FSTAT 28 2
+IOCTL 54 3 . Make this and fcntl the same ?
+FCNTL 55 3
+FCHMOD 94 X
+FCHOWN 95 X
+FSYNC 118 1
+FCHDIR 133 X
+LLSEEK 140 X
+READV 145 X
+WRITEV 146 X
+FLOCK 143 X - Use fcntl
+DUP 41 1 - Using nasty fcntl function
+
+#
+SETUP 0 X
+EXIT 1 1 * C exit does stdio, _exit in crt0
+FORK 2 0
+OPEN 5 3
+WAIT4 7 4
+VFORK 8 0 . Needed for 8086
+GETINFO 49 1 - Possible? Gets pid,ppid,uid,euid etc
+LINK 9 2
+UNLINK 10 1
+EXEC 11 3 * Minix style exec
+CHDIR 12 1
+GETTIMEOFDAY 13 2 . time() exists only in libc
+MKNOD 14 3
+CHMOD 15 2
+CHOWN 16 3
+BRK 17 1 * This is only to tell the system
+STAT 18 2
+GETPID 20 1 * This gets both pid & ppid
+MOUNT 21 5
+UMOUNT 22 1
+SETUID 23 1
+GETUID 24 1 * This gets both uid and euid
+SETTIMEOFDAY 25 2 . STIME should _NOT_ exist even as a libc.
+STIME 25 2 - This must NOT exist - even as a libc.
+PTRACE 26 4
+ALARM 27 2
+PAUSE 29 0
+UTIME 30 2
+ACCESS 33 2
+NICE 34 1 .
+FTIME 35 1 - Use gettimeofday
+SYNC 36 0
+KILL 37 2
+RENAME 38 2
+MKDIR 39 2
+RMDIR 40 1
+PIPE 42 1
+TIMES 43 1
+PROF 44 X
+BRK 45 X
+SETGID 46 1
+GETGID 47 1 * This gets both gid and egid
+SIGNAL 48 2 * Have put the despatch table in user space.
+ACCT 51 1
+PHYS 52 X
+LOCK 53 X
+MPX 56 X
+SETPGID 57 X
+ULIMIT 58 X
+UMASK 60 1
+CHROOT 61 1
+USTAT 62 X
+GETPGRP 65 X
+SETSID 66 X
+SIGACTION 67 X
+SGETMASK 68 X
+SSETMASK 69 X
+SETREUID 70 X
+SETREGID 71 X
+SIGSUSPEND 72 X
+SIGPENDING 73 X
+SETHOSTNAME 74 X
+SETRLIMIT 75 X
+GETRLIMIT 76 X
+REBOOT 76 3 . The magic number is 0xfee1,0xdead,...
+GETRUSAGE 77 X
+GETGROUPS 80 2
+SETGROUPS 81 2
+SYMLINK 83 2
+LSTAT 84 2
+READLINK 85 3
+SWAPON 87 X
+REBOOT 88 X
+MUNMAP 91 X
+TRUNCATE 92 X
+FTRUNCATE 93 X
+GETPRIORITY 96 X
+SETPRIORITY 97 X
+PROFIL 98 X
+STATFS 99 X
+FSTATFS 100 X
+SOCKETCALL 102 X
+SYSLOG 103 X
+SETITIMER 104 X
+GETITIMER 105 X
+UNAME 109 X
+VHANGUP 111 X
+SWAPOFF 115 X
+SYSINFO 116 X - Use /proc
+IPC 117 5 * This is for all SYSV IPC
+SIGRETURN 119 X
+SETDOMAINNAME 121 X
+ADJTIMEX 124 X
+MPROTECT 125 X
+SIGPROCMASK 126 X
+QUOTACTL 131 X
+GETPGID 132 X
+SYSFS 135 X
+PERSONALITY 136 X
+SETFSUID 138 X
+SETFSGID 139 X
+GETDENTS 141 X
+SELECT 142 5 *
+MSYNC 144 X
+GETSID 147 X
+FDATASYNC 148 X
+SYSCTL 149 X
+MUNLOCK 151 X
+MUNLOCKALL 153 X
+SCHED_SETPARAM 154 X
+SCHED_GETPARAM 155 X
+SCHED_SETSCHEDULER 156 X
+SCHED_GETSCHEDULER 157 X
+SCHED_YIELD 158 X
+SCHED_GET_PRIORITY_MAX 159 X
+SCHED_GET_PRIORITY_MIN 160 X
+SCHED_RR_GET_INTERVAL 161 X
diff --git a/libc-0.0.4/syscall/syslibc.c b/libc-0.0.4/syscall/syslibc.c
new file mode 100644
index 0000000..1e604e8
--- /dev/null
+++ b/libc-0.0.4/syscall/syslibc.c
@@ -0,0 +1,330 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This file is part of the Linux-8086 C library and is distributed
+ * under the GNU Library General Public License.
+ */
+
+#include <sys/types.h>
+#include <time.h>
+
+/* MSDOS has it's own versions */
+#ifndef __MSDOS__
+#ifdef __AS386_16__
+
+/********************** Function __cstartup *******************************/
+
+#ifdef L___cstartup
+
+void (*__cleanup)() = 0;
+char ** environ;
+
+#asm
+ loc 2
+call_main:
+ .word _main ! Segment 2 is the trailing pointers, main and the
+ .word call_exit ! routine to call exit.
+#if __FIRST_ARG_IN_AX__
+ .data
+saved_arg1:
+ .word 0
+#endif
+#if __CALLER_SAVES__
+ .data
+loopy_safe:
+ .word 0
+#endif
+ .text
+
+export ___cstartup
+___cstartup: ! Crt0 startup
+ pop cx ! Argc
+ mov bx,sp ! Calculate ptrs to argv and envp
+ mov ax,cx
+ inc ax
+ shl ax,#1
+ add ax,bx
+ push ax ! Push Envp
+ mov [_environ],ax ! And save
+ push bx ! Push argv
+#if __FIRST_ARG_IN_AX__
+ mov [saved_arg1],cx
+#else
+ push cx ! Push argc
+#endif
+
+ mov si,#auto_start ! Pointer to first autostart function
+auto_run:
+#if __FIRST_ARG_IN_AX__
+ mov ax,[saved_arg1]
+#endif
+#if __CALLER_SAVES__
+ mov [loopy_safe],si
+#endif
+ call [si] ! Call the function
+#if __CALLER_SAVES__
+ mov si,[loopy_safe]
+#endif
+ inc si ! SI at next
+ inc si
+ jmp auto_run ! And round for the next.
+
+call_exit: ! Last item called by above.
+ pop bx ! Be tidy.
+#if !__FIRST_ARG_IN_AX__
+ push ax ! At the end the last called was main() push it`s
+#endif
+ call _exit ! return val and call exit();
+bad_exit:
+ jmp bad_exit ! Exit returned !!
+
+export _exit
+export __exit
+_exit: ! exit(rv) function
+#if __FIRST_ARG_IN_AX__
+ mov [saved_arg1],ax
+#else
+ mov bx,sp
+ push [bx+2] ! Copy the `rv` for the exit fuctions.
+#endif
+ mov bx,[___cleanup] ! Call exit, normally this is `__do_exit`
+ test bx,bx
+ je no_clean ! But it`s default is null
+ call bx
+no_clean:
+#if __FIRST_ARG_IN_AX__
+ mov ax,[saved_arg1]
+#else
+ inc sp
+ inc sp
+#endif
+__exit: ! _exit(rv)
+ br ___exit ! This is just an alias for __exit();
+
+#endasm
+
+#endif
+
+/********************** Function time ************************************/
+
+#ifdef L_time
+time_t time(where)
+time_t *where;
+{
+ struct timeval rv;
+ if( gettimeofday(&rv, (void*)0) < 0 ) return -1;
+ if(where) *where = rv.tv_sec;
+ return rv.tv_sec;
+}
+#endif
+
+/********************** Function lseek ************************************/
+
+#ifdef L_lseek
+off_t lseek(fd, posn, where)
+int fd;
+off_t posn;
+int where;
+{
+ off_t __lseek();
+ if( __lseek(fd, &posn, where) < 0 ) return -1;
+ else return posn;
+}
+#endif
+
+/********************** Function getpid ************************************/
+
+#ifdef L_getpid
+int getpid()
+{
+ int ppid;
+ return __getpid(&ppid);
+}
+#endif
+
+/********************** Function getppid ************************************/
+
+#ifdef L_getppid
+int getppid()
+{
+ int ppid;
+ __getpid(&ppid);
+ return ppid;
+}
+#endif
+
+/********************** Function getuid ************************************/
+
+#ifdef L_getuid
+int getuid()
+{
+ int euid;
+ return __getuid(&euid);
+}
+#endif
+
+/********************** Function geteuid ************************************/
+
+#ifdef L_geteuid
+int geteuid()
+{
+ int euid;
+ __getuid(&euid);
+ return euid;
+}
+#endif
+
+/********************** Function getgid ************************************/
+
+#ifdef L_getgid
+int getgid()
+{
+ int egid;
+ return __getgid(&egid);
+}
+#endif
+
+/********************** Function getegid ************************************/
+
+#ifdef L_getegid
+int getegid()
+{
+ int egid;
+ __getgid(&egid);
+ return egid;
+}
+#endif
+
+/********************** Function dup2 ************************************/
+
+#ifdef L_dup2
+
+#include <fcntl.h>
+
+int dup2(ifd, ofd)
+int ifd;
+{
+ return fcntl(ifd, F_DUPFD, ofd);
+}
+#endif
+
+/********************** Function dup ************************************/
+
+#ifdef L_dup
+#include <sys/param.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* This is horribly complicated, there _must_ be a better way! */
+
+int
+dup(fd)
+int fd;
+{
+ int nfd;
+ extern int errno;
+ int oerr = errno;
+
+ errno = 0;
+ for(nfd=0; nfd<NR_OPEN; nfd++)
+ {
+ if( fcntl(nfd, F_GETFD) < 0 )
+ break;
+ }
+ if( nfd == NR_OPEN ) { errno = EMFILE ; return -1; }
+ errno = oerr;
+ if( fcntl(fd, F_DUPFD, nfd) < 0 )
+ {
+ if( errno == EINVAL ) errno = EMFILE;
+ return -1;
+ }
+ return nfd;
+}
+#endif
+
+/********************** Function abort ************************************/
+
+#ifdef L_abort
+#include <signal.h>
+
+int abort()
+{
+ signal(SIGABRT, SIG_DFL);
+ kill(SIGABRT, getpid()); /* Correct one */
+ pause(); /* System may just schedule */
+ signal(SIGKILL, SIG_DFL);
+ kill(SIGKILL, getpid()); /* Can't trap this! */
+ __exit(255); /* WHAT!! */
+}
+#endif
+
+/********************** Function wait ************************************/
+
+#ifdef L_wait
+int
+wait(status)
+int * status;
+{
+ return wait4(-1, status, 0, (void*)0);
+}
+#endif
+
+/********************** Function waitpid ************************************/
+
+#ifdef L_waitpid
+int
+waitpid(pid, status, opts)
+int pid;
+int * status;
+int opts;
+{
+ return wait4(pid, status, opts, (void*)0);
+}
+#endif
+
+/********************** Function sleep ************************************/
+
+#ifdef L_sleep
+#include <signal.h>
+
+/* This uses SIGALRM, it does keep the previous alarm call but will lose
+ * any alarms that go off during the sleep
+ */
+
+static void alrm() { }
+
+unsigned int sleep(seconds)
+unsigned int seconds;
+{
+ void (*last_alarm)();
+ unsigned int prev_sec;
+
+ prev_sec = alarm(0);
+ if( prev_sec <= seconds ) prev_sec = 1; else prev_sec -= seconds;
+
+ last_alarm = signal(SIGALRM, alrm);
+ alarm(seconds);
+ pause();
+ seconds = alarm(prev_sec);
+ signal(SIGALRM, last_alarm);
+ return seconds;
+}
+#if 0
+ /* Is this a better way ? If we have select of course :-) */
+#include <sys/time.h>
+unsigned int
+sleep(seconds)
+unsigned int seconds;
+{
+ struct timeval timeout;
+ time_t start = time((void*)0);
+ timeout.tv_sec = seconds;
+ timeout.tv_usec = 0;
+ select(1, NULL, NULL, NULL, &timeout);
+ return seconds - (time((void*)0) - start);
+}
+#endif
+#endif
+
+/********************** THE END ********************************************/
+
+#endif /* __AS386_16__ */
+#endif /* __MSDOS__ */
diff --git a/libc-0.0.4/termios/Config b/libc-0.0.4/termios/Config
new file mode 100644
index 0000000..f0c9bde
--- /dev/null
+++ b/libc-0.0.4/termios/Config
@@ -0,0 +1 @@
+termios: Termios functions
diff --git a/libc-0.0.4/termios/Makefile b/libc-0.0.4/termios/Makefile
new file mode 100644
index 0000000..6925bb3
--- /dev/null
+++ b/libc-0.0.4/termios/Makefile
@@ -0,0 +1,27 @@
+# Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+
+TSRC=termios.c
+TOBJ=tcsetattr.o tcgetattr.o tcdrain.o tcflow.o tcflush.o tcsendbreak.o \
+ tcsetpgrp.o tcgetpgrp.o isatty.o
+
+OBJ=$(TOBJ)
+
+all: $(OBJ)
+
+libdos.a:
+
+libc.a: $(OBJ)
+ ar r ../libc.a $(OBJ)
+ @touch libc.a
+
+clean:
+ rm -f $(OBJ) libc.a
+
+$(TOBJ): $(TSRC)
+ $(CC) $(CFLAGS) -c -DL_$* -o $@ $(TSRC)
+
diff --git a/libc-0.0.4/termios/README b/libc-0.0.4/termios/README
new file mode 100644
index 0000000..c83448d
--- /dev/null
+++ b/libc-0.0.4/termios/README
@@ -0,0 +1,7 @@
+Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+This file is part of the Linux-8086 C library and is distributed
+under the GNU Library General Public License.
+
+There's currently nothing special about termios.
+
+-Robert
diff --git a/libc-0.0.4/termios/termios.c b/libc-0.0.4/termios/termios.c
new file mode 100644
index 0000000..1c7da7f
--- /dev/null
+++ b/libc-0.0.4/termios/termios.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk> This
+ * file is part of the Linux-8086 C library and is distributed under the
+ * GNU Library General Public License.
+ */
+
+/* Note: This is based loosely on the Glib termios routines. */
+
+#ifndef __MSDOS__
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+
+#ifdef L_isatty
+isatty(fd)
+int fd;
+{
+ struct termios term;
+ int rv, err = errno;
+ rv= (ioctl(fd, TCGETS, &term)==0);
+ if( rv==0 && errno == ENOSYS )
+ rv = (fd<3);
+ errno = err;
+ return rv;
+}
+#endif
+
+#ifdef L_tcgetattr
+int
+tcgetattr(fd, term)
+int fd;
+struct termios *term;
+{
+ return ioctl(fd, TCGETS, term);
+}
+#endif
+
+#ifdef L_tcsetattr
+int
+tcsetattr(fildes, optional_actions, termios_p)
+int fildes;
+int optional_actions;
+struct termios *termios_p;
+{
+ switch (optional_actions)
+ {
+ case TCSANOW:
+ return ioctl(fildes, TCSETS, termios_p);
+ case TCSADRAIN:
+ return ioctl(fildes, TCSETSW, termios_p);
+ case TCSAFLUSH:
+ return ioctl(fildes, TCSETSF, termios_p);
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+#endif
+
+#ifdef L_tcdrain
+/* Wait for pending output to be written on FD. */
+int
+tcdrain(fd)
+int fd;
+{
+ /* With an argument of 1, TCSBRK just waits for output to drain. */
+ return ioctl(fd, TCSBRK, 1);
+}
+#endif
+
+#ifdef L_tcflow
+int
+tcflow(fd, action)
+int fd;
+int action;
+{
+ return ioctl(fd, TCXONC, action);
+}
+#endif
+
+#ifdef L_tcflush
+/* Flush pending data on FD. */
+int
+tcflush(fd, queue_selector)
+int fd;
+int queue_selector;
+{
+ return ioctl(fd, TCFLSH, queue_selector);
+}
+#endif
+
+#ifdef L_tcsendbreak
+/* Send zero bits on FD. */
+int
+tcsendbreak(fd, duration)
+int fd;
+int duration;
+{
+ /*
+ * The break lasts 0.25 to 0.5 seconds if DURATION is zero, and an
+ * implementation-defined period if DURATION is nonzero. We define a
+ * positive DURATION to be number of milliseconds to break.
+ */
+ if (duration <= 0)
+ return ioctl(fd, TCSBRK, 0);
+
+ /*
+ * ioctl can't send a break of any other duration for us. This could be
+ * changed to use trickery (e.g. lower speed and send a '\0') to send
+ * the break, but for now just return an error.
+ */
+ errno = EINVAL;
+ return -1;
+}
+#endif
+
+#ifdef L_tcsetpgrp
+/* Set the foreground process group ID of FD set PGRP_ID. */
+int
+tcsetpgrp(fd, pgrp_id)
+int fd;
+pid_t pgrp_id;
+{
+ return ioctl(fd, TIOCSPGRP, &pgrp_id);
+}
+#endif
+
+#ifdef L_tcgetpgrp
+/* Return the foreground process group ID of FD. */
+pid_t
+tcgetpgrp(fd)
+int fd;
+{
+ int pgrp;
+ if (ioctl(fd, TIOCGPGRP, &pgrp) < 0)
+ return (pid_t) - 1;
+ return (pid_t) pgrp;
+}
+#endif
+
+#endif
diff --git a/libc-0.0.4/tests/Config b/libc-0.0.4/tests/Config
new file mode 100644
index 0000000..4bdf884
--- /dev/null
+++ b/libc-0.0.4/tests/Config
@@ -0,0 +1,2 @@
+
+tools: These are tools to test libc - make directly
diff --git a/libc-0.0.4/tests/README b/libc-0.0.4/tests/README
new file mode 100644
index 0000000..642e636
--- /dev/null
+++ b/libc-0.0.4/tests/README
@@ -0,0 +1,19 @@
+Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+This file is part of the Linux-8086 C library and is distributed
+under the GNU Library General Public License.
+
+These are user level tools, they're being used to test libc routines.
+
+env.c Prints the environment and arguments (Plus some junk)
+compr.c Mini compression program (rather slow at times)
+ucomp.c Mini uncompression program (Very fast)
+ft.c Multiple simple file tools.
+hd.c Hex dump.
+line2.c Print lines from /etc/passwd (stdio)
+lines.c Print lines from /etc/passwd
+ouch.c Signal test
+size.c Size of executables and object files.
+sync.c :-)
+wc.c Word count.
+
+-Robert
diff --git a/libc-0.0.4/tests/Real_make b/libc-0.0.4/tests/Real_make
new file mode 100644
index 0000000..38c4232
--- /dev/null
+++ b/libc-0.0.4/tests/Real_make
@@ -0,0 +1,19 @@
+# Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+SRC=env.c ft.c hd.c size.c sync.c compr.c ucomp.c ouch.c lines.c \
+ wc.c line2.c rand.c grab.c
+OBJ=
+EXE=env ft hd size sync compr ucomp ouch lines wc line2 rand grab
+
+LINK_FILES=cat chgrp chmod chown cp install ln mkdir mkfifo mknod mv rm
+
+all: $(EXE)
+
+links:
+ for i in $(LINK_FILES) ; do ln -s ft $$i ; done
+
+no_links:
+ rm -f $(LINK_FILES)
+
diff --git a/libc-0.0.4/tests/compr.c b/libc-0.0.4/tests/compr.c
new file mode 100644
index 0000000..8e53443
--- /dev/null
+++ b/libc-0.0.4/tests/compr.c
@@ -0,0 +1,383 @@
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#define MAXNO 32767
+#define MAXLEN 127
+#define XXQSCAN /* Speed up scanning at the cost of not being optimal */
+
+unsigned char *fptr;
+unsigned short *vptr;
+FILE * fd;
+
+#define ITBSIZE 4096
+#define itbfunc() (ptr[mainscan]^(ptr[mainscan+1]<<4)^(ptr[mainscan+2]<<2))
+/*
+#define ITBSIZE 4001
+#define itbfunc() ((ptr[mainscan]+ptr[mainscan+1]*79+ptr[mainscan+2]*307)%4001)
+*/
+int * itb;
+
+int size;
+int maxno= 8000;
+long cnt=0;
+
+long icount = 0;
+long ocount = 0;
+
+unsigned char key;
+
+int fl;
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ if( argc < 2 ) { fprintf(stderr, "Usage; ... \n"); exit(1); }
+
+ if( argc == 3 )
+ {
+ maxno = atoi(argv[2]);
+ if( maxno < 256 ) maxno = 256;
+ if( maxno > MAXNO) maxno = MAXNO;
+ }
+
+ if( strcmp(argv[1], "-") == 0 )
+ fd = stdin;
+ else
+ fd = fopen(argv[1], "r" );
+ if( fd == 0 ) { perror("Open failed\n"); exit(1); }
+
+ fptr = (unsigned char * ) malloc((unsigned)maxno*2);
+ itb = (int * ) malloc(ITBSIZE*sizeof(int));
+ if( itb )
+ vptr = (unsigned short * ) malloc((unsigned)maxno * sizeof(short)*2 );
+ else
+ vptr = 0;
+
+ if( fptr == 0 )
+ {
+ perror("Cannot allocate RAM");
+ exit(1);
+ }
+ if( vptr == 0 && itb ) free(itb);
+
+ fl = 0;
+ {
+ if( (size = fread(fptr, 1, (int)maxno, fd )) < 0 ) { fprintf(stderr, "\nRead failed\n"); exit(1); }
+
+ if( size )
+ {
+ icount += size;
+ if( fl == 0 )
+ {
+ key = scan_min();
+ putchar(key); ocount++;
+ fl = 1;
+ }
+ else
+ fprintf(stderr, "\rBlock %d \r", fl++ );
+ if( vptr) compress();
+ else slo_compress();
+ }
+ }
+
+ fprintf(stderr, "\n");
+ exit(0);
+}
+
+scan_min()
+{
+ long count[256];
+ long i;
+ int j, n;
+
+ for( j=0; j<256; j++ ) count[j] = 0;
+
+ for( i=0; i<size; i++) count[ fptr[i] & 0xFF ]++;
+
+ for( i= (((unsigned long) -1) >> 1), j=0; j<256; j++ )
+ if( count[j] < i )
+ {
+ i = count[j] ;
+ n = j;
+ }
+
+ fprintf(stderr, "Most unused in 0x%lx to 0x%lx is 0x%02x at %ld\n", cnt, cnt+size, n, i );
+ cnt+= size;
+
+ return n;
+}
+
+compress()
+{
+ register long mainscan;
+ register long secondscan;
+ register unsigned char * ptr = (unsigned char * ) fptr;
+ register int len;
+ register int matchlen;
+ long notepos;
+ long emark;
+#ifdef QSCAN
+ int count;
+#endif
+
+ for( mainscan=0; mainscan <ITBSIZE; itb[mainscan++] = -1 );
+
+ mainscan=0;
+ emark = size - 130 ;
+loopback:
+
+ for( ; mainscan < emark; )
+ {
+ matchlen = 3;
+ notepos = -1;
+#ifdef QSCAN
+ count = 0;
+#endif
+ for( secondscan=itb[itbfunc()];
+ secondscan >= 0 && mainscan - secondscan < maxno;
+ secondscan -= vptr[secondscan] )
+ {
+#ifdef DEBUG
+if( vptr[secondscan] == 0 )
+{
+ fprintf(stderr, "\nOh !!!!! mainsc %ld, sec-scan %ld\n", mainscan, secondscan);
+ vptr[secondscan] = secondscan+1;
+}
+#endif
+
+ for( len = 0; len < MAXLEN ; len++ )
+ if( mainscan+len >= size || ptr[mainscan+len] != ptr[secondscan+len] ) break;
+ if( len > matchlen && (len != 4 || mainscan - secondscan < 256 ) )
+ {
+ notepos = secondscan;
+ matchlen = len;
+ if( len == MAXLEN ) break;
+ }
+#ifdef QSCAN
+ if( matchlen > 20 && len > 3 && ++count > 5 )
+ break;
+#endif
+ }
+
+ if( notepos == -1 )
+ {
+ if( ptr[mainscan] == key )
+ {
+ ocount+=2;
+ putchar(key);
+ putchar(0);
+ }
+ else
+ {
+ ocount++;
+ putchar(ptr[mainscan]);
+ }
+ matchlen = 1;
+ }
+ else
+ {
+ long x = mainscan - notepos;
+ ocount+=3;
+ putchar(key);
+ if( x > 255 ) putchar(matchlen | 0x80);
+ else putchar(matchlen);
+ putchar((int)x);
+ if( x > 255 ) { putchar((int)x>>8); ocount++; }
+ }
+
+ while( matchlen-- )
+ {
+ len = itbfunc();
+ vptr[mainscan] = mainscan - itb[len];
+#if 1
+ if( vptr[mainscan] == 0 )
+ {
+ fprintf(stderr, "\nHumm.. ms=%ld, hash=%d, itb[hash]=%ld\n", mainscan, len, itb[len]);
+ vptr[mainscan] = mainscan+1;
+ }
+#endif
+ itb[len] = mainscan;
+ mainscan++;
+ }
+ }
+
+ fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount );
+
+ if( emark < size-4 )
+ {
+ int cnt;
+ long l ;
+ if(mainscan > maxno )
+ {
+ for(cnt=0; cnt<ITBSIZE; cnt++)
+ {
+ if( itb[cnt] < maxno) itb[cnt] = -1;
+ else itb[cnt] -= maxno;
+ }
+ for(l=0; l<maxno; l++)
+ {
+ ptr[l] = ptr[l+maxno];
+ vptr[l] = vptr[l+maxno];
+ }
+ mainscan -= maxno;
+ size -= maxno;
+ }
+ if( size <= maxno )
+ {
+ if(( cnt = fread(ptr+size, 1, (int)maxno, fd)) < 0 )
+ { fprintf(stderr, "\nRead failed\n"); exit(1); }
+ size += cnt;
+ icount += cnt;
+ fprintf(stderr, "\rBlock %d \r", fl++ );
+ }
+ emark = size - 130;
+ if( mainscan >= emark )
+ emark = size -4;
+
+ goto loopback;
+ }
+
+ for( ; mainscan < size; )
+ {
+ if( ptr[mainscan] == key )
+ {
+ ocount+=2;
+ putchar(key);
+ putchar(0);
+ }
+ else
+ {
+ ocount++;
+ putchar(fptr[mainscan]);
+ }
+ mainscan++;
+ }
+ fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount );
+ /* end */
+}
+
+slo_compress()
+{
+ register long mainscan;
+ register long secondscan;
+ register unsigned char * ptr = (unsigned char * ) fptr;
+ register int len;
+ register int matchlen;
+ long notepos;
+ long emark;
+#ifdef QSCAN
+ int count;
+#endif
+
+ mainscan=0;
+ emark = size - 130 ;
+loopback:
+
+ for( ; mainscan < emark; )
+ {
+ matchlen = 3;
+ notepos = -1;
+#ifdef QSCAN
+ count = 0;
+#endif
+ for( secondscan=mainscan-1;
+ secondscan >= 0 && mainscan - secondscan < maxno;
+ secondscan-- )
+ {
+ for( len = 0; len < MAXLEN ; len++ )
+ if( mainscan+len >= size || ptr[mainscan+len] != ptr[secondscan+len] ) break;
+ if( len > matchlen && (len != 4 || mainscan - secondscan < 256 ) )
+ {
+ notepos = secondscan;
+ matchlen = len;
+ if( len == MAXLEN ) break;
+ }
+#ifdef QSCAN
+ if( matchlen > 20 && len > 3 && ++count > 5 )
+ break;
+#endif
+ }
+
+ if( notepos == -1 )
+ {
+ if( ptr[mainscan] == key )
+ {
+ ocount+=2;
+ putchar(key);
+ putchar(0);
+ }
+ else
+ {
+ ocount++;
+ putchar(ptr[mainscan]);
+ }
+ matchlen = 1;
+ }
+ else
+ {
+ long x = mainscan - notepos;
+ ocount+=3;
+ putchar(key);
+ if( x > 255 ) putchar(matchlen | 0x80);
+ else putchar(matchlen);
+ putchar((int)x);
+ if( x > 255 ) { putchar((int)x>>8); ocount++; }
+ }
+
+ mainscan += matchlen;
+ }
+
+ fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount );
+
+ if( emark < size-4 )
+ {
+ int cnt;
+ long l ;
+ if(mainscan > maxno )
+ {
+ for(l=0; l<maxno; l++)
+ {
+ ptr[l] = ptr[l+maxno];
+ }
+ mainscan -= maxno;
+ size -= maxno;
+ }
+ if( size <= maxno )
+ {
+ if(( cnt = fread(ptr+size, 1, (int)maxno, fd)) < 0 )
+ { fprintf(stderr, "\nRead failed\n"); exit(1); }
+ size += cnt;
+ icount += cnt;
+ fprintf(stderr, "\rBlock %d \r", fl++ );
+ }
+ emark = size - 130;
+ if( mainscan >= emark )
+ emark = size -4;
+
+ goto loopback;
+ }
+
+ for( ; mainscan < size; )
+ {
+ if( ptr[mainscan] == key )
+ {
+ ocount+=2;
+ putchar(key);
+ putchar(0);
+ }
+ else
+ {
+ ocount++;
+ putchar(fptr[mainscan]);
+ }
+ mainscan++;
+ }
+ fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount );
+ /* end */
+}
+
diff --git a/libc-0.0.4/tests/env.c b/libc-0.0.4/tests/env.c
new file mode 100644
index 0000000..baeb8e9
--- /dev/null
+++ b/libc-0.0.4/tests/env.c
@@ -0,0 +1,82 @@
+
+char hex[] = "0123456789ABCDEF";
+
+char buf[20];
+main(argc, argv, envp)
+int argc;
+char ** argv;
+char ** envp;
+{
+ int i,j; char *p; char * str;
+ int * arg = &argc;
+
+ for(j=0; j<8; j++)
+ {
+ phex(arg);
+ putstr(":");
+ for(i=0; i<8; i++)
+ {
+ putstr(" ");
+ phex(*arg++);
+ }
+ putstr("\n");
+ }
+
+#if 0
+ str = alloca(sizeof(hex)+2);
+ putstr("Alloca = ");
+ phex(&str);
+ putstr(",");
+ phex(str);
+ putstr("\n");
+#endif
+
+ p = (char*) &argc;
+
+ putstr("ARGC="); phex(argc); putstr("\n");
+ for(i=0; i<argc; i++)
+ {
+ phex(argv[i]);
+ putstr(":");
+ putstr(argv[i]);
+ putstr("\n");
+ }
+ putstr("ENV=>\n");
+ for(; *envp; envp++)
+ {
+ phex(envp);
+ putstr(":");
+ phex(*envp);
+ putstr(":");
+ putstr(*envp);
+ putstr("\n");
+ }
+}
+
+phex(val)
+{
+ int i;
+ printf("%04x", val);
+}
+
+putstr(str)
+{
+ printf("%s", str);
+}
+
+#if 0
+int global_var_that_needs_init = 0x201;
+
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word _init_vars ! Pointer to the autorun function
+ .word no_op ! Space filler cause segs are padded to 4 bytes.
+ .text ! So the function after is also in the correct seg.
+#endasm
+
+static void init_vars()
+{
+ global_var_that_needs_init = getuid();
+}
+#endif
diff --git a/libc-0.0.4/tests/ft.c b/libc-0.0.4/tests/ft.c
new file mode 100644
index 0000000..6456d0b
--- /dev/null
+++ b/libc-0.0.4/tests/ft.c
@@ -0,0 +1,1217 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This program is distributed under the GNU General Public License.
+ */
+
+/*
+ * File Tool, This program is a collection of basic file tools
+ * it includes cat, cp, ln, mkdir, mknod, chmod, chown, mv, rm
+ *
+ * Links may be used to call it under any of these names.
+ */
+#include <stdio.h>
+#ifdef __STDC__
+#include <unistd.h>
+#include <stdlib.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/param.h>
+#include <utime.h>
+#include <pwd.h>
+#include <grp.h>
+
+#ifdef __BCC__X
+#undef S_IFLNK
+#undef S_IFSOCK
+#endif
+
+#ifdef S_IFSOCK
+#include <sys/socket.h>
+#endif
+#ifndef S_IFLNK
+#define lstat stat
+#endif
+
+/* Ansi prototypes */
+#ifdef __STDC__
+#define PR(x) x
+#else
+#define PR(x) ()
+#endif
+
+void main PR((int argc, char ** argv));
+int select_command PR((char * argv));
+void do_prep PR((void));
+void do_post PR((void));
+void execute PR((char * dname, char * fname));
+int exec_for_subdir PR((char * dname));
+void exec_for_item PR((int when, char * fname));
+void parse_perms PR((char * prefix, char * ustring));
+int edit_mode PR((int mode, char * mode_str));
+int cmd_ft PR((char * fname));
+int cmd_mkfifo PR((char * fname));
+int cmd_mksock PR((char * fname));
+int cmd_rm PR((char * fname));
+void build_dest PR((char * dest, char * name, char * newpath));
+int strisdigit PR((char * str));
+int cmd_mv PR((char * fname));
+int cmd_ln PR((char * fname));
+int cmd_cp PR((char * fname));
+int copy_modes PR((char * file));
+int copy_file PR((char * source, char * dest));
+void Usage PR((void));
+int cmd_mkdir PR((char * dirname));
+int cmd_mknod PR((void));
+int warn_func PR((int enumber, char * estr, char * eobj));
+int error_func PR((int enumber, char * estr, char * eobj));
+
+#define warning(x,y,z) ( Line_no = __LINE__, warn_func(x,y,z))
+#define error(x,y,z) ( Line_no = __LINE__, error_func(x,y,z))
+int Line_no = -1;
+
+#define DO_BDIR 0x0010 /* Do Dir before contents */
+#define DO_ADIR 0x0020 /* Do Dir after contents */
+#define DO_MCOPY 0x0040 /* Preserve modes flag forced */
+#define OK_DIR 0x0080 /* Directorys OK even if no flg_recurse */
+#define IGN_LNK 0x0100 /* Not interested in symlinks */
+#define NO_SOURCE 0x0200 /* Named files created */
+#define OK_NO_SOURCE 0x0400 /* Don't need the source */
+
+#define CMD_FT (0+OK_DIR+DO_BDIR)
+#define CMD_CAT (1+IGN_LNK)
+#define CMD_CHGRP (2+OK_DIR+IGN_LNK+DO_ADIR)
+#define CMD_CHMOD (3+OK_DIR+IGN_LNK+DO_ADIR)
+#define CMD_CHOWN (4+OK_DIR+IGN_LNK+DO_ADIR)
+#define CMD_CP (5+IGN_LNK)
+#define CMD_EXTAR (6+DO_MCOPY+DO_BDIR)
+#define CMD_INSTALL (7+DO_MCOPY)
+#define CMD_LN (8+IGN_LNK+DO_BDIR)
+#define CMD_MKDIR (9+NO_SOURCE)
+#define CMD_MKFIFO (10+NO_SOURCE)
+#define CMD_MKSOCK (11+NO_SOURCE)
+#define CMD_MKNOD (12+NO_SOURCE)
+#define CMD_MV (13+DO_MCOPY+OK_DIR+DO_BDIR)
+#define CMD_RM (14+DO_ADIR)
+
+struct {
+ char * name;
+ int cmd;
+ int argpat;
+ char * opts;
+} command_list[] =
+{
+ { "ft", CMD_FT, 0, "-Rv" },
+ { "cat", CMD_CAT, 0, "uR" },
+ { "chgrp", CMD_CHGRP, 1, "vfR" },
+ { "chmod", CMD_CHMOD, 1, "vfR" },
+ { "chown", CMD_CHOWN, 1, "vfR" },
+ { "cp", CMD_CP, -1, "vifRrpsd" },
+ { "extar", CMD_EXTAR, 1, "" },
+ { "install", CMD_INSTALL, -1, "cdso:g:m:" },
+ { "ln", CMD_LN, -1, "vifs" },
+ { "mkdir", CMD_MKDIR, 0, "m:" },
+ { "mkfifo", CMD_MKFIFO, 0, "m:" },
+#ifdef S_IFSOCK
+ { "mksock", CMD_MKSOCK, 0, "m:" },
+#endif
+ { "mknod", CMD_MKNOD, 4, "m:" },
+ { "mv", CMD_MV, -1, "vif" },
+ { "rm", CMD_RM, 0, "vifr" },
+ { 0 }
+};
+
+int cmd_arg = 0;
+int cmd_tok = CMD_FT;
+char * cmd_opt = "-";
+char * cmd_string = 0; /* the first (or last) arg where special */
+char * prog_name = "";
+
+char ** flist = 0;
+int fcount = 0;
+int add_base=0;
+char * or_name = 0;
+int or_offset = 0;
+
+int flg_recurse = 0;
+int flg_verbose = 1;
+int flg_preserve= 0;
+int flg_mkpdir = 0;
+int flg_noderef = 0;
+int flg_symlink = 0;
+int flg_exestrip= 0;
+
+int flg_r, flg_force;
+char *str_o, *str_g, *str_m;
+
+/* Things to set on the new file */
+int set_user = -1;
+int set_group = -1;
+int set_mode = -1;
+time_t set_time = -1;
+char mode_str[32] = "";
+int u_mask = 0; /* 07777 altered by umask() */
+
+struct stat cur_file_stat;
+struct stat dest_item;
+struct stat access_stat;
+
+int done_something = 0;
+
+void
+main(argc, argv)
+int argc; char ** argv;
+{
+ int ar;
+ (void) select_command(argv[0]);
+
+ for(ar=1;
+ argv[ar] && argv[ar][0] == '-' && argv[ar][1];
+ ar++)
+ {
+ char * p = argv[ar]+1;
+ /* For symbolic changes of the form -rwx */
+ if( cmd_tok == CMD_CHMOD && strchr("rwx", *p) != 0 ) break;
+ while(*p)
+ {
+ char * ap=0, *av=0;
+ char ch;
+ /* Is it a valid opt for this cmd */
+ if(*p == ':' || (ap=strchr(cmd_opt, *p)) == 0) Usage();
+
+ /* Got an argument ? */
+ if(ap[1] == ':')
+ {
+ if(!argv[ar+1]) Usage();
+ av = argv[++ar];
+ }
+
+ if( (ch = *p) == '-' )
+ {
+ if( (ch=select_command(p)) < 0 ) Usage();
+ }
+ switch(ch)
+ {
+ case '\0': break;
+ case 'r':
+ case 'R': flg_recurse++; break;
+ case 'v': flg_verbose++; break;
+ case 'p': if(cmd_tok == CMD_MKDIR) flg_mkpdir++;
+ else flg_preserve++;
+ break;
+ case 'd': if(cmd_tok == CMD_INSTALL)
+ { flg_mkpdir++; cmd_arg=0; } /* Special mkdir */
+ else flg_noderef++; /* cmd_copy */
+ break;
+
+ case 'f': flg_force++; flg_verbose=0; break;
+ case 'o': str_o = av; break;
+ case 'g': str_g = av; break;
+ case 'm': str_m = av; break;
+
+ case 's': flg_symlink++;
+ if( cmd_tok == CMD_LN) cmd_tok |= OK_DIR+OK_NO_SOURCE;
+ break;
+ }
+ if(*p == '-') break;
+ p++;
+ }
+ }
+
+ switch(cmd_arg)
+ {
+ case 1:
+ if( ar >= argc ) Usage();
+ cmd_string = argv[ar++];
+ fcount = argc-ar;
+ flist = argv+ar;
+ break;
+ case 0:
+ fcount = argc-ar;
+ flist = argv+ar;
+ break;
+ case -1:
+ if( ar >= argc ) Usage();
+ cmd_string = argv[argc-1];
+ fcount = argc-ar-1;
+ flist = argv+ar;
+ break;
+ default:
+ if( ar != argc-cmd_arg ) Usage();
+ fcount = argc-ar;
+ flist = argv+ar;
+ break;
+ }
+
+ do_prep();
+
+ for(ar=0; ar<fcount; ar++)
+ {
+ done_something=1;
+ or_name = flist[ar]; or_offset = strlen(or_name)+1;
+ execute(flist[ar], (char*)0);
+ }
+
+ do_post();
+
+ if( !done_something )
+ {
+ if( cmd_tok == CMD_CAT )
+ execute("-", (char*)0);
+ else
+ Usage();
+ }
+ exit(0);
+}
+
+int select_command(argv)
+char * argv;
+{
+ int ar;
+ char *p, *s;
+ prog_name = argv;
+ for(ar=0; command_list[ar].name; ar++)
+ {
+ p = strrchr(argv, '-'); if(p) p++; else p=argv;
+ s = strrchr(p, '/'); if(s) s++; else s=p;
+ if( strcmp(s, command_list[ar].name) == 0 )
+ {
+ cmd_arg = command_list[ar].argpat;
+ cmd_tok = command_list[ar].cmd;
+ cmd_opt = command_list[ar].opts;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void do_prep()
+{
+ char * prefix = "::";
+
+ u_mask = umask(077);
+ umask(u_mask);
+ u_mask = (07777&(~u_mask));
+
+ if(cmd_tok&DO_MCOPY) flg_preserve++;
+ if(str_m) parse_perms(prefix, str_m);
+
+ switch(cmd_tok)
+ {
+ /* mknod is very different */
+ case CMD_MKNOD: cmd_mknod(); exit(0); break;
+
+ case CMD_CP:
+ if(strcmp(cmd_string, "-") == 0)
+ {
+ cmd_tok = CMD_CAT;
+ cmd_arg = 0;
+ break;
+ }
+ if(flg_symlink)
+ {
+ cmd_tok = CMD_LN+OK_DIR+OK_NO_SOURCE;
+ flg_preserve = 0;
+ }
+ break;
+
+ case CMD_CHOWN: prefix++;
+ case CMD_CHGRP: prefix++;
+ case CMD_CHMOD:
+ parse_perms(prefix, cmd_string);
+ set_time = 0;
+ break;
+ case CMD_INSTALL:
+ flg_exestrip = flg_symlink;
+ flg_symlink = 0;
+ if(str_o) parse_perms(prefix+2, str_o);
+ if(str_g) parse_perms(prefix+1, str_g);
+ if(flg_mkpdir) cmd_tok = CMD_MKDIR;
+ else
+ {
+ cmd_tok = CMD_CP;
+ flg_preserve = 1;
+ }
+ break;
+ }
+
+#ifndef S_IFLNK
+ if(flg_symlink)
+ {
+ error(0, "No support for symlinks available:", cmd_string);
+ exit(1);
+ }
+#endif
+
+ /* Are we transfering many to one ? Then it must be a directory */
+ if(cmd_arg == -1)
+ {
+ if( stat(cmd_string, &dest_item) == -1)
+ {
+ if( fcount > 1 )
+ {
+ if( cmd_mkdir(cmd_string) < 0 )
+ exit(1);
+ stat(cmd_string, &dest_item);
+ add_base = 1;
+ }
+ }
+ else
+ {
+ if( !S_ISDIR(dest_item.st_mode) )
+ {
+ if( fcount > 1 )
+ {
+ error(0, "Destination must be a directory:", cmd_string);
+ exit(1);
+ }
+ }
+ else add_base = 1;
+ }
+ }
+}
+
+void do_post()
+{
+ /* Oh! It seems there's nothing to do, ah well. */
+}
+
+void execute(dname, fname)
+char * dname; char * fname;
+{
+ char * buf;
+ if( strcmp(dname, "-") == 0 )
+ {
+ exec_for_item(0, dname);
+ return;
+ }
+ if( fname )
+ {
+ buf = alloca(strlen(dname) + strlen(fname) + 4);
+ if( buf == 0 )
+ {
+ error(errno, "Can't allocate memory for path beyond", dname);
+ return ;
+ }
+ strcpy(buf, dname);
+ if(strcmp(dname, "/")) strcat(buf, "/");
+ strcat(buf, fname);
+ }
+ else buf = dname;
+
+ if( lstat(buf, &cur_file_stat) == -1 )
+ {
+ if( cmd_tok&(NO_SOURCE|OK_NO_SOURCE) )
+ exec_for_item(0, buf);
+ else
+ warning(errno, "", buf);
+ return;
+ }
+ if( !flg_force && ( cmd_tok&NO_SOURCE ))
+ {
+ error(EEXIST, "", buf);
+ return;
+ }
+
+ if( S_ISDIR(cur_file_stat.st_mode))
+ {
+ if( (cmd_tok&OK_DIR) || flg_recurse )
+ (void) exec_for_subdir(buf);
+ else
+ error(EISDIR, "", buf);
+ return;
+ }
+
+#ifdef S_IFLNK
+ if( S_ISLNK(cur_file_stat.st_mode))
+ {
+ /* Links are special */
+ if( cmd_tok&IGN_LNK )
+ {
+ if( stat(buf, &cur_file_stat) == -1 )
+ {
+ warning(errno, "", buf);
+ return;
+ }
+ }
+ }
+#endif
+ exec_for_item(0, buf);
+}
+
+int exec_for_subdir(dname)
+char * dname;
+{
+ DIR * dfd;
+ struct dirent * ent;
+ int old_mode = -1;
+
+ if( cmd_tok&DO_BDIR ) exec_for_item(-1, dname);
+
+ if( flg_recurse )
+ {
+ dfd = opendir(dname);
+
+ if( dfd == 0 && errno == EACCES && flg_force )
+ {
+ old_mode = (cur_file_stat.st_mode & 07777);
+ if( chmod(dname, (0700|old_mode)) )
+ return error(errno, "Can't unlock", dname);
+
+ dfd = opendir(dname);
+ }
+ if( dfd == 0 ) return error(errno, "Can't open", dname);
+
+ while((ent=readdir(dfd)))
+ {
+ if( strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0 )
+ continue;
+
+ alloca(0); /* Free up if using fake version */
+ execute(dname, ent->d_name);
+ }
+ closedir(dfd);
+ if( old_mode != -1 )
+ chmod(dname, old_mode);
+ }
+
+ if( cmd_tok&DO_ADIR )
+ {
+ lstat(dname, &cur_file_stat);
+ exec_for_item(1, dname);
+ }
+ return 0;
+}
+
+void exec_for_item(when, fname)
+int when; char * fname;
+{
+ int rv = -1;
+ switch(cmd_tok)
+ {
+ case CMD_FT: rv = cmd_ft(fname); break;
+
+ case CMD_CAT: rv = copy_file(fname, "-"); break;
+
+ case CMD_CHGRP: /* And fall */
+ case CMD_CHMOD: /* And fall */
+ case CMD_CHOWN: rv = copy_modes(fname); break;
+
+ case CMD_CP: rv = cmd_cp(fname); break;
+ case CMD_MV: rv = cmd_mv(fname); break;
+ case CMD_RM: rv = cmd_rm(fname); break;
+
+ case CMD_EXTAR: error(ENOSYS, "", ""); exit(1);
+
+ case CMD_LN+OK_DIR+OK_NO_SOURCE:
+ case CMD_LN: rv = cmd_ln(fname); break;
+
+ case CMD_INSTALL: error(EINVAL, "", "Bad program"); exit(1);
+
+ case CMD_MKDIR: rv = cmd_mkdir(fname); break;
+ case CMD_MKFIFO: rv = cmd_mkfifo(fname); break;
+#ifdef S_IFSOCK
+ case CMD_MKSOCK: rv = cmd_mksock(fname); break;
+#endif
+ case CMD_MKNOD: break;
+ }
+}
+
+void parse_perms(prefix, ustring)
+char * prefix; char * ustring;
+{
+ char * userstr;
+ char * groupstr;
+ char * modestr;
+ char * cp;
+ struct passwd * pwd = 0;
+ struct group * grp;
+
+ userstr = alloca(strlen(prefix) + strlen(ustring) + 2);
+ strcpy(userstr, prefix);
+ strcat(userstr, ustring);
+
+ /* Select User */
+ cp = strchr(userstr, ':');
+ if(!cp) cp = strchr(userstr, '.');
+ if(cp) *cp = '\0';
+
+ /* If there's a user */
+ if( *userstr != 0 )
+ {
+ pwd = getpwnam(userstr);
+ if(pwd == NULL)
+ {
+ if(!strisdigit(userstr) )
+ {
+ error(EINVAL, "Unknown user", userstr);
+ exit(1);
+ }
+ set_user = atoi(userstr);
+ }
+ else set_user = pwd->pw_uid;
+ endpwent();
+ }
+ if(cp)
+ {
+ groupstr = cp+1;
+ cp = strchr(groupstr, ':');
+ if(!cp) cp = strchr(groupstr, '.');
+ if(cp) *cp = '\0';
+ if( *groupstr != '\0' )
+ {
+ grp = getgrnam(groupstr);
+ if(grp == NULL)
+ {
+ if(!strisdigit(groupstr) )
+ {
+ error(EINVAL, "Unknown group", groupstr);
+ exit(1);
+ }
+ set_group = atoi(groupstr);
+ }
+ else set_group = grp->gr_gid;
+ endgrent();
+ }
+ else if( pwd )
+ set_group = pwd->pw_gid;
+ }
+ if(cp)
+ {
+ modestr = cp+1;
+ if(strisdigit(modestr))
+ set_mode = strtol(modestr, NULL, 8);
+ else
+ {
+ strncpy(mode_str, modestr, sizeof(mode_str)-1);
+ /* This is the time that the mode change will fail on syn error */
+ (void) edit_mode(u_mask, mode_str);
+ }
+ }
+
+ if( set_user < 0 && set_group < 0 && set_mode < 0 && *mode_str == 0)
+ {
+ error(EINVAL, "", "Permission string has no changes");
+ exit(1);
+ }
+}
+
+int edit_mode(mode, mode_str)
+int mode; char * mode_str;
+{
+ char * str=mode_str;
+static mtab[] = {0, 0111, 0222, 0333, 0444, 0555, 0666, 0777 };
+
+ int done_change = 0;
+ int isdir = S_ISDIR(mode);
+ int change_op = 0;
+ int change_mask = u_mask;
+ int v=0, s=0, nm=0;
+
+ for(; *mode_str; mode_str++)
+ {
+ switch(*mode_str)
+ {
+ case ',': change_op = 0;
+ change_mask=u_mask; continue;
+ case '=': change_op = 1; if(0) {
+ case '+': change_op = 2; } if(0) {
+ case '-': change_op = 3; }
+ v=0; nm=0;
+ if(strchr(",=+-", mode_str[1]) == 0 ) continue;
+ break;
+ case 'a': if(change_op) goto ch_error;
+ nm |= 07777; if(0) {
+ case 'u': nm |= 04700; s= 6; } if(0) {
+ case 'g': nm |= 02070; s= 3; } if(0) {
+ case 'o': nm |= 01007; s= 0; }
+ if(change_op==0) { change_mask=nm; continue; }
+ v |= mtab[(mode>>s)&7];
+ break;
+ case 'r': v |= 0444; break;
+ case 'w': v |= 0222; break;
+ case 'x': v |= 0111; break;
+ case 's': v |=06000; break;
+ case 't': v |=01000; break;
+ case 'X': v |= mtab[isdir]; break;
+ default: goto ch_error;
+ }
+ switch(change_op)
+ {
+ case 0: goto ch_error;
+ case 1: mode= ((mode&(~change_mask)) | (v&change_mask));
+ break;
+ case 2: mode= ( mode | (v&change_mask));
+ break;
+ case 3: mode= ( mode & ~(v&change_mask));
+ break;
+ }
+ done_change=1;
+ }
+ if(!done_change)
+ {
+ch_error:
+ error(EINVAL, "Invalid mode string", str);
+ exit(1);
+ }
+ return mode;
+}
+
+int
+cmd_ft(fname)
+char * fname;
+{
+static char oldpath[2048] = "~";
+static int last_uid=-1, last_gid=-1, last_mode=-1;
+ struct passwd * pptr;
+ struct group * gptr;
+
+ if( flg_verbose>1 )
+ {
+ char *p = 0;
+ if( fname[1] ) p = strrchr(fname, '/');
+ if( p )
+ {
+ *p = '\0';
+ if( strcmp(fname, oldpath) != 0 )
+ {
+ strcpy(oldpath, fname);
+ printf("%s/\n", oldpath);
+ }
+ *p = '/';
+ }
+ else if( *oldpath )
+ *oldpath = '\0';
+ if(p) printf("%s", p+1);
+ else printf("%s", fname);
+
+#ifdef S_IFLNK
+ if( S_ISLNK(cur_file_stat.st_mode))
+ {
+ char linkbuf[1024];
+ int v;
+ *linkbuf='\0';
+ v = readlink(fname, linkbuf, sizeof(linkbuf));
+ if(v>0) linkbuf[v] = '\0';
+ printf("\t+%s", linkbuf);
+ }
+ else
+#endif
+ if( cur_file_stat.st_mode != last_mode
+ || cur_file_stat.st_uid != last_uid
+ || cur_file_stat.st_gid != last_gid)
+ {
+ printf("\t");
+ if( cur_file_stat.st_uid != last_uid )
+ {
+ pptr = getpwuid(cur_file_stat.st_uid);
+ if( pptr )
+ printf("%s", pptr->pw_name);
+ else
+ printf("%d", cur_file_stat.st_uid);
+ }
+ printf(":");
+ if( cur_file_stat.st_gid != last_gid )
+ {
+ gptr = getgrgid(cur_file_stat.st_gid);
+ if( gptr )
+ printf("%s", gptr->gr_name);
+ else
+ printf("%d", cur_file_stat.st_gid);
+ }
+ if( (cur_file_stat.st_mode&07777) != (last_mode&07777) )
+ printf(":%03o", cur_file_stat.st_mode & 07777);
+
+ switch(cur_file_stat.st_mode & S_IFMT)
+ {
+ case S_IFDIR: printf("\td"); break;
+ case S_IFIFO: printf("\tp"); break;
+#ifdef S_IFSOCK
+ case S_IFSOCK: printf("\ts"); break;
+#endif
+ case S_IFBLK: printf("\tb,%d,%d", cur_file_stat.st_rdev>>8,
+ cur_file_stat.st_rdev&0xFF);
+ break;
+ case S_IFCHR: printf("\tc,%d,%d", cur_file_stat.st_rdev>>8,
+ cur_file_stat.st_rdev&0xFF);
+ break;
+ }
+ last_mode = ((cur_file_stat.st_mode&07777)|S_IFREG);
+ if( (cur_file_stat.st_mode&07000) ) last_mode = -1;
+ last_uid = cur_file_stat.st_uid;
+ last_gid = cur_file_stat.st_gid;
+ }
+ printf("\n");
+ }
+ else printf("%s\n", fname);
+
+ return 0;
+}
+
+int
+cmd_mkfifo(fname)
+char * fname;
+{
+ int rv;
+ int mode=0666;
+ if( set_mode >= 0 ) mode=set_mode;
+ rv = mknod(fname, S_IFIFO|mode, 0);
+ if(rv<0)
+ warning(errno, "Cannot create fifo", fname);
+ return rv;
+}
+
+#ifdef S_IFSOCK
+int
+cmd_mksock(fname)
+char * fname;
+{
+ int rv, fd, len;
+ struct sockaddr *adr;
+
+ len = strlen(fname)+1 + sizeof(*adr) - sizeof(adr->sa_data);
+ if( len < sizeof(*adr) ) len = sizeof(*adr);
+
+ adr = alloca(len+2);
+ adr->sa_family = AF_UNIX;
+ strcpy(adr->sa_data, fname);
+
+ rv = fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if( fd>=0 ) rv = bind(fd, adr, len);
+ if( fd>=0 ) close(fd);
+ if(set_mode >= 0 && chmod(fname, set_mode&07777) < 0 )
+ warning(errno, "Chmod", fname);
+
+ if(rv<0)
+ warning(errno, "Cannot create socket", fname);
+ return rv;
+}
+#endif
+
+int
+cmd_rm(fname)
+char * fname;
+{
+ struct stat dirstat;
+ int rv;
+ char * buf, * p;
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ if( !flg_recurse ) return error(EISDIR, "", fname);
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ {
+ if( rmdir(fname) >= 0 ) return 0;
+ }
+ else
+ {
+ if( unlink(fname) >= 0 ) return 0;
+ }
+
+ if( !flg_force )
+ return error(errno, "", fname);
+
+ /* Try VERY hard */
+ buf = alloca(strlen(fname)+4);
+ strcpy(buf, fname);
+ p = strrchr(buf, '/');
+ if( p ) strcpy(p+1, "."); else strcpy(buf, ".");
+
+ if( stat(buf, &dirstat) < 0 ) return -1;
+ if( chmod(buf, dirstat.st_mode|0700) < 0 ) return -1;
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ rv = rmdir(fname);
+ else
+ rv = unlink(fname);
+
+ chmod(buf, dirstat.st_mode);
+
+ return rv;
+}
+
+void
+build_dest(dest, name, newpath)
+char * dest; char * name; char * newpath;
+{
+ char * p;
+ strcpy(dest, newpath);
+ if( add_base )
+ {
+ strcat(dest, "/");
+ p = strrchr(or_name, '/');
+ if(p==0) strcat(dest, or_name);
+ else strcat(dest, p+1);
+ }
+ if(strlen(name) <= or_offset) return;
+ strcat(dest, name+or_offset);
+}
+
+int
+strisdigit(str)
+char * str;
+{
+ if( str==0 || *str == 0 ) return 0;
+
+ for(;*str; str++)
+ if(*str>'9'|| *str<'0') return 0;
+ return 1;
+}
+
+int
+cmd_mv(fname)
+char * fname;
+{
+ char * destfile;
+ destfile = alloca(strlen(fname)+strlen(cmd_string)+4);
+
+ build_dest(destfile, fname, cmd_string);
+
+ if( !flg_force && lstat(destfile, &access_stat) == 0 )
+ return error(EEXIST, "", destfile);
+
+ if( rename(fname, destfile) == 0 ) return 0;
+
+ if( errno != EXDEV )
+ return error(errno, "", fname);
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ return error(EISDIR, "Can't rename across devices", fname);
+
+ if( copy_file(fname, destfile) != 0 ) return -1;
+ copy_modes(destfile);
+ return unlink(fname);
+}
+
+int
+cmd_ln(fname)
+char * fname;
+{
+ char * destfile;
+ destfile = alloca(strlen(fname)+strlen(cmd_string)+4);
+
+ build_dest(destfile, fname, cmd_string);
+
+ if( lstat(destfile, &access_stat) != -1 )
+ {
+ if( !flg_force ) return error(EEXIST, "", destfile);
+ cmd_rm(destfile);
+ }
+
+#ifdef S_IFLNK
+ if( flg_symlink )
+ {
+ if( symlink(fname, destfile) == 0 ) return 0;
+ }
+ else
+ {
+#endif
+ if( link(fname, destfile) == 0 ) return 0;
+#ifdef S_IFLNK
+ }
+#endif
+
+ return error(errno, "", destfile);
+}
+
+int
+cmd_cp(fname)
+char * fname;
+{
+ struct stat dest_stat;
+ char * destfile;
+ int no_dest = 0;
+
+ destfile = alloca(strlen(fname)+strlen(cmd_string)+4);
+
+ build_dest(destfile, fname, cmd_string);
+
+ if( stat(destfile, &dest_stat) >= 0 )
+ {
+ if( dest_stat.st_ino == cur_file_stat.st_ino
+ && dest_stat.st_dev == cur_file_stat.st_dev )
+ {
+ warning(EPERM, "Can't copy file to itself", fname);
+ return -1;
+ }
+ }
+ else no_dest = 1;
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ {
+ if( !no_dest )
+ {
+ if( S_ISDIR(dest_stat.st_mode) ) return 0;
+ if( unlink(destfile) < 0 )
+ return error(errno, "Can't delete", destfile);
+ }
+ return cmd_mkdir(destfile);
+ }
+ else if( S_ISDIR(dest_stat.st_mode) )
+ return error(EPERM, "Can't copy non-directory to directory", destfile);
+ else if( S_ISREG(cur_file_stat.st_mode) )
+ {
+ /* Copy_ok - do we want to force a real file */;
+ if( flg_force && !no_dest && !S_ISREG(dest_stat.st_mode) )
+ cmd_rm(destfile);
+ }
+ else if( flg_recurse ) /* Don't copy other things while recursing */
+ {
+ return error(EPERM, "Can't copy", fname);
+ }
+
+ if( copy_file(fname, destfile) != 0 ) return -1;
+ if( flg_preserve ) copy_modes(destfile);
+ return 0;
+}
+
+int
+copy_modes(file)
+char * file;
+{
+ int user, group, mode;
+ /* chown turns off set[ug]id bits for non-root,
+ so do the chmod last. */
+
+ /* Try to copy the old file's modtime and access time. */
+ if(set_time)
+ {
+ struct utimbuf tv;
+
+ tv.actime = cur_file_stat.st_atime;
+ tv.modtime = cur_file_stat.st_mtime;
+ if( set_time != -1 )
+ tv.modtime = set_time;
+ if (utime (file, &tv) && !flg_force)
+ return error (errno, "", file);
+ }
+
+ /* Try to preserve ownership. For non-root it might fail, but that's ok.
+ But root probably wants to know, e.g. if NFS disallows it. */
+ user = cur_file_stat.st_uid; if(set_user>=0) user = set_user;
+ group = cur_file_stat.st_gid; if(set_group>=0) group = set_group;
+
+ if (chown (file, user, group)
+ && (errno != EPERM || geteuid() == 0 || (flg_preserve==0 && flg_force==0)))
+ error (errno, "Can't change perms for", file);
+
+ mode = cur_file_stat.st_mode;
+ if(set_mode>=0) mode=set_mode;
+ else if(*mode_str)
+ mode = edit_mode(mode, mode_str);
+
+ if (chmod (file, mode & 07777))
+ return error (errno, "", file);
+
+ return 0;
+}
+
+/* This copies from something to a file or stdout */
+/* If the source has zero blocks (possibly holes) the destination
+ * is built with holes (assuming it's a normal file) */
+
+int
+copy_file(source, dest)
+char * source; char * dest;
+{
+ char * buf;
+ int sfd, dfd;
+ struct stat st;
+ int blksz = BUFSIZ;
+ int cc;
+ char * ptr;
+ int hole_flag = 0;
+ int retv = 0;
+ int no_seek;
+ int mmode = 0666;
+
+ if(flg_verbose>1) printf("%s -> %s\n", source, dest);
+ if( strcmp(source, "-") == 0 )
+ sfd = 0;
+ else
+ {
+ sfd = open(source, O_RDONLY);
+ if(sfd<0) return error(errno, "", source);
+ mmode = (cur_file_stat.st_mode&0777);
+ }
+
+ if( strcmp(dest, "-") == 0 )
+ dfd = 1;
+ else
+ {
+ dfd = open(dest, O_WRONLY|O_TRUNC|O_CREAT, mmode);
+ if(dfd<0)
+ {
+ close(sfd);
+ return error(errno, "Cannot create", source);
+ }
+ }
+
+ if( fstat(dfd, &st) )
+ {
+ retv = error(errno, "", dest);
+ no_seek = 1;
+ }
+ else
+ {
+#ifndef __BCC__
+ blksz = st.st_blksize;
+#endif
+ no_seek = !S_ISREG(st.st_mode);
+ }
+ buf = alloca(blksz + sizeof(int));
+ if( buf == 0 ) return error(0, "Out of memory", "");
+
+ for(;;)
+ {
+ cc = read(sfd, buf, blksz);
+ if(cc<0)
+ {
+ retv = error(errno, "", source);
+ goto exit_now;
+ }
+ if(cc==0) break;
+ buf[cc] = 1;
+ for(ptr=buf; *ptr==0 ; ptr++) ;
+ if((hole_flag = (ptr == buf+cc)))
+ { /* Make a hole */
+ if( lseek(dfd, (off_t) cc, SEEK_CUR) < 0 )
+ {
+ retv = error(errno, "", dest);
+ goto exit_now;
+ }
+ }
+ else
+ {
+ if( cc != write(dfd, buf, cc))
+ {
+ retv = error(errno, "", dest);
+ goto exit_now;
+ }
+ }
+ }
+ if( hole_flag )
+ {
+ if( lseek(dfd, (off_t) -1, SEEK_CUR) < 0
+ || write(dfd, "", 1) != 1 )
+ {
+ retv = error(errno, "", dest);
+ goto exit_now;
+ }
+ }
+
+exit_now:
+ if(sfd>2) close(sfd);
+ if(dfd>2) close(dfd);
+ return retv;
+}
+
+void
+Usage()
+{
+ int i;
+
+ printf("FileTool Usage: %s%s", prog_name[0]=='-'?"ft -":"", prog_name);
+ if( cmd_tok == CMD_FT )
+ {
+ printf(" --[com_name] [-options] [files]\n");
+ printf("\nAvailable commands are:\n");
+ }
+
+ for(i=1; command_list[i].name; i++)
+ {
+ if( cmd_tok == CMD_FT )
+ printf(" %s --%s", prog_name, command_list[i].name);
+ else if( cmd_tok != command_list[i].cmd )
+ continue;
+
+ if( *command_list[i].opts )
+ printf(" [-%s]", command_list[i].opts);
+ switch(command_list[i].argpat)
+ {
+ case 1: printf(" <info> [files]"); break;
+ case -1: printf(" [files] [dest]"); break;
+ case 0: printf(" [files]"); break;
+ default: printf(" path [bcu] major minor"); break;
+ }
+ printf("\n");
+ }
+
+ exit(99);
+}
+
+int
+cmd_mkdir(dirname)
+char * dirname;
+{
+ int retv;
+ int mode = 0777;
+ if( set_mode >= 0 ) mode = set_mode;
+
+ retv = mkdir(dirname, mode);
+ if(retv<0)
+ {
+ if(flg_mkpdir && errno == ENOENT)
+ {
+ /* Create parents */
+ }
+ }
+ if( retv>=0 && cmd_tok == CMD_MKDIR )
+ {
+ if( set_user > 0 || set_group > 0 )
+ {
+ if( chown(dirname, set_user, set_group) < 0)
+ warning(errno, "Cannot change directory owner", dirname);
+ else if( chmod (dirname, mode & 07777) )
+ warning(errno, "", dirname);
+ }
+ }
+
+ if(retv<0) error(errno, "Cannot create directory", dirname);
+ return retv;
+}
+
+int
+cmd_mknod()
+{
+ int device;
+ int rv = -1;
+ int mode=0666;
+ if( set_mode >= 0 ) mode=set_mode;
+
+ device = (atoi(flist[2])<<8) + atoi(flist[3]);
+
+ if(flist[1][0] == 'b')
+ rv = mknod(flist[0], S_IFBLK|mode, device);
+ else if(flist[1][0] == 'c' || flist[1][0] == 'u')
+ rv = mknod(flist[0], S_IFCHR|mode, device);
+ else Usage();
+
+ if(rv<0)
+ {
+ error(errno, "", flist[0]);
+ exit(1);
+ }
+ return rv;
+}
+
+int
+warn_func(enumber, estr, eobj)
+int enumber; char * estr; char * eobj;
+{
+ if(flg_verbose)
+ return error_func(enumber, estr, eobj);
+ return 0;
+}
+
+int
+error_func(enumber, estr, eobj)
+int enumber; char * estr; char * eobj;
+{
+ fprintf(stderr, "%s%s(%d): ", prog_name[0]=='-'?"ft":"", prog_name, Line_no);
+ fprintf(stderr, "%s%s%s: %s\n", estr, (*estr?" ":""), eobj, strerror(enumber));
+ return -1;
+}
diff --git a/libc-0.0.4/tests/grab.c b/libc-0.0.4/tests/grab.c
new file mode 100755
index 0000000..bd62a0f
--- /dev/null
+++ b/libc-0.0.4/tests/grab.c
@@ -0,0 +1,80 @@
+
+#include <stdio.h>
+#include <malloc.h>
+
+struct s
+{
+ struct s * n;
+ char v[1];
+};
+
+#define M ((unsigned)-1>>1)
+#define V (M^(M>>1))
+
+main (argc,argv)
+int argc;
+char ** argv;
+{
+ struct s * ptr1 = 0;
+ struct s * ptr2;
+ struct s * ptr3;
+ int i,sz;
+ long total = 0;
+
+ for(i=0, sz=256 ; i<32; i++, sz = ((sz << 1) | (sz & V)) & M)
+ {
+ ptr2 = (struct s *) malloc(sz-sizeof(int));
+ printf("%2d(%8u)..%08lx..%ld\n",i,sz,(long)ptr2,(long)ptr2);
+ if(ptr2==0) break;
+ total+=sz;
+ if(ptr1==0)
+ {
+ ptr1 = ptr3 = ptr2;
+ ptr3->n = 0;
+ }
+ else
+ {
+ ptr3->n = ptr2;
+ ptr3 = ptr2;
+ ptr3->n = 0;
+ }
+ }
+ for(sz>>=1; sz>255; )
+ {
+ ptr2 = (struct s *) malloc(sz-sizeof(int));
+ if(ptr2==0) { sz >>=1; continue; }
+ printf("%2d(%8u)..%08lx..%ld\n",i++,sz,(long)ptr2,(long)ptr2);
+ total+=sz;
+ if(ptr1==0)
+ {
+ ptr1 = ptr3 = ptr2;
+ ptr3->n = 0;
+ }
+ else
+ {
+ ptr3->n = ptr2;
+ ptr3 = ptr2;
+ ptr3->n = 0;
+ }
+ }
+ printf("Free all - total was %ldK bytes\n", total/1024);
+ while( ptr1 )
+ {
+ ptr3 = ptr1->n;
+ free(ptr1);
+ ptr1 = ptr3;
+ }
+ ptr2 = (struct s *) malloc(200);
+ printf("%2d(%8u)..%08lx..%ld\n",i++,200,(long)ptr2,(long)ptr2);
+ ptr2 = (struct s *) malloc(30000);
+ printf("%2d(%8u)..%08lx..%ld\n",i++,30000,(long)ptr2,(long)ptr2);
+ ptr2 = (struct s *) malloc(20000);
+ printf("%2d(%8u)..%08lx..%ld\n",i++,20000,(long)ptr2,(long)ptr2);
+ sz = (256<<sizeof(int));
+ do
+ {
+ ptr2 = (struct s *) malloc(sz-sizeof(int));
+ printf("%2d(%8u)..%08lx..%ld\n",i++,sz,(long)ptr2,(long)ptr2);
+ }
+ while(ptr2 && i < 100);
+}
diff --git a/libc-0.0.4/tests/hd.c b/libc-0.0.4/tests/hd.c
new file mode 100644
index 0000000..f6af1f9
--- /dev/null
+++ b/libc-0.0.4/tests/hd.c
@@ -0,0 +1,90 @@
+#include <stdio.h>
+#include <ctype.h>
+
+int lastnum[16] = { -1 };
+long lastaddr = -1;
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ FILE * fd;
+ int j, ch;
+ char buf[20];
+ int num[16];
+ long offset = 0;
+
+#ifndef MSDOS
+ if( argc == 1 )
+ {
+ fd = stdin;
+ }
+ else
+#endif
+ {
+ if( argc == 3 ) offset = strtol(argv[2], (char*)0, 16);
+ else if( argc != 2 )
+ {
+ fprintf(stderr, "Usage: hd file [hexoffset]\n");
+ exit(1);
+ }
+ fd = fopen(argv[1], "rb");
+ if( fd == 0 )
+ {
+ fprintf(stderr, "Cannot open file '%s'\n", argv[1]);
+ exit(1);
+ }
+ }
+
+ /* if( offset ) fseek(fd, offset, 0); */
+
+ for(ch=0; ch!=EOF; offset+=16)
+ {
+ memset(buf, '\0', 16);
+ for(j=0; j<16; j++) num[j] = -1;
+ for(j=0; j<16; j++)
+ {
+ ch = fgetc(fd);
+ if( ch == EOF ) break;
+
+ num[j] = ch;
+ if( isascii(ch) && isprint(ch) ) buf[j] = ch;
+ else buf[j] = '.';
+ }
+ printline(offset, num, buf, ch==EOF);
+ }
+ fclose(fd);
+}
+
+printline(address, num, chr, eofflag)
+long address;
+int * num;
+char * chr;
+int eofflag;
+{
+ int j;
+
+ if( lastaddr >= 0 )
+ {
+ for(j=0; j<16; j++)
+ if( num[j] != lastnum[j] )
+ break;
+ if( j == 16 && !eofflag ) return;
+ if( lastaddr+16 != address )
+ printf("*\n");
+ }
+
+ lastaddr = address;
+ printf("%06lx:", address);
+ for(j=0; j<16; j++)
+ {
+ if( num[j] >= 0 )
+ printf(" %02x", num[j]);
+ else
+ printf(" ");
+ lastnum[j] = num[j];
+ num[j] = -1;
+ }
+
+ printf(" %.16s\n", chr);
+}
diff --git a/libc-0.0.4/tests/line2.c b/libc-0.0.4/tests/line2.c
new file mode 100644
index 0000000..6cc11ff
--- /dev/null
+++ b/libc-0.0.4/tests/line2.c
@@ -0,0 +1,15 @@
+
+#include <stdio.h>
+
+char buf[256];
+
+main()
+{
+ FILE * fd;
+ fd = fopen("/etc/passwd", "r");
+
+ while(fgets(buf, sizeof(buf), fd) != NULL)
+ {
+ printf(">>%s", buf);
+ }
+}
diff --git a/libc-0.0.4/tests/lines.c b/libc-0.0.4/tests/lines.c
new file mode 100644
index 0000000..6f3afb0
--- /dev/null
+++ b/libc-0.0.4/tests/lines.c
@@ -0,0 +1,36 @@
+
+#include <string.h>
+#include <fcntl.h>
+
+char *
+readline(fd)
+{
+static char linebuf[256];
+ int cc;
+ char * p;
+
+ cc = read(fd, linebuf, sizeof(linebuf)-1);
+ if( cc <= 0 ) return 0;
+ p = strchr(linebuf, '\n');
+ if( p == 0 ) p = linebuf+sizeof(linebuf)-1;
+ else
+ {
+ p++; lseek(fd, (long)(p-linebuf)-cc, 1);
+ }
+ *p = 0;
+ return linebuf;
+}
+
+main()
+{
+ int fd = open("/etc/passwd", O_RDONLY);
+ char * p;
+
+ if(fd<0) exit(1);
+
+ while( p=readline(fd) )
+ {
+ write(1, ">>", 2);
+ write(1, p, strlen(p));
+ }
+}
diff --git a/libc-0.0.4/tests/ls.c b/libc-0.0.4/tests/ls.c
new file mode 100755
index 0000000..8cae4d0
--- /dev/null
+++ b/libc-0.0.4/tests/ls.c
@@ -0,0 +1,1049 @@
+/* ls 3.2 - List files. Author: Kees J. Bot
+ *
+ * About the amount of bytes for heap + stack under Minix:
+ * Ls needs a average amount of 42 bytes per unserviced directory entry, so
+ * scanning 10 directory levels deep in an ls -R with 100 entries per directory
+ * takes 42000 bytes of heap. So giving ls 10000 bytes is tight, 20000 is
+ * usually enough, 40000 is pessimistic.
+ */
+
+/* Compile with the proper -D flag for your system:
+ *
+ * _MINIX Minix (1.5 or later)
+ * BSD BSD derived (has st_blocks)
+ * AMOEBA Amoeba's emulation of UNIX
+ */
+
+/* The array _ifmt[] is used in an 'ls -l' to map the type of a file to a
+ * letter. This is done so that ls can list any future file or device type
+ * other than symlinks, without recompilation. (Yes it's dirty.)
+ */
+char _ifmt[] = "0pcCd?bB-?l?s???";
+
+#define ifmt(mode) _ifmt[((mode) >> 12) & 0xF]
+
+#define nil 0
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef AMOEBA
+#undef S_IFLNK /* Liars */
+#endif
+#include <dirent.h>
+#include <time.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <fcntl.h>
+#if BSD || __minix_vmd
+#include <termios.h>
+#endif
+#if __minix_vmd
+#include <sys/ioctl.h>
+#endif
+
+#ifndef major
+#define major(dev) ((int) (((dev) >> 8) & 0xFF))
+#define minor(dev) ((int) (((dev) >> 0) & 0xFF))
+#endif
+
+#if !_MINIX
+#define SUPER_ID uid /* Let -A flag be default for SUPER_ID == 0. */
+#else
+#define SUPER_ID gid
+#endif
+
+#ifdef S_IFLNK
+int (*status)(const char *file, struct stat *stp);
+#else
+#define status stat
+#endif
+
+/* Basic disk block size is 512 except for one niche O.S. */
+#if _MINIX
+#define BLOCK 1024
+#else
+#define BLOCK 512
+#endif
+
+/* Some terminals ignore more than 80 characters on a line. Dumb ones wrap
+ * when the cursor hits the side. Nice terminals don't wrap until they have
+ * to print the 81st character. Wether we like it or not, no column 80.
+ */
+#ifdef TIOCGWINSZ
+int ncols= 79;
+#else
+#define ncols 79
+#endif
+
+#define NSEP 2 /* # spaces between columns. */
+
+#ifdef TIOCGWINSZ
+#define MAXCOLS 150
+#else
+#define MAXCOLS (1 + (ncols / (1+NSEP))) /* Max # of files per line. */
+#endif
+
+char *arg0; /* Last component of argv[0]. */
+int uid, gid; /* callers id. */
+int ex= 0; /* Exit status to be. */
+int istty; /* Output is on a terminal. */
+
+/* Safer versions of malloc and realloc: */
+
+void heaperr(void)
+{
+ fprintf(stderr, "%s: Out of memory\n", arg0);
+ exit(-1);
+}
+
+void *allocate(size_t n)
+/* Deliver or die. */
+{
+ void *a;
+
+ if ((a= malloc(n)) == nil) heaperr();
+ return a;
+}
+
+#define reallocate rllct /* Same as realloc under some compilers. */
+
+void *reallocate(void *a, size_t n)
+{
+ if ((a= realloc(a, n)) == nil) heaperr();
+ return a;
+}
+
+char allowed[] = "acdfgilnqrstu1ACFLMRTX";
+char flags[sizeof(allowed)];
+
+char arg0flag[] = "cfmrtx"; /* These in argv[0] go to upper case. */
+
+void setflags(char *flgs)
+{
+ int c;
+
+ while ((c= *flgs++) != 0) {
+ if (strchr(allowed, c) == nil) {
+ fprintf(stderr, "Usage: %s -[%s] [file ...]\n",
+ arg0, allowed);
+ exit(1);
+ } else
+ if (strchr(flags, c) == nil)
+ flags[strlen(flags)] = c;
+ }
+}
+
+int present(int f)
+{
+ return f == 0 || strchr(flags, f) != nil;
+}
+
+void report(char *f)
+/* Like perror(3), but in the style: "ls: junk: No such file or directory. */
+{
+ fprintf(stderr, "%s: %s: %s\n", arg0, f, strerror(errno));
+ ex= 1;
+}
+
+/* Two functions, uidname and gidname, translate id's to readable names.
+ * All names are remembered to avoid searching the password file.
+ */
+#define NNAMES (1 << (sizeof(int) + sizeof(char *)))
+enum whatmap { PASSWD, GROUP };
+
+struct idname { /* Hash list of names. */
+ struct idname *next;
+ char *name;
+ uid_t id;
+} *uids[NNAMES], *gids[NNAMES];
+
+char *idname(unsigned id, enum whatmap map)
+/* Return name for a given user/group id. */
+{
+ struct idname *i;
+ struct idname **ids= &(map == PASSWD ? uids : gids)[id % NNAMES];
+
+ while ((i= *ids) != nil && id < i->id) ids= &i->next;
+
+ if (i == nil || id != i->id) {
+ /* Not found, go look in the password or group map. */
+ char *name= nil;
+ char noname[3 * sizeof(uid_t)];
+
+ if (!present('n')) {
+ if (map == PASSWD) {
+ struct passwd *pw= getpwuid(id);
+
+ if (pw != nil) name= pw->pw_name;
+ } else {
+ struct group *gr= getgrgid(id);
+
+ if (gr != nil) name= gr->gr_name;
+ }
+ }
+ if (name == nil) {
+ /* Can't find it, weird. Use numerical "name." */
+ sprintf(noname, "%u", id);
+ name= noname;
+ }
+
+ /* Add a new id-to-name cell. */
+ i= allocate(sizeof(*i));
+ i->id= id;
+ i->name= allocate(strlen(name) + 1);
+ strcpy(i->name, name);
+ i->next= *ids;
+ *ids= i;
+ }
+ return i->name;
+}
+
+#define uidname(uid) idname((uid), PASSWD)
+#define gidname(gid) idname((gid), GROUP)
+
+/* Path name construction, addpath adds a component, delpath removes it.
+ * The string path is used throughout the program as the file under examination.
+ */
+
+char *path; /* Path name constructed in path[]. */
+int plen= 0, pidx= 0; /* Lenght/index for path[]. */
+
+void addpath(int *didx, char *name)
+/* Add a component to path. (name may also be a full path at the first call)
+ * The index where the current path ends is stored in *pdi.
+ */
+{
+ if (plen == 0) path= (char *) allocate((plen= 32) * sizeof(path[0]));
+
+ if (pidx == 1 && path[0] == '.') pidx= 0; /* Remove "." */
+
+ *didx= pidx; /* Record point to go back to for delpath. */
+
+ if (pidx > 0 && path[pidx-1] != '/') path[pidx++]= '/';
+
+ do {
+ if (*name != '/' || pidx == 0 || path[pidx-1] != '/') {
+ if (pidx == plen)
+ path= (char *) reallocate((void *) path,
+ (plen*= 2) * sizeof(path[0]));
+ path[pidx++]= *name;
+ }
+ } while (*name++ != 0);
+
+ --pidx; /* Put pidx back at the null. The path[pidx++]= '/'
+ * statement will overwrite it at the next call.
+ */
+}
+
+#define delpath(didx) (path[pidx= didx]= 0) /* Remove component. */
+
+int field = 0; /* (used to be) Fields that must be printed. */
+ /* (now) Effects triggered by certain flags. */
+
+#define F_INODE 0x001 /* -i */
+#define F_BLOCKS 0x002 /* -s */
+#define F_EXTRA 0x004 /* -X */
+#define F_MODE 0x008 /* -lMX */
+#define F_LONG 0x010 /* -l */
+#define F_GROUP 0x020 /* -g */
+#define F_BYTIME 0x040 /* -tuc */
+#define F_ATIME 0x080 /* -u */
+#define F_CTIME 0x100 /* -c */
+#define F_MARK 0x200 /* -F */
+#define F_TYPE 0x400 /* -T */
+#define F_DIR 0x800 /* -d */
+
+struct file { /* A file plus stat(2) information. */
+ struct file *next; /* Lists are made of them. */
+ char *name; /* Null terminated name. */
+ ino_t ino;
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+ nlink_t nlink;
+ dev_t rdev;
+ off_t size;
+ time_t mtime;
+ time_t atime;
+ time_t ctime;
+#if BSD
+ long blocks;
+#endif
+};
+
+void setstat(struct file *f, struct stat *stp)
+{
+ f->ino= stp->st_ino;
+ f->mode= stp->st_mode;
+ f->nlink= stp->st_nlink;
+ f->uid= stp->st_uid;
+ f->gid= stp->st_gid;
+ f->rdev= stp->st_rdev;
+ f->size= stp->st_size;
+ f->mtime= stp->st_mtime;
+ f->atime= stp->st_atime;
+ f->ctime= stp->st_ctime;
+#if BSD
+ f->blocks= stp->st_blocks;
+#endif
+}
+
+#define PAST (26*7*24*3600L) /* Half a year ago. */
+/* Between PAST and FUTURE from now a time is printed, otherwise a year. */
+#define FUTURE (15*60L) /* Fifteen minutes. */
+
+static char *timestamp(struct file *f)
+/* Transform the right time field into something readable. */
+{
+ struct tm *tm;
+ time_t t;
+ static time_t now;
+ static int drift= 0;
+ static char date[] = "Jan 19 2038";
+ static char month[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+
+ t= f->mtime;
+ if (field & F_ATIME) t= f->atime;
+ if (field & F_CTIME) t= f->ctime;
+
+ tm= localtime(&t);
+ if (--drift < 0) { time(&now); drift= 50; } /* limit time() calls */
+
+ if (t < now - PAST || t > now + FUTURE) {
+ sprintf(date, "%.3s %2d %4d",
+ month + 3*tm->tm_mon,
+ tm->tm_mday,
+ 1900 + tm->tm_year);
+ } else {
+ sprintf(date, "%.3s %2d %02d:%02d",
+ month + 3*tm->tm_mon,
+ tm->tm_mday,
+ tm->tm_hour, tm->tm_min);
+ }
+ return date;
+}
+
+char *permissions(struct file *f)
+/* Compute long or short rwx bits. */
+{
+ static char rwx[] = "drwxr-x--x";
+
+ rwx[0] = ifmt(f->mode);
+ /* Note that rwx[0] is a guess for the more alien file types. It is
+ * correct for BSD4.3 and derived systems. I just don't know how
+ * "standardized" these numbers are.
+ */
+
+ if (field & F_EXTRA) { /* Short style */
+ int mode = f->mode, ucase= 0;
+
+ if (uid == f->uid) /* What group of bits to use. */
+ /* mode<<= 0, */
+ ucase= (mode<<3) | (mode<<6);
+ /* Remember if group or others have permissions. */
+ else
+ if (gid == f->gid)
+ mode<<= 3;
+ else
+ mode<<= 6;
+
+ rwx[1]= mode&S_IRUSR ? (ucase&S_IRUSR ? 'R' : 'r') : '-';
+ rwx[2]= mode&S_IWUSR ? (ucase&S_IWUSR ? 'W' : 'w') : '-';
+
+ if (mode&S_IXUSR) {
+ static char sbit[]= { 'x', 'g', 'u', 's' };
+
+ rwx[3]= sbit[(f->mode&(S_ISUID|S_ISGID))>>10];
+ if (ucase&S_IXUSR) rwx[3] += 'A'-'a';
+ } else
+ rwx[3]= f->mode&(S_ISUID|S_ISGID) ? '=' : '-';
+ rwx[4]= 0;
+ } else { /* Long form. */
+ char *p= rwx+1;
+ int mode= f->mode;
+
+ do {
+ p[0] = (mode & S_IRUSR) ? 'r' : '-';
+ p[1] = (mode & S_IWUSR) ? 'w' : '-';
+ p[2] = (mode & S_IXUSR) ? 'x' : '-';
+ mode<<= 3;
+ } while ((p+=3) <= rwx+7);
+
+ if (f->mode&S_ISUID) rwx[3]= f->mode&(S_IXUSR>>0) ? 's' : '=';
+ if (f->mode&S_ISGID) rwx[6]= f->mode&(S_IXUSR>>3) ? 's' : '=';
+ if (f->mode&S_ISVTX) rwx[9]= f->mode&(S_IXUSR>>6) ? 't' : '=';
+ }
+ return rwx;
+}
+
+void numeral(int i, char **pp)
+{
+ char itoa[3*sizeof(int)], *a=itoa;
+
+ do *a++ = i%10 + '0'; while ((i/=10) > 0);
+
+ do *(*pp)++ = *--a; while (a>itoa);
+}
+
+#define K 1024L /* A kilobyte counts in multiples of K */
+#define T 1000L /* A megabyte in T*K, a gigabyte in T*T*K */
+
+char *cxsize(struct file *f)
+/* Try and fail to turn a 32 bit size into 4 readable characters. */
+{
+ static char siz[] = "1.2m";
+ char *p= siz;
+ off_t z;
+
+ siz[1]= siz[2]= siz[3]= 0;
+
+ if (f->size <= 5*K) { /* <= 5K prints as is. */
+ numeral((int) f->size, &p);
+ return siz;
+ }
+ z= (f->size + K-1) / K;
+
+ if (z <= 999) { /* Print as 123k. */
+ numeral((int) z, &p);
+ *p = 'k'; /* Can't use 'K', looks bad */
+ } else
+ if (z*10 <= 99*T) { /* 1.2m (Try ls -X /dev/at0) */
+ z= (z*10 + T-1) / T; /* Force roundup */
+ numeral((int) z / 10, &p);
+ *p++ = '.';
+ numeral((int) z % 10, &p);
+ *p = 'm';
+ } else
+ if (z <= 999*T) { /* 123m */
+ numeral((int) ((z + T-1) / T), &p);
+ *p = 'm';
+ } else { /* 1.2g */
+ z= (z*10 + T*T-1) / (T*T);
+ numeral((int) z / 10, &p);
+ *p++ = '.';
+ numeral((int) z % 10, &p);
+ *p = 'g';
+ }
+ return siz;
+}
+
+/* Transform size of file to number of blocks. This was once a function that
+ * guessed the number of indirect blocks, but that nonsense has been removed.
+ */
+#if BSD
+#define nblocks(f) ((f)->blocks)
+#else
+#define nblocks(f) (((f)->size + BLOCK-1) / BLOCK)
+#endif
+
+/* From number of blocks to kilobytes. */
+#if BLOCK < 1024
+#define nblk2k(nb) (((nb) + (1024 / BLOCK - 1)) / (1024 / BLOCK))
+#else
+#define nblk2k(nb) ((nb) * (BLOCK / 1024))
+#endif
+
+static int (*CMP)(struct file *f1, struct file *f2);
+static int (*rCMP)(struct file *f1, struct file *f2);
+
+static void mergesort(struct file **al)
+/* This is either a stable mergesort, or thermal noise, I'm no longer sure.
+ * It must be called like this: if (L != nil && L->next != nil) mergesort(&L);
+ */
+{
+ /* static */ struct file *l1, **mid; /* Need not be local */
+ struct file *l2;
+
+ l1= *(mid= &(*al)->next);
+ do {
+ if ((l1= l1->next) == nil) break;
+ mid= &(*mid)->next;
+ } while ((l1= l1->next) != nil);
+
+ l2= *mid;
+ *mid= nil;
+
+ if ((*al)->next != nil) mergesort(al);
+ if (l2->next != nil) mergesort(&l2);
+
+ l1= *al;
+ for (;;) {
+ if ((*CMP)(l1, l2) <= 0) {
+ if ((l1= *(al= &l1->next)) == nil) {
+ *al= l2;
+ break;
+ }
+ } else {
+ *al= l2;
+ l2= *(al= &l2->next);
+ *al= l1;
+ if (l2 == nil) break;
+ }
+ }
+}
+
+int namecmp(struct file *f1, struct file *f2)
+{
+ return strcmp(f1->name, f2->name);
+}
+
+int mtimecmp(struct file *f1, struct file *f2)
+{
+ return f1->mtime == f2->mtime ? 0 : f1->mtime > f2->mtime ? -1 : 1;
+}
+
+int atimecmp(struct file *f1, struct file *f2)
+{
+ return f1->atime == f2->atime ? 0 : f1->atime > f2->atime ? -1 : 1;
+}
+
+int ctimecmp(struct file *f1, struct file *f2)
+{
+ return f1->ctime == f2->ctime ? 0 : f1->ctime > f2->ctime ? -1 : 1;
+}
+
+int typecmp(struct file *f1, struct file *f2)
+{
+ return ifmt(f1->mode) - ifmt(f2->mode);
+}
+
+int revcmp(struct file *f1, struct file *f2) { return (*rCMP)(f2, f1); }
+
+static void sort(struct file **al)
+/* Sort the files according to the flags. */
+{
+ if (!present('f') && *al != nil && (*al)->next != nil) {
+ CMP= namecmp;
+
+ if (!(field & F_BYTIME)) {
+ /* Sort on name */
+
+ if (present('r')) { rCMP= CMP; CMP= revcmp; }
+ mergesort(al);
+ } else {
+ /* Sort on name first, then sort on time. */
+
+ mergesort(al);
+ if (field & F_CTIME)
+ CMP= ctimecmp;
+ else
+ if (field & F_ATIME)
+ CMP= atimecmp;
+ else
+ CMP= mtimecmp;
+
+ if (present('r')) { rCMP= CMP; CMP= revcmp; }
+ mergesort(al);
+ }
+ /* Separate by file type if so desired. */
+
+ if (field & F_TYPE) {
+ CMP= typecmp;
+ mergesort(al);
+ }
+ }
+}
+
+struct file *newfile(char *name)
+/* Create file structure for given name. */
+{
+ struct file *new;
+
+ new= (struct file *) allocate(sizeof(*new));
+ new->name= strcpy((char *) allocate(strlen(name)+1), name);
+ return new;
+}
+
+void pushfile(struct file **flist, struct file *new)
+/* Add file to the head of a list. */
+{
+ new->next= *flist;
+ *flist= new;
+}
+
+void delfile(struct file *old)
+/* Release old file structure. */
+{
+ free((void *) old->name);
+ free((void *) old);
+}
+
+struct file *popfile(struct file **flist)
+/* Pop file off top of file list. */
+{
+ struct file *f;
+
+ f= *flist;
+ *flist= f->next;
+ return f;
+}
+
+int dotflag(char *name)
+/* Return flag that would make ls list this name: -a or -A. */
+{
+ if (*name++ != '.') return 0;
+
+ switch (*name++) {
+ case 0: return 'a'; /* "." */
+ case '.': if (*name == 0) return 'a'; /* ".." */
+ default: return 'A'; /* ".*" */
+ }
+}
+
+int adddir(struct file **aflist, char *name)
+/* Add directory entries of directory name to a file list. */
+{
+ DIR *d;
+ struct dirent *e;
+
+ if (access(name, 0) < 0) {
+ report(name);
+ return 0;
+ }
+
+ if ((d= opendir(name)) == nil) {
+ report(name);
+ return 0;
+ }
+ while ((e= readdir(d)) != nil) {
+ if (e->d_ino != 0 && present(dotflag(e->d_name))) {
+ pushfile(aflist, newfile(e->d_name));
+ aflist= &(*aflist)->next;
+ }
+ }
+ closedir(d);
+ return 1;
+}
+
+off_t countblocks(struct file *flist)
+/* Compute total block count for a list of files. */
+{
+ off_t cb = 0;
+
+ while (flist != nil) {
+ switch (flist->mode & S_IFMT) {
+ case S_IFDIR:
+ case S_IFREG:
+#ifdef S_IFLNK
+ case S_IFLNK:
+#endif
+ cb += nblocks(flist);
+ }
+ flist= flist->next;
+ }
+ return cb;
+}
+
+void printname(char *name)
+/* Print a name with control characters as '?' (unless -q). The terminal is
+ * assumed to be eight bit clean.
+ */
+{
+ int c, q= present('q');
+
+ while ((c= *name++) != 0) {
+ if (q && (c <= ' ' || c == 0177)) c= '?';
+ putchar(c);
+ }
+}
+
+int mark(struct file *f, int doit)
+{
+ int c;
+
+ if (!(field & F_MARK)) return 0;
+
+ switch (f->mode & S_IFMT) {
+ case S_IFDIR: c= '/'; break;
+#ifdef S_IFIFO
+ case S_IFIFO: c= '|'; break;
+#endif
+#ifdef S_IFLNK
+ case S_IFLNK: c= '@'; break;
+#endif
+#ifdef S_IFSOCK
+ case S_IFSOCK: c= '='; break;
+#endif
+ case S_IFREG:
+ if (f->mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
+ c= '*';
+ break;
+ }
+ default:
+ c= 0;
+ }
+ if (doit && c != 0) putchar(c);
+ return c;
+}
+
+int colwidth[MAXCOLS]; /* Need colwidth[i] spaces to print column i. */
+int sizwidth[MAXCOLS]; /* Spaces for the size field in a -X print. */
+int namwidth[MAXCOLS]; /* Name field. */
+
+int maxise(int *aw, int w)
+/* Set *aw to the larger of it and w. Then return it. */
+{
+ if (w > *aw) *aw= w;
+ return *aw;
+}
+
+static int nsp= 0; /* This many spaces have not been printed yet. */
+#define spaces(n) (nsp= (n))
+#define terpri() (nsp= 0, putchar('\n')) /* No trailing spaces */
+
+void print1(struct file *f, int col, int doit)
+/* Either compute the number of spaces needed to print file f (doit == 0) or
+ * really print it (doit == 1).
+ */
+{
+ int width= 0, n;
+ char *p;
+
+ while (nsp>0) { putchar(' '); nsp--; }/* Fill gap between two columns */
+
+ if (field & F_INODE) {
+ if (doit) printf("%5d ", f->ino); else width+= 6;
+ }
+ if (field & F_BLOCKS) {
+ if (doit) printf("%4ld ", nblk2k(nblocks(f))); else width+= 5;
+ }
+ if (field & F_MODE) {
+ if (doit)
+ printf("%s ", permissions(f));
+ else
+ width+= (field & F_EXTRA) ? 5 : 11;
+ }
+ if (field & F_EXTRA) {
+ p= cxsize(f);
+ n= strlen(p)+1;
+
+ if (doit) {
+ n= sizwidth[col] - n;
+ while (n > 0) { putchar(' '); --n; }
+ printf("%s ", p);
+ } else
+ width+= maxise(&sizwidth[col], n);
+ }
+ if (field & F_LONG) {
+ if (doit) {
+ printf("%2d %-8s ", f->nlink, uidname(f->uid));
+ if (field & F_GROUP) printf("%-8s ", gidname(f->gid));
+
+ switch (f->mode & S_IFMT) {
+ case S_IFBLK:
+ case S_IFCHR:
+#ifdef S_IFMPB
+ case S_IFMPB:
+#endif
+#ifdef S_IFMPC
+ case S_IFMPC:
+#endif
+ printf("%3d, %3d ",
+ major(f->rdev), minor(f->rdev));
+ break;
+ default:
+ printf("%8ld ", (long) f->size);
+ }
+ printf("%s ", timestamp(f));
+ } else
+ width += (field & F_GROUP) ? 43 : 34;
+ }
+ n= strlen(f->name);
+ if (doit) {
+ printname(f->name);
+ if (mark(f, 1) != 0) n++;
+#ifdef S_IFLNK
+ if ((field & F_LONG) && (f->mode & S_IFMT) == S_IFLNK) {
+ char *buf;
+ int r, didx;
+
+ buf= (char *) allocate(((size_t) f->size + 1)
+ * sizeof(buf[0]));
+ addpath(&didx, f->name);
+ r= readlink(path, buf, (int) f->size);
+ delpath(didx);
+ if (r > 0) buf[r] = 0; else r=1, strcpy(buf, "?");
+ printf(" -> ");
+ printname(buf);
+ free((void *) buf);
+ n+= 4 + r;
+ }
+#endif
+ spaces(namwidth[col] - n);
+ } else {
+ if (mark(f, 0) != 0) n++;
+#ifdef S_IFLNK
+ if ((field & F_LONG) && (f->mode & S_IFMT) == S_IFLNK) {
+ n+= 4 + (int) f->size;
+ }
+#endif
+ width+= maxise(&namwidth[col], n + NSEP);
+ maxise(&colwidth[col], width);
+ }
+}
+
+int countfiles(struct file *flist)
+/* Return number of files in the list. */
+{
+ int n= 0;
+
+ while (flist != nil) { n++; flist= flist->next; }
+
+ return n;
+}
+
+struct file *filecol[MAXCOLS]; /* filecol[i] is list of files for column i. */
+int nfiles, nlines; /* # files to print, # of lines needed. */
+
+int columnise(struct file *flist, int nplin)
+/* Chop list of files up in columns. Note that 3 columns are used for 5 files
+ * even though nplin may be 4, filecol[3] will simply be nil.
+ */
+{
+ int i, j;
+
+ nlines= (nfiles + nplin - 1) / nplin; /* nlines needed for nfiles */
+
+ filecol[0]= flist;
+
+ for (i=1; i<nplin; i++) { /* Give nlines files to each column. */
+ for (j=0; j<nlines && flist != nil; j++) flist= flist->next;
+
+ filecol[i]= flist;
+ }
+}
+
+int print(struct file *flist, int nplin, int doit)
+/* Try (doit == 0), or really print the list of files over nplin columns.
+ * Return true if it can be done in nplin columns or if nplin == 1.
+ */
+{
+ register struct file *f;
+ register int i, totlen;
+
+ columnise(flist, nplin);
+
+ if (!doit) {
+ if (nplin==1 && !(field & F_EXTRA))
+ return 1; /* No need to try 1 column. */
+
+ for (i=0; i<nplin; i++)
+ colwidth[i]= sizwidth[i]= namwidth[i]= 0;
+ }
+ while (--nlines >= 0) {
+ totlen=0;
+
+ for (i=0; i<nplin; i++) {
+ if ((f= filecol[i]) != nil) {
+ filecol[i]= f->next;
+ print1(f, i, doit);
+ }
+ if (!doit && nplin>1) {
+ /* See if this line is not too long. */
+ totlen+= colwidth[i];
+ if (totlen > ncols+NSEP) return 0;
+ }
+ }
+ if (doit) terpri();
+ }
+ return 1;
+}
+
+enum depth { SURFACE, SURFACE1, SUBMERGED };
+enum state { BOTTOM, SINKING, FLOATING };
+
+void listfiles(struct file *flist, enum depth depth, enum state state)
+/* Main workhorse of ls, it sorts and prints the list of files. Flags:
+ * depth: working with the command line / just one file / listing dir.
+ * state: How "recursive" do we have to be.
+ */
+{
+ struct file *dlist= nil, **afl= &flist, **adl= &dlist;
+ int nplin;
+ static int white = 1; /* Nothing printed yet. */
+
+ /* Flush everything previously printed, so new error output will
+ * not intermix with files listed earlier.
+ */
+ fflush(stdout);
+
+ if (field != 0 || state != BOTTOM) { /* Need stat(2) info. */
+ while (*afl != nil) {
+ static struct stat st;
+ int r, didx;
+
+ addpath(&didx, (*afl)->name);
+
+ if ((r= status(path, &st)) < 0
+#ifdef S_IFLNK
+ && (status == lstat || lstat(path, &st) < 0)
+#endif
+ ) {
+ if (depth != SUBMERGED || errno != ENOENT)
+ report((*afl)->name);
+ delfile(popfile(afl));
+ } else {
+ setstat(*afl, &st);
+ afl= &(*afl)->next;
+ }
+ delpath(didx);
+ }
+ }
+ sort(&flist);
+
+ if (depth == SUBMERGED && (field & (F_BLOCKS | F_LONG)))
+ printf("total %ld\n", nblk2k(countblocks(flist)));
+
+ if (state == SINKING || depth == SURFACE1) {
+ /* Don't list directories themselves, list their contents later. */
+ afl= &flist;
+ while (*afl != nil) {
+ if (((*afl)->mode & S_IFMT) == S_IFDIR) {
+ pushfile(adl, popfile(afl));
+ adl= &(*adl)->next;
+ } else
+ afl= &(*afl)->next;
+ }
+ }
+
+ if ((nfiles= countfiles(flist)) > 0) {
+ /* Print files in how many columns? */
+ nplin= !present('C') ? 1 : nfiles < MAXCOLS ? nfiles : MAXCOLS;
+
+ while (!print(flist, nplin, 0)) nplin--; /* Try first */
+
+ print(flist, nplin, 1); /* Then do it! */
+ white = 0;
+ }
+
+ while (flist != nil) { /* Destroy file list */
+ if (state == FLOATING && (flist->mode & S_IFMT) == S_IFDIR) {
+ /* But keep these directories for ls -R. */
+ pushfile(adl, popfile(&flist));
+ adl= &(*adl)->next;
+ } else
+ delfile(popfile(&flist));
+ }
+
+ while (dlist != nil) { /* List directories */
+ if (dotflag(dlist->name) != 'a' || depth != SUBMERGED) {
+ int didx;
+
+ addpath(&didx, dlist->name);
+
+ flist= nil;
+ if (adddir(&flist, path)) {
+ if (depth != SURFACE1) {
+ if (!white) putchar('\n');
+ printf("%s:\n", path);
+ white = 0;
+ }
+ listfiles(flist, SUBMERGED,
+ state == FLOATING ? FLOATING : BOTTOM);
+ }
+ delpath(didx);
+ }
+ delfile(popfile(&dlist));
+ }
+}
+
+int main(int argc, char **argv)
+{
+ struct file *flist= nil, **aflist= &flist;
+ enum depth depth;
+ char *lsflags;
+#ifdef TIOCGWINSZ
+ struct winsize ws;
+#endif
+
+ uid= geteuid();
+ gid= getegid();
+
+ if ((arg0= strrchr(argv[0], '/')) == nil) arg0= argv[0]; else arg0++;
+ argv++;
+
+ if (strcmp(arg0, "ls") != 0) {
+ char *p= arg0+1;
+
+ while (*p != 0) {
+ if (strchr(arg0flag, *p) != nil) *p += 'A' - 'a';
+ p++;
+ }
+ setflags(arg0+1);
+ }
+ while (*argv != nil && (*argv)[0] == '-') {
+ if ((*argv)[1] == '-' && (*argv)[2] == 0) {
+ argv++;
+ break;
+ }
+ setflags(*argv++ + 1);
+ }
+
+ istty= isatty(1);
+
+ if (istty && (lsflags= getenv("LSOPTS")) != nil) {
+ if (*lsflags == '-') lsflags++;
+ setflags(lsflags);
+ }
+
+ if (!present('1') && !present('C') && !present('l')
+ && (istty || present('M') || present('X') || present('F'))
+ ) setflags("C");
+
+ if (istty) setflags("q");
+
+ if (SUPER_ID == 0 || present('a')) setflags("A");
+
+ if (present('i')) field|= F_INODE;
+ if (present('s')) field|= F_BLOCKS;
+ if (present('M')) field|= F_MODE;
+ if (present('X')) field|= F_EXTRA|F_MODE;
+ if (present('t')) field|= F_BYTIME;
+ if (present('u')) field|= F_ATIME;
+ if (present('c')) field|= F_CTIME;
+ if (present('l')) {
+ field= (field | F_MODE | F_LONG) & ~F_EXTRA;
+ if (present('g')) field|= F_GROUP;
+ }
+ if (present('F')) field|= F_MARK;
+ if (present('T')) field|= F_TYPE;
+ if (present('d')) field|= F_DIR;
+
+#ifdef S_IFLNK
+ status= present('L') ? stat : lstat;
+#endif
+
+#ifdef TIOCGWINSZ
+ if (present('C')) {
+ int t= istty ? 1 : open("/dev/tty", O_WRONLY);
+
+ if (t >= 0 && ioctl(t, TIOCGWINSZ, &ws) == 0 && ws.ws_col > 0)
+ ncols= ws.ws_col - 1;
+
+ if (t != 1) close(t);
+ }
+#endif
+
+ depth= SURFACE;
+
+ if (*argv == nil) {
+ if (!(field & F_DIR)) depth= SURFACE1;
+ pushfile(aflist, newfile("."));
+ } else {
+ if (argv[1] == nil && !(field & F_DIR)) depth= SURFACE1;
+
+ do {
+ pushfile(aflist, newfile(*argv++));
+ aflist= &(*aflist)->next;
+ } while (*argv!=nil);
+ }
+ listfiles(flist, depth,
+ (field & F_DIR) ? BOTTOM : present('R') ? FLOATING : SINKING);
+ exit(ex);
+}
+/* Kees J. Bot 25-4-89. */
diff --git a/libc-0.0.4/tests/makefile b/libc-0.0.4/tests/makefile
new file mode 100644
index 0000000..150bf45
--- /dev/null
+++ b/libc-0.0.4/tests/makefile
@@ -0,0 +1,17 @@
+# Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+TOP=..
+include $(TOP)/Make.defs
+CFLAGS=$(CCFLAGS) -ansi
+
+default: all
+
+include Real_make
+
+fetch_them:
+ cp -p $(SRC) Real_make $(TOPDIR)/tests/.
+
+clean:
+ rm -f $(OBJ) $(EXE) $(LINK_FILES)
diff --git a/libc-0.0.4/tests/ouch.c b/libc-0.0.4/tests/ouch.c
new file mode 100644
index 0000000..c2925c6
--- /dev/null
+++ b/libc-0.0.4/tests/ouch.c
@@ -0,0 +1,27 @@
+
+#include <signal.h>
+#include <stdio.h>
+#include <errno.h>
+
+void trap()
+{
+ write(1, "Ouch!!\n", 7);
+}
+
+main()
+{
+ char buf[2];
+ int cc;
+
+ signal(SIGINT, trap);
+ while( (cc=read(0, buf, 1)) > 0 || (cc == -1 && errno == EINTR) )
+ {
+ if( cc < 0 )
+ fprintf(stderr, "INTR\n");
+ else
+ fprintf(stderr, "%x\n", buf[0]);
+ }
+
+
+ write(1, "\nExit!\n", 7);
+}
diff --git a/libc-0.0.4/tests/rand.c b/libc-0.0.4/tests/rand.c
new file mode 100644
index 0000000..c4fc6d2
--- /dev/null
+++ b/libc-0.0.4/tests/rand.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+FILE * popen();
+
+main()
+{
+ FILE * fd = popen("./hd", "w");
+ int ch;
+
+ srand(time((void*)0));
+
+ for(ch=0; ch<256; ch++)
+ putc(rand(), fd);
+
+ pclose(fd);
+}
diff --git a/libc-0.0.4/tests/size.c b/libc-0.0.4/tests/size.c
new file mode 100644
index 0000000..2d6676b
--- /dev/null
+++ b/libc-0.0.4/tests/size.c
@@ -0,0 +1,51 @@
+#include <fcntl.h>
+#include <a.out.h>
+
+void size(filename)
+ char *filename;
+{
+ int f;
+ struct exec ex;
+ long total;
+ int cc;
+
+ if ((f = open(filename, O_RDONLY)) < 0 )
+ {
+ perror(filename);
+ return;
+ }
+ cc = read(f, &ex, sizeof(ex));
+
+ if (cc == sizeof(ex) && !BADMAG(ex))
+ {
+ total = ex.a_text + ex.a_data + ex.a_bss;
+ printf("%-ld\t%-ld\t%-ld\t%-ld\t%-lx\t%s\n",
+ ex.a_text, ex.a_data, ex.a_bss, total, total,
+ filename);
+ }
+ else if( cc > 16 && memcmp(&ex, "\243\206\001\000*", 5) == 0 )
+ { /* *.o file */
+ total = ((unsigned char*)&ex)[9] +
+ ((unsigned char*)&ex)[10] * 256;
+ printf("\t\t\t%-ld\t%-lx\t%s\n",
+ total, total, filename);
+ }
+ else
+ printf("%s: Not an a.out file\n", filename);
+ close(f);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ if (argc < 2)
+ {
+ printf("Usage: %s file\n", argv[0]);
+ exit(1);
+ }
+ printf("text\tdata\tbss\tdec\thex\tfilename\n");
+ for (--argc, ++argv; argc > 0; --argc, ++argv)
+ size(*argv);
+ exit(0);
+}
diff --git a/libc-0.0.4/tests/sync.c b/libc-0.0.4/tests/sync.c
new file mode 100644
index 0000000..03ca096
--- /dev/null
+++ b/libc-0.0.4/tests/sync.c
@@ -0,0 +1 @@
+int main() { return sync(); }
diff --git a/libc-0.0.4/tests/ucomp.c b/libc-0.0.4/tests/ucomp.c
new file mode 100644
index 0000000..cc3eef8
--- /dev/null
+++ b/libc-0.0.4/tests/ucomp.c
@@ -0,0 +1,108 @@
+
+/*
+ * Uncompress program this is very very fast
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#define MAXLEN 255
+
+#define maxno 61000U
+#define USE_BSS
+
+#ifdef USE_BSS
+unsigned char fptr[maxno];
+#else
+unsigned char *fptr;
+#endif
+FILE * fd;
+int key;
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+#ifndef USE_BSS
+ fptr = (unsigned char * ) malloc(maxno);
+
+ if( fptr == 0 )
+ {
+ perror("Cannot allocate memory");
+ exit(1);
+ }
+#endif
+
+ if( argc < 2 )
+ {
+ fd = stdin;
+ key = getc(fd);
+ uncompress();
+ }
+ else
+ {
+ fd = fopen(argv[1], "r" );
+ if( fd == 0 ) { perror("Open failed"); exit(1); }
+
+ key = getc(fd);
+ uncompress();
+ }
+}
+
+/*
+
+ Uncompression routine -- v.v.fast
+*/
+
+uncompress()
+{
+ register unsigned char * mainscan;
+ register unsigned char * secondscan;
+ register unsigned char * ptr = (unsigned char * ) fptr;
+ register unsigned char * eptr = ptr+maxno;
+ register unsigned int len;
+ register int ch;
+
+ mainscan = ptr;
+
+ for(;;)
+ {
+ ch = getc(fd);
+ if(ch == EOF) break;
+ ch &= 0xFF;
+ if(ch == key)
+ {
+ ch = getc(fd);
+ if( ch == 0 )
+ *mainscan++ = key;
+ else
+ {
+ len = (unsigned char) getc(fd);
+ if( ch & 0x80 )
+ len += ((unsigned char) getc(fd)) << 8;
+ secondscan = mainscan - len;
+ if(len > mainscan - ptr) secondscan += maxno;
+ len = (unsigned char) ch & 0x7F;
+ for( ; len>0; len-- )
+ {
+ *mainscan++ = *secondscan++;
+ if( secondscan == eptr ) secondscan = ptr;
+ if( mainscan == eptr )
+ { write(1, ptr, (int)(mainscan-ptr)); mainscan = ptr; }
+ }
+ }
+ }
+ else
+ *mainscan++ = ch;
+
+ if( mainscan == eptr )
+ { write(1, ptr, (int)(mainscan-ptr)); mainscan = ptr; }
+ }
+ if( mainscan != ptr )
+ { write(1, ptr, (int)(mainscan-ptr)); mainscan = ptr; }
+}
+
diff --git a/libc-0.0.4/tests/wc.c b/libc-0.0.4/tests/wc.c
new file mode 100644
index 0000000..08b93ca
--- /dev/null
+++ b/libc-0.0.4/tests/wc.c
@@ -0,0 +1,133 @@
+
+#include <stdio.h>
+#include <ctype.h>
+
+int lflag; /* Want count lines */
+int wflag; /* Want count words */
+int cflag; /* Want count characters */
+
+long lcount; /* File count of lines */
+long wcount; /* File count of words */
+long ccount; /* File count of characters */
+
+long ltotal; /* Total count of lines */
+long wtotal; /* Total count of words */
+long ctotal; /* Total count of characters */
+
+int
+main(argc, argv)
+int argc;
+char **argv;
+{
+ char *p;
+ int ar;
+
+ if (argc > 1 && argv[1][0] == '-')
+ {
+ for (p = argv[1] + 1; *p; p++)
+ {
+ switch (*p)
+ {
+ case 'l':
+ lflag++;
+ break;
+ case 'w':
+ wflag++;
+ break;
+ case 'c':
+ cflag++;
+ break;
+ default:
+ Usage();
+ }
+ }
+ argc--;
+ argv++;
+ }
+
+ /* If no flags are set, treat as wc -lwc. */
+ if (!lflag && !wflag && !cflag)
+ lflag = wflag = cflag = 1;
+
+ /* No filename, use stdin */
+ if (argc == 1)
+ {
+ count(stdin, "");
+ exit(0);
+ }
+
+ /* There is an explicit list of files. Loop on files. */
+ for (ar = 1; ar < argc; ar++)
+ {
+ FILE *f;
+
+ if ((f = fopen(argv[ar], "r")) == NULL)
+ fprintf(stderr, "wc: cannot open %s\n", argv[ar]);
+ else
+ {
+ count(f, argv[ar]);
+ fclose(f);
+ }
+ }
+
+ if (argc > 2)
+ {
+ if (lflag)
+ printf("%7ld ", ltotal);
+ if (wflag)
+ printf("%7ld ", wtotal);
+ if (cflag)
+ printf("%7ld ", ctotal);
+ printf("total\n");
+ }
+ exit(0);
+}
+
+count(f, fname)
+FILE *f;
+char *fname;
+{
+ register int c;
+ register int inword = 0;
+
+ lcount = 0;
+ wcount = 0;
+ ccount = 0;
+
+ while ((c = getc(f)) != EOF)
+ {
+ ccount++;
+
+ if (isspace(c))
+ {
+ if (inword)
+ wcount++;
+ inword = 0;
+ }
+ else
+ inword = 1;
+
+ if (c == '\n' || c == '\f')
+ lcount++;
+ }
+
+ ltotal += lcount;
+ wtotal += wcount;
+ ctotal += ccount;
+
+ if (lflag)
+ printf("%7ld ", lcount);
+ if (wflag)
+ printf("%7ld ", wcount);
+ if (cflag)
+ printf("%7ld ", ccount);
+ if (fname && *fname)
+ printf("%s", fname);
+ printf("\n");
+}
+
+Usage()
+{
+ fprintf(stderr, "Usage: wc [-lwc] [name ...]\n");
+ exit(1);
+}
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..52eb94a
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,23 @@
+# Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+# This file is part of the Linux-8086 C library and is distributed
+# under the GNU Library General Public License.
+
+CC=bcc
+CFLAGS=-O -ansi
+LDFLAGS=
+
+ifeq (Real_make,$(wildcard Real_make))
+include Real_make
+endif
+
+ifneq ($(TOPDIR),)
+starter:
+ make -C ../libc/tests fetch_them
+ make all
+endif
+
+not_from_here:
+ @echo Do make tests from the top directory
+
+clean:
+ rm -f Real_make $(SRC) $(OBJ) $(EXE) $(LINK_FILES)
diff --git a/unproto/Makefile b/unproto/Makefile
new file mode 100644
index 0000000..638be25
--- /dev/null
+++ b/unproto/Makefile
@@ -0,0 +1,97 @@
+# @(#) Makefile 1.3 91/12/01 12:37:57
+
+## BEGIN CONFIGURATION STUFF
+
+# For maximal flexibility, the "/lib/cpp | unproto" pipeline can be
+# packaged as an executable shell script (see the provided "cpp.sh" script)
+# that should be installed as "/whatever/cpp". This script should then be
+# specified to the C compiler as a non-default preprocessor.
+#
+PROG = unproto
+PIPE =
+
+# For maximal performance, the overhead of shell script inpretation can
+# be eliminated by having the unprototyper program itself open the pipe
+# to the preprocessor. In that case, define the PIPE_THROUGH_CPP macro
+# as the path name of the default C preprocessor (usually "/lib/cpp"),
+# install the unprototyper as "/whatever/cpp" and specify that to the C
+# compiler as a non-default preprocessor.
+#
+# PROG = cpp
+# PIPE = -DPIPE_THROUGH_CPP=\"/lib/cpp\"
+
+# Some compilers complain about some #directives. The following is only a
+# partial solution, because the directives are still seen by /lib/cpp.
+# Be careful with filtering out #pragma, because some non-ANSI compilers
+# (SunOS) rely on its use.
+#
+# SKIP = -DIGNORE_DIRECTIVES=\"pragma\",\"foo\",\"bar\"
+#
+SKIP =
+
+# If you need support for functions that implement ANSI-style variable
+# length argument lists, edit the stdarg.h file provided with this
+# package so that it contains the proper definitions for your machine.
+
+## END CONFIGURATION STUFF
+
+SHELL = /bin/sh
+
+CFILES = tok_io.c tok_class.c tok_pool.c unproto.c vstring.c symbol.c error.c
+HFILES = error.h token.h vstring.h symbol.h
+SCRIPTS = cpp.sh
+SAMPLES = stdarg.h varargs.c example.c example.out
+SOURCES = README Makefile $(CFILES) $(HFILES) $(SCRIPTS) $(SAMPLES)
+FILES = $(SOURCES) unproto.1
+OBJECTS = tok_io.o tok_class.o tok_pool.o unproto.o vstring.o symbol.o error.o
+
+ifneq ($(TOPDIR),)
+include $(TOPDIR)/Make.defs
+CFLAGS=$(CCFLAGS) $(PIPE) $(SKIP)
+else
+CC=bcc
+CFLAGS=-O $(PIPE) $(SKIP)
+LDFLAGS=-s
+endif
+
+#CFLAGS = -O -pg -Dstatic= $(PIPE) $(SKIP)
+#CFLAGS = -g $(PIPE) $(SKIP) -DDEBUG
+
+$(PROG): $(OBJECTS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(MALLOC)
+
+install: $(PROG)
+ install -d $(LIBDIR)
+ install -m 755 $(PROG) $(LIBDIR)/unproto
+
+# For linting, enable all bells and whistles.
+
+lint:
+ lint -DPIPE_THROUGH_CPP=\"foo\" -DIGNORE_DIRECTIVES=\"foo\",\"bar\" \
+ $(CFILES)
+
+# Testing requires that the program is compiled with -DDEBUG
+
+test: $(PROG) example.c example.out
+ ./cpp example.c >example.tmp
+ @echo the following diff command should produce no output
+ diff -b example.out example.tmp
+ rm -f example.tmp
+
+shar: $(FILES)
+ @shar $(FILES)
+
+archive:
+ $(ARCHIVE) $(SOURCES)
+
+clean:
+ rm -f *.o core cpp unproto mon.out varargs.o varargs example.tmp
+
+error.o : error.c token.h error.h Makefile
+symbol.o : symbol.c token.h symbol.h Makefile
+tok_class.o : tok_class.c error.h vstring.h token.h symbol.h Makefile
+tok_io.o : tok_io.c token.h vstring.h error.h Makefile
+tok_pool.o : tok_pool.c token.h vstring.h Makefile
+unproto.o : unproto.c vstring.h stdarg.h token.h error.h symbol.h Makefile
+varargs.o : varargs.c stdarg.h Makefile
+vstring.o : vstring.c vstring.h Makefile
diff --git a/unproto/README b/unproto/README
new file mode 100644
index 0000000..6856d3a
--- /dev/null
+++ b/unproto/README
@@ -0,0 +1,130 @@
+@(#) README 1.3 91/12/01 12:37:55
+
+unproto - ANSI C to old C converter
+
+Purpose:
+
+This is a filter that sits in between the C preprocessor and the next C
+compiler stage, and that on the fly rewrites ANSI C to old C. Its
+primary application is to compile ANSI C software in UNIX environments
+that do not (yet) have an ANSI C compiler and that cannot run GCC
+because of technical or political problems.
+
+The filter leaves old-style C alone, and de-ANSI-fies function
+headings, function pointer type declarations (and casts), function type
+declarations, and combinations thereof. Many freely-distributable
+unprotoizers have problems with the latter because they are based on a
+non-recursive algorithm or even make assumptions about code layout.
+
+The unprototyper has support for systems that require special tricks
+for variadic functions (fortunately, many don't). A sample `stdarg.h'
+file is provided with support for sparc, mc68k, 80x86, vax and others.
+
+The program has been tested on a Sun SLC running SunOS 4.1.1 and on a
+80286 PC clone running Microport's version of System V Release 2. It
+runs at about the same speed as /lib/cpp, so it should have negigible
+impact on compilation times.
+
+Problems solved with this release:
+
+Minor: the program was originally intended for the compilation of
+already tested ANSI C source, so that diagnostics from the native C
+compiler would be sufficient. The present release produces better
+diagnostics, so that it can also be used for program development.
+
+Major: the template Makefile suggested that all #pragma directives be
+filtered out. This turns out to be a bad idea because some non-ANSI
+compilers (SunOS) rely on #pragmas to correctly handle the unusual flow
+control caused by vfork(2), setjmp(3) etcetera. A warning to this
+effect has been added to the Makefile.
+
+No changes were made to the actual filter logic; output should be
+identical to that of the previous release.
+
+Restrictions:
+
+Other ANSI-isms are just passed on without modification, such as
+trigraphs, token pasting (##), #pragmas, stringizing (#text) and
+string concatenation ("string1" "string2").
+
+The unprototyper does not understand declarations of (object). The
+result (the object disappears) will be a syntax error so this should
+not go by unnoticed.
+
+Some C programmers rely on ANSI-style prototypes for the automatic type
+conversion of function arguments. The unprototyper, however, does not
+generate casts. The lack of automatic conversion between integral
+and/or pointer argument types should not be a problem in environments
+where sizeof(int) == sizeof(long) == sizeof(pointer). A more serious
+problem is the lack of automatic type conversions beteen integral and
+floating-point function argument types. Let lint(1) be your friend.
+
+Operation:
+
+This package implements an non-default C preprocessor (the output from
+the default C preprocessor being piped through the unprototyper). How
+one tells the C compiler to use an non-default preprocessor program is
+somewhat compiler-dependent:
+
+ SunOS 4.x: cc -Qpath directory_with_non-default_cpp ...
+
+ SysV Rel2: cc -Bdirectory_with_non-default_cpp/ -tp ...
+
+Your C compiler manual should provide the necessary information.
+
+On some systems the lint(1) command is just a shell script, and writing
+a version that uses the unprototyper should not be too hard. With SunOS
+4.x, /usr/bin/lint is not a shell script, but it does accept the same
+syntax as the cc(1) command for the specification of a non-default
+compiler pass.
+
+You may have to do some research on the lint command provided with your
+own machine.
+
+Configuration:
+
+Check the contents of the `stdarg.h' file provided with this package.
+This file serves a dual purpose. It should be included by C source file
+that implements ANSI-style variadic functions. It is also used to
+configure the `unproto' program so that it emits the proper magic for
+the `...' construct.
+
+The `stdarg.h' file contains definitions for the sparc architecture and
+for architectures that pass arguments via the stack (usually OK for
+80*86, mc68k and vax C compilers). Risc processors often need special
+tricks. These are usually found in the file `/usr/include/varargs.h'.
+
+The file `varargs.c' provided with this package can be used to verify
+that the `stdarg.h' file has been set up correctly.
+
+For maximal flexibility, you can use the `cpp' shell script provided
+with this package to set up the pipe between the default C preprocessor
+and the unprototyper command. The script assumes that the unprototyper
+binary is called `unproto'. See the cpp.sh script and the Makefile for
+details.
+
+The overhead of shell-script interpretation can be avoided by having
+the unprototyper itself open the pipe to the C preprocessor. In this
+case, the `unproto.c' source file should be compiled with the
+`PIPE_THROUGH_CPP' macro defined as the pathname of the C preprocessor
+(usually `/lib/cpp'), and the unprototyper binary should be called
+`cpp'. See the Makefile for details.
+
+Installation:
+
+Install the `stdarg.h' include file and the `unproto.1' manual page in
+suitable places.
+
+If you use the `cpp' shell script to pipe the preprocessor output
+through the unprototyper program, install the `unproto' binary in a
+place where the `cpp' shell script can find it, and install the `cpp'
+shell script in a suitable place.
+
+If the unprototyper itself opens the pipe to the C preprocessor (i.e.
+the unprototyper was built with the `PIPE_THROUGH_CPP' macro defined),
+install the `cpp' unprototyper binary in a suitable place.
+
+ Wietse Venema
+ wietse@wzv.win.tue.nl
+ Eindhoven University of Technology
+ The Netherlands
diff --git a/unproto/Shar.Headers b/unproto/Shar.Headers
new file mode 100644
index 0000000..d707a4f
--- /dev/null
+++ b/unproto/Shar.Headers
@@ -0,0 +1,50 @@
+Newsgroups: comp.sources.misc
+From: wietse@wzv.win.tue.nl (Wietse Venema)
+Subject: v26i094: unproto - compile ANSI C with old C compiler, Part01/02
+Message-ID: <csm-v26i094=unproto.083344@sparky.IMD.Sterling.COM>
+X-Md4-Signature: 69685c0673793ce6c539657a3d1de2ab
+Date: Sun, 1 Dec 1991 14:35:08 GMT
+Approved: kent@sparky.imd.sterling.com
+
+Submitted-by: wietse@wzv.win.tue.nl (Wietse Venema)
+Posting-number: Volume 26, Issue 94
+Archive-name: unproto/part01
+Environment: SYSV2, SunOS
+Supersedes: unproto: Volume 23, Issue 12-13
+
+This is a filter that sits in between the C preprocessor and the next C
+compiler stage, and that on the fly rewrites ANSI C to old C. Its
+primary application is to compile ANSI C software in UNIX environments
+that do not (yet) have an ANSI C compiler and that cannot run GCC
+because of technical or political problems.
+
+Problems solved with this release:
+
+Minor: the program was originally intended for the compilation of
+already tested ANSI C source, so that diagnostics from the native C
+compiler would be sufficient. The present release produces better
+diagnostics, so that it can also be used for program development.
+
+Major: the template Makefile suggested that all #pragma directives be
+filtered out. This turns out to be a bad idea because some non-ANSI
+compilers (SunOS) rely on #pragmas to correctly handle the unusual flow
+control caused by vfork(2), setjmp(3) etcetera. A warning to this
+effect has been added to the Makefile.
+
+No changes were made to the actual filter logic; output should be
+identical to that of the previous release.
+
+Newsgroups: comp.sources.misc
+From: wietse@wzv.win.tue.nl (Wietse Venema)
+Subject: v26i095: unproto - compile ANSI C with old C compiler, Part02/02
+Message-ID: <1991Dec1.143532.21763@sparky.imd.sterling.com>
+X-Md4-Signature: e41270a11de3ed19fd262a273924fc94
+Date: Sun, 1 Dec 1991 14:35:32 GMT
+Approved: kent@sparky.imd.sterling.com
+
+Submitted-by: wietse@wzv.win.tue.nl (Wietse Venema)
+Posting-number: Volume 26, Issue 95
+Archive-name: unproto/part02
+Environment: SYSV2, SunOS
+Supersedes: unproto: Volume 23, Issue 12-13
+
diff --git a/unproto/cpp.sh b/unproto/cpp.sh
new file mode 100644
index 0000000..8122b68
--- /dev/null
+++ b/unproto/cpp.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# @(#) cpp.sh 1.2 91/09/22 21:21:43
+
+# Unprototypeing preprocessor for non-ANSI C compilers. Define __STDC__
+# if you have enough courage. You will have to modify this script if
+# your cc(1) command specifies output file names to the preprocessor.
+
+exec /lib/cpp "$@" -Dconst= -Dvolatile= | unproto
diff --git a/unproto/error.c b/unproto/error.c
new file mode 100644
index 0000000..bc9702b
--- /dev/null
+++ b/unproto/error.c
@@ -0,0 +1,78 @@
+/*++
+/* NAME
+/* error 3
+/* SUMMARY
+/* diagnostics
+/* PACKAGE
+/* unproto
+/* SYNOPSIS
+/* #include "error.h"
+/*
+/* void error(quit, text)
+/* int quit;
+/* char *text;
+/*
+/* void error_where(quit, path, line, text)
+/* int quit;
+/* char *path;
+/* int line;
+/* char *text;
+/* DESCRIPTION
+/* The routines in this file print a diagnostic (text) and optionally
+/* terminate the program (quit != 0) with exit status "quit".
+/*
+/* error() provides a default context, i.e. the source-file
+/* coordinate of the last read token.
+/*
+/* error_where() allows the caller to explicitly specify context: path
+/* is a source-file name, and line is a line number.
+/*
+/* context is ignored if the line number is zero or if the path
+/* is an empty string.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Eindhoven University of Technology
+/* Department of Mathematics and Computer Science
+/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
+/* LAST MODIFICATION
+/* 91/11/30 21:10:35
+/* VERSION/RELEASE
+/* 1.1
+/*--*/
+
+static char error_sccsid[] = "@(#) error.c 1.1 91/11/30 21:10:35";
+
+/* C library */
+
+#include <stdio.h>
+
+void exit();
+
+/* Application-specific stuff */
+
+#include "token.h"
+#include "error.h"
+
+/* error - report problem (implicit context) and optionally quit */
+
+void error(quit, text)
+int quit;
+char *text;
+{
+ error_where(quit, curr_path, curr_line, text);
+}
+
+/* error_where - report problem (explicit context) and optionally quit */
+
+void error_where(quit, path, line, text)
+int quit;
+char *path;
+int line;
+char *text;
+{
+ if (line && path[0])
+ fprintf(stderr, "%s, line %d: ", path, line);
+ fprintf(stderr, "%s\n", text);
+ if (quit)
+ exit(quit);
+}
diff --git a/unproto/error.h b/unproto/error.h
new file mode 100644
index 0000000..579906d
--- /dev/null
+++ b/unproto/error.h
@@ -0,0 +1,4 @@
+/* @(#) error.h 1.1 91/11/30 21:10:36 */
+
+extern void error(); /* default context */
+extern void error_where(); /* user-specified context */
diff --git a/unproto/example.c b/unproto/example.c
new file mode 100644
index 0000000..003df4a
--- /dev/null
+++ b/unproto/example.c
@@ -0,0 +1,140 @@
+ /*
+ * @(#) example.c 1.2 91/09/22 21:21:45
+ *
+ * Examples of things that can be done with the unproto package
+ */
+
+ /*
+ * New-style argument list with structured argument, one field being pointer
+ * to function returning pointer to function with function-pointer argument
+ */
+
+x(struct {
+ struct {
+ int (*(*foo) (int (*arg1) (double))) (float arg2);
+ } foo;
+} baz) {
+ return (0);
+}
+
+ /*
+ * Old-style argument list with new-style argument type, declaration
+ * embedded within block. Plus a couple assignments with function calls that
+ * look like casts.
+ */
+
+foo(bar)
+int (*(*bar) (float)) (int);
+{
+ int (*baz) (int) = (int (*) (int)) 0,
+ y = (y * (*baz) (y)),
+ *(*z) (int) = (int *(*) (int)) 0;
+
+ struct { int (*foo)(int); } *(*s)(int) =
+ (struct { int (*foo)(int); } *(*)(int)) 0;
+
+ {
+ y = (y * (*baz) (y));
+ }
+ {
+ z = (int *(*) (int)) 0;
+ }
+ {
+ s = (struct { int (*foo)(int); } *(*)(int)) 0;
+ }
+
+ return (0);
+}
+
+/* Multiple declarations in one statement */
+
+test1()
+{
+ int foo2,*(*(*bar)(int))(float),*baz(double);
+}
+
+/* Discriminate declarations from executable statements */
+
+test2(char *y)
+{
+ int foo = 5,atoi(char *);
+
+ foo = 5,atoi(y);
+}
+
+/* Declarations without explicit type */
+
+test3,test4(int);
+
+test5(int y)
+{
+ {
+ test3;
+ }
+ {
+ test4(y);
+ }
+}
+
+test6[1],test7(int);
+
+test7(int x)
+{
+ {
+ test6[1];
+ }
+ {
+ test7(x);
+ }
+}
+
+/* Checking a complicated cast */
+
+struct {
+ struct {
+ int (*f)(int), o;
+ } bar;
+} (*baz2)(int) = (struct { struct { int (*f)(int), o; } bar; } (*)(int)) 0;
+
+/* Distinguish things with the same shape but with different meaning */
+
+test8(x)
+{
+ {
+ struct {
+ int foo;
+ } bar(int);
+ }
+ {
+ do {
+ int foo;
+ } while (x);
+ }
+}
+
+/* Do not think foo(*bar) is a function pointer declaration */
+
+test9(char *bar)
+{
+ foo(*bar);
+}
+
+/* another couple of special-cased words. */
+
+test10(int x)
+{
+ {
+ int test10(int);
+ do test10(x);
+ while (x);
+ }
+ {
+ return test10(x);
+ }
+}
+
+test11(int *x)
+{
+ while (*x)
+ (putchar(*x++));
+}
diff --git a/unproto/example.out b/unproto/example.out
new file mode 100644
index 0000000..6dc75f3
--- /dev/null
+++ b/unproto/example.out
@@ -0,0 +1,173 @@
+# 1 "example.c"
+
+
+
+
+
+
+
+
+
+
+
+x
+
+
+
+(baz)
+# 16 "example.c"
+struct { struct { int (*(*foo)())(); } foo;} baz;
+# 16 "example.c"
+{/*1*/
+ /* end dcls */return (0);
+}/*1*/
+
+
+
+
+
+
+
+foo
+(bar)int (*(*bar)())();
+{/*1*/
+ int (*baz)() = (int (*)()) 0,
+ y = (y * (*baz)(y)),
+ *(*z)() = (int *(*)()) 0;
+
+ struct {/*2*/ int (*foo)(); }/*2*/ *(*s)() =
+ (struct { int (*foo)(); } *(*)()) 0;
+
+ /* end dcls */{/*2*/
+ y /* end dcls */= (y * (*baz)(y));
+ }/*2*/
+ {/*2*/
+ z /* end dcls */= (int *(*)()) 0;
+ }/*2*/
+ {/*2*/
+ s /* end dcls */= (struct { int (*foo)(); } *(*)()) 0;
+ }/*2*/
+
+ return (0);
+}/*1*/
+
+
+
+test1
+()
+# 52 "example.c"
+{/*1*/
+ int foo2,*(*(*bar)())(),*baz();
+}/*1*/
+
+
+
+test2
+(y)
+# 59 "example.c"
+char *y;
+# 59 "example.c"
+{/*1*/
+ int foo = 5,atoi();
+
+ foo /* end dcls */= 5,atoi(y);
+}/*1*/
+
+
+
+test3,test4();
+
+test5
+(y)
+# 70 "example.c"
+int y;
+# 70 "example.c"
+{/*1*/
+ /* end dcls */{/*2*/
+ test3/* end dcls */;
+ }/*2*/
+ {/*2*/
+ test4/* end dcls */(y);
+ }/*2*/
+}/*1*/
+
+test6[1],test7();
+
+test7
+(x)
+# 82 "example.c"
+int x;
+# 82 "example.c"
+{/*1*/
+ /* end dcls */{/*2*/
+ test6/* end dcls */[1];
+ }/*2*/
+ {/*2*/
+ test7/* end dcls */(x);
+ }/*2*/
+}/*1*/
+
+
+
+struct {/*1*/
+ struct {/*2*/
+ int (*f)(), o;
+ }/*2*/ bar;
+}/*1*/ (*baz2)() = (struct { struct { int (*f)(), o; } bar; } (*)()) 0;
+
+
+
+test8
+(x)
+# 102 "example.c"
+{/*1*/
+ /* end dcls */{/*2*/
+ struct {/*3*/
+ int foo;
+ }/*3*/ bar();
+ }/*2*/
+ {/*2*/
+ /* end dcls */do {/*3*/
+ int foo;
+ }/*3*/ while (x);
+ }/*2*/
+}/*1*/
+
+
+
+test9
+(bar)
+# 118 "example.c"
+char *bar;
+# 118 "example.c"
+{/*1*/
+ foo/* end dcls */(*bar);
+}/*1*/
+
+
+
+test10
+(x)
+# 125 "example.c"
+int x;
+# 125 "example.c"
+{/*1*/
+ /* end dcls */{/*2*/
+ int test10();
+ /* end dcls */do test10(x);
+ while (x);
+ }/*2*/
+ {/*2*/
+ /* end dcls */return test10(x);
+ }/*2*/
+}/*1*/
+
+test11
+(x)
+# 137 "example.c"
+int *x;
+# 137 "example.c"
+{/*1*/
+ /* end dcls */while (*x)
+ (putchar(*x++));
+}/*1*/
diff --git a/unproto/stdarg.h b/unproto/stdarg.h
new file mode 100644
index 0000000..978529b
--- /dev/null
+++ b/unproto/stdarg.h
@@ -0,0 +1,38 @@
+ /*
+ * @(#) stdarg.h 1.2 91/11/30 21:10:39
+ *
+ * Sample stdarg.h file for use with the unproto filter.
+ *
+ * This file serves two purposes.
+ *
+ * 1 - As an include file for use with ANSI-style C source that implements
+ * variadic functions.
+ *
+ * 2 - To configure the unproto filter itself. If the _VA_ALIST_ macro is
+ * defined, its value will appear in the place of the "..." in argument
+ * lists of variadic function *definitions* (not declarations).
+ *
+ * Compilers that pass arguments via the stack can use the default code at the
+ * end of this file (this usually applies for the VAX, MC68k and 80*86
+ * architectures).
+ *
+ * RISC-based systems often need special tricks. An example of the latter is
+ * given for the SPARC architecture. Read your /usr/include/varargs.h for
+ * more information.
+ *
+ * You can use the varargs.c program provided with the unproto package to
+ * verify that the stdarg.h file has been set up correctly.
+ */
+
+#ifdef sparc
+# define _VA_ALIST_ "__builtin_va_alist"
+ typedef char *va_list;
+# define va_start(ap, p) (ap = (char *) &__builtin_va_alist)
+# define va_arg(ap, type) ((type *) __builtin_va_arg_incr((type *) ap))[0]
+# define va_end(ap)
+#else /* vax, mc68k, 80*86 */
+ typedef char *va_list;
+# define va_start(ap, p) (ap = (char *) (&(p)+1))
+# define va_arg(ap, type) ((type *) (ap += sizeof(type)))[-1]
+# define va_end(ap)
+#endif
diff --git a/unproto/symbol.c b/unproto/symbol.c
new file mode 100644
index 0000000..0871f63
--- /dev/null
+++ b/unproto/symbol.c
@@ -0,0 +1,161 @@
+/*++
+/* NAME
+/* symbol 3
+/* SUMMARY
+/* rudimentary symbol table package
+/* SYNOPSIS
+/* #include "symbol.h"
+/*
+/* void sym_init()
+/*
+/* void sym_enter(name, type)
+/* char *name;
+/* int type;
+/*
+/* struct symbol *sym_find(name)
+/* char *name;
+/* DESCRIPTION
+/* This is a rudimentary symbol-table package, just enough to
+/* keep track of a couple of C keywords.
+/*
+/* sym_init() primes the table with C keywords. At present, most of
+/* the keywords that have to do with types are left out.
+/* We need a different strategy to detect type definitions because
+/* we do not keep track of typedef names.
+/*
+/* sym_enter() adds an entry to the symbol table.
+/*
+/* sym_find() locates a symbol table entry (it returns 0 if
+/* it is not found).
+/* AUTHOR(S)
+/* Wietse Venema
+/* Eindhoven University of Technology
+/* Department of Mathematics and Computer Science
+/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
+/* LAST MODIFICATION
+/* 91/11/30 21:10:33
+/* VERSION/RELEASE
+/* 1.2
+/*--*/
+
+static char symbol_sccsid[] = "@(#) symbol.c 1.2 91/11/30 21:10:33";
+
+/* C library */
+
+extern char *strcpy();
+extern char *malloc();
+
+/* Application-specific stuff */
+
+#include "error.h"
+#include "token.h"
+#include "symbol.h"
+
+#define SYM_TABSIZE 20
+
+static struct symbol *sym_tab[SYM_TABSIZE] = {0,};
+
+/* More string stuff. Maybe it should go to an #include file. */
+
+#define STREQ(x,y) (*(x) == *(y) && strcmp((x),(y)) == 0)
+
+/* hash - hash a string; original author: P. J. Weinberger at Bell Labs. */
+
+static unsigned hash(s, size)
+register char *s;
+unsigned size;
+{
+ register unsigned long h = 0;
+ register unsigned long g;
+
+ /*
+ * For a performance comparison with the hash function presented in K&R,
+ * first edition, see the "Dragon" book by Aho, Sethi and Ullman.
+ */
+
+ while (*s) {
+ h = (h << 4) + *s++;
+ if (g = (h & 0xf0000000)) {
+ h ^= (g >> 24);
+ h ^= g;
+ }
+ }
+ return (h % size);
+}
+
+/* sym_enter - enter symbol into table */
+
+void sym_enter(name, type)
+char *name;
+int type;
+{
+ struct symbol *s;
+ int where;
+
+ if ((s = (struct symbol *) malloc(sizeof(*s))) == 0
+ || (s->name = malloc(strlen(name) + 1)) == 0)
+ error(1, "out of memory");
+ (void) strcpy(s->name, name);
+ s->type = type;
+
+ where = hash(name, SYM_TABSIZE);
+ s->next = sym_tab[where];
+ sym_tab[where] = s;
+}
+
+/* sym_find - locate symbol definition */
+
+struct symbol *sym_find(name)
+register char *name;
+{
+ register struct symbol *s;
+
+ /*
+ * This function is called for almost every "word" token, so it better be
+ * fast.
+ */
+
+ for (s = sym_tab[hash(name, SYM_TABSIZE)]; s; s = s->next)
+ if (STREQ(name, s->name))
+ return (s);
+ return (0);
+}
+
+ /*
+ * Initialization data for symbol table. We do not enter keywords for types.
+ * We use a different strategy to detect type declarations because we do not
+ * keep track of typedef names.
+ */
+
+struct sym {
+ char *name;
+ int tokno;
+};
+
+static struct sym syms[] = {
+ "if", TOK_CONTROL,
+ "else", TOK_CONTROL,
+ "while", TOK_CONTROL,
+ "do", TOK_CONTROL,
+ "switch", TOK_CONTROL,
+ "case", TOK_CONTROL,
+ "default", TOK_CONTROL,
+ "return", TOK_CONTROL,
+ "continue", TOK_CONTROL,
+ "break", TOK_CONTROL,
+ "goto", TOK_CONTROL,
+ "struct", TOK_COMPOSITE,
+ "union", TOK_COMPOSITE,
+ 0,
+};
+
+/* sym_init - enter known keywords into symbol table */
+
+void sym_init()
+{
+ register struct sym *p;
+
+ for (p = syms; p->name; p++)
+ sym_enter(p->name, p->tokno);
+}
+
diff --git a/unproto/symbol.h b/unproto/symbol.h
new file mode 100644
index 0000000..0711c1f
--- /dev/null
+++ b/unproto/symbol.h
@@ -0,0 +1,11 @@
+/* @(#) symbol.h 1.1 91/09/22 21:21:42 */
+
+struct symbol {
+ char *name; /* symbol name */
+ int type; /* symbol type */
+ struct symbol *next;
+};
+
+extern void sym_enter(); /* add symbol to table */
+extern struct symbol *sym_find(); /* locate symbol */
+extern void sym_init(); /* prime the table */
diff --git a/unproto/tok_class.c b/unproto/tok_class.c
new file mode 100644
index 0000000..e25b695
--- /dev/null
+++ b/unproto/tok_class.c
@@ -0,0 +1,180 @@
+/*++
+/* NAME
+/* tok_class 3
+/* SUMMARY
+/* token classification
+/* PACKAGE
+/* unproto
+/* SYNOPSIS
+/* #include "token.h"
+/*
+/* struct token *tok_class(skip)
+/* int skip;
+/* DESCRIPTION
+/* tok_class() collects a single and composite tokens, and
+/* recognizes keywords.
+/* At present, the only composite tokens are ()-delimited,
+/* comma-separated lists.
+/*
+/* The skip argument has the same meaning as with the tok_get()
+/* function.
+/* DIAGNOSTICS
+/* The code complains if input terminates in the middle of a list.
+/* BUGS
+/* Does not preserve white space at the beginning of a list element
+/* or after the end of a list.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Eindhoven University of Technology
+/* Department of Mathematics and Computer Science
+/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
+/* LAST MODIFICATION
+/* 91/11/30 21:10:28
+/* VERSION/RELEASE
+/* 1.3
+/*--*/
+
+static char class_sccsid[] = "@(#) tok_class.c 1.3 91/11/30 21:10:28";
+
+/* C library */
+
+#include <stdio.h>
+
+extern char *strcpy();
+
+/* Application-specific stuff */
+
+#include "error.h"
+#include "vstring.h"
+#include "token.h"
+#include "symbol.h"
+
+static struct token *tok_list();
+static void tok_list_struct();
+static void tok_list_append();
+
+/* tok_space_append - append trailing space except after list */
+
+#define tok_space_append(list,t) { \
+ if (list == 0 /* leading space*/ \
+ || list->tokno == TOK_LIST) \
+ tok_free(t); \
+ else \
+ tok_list_append(list, t); \
+ }
+
+/* tok_class - discriminate single tokens, keywords, and composite tokens */
+
+struct token *tok_class(skip)
+int skip;
+{
+ register struct token *t;
+ register struct symbol *s;
+
+ if (t = tok_get(skip)) {
+ switch (t->tokno) {
+ case '(': /* beginning of list */
+ t = tok_list(t);
+ break;
+ case TOK_WORD: /* look up keyword */
+ if (s = sym_find(t->vstr->str))
+ t->tokno = s->type;
+ break;
+ }
+ }
+ return (t);
+}
+
+/* tok_list - collect ()-delimited, comma-separated list of tokens */
+
+static struct token *tok_list(t)
+struct token *t;
+{
+ register struct token *list = tok_alloc();
+ char filename[BUFSIZ];
+ int lineno;
+
+ /* Save context of '(' for diagnostics. */
+
+ strcpy(filename, curr_path);
+ lineno = curr_line;
+
+ list->tokno = TOK_LIST;
+ list->head = list->tail = t;
+#ifdef DEBUG
+ strcpy(list->vstr->str, "LIST");
+#endif
+
+ for (;;) {
+ if ((t = tok_get(DO_WSPACE)) == 0) { /* skip blanks */
+ error_where(0, filename, lineno, "unmatched '('");
+ return (list); /* do not waste any data */
+ }
+ switch (t->tokno) {
+ case ')': /* end of list */
+ tok_free(t);
+ return (list);
+ case '{': /* struct/union type */
+ tok_list_struct(list->tail, t);
+ break;
+ case TOK_WSPACE: /* preserve trailing blanks */
+ tok_space_append(list->tail->tail, t); /* except after list */
+ break;
+ case '\n': /* preserve line count */
+ tok_flush(t);
+ break;
+ case ',': /* list separator */
+ tok_list_append(list, t);
+ break;
+ case '(': /* beginning of list */
+ tok_list_append(list->tail, tok_list(t));
+ break;
+ default: /* ordinary token */
+ tok_list_append(list->tail, t);
+ break;
+ }
+ }
+}
+
+/* tok_list_struct - collect structured type info within list */
+
+static void tok_list_struct(list, t)
+register struct token *list;
+register struct token *t;
+{
+ tok_list_append(list, t);
+
+ while (t = tok_class(DO_WSPACE)) {
+ switch (t->tokno) {
+ case '\n': /* preserve line count */
+ tok_flush(t);
+ break;
+ case TOK_WSPACE: /* preserve trailing blanks */
+ tok_space_append(list->tail, t); /* except after list */
+ break;
+ case '{': /* recurse */
+ tok_list_struct(list, t);
+ break;
+ case '}': /* done */
+ tok_list_append(list, t);
+ return;
+ default: /* other */
+ tok_list_append(list, t);
+ break;
+ }
+ }
+}
+
+/* tok_list_append - append data to list */
+
+static void tok_list_append(h, t)
+struct token *h;
+struct token *t;
+{
+ if (h->head == 0) {
+ h->head = h->tail = t;
+ } else {
+ h->tail->next = t;
+ h->tail = t;
+ }
+}
diff --git a/unproto/tok_io.c b/unproto/tok_io.c
new file mode 100644
index 0000000..ab1129b
--- /dev/null
+++ b/unproto/tok_io.c
@@ -0,0 +1,464 @@
+/*++
+/* NAME
+/* tok_io 3
+/* SUMMARY
+/* token I/O
+/* PACKAGE
+/* unproto
+/* SYNOPSIS
+/* #include "token.h"
+/*
+/* struct token *tok_get(skip_flag)
+/* int skip_flag;
+/*
+/* void tok_unget(t)
+/* struct token *t;
+/*
+/* void tok_flush(t)
+/* struct token *t;
+/*
+/* void tok_show(t)
+/* struct token *t;
+/*
+/* void put_str(s)
+/* char *s;
+/*
+/* void put_ch(c)
+/* int c;
+/*
+/* void show_line_control()
+/*
+/* char curr_path[];
+/* int curr_line;
+/* DESCRIPTION
+/* These functions read from stdin and write to stdout. The
+/* output functions maintain some memory so that two successive
+/* words will always be separated by white space.
+/*
+/* The input routines eliminate backslash-newline from the input.
+/*
+/* tok_get() reads the next token from standard input. It returns
+/* a null pointer when the end of input is reached. If the skip_flag
+/* argument is nonzero, white space (except newline) will be skipped.
+/*
+/* tok_unget() implements a limited amount of token push back.
+/*
+/* tok_show() displays the contents of a (possibly composite) token
+/* on the standard output.
+/*
+/* tok_flush() displays the contents of a (possibly composite) token
+/* on the standard output and makes it available for re-use.
+/*
+/* put_str() writes a null-terminated string to standard output.
+/*
+/* put_ch() writes one character to standard output.
+/*
+/* show_line_control() displays the line number of the next line
+/* to be written to standard output, in a format suitable for the C
+/* compiler parser phase.
+/*
+/* The curr_path[] and curr_line variables contain the input file name and
+/* line number of the most recently read token.
+/* BUGS
+/* The tokenizer is just good enough for the unproto filter.
+/* As a benefit, it is quite fast.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Eindhoven University of Technology
+/* Department of Mathematics and Computer Science
+/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
+/* LAST MODIFICATION
+/* 91/11/30 21:10:26
+/* VERSION/RELEASE
+/* 1.2
+/*--*/
+
+static char io_sccsid[] = "@(#) tok_io.c 1.2 91/11/30 21:10:26";
+
+/* C library */
+
+#include <stdio.h>
+#include <ctype.h>
+
+extern char *strchr();
+extern char *malloc();
+extern char *realloc();
+extern char *strcpy();
+
+/* Application-specific stuff */
+
+#include "token.h"
+#include "vstring.h"
+#include "error.h"
+
+/* Stuff to keep track of original source file name and position */
+
+char curr_path[BUFSIZ]; /* current file name */
+int curr_line = 0; /* # of last read line */
+
+/* Forward declarations */
+
+static void read_quoted();
+static void read_comment();
+
+/* Buffered i/o stuff */
+
+static struct vstring *buf = 0; /* read-ahead buffer */
+static char *bp = ""; /* buffer position */
+
+#ifdef DEBUG
+#define INITBUF 1 /* small initial buffer size */
+#else
+#define INITBUF BUFSIZ /* reasonable initial buffer size */
+#endif
+
+#define input() (*bp ? *bp++ : next_line())
+#define unput(c) (*--bp = (c))
+
+#define TOK_BUFSIZE 5 /* token push-back buffer size */
+
+static struct token *tok_buf[TOK_BUFSIZE];
+static int tok_bufpos = 0;
+
+/* Type of last token sent to output, for pretty printing */
+
+static int last_tok = 0;
+
+/* Directives that should be ignored. */
+
+#ifdef IGNORE_DIRECTIVES
+
+static char *ignore_directives[] = {
+ IGNORE_DIRECTIVES,
+ 0,
+};
+
+#endif
+
+/* Modified string and ctype stuff. */
+
+#define STREQUAL(x,y) (*(x) == *(y) && strcmp((x),(y)) == 0)
+
+#define ISALNUM(c) (isalnum(c) || (c) == '_')
+#define ISALPHA(c) (isalpha(c) || (c) == '_')
+#define ISSPACE(c) (isspace(c) && c != '\n')
+#define ISDOT(c) (c == '.')
+
+/* Collect all characters that satisfy one condition */
+
+#define COLLECT(v,c,cond) { \
+ register struct vstring *vs = v; \
+ register char *cp = vs->str; \
+ *cp++ = c; \
+ for (;;) { \
+ if ((c = input()) == 0) { \
+ break; \
+ } else if (cond) { \
+ if (VS_ADDCH(vs, cp, c) == 0) \
+ error(1, "out of memory"); \
+ } else { \
+ unput(c); \
+ break; \
+ } \
+ } \
+ *cp = 0; \
+ }
+
+/* do_control - parse control line, uses tok_get() */
+
+static int do_control()
+{
+ struct token *t1;
+ struct token *t2;
+ int pass_thru = 1; /* 0 = ignore, 1 = output */
+
+ (void) input(); /* skip the hash */
+
+ if (t1 = tok_get(NO_WSPACE)) {
+ switch (t1->tokno) {
+
+ /*
+ * In case of line number control, the remainder of the line has
+ * the format: linenumber "pathname".
+ */
+ case TOK_NUMBER:
+ if (t2 = tok_get(NO_WSPACE)) {
+ if (t2->tokno == '"') {
+ curr_line = atoi(t1->vstr->str) - 1;
+ strcpy(curr_path, t2->vstr->str);
+ }
+ tok_free(t2);
+ }
+ break;
+
+#ifdef IGNORE_DIRECTIVES
+ case TOK_WORD:
+ /* Optionally ignore other #directives, such as #pragma. */
+ {
+ char **cpp;
+ char *cp = t1->vstr->str;
+
+ for (cpp = ignore_directives; *cpp; cpp++) {
+ if (STREQUAL(cp, *cpp)) {
+ pass_thru = 0;
+ break;
+ }
+ }
+ }
+ break;
+#endif
+ }
+ tok_free(t1);
+ }
+ return (pass_thru);
+}
+
+/* next_line - read one logical line, handle #control */
+
+static int next_line()
+{
+ register int c;
+ register char *cp;
+
+ /* Allocate buffer upon first entry */
+
+ if (buf == 0)
+ buf = vs_alloc(INITBUF);
+
+ for (;;) {
+ cp = buf->str;
+
+ /* Account for EOF and line continuations */
+
+ while ((c = getchar()) != EOF) {
+ if (VS_ADDCH(buf, cp, c) == 0) /* store character */
+ error(1, "out of memory");
+ if (c == '\n') { /* real end of line */
+ curr_line++;
+ break;
+ } else if (c == '\\') {
+ if ((c = getchar()) == EOF) { /* XXX strip backslash-EOF */
+ break;
+ } else if (c == '\n') { /* strip backslash-newline */
+ curr_line++;
+ put_ch('\n'); /* preserve line count */
+ cp--; /* un-store backslash */
+ } else {
+ ungetc(c, stdin); /* keep backslash-other */
+ }
+ }
+ }
+ *cp = 0;
+ bp = buf->str;
+
+ /* Account for EOF and #control */
+
+ switch (bp[0]) {
+ case 0: /* EOF */
+ return (0);
+ case '#': /* control */
+ if (do_control())
+ fputs(buf->str, stdout); /* pass through */
+ else
+ putchar('\n'); /* filter out */
+ break;
+ default: /* non-control */
+ return (input());
+ }
+ }
+}
+
+/* tok_unget - push back one token */
+
+void tok_unget(t)
+register struct token *t;
+{
+ if (tok_bufpos >= TOK_BUFSIZE)
+ error(1, "too much pushback");
+ tok_buf[tok_bufpos++] = t;
+}
+
+/* tok_get - get next token */
+
+struct token *tok_get(skip_flag)
+int skip_flag;
+{
+ register struct token *t;
+ register int c;
+ int d;
+
+ /* Use push-back token, if any. */
+
+ if (tok_bufpos) {
+ t = tok_buf[--tok_bufpos];
+ return (t);
+ }
+
+ /*
+ * Get one from the pool and fill it in. The loop is here in case we
+ * should skip white-space tokens, which happens in a minority of all
+ * cases.
+ */
+
+ t = tok_alloc();
+
+ for (;;) {
+ if ((c = input()) == 0) {
+ tok_free(t);
+ return (0);
+ } else if (!isascii(c)) {
+ t->vstr->str[0] = c;
+ t->vstr->str[1] = 0;
+ t->tokno = TOK_OTHER;
+ return (t);
+ } else if (c == '"' || c == '\'') {
+ read_quoted(t, c);
+ t->tokno = c;
+ return (t);
+ } else if (ISALPHA(c)) {
+ COLLECT(t->vstr, c, ISALNUM(c));
+ t->tokno = TOK_WORD;
+ return (t);
+ } else if (isdigit(c)) {
+ COLLECT(t->vstr, c, isdigit(c));
+ t->tokno = TOK_NUMBER;
+ return (t);
+ } else if (ISSPACE(c)) {
+ COLLECT(t->vstr, c, ISSPACE(c));
+ if (skip_flag)
+ continue;
+ t->tokno = TOK_WSPACE;
+ return (t);
+ } else if (ISDOT(c)) {
+ COLLECT(t->vstr, c, ISDOT(c));
+ t->tokno = TOK_OTHER;
+ return (t);
+ } else {
+ t->vstr->str[0] = c;
+ if (c == '/') {
+ if ((d = input()) == '*') {
+ t->vstr->str[1] = d; /* comment */
+ read_comment(t->vstr);
+ if (skip_flag)
+ continue;
+ t->tokno = TOK_WSPACE;
+ return (t);
+ } else {
+ unput(d);
+ }
+ }
+ t->vstr->str[1] = 0;
+ t->tokno = c;
+ return (t);
+ }
+ }
+}
+
+/* read_qouted - read string or character literal */
+
+static void read_quoted(t, ch)
+register struct token *t;
+int ch;
+{
+ register char *cp = t->vstr->str;
+ register int c;
+
+ *cp++ = ch;
+
+ while (c = input()) {
+ if (c == '\n') { /* newline in string */
+ unput(c);
+ break;
+ }
+ if (VS_ADDCH(t->vstr, cp, c) == 0) /* store character */
+ error(1, "out of memory");
+ if (c == ch) /* end of string */
+ break;
+ if (c == '\\') /* eat next character */
+ if ((c = input()) != 0 && VS_ADDCH(t->vstr, cp, c) == 0)
+ error(1, "out of memory");
+ }
+ *cp = 0;
+ return;
+}
+
+/* read_comment - stuff a whole comment into one huge token */
+
+static void read_comment(vs)
+register struct vstring *vs;
+{
+ register char *cp = vs->str + 2; /* skip slash star */
+ register int c;
+ register int d;
+
+ while (c = input()) {
+ if (VS_ADDCH(vs, cp, c) == 0)
+ error(1, "out of memory");
+ if (c == '*') {
+ if ((d = input()) == '/') {
+ if (VS_ADDCH(vs, cp, d) == 0)
+ error(1, "out of memory");
+ break;
+ } else {
+ unput(d);
+ }
+ }
+ }
+ *cp = 0;
+}
+
+/* put_str - output a string */
+
+void put_str(s)
+char *s;
+{
+ fputs(s, stdout);
+ last_tok = s[0]; /* XXX */
+#ifdef DEBUG
+ fflush(stdout);
+#endif
+}
+
+/* put_ch - put character */
+
+void put_ch(c)
+int c;
+{
+ last_tok = putchar(c);
+#ifdef DEBUG
+ fflush(stdout);
+#endif
+}
+
+/* tok_show - output (possibly composite) token */
+
+void tok_show(t)
+struct token *t;
+{
+ register struct token *p;
+ register struct token *s;
+
+ switch (t->tokno) {
+ case TOK_LIST:
+ for (s = t->head; s; s = s->next) {
+ put_ch(s->tokno); /* opening paren or ',' */
+ for (p = s->head; p; p = p->next)
+ tok_show(p);
+ }
+ put_ch(')'); /* closing paren */
+ break;
+ case TOK_WORD:
+ if (ISALPHA(last_tok))
+ putchar(' ');
+ /* FALLTRHOUGH */
+ default:
+ fputs(t->vstr->str, stdout); /* token contents */
+ last_tok = t->vstr->str[0];
+#ifdef DEBUG
+ fflush(stdout);
+#endif
+ if (t->head) /* trailing blanks */
+ for (p = t->head; p; p = p->next)
+ tok_show(p);
+ }
+}
diff --git a/unproto/tok_pool.c b/unproto/tok_pool.c
new file mode 100644
index 0000000..c2a9665
--- /dev/null
+++ b/unproto/tok_pool.c
@@ -0,0 +1,104 @@
+/*++
+/* NAME
+/* tok_pool 3
+/* SUMMARY
+/* maintain pool of unused token structures
+/* PACKAGE
+/* unproto
+/* SYNOPSIS
+/* #include "token.h"
+/*
+/* struct token *tok_alloc()
+/*
+/* void tok_free(t)
+/* struct token *t;
+/* DESCRIPTION
+/* tok_alloc() and tok_free() maintain a pool of unused token
+/* structures.
+/*
+/* tok_alloc() takes the first free token structure from the pool
+/* or allocates a new one if the pool is empty.
+/*
+/* tok_free() adds a (possibly composite) token structure to the pool.
+/* BUGS
+/* The pool never shrinks.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Eindhoven University of Technology
+/* Department of Mathematics and Computer Science
+/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
+/* LAST MODIFICATION
+/* 91/09/01 23:08:36
+/* VERSION/RELEASE
+/* 1.1
+/*--*/
+
+static char pool_sccsid[] = "@(#) tok_pool.c 1.1 91/09/01 23:08:36";
+
+/* C library */
+
+extern char *malloc();
+
+/* Application-specific stuff */
+
+#include "token.h"
+#include "vstring.h"
+
+extern void error();
+
+#define TOKLEN 5 /* initial string buffer length */
+
+struct token *tok_pool = 0; /* free token pool */
+
+/* tok_alloc - allocate token structure from pool or heap */
+
+struct token *tok_alloc()
+{
+ register struct token *t;
+
+ if (tok_pool) { /* re-use an old one */
+ t = tok_pool;
+ tok_pool = t->next;
+ } else { /* create a new one */
+ if ((t = (struct token *) malloc(sizeof(struct token))) == 0
+ || (t->vstr = vs_alloc(TOKLEN)) == 0)
+ error(1, "out of memory");
+ }
+ t->next = t->head = t->tail = 0;
+#ifdef DEBUG
+ strcpy(t->vstr->str, "BUSY");
+#endif
+ return (t);
+}
+
+/* tok_free - return (possibly composite) token to pool of free tokens */
+
+void tok_free(t)
+register struct token *t;
+{
+#ifdef DEBUG
+ /* Check if we are freeing free token */
+
+ register struct token *p;
+
+ for (p = tok_pool; p; p = p->next)
+ if (p == t)
+ error(1, "freeing free token");
+#endif
+
+ /* Free neighbours and subordinates first */
+
+ if (t->next)
+ tok_free(t->next);
+ if (t->head)
+ tok_free(t->head);
+
+ /* Free self */
+
+ t->next = tok_pool;
+ t->head = t->tail = 0;
+ tok_pool = t;
+#ifdef DEBUG
+ strcpy(t->vstr->str, "FREE");
+#endif
+}
diff --git a/unproto/token.h b/unproto/token.h
new file mode 100644
index 0000000..672039d
--- /dev/null
+++ b/unproto/token.h
@@ -0,0 +1,47 @@
+/* @(#) token.h 1.3 91/11/30 21:10:37 */
+
+struct token {
+ int tokno; /* token value, see below */
+ int len; /* string or list length */
+ struct vstring *vstr; /* token contents */
+ struct token *next;
+ struct token *head;
+ struct token *tail;
+};
+
+/* Special token values */
+
+#define TOK_LIST 256 /* () delimited list */
+#define TOK_WORD 257 /* keyword or identifier */
+#define TOK_NUMBER 258 /* number */
+#define TOK_WSPACE 259 /* white space except newline */
+#define TOK_OTHER 260 /* other multi-char token */
+#define TOK_CONTROL 261 /* flow control keyword */
+#define TOK_COMPOSITE 262 /* struct or union */
+
+/* Input/output functions and macros */
+
+extern struct token *tok_get(); /* read next single token */
+extern void tok_show(); /* display (composite) token */
+extern struct token *tok_class(); /* classify tokens */
+extern void put_ch(); /* write character */
+extern void put_str(); /* write string */
+extern void tok_unget(); /* stuff token back into input */
+
+#define tok_flush(t) (tok_show(t), tok_free(t))
+
+/* tok_get() and tok_class() options */
+
+#define DO_WSPACE 0 /* retain space, tab */
+#define NO_WSPACE 1 /* skip space, tab */
+
+/* Memory management */
+
+struct token *tok_alloc(); /* allocate token storage */
+extern void tok_free(); /* re-cycle storage */
+
+/* Context */
+
+extern char curr_path[]; /* current path name */
+extern int curr_line; /* current line number */
+#define show_line_control() printf("# %d %s\n", curr_line, curr_path);
diff --git a/unproto/unproto.1 b/unproto/unproto.1
new file mode 100644
index 0000000..671e917
--- /dev/null
+++ b/unproto/unproto.1
@@ -0,0 +1,79 @@
+.TH UNPROTO 1
+.ad
+.fi
+.SH NAME
+unproto
+\-
+ANSI C to old C converter
+.SH PACKAGE
+.na
+.nf
+unproto
+.SH SYNOPSIS
+.na
+.nf
+/lib/cpp ... | unproto
+
+/somewhere/cpp ...
+.SH DESCRIPTION
+.ad
+.fi
+This document describes a filter that sits between the
+C preprocessor (usually \fI/lib/cpp\fP) and the next C compiler
+pass. It rewrites ANSI-C style function headers, function type
+declarations, function pointer types, and function pointer casts
+to old style. Other ANSI-isms are passed on without modification
+(token pasting, pragmas, etcetera).
+
+For maximal flexibility, the "cpp | unproto" pipeline can be
+packaged as an executable shell script named "/somewhere/cpp".
+This script should then be specified to the C compiler as a
+non-default preprocessor.
+
+The overhead of shell script interpretation can be avoided by
+having the unprototyper itself open the pipe to the preprocessor.
+In that case, the source should be compiled with the PIPE_THROUGH_CPP
+macro defined (usually as "/lib/cpp"), and the resulting binary
+should be installed as "/somewhere/cpp".
+.SH SEE ALSO
+.na
+.nf
+.ad
+.fi
+cc(1), how to specify a non-default C preprocessor.
+
+Some versions of the lint command are implemented as a shell
+script. It should require only minor modification for integration
+with the unprotoizer. Other versions of the lint command accept the same
+command syntax as the C compiler for the specification of a non-default
+preprocessor. Some research may be needed.
+.SH DIAGNOSTICS
+.ad
+.fi
+The progam will complain if it unexpectedly
+reaches the end of input.
+.SH BUGS
+.ad
+.fi
+Should be run on preprocessed source only, i.e. after macro expansion.
+
+Declarations of (whatever) are misunderstood and will result in
+syntax errors.
+
+Does not generate explicit type casts for function argument
+expressions.
+.SH AUTHOR(S)
+.na
+.nf
+Wietse Venema (wietse@wzv.win.tue.nl)
+Eindhoven University of Technology
+Department of Mathematics and Computer Science
+Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
+.SH LAST MODIFICATION
+.na
+.nf
+91/09/22 21:21:35
+.SH VERSION/RELEASE
+.na
+.nf
+1.2
diff --git a/unproto/unproto.c b/unproto/unproto.c
new file mode 100644
index 0000000..9ca26ce
--- /dev/null
+++ b/unproto/unproto.c
@@ -0,0 +1,749 @@
+/*++
+/* NAME
+/* unproto 1
+/* SUMMARY
+/* ANSI C to old C converter
+/* PACKAGE
+/* unproto
+/* SYNOPSIS
+/* /lib/cpp ... | unproto
+/*
+/* /somewhere/cpp ...
+/* DESCRIPTION
+/* This document describes a filter that sits between the
+/* C preprocessor (usually \fI/lib/cpp\fP) and the next C compiler
+/* pass. It rewrites ANSI-C style function headers, function type
+/* declarations, function pointer types, and function pointer casts
+/* to old style. Other ANSI-isms are passed on without modification
+/* (token pasting, pragmas, etcetera).
+/*
+/* For maximal flexibility, the "cpp | unproto" pipeline can be
+/* packaged as an executable shell script named "/somewhere/cpp".
+/* This script should then be specified to the C compiler as a
+/* non-default preprocessor. It will not work if your C compiler
+/* specifies output file names to the preprocessor.
+/*
+/* The overhead of shell script interpretation can be avoided by
+/* having the unprototyper itself open the pipe to the preprocessor.
+/* In that case, the source should be compiled with the PIPE_THROUGH_CPP
+/* macro defined (usually as "/lib/cpp"), and the resulting binary
+/* should be installed as "/somewhere/cpp".
+/* SEE ALSO
+/* .ad
+/* .fi
+/* cc(1), how to specify a non-default C preprocessor.
+/*
+/* Some versions of the lint command are implemented as a shell
+/* script. It should require only minor modification for integration
+/* with the unprotoizer. Other versions of the lint command accept the same
+/* command syntax as the C compiler for the specification of a non-default
+/* preprocessor. Some research may be needed.
+/* DIAGNOSTICS
+/* The progam will complain if it unexpectedly
+/* reaches the end of input.
+/* BUGS
+/* Should be run on preprocessed source only, i.e. after macro expansion.
+/*
+/* Declarations of (whatever) are misunderstood and will result in
+/* syntax errors.
+/*
+/* Does not generate explicit type casts for function argument
+/* expressions.
+/* AUTHOR(S)
+/* Wietse Venema (wietse@wzv.win.tue.nl)
+/* Eindhoven University of Technology
+/* Department of Mathematics and Computer Science
+/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
+/* LAST MODIFICATION
+/* 91/09/22 21:21:35
+/* VERSION/RELEASE
+/* 1.2
+/*--*/
+
+static char unproto_sccsid[] = "@(#) unproto.c 1.3 91/11/30 21:10:30";
+
+/* C library */
+
+#include <stdio.h>
+#include <errno.h>
+
+extern void exit();
+extern int optind;
+extern char *optarg;
+extern int getopt();
+
+/* Application-specific stuff */
+
+#include "vstring.h"
+#include "stdarg.h"
+#include "token.h"
+#include "error.h"
+#include "symbol.h"
+
+/* Forward declarations. */
+
+static struct token *dcl_flush();
+static void block_flush();
+static void block_dcls();
+static struct token *show_func_ptr_type();
+static struct token *show_struct_type();
+static void show_arg_name();
+static void show_type();
+static void pair_flush();
+static void check_cast();
+
+#define check_cast_flush(t) (check_cast(t), tok_free(t))
+
+#ifdef PIPE_THROUGH_CPP
+static int pipe_stdin_through_cpp();
+#endif
+
+/* Disable debugging printfs while preserving side effects. */
+
+#ifdef DEBUG
+#define DPRINTF printf
+#else
+#define DPRINTF (void)
+#endif
+
+/* An attempt to make some complicated expressions a bit more readable. */
+
+#define STREQ(x,y) (*(x) == *(y) && !strcmp((x),(y)))
+
+#define LAST_ARG_AND_EQUAL(s,c) ((s)->next == 0 && (s)->head \
+ && ((s)->head == (s)->tail) \
+ && (STREQ((s)->head->vstr->str, (c))))
+
+#define LIST_BEGINS_WITH_STAR(s) (s->head->head && s->head->head->tokno == '*')
+
+#define IS_FUNC_PTR_TYPE(s) (s->tokno == TOK_LIST && s->next \
+ && s->next->tokno == TOK_LIST \
+ && LIST_BEGINS_WITH_STAR(s))
+
+/* main - driver */
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ register struct token *t;
+#ifdef PIPE_THROUGH_CPP /* pipe through /lib/cpp */
+ int cpp_status;
+ int wait_pid;
+ int cpp_pid;
+
+ cpp_pid = pipe_stdin_through_cpp(argv);
+#else
+ if ( argc > 1 ) {
+ if( freopen(argv[1], "r", stdin) == 0 ) {
+ fprintf(stderr, "Cannot open '%s'\n", argv[1]);
+ exit(9);
+ }
+ }
+ if ( argc > 2 ) {
+ if( freopen(argv[2], "w", stdout) == 0 ) {
+ fprintf(stderr, "Cannot open '%s'\n", argv[2]);
+ exit(9);
+ }
+ }
+#endif
+
+ sym_init(); /* prime the symbol table */
+
+ while (t = tok_class(DO_WSPACE)) {
+ if (t = dcl_flush(t)) { /* try declaration */
+ if (t->tokno == '{') { /* examine rejected token */
+ block_flush(t); /* body */
+ } else {
+ tok_flush(t); /* other, recover */
+ }
+ }
+ }
+
+#ifdef PIPE_THROUGH_CPP /* pipe through /lib/cpp */
+ while ((wait_pid = wait(&cpp_status)) != -1 && wait_pid != cpp_pid)
+ /* void */ ;
+ return (wait_pid != cpp_pid || cpp_status != 0);
+#else
+ return (0);
+#endif
+}
+
+#ifdef PIPE_THROUGH_CPP /* pipe through /lib/cpp */
+
+/* pipe_stdin_through_cpp - avoid shell script overhead */
+
+static int pipe_stdin_through_cpp(argv)
+char **argv;
+{
+ int pipefds[2];
+ int pid;
+ char **cpptr = argv;
+
+ /*
+ * With most UNIX implementations, the second non-option argument to
+ * /lib/cpp specifies the output file. If an output file other than
+ * stdout is specified, we must force /lib/cpp to write to stdout, and we
+ * must redirect our own standard output to the specified output file.
+ */
+
+#define IS_OPTION(cp) ((cp)[0] == '-' && (cp)[1] != 0)
+
+ /* Skip to first non-option argument, if any. */
+
+ while (*++cpptr && IS_OPTION(*cpptr))
+ /* void */ ;
+
+ /*
+ * Assume that the first non-option argument is the input file name. The
+ * next argument could be the output destination or an option (System V
+ * Release 2 /lib/cpp gets the options *after* the file arguments).
+ */
+
+ if (*cpptr && *++cpptr && **cpptr != '-') {
+
+ /*
+ * The first non-option argument is followed by another argument that
+ * is not an option ("-stuff") or a hyphen ("-"). Redirect our own
+ * standard output before we clobber the file name.
+ */
+
+ if (freopen(*cpptr, "w", stdout) == 0) {
+ perror(*cpptr);
+ exit(1);
+ }
+ /* Clobber the file name argument so that /lib/cpp writes to stdout */
+
+ *cpptr = "-";
+ }
+ /* Set up the pipe that connects /lib/cpp to our standard input. */
+
+ if (pipe(pipefds)) {
+ perror("pipe");
+ exit(1);
+ }
+ switch (pid = fork()) {
+ case -1: /* error */
+ perror("fork");
+ exit(1);
+ case 0: /* child */
+ close(pipefds[0]); /* close reading end */
+ close(1); /* connect stdout to pipe */
+ if (dup(pipefds[1]) != 1)
+ error(1, "dup() problem");
+ close(pipefds[1]); /* close redundant fd */
+ execv(PIPE_THROUGH_CPP, argv);
+ perror(PIPE_THROUGH_CPP);
+ exit(1);
+ default: /* parent */
+ close(pipefds[1]); /* close writing end */
+ close(0); /* connect stdin to pipe */
+ if (dup(pipefds[0]) != 0)
+ error(1, "dup() problem");
+ close(pipefds[0]); /* close redundant fd */
+ return (pid);
+ }
+}
+
+#endif
+
+/* header_flush - rewrite new-style function header to old style */
+
+static void header_flush(t)
+register struct token *t;
+{
+ register struct token *s;
+
+ /* Do argument names, but suppress void and rewrite trailing ... */
+
+ if (LAST_ARG_AND_EQUAL(t->head, "void")) {
+ put_str("()\n"); /* no arguments */
+ } else {
+ for (s = t->head; s; s = s->next) { /* foreach argument... */
+ if (LAST_ARG_AND_EQUAL(s, "...")) {
+#ifdef _VA_ALIST_ /* see ./stdarg.h */
+ put_ch(s->tokno); /* ',' */
+ put_str(_VA_ALIST_); /* varargs magic */
+#endif
+ } else {
+ put_ch(s->tokno); /* opening '(' or ',' */
+ show_arg_name(s); /* extract argument name */
+ }
+ }
+ put_str(")\n"); /* closing ')' */
+ }
+
+ /* Do argument types, but suppress void and trailing ... */
+
+ if (!LAST_ARG_AND_EQUAL(t->head, "void")) {
+ for (s = t->head; s; s = s->next) { /* foreach argument... */
+ if (!LAST_ARG_AND_EQUAL(s, "...")) {
+ if (s->head != s->tail) { /* really new-style argument? */
+ show_line_control(); /* fix line number */
+ show_type(s); /* rewrite type info */
+ put_str(";\n");
+ }
+ }
+ }
+ }
+ tok_free(t);
+ show_line_control(); /* because '{' follows */
+}
+
+/* show_arg_name - extract argument name from argument type info */
+
+static void show_arg_name(s)
+register struct token *s;
+{
+ if (s->head) {
+ register struct token *p;
+ register struct token *t = 0;
+
+ /* Find the last interesting item. */
+
+ for (p = s->head; p; p = p->next) {
+ if (p->tokno == TOK_WORD) {
+ t = p; /* remember last word */
+ } else if (IS_FUNC_PTR_TYPE(p)) {
+ t = p; /* or function pointer */
+ p = p->next;
+ }
+ }
+
+ /* Extract argument name from last interesting item. */
+
+ if (t) {
+ if (t->tokno == TOK_LIST)
+ show_arg_name(t->head); /* function pointer, recurse */
+ else
+ tok_show(t); /* print last word */
+ }
+ }
+}
+
+/* show_type - rewrite type to old-style syntax */
+
+static void show_type(s)
+register struct token *s;
+{
+ register struct token *p;
+
+ for (p = s->head; p; p = p->next) {
+ if (IS_FUNC_PTR_TYPE(p)) {
+ p = show_func_ptr_type(p); /* function pointer type */
+ } else {
+ tok_show(p); /* other */
+ }
+ }
+}
+
+/* show_func_ptr_type - display function_pointer type using old-style syntax */
+
+static struct token *show_func_ptr_type(t)
+struct token *t;
+{
+ register struct token *s;
+
+ /*
+ * Rewrite (list1) (list2) to (list1) (). Only (list1) is given to us;
+ * the caller must have verified the presence of (list2). Account for the
+ * rare case that (list1) is a comma-separated list. That should be an
+ * error, but we do not want to waste any information.
+ */
+
+ for (s = t->head; s; s = s->next) {
+ put_ch(s->tokno); /* opening paren or ',' */
+ show_type(s); /* recurse */
+ }
+ put_str(")()"); /* closing paren */
+ return (t->next);
+}
+
+/* show_struct_type - display structured type, rewrite function-pointer types */
+
+static struct token *show_struct_type(p)
+register struct token *p;
+{
+ tok_show(p); /* opening brace */
+
+ while (p->next) { /* XXX cannot return 0 */
+ p = p->next;
+ if (IS_FUNC_PTR_TYPE(p)) {
+ p = show_func_ptr_type(p); /* function-pointer member */
+ } else if (p->tokno == '{') {
+ p = show_struct_type(p); /* recurse */
+ } else {
+ tok_show(p); /* other */
+ if (p->tokno == '}') {
+ return (p); /* done */
+ }
+ }
+ }
+ DPRINTF("/* missing '}' */");
+ return (p);
+}
+
+/* is_func_ptr_cast - recognize function-pointer type cast */
+
+static int is_func_ptr_cast(t)
+register struct token *t;
+{
+ register struct token *p;
+
+ /*
+ * Examine superficial structure. Require (list1) (list2). Require that
+ * list1 begins with a star.
+ */
+
+ if (!IS_FUNC_PTR_TYPE(t))
+ return (0);
+
+ /*
+ * Make sure that there is no name in (list1). Do not worry about
+ * unexpected tokens, because the compiler will complain anyway.
+ */
+
+ for (p = t->head->head; p; p = p->next) {
+ switch (p->tokno) {
+ case TOK_LIST: /* recurse */
+ return (is_func_ptr_cast(p));
+ case TOK_WORD: /* name in list */
+ return (0);
+ }
+ }
+ return (1); /* no name found */
+}
+
+/* check_cast - display ()-delimited, comma-separated list */
+
+static void check_cast(t)
+struct token *t;
+{
+ register struct token *s;
+ register struct token *p;
+
+ /*
+ * Rewrite function-pointer types and function-pointer casts. Do not
+ * blindly rewrite (*list1)(list2) to (*list1)(). Function argument lists
+ * are about the only thing we can discard without provoking diagnostics
+ * from the compiler.
+ */
+
+ for (s = t->head; s; s = s->next) {
+ put_ch(s->tokno); /* opening paren or ',' */
+ for (p = s->head; p; p = p->next) {
+ switch (p->tokno) {
+ case TOK_LIST:
+ if (is_func_ptr_cast(p)) { /* not: IS_FUNC_PTR_TYPE(p) */
+ p = show_func_ptr_type(p); /* or we might take away */
+ } else { /* function-call arguments */
+ check_cast(p); /* recurse */
+ }
+ break;
+ case '{':
+ p = show_struct_type(p); /* rewrite func. ptr. types */
+ break;
+ default:
+ tok_show(p);
+ break;
+ }
+ }
+ }
+ put_ch(')'); /* closing paren */
+}
+
+/* block_dcls - on the fly rewrite decls/initializers at start of block */
+
+static void block_dcls()
+{
+ register struct token *t;
+
+ /*
+ * Away from the top level, a declaration should be preceded by type or
+ * storage-class information. That is why inside blocks, structs and
+ * unions we insist on reading one word before passing the _next_ token
+ * to the dcl_flush() function.
+ *
+ * Struct and union declarations look the same everywhere: we make an
+ * exception for these more regular constructs and pass the "struct" and
+ * "union" tokens to the type_dcl() function.
+ */
+
+ while (t = tok_class(DO_WSPACE)) {
+ switch (t->tokno) {
+ case TOK_WSPACE: /* preserve white space */
+ case '\n': /* preserve line count */
+ tok_flush(t);
+ break;
+ case TOK_WORD: /* type declarations? */
+ tok_flush(t); /* advance to next token */
+ t = tok_class(DO_WSPACE); /* null return is ok */
+ case TOK_COMPOSITE: /* struct or union */
+ if ((t = dcl_flush(t)) == 0)
+ break;
+ /* FALLTRHOUGH */
+ default: /* end of declarations */
+ DPRINTF("/* end dcls */");
+ /* FALLTRHOUGH */
+ case '}': /* end of block */
+ tok_unget(t);
+ return;
+ }
+ }
+}
+
+/* block_flush - rewrite struct, union or statement block on the fly */
+
+static void block_flush(t)
+register struct token *t;
+{
+ static int count = 0;
+
+ tok_flush(t);
+ DPRINTF("/*%d*/", ++count);
+
+ /*
+ * Rewrite function pointer types in declarations and function pointer
+ * casts in initializers at start of block.
+ */
+
+ block_dcls();
+
+ /* Remainder of block: only rewrite function pointer casts. */
+
+ while (t = tok_class(DO_WSPACE)) {
+ if (t->tokno == TOK_LIST) {
+ check_cast_flush(t);
+ } else if (t->tokno == '{') {
+ block_flush(t);
+ } else {
+ tok_flush(t);
+ if (t->tokno == '}') {
+ DPRINTF("/*%d*/", count--);
+ return;
+ }
+ }
+ }
+ DPRINTF("/* missing '}' */");
+}
+
+/* pair_flush - on the fly rewrite casts in grouped stuff */
+
+static void pair_flush(t, start, stop)
+register struct token *t;
+register int start;
+register int stop;
+{
+ tok_flush(t);
+
+ while (t = tok_class(DO_WSPACE)) {
+ if (t->tokno == start) { /* recurse */
+ pair_flush(t, start, stop);
+ } else if (t->tokno == TOK_LIST) { /* expression or cast */
+ check_cast_flush(t);
+ } else { /* other, copy */
+ tok_flush(t);
+ if (t->tokno == stop) { /* done */
+ return;
+ }
+ }
+ }
+ DPRINTF("/* missing '%c' */", stop);
+}
+
+/* initializer - on the fly rewrite casts in initializer */
+
+static void initializer()
+{
+ register struct token *t;
+
+ while (t = tok_class(DO_WSPACE)) {
+ switch (t->tokno) {
+ case ',': /* list separator */
+ case ';': /* list terminator */
+ tok_unget(t);
+ return;
+ case TOK_LIST: /* expression or cast */
+ check_cast_flush(t);
+ break;
+ case '[': /* array substript, may nest */
+ pair_flush(t, '[', ']');
+ break;
+ case '{': /* structured data, may nest */
+ pair_flush(t, '{', '}');
+ break;
+ default: /* other, just copy */
+ tok_flush(t);
+ break;
+ }
+ }
+}
+
+/* func_ptr_dcl_flush - rewrite function pointer declaration */
+
+static struct token *func_ptr_dcl_flush(list)
+register struct token *list;
+{
+ register struct token *t;
+
+ /*
+ * Ignore blanks because they would be output earlier than the list that
+ * preceded them... Recover gracefully from syntax errors.
+ */
+
+ while (t = tok_class(NO_WSPACE)) {
+ switch (t->tokno) {
+ case '\n': /* preserve line count */
+ tok_flush(t);
+ break;
+ case TOK_LIST:
+ /* Function pointer type: (list1) (list2) -> (list1) () */
+ (void) show_func_ptr_type(list); /* may be recursive */
+ tok_free(list);
+ tok_free(t);
+ return (0);
+ default: /* not a declaration */
+ tok_unget(t);
+ return (list);
+ }
+ }
+
+ /* Hit EOF; must be mistake, but do not waste any information. */
+
+ return (list);
+}
+
+/* function_dcl_flush - rewrite function { heading, type declaration } */
+
+static struct token *function_dcl_flush(list)
+register struct token *list;
+{
+ register struct token *t;
+
+ /*
+ * Ignore blanks because they would be output earlier than the list that
+ * preceded them...
+ */
+
+ while (t = tok_class(NO_WSPACE)) {
+ switch (t->tokno) {
+ case '\n':
+ /* Preserve line count */
+ tok_flush(t);
+ break;
+ case '{':
+ /* Function heading: word (list) { -> old style heading */
+ header_flush(list);
+ tok_unget(t);
+ return (0);
+ case TOK_WORD:
+ /* Old-style function heading: word (list) word...{ */
+ tok_flush(list);
+ tok_unget(t);
+ return (0);
+ case TOK_LIST:
+ /* Function typedef? word (list1) (list) -> word (list1) () */
+ tok_flush(list);
+ put_str("()");
+ tok_free(t);
+ return (0);
+ case ',':
+ case ';':
+ /* Function type declaration: word (list) -> word () */
+ tok_free(list);
+ put_str("()");
+ tok_unget(t);
+ return (0);
+ default:
+ /* Something else, reject the list. */
+ tok_unget(t);
+ return (list);
+ }
+ }
+
+ /* Hit EOF; must be mistake, but do not waste any information. */
+
+ return (list);
+}
+
+/* dcl_flush - parse declaration on the fly, return rejected token */
+
+static struct token *dcl_flush(t)
+register struct token *t;
+{
+ register int got_word;
+
+ /*
+ * Away from the top level, type or storage-class information is required
+ * for an (extern or forward) function type declaration or a variable
+ * declaration.
+ *
+ * With our naive word-counting approach, this means that the caller should
+ * read one word before passing the next token to us. This is how we
+ * distinguish, for example, function declarations from function calls.
+ *
+ * An exception are structs and unions, because they look the same at any
+ * level. The caller should give is the "struct" or "union" token.
+ */
+
+ for (got_word = 0; t; t = tok_class(DO_WSPACE)) {
+ switch (t->tokno) {
+ case TOK_WSPACE: /* advance past blanks */
+ case '\n': /* advance past newline */
+ case '*': /* indirection: keep trying */
+ tok_flush(t);
+ break;
+ case TOK_WORD: /* word: keep trying */
+ case TOK_COMPOSITE: /* struct or union */
+ got_word = 1;
+ tok_flush(t);
+ break;
+ default:
+
+ /*
+ * Function pointer types can be preceded by zero or more words
+ * (at least one when not at the top level). Other stuff can be
+ * accepted only after we have seen at least one word (two words
+ * when not at the top level). See also the above comment on
+ * structs and unions.
+ */
+
+ if (t->tokno == TOK_LIST && LIST_BEGINS_WITH_STAR(t)) {
+ if (t = func_ptr_dcl_flush(t)) {
+ return (t); /* reject token */
+ } else {
+ got_word = 1; /* for = and [ and , and ; */
+ }
+ } else if (got_word == 0) {
+ return (t); /* reject token */
+ } else {
+ switch (t->tokno) {
+ case TOK_LIST: /* function type */
+ if (t = function_dcl_flush(t))
+ return (t); /* reject token */
+ break;
+ case '[': /* dimension, does not nest */
+ pair_flush(t, '[', ']');
+ break;
+ case '=': /* initializer follows */
+ tok_flush(t);
+ initializer(); /* rewrite casts */
+ break;
+ case '{': /* struct, union, may nest */
+ block_flush(t); /* use code for stmt blocks */
+ break;
+ case ',': /* separator: keep trying */
+ got_word = 0;
+ tok_flush(t);
+ break;
+ case ';': /* terminator: succeed */
+ tok_flush(t);
+ return (0);
+ default: /* reject token */
+ return (t);
+ }
+ }
+ }
+ }
+ return (0); /* hit EOF */
+}
diff --git a/unproto/varargs.c b/unproto/varargs.c
new file mode 100644
index 0000000..4ca56d8
--- /dev/null
+++ b/unproto/varargs.c
@@ -0,0 +1,32 @@
+ /*
+ * @(#) varargs.c 1.1 91/09/01 23:08:45
+ *
+ * This program can be used to verify that the stdarg.h file is set up
+ * correctly for your system. If it works, it should print one line with the
+ * text "stdarg.h works".
+ */
+
+#include <stdio.h>
+#include "stdarg.h"
+
+main(int argc, char *argv[])
+{
+ varargs_test("%s %s\n", "stdarg.h", "works");
+}
+
+varargs_test(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ while (*fmt) {
+ if (strncmp("%s", fmt, 2) == 0) {
+ fputs(va_arg(ap, char *), stdout);
+ fmt += 2;
+ } else {
+ putchar(*fmt);
+ fmt++;
+ }
+ }
+ va_end(ap);
+}
diff --git a/unproto/vstring.c b/unproto/vstring.c
new file mode 100644
index 0000000..fb8d053
--- /dev/null
+++ b/unproto/vstring.c
@@ -0,0 +1,91 @@
+/*++
+/* NAME
+/* vs_alloc(), VS_ADDCH()
+/* SUMMARY
+/* auto-resizing string library
+/* PACKAGE
+/* vstring
+/* SYNOPSIS
+/* #include "vstring.h"
+/*
+/* struct vstring *vs_alloc(len)
+/* int len;
+/*
+/* int VS_ADDCH(vs, wp, ch)
+/* struct vstring *vs;
+/* char *wp;
+/* int ch;
+/* DESCRIPTION
+/* These functions and macros implement a small library for
+/* arbitrary-length strings that grow automatically when
+/* they fill up. The allocation strategy is such that there
+/* will always be place for the terminating null character.
+/*
+/* vs_alloc() allocates storage for a variable-length string.
+/*
+/* VS_ADDCH() adds a character to a variable-length string
+/* and automagically extends the string if fills up.
+/* \fIvs\fP is a pointer to a vstring structure; \fIwp\fP
+/* the current write position in the corresponding character
+/* array; \fIch\fP the character value to be written.
+/* Note that VS_ADDCH() is a macro that evaluates some
+/* arguments more than once.
+/* DIAGNOSTICS
+/* VS_ADDCH() returns zero if it was unable to dynamically
+/* resize a string.
+/*
+/* vs_alloc() returns a null pointer in case of problems.
+/* BUGS
+/* Auto-resizing may change the address of the string data in
+/* a vstring structure. Beware of dangling pointers.
+/* AUTHOR(S)
+/* Wietse Venema
+/* Eindhoven University of Technology
+/* Department of Mathematics and Computer Science
+/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
+/* LAST MODIFICATION
+/* 91/09/22 21:21:38
+/* VERSION/RELEASE
+/* 1.2
+/*--*/
+
+static char vstring_sccsid[] = "@(#) vstring.c 1.2 91/09/22 21:21:38";
+
+/* C library */
+
+extern char *malloc();
+extern char *realloc();
+
+/* Application-specific stuff */
+
+#include "vstring.h"
+
+/* vs_alloc - initial string allocation */
+
+struct vstring *vs_alloc(len)
+int len;
+{
+ register struct vstring *vp;
+
+ if (len < 1
+ || (vp = (struct vstring *) malloc(sizeof(struct vstring))) == 0
+ || (vp->str = malloc(len)) == 0)
+ return (0);
+ vp->last = vp->str + len - 1;
+ return (vp);
+}
+
+/* vs_realloc - extend string, update write pointer */
+
+char *vs_realloc(vp, cp)
+register struct vstring *vp;
+char *cp;
+{
+ int where = cp - vp->str;
+ int len = vp->last - vp->str + 1;
+
+ if ((vp->str = realloc(vp->str, len *= 2)) == 0)
+ return (0);
+ vp->last = vp->str + len - 1;
+ return (vp->str + where);
+}
diff --git a/unproto/vstring.h b/unproto/vstring.h
new file mode 100644
index 0000000..ec02a6e
--- /dev/null
+++ b/unproto/vstring.h
@@ -0,0 +1,14 @@
+/* @(#) vstring.h 1.1 91/09/01 23:08:42 */
+
+struct vstring {
+ char *str; /* string value */
+ char *last; /* last position */
+};
+
+extern struct vstring *vs_alloc(); /* initial allocation */
+extern char *vs_realloc(); /* string extension */
+
+/* macro to add one character to auto-resized string */
+
+#define VS_ADDCH(vs,wp,c) \
+ ((wp < (vs)->last || (wp = vs_realloc(vs,wp))) ? (*wp++ = c) : 0)