summaryrefslogtreecommitdiffstats
path: root/private/crt32
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/crt32')
-rw-r--r--private/crt32/buildcrt.cmd52
-rw-r--r--private/crt32/convert/_ctype.c156
-rw-r--r--private/crt32/convert/_fptostr.c104
-rw-r--r--private/crt32/convert/_mbslen.c99
-rw-r--r--private/crt32/convert/_wctype.c140
-rw-r--r--private/crt32/convert/atof.c81
-rw-r--r--private/crt32/convert/atox.c96
-rw-r--r--private/crt32/convert/fcvt.c252
-rw-r--r--private/crt32/convert/gcvt.c122
-rw-r--r--private/crt32/convert/isctype.c119
-rw-r--r--private/crt32/convert/iswctype.c128
-rw-r--r--private/crt32/convert/makefile6
-rw-r--r--private/crt32/convert/mblen.c109
-rw-r--r--private/crt32/convert/mbstowcs.c197
-rw-r--r--private/crt32/convert/mbtowc.c174
-rw-r--r--private/crt32/convert/sources64
-rw-r--r--private/crt32/convert/strtod.c121
-rw-r--r--private/crt32/convert/strtol.c227
-rw-r--r--private/crt32/convert/strtoq.c236
-rw-r--r--private/crt32/convert/swab.c58
-rw-r--r--private/crt32/convert/testconv.c152
-rw-r--r--private/crt32/convert/tolower.c155
-rw-r--r--private/crt32/convert/toupper.c189
-rw-r--r--private/crt32/convert/towlower.c84
-rw-r--r--private/crt32/convert/towupper.c94
-rw-r--r--private/crt32/convert/wcstod.c115
-rw-r--r--private/crt32/convert/wcstol.c215
-rw-r--r--private/crt32/convert/wcstombs.c213
-rw-r--r--private/crt32/convert/wctomb.c136
-rw-r--r--private/crt32/convert/wtox.c82
-rw-r--r--private/crt32/convert/xtoa.c127
-rw-r--r--private/crt32/convert/xtow.c85
-rw-r--r--private/crt32/crt32.def95
-rw-r--r--private/crt32/direct/drivemap.c39
-rw-r--r--private/crt32/direct/drivfree.c69
-rw-r--r--private/crt32/direct/findfile.c224
-rw-r--r--private/crt32/direct/makefile6
-rw-r--r--private/crt32/direct/peekpoke.c95
-rw-r--r--private/crt32/direct/seterrm.c63
-rw-r--r--private/crt32/direct/slbeep.c105
-rw-r--r--private/crt32/direct/sources40
-rw-r--r--private/crt32/dirs43
-rw-r--r--private/crt32/dllstuff/cinitexe.c92
-rw-r--r--private/crt32/dllstuff/crtdll.c376
-rw-r--r--private/crt32/dllstuff/crtexe.c215
-rw-r--r--private/crt32/dllstuff/crtexew.c4
-rw-r--r--private/crt32/dllstuff/crtlib.c258
-rw-r--r--private/crt32/dllstuff/dllargv.c49
-rw-r--r--private/crt32/dllstuff/i386/dllsupp.asm39
-rw-r--r--private/crt32/dllstuff/makefile6
-rw-r--r--private/crt32/dllstuff/sources44
-rw-r--r--private/crt32/dos/access.c116
-rw-r--r--private/crt32/dos/chdir.c138
-rw-r--r--private/crt32/dos/chmod.c121
-rw-r--r--private/crt32/dos/dosmap.c252
-rw-r--r--private/crt32/dos/drive.c208
-rw-r--r--private/crt32/dos/fullpath.c318
-rw-r--r--private/crt32/dos/getcwd.c451
-rw-r--r--private/crt32/dos/getpid.c72
-rw-r--r--private/crt32/dos/makefile6
-rw-r--r--private/crt32/dos/mkdir.c80
-rw-r--r--private/crt32/dos/rename.c83
-rw-r--r--private/crt32/dos/rmdir.c83
-rw-r--r--private/crt32/dos/sources48
-rw-r--r--private/crt32/dos/stat.c397
-rw-r--r--private/crt32/dos/unlink.c101
-rw-r--r--private/crt32/exec/cenvarg.c373
-rw-r--r--private/crt32/exec/cfinfo.c22
-rw-r--r--private/crt32/exec/dospawn.c303
-rw-r--r--private/crt32/exec/execl.c76
-rw-r--r--private/crt32/exec/execle.c79
-rw-r--r--private/crt32/exec/execlp.c77
-rw-r--r--private/crt32/exec/execlpe.c82
-rw-r--r--private/crt32/exec/execv.c60
-rw-r--r--private/crt32/exec/execve.c2
-rw-r--r--private/crt32/exec/execvp.c62
-rw-r--r--private/crt32/exec/execvpe.c171
-rw-r--r--private/crt32/exec/fileinfo.c22
-rw-r--r--private/crt32/exec/getproc.c62
-rw-r--r--private/crt32/exec/loaddll.c70
-rw-r--r--private/crt32/exec/makefile6
-rw-r--r--private/crt32/exec/sources58
-rw-r--r--private/crt32/exec/spawnl.c83
-rw-r--r--private/crt32/exec/spawnle.c83
-rw-r--r--private/crt32/exec/spawnlp.c85
-rw-r--r--private/crt32/exec/spawnlpe.c87
-rw-r--r--private/crt32/exec/spawnv.c67
-rw-r--r--private/crt32/exec/spawnve.c318
-rw-r--r--private/crt32/exec/spawnvp.c62
-rw-r--r--private/crt32/exec/spawnvpe.c209
-rw-r--r--private/crt32/exec/system.c95
-rw-r--r--private/crt32/exec/wait.c199
-rw-r--r--private/crt32/h/assert.h89
-rw-r--r--private/crt32/h/cmacros.mas3050
-rw-r--r--private/crt32/h/cmsgs.h71
-rw-r--r--private/crt32/h/conio.h127
-rw-r--r--private/crt32/h/cruntime.h277
-rw-r--r--private/crt32/h/cruntime.inc826
-rw-r--r--private/crt32/h/ctime.h41
-rw-r--r--private/crt32/h/ctype.h321
-rw-r--r--private/crt32/h/cvt.h41
-rw-r--r--private/crt32/h/defsects.inc58
-rw-r--r--private/crt32/h/direct.h134
-rw-r--r--private/crt32/h/dos.h222
-rw-r--r--private/crt32/h/doscalls.h545
-rw-r--r--private/crt32/h/dostypes.h112
-rw-r--r--private/crt32/h/errmsg.h36
-rw-r--r--private/crt32/h/errno.h127
-rw-r--r--private/crt32/h/error.h383
-rw-r--r--private/crt32/h/error2.h277
-rw-r--r--private/crt32/h/except.inc100
-rw-r--r--private/crt32/h/excpt.h209
-rw-r--r--private/crt32/h/exsup.inc79
-rw-r--r--private/crt32/h/fcntl.h84
-rw-r--r--private/crt32/h/file2.h71
-rw-r--r--private/crt32/h/float.h493
-rw-r--r--private/crt32/h/fltintrn.h192
-rw-r--r--private/crt32/h/fpieee.h362
-rw-r--r--private/crt32/h/fstream.h145
-rw-r--r--private/crt32/h/heap.h433
-rw-r--r--private/crt32/h/internal.h359
-rw-r--r--private/crt32/h/io.h236
-rw-r--r--private/crt32/h/iomanip.h133
-rw-r--r--private/crt32/h/ios.h272
-rw-r--r--private/crt32/h/iostream.h90
-rw-r--r--private/crt32/h/istream.h165
-rw-r--r--private/crt32/h/jctype.h111
-rw-r--r--private/crt32/h/limits.h89
-rw-r--r--private/crt32/h/locale.h125
-rw-r--r--private/crt32/h/malloc.h168
-rw-r--r--private/crt32/h/math.h283
-rw-r--r--private/crt32/h/mbctype.h146
-rw-r--r--private/crt32/h/mbdata.h130
-rw-r--r--private/crt32/h/mbstring.h227
-rw-r--r--private/crt32/h/memory.h101
-rw-r--r--private/crt32/h/msdos.h83
-rw-r--r--private/crt32/h/msdos.inc276
-rw-r--r--private/crt32/h/mtest.h68
-rw-r--r--private/crt32/h/new.h67
-rw-r--r--private/crt32/h/nlsint.h60
-rw-r--r--private/crt32/h/os2dll.h260
-rw-r--r--private/crt32/h/oscalls.h141
-rw-r--r--private/crt32/h/ostream.h135
-rw-r--r--private/crt32/h/process.h244
-rw-r--r--private/crt32/h/pversion.inc28
-rw-r--r--private/crt32/h/rterr.h76
-rw-r--r--private/crt32/h/search.h104
-rw-r--r--private/crt32/h/setjmp.h299
-rw-r--r--private/crt32/h/setjmpex.h41
-rw-r--r--private/crt32/h/setlocal.h142
-rw-r--r--private/crt32/h/share.h35
-rw-r--r--private/crt32/h/signal.h129
-rw-r--r--private/crt32/h/sizeptr.h45
-rw-r--r--private/crt32/h/stdarg.h153
-rw-r--r--private/crt32/h/stddef.h153
-rw-r--r--private/crt32/h/stdio.h503
-rw-r--r--private/crt32/h/stdiostr.h59
-rw-r--r--private/crt32/h/stdlib.h552
-rw-r--r--private/crt32/h/streamb.h184
-rw-r--r--private/crt32/h/string.h228
-rw-r--r--private/crt32/h/strstrea.h93
-rw-r--r--private/crt32/h/sys/locking.h38
-rw-r--r--private/crt32/h/sys/stat.h151
-rw-r--r--private/crt32/h/sys/timeb.h129
-rw-r--r--private/crt32/h/sys/types.h58
-rw-r--r--private/crt32/h/sys/utime.h106
-rw-r--r--private/crt32/h/syserr.h44
-rw-r--r--private/crt32/h/tchar.h587
-rw-r--r--private/crt32/h/time.h242
-rw-r--r--private/crt32/h/timeb.inc37
-rw-r--r--private/crt32/h/v2tov3.h74
-rw-r--r--private/crt32/h/varargs.h160
-rw-r--r--private/crt32/h/wchar.h352
-rw-r--r--private/crt32/h/winheap.h25
-rw-r--r--private/crt32/hack/makefile6
-rw-r--r--private/crt32/hack/sources36
-rw-r--r--private/crt32/hack/stubs.c42
-rw-r--r--private/crt32/heap/calloc.c88
-rw-r--r--private/crt32/heap/delete.cxx28
-rw-r--r--private/crt32/heap/findaddr.c108
-rw-r--r--private/crt32/heap/free.c171
-rw-r--r--private/crt32/heap/handler.cxx53
-rw-r--r--private/crt32/heap/heapadd.c413
-rw-r--r--private/crt32/heap/heapchk.c330
-rw-r--r--private/crt32/heap/heapdump.c334
-rw-r--r--private/crt32/heap/heapgrow.c490
-rw-r--r--private/crt32/heap/heapinit.c266
-rw-r--r--private/crt32/heap/heapmin.c520
-rw-r--r--private/crt32/heap/heapprm.c87
-rw-r--r--private/crt32/heap/heapsrch.c150
-rw-r--r--private/crt32/heap/heapwalk.c170
-rw-r--r--private/crt32/heap/hpabort.c47
-rw-r--r--private/crt32/heap/makefile7
-rw-r--r--private/crt32/heap/malloc.c474
-rw-r--r--private/crt32/heap/msize.c112
-rw-r--r--private/crt32/heap/new.cxx28
-rw-r--r--private/crt32/heap/realloc.c477
-rw-r--r--private/crt32/heap/sources71
-rw-r--r--private/crt32/helper/empty.c5
-rw-r--r--private/crt32/helper/makefile8
-rw-r--r--private/crt32/helper/mips/llabsdiv.c62
-rw-r--r--private/crt32/helper/mips/llbit.c127
-rw-r--r--private/crt32/helper/mips/llcvt.s364
-rw-r--r--private/crt32/helper/mips/lldefs.h92
-rw-r--r--private/crt32/helper/mips/lldiv.c251
-rw-r--r--private/crt32/helper/mips/lldivrem.s237
-rw-r--r--private/crt32/helper/mips/llmul.s57
-rw-r--r--private/crt32/helper/mips/llshift.s226
-rw-r--r--private/crt32/helper/mips/llshiftt.c146
-rw-r--r--private/crt32/helper/sources65
-rw-r--r--private/crt32/iostream/cerrinit.cxx28
-rw-r--r--private/crt32/iostream/cininit.cxx28
-rw-r--r--private/crt32/iostream/cloginit.cxx28
-rw-r--r--private/crt32/iostream/filebuf.cxx460
-rw-r--r--private/crt32/iostream/filebuf1.cxx231
-rw-r--r--private/crt32/iostream/fstream.cxx261
-rw-r--r--private/crt32/iostream/ifstream.cxx240
-rw-r--r--private/crt32/iostream/ios.cxx323
-rw-r--r--private/crt32/iostream/iostream.cxx83
-rw-r--r--private/crt32/iostream/iostrini.cxx83
-rw-r--r--private/crt32/iostream/istrchar.cxx40
-rw-r--r--private/crt32/iostream/istrdbl.cxx46
-rw-r--r--private/crt32/iostream/istream.cxx278
-rw-r--r--private/crt32/iostream/istream1.cxx98
-rw-r--r--private/crt32/iostream/istrflt.cxx58
-rw-r--r--private/crt32/iostream/istrgdbl.cxx105
-rw-r--r--private/crt32/iostream/istrget.cxx65
-rw-r--r--private/crt32/iostream/istrgetl.cxx70
-rw-r--r--private/crt32/iostream/istrgint.cxx145
-rw-r--r--private/crt32/iostream/istrint.cxx71
-rw-r--r--private/crt32/iostream/istrldbl.cxx48
-rw-r--r--private/crt32/iostream/istrlong.cxx63
-rw-r--r--private/crt32/iostream/istrshrt.cxx71
-rw-r--r--private/crt32/iostream/istruint.cxx72
-rw-r--r--private/crt32/iostream/istrulng.cxx65
-rw-r--r--private/crt32/iostream/istrusht.cxx73
-rw-r--r--private/crt32/iostream/makefile7
-rw-r--r--private/crt32/iostream/mtlock.c943
-rw-r--r--private/crt32/iostream/ofstream.cxx239
-rw-r--r--private/crt32/iostream/ostrchar.cxx39
-rw-r--r--private/crt32/iostream/ostrdbl.cxx65
-rw-r--r--private/crt32/iostream/ostream.cxx229
-rw-r--r--private/crt32/iostream/ostream1.cxx70
-rw-r--r--private/crt32/iostream/ostrint.cxx55
-rw-r--r--private/crt32/iostream/ostrldbl.cxx61
-rw-r--r--private/crt32/iostream/ostrlong.cxx55
-rw-r--r--private/crt32/iostream/ostrptr.cxx41
-rw-r--r--private/crt32/iostream/ostrput.cxx42
-rw-r--r--private/crt32/iostream/ostrshrt.cxx56
-rw-r--r--private/crt32/iostream/ostruint.cxx55
-rw-r--r--private/crt32/iostream/ostrulng.cxx55
-rw-r--r--private/crt32/iostream/ostrusht.cxx56
-rw-r--r--private/crt32/iostream/sources83
-rw-r--r--private/crt32/iostream/stdiostr.cxx266
-rw-r--r--private/crt32/iostream/streamb.cxx514
-rw-r--r--private/crt32/iostream/streamb1.cxx165
-rw-r--r--private/crt32/iostream/strmbdbp.cxx48
-rw-r--r--private/crt32/iostream/strstrea.cxx440
-rw-r--r--private/crt32/linkopts/binmode.c28
-rw-r--r--private/crt32/linkopts/commode.c26
-rw-r--r--private/crt32/linkopts/makefile6
-rw-r--r--private/crt32/linkopts/setargv.c43
-rw-r--r--private/crt32/linkopts/sources38
-rw-r--r--private/crt32/lowio/cgets.c129
-rw-r--r--private/crt32/lowio/chsize.c231
-rw-r--r--private/crt32/lowio/close.c135
-rw-r--r--private/crt32/lowio/commit.c115
-rw-r--r--private/crt32/lowio/cputs.c100
-rw-r--r--private/crt32/lowio/creat.c52
-rw-r--r--private/crt32/lowio/dup.c156
-rw-r--r--private/crt32/lowio/dup2.c200
-rw-r--r--private/crt32/lowio/eof.c90
-rw-r--r--private/crt32/lowio/flength.c84
-rw-r--r--private/crt32/lowio/fstat.c352
-rw-r--r--private/crt32/lowio/getch.c672
-rw-r--r--private/crt32/lowio/i386/_initcon.asm17
-rw-r--r--private/crt32/lowio/i386/cinitcon.asm99
-rw-r--r--private/crt32/lowio/initcon.c113
-rw-r--r--private/crt32/lowio/ioinit.c242
-rw-r--r--private/crt32/lowio/isatty.c62
-rw-r--r--private/crt32/lowio/locking.c187
-rw-r--r--private/crt32/lowio/lseek.c187
-rw-r--r--private/crt32/lowio/makefile6
-rw-r--r--private/crt32/lowio/mktemp.c115
-rw-r--r--private/crt32/lowio/open.c590
-rw-r--r--private/crt32/lowio/osfinfo.c319
-rw-r--r--private/crt32/lowio/pipe.c180
-rw-r--r--private/crt32/lowio/ppc/cinitcon.s53
-rw-r--r--private/crt32/lowio/putch.c129
-rw-r--r--private/crt32/lowio/read.c349
-rw-r--r--private/crt32/lowio/setmode.c155
-rw-r--r--private/crt32/lowio/sources62
-rw-r--r--private/crt32/lowio/tell.c46
-rw-r--r--private/crt32/lowio/txtmode.c19
-rw-r--r--private/crt32/lowio/write.c324
-rw-r--r--private/crt32/makefile597
-rw-r--r--private/crt32/mbstring/i386/ismbbyte.sav205
-rw-r--r--private/crt32/mbstring/i386/mbcsinit.os255
-rw-r--r--private/crt32/mbstring/i386/mbscat.asm18
-rw-r--r--private/crt32/mbstring/i386/mbsdup.asm16
-rw-r--r--private/crt32/mbstring/ismbalph.c67
-rw-r--r--private/crt32/mbstring/ismbbyte.c148
-rw-r--r--private/crt32/mbstring/ismbdgt.c60
-rw-r--r--private/crt32/mbstring/ismbknj.c93
-rw-r--r--private/crt32/mbstring/ismblgl.c42
-rw-r--r--private/crt32/mbstring/ismblwr.c63
-rw-r--r--private/crt32/mbstring/ismbprn.c60
-rw-r--r--private/crt32/mbstring/ismbsle.c58
-rw-r--r--private/crt32/mbstring/ismbspc.c61
-rw-r--r--private/crt32/mbstring/ismbstr.c58
-rw-r--r--private/crt32/mbstring/ismbupr.c63
-rw-r--r--private/crt32/mbstring/makefile6
-rw-r--r--private/crt32/mbstring/makefile.knj508
-rw-r--r--private/crt32/mbstring/mbascii0.c33
-rw-r--r--private/crt32/mbstring/mbascii1.opt19
-rw-r--r--private/crt32/mbstring/mbbtype.c70
-rw-r--r--private/crt32/mbstring/mbccpy.c47
-rw-r--r--private/crt32/mbstring/mbclen.c42
-rw-r--r--private/crt32/mbstring/mbclevel.c92
-rw-r--r--private/crt32/mbstring/mbctype.c318
-rw-r--r--private/crt32/mbstring/mbsbtype.c64
-rw-r--r--private/crt32/mbstring/mbscat.c21
-rw-r--r--private/crt32/mbstring/mbschr.c67
-rw-r--r--private/crt32/mbstring/mbscmp.c61
-rw-r--r--private/crt32/mbstring/mbscspn.c105
-rw-r--r--private/crt32/mbstring/mbsdec.c84
-rw-r--r--private/crt32/mbstring/mbsdup.c18
-rw-r--r--private/crt32/mbstring/mbsicmp.c90
-rw-r--r--private/crt32/mbstring/mbsinc.c48
-rw-r--r--private/crt32/mbstring/mbslen.c51
-rw-r--r--private/crt32/mbstring/mbslwr.c76
-rw-r--r--private/crt32/mbstring/mbsnbcat.c99
-rw-r--r--private/crt32/mbstring/mbsnbcmp.c75
-rw-r--r--private/crt32/mbstring/mbsnbcnt.c62
-rw-r--r--private/crt32/mbstring/mbsnbcpy.c79
-rw-r--r--private/crt32/mbstring/mbsnbicm.c101
-rw-r--r--private/crt32/mbstring/mbsnbset.c102
-rw-r--r--private/crt32/mbstring/mbsncat.c95
-rw-r--r--private/crt32/mbstring/mbsnccnt.c59
-rw-r--r--private/crt32/mbstring/mbsncmp.c69
-rw-r--r--private/crt32/mbstring/mbsncpy.c74
-rw-r--r--private/crt32/mbstring/mbsnextc.c50
-rw-r--r--private/crt32/mbstring/mbsnicmp.c97
-rw-r--r--private/crt32/mbstring/mbsninc.c50
-rw-r--r--private/crt32/mbstring/mbsnset.c110
-rw-r--r--private/crt32/mbstring/mbspbrk.c18
-rw-r--r--private/crt32/mbstring/mbsrchr.c67
-rw-r--r--private/crt32/mbstring/mbsrev.c72
-rw-r--r--private/crt32/mbstring/mbsset.c76
-rw-r--r--private/crt32/mbstring/mbsspn.c101
-rw-r--r--private/crt32/mbstring/mbsspnp.c18
-rw-r--r--private/crt32/mbstring/mbsstr.c80
-rw-r--r--private/crt32/mbstring/mbstok.c174
-rw-r--r--private/crt32/mbstring/mbsupr.c72
-rw-r--r--private/crt32/mbstring/mbtohira.c53
-rw-r--r--private/crt32/mbstring/mbtokata.c51
-rw-r--r--private/crt32/mbstring/mbtolwr.c72
-rw-r--r--private/crt32/mbstring/mbtoupr.c72
-rw-r--r--private/crt32/mbstring/sources105
-rw-r--r--private/crt32/mbstring/strdec.c46
-rw-r--r--private/crt32/mbstring/strinc.c44
-rw-r--r--private/crt32/mbstring/strncnt.c52
-rw-r--r--private/crt32/mbstring/strnextc.c44
-rw-r--r--private/crt32/mbstring/strninc.c47
-rw-r--r--private/crt32/mbstring/strspnp.c65
-rw-r--r--private/crt32/mbstring/tojisjms.c116
-rw-r--r--private/crt32/mbstring/tombbmbc.c312
-rw-r--r--private/crt32/misc/_strerr.c143
-rw-r--r--private/crt32/misc/abort.c96
-rw-r--r--private/crt32/misc/abs.c51
-rw-r--r--private/crt32/misc/alpha/chandler.c296
-rw-r--r--private/crt32/misc/alpha/divdat.s597
-rw-r--r--private/crt32/misc/alpha/divide.s1319
-rw-r--r--private/crt32/misc/alpha/divide2.s1002
-rw-r--r--private/crt32/misc/alpha/extv.s82
-rw-r--r--private/crt32/misc/alpha/extvvol.s98
-rw-r--r--private/crt32/misc/alpha/extzv.s83
-rw-r--r--private/crt32/misc/alpha/extzvvol.s101
-rw-r--r--private/crt32/misc/alpha/fastdiv.s662
-rw-r--r--private/crt32/misc/alpha/ghandler.c435
-rw-r--r--private/crt32/misc/alpha/insv.s158
-rw-r--r--private/crt32/misc/alpha/insvvol.s137
-rw-r--r--private/crt32/misc/alpha/jmpuwind.s167
-rw-r--r--private/crt32/misc/alpha/longjmp.s192
-rw-r--r--private/crt32/misc/alpha/ots_as.hs38
-rw-r--r--private/crt32/misc/alpha/ots_defs.hs3
-rw-r--r--private/crt32/misc/alpha/otsdiv.s1178
-rw-r--r--private/crt32/misc/alpha/otsjmp.s117
-rw-r--r--private/crt32/misc/alpha/otsjmpex.s84
-rw-r--r--private/crt32/misc/alpha/otsnote.txt115
-rw-r--r--private/crt32/misc/alpha/otsuwind.s80
-rw-r--r--private/crt32/misc/alpha/scmpeql.s295
-rw-r--r--private/crt32/misc/alpha/scmpeqlp.s443
-rw-r--r--private/crt32/misc/alpha/scmpleq.s338
-rw-r--r--private/crt32/misc/alpha/scmpleqp.s478
-rw-r--r--private/crt32/misc/alpha/scmplss.s339
-rw-r--r--private/crt32/misc/alpha/scmplssp.s478
-rw-r--r--private/crt32/misc/alpha/setjmp.s111
-rw-r--r--private/crt32/misc/alpha/setjmpex.s147
-rw-r--r--private/crt32/misc/alpha/sfill.s161
-rw-r--r--private/crt32/misc/alpha/sloc.s702
-rw-r--r--private/crt32/misc/alpha/smove.s652
-rw-r--r--private/crt32/misc/alpha/smovem.s667
-rw-r--r--private/crt32/misc/alpha/strans.s122
-rw-r--r--private/crt32/misc/alpha/strcmp_.s357
-rw-r--r--private/crt32/misc/alpha/strcpy_.s257
-rw-r--r--private/crt32/misc/alpha/strlen_.s95
-rw-r--r--private/crt32/misc/alpha/szero.s137
-rw-r--r--private/crt32/misc/assert.c66
-rw-r--r--private/crt32/misc/bsearch.c99
-rw-r--r--private/crt32/misc/cmiscdat.c68
-rw-r--r--private/crt32/misc/ctype.c161
-rw-r--r--private/crt32/misc/div.c59
-rw-r--r--private/crt32/misc/getenv.c167
-rw-r--r--private/crt32/misc/getpath.c174
-rw-r--r--private/crt32/misc/getqloc.c736
-rw-r--r--private/crt32/misc/i386/_initone.asm17
-rw-r--r--private/crt32/misc/i386/cinitone.asm78
-rw-r--r--private/crt32/misc/i386/exsup.asm299
-rw-r--r--private/crt32/misc/i386/exsup2.asm271
-rw-r--r--private/crt32/misc/i386/exsup3.asm290
-rw-r--r--private/crt32/misc/i386/longjmp.asm150
-rw-r--r--private/crt32/misc/i386/sehsupp.c59
-rw-r--r--private/crt32/misc/i386/setjmp.asm151
-rw-r--r--private/crt32/misc/i386/setjmp3.asm148
-rw-r--r--private/crt32/misc/i386/setjmpex.asm55
-rw-r--r--private/crt32/misc/initcoll.c51
-rw-r--r--private/crt32/misc/initctyp.c212
-rw-r--r--private/crt32/misc/inithelp.c143
-rw-r--r--private/crt32/misc/initmon.c191
-rw-r--r--private/crt32/misc/initnum.c129
-rw-r--r--private/crt32/misc/inittime.c301
-rw-r--r--private/crt32/misc/labs.c52
-rw-r--r--private/crt32/misc/lconv.c86
-rw-r--r--private/crt32/misc/ldiv.c59
-rw-r--r--private/crt32/misc/lfind.c79
-rw-r--r--private/crt32/misc/lsearch.c87
-rw-r--r--private/crt32/misc/makefile6
-rw-r--r--private/crt32/misc/makepath.c128
-rw-r--r--private/crt32/misc/mbval.c22
-rw-r--r--private/crt32/misc/mips/chandler.c219
-rw-r--r--private/crt32/misc/mips/jmpuwind.s138
-rw-r--r--private/crt32/misc/mips/longjmp.s128
-rw-r--r--private/crt32/misc/mips/setjmp.s101
-rw-r--r--private/crt32/misc/mips/setjmpex.s156
-rw-r--r--private/crt32/misc/mtest.c530
-rw-r--r--private/crt32/misc/nlsdata1.c38
-rw-r--r--private/crt32/misc/nlsdata2.c34
-rw-r--r--private/crt32/misc/nlsdata3.c34
-rw-r--r--private/crt32/misc/onexit.c286
-rw-r--r--private/crt32/misc/perror.c78
-rw-r--r--private/crt32/misc/ppc/chandler.c222
-rw-r--r--private/crt32/misc/ppc/cinitone.s41
-rw-r--r--private/crt32/misc/ppc/jmpuwind.s162
-rw-r--r--private/crt32/misc/ppc/longjmp.s143
-rw-r--r--private/crt32/misc/ppc/miscasm.s273
-rw-r--r--private/crt32/misc/ppc/setjmp.s138
-rw-r--r--private/crt32/misc/ppc/setjmpex.s194
-rw-r--r--private/crt32/misc/ppc/sources6
-rw-r--r--private/crt32/misc/purevirt.c42
-rw-r--r--private/crt32/misc/putenv.c453
-rw-r--r--private/crt32/misc/qsort.c329
-rw-r--r--private/crt32/misc/rand.c133
-rw-r--r--private/crt32/misc/rotl.c90
-rw-r--r--private/crt32/misc/rotr.c90
-rw-r--r--private/crt32/misc/searchen.c114
-rw-r--r--private/crt32/misc/setlocal.c620
-rw-r--r--private/crt32/misc/setmbval.c35
-rw-r--r--private/crt32/misc/sources129
-rw-r--r--private/crt32/misc/splitpat.c201
-rw-r--r--private/crt32/misc/strerror.c142
-rw-r--r--private/crt32/misc/syserr.c85
-rw-r--r--private/crt32/misc/umask.c55
-rw-r--r--private/crt32/misc/winsig.c709
-rw-r--r--private/crt32/misc/winxfltr.c618
-rw-r--r--private/crt32/misc/wrt2err.c84
-rw-r--r--private/crt32/small/crt0dat.c1
-rw-r--r--private/crt32/small/ctype.c1
-rw-r--r--private/crt32/small/makefile6
-rw-r--r--private/crt32/small/makefile.inc19
-rw-r--r--private/crt32/small/mips/huge.s2
-rw-r--r--private/crt32/small/nlsdata1.c1
-rw-r--r--private/crt32/small/nlsdata2.c1
-rw-r--r--private/crt32/small/nlsdata3.c1
-rw-r--r--private/crt32/small/sources54
-rw-r--r--private/crt32/small/syserr.c1
-rw-r--r--private/crt32/small/timeset.c1
-rw-r--r--private/crt32/small/tlssup.c1
-rw-r--r--private/crt32/startup/_setargv.c18
-rw-r--r--private/crt32/startup/alpha/chkstk.s131
-rw-r--r--private/crt32/startup/crt0.c594
-rw-r--r--private/crt32/startup/crt0dat.c794
-rw-r--r--private/crt32/startup/crt0fp.c57
-rw-r--r--private/crt32/startup/crt0init.c69
-rw-r--r--private/crt32/startup/crt0msg.c231
-rw-r--r--private/crt32/startup/dllcrt0.c306
-rw-r--r--private/crt32/startup/dllmain.c42
-rw-r--r--private/crt32/startup/i386/atlssup.asm15
-rw-r--r--private/crt32/startup/i386/chkstk.asm127
-rw-r--r--private/crt32/startup/makefile6
-rw-r--r--private/crt32/startup/makefile.inc3
-rw-r--r--private/crt32/startup/mips/chkstk.s104
-rw-r--r--private/crt32/startup/mlock.c382
-rw-r--r--private/crt32/startup/ppc/chkstk.s190
-rw-r--r--private/crt32/startup/ppc/sources3
-rw-r--r--private/crt32/startup/sources65
-rw-r--r--private/crt32/startup/stdargv.c501
-rw-r--r--private/crt32/startup/stdenvp.c192
-rw-r--r--private/crt32/startup/thread.c254
-rw-r--r--private/crt32/startup/tidprint.c286
-rw-r--r--private/crt32/startup/tidtable.c324
-rw-r--r--private/crt32/startup/tlssup.c52
-rw-r--r--private/crt32/startup/wild.c341
-rw-r--r--private/crt32/startup/wincrt0.c6
-rw-r--r--private/crt32/stdio/_filbuf.c195
-rw-r--r--private/crt32/stdio/_file.c86
-rw-r--r--private/crt32/stdio/_filwbuf.c25
-rw-r--r--private/crt32/stdio/_flsbuf.c275
-rw-r--r--private/crt32/stdio/_flswbuf.c25
-rw-r--r--private/crt32/stdio/_freebuf.c72
-rw-r--r--private/crt32/stdio/_getbuf.c102
-rw-r--r--private/crt32/stdio/_open.c272
-rw-r--r--private/crt32/stdio/_sftbuf.c223
-rw-r--r--private/crt32/stdio/clearerr.c77
-rw-r--r--private/crt32/stdio/closeall.c71
-rw-r--r--private/crt32/stdio/cprintf.c15
-rw-r--r--private/crt32/stdio/cscanf.c15
-rw-r--r--private/crt32/stdio/fclose.c221
-rw-r--r--private/crt32/stdio/fdopen.c191
-rw-r--r--private/crt32/stdio/feoferr.c78
-rw-r--r--private/crt32/stdio/fflush.c424
-rw-r--r--private/crt32/stdio/fgetc.c79
-rw-r--r--private/crt32/stdio/fgetchar.c62
-rw-r--r--private/crt32/stdio/fgetpos.c55
-rw-r--r--private/crt32/stdio/fgets.c111
-rw-r--r--private/crt32/stdio/fgetwc.c154
-rw-r--r--private/crt32/stdio/fgetwchr.c52
-rw-r--r--private/crt32/stdio/fileno.c50
-rw-r--r--private/crt32/stdio/fopen.c125
-rw-r--r--private/crt32/stdio/fprintf.c93
-rw-r--r--private/crt32/stdio/fputc.c89
-rw-r--r--private/crt32/stdio/fputchar.c63
-rw-r--r--private/crt32/stdio/fputs.c81
-rw-r--r--private/crt32/stdio/fputwc.c159
-rw-r--r--private/crt32/stdio/fputwchr.c53
-rw-r--r--private/crt32/stdio/fread.c197
-rw-r--r--private/crt32/stdio/freopen.c105
-rw-r--r--private/crt32/stdio/fscanf.c83
-rw-r--r--private/crt32/stdio/fseek.c258
-rw-r--r--private/crt32/stdio/fsetpos.c51
-rw-r--r--private/crt32/stdio/ftell.c257
-rw-r--r--private/crt32/stdio/fwprintf.c79
-rw-r--r--private/crt32/stdio/fwrite.c202
-rw-r--r--private/crt32/stdio/fwscanf.c72
-rw-r--r--private/crt32/stdio/gets.c89
-rw-r--r--private/crt32/stdio/getw.c86
-rw-r--r--private/crt32/stdio/i386/_initstd.asm17
-rw-r--r--private/crt32/stdio/i386/_inittmp.asm17
-rw-r--r--private/crt32/stdio/i386/cinitstd.asm88
-rw-r--r--private/crt32/stdio/i386/cinittmp.asm92
-rw-r--r--private/crt32/stdio/input.c1130
-rw-r--r--private/crt32/stdio/makefile6
-rw-r--r--private/crt32/stdio/makefile.inc17
-rw-r--r--private/crt32/stdio/maketab.c101
-rw-r--r--private/crt32/stdio/maketabc.c128
-rw-r--r--private/crt32/stdio/ncommode.c18
-rw-r--r--private/crt32/stdio/output.c1393
-rw-r--r--private/crt32/stdio/popen.c562
-rw-r--r--private/crt32/stdio/ppc/cinitstd.s47
-rw-r--r--private/crt32/stdio/ppc/cinittmp.s52
-rw-r--r--private/crt32/stdio/printf.c92
-rw-r--r--private/crt32/stdio/puts.c91
-rw-r--r--private/crt32/stdio/putw.c87
-rw-r--r--private/crt32/stdio/rewind.c117
-rw-r--r--private/crt32/stdio/rmtmp.c116
-rw-r--r--private/crt32/stdio/scanf.c86
-rw-r--r--private/crt32/stdio/setbuf.c61
-rw-r--r--private/crt32/stdio/setvbuf.c180
-rw-r--r--private/crt32/stdio/snprintf.c17
-rw-r--r--private/crt32/stdio/snwprint.c17
-rw-r--r--private/crt32/stdio/sources115
-rw-r--r--private/crt32/stdio/sprintf.c130
-rw-r--r--private/crt32/stdio/sscanf.c95
-rw-r--r--private/crt32/stdio/stream.c95
-rw-r--r--private/crt32/stdio/swprintf.c115
-rw-r--r--private/crt32/stdio/swscanf.c81
-rw-r--r--private/crt32/stdio/tempnam.c262
-rw-r--r--private/crt32/stdio/test_out.c224
-rw-r--r--private/crt32/stdio/tmpfile.c418
-rw-r--r--private/crt32/stdio/ungetc.c174
-rw-r--r--private/crt32/stdio/ungetwc.c206
-rw-r--r--private/crt32/stdio/vfprintf.c90
-rw-r--r--private/crt32/stdio/vfwprint.c76
-rw-r--r--private/crt32/stdio/vprintf.c81
-rw-r--r--private/crt32/stdio/vsnprint.c17
-rw-r--r--private/crt32/stdio/vsnwprnt.c17
-rw-r--r--private/crt32/stdio/vsprintf.c126
-rw-r--r--private/crt32/stdio/vswprint.c111
-rw-r--r--private/crt32/stdio/vwprintf.c68
-rw-r--r--private/crt32/stdio/winput.c29
-rw-r--r--private/crt32/stdio/woutput.c31
-rw-r--r--private/crt32/stdio/wprintf.c79
-rw-r--r--private/crt32/stdio/wscanf.c74
-rw-r--r--private/crt32/string/alpha/strcat.c63
-rw-r--r--private/crt32/string/alpha/strcmps.s357
-rw-r--r--private/crt32/string/alpha/strcpys.s257
-rw-r--r--private/crt32/string/alpha/strlens.s95
-rw-r--r--private/crt32/string/i386/memccpy.asm103
-rw-r--r--private/crt32/string/i386/memchr.asm96
-rw-r--r--private/crt32/string/i386/memcmp.asm101
-rw-r--r--private/crt32/string/i386/memcpy.asm354
-rw-r--r--private/crt32/string/i386/memicmp.asm132
-rw-r--r--private/crt32/string/i386/memmove.asm19
-rw-r--r--private/crt32/string/i386/memset.asm127
-rw-r--r--private/crt32/string/i386/strcat.asm155
-rw-r--r--private/crt32/string/i386/strchr.asm94
-rw-r--r--private/crt32/string/i386/strcmp.asm104
-rw-r--r--private/crt32/string/i386/strcspn.asm19
-rw-r--r--private/crt32/string/i386/strdup.asm126
-rw-r--r--private/crt32/string/i386/stricmp.asm127
-rw-r--r--private/crt32/string/i386/strlen.asm84
-rw-r--r--private/crt32/string/i386/strlwr.asm104
-rw-r--r--private/crt32/string/i386/strncat.asm117
-rw-r--r--private/crt32/string/i386/strncmp.asm120
-rw-r--r--private/crt32/string/i386/strncpy.asm108
-rw-r--r--private/crt32/string/i386/strnicmp.asm153
-rw-r--r--private/crt32/string/i386/strnset.asm104
-rw-r--r--private/crt32/string/i386/strpbrk.asm19
-rw-r--r--private/crt32/string/i386/strrchr.asm105
-rw-r--r--private/crt32/string/i386/strrev.asm121
-rw-r--r--private/crt32/string/i386/strset.asm93
-rw-r--r--private/crt32/string/i386/strspn.asm277
-rw-r--r--private/crt32/string/i386/strstr.asm135
-rw-r--r--private/crt32/string/i386/strupr.asm104
-rw-r--r--private/crt32/string/makefile6
-rw-r--r--private/crt32/string/makefile.inc9
-rw-r--r--private/crt32/string/memccpy.c59
-rw-r--r--private/crt32/string/memchr.c57
-rw-r--r--private/crt32/string/memcmp.c65
-rw-r--r--private/crt32/string/memcpy.c80
-rw-r--r--private/crt32/string/memicmp.c77
-rw-r--r--private/crt32/string/memmove.c93
-rw-r--r--private/crt32/string/memset.c70
-rw-r--r--private/crt32/string/mips/memcmpm.s125
-rw-r--r--private/crt32/string/mips/memcmpt.c334
-rw-r--r--private/crt32/string/mips/memcpym.s298
-rw-r--r--private/crt32/string/mips/memorym.s1218
-rw-r--r--private/crt32/string/mips/memsetm.s105
-rw-r--r--private/crt32/string/mips/memsett.c20
-rw-r--r--private/crt32/string/mips/strcatm.s98
-rw-r--r--private/crt32/string/mips/strchrm.s26
-rw-r--r--private/crt32/string/mips/strchrt.c20
-rw-r--r--private/crt32/string/mips/strcmpm.s50
-rw-r--r--private/crt32/string/mips/strcpym.s148
-rw-r--r--private/crt32/string/mips/strcpyt.c23
-rw-r--r--private/crt32/string/mips/strlenm.s19
-rw-r--r--private/crt32/string/mips/strrchrm.s24
-rw-r--r--private/crt32/string/mips/strrchrt.c20
-rw-r--r--private/crt32/string/mips/wcscmpm.s67
-rw-r--r--private/crt32/string/mips/wcscmpt.c62
-rw-r--r--private/crt32/string/mips/wcscpym.s139
-rw-r--r--private/crt32/string/mips/wcslenm.s45
-rw-r--r--private/crt32/string/ppc/memccpyp.s78
-rw-r--r--private/crt32/string/ppc/memchrp.s74
-rw-r--r--private/crt32/string/ppc/memcmpp.s71
-rw-r--r--private/crt32/string/ppc/strcatp.s137
-rw-r--r--private/crt32/string/ppc/strchrp.s70
-rw-r--r--private/crt32/string/ppc/strcmpp.s74
-rw-r--r--private/crt32/string/ppc/stricmpp.s89
-rw-r--r--private/crt32/string/ppc/strlenp.s164
-rw-r--r--private/crt32/string/ppc/strrchrp.s87
-rw-r--r--private/crt32/string/sources175
-rw-r--r--private/crt32/string/strcat.c90
-rw-r--r--private/crt32/string/strchr.c52
-rw-r--r--private/crt32/string/strcmp.c68
-rw-r--r--private/crt32/string/strcoll.c103
-rw-r--r--private/crt32/string/strcspn.c2
-rw-r--r--private/crt32/string/strdup.c60
-rw-r--r--private/crt32/string/stricmp.c80
-rw-r--r--private/crt32/string/stricoll.c95
-rw-r--r--private/crt32/string/strlen.c54
-rw-r--r--private/crt32/string/strlwr.c137
-rw-r--r--private/crt32/string/strncat.c63
-rw-r--r--private/crt32/string/strncmp.c61
-rw-r--r--private/crt32/string/strncpy.c59
-rw-r--r--private/crt32/string/strnicmp.c76
-rw-r--r--private/crt32/string/strnset.c54
-rw-r--r--private/crt32/string/strpbrk.c2
-rw-r--r--private/crt32/string/strrchr.c59
-rw-r--r--private/crt32/string/strrev.c58
-rw-r--r--private/crt32/string/strset.c58
-rw-r--r--private/crt32/string/strspn.c179
-rw-r--r--private/crt32/string/strstr.c68
-rw-r--r--private/crt32/string/strtok.c125
-rw-r--r--private/crt32/string/strupr.c138
-rw-r--r--private/crt32/string/strxfrm.c149
-rw-r--r--private/crt32/string/wcscat.c87
-rw-r--r--private/crt32/string/wcschr.c48
-rw-r--r--private/crt32/string/wcscmp.c59
-rw-r--r--private/crt32/string/wcscoll.c70
-rw-r--r--private/crt32/string/wcscspn.c61
-rw-r--r--private/crt32/string/wcsdup.c57
-rw-r--r--private/crt32/string/wcsicmp.c90
-rw-r--r--private/crt32/string/wcsicoll.c73
-rw-r--r--private/crt32/string/wcslen.c45
-rw-r--r--private/crt32/string/wcslwr.c100
-rw-r--r--private/crt32/string/wcsncat.c61
-rw-r--r--private/crt32/string/wcsncmp.c57
-rw-r--r--private/crt32/string/wcsncpy.c57
-rw-r--r--private/crt32/string/wcsnicmp.c91
-rw-r--r--private/crt32/string/wcsnset.c51
-rw-r--r--private/crt32/string/wcspbrk.c56
-rw-r--r--private/crt32/string/wcsrchr.c56
-rw-r--r--private/crt32/string/wcsrev.c56
-rw-r--r--private/crt32/string/wcsset.c51
-rw-r--r--private/crt32/string/wcsspn.c67
-rw-r--r--private/crt32/string/wcsstr.c62
-rw-r--r--private/crt32/string/wcstok.c174
-rw-r--r--private/crt32/string/wcsupr.c104
-rw-r--r--private/crt32/string/wcsxfrm.c126
-rw-r--r--private/crt32/time/asctime.c194
-rw-r--r--private/crt32/time/clock.c169
-rw-r--r--private/crt32/time/ctime.c56
-rw-r--r--private/crt32/time/days.c26
-rw-r--r--private/crt32/time/difftime.c53
-rw-r--r--private/crt32/time/dtoxtime.c113
-rw-r--r--private/crt32/time/ftime.c107
-rw-r--r--private/crt32/time/gmtime.c185
-rw-r--r--private/crt32/time/i386/_initclk.asm17
-rw-r--r--private/crt32/time/i386/cinitclk.asm93
-rw-r--r--private/crt32/time/localtim.c252
-rw-r--r--private/crt32/time/makefile6
-rw-r--r--private/crt32/time/mktime.c315
-rw-r--r--private/crt32/time/ppc/cinitclk.s49
-rw-r--r--private/crt32/time/sources54
-rw-r--r--private/crt32/time/strdate.c99
-rw-r--r--private/crt32/time/strftime.c891
-rw-r--r--private/crt32/time/strtime.c98
-rw-r--r--private/crt32/time/systime.c104
-rw-r--r--private/crt32/time/time.c78
-rw-r--r--private/crt32/time/timeset.c92
-rw-r--r--private/crt32/time/tzset.c927
-rw-r--r--private/crt32/time/utime.c202
-rw-r--r--private/crt32/time/wcsftime.c67
-rw-r--r--private/crt32/tools/i386mips.c368
-rw-r--r--private/crt32/tools/win32/relinc.cmd172
-rw-r--r--private/crt32/tools/win32/relinc.if74
-rw-r--r--private/crt32/tools/win32/relinc.sed8
-rw-r--r--private/crt32/winheap/calloc.c81
-rw-r--r--private/crt32/winheap/delete.cxx28
-rw-r--r--private/crt32/winheap/expand.c92
-rw-r--r--private/crt32/winheap/handler.cxx53
-rw-r--r--private/crt32/winheap/heapchk.c131
-rw-r--r--private/crt32/winheap/heapinit.c52
-rw-r--r--private/crt32/winheap/heapmin.c73
-rw-r--r--private/crt32/winheap/heapwalk.c101
-rw-r--r--private/crt32/winheap/hpabort.c47
-rw-r--r--private/crt32/winheap/makefile7
-rw-r--r--private/crt32/winheap/malloc.c104
-rw-r--r--private/crt32/winheap/msize.c49
-rw-r--r--private/crt32/winheap/new.cxx28
-rw-r--r--private/crt32/winheap/realloc.c85
-rw-r--r--private/crt32/winheap/sources51
-rw-r--r--private/crt32/wstring/makefile6
-rw-r--r--private/crt32/wstring/sources53
765 files changed, 113842 insertions, 0 deletions
diff --git a/private/crt32/buildcrt.cmd b/private/crt32/buildcrt.cmd
new file mode 100644
index 000000000..4e2142739
--- /dev/null
+++ b/private/crt32/buildcrt.cmd
@@ -0,0 +1,52 @@
+@setlocal
+@set CRTLIBDEBUG=
+@set CRTLIBTYPE=
+@set 386_USE_LIBCMT=
+
+@set _helpdir=
+@if "%MIPS%" == "1" set _helpdir=helper
+@if "%PPC%" == "1" set _helpdir=helper
+@if "%_targetcpu%" == "mips" set _helpdir=helper
+@if "%_targetcpu%" == "ppc" set _helpdir=helper
+
+:bldtype
+@if "%1" == "DLL" (set CRTLIBTYPE=DLL) && goto blddll
+@if "%1" == "Dll" (set CRTLIBTYPE=DLL) && goto blddll
+@if "%1" == "dll" (set CRTLIBTYPE=DLL) && goto blddll
+@if "%1" == "posix" (set CRTLIBTYPE=POSIX) && goto bldpsx
+@if "%1" == "POSIX" (set CRTLIBTYPE=POSIX) && goto bldpsx
+@if "%1" == "Posix" (set CRTLIBTYPE=POSIX) && goto bldpsx
+@if "%1" == "st" (set CRTLIBTYPE=ST) && goto bldst
+@if "%1" == "ST" (set CRTLIBTYPE=ST) && goto bldst
+@if "%1" == "St" (set CRTLIBTYPE=ST) && goto bldst
+@if "%1" == "nt" (set CRTLIBTYPE=NT) && goto bldnt
+@if "%1" == "NT" (set CRTLIBTYPE=NT) && goto bldnt
+@if "%1" == "Nt" (set CRTLIBTYPE=NT) && goto bldnt
+@if "%1" == "mt" set CRTLIBTYPE=MT
+@if "%1" == "MT" set CRTLIBTYPE=MT
+@if "%1" == "Mt" set CRTLIBTYPE=MT
+@if "%CRTLIBTYPE%" == "" goto bogus
+
+build %2 %3 %4 %5 startup time winheap direct dos exec iostream lowio mbstring %_helpdir%
+@goto done
+
+:bldst
+build %2 %3 %4 %5 linkopts startup time winheap direct dos exec iostream lowio small mbstring %_helpdir% %2 %3 %4 %5
+@goto done
+
+:blddll
+build %2 %3 %4 %5 startup time winheap dllstuff direct dos exec iostream lowio mbstring %_helpdir% %2 %3 %4
+@goto done
+
+:bldpsx
+build %2 %3 %4 %5 startup time winheap mbstring %_helpdir% %2 %3 %4 %5 %6 %7 %8 %9
+@goto done
+
+:bldnt
+build %2 %3 %4 %5 hack %_helpdir% %2 %3 %4 %5 %6 %7 %8 %9
+@goto done
+
+:bogus
+@echo Usage: BUILDCRT (NT, ST, MT, DLL, or POSIX) [BuildOptions]
+:done
+@endlocal
diff --git a/private/crt32/convert/_ctype.c b/private/crt32/convert/_ctype.c
new file mode 100644
index 000000000..7e65d82b5
--- /dev/null
+++ b/private/crt32/convert/_ctype.c
@@ -0,0 +1,156 @@
+/***
+*_ctype.c - function versions of ctype macros
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This files provides function versions of the character
+* classification and conversion macros in ctype.h.
+*
+*Revision History:
+* 06-05-89 PHG Module created
+* 03-05-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 09-27-90 GJF New-style function declarators.
+* 01-16-91 GJF ANSI naming.
+* 02-03-92 GJF Got rid of #undef/#include-s, the MIPS compiler didn't
+* like 'em.
+* 08-07-92 GJF Fixed function calling type macros.
+*
+*******************************************************************************/
+
+/***
+*ctype - Function versions of ctype macros
+*
+*Purpose:
+* Function versions of the macros in ctype.h. In order to define
+* these, we use a trick -- we undefine the macro so we can use the
+* name in the function declaration, then re-include the file so
+* we can use the macro in the definition part.
+*
+* Functions defined:
+* isalpha isupper islower
+* isdigit isxdigit isspace
+* ispunct isalnum isprint
+* isgraph isctrl __isascii
+* __toascii __iscsym __iscsymf
+*
+*Entry:
+* int c = character to be tested
+*Exit:
+* returns non-zero = character is of the requested type
+* 0 = character is NOT of the requested type
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#define __STDC__ 1
+#include <ctype.h>
+
+int (_CRTAPI1 isalpha) (
+ int c
+ )
+{
+ return isalpha(c);
+}
+
+int (_CRTAPI1 isupper) (
+ int c
+ )
+{
+ return isupper(c);
+}
+
+int (_CRTAPI1 islower) (
+ int c
+ )
+{
+ return islower(c);
+}
+
+int (_CRTAPI1 isdigit) (
+ int c
+ )
+{
+ return isdigit(c);
+}
+
+int (_CRTAPI1 isxdigit) (
+ int c
+ )
+{
+ return isxdigit(c);
+}
+
+int (_CRTAPI1 isspace) (
+ int c
+ )
+{
+ return isspace(c);
+}
+
+int (_CRTAPI1 ispunct) (
+ int c
+ )
+{
+ return ispunct(c);
+}
+
+int (_CRTAPI1 isalnum) (
+ int c
+ )
+{
+ return isalnum(c);
+}
+
+int (_CRTAPI1 isprint) (
+ int c
+ )
+{
+ return isprint(c);
+}
+
+int (_CRTAPI1 isgraph) (
+ int c
+ )
+{
+ return isgraph(c);
+}
+
+int (_CRTAPI1 iscntrl) (
+ int c
+ )
+{
+ return iscntrl(c);
+}
+
+int (_CRTAPI1 __isascii) (
+ int c
+ )
+{
+ return __isascii(c);
+}
+
+int (_CRTAPI1 __toascii) (
+ int c
+ )
+{
+ return __toascii(c);
+}
+
+int (_CRTAPI1 __iscsymf) (
+ int c
+ )
+{
+ return __iscsymf(c);
+}
+
+int (_CRTAPI1 __iscsym) (
+ int c
+ )
+{
+ return __iscsym(c);
+}
diff --git a/private/crt32/convert/_fptostr.c b/private/crt32/convert/_fptostr.c
new file mode 100644
index 000000000..287716842
--- /dev/null
+++ b/private/crt32/convert/_fptostr.c
@@ -0,0 +1,104 @@
+/***
+*_fptostr.c - workhorse routine for converting floating point to string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Workhorse routine for fcvt, ecvt.
+*
+*Revision History:
+* 09-17-84 DFW created
+* 03-05-90 GJF Fixed calling type, added #include <cruntime.h>,
+* removed #include <register.h>, fixed copyright. Also,
+* cleaned up the formatting a bit.
+* 07-20-90 SBM Compiles cleanly with -W3 (added #include <string.h>)
+* 08-01-90 SBM Renamed <struct.h> to <fltintrn.h>
+* 09-27-90 GJF New-style function declarator.
+* 06-11-92 GDP Bug fix: Shorten string if leadig (overflow) digit is 1
+* 10-09-92 GDP Backed out last fix for ecvt (printf regressed)
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <fltintrn.h>
+
+/***
+*void _fptostr(buf, digits, pflt) - workhorse floating point conversion
+*
+*Purpose:
+* This is the workhorse routine for fcvt, ecvt. Here is where
+* all the digits are put into a buffer and the rounding is
+* performed and indicators of the decimal point position are set. Note,
+* this must not change the mantissa field of pflt since routines which
+* use this routine rely on this being unchanged.
+*
+*Entry:
+* char *buf - the buffer in which the digits are to be put
+* int digits - the number of digits which are to go into the buffer
+* STRFLT pflt - a pointer to a structure containing information on the
+* floating point value, including a string containing the
+* non-zero significant digits of the mantissa.
+*
+*Exit:
+* Changes the contents of the buffer and also may increment the decpt
+* field of the structure pointer to by the 'pflt' parameter if overflow
+* occurs during rounding (e.g. 9.999999... gets rounded to 10.000...).
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _fptostr (
+ char *buf,
+ REG4 int digits,
+ REG3 STRFLT pflt
+ )
+{
+ REG1 char *pbuf = buf;
+ REG2 char *mantissa = pflt->mantissa;
+
+ /* initialize the first digit in the buffer to '0' (NOTE - NOT '\0')
+ * and set the pointer to the second digit of the buffer. The first
+ * digit is used to handle overflow on rounding (e.g. 9.9999...
+ * becomes 10.000...) which requires a carry into the first digit.
+ */
+
+ *pbuf++ = '0';
+
+ /* Copy the digits of the value into the buffer (with 0 padding)
+ * and insert the terminating null character.
+ */
+
+ while (digits > 0) {
+ *pbuf++ = (*mantissa) ? *mantissa++ : (char)'0';
+ digits--;
+ }
+ *pbuf = '\0';
+
+ /* do any rounding which may be needed. Note - if digits < 0 don't
+ * do any rounding since in this case, the rounding occurs in a digit
+ * which will not be output beause of the precision requested
+ */
+
+ if (digits >= 0 && *mantissa >= '5') {
+ pbuf--;
+ while (*pbuf == '9')
+ *pbuf-- = '0';
+ *pbuf += 1;
+ }
+
+ if (*buf == '1') {
+ /* the rounding caused overflow into the leading digit (e.g.
+ * 9.999.. went to 10.000...), so increment the decpt position
+ * by 1
+ */
+ pflt->decpt++;
+ }
+ else {
+ /* move the entire string to the left one digit to remove the
+ * unused overflow digit.
+ */
+ strcpy(buf, buf+1);
+ }
+}
diff --git a/private/crt32/convert/_mbslen.c b/private/crt32/convert/_mbslen.c
new file mode 100644
index 000000000..3b9710a9c
--- /dev/null
+++ b/private/crt32/convert/_mbslen.c
@@ -0,0 +1,99 @@
+/***
+*_mbslen.c - Return number of multibyte characters in a multibyte string
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Return number of multibyte characters in a multibyte string
+* excluding the terminal null. Locale-dependent.
+*
+*Revision History:
+* 10-01-91 ETC Created.
+* 12-08-91 ETC Add multithread lock.
+* 12-18-92 CFW Ported to Cuda tree, changed _CALLTYPE1 to _CRTAPI1.
+* 04-29-93 CFW Change to const char *s.
+* 06-01-93 CFW Test for bad MB chars.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 06-03-93 KRS Change name to avoid conflict with mbstring function.
+* Change return type to size_t.
+* 08-19-93 CFW Disallow skipping LB:NULL combos.
+* 10-26-93 CFW Test for invalid MB chars using global preset flag.
+* 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
+*
+*******************************************************************************/
+
+#ifdef _INTL
+#ifdef _NTSUBSET_
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <os2dll.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <assert.h>
+
+/***
+*_mbstrlen - Return number of multibyte characters in a multibyte string
+*
+*Purpose:
+* Return number of multibyte characters in a multibyte string
+* excluding the terminal null. Locale-dependent.
+*
+*Entry:
+* char *s = string
+*
+*Exit:
+* Returns the number of multibyte characters in the string, or
+* (size_t)-1 if the string contains an invalid multibyte character.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 _mbstrlen(
+ const char *s
+ )
+{
+ int n;
+
+ assert (MB_CUR_MAX == 1 || MB_CUR_MAX == 2);
+
+ if ( MB_CUR_MAX == 1 )
+ /* handle single byte character sets */
+ return (int)strlen(s);
+
+#ifndef _NTSUBSET_
+ _mlock (_LC_CTYPE_LOCK);
+
+ /* verify all valid MB chars */
+ if ( MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED|__invalid_mb_chars,
+ s, -1, NULL, 0) == 0 ) {
+ /* bad MB char */
+ n = (size_t)-1;
+ } else {
+ /* count MB chars */
+ for (n = 0; *s; n++, s++) {
+ if ( isleadbyte((unsigned char)*s) && *++s == '\0')
+ break;
+ }
+ }
+ _munlock (_LC_CTYPE_LOCK);
+#else
+ {
+ char *s1 = (char *)s;
+
+
+ n = 0;
+ while (RtlAnsiCharToUnicodeChar( &s1 ) != UNICODE_NULL)
+ n += 1;
+ }
+#endif
+
+ return(n);
+}
+#endif /* _INTL */
diff --git a/private/crt32/convert/_wctype.c b/private/crt32/convert/_wctype.c
new file mode 100644
index 000000000..989d1a2a3
--- /dev/null
+++ b/private/crt32/convert/_wctype.c
@@ -0,0 +1,140 @@
+/***
+*_wctype.c - function versions of wctype macros
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file provides function versions of the wide character
+* classification and conversion macros in ctype.h.
+*
+*Revision History:
+* 10-11-91 ETC Created from _ctype.c
+* 12-08-91 ETC Surround with #ifdef _INTL
+* 04-06-92 KRS Remove _INTL rwitches again
+* 10-26-92 GJF Cleaned up a bit.
+*
+*******************************************************************************/
+
+/***
+*wctype - Function versions of wctype macros
+*
+*Purpose:
+* Function versions of the wide char macros in ctype.h,
+* including isleadbyte and iswascii. In order to define
+* these, we use a trick -- we undefine the macro so we can use the
+* name in the function declaration, then re-include the file so
+* we can use the macro in the definition part.
+*
+* Functions defined:
+* iswalpha iswupper iswlower
+* iswdigit iswxdigit iswspace
+* iswpunct iswalnum iswprint
+* iswgraph iswctrl iswascii
+* isleadbyte
+*
+*Entry:
+* wchar_t c = character to be tested
+*Exit:
+* returns non-zero = character is of the requested type
+* 0 = character is NOT of the requested type
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#define __STDC__ 1
+#include <stdlib.h>
+#include <ctype.h>
+
+int (_CRTAPI1 isleadbyte) (
+ int c
+ )
+{
+ return isleadbyte(c);
+}
+
+int (_CRTAPI1 iswalpha) (
+ wchar_t c
+ )
+{
+ return iswalpha(c);
+}
+
+int (_CRTAPI1 iswupper) (
+ wchar_t c
+ )
+{
+ return iswupper(c);
+}
+
+int (_CRTAPI1 iswlower) (
+ wchar_t c
+ )
+{
+ return iswlower(c);
+}
+
+int (_CRTAPI1 iswdigit) (
+ wchar_t c
+ )
+{
+ return iswdigit(c);
+}
+
+int (_CRTAPI1 iswxdigit) (
+ wchar_t c
+ )
+{
+ return iswxdigit(c);
+}
+
+int (_CRTAPI1 iswspace) (
+ wchar_t c
+ )
+{
+ return iswspace(c);
+}
+
+int (_CRTAPI1 iswpunct) (
+ wchar_t c
+ )
+{
+ return iswpunct(c);
+}
+
+int (_CRTAPI1 iswalnum) (
+ wchar_t c
+ )
+{
+ return iswalnum(c);
+}
+
+int (_CRTAPI1 iswprint) (
+ wchar_t c
+ )
+{
+ return iswprint(c);
+}
+
+int (_CRTAPI1 iswgraph) (
+ wchar_t c
+ )
+{
+ return iswgraph(c);
+}
+
+int (_CRTAPI1 iswcntrl) (
+ wchar_t c
+ )
+{
+ return iswcntrl(c);
+}
+
+int (_CRTAPI1 iswascii) (
+ wchar_t c
+ )
+{
+ return iswascii(c);
+}
diff --git a/private/crt32/convert/atof.c b/private/crt32/convert/atof.c
new file mode 100644
index 000000000..debc9635c
--- /dev/null
+++ b/private/crt32/convert/atof.c
@@ -0,0 +1,81 @@
+/***
+*atof.c - convert char string to floating point number
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts a character string into a floating point number.
+*
+*Revision History:
+* 09-09-87 RKW written
+* 04-13-87 JCR added const to declaration
+* 11-09-87 BCM different interface under ifdef MTHREAD
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-24-88 PHG Merged DLL and normal versions
+* 08-18-88 PHG now calls isspace to process all kinds of whitespce
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 11-20-89 JCR atof() is always _cdecl in 386 (not pascal)
+* 03-05-90 GJF Fixed calling type, added #include <cruntime.h>,
+* removed #include <register.h>, removed some redundant
+* prototypes, removed some leftover 16-bit support and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 07-20-90 SBM Compiles cleanly with -W3 (added/removed appropriate
+* #includes)
+* 08-01-90 SBM Renamed <struct.h> to <fltintrn.h>
+* 09-27-90 GJF New-style function declarator.
+* 10-21-92 GJF Made char-to-int conversion unsigned.
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+#include <math.h>
+#include <cruntime.h>
+#include <fltintrn.h>
+#include <string.h>
+#include <ctype.h>
+
+/***
+*double atof(nptr) - convert string to floating point number
+*
+*Purpose:
+* atof recognizes an optional string of whitespace, then
+* an optional sign, then a string of digits optionally
+* containing a decimal point, then an optional e or E followed
+* by an optionally signed integer, and converts all this to
+* to a floating point number. The first unrecognized
+* character ends the string.
+*
+*Entry:
+* nptr - pointer to string to convert
+*
+*Exit:
+* returns floating point value of character representation
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+double _CRTAPI1 atof(
+ REG1 const char *nptr
+ )
+{
+
+#ifdef MTHREAD
+ struct _flt fltstruct; /* temporary structure */
+#endif
+
+ /* scan past leading space/tab characters */
+
+ while ( isspace((int)(unsigned char)*nptr) )
+ nptr++;
+
+ /* let _fltin routine do the rest of the work */
+
+#ifdef MTHREAD
+ return( *(double *)&(_fltin2( &fltstruct, nptr, strlen(nptr), 0, 0 )->
+ dval) );
+#else
+ return( *(double *)&(_fltin( nptr, strlen(nptr), 0, 0 )->dval) );
+#endif
+}
diff --git a/private/crt32/convert/atox.c b/private/crt32/convert/atox.c
new file mode 100644
index 000000000..4e3934735
--- /dev/null
+++ b/private/crt32/convert/atox.c
@@ -0,0 +1,96 @@
+/***
+*atox.c - atoi and atol conversion
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts a character string into an int or long.
+*
+*Revision History:
+* 06-05-89 PHG Module created, based on asm version
+* 03-05-90 GJF Fixed calling type, added #include <cruntime.h> and
+* cleaned up the formatting a bit. Also, fixed the
+* copyright.
+* 09-27-90 GJF New-style function declarators.
+* 10-21-92 GJF Fixed conversions of char to int.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+/***
+*long atol(char *nptr) - Convert string to long
+*
+*Purpose:
+* Converts ASCII string pointed to by nptr to binary.
+* Overflow is not detected.
+*
+*Entry:
+* nptr = ptr to string to convert
+*
+*Exit:
+* return long int value of the string
+*
+*Exceptions:
+* None - overflow is not detected.
+*
+*******************************************************************************/
+
+long _CRTAPI1 atol(
+ const char *nptr
+ )
+{
+ int c; /* current char */
+ long total; /* current total */
+ int sign; /* if '-', then negative, otherwise positive */
+
+ /* skip whitespace */
+ while ( isspace((int)(unsigned char)*nptr) )
+ ++nptr;
+
+ c = (int)(unsigned char)*nptr++;
+ sign = c; /* save sign indication */
+ if (c == '-' || c == '+')
+ c = (int)(unsigned char)*nptr++; /* skip sign */
+
+ total = 0;
+
+ while (isdigit(c)) {
+ total = 10 * total + (c - '0'); /* accumulate digit */
+ c = (int)(unsigned char)*nptr++; /* get next char */
+ }
+
+ if (sign == '-')
+ return -total;
+ else
+ return total; /* return result, negated if necessary */
+}
+
+
+/***
+*int atoi(char *nptr) - Convert string to long
+*
+*Purpose:
+* Converts ASCII string pointed to by nptr to binary.
+* Overflow is not detected. Because of this, we can just use
+* atol().
+*
+*Entry:
+* nptr = ptr to string to convert
+*
+*Exit:
+* return int value of the string
+*
+*Exceptions:
+* None - overflow is not detected.
+*
+*******************************************************************************/
+
+int _CRTAPI1 atoi(
+ const char *nptr
+ )
+{
+ return (int)atol(nptr);
+}
diff --git a/private/crt32/convert/fcvt.c b/private/crt32/convert/fcvt.c
new file mode 100644
index 000000000..92bb49b3f
--- /dev/null
+++ b/private/crt32/convert/fcvt.c
@@ -0,0 +1,252 @@
+/***
+*fcvt.c - convert floating point value to string
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts a floating point value to a string.
+*
+*Revision History:
+* 09-09-83 RKW written
+* 09-14-84 DFW fixed problems with buffer overflow and
+* streamlined the code
+* 11-09-87 BCM different interface under ifdef MTHREAD
+* 11-19-87 WAJ fcvt now uses emulator data area for buffer
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-24-88 PHG Merged DLL and normal versions
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 10-20-88 JCR Changed 'DOUBLE' to 'double' for 386
+* 03-02-90 GJF Added #include <cruntime.h>. Removed some (now) useless
+* preprocessor directives. Also, fixed copyright.
+* 03-06-90 GJF Fixed calling type, removed some leftover 16-bit
+* support.
+* 03-23-90 GJF Made _fpcvt() _CALLTYPE4 and removed prototype for
+* _fptostr() (now in struct.h).
+* 08-01-90 SBM Renamed <struct.h> to <fltintrn.h>
+* 09-27-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 10-03-91 JCR Fixed mthread buffer allocation
+* 02-16-93 GJF Changed for new _getptd().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <fltintrn.h>
+#include <cvt.h>
+#include <os2dll.h>
+#include <stdlib.h>
+
+/*
+ * The static character array buf[CVTBUFSIZE] is used by the _fpcvt routine
+ * (the workhorse for _ecvt and _fcvt) for storage of its output. The routine
+ * gcvt expects the user to have set up their own storage. CVTBUFSIZE is set
+ * large enough to accomodate the largest double precision number plus 40
+ * decimal places (even though you only have 16 digits of accuracy in a
+ * double precision IEEE number, the user may ask for more to effect 0
+ * padding; but there has to be a limit somewhere).
+ */
+
+/*
+ * define a maximum size for the conversion buffer. It should be at least
+ * as long as the number of digits in the largest double precision value
+ * (?.?e308 in IEEE arithmetic). We will use the same size buffer as is
+ * used in the printf support routine (_output)
+ */
+
+#ifdef MTHREAD
+char * _CRTAPI3 _fpcvt(STRFLT, int, int *, int *);
+#else
+static char * _CRTAPI3 _fpcvt(STRFLT, int, int *, int *);
+static char buf[CVTBUFSIZE];
+#endif
+
+/***
+*char *_fcvt(value, ndec, decpr, sign) - convert floating point to char string
+*
+*Purpose:
+* _fcvt like _ecvt converts the value to a null terminated
+* string of ASCII digits, and returns a pointer to the
+* result. The routine prepares data for Fortran F-format
+* output with the number of digits following the decimal
+* point specified by ndec. The position of the decimal
+* point relative to the beginning of the string is returned
+* indirectly through decpt. The correct digit for Fortran
+* F-format is rounded.
+* NOTE - to avoid the possibility of generating floating
+* point instructions in this code we fool the compiler
+* about the type of the 'value' parameter using a struct.
+* This is OK since all we do is pass it off as a
+* parameter.
+*
+*Entry:
+* double value - number to be converted
+* int ndec - number of digits after decimal point
+*
+*Exit:
+* returns pointer to the character string representation of value.
+* also, the output is written into the static char array buf.
+* int *decpt - pointer to int with pos. of dec. point
+* int *sign - pointer to int with sign (0 = pos, non-0 = neg)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CRTAPI1 _fcvt (
+ double value,
+ int ndec,
+ int *decpt,
+ int *sign
+ )
+{
+ REG1 STRFLT pflt;
+
+#ifdef MTHREAD
+ struct _strflt strfltstruct;
+ char resultstring[21];
+
+ /* ok to take address of stack struct here; fltout2 knows to use ss */
+ pflt = _fltout2( value, &strfltstruct, resultstring );
+
+
+#else
+ pflt = _fltout( value );
+#endif
+
+ return( _fpcvt( pflt, pflt->decpt + ndec, decpt, sign ) );
+}
+
+
+/***
+*char *_ecvt( value, ndigit, decpt, sign ) - convert floating point to string
+*
+*Purpose:
+* _ecvt converts value to a null terminated string of
+* ASCII digits, and returns a pointer to the result.
+* The position of the decimal point relative to the
+* begining of the string is stored indirectly through
+* decpt, where negative means to the left of the returned
+* digits. If the sign of the result is negative, the
+* word pointed to by sign is non zero, otherwise it is
+* zero. The low order digit is rounded.
+*
+*Entry:
+* double value - number to be converted
+* int ndigit - number of digits after decimal point
+*
+*Exit:
+* returns pointer to the character representation of value.
+* also the output is written into the statuc char array buf.
+* int *decpt - pointer to int with position of decimal point
+* int *sign - pointer to int with sign in it (0 = pos, non-0 = neg)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CRTAPI1 _ecvt (
+ double value,
+ int ndigit,
+ int *decpt,
+ int *sign
+ )
+{
+
+#ifdef MTHREAD
+ REG1 STRFLT pflt;
+
+ struct _strflt strfltstruct; /* temporary buffers */
+ char resultstring[21];
+
+ /* ok to take address of stack struct here; fltout2 knows to use ss */
+ pflt = _fltout2( value, &strfltstruct, resultstring );
+
+ return( _fpcvt( pflt, ndigit, decpt, sign ) );
+
+#else
+ return( _fpcvt( _fltout(value), ndigit, decpt, sign ) );
+#endif
+}
+
+
+/***
+*char *_fpcvt() - gets final string and sets decpt and sign [STATIC]
+*
+*Purpose:
+* This is a small common routine used by [ef]cvt. It calls fptostr
+* to get the final string and sets the decpt and sign indicators.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+char * _CRTAPI3 _fpcvt (
+#else
+static char * _CRTAPI3 _fpcvt (
+#endif
+ REG2 STRFLT pflt,
+ REG3 int digits,
+ int *decpt,
+ int *sign
+ )
+{
+
+#ifdef MTHREAD
+
+ /* use a per-thread buffer */
+
+ char *buf;
+
+#ifdef _CRUISER_
+
+ struct _tiddata * tdata;
+
+ tdata = _gettidtab(); /* get tid's data address */
+ if (tdata->_cvtbuf == NULL)
+ if ( (tdata->_cvtbuf = malloc(CVTBUFSIZE)) == NULL)
+ return(NULL);
+ buf = tdata->_cvtbuf;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ _ptiddata ptd;
+
+ ptd = _getptd();
+ if ( ptd->_cvtbuf == NULL )
+ if ( (ptd->_cvtbuf = malloc(CVTBUFSIZE)) == NULL )
+ return(NULL);
+ buf = ptd->_cvtbuf;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#endif /* MTHREAD */
+
+
+ /* make sure we don't overflow the buffer size. If the user asks for
+ * more digits than the buffer can handle, truncate it to the maximum
+ * size allowed in the buffer. The maximum size is CVTBUFSIZE - 2
+ * since we useone character for overflow and one for the terminating
+ * null character.
+ */
+
+ _fptostr(buf, (digits > CVTBUFSIZE - 2) ? CVTBUFSIZE - 2 : digits, pflt);
+
+ /* set the sign flag and decimal point position */
+
+ *sign = (pflt->sign == '-') ? 1 : 0;
+ *decpt = pflt->decpt;
+ return(buf);
+}
diff --git a/private/crt32/convert/gcvt.c b/private/crt32/convert/gcvt.c
new file mode 100644
index 000000000..a720725fc
--- /dev/null
+++ b/private/crt32/convert/gcvt.c
@@ -0,0 +1,122 @@
+/***
+*gcvt.c - convert floating point number to character string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts floating point number into character string representation.
+*
+*Revision History:
+* 09-09-93 RKW written
+* 11-09-87 BCM different interface under ifdef MTHREAD
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-24-88 PHG Merged DLL and normal versions
+* 10-20-88 JCR Changed 'DOUBLE' to 'double' for 386
+* 06-27-89 PHG Changed "ndec" to "ndec-1" to correct significant
+* digits in exponential format (C6 bug #2124)
+* 03-05-90 GJF Fixed calling type, added #include <cruntime.h>,
+* removed #include <register.h>, removed redundant
+* prototypes, removed some leftover 16-bit support and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 07-20-90 SBM Compiles cleanly with -W3 (added/removed appropriate
+* #includes)
+* 08-01-90 SBM Renamed <struct.h> to <fltintrn.h>
+* 09-27-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 08-13-92 SKS An old bug that was fixed in C 6.0 but that did not
+* make it into C 7.0, an off by 1 error when switching
+* from fixed point to scientific notation
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <fltintrn.h>
+#include <internal.h>
+
+/***
+*double _gcvt(value, ndec, buffer) - convert floating point value to char
+* string
+*
+*Purpose:
+* _gcvt converts the value to a null terminated ASCII string
+* buf. It attempts to produce ndigit significant digits
+* in Fortran F format if possible, ortherwise E format,
+* ready for printing. Trailing zeros may be suppressed.
+* No error checking or overflow protection is provided.
+* NOTE - to avoid the possibility of generating floating
+* point instructions in this code we fool the compiler
+* about the type of the 'value' parameter using a struct.
+* This is OK since all we do is pass it off as a
+* parameter.
+*
+*Entry:
+* value - double - number to be converted
+* ndec - int - number of significant digits
+* buf - char * - buffer to place result
+*
+*Exit:
+* result is written into buffer; it will be overwritten if it has
+* not been made big enough.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _gcvt (
+ double value,
+ int ndec,
+ char *buf
+ )
+{
+
+#ifdef MTHREAD
+ struct _strflt strfltstruct; /* temporary buffers */
+ char resultstring[21];
+#endif
+
+ STRFLT string;
+ int magnitude;
+ char *rc;
+
+ REG1 char *str;
+ REG2 char *stop;
+
+ /* get the magnitude of the number */
+
+#ifdef MTHREAD
+ string = _fltout2( value, &strfltstruct, resultstring );
+#else
+ string = _fltout( value );
+#endif
+
+ magnitude = string->decpt - 1;
+
+ /* output the result according to the Fortran G format as outlined in
+ Fortran language specification */
+
+ if ( magnitude < -1 || magnitude > ndec-1 )
+ /* then Ew.d d = ndec */
+ rc = str = _cftoe( &value, buf, ndec-1, 0);
+ else
+ /* Fw.d where d = ndec-string->decpt */
+ rc = str = _cftof( &value, buf, ndec-string->decpt );
+
+ while (*str && *str != '.')
+ str++;
+
+ if (*str++) {
+ while (*str && *str != 'e')
+ str++;
+
+ stop = str--;
+
+ while (*str == '0')
+ str--;
+
+ while (*++str = *stop++)
+ ;
+ }
+
+ return(rc);
+}
diff --git a/private/crt32/convert/isctype.c b/private/crt32/convert/isctype.c
new file mode 100644
index 000000000..730470b92
--- /dev/null
+++ b/private/crt32/convert/isctype.c
@@ -0,0 +1,119 @@
+/***
+*isctype.c - support is* ctype functions/macros for two-byte multibyte chars
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines _isctype.c - support is* ctype functions/macros for
+* two-byte multibyte chars.
+*
+*Revision History:
+* 10-11-91 ETC Created.
+* 12-08-91 ETC Updated api; added multhread lock; check char masks.
+* 04-06-92 KRS Fix logic error in return value.
+* 08-07-92 GJF _CALLTYPE4 (bogus usage) -> _CRTAPI1 (legit).
+* 01-19-93 CFW Change C1_* to new names, call new APIs.
+* 03-04-93 CFW Removed CTRL-Z.
+* 04-01-93 CFW Remove EOF test (handled by array), return masked.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+#include <stdio.h>
+#include <cruntime.h>
+#include <ctype.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+
+/*
+ * Use GetCharType() API so check that character type masks agree between
+ * ctype.h and winnls.h
+ */
+#if _UPPER != C1_UPPER || \
+ _LOWER != C1_LOWER || \
+ _DIGIT != C1_DIGIT || \
+ _SPACE != C1_SPACE || \
+ _PUNCT != C1_PUNCT || \
+ _CONTROL != C1_CNTRL
+#error Character type masks do not agree in ctype and winnls
+#endif
+
+/***
+*_isctype - support is* ctype functions/macros for two-byte multibyte chars
+*
+*Purpose:
+* This function is called by the is* ctype functions/macros
+* (e.g. isalpha()) when their argument is a two-byte multibyte char.
+* Returns true or false depending on whether the argument satisfies
+* the character class property encoded by the mask.
+*
+*Entry:
+* int c - the multibyte character whose type is to be tested
+* unsigned int mask - the mask used by the is* functions/macros
+* corresponding to each character class property
+*
+* The leadbyte and the trailbyte should be packed into the int c as:
+*
+* H.......|.......|.......|.......L
+* 0 0 leadbyte trailbyte
+*
+*Exit:
+* Returns non-zero if c is of the character class.
+* Returns 0 if c is not of the character class.
+*
+*Exceptions:
+* Returns 0 on any error.
+*
+*******************************************************************************/
+
+int _CRTAPI1 _isctype (
+ int c,
+ int mask
+ )
+{
+ wchar_t widechar[2], chartype;
+ char buffer[3];
+
+ /* c valid between -1 and 255 */
+ if (((unsigned)(c + 1)) <= 256)
+ return _pctype[c] & mask;
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if (isleadbyte(c>>8 & 0xff))
+ {
+ buffer[0] = (c>>8 & 0xff); /* put lead-byte at start of str */
+ buffer[1] = (char)c;
+ buffer[2] = 0;
+ }
+ else
+ {
+ buffer[0] = (char)c;
+ buffer[1] = 0;
+ }
+ if (MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED,
+ buffer, -1, widechar, 2) == 0)
+ return 0;
+
+ _munlock (_LC_CTYPE_LOCK);
+
+ if (GetStringTypeW(CT_CTYPE1, widechar, 2, &chartype) != NO_ERROR) {
+ return 0;
+ }
+
+ return (int)(chartype & mask);
+}
+
+#else /* defined(_INTL) && !defined(_NTSUBSET_) */
+
+int _CRTAPI1 _isctype (
+ int c,
+ int mask
+ )
+{
+ return 0;
+}
+
+#endif /* _INTL */
diff --git a/private/crt32/convert/iswctype.c b/private/crt32/convert/iswctype.c
new file mode 100644
index 000000000..c8f9629b0
--- /dev/null
+++ b/private/crt32/convert/iswctype.c
@@ -0,0 +1,128 @@
+/***
+*iswctype.c - support isw* wctype functions/macros for wide characters
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines iswctype - support isw* wctype functions/macros for
+* wide characters (esp. > 255).
+*
+*Revision History:
+* 10-11-91 ETC Created.
+* 12-08-91 ETC Updated api; check type masks.
+* 04-06-92 KRS Change to match ISO proposal. Fix logic error.
+* 08-07-92 GJF _CALLTYPE4 (bogus usage) -> _CRTAPI1 (legit).
+* 08-20-92 KRS Activated NLS support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 09-03-92 GJF Merged last 4 changes.
+* 01-15-93 CFW Put #ifdef _INTL around wint_t d def to avoid warnings
+* 02-12-93 CFW Return d not c, remove CTRL-Z.
+* 02-17-93 CFW Include locale.h.
+* 05-05-93 CFW Change name from is_wctype to iswctype as per ISO.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 06-26-93 CFW Support is_wctype forever.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <locale.h>
+#include <setlocal.h>
+
+/*
+ * Use GetStringTypeW() API so check that character type masks agree between
+ * ctype.h and winnls.h
+ */
+#if defined(_INTL) && !defined(_NTSUBSET_)
+#if _UPPER != C1_UPPER || \
+ _LOWER != C1_LOWER || \
+ _DIGIT != C1_DIGIT || \
+ _SPACE != C1_SPACE || \
+ _PUNCT != C1_PUNCT || \
+ _CONTROL != C1_CNTRL
+#error Character type masks do not agree in ctype and winnls
+#endif
+#endif
+
+
+/***
+*iswctype - support isw* wctype functions/macros.
+*
+*Purpose:
+* This function is called by the isw* wctype functions/macros
+* (e.g. iswalpha()) when their argument is a wide character > 255.
+* It is also a standard ITSCJ (proposed) ISO routine and can be called
+* by the user, even for characters < 256.
+* Returns true or false depending on whether the argument satisfies
+* the character class property encoded by the mask. Returns 0 if the
+* argument is WEOF.
+*
+* NOTE: The isw* functions are neither locale nor codepage dependent.
+*
+*Entry:
+* wchar_t c - the wide character whose type is to be tested
+* wchar_t mask - the mask used by the isw* functions/macros
+* corresponding to each character class property
+*
+*Exit:
+* Returns non-zero if c is of the character class.
+* Returns 0 if c is not of the character class.
+*
+*Exceptions:
+* Returns 0 on any error.
+*
+*******************************************************************************/
+
+int _CRTAPI1 iswctype (
+ wchar_t c,
+ wctype_t mask
+ )
+{
+ wint_t d;
+
+ if (c == WEOF)
+ return 0;
+
+ if (c < 256) /* consider: necessary? */
+ d = _pwctype[c];
+ else
+ {
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE
+ || GetStringTypeW(CT_CTYPE1, &c, 1, &d) == 0)
+#endif /* _INTL */
+ return 0;
+ }
+
+ return (int)(d & mask);
+}
+
+
+/***
+*is_wctype - support obsolete name
+*
+*Purpose:
+* Name changed from is_wctype to iswctype. is_wctype must be supported.
+*
+*Entry:
+* wchar_t c - the wide character whose type is to be tested
+* wchar_t mask - the mask used by the isw* functions/macros
+* corresponding to each character class property
+*
+*Exit:
+* Returns non-zero if c is of the character class.
+* Returns 0 if c is not of the character class.
+*
+*Exceptions:
+* Returns 0 on any error.
+*
+*******************************************************************************/
+int _CRTAPI1 is_wctype (
+ wchar_t c,
+ wctype_t mask
+ )
+{
+ return iswctype(c, mask);
+}
diff --git a/private/crt32/convert/makefile b/private/crt32/convert/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/convert/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/convert/mblen.c b/private/crt32/convert/mblen.c
new file mode 100644
index 000000000..5e9d7473b
--- /dev/null
+++ b/private/crt32/convert/mblen.c
@@ -0,0 +1,109 @@
+/***
+*mblen.c - length of multibyte character
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Return the number of bytes contained in a multibyte character.
+*
+*Revision History:
+* 03-19-90 KRS Module created.
+* 12-20-90 KRS Include ctype.h.
+* 03-20-91 KRS Ported from 16-bit tree.
+* 12-09-91 ETC Updated comments; move __mb_cur_max to nlsdata1.c;
+* add multithread.
+* 06-01-93 CFW Re-write; verify valid MB char, proper error return,
+* optimize, correct conversion bug.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 10-26-93 CFW Test for invalid MB chars using global preset flag.
+* 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
+*
+*******************************************************************************/
+
+#ifdef _NTSUBSET_
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <os2dll.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <assert.h>
+
+/***
+*int mblen() - length of multibyte character
+*
+*Purpose:
+* Return the number of bytes contained in a multibyte character.
+* [ANSI].
+*
+*Entry:
+* const char *s = pointer to multibyte character
+* size_t n = maximum length of multibyte character to consider
+*
+*Exit:
+* If s = NULL, returns 0, indicating we use (only) state-independent
+* character encodings.
+* If s != NULL, returns: 0 (if *s = null char)
+* -1 (if the next n or fewer bytes not valid mbc)
+* number of bytes contained in multibyte char
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 mblen
+ (
+ const char * s,
+ size_t n
+ )
+{
+ assert (MB_CUR_MAX == 1 || MB_CUR_MAX == 2);
+
+ if ( !s || !(*s) || (n == 0) )
+ /* indicate do not have state-dependent encodings,
+ empty string length is 0 */
+ return 0;
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ if ( isleadbyte((unsigned char)*s) )
+ {
+ /* multi-byte char */
+
+ /* verify valid MB char */
+ if ( MB_CUR_MAX <= 1 || (int)n < MB_CUR_MAX ||
+ MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED|__invalid_mb_chars,
+ s, MB_CUR_MAX, NULL, 0) == 0 )
+ /* bad MB char */
+ return -1;
+ else
+ return MB_CUR_MAX;
+ }
+ else {
+ /* single byte char */
+
+ /* verify valid SB char */
+ if ( MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED|__invalid_mb_chars,
+ s, 1, NULL, 0) == 0 )
+ return -1;
+
+ return sizeof(char);
+ }
+#else /* defined(_INTL) && !defined(_NTSUBSET_) */
+
+#ifdef _NTSUBSET_
+ {
+ char *s1 = (char *)s;
+
+ RtlAnsiCharToUnicodeChar( &s1 );
+ return s1 - s;
+ }
+#else
+ return sizeof(char);
+#endif
+#endif /* _INTL */
+}
diff --git a/private/crt32/convert/mbstowcs.c b/private/crt32/convert/mbstowcs.c
new file mode 100644
index 000000000..739b91c5e
--- /dev/null
+++ b/private/crt32/convert/mbstowcs.c
@@ -0,0 +1,197 @@
+/***
+*mbstowcs.c - Convert multibyte char string to wide char string.
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert a multibyte char string into the equivalent wide char string.
+*
+*Revision History:
+* 08-24-90 KRS Module created.
+* 03-20-91 KRS Ported from 16-bit tree.
+* 10-16-91 ETC Locale support under _INTL switch.
+* 12-09-91 ETC Updated nlsapi; added multithread.
+* 08-20-92 KRS Activated NLSAPI support.
+* 08-31-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 02-09-93 CFW Always stuff WC 0 at end of output string of room (non _INTL).
+* 04-06-93 SKS Replace _CRTAPI* with _cdecl
+* 05-03-93 CFW Return pointer == NULL, return size, plus massive cleanup.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 09-27-93 CFW Avoid cast bug.
+* 10-26-93 CFW Test for invalid MB chars using global preset flag.
+* 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
+* 07-06-94 SRW Call mblen instead of _mbstrlen for input to Rtl function
+* 07-07-94 MMS/IJH Undo previous change, Call _mbstrlen
+*
+*******************************************************************************/
+
+#ifdef _NTSUBSET_
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <os2dll.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <errno.h>
+#include <assert.h>
+
+/***
+*size_t mbstowcs() - Convert multibyte char string to wide char string.
+*
+*Purpose:
+* Convert a multi-byte char string into the equivalent wide char string,
+* according to the LC_CTYPE category of the current locale.
+* [ANSI].
+*
+* NOTE: Currently, the C libraries support the "C" locale only.
+* Non-C locale support now available under _INTL switch.
+*Entry:
+* wchar_t *pwcs = pointer to destination wide character string buffer
+* const char *s = pointer to source multibyte character string
+* size_t n = maximum number of wide characters to store
+*
+*Exit:
+* If s != NULL, returns: number of words modified (<=n)
+* (size_t)-1 (if invalid mbcs)
+*
+*Exceptions:
+* Returns (size_t)-1 if s is NULL or invalid mbcs character encountered
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+size_t _CRTAPI1 mbstowcs
+ (
+ wchar_t *pwcs,
+ const char *s,
+ size_t n
+ )
+{
+ size_t retval;
+
+ _mlock (_LC_CTYPE_LOCK);
+ retval = _mbstowcs_lk(pwcs, s, n);
+ _munlock (_LC_CTYPE_LOCK);
+ return retval;
+}
+#endif /* MTHREAD */
+
+#ifdef MTHREAD
+size_t _CRTAPI1 _mbstowcs_lk
+#else
+size_t _CRTAPI1 mbstowcs
+#endif
+ (
+ wchar_t *pwcs,
+ const char *s,
+ size_t n
+ )
+{
+ int retval = 0;
+ size_t count = 0;
+
+ if (pwcs && n == 0)
+ return (size_t) 0;
+
+ assert(s != NULL);
+
+ /* if destination string exists, fill it in */
+ if (pwcs)
+ {
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE &&
+ _lc_codepage == _CLOCALECP)
+ {
+#endif /* _INTL */
+#ifdef _NTSUBSET_
+ {
+ NTSTATUS Status;
+ int size;
+
+ size = _mbstrlen(s);
+ Status = RtlMultiByteToUnicodeN(pwcs, n * sizeof( *pwcs ), (PULONG)&size, s, size+1 );
+ if (!NT_SUCCESS(Status))
+ {
+ errno = EILSEQ;
+ size = -1;
+ } else {
+ size = size / sizeof( *pwcs );
+ if (pwcs[size-1] == L'\0') {
+ size -= 1;
+ }
+ }
+
+ return size;
+ }
+#else
+ /* C locale: easy and fast */
+ while (count < n)
+ {
+ *pwcs = (wchar_t) ((unsigned char)s[count]);
+ if (!s[count])
+ return count;
+ count++;
+ pwcs++;
+ }
+#endif
+ return count;
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ } else {
+ /* Assume that usually the buffer is large enough */
+ if ((count=MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED|__invalid_mb_chars,
+ s, -1, pwcs, n)) != 0)
+ return count - 1;
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ errno = EILSEQ;
+ return (size_t)-1;
+ }
+
+ /* buffer not large enough, must do char by char */
+ while (count < n)
+ {
+ if ((retval = MultiByteToWideChar (_lc_codepage, MB_PRECOMPOSED,
+ s, MB_CUR_MAX, pwcs, 1)) == 0)
+ {
+ errno = EILSEQ;
+ return (size_t)-1;
+ }
+ if (!*s)
+ return count;
+ if (isleadbyte((unsigned char)*s))
+ s++;
+ s++;
+ count++;
+ pwcs++;
+ }
+ return count;
+ }
+#endif /* _INTL */
+ }
+ else { /* pwcs == NULL, get size only, s must be NUL-terminated */
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE &&
+ _lc_codepage == _CLOCALECP)
+#endif /* _INTL */
+ return strlen(s);
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ else {
+ if ((count=MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED|__invalid_mb_chars,
+ s, -1, NULL, 0)) == 0)
+ {
+ errno = EILSEQ;
+ return (size_t)-1;
+ }
+
+ return count - 1;
+ }
+#endif /* _INTL */
+ }
+}
diff --git a/private/crt32/convert/mbtowc.c b/private/crt32/convert/mbtowc.c
new file mode 100644
index 000000000..7f8aea165
--- /dev/null
+++ b/private/crt32/convert/mbtowc.c
@@ -0,0 +1,174 @@
+/***
+*mbtowc.c - Convert multibyte char to wide char.
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert a multibyte character into the equivalent wide character.
+*
+*Revision History:
+* 03-19-90 KRS Module created.
+* 12-20-90 KRS Put some intl stuff here for now...
+* 03-18-91 KRS Fixed bogus cast involving wchar_t. Fix copyright.
+* 03-20-91 KRS Ported from 16-bit tree.
+* 07-22-91 KRS C700 3525: Check for s==0 before calling mblen.
+* 07-23-91 KRS Hard-coded for "C" locale to avoid bogus interim #'s.
+* 10-15-91 ETC Locale support under _INTL (finally!).
+* 12-09-91 ETC Updated nlsapi; added multithread.
+* 08-20-92 KRS Activated NLSAPI support.
+* 08-31-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 04-26-93 CFW Remove unused variable.
+* 05-04-93 CFW Kinder, gentler error handling.
+* 06-01-93 CFW Re-write; verify valid MB char, proper error return,
+* optimize, fix bugs.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 10-26-93 CFW Test for invalid MB chars using global preset flag.
+* 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
+*
+*******************************************************************************/
+
+#ifdef _NTSUBSET_
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <os2dll.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <errno.h>
+#include <assert.h>
+
+/***
+*int mbtowc() - Convert multibyte char to wide character.
+*
+*Purpose:
+* Convert a multi-byte character into the equivalent wide character,
+* according to the LC_CTYPE category of the current locale.
+* [ANSI].
+*
+* NOTE: Currently, the C libraries support the "C" locale only.
+* Non-C locale support now available under _INTL switch.
+*Entry:
+* wchar_t *pwc = pointer to destination wide character
+* const char *s = pointer to multibyte character
+* size_t n = maximum length of multibyte character to consider
+*
+*Exit:
+* If s = NULL, returns 0, indicating we only use state-independent
+* character encodings.
+* If s != NULL, returns: 0 (if *s = null char)
+* -1 (if the next n or fewer bytes not valid mbc)
+* number of bytes comprising converted mbc
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+int _CRTAPI1 mbtowc
+ (
+ wchar_t *pwc,
+ const char *s,
+ size_t n
+ )
+{
+ int retval;
+
+ _mlock (_LC_CTYPE_LOCK);
+ retval = _mbtowc_lk(pwc, s, n);
+ _munlock (_LC_CTYPE_LOCK);
+ return retval;
+}
+#endif /* MTHREAD */
+
+#ifdef MTHREAD
+int _CRTAPI1 _mbtowc_lk
+#else
+int _CRTAPI1 mbtowc
+#endif
+ (
+ wchar_t *pwc,
+ const char *s,
+ size_t n
+ )
+{
+ assert (MB_CUR_MAX == 1 || MB_CUR_MAX == 2);
+
+ if ( !s || n == 0 )
+ /* indicate do not have state-dependent encodings,
+ handle zero length string */
+ return 0;
+
+ if ( !*s )
+ {
+ /* handle NULL char */
+ if (pwc)
+ *pwc = 0;
+ return 0;
+ }
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+
+ if ( _lc_handle[LC_CTYPE] == _CLOCALEHANDLE )
+ {
+
+#endif /* _INTL */
+
+#ifdef _NTSUBSET_
+ {
+ NTSTATUS Status;
+ int size;
+
+ Status = RtlMultiByteToUnicodeN(pwc, (pwc) ? sizeof( *pwc ) : 0, (PULONG)&size, s, n );
+ if (!NT_SUCCESS(Status))
+ {
+ errno = EILSEQ;
+ size = -1;
+
+
+ } else
+ size = mblen(s, n);
+
+ return size;
+ }
+#else
+ if (pwc)
+ *pwc = (wchar_t)(unsigned char)*s;
+ return sizeof(char);
+#endif
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+
+ }
+
+ if ( isleadbyte((unsigned char)*s) )
+ {
+ /* multi-byte char */
+
+ if ( MB_CUR_MAX <= 1 || (int)n < MB_CUR_MAX ||
+ (MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED|__invalid_mb_chars,
+ s, MB_CUR_MAX, pwc, (pwc) ? 1 : 0) == 0) )
+ {
+ errno = EILSEQ;
+ return -1;
+ }
+ return MB_CUR_MAX;
+ }
+ else {
+ /* single byte char */
+
+ if ( MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED|__invalid_mb_chars,
+ s, 1, pwc, (pwc) ? 1 : 0) == 0 )
+ {
+ errno = EILSEQ;
+ return -1;
+ }
+
+ return sizeof(char);
+ }
+#endif /* _INTL */
+}
diff --git a/private/crt32/convert/sources b/private/crt32/convert/sources
new file mode 100644
index 000000000..15815f858
--- /dev/null
+++ b/private/crt32/convert/sources
@@ -0,0 +1,64 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=convert
+
+TARGETNAME=convert
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=_ctype.c \
+ _fptostr.c \
+ _mbslen.c \
+ _wctype.c \
+ atof.c \
+ atox.c \
+ fcvt.c \
+ gcvt.c \
+ isctype.c \
+ iswctype.c \
+ mblen.c \
+ mbstowcs.c \
+ mbtowc.c \
+ strtod.c \
+ strtol.c \
+ swab.c \
+ tolower.c \
+ toupper.c \
+ towlower.c \
+ towupper.c \
+ wcstod.c \
+ wcstol.c \
+ wcstombs.c \
+ wctomb.c \
+ wtox.c \
+ xtoa.c \
+ xtow.c
+
+ALPHA_SOURCES=strtoq.c
diff --git a/private/crt32/convert/strtod.c b/private/crt32/convert/strtod.c
new file mode 100644
index 000000000..68e3b5d76
--- /dev/null
+++ b/private/crt32/convert/strtod.c
@@ -0,0 +1,121 @@
+/***
+*strtod.c - convert string to floating point number
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert character string to floating point number
+*
+*Revision History:
+* 09-09-83 RKW Module created
+* 08-19-85 TDC changed to strtod
+* 04-13-87 JCR Added "const" to declaration
+* 04-20-87 BCM Added checks for negative overflow and for underflow
+* 11-09-87 BCM different interface under ifdef MTHREAD
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 02-22-88 JCR Added cast to nptr to get rid of cl const warning
+* 05-24-88 PHG Merged DLL and normal versions
+* 08-24-88 PHG No digits found => *endptr = nptr [ANSI]
+* Revised test order so invalid detection works always
+* 10-20-88 JCR Changed 'DOUBLE' to 'double' for 386
+* 11-20-89 JCR atof() is always _cdecl in 386 (not pascal)
+* 03-05-90 GJF Fixed calling type, added #include <cruntime.h>,
+* removed #include <register.h>, removed redundant
+* prototypes, removed some leftover 16-bit support and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 07-23-90 SBM Compiles cleanly with -W3 (added/removed appropriate
+* #includes)
+* 08-01-90 SBM Renamed <struct.h> to <fltintrn.h>
+* 09-27-90 GJF New-style function declarators.
+* 10-21-92 GJF Made char-to-int conversion unsigned.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <fltintrn.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+
+/***
+*double strtod(nptr, endptr) - convert string to double
+*
+*Purpose:
+* strtod recognizes an optional string of tabs and spaces,
+* then an optional sign, then a string of digits optionally
+* containing a decimal point, then an optional e or E followed
+* by an optionally signed integer, and converts all this to
+* to a floating point number. The first unrecognized
+* character ends the string, and is pointed to by endptr.
+*
+*Entry:
+* nptr - pointer to string to convert
+*
+*Exit:
+* returns value of character string
+* char **endptr - if not NULL, points to character which stopped
+* the scan
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+double _CRTAPI1 strtod (
+ const char *nptr,
+ REG2 char **endptr
+ )
+{
+
+#ifdef MTHREAD
+ struct _flt answerstruct;
+#endif
+
+ FLT answer;
+ double tmp;
+ unsigned int flags;
+ REG1 char *ptr = (char *) nptr;
+
+ /* scan past leading space/tab characters */
+
+ while ( isspace((int)(unsigned char)*ptr) )
+ ptr++;
+
+ /* let _fltin routine do the rest of the work */
+
+#ifdef MTHREAD
+ /* ok to take address of stack variable here; fltin2 knows to use ss */
+ answer = _fltin2( &answerstruct, ptr, strlen(ptr), 0, 0);
+#else
+ answer = _fltin(ptr, strlen(ptr), 0, 0);
+#endif
+
+ if ( endptr != NULL )
+ *endptr = (char *) ptr + answer->nbytes;
+
+ flags = answer->flags;
+ if ( flags & (512 | 64)) {
+ /* no digits found or invalid format:
+ ANSI says return 0.0, and *endptr = nptr */
+ tmp = 0.0;
+ if ( endptr != NULL )
+ *endptr = (char *) nptr;
+ }
+ else if ( flags & (128 | 1) ) {
+ if ( *ptr == '-' )
+ tmp = -HUGE_VAL; /* negative overflow */
+ else
+ tmp = HUGE_VAL; /* positive overflow */
+ errno = ERANGE;
+ }
+ else if ( flags & 256 ) {
+ tmp = 0.0; /* underflow */
+ errno = ERANGE;
+ }
+ else
+ tmp = answer->dval;
+
+ return(tmp);
+}
diff --git a/private/crt32/convert/strtol.c b/private/crt32/convert/strtol.c
new file mode 100644
index 000000000..d74bde7be
--- /dev/null
+++ b/private/crt32/convert/strtol.c
@@ -0,0 +1,227 @@
+/***
+*strtol.c - Contains C runtimes strtol and strtoul
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* strtol - convert ascii string to long signed integer
+* strtoul - convert ascii string to long unsigned integer
+*
+*Revision History:
+* 06-05-89 PHG Module created, based on strtol.asm
+* 03-06-90 GJF Fixed calling type, added #include <cruntime.h>
+* and fixed the copyright. Also, cleaned up the
+* formatting a bit.
+* 03-07-90 GJF Fixed compiler warnings (added const qualifier to
+* an arg type and local var type).
+* 03-23-90 GJF Made strtoxl() _CALLTYPE4.
+* 08-13-90 SBM Compiles cleanly with -W3
+* 09-27-90 GJF New-style function declarators.
+* 10-24-91 GJF Had to cast LONG_MAX to unsigned long in expr. to
+* mollify MIPS compiler.
+* 10-21-92 GJF Made char-to-int conversions unsigned.
+* 04-21-93 GJF Removed assumption that LONG_MIN == -LONG_MAX.
+* 05-10-93 GJF Fixed error check.
+* 05-20-93 GJF Nothing like taking ugly code and making prettier...
+* and wrong. Fixed bug introduced on 5-10.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+
+
+/***
+*strtol, strtoul(nptr,endptr,ibase) - Convert ascii string to long un/signed
+* int.
+*
+*Purpose:
+* Convert an ascii string to a long 32-bit value. The base
+* used for the caculations is supplied by the caller. The base
+* must be in the range 0, 2-36. If a base of 0 is supplied, the
+* ascii string must be examined to determine the base of the
+* number:
+* (a) First char = '0', second char = 'x' or 'X',
+* use base 16.
+* (b) First char = '0', use base 8
+* (c) First char in range '1' - '9', use base 10.
+*
+* If the 'endptr' value is non-NULL, then strtol/strtoul places
+* a pointer to the terminating character in this value.
+* See ANSI standard for details
+*
+*Entry:
+* nptr == NEAR/FAR pointer to the start of string.
+* endptr == NEAR/FAR pointer to the end of the string.
+* ibase == integer base to use for the calculations.
+*
+* string format: [whitespace] [sign] [0] [x] [digits/letters]
+*
+*Exit:
+* Good return:
+* result
+*
+* Overflow return:
+* strtol -- LONG_MAX or LONG_MIN
+* strtoul -- ULONG_MAX
+* strtol/strtoul -- errno == ERANGE
+*
+* No digits or bad base return:
+* 0
+* endptr = nptr*
+*
+*Exceptions:
+* None.
+*******************************************************************************/
+
+/* flag values */
+#define FL_UNSIGNED 1 /* strtoul called */
+#define FL_NEG 2 /* negative sign found */
+#define FL_OVERFLOW 4 /* overflow occured */
+#define FL_READDIGIT 8 /* we've read at least one correct digit */
+
+
+static unsigned long _CRTAPI3 strtoxl (
+ const char *nptr,
+ const char **endptr,
+ int ibase,
+ int flags
+ )
+{
+ const char *p;
+ char c;
+ unsigned long number;
+ unsigned digval;
+ unsigned long maxval;
+
+ p = nptr; /* p is our scanning pointer */
+ number = 0; /* start with zero */
+
+ c = *p++; /* read char */
+ while ( isspace((int)(unsigned char)c) )
+ c = *p++; /* skip whitespace */
+
+ if (c == '-') {
+ flags |= FL_NEG; /* remember minus sign */
+ c = *p++;
+ }
+ else if (c == '+')
+ c = *p++; /* skip sign */
+
+ if (ibase < 0 || ibase == 1 || ibase > 36) {
+ /* bad base! */
+ if (endptr)
+ /* store beginning of string in endptr */
+ *endptr = nptr;
+ return 0L; /* return 0 */
+ }
+ else if (ibase == 0) {
+ /* determine base free-lance, based on first two chars of
+ string */
+ if (c != '0')
+ ibase = 10;
+ else if (*p == 'x' || *p == 'X')
+ ibase = 16;
+ else
+ ibase = 8;
+ }
+
+ if (ibase == 16) {
+ /* we might have 0x in front of number; remove if there */
+ if (c == '0' && (*p == 'x' || *p == 'X')) {
+ ++p;
+ c = *p++; /* advance past prefix */
+ }
+ }
+
+ /* if our number exceeds this, we will overflow on multiply */
+ maxval = ULONG_MAX / ibase;
+
+
+ for (;;) { /* exit in middle of loop */
+ /* convert c to value */
+ if ( isdigit((int)(unsigned char)c) )
+ digval = c - '0';
+ else if ( isalpha((int)(unsigned char)c) )
+ digval = toupper(c) - 'A' + 10;
+ else
+ break;
+ if (digval >= (unsigned)ibase)
+ break; /* exit loop if bad digit found */
+
+ /* record the fact we have read one digit */
+ flags |= FL_READDIGIT;
+
+ /* we now need to compute number = number * base + digval,
+ but we need to know if overflow occured. This requires
+ a tricky pre-check. */
+
+ if (number < maxval || (number == maxval &&
+ (unsigned long)digval <= ULONG_MAX % ibase)) {
+ /* we won't overflow, go ahead and multiply */
+ number = number * ibase + digval;
+ }
+ else {
+ /* we would have overflowed -- set the overflow flag */
+ flags |= FL_OVERFLOW;
+ }
+
+ c = *p++; /* read next digit */
+ }
+
+ --p; /* point to place that stopped scan */
+
+ if (!(flags & FL_READDIGIT)) {
+ /* no number there; return 0 and point to beginning of
+ string */
+ if (endptr)
+ /* store beginning of string in endptr later on */
+ p = nptr;
+ number = 0L; /* return 0 */
+ }
+ else if ( (flags & FL_OVERFLOW) ||
+ ( !(flags & FL_UNSIGNED) &&
+ ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
+ ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
+ {
+ /* overflow or signed overflow occurred */
+ errno = ERANGE;
+ if ( flags & FL_UNSIGNED )
+ number = ULONG_MAX;
+ else if ( flags & FL_NEG )
+ number = (unsigned long)(-LONG_MIN);
+ else
+ number = LONG_MAX;
+ }
+
+ if (endptr != NULL)
+ /* store pointer to char that stopped the scan */
+ *endptr = p;
+
+ if (flags & FL_NEG)
+ /* negate result if there was a neg sign */
+ number = (unsigned long)(-(long)number);
+
+ return number; /* done. */
+}
+
+long _CRTAPI1 strtol (
+ const char *nptr,
+ char **endptr,
+ int ibase
+ )
+{
+ return (long) strtoxl(nptr, endptr, ibase, 0);
+}
+
+unsigned long _CRTAPI1 strtoul (
+ const char *nptr,
+ char **endptr,
+ int ibase
+ )
+{
+ return strtoxl(nptr, endptr, ibase, FL_UNSIGNED);
+}
diff --git a/private/crt32/convert/strtoq.c b/private/crt32/convert/strtoq.c
new file mode 100644
index 000000000..b0e370a1f
--- /dev/null
+++ b/private/crt32/convert/strtoq.c
@@ -0,0 +1,236 @@
+/***
+*strtoq.c - Contains C runtimes strtoq and strtouq
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+* Copyright (c) 1992, Digital Equipment Corporation.
+*
+*Purpose:
+* strtoq - convert ascii string to QUAD (signed quad) integer
+* strtouq - convert ascii string to UQUAD (unsigned quad) integer
+*
+*Revision History:
+* 06-05-89 PHG Module created, based on strtol.asm
+* 03-06-90 GJF Fixed calling type, added #include <cruntime.h>
+* and fixed the copyright. Also, cleaned up the
+* formatting a bit.
+* 03-07-90 GJF Fixed compiler warnings (added const qualifier to
+* an arg type and local var type).
+* 03-23-90 GJF Made strtoxl() _CALLTYPE4.
+* 08-13-90 SBM Compiles cleanly with -W3
+* 09-27-90 GJF New-style function declarators.
+* 10-24-91 GJF Had to cast LONG_MAX to unsigned long in expr. to
+* mollify MIPS compiler.
+* 08-28-92 TVB Created strtoq.c directly from strtol.c.
+* 10-21-92 GJF Made char-to-int conversions unsigned.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+
+#ifdef _ALPHA_
+
+#ifdef _MSC_VER
+typedef __int64 quad;
+typedef unsigned __int64 uquad;
+#else
+typedef long long quad;
+typedef unsigned long long uquad;
+#endif
+
+#define QUAD_MIN ((quad)-9223372036854775807) /* minimum (signed) quad value */
+#define QUAD_MAX ((quad) 9223372036854775807) /* maximum (signed) quad value */
+#define UQUAD_MAX ((uquad)0xffffffffffffffff) /* maximum unsigned quad value */
+
+#endif
+
+/***
+*strtoq, strtouq(nptr,endptr,ibase) - Convert ascii string to QUAD un/signed
+* int.
+*
+*Purpose:
+* Convert an ascii string to a 64-bit quad value. The base
+* used for the caculations is supplied by the caller. The base
+* must be in the range 0, 2-36. If a base of 0 is supplied, the
+* ascii string must be examined to determine the base of the
+* number:
+* (a) First char = '0', second char = 'x' or 'X',
+* use base 16.
+* (b) First char = '0', use base 8
+* (c) First char in range '1' - '9', use base 10.
+*
+* If the 'endptr' value is non-NULL, then strtoq/strtouq places
+* a pointer to the terminating character in this value.
+* See ANSI standard for details
+*
+*Entry:
+* nptr == NEAR/FAR pointer to the start of string.
+* endptr == NEAR/FAR pointer to the end of the string.
+* ibase == integer base to use for the calculations.
+*
+* string format: [whitespace] [sign] [0] [x] [digits/letters]
+*
+*Exit:
+* Good return:
+* result
+*
+* Overflow return:
+* strtoq -- QUAD_MAX or QUAD_MIN
+* strtouq -- UQUAD_MAX
+* strtoq/strtouq -- errno == ERANGE
+*
+* No digits or bad base return:
+* 0
+* endptr = nptr*
+*
+*Exceptions:
+* None.
+*******************************************************************************/
+
+/* flag values */
+#define FL_UNSIGNED 1 /* strtouq called */
+#define FL_NEG 2 /* negative sign found */
+#define FL_OVERFLOW 4 /* overflow occured */
+#define FL_READDIGIT 8 /* we've read at least one correct digit */
+
+
+static uquad _CRTAPI3 strtoxq (
+ const char *nptr,
+ const char **endptr,
+ int ibase,
+ int flags
+ )
+{
+ const char *p;
+ char c;
+ uquad number;
+ unsigned digval;
+ uquad maxval;
+
+ p = nptr; /* p is our scanning pointer */
+ number = 0; /* start with zero */
+
+ c = *p++; /* read char */
+ while ( isspace((int)(unsigned char)c) )
+ c = *p++; /* skip whitespace */
+
+ if (c == '-') {
+ flags |= FL_NEG; /* remember minus sign */
+ c = *p++;
+ }
+ else if (c == '+')
+ c = *p++; /* skip sign */
+
+ if (ibase < 0 || ibase == 1 || ibase > 36) {
+ /* bad base! */
+ if (endptr)
+ /* store beginning of string in endptr */
+ *endptr = nptr;
+ return 0L; /* return 0 */
+ }
+ else if (ibase == 0) {
+ /* determine base free-lance, based on first two chars of
+ string */
+ if (c != '0')
+ ibase = 10;
+ else if (*p == 'x' || *p == 'X')
+ ibase = 16;
+ else
+ ibase = 8;
+ }
+
+ if (ibase == 16) {
+ /* we might have 0x in front of number; remove if there */
+ if (c == '0' && (*p == 'x' || *p == 'X')) {
+ ++p;
+ c = *p++; /* advance past prefix */
+ }
+ }
+
+ /* if our number exceeds this, we will overflow on multiply */
+ maxval = UQUAD_MAX / ibase;
+
+
+ for (;;) { /* exit in middle of loop */
+ /* convert c to value */
+ if ( isdigit((int)(unsigned char)c) )
+ digval = c - '0';
+ else if ( isalpha((int)(unsigned char)c) )
+ digval = toupper(c) - 'A' + 10;
+ else
+ break;
+ if (digval >= (unsigned)ibase)
+ break; /* exit loop if bad digit found */
+
+ /* record the fact we have read one digit */
+ flags |= FL_READDIGIT;
+
+ /* we now need to compute number = number * base + digval,
+ but we need to know if overflow occured. This requires
+ a tricky pre-check. */
+
+ if (number < maxval || (number == maxval &&
+ (uquad)digval <= UQUAD_MAX % ibase)) {
+ /* we won't overflow, go ahead and multiply */
+ number = number * ibase + digval;
+ }
+ else {
+ /* we would have overflowed -- set the overflow flag */
+ flags |= FL_OVERFLOW;
+ }
+
+ c = *p++; /* read next digit */
+ }
+
+ --p; /* point to place that stopped scan */
+
+ if (!(flags & FL_READDIGIT)) {
+ /* no number there; return 0 and point to beginning of
+ string */
+ if (endptr)
+ /* store beginning of string in endptr later on */
+ p = nptr;
+ number = 0L; /* return 0 */
+ }
+ else if ((flags & FL_OVERFLOW) || (!(flags & FL_UNSIGNED) &&
+ (number & ((uquad)QUAD_MAX+1)))) {
+ /* overflow occurred or signed overflow occurred */
+ errno = ERANGE;
+ if (flags & FL_UNSIGNED)
+ number = UQUAD_MAX;
+ else
+ /* set error code, will be negated if necc. */
+ number = QUAD_MAX;
+ }
+
+ if (endptr != NULL)
+ /* store pointer to char that stopped the scan */
+ *endptr = p;
+
+ if (flags & FL_NEG)
+ /* negate result if there was a neg sign */
+ number = (uquad)(-(quad)number);
+
+ return number; /* done. */
+}
+
+quad _CRTAPI1 strtoq (
+ const char *nptr,
+ char **endptr,
+ int ibase
+ )
+{
+ return (quad) strtoxq(nptr, endptr, ibase, 0);
+}
+
+uquad _CRTAPI1 strtouq (
+ const char *nptr,
+ char **endptr,
+ int ibase
+ )
+{
+ return strtoxq(nptr, endptr, ibase, FL_UNSIGNED);
+}
diff --git a/private/crt32/convert/swab.c b/private/crt32/convert/swab.c
new file mode 100644
index 000000000..1b8fdbf4a
--- /dev/null
+++ b/private/crt32/convert/swab.c
@@ -0,0 +1,58 @@
+/***
+*swab.c - block copy, while swapping even/odd bytes
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains the routine _swab() which swaps the odd/even
+* bytes of words during a block copy.
+*
+*Revision History:
+* 06-02-89 PHG module created, based on asm version
+* 03-06-90 GJF Fixed calling type, added #include <cruntime.h> and
+* fixed copyright. Also, cleaned up the formatting a
+* bit.
+* 09-27-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+
+/***
+*void _swab(srcptr, dstptr, nbytes) - swap ODD/EVEN bytes during word move
+*
+*Purpose:
+* This routine copys a block of words and swaps the odd and even
+* bytes. nbytes must be > 0, otherwise nothing is copied. If
+* nbytes is odd, then only (nbytes-1) bytes are copied.
+*
+*Entry:
+* srcptr = pointer to the source block
+* dstptr = pointer to the destination block
+* nbytes = number of bytes to swap
+*
+*Returns:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _swab (
+ char *src,
+ char *dest,
+ int nbytes
+ )
+{
+ char b1, b2;
+
+ while (nbytes > 1) {
+ b1 = *src++;
+ b2 = *src++;
+ *dest++ = b2;
+ *dest++ = b1;
+ nbytes -= 2;
+ }
+}
diff --git a/private/crt32/convert/testconv.c b/private/crt32/convert/testconv.c
new file mode 100644
index 000000000..6749cce26
--- /dev/null
+++ b/private/crt32/convert/testconv.c
@@ -0,0 +1,152 @@
+/* incomplete test suite for convert functions
+
+ Current functions tested:
+ all isxxxxx functions
+ toupper
+ tolower
+ atoi
+ atol
+ strtol
+ strtoul
+ swab
+ itoa
+ ltoa
+ ultoa
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <errno.h>
+
+fail(int n)
+{
+ printf("Test #%d failed.\n", n);
+}
+
+main()
+{
+ char s[512];
+ char t[512];
+ char *p;
+
+ /* test isxxxx functions */
+ if (!iscntrl(0x7)) fail(1);
+ if (iscntrl('c')) fail(2);
+ if (!isdigit('0')) fail(3);
+ if (isdigit('A')) fail(4);
+ if (!isgraph(';')) fail(5);
+ if (isgraph(' ')) fail(6);
+ if (!islower('f')) fail(7);
+ if (islower('F')) fail(8);
+ if (!isprint('S')) fail(9);
+ if (isprint('\v')) fail(10);
+ if (!ispunct('.')) fail(11);
+ if (ispunct('A')) fail(12);
+ if (!isspace('\v')) fail(13);
+ if (isspace('D')) fail(14);
+ if (!isupper('D')) fail(15);
+ if (isupper('z')) fail(16);
+ if (!isxdigit('D')) fail(17);
+ if (isxdigit('G')) fail(18);
+ if (!isalnum('7')) fail(19);
+ if (isalnum(';')) fail(20);
+ if (!isalpha('j')) fail(21);
+ if (isalpha('$')) fail(22);
+ if (!isascii(0x3)) fail(23);
+ if (isascii(234)) fail(24);
+ if (!iscsym('d')) fail(25);
+ if (iscsym('$')) fail(26);
+ if (!iscsymf('A')) fail(27);
+ if (iscsymf('5')) fail(28);
+
+
+ /* test toupper and tolower */
+ if (tolower('C') != 'c') fail(29);
+ if (tolower('d') != 'd') fail(30);
+ if (tolower('$') != '$') fail(31);
+ if (toupper('q') != 'Q') fail(32);
+ if (toupper('A') != 'A') fail(33);
+ if (toupper(';') != ';') fail(34);
+
+
+ /* test atol/atoi */
+ if (atol("-123") != -123) fail(35);
+ if (atoi("32767") != 32767) fail(36);
+ if (atoi("-32767") != -32767) fail(36);
+ if (atol("0") != 0) fail(37);
+ if (atol("2147483647") != 2147483647) fail(38);
+ if (atol("-2147483647") != -2147483647) fail(39);
+ if (atol("123456") != 123456) fail(40);
+ if (atol("-123456") != -123456) fail(41);
+
+ /* test strtol */
+ if (strtol("-123", NULL, 10) != -123) fail(42);
+ if (strtol(" 2147483646", NULL, 10) != 2147483646) fail(43);
+ if (strtol("-2147483646$$", NULL, 10) != -2147483646) fail(44);
+ if (strtol(" 2147483648x", NULL, 10) != LONG_MAX) fail(45);
+ if (strtol(" -2147483648", NULL, 10) != LONG_MIN) fail(46);
+ if (strtol("0", NULL, 10) != 0) fail(47);
+ if (strtol("981235b", NULL, 10) != 981235) fail(48);
+ if (strtol(" -1234567a", NULL, 10) != -1234567) fail(49);
+ if (strtol("FFDE", NULL, 16) != 0xFFDE) fail(50);
+ if (strtol("7FFFFFFE", NULL, 16) != 0x7FFFFFFE) fail(51);
+ if (strtol("-0x45", NULL, 16) != -0x45) fail(52);
+ if (strtol("23478", NULL, 8) != 02347) fail(53);
+ if (strtol(" -0x123D", NULL, 0) != -0x123d) fail(54);
+ if (strtol(" 01238", NULL, 0) != 0123) fail(55);
+ if (strtol(" -678899", NULL, 0) != -678899) fail(56);
+
+ errno = 0;
+ strtol("2147483647", NULL, 10);
+ if (errno != 0) fail(57);
+ errno = 0;
+ strtol("2147483648", NULL, 10);
+ if (errno != ERANGE) fail(58);
+ errno = 0;
+ strtol("63234283743", NULL, 10);
+ if (errno != ERANGE) fail(59);
+ strcpy(s, " 8983");
+ strtol(s, &p, 8);
+ if (s != p) fail(60);
+ strcpy(s, "12345678901234567890XX");
+ strtol(s, &p, 0);
+ if (p != s+20) fail(61);
+ strcpy(s, " 111");
+ strtol(s, &p, 1);
+ if (p != s) fail(62);
+
+ errno = 0;
+ if (strtoul("4294967295", NULL, 10) != ULONG_MAX) fail(63);
+ if (errno != 0) fail(64);
+ errno = 0;
+ strtoul("4294967296", NULL, 10);
+ if (errno != ERANGE) fail(65);
+ errno = 0;
+ strtoul("63234283743", NULL, 10);
+ if (errno != ERANGE) fail(66);
+
+ /* test swab */
+ strcpy(s, "abcdefghijklmn");
+ swab(s, t, 14);
+ if (strcmp(t, "badcfehgjilknm") != 0) fail(67);
+ strcpy(t, s);
+ swab(s, t, 7);
+ if (strcmp(t, "badcfeghijklmn") != 0) fail(68);
+ strcpy(t, s);
+ swab(s, t, -5);
+ if (strcmp(s, t) != 0) fail(69);
+
+ /* test itoa/ltoa/ultoa */
+ if (strcmp(itoa(345, s, 10), "345") != 0) fail(70);
+ if (strcmp(itoa(-345, s, 10), "-345") != 0) fail(71);
+ if (strcmp(itoa(33, s, 36), "x") != 0) fail(72);
+ if (strcmp(itoa(65535U, s, 16), "ffff") != 0) fail(73);
+ if (strcmp(ltoa(123457, s, 10), "123457") != 0) fail(74);
+ if (strcmp(ltoa(-123457, s, 10), "-123457") != 0) fail(75);
+ if (strcmp(ltoa(076512L, s, 8), "76512") != 0) fail(76);
+ if (strcmp(ltoa(-1L, s, 10), "-1") != 0) fail(77);
+ if (strcmp(ltoa(-1L, s, 16), "ffffffff") != 0) fail(78);
+ if (strcmp(ultoa(-1L, s, 10), "4294967295") != 0) fail(79);
+
+}
diff --git a/private/crt32/convert/tolower.c b/private/crt32/convert/tolower.c
new file mode 100644
index 000000000..604026f4c
--- /dev/null
+++ b/private/crt32/convert/tolower.c
@@ -0,0 +1,155 @@
+/***
+*tolower.c - convert character to lower case
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines function versions of _tolower() and tolower().
+*
+*Revision History:
+* 11-09-84 DFW created
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 02-23-89 GJF Added function version of _tolower and cleaned up.
+* 03-26-89 GJF Migrated to 386 tree
+* 03-06-90 GJF Fixed calling type, added #include <cruntime.h> and
+* fixed copyright.
+* 09-27-90 GJF New-style function declarators.
+* 10-11-91 ETC Locale support for tolower under _INTL switch.
+* 12-10-91 ETC Updated nlsapi; added multithread.
+* 12-17-92 KRS Updated and optimized for latest NLSAPI. Bug-fixes.
+* 01-19-93 CFW Fixed typo.
+* 03-25-93 CFW _tolower now defined when _INTL.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 09-15-93 CFW Change buffer to unsigned char to fix nasty cast bug.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+#include <stddef.h>
+#ifdef _INTL
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+#endif
+
+/* remove macro defintions of _tolower() and tolower()
+ */
+#undef _tolower
+#undef tolower
+
+/* define function-like macro equivalent to _tolower()
+ */
+#define mklower(c) ( (c)-'A'+'a' )
+
+/***
+*int _tolower(c) - convert character to lower case
+*
+*Purpose:
+* _tolower() is simply a function version of the macro of the same name.
+*
+*Entry:
+* c - int value of character to be converted
+*
+*Exit:
+* returns int value of lower case representation of c
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _tolower (
+ int c
+ )
+{
+ return(mklower(c));
+}
+
+/***
+*int tolower(c) - convert character to lower case
+*
+*Purpose:
+* tolower() is simply a function version of the macro of the same name.
+*
+*Entry:
+* c - int value of character to be converted
+*
+*Exit:
+* if c is an upper case letter, returns int value of lower case
+* representation of c. otherwise, it returns c.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+int _CALLTYPE1 tolower (
+ int c
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ wchar_t widechar1[2], widechar2[2];
+ int size;
+ unsigned char buffer[3];
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP)) {
+ if (isupper(c))
+ c = c + ('a' - 'A');
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ /* if checking case of c does not require API call, do it */
+ if (c < 256) {
+ if (!isupper(c)) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+ }
+
+ /* convert c to wide char */
+ if (isleadbyte(c>>8 & 0xff))
+ {
+ buffer[0] = (c>>8 & 0xff); /* put lead-byte at start of str */
+ buffer[1] = (unsigned char)c;
+ buffer[2] = 0;
+ }
+ else
+ {
+ buffer[0] = (unsigned char)c;
+ buffer[1] = 0;
+ }
+ if (!(size=MultiByteToWideChar(_lc_codepage,MB_PRECOMPOSED,
+ buffer, -1, widechar1, 2))) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ /* convert wide char to uppercase */
+ if (!(size=LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_LOWERCASE,
+ widechar1, size, widechar2, 2))) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ /* convert wide char back to multibyte */
+ if (!(size=WideCharToMultiByte(_lc_codepage,(WC_COMPOSITECHECK|WC_DISCARDNS),
+ widechar2, size, buffer, 2, NULL, NULL))) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ _munlock (_LC_CTYPE_LOCK);
+
+ /* construct integer return value */
+ if (size == 1)
+ return ((int)buffer[0]);
+ else
+ return ((int)buffer[0] | ((int)buffer[1] << 8));
+#else
+ return(isupper(c) ? mklower(c) : c);
+#endif /* _INTL */
+}
diff --git a/private/crt32/convert/toupper.c b/private/crt32/convert/toupper.c
new file mode 100644
index 000000000..4dd0e8176
--- /dev/null
+++ b/private/crt32/convert/toupper.c
@@ -0,0 +1,189 @@
+/***
+*toupper.c - convert character to uppercase
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines function versions of _toupper() and toupper().
+*
+*Revision History:
+* 11-09-84 DFW created
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 02-23-89 GJF Added function version of _toupper and cleaned up.
+* 03-26-89 GJF Migrated to 386 tree
+* 03-06-90 GJF Fixed calling type, added #include <cruntime.h> and
+* fixed copyright.
+* 09-27-90 GJF New-style function declarators.
+* 10-11-91 ETC Locale support for toupper under _INTL switch.
+* 12-10-91 ETC Updated nlsapi; added multithread.
+* 12-17-92 KRS Updated and optimized for latest NLSAPI. Bug-fixes.
+* 01-19-93 CFW Fixed typo.
+* 03-25-93 CFW _toupper now defined when _INTL.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 09-15-93 CFW Change buffer to unsigned char to fix nasty cast bug.
+* 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
+*
+*******************************************************************************/
+
+#ifdef _NTSUBSET_
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+#include <cruntime.h>
+#include <ctype.h>
+#include <stddef.h>
+#ifdef _INTL
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+#endif
+
+/* remove macro definitions of _toupper() and toupper()
+ */
+#undef _toupper
+#undef toupper
+
+/* define function-like macro equivalent to _toupper()
+ */
+#define mkupper(c) ( (c)-'a'+'A' )
+
+/***
+*int _toupper(c) - convert character to uppercase
+*
+*Purpose:
+* _toupper() is simply a function version of the macro of the same name.
+*
+*Entry:
+* c - int value of character to be converted
+*
+*Exit:
+* returns int value of uppercase representation of c
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _toupper (
+ int c
+ )
+{
+ return(mkupper(c));
+}
+
+
+/***
+*int toupper(c) - convert character to uppercase
+*
+*Purpose:
+* toupper() is simply a function version of the macro of the same name.
+*
+*Entry:
+* c - int value of character to be converted
+*
+*Exit:
+* if c is a lower case letter, returns int value of uppercase
+* representation of c. otherwise, it returns c.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+int _CALLTYPE1 toupper (
+ int c
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ wchar_t widechar1[2], widechar2[2];
+ int size;
+ unsigned char buffer[3];
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP)) {
+ if (islower(c))
+ c = c - ('a' - 'A');
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ /* if checking case of c does not require API call, do it */
+ if (c < 256) {
+ if (!islower(c)) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+ }
+
+ /* convert c to wide char */
+ if (isleadbyte(c>>8 & 0xff))
+ {
+ buffer[0] = (c>>8 & 0xff); /* put lead-byte at start of str */
+ buffer[1] = (unsigned char)c;
+ buffer[2] = 0;
+ }
+ else
+ {
+ buffer[0] = (unsigned char)c;
+ buffer[1] = 0;
+ }
+ if (!(size=MultiByteToWideChar(_lc_codepage,MB_PRECOMPOSED,
+ buffer, -1, widechar1, 2))) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ /* convert wide char to uppercase */
+ if (!(size=LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_UPPERCASE,
+ widechar1, size, widechar2, 2))) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ /* convert wide char back to multibyte */
+ if (!(size=WideCharToMultiByte(_lc_codepage,(WC_COMPOSITECHECK|WC_DISCARDNS),
+ widechar2, size, buffer, 2, NULL, NULL))) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ _munlock (_LC_CTYPE_LOCK);
+
+ /* construct integer return value */
+ if (size == 1)
+ return ((int)buffer[0]);
+ else
+ return ((int)buffer[0] | ((int)buffer[1] << 8));
+#else
+#ifdef _NTSUBSET_
+ {
+ NTSTATUS Status;
+ char *s = &c;
+ WCHAR Unicode;
+ ULONG UnicodeSize;
+ ULONG MultiSize;
+ UCHAR MultiByte[2];
+
+ Unicode = RtlAnsiCharToUnicodeChar( &s );
+ Status = RtlUpcaseUnicodeToMultiByteN( MultiByte,
+ sizeof( MultiByte ),
+ &MultiSize,
+ &Unicode,
+ sizeof( Unicode )
+ );
+ if (!NT_SUCCESS( Status ))
+ return c;
+ else
+ if (MultiSize == 1)
+ return ((int)MultiByte[0]);
+ else
+ return ((int)MultiByte[0] | ((int)MultiByte[1] << 8));
+
+ }
+#else
+ return(islower(c) ? mkupper(c) : c);
+#endif
+#endif /* _INTL */
+}
diff --git a/private/crt32/convert/towlower.c b/private/crt32/convert/towlower.c
new file mode 100644
index 000000000..1f4c2abb2
--- /dev/null
+++ b/private/crt32/convert/towlower.c
@@ -0,0 +1,84 @@
+/***
+*towlower.c - convert wide character to lower case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines towlower().
+*
+*Revision History:
+* 10-11-91 ETC Created.
+* 12-10-91 ETC Updated nlsapi; added multithread.
+* 04-06-92 KRS Make work without _INTL also.
+* 01-19-93 CFW Changed LCMapString to LCMapStringW.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 06-11-93 CFW Fix error handling bug.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <locale.h>
+#ifdef _INTL
+#include <setlocal.h>
+#include <os2dll.h>
+#endif
+
+/***
+*wchar_t towlower(c) - convert wide character to lower case
+*
+*Purpose:
+* towlower() returns the lowercase equivalent of its argument
+*
+*Entry:
+* c - wchar_t value of character to be converted
+*
+*Exit:
+* if c is an upper case letter, returns wchar_t value of lower case
+* representation of c. otherwise, it returns c.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t _CALLTYPE1 towlower (
+ wchar_t c
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ wchar_t widechar;
+
+ if (c == WEOF)
+ return c;
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) {
+ if (iswupper(c))
+ c = c - L'A' + L'a';
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ /* if checking case of c does not require API call, do it */
+ if (c < 256) {
+ if (!iswupper(c)) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+ }
+
+ /* convert wide char to lowercase */
+ if (LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_LOWERCASE,
+ (LPCWSTR)&c, 1, (LPWSTR)&widechar, 1) == 0) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ _munlock (_LC_CTYPE_LOCK);
+ return widechar;
+#else
+ return (iswupper(c) ? (c + (wchar_t)(L'a' - L'A')) : c);
+#endif /* _INTL */
+}
diff --git a/private/crt32/convert/towupper.c b/private/crt32/convert/towupper.c
new file mode 100644
index 000000000..177da7e07
--- /dev/null
+++ b/private/crt32/convert/towupper.c
@@ -0,0 +1,94 @@
+/***
+*towupper.c - convert wide character to upper case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines towupper().
+*
+*Revision History:
+* 10-11-91 ETC Created.
+* 12-10-91 ETC Updated nlsapi; added multithread.
+* 04-06-92 KRS Make work without _INTL also.
+* 01-19-93 CFW Changed LCMapString to LCMapStringW.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 06-11-93 CFW Fix error handling bug.
+* 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
+*
+*******************************************************************************/
+
+#ifdef _NTSUBSET_
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+#include <cruntime.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <locale.h>
+#ifdef _INTL
+#include <setlocal.h>
+#include <os2dll.h>
+#endif
+
+/***
+*wchar_t towupper(c) - convert wide character to upper case
+*
+*Purpose:
+* towupper() returns the uppercase equivalent of its argument
+*
+*Entry:
+* c - wchar_t value of character to be converted
+*
+*Exit:
+* if c is a lower case letter, returns wchar_t value of upper case
+* representation of c. otherwise, it returns c.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t _CALLTYPE1 towupper (
+ wchar_t c
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ wchar_t widechar;
+
+ if (c == WEOF)
+ return c;
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) {
+ if (iswlower(c))
+ c = c - L'a' + L'A';
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ /* if checking case of c does not require API call, do it */
+ if (c < 256) {
+ if (!iswlower(c)) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+ }
+
+ /* convert wide char to uppercase */
+ if (LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_UPPERCASE,
+ (LPCWSTR)&c, 1, (LPWSTR)&widechar, 1) == 0) {
+ _munlock (_LC_CTYPE_LOCK);
+ return c;
+ }
+
+ _munlock (_LC_CTYPE_LOCK);
+ return widechar;
+#else
+#ifdef _NTSUBSET_
+ return RtlUpcaseUnicodeChar( c );
+#else
+ return (iswlower(c) ? (c - (wchar_t)(L'a' - L'A')) : c);
+#endif
+#endif /* _INTL */
+}
diff --git a/private/crt32/convert/wcstod.c b/private/crt32/convert/wcstod.c
new file mode 100644
index 000000000..18db8b193
--- /dev/null
+++ b/private/crt32/convert/wcstod.c
@@ -0,0 +1,115 @@
+/***
+*wcstod.c - convert wide char string to floating point number
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert character string to floating point number
+*
+*Revision History:
+* 06-15-92 KRS Created from strtod.c.
+* 11-06-92 KRS Fix bugs in wctomb() loop.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <fltintrn.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+
+/***
+*double wcstod(nptr, endptr) - convert wide string to double
+*
+*Purpose:
+* wcstod recognizes an optional string of tabs and spaces,
+* then an optional sign, then a string of digits optionally
+* containing a decimal point, then an optional e or E followed
+* by an optionally signed integer, and converts all this to
+* to a floating point number. The first unrecognized
+* character ends the string, and is pointed to by endptr.
+*
+*Entry:
+* nptr - pointer to wide string to convert
+*
+*Exit:
+* returns value of wide character string
+* wchar_t **endptr - if not NULL, points to character which stopped
+* the scan
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+double _CALLTYPE1 wcstod (
+ const wchar_t *nptr,
+ REG2 wchar_t **endptr
+ )
+{
+
+#ifdef MTHREAD
+ struct _flt answerstruct;
+#endif
+
+ FLT answer;
+ double tmp;
+ unsigned int flags;
+ REG1 wchar_t *ptr = (wchar_t *) nptr;
+ char * cptr;
+ int retval, len;
+ int clen = 0;
+
+ /* scan past leading space/tab characters */
+
+ while (iswspace(*ptr))
+ ptr++;
+
+ cptr = (char *)malloc((wcslen(ptr)+1) * sizeof(wchar_t));
+ // UNDONE: check for errors
+ for (len = 0; ptr[len]; len++)
+ {
+ if ((retval = wctomb(cptr+len,ptr[len]))<=0)
+ break;
+ clen += retval;
+ }
+ cptr[clen++] = '\0';
+
+ /* let _fltin routine do the rest of the work */
+
+#ifdef MTHREAD
+ /* ok to take address of stack variable here; fltin2 knows to use ss */
+ answer = _fltin2( &answerstruct, cptr, clen, 0, 0);
+#else
+ answer = _fltin(cptr, clen, 0, 0);
+#endif
+
+ if ( endptr != NULL )
+ *endptr = (wchar_t *) ptr + answer->nbytes;
+ /* UNDONE: assumes no multi-byte chars in string */
+
+ flags = answer->flags;
+ if ( flags & (512 | 64)) {
+ /* no digits found or invalid format:
+ ANSI says return 0.0, and *endptr = nptr */
+ tmp = 0.0;
+ if ( endptr != NULL )
+ *endptr = (wchar_t *) nptr;
+ }
+ else if ( flags & (128 | 1) ) {
+ if ( *ptr == '-' )
+ tmp = -HUGE_VAL; /* negative overflow */
+ else
+ tmp = HUGE_VAL; /* positive overflow */
+ errno = ERANGE;
+ }
+ else if ( flags & 256 ) {
+ tmp = 0.0; /* underflow */
+ errno = ERANGE;
+ }
+ else
+ tmp = answer->dval;
+
+ return(tmp);
+}
diff --git a/private/crt32/convert/wcstol.c b/private/crt32/convert/wcstol.c
new file mode 100644
index 000000000..6d3c3d201
--- /dev/null
+++ b/private/crt32/convert/wcstol.c
@@ -0,0 +1,215 @@
+/***
+*wcstol.c - Contains C runtimes wcstol and wcstoul
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* wcstol - convert wchar_t string to long signed integer
+* wcstoul - convert wchar_t string to long unsigned integer
+*
+*Revision History:
+* 06-15-92 KRS Module created, based on strtol.c
+* 04-21-93 GJF Removed assumption that LONG_MIN == -LONG_MAX.
+* 05-10-93 GJF Fixed error check.
+* 05-20-93 GJF Nothing like taking ugly code and making prettier...
+* and wrong. Fixed bug introduced on 5-10.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+
+/***
+*wcstol, wcstoul(nptr,endptr,ibase) - Convert ascii string to long un/signed
+* int.
+*
+*Purpose:
+* Convert an ascii string to a long 32-bit value. The base
+* used for the caculations is supplied by the caller. The base
+* must be in the range 0, 2-36. If a base of 0 is supplied, the
+* ascii string must be examined to determine the base of the
+* number:
+* (a) First char = '0', second char = 'x' or 'X',
+* use base 16.
+* (b) First char = '0', use base 8
+* (c) First char in range '1' - '9', use base 10.
+*
+* If the 'endptr' value is non-NULL, then wcstol/wcstoul places
+* a pointer to the terminating character in this value.
+* See ANSI standard for details
+*
+*Entry:
+* nptr == NEAR/FAR pointer to the start of string.
+* endptr == NEAR/FAR pointer to the end of the string.
+* ibase == integer base to use for the calculations.
+*
+* string format: [whitespace] [sign] [0] [x] [digits/letters]
+*
+*Exit:
+* Good return:
+* result
+*
+* Overflow return:
+* wcstol -- LONG_MAX or LONG_MIN
+* wcstoul -- ULONG_MAX
+* wcstol/wcstoul -- errno == ERANGE
+*
+* No digits or bad base return:
+* 0
+* endptr = nptr*
+*
+*Exceptions:
+* None.
+*******************************************************************************/
+
+/* flag values */
+#define FL_UNSIGNED 1 /* wcstoul called */
+#define FL_NEG 2 /* negative sign found */
+#define FL_OVERFLOW 4 /* overflow occured */
+#define FL_READDIGIT 8 /* we've read at least one correct digit */
+
+
+static unsigned long _CRTAPI3 wcstoxl (
+ const wchar_t *nptr,
+ const wchar_t **endptr,
+ int ibase,
+ int flags
+ )
+{
+ const wchar_t *p;
+ wchar_t c;
+ unsigned long number;
+ unsigned digval;
+ unsigned long maxval;
+
+ p = nptr; /* p is our scanning pointer */
+ number = 0; /* start with zero */
+
+ c = *p++; /* read char */
+ while (iswspace(c))
+ c = *p++; /* skip whitespace */
+
+ if (c == '-') {
+ flags |= FL_NEG; /* remember minus sign */
+ c = *p++;
+ }
+ else if (c == '+')
+ c = *p++; /* skip sign */
+
+ if (ibase < 0 || ibase == 1 || ibase > 36) {
+ /* bad base! */
+ if (endptr)
+ /* store beginning of string in endptr */
+ *endptr = nptr;
+ return 0L; /* return 0 */
+ }
+ else if (ibase == 0) {
+ /* determine base free-lance, based on first two chars of
+ string */
+ if (c != L'0')
+ ibase = 10;
+ else if (*p == L'x' || *p == L'X')
+ ibase = 16;
+ else
+ ibase = 8;
+ }
+
+ if (ibase == 16) {
+ /* we might have 0x in front of number; remove if there */
+ if (c == L'0' && (*p == L'x' || *p == L'X')) {
+ ++p;
+ c = *p++; /* advance past prefix */
+ }
+ }
+
+ /* if our number exceeds this, we will overflow on multiply */
+ maxval = ULONG_MAX / ibase;
+
+
+ for (;;) { /* exit in middle of loop */
+ /* convert c to value */
+ if (iswdigit(c))
+ digval = c - L'0';
+ else if (iswalpha(c))
+ digval = towupper(c) - L'A' + 10;
+ else
+ break;
+ if (digval >= (unsigned)ibase)
+ break; /* exit loop if bad digit found */
+
+ /* record the fact we have read one digit */
+ flags |= FL_READDIGIT;
+
+ /* we now need to compute number = number * base + digval,
+ but we need to know if overflow occured. This requires
+ a tricky pre-check. */
+
+ if (number < maxval || (number == maxval &&
+ (unsigned long)digval <= ULONG_MAX % ibase)) {
+ /* we won't overflow, go ahead and multiply */
+ number = number * ibase + digval;
+ }
+ else {
+ /* we would have overflowed -- set the overflow flag */
+ flags |= FL_OVERFLOW;
+ }
+
+ c = *p++; /* read next digit */
+ }
+
+ --p; /* point to place that stopped scan */
+
+ if (!(flags & FL_READDIGIT)) {
+ /* no number there; return 0 and point to beginning of
+ string */
+ if (endptr)
+ /* store beginning of string in endptr later on */
+ p = nptr;
+ number = 0L; /* return 0 */
+ }
+ else if ( (flags & FL_OVERFLOW) ||
+ ( !(flags & FL_UNSIGNED) &&
+ ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
+ ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
+ {
+ /* overflow or signed overflow occurred */
+ errno = ERANGE;
+ if ( flags & FL_UNSIGNED )
+ number = ULONG_MAX;
+ else if ( flags & FL_NEG )
+ number = (unsigned long)(-LONG_MIN);
+ else
+ number = LONG_MAX;
+ }
+
+ if (endptr != NULL)
+ /* store pointer to char that stopped the scan */
+ *endptr = p;
+
+ if (flags & FL_NEG)
+ /* negate result if there was a neg sign */
+ number = (unsigned long)(-(long)number);
+
+ return number; /* done. */
+}
+
+long _CRTAPI1 wcstol (
+ const wchar_t *nptr,
+ wchar_t **endptr,
+ int ibase
+ )
+{
+ return (long) wcstoxl(nptr, endptr, ibase, 0);
+}
+
+unsigned long _CRTAPI1 wcstoul (
+ const wchar_t *nptr,
+ wchar_t **endptr,
+ int ibase
+ )
+{
+ return wcstoxl(nptr, endptr, ibase, FL_UNSIGNED);
+}
diff --git a/private/crt32/convert/wcstombs.c b/private/crt32/convert/wcstombs.c
new file mode 100644
index 000000000..2b7f97194
--- /dev/null
+++ b/private/crt32/convert/wcstombs.c
@@ -0,0 +1,213 @@
+/***
+*wcstombs.c - Convert wide char string to multibyte char string.
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert a wide char string into the equivalent multibyte char string.
+*
+*Revision History:
+* 08-24-90 KRS Module created.
+* 01-14-91 KRS Added _WINSTATIC for Windows DLL. Fix wctomb() call.
+* 03-18-91 KRS Fix check for NUL.
+* 03-20-91 KRS Ported from 16-bit tree.
+* 10-16-91 ETC Locale support under _INTL switch.
+* 12-09-91 ETC Updated nlsapi; added multithread.
+* 08-20-92 KRS Activated NLSAPI support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 01-06-93 CFW Added (count < n) to outer loop - avoid bad wctomb calls
+* 01-07-93 KRS Major code cleanup. Fix error return, comments.
+* 05-03-93 CFW Return pointer == NULL, return size, plus massive cleanup.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
+*
+*******************************************************************************/
+
+#ifdef _NTSUBSET_
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+#include <cruntime.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <errno.h>
+#include <assert.h>
+
+/***
+*size_t wcstombs() - Convert wide char string to multibyte char string.
+*
+*Purpose:
+* Convert a wide char string into the equivalent multibyte char string,
+* according to the LC_CTYPE category of the current locale.
+* [ANSI].
+*
+* NOTE: Currently, the C libraries support the "C" locale only.
+* Non-C locale support now available under _INTL switch.
+*Entry:
+* char *s = pointer to destination multibyte char string
+* const wchar_t *pwc = pointer to source wide character string
+* size_t n = maximum number of bytes to store in s
+*
+*Exit:
+* If s != NULL, returns (size_t)-1 (if a wchar cannot be converted)
+* Otherwise: Number of bytes modified (<=n), not including
+* the terminating NUL, if any.
+*
+*Exceptions:
+* Returns (size_t)-1 if s is NULL or invalid mb character encountered.
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+size_t _CRTAPI1 wcstombs
+ (
+ char *s,
+ const wchar_t *pwcs,
+ size_t n
+ )
+{
+ int retval;
+
+ _mlock (_LC_CTYPE_LOCK);
+ retval = _wcstombs_lk(s, pwcs, n);
+ _munlock (_LC_CTYPE_LOCK);
+ return retval;
+}
+#endif /* MTHREAD */
+
+#ifdef MTHREAD
+size_t _CRTAPI1 _wcstombs_lk
+#else
+size_t _CRTAPI1 wcstombs
+#endif
+ (
+ char *s,
+ const wchar_t *pwcs,
+ size_t n
+ )
+{
+ int i, retval;
+ size_t count = 0;
+ char buffer[MB_LEN_MAX]; /* UNDONE: what about MTHREAD ? */
+ BOOL defused = 0;
+
+ if (s && n == 0)
+ return (size_t) 0;
+
+ assert(pwcs != NULL);
+
+ /* if destination string exists, fill it in */
+ if (s)
+ {
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE &&
+ _lc_codepage == _CLOCALECP)
+ {
+#endif /* _INTL */
+#ifdef _NTSUBSET_
+ {
+ NTSTATUS Status;
+
+ Status = RtlUnicodeToMultiByteN(s, n, (PULONG)&count, (wchar_t *)pwcs, (wcslen(pwcs)+1)*sizeof(WCHAR));
+ if (NT_SUCCESS(Status))
+ {
+ return count - 1; /* don't count NUL */
+ } else {
+ errno = EILSEQ;
+ count = (size_t)-1;
+ }
+ }
+#else
+ /* C locale: easy and fast */
+ while(count < n)
+ {
+ if (*pwcs > 255) /* validate high byte */
+ {
+ errno = EILSEQ;
+ return (size_t)-1; /* error */
+ }
+ s[count] = (char) *pwcs;
+ if (*pwcs++ == L'\0')
+ return count;
+ count++;
+ }
+#endif
+ return count;
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ } else {
+ /* Assume that usually the buffer is large enough */
+ if (((count=WideCharToMultiByte(_lc_codepage,
+ WC_COMPOSITECHECK | WC_SEPCHARS,
+ pwcs, -1, s, n, NULL, &defused)) != 0) && (!defused))
+ return count - 1; /* don't count NUL */
+
+ if (defused || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ errno = EILSEQ;
+ return (size_t)-1;
+ }
+
+ /* buffer not large enough, must do char by char */
+ while (count < n)
+ {
+ if (((retval = WideCharToMultiByte (_lc_codepage, 0,
+ pwcs, 1, buffer, MB_CUR_MAX, NULL, &defused)) == 0) || defused)
+ {
+ errno = EILSEQ;
+ return (size_t)-1;
+ }
+
+ if (count + retval > n)
+ return count;
+
+ for (i = 0; i < retval; i++, count++) /* store character */
+ if((s[count] = buffer[i])=='\0')
+ return count; /* done if NUL */
+ pwcs++;
+ }
+ return count;
+ }
+#endif /* _INTL */
+ }
+ else { /* s == NULL, get size only, pwcs must be NUL-terminated */
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE &&
+ _lc_codepage == _CLOCALECP)
+#endif /* _INTL */
+#ifdef _NTSUBSET_
+ {
+ NTSTATUS Status;
+
+ Status = RtlUnicodeToMultiByteSize((PULONG)&count, (wchar_t *)pwcs, (wcslen(pwcs)+1)*sizeof(WCHAR));
+ if (NT_SUCCESS(Status))
+ {
+ return count - 1; /* don't count NUL */
+ } else {
+ errno = EILSEQ;
+ count = (size_t)-1;
+ }
+ }
+#else
+ return wcslen(pwcs);
+#endif
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ else {
+ if (((count=WideCharToMultiByte(_lc_codepage,
+ WC_COMPOSITECHECK | WC_SEPCHARS,
+ pwcs, -1, NULL, 0, NULL, &defused)) == 0) || (defused))
+ {
+ errno = EILSEQ;
+ return (size_t)-1;
+ }
+
+ return count - 1;
+ }
+#endif /* _INTL */
+ }
+}
diff --git a/private/crt32/convert/wctomb.c b/private/crt32/convert/wctomb.c
new file mode 100644
index 000000000..5b2fd734c
--- /dev/null
+++ b/private/crt32/convert/wctomb.c
@@ -0,0 +1,136 @@
+/***
+*wctomb.c - Convert wide character to multibyte character.
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert a wide character into the equivalent multibyte character.
+*
+*Revision History:
+* 03-19-90 KRS Module created.
+* 12-20-90 KRS Include ctype.h.
+* 01-14-91 KRS Fix argument error: wchar is pass-by-value.
+* 03-20-91 KRS Ported from 16-bit tree.
+* 07-23-91 KRS Hard-coded for "C" locale to avoid bogus interim #'s.
+* 10-15-91 ETC Locale support under _INTL (finally!).
+* 12-09-91 ETC Updated nlsapi; added multithread.
+* 08-20-92 KRS Activated NLSAPI support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 05-04-93 CFW Kinder, gentler error handling.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+* 01-14-94 SRW if _NTSUBSET_ defined call Rtl functions
+*
+*******************************************************************************/
+
+#ifdef _NTSUBSET_
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+#include <cruntime.h>
+#include <stdlib.h>
+#include <os2dll.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <errno.h>
+
+/***
+*int wctomb() - Convert wide character to multibyte character.
+*
+*Purpose:
+* Convert a wide character into the equivalent multi-byte character,
+* according to the LC_CTYPE category of the current locale.
+* [ANSI].
+*
+* NOTE: Currently, the C libraries support the "C" locale only.
+* Non-C locale support now available under _INTL switch.
+*Entry:
+* char *s = pointer to multibyte character
+* wchar_t wchar = source wide character
+*
+*Exit:
+* If s = NULL, returns 0, indicating we only use state-independent
+* character encodings.
+* If s != NULL, returns:
+* -1 (if error) or number of bytes comprising
+* converted mbc
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+int _CRTAPI1 wctomb
+ (
+ char *s,
+ wchar_t wchar
+ )
+{
+ int retval;
+
+ _mlock (_LC_CTYPE_LOCK);
+ retval = _wctomb_lk(s, wchar);
+ _munlock (_LC_CTYPE_LOCK);
+ return retval;
+}
+#endif /* MTHREAD */
+
+#ifdef MTHREAD
+int _CRTAPI1 _wctomb_lk
+#else
+int _CRTAPI1 wctomb
+#endif
+ (
+ char *s,
+ wchar_t wchar
+ )
+{
+ if (!s)
+ return 0;
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP))
+ {
+#endif /* _INTL */
+#ifdef _NTSUBSET_
+ {
+ NTSTATUS Status;
+ int size;
+
+ Status = RtlUnicodeToMultiByteN(s, MB_CUR_MAX, (PULONG)&size, &wchar, sizeof( wchar ));
+ if (!NT_SUCCESS(Status))
+ {
+ errno = EILSEQ;
+ size = -1;
+ }
+ return size;
+ }
+#else
+ if (wchar>255) /* validate high byte */
+ {
+ errno = EILSEQ;
+ return -1;
+ }
+
+ *s = (char) wchar;
+ return sizeof(char);
+#endif
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ } else {
+ int size;
+ BOOL defused = 0;
+
+ if (((size=WideCharToMultiByte(_lc_codepage,
+ WC_COMPOSITECHECK | WC_SEPCHARS, &wchar, 1,
+ s, MB_CUR_MAX, NULL, &defused)) == 0) || (defused))
+ {
+ errno = EILSEQ;
+ size = -1;
+ }
+
+ return size;
+ }
+#endif /* _INTL */
+}
diff --git a/private/crt32/convert/wtox.c b/private/crt32/convert/wtox.c
new file mode 100644
index 000000000..c151692af
--- /dev/null
+++ b/private/crt32/convert/wtox.c
@@ -0,0 +1,82 @@
+/***
+*wtox.c - _wtoi and _wtol conversion
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts a wide character string into an int or long.
+*
+*Revision History:
+* 09-10-93 CFW Module created, based on ASCII version.
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <stdlib.h>
+
+#define INT_SIZE_LENGTH 20
+#define LONG_SIZE_LENGTH 40
+
+/***
+*long _wtol(wchar_t *nptr) - Convert wide string to long
+*
+*Purpose:
+* Converts wide string pointed to by nptr to binary.
+* Overflow is not detected. Because of this, we can just use
+* atol().
+*
+*Entry:
+* nptr = ptr to wide string to convert
+*
+*Exit:
+* return long value of the string
+*
+*Exceptions:
+* None - overflow is not detected.
+*
+*******************************************************************************/
+
+long _CRTAPI1 _wtol(
+ const wchar_t *nptr
+ )
+{
+ char astring[INT_SIZE_LENGTH];
+ int defused;
+
+ WideCharToMultiByte (CP_ACP, 0, nptr, -1,
+ astring, INT_SIZE_LENGTH, NULL, &defused);
+
+ return (atol(astring));
+}
+
+/***
+*int _wtoi(wchar_t *nptr) - Convert wide string to int
+*
+*Purpose:
+* Converts wide string pointed to by nptr to binary.
+* Overflow is not detected. Because of this, we can just use
+* atol().
+*
+*Entry:
+* nptr = ptr to wide string to convert
+*
+*Exit:
+* return int value of the string
+*
+*Exceptions:
+* None - overflow is not detected.
+*
+*******************************************************************************/
+
+int _CRTAPI1 _wtoi(
+ const wchar_t *nptr
+ )
+{
+ char astring[INT_SIZE_LENGTH];
+ int defused;
+
+ WideCharToMultiByte (CP_ACP, 0, nptr, -1,
+ astring, INT_SIZE_LENGTH, NULL, &defused);
+
+ return ((int)atol(astring));
+}
diff --git a/private/crt32/convert/xtoa.c b/private/crt32/convert/xtoa.c
new file mode 100644
index 000000000..72fcfb265
--- /dev/null
+++ b/private/crt32/convert/xtoa.c
@@ -0,0 +1,127 @@
+/***
+*xtoa.c - convert integers/longs to ASCII string
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The module has code to convert integers/longs to ASCII strings. See
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 03-06-90 GJF Fixed calling type, added #include <cruntime.h> and
+* fixed copyright.
+* 03-23-90 GJF Made xtoa() _CALLTYPE4.
+* 09-27-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <limits.h>
+
+/***
+*char *_itoa, *_ltoa, *_ultoa(val, buf, radix) - convert binary int to ASCII
+* string
+*
+*Purpose:
+* Converts an int to a character string.
+*
+*Entry:
+* val - number to be converted (int, long or unsigned long)
+* int radix - base to convert into
+* char *buf - ptr to buffer to place result
+*
+*Exit:
+* fills in space pointed to by buf with string result
+* returns a pointer to this buffer
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+/* helper routine that does the main job. */
+
+static void _CALLTYPE4 xtoa (
+ unsigned long val,
+ char *buf,
+ unsigned radix,
+ int is_neg
+ )
+{
+ char *p; /* pointer to traverse string */
+ char *firstdig; /* pointer to first digit */
+ char temp; /* temp char */
+ unsigned digval; /* value of digit */
+
+ p = buf;
+
+ if (is_neg) {
+ /* negative, so output '-' and negate */
+ *p++ = '-';
+ val = (unsigned long)(-(long)val);
+ }
+
+ firstdig = p; /* save pointer to first digit */
+
+ do {
+ digval = (unsigned) (val % radix);
+ val /= radix; /* get next digit */
+
+ /* convert to ascii and store */
+ if (digval > 9)
+ *p++ = (char) (digval - 10 + 'a'); /* a letter */
+ else
+ *p++ = (char) (digval + '0'); /* a digit */
+ } while (val > 0);
+
+ /* We now have the digit of the number in the buffer, but in reverse
+ order. Thus we reverse them now. */
+
+ *p-- = '\0'; /* terminate string; p points to last digit */
+
+ do {
+ temp = *p;
+ *p = *firstdig;
+ *firstdig = temp; /* swap *p and *firstdig */
+ --p;
+ ++firstdig; /* advance to next two digits */
+ } while (firstdig < p); /* repeat until halfway */
+}
+
+
+/* Actual functions just call conversion helper with neg flag set correctly,
+ and return pointer to buffer. */
+
+char * _CALLTYPE1 _itoa (
+ int val,
+ char *buf,
+ int radix
+ )
+{
+ if (radix == 10 && val < 0)
+ xtoa((unsigned long)val, buf, radix, 1);
+ else
+ xtoa((unsigned long)(unsigned int)val, buf, radix, 0);
+ return buf;
+}
+
+char * _CALLTYPE1 _ltoa (
+ long val,
+ char *buf,
+ int radix
+ )
+{
+ xtoa((unsigned long)val, buf, radix, (radix == 10 && val < 0));
+ return buf;
+}
+
+char * _CALLTYPE1 _ultoa (
+ unsigned long val,
+ char *buf,
+ int radix
+ )
+{
+ xtoa(val, buf, radix, 0);
+ return buf;
+}
diff --git a/private/crt32/convert/xtow.c b/private/crt32/convert/xtow.c
new file mode 100644
index 000000000..2b1c0605a
--- /dev/null
+++ b/private/crt32/convert/xtow.c
@@ -0,0 +1,85 @@
+/***
+*xtow.c - convert integers/longs to wide char string
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The module has code to convert integers/longs to wide char strings.
+*
+*Revision History:
+* 09-10-93 CFW Module created, based on ASCII version.
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <stdlib.h>
+
+#define INT_SIZE_LENGTH 20
+#define LONG_SIZE_LENGTH 40
+
+/***
+*wchar_t *_itow, *_ltow, *_ultow(val, buf, radix) - convert binary int to wide
+* char string
+*
+*Purpose:
+* Converts an int to a wide character string.
+*
+*Entry:
+* val - number to be converted (int, long or unsigned long)
+* int radix - base to convert into
+* wchar_t *buf - ptr to buffer to place result
+*
+*Exit:
+* calls ASCII version to convert, converts ASCII to wide char into buf
+* returns a pointer to this buffer
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CRTAPI1 _itow (
+ int val,
+ wchar_t *buf,
+ int radix
+ )
+{
+ char astring[INT_SIZE_LENGTH];
+
+ _itoa (val, astring, radix);
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, astring, -1,
+ buf, INT_SIZE_LENGTH);
+
+ return (buf);
+}
+
+wchar_t * _CRTAPI1 _ltow (
+ long val,
+ wchar_t *buf,
+ int radix
+ )
+{
+ char astring[LONG_SIZE_LENGTH];
+
+ _ltoa (val, astring, radix);
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, astring, -1,
+ buf, LONG_SIZE_LENGTH);
+
+ return (buf);
+}
+
+wchar_t * _CRTAPI1 _ultow (
+ unsigned long val,
+ wchar_t *buf,
+ int radix
+ )
+{
+ char astring[LONG_SIZE_LENGTH];
+
+ _ultoa (val, astring, radix);
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, astring, -1,
+ buf, LONG_SIZE_LENGTH);
+
+ return (buf);
+}
+
+
diff --git a/private/crt32/crt32.def b/private/crt32/crt32.def
new file mode 100644
index 000000000..43add7b8f
--- /dev/null
+++ b/private/crt32/crt32.def
@@ -0,0 +1,95 @@
+####
+#crt32.def - definitions for the crt32 build
+#
+# Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+#
+#Purpose:
+# This file is included in the 'sources' files in this tree
+#
+# Key to CRT32 environment variables:
+#
+# CRTLIBDEBUG = debug flag (define for debug libs)
+# CRTLIBTYPE = [dll/mt/st], dll = dynalink, mt = multithread,
+# st = singlethread
+#
+# [Other variables are used directly by the NT build tool.]
+#
+#Revision History:
+# 09-29-91 JCR File created.
+# 10-04-91 JCR Added mt vs st build
+# 01-06-92 GJF Added DLL support. Cleaned up a bit.
+# 04-16-92 DJM POSIX support.
+# 08-28-92 GJF Fixed POSIX support.
+# 09-02-92 SRW Removed -D_INTL from all versions until
+# Win32 NLS API calls are faster. When that
+# happens, add it back to all but Posix version.
+# 12-03-92 KRS Added optional _MBCS defines.
+# 05-22-93 SRW Compile runtines with no debug info except globals.
+# 06-03-93 SRW Okay to allow FPO now, as crt32\startup\mlock.c has
+# been fixed to explicitly disable FPO for itself.
+# 10-18-93 SRW Disable intrinsics on Alpha
+#
+################################################################################
+
+NTDEBUG=
+
+NTLEGO=1
+
+!IF "$(CRTLIBTYPE)" == "DLL"
+TARGETNAMESUFFIX=dll
+TARGETTYPE=LIBRARY
+MTOPTION=-DMTHREAD -D_MT -DCRTDLL
+C_DEFINES1=-D_WIN32_=1 -D_INTL -D_MBCS -D_KANJI
+ASM_DEFINES1=-D_WIN32_=1 -D_INTL
+INCLUDES=..\h
+!ELSE
+!IF "$(CRTLIBTYPE)" == "MT"
+TARGETNAMESUFFIX=mt
+TARGETTYPE=LIBRARY
+MTOPTION=-DMTHREAD -D_MT
+C_DEFINES1=-D_WIN32_=1 -D_INTL -D_MBCS -D_KANJI
+ASM_DEFINES1=-D_WIN32_=1 -D_INTL
+INCLUDES=..\h
+!ELSE
+!IF "$(CRTLIBTYPE)" == "ST"
+TARGETNAMESUFFIX=
+TARGETTYPE=LIBRARY
+MTOPTION=
+C_DEFINES1=-D_WIN32_=1 -D_INTL -D_MBCS -D_KANJI
+ASM_DEFINES1=-D_WIN32_=1 -D_INTL
+INCLUDES=..\h
+!ELSE
+!IF "$(CRTLIBTYPE)" == "NT"
+TARGETNAMESUFFIX=nt
+TARGETTYPE=LIBRARY
+MTOPTION=
+C_DEFINES1=-D_WIN32_=1 -D_NTSUBSET_=1 -D_NTSYSTEM_=1 -D_INTL
+ASM_DEFINES1=-D_WIN32_=1 -D_NTSUBSET_=1 -D_NTSYSTEM_=1 -D_INTL
+INCLUDES=..\h
+!ELSE
+!IF "$(CRTLIBTYPE)" == "POSIX"
+TARGETNAMESUFFIX=psx
+TARGETTYPE=LIBRARY
+MTOPTION=
+C_DEFINES1=-D_POSIX_=1 -D_CRTHEAP_ -D_INTL -D_MBCS -D_KANJI -D_NTSUBSET_
+ASM_DEFINES1=-D_POSIX_=1 -D_INTL
+INCLUDES=$(BASEDIR)\public\sdk\inc\posix;..\h
+!ELSE
+!ERROR Unsupported Library CRTLIBTYPE: $(CRTLIBTYPE)
+!ENDIF
+!ENDIF
+!ENDIF
+!ENDIF
+!ENDIF
+
+
+!IF "$(CRTLIBDEBUG)" == ""
+C_DEFINES=-DNDEBUG $(C_DEFINES1) $(MTOPTION) $(MBCS_DEFINES)
+ASM_DEFINES=$(ASM_DEFINES1) $(MTOPTION) $(MBCS_DEFINES)
+!ELSE
+C_DEFINES=$(C_DEFINES1) -DDEBUG=1 $(MTOPTION) $(MBCS_DEFINES)
+ASM_DEFINES=$(ASM_DEFINES1) -DDEBUG=1 $(MTOPTION) $(MBCS_DEFINES)
+!ENDIF
+
+# Disable intrinsics on Alpha as it will not allow redefinition of intrinsics
+ALPHA_OPTIMIZATION=/Ox /Oi-
diff --git a/private/crt32/direct/drivemap.c b/private/crt32/direct/drivemap.c
new file mode 100644
index 000000000..160eab54c
--- /dev/null
+++ b/private/crt32/direct/drivemap.c
@@ -0,0 +1,39 @@
+/***
+*drivemap.c - _getdrives
+*
+* Copyright (c) 1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _getdrives()
+*
+*Revision History:
+* 08-22-91 BWM Wrote module.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <direct.h>
+
+#if !defined(_WIN32_)
+#error ERROR - ONLY WIN32 TARGET SUPPORTED!
+#endif
+
+/***
+*void _getdrivemap(void) - Get bit map of all available drives
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+* drive map with drive A in bit 0, B in 1, etc.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned long _CALLTYPE1 _getdrives()
+{
+ return (GetLogicalDrives());
+}
diff --git a/private/crt32/direct/drivfree.c b/private/crt32/direct/drivfree.c
new file mode 100644
index 000000000..3ff8b77a5
--- /dev/null
+++ b/private/crt32/direct/drivfree.c
@@ -0,0 +1,69 @@
+/***
+*drivfree.c - Get the size of a disk
+*
+* Copyright (c) 1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file has _getdiskfree()
+*
+*Revision History:
+* 08-21-91 PHG Module created for Win32
+* 10-24-91 GJF Added LPDWORD casts to make MIPS compiler happy.
+* ASSUMES THAT sizeof(unsigned) == sizeof(DWORD).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <direct.h>
+#include <oscalls.h>
+
+/***
+*int _getdiskfree(drivenum, diskfree) - get size of a specified disk
+*
+*Purpose:
+* Gets the size of the current or specified disk drive
+*
+*Entry:
+* int drivenum - 0 for current drive, or drive 1-26
+*
+*Exit:
+* returns 0 if succeeds
+* returns system error code on error.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#if !defined(_WIN32_)
+#error ERROR - ONLY WIN32 TARGET SUPPORTED!
+#endif
+
+unsigned _CALLTYPE1 _getdiskfree(unsigned uDrive, struct _diskfree_t * pdf)
+{
+ char szRoot[] = "?:\\";
+ char szCur[MAX_PATH];
+
+ if (uDrive == 0) {
+ GetCurrentDirectory(MAX_PATH, szCur);
+ if ((szCur[0] == '\\') && (szCur[1] == '\\')) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+ szRoot[0] = szCur[0];
+ }
+ else if (uDrive > 26) {
+ return (ERROR_INVALID_PARAMETER);
+ }
+ else {
+ szRoot[0] = (char)uDrive + (char)('A' - 1);
+ }
+
+
+ if (!GetDiskFreeSpace(szRoot,
+ (LPDWORD)&(pdf->sectors_per_cluster),
+ (LPDWORD)&(pdf->bytes_per_sector),
+ (LPDWORD)&(pdf->avail_clusters),
+ (LPDWORD)&(pdf->total_clusters))) {
+ return ((int)GetLastError());
+ }
+ return (0);
+}
diff --git a/private/crt32/direct/findfile.c b/private/crt32/direct/findfile.c
new file mode 100644
index 000000000..346c63f78
--- /dev/null
+++ b/private/crt32/direct/findfile.c
@@ -0,0 +1,224 @@
+/***
+*findfile.c - C find file functions
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines findfirst(), findnext(), and findclose().
+*
+*Revision History:
+* 08-21-91 BWM Wrote Win32 versions.
+* 09-13-91 BWM Changed handle type to long.
+* 08-18-92 SKS Add a call to FileTimeToLocalFileTime
+* as a temporary fix until _dtoxtime takes UTC
+* 08-26-92 SKS creation and last access time should be same as the
+* last write time if ctime/atime are not available.
+* 01-08-93 SKS Remove change I made 8-26-92. Previous behavior
+* was deemed "by design" and preferable.
+* 03-30-93 GJF Replaced reference to _dtoxtime with __gmtotime_t. Also
+* made _timet_from_ft a static function.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <errno.h>
+#include <io.h>
+#include <time.h>
+#include <ctime.h>
+#include <string.h>
+#include <internal.h>
+
+#if !defined(_WIN32_)
+#error ERROR - ONLY WIN32 TARGET SUPPORTED!
+#endif
+
+static time_t _CRTAPI3 _timet_from_ft(FILETIME * pft);
+
+/***
+*long findfirst(wildspec, finddata) - Find first matching file
+*
+*Purpose:
+* Finds the first file matching a given wild card filespec and
+* returns data about the file.
+*
+*Entry:
+* char * wild - file spec optionally containing wild cards
+*
+* struct _finddata_t * finddata - structure to receive file data
+*
+*Exit:
+* Good return:
+* Unique handle identifying the group of files matching the spec
+*
+* Error return:
+* Returns -1 and errno is set to error value
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+long _CRTAPI1 _findfirst(char * szWild, struct _finddata_t * pfd)
+{
+ WIN32_FIND_DATA wfd;
+ HANDLE hFile;
+ DWORD err;
+
+ if ((hFile = FindFirstFile(szWild, &wfd)) == INVALID_HANDLE_VALUE) {
+ err = GetLastError();
+ switch (err) {
+ case ERROR_NO_MORE_FILES:
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ errno = ENOENT;
+ break;
+
+ case ERROR_NOT_ENOUGH_MEMORY:
+ errno = ENOMEM;
+ break;
+
+ default:
+ errno = EINVAL;
+ break;
+ }
+ return (-1);
+ }
+
+ pfd->attrib = (wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
+ ? 0 : wfd.dwFileAttributes;
+ pfd->time_create = _timet_from_ft(&wfd.ftCreationTime);
+ pfd->time_access = _timet_from_ft(&wfd.ftLastAccessTime);
+ pfd->time_write = _timet_from_ft(&wfd.ftLastWriteTime);
+ pfd->size = wfd.nFileSizeLow;
+ strcpy(pfd->name, wfd.cFileName);
+
+ return ((long)hFile);
+}
+
+/***
+*int _findnext(hfind, finddata) - Find next matching file
+*
+*Purpose:
+* Finds the next file matching a given wild card filespec and
+* returns data about the file.
+*
+*Entry:
+* hfind - handle from _findfirst
+*
+* struct _finddata_t * finddata - structure to receive file data
+*
+*Exit:
+* Good return:
+* 0 if file found
+* -1 if error or file not found
+* errno set
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+int _CRTAPI1 _findnext(long hFile, struct _finddata_t * pfd)
+{
+ WIN32_FIND_DATA wfd;
+ DWORD err;
+
+ if (!FindNextFile((HANDLE)hFile, &wfd)) {
+ err = GetLastError();
+ switch (err) {
+ case ERROR_NO_MORE_FILES:
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ errno = ENOENT;
+ break;
+
+ case ERROR_NOT_ENOUGH_MEMORY:
+ errno = ENOMEM;
+ break;
+
+ default:
+ errno = EINVAL;
+ break;
+ }
+ return (-1);
+ }
+
+ pfd->attrib = (wfd.dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
+ ? 0 : wfd.dwFileAttributes;
+ pfd->time_create = _timet_from_ft(&wfd.ftCreationTime);
+ pfd->time_access = _timet_from_ft(&wfd.ftLastAccessTime);
+ pfd->time_write = _timet_from_ft(&wfd.ftLastWriteTime);
+ pfd->size = wfd.nFileSizeLow;
+ strcpy(pfd->name, wfd.cFileName);
+
+ return (0);
+}
+
+/***
+*int _findclose(hfind) - Release resources of find
+*
+*Purpose:
+* Releases resources of a group of files found by _findfirst and
+* _findnext
+*
+*Entry:
+* hfind - handle from _findfirst
+*
+*Exit:
+* Good return:
+* 0 if success
+* -1 if fail, errno set
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+int _CRTAPI1 _findclose(long hFile)
+{
+ if (!FindClose((HANDLE)hFile)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ return (0);
+}
+
+/***
+*time_t _fttotimet(ft) - convert Win32 file time to Xenix time
+*
+*Purpose:
+* converts a Win32 file time value to Xenix time_t
+*
+*Entry:
+* int yr, mo, dy - date
+* int hr, mn, sc - time
+*
+*Exit:
+* returns Xenix time value
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static time_t _CRTAPI3 _timet_from_ft(FILETIME * pft)
+{
+ SYSTEMTIME st;
+
+ // 0 FILETIME returns a -1 time_t
+
+ if (!pft->dwLowDateTime && !pft->dwHighDateTime) {
+ return (-1L);
+ }
+
+ if (!FileTimeToSystemTime(pft, &st)) {
+ return (-1L);
+ }
+
+ return ( __gmtotime_t(st.wYear,
+ st.wMonth,
+ st.wDay,
+ st.wHour,
+ st.wMinute,
+ st.wSecond) );
+}
diff --git a/private/crt32/direct/makefile b/private/crt32/direct/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/direct/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/direct/peekpoke.c b/private/crt32/direct/peekpoke.c
new file mode 100644
index 000000000..f00ffb6c2
--- /dev/null
+++ b/private/crt32/direct/peekpoke.c
@@ -0,0 +1,95 @@
+/***
+*peekpoke.c - Peek or poke absolute memory.
+*
+* Copyright (c) 1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _peek(), _poke(), and _getvideoaddress().
+*
+*Revision History:
+* 08-21-91 BWM Wrote module.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <stdlib.h>
+#include <dos.h>
+
+#if !defined(_DOSX32_)
+#error ERROR - ONLY DOSX32 TARGET SUPPORTED!
+#endif
+
+/***
+*void _peek(src, dst, size) - Peek at memory
+*
+*Purpose:
+*
+*Entry:
+* _absaddr_t src - address to be peeked
+* void * dst - pointer to location to receive copy
+* unsigned short size - number of bytes to peek
+*
+*Exit:
+* None
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _peek(_absaddr_t aaSrc, void * pvDst, unsigned short cb)
+{
+ PeekAddress((WORD)((aaSrc & 0xffff0000) >> 16),
+ (WORD) (aaSrc & 0x0000ffff),
+ pvDst, cb);
+}
+
+/***
+*void _poke(src, dst, size) - Poke into memory
+*
+*Purpose:
+*
+*Entry:
+* void * src - pointer to data to be poked
+* _absaddr_t dst - address where data will be poked
+* unsigned short size - number of bytes to poke
+*
+*Exit:
+* None
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _poke(void * pvSrc, _absaddr_t aaDst, unsigned short cb)
+{
+ PokeAddress(pvSrc,
+ (WORD)((aaDst & 0xffff0000) >> 16),
+ (WORD) (aaDst & 0x0000ffff), cb);
+}
+
+
+/***
+*void _getvideoaddr(region) - Get flat address of video memory
+*
+*Purpose:
+*
+*Entry:
+* unsigned region - screen memory region:
+*
+* _ADDR_NO_PALETTE_GRAPHICS - Absolute B800:0000
+* _ADDR_PALETTE_GRAPHICS - Absolute A000:0000
+* _ADDR_COLOR_TEXT - Absolute B800:0000
+* _ADDR_MONO_TEXT - Absolute B000:0000
+*
+*Exit:
+* None
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 _getvideoaddr(unsigned dwRegion)
+{
+ return (GetVideoAddress(dwRegion));
+}
diff --git a/private/crt32/direct/seterrm.c b/private/crt32/direct/seterrm.c
new file mode 100644
index 000000000..838854db0
--- /dev/null
+++ b/private/crt32/direct/seterrm.c
@@ -0,0 +1,63 @@
+/***
+*seterrm.c - Set mode for handling critical errors
+*
+* Copyright (c) 1991, Microsoft Corporation. All rights reserved
+*
+*Purpose:
+* Defines signal() and raise().
+*
+*Revision History:
+* 08-21-92 BWM Wrote for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+
+/***
+*void _seterrormode(mode) - set the critical error mode
+*
+*Purpose:
+*
+*Entry:
+* int mode - error mode:
+*
+* 0 means system displays a prompt asking user how to
+* respond to the error. Choices differ depending on the
+* error but may include Abort, Retry, Ignore, and Fail.
+*
+* 1 means the call system call causing the error will fail
+* and return an error indicating the cause.
+*
+*Exit:
+* none
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _seterrormode(int mode)
+{
+#ifdef _CRUISER_
+
+ if (mode == 1) {
+ DOSERROR(1);
+ else if (mode == 0) {
+ DOSERROR(0);
+ }
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ SetErrorMode(mode);
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
diff --git a/private/crt32/direct/slbeep.c b/private/crt32/direct/slbeep.c
new file mode 100644
index 000000000..a549e4a5e
--- /dev/null
+++ b/private/crt32/direct/slbeep.c
@@ -0,0 +1,105 @@
+/***
+*slbeep.c - Sleep and beep
+*
+* Copyright (c) 1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _sleep() and _beep()
+*
+*Revision History:
+* 08-22-91 BWM Wrote module.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <stdlib.h>
+
+/***
+*void _sleep(duration) - Length of sleep
+*
+*Purpose:
+*
+*Entry:
+* unsigned long duration - length of sleep in milliseconds or
+* one of the following special values:
+*
+* _SLEEP_MINIMUM - Sends a yield message without any delay
+* _SLEEP_FOREVER - Never return
+*
+*Exit:
+* None
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _sleep(unsigned long dwDuration)
+{
+#ifdef _CRUISER_
+
+ if (dwDuration == _SLEEP_FOREVER) {
+ while(1) {
+ DOSSLEEP(dwDuration);
+ }
+ }
+ else {
+ DOSSLEEP(dwDuration);
+ }
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (dwDuration == 0) {
+ dwDuration++;
+ }
+ Sleep(dwDuration);
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
+
+/***
+*void _beep(frequency, duration) - Length of sleep
+*
+*Purpose:
+*
+*Entry:
+* unsigned frequency - frequency in hertz
+* unsigned duration - length of beep in milliseconds
+*
+*Exit:
+* None
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _beep(unsigned dwFrequency, unsigned dwDuration)
+{
+#ifdef _CRUISER_
+
+ DOSBEEP(dwFrequency, dwDuration);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ Beep(dwFrequency, dwDuration);
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
diff --git a/private/crt32/direct/sources b/private/crt32/direct/sources
new file mode 100644
index 000000000..2fe65d1d1
--- /dev/null
+++ b/private/crt32/direct/sources
@@ -0,0 +1,40 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=direct
+
+TARGETNAME=direct
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=drivemap.c \
+ drivfree.c \
+ findfile.c \
+ seterrm.c \
+ slbeep.c
diff --git a/private/crt32/dirs b/private/crt32/dirs
new file mode 100644
index 000000000..57fcf957c
--- /dev/null
+++ b/private/crt32/dirs
@@ -0,0 +1,43 @@
+!IF 0
+
+Copyright (c) 1989 - 1992, Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+ KarlSi 15-Jun-1992 Added iostream.
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=convert \
+ misc \
+ startup \
+ stdio \
+ string
+
+OPTIONAL_DIRS=iostream \
+ linkopts \
+ time \
+ winheap \
+ dllstuff \
+ direct \
+ dos \
+ exec \
+ hack \
+ heap \
+ lowio \
+ small \
+ helper \
+ mbstring
diff --git a/private/crt32/dllstuff/cinitexe.c b/private/crt32/dllstuff/cinitexe.c
new file mode 100644
index 000000000..ac7c875af
--- /dev/null
+++ b/private/crt32/dllstuff/cinitexe.c
@@ -0,0 +1,92 @@
+/***
+*cinitexe.asm - C Run-Time Startup Initialization for WIN32
+*
+* Copyright (c) 1992-1994, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Do C++ initialization segment declarations for the EXE in CRT DLL
+* model
+*
+*Notes:
+* The C++ initializers will exist in the user EXE's data segment
+* so the special segments to contain them must be in the user EXE.
+*
+*Revision History:
+* 03-19-92 SKS Module created (based on CRT0INIT.ASM)
+* 08-06-92 SKS Revised to use new section names and macros
+* 04-12-93 CFW Added xia..xiz initializers.
+* 10-20-93 SKS Add .DiRECTiVE section for MIPS, too!
+* 10-28-93 GJF Rewritten in C
+* 10-28-94 SKS Add user32.lib as a default library
+* 02-27-95 CFW Remove user32.lib as a default library
+*
+*******************************************************************************/
+
+#ifdef _WIN32
+
+#ifdef _MSC_VER
+
+#include <stdio.h>
+#include <internal.h>
+
+#pragma data_seg(".CRT$XCA")
+_PVFV __xc_a[] = { NULL };
+
+#pragma data_seg(".CRT$XCZ")
+_PVFV __xc_z[] = { NULL };
+
+#pragma data_seg(".drectve")
+static char __drectve_win32lib[] =
+ "-merge:.CRT=.rdata";
+#pragma data_seg() /* reset */
+
+#endif /* _MSC_VER */
+
+#else /* _WIN32 */
+
+#include <cruntime.h>
+#include <msdos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <internal.h>
+#include <fltintrn.h>
+#include <mpw.h>
+#include <mtdll.h>
+#include <macos\types.h>
+#include <macos\segload.h>
+#include <macos\gestalte.h>
+#include <macos\osutils.h>
+#include <macos\traps.h>
+
+/*
+ * pointers to initialization functions
+ */
+
+#pragma data_seg(".CRT$XIA")
+PFV __xi_a = 0; /* C initializers */
+
+#pragma data_seg(".CRT$XIZ")
+PFV __xi_z = 0;
+
+#pragma data_seg(".CRT$XCA")
+PFV __xc_a = 0; /* C++ initializers */
+
+#pragma data_seg(".CRT$XCZ")
+PFV __xc_z = 0;
+
+#pragma data_seg(".CRT$XPA")
+PFV __xp_a = 0; /* C pre-terminators */
+
+#pragma data_seg(".CRT$XPZ")
+PFV __xp_z = 0;
+
+#pragma data_seg(".CRT$XTA")
+PFV __xt_a = 0; /* C terminators */
+
+#pragma data_seg(".CRT$XTZ")
+PFV __xt_z = 0;
+
+#pragma data_seg()
+
+
+#endif
diff --git a/private/crt32/dllstuff/crtdll.c b/private/crt32/dllstuff/crtdll.c
new file mode 100644
index 000000000..a03adc428
--- /dev/null
+++ b/private/crt32/dllstuff/crtdll.c
@@ -0,0 +1,376 @@
+#ifdef CRTDLL
+/***
+*crtdll.c - CRT initialization for a DLL using the CRTDLL model of C run-time
+*
+* Copyright (c) 1991-1994, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains the initialization entry point for the C run-time
+* stub in this DLL. All C run-time code is located in the C Run-Time
+* Library DLL "CRTDLL.DLL", except for a little bit of start-up code in
+* the EXE, and this code in each DLL. This code is necessary to invoke
+* the C++ constructors for the C++ code in this DLL.
+*
+* This entry point should either be specified as the DLL initialization
+* entry point, or else it must be called by the DLL initialization entry
+* point of the DLL with the same arguments that the entry point receives.
+*
+*Revision History:
+* 05-19-92 SKS Initial version
+* 08-01-92 SRW winxcpt.h replaced bu excpt.h which is included by oscalls.h
+* 09-16-92 SKS Prepare for C8 C++ for MIPS by calling C++ constructors
+* 09-29-92 SKS _CRT_DLL must be a WINAPI function!
+* 05-11-93 SKS Add _DllMainCRTStartup as an alternative to _CRT_INIT
+* 06-05-93 SRW Pin CRTDLL.DLL in memory once loaded.
+* 06-07-93 GJF Added __proc_attached flag.
+* 06-07-93 GJF Backed out SteveWo's change of 06-05 and put it into
+* crtlib.c
+* 06-08-93 SKS Clean up failure handling in _CRT_INIT
+* 07-16-93 SRW ALPHA Merge
+* 12-02-93 SKS Add atexit/_onexit support. These routines must be
+* defined here so that DLL's that are linked with
+* CRTDLL.LIB will get these versions (suitable for DLLs),
+* not the versions of atexit/_onexit from CRTDLL.DLL,
+* which are only suitable for an EXE file.
+* 07-18-94 GJF Moved over Win32s support from VC 2.0 tree.
+*
+*******************************************************************************/
+
+/*
+ * SPECIAL BUILD MACRO! Note that crtexe.c (and crtexew.c) is linked in with
+ * the client's code. It does not go into crtdll.dll! Therefore, it must be
+ * built under the _DLL switch (like user code) and CRTDLL must be undefined.
+ */
+#undef CRTDLL
+#define _DLL
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <stdlib.h>
+#define _DECL_DLLMAIN /* enable prototypes for DllMain and _CRT_INIT */
+#include <process.h>
+
+/*
+ * routine in DLL to do initialization (in this case, C++ constructors)
+ */
+typedef void (_CALLTYPE1 *PF)(void);
+
+extern void _CALLTYPE4 _initterm(PF *, PF *);
+
+/*
+ * pointers to initialization sections
+ */
+extern PF __xc_a[], __xc_z[]; /* C++ initializers */
+
+/*
+ * Flag identifying the host as Win32s or not-Win32s.
+ */
+int __win32sflag = 0;
+
+static int onexitflag = 0;
+
+/*
+ * flag set iff _CRTDLL_INIT was called with DLL_PROCESS_ATTACH
+ */
+static int __proc_attached = 0;
+
+/*
+ * Pointers to beginning and end of the table of function pointers manipulated
+ * by _onexit()/atexit(). The atexit/_onexit code is shared for both EXE's and
+ * DLL's but different behavior is required. These values are initialized to
+ * 0 by default and will be set to point to a malloc-ed memory block to mark
+ * this module as an DLL.
+ */
+
+PF *__onexitbegin;
+PF *__onexitend;
+
+
+/*
+ * User routine DllMain is called on all notifications
+ */
+
+extern BOOL WINAPI DllMain(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ ) ;
+
+/***
+*BOOL WINAPI _CRT_INIT(hDllHandle, dwReason, lpreserved) - C++ DLL initialization.
+*
+*Purpose:
+* This routine does the C runtime initialization for a DLL using CRTDLL.
+* It may be specified as the entry point for the DLL, or it may be
+* called by the routine that is the DLL entry point.
+*
+* On DLL_PROCESS_ATTACH, the C++ constructors for the DLL will be called.
+*
+* On DLL_PROCESS_DETACH, the C++ destructors and _onexit/atexit routines
+* will be called.
+*
+*Entry:
+*
+*Exit:
+*
+*******************************************************************************/
+
+BOOL WINAPI _CRT_INIT(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ )
+{
+ unsigned osver;
+
+ /*
+ * First, set the __proc_attached flag
+ */
+ if ( dwReason == DLL_PROCESS_ATTACH )
+ __proc_attached++;
+ else if ( dwReason == DLL_PROCESS_DETACH ) {
+ if ( __proc_attached > 0 )
+ __proc_attached--;
+ else
+ /*
+ * no prior process attach. just return failure.
+ */
+ return FALSE;
+ }
+
+ /*
+ * Get the host version (on first call).
+ */
+ if ( __win32sflag == 0 ) {
+ osver = GetVersion();
+ if ( ((osver & 0x00ff) == 3) && ((osver >> 31) & 1) )
+ __win32sflag++;
+ else
+ __win32sflag--;
+ }
+
+
+ /*
+ * do C++ constructors (initializers) specific to this DLL
+ */
+
+ if ( dwReason == DLL_PROCESS_ATTACH ) {
+
+ /*
+ * If the host is Win32s, create the onexit table and do C++
+ * constructors only for the first connecting process.
+ */
+ if ( (__win32sflag < 0) || (__proc_attached == 1) ) {
+
+ if ( __win32sflag < 0 ) {
+ /*
+ * not Win32s! just malloc the table.
+ */
+ if ( (__onexitbegin = (PF *)malloc(32 *
+ sizeof(PF))) == NULL )
+ /*
+ * cannot allocate minimal required
+ * size. generate failure to load DLL
+ */
+ return FALSE;
+ }
+ else if ( __proc_attached == 1 ) {
+ if ( (__onexitbegin =
+ (PF *)GlobalAlloc( GMEM_FIXED |
+ GMEM_SHARE, 32 * sizeof(PF) )) ==
+ NULL )
+ /*
+ * cannot allocate minimal required
+ * size. generate failure to load DLL
+ */
+ return FALSE;
+ }
+
+ *(__onexitbegin) = (PF) NULL;
+
+ __onexitend = __onexitbegin;
+
+ /*
+ * Invoke C++ constructors
+ */
+ _initterm(__xc_a,__xc_z);
+
+ }
+ }
+ else if ( dwReason == DLL_PROCESS_DETACH ) {
+
+ if ( (__win32sflag < 0) || (__proc_attached == 0) )
+ {
+ /*
+ * Any basic clean-up code that goes here must be
+ * duplicated below in _DllMainCRTStartup for the
+ * case where the user's DllMain() routine fails on a
+ * Process Attach notification. This does not include
+ * calling user C++ destructors, etc.
+ */
+
+ /*
+ * do _onexit/atexit() terminators
+ * (if there are any)
+ *
+ * These terminators MUST be executed in
+ * reverse order (LIFO)!
+ *
+ * NOTE:
+ * This code assumes that __onexitbegin
+ * points to the first valid onexit()
+ * entry and that __onexitend points
+ * past the last valid entry. If
+ * __onexitbegin == __onexitend, the
+ * table is empty and there are no
+ * routines to call.
+ */
+
+ if (__onexitbegin) {
+ PF * pfend = __onexitend;
+
+ while ( -- pfend >= __onexitbegin )
+ /*
+ * if current table entry is not
+ * NULL, call thru it.
+ */
+ if ( *pfend != NULL )
+ (**pfend)();
+
+ /*
+ * just in case Win32s doesn't clean up after
+ * us (any bets?), free the block holding
+ * onexit table
+ */
+ if ( __win32sflag > 0 )
+ GlobalFree( (HGLOBAL)__onexitbegin );
+ else
+ free(__onexitbegin);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/***
+*BOOL WINAPI _DllMainCRTStartup(hDllHandle, dwReason, lpreserved) - C++ DLL initialization.
+*
+*Purpose:
+* This is an alternative entry point for DLL's linked with the C run-time
+* libs, rather than using _CRT_INIT. The user should specify this routine
+* as the DLL entry point, and define his/her own routine DllMain to get
+* notifications in his/her code. CRT initialization/termination will be
+* done before or after calling DllMain, as appropriate.
+*
+*Entry:
+*
+*Exit:
+*
+*******************************************************************************/
+BOOL WINAPI _DllMainCRTStartup(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ )
+{
+ BOOL retcode = TRUE;
+
+ /*
+ * If this is a process detach notification, check that there has
+ * been a prior process attach notification.
+ */
+ if ( (dwReason == DLL_PROCESS_DETACH) && (__proc_attached == 0) )
+ return FALSE;
+
+ if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH )
+ retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved);
+
+ if ( retcode )
+ retcode = DllMain(hDllHandle, dwReason, lpreserved);
+
+ /*
+ * If _CRT_INIT successfully handles a Process Attach notification
+ * but the user's DllMain routine returns failure, we need to do
+ * clean-up of the C run-time similar to what _CRT_INIT does on a
+ * Process Detach Notification.
+ */
+
+ if ( dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH )
+ {
+ if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE )
+ retcode = FALSE ;
+ }
+
+ return retcode ;
+}
+
+/***
+*_onexit, atexit - calls to DLL versioons of _onexit & atexit in CRTDLL.DLL
+*
+*Purpose:
+* A DLL linked with CRTDLL.LIB must not call the standard _onexit or
+* atexit exported from CRTDLL.DLL, but an EXE linked with CRTDLL.LIB
+* will call the standard versions of those two routines. Since the
+* names are exported from CRTDLL.DLL, we must define them here for DLLs.
+* All DLLs linked with CRTDLL.LIB must pull in this startup object.
+*
+*Entry:
+* Same as the regular versions of _onexit, atexit.
+*
+*Exit:
+* Same as the regular versions of _onexit, atexit.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+extern _onexit_t _CALLTYPE1 __dllonexit(_onexit_t, PF **, PF **);
+
+_onexit_t _CALLTYPE1 _onexit (
+ _onexit_t func
+ )
+{
+ unsigned osver;
+ _onexit_t retval;
+
+ /*
+ * Get the host version (on first call).
+ */
+ if ( __win32sflag == 0 ) {
+ osver = GetVersion();
+ if ( ((osver & 0x00ff) == 3) && ((osver >> 31) & 1) )
+ __win32sflag++;
+ else
+ __win32sflag--;
+ }
+
+ /*
+ * If we are running in Win32s, test and set the flag used to
+ * serialize access. Note that we assume no process switch can take
+ * place between a successful test of the flag and the setting of
+ * the flag.
+ */
+ if ( __win32sflag > 0 ) {
+ while ( onexitflag > 0 )
+ Sleep(0);
+ onexitflag++;
+ }
+
+ retval = __dllonexit(func, &__onexitbegin, &__onexitend);
+
+ if ( __win32sflag > 0 )
+ onexitflag--;
+
+ return retval;
+}
+
+int _CALLTYPE1 atexit (
+ PF func
+ )
+{
+ return (_onexit((_onexit_t)func) == NULL) ? -1 : 0;
+}
+
+#endif /* CRTDLL */
diff --git a/private/crt32/dllstuff/crtexe.c b/private/crt32/dllstuff/crtexe.c
new file mode 100644
index 000000000..fbaa86fff
--- /dev/null
+++ b/private/crt32/dllstuff/crtexe.c
@@ -0,0 +1,215 @@
+#ifdef CRTDLL
+/***
+*crtexe.c - Initialization for client EXE using CRT DLL (Win32, Dosx32)
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Set up call to client's main() or WinMain().
+*
+*Revision History:
+* 08-12-91 GJF Module created.
+* 01-05-92 GJF Substantially revised
+* 01-17-92 GJF Restored Stevewo's scheme for unhandled exceptions.
+* 01-29-92 GJF Added support for linked-in options (equivalents of
+* binmode.obj, commode.obj and setargv.obj).
+* 04-17-92 SKS Add call to _initterm() to do C++ constructors (I386)
+* 08-01-92 SRW winxcpt.h replaced bu excpt.h which is included by oscalls.h
+* 09-16-92 SKS Prepare for C8 C++ for MIPS by calling C++ constructors
+* 04-26-93 GJF Made lpszCommandLine (unsigned char *) to deal with
+* chars > 127 in the command line.
+* 04-27-93 GJF Removed support for _RT_STACK, _RT_INTDIV,
+* _RT_INVALDISP and _RT_NONCONT.
+* 05-14-93 GJF Added support for quoted program names.
+* 07-16-93 SRW ALPHA Merge
+* 12-07-93 GJF MS C++ front-end now used on Alpha
+* 05-24-94 SRW Fix call to WinMain to match one in ..\startup\crt0.c
+*
+*******************************************************************************/
+
+/*
+ * SPECIAL BUILD MACRO! Note that crtexe.c (and crtexew.c) is linked in with
+ * the client's code. It does not go into crtdll.dll! Therefore, it must be
+ * built under the _DLL switch (like user code) and CRTDLL must be undefined.
+ */
+#undef CRTDLL
+#define _DLL
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <rterr.h>
+#include <stdlib.h>
+
+#undef _fmode /* undefine these so that we can reference the */
+#undef _commode /* local version as well as the DLL variables */
+
+extern int _CRTVAR1 _fmode; /* must match the definition in <stdlib.h> */
+extern int _commode; /* must match the definition in <internal.h> */
+
+static int _dowildcard = 0; /* passed to __GetMainArgs() */
+
+/*
+ * routine in DLL to do initialization (in this case, C++ constructors)
+ */
+typedef void (_CALLTYPE1 *PF)(void);
+
+extern void _CALLTYPE4 _initterm(PF *, PF *);
+
+/*
+ * pointers to initialization sections
+ */
+extern PF __xc_a[], __xc_z[]; /* C++ initializers */
+
+/***
+*void mainCRTStartup(void)
+*
+*Purpose:
+* This routine does the C runtime initialization, calls main(), and
+* then exits. It never returns.
+*
+*Entry:
+*
+*Exit:
+*
+*******************************************************************************/
+
+#ifdef _WINMAIN_
+void WinMainCRTStartup(
+#else
+void mainCRTStartup(
+#endif
+ void
+ )
+{
+ int argc; /* three standard arguments to main */
+ char **argv;
+ char **envp;
+
+ int mainret;
+
+#ifdef _WINMAIN_
+ unsigned char *lpszCommandLine;
+ STARTUPINFOA StartupInfo;
+#endif
+
+ /*
+ * Propogate the _fmode and _commode variables to the DLL
+ */
+
+ *_fmode_dll = _fmode;
+ *_commode_dll = _commode;
+
+ /*
+ * Call _setargv(), which will call the __setargv() in this module
+ * if SETARGV.OBJ is linked with the EXE. If SETARGV.OBJ is not
+ * linked with the EXE, a _dummy setargv() will be called.
+ */
+
+ _setargv();
+
+ /*
+ * Get the arguments for the call to main. Note this must be done
+ * explicitly, rather than as part of the dll's initialization, to
+ * implement optional expansion of wild card chars in filename args
+ */
+ __GetMainArgs(&argc, &argv, &envp, _dowildcard);
+
+ /*
+ * do C++ constructors (initializers) specific to this EXE
+ */
+ _initterm( __xc_a, __xc_z );
+
+ try {
+#ifdef _WINMAIN_
+ /*
+ * Skip past program name (first token in command line).
+ * Check for and handle quoted program name.
+ */
+ lpszCommandLine = (unsigned char *)_acmdln;
+
+ if ( *lpszCommandLine == '\"' ) {
+ /*
+ * Scan, and skip over, subsequent characters until
+ * another double-quote or a null is encountered.
+ */
+ while ( *++lpszCommandLine && (*lpszCommandLine
+ != '\"') );
+ /*
+ * If we stopped on a double-quote (usual case), skip
+ * over it.
+ */
+ if ( *lpszCommandLine == '\"' )
+ lpszCommandLine++;
+ }
+ else {
+ while (*lpszCommandLine > ' ')
+ lpszCommandLine++;
+ }
+
+ /*
+ * Skip past any white space preceeding the second token.
+ */
+ while (*lpszCommandLine && (*lpszCommandLine <= ' ')) {
+ lpszCommandLine++;
+ }
+
+ StartupInfo.dwFlags = 0;
+ GetStartupInfoA( &StartupInfo );
+
+ mainret = WinMain( GetModuleHandle(NULL),
+ NULL,
+ lpszCommandLine,
+ StartupInfo.dwFlags & STARTF_USESHOWWINDOW
+ ? StartupInfo.wShowWindow
+ : SW_SHOWDEFAULT
+ );
+#else
+ mainret = main(argc, argv, envp);
+#endif
+ exit(mainret);
+ }
+ except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
+ {
+ /*
+ * Should never reach here
+ */
+ _exit( GetExceptionCode() );
+
+ } /* end of try - except */
+
+}
+
+/***
+*__setargv - dummy version (for wildcard expansion) for CRTDLL.DLL model only
+*
+*Purpose:
+* If the EXE that is linked with CRTDLL.LIB is linked explicitly with
+* SETARGV.OBJ, the call to _setargv() in the C Run-Time start-up code
+* (above) will call this routine, instead of calling a dummy version of
+* _setargv() which will do nothing. This will set to one the static
+* variable which is passed to __GetMainArgs(), thus enabling wildcard
+* expansion of the command line arguments.
+*
+* In the statically-linked C Run-Time models, _setargv() and __setargv()
+* are the actual routines that do the work, but this code exists in
+* CRTDLL.DLL and so some tricks have to be played to make the same
+* SETARGV.OBJ work for EXE's linked with both LIBC.LIB and CRTDLL.LIB.
+*
+*Entry:
+* The static variable _dowildcard is zero (presumably).
+*
+*Exit:
+* The static variable _dowildcard is set to one, meaning that the
+* routine __GetMainArgs() in CRTDLL.DLL *will* do wildcard expansion on
+* the command line arguments. (The default behavior is that it won't.)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 __setargv ( void )
+{
+ _dowildcard = 1;
+}
+#endif /* CRTDLL */
diff --git a/private/crt32/dllstuff/crtexew.c b/private/crt32/dllstuff/crtexew.c
new file mode 100644
index 000000000..276fae13a
--- /dev/null
+++ b/private/crt32/dllstuff/crtexew.c
@@ -0,0 +1,4 @@
+#ifdef CRTDLL
+#define _WINMAIN_
+#include "crtexe.c"
+#endif /* CRTDLL */
diff --git a/private/crt32/dllstuff/crtlib.c b/private/crt32/dllstuff/crtlib.c
new file mode 100644
index 000000000..8a813c580
--- /dev/null
+++ b/private/crt32/dllstuff/crtlib.c
@@ -0,0 +1,258 @@
+#ifdef CRTDLL
+/***
+*crtlib.c - CRT DLL initialization and termination routine (Win32, Dosx32)
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains initialization entry point for the CRT DLL in
+* Win32 and Dosx32 environments. It also contains some of the supporting
+* initialization and termination code.
+*
+*Revision History:
+* 08-12-91 GJF Module created. Sort of.
+* 01-17-92 GJF Return exception code value for RTEs corresponding
+* to exceptions.
+* 01-29-92 GJF Support for wildcard expansion in filenames on the
+* command line.
+* 02-14-92 GJF Moved file inheritance stuff to ioinit.c. Call to
+* inherit() is replace by call to _ioinit().
+* 08-26-92 SKS Add _osver, _winver, _winmajor, _winminor
+* 09-04-92 GJF Replaced _CALLTYPE3 with WINAPI.
+* 09-30-92 SRW Call _heap_init before _mtinit
+* 10-19-92 SKS Add "dowildcard" parameter to GetMainArgs()
+* Prepend a second "_" to name since it is internal-only
+* 04-16-93 SKS Change call to _mtdeletelocks to _mtterm. _mtterm
+* calls _mtdeletelocks and also frees up the TLS index.
+* 04-27-93 GJF Removed support for _RT_STACK, _RT_INTDIV,
+* _RT_INVALDISP and _RT_NONCONT.
+* 05-11-93 SKS Change _CRTDLL_INIT to fail loading on failure to
+* initialize/clean up, rather than calling _amsg_exit().
+* 06-03-93 GJF Added __proc_attached flag.
+* 06-07-93 GJF Incorporated SteveWo's code to call LoadLibrary, from
+* crtdll.c.
+* 12-14-93 SKS Add _freeptd(), which frees up the per-thread data
+* maintained by the C run-time library.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <dos.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <process.h>
+#include <rterr.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * flag set iff _CRTDLL_INIT was called with DLL_PROCESS_ATTACH
+ */
+static int __proc_attached = 0;
+
+/*
+ * command line, environment, and a few other globals
+ */
+char *_acmdln; /* points to command line */
+char *_aenvptr; /* points to environment block */
+
+void (_CALLTYPE1 * _aexit_rtn)(int) = _exit; /* RT message return procedure */
+
+static void _CALLTYPE4 inherit(void); /* local function */
+
+
+/***
+*void __GetMainArgs(pargc, pargv, penvp, dowildcard) - get values for args to main()
+*
+*Purpose:
+* This function invokes the command line parsing and copies the args
+* to main back through the passsed pointers. The reason for doing
+* this here, rather than having _CRTDLL_INIT do the work and exporting
+* the __argc and __argv, is to support the linked-in option to have
+* wildcard characters in filename arguments expanded.
+*
+*Entry:
+* int *pargc - pointer to argc
+* char ***pargv - pointer to argv
+* char ***penvp - pointer to envp
+* int dowildcard - flag (true means expand wildcards in cmd line)
+*
+*Exit:
+* No return value. Values for the arguments to main() are copied through
+* the passed pointers.
+*
+*******************************************************************************/
+
+
+void _CALLTYPE1 __GetMainArgs (
+ int *pargc,
+ char ***pargv,
+ char ***penvp,
+ int dowildcard)
+{
+ if ( dowildcard )
+ __setargv(); /* do wildcard expansion after parsing args */
+ else
+ _setargv(); /* NO wildcard expansion; just parse args */
+
+ *pargc = __argc;
+ *pargv = __argv;
+ *penvp = _environ;
+}
+
+
+/***
+*BOOL _CRTDLL_INIT(hDllHandle, dwReason, lpreserved) - C DLL initialization.
+*
+*Purpose:
+* This routine does the C runtime initialization.
+*
+*Entry:
+*
+*Exit:
+*
+*******************************************************************************/
+
+BOOL WINAPI _CRTDLL_INIT(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ )
+{
+ char szDllName[ MAX_PATH ];
+
+ if ( dwReason == DLL_PROCESS_ATTACH ) {
+
+ /*
+ * Increment flag indicating process attach notification
+ * has been received.
+ */
+ __proc_attached++;
+
+ /*
+ * Pin ourselves in memory since we dont clean up if we
+ * unload.
+ */
+ if ( !GetModuleFileName( hDllHandle,
+ szDllName,
+ sizeof(szDllName))
+ )
+ {
+ strcpy(szDllName, "CRTDLL");
+ }
+ LoadLibrary(szDllName);
+ }
+ else if ( dwReason == DLL_PROCESS_DETACH ) {
+ /*
+ * if this is a process detach notification, make sure there
+ * has been a prior process attach notification.
+ */
+ if ( __proc_attached > 0 )
+ __proc_attached--;
+ else
+ /* no prior process attach, just return */
+ return FALSE;
+ }
+ else if ( dwReason == DLL_THREAD_DETACH )
+ {
+ _freeptd(NULL); /* free up per-thread CRT data */
+ }
+
+
+ /*
+ * Only do initialization when a client process attaches to
+ * the DLL.
+ */
+ if ( dwReason != DLL_PROCESS_ATTACH ) {
+ /*
+ * if a client process is detaching, make sure minimal
+ * runtime termination is performed and clean up our
+ * 'locks' (i.e., delete critical sections).
+ */
+ if ( dwReason == DLL_PROCESS_DETACH ) {
+
+ if ( _C_Termination_Done == FALSE )
+ _c_exit();
+#ifdef MTHREAD
+ _mtterm(); /* free TLS index, call _mtdeletelocks() */
+#endif
+ }
+
+ return TRUE;
+ }
+
+ _acmdln = (char *)GetCommandLine();
+ _aenvptr = (char *)GetEnvironmentStrings();
+
+ /*
+ * Get the full Win32 version
+ */
+ _osversion = /* OBSOLETE */
+ _osver = GetVersion();
+
+ _winminor = (_osver >> 8) & 0x00FF ;
+ _winmajor = _osver & 0x00FF ;
+ _winver = (_winmajor << 8) + _winminor;
+ _osver = (_osver >> 16) & 0x00FFFF ;
+
+ /* --------- The following block is OBSOLETE --------- */
+
+ /*
+ * unpack base version info
+ */
+ _baseversion = (_osversion & 0xFFFF0000) >> 16;
+ _baseminor = _baseversion & 0x00FF;
+ _basemajor = (_baseversion & 0xFF00) >> 8;
+
+ /*
+ * unpack top-level version info (Windows version)
+ */
+ _osversion &= 0x0000FFFF;
+ _osmajor = _osversion & 0x00FF;
+ _osminor = (_osversion & 0xFF00) >> 8;
+
+ /* --------- The preceding block is OBSOLETE --------- */
+
+ _heap_init(); /* initialize heap */
+#ifdef MTHREAD
+ if(!_mtinit()) /* initialize multi-thread */
+ return FALSE; /* fail DLL load on failure */
+#endif
+ _ioinit(); /* inherit file info */
+ _setenvp(); /* get environ info */
+
+ _cinit(); /* do C data initialize */
+
+ return TRUE;
+}
+
+/***
+*_amsg_exit(rterrnum) - Fast exit fatal errors
+*
+*Purpose:
+* Exit the program with error code of 255 and appropriate error
+* message.
+*
+*Entry:
+* int rterrnum - error message number (amsg_exit only).
+*
+*Exit:
+* Calls exit() (for integer divide-by-0) or _exit() indirectly
+* through _aexit_rtn [amsg_exit].
+* For multi-thread: calls _exit() function
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _amsg_exit (
+ int rterrnum
+ )
+{
+ _FF_MSGBANNER(); /* write run-time error banner */
+ _NMSG_WRITE(rterrnum); /* write message */
+
+ _aexit_rtn(255); /* normally _exit(255) */
+}
+#endif /* CRTDLL */
diff --git a/private/crt32/dllstuff/dllargv.c b/private/crt32/dllstuff/dllargv.c
new file mode 100644
index 000000000..9b6875a00
--- /dev/null
+++ b/private/crt32/dllstuff/dllargv.c
@@ -0,0 +1,49 @@
+#ifndef _POSIX_
+#ifdef CRTDLL
+/***
+*dllargv.c - Dummy _setargv() routine for use with C Run-Time as a DLL (CRTDLL)
+*
+* Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This object goes into CRTDLL.LIB, which is linked with user programs
+* to use CRTDLL.DLL for C run-time library functions. If the user
+* program links explicitly with SETARGV.OBJ, this object will not be
+* linked in, and the _setargv() that does get called with set the flag
+* that will enable wildcard expansion. If SETARGV.OBJ is not linked
+* into the EXE, this object will get called by the CRT start-up stub
+* and the flag to enable wildcard expansion will not be set.
+*
+*Revision History:
+* 10-19-92 SKS Initial version
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+
+/***
+*_setargv - dummy version for CRTDLL.DLL model only
+*
+*Purpose:
+* This routine gets called by the C Run-Time start-up code in CRTEXE.C
+* which gets linked into an EXE file linked with CRTDLL.LIB. It does
+* nothing, but if the user links the EXE with SETARGV.OBJ, this routine
+* will not get called but instead __setargv() will be called. (In the
+* CRTDLL model, it will set the variable that is passed to _GetMainArgs
+* and enable wildcard expansion in the command line arguments.)
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _setargv ( void )
+{
+ /* NOTHING */
+}
+#endif /* !_POSIX_ */
+#endif /* CRTDLL */
diff --git a/private/crt32/dllstuff/i386/dllsupp.asm b/private/crt32/dllstuff/i386/dllsupp.asm
new file mode 100644
index 000000000..33ae13262
--- /dev/null
+++ b/private/crt32/dllstuff/i386/dllsupp.asm
@@ -0,0 +1,39 @@
+ page ,132
+ title dllsupp - defines some public constants
+;***
+;dllsupp.asm - Definitions of public constants
+;
+; Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Provides definitions for public constants (absolutes) that are
+; 'normally' defined in objects in the C library, but must be defined
+; here for clients of crtdll.dll. These constants are:
+;
+; _except_list
+; _fltused
+; _ldused
+;
+;Revision History:
+; 01-23-92 GJF Module created.
+;
+;*******************************************************************************
+
+.xlist
+include cruntime.inc
+include except.inc
+.list
+
+; offset, with respect to FS, of pointer to currently active exception handler.
+; referenced by compiler generated code for SEH and by _setjmp().
+
+ public _except_list
+_except_list equ 0
+
+ public _fltused
+_fltused equ 9876h
+
+ public _ldused
+_ldused equ 9876h
+
+ end
diff --git a/private/crt32/dllstuff/makefile b/private/crt32/dllstuff/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/dllstuff/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/dllstuff/sources b/private/crt32/dllstuff/sources
new file mode 100644
index 000000000..7ea3dcdfa
--- /dev/null
+++ b/private/crt32/dllstuff/sources
@@ -0,0 +1,44 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=dllstuff
+
+TARGETNAME=dllstuff
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=dllargv.c \
+ cinitexe.c \
+ crtexe.c \
+ crtexew.c \
+ crtdll.c \
+ crtlib.c
+
+i386_SOURCES=i386\dllsupp.asm
+
diff --git a/private/crt32/dos/access.c b/private/crt32/dos/access.c
new file mode 100644
index 000000000..3dc318d22
--- /dev/null
+++ b/private/crt32/dos/access.c
@@ -0,0 +1,116 @@
+/***
+*access.c - OS/2 access function
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file has the _access() function which checks on file accessability.
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 11-10-89 JCR Replaced DOS32QUERYFILEMODE with DOS32QUERYPATHINFO
+* 03-07-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h>, fixed copyright and fixed compiler
+* warnings. Also, cleaned up the formatting a bit.
+* 03-30-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+* 04-09-91 PNT Added _MAC_ conditional
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <io.h>
+#include <oscalls.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <msdos.h>
+#include <internal.h>
+
+/***
+*int _access(path, amode) - check whether file can be accessed under mode
+*
+*Purpose:
+* Checks to see if the specified file exists and can be accessed
+* in the given mode.
+*
+*Entry:
+* char *path - pathname
+* int amode - access mode
+* (0 = exist only, 2 = write, 4 = read, 6 = read/write)
+*
+*Exit:
+* returns 0 if file has given mode
+* returns -1 and sets errno if file does not have given mode or
+* does not exist
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _access (
+ const char *path,
+ int amode
+ )
+{
+#ifdef _CRUISER_
+ FILESTATUS fs;
+ ULONG dosretval;
+
+ /* ask OS/2 about the file mode */
+ if (dosretval = DOSQUERYPATHINFO((char *)path, 1, &fs, sizeof(fs))) {
+ /* error occured -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ /* no error; see if returned premission settings OK */
+ if (fs.attrFile & FILE_READONLY
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ DWORD attr;
+
+ attr = GetFileAttributes((LPSTR)path);
+ if (attr == 0xffffffff) {
+ /* error occured -- map error code and return */
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ /* no error; see if returned premission settings OK */
+ if (attr & FILE_ATTRIBUTE_READONLY
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+ if (0
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ && (amode & 2)) {
+ /* no write permission on file, return error */
+ errno = EACCES;
+ _doserrno = E_access;
+ return -1;
+ }
+ else
+ /* file exists and has requested permission setting */
+ return 0;
+
+}
diff --git a/private/crt32/dos/chdir.c b/private/crt32/dos/chdir.c
new file mode 100644
index 000000000..2d4429d73
--- /dev/null
+++ b/private/crt32/dos/chdir.c
@@ -0,0 +1,138 @@
+/***
+*chdir.c - OS/2 change directory
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file has the _chdir() function - change current directory.
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 03-07-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h>, fixed copyright and fixed compiler
+* warnings. Also, cleaned up the formatting a bit.
+* 03-30-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+* 05-19-92 GJF Revised to support the 'current directory' environment
+* variables of Win32/NT.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <os2dll.h>
+#include <internal.h>
+#include <direct.h>
+#include <stdlib.h>
+
+/***
+*int _chdir(path) - change current directory
+*
+*Purpose:
+* Changes the current working directory to that given in path.
+*
+*Entry:
+* char *path - directory to change to
+*
+*Exit:
+* returns 0 if successful,
+* returns -1 and sets errno if unsuccessful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _chdir (
+ const char *path
+ )
+{
+#ifdef _CRUISER_
+
+ ULONG dosretval;
+
+ /* call OS/2 to set current directory */
+ dosretval = DOSSETCURRENTDIR((char *)path, 0);
+
+ if (dosretval) {
+ /* error occured -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ return 0;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+
+ char *envcurdir;
+ char dirtmp[4];
+ unsigned dirlen;
+
+ _mlock(_ENV_LOCK);
+
+ if ( SetCurrentDirectory((LPSTR)path) ) {
+
+ /*
+ * Try to update the environment variable that specifies the
+ * current directory for the drive which is the current drive.
+ * To do this, get the full current directory, build the
+ * environment variable string and call _putenv(). If an error
+ * occurs, just return to the caller.
+ *
+ * The current directory should have the form of the example
+ * below:
+ *
+ * D:\nt\private\mytests
+ *
+ * so that the environment variable should be of the form:
+ *
+ * =D:=D:\nt\private\mytests
+ *
+ */
+ if ( (dirlen = GetCurrentDirectory(0L, dirtmp)) &&
+ ((envcurdir = malloc(dirlen + 5)) != NULL) ) {
+
+ if ( GetCurrentDirectory(dirlen, &envcurdir[4])&&
+ (envcurdir[5] == ':') ) {
+ /*
+ * The current directory string has been
+ * copied into &envcurdir[3]. Prepend the
+ * special environment variable name and the
+ * '='.
+ */
+ envcurdir[0] = envcurdir[3] = '=';
+ envcurdir[1] = envcurdir[4];
+ envcurdir[2] = ':';
+ if ( _putenv_lk(envcurdir) )
+ free(envcurdir);
+ }
+ else
+ free(envcurdir);
+
+ }
+
+ _munlock(_ENV_LOCK);
+ return 0;
+ }
+ else {
+ _dosmaperr(GetLastError());
+ _munlock(_ENV_LOCK);
+ return -1;
+ }
+
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
diff --git a/private/crt32/dos/chmod.c b/private/crt32/dos/chmod.c
new file mode 100644
index 000000000..8ab9137fe
--- /dev/null
+++ b/private/crt32/dos/chmod.c
@@ -0,0 +1,121 @@
+/***
+*chmod.c - OS/2 change file attributes
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines _chmod() - change file attributes
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 11-10-89 JCR Replaced DOS32QUERYFILEMODE with DOS32QUERYPATHINFO
+* 03-07-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h>, fixed copyright and fixed compiler
+* warnings. Also, cleaned up the formatting a bit.
+* 03-30-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <io.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+
+/***
+*int _chmod(path, mode) - change file mode
+*
+*Purpose:
+* Changes file mode permission setting to that specified in
+* mode. The only XENIX mode bit supported is user write.
+*
+*Entry:
+* char *path - file name
+* int mode - mode to change to
+*
+*Exit:
+* returns 0 if successful
+* returns -1 and sets errno if not successful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _chmod (
+ const char *path,
+ int mode
+ )
+{
+#ifdef _CRUISER_
+ ULONG dosretval;
+ FILESTATUS fs;
+
+ /* query OS/2 for file attribute */
+ if (dosretval = DOSQUERYPATHINFO((char *)path, 1, &fs, sizeof(fs))) {
+ /* error occured -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ if (mode & _S_IWRITE) {
+ /* clear read only bit */
+ fs.attrFile &= ~FILE_READONLY;
+ }
+ else {
+ /* set read only bit */
+ fs.attrFile |= FILE_READONLY;
+ }
+
+ /* set new attribute */
+ if (dosretval = DOSSETPATHINFO((char *)path, 1, &fs, sizeof(fs),0)) {
+ /* error occured -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ DWORD attr;
+
+ attr = GetFileAttributes((LPSTR)path);
+ if (attr == 0xffffffff) {
+ /* error occured -- map error code and return */
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ if (mode & _S_IWRITE) {
+ /* clear read only bit */
+ attr &= ~FILE_ATTRIBUTE_READONLY;
+ }
+ else {
+ /* set read only bit */
+ attr |= FILE_ATTRIBUTE_READONLY;
+ }
+
+ /* set new attribute */
+ if (!SetFileAttributes((LPSTR)path, attr)) {
+ /* error occured -- map error code and return */
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+
+
+ return 0;
+}
diff --git a/private/crt32/dos/dosmap.c b/private/crt32/dos/dosmap.c
new file mode 100644
index 000000000..c84e399eb
--- /dev/null
+++ b/private/crt32/dos/dosmap.c
@@ -0,0 +1,252 @@
+/***
+*dosmap.c - Maps OS errors to errno values
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* _dosmaperr: Maps OS errors to errno values
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 06-16-89 PHG Changed name to _dosmaperr
+* 08-22-89 JCR ERROR_INVALID_DRIVE (15) now maps to ENOENT not EXDEV
+* 03-07-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed copyright. Also, cleaned up the
+* formatting a bit.
+* 09-27-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 04-26-91 SRW Added ERROR_LOCK_VIOLATION translation to EACCES
+* 08-15-91 GJF Multi-thread support for Win32.
+* 03-31-92 GJF Added more error codes (Win32 only) and removed OS/2
+* specific nomenclature.
+* 07-29-92 GJF Added ERROR_FILE_EXISTS to table for Win32. It gets
+* mapped it to EEXIST.
+* 09-14-92 SRW Added ERROR_BAD_PATHNAME table for Win32. It gets
+* mapped it to ENOENT.
+* 10-02-92 GJF Map ERROR_INVALID_PARAMETER to EINVAL (rather than
+* EACCES). Added ERROR_NOT_LOCKED and mapped it to
+* EACCES. Added ERROR_DIR_NOT_EMPTY and mapped it to
+* ENOTEMPTY.
+* 02-16-93 GJF Changed for new _getptd().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <errno.h>
+#include <oscalls.h>
+#include <stdlib.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/* This is the error table that defines the mapping between OS/2 and
+ System V error values */
+
+struct errentry {
+ unsigned char oscode; /* OS return value */
+ unsigned char errnocode; /* System V error code */
+};
+
+#ifdef _CRUISER_
+
+static struct errentry errtable[] = {
+ { ERROR_INVALID_FUNCTION, EINVAL }, /* 1 */
+ { ERROR_FILE_NOT_FOUND, ENOENT }, /* 2 */
+ { ERROR_PATH_NOT_FOUND, ENOENT }, /* 3 */
+ { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, /* 4 */
+ { ERROR_ACCESS_DENIED, EACCES }, /* 5 */
+ { ERROR_INVALID_HANDLE, EBADF }, /* 6 */
+ { ERROR_ARENA_TRASHED, ENOMEM }, /* 7 */
+ { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, /* 8 */
+ { ERROR_INVALID_BLOCK, ENOMEM }, /* 9 */
+ { ERROR_BAD_ENVIRONMENT, E2BIG }, /* 10 */
+ { ERROR_BAD_FORMAT, ENOEXEC }, /* 11 */
+ { ERROR_INVALID_ACCESS, EINVAL }, /* 12 */
+ { ERROR_INVALID_DATA, EINVAL }, /* 13 */
+ { ERROR_INVALID_DRIVE, ENOENT }, /* 15 */
+ { ERROR_CURRENT_DIRECTORY, EACCES }, /* 16 */
+ { ERROR_NOT_SAME_DEVICE, EXDEV }, /* 17 */
+ { ERROR_NO_MORE_FILES, ENOENT }, /* 18 */
+ { ERROR_LOCK_VIOLATION, EACCES }, /* 33 */
+ { ERROR_BAD_NETPATH, ENOENT }, /* 53 */
+ { ERROR_NETWORK_ACCESS_DENIED, EACCES }, /* 65 */
+ { ERROR_BAD_NET_NAME, ENOENT }, /* 67 */
+ { ERROR_CANNOT_MAKE, EACCES }, /* 82 */
+ { ERROR_FAIL_I24, EACCES }, /* 83 */
+ { ERROR_INVALID_PARAMETER, EINVAL }, /* 87 */
+ { ERROR_NO_PROC_SLOTS, EAGAIN }, /* 89 */
+ { ERROR_DRIVE_LOCKED, EACCES }, /* 108 */
+ { ERROR_BROKEN_PIPE, EPIPE }, /* 109 */
+ { ERROR_DISK_FULL, ENOSPC }, /* 112 */
+ { ERROR_INVALID_TARGET_HANDLE, EBADF }, /* 114 */
+ { ERROR_INVALID_HANDLE, EINVAL }, /* 124 */
+ { ERROR_WAIT_NO_CHILDREN, ECHILD }, /* 128 */
+ { ERROR_CHILD_NOT_COMPLETE, ECHILD }, /* 129 */
+ { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, /* 130 */
+ { ERROR_SEEK_ON_DEVICE, EACCES }, /* 132 */
+ { ERROR_MAX_THRDS_REACHED, EAGAIN }, /* 164 */
+ { ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */
+ { ERROR_NESTING_NOT_ALLOWED, EAGAIN } /* 215 */
+};
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+static struct errentry errtable[] = {
+ { ERROR_INVALID_FUNCTION, EINVAL }, /* 1 */
+ { ERROR_FILE_NOT_FOUND, ENOENT }, /* 2 */
+ { ERROR_PATH_NOT_FOUND, ENOENT }, /* 3 */
+ { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, /* 4 */
+ { ERROR_ACCESS_DENIED, EACCES }, /* 5 */
+ { ERROR_INVALID_HANDLE, EBADF }, /* 6 */
+ { ERROR_ARENA_TRASHED, ENOMEM }, /* 7 */
+ { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, /* 8 */
+ { ERROR_INVALID_BLOCK, ENOMEM }, /* 9 */
+ { ERROR_BAD_ENVIRONMENT, E2BIG }, /* 10 */
+ { ERROR_BAD_FORMAT, ENOEXEC }, /* 11 */
+ { ERROR_INVALID_ACCESS, EINVAL }, /* 12 */
+ { ERROR_INVALID_DATA, EINVAL }, /* 13 */
+ { ERROR_INVALID_DRIVE, ENOENT }, /* 15 */
+ { ERROR_CURRENT_DIRECTORY, EACCES }, /* 16 */
+ { ERROR_NOT_SAME_DEVICE, EXDEV }, /* 17 */
+ { ERROR_NO_MORE_FILES, ENOENT }, /* 18 */
+ { ERROR_LOCK_VIOLATION, EACCES }, /* 33 */
+ { ERROR_BAD_NETPATH, ENOENT }, /* 53 */
+ { ERROR_NETWORK_ACCESS_DENIED, EACCES }, /* 65 */
+ { ERROR_BAD_NET_NAME, ENOENT }, /* 67 */
+ { ERROR_FILE_EXISTS, EEXIST }, /* 80 */
+ { ERROR_CANNOT_MAKE, EACCES }, /* 82 */
+ { ERROR_FAIL_I24, EACCES }, /* 83 */
+ { ERROR_INVALID_PARAMETER, EINVAL }, /* 87 */
+ { ERROR_NO_PROC_SLOTS, EAGAIN }, /* 89 */
+ { ERROR_DRIVE_LOCKED, EACCES }, /* 108 */
+ { ERROR_BROKEN_PIPE, EPIPE }, /* 109 */
+ { ERROR_DISK_FULL, ENOSPC }, /* 112 */
+ { ERROR_INVALID_TARGET_HANDLE, EBADF }, /* 114 */
+ { ERROR_INVALID_HANDLE, EINVAL }, /* 124 */
+ { ERROR_WAIT_NO_CHILDREN, ECHILD }, /* 128 */
+ { ERROR_CHILD_NOT_COMPLETE, ECHILD }, /* 129 */
+ { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, /* 130 */
+ { ERROR_NEGATIVE_SEEK, EINVAL }, /* 131 */
+ { ERROR_SEEK_ON_DEVICE, EACCES }, /* 132 */
+ { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, /* 145 */
+ { ERROR_NOT_LOCKED, EACCES }, /* 158 */
+ { ERROR_BAD_PATHNAME, ENOENT }, /* 161 */
+ { ERROR_MAX_THRDS_REACHED, EAGAIN }, /* 164 */
+ { ERROR_LOCK_FAILED, EACCES }, /* 167 */
+ { ERROR_ALREADY_EXISTS, EEXIST }, /* 183 */
+ { ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */
+ { ERROR_NESTING_NOT_ALLOWED, EAGAIN } /* 215 */
+};
+
+#else /* ndef _WIN32 */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+/* size of the table */
+#define ERRTABLESIZE (sizeof(errtable)/sizeof(errtable[0]))
+
+/* The following two constants must be the minimum and maximum
+ values in the (contiguous) range of Exec Failure errors. */
+#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
+#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
+
+/* These are the low and high value in the range of errors that are
+ access violations */
+#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
+#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
+
+
+/***
+*void _dosmaperr(ULONG oserrno) - Map function number
+*
+*Purpose:
+* This function takes an OS error number, and maps it to the
+* corresponding errno value (based on UNIX System V values). The
+* OS error number is stored in _doserrno (and the mapped value is
+* stored in errno)
+*
+*Entry:
+* ULONG os2errno = OS error value
+*
+*Exit:
+* sets _doserrno and errno.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _dosmaperr (
+ ULONG oserrno
+ )
+{
+ int i;
+
+ _doserrno = oserrno; /* set _doserrno */
+
+ /* check the table for the OS error code */
+ for (i = 0; i < ERRTABLESIZE; ++i) {
+ if (oserrno == errtable[i].oscode) {
+ errno = errtable[i].errnocode;
+ return;
+ }
+ }
+
+ /* The error code wasn't in the table. We check for a range of */
+ /* EACCES errors or exec failure errors (ENOEXEC). Otherwise */
+ /* EINVAL is returned. */
+
+ if (oserrno >= MIN_EACCES_RANGE && oserrno <= MAX_EACCES_RANGE)
+ errno = EACCES;
+ else if (oserrno >= MIN_EXEC_ERROR && oserrno <= MAX_EXEC_ERROR)
+ errno = ENOEXEC;
+ else
+ errno = EINVAL;
+}
+
+#ifdef MTHREAD
+
+#ifdef _WIN32_
+
+/***
+*int * _errno() - return pointer to thread's errno
+*unsigned long * __doserrno() - return pointer to thread's _doserrno
+*
+*Purpose:
+* _errno() returns a pointer to the _terrno field in the current
+* thread's _tiddata structure.
+* __doserrno returns a pointer to the _tdoserrno field in the current
+* thread's _tiddata structure
+*
+*Entry:
+* None.
+*
+*Exit:
+* See above.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int * _CRTAPI1 _errno(
+ void
+ )
+{
+ return ( &(_getptd()->_terrno) );
+}
+
+unsigned long * _CRTAPI1 __doserrno(
+ void
+ )
+{
+ return ( &(_getptd()->_tdoserrno) );
+}
+
+#endif /* _WIN32_ */
+
+#endif /* MTHREAD */
diff --git a/private/crt32/dos/drive.c b/private/crt32/dos/drive.c
new file mode 100644
index 000000000..02b85263b
--- /dev/null
+++ b/private/crt32/dos/drive.c
@@ -0,0 +1,208 @@
+/***
+*drive.c - get and change current drive
+*
+* Copyright (c) 1989-1995, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file has the _getdrive() and _chdrive() functions
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 03-07-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed copyright. Also, cleaned up
+* the formatting a bit.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 05-10-91 GJF Fixed off-by-1 error in Win32 version and updated the
+* function descriptions a bit [_WIN32_].
+* 05-19-92 GJF Revised to use the 'current directory' environment
+* variables of Win32/NT.
+* 06-09-92 GJF Use _putenv instead of Win32 API call. Also, defer
+* adding env var until after the successful call to
+* change the dir/drive.
+* 04-06-93 SKS Replace _CRTAPI* with __cdecl
+* 11-24-93 CFW Rip out Cruiser.
+* 11-24-93 CFW No longer store current drive in CRT env strings.
+* 02-08-95 JWM Spliced _WIN32 & Mac versions.
+*
+*******************************************************************************/
+
+#ifdef _WIN32
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <os2dll.h>
+#include <internal.h>
+#include <msdos.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/***
+*int _getdrive() - get current drive (1=A:, 2=B:, etc.)
+*
+*Purpose:
+* Returns the current disk drive
+*
+*Entry:
+* No parameters.
+*
+*Exit:
+* returns 1 for A:, 2 for B:, 3 for C:, etc.
+* returns 0 if current drive cannot be determined.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int __cdecl _getdrive (
+ void
+ )
+{
+ ULONG drivenum;
+ UCHAR curdirstr[_MAX_PATH];
+
+ drivenum = 0;
+ if (GetCurrentDirectory(sizeof(curdirstr), curdirstr))
+ if (curdirstr[1] == ':')
+ drivenum = toupper(curdirstr[0]) - 64;
+
+ return drivenum;
+}
+
+
+/***
+*int _chdrive(int drive) - set the current drive (1=A:, 2=B:, etc.)
+*
+*Purpose:
+* Allows the user to change the current disk drive
+*
+*Entry:
+* drive - the number of drive which should become the current drive
+*
+*Exit:
+* returns 0 if successful, else -1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int __cdecl _chdrive (
+ int drive
+ )
+{
+ char newdrive[3];
+
+ if (drive < 1 || drive > 31) {
+ errno = EACCES;
+ _doserrno = ERROR_INVALID_DRIVE;
+ return -1;
+ }
+
+ _mlock(_ENV_LOCK);
+
+ newdrive[0] = (char)('A' + (char)drive - (char)1);
+ newdrive[1] = ':';
+ newdrive[2] = '\0';
+
+ /*
+ * Set new drive. If current directory on new drive exists, it
+ * will become the cwd. Otherwise defaults to root directory.
+ */
+
+ if ( SetCurrentDirectory((LPSTR)newdrive) ) {
+ _munlock(_ENV_LOCK);
+ return 0;
+ }
+ else {
+ _dosmaperr(GetLastError());
+ _munlock(_ENV_LOCK);
+ return -1;
+ }
+}
+
+#else /* ndef _WIN32 */
+
+#include <cruntime.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <macos\osutils.h>
+#include <macos\files.h>
+#include <macos\errors.h>
+
+/***
+*int _getdrive() - get current drive (-1=BootDisk, -2=Second mounted drive, etc.)
+*
+*Purpose:
+* Returns the current disk drive
+*
+*Entry:
+* No parameters.
+*
+*Exit:
+* returns 1 for BootDisk, 2 for Second mounted drive, etc.
+* returns 0 if current drive cannot be determined.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _getdrive (
+ void
+ )
+{
+ OSErr osErr;
+ WDPBRec wdPB;
+ char st[256];
+
+ wdPB.ioNamePtr = &st[0];
+ osErr = PBHGetVolSync(&wdPB);
+ if (osErr) {
+ return 0;
+ }
+
+
+ return wdPB.ioWDVRefNum;
+}
+
+
+/***
+*int _chdrive(int drive) - set the current drive (-1=BootDisk, -2=Second drive, etc.)
+*
+*Purpose:
+* Allows the user to change the current disk drive
+*
+*
+*Entry:
+* drive - the number of drive which should become the current drive
+*
+*Exit:
+* returns 0 if successful, else -1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _chdrive (
+ int drive
+ )
+{
+ OSErr osErr;
+ WDPBRec wdPB;
+
+ wdPB.ioNamePtr = NULL;
+ wdPB.ioWDDirID = 0;
+ wdPB.ioVRefNum = drive;
+ osErr = PBHSetVolSync(&wdPB);
+ if (osErr) {
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif /* _WIN32 */
diff --git a/private/crt32/dos/fullpath.c b/private/crt32/dos/fullpath.c
new file mode 100644
index 000000000..30f27dfe4
--- /dev/null
+++ b/private/crt32/dos/fullpath.c
@@ -0,0 +1,318 @@
+/***
+*fullpath.c -
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose: contains the function _fullpath which makes an absolute path out
+* of a relative path. i.e. ..\pop\..\main.c => c:\src\main.c if the
+* current directory is c:\src\src
+*
+*Revision History:
+*
+* 12-21-87 WAJ Initial version
+* 01-08-88 WAJ now treats / as an \
+* 06-22-88 WAJ now handles network paths ie \\sl\users
+* 01-31-89 SKS/JCR Renamed _canonic to _fullpath
+* 04-03-89 WAJ Now returns "d:\dir" for "."
+* 05-09-89 SKS Do not change the case of arguments
+* 11-30-89 JCR Preserve errno setting from _getdcwd() call on errors
+* 03-07-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and fixed
+* the copyright.
+* 04-25-90 JCR Fixed an incorrect errno setting
+* 06-14-90 SBM Fixed bugs in which case of user provided drive letter
+* was not always preserved, and c:\foo\\bar did not
+* generate an error
+* 08-10-90 SBM Compiles cleanly with -W3
+* 08-28-90 SBM Fixed bug in which UNC names were being rejected
+* 09-27-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 11-30-92 KRS Ported _MBCS code from 16-bit tree.
+* 08-03-93 KRS Change to use _ismbstrail instead of isdbcscode.
+* 09-27-93 CFW Avoid cast bug.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <direct.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <internal.h>
+#include <ctype.h>
+#ifdef _MBCS
+#include <mbdata.h>
+#include <mbctype.h>
+#endif
+
+
+#define ISSLASH(a) ((a) == '\\' || (a) == '/')
+
+/***
+*char *_fullpath( char *buf, const char *path, maxlen );
+*
+*Purpose:
+*
+* _fullpath - combines the current directory with path to form
+* an absolute path. i.e. _fullpath takes care of .\ and ..\
+* in the path.
+*
+* The result is placed in buf. If the length of the result
+* is greater than maxlen NULL is returned, otherwise
+* the address of buf is returned.
+*
+* If buf is NULL then a buffer is malloc'ed and maxlen is
+* ignored. If there are no errors then the address of this
+* buffer is returned.
+*
+* If path specifies a drive, the curent directory of this
+* drive is combined with path. If the drive is not valid
+* and _fullpath needs the current directory of this drive
+* then NULL is returned. If the current directory of this
+* non existant drive is not needed then a proper value is
+* returned.
+* For example: path = "z:\\pop" does not need z:'s current
+* directory but path = "z:pop" does.
+*
+*
+*
+*Entry:
+* char *buf - pointer to a buffer maintained by the user;
+* char *path - path to "add" to the current directory
+* int maxlen - length of the buffer pointed to by buf
+*
+*Exit:
+* Returns pointer to the buffer containing the absolute path
+* (same as buf if non-NULL; otherwise, malloc is
+* used to allocate a buffer)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+char * _CALLTYPE1 _fullpath (
+ char *UserBuf,
+ const char *path,
+ size_t maxlen
+ )
+{
+ char *RetValue;
+ char *buf;
+ char *StartBuf;
+ char *EndBuf;
+ char *SaveBuf;
+ char c;
+ int count;
+ unsigned drive;
+#ifdef _MBCS
+const char *StartPath = path;
+#endif
+
+
+ if( !path || !*path ) /* no work to do */
+ return( _getcwd( UserBuf, maxlen ) );
+
+ /* allocate buffer if necessary */
+
+ if( !UserBuf )
+ if( !(buf = malloc(_MAX_PATH)) ){
+ errno = ENOMEM;
+ return( NULL );
+ }
+ else
+ maxlen = _MAX_PATH;
+
+ else {
+ if( maxlen < _MAX_DRIVE+1 ){ /* we need at least 4 chars for "A:\" */
+ errno = ERANGE;
+ return( NULL );
+ }
+ buf = UserBuf;
+ }
+
+ RetValue = buf;
+ EndBuf = buf + maxlen - 1;
+
+ if( ISSLASH(*(path+1)) && ISSLASH(*path) ){ /* check for network drive */
+
+ count = 0; /* count the '\\'s */
+ while( (c = *path) ){
+ *buf = c;
+ path++;
+
+ if( buf >= EndBuf ){
+ReturnError1:
+ errno = ERANGE;
+ReturnError2:
+ if( UserBuf == NULL )
+ free( RetValue );
+ return( NULL );
+ }
+
+#ifdef _MBCS
+ if ( !_ISLEADBYTE(*(buf-2)))
+#endif
+ if( ISSLASH( c ) ){
+ /* ensure that path contains a '\\', not a '/' */
+ *buf = '\\';
+
+ /* ensure that '\\\\' is followed by something */
+ if( ++count == 2 ){
+ if( !*path ){
+ errno = EINVAL;
+ goto ReturnError2;
+ }
+ }
+
+ /* check that third and fourth '\\'are preceded by non-'\\' */
+ if( count >= 3 ){
+ if( *(buf-1) == '\\' ){
+ errno = EINVAL;
+ goto ReturnError2;
+ }
+ }
+
+ /* stop on fourth '\\', \\foo\bar\ <-- namely this one */
+ if( count == 4 )
+ break;
+ }
+
+ buf++;
+ }
+
+ *buf = '\\';
+ StartBuf = buf;
+ }
+
+ else { /* not a UNC path */
+
+ if( path[1] == ':' && isalpha((unsigned char)path[0]) ) { /* get drive information */
+ *buf = *path;
+ /*
+ ** drive must be in the range 1-26
+ ** "*buf" may be upper or lower case
+ */
+ drive = (*buf++ - 'A' + 1) & 0x1F;
+ *buf++ = ':';
+ path += 2;
+ }
+ else
+ drive = 0;
+
+ if( ISSLASH( *path ) ){
+ if( drive == 0 ){
+ *buf++ = (char)(_getdrive() + 'A' - 1);
+ *buf++ = ':';
+ }
+
+ path++;
+ }
+
+ else {
+ /* preserve the driveletter in original case from path,
+ since _getdcwd will always return it in upper case */
+ if (drive)
+ c = *(path-2);
+ if( !_getdcwd( drive, RetValue, maxlen ) )
+ goto ReturnError2; /* error: preserve errno value */
+ buf = RetValue + strlen( RetValue );
+ /* restore drive letter in original case */
+ if (drive)
+ *RetValue = c;
+#ifdef _MBCS
+ if (!_ISLEADBYTE(*(buf-2)))
+#endif
+ if( ISSLASH( *(buf-1) ) ) /* buf must point to last slash */
+ buf--; /* if this is a root directory */
+ }
+
+ *buf = '\\';
+ StartBuf = RetValue + 2;
+ }
+
+
+ while( *path ){
+
+ if( *path == '.'
+ && *(path+1) == '.'
+ && ( ISSLASH(*(path+2)) || !*(path+2) ) ){ /* handle .. */
+
+ do{
+ buf--;
+#ifdef _MBCS
+ if (ISSLASH(*buf))
+ if (_ismbstrail(StartBuf,buf))
+ buf--;
+#endif
+ }
+ while( !ISSLASH( *buf ) && buf > StartBuf );
+
+ if( buf < StartBuf ) { /* unable to do cd .. */
+ errno = EACCES;
+ goto ReturnError2;
+ }
+
+ path += 2;
+ if( *path ) /* if it was "..\" */
+ path++;
+ }
+
+ else if( *path == '.' && ( ISSLASH(*(path+1)) || !*(path+1) )){
+
+ path++; /* handle . */
+ if( *path ) /* if it was ".\" */
+ path++;
+ }
+
+ else {
+ SaveBuf = buf; /* save for DBCS-safe test for null path */
+
+ while((*path) && (!ISSLASH(*path)) && (buf < EndBuf)) {
+ *++buf = *path++;
+#ifdef _MBCS
+ if (_ISLEADBYTE(*(path-1)))
+ {
+ if ((*path) && (buf < EndBuf))
+ *++buf = *path++;
+ else
+ { /* ill-formed DBCS character */
+ errno = EINVAL;
+ goto ReturnError2;
+ }
+ }
+#endif
+ }
+
+ if( buf >= EndBuf ) /* if buf == EndBuf then */
+ goto ReturnError1; /* no room for '\0' */
+
+ /* DBCS-safe test for non-empty path component */
+ if ((buf==SaveBuf) /* && (*buf=='\\') */ ) /* 2nd test redundent */
+ {
+ errno = EINVAL;
+ goto ReturnError2;
+ }
+
+ *++buf = '\\';
+ if( ISSLASH( *path ) )
+#ifdef _MBCS
+ if (!_ismbstrail(StartPath,path))
+#endif
+ path++;
+ }
+ }
+
+
+ /* buf points to last character in the string which is an '\\' */
+
+ if( *(buf-1) == ':' ) /* keep trailing '\' if */
+#ifdef _MBCS
+ if (!_ismbstrail(StartBuf,buf-1))
+#endif
+ buf++; /* this is a root directory */
+ *buf = '\0';
+
+ return( RetValue );
+}
diff --git a/private/crt32/dos/getcwd.c b/private/crt32/dos/getcwd.c
new file mode 100644
index 000000000..e2c8042a2
--- /dev/null
+++ b/private/crt32/dos/getcwd.c
@@ -0,0 +1,451 @@
+/***
+*getcwd.c - get current working directory (OS/2 version)
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+* contains functions _getcwd, _getdcwd and _getcdrv for getting the
+* current working directory. getcwd gets the c.w.d. for the default disk
+* drive, whereas _getdcwd allows one to get the c.w.d. for whatever disk
+* drive is specified. _getcdrv gets the current drive.
+*
+*Revision History:
+* 09-09-83 RKW created
+* 05-??-84 DCW added conditional compilation to handle case of library
+* where SS != DS (can't take address of a stack variable).
+* 09-??-84 DCW changed comparison of path length to maxlen to take the
+* terminating null character into account.
+* 11-28-84 DCW changed to return errno values compatibly with the
+* System 3 version.
+* 05-19-86 SKS adapted for OS/2
+* 11-19-86 SKS if pnbuf==NULL, maxlen is ignored;
+* eliminated use of intermediate buffer "buf[]"; added
+* entry point "_getdcwd()" which takes a drive number.
+* 12-03-86 SKS if pnbuf==NULL, maxlen is the minimum allocation size
+* 02-05-87 BCM fixed comparison in _getdcwd,
+* (unsigned)(len+3) > (int)(maxlen), to handle maxlen < 0,
+* since implicit cast to (unsigned) was occurring.
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 12-21-87 WAJ Added _getcdrv()
+* 06-22-88 WAJ _getcdrv() is now made for all OS/2 libs
+* 10-03-88 JCR 386: Change DOS calls to SYS calls
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 10-10-88 GJF Made API names match DOSCALLS.H
+* 01-31-89 JCR Remove _getcdrv(), which has been renamed _getdrive()
+* 04-12-89 JCR Use new OS/2 system calls
+* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
+* 11-27-89 JCR Corrected ERRNO values
+* 12-12-89 JCR Fixed bogus syscall introduced in previous fix (oops)
+* 03-07-90 GJF Replaced _LOAD_DS by _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h>, removed
+* some leftover 16-bit support and fixed the copyright.
+* Also, cleaned up the formatting a bit.
+* 07-24-90 SBM Compiles cleanly with -W3 (removed unreferenced
+* variable), removed redundant includes, removed
+* '32' from API names
+* 08-10-90 SBM Compiles cleanly with -W3 with new build of compiler
+* 09-27-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+* 08-21-91 JCR Test DOSQUERYCURRENTDIR call for error return (bug fix)
+* 04-23-92 GJF Fixed initialization of DriveVar[].
+* 04-28-92 GJF Revised Win32 version.
+* 12-13-93 GJF In _getdcwd(), was using local array to hold env
+* string which was _putenv-ed. Ouch!
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <os2dll.h>
+#include <msdos.h>
+#include <errno.h>
+#include <malloc.h>
+#include <oscalls.h>
+#include <stdlib.h>
+#include <internal.h>
+#include <direct.h>
+
+
+#ifdef _CRUISER_
+
+/***
+*char *_getcwd(pnbuf, maxlen) - get current working directory of default drive
+*
+*Purpose:
+* _getcwd gets the current working directory for the user,
+* placing it in the buffer pointed to by pnbuf. It returns
+* the length of the string put in the buffer. If the length
+* of the string exceeds the length of the buffer, maxlen,
+* then NULL is returned. If pnbuf = NULL, maxlen is ignored.
+* An entry point "_getdcwd()" is defined with takes the above
+* parameters, plus a drive number. "_getcwd()" is implemented
+* as a call to "_getcwd()" with the default drive (0).
+*
+* If pnbuf = NULL, maxlen is ignored, and a buffer is automatically
+* allocated using malloc() -- a pointer to which is returned by
+* _getcwd().
+*
+* side effects: no global data is used or affected
+*
+*Entry:
+* char *pnbuf = pointer to a buffer maintained by the user;
+* int maxlen = length of the buffer pointed to by pnbuf;
+*
+*Exit:
+* Returns pointer to the buffer containing the c.w.d. name
+* (same as pnbuf if non-NULL; otherwise, malloc is
+* used to allocate a buffer)
+*
+*Exceptions:
+*******************************************************************************/
+
+/*
+** _getcwd() is just a call to _getdcwd() with the default drive
+*/
+
+char * _CALLTYPE1 _getcwd (
+ char *pnbuf,
+ int maxlen
+ )
+{
+ return(_getdcwd(0, pnbuf, maxlen));
+}
+
+
+/***
+*char *_getdcwd(drive, pnbuf, maxlen) - get c.w.d. for given drive
+*
+*Purpose:
+* _getdcwd gets the current working directory for the user,
+* placing it in the buffer pointed to by pnbuf. It returns
+* the length of the string put in the buffer. If the length
+* of the string exceeds the length of the buffer, maxlen,
+* then NULL is returned. If pnbuf = NULL, maxlen is ignored,
+* and a buffer is automatically allocated using malloc() --
+* a pointer to which is returned by _getdcwd().
+*
+* side effects: no global data is used or affected
+*
+*Entry:
+* int drive - number of the drive being inquired about
+* 0 = default, 1 = 'a:', 2 = 'b:', etc.
+* char *pnbuf - pointer to a buffer maintained by the user;
+* int maxlen - length of the buffer pointed to by pnbuf;
+*
+*Exit:
+* Returns pointer to the buffer containing the c.w.d. name
+* (same as pnbuf if non-NULL; otherwise, malloc is
+* used to allocate a buffer)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _getdcwd (
+ int drive,
+ char *pnbuf,
+ REG2 int maxlen
+ )
+{
+ REG1 char *p;
+ char dirbuf[1];
+
+ unsigned len = 1;
+ unsigned oserr;
+
+ /*
+ ** Get default drive if necessary
+ */
+ if (drive == 0)
+ drive = _getdrive();
+
+ /*
+ ** Ask DOS the length of the current directory string
+ */
+
+ if ((oserr = DOSQUERYCURRENTDIR(drive,(char *)dirbuf,(unsigned *)&len))
+ != ERROR_BUFFER_OVERFLOW) {
+ oserr_rtn: /* common error return */
+ errno = EACCES; /* probably bogus drive */
+ _doserrno = oserr;
+ return(NULL);
+ }
+
+ /* see if need to try to allocate buffer in heap */
+
+ if (!(p = pnbuf)) {
+ if (((int)len+3) > maxlen)
+ maxlen = len+3;
+ if (!(p = malloc(maxlen))) {
+ errno = ENOMEM;
+ _doserrno = E_nomem;
+ return(p);
+ }
+ pnbuf = p;
+ }
+
+ /* set up string - prepend drive letter + colon to the path name
+ */
+
+ *p++ = (char)(drive + 'A' - 1); /* drive specifier */
+ *p++ = ':';
+ *p++ = '\\';
+
+ /* check to make sure it all fits in the supplied (or created) buffer.
+ */
+
+ if ((int)len+3 > maxlen) {
+ errno = ERANGE; /* Won't fit in user buffer */
+ return(NULL);
+ }
+
+ /* get root relative path name
+ */
+
+ if (oserr = DOSQUERYCURRENTDIR(drive,(char *)p,(unsigned *)&len))
+ goto oserr_rtn; /* join other DOSQUERYCURRENTDIRDIR error return */
+
+ return(p-3);
+
+}
+
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+
+/***
+*char *_getcwd(pnbuf, maxlen) - get current working directory of default drive
+*
+*Purpose:
+* _getcwd gets the current working directory for the user,
+* placing it in the buffer pointed to by pnbuf. It returns
+* the length of the string put in the buffer. If the length
+* of the string exceeds the length of the buffer, maxlen,
+* then NULL is returned. If pnbuf = NULL, maxlen is ignored.
+* An entry point "_getdcwd()" is defined with takes the above
+* parameters, plus a drive number. "_getcwd()" is implemented
+* as a call to "_getcwd()" with the default drive (0).
+*
+* If pnbuf = NULL, maxlen is ignored, and a buffer is automatically
+* allocated using malloc() -- a pointer to which is returned by
+* _getcwd().
+*
+* side effects: no global data is used or affected
+*
+*Entry:
+* char *pnbuf = pointer to a buffer maintained by the user;
+* int maxlen = length of the buffer pointed to by pnbuf;
+*
+*Exit:
+* Returns pointer to the buffer containing the c.w.d. name
+* (same as pnbuf if non-NULL; otherwise, malloc is
+* used to allocate a buffer)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+char * _CALLTYPE1 _getcwd (
+ char *pnbuf,
+ int maxlen
+ )
+{
+ char *retval;
+
+ _mlock(_ENV_LOCK);
+
+ retval = _getdcwd_lk(0, pnbuf, maxlen);
+
+ _munlock(_ENV_LOCK);
+
+ return retval;
+}
+
+
+/***
+*char *_getdcwd(drive, pnbuf, maxlen) - get c.w.d. for given drive
+*
+*Purpose:
+* _getdcwd gets the current working directory for the user,
+* placing it in the buffer pointed to by pnbuf. It returns
+* the length of the string put in the buffer. If the length
+* of the string exceeds the length of the buffer, maxlen,
+* then NULL is returned. If pnbuf = NULL, maxlen is ignored,
+* and a buffer is automatically allocated using malloc() --
+* a pointer to which is returned by _getdcwd().
+*
+* side effects: no global data is used or affected
+*
+*Entry:
+* int drive - number of the drive being inquired about
+* 0 = default, 1 = 'a:', 2 = 'b:', etc.
+* char *pnbuf - pointer to a buffer maintained by the user;
+* int maxlen - length of the buffer pointed to by pnbuf;
+*
+*Exit:
+* Returns pointer to the buffer containing the c.w.d. name
+* (same as pnbuf if non-NULL; otherwise, malloc is
+* used to allocate a buffer)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+#ifdef MTHREAD
+
+char * _CALLTYPE1 _getdcwd (
+ int drive,
+ char *pnbuf,
+ int maxlen
+ )
+{
+ char *retval;
+
+ _mlock(_ENV_LOCK);
+
+ retval = _getdcwd_lk(drive, pnbuf, maxlen);
+
+ _munlock(_ENV_LOCK);
+
+ return retval;
+}
+
+char * _CALLTYPE1 _getdcwd_lk (
+ int drive,
+ char *pnbuf,
+ int maxlen
+ )
+#else
+
+char * _CALLTYPE1 _getdcwd (
+ int drive,
+ char *pnbuf,
+ int maxlen
+ )
+#endif
+
+{
+ char *p;
+ char dirbuf[1];
+ int len;
+ char DirOnDriveVar[4];
+ char *envval;
+
+ /*
+ * Only works for default drive in Win32 environment.
+ */
+ if ( drive != 0 ) {
+ /*
+ * Not the default drive - make sure it's valid.
+ */
+ if ( !_ValidDrive(drive) ) {
+ errno = EACCES;
+ return NULL;
+ }
+
+ /*
+ * Get special environment variable that specifies the current
+ * directory on drive.
+ */
+ DirOnDriveVar[0] = '=';
+ DirOnDriveVar[1] = (char)('A' + (char)drive - (char)1);
+ DirOnDriveVar[2] = ':';
+ DirOnDriveVar[3] = '\0';
+
+ if ( (envval = _getenv_lk(DirOnDriveVar)) == NULL ) {
+
+ /*
+ * Need to define the environment variable, allocate
+ * space from the heap to hold the string
+ */
+ if ( (envval = malloc( 8 * sizeof(char) )) == NULL ) {
+ errno = ENOMEM; /* must be out of heap memory */
+ return NULL;
+ }
+
+ /*
+ * Environment variable not defined! Define it to be the
+ * root on that drive.
+ */
+ envval[0] = envval[3] = '=';
+ envval[1] = envval[4] = (char)('A' + (char)drive
+ - (char)1);
+ envval[2] = envval[5] = ':';
+ envval[6] = '\\';
+ envval[7] = '\0';
+ if ( _putenv_lk(envval) != 0 ) {
+ errno = ENOMEM; /* must be out of heap memory */
+ return NULL;
+ }
+ envval += 4;
+ }
+
+ len = strlen(envval) + 1;
+
+ } else {
+
+ /*
+ * Ask OS the length of the current directory string
+ */
+ len = GetCurrentDirectory(sizeof(dirbuf), (LPSTR)dirbuf) + 1;
+ }
+
+ /*
+ * Set up the buffer.
+ */
+ if ( (p = pnbuf) == NULL ) {
+ /*
+ * Allocate a buffer for the user.
+ */
+ if ( (p = malloc(__max(len, maxlen))) == NULL ) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+ else if ( len > maxlen ) {
+ /*
+ * Won't fit in the user-supplied buffer!
+ */
+ errno = ERANGE; /* Won't fit in user buffer */
+ return NULL;
+ }
+
+ /*
+ * Place the current directory string into the user buffer
+ */
+
+ if ( drive != 0 )
+ /*
+ * Copy value of special environment variable into user buffer.
+ */
+ strcpy(p, envval);
+ else
+ /*
+ * Get the current directory directly from the OS
+ */
+ if ( GetCurrentDirectory(len,p) == 0 ) {
+ /*
+ * Oops. For lack of a better idea, assume some sort
+ * of access error has occurred.
+ */
+ errno = EACCES;
+ _doserrno = GetLastError();
+ return NULL;
+ }
+
+ return p;
+}
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
diff --git a/private/crt32/dos/getpid.c b/private/crt32/dos/getpid.c
new file mode 100644
index 000000000..b3967bf87
--- /dev/null
+++ b/private/crt32/dos/getpid.c
@@ -0,0 +1,72 @@
+/***
+*getpid.c - OS/2 get current process id
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines _getpid() - get current process id
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 10-27-89 JCR Added new Dos32GetThreadInfo code (under DCR757 switch)
+* 11-17-89 JCR Enabled DOS32GETTHREADINFO code (DCR757)
+* 03-07-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed copyright. Also, cleaned up the
+* formatting a bit.
+* 07-02-90 GJF Removed pre-DCR757 stuff.
+* 08-08-90 GJF Changed API prefix from DOS32 to DOS
+* 10-03-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-28-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+
+/***
+*int _getpid() - get current process id
+*
+*Purpose:
+* Returns the current process id for the calling process.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns the current process id.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _getpid (
+ void
+ )
+{
+#ifdef _CRUISER_
+ PTIB tid_info; /* thread info */
+ PPIB pid_info; /* process info */
+
+ DOSGETTHREADINFO(&tid_info, &pid_info);
+
+ return(pid_info->pib_ulpid); /* return process id */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ return GetCurrentProcessId();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
diff --git a/private/crt32/dos/makefile b/private/crt32/dos/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/dos/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/dos/mkdir.c b/private/crt32/dos/mkdir.c
new file mode 100644
index 000000000..42431ab9e
--- /dev/null
+++ b/private/crt32/dos/mkdir.c
@@ -0,0 +1,80 @@
+/***
+*mkdir.c - OS/2 make directory
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines function _mkdir() - make a directory
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 03-07-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h>, fixed compiler warnings and fixed the
+* copyright. Also, cleaned up the formatting a bit.
+* 03-30-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <direct.h>
+
+/***
+*int _mkdir(path) - make a directory
+*
+*Purpose:
+* creates a new directory with the specified name
+*
+*Entry:
+* char *path - name of new directory
+*
+*Exit:
+* returns 0 if successful
+* returns -1 and sets errno if unsuccessful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _mkdir (
+ const char *path
+ )
+{
+ ULONG dosretval;
+
+ /* ask OS to create directory */
+#ifdef _CRUISER_
+
+ dosretval = DOSCREATEDIR((char *)path, 0, 0);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (!CreateDirectory((LPSTR)path, (LPSECURITY_ATTRIBUTES)NULL))
+ dosretval = GetLastError();
+ else
+ dosretval = 0;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ if (dosretval) {
+ /* error occured -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/private/crt32/dos/rename.c b/private/crt32/dos/rename.c
new file mode 100644
index 000000000..5aeec210b
--- /dev/null
+++ b/private/crt32/dos/rename.c
@@ -0,0 +1,83 @@
+/***
+*rename.c - OS/2 rename file
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines rename() - rename a file
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 03-07-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h>, fixed compiler warnings and fixed the
+* copyright. Also, cleaned up the formatting a bit.
+* 03-30-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <io.h>
+
+/***
+*int rename(oldname, newname) - rename a file
+*
+*Purpose:
+* Renames a file to a new name -- no file with new name must
+* currently exist.
+*
+*Entry:
+* char *oldname - name of file to rename
+* char *newname - new name for file
+*
+*Exit:
+* returns 0 if successful
+* returns not 0 and sets errno if not successful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 rename (
+ const char *oldname,
+ const char *newname
+ )
+{
+ ULONG dosretval;
+
+ /* ask OS to move file */
+
+#ifdef _CRUISER_
+
+ dosretval = DOSMOVE((char *)oldname, (char *)newname, 0);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (!MoveFile((LPSTR)oldname, (LPSTR)newname))
+ dosretval = GetLastError();
+ else
+ dosretval = 0;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ if (dosretval) {
+ /* error occured -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/private/crt32/dos/rmdir.c b/private/crt32/dos/rmdir.c
new file mode 100644
index 000000000..2f387cb11
--- /dev/null
+++ b/private/crt32/dos/rmdir.c
@@ -0,0 +1,83 @@
+/***
+*rmdir.c - OS/2 remove directory
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _rmdir() - remove a directory
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 03-07-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h>, fixed compiler warnings and fixed the
+* copyright. Also, cleaned up the formatting a bit.
+* 03-30-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <direct.h>
+
+/***
+*int _rmdir(path) - remove a directory
+*
+*Purpose:
+* deletes the directory speicifed by path. The directory must
+* be empty, and it must not be the current working directory or
+* the root directory.
+*
+*Entry:
+* char *path - directory to remove
+*
+*Exit:
+* returns 0 if successful
+* returns -1 and sets errno if unsuccessful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _rmdir (
+ const char *path
+ )
+{
+ ULONG dosretval;
+
+ /* ask OS to remove directory */
+
+#ifdef _CRUISER_
+
+ dosretval = DOSDELETEDIR((char *)path, 0);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (!RemoveDirectory((LPSTR)path))
+ dosretval = GetLastError();
+ else
+ dosretval = 0;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ if (dosretval) {
+ /* error occured -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/private/crt32/dos/sources b/private/crt32/dos/sources
new file mode 100644
index 000000000..ce098d931
--- /dev/null
+++ b/private/crt32/dos/sources
@@ -0,0 +1,48 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=dos
+
+TARGETNAME=dos
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=access.c \
+ chmod.c \
+ chdir.c \
+ dosmap.c \
+ drive.c \
+ fullpath.c \
+ getcwd.c \
+ getpid.c \
+ mkdir.c \
+ rename.c \
+ rmdir.c \
+ stat.c \
+ unlink.c
diff --git a/private/crt32/dos/stat.c b/private/crt32/dos/stat.c
new file mode 100644
index 000000000..976d96009
--- /dev/null
+++ b/private/crt32/dos/stat.c
@@ -0,0 +1,397 @@
+/***
+*stat.c - get file status
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _stat() - get file status
+*
+*Revision History:
+* 03-??-84 RLB Module created
+* 05-??-84 DCW Some cleanup and addition of register variables
+* 05-17-86 SKS Ported to OS/2
+* 11-19-86 SKS Better check for root directory; KANJI support
+* 05-22-87 SKS Cleaned up declarations and include files
+* 11-18-87 SKS Make _dtoxmode a static near procedure
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 12-21-87 WAJ stat no longer uses chdir to figure out if it has been
+* passed a root directory in the MTHREAD case.
+* 01-05-88 WAJ now uses _MAX_PATH (defined in stdlib.h)
+* 06-22-88 SKS find Hidden and System files, not just normal ones
+* 06-22-88 SKS Always use better algorithm to detect root dirs
+* 06-29-88 WAJ When looking for root dir makes sure it exists
+* 09-28-88 JCR Use new 386 dostypes.h structures
+* 10-03-88 JCR 386: Change DOS calls to SYS calls
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 10-10-88 GJF Made API names match DOSCALLS.H
+* 11-24-88 GJF ".cmd" should be considered executable, not ".bat"
+* 01-31-89 JCR _canonic() is now _fullpath() and args reversed
+* 04-12-89 JCR New syscall interace
+* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
+* 03-07-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* removed some leftover 16-bit support. Also, fixed
+* the copyright.
+* 04-02-90 GJF Made _ValidDrive() and _dtoxmode() _CALLTYPE1. Removed
+* #include <dos.h>.
+* 07-23-90 SBM Compiles cleanly with -W3 (added/removed appropriate
+* includes), removed '32' from API names
+* 08-10-90 SBM Compiles cleanly with -W3 with new build of compiler
+* 09-03-90 SBM Removed EXT macro
+* 09-27-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 01-18-91 GJF ANSI naming.
+* 01-28-91 GJF Fixed call to DOSFINDFIRST (removed last arg).
+* 02-28-91 SRW Fixed bug in _dtoxtime calls [_WIN32_]
+* 03-05-91 MHL Fixed stat to not use _ValidDrive for stat of root
+* 05-19-92 SKS .BAT is a valid "executable" extension for NT, as
+* well as CMD. Also, File Creation and File Last Access
+* timestamps may be 0 on some file systems (e.g. FAT)
+* in which case the File Last Write time should be used.
+* 05-29-92 SKS Files with SYSTEM bit set should NOT be marked
+* READ-ONLY; these two attributes are independent.
+* 08-18-92 SKS Add a call to FileTimeToLocalFileTime
+* as a temporary fix until _dtoxtime takes UTC
+* 11-20-92 SKS _doserrno must always be set whenever errno is.
+* 11-30-92 KRS Port _MBCS support from 16-bit tree.
+* 03-29-93 GJF Converted from using _dtoxtime() to __gmtotime_t().
+* 04-07-93 GJF Changed first arg type to const char *.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
+#include <msdos.h>
+#include <dostypes.h>
+#include <oscalls.h>
+#include <string.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <direct.h>
+#include <mbstring.h>
+
+int _CRTAPI1 _ValidDrive( unsigned drive );
+
+#define ISSLASH(a) ((a) == '\\' || (a) == '/')
+
+/***
+*static unsigned _dtoxmode(attr, name) -
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static unsigned short _CRTAPI3 _dtoxmode (
+ int attr,
+ const char *name
+ )
+{
+ REG1 unsigned short uxmode;
+ unsigned dosmode;
+ REG2 const char *p;
+
+ dosmode = attr & 0xff;
+ if ((p = name)[1] == ':')
+ p += 2;
+
+ /* check to see if this is a directory - note we must make a special
+ * check for the root, which DOS thinks is not a directory
+ */
+
+ uxmode = (unsigned short)
+ (((ISSLASH(*p) && !p[1]) || (dosmode & A_D) || !*p)
+ ? _S_IFDIR|_S_IEXEC : _S_IFREG);
+
+ /* If attribute byte does not have read-only bit, it is read-write */
+
+ uxmode |= (dosmode & A_RO) ? _S_IREAD : (_S_IREAD|_S_IWRITE);
+
+ /* see if file appears to be executable - check extension of name */
+
+ if (p = strrchr(name, '.')) {
+ if ( !_stricmp(p, ".exe") ||
+ !_stricmp(p, ".cmd") ||
+#ifndef _CRUISER_
+ !_stricmp(p, ".bat") ||
+#endif
+ !_stricmp(p, ".com") )
+ uxmode |= _S_IEXEC;
+ }
+
+ /* propagate user read/write/execute bits to group/other fields */
+
+ uxmode |= (uxmode & 0700) >> 3;
+ uxmode |= (uxmode & 0700) >> 6;
+
+ return(uxmode);
+}
+
+
+/***
+*int _stat(name, buf) - get file status info
+*
+*Purpose:
+* _stat obtains information about the file and stores it in the structure
+* pointed to by buf.
+*
+*Entry:
+* char *name - pathname of given file
+* struct _stat *buffer - pointer to buffer to store info in
+*
+*Exit:
+* fills in structure pointed to by buffer
+* returns 0 if successful
+* returns -1 and sets errno if unsuccessful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _stat (
+ REG1 const char *name,
+ REG2 struct _stat *buf
+ )
+{
+ char * path;
+ char pathbuf[ _MAX_PATH ];
+ int drive; /* A: = 1, B: = 2, etc. */
+
+#ifdef _CRUISER_
+ HDIR findhandle = -1; /* any unused handle */
+ struct _FILEFINDBUF findbuf;
+ unsigned findcount = 1; /* Find only 1 match */
+ unsigned long dmap; /* Valid Drive Map (ignored) */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ HANDLE findhandle;
+ WIN32_FIND_DATA findbuf;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* Don't allow wildcards to be interpreted by system */
+
+ if (_mbspbrk(name, "?*")) {
+ errno = ENOENT;
+ _doserrno = E_nofile;
+ return(-1);
+ }
+
+ /* Try to get disk from name. If none, get current disk. */
+
+ if (name[1] == ':'){
+ if ( *name && !name[2] ){
+ errno = ENOENT; /* return an error if name is */
+ _doserrno = E_nofile; /* just drive letter then colon */
+ return( -1 );
+ }
+ drive = tolower(*name) - 'a' + 1;
+ }
+#ifdef _CRUISER_
+ else
+ (void)DOSQUERYCURRENTDISK((unsigned long *) &drive,
+ (unsigned long *) &dmap);
+
+ /* Call Find Match File */
+
+ if (DOSFINDFIRST((char *)name, (HDIR *)&findhandle,
+ A_D + A_H + A_S, /* find everything except volume labels */
+ (struct _FILEFINDBUF *) &findbuf, sizeof(findbuf),
+ (unsigned *) &findcount, 1L)) {
+
+ if ( !( _mbspbrk(name, "./\\") &&
+ (path = _fullpath( pathbuf, name, _MAX_PATH )) &&
+ (strlen( path ) == 3) &&
+ _ValidDrive( drive ) ) ) {
+ errno = ENOENT;
+ _doserrno = E_nofile;
+ return( -1 );
+ }
+
+ findbuf.attrFile = A_D;
+ findbuf.cbFile = 0L;
+ _DATECAST(findbuf.fdateLastWrite) = (1 << 5) + 1; /* 1 January 1980 */
+ _TIMECAST(findbuf.ftimeLastWrite) = 0; /* 00:00:00 */
+ _DATECAST(findbuf.fdateLastAccess) =
+ _DATECAST(findbuf.fdateCreation) =
+ _TIMECAST(findbuf.ftimeLastAccess) =
+ _TIMECAST(findbuf.ftimeCreation) = 0;
+ }
+ else
+ DOSFINDCLOSE(findhandle); /* Release Find handle */
+
+ /* Fill in buf */
+
+ buf->st_mode = _dtoxmode(findbuf.attrFile, name);
+ buf->st_nlink = 1;
+ buf->st_size = findbuf.cbFile;
+ buf->st_mtime = XTIME(findbuf.fdateLastWrite, findbuf.ftimeLastWrite);
+
+ /*
+ * If create and access times are 0L, use modification time instead
+ */
+ if( _DATECAST(findbuf.fdateCreation) || _TIMECAST(findbuf.ftimeCreation) )
+ buf->st_ctime = XTIME(findbuf.fdateCreation, findbuf.ftimeCreation);
+ else
+ buf->st_ctime = buf->st_mtime;
+
+ if( _DATECAST(findbuf.fdateLastAccess) || _TIMECAST(findbuf.ftimeLastAccess) )
+ buf->st_atime = XTIME(findbuf.fdateLastAccess, findbuf.ftimeLastAccess);
+ else
+ buf->st_atime = buf->st_mtime;
+
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ else
+ drive = _getdrive();
+
+ /* Call Find Match File */
+ findhandle = FindFirstFile((char *)name, &findbuf);
+ if ( findhandle == (HANDLE)0xffffffff ) {
+ if ( !( _mbspbrk(name, "./\\") &&
+ (path = _fullpath( pathbuf, name, _MAX_PATH )) &&
+ (strlen( path ) == 3) &&
+ (GetDriveType( path ) > 1) ) ) {
+ errno = ENOENT;
+ _doserrno = E_nofile;
+ return( -1 );
+ }
+
+ findbuf.dwFileAttributes = A_D;
+ findbuf.nFileSizeHigh = 0;
+ findbuf.nFileSizeLow = 0;
+ findbuf.cFileName[0] = '\0';
+
+ buf->st_mtime = __gmtotime_t(80,1,1,0,0,0);
+ buf->st_atime = buf->st_mtime;
+ buf->st_ctime = buf->st_mtime;
+ }
+ else {
+ SYSTEMTIME SystemTime;
+
+ FileTimeToSystemTime(&findbuf.ftLastWriteTime, &SystemTime);
+
+ buf->st_mtime = __gmtotime_t(SystemTime.wYear,
+ SystemTime.wMonth,
+ SystemTime.wDay,
+ SystemTime.wHour,
+ SystemTime.wMinute,
+ SystemTime.wSecond
+ );
+
+ if ( findbuf.ftLastAccessTime.dwLowDateTime ||
+ findbuf.ftLastAccessTime.dwHighDateTime )
+ {
+ FileTimeToSystemTime(&findbuf.ftLastAccessTime, &SystemTime);
+
+ buf->st_atime = __gmtotime_t(SystemTime.wYear,
+ SystemTime.wMonth,
+ SystemTime.wDay,
+ SystemTime.wHour,
+ SystemTime.wMinute,
+ SystemTime.wSecond
+ );
+ } else
+ buf->st_atime = buf->st_mtime ;
+
+ if ( findbuf.ftCreationTime.dwLowDateTime ||
+ findbuf.ftCreationTime.dwHighDateTime )
+ {
+ FileTimeToSystemTime(&findbuf.ftCreationTime, &SystemTime);
+
+ buf->st_ctime = __gmtotime_t(SystemTime.wYear,
+ SystemTime.wMonth,
+ SystemTime.wDay,
+ SystemTime.wHour,
+ SystemTime.wMinute,
+ SystemTime.wSecond
+ );
+ } else
+ buf->st_ctime = buf->st_mtime ;
+
+ FindClose(findhandle);
+ }
+
+ /* Fill in buf */
+
+ buf->st_mode = _dtoxmode(findbuf.dwFileAttributes, name);
+ buf->st_nlink = 1;
+ buf->st_size = findbuf.nFileSizeLow;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* now set the common fields */
+
+ buf->st_uid = buf->st_gid = buf->st_ino = 0;
+
+ buf->st_rdev = buf->st_dev = (_dev_t)(drive - 1); /* A=0, B=1, etc. */
+
+ return(0);
+}
+
+
+/***
+*int _ValidDrive( unsigned drive ) -
+*
+*Purpose: returns non zero if drive is a valid drive number.
+*
+*Entry: drive = 0 => default drive, 1 => a:, 2 => b: ...
+*
+*Exit: 0 => drive does not exist.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ValidDrive (
+ unsigned drive
+ )
+{
+ unsigned long DriveMap;
+
+#ifdef _CRUISER_
+ unsigned int CurDrive;
+
+ DOSQUERYCURRENTDISK( &CurDrive, &DriveMap );
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ DriveMap = GetLogicalDrives();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+ return( ( DriveMap>>(drive-1) ) & 1l );
+}
diff --git a/private/crt32/dos/unlink.c b/private/crt32/dos/unlink.c
new file mode 100644
index 000000000..f4fa237ec
--- /dev/null
+++ b/private/crt32/dos/unlink.c
@@ -0,0 +1,101 @@
+/***
+*unlink.c - OS/2 unlink a file
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines unlink() - unlink a file
+*
+*Revision History:
+* 06-06-89 PHG Module created, based on asm version
+* 03-07-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h>, fixed compiler warnings and fixed the
+* copyright. Also, cleaned up the formatting a bit.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+* 04-10-91 PNT Added _MAC_ conditional
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <io.h>
+
+/***
+*int _unlink(path) - unlink(delete) the given file
+*
+*Purpose:
+* This version deletes the given file because there are no
+* links under OS/2.
+*
+* NOTE: remove() is an alternative entry point to the _unlink()
+* routine* interface is identical.
+*
+*Entry:
+* char *path - file to unlink/delete
+*
+*Exit:
+* returns 0 if successful
+* returns -1 and sets errno if unsuccessful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 remove (
+ const char *path
+ )
+{
+ ULONG dosretval;
+
+ /* ask OS/2 to remove the file */
+#ifdef _CRUISER_
+
+ dosretval = DOSDELETE((char *)path, 0);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (!DeleteFile((LPSTR)path))
+ dosretval = GetLastError();
+ else
+ dosretval = 0;
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+
+ if (dosretval) {
+ /* error occured -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ return 0;
+}
+
+int _CALLTYPE1 _unlink (
+ const char *path
+ )
+{
+ /* remove is synonym for unlink */
+ return remove(path);
+}
diff --git a/private/crt32/exec/cenvarg.c b/private/crt32/exec/cenvarg.c
new file mode 100644
index 000000000..0a0755748
--- /dev/null
+++ b/private/crt32/exec/cenvarg.c
@@ -0,0 +1,373 @@
+/***
+*cenvarg.c - OS/2 set up environment, command line blocks
+*
+* Copyright (c) 1986-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _cenvarg() - setup environment/command line blocks
+*
+*Revision History:
+* 05-20-86 SKS Module created
+* 10-03-86 SKS Wasn't clearing final null byte in environment block
+* 10-13-86 SKS Check for environment segment > 32 KB (esp. > 64 KB)
+* 10-23-86 SKS New format for C_FILE_INFO for Prot-Mode execution
+* 12-17-86 SKS Support for new command line format
+* 01-21-87 BCM Removed DCR475 switch, new command line format official
+* 07-07-87 JCR Corrected bug in ENV_MAX check
+* 05-24-88 SJM Removed support for ;C_FILE_INFO for Real-Mode execution
+* 06-01-88 SJM Added support for .cmd files via comname/cmdname
+* 12-27-88 JCR Added support for _fileinfo option
+* 03-08-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and fixed
+* the copyright. Also, cleaned up the formatting a bit.
+* 04-02-90 GJF Added const to arg types.
+* 08-10-90 SBM Compiles cleanly with -W3
+* 09-27-90 GJF New-style function declarator.
+* 12-06-90 GJF Added Win32 support. That is, support for encoding
+* _osfinfo[] data into _C_FILE_INFO environment variable.
+* 01-18-91 GJF ANSI naming.
+* 02-05-91 SRW Removed usage of _C_FILE_INFO to pass binary data
+* to child process. [_WIN32_]
+* 05-07-92 SKS Remove code which stripped the extension from a batch
+* file while building arguments to CMD.EXE. This was
+* done long ago (1988) for DOS 3.X, I think.
+* 10-24-92 SKS Remove special code for batch files - not needed on NT
+* 07-15-93 SRW Added _capture_argv function
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <errno.h>
+#include <msdos.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <string.h>
+
+#define ENV_MAX 32767
+
+/***
+*int _cenvarg(argv, envp, argblk, envblk, name) - set up cmd line/environ
+*
+*Purpose:
+* Set up the block forms of the environment and the command line.
+* If "envp" is null, "_environ" is used instead.
+* File handle info is passed in the environment if _fileinfo is !0.
+*
+*Entry:
+* char **argv - argument vector
+* char **envp - environment vector
+* char **argblk - pointer to pointer set to malloc'ed space for args
+* char **envblk - pointer to pointer set to malloc'ed space for env
+* char *name - name of program being invoked
+*
+*Exit:
+* returns 0 if ok, -1 if fails
+* stores through argblk and envblk
+* (calls malloc)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _cenvarg (
+ const char * const *argv,
+ const char * const *envp,
+ char **argblk,
+ char **envblk,
+ const char *name
+ )
+{
+ REG1 const char * const *vp;
+ REG2 unsigned tmp;
+ REG3 char *cptr;
+ unsigned arg_len;
+ int cfi_len; /* counts the number of file handles in CFI */
+
+ /*
+ * Null environment pointer "envp" means use global variable "_environ"
+ */
+
+#ifdef _CRUISER_
+ int i; /* loop counter */
+
+ if (!envp)
+ envp = _environ;
+#endif /* _CRUISER_ */
+
+ /*
+ * Allocate space for command line string
+ * tmp counts the number of bytes in the command line string
+ * including spaces between arguments
+ * An empty string is special -- 2 bytes
+ */
+
+ for (vp = argv, tmp = 2; *vp; tmp += strlen(*vp++) + 1)
+ if( tmp > ENV_MAX )
+ break;
+
+ /*
+ * Make sure there are not already > 32 KB in strings
+ */
+
+ if ((arg_len = tmp) >= ENV_MAX) {
+ *envblk = NULL;
+ errno = E2BIG;
+ _doserrno = E_badenv;
+ return(-1);
+ }
+
+ /*
+ * Allocate space for the command line plus 2 null bytes
+ */
+
+ if ( (*argblk = malloc(tmp)) == NULL) {
+ *envblk = NULL;
+ errno = ENOMEM;
+ _doserrno = E_nomem;
+ return(-1);
+ }
+
+ /*
+ * Allocate space for environment strings
+ * tmp counts the number of bytes in the environment strings
+ * including nulls between strings
+ * Also add "_C_FILE_INFO=" string
+ */
+
+#ifdef _WIN32_
+ if (envp)
+#endif /* _WIN32_ */
+
+ for (vp = envp, tmp = 2; *vp; tmp += strlen(*vp++) + 1)
+ if( tmp > ENV_MAX )
+ break;
+
+#ifdef _CRUISER_
+ if (_fileinfo)
+ for (cfi_len = _nfile; cfi_len && !_osfile[cfi_len-1];
+ cfi_len--) ;
+ else
+ cfi_len = 0; /* no _C_FILE_INFO */
+
+ /*
+ * mode-independent C-FILE-INFO calculation
+ */
+
+ if (cfi_len) /* Add 1 (each) for the "=" & null byte */
+ /* Plus 2 bytes for each value in _osfile */
+ tmp += /* strlen(_acfinfo) */ CFI_LENGTH + 2 + cfi_len +
+ cfi_len;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ ** The _osfile and _osfhnd arrays are passed as binary data in
+ ** dospawn.c
+ */
+
+ cfi_len = 0; /* no _C_FILE_INFO */
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#ifdef _WIN32_
+ if (!envp)
+ *envblk = NULL;
+ else {
+#endif /* _WIN32_ */
+
+ /*
+ * Check for too many strings to be placed in the environment
+ * Increment tmp for final null byte after environment strings
+ * "tmp + arg_len + strlen(name) + 1" must also be < ENV_MAX
+ * Do (long) comparison in case tmp > ENV_MAX from C_FILE_INFO
+ */
+
+ if( (long) tmp + arg_len + strlen(name) > ENV_MAX - 1 ) {
+ free(*argblk);
+ *argblk = NULL;
+ errno = E2BIG;
+ _doserrno = E_badenv;
+ return(-1);
+ }
+
+ /*
+ * Allocate space for the environment strings plus extra null byte
+ */
+
+ if( !(*envblk = malloc(tmp)) ) {
+ free(*argblk);
+ *argblk = NULL;
+ errno = ENOMEM;
+ _doserrno = E_nomem;
+ return(-1);
+ }
+
+#ifdef _WIN32_
+ }
+#endif /* _WIN32_ */
+
+ /*
+ * Build the command line by concatenating the argument strings
+ * with spaces between, and two null bytes at the end
+ * NOTE: The argv[0] argument is followed by a null.
+ */
+
+ cptr = *argblk;
+ vp = argv;
+
+ if (!*vp) /* Empty argument list ? */
+ ++cptr; /* just two null bytes */
+ else { /* argv[0] must be followed by a null */
+ strcpy(cptr, *vp);
+ cptr += strlen(*vp++) + 1;
+ }
+
+ while( *vp ) {
+ strcpy(cptr, *vp);
+ cptr += strlen(*vp++);
+ *cptr++ = ' ';
+ }
+
+ * cptr = cptr[ -1 ] = '\0'; /* remove extra blank, add double null */
+
+#ifdef _WIN32_
+ if (envp) {
+#endif /* _WIN32_ */
+
+ /*
+ * Build the environment block by concatenating the environment strings
+ * with nulls between and two null bytes at the end
+ * C_FILE_INFO is stored as if it were an environment string
+ */
+
+ cptr = *envblk;
+ vp = envp;
+
+ if( !(*vp || cfi_len) ) /* No environment strings? */
+ *cptr++ = '\0'; /* just two null bytes */
+
+ while( *vp ) {
+ strcpy(cptr, *vp);
+ cptr += 1 + strlen(*vp++);
+ }
+
+#ifdef _CRUISER_
+
+ if(cfi_len) {
+ strcpy(cptr,_acfinfo);
+ cptr += /* strlen(_acfinfo) */ CFI_LENGTH;
+
+ i = cfi_len;
+ for(tmp = 0; i--; ++tmp) {
+ *cptr++ = (char)(((_osfile[tmp] >> 4) & 0xF) + 'A');
+ *cptr++ = (char)((_osfile[tmp] & 0xF) + 'A');
+ }
+ *cptr++ = '\0';
+ }
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ ** The _osfile and _osfhnd arrays are passed as binary data in
+ ** dospawn.c
+ */
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#ifdef _WIN32_
+ }
+#endif /* _WIN32_ */
+
+ /*
+ * Extra null terminates the segment
+ */
+ *cptr = '\0';
+
+ return(0);
+}
+
+
+/***
+*int _capture_argv(arglist, static_argv, max_static_entries) - set up argv array
+* for exec?? functions
+*
+*Purpose:
+* Set up the argv array for the exec?? functions by captures the arguments
+* from the passed va_list into the static_argv array. If the size of the
+* static_argv array as specified by the max_static_entries parameter is
+* not large enough, then allocates a dynamic array to hold the arguments.
+* Return the address of the final argv array. If NULL then not enough
+* memory to hold argument array. If different from static_argv parameter
+* then call must free the return argv array when done with it.
+*
+* The scan of the arglist is terminated when a NULL argument is reached.
+* The terminating NULL parameter is stored in the resulting argv array.
+*
+*Entry:
+* va_list *arglist - pointer to variable length argument list.
+* char *firstarg - first argument to store in array
+* char **static_argv - pointer to static argv to use.
+* size_t max_static_entries - maximum number of entries that can be placed
+* in static_argv array.
+*
+*Exit:
+* returns NULL if no memory.
+* Otherwise returns pointer to argv array.
+* (sometimes calls malloc)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char ** _CALLTYPE1 _capture_argv(
+ va_list *arglist,
+ const char *firstarg,
+ char **static_argv,
+ size_t max_static_entries
+ )
+{
+ char ** argv;
+ char * nextarg;
+ size_t i;
+ size_t max_entries;
+
+ nextarg = (char *)firstarg;
+ argv = static_argv;
+ max_entries = max_static_entries;
+ i = 0;
+ for (;;) {
+ if (i >= max_entries) {
+ if (argv == static_argv)
+ argv = malloc((max_entries * 2) * sizeof(char *));
+ else
+ argv = realloc(argv, (max_entries * 2) * sizeof(char *));
+
+ if (argv == NULL) break;
+ max_entries += max_entries;
+ }
+
+ argv[ i++ ] = nextarg;
+ if (nextarg == NULL) break;
+ nextarg = va_arg(*arglist, char *);
+ }
+
+ return argv;
+}
diff --git a/private/crt32/exec/cfinfo.c b/private/crt32/exec/cfinfo.c
new file mode 100644
index 000000000..e761a1f68
--- /dev/null
+++ b/private/crt32/exec/cfinfo.c
@@ -0,0 +1,22 @@
+/***
+*cfinfo.c - clears C file info flag
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Clears the C file info flag. By default, the openfile information
+* is NOT passed along to children on spawn/exec calls. If the flag
+* is set, openfile information WILL get passed on to children on
+* spawn/exec calls.
+*
+*Revision History:
+* 06-07-89 PHG Module created, based on asm version
+* 04-03-90 GJF Added #include <cruntime.h>. Also, fixed the copyright.
+* 01-23-92 GJF Added #include <stdlib.h> (contains decl of _fileinfo).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+
+int _fileinfo = 0;
diff --git a/private/crt32/exec/dospawn.c b/private/crt32/exec/dospawn.c
new file mode 100644
index 000000000..900c2996d
--- /dev/null
+++ b/private/crt32/exec/dospawn.c
@@ -0,0 +1,303 @@
+/***
+*dospawn.c - OS/2 spawn a child process
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _dospawn - spawn a child process
+*
+*Revision History:
+* 06-07-89 PHG Module created, based on asm version
+* 03-08-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 04-02-90 GJF Now _CALLTYPE1. Added const to type of name arg.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarator.
+* 10-30-90 GJF Added _p_overlay (temporary hack).
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 SRW Fixed return value for dospawn [_WIN32_]
+* 01-17-91 GJF ANSI naming.
+* 01-25-91 SRW Changed CreateProcess parameters [_WIN32_]
+* 01-29-91 SRW Changed CreateProcess parameters again [_WIN32_]
+* 02-05-91 SRW Changed to pass _osfile and _osfhnd arrays as binary
+* data to child process. [_WIN32_]
+* 02-18-91 SRW Fixed code to return correct process handle and close
+* handle for P_WAIT case. [_WIN32_]
+* 04-05-91 SRW Fixed code to free StartupInfo.lpReserved2 after
+* CreateProcess call. [_WIN32_]
+* 04-26-91 SRW Removed level 3 warnings (_WIN32_)
+* 12-02-91 SRW Fixed command line setup code to not append an extra
+* space [_WIN32_]
+* 12-16-91 GJF Return full 32-bit exit code from the child process
+* [_WIN32_].
+* 02-14-92 GJF Replaced _nfile with _nhandle for Win32.
+* 02-18-92 GJF Merged in 12-16-91 change from \\vangogh version
+* 11-20-92 SKS errno/_doserrno must be 0 in case of success. This
+* will distinguish a child process return code of -1L
+* (errno == 0) from an actual error (where errno != 0).
+* 01-08-93 CFW Added code to handle _P_DETACH case; add fdwCreate variable,
+* nuke stdin, stdout, stderr entries of _osfile & _osfhnd tables,
+* close process handle to completely detach process
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <process.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int _VARTYPE1 _p_overlay = 2;
+
+/***
+*int _dospawn(mode, name, cmdblk, envblk) - spawn a child process
+*
+*Purpose:
+* Spawns a child process
+*
+*Entry:
+* int mode - _P_WAIT, _P_NOWAIT, _P_NOWAITO, _P_OVERLAY, or _P_DETACH
+* char *name - name of program to execute
+* char *cmdblk - parameter block
+* char *envblk - environment block
+*
+*Exit:
+* _P_OVERLAY: -1 = error, otherwise doesn't return
+* _P_WAIT: termination code << 8 + result code
+* _P_DETACH: -1 = error, 0 = success
+* others: PID of process
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _dospawn (
+ int mode,
+ const char *name,
+ char *cmdblk,
+ char *envblk
+ )
+{
+ char syncexec, asyncresult, background;
+#ifdef _CRUISER_
+
+ RESULTCODES result_codes; /* result code of DosExecPgm */
+ ULONG exec_flags; /* flags for DosExecPgm */
+ ULONG dosretval; /* OS/2 return value */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ LPSTR CommandLine;
+ STARTUPINFO StartupInfo;
+ PROCESS_INFORMATION ProcessInformation;
+ BOOL CreateProcessStatus;
+ ULONG dosretval; /* OS return value */
+ DWORD retval;
+ DWORD fdwCreate = 0; /* Flags for CreateProcess */
+ int cfi_len; /* counts the number of file handles in CFI */
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* translate input mode value to individual flags */
+ syncexec = asyncresult = background = 0;
+ switch (mode) {
+ case _P_WAIT: syncexec=1; break; /* synchronous execution */
+ case 2: /* _P_OVERLAY */
+ case _P_NOWAITO: break; /* asynchronous execution */
+ case _P_NOWAIT: asyncresult=1; break; /* asynch + remember result */
+ case _P_DETACH: background=1; break; /* detached in null scrn grp */
+ default:
+ /* invalid mode */
+ errno = EINVAL;
+ _doserrno = 0; /* not a Dos error */
+ return -1;
+ }
+
+#ifdef _CRUISER_
+ /* translate input mode value to system call value */
+ if (syncexec)
+ exec_flags = EXEC_SYNC;
+ else
+ if (asyncresult)
+ exec_flags = EXEC_ASYNCRESULT;
+ else
+ if (background)
+ exec_flags = EXEC_BACKGROUND;
+ else
+ exec_flags = EXEC_ASYNC;
+
+ /* issue system call to run process, want no DynaLink failure name */
+ if (dosretval = DOSEXECPGM(NULL, 0, exec_flags, cmdblk, envblk,
+ &result_codes, (char *)name)) {
+ /* error -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ if (mode == 2 /* _P_OVERLAY */) {
+ /* destroy ourselves */
+ _exit(0);
+ }
+ else if (mode == _P_WAIT) {
+ /* return termination code and exit code -- note we only
+ return low byte of result code, although OS/2 allows a
+ word -- this is for XENIX compatability */
+ return ((result_codes.codeTerminate & 0xFF) << 8) +
+ (result_codes.codeResult & 0xFF);
+ }
+ else {
+ /* asynchronous spawn -- return PID */
+ return result_codes.codeTerminate;
+ }
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ //
+ // Loop over null separate arguments, and replace null separators
+ // with spaces to turn it back into a single null terminated
+ // command line.
+ //
+ CommandLine = cmdblk;
+ while (*cmdblk) {
+ while (*cmdblk) {
+ cmdblk++;
+ }
+
+ //
+ // If not last argument, turn null separator into a space.
+ //
+ if (cmdblk[1] != '\0') {
+ *cmdblk++ = ' ';
+ }
+ }
+
+ memset(&StartupInfo,0,sizeof(StartupInfo));
+ StartupInfo.cb = sizeof(StartupInfo);
+
+ for (cfi_len = _nhandle; cfi_len && !_osfile[cfi_len-1];cfi_len--) {
+ }
+
+ StartupInfo.cbReserved2 = (WORD)(sizeof( int ) +
+ (cfi_len *
+ (sizeof( char ) + sizeof( long ) )
+ )
+ );
+ StartupInfo.lpReserved2 = calloc( StartupInfo.cbReserved2, 1 );
+ memcpy( StartupInfo.lpReserved2,
+ &cfi_len,
+ sizeof( int )
+ );
+ memcpy( StartupInfo.lpReserved2 + sizeof( int ),
+ _osfile,
+ cfi_len * sizeof( char )
+ );
+ memcpy( StartupInfo.lpReserved2 + sizeof( int ) +
+ (cfi_len * sizeof( char )),
+ _osfhnd,
+ cfi_len * sizeof( long )
+ );
+
+ if (background)
+ {
+ int fh;
+
+ /* child process is detached, cannot access console, must nuke first
+ three entries (stdin, stdout, stderr) in _osfile & _osfhnd tables */
+
+ // set _osfile[]
+ for ( fh = 0 ; fh <= 2 ; ++fh )
+ {
+ *(char *)(StartupInfo.lpReserved2
+ + sizeof(int)
+ + fh * sizeof(char)) = 0;
+ }
+
+ // set _osfhnd[]
+ for ( fh = 0 ; fh <= 2 ; ++fh )
+ {
+ *(long *)(StartupInfo.lpReserved2
+ + sizeof(int)
+ + cfi_len * sizeof(char)
+ + fh * sizeof(long)) = (long)INVALID_HANDLE_VALUE;
+ }
+
+ fdwCreate |= DETACHED_PROCESS;
+ }
+
+ /**
+ * Set errno to 0 to distinguish a child process
+ * which returns -1L from an error in the spawning
+ * (which will set errno to something non-zero
+ **/
+
+ _doserrno = errno = 0 ;
+
+ CreateProcessStatus = CreateProcess( (LPSTR)name,
+ CommandLine,
+ NULL,
+ NULL,
+ TRUE,
+ fdwCreate,
+ envblk,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation
+ );
+
+ dosretval = GetLastError();
+ free( StartupInfo.lpReserved2 );
+
+ if (!CreateProcessStatus)
+ {
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ if (mode == 2 /* _P_OVERLAY */) {
+ /* destroy ourselves */
+ _exit(0);
+ }
+ else if (mode == _P_WAIT) {
+ WaitForSingleObject(ProcessInformation.hProcess, (DWORD)(-1L));
+
+ /* return termination code and exit code -- note we return
+ the full exit code */
+ GetExitCodeProcess(ProcessInformation.hProcess, &retval);
+
+ CloseHandle(ProcessInformation.hProcess);
+ }
+ else if (mode == _P_DETACH) {
+ /* like totally detached asynchronous spawn, dude,
+ close process handle, return 0 for success */
+ CloseHandle(ProcessInformation.hProcess);
+ retval = (DWORD)0;
+ }
+ else {
+ /* asynchronous spawn -- return PID */
+ retval = (DWORD)ProcessInformation.hProcess;
+ }
+
+ CloseHandle(ProcessInformation.hThread);
+ return retval;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+}
diff --git a/private/crt32/exec/execl.c b/private/crt32/exec/execl.c
new file mode 100644
index 000000000..3c2d5efd5
--- /dev/null
+++ b/private/crt32/exec/execl.c
@@ -0,0 +1,76 @@
+/***
+*execl.c - execute a file with a list of arguments
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _execl() - execute a file with a list of arguments
+*
+*Revision History:
+* 10-14-83 RN written
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, indents. Added const attribute to
+* types of filename and arglist. #include-d PROCESS.H
+* and added ellipsis to match prototype.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 02-14-90 SRW Use NULL instead of _environ to get default.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <process.h>
+#include <stdarg.h>
+#include <internal.h>
+
+/***
+*int _execl(filename, arglist) - execute a file with arg list
+*
+*Purpose:
+* Transform the argument list so it is a vector, then pass its address
+* to execve. Use a pointer to the default environment vector.
+*
+*Entry:
+* char *filename - file to execute
+* char *arglist - list of arguments
+* call as _execl(path, arg0, arg1, ..., argn, NULL);
+*
+*Exit:
+* destroys the calling process, hopefully
+* returns -1 if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _execl (
+ const char *filename,
+ const char *arglist,
+ ...
+ )
+{
+ va_list vargs;
+ char * argbuf[64];
+ char ** argv;
+ int result;
+
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(arglist != NULL);
+ assert(*arglist != '\0');
+
+ va_start(vargs, arglist);
+ argv = _capture_argv(&vargs, arglist, argbuf, 64);
+ va_end(vargs);
+
+ result = _execve(filename,argv,NULL);
+ if (argv && argv != argbuf) free(argv);
+ return result;
+}
diff --git a/private/crt32/exec/execle.c b/private/crt32/exec/execle.c
new file mode 100644
index 000000000..2b74e4d31
--- /dev/null
+++ b/private/crt32/exec/execle.c
@@ -0,0 +1,79 @@
+/***
+*execle.c - execute a file with arg list and environment
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _execle() - execute a file
+*
+*Revision History:
+* 10-14-83 RN written
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, indents. Added const attribute to
+* types of filename and arglist. #include-d PROCESS.H
+* and added ellipsis to match prototype.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stddef.h>
+#include <process.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <malloc.h>
+
+/***
+*int _execle(filename, arglist) - execute a file
+*
+*Purpose:
+* Execute the given file (overlays the calling process).
+* We must dig the environment vector out of the stack and pass it
+* and address of argument vector to execve.
+*
+*Entry:
+* char *filename - file to execute
+* char *arglist - argument list followed by environment
+* should be called like _execle(path, arg0, arg1, ..., argn, NULL, envp);
+*
+*Exit:
+* destroys calling process (hopefully)
+* if fails, returns -1.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _execle (
+ const char *filename,
+ const char *arglist,
+ ...
+ )
+{
+ va_list vargs;
+ char * argbuf[64];
+ char ** argv;
+ char ** envp;
+ int result;
+
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(arglist != NULL);
+ assert(*arglist != '\0');
+
+ va_start(vargs, arglist);
+ argv = _capture_argv(&vargs, arglist, argbuf, 64);
+ envp = va_arg(vargs, char **);
+ va_end(vargs);
+
+ result = _execve(filename,argv,envp);
+ if (argv && argv != argbuf) free(argv);
+ return result;
+}
diff --git a/private/crt32/exec/execlp.c b/private/crt32/exec/execlp.c
new file mode 100644
index 000000000..4e622be61
--- /dev/null
+++ b/private/crt32/exec/execlp.c
@@ -0,0 +1,77 @@
+/***
+*execlp.c - execute a file (search along PATH)
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _execlp() - execute a file and search along PATH
+*
+*Revision History:
+* 10-17-83 RN written
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, indents. Added const attribute to
+* types of filename and arglist. #include-d PROCESS.H
+* and added ellipsis to match prototype.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stddef.h>
+#include <process.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <malloc.h>
+
+/***
+*int _execlp(filename, arglist) - execute a file, search along PATH
+*
+*Purpose:
+* Execute the given file with the given arguments; search along PATH
+* for the file. We pass the arguments to execvp where several paths
+* will be tried until one works.
+*
+*Entry:
+* char *filename - file to execute
+* char *arglist - argument list
+* call as _execlp(path, arg0, arg1, ..., argn, NULL);
+*
+*Exit:
+* destroys calling process (hopefully)
+* returns -1 if fails.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _execlp (
+ const char *filename,
+ const char *arglist,
+ ...
+ )
+{
+ va_list vargs;
+ char * argbuf[64];
+ char ** argv;
+ int result;
+
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(arglist != NULL);
+ assert(*arglist != '\0');
+
+ va_start(vargs, arglist);
+ argv = _capture_argv(&vargs, arglist, argbuf, 64);
+ va_end(vargs);
+
+ result = _execvp(filename,argbuf);
+ if (argv && argv != argbuf) free(argv);
+ return result;
+}
diff --git a/private/crt32/exec/execlpe.c b/private/crt32/exec/execlpe.c
new file mode 100644
index 000000000..991cf757a
--- /dev/null
+++ b/private/crt32/exec/execlpe.c
@@ -0,0 +1,82 @@
+/***
+*execlpe.c - execute a file with environ, search along path
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _execlpe() - execute a file with environ and search along PATH
+*
+*Revision History:
+* 10-17-83 RN written
+* ??-??-?? TC added execlpe
+* 06-18-86 JMB added environment pointer which was erroneously missing
+* 06-11-87 PHG removed unnecessary environment pointer (isn't this
+* fun!)
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, indents. Added const attribute to
+* types of filename and arglist. #include-d PROCESS.H
+* and added ellipsis to match prototype.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <process.h>
+#include <stdarg.h>
+#include <internal.h>
+
+/***
+*int _execlpe(filename, arglist) - execute a file with environ
+*
+*Purpose:
+* Executes the given file with the parameters and the environment
+* which is passed after the parameters. Searches along the PATH
+* for the file (done by execvp).
+*
+*Entry:
+* char *filename - file to execute
+* char *arglist - argument list (environment is at the end)
+* call as _execlpe(path, arg0, arg1, ..., argn, NULL, envp);
+*
+*Exit:
+* destroys the calling process (hopefully)
+* if fails, returns -1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _execlpe (
+ const char *filename,
+ const char *arglist,
+ ...
+ )
+{
+ va_list vargs;
+ char * argbuf[64];
+ char ** argv;
+ char ** envp;
+ int result;
+
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(arglist != NULL);
+ assert(*arglist != '\0');
+
+ va_start(vargs, arglist);
+ argv = _capture_argv(&vargs, arglist, argbuf, 64);
+ envp = va_arg(vargs, char **);
+ va_end(vargs);
+
+ result = _execvpe(filename,argv,envp);
+ if (argv && argv != argbuf) free(argv);
+ return result;
+}
diff --git a/private/crt32/exec/execv.c b/private/crt32/exec/execv.c
new file mode 100644
index 000000000..a369e3738
--- /dev/null
+++ b/private/crt32/exec/execv.c
@@ -0,0 +1,60 @@
+/***
+*execv.c - execute a file
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _execv() - execute a file
+*
+*Revision History:
+* 10-14-83 RN written
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, indents. Added const attribute to
+* types of filename and argvector.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 02-14-90 SRW Use NULL instead of _environ to get default.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <process.h>
+
+/***
+*int _execv(filename, argvector) - execute a file
+*
+*Purpose:
+* Executes a file with given arguments. Passes arguments to _execve and
+* uses pointer to the default environment.
+*
+*Entry:
+* char *filename - file to execute
+* char **argvector - vector of arguments.
+*
+*Exit:
+* destroys calling process (hopefully)
+* if fails, returns -1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _execv (
+ const char *filename,
+ const char * const *argvector
+ )
+{
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(argvector != NULL);
+ assert(*argvector != NULL);
+ assert(**argvector != '\0');
+
+ return(_execve(filename,argvector,NULL));
+}
diff --git a/private/crt32/exec/execve.c b/private/crt32/exec/execve.c
new file mode 100644
index 000000000..386ed4d0f
--- /dev/null
+++ b/private/crt32/exec/execve.c
@@ -0,0 +1,2 @@
+#define EXECVE
+#include "spawnve.c"
diff --git a/private/crt32/exec/execvp.c b/private/crt32/exec/execvp.c
new file mode 100644
index 000000000..f6b94de8b
--- /dev/null
+++ b/private/crt32/exec/execvp.c
@@ -0,0 +1,62 @@
+/***
+*execvp.c - execute a file and search along PATH
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _execvp() - execute a file and search along PATH
+*
+*Revision History:
+* 10-17-83 RN written
+* 10-29-85 TC added execvpe capability
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, indents. Added const attribute to
+* types of filename and argvector.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>
+* 05-21-90 GJF Fixed stack checking pragma syntax.
+* 08-24-90 SBM Removed check_stack pragma since workhorse execve
+* does stack checks
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 02-14-90 SRW Use NULL instead of _environ to get default.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <process.h>
+
+/***
+*int _execvp(filename, argvector) - execute file; search along PATH
+*
+*Purpose:
+* Execute the given file with given path and current environ.
+* try to execute the file. start with the name itself (directory '.'),
+* and if that doesn't work start prepending pathnames from the
+* environment until one works or we run out. if the file is a pathname,
+* don't go to the environment to get alternate paths. if errno comes
+* back ENOEXEC, try it as a shell command file with up to MAXARGS-2
+* arguments from the original vector. if a needed text file is busy,
+* wait a little while and try again before despairing completely
+* Actually calls _execvpe() to do all the work.
+*
+*Entry:
+* char *filename - file to execute
+* char **argvector - vector of arguments
+*
+*Exit:
+* destroys the calling process (hopefully)
+* if fails, returns -1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _execvp (
+ REG3 const char *filename,
+ const char * const *argvector
+ )
+{
+ return _execvpe( filename, argvector, NULL );
+}
diff --git a/private/crt32/exec/execvpe.c b/private/crt32/exec/execvpe.c
new file mode 100644
index 000000000..650f34b2a
--- /dev/null
+++ b/private/crt32/exec/execvpe.c
@@ -0,0 +1,171 @@
+/***
+*execvpe.c - execute a file with given environ; search along PATH
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _execvpe() - execute a file with given environ
+*
+*Revision History:
+* 10-17-83 RN written
+* 10-29-85 TC added execvpe capability
+* 11-19-86 SKS handle both kinds of slashes
+* 12-01-86 JMB added Kanji file name support under conditional KANJI
+* switches, corrected header info
+* removed bogus check for env = b after call to strncpy().
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 09-05-88 SKS Treat EACCES the same as ENOENT -- keep trying
+* 10-18-88 GJF Removed copy of PATH string to local array, changed
+* bbuf to be a malloc-ed buffer. Removed bogus limits
+* on the size of that PATH string.
+* 10-26-88 GJF Don't search PATH when relative pathname is given (per
+* Stevesa). Also, if the name built from PATH component
+* and filename is a UNC name, allow any error.
+* 11-20-89 GJF Fixed copyright. Added const attribute to types of
+* filename, argvector and envptr. Also, added "#include
+* <jstring.h>" under KANJI switch (same as 5-17-89 change
+* to CRT version).
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>. Also,
+* cleaned up the formatting a bit.
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 11-30-92 KRS Port _MBCS code from 16-bit tree.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+#include <mbstring.h>
+
+#define SLASH "\\"
+#define SLASHCHAR '\\'
+#define XSLASHCHAR '/'
+#define DELIMITER ";"
+
+#ifdef _MBCS
+/* note, the macro below assumes p is to pointer to a single-byte character
+ * or the 1st byte of a double-byte character, in a string.
+ */
+#define ISPSLASH(p) ( ((p) == _mbschr((p), SLASHCHAR)) || ((p) == \
+_mbschr((p), XSLASHCHAR)) )
+#else
+#define ISSLASH(c) ( ((c) == SLASHCHAR) || ((c) == XSLASHCHAR) )
+#endif
+
+
+/***
+*int _execvpe(filename, argvector, envvector) - execute a file
+*
+*Purpose:
+* Executes a file with given arguments and environment.
+* try to execute the file. start with the name itself (directory '.'),
+* and if that doesn't work start prepending pathnames from the
+* environment until one works or we run out. if the file is a pathname,
+* don't go to the environment to get alternate paths. If a needed text
+* file is busy, wait a little while and try again before despairing
+* completely
+*
+*Entry:
+* char *filename - file to execute
+* char **argvector - vector of arguments
+* char **envvector - vector of environment variables
+*
+*Exit:
+* destroys the calling process (hopefully)
+* if fails, returns -1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _execvpe (
+ REG3 const char *filename,
+ const char * const *argvector,
+ const char * const *envptr
+ )
+{
+ REG1 char *env;
+ char *bbuf = NULL;
+ REG2 char *buf;
+ char *pfin;
+
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(argvector != NULL);
+ assert(*argvector != NULL);
+ assert(**argvector != '\0');
+
+ _execve(filename,argvector,envptr);
+
+ /* In a SBCS build, _mbschr will map to strchr. */
+
+ if ( (errno != ENOENT)
+ || (_mbschr(filename, SLASHCHAR) != NULL)
+ || (_mbschr(filename, XSLASHCHAR) != NULL)
+ || *filename && *(filename+1) == ':'
+ || !(env=getenv("PATH")) )
+ goto reterror;
+
+ /* allocate a buffer to hold alternate pathnames for the executable
+ */
+ if ( (buf = bbuf = (char *)malloc(_MAX_PATH)) == NULL ) goto reterror;
+
+ do {
+ /* copy a component into bbuf[], taking care not to overflow it
+ */
+ /* UNDONE: make sure ';' isn't 2nd byte of DBCS char */
+ while ( (*env) && (*env != ';') && (buf < bbuf+_MAX_PATH-2) )
+ *buf++ = *env++;
+
+ *buf = '\0';
+ pfin = --buf;
+ buf = bbuf;
+
+#ifdef _MBCS
+ if (*pfin == SLASHCHAR) {
+ if (pfin != _mbsrchr(buf,SLASHCHAR))
+ /* *pfin is the second byte of a double-byte
+ * character
+ */
+ strcat( buf, SLASH );
+ }
+ else if (*pfin != XSLASHCHAR)
+ strcat(buf, SLASH);
+#else
+ if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR)
+ strcat(buf, SLASH);
+#endif
+
+ /* check that the final path will be of legal size. if so,
+ * build it. otherwise, return to the caller (return value
+ * and errno rename set from initial call to _execve()).
+ */
+ if ( (strlen(buf) + strlen(filename)) < _MAX_PATH )
+ strcat(buf, filename);
+ else
+ break;
+
+ _execve(buf, argvector, envptr);
+
+ if ( (errno != ENOENT)
+#ifdef _MBCS
+ && (!ISPSLASH(buf) || !ISPSLASH(buf+1)) )
+#else
+ && (!ISSLASH(*buf) || !ISSLASH(*(buf+1))) )
+#endif
+ break;
+ } while ( *env && env++ );
+
+reterror:
+ if (bbuf != NULL)
+ free(bbuf);
+
+ return(-1);
+}
diff --git a/private/crt32/exec/fileinfo.c b/private/crt32/exec/fileinfo.c
new file mode 100644
index 000000000..c617cf8c4
--- /dev/null
+++ b/private/crt32/exec/fileinfo.c
@@ -0,0 +1,22 @@
+/***
+*fileinfo.c - sets C file info flag
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Sets the C file info flag. By default, the openfile information
+* is NOT passed along to children on spawn/exec calls. If the flag
+* is set, openfile information WILL get passed on to children on
+* spawn/exec calls.
+*
+*Revision History:
+* 06-07-89 PHG Module created, based on asm version
+* 04-03-90 GJF Added #include <cruntime.h>. Also, fixed the copyright.
+* 01-23-92 GJF Added #include <stdlib.h> (contains decl of _fileinfo).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+
+int _fileinfo = -1;
diff --git a/private/crt32/exec/getproc.c b/private/crt32/exec/getproc.c
new file mode 100644
index 000000000..2cb78323e
--- /dev/null
+++ b/private/crt32/exec/getproc.c
@@ -0,0 +1,62 @@
+/***
+*getproc.c - Get the address of a procedure in a DLL.
+*
+* Copyright (c) 1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _getdllprocadd() - gets a procedure address by name or
+* ordinal
+*
+*Revision History:
+* 08-21-91 BWM Wrote module.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <process.h>
+
+#if !defined(_WIN32_)
+#error ERROR - ONLY WIN32 TARGET SUPPORTED!
+#endif
+
+/***
+*int (*)() _getdllprocaddr(handle, name, ordinal) - Get the address of a
+* DLL procedure specified by name or ordinal
+*
+*Purpose:
+*
+*Entry:
+* int handle - a DLL handle from _loaddll
+* char * name - Name of the procedure, or NULL to get by ordinal
+* int ordinal - Ordinal of the procedure, or -1 to get by name
+*
+*
+*Exit:
+* returns a pointer to the procedure if found
+* returns NULL if not found
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int (_CALLTYPE1 * _CALLTYPE1 _getdllprocaddr(int hMod,
+ char * szProcName,
+ int iOrdinal))()
+{
+ typedef int (_CALLTYPE1 * PFN)();
+
+ if (szProcName == NULL) {
+ if (iOrdinal <= 65535) {
+ return ((PFN)GetProcAddress((HANDLE)hMod, (LPSTR)iOrdinal));
+ }
+ }
+ else {
+ if (iOrdinal == -1) {
+ return ((PFN)GetProcAddress((HANDLE)hMod, szProcName));
+ }
+ }
+
+ return (NULL);
+
+}
diff --git a/private/crt32/exec/loaddll.c b/private/crt32/exec/loaddll.c
new file mode 100644
index 000000000..a6f41b7e2
--- /dev/null
+++ b/private/crt32/exec/loaddll.c
@@ -0,0 +1,70 @@
+/***
+*loaddll.c - load or free a Dynamic Link Library
+*
+* Copyright (c) 1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _loaddll() and _unloaddll() - load and unload DLL
+*
+*Revision History:
+* 08-21-91 BWM Wrote module.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <process.h>
+
+#if !defined(_WIN32_)
+#error ERROR - ONLY WIN32 TARGET SUPPORTED!
+#endif
+
+/***
+*int _loaddll(filename) - Load a dll
+*
+*Purpose:
+* Load a DLL into memory
+*
+*Entry:
+* char *filename - file to load
+*
+*Exit:
+* returns a unique DLL (module) handle if succeeds
+* returns 0 if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _loaddll(char * szName)
+{
+ return ((int)LoadLibrary(szName));
+}
+
+/***
+*int _unloaddll(handle) - Unload a dll
+*
+*Purpose:
+* Unloads a DLL. The resources of the DLL will be freed if no other
+* processes are using it.
+*
+*Entry:
+* int handle - handle from _loaddll
+*
+*Exit:
+* returns 0 if succeeds
+* returns DOS error if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _unloaddll(int hMod)
+{
+ if (!FreeLibrary((HANDLE)hMod)) {
+ return ((int)GetLastError());
+ }
+ return (0);
+}
diff --git a/private/crt32/exec/makefile b/private/crt32/exec/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/exec/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/exec/sources b/private/crt32/exec/sources
new file mode 100644
index 000000000..ed4f1c187
--- /dev/null
+++ b/private/crt32/exec/sources
@@ -0,0 +1,58 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=exec
+
+TARGETNAME=exec
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=cenvarg.c \
+ fileinfo.c \
+ dospawn.c \
+ execl.c \
+ execle.c \
+ execlp.c \
+ execlpe.c \
+ execv.c \
+ execve.c \
+ execvp.c \
+ execvpe.c \
+ getproc.c \
+ loaddll.c \
+ spawnl.c \
+ spawnle.c \
+ spawnlp.c \
+ spawnlpe.c \
+ spawnv.c \
+ spawnve.c \
+ spawnvp.c \
+ spawnvpe.c \
+ system.c \
+ wait.c
diff --git a/private/crt32/exec/spawnl.c b/private/crt32/exec/spawnl.c
new file mode 100644
index 000000000..826e5be46
--- /dev/null
+++ b/private/crt32/exec/spawnl.c
@@ -0,0 +1,83 @@
+/***
+*spawnl.c - spawn a child process
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _spawnl() - spawn a child process
+*
+*Revision History:
+* 04-15-84 DFW Re-do to correspond to similar exec call format
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types
+* for pathname and arglist. #include-d PROCESS.H and
+* added ellipsis to match prototype.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2 and added #include
+* <cruntime.h>.
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 02-14-90 SRW Use NULL instead of _environ to get default.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <process.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <malloc.h>
+
+/***
+*int _spawnl(modeflag, pathname, arglist) - spawn a child process
+*
+*Purpose:
+* Spawns a child process.
+* formats the parameters and calls spawnve to do the actual work. The
+* new process will inherit the parent's environment. NOTE - at least
+* one argument must be present. This argument is always, by convention,
+* the name of the file being spawned.
+*
+*Entry:
+* int modeflag - defines which mode of spawn (WAIT, NOWAIT, or OVERLAY)
+* only WAIT and OVERLAY are currently implemented
+* char *pathname - file to be spawned
+* char *arglist - list of argument
+* call as _spawnl(modeflag, path, arg0, arg1, ..., argn, NULL);
+*
+*Exit:
+* returns exit code of child process
+* returns -1 if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _spawnl (
+ int modeflag,
+ const char *pathname,
+ const char *arglist,
+ ...
+ )
+{
+ va_list vargs;
+ char * argbuf[64];
+ char ** argv;
+ int result;
+
+ assert(pathname != NULL);
+ assert(*pathname != '\0');
+ assert(arglist != NULL);
+ assert(*arglist != '\0');
+
+ va_start(vargs, arglist);
+ argv = _capture_argv(&vargs, arglist, argbuf, 64);
+ va_end(vargs);
+
+ result = _spawnve(modeflag,pathname,argv,NULL);
+ if (argv && argv != argbuf) free(argv);
+ return result;
+}
diff --git a/private/crt32/exec/spawnle.c b/private/crt32/exec/spawnle.c
new file mode 100644
index 000000000..5b09417f2
--- /dev/null
+++ b/private/crt32/exec/spawnle.c
@@ -0,0 +1,83 @@
+/***
+*spawnle.c - spawn a child process with given environment
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _spawnle() - spawn a child process with given environ
+*
+*Revision History:
+* 04-15-84 DFW written
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types
+* for pathname and arglist. #include-d PROCESS.H and
+* added ellipsis to match prototype
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stddef.h>
+#include <process.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <malloc.h>
+
+/***
+*int _spawnle(modeflag, pathname, arglist) - spawn a child process with env.
+*
+*Purpose:
+* Spawns a child process with given parameters and environment.
+* formats the parameters and calls _spawnve to do the actual work.
+* NOTE - at least one argument must be present. This argument is always,
+* by convention, the name of the file being spawned.
+*
+*Entry:
+* int modeflag - mode of spawn (WAIT, NOWAIT, OVERLAY)
+* only WAIT, and OVERLAY currently implemented
+* char *pathname - name of file to spawn
+* char *arglist - argument list, environment is at the end
+* call as _spawnle(modeflag, path, arg0, arg1, ..., argn, NULL, envp);
+*
+*Exit:
+* returns exit code of spawned process
+* if fails, return -1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _spawnle (
+ int modeflag,
+ const char *pathname,
+ const char *arglist,
+ ...
+ )
+{
+ va_list vargs;
+ char * argbuf[64];
+ char ** argv;
+ char ** envp;
+ int result;
+
+ assert(pathname != NULL);
+ assert(*pathname != '\0');
+ assert(arglist != NULL);
+ assert(*arglist != '\0');
+
+ va_start(vargs, arglist);
+ argv = _capture_argv(&vargs, arglist, argbuf, 64);
+ envp = va_arg(vargs, char **);
+ va_end(vargs);
+
+ result = _spawnve(modeflag,pathname,argv,envp);
+ if (argv && argv != argbuf) free(argv);
+ return result;
+}
diff --git a/private/crt32/exec/spawnlp.c b/private/crt32/exec/spawnlp.c
new file mode 100644
index 000000000..22516c929
--- /dev/null
+++ b/private/crt32/exec/spawnlp.c
@@ -0,0 +1,85 @@
+/***
+*spawnlp.c - spawn a file; search along PATH
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _spawnlp() - spawn a file with search along PATH
+*
+*Revision History:
+* 04-15-84 DFW written
+* 10-29-85 TC added spawnlpe
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types
+* for filename and arglist. #include-d PROCESS.H and
+* added ellipsis to match prototype.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2 and added #include
+* <cruntime.h>.
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stddef.h>
+#include <process.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <malloc.h>
+
+/***
+*_spawnlp(modeflag, filename, arglist) - spawn file and search along PATH
+*
+*Purpose:
+* Spawns a child process.
+* formats the parameters and calls _spawnvp to do the work of searching
+* the PATH environment variable and calling _spawnve. The NULL
+* environment pointer indicates that the new process will inherit the
+* parents process's environment. NOTE - at least one argument must be
+* present. This argument is always, by convention, the name of the file
+* being spawned.
+*
+*Entry:
+* int modeflag - mode of spawn (WAIT, NOWAIT, OVERLAY)
+* only WAIT, OVERLAY currently implemented
+* char *pathname - file to spawn
+* char *arglist - argument list
+* call as _spawnlp(modeflag, path, arg0, arg1, ..., argn, NULL);
+*
+*Exit:
+* returns exit code of child process
+* returns -1 if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _spawnlp (
+ int modeflag,
+ const char *filename,
+ const char *arglist,
+ ...
+ )
+{
+ va_list vargs;
+ char * argbuf[64];
+ char ** argv;
+ int result;
+
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(arglist != NULL);
+ assert(*arglist != '\0');
+
+ va_start(vargs, arglist);
+ argv = _capture_argv(&vargs, arglist, argbuf, 64);
+ va_end(vargs);
+
+ result = _spawnvp(modeflag,filename,argv);
+ if (argv && argv != argbuf) free(argv);
+ return result;
+}
diff --git a/private/crt32/exec/spawnlpe.c b/private/crt32/exec/spawnlpe.c
new file mode 100644
index 000000000..10520aecb
--- /dev/null
+++ b/private/crt32/exec/spawnlpe.c
@@ -0,0 +1,87 @@
+/***
+*spawnlpe.c - spawn a child process with environ and search along PATH
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _spawnlpe() - spawn a child process with environ/PATH search
+*
+*Revision History:
+* 04-15-84 DFW written
+* 10-29-85 TC added spawnlpe
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types
+* for filename and arglist. #include-d PROCESS.H and
+* added ellipsis to match prototype.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stddef.h>
+#include <process.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <malloc.h>
+
+/***
+*int _spawnlpe(modeflag, filename, arglist) - spawn a child process
+*
+*Purpose:
+* Spawns a child process.
+* formats the parameters and calls _spawnvpe to do the work of searching
+* the PATH environment variable and calling _spawnve. The NULL
+* environment pointer indicates that the new process will inherit the
+* parents process's environment. NOTE - at least one argument must be
+* present. This argument is always, by convention, the name of the file
+* being spawned.
+*
+*Entry:
+* int modeflag - defines what mode of spawn (WAIT, NOWAIT, OVERLAY)
+* only WAIT and OVERLAY currently supported
+* char *pathname - file to spawn
+* char *arglist - list of arguments (environ at end)
+* call as _spawnlpe(modeflag, path, arg0, arg1, ..., argn, NULL, envp);
+*
+*Exit:
+* returns exit code of spawned process
+* returns -1 if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _spawnlpe (
+ int modeflag,
+ const char *filename,
+ const char *arglist,
+ ...
+ )
+{
+ va_list vargs;
+ char * argbuf[64];
+ char ** argv;
+ char ** envp;
+ int result;
+
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(arglist != NULL);
+ assert(*arglist != '\0');
+
+ va_start(vargs, arglist);
+ argv = _capture_argv(&vargs, arglist, argbuf, 64);
+ envp = va_arg(vargs, char **);
+ va_end(vargs);
+
+ result = _spawnvpe(modeflag,filename,argv,envp);
+ if (argv && argv != argbuf) free(argv);
+ return result;
+}
diff --git a/private/crt32/exec/spawnv.c b/private/crt32/exec/spawnv.c
new file mode 100644
index 000000000..fe90c213f
--- /dev/null
+++ b/private/crt32/exec/spawnv.c
@@ -0,0 +1,67 @@
+/***
+*spawnv.c - spawn a child process
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _spawnv() - spawn a child process
+*
+*Revision History:
+* 04-15-84 DFW written
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types
+* for pathname and argv.
+* 03-08-90 GJF Replace _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 02-14-90 SRW Use NULL instead of _environ to get default.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <process.h>
+
+/***
+*int _spawnv(modeflag, pathname, argv) - spawn a child process
+*
+*Purpose:
+* Spawns a child process.
+* formats the parameters and calls _spawnve to do the actual work. The
+* NULL environment pointer indicates that the new process will inherit
+* the parents process's environment. NOTE - at least one argument must
+* be present. This argument is always, by convention, the name of the
+* file being spawned.
+*
+*Entry:
+* int modeflag - mode to spawn (WAIT, NOWAIT, or OVERLAY)
+* only WAIT and OVERLAY currently implemented
+* char *pathname - file to spawn
+* char **argv - vector of arguments
+*
+*Exit:
+* returns exit code of child process
+* if fails, returns -1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _spawnv (
+ int modeflag,
+ const char *pathname,
+ const char * const *argv
+ )
+{
+ assert(pathname != NULL);
+ assert(*pathname != '\0');
+ assert(argv != NULL);
+ assert(*argv != NULL);
+ assert(**argv != '\0');
+
+ return(_spawnve(modeflag,pathname,argv,NULL));
+}
diff --git a/private/crt32/exec/spawnve.c b/private/crt32/exec/spawnve.c
new file mode 100644
index 000000000..00e321dd2
--- /dev/null
+++ b/private/crt32/exec/spawnve.c
@@ -0,0 +1,318 @@
+/***
+*spawnve.c - OS/2 low level routine eventually called by all _spawnXX routines
+* also contains all code for _execve, called by _execXX routines
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+* This is the low level routine which is eventually invoked by all the
+* _spawnXX routines.
+*
+* This is also the low-level routine which is eventually invoked by
+* all of the _execXX routines.
+*
+*Revision History:
+* 03-??-84 RLB created
+* 05-??-84 DCW modified to fix bug in initialization of envblock
+* pointer (used int 0 which would fail in long model) and
+* changed (char *)0 to NULL.
+* 03-31-86 SKS modified for OS/2; no OVERLAY mode,
+* new format for DOS Exec function
+* also check for Xenix or DOS style slash characters
+* 10-13-86 SKS pass program name to _cenvarg()
+* 11-19-86 SKS handle both kinds of slashes, with support for Kanji
+* 01-29-87 BCM don't try ".com" extension in protected mode (OS/2)
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05/31/88 SJM Re-written to allow spawn of .CMD files, increase
+* speed. Added comexecmd routine.
+* 06/01/88 SJM added #ifdef statements for execve.obj compilation
+* 10-30-88 GJF Call _dospawn() for EXECVE, not _doexec().
+* 07-21-89 GJF Progagated fixes of 11-23-88 and 05-27-89 from CRT tree.
+* 11-16-89 GJF Added code to execve/spawnve to ensure a relative or
+* or absolute pathname is always used for the executable,
+* not just a filename (otherwise DOSEXECPGM will search
+* the PATH!). Also, cleaned up some of the erratic
+* formatting. Same as 9-15-89 change to CRT version
+* 11-20-89 GJF Added const attribute to types of appropriate args.
+* 02-08-90 GJF Fixed bug in comexecmd (must free(comname) if and only
+* if comname points to a malloc-ed block). Propagated
+* from 02-07-90 change in crt6 version.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 04-02-90 GJF Made comexecmd() _CALLTYPE4. Added #include <io.h>
+* and a prototype for comexecmd() to fix compiler
+* warnings (-W3).
+* 05-21-90 GJF Fixed stack checking pragma syntax.
+* 07-24-90 SBM Removed redundant include, minor optimization
+* 09-27-90 GJF New-style function declarators.
+* 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragma
+* 01-17-91 GJF ANSI naming.
+* 08-21-91 JCR Call access() in before comexecmd (bug fix)
+* 01-24-92 JCR upgraded for Win32
+* 10-24-92 SKS Remove special treatment for batch files -
+* Windows NT will spawn %COMSPEC% automatically
+* 11-30-92 KRS Ported _MBCS support from 16-bit tree.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <io.h>
+#include <process.h>
+#include <errno.h>
+#include <msdos.h>
+#include <string.h>
+#include <stdlib.h>
+#include <internal.h>
+#include <mbstring.h>
+
+#ifdef _CRUISER_
+#pragma check_stack(on) /* turn on stack checking */
+#endif /* ndef _CRUISER_ */
+
+#define SLASHCHAR '\\'
+#define XSLASHCHAR '/'
+
+#ifndef EXECVE
+static int _CALLTYPE4 comexecmd(int mode, const char * name,
+ const char * const * argv, const char * const * envp);
+#else
+static int _CALLTYPE4 comexecmd(const char * name,
+ const char * const * argv, const char * const * envp);
+#endif /* EXECVE */
+
+/***
+*static int comexecmd(mode, name, argv, envp) - do the exec
+* or spawn after name fixup
+*
+*Purpose:
+* Spawns a child process with given parameters and environment. Either
+* overlays current process or loads in free memory while parent process
+* waits. If the named file is a .cmd file, modifies the calling sequence
+* and prepends the /c and filename arguments into the command string
+*
+* Exec doesn't take a mode; instead, the parent process goes away as
+* the child process is brought in.
+*
+*Entry:
+* int mode - mode to spawn (WAIT, NOWAIT, or OVERLAY)
+* only WAIT and OVERLAY currently supported
+*
+* **** mode is only used in the spawnve() version ****
+*
+* char *name - pathname of file to spawn. Includes the extension
+* char **argv - vector of parameter strings
+* char **envp - vector of environment variables
+*
+*Exit:
+* returns exit code of child process
+* if fails, returns -1
+*
+*Exceptions:
+* Returns a value of (-1) to indicate an error in exec'ing the child
+* process. errno may be set to:
+*
+* E2BIG = failed in argument/environment processing (_cenvarg)
+* argument list or environment too big;
+* EACCESS = locking or sharing violation on file;
+* EMFILE = too many files open;
+* ENOENT = failed to find program name - no such file or directory;
+* ENOEXEC = failed in exec - bad executable format;
+* ENOMEM = failed in memory allocation (during malloc, or in
+* setting up memory for executing child process).
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 comexecmd (
+
+#ifndef EXECVE
+ REG3 int mode,
+#endif /* EXECVE */
+
+ REG2 const char *name,
+ const char * const *argv,
+ const char * const *envp
+ )
+{
+ char *argblk;
+ char *envblk;
+ REG4 int rc;
+
+ if (_cenvarg(argv, envp, &argblk, &envblk, name) == -1)
+ return -1;
+
+#ifndef EXECVE
+ rc = _dospawn(mode, name, argblk, envblk);
+#else
+ rc = _dospawn(_P_OVERLAY, name, argblk, envblk);
+#endif
+ /* free memory */
+
+ free(argblk);
+ free(envblk);
+
+ return rc;
+}
+
+/***
+*int _spawnve(mode, name, argv, envp) - low level _spawnXX library function
+*int _execve(name, argv, envp) - low level _execXX library function
+*
+*Purpose:
+* spawns or execs a child process; takes a single pointer to an argument
+* list as well as a pointer to the environment; unlike _spawnvpe,
+* _spawnve does not search the PATH= list in processing the name
+* parameter; mode specifies the parent's execution mode.
+*
+*Entry:
+* int mode - parent process's execution mode:
+* must be one of _P_OVERLAY, _P_WAIT, _P_NOWAIT;
+* not used for _execve
+* char *name - path name of program to spawn;
+* char **argv - pointer to array of pointers to child's arguments;
+* char **envp - pointer to array of pointers to child's environment
+* settings.
+*
+*Exit:
+* Returns : (int) a status value whose meaning is as follows:
+* 0 = normal termination of child process;
+* positive = exit code of child upon error termination
+* (abort or exit(nonzero));
+* -1 = child process was not spawned;
+* errno indicates what kind of error:
+* (E2BIG, EINVAL, ENOENT, ENOEXEC, ENOMEM).
+*
+*Exceptions:
+* Returns a value of (-1) to indicate an error in spawning the child
+* process. errno may be set to:
+*
+* E2BIG = failed in argument/environment processing (_cenvarg) -
+* argument list or environment too big;
+* EINVAL = invalid mode argument;
+* ENOENT = failed to find program name - no such file or directory;
+* ENOEXEC = failed in spawn - bad executable format;
+* ENOMEM = failed in memory allocation (during malloc, or in
+* setting up memory for spawning child process).
+*
+*******************************************************************************/
+
+/* Extension array - ordered in search order from right to left.
+
+ ext_strings = array of extensions
+*/
+
+#ifdef _CRUISER_
+static char *ext_strings[] = { NULL, ".exe", ".com" };
+enum {CMD, EXE, COM, EXTFIRST=CMD, EXTLAST=COM};
+#else
+static char *ext_strings[] = { ".cmd", ".bat", ".exe" , ".com" };
+enum {CMD, BAT, EXE, COM, EXTFIRST=CMD, EXTLAST=COM};
+#endif
+
+int _CALLTYPE1
+
+#ifndef EXECVE
+
+_spawnve (
+ REG3 int mode,
+
+#else
+
+_execve (
+
+#endif /* EXECVE */
+
+ const char *name,
+ const char * const *argv,
+ const char * const *envp
+ )
+{
+ char *ext; /* where the extension goes if we have to add one */
+ REG1 char *p;
+ char *q;
+ REG2 char *pathname = (char *)name;
+ REG4 int rc;
+ REG5 int i;
+
+#ifdef _CRUISER_
+ exstrings[CMD] = _osmode ? ".cmd" : ".bat";
+#endif
+
+ p = _mbsrchr(pathname, SLASHCHAR);
+ q = strrchr(pathname, XSLASHCHAR); /* No need for _mbsrchr with "/" */
+
+ /* ensure that pathname is an absolute or relative pathname. also,
+ * position p to point at the filename portion of pathname (i.e., just
+ * after the last occurence of a colon, slash or backslash character */
+
+ if (!q) {
+ if (!p)
+ if (!(p = strchr(pathname, ':'))) {
+
+ /* pathname is a filename only, force it to be
+ * a relative pathname. note that an extra byte
+ * is malloc-ed just in case pathname is NULL,
+ * to keep the heap from being trashed by
+ * strcpy */
+ if (!(pathname = malloc(strlen(pathname) + 3)))
+ return(-1);
+
+ strcpy(pathname, ".\\");
+ strcat(pathname, name);
+
+ /* set p to point to the start of the filename
+ * (i.e., past the ".\\" prefix) */
+ p = pathname + 2;
+ }
+ /* else pathname has drive specifier prefix and p is
+ * is pointing to the ':' */
+ }
+ else if (!p || q > p) /* p == NULL or q > p */
+ p = q;
+
+
+ rc = -1; /* init to error value */
+
+ if (ext = strrchr(p, '.')) {
+
+ /* extension given; only do filename */
+
+ if (_access(pathname, 0) != -1) {
+#ifndef EXECVE
+ rc = comexecmd(mode, pathname, argv, envp);
+#else
+ rc = comexecmd(pathname, argv, envp);
+#endif
+ }
+
+ }
+ else {
+
+ /* no extension; try .cmd/.bat, then .com and .exe */
+
+ if (!(p = malloc(strlen(pathname) + 5)))
+ return(-1);
+
+ strcpy(p, pathname);
+ ext = p + strlen(pathname);
+
+ for (i = EXTLAST; i >= EXTFIRST; --i) {
+ strcpy(ext, ext_strings[i]);
+
+ if (_access(p, 0) != -1) {
+#ifndef EXECVE
+ rc = comexecmd(mode, p, argv, envp);
+#else
+ rc = comexecmd(p, argv, envp);
+#endif /* EXECVE */
+ break;
+ }
+ }
+ free(p);
+ }
+
+ if (pathname != name)
+ free(pathname);
+
+ return rc;
+}
diff --git a/private/crt32/exec/spawnvp.c b/private/crt32/exec/spawnvp.c
new file mode 100644
index 000000000..f31dc2c60
--- /dev/null
+++ b/private/crt32/exec/spawnvp.c
@@ -0,0 +1,62 @@
+/***
+*spawnvp.c - spawn a child process; search along PATH
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _spawnvp() - spawn a child process; search along PATH
+*
+*Revision History:
+* 04-15-84 DFW written
+* 10-29-85 TC added spawnvpe capability
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, alignment. Added const to arg types
+* for filename and argv.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>
+* 05-21-90 GJF Fixed stack checking pragma syntax.
+* 08-24-90 SBM Removed check_stack pragma since workhorse _spawnve
+* does stack checks
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 02-14-90 SRW Use NULL instead of _environ to get default.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <process.h>
+
+/***
+*int _spawnvp(modeflag, filename, argv) - spawn a child process (search PATH)
+*
+*Purpose:
+* Spawns a child process, with search along PATH variable.
+* formats the parameters and calls _spawnve to do the actual work. The
+* NULL environment pointer indicates the new process will inherit the
+* parents process's environment. NOTE - at least one argument must be
+* present. This argument is always, by convention, the name of the file
+* being spawned.
+*
+*Entry:
+* int modeflag - mode to spawn (WAIT, NOWAIT, or OVERLAY)
+* only WAIT and OVERLAY currently supported
+* char *pathname - name of file to spawn
+* char **argv - vector of arguments
+*
+*Exit:
+* returns exit code of child process
+* returns -1 if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _spawnvp (
+ int modeflag,
+ REG3 const char *filename,
+ const char * const *argv
+ )
+{
+ return _spawnvpe(modeflag, filename, argv, NULL);
+}
diff --git a/private/crt32/exec/spawnvpe.c b/private/crt32/exec/spawnvpe.c
new file mode 100644
index 000000000..ffbdbb55a
--- /dev/null
+++ b/private/crt32/exec/spawnvpe.c
@@ -0,0 +1,209 @@
+/***
+*spawnvpe.c - spawn a child process with given environ (search PATH)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _spawnvpe() - spawn a child process with given environ (search
+* PATH)
+*
+*Revision History:
+* 04-15-84 DFW written
+* 10-29-85 TC added spawnvpe capability
+* 11-19-86 SKS handle both kinds of slashes
+* 12-01-86 JMB added Kanji file name support under conditional KANJI
+* switches. Corrected header info. Removed bogus check
+* for env = b after call to strncpy
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 09-05-88 SKS Treat EACCES the same as ENOENT -- keep trying
+* 10-17-88 GJF Removed copy of PATH string to local array, changed
+* bbuf to be a malloc-ed buffer. Removed bogus limits
+* on the size of that PATH string.
+* 10-25-88 GJF Don't search PATH when relative pathname is given (per
+* Stevesa). Also, if the name built from PATH component
+* and filename is a UNC name, allow any error.
+* 05-17-89 MT Added "include <jstring.h>" under KANJI switch
+* 05-24-89 PHG Reduce _amblksiz to use minimal memory (DOS only)
+* 08-29-89 GJF Use _getpath() to retrieve PATH components, fixing
+* several problems in handling unusual or bizarre
+* PATH's.
+* 11-20-89 GJF Added const attribute to types of filename, argv and
+* envptr.
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>
+* 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
+* <assert.h>
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 09-25-91 JCR Changed ifdef "OS2" to "_DOS_" (unused in 32-bit tree)
+* 11-30-92 KRS Port _MBCS code from 16-bit tree.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <internal.h>
+#include <process.h>
+#include <mbstring.h>
+
+#define SLASH "\\"
+#define SLASHCHAR '\\'
+#define XSLASHCHAR '/'
+#define DELIMITER ";"
+
+#ifdef _MBCS
+/* note, the macro below assumes p is to pointer to a single-byte character
+ * or the 1st byte of a double-byte character, in a string.
+ */
+#define ISPSLASH(p) ( ((p) == _mbschr((p), SLASHCHAR)) || ((p) == \
+_mbschr((p), XSLASHCHAR)) )
+#else
+#define ISSLASH(c) ( ((c) == SLASHCHAR) || ((c) == XSLASHCHAR) )
+#endif
+
+/***
+*_spawnvpe(modeflag, filename, argv, envptr) - spawn a child process
+*
+*Purpose:
+* Spawns a child process with the given arguments and environ,
+* searches along PATH for given file until found.
+* Formats the parameters and calls _spawnve to do the actual work. The
+* NULL environment pointer indicates that the new process will inherit
+* the parents process's environment. NOTE - at least one argument must
+* be present. This argument is always, by convention, the name of the
+* file being spawned.
+*
+*Entry:
+* int modeflag - defines mode of spawn (WAIT, NOWAIT, or OVERLAY)
+* only WAIT and OVERLAY supported
+* char *filename - name of file to execute
+* char **argv - vector of parameters
+* char **envptr - vector of environment variables
+*
+*Exit:
+* returns exit code of spawned process
+* if fails, returns -1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _spawnvpe (
+ int modeflag,
+ REG3 const char *filename,
+ const char * const *argv,
+ const char * const *envptr
+ )
+{
+ int i;
+ REG1 char *env;
+ REG2 char *buf = NULL;
+ char *pfin;
+#ifdef _DOS_
+ int tempamblksiz; /* old _amblksiz */
+#endif
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(argv != NULL);
+ assert(*argv != NULL);
+ assert(**argv != '\0');
+
+#ifdef _DOS_
+ tempamblksiz = _amblksiz;
+ _amblksiz = 0x10; /* reduce _amblksiz for efficient mallocs */
+#endif
+
+ if (
+ (i = _spawnve(modeflag, filename, argv, envptr)) != -1
+ /* everything worked just fine; return i */
+
+ || (errno != ENOENT)
+ /* couldn't spawn the process, return failure */
+
+ /* In a SBCS build, _mbschr will map to strchr. */
+
+ || (_mbschr(filename, XSLASHCHAR) != NULL)
+ /* filename contains a '/', return failure */
+
+#ifdef _DOS_
+ || (_mbschr(filename,SLASHCHAR) != NULL)
+ /* filename contains a '\', return failure */
+
+ || *filename && *(filename+1) == ':'
+ /* drive specification, return failure */
+#endif
+
+ || !(env = getenv("PATH"))
+ /* no PATH environment string name, return failure */
+
+ || ( (buf = (char *)malloc(_MAX_PATH)) == NULL )
+ /* cannot allocate buffer to build alternate pathnames, return
+ * failure */
+ ) {
+#ifdef _DOS_
+ _amblksiz = tempamblksiz; /* restore old _amblksiz */
+#endif
+ goto done;
+ }
+
+#ifdef _DOS_
+ _amblksiz = tempamblksiz; /* restore old _amblksiz */
+#endif
+
+
+ /* could not find the file as specified, search PATH. try each
+ * component of the PATH until we get either no error return, or the
+ * error is not ENOENT and the component is not a UNC name, or we run
+ * out of components to try.
+ */
+
+ while ( (env = _getpath(env, buf, _MAX_PATH - 1)) && (*buf) ) {
+
+ pfin = buf + strlen(buf) - 1;
+
+ /* if necessary, append a '/'
+ */
+#ifdef _MBCS
+ if (*pfin == SLASHCHAR) {
+ if (pfin != _mbsrchr(buf,SLASHCHAR))
+ /* fin is the second byte of a double-byte char */
+ strcat(buf, SLASH );
+ }
+ else if (*pfin !=XSLASHCHAR)
+ strcat(buf, SLASH);
+#else
+ if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR)
+ strcat(buf, SLASH);
+#endif
+ /* check that the final path will be of legal size. if so,
+ * build it. otherwise, return to the caller (return value
+ * and errno rename set from initial call to _spawnve()).
+ */
+ if ( (strlen(buf) + strlen(filename)) < _MAX_PATH )
+ strcat(buf, filename);
+ else
+ break;
+
+ /* try spawning it. if successful, or if errno comes back with a
+ * value other than ENOENT and the pathname is not a UNC name,
+ * return to the caller.
+ */
+ if ( (i = _spawnve(modeflag, buf, argv, envptr)) != -1
+ || ((errno != ENOENT)
+#ifdef _MBCS
+ && (!ISPSLASH(buf) || !ISPSLASH(buf+1))) )
+#else
+ && (!ISSLASH(*buf) || !ISSLASH(*(buf+1)))) )
+#endif
+ break;
+
+ }
+
+done:
+ if (buf != NULL) free(buf);
+ return(i);
+}
diff --git a/private/crt32/exec/system.c b/private/crt32/exec/system.c
new file mode 100644
index 000000000..44536cf38
--- /dev/null
+++ b/private/crt32/exec/system.c
@@ -0,0 +1,95 @@
+/***
+*system.c - pass a command line to the shell
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines system() - passes a command to the shell
+*
+*Revision History:
+* 12-01-83 RN written
+* 10-23-86 SKS Fixed use of strtok(), added check for NULL rtn from getenv
+* 12-18-86 SKS PROTMODE symbol used for dual-modal version
+* 02-23-86 JCR Put in support for NULL command pointer (MSDOS only)
+* 04-13-86 JCR Added const to declaration
+* 06-30-87 JCR Re-wrote system to use spawnvpe, removed XENIX conditional
+* code, lots of general cleaning up.
+* 07-01-87 PHG removed P->PROTMODE compile switch hack
+* 09-22-87 SKS remove extern variable declarations, add ";" to assert()'s
+* 11-10-87 SKS Removed IBMC20 switch, change PROTMODE to OS2
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 02-22-88 JCR Added cast to get rid of cl const warning
+* 09-05-88 SKS Treat EACCES the same as ENOENT -- keep trying
+* 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed some leftover DOS support and
+* fixed the copyright. Also, cleaned up the formatting
+* formatting a bit.
+* 07-23-90 SBM Compiles cleanly with -W3 (removed unreferenced
+* variable), removed redundant includes, replaced
+* <assertm.h> by <assert.h>, minor optimizations
+* 09-27-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+* 02-14-90 SRW Use NULL instead of _environ to get default.
+* 02-23-93 SKS Remove reference to _osmode and use of "command.com"
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <process.h>
+#include <io.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/***
+*int system(command) - send the command line to a shell
+*
+*Purpose:
+* Executes a shell and passes the command line to it.
+* If command is NULL, determine if a command processor exists.
+*
+*Entry:
+* char *command - command to pass to the shell (if NULL, just determine
+* if command processor exists)
+*
+*Exit:
+* if command != NULL returns status of the shell
+* if command == NULL returns non-zero if CP exists, zero if CP doesn't exist
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 system (
+ const char *command
+ )
+{
+ int catch;
+ char *argv[4];
+
+ argv[0] = getenv("COMSPEC");
+
+ if (command == NULL) {
+ return (!_access(argv[0],0));
+ }
+
+ assert(*command != '\0');
+
+ argv[1] = "/c";
+ argv[2] = (char *) command;
+ argv[3] = NULL;
+
+ /* If there is a COMSPEC defined, try spawning the shell */
+
+ if (argv[0]) /* Do not try to spawn the null string */
+ if ((catch = _spawnve(_P_WAIT,argv[0],argv,NULL)) != -1
+ || (errno != ENOENT && errno != EACCES))
+ return(catch);
+
+ /* No COMSPEC so set argv[0] to what COMSPEC should be. */
+ argv[0] = "cmd.exe";
+
+ /* Let the _spawnvpe routine do the path search and spawn. */
+
+ return(_spawnvpe(_P_WAIT,argv[0],argv,NULL));
+}
diff --git a/private/crt32/exec/wait.c b/private/crt32/exec/wait.c
new file mode 100644
index 000000000..c6ba4cae4
--- /dev/null
+++ b/private/crt32/exec/wait.c
@@ -0,0 +1,199 @@
+/***
+*wait.c - OS/2 wait for child process to terminate
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wait() - wait for child process to terminate
+*
+*Revision History:
+* 06-08-89 PHG Module created, based on asm version
+* 03-08-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned up
+* the formatting a bit.
+* 04-02-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 09-27-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-17-91 GJF ANSI naming
+* 02-18-91 SRW Fixed code to close process handle. [_WIN32_]
+* 04-26-91 SRW Removed level 3 warnings [_WIN32_]
+* 12-17-91 GJF Fixed _cwait for Win32. However, _wait is still
+* broken [_WIN32_].
+* 07-21-92 GJF Removed _wait for Win32, not implemented and no good
+* way to implement.
+* 12-14-92 GJF For Win32, map ERROR_INVALID_HANDLE to ECHILD.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <process.h>
+#include <errno.h>
+#include <internal.h>
+#include <stdlib.h>
+
+/***
+*int _cwait(stat_loc, process_id, action_code) - wait for specific child
+* process
+*
+*Purpose:
+* The function _cwait() suspends the calling-process until the specified
+* child-process terminates. If the specifed child-process terminated
+* prior to the call to _cwait(), return is immediate.
+*
+*Entry:
+* int *stat_loc - pointer to where status is stored or NULL
+* process_id - specific process id to be interrogated (0 means any)
+* action_code - specific action to perform on process ID
+* either _WAIT_CHILD or _WAIT_GRANDCHILD
+*
+*Exit:
+* process ID of terminated child or -1 on error
+*
+* *stat_loc is updated to contain the following:
+* Normal termination: lo-byte = 0, hi-byte = child exit code
+* Abnormal termination: lo-byte = term status, hi-byte = 0
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _cwait (
+ int *stat_loc,
+ int process_id,
+ int action_code
+ )
+{
+#ifdef _CRUISER_
+ ULONG retstatus; /* return status from child */
+ ULONG retval; /* return value from wait */
+ char abnormend; /* child terminated abnormally */
+ ULONG dosretval; /* return value from OS/2 call */
+ RESULTCODES retcodes; /* return codes from child process */
+ PID pid_finished; /* process id of child that finished */
+
+ /* call OS/2 wait for child routine */
+ if (dosretval = DOSWAITCHILD(action_code, DCWW_WAIT, &retcodes,
+ &pid_finished, process_id)) {
+ /* error occured -- map error code and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ /* set status code values -- note that return value is
+ truncated to a byte for XENIX compatibility */
+
+ if (retcodes.codeTerminate != 0) {
+ abnormend = 1;
+ retstatus = retcodes.codeTerminate & 0xFF;
+ }
+ else {
+ abnormend = 0;
+ retstatus = (retcodes.codeResult & 0xFF) << 8 +
+ (retcodes.codeTerminate & 0xFF);
+ }
+
+ if (stat_loc != NULL)
+ *stat_loc = retstatus;
+
+ if (abnormend) {
+ /* abnormal termination, set errno and return -1 */
+ errno = EINTR;
+ _doserrno = 0; /* no OS/2 error */
+ return -1;
+ }
+
+ return retval;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ int retval;
+ int retstatus;
+ unsigned long oserror;
+
+ DBG_UNREFERENCED_PARAMETER(action_code);
+
+ /* Explicitly check for process_id being -1 or -2. In Windows NT,
+ * -1 is a handle on the current process, -2 is a handle on the
+ * current thread, and it is perfectly legal to to wait (forever)
+ * on either */
+ if ( (process_id == -1) || (process_id == -2) ) {
+ errno = ECHILD;
+ return -1;
+ }
+
+ /* wait for child process, then fetch its exit code */
+ if ( (WaitForSingleObject((HANDLE)process_id, (DWORD)(-1L)) == 0) &&
+ GetExitCodeProcess((HANDLE)process_id, (LPDWORD)&retstatus) ) {
+ retval = process_id;
+ }
+ else {
+ /* one of the API calls failed. map the error and set up to
+ return failure. note the invalid handle error is mapped in-
+ line to ECHILD */
+ if ( (oserror = GetLastError()) == ERROR_INVALID_HANDLE ) {
+ errno = ECHILD;
+ _doserrno = oserror;
+ }
+ else
+ _dosmaperr(GetLastError());
+
+ retval = -1;
+ retstatus = -1;
+ }
+
+ CloseHandle((HANDLE)process_id);
+
+ if (stat_loc != NULL)
+ *stat_loc = retstatus;
+
+ return retval;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+}
+
+
+#ifndef _WIN32_
+
+/***
+*int _wait(stat_loc) - wait for a child to terminate
+*
+*Purpose:
+* The function _wait() suspends the calling-process until one of the
+* immediate children terminates. If a child-process terminated prior to
+* the call on the function _wait(), return is immediate.
+*
+*Entry:
+* int *stat_loc - pointer to where status is stored or NULL
+*
+*Exit:
+* returns process id or -1 on errors.
+*
+* *stat_loc is updated to contain the following:
+* Normal termination: lo-byte = 0, hi-byte = child exit code
+* Abnormal termination: lo-byte = term status, hi-byte = 0
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+/* _wait calls _cwait to do all the real work */
+int _CRTAPI1 _wait (
+ int *stat_loc
+ )
+{
+ return _cwait(stat_loc, 0, _WAIT_CHILD);
+}
+
+
+#endif
diff --git a/private/crt32/h/assert.h b/private/crt32/h/assert.h
new file mode 100644
index 000000000..944ba02b4
--- /dev/null
+++ b/private/crt32/h/assert.h
@@ -0,0 +1,89 @@
+/***
+*assert.h - define the assert macro
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the assert(exp) macro.
+* [ANSI/System V]
+*
+*Revision History:
+* 12-18-87 JCR Added _FAR_ to declarations
+* 01-18-88 JCR Added fflush(stderr) to go with new stderr buffering scheme
+* 02-10-88 JCR Cleaned up white space
+* 05-19-88 JCR Use routine _assert() to save space
+* 07-14-88 JCR Allow user's to enable/disable assert multiple times in
+* a single module [ANSI]
+* 10-19-88 JCR Revised to also work for the 386 (small model only)
+* 12-22-88 JCR Assert() must be an expression (no 'if' statements)
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 07-27-89 GJF Cleanup, now specific to the 386
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 02-27-90 GJF Added #include <cruntime.h> stuff. Also, removed some
+* (now) useless preprocessor directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 in prototype.
+* 07-31-90 SBM added ((void)0) to NDEBUG definition, now ANSI
+* 08-20-91 JCR C++ and ANSI naming
+* 08-26-92 GJF Function calling type and variable type macros.
+* 09-25-92 SRW Don't use ? in assert macro to keep CFRONT happy.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 02-01-93 GJF Replaced SteveWo's assert macro with an ANSI-conformant
+* one. Also got rid of '//' comment characters.
+*
+****/
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+#undef assert
+
+#ifdef NDEBUG
+
+#define assert(exp) ((void)0)
+
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void _CRTAPI1 _assert(void *, void *, unsigned);
+#ifdef __cplusplus
+}
+#endif
+
+#define assert(exp) (void)( (exp) || (_assert(#exp, __FILE__, __LINE__), 0) )
+
+#ifndef _INTERNAL_IFSTRIP_
+/*
+ * CFRONT chokes on ? if uses on a cdecl function call. So use if
+ * for now, until we convert to c8
+ *
+ * ( (exp) ? (void) 0 : _assert(#exp, __FILE__, __LINE__) )
+ */
+#endif /* _INTERNAL_IFSTRIP_ */
+
+#endif /* NDEBUG */
diff --git a/private/crt32/h/cmacros.mas b/private/crt32/h/cmacros.mas
new file mode 100644
index 000000000..a39638c24
--- /dev/null
+++ b/private/crt32/h/cmacros.mas
@@ -0,0 +1,3050 @@
+comment $
+
+ SCCSID = "@(#)cmacros.mas:1.12"
+
+cmacros - assembly macros for interfacing to hhls
+
+(C)Copyright Microsoft Corp. 1984-1987
+
+$
+
+;; Revision History
+;;
+;; 1.00 05/03/84 Initial Release
+;;
+;; 1.01 05/06/84 Greg Whitten
+;; Added defgrp and changed cMerge to Microsoft C
+;; Added copyright message and changed to 1.01
+;; Changes should have no affect on working programs
+;;
+;; 1.02 07/10/84 Steve Wood
+;; Added labelx macros
+;;
+;; 1.03 07/14/84 Greg Whitten
+;; Added defines for ?pu, ?adj, ?lblpu
+;; (removes undefined errors)
+;; Changes should have no affect on working programs
+;;
+;; 1.04 07/18/84 Greg Whitten
+;; Added local control from PL/M or C conventions
+;; except for cCall macro
+;;
+;; 1.05 08/06/84 Steve Wood
+;; Made ?PLM and ?WIN be the defaults
+;;
+;; 1.06 01/02/85 Steve Wood
+;; Changed createSeg and defgrp to automatically
+;; define the ln_assumes macro and the lnoffset
+;; and lnbase equates for each logical segment
+;; name.
+;;
+;; 1.07 02/19/85 Walt Moore
+;; Added farptr macro for defining a far pointer
+;; to be used in a cCall. Folded regptr into
+;; farptr. Space compaction in macros. Changed
+;; ?pp to be smaller. Moved ?ia out of ?al1 into
+;; ?aloc. Merged cProc and ?pd into one macro.
+;; Changed some %outs to use the error macro so
+;; an error would be generated. Added makeframe
+;; and parmR to cProc. Changed error to also put
+;; the error message in the listing.
+;; Deleted the smashes macro.
+;;
+;; 1.08 03/18/85 Steve Wood
+;; Added NODATA support.
+;;
+;; 1.09 03/27/85 Steve Wood
+;; Added ?definitions
+;;
+;; 2.00 04/01/85 Steve Wood
+;; April fools
+;;
+;; 2.01 06/17/85 Steve Wood
+;; Changed NODATA to always generate POP DS
+;; for return address patching
+;;
+;; 2.02 02/11/86 Steve Wood
+;; Added ATOMIC keyword to cProc macro
+;; Changed far epilog to use LEA SP,BP-2
+;; Changed error macro to ??error to avoid
+;; conflict
+;;
+;; 2.03 03/06/86 Steve Wood
+;; Fixed bug with ATOMIC and locals in far proc
+;; Added DOS5 switch to disable INC/DEC BP
+;; instructions in special far prologs/epilogs
+;;
+;; 2.04 08/07/86 Scott Randell
+;; Fixed bug with ATOMIC and ?TF
+;; (was doing unnecessary MOV SP,BP)
+;; Added pcode profile ?PROFILE
+;;
+;; 2.05 08/12/86 Walt Moore
+;; Changed _TEXT alignment to word.
+;; Added/corrected some comments.
+;; Removed redundant init of ?pc in cProc
+;; Made ATOMIC require NODATA
+;; Moved definition of non-underscored 'C' label
+;; from the cProc to the cBegin macro
+;; Minor clean-up of code
+;;
+;; 2.06 09/11/86 Walt Moore
+;; Added private stack checking
+;; Put local control for PL/M or C into cCall
+;;
+;;
+;; 2.07 09/19/86 Steve Wood
+;; Added ?SMALL, ?MEDIUM, etc. symbols
+;; Added forceframe keyword to cProc macro.
+;; Interpret ?TF for all epilogs.
+;;
+;; 3.xx.a 02/26/87 Walt Moore
+;; Massive rework. Documentation coming.
+;;
+;; 3.xx.b 04/08/87 NeilK
+;; Added parmH, which is like parmW except
+;; that it reserves 4 bytes on frame.
+;;
+;; 3.xx.c 05/11/87 Walt Moore
+;; Added <> to ?ap so that arg <DataOFFSET foo>
+;; can be used.
+;;
+;; 3.01 07/03/87 Walt Moore
+;; parm_bytes_&procname is now generated for
+;; all cProcs, and is the number of bytes of
+;; parameters to the cProc.
+;;
+;; NO_BP added as a keyword to cProc which
+;; causes all equates to be generated without
+;; reference to BP for the procedure. All type
+;; info is still generated, but the user must
+;; supply any segment and base register.
+;; ?NO_BP, if defined, makes this the default.
+;;
+;; USE_BP can be specified on the cProc line
+;; to force the generation of BP in equates.
+;;
+;; Moved definition of xxxxBASE. The equ was to
+;; a forward reference.
+;;
+;; Don't generate a warning for a nogen if only
+;; parameters are present.
+;;
+;; Keywords for cProc, cBegin, cEnd, and registers
+;; are now allowed to be either all upper case or
+;; all lower case.
+;;
+;; Only generate warnings on pass 2.
+;;
+;; 3.02 07/06/87 Walt Moore
+;; Boy did I screw up <nogen> If the text is
+;; recognized as nogen, then process it as such,
+;; else ignore it and generate frame as needed.
+;;
+;; 3.03 07/14/87 Walt Moore
+;; Added <partial> keyword to the cBegin macro
+;; to only allocate locals and save registers.
+;; Used in conjunction with dispatching in the
+;; Winthorn engine and drivers.
+;;
+;; Added cleanframe macro which will take the
+;; frame down, but not generate the RET statement.
+;; Used in conjunction with dispatching in the
+;; Winthorn engine and drivers.
+;;
+;; 3.04 07/16/87 Walt Moore
+;; globalD was generating off and seg name
+;; without word ptr override, giving them a
+;; dword attribute
+;;
+;; 3.05 07/17/87 Walt Moore
+;; .xcref cleanframe
+;;
+;; 3.06 07/24/87 Hans Spiller
+;; 32 bit small model (?SMALL32):
+;; new entry exit sequences using pseudoregs
+;; mach independant register names (IAX, etc)
+;; parmI/localI (int size variables)
+;; mpush/mpop uses mach independant names
+;; IPUSHF, IPOPF, IPUSHA,IPOPA,IIRET
+;;
+;; case sensitivity bugfix. the compiler
+;; generates "CODE", not "Code"
+;;
+;; 32 bit issues as yet undone: allocation
+;; macros for dealing with 32 bit mode far
+;; pointers, globalI, staticI, parmR, saving
+;; si,di vs. esi,edi,ebx
+;;
+;; 3.06a 09/29/87 Mark Roberts
+;; 32 bit small model (?SMALL32):
+;; fix a few bugs and add staticI
+;;
+;; 3.06b 07/20/87 Scott Randell
+;; Fix up for ?COW compatibility, added ?NOATOMIC
+;; to 3.xx version.
+;;
+;; 3.06c 04/29/88 Jim Schaad
+;; Put in ?DFDATA to force data segments even if
+;; ?NODATA is set.
+;;
+;; 3.06d 05/02/88 Andy Padawer
+;; Bug fixes for 3.06b (cEnd), 3.06c (general).
+;;
+;; 3.06e 08/31/88 Andy Padawer
+;; use "if memS32" not "ifdef ?SMALL32".
+;;
+;; 3.06f 05/12/89 Mark Roberts
+;; fix staticI, globalDP and add globalI
+;;
+;; 3.06g 12/07/89 Mark Roberts
+;; add externI
+;;
+;; 3.06h 01/25/90 Jan de Rie
+;; add ?DFCODE to allow suppressing code segments
+;;
+;; Assembly macros for interfacing to C
+;;
+;; User settable conditional assembly flags used within the cmacros
+;;
+;; Memory model flags. Set only one of the following. memS is the
+;; default. The symbols with ? are for defining from the command line
+;; and the memx symbols are numeric symbols that can be set in your source
+;; file prior to including this file.
+;;
+;; ?SMALL memS - small model
+;; ?MEDIUM memM - medium model
+;; ?LARGE memL - large model
+;; ?COMPACT memC - compact model
+;; ?HUGE memH - huge model
+;; ?SMALL32 memS32 - 32 bit small model
+;;
+;; ?DF Define flag. If this flag is 0, then defines default segment
+;; and group definitions based on the compiler flag. If this
+;; flag is 1, then does not define any segments or groups.
+;;
+;; ?DFDATA Define Data Flag. If this flag is 0, then defines default
+;; data segment and group definitions based on compiler flag.
+;; If this flag is 1, then does not define any data segments
+;; or groups.
+;;
+;; ?DFCODE Define Code Flag. If this flag is 0, then defines default
+;; code segments based on the compiler flag. If this flag is 1,
+;; then does not define the code segments. Inactive if
+;; ?DF is 1.
+;;
+;; ?TF Tight flag. If this flag is 0, then use longer epilog
+;; sequence that safely cleans up a stack frame. If this flag is
+;; 1, then use more efficient epilog that assumes the stack is
+;; valid (SP)
+;;
+;; ?WIN Windows flag. Enables generation of special prolog/epilog
+;; for far procedures. Default value is 1 (Windows).
+;;
+;; ?COW Character Windows flag. To be used in conjunction with ?WIN,
+;; If defined will not save DS for ?NODATA far prolog/epilog
+;; (CW does not modify the DS on the stack).
+;;
+;; DOS5 If defined, then special far prolog/epilog seqeuences will not
+;; include the INC/DEC BP instructions.
+;;
+;; ?PLM Calling convention flag. If this flag is 0, then the
+;; calling convention used is that of C. If this flag
+;; is 1, then the PL/M calling convention is used.
+;; The default value is 1. The PL/M calling convention
+;; is used by pascal, fortran, basic, and cobol.
+;;
+;; In the C calling convention, arguments are passed
+;; in reverse order; arg0 is the last pushed, argn is the
+;; first pushed. also, it is the callers responsibility
+;; to remove the arguments from the stack upon a return
+;; from a call.
+;;
+;; In the PL/M calling comvention, arguments are passed
+;; as encountered; arg0 is the first pushed, argn is the
+;; last pushed. also, it is the called procedure's
+;; responsibility to remove parameters from the stack
+;; before returning (using the RET n instruction)
+;;
+;; ?NODATA If defined, then no data segment or DGROUP is defined and
+;; the special prolog/epilog sequences will not contain the
+;; code needed to setup DS.
+;;
+;; ?CHKSTK If defined, then prolog sequences for cProcs with local
+;; parameters will call the CHKSTK procedure to allocate
+;; the stack space.
+;;
+;; ?CHKSTKPROC If defined, then this macro will be invoked to
+;; perform the stack checking, otherwise the
+;; standard stack checking procedure will be
+;; performed. ?CHKSTKPROC must be declared
+;; before the cmacros are included in the source
+;; else the standard chkstk routine will be declared
+;; as an external symbol.
+;;
+;; On entry to the user's stack checking procedure,
+;; the frame has been setup except for allocating
+;; local variable space and saving autosave registers.
+;;
+;; The user supplied macro is passed as an argument
+;; the number of byte of stack space requested.
+;;
+;; ?PROFILE If defined then all far cBegin entries will have StartNMeas,
+;; and all cEnd will have StopNMeas calls, StartNMeas and
+;; StopNMeas will be defined as externfp
+;;
+;; ?NOPARMR If defined, then the "parmR" macro will not be defined.
+;;
+;; ?NOGLOBAL If defined, then the "globalx" macros will not be defined.
+;;
+;; ?NOSTATIC If defined, then the "staticx" macros will not be defined.
+;;
+;; ?NOEXTERN If defined, then the "externx" macros will not be defined.
+;;
+;; ?NOLABEL If defined, then the "labelx" macros will not be defined.
+;;
+;; ?NODEF If defined, then the "defx" macros will not be defined.
+;;
+;; ?NOPTR If defined, then "farptr & regptr" will not be defined.
+;;
+;; ?QUIET If defined, then only error messages will be issued to
+;; the console. If undefined, then certain cmacro text will
+;; be generated to the console.
+;;
+;; ?NOATOMIC If defined, then ATOMIC will be ignored (for giving real
+;; frames to all procedures (and profiling).
+;;
+;; ?NO_BP If defined, then equates generated for parms and locals
+;; will not explicitly reference BP.
+;; IAX, ICX, IDX, IBX, ISP, IBP, ISI, IDI
+;; these pseudo registers expand to either ax..., or eax...
+;; depending upon 32bit mode being enabled. they should be
+;; used whenever a pointer or integer is being used in order
+;; to make source code machine independant
+
+
+
+.xcref ;;Get rid of a lot of symbols
+
+
+; ??_out - output given message to the console unless ?QUIET has
+; been specified.
+;
+; usage:
+; ??_out <t>
+;
+; where:
+; <t> is the message to output
+
+.xcref ??_out
+??_out macro t
+ ifndef ?QUIET
+ %out t
+ endif
+endm
+
+
+
+; outif - output msg if name is non-zero. if name is undefined,
+; set name = 0, else set name to the default value.
+;
+; usage:
+; outif name,defval,onmsg,offmsg
+; where:
+; name name of symbol
+; defval default value to give symbol if not defined
+; if blank, then 0 will be used
+; onmsg text to display if symbol is non-zero
+; offmsg test to be displayed if symbol is zero
+
+
+outif macro name,defval,onmsg,offmsg
+ ifndef name
+ ifb <defval>
+ name=0
+ else
+ name=defval
+ endif
+ endif
+ if name
+ name=1
+ ifnb <onmsg>
+ ??_out <! onmsg>
+ endif
+ else
+ ifnb <offmsg>
+ ??_out <! offmsg>
+ endif
+ endif
+endm
+
+
+
+; ??error - output msg and generate an assembly time error
+; on regardess of assembler pass
+; usage:
+; ??error <t>
+; where:
+; t is the text to be output
+
+
+.xcref ??error
+??error macro msg
+ %out e r r o r ----- msg ;;to console
+ .err e r r o r ----- msg ;;forced error by assembler
+endm
+
+
+; ??error2 - output msg and generate an assembly time error
+; on pass 2 only
+; usage:
+; ??error2 <t>
+; where:
+; t is the text to be output
+
+
+.xcref ??error2
+??error2 macro msg
+ if2
+ %out e r r o r ----- msg ;;to console
+ .err e r r o r ----- msg ;;forced error by assembler
+ endif
+endm
+
+
+.xcref ASMpass
+.xcref memS,memM,memL,memC,memH,memMOD,sizec,sized,memS32,sizeI,wordI
+
+;if1 ;;Only on pass 1
+ ASMpass=1
+ ifdef ?SMALL ;;inform user what is going on
+ memS=1
+ endif
+ ifdef ?MEDIUM
+ memM=1
+ endif
+ ifdef ?COMPACT
+ memC=1
+ endif
+ ifdef ?LARGE
+ memL=1
+ endif
+ ifdef ?HUGE
+ memH=1
+ endif
+ ifdef ?SMALL32
+ memS32=1
+ endif
+ ifdef ?FLAT32
+ memF32=1
+ endif
+
+ ??_out <cMacros Version 3.06h - 01/25/90>
+ ??_out <Copyright (C) Microsoft Corp. 1984-1990. All rights reserved.>
+ outif memS,0,<Small Model>
+ outif memM,0,<Medium model>
+ outif memL,0,<Large Model>
+ outif memC,0,<Compact Model>
+ outif memH,0,<Huge Model>
+ outif memS32,0,<32 Bit Small Model>
+ outif memF32,0,<32 Bit Flat Model>
+
+ memMOD= memS + memM + memL + memC + memH + memS32
+ if memMOD ne 1
+ if memMOD eq 0
+ memS = 1 ; assume small model
+ outif memS,0,<Small model>
+ else
+ ??error <must have only 1 memory model selected>
+ endif
+ endif
+
+ sizec= memM + memL + memH ; large code
+ sized= memL + memC + (memH*2) ; large data (2 if huge)
+ ;; note that memS32 is used generaly to indicate 32 bitness. I
+ ;; doubt very much whether anyone will ever do other models in
+ ;; 32 bit code...
+ if memS32
+ sizeI = 4 ; size of a push
+ wordI equ <dword>
+ asmdI equ <dd>
+ else
+ sizeI = 2
+ wordI equ <word>
+ asmdI equ <dw>
+ endif
+
+ outif ?DF,0,<No segments or groups will be defined>
+ outif ?DFDATA,0,<No data segments will be defined>
+ outif ?DFCODE,0,<No code segments will be defined>
+ outif ?TF,0,<Epilog sequences assume valid SP>
+ outif ?WIN,1,<Windows support>
+ outif ?COW,0,<Characters Windows support>
+ outif ?PLM,1,<PL/M calling convention>
+ outif ?NOATOMIC,0,<ATOMIC disabled>
+ outif ?NODATA,0,<NODATA module>
+
+ ife ?NODATA
+ ?nodata1=0
+ else
+ ?nodata1=1
+ endif
+
+ ifndef ?CHKSTK
+ ?chkstk1=0
+ else
+ ?chkstk1=1
+ ifdef ?CHKSTKPROC
+ ??_out <! Private stack checking enabled>
+ else
+ ??_out <! Stack checking enabled>
+ endif
+ endif
+
+ ifndef DOS5
+ ?DOS5=0
+ else
+ ?DOS5=1
+ ??_out <! DOS5 module>
+ endif
+
+ ifdef ?PROFILE
+ ??_out <! Native profiling enabled>
+ endif
+
+ ifndef ?NO_BP
+ ?no_bp1=0
+ else
+ ?no_bp1=1
+ ??_out <! NO_BP is default>
+ endif
+;else
+ ASMpass=2
+;endif
+
+;; define pseudo registers and instructions for 386/8086 independance
+if memS32
+ .386
+ IAX equ <eax>
+ ICX equ <ecx>
+ IDX equ <edx>
+ IBX equ <ebx>
+ ISP equ <esp>
+ IBP equ <ebp>
+ ISI equ <esi>
+ IDI equ <edi>
+ IPUSHF equ pushfd
+ IPOPF equ popfd
+ IPUSHA equ pushad
+ IPOPA equ popad
+ IIRET equ iretd
+else
+ IAX equ <ax>
+ ICX equ <cx>
+ IDX equ <dx>
+ IBX equ <bx>
+ ISP equ <sp>
+ IBP equ <bp>
+ ISI equ <si>
+ IDI equ <di>
+ IPUSHF equ pushf
+ IPOPF equ popf
+; IPUSHA equ pusha
+; IPOPA equ popa
+ IIRET equ iret
+endif
+
+;; Initialize all symbols used in the macros. Theses symbols will not be
+;; included in any cross reference listing.
+
+ .xcref ?n,?ax,?ah,?al,?bx,?bh
+ .xcref ?bl,?cx,?ch,?cl,?dx,?dh
+ .xcref ?dl,?si,?di,?es,?ds,?bp
+ .xcref ?sp,?ss,?cs
+ .xcref ?n,?AX,?AH,?AL,?BX,?BH
+ .xcref ?BL,?CX,?CH,?CL,?DX,?DH
+ .xcref ?DL,?SI,?DI,?ES,?DS,?BP
+ .xcref ?SP,?SS,?CS
+ .xcref ?EAX,?EBX,?ECX,?EDX,?ESI,?EDI,?ESP,?EBP
+ .xcref ?eax,?ebx,?ecx,?edx,?esi,?edi,?esp,?ebp
+ .xcref ?IAX,?IBX,?ICX,?IDX,?ISI,?IDI,?ISP,?IBP
+
+ .xcref ?rsl,?cpd,?argl,?argc,?ba
+ .xcref ?acb,???,?po
+ .xcref ?pas,?pc
+
+ .xcref uconcat,mpush,mpop
+ .xcref ?ri,?pp,?pp1,?al1
+ .xcref ?ad,?ap,?atal,?dd,?dd1,?dd2
+ .xcref ?pg,?pg1,?aloc,?cs1,?cs2
+ .xcref ?DF,?TF,?ff,?PLM,?WIN,?ia,?pu,?adj
+ .xcref ?uf,?rp,?nx,?nd,?nodata1,?chkstk1,?DOS5
+ .xcref ?wfp,arg,cCall,cProc,assumes,?cs3,?cs2,?cs1
+ .xcref defgrp,addseg,createSeg
+ .xcref save,outif,errnz,errn$,errnz1
+ .xcref ?PLMPrevParm,?gcc
+ .xcref ?cCall1,?pcc,?no_bp1,?no_bp2
+ .xcref ?cbe,?pcbe
+
+
+
+;; conditionals set by the macros
+;;
+;; ?pc Procedure class. If this is set to 1, then the procedure
+;; is a far procedure, else it is a near procedure.
+;;
+;; ?ia Interface adjustment count for far procedures. The
+;; interface adjustment defines the number of bytes of
+;; storage allocated between BP and the first frame variable
+;; allocated on the stack.
+;;
+;; Normally zero, it will be adjusted for both far windows
+;; procedures and by register parameters.
+;;
+;; ?cpd Current procedure defined. This is set to a non-zero
+;; value if a procedure is being defined (i.e a cProc has
+;; been encountered, and cBegin has not).
+;;
+;; ?ba Begin active. This is set to a non-zero value if a
+;; cBegin is active (i.e. a cBegin has been encountered,
+;; and cEnd has not).
+;;
+;; ?wfp Windows far procedure. Set if a windows far procedure
+;;
+;; ?pcc procedure calling conventing. Calling convention for
+;; this procedure. May be different than the default set
+;; via ?PLM
+;;
+;;
+;; Other variables that are defined once so that the .xcref command
+;; doesn't get too upset if they show up missing!
+
+?rsl = 0 ;;0 = no register to save
+?cpd = 0 ;;<> 0 if in a procedure definition
+?argl = 0 ;;length of arguments pushed on stack
+?argc = 0 ;;# of arguments so far
+?ba = 0 ;;<>0 if in a procedure (xbegin)
+?acb = 0 ;;number of arguments to a call
+??? = 0 ;;byte count of local storage
+?po = 0 ;;byte count of parameters
+?pas = 0 ;;autosave value for procedure
+?pc = 0 ;;class of a procedure (near/far)
+?ia = 0 ;;no adjustment
+?pu = 0 ;;public flag for some macros
+?adj = 0 ;;initial define for .xcref
+?rp = 0 ;;count of register parameters
+?uf = 0 ;;user's frame code specified
+?nd = 0 ;;NODATA keyword specified
+?nx = 0 ;;ATOMIC keyword specified
+?wfp = 0 ;;window far procedure
+?ff = 0 ;;forceframe keyword specified
+?dd2 = 0 ;;used for globalx and staticx
+?cCall1 = 0 ;;used for cCalls
+?pcc = ?PLM ;;procedure calling convention
+?PLMPrevParm = 0 ;;Used in parameter processing
+?no_bp2 = ?no_bp1 ;;BP / No BP flag
+?cbe = 0 ;;cbegin/cEnd keyword flag
+
+ .xcref ?casen
+if1 ;;only define ?casen on pass 1
+?casen = 0 ;;case sensitive assembly if <> 0
+endif
+
+
+
+?n = 0000000000000000b ;;register none
+?ax = 0000000000000011b ;;register ax
+?ah = 0000000000000001b ;;register ah
+?al = 0000000000000010b ;;register al
+?bx = 0000000000001100b ;;register bx
+?bh = 0000000000000100b ;;register bh
+?bl = 0000000000001000b ;;register bl
+?cx = 0000000000110000b ;;register cx
+?ch = 0000000000010000b ;;register ch
+?cl = 0000000000100000b ;;register cl
+?dx = 0000000011000000b ;;register dx
+?dh = 0000000001000000b ;;register dh
+?dl = 0000000010000000b ;;register dl
+?si = 0000000100000000b ;;register si
+?di = 0000001000000000b ;;register di
+?es = 0000010000000000b ;;register es
+?ds = 0000100000000000b ;;register ds
+?bp = 0001000000000000b ;;register bp
+?sp = 0010000000000000b ;;register sp
+?ss = 0100000000000000b ;;register ss
+?cs = 1000000000000000b ;;register cs
+ ;;Incase we're case sensitive
+?AX = 0000000000000011b ;;register ax
+?AH = 0000000000000001b ;;register ah
+?AL = 0000000000000010b ;;register al
+?BX = 0000000000001100b ;;register bx
+?BH = 0000000000000100b ;;register bh
+?BL = 0000000000001000b ;;register bl
+?CX = 0000000000110000b ;;register cx
+?CH = 0000000000010000b ;;register ch
+?CL = 0000000000100000b ;;register cl
+?DX = 0000000011000000b ;;register dx
+?DH = 0000000001000000b ;;register dh
+?DL = 0000000010000000b ;;register dl
+?SI = 0000000100000000b ;;register si
+?DI = 0000001000000000b ;;register di
+?ES = 0000010000000000b ;;register es
+?DS = 0000100000000000b ;;register ds
+?BP = 0001000000000000b ;;register bp
+?SP = 0010000000000000b ;;register sp
+?SS = 0100000000000000b ;;register ss
+?CS = 1000000000000000b ;;register cs
+
+?EAX = 0000000000000011b ;;register ax
+?EBX = 0000000000001100b ;;register bx
+?ECX = 0000000000110000b ;;register cx
+?EDX = 0000000011000000b ;;register dx
+?ESI = 0000000100000000b ;;register si
+?EDI = 0000001000000000b ;;register di
+?EBP = 0001000000000000b ;;register bp
+?ESP = 0010000000000000b ;;register sp
+
+?eax = 0000000000000011b ;;register ax
+?ebx = 0000000000001100b ;;register bx
+?ecx = 0000000000110000b ;;register cx
+?edx = 0000000011000000b ;;register dx
+?esi = 0000000100000000b ;;register si
+?edi = 0000001000000000b ;;register di
+?ebp = 0001000000000000b ;;register bp
+?esp = 0010000000000000b ;;register sp
+
+?IAX = 0000000000000011b ;;register ax
+?IBX = 0000000000001100b ;;register bx
+?ICX = 0000000000110000b ;;register cx
+?IDX = 0000000011000000b ;;register dx
+?ISI = 0000000100000000b ;;register si
+?IDI = 0000001000000000b ;;register di
+?IBP = 0001000000000000b ;;register bp
+?ISP = 0010000000000000b ;;register sp
+
+ .cref
+
+
+
+;; uconcat - unconditionally generate a statement from a field
+;; of given parameters
+;;
+;; usage:
+;; uconcat a,b,c,d,e,f,g
+;;
+;; where:
+;; a,b are concatenated for field 1
+;; c,d are concatenated for field 2
+;; e,f,g are concatenated for field 3
+
+uconcat macro a,b,c,d,e,f,g
+ a&b c&d e&f&g
+endm
+
+
+
+;; mpush pushes multiple registers onto the stack according to
+;; a register specification.
+;;
+;; format:
+;; mpush r
+;;
+;; where:
+;; r is a numeric expression returned from ?ri
+;; or any other valid register expression
+
+mpush macro r
+ irp x,<IAX,IBX,ICX,IDX,ISI,IDI,es,ds,IBP,ISP,ss,cs>
+ if (r and ?&&x)
+ push x ;@
+ endif
+ endm
+endm
+
+
+
+;; mpop pops multiple registers from the stack according to
+;; a register specification.
+;;
+;; format:
+;; mpop r
+;;
+;; where:
+;; r is a numeric expression returned from ?ri
+;; or any other valid register expression
+
+mpop macro r
+ irp x,<cs,ss,ISP,IBP,ds,es,IDI,ISI,IDX,ICX,IBX,IAX>
+ if (r and ?&&x)
+ pop x ;@
+ endif
+ endm
+endm
+
+
+;; save - flag that the indicated registers are to be saved/restored
+;;
+;; A flag is created which indicates which registers are to be saved
+;; when the cCall macro is invoked, and then restored after the call.
+;;
+;; usage:
+;; save <r>
+;;
+;; where r is the list of registers to save, which may be:
+;;
+;; register saves
+;; AX AX
+;; AH AX
+;; AL AX
+;; BX BX
+;; BH BX
+;; BL BX
+;; CX CX
+;; CH CX
+;; CL CX
+;; DX DX
+;; DH DX
+;; DL DX
+;; SI SI
+;; DI DI
+;; ES ES
+;; DS DS
+;; BP BP
+;;
+;; none nothing
+;;
+;; the macro generates a value for the variable ?rsl
+
+save macro r
+ ?rsl=0 ;;initialize save list
+ ?ri ?rsl,<r> ;;generate magic number
+endm
+
+
+
+;; ?ri - or register indexes to variable
+;;
+;; ?ri is a macro that examines the passed argument list and computes
+;; a register index variable.
+;;
+;; The values ORed with the variable are:
+;;
+;; ?n equ 0000000000000000b;
+;; ?AX equ 0000000000000011b;
+;; ?AH equ 0000000000000001b;
+;; ?AL equ 0000000000000010b;
+;; ?BX equ 0000000000001100b;
+;; ?BH equ 0000000000000100b;
+;; ?BL equ 0000000000001000b;
+;; ?CX equ 0000000000110000b;
+;; ?CH equ 0000000000010000b;
+;; ?CL equ 0000000000100000b;
+;; ?DX equ 0000000011000000b;
+;; ?DH equ 0000000001000000b;
+;; ?DL equ 0000000010000000b;
+;; ?SI equ 0000000100000000b;
+;; ?DI equ 0000001000000000b;
+;; ?ES equ 0000010000000000b;
+;; ?DS equ 0000100000000000b;
+;; ?BP equ 0001000000000000b;
+;; ?SP equ 0010000000000000b;
+;; ?SS equ 0100000000000000b;
+;; ?CS equ 1000000000000000b;
+;; usage:
+;; ?ri n,<rl>
+;s mach independant names; where:
+;; n is the variable to contain the new index value
+;; r is the register list
+
+?ri macro n,r
+ irp x,<r>
+ ifdef ?&&x ;;if defined, then add to list
+ n=n or ?&&x
+ else
+ ??error2 <unknown register x>
+ .err
+ endif
+ endm
+endm
+
+
+
+;; parmx - generate reference to parameter(s) on the stack
+;;
+;; An equate is generated for addressing a paramter(s)
+;; on the stack for the current procedural frame.
+;;
+;; An error message is generated if there isn't a current frame.
+;;
+;; usage:
+;; parmX n
+;; where:
+;; X is the type of the argument(s) B=byte, W=word, D=dword
+;; I = machine independant int size
+;; n is the name(s) to be given the parameter(s).
+;;
+;; Bytes are considered to be two bytes long for alignment.
+;;
+;; The parmd form of the macro generates three equates:
+;;
+;; name - for accessing the parameter as a double word
+;; off_name - for accessing the offset (lsw) of the parameter
+;; seg_name - for accessing the segment (msw) of the parameter
+
+.xcref
+.xcref parmB,parmW,parmD,parmQ,parmT,parmCP,parmDP,parmH,parmI
+.cref
+
+parmB macro n
+ ?pp <n>,<byte>,sizeI,1
+endm
+
+parmW macro n
+ ?pp <n>,<word>,sizeI,2
+endm
+
+parmI macro n
+ ?pp <n>,wordI,sizeI,sizeI
+endm
+
+parmD macro n
+ ife ?pcc ;;if to assemble for C
+ irp x,<n>
+ ?pp <&&x>,<dword>,0,4
+ ?pp <off_&&x>,<word>,2,2
+ ?pp <seg_&&x>,<word>,2,2
+ endm
+ else ;;if to assemble for PL/M
+ irp x,<n>
+ ?pp <seg_&&x>,<word>,2,2
+ ?pp <off_&&x>,<word>,2,2
+ ?pp <&&x>,<dword>,0,4
+ endm
+ endif
+endm
+
+parmH macro n
+ ?pp <n>,<word>,4,2
+endm
+
+parmQ macro n
+ ?pp <n>,<qword>,8,8
+endm
+
+parmT macro n
+ ?pp <n>,<tbyte>,10,10
+endm
+
+if sizec
+ parmCP macro n
+ parmD <n>
+ endm
+else
+ parmCP macro n
+ parmW <n>
+ endm
+endif
+
+if sized
+ parmDP macro n
+ parmD <n>
+ endm
+else
+ parmDP macro n
+ parmI <n>
+ endm
+endif
+
+
+
+;; ?pp is the generalized parameter definition macro
+;;
+;; usage:
+;; ?pp m,t,l,s
+;;
+;; where:
+;; n is the name(s) of the parameters
+;; t is the type (word, dword)
+;; l is the length to update parameter byte count by
+;; s is the internal typing size
+
+
+?pp macro n,t,l,s ;;process parameter
+ if ?cpd ;;must be in a procedure definition
+ .xcref
+ irp x,<n>
+ .xcref ?t&&x ;;don't want this in xref
+ ?t&&x=s ;;save size info
+ ife ?pcc ;;if C calling convention
+ ?pp1 x,<t>,,,%(?po+?adj)
+ ?po=?po+l ;;update parameter offset
+ else ;;else assemble for PL/M
+ ?PLMPrevParm=?PLMPrevParm+1 ;;Show next parameter
+ ?po=?po+l ;;update parameter offset
+ ?pp1 x,<t>,%?po,%?adj,,%?PLMPrevParm,%(?PLMPrevParm-1)
+ endif
+ endm
+ .cref
+ else
+ ??error2 <parm(s) "&n" declared outside proc def>
+ endif
+endm
+
+
+
+;; ?pp1 is the macro that generates the text equate for the
+;; parameter. Two options exist, one for the C calling
+;; convention where the last parameter was the first pushed onto
+;; the stack ('C' convention), and one for the PL/M calling
+;; convention where the first parameter was the first
+;; pushed (also the same as ms-pascal).
+;;
+;; The text generated will be of one of two forms:
+;;
+;; name equ (type ptr [bp+(adj+offset)]) for C
+;; or
+;; name equ (type ptr [bp+adj+?po-offset]) for PL/M
+;;
+;;
+;; For C, since parameters are pushed first last, the offset
+;; plus the adjust will point to the correct parameter.
+;;
+;; For PL/M, since parameters are pushed first first, the offset
+;; of a parameter is much more complicated. A known portion of
+;; the offset can be computed when the text equate is generated.
+;;
+;; What is known is the number of garbage bytes between BP and
+;; the nearest parameter (in this case the last parameter), and
+;; also how many bytes of parameters have preceeded this parameter.
+;;
+;; What is unknown is how many total bytes of parameters there will
+;; be, which affects all the generated text equates since the offset
+;; from bp must be determined at some point.
+;;
+;; Well, the offset from BP can be computed with one variable if
+;; the following is remembered:
+;;
+;; the offset of any parameter from the first parameter is always
+;; the current parameter offset (?po).
+;;
+;; With this in mind, you just have to figure out where the first
+;; parameter is, which is:
+;;
+;; bp + garbage adjustment + distance to first parameter
+;; or
+;; bp + ?adj + ?po
+;;
+;; This implies that any parameter can be defined as:
+;;
+;; bp + ?adj + ?po -%?po
+;;
+;; Make any sense?
+;;
+;; For PL/M, a chain of self-purging macros will be generated
+;; which will pass the evaluated ?po to any previous incarnation
+;; of the macro. This will allow the text equate to be generated
+;; with the actual offset instead of the symbolic ?po.
+;;
+;;
+;; usage:
+;; ?pp1 n,t,o,a,b,cpc,ppc
+;;
+;; where:
+;; n is the name to be given the equate
+;; t is the type (byte, word, dword)
+;; o is the offset from the first parameter
+;; a is the adjustment
+;; b is the adjustment plus the offset from the first parameter
+;; cpc is the number of parameters so far
+;; ppc is cpc - 1
+
+
+?pp1 macro n,t,o,a,b,cpc,ppc
+ ife ?pcc ;;if to generate for C
+ if ?no_bp2
+ n equ (t ptr [+b])
+ else
+ n equ (t ptr [IBP][+b])
+ endif
+ else ;;else generate for PL/M
+ .xcref
+ .xcref ?PLMParm&cpc
+ .cref
+ if ?no_bp2
+ ?PLMParm&cpc &macro po
+ uconcat <n>,,<equ>,,<(t ptr [+>,%(a+po-o),<])>
+ ?PLMParm&ppc po
+ purge ?PLMParm&cpc
+ &endm
+ else
+ ?PLMParm&cpc &macro po
+ uconcat <n>,,<equ>,,<(t ptr [IBP][+>,%(a+po-o),<])>
+ ?PLMParm&ppc po
+ purge ?PLMParm&cpc
+ &endm
+ endif
+ endif
+endm
+
+
+
+;; parmR - register parameter
+;;
+;; parmR is the macro used for generating register parameters.
+;; The space allocated for the register parameters will be
+;; the ?ia (interface adjust) area which is between the old
+;; BP and the first parameter. Normally this is empty (?ia=0),
+;; or has the saved ds for a windows far procedure.
+;;
+;; Byte and dword register parameters will be allowed.
+;;
+;; usage:
+;; parmR n,r,r2
+;; where:
+;; n is the name of the parameter
+;; r is the register it is in
+;; r2 is the offset register if a dword
+
+
+ifndef ?NOPARMR
+ .xcref
+ .xcref ?pr,parmR
+ .cref
+
+ parmR macro n,r,r2
+ ?pr n,r,r2,%?rp,%(?ia+2)
+ endm
+
+ ;; ?pr - register parameter
+ ;;
+ ;; ?pr is the actual macro for generating the equates for
+ ;; register parameters.
+ ;;
+ ;; usage:
+ ;; parmR n,r,r2,i,o
+ ;; where:
+ ;; n is the name of the parameter
+ ;; r is the register it is in
+ ;; r2 is the offset register if a dword
+ ;; i is the index of the ?rp to generate
+ ;; o is the offset from bp where the parm will be
+
+ ?pr macro n,r,r2,i,o
+ .xcref
+ ifnb <r2> ;;if a dword parameter
+ parmR seg_&n,r ;;define segment equate
+ parmR off_&n,r2 ;;define offset equate
+ if ?no_bp2
+ n equ (dword ptr [-o-2]) ;;define dword equate
+ else
+ n equ (dword ptr [bp][-o-2]) ;;define dword equate
+ endif
+ .xcref ?t&n
+ ?t&n=4 ;;show a dword to cmacros
+ else
+ .xcref ?rp&i
+ ?rp&i=0 ;;show no register(s)
+ ifdef ?&r ;;define register if valid
+ ?rp&i=?&r
+ endif
+
+ if ??? or (?cpd eq 0) or (?rp&i eq 0)
+ ??error2 <invalid parmR encountered: &n,&r>
+ exitm
+ endif
+
+ if ?no_bp2
+ n equ (word ptr [-o]) ;;assume a word register
+ else
+ n equ (word ptr [bp][-o]) ;;assume a word register
+ endif
+ .xcref ?t&n
+ ?t&n=2 ;;show a word to cmacros
+ irp x,<bh,ch,dh,bl,cl,dl,ah,al>
+ if ?&&x eq ?&r ;;if really a byte register
+ if ?no_bp2
+ n equ (byte ptr [-o]) ;; then make it a byte
+ else
+ n equ (byte ptr [bp][-o]) ;; then make it a byte
+ endif
+ ?t&n=1 ;;show a byte to cmacros
+ exitm
+ endif
+ endm
+ ?ia=?ia+2 ;;show this guy is out there
+ ?rp=?rp+1 ;;show one more register parameter
+ endif
+ .cref
+ endm
+endif
+
+
+
+;; localx - generate reference to a local variable on the stack
+;;
+;; An equate is generated for addressing a local variable
+;; on the stack for the current procedural frame.
+;;
+;; usage:
+;; localx n
+;; where:
+;; x is the type b=byte, w=word, d=dword, v=variable size
+;; n is the name(s) to be given the variable(s).
+;;
+;; Bytes are considered to be two bytes long for alignment reasons
+;;
+;; The locald form of the macro generates three equates:
+;;
+;; name - for accessing the variable as a double word
+;; off_name - for accessing the offset (lsw) of the variable
+;; seg_name - for accessing the segment (msw) of the variable
+
+
+.xcref
+.xcref localB,localW,localD,localQ,localT,localCP,localDP,localV,localI
+.cref
+
+localB macro n
+ ?aloc <n>,<byte ptr>,1,1,0 ;; no alignment
+endm
+
+localW macro n
+ ?aloc <n>,<word ptr>,2,2,1 ;; word aligned
+endm
+
+localI macro n
+ ?aloc <n>,&wordI&< ptr>,sizeI,sizeI,1 ;; dword aligned
+endm
+
+localD macro n
+ irp x,<n>
+ ?aloc <seg_&&x>,<word ptr>,2,2,1 ;; word aligned
+ ?aloc <off_&&x>,<word ptr>,2,2,1 ;; word aligned
+ ?aloc <&&x>,<dword ptr>,0,4,1 ;; word aligned
+ endm
+endm
+
+localQ macro n
+ ?aloc <n>,<qword ptr>,8,8,1 ;; word aligned
+endm
+
+localT macro n
+ ?aloc <n>,<tbyte ptr>,10,10,1 ;; word aligned
+endm
+
+if sizec
+ localCP macro n
+ localD <n>
+ endm
+else
+ localCP macro n
+ localW <n>
+ endm
+endif
+
+if sized
+ localDP macro n
+ localD <n>
+ endm
+else
+ localDP macro n
+ localI <n>
+ endm
+endif
+
+localV macro n,a
+ ?aloc <n>,,%(a),0,1 ;; word aligned
+endm
+
+
+;; ?aloc is the macro that actually allocates local storage.
+;; it is only invoked by the localx macros.
+;;
+;; usage:
+;; ?aloc n,t,l,s,a
+;; where:
+;; n is a list of names of local variable of the
+;; given type.
+;; t is the text string for the given variable
+;; and is one of:
+;; word ptr
+;; dword ptr
+;; byte ptr
+;; or alternatively left blank for variable size
+;; allocations (no implicit type).
+;; l is the size of the variable in bytes
+;; s is the internal type flag (size), and is one of:
+;; word - 2
+;; dword - 4
+;; byte - 1
+;; variable - 0
+;; a is a flag indicating that word alignment is to be
+;; forced for this type of item.
+;;
+;; NOTE: It is assumed that the stack is already aligned on a word
+;; boundary when the cProc is invoked. The macros will guarantee
+;; to allocate an even number of bytes on the stack to maintain
+;; word alignment.
+
+
+?aloc macro n,t,l,s,a
+ if ?cpd ;;must be in a proc def
+ .xcref
+ irp x,<n> ;;generate symbol equates
+ ???=???+l ;;update length of locals
+ if a ;;if align, then force word alignment
+ if memS32 and l GT 2
+ ???=((??? + 3) and 0fffffffch) ;; dword alignment
+ else
+ ???=((??? + 1) and 0fffeh)
+ endif
+ endif
+ ?al1 x,<t>,%(???+?ia) ;;?ia will always be valid (0 or 2)
+ .xcref ?t&&x
+ ?t&&x=s ;;save size info
+ endm
+ .cref
+ else
+ ??error2 <locals "&n" declared outside procedure def>
+ endif
+endm
+
+
+
+;; ?al1 - allocate local, continued.
+;;
+;; ?al1 actually generates the text equate for the local variable.
+;; The form of the text equate generated is more or less:
+;;
+;; name equ (type ptr [bp-?ia-nn])
+;; or
+;; name equ ([bp-?ia-nn])
+;;
+;; where:
+;; ?ia is defined to be either zero, or is defined to be
+;; the number of bytes between the saved BP and the first
+;; local. ?ia is only applicable if the current cProc is
+;; a windows far procedure or if parmRs have been
+;; encountered. If not, the ?ia will be zero. since ?ia
+;; is determinable prior to invoking this macro, it will be
+;; added into the offset ("nn") passed to this macro
+;;
+;; usage:
+;; ?al1 n,t,o
+;; where:
+;; n is the name for the text equate
+;; t is the type of the equate
+;; o is the offset of the equate
+
+
+?al1 macro n,t,o
+ if ?no_bp2
+ n equ (t [-o])
+ else
+ n equ (t [IBP][-o])
+ endif
+endm
+
+
+;; ?gcc - get calling convention
+;;
+;; ?gcv sets the given symbol to the calling convention
+;; to be used.
+;;
+;; usage:
+;; ?gcc s,i,cc
+;;
+;; where:
+;; s is the symbol to return the convention in
+;; s = 0 if 'C' calling convention
+;; s = 1 if PL/M (PASCAL) calling convention
+;; i is the initial value for s
+;; cc is the calling convention override, and may be one of
+;; C use 'C' convention
+;; PLM use PL/M calling convention
+;; PASCAL use PL/M calling convention
+
+?gcc macro s,i,cc
+ s = i ;;Set default calling convention
+ ifnb <cc>
+ ifidn <cc>,<C> ;;If overriding default
+ s=0 ;; 'C' calling convention
+ endif
+ ifidn <cc>,<PLM>
+ s=1 ;; PL/M calling convention
+ endif
+ ifidn <cc>,<PASCAL>
+ s=1 ;; PL/M calling convention
+ endif
+ endif
+endm
+
+
+
+ifndef ?NOGLOBAL
+ .xcref
+ .xcref globalB,globalW,globalD,globalQ,globalT,globalCP,globalDP,globalI
+ .cref
+
+ ;; globalx - define global data of type x
+ ;;
+ ;; usage:
+ ;; globalx n,i,s,c
+ ;; where:
+ ;; x is the type of the variable b=byte, w=word, d=dword
+ ;; q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
+ ;; n is the name to be given the variable.
+ ;; i is the initial value of the variable.
+ ;; s is the duplication factor
+ ;; c is the convention, C for C, PLM or PASCAL for PL/M.
+ ;; The default (?PLM flag) will be used if not specified.
+ ;;
+ ;; The D form will generate two extra equates of the form off_n and seg_n.
+
+ globalB macro n,i,s,c
+ ?ad <n>,1
+ ?dd n,1,<byte>,<db>,<i>,<s>,<c>
+ endm
+
+ globalW macro n,i,s,c
+ ?ad <n>,2
+ ?dd n,1,<word>,<dw>,<i>,<s>,<c>
+ endm
+
+ globalI macro n,i,s,c
+ ?ad <n>,2
+ ?dd n,1,wordI,%asmdI,<i>,<s>,<c>
+ endm
+
+ globalD macro n,i,s,c
+ ?ad <n>,4
+ ?dd n,1,<dword>,<dd>,<i>,<s>,<c>
+ off_&n equ word ptr n[0]
+ seg_&n equ word ptr n[2]
+ endm
+
+ globalQ macro n,i,s,c
+ ?ad <n>,8
+ ?dd n,1,<qword>,<dq>,<i>,<s>,<c>
+ endm
+
+ globalT macro n,i,s,c
+ ?ad <n>,10
+ ?dd n,1,<tbyte>,<dt>,<i>,<s>,<c>
+ endm
+
+ if sizec
+ globalCP macro n,i,s,c
+ globalD n,<i>,<s>,<c>
+ endm
+ else
+ globalCP macro n,i,s,c
+ globalW n,<i>,<s>,<c>
+ endm
+ endif
+
+ if sized
+ globalDP macro n,i,s,c
+ globalD n,<i>,<s>,<c>
+ endm
+ else
+ globalDP macro n,i,s,c
+ globalI n,<i>,<s>,<c>
+ endm
+ endif
+
+endif
+
+
+ifndef ?NOSTATIC
+ .xcref
+ .xcref staticB,staticW,staticD,staticQ,staticT,staticCP,staticDP,staticI
+ .cref
+
+ ;; staticx - define static data of type x
+ ;;
+ ;; usage:
+ ;; staticx n,i,s
+ ;; where:
+ ;; x is the type of the variable b=byte, w=word, d=dword
+ ;; q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
+ ;; n is the name to be given the variable.
+ ;; i is the initial value of the variable.
+ ;; s is the duplication factor
+ ;;
+ ;; statics do not generate an underscored version of the symbol
+ ;; since they are intended to be internal symbols. If they are
+ ;; required to be public, use globlax.
+
+
+ staticB macro n,i,s
+ ?ad <n>,1
+ ?dd n,0,<byte>,<db>,<i>,<s>,<PLM> ;;PLM to keep from generating _
+ endm
+
+ staticW macro n,i,s
+ ?ad <n>,2
+ ?dd n,0,<word>,<dw>,<i>,<s>,<PLM>
+ endm
+
+ staticD macro n,i,s
+ ?ad <n>,4
+ ?dd n,0,<dword>,<dd>,<i>,<s>,<PLM>
+ endm
+
+ staticI macro n,i,s
+ ?ad <n>,sizeI
+ ?dd n,0,wordI,%asmdI,<i>,<s>,<PLM>
+ endm
+
+ staticQ macro n,i,s
+ ?ad <n>,8
+ ?dd n,0,<qword>,<dq>,<i>,<s>,<PLM>
+ endm
+
+ staticT macro n,i,s
+ ?ad <n>,10
+ ?dd n,0,<tbyte>,<dt>,<i>,<s>,<PLM>
+ endm
+
+ if sizec
+ staticCP macro n,i,s
+ staticD n,<i>,<s>
+ endm
+ else
+ staticCP macro n,i,s
+ staticW n,<i>,<s>
+ endm
+ endif
+
+ if sized
+ staticDP macro n,i,s
+ staticD n,<i>,<s>
+ endm
+ else
+ staticDP macro n,i,s
+ staticI n,<i>,<s>
+ endm
+ endif
+endif
+
+
+
+;; ?dd is the generalized data definition macro.
+;;
+;; format:
+;; ?dd n,p,t,d,i,s,c
+;; where:
+;; n is the name of the procedure
+;; p is the public flag
+;; t is the assembler type (byte, word, dword)
+;; d is the assembler directive (db,dw or dd)
+;; i is the initial value
+;; s is a duplication factor
+;; c is the convention, C for C, PLM or PSACAL for PL/M.
+;; The default (?PLM flag) will be used if not specified.
+
+
+?dd macro n,p,t,d,i,s,c
+ ?gcc ?dd2,%?PLM,<c> ;;Set calling convention
+ ife ?dd2 ;;If 'C'
+ n label t
+ ?dd1 _&n,p,<d>,<i>,<s> ;;Microsoft C uses leading underscores
+ else
+ ?dd1 n,p,<d>,<i>,<s> ;;If PL/M
+ endif
+endm
+
+
+
+;; ?dd1 is the generalized data definition macro.
+;;
+;; format:
+;; ?dd1 n,p,d,i,s
+;; where:
+;; n is the name of the procedure
+;; p is the public flag
+;; d is the assembler directive (db,dw or dd)
+;; i is the initial value
+;; s is a duplication factor
+
+
+?dd1 macro n,p,d,i,s
+ if p
+ public n
+ endif
+ ifb <s>
+ n d i
+ else
+ ifb <i>
+ n d s dup (?)
+ else
+ n d s dup (i)
+ endif
+ endif
+endm
+
+
+
+ifndef ?NOEXTERN
+ .xcref
+ .xcref ?ex1,?ex2,externB,externW,externD,externQ,externT,externI
+ .xcref externNP,externFP,externP,externCP,externDP,externA
+ .cref
+ ?ex2 = 0
+
+ ;; externx - define external data of type x
+ ;;
+ ;; usage:
+ ;; externx n,c
+ ;; where:
+ ;; x is the type of the variable b=byte, w=word, d=dword
+ ;; q=quad word, t=tenbytes, cp=code pointer
+ ;; dp=data pointer, a=absolute
+ ;; n is a list of names to define
+ ;; c is the convention, C for C, PLM or PSACAL forPL/M.
+ ;; The default (?PLM flag) will be used if not specified.
+
+ externA macro n,c ;;40h is reserved for whatever will
+ ?ex1 <n>,40h,<abs>,<c>,<> ;; be done in the future for ASB
+ endm ;; externals
+
+ externB macro n,c
+ ?ex1 <n>,1,<byte>,<c>,<>
+ endm
+
+ externW macro n,c
+ ?ex1 <n>,2,<word>,<c>,<>
+ endm
+
+ externD macro n,c
+ ?ex1 <n>,4,<dword>,<c>,<>
+ endm
+
+ externI macro n,c
+ ?ex1 <n>,sizeI,%wordI,<c>,<>
+ endm
+
+ externQ macro n,c
+ ?ex1 <n>,8,<qword>,<c>,<>
+ endm
+
+ externT macro n,c
+ ?ex1 <n>,10,<tbyte>,<c>,<>
+ endm
+
+ externNP macro n,c
+ ?ex1 <n>,2,<near>,<c>,<cc>
+ endm
+
+ externFP macro n,c
+ ?ex1 <n>,4,<far>,<c>,<cc>
+ endm
+
+ if sizec
+ externP macro n,c
+ ?ex1 <n>,4,<far>,<c>,<cc>
+ endm
+ else
+ externP macro n,c
+ ?ex1 <n>,2,<near>,<c>,<cc>
+ endm
+ endif
+
+ if sizec
+ externCP macro n,c
+ ?ex1 <n>,4,<dword>,<c>,<>
+ endm
+ else
+ externCP macro n,c
+ ?ex1 <n>,2,<word>,<c>,<>
+ endm
+ endif
+
+ if sized
+ externDP macro n,c
+ ?ex1 <n>,4,<dword>,<c>,<>
+ endm
+ else
+ externDP macro n,c
+ ?ex1 <n>,2,<word>,<c>,<>
+ endm
+ endif
+
+
+
+ ;; ?ex1 is the generalized external definition macro
+ ;;
+ ;; format:
+ ;; ?ex1 n,s,d,c,scv
+ ;; where:
+ ;; n is are the names of the externals
+ ;; s is the size in bytes (used for typing)
+ ;; d is the type
+ ;; c is the convention, C for C, PLM or PSACAL for PL/M.
+ ;; The default (?PLM flag) will be used if not specified.
+ ;; scv save calling convention. If this field is "cc", then
+ ;; the calling convention will be saved in a ?CCn equ.
+
+ ?ex1 macro n,s,d,c,scv
+ ?gcc ?ex2,%?PLM,<c>
+ irp x,<n>
+ .xcref
+ .xcref ?t&&x
+ .cref
+ ?t&&x=s ;;save size info
+ ife ?ex2
+ extrn _&&x:&d
+ x equ _&&x
+ else
+ extrn x:&d
+ endif
+ ifidn <scv>,<cc> ;;save calling convention (C or PL/M)
+ .xcref ;; if NP, FP, or P
+ .xcref ?CC&&x
+ .cref
+ ?CC&&x=?ex2
+ endif
+ endm
+ endm
+endif
+
+
+
+ifndef ?NOLABEL
+ .xcref
+ .xcref ?lb1,?lblpu,?lb2
+ .xcref labelB,labelW,labelD,labelQ,labelT
+ .xcref labelNP,labelFP,labelP,labelCP,labelDP
+ .cref
+ ?lblpu = 0
+ ?lb2 = 0
+
+ ;; labelx - define label of data type x
+ ;;
+ ;; usage:
+ ;; labelx n,c
+ ;; where:
+ ;; x is the type of the variable b=byte, w=word, d=dword
+ ;; q=quad word, t=tenbytes, cp=code pointer, dp=data pointer
+ ;; n is a list of names to define, the first of which can
+ ;; be the keyword public
+ ;; c is the convention, C for C, PLM or PSACAL for PL/M.
+ ;; The default (?PLM flag) will be used if not specified.
+
+ labelB macro n,c
+ ?lb1 <n>,1,<byte>,<c>
+ endm
+
+ labelW macro n,c
+ ?lb1 <n>,2,<word>,<c>
+ endm
+
+ labelD macro n,c
+ ?lb1 <n>,4,<dword>,<c>
+ endm
+
+ labelQ macro n,c
+ ?lb1 <n>,8,<qword>,<c>
+ endm
+
+ labelT macro n,c
+ ?lb1 <n>,10,<tbyte>,<c>
+ endm
+
+ labelNP macro n,c
+ ?lb1 <n>,2,<near>,<c>
+ endm
+
+ labelFP macro n,c
+ ?lb1 <n>,4,<far>,<c>
+ endm
+
+ if sizec
+ labelP macro n,c
+ ?lb1 <n>,4,<far>,<c>
+ endm
+ else
+ labelP macro n,c
+ ?lb1 <n>,2,<near>,<c>
+ endm
+ endif
+
+ if sizec
+ labelCP macro n,c
+ ?lb1 <n>,4,<dword>,<c>
+ endm
+ else
+ labelCP macro n,c
+ ?lb1 <n>,2,<word>,<c>
+ endm
+ endif
+
+ if sized
+ labelDP macro n,c
+ ?lb1 <n>,4,<dword>,<c>
+ endm
+ else
+ labelDP macro n,c
+ ?lb1 <n>,2,<word>,<c>
+ endm
+ endif
+
+
+ ;; ?lb1 is the generalized label definition macro
+ ;;
+ ;; format:
+ ;; ?lb1 n,s,d
+ ;; where:
+ ;; n are the names of the labels
+ ;; s is the size in bytes (used for typing)
+ ;; d is the type
+ ;; c is the convention, C for C, PLM or PSACAL for PL/M.
+ ;; The default (?PLM flag) will be used if not specified.
+
+ ?lb1 macro n,s,d,c
+ ?gcc ?lb2,%?PLM,<c>
+ ?lblpu=0
+ irp x,<n>
+ ifidn <x>,<PUBLIC>
+ ?lblpu=1
+ else
+ .xcref
+ .xcref ?t&&x
+ .cref
+ ?t&&x=s ;;save size info
+ ife ?lb2 ;;If C
+ if ?lblpu
+ public _&&x
+ endif
+ _&&x label &d
+ x equ _&&x
+ else ;;If PL/M
+ if ?lblpu
+ public x
+ endif
+ x label &d
+ endif
+ endif
+ endm
+ endm
+endif
+
+
+
+ifndef ?NODEF
+
+ ;; defx - inform macros that name is of type x
+ ;;
+ ;; The given name(s) is flaged to be of the given type. This macro
+ ;; is intended for giving types to variables that were not generated
+ ;; by the macros (i.e., static storage). There must be a type definition
+ ;; for all parameters in a call list.
+ ;;
+ ;; usage:
+ ;; defx n
+ ;; where:
+ ;; x is the type of the variable b=byte, w=word, d=dword
+ ;; n is the name(s) to be given the variable(s).
+ ;;
+ ;; Bytes are considered to be two bytes long for alignment reasons
+
+ .xcref
+ .xcref defB,defW,defD,defQ,defT,defCP,defDP
+ .cref
+
+ defB macro n
+ ?ad <n>,1
+ endm
+
+ defW macro n
+ ?ad <n>,2
+ endm
+
+ defD macro n
+ ?ad <n>,4
+ endm
+
+ defQ macro n
+ ?ad <n>,8
+ endm
+
+ defT macro n
+ ?ad <n>,10
+ endm
+
+ if sizec
+ defCP macro n
+ defD <n>
+ endm
+ else
+ defCP macro n
+ defW <n>
+ endm
+ endif
+
+ if sized
+ defDP macro n
+ defD <n>
+ endm
+ else
+ defDP macro n
+ defW <n>
+ endm
+ endif
+endif
+
+
+
+; ?ad is the macro which creates a definition for the given
+; symbol
+;
+; usage:
+; ?ad <n>,s
+; where:
+; n is a list of names to define
+; s is the size info (1,2,4,8,10)
+
+
+?ad macro n,s
+ irp x,<n>
+ .xcref
+ .xcref ?t&&x
+ .cref
+ ?t&&x=s ;;save size info
+ endm
+endm
+
+
+
+ifndef ?NOPTR
+ .xcref
+ .xcref regPtr,farPtr
+ .cref
+
+ ;; regPtr generates information allowing a 32-bit pointer currently
+ ;; in a register to be pushed as a parameter to a subroutine using
+ ;; the cCall macro.
+ ;;
+ ;; usage:
+ ;; regptr n,s,o
+ ;; where:
+ ;; n is the name the argument will be known as
+ ;; s is the register containing the segment portion
+ ;; of the pointer
+ ;; o is the register containing the offset portion
+ ;; of the pointer
+ ;;
+ ;; 2/14/85 - made obsolete with farptr
+
+ regPtr macro n,s,o
+ farPtr n,s,o
+ endm
+
+
+
+ ;; farPtr generates information allowing a 32-bit pointer to be
+ ;; pushed as a parameter to a subroutine using the cCall macro.
+ ;;
+ ;; usage:
+ ;; farptr n,s,o
+ ;; where:
+ ;; n is the name the argument will be known as
+ ;; s is the segment portion of the pointer
+ ;; o is the offset portion of the pointer
+ ;;
+ ;; Note that any cast must have been made in the argument itself
+ ;; (i.e. regptr ptr1,ds,<word ptr 3[si]>)
+
+
+ farPtr macro n,s,o
+ .xcref
+ .xcref ?t&n
+ .cref
+ n &macro
+ push s ;@
+ push o ;@
+ &endm
+ ?t&n=80h
+ endm
+endif
+
+
+
+;; arg - declare argument
+;;
+;; The given argument(s) is added to the argument list structure
+;;
+;; format:
+;; arg a
+;;
+;; where:
+;; a is any valid argument to push.
+;;
+;; If any element in arglist has not been defined or isn't a 16-bit
+;; register, then a complete specification must have been given in a
+;; text equate and a defx also given (if not, you'll pay the penalty!)
+
+
+arg macro a
+ irp x,<a>
+ ?argc=?argc+1 ;;increment the arg count
+ ?atal <x>,%?argc ;;generate argument
+ endm
+endm
+
+
+
+;; ?atal (add to argument list) generates a macro that will cause
+;; the given argument to be processed when invoked. It is used by
+;; the arg macro only.
+
+
+?atal macro n,i
+ .xcref
+ .xcref ?ali&i
+ .cref
+ ?ali&i &macro
+ ?ap <n>
+ &endm
+endm
+
+
+
+;; ?ap - process arguments and place onto stack
+;;
+;; The given argument is processed (type checking) and place on
+;; the stack for a pending call. There must be a type definition
+;; for all arguments (except words). This can be done by using
+;; text equates and the defx macro.
+;;
+;; format:
+;; ?ap n
+;; where:
+;; n is the name of the argument to be pushed
+;;
+;; The variable ?argl is updated by the length of the arguments
+;; pushed so that the stack can be cleaned up after the call.
+
+
+?ap macro n
+ ?argl=?argl+2 ;;assume one word is pushed
+ ifdef ?t&n
+ ife ?t&n-1 ;;byte type
+ push word ptr (n) ;@
+ exitm
+ endif
+
+ ife ?t&n-2 ;;word type
+ push n ;@
+ exitm
+ endif
+
+ ife ?t&n-4 ;;dword type
+ push word ptr (n)[2] ;@
+ push word ptr (n) ;@
+ ?argl=?argl+2
+ exitm
+ endif
+
+ ife ?t&n-8 ;;qword type
+ push word ptr (n)[6] ;@
+ push word ptr (n)[4] ;@
+ push word ptr (n)[2] ;@
+ push word ptr (n) ;@
+ ?argl=?argl+6
+ exitm
+ endif
+
+ if ?t&n and 80h ;;far pointer type
+ n
+ ?argl=?argl+2
+ exitm
+ endif
+
+ ife ?t&n ;;variable storage
+ push word ptr (n) ;@
+ exitm
+ endif
+ endif
+
+ push n ;;unknown or register or immediate ;@
+endm
+
+
+
+;; cCall - call a 'c' language procedure
+;;
+;; The given procedure is called with the given parameters.
+;; If the calling convention is C, the arguments are pushed
+;; in reverse order, and removed after the called procedure
+;; returns. If the calling conventing is PL/M, the arguments
+;; are pushed as they were encountered, and the called procedure
+;; is assumed to have removed them from the stack.
+;;
+;; The calling convention priority will be:
+;; 1) that specified on the cCall if present
+;; 2) that defined by the target
+;; 3) the default (?PLM flag)
+;;
+;; format:
+;; ccall n,<a>,c
+;;
+;; where:
+;; n is the name of the procedure to call
+;; a are arguments to be pushed (optional, may be
+;; specified with the "arg" macro.
+;; c is the convention, C for C, PLM or PSACAL for PL/M.
+;; The default (?PLM flag) will be used if not specified.
+
+
+cCall macro n,a,c
+ ifnb <a> ;;add any arguments to list
+ arg <a>
+ endif
+ mpush %?rsl ;;save registers (if any)
+
+ ifdef ?CC&n ;;if calling convention has been
+ ?cCall1=?CC&n ;; defined for target, use it
+ else ;;else use the default
+ ?cCall1=?PLM
+ endif
+
+ ifnb <c> ;;If possible override, check it out
+ ?gcc ?cCall1,%?cCall1,<c>
+ endif
+
+ ?argl=0 ;;init argument length
+ ife ?cCall1 ;;if C calling convention
+ ?acb=?argc ;;initialize for looping
+ else
+ ?acb=1 ;;initialize for looping
+ endif
+
+ rept ?argc ;;push arguments and purge macros
+ uconcat <?ali>,%?acb
+ uconcat <purge>,,<?ali>,%?acb
+ ife ?cCall1 ;;if C calling convention
+ ?acb=?acb-1
+ else
+ ?acb=?acb+1
+ endif
+ endm
+ call n ;;call the procedure ;@
+ if ((?cCall1 eq 0) and (?argl ne 0)) ;;If C calling convention and arguments
+ add sp,?argl ;; then remove them ;@
+ endif
+ mpop %?rsl ;;pop all specified regs
+ ?rsl=0 ;;invalidate save list
+ ?argc= 0 ;; " arguments
+ ?argl= 0
+endm
+
+
+
+
+;; cProc - define a 'c' procedure
+;;
+;; cProc is the procedure definition for procedures.
+;;
+;; format:
+;; cProc n,cf,a
+;; where:
+;; n is the name of the procedure
+;;
+;; cf controls certain definitions, and may be:
+;; NEAR proc is to be a near label
+;; FAR proc is to be a far label
+;; PUBLIC proc is to be defined as public
+;; SMALL call makeframe procedure
+;; NODATA dont create prolog code to setup DS
+;; ATOMIC don't link stack if not needed
+;; NODATA must be specified for ATOMIC
+;; FORCEFRAME Force generation of a frame
+;; C proc is to be a C procedure
+;; PLM proc is to be a PL/M procedure
+;; PASCAL proc is to be a PL/M procedure
+;; WIN proc is to be a windows procedure
+;; NONWIN proc isn't to be a windows procedure
+;; NO_BP don't generate BP in text equates
+;; BP generate BP in text equates
+;;
+;; a is a list of registers that are to be saved whenever
+;; the procedure is invoked.
+;;
+;; makeframe procedure: If small is specified, then
+;; the "makeframe procedure" is invoked instead of
+;; generating normal prologues/epilogues
+;;
+;; A call is performed to the makeframe procedure. The
+;; call is followed by two bytes. the first byte is the
+;; number of locals to allocate for the frame, the second
+;; is the number of bytes of parameters. The makeframe
+;; procedure will in turn call the cProc routine at the
+;; address following the data bytes. When the cProc is
+;; finished, it will do a near return to the makeframe
+;; procedure to clean up the frame and exit.
+;;
+;; Note that register parameters and makeframe are
+;; incompatible and cannot be used together.
+;;
+;; The makeframe procedure will save SI, DI, and also
+;; DS if a far procedure. These registers will be
+;; removed from the autosave list if specified.
+
+
+cProc macro n,cf,a
+ if ?cpd
+ ?utpe ;;generate unterminated proc error
+ endif
+
+ ?cpd=1 ;;a procdef is active now
+ ???=0 ;;no locals are defined yet
+ ?argc=0 ;;no arguments are defined
+ ?ba=0 ;;not in a procedure
+ ?po=0 ;;initial parameter offset
+ ?pu=0 ;;initial public setting
+ ?ia=0 ;;no special prolog/epilog
+ ?adj=2*sizeI ;;parameter adjustment (near ret+bp)
+ ?rp=0 ;;no register parameters
+ ?uf=0 ;;don't use makeframe
+ ?wfp=?WIN ;;default far procedure (win or not)
+ ?ff=0 ;;don't force frame setup
+ ?pas=0 ;;process register save list
+ ?pcc=?PLM ;;calling convention (C or PL/M)
+ ?no_bp2=?no_bp1 ;;Default base register generation
+
+ ifnb <a> ;;register save list
+ ?ri ?pas,<a>
+ endif
+
+ ?pc=sizec ;;default size
+ ?nd=?nodata1 ;;default NODATA flag
+ ?nx=0 ;;default is not ATOMIC
+
+ irp x,<cf>
+ ifdef ??_cproc_&&x
+ ??_cproc_&&x
+ else
+ ??error2 <e r r o r - unknown keyword x>
+ .err
+ endif
+
+ endm
+
+ if ?pcc ;;If PLM
+ ?PLMPrevParm=0 ;; show no previous parameter
+ .xcref
+ .xcref ?PLMParm0
+ .cref
+ ?PLMParm0 &macro ;;Null macro to terminate
+ purge ?PLMParm0
+ &endm
+ endif
+
+ .xcref
+ .xcref ?CC&n
+ .cref
+ ?CC&n=?pcc ;;Save procedure type
+
+ if (?nx eq 1) and (?nd eq 0) ;;ATOMIC requires NODATA
+ ?nx = 0 ;;clear the ATOMIC keyword
+ ??error2 <ATOMIC specified without NODATA - ATOMIC ignored>
+ endif
+
+ if ?pc ;;if a far procedure
+ if ?wfp ;;if windows
+ ife ?nx ;;if not ATOMIC
+ ife ?COW ;; COW dos not save DS
+ ?ia=2 ;; adjust locals for saved ds
+ ?pas = ?pas and (not ?ds) ;;no need for extra save
+ endif
+ endif
+ endif
+ ?adj=?adj+sizeI ;;far, make parameter adjustment
+ else
+ ?wfp=0 ;;not a far windows procedure
+ endif
+
+ ?pas = ?pas and (not (?sp+?cs+?ss)) ;;make no sense to save these
+
+ if ?uf ;;don't save these if user frame
+ ?pas = ?pas and (not (?bp+?si+?di))
+ endif
+
+ ife ?pcc
+ ?pg <_&n>,%?pu,%?pc,%?pas,%?wfp,<n>,%?pcc
+ else
+ ?pg <n>,%?pu,%?pc,%?pas,%?wfp,<n>,%?pcc
+ endif
+endm
+
+
+
+
+;; ?pg - generate begin and nested macros for current procedure
+;;
+;; format:
+;; ?pg n,p,c,a,w,nnu,cc
+;; where:
+;; n is the name of the procedure
+;; p is the public flag
+;; c is the class definition for the procedure
+;; a is an enumerated list of registers to save
+;; at entry and restore at exit
+;; w true if a far windows procedure
+;; nnu procedure name without any underscore
+;; cc calling convention (C or PL/M)
+;;
+;;
+;; local stack allocation will be forced to an even byte count to
+;; maintain stack word alignment.
+
+
+?pg macro n,p,c,a,w,nnu,cc
+ .xcref
+ if ?uf ;;if user frame
+ if ?nd
+ ??error2 <NODATA encountered in &n - user frame ignored>
+ ?uf=0
+ endif
+ endif
+
+ .xcref cBegin
+ cBegin &macro g ;;generate cBegin macro
+ .xcref
+ if cc ;;Finish definition of parameters
+ uconcat <?PLMParm>,%?PLMPrevParm,%?po
+ endif
+
+ if ?uf ;;if user frame
+ if ?rp ;;If register parameters
+ ??error2 <parmR encountered in &n - user frame ignored>
+ ?uf=0
+ endif
+ endif
+ ?pg1 <n>,c,a,%?po,w,%?uf,%?nd,%?rp,cc,<nnu>,%??? ;;generate cEnd macro
+ ?cpd=0 ;;terminate current proc def
+ ?argc=0 ;;no arguments are defined yet
+ ?ba=1 ;;have reached a begin
+ ???=(???+1) and 0fffeh ;;word align local storage
+
+ if p ;;If to be public
+ public n
+ endif
+
+ ife c ;;declare procedure type
+ n proc near
+ else
+ n proc far
+ endif
+
+ ife cc ;;if 'C' calling convention
+ nnu equ n ;; generate label without underscore
+ endif
+
+ ?cbe = 0 ;;Assume no command on cBegin line
+ ifnb <g>
+ ?pcbe <g>,<nnu>,<cBegin>
+ endif
+ if ?cbe eq 1 ;;if nogen, then cannot have locals
+ if ???+a+?rp ;; saved regs, or parmRs
+ if2
+ ??_out <cBegin - possibly invalid use of nogen>
+ endif
+ endif
+ else ;;else must generate a frame
+ if ?uf ;;if user frame code specified
+ ?mf c,%???,%?po ;; call user's makeframe
+ mpush a ;; save specified registers
+ else
+ ife ?cbe ;;If full frame to be set up
+ if w ;;if a far windows procedure
+ ife ?nd ;;if not NODATA,
+ mov IAX,ds ;; then set AX = current ds, and ;@
+ nop ;; leave room for MOV AX,1234h ;@
+ endif
+ ife ?nx ;;if not ATOMIC, far frame must be set
+ ife ?DOS5 ;;if not DOS5, then set far frame flag
+ inc IBP ;; by incrementing the old bp ;@
+ endif
+ push IBP ;@
+ mov IBP,ISP ;@
+ ife ?COW ;; save DS not needed for CW
+ push ds ;@
+ endif
+ else ;;ATOMIC procedure
+ if ?ff+???+?po+?rp ;;if any locals or parameters
+ push IBP ;; then must set frame pointer ;@
+ mov IBP,ISP ;; to be able to access them ;@
+ endif
+ endif
+ ife ?nd ;;if not NODATA, then AX should
+ mov ds,IAX ;; have the ds to use ;@
+ endif
+ else ;;not windows. use standard prolog
+ if ?ff+???+?po+?rp ;;if any locals or parameters
+ push IBP ;; then must set frame pointer ;@
+ mov IBP,ISP ;; to be able to access them ;@
+ endif
+ endif
+ if ?rp ;;if parmR's, push them before
+ ?uf=0 ;; allocating locals and saving
+ rept ?rp ;; the autosave registers
+ uconcat mpush,,?rp,%?uf
+ ?uf=?uf+1
+ endm
+ endif
+ if ??? ;;if locals to allocate
+ if ?chkstk1 ;;if stack checking enabled
+ ifdef ?CHKSTKPROC ;;if user supplied stack checking
+ ?CHKSTKPROC %??? ;; invoke it with bytes requested
+ else
+ mov IAX,??? ;;invoke default stack checking ;@
+ ife cc
+ call _chkstk ;@
+ else
+ call chkstk ;@
+ endif
+ endif
+ else ;;no stack checking
+ sub ISP,??? ;; allocate any local storage ;@
+ endif
+ endif
+ else ;;partial frame, only set locals
+ if ?rp ;;If parmRs, error
+ ??error2 <cBegin - parmRs encountered with partial frame>
+ else
+ if ??? ;;Only realloc frame if locals
+ lea ISP,[IBP][-???-?ia] ;;?ia will adjust for saved BP ;@
+ endif
+ endif
+ endif
+ mpush a ;;save autosave registers
+ endif
+
+ ifdef ?PROFILE ;;if profiling enabled
+ if c ;; and a far procedure
+ call StartNMeas ;; invoke profile start procedure ;@
+ endif
+ endif
+
+ endif
+
+ .cref
+ purge cBegin ;;remove the macro
+ &endm ;;end of cBegin macro
+
+ .xcref ?utpe
+ ?utpe &macro
+ ??error2 <unterminated procedure definition: "&n">
+ &endm
+ .cref
+endm ;;end of ?pg macro
+
+
+
+
+;; ?pg1 - generate end macro for current procedure
+;;
+;; format:
+;; ?pg1 n,c,a,o,w,f,d,r,cc,nnu,lc
+;; where:
+;; n is the name of the procedure
+;; c is the class definition for the procedure
+;; a is an enumerated list of registers to save
+;; at entry and restore at exit
+;; o is the number of bytes of paramteres to remove at exit
+;; w true if a far windows procedure
+;; f is 1 if to use the user's makeframe procedure
+;; d is 1 if NODATA procedure
+;; r number of register parameters
+;; cc calling convention (C or PL/M)
+;; nnu procedure name without any underscore
+;; lc locals byte count
+
+
+?pg1 macro n,c,a,o,w,f,d,r,cc,nnu,lc
+ .xcref
+ .xcref cEnd
+
+ parm_bytes_&nnu = o ;;Define number of parameter bytes
+
+ cEnd &macro g ;;start of cEnd macro
+ .xcref
+ ?ba=0 ;;no longer in a procedure
+ ?cbe = 0 ;;Assume no command on cBegin line
+ ifnb <g>
+ ?pcbe <g>,<nnu>,<cEnd>
+ endif
+ if ?cbe eq 1 ;;if nogen, then cannot have parmRs
+ if a+r+lc ;; locals, or saved registers
+ if2
+ ??_out <cEnd - possibly invalid use of nogen>
+ endif
+ endif
+ else ;;else must remove the frame
+ ifdef ?PROFILE ;;if profiling enabled
+ if c ;; and a far procedure
+ call StopNMeas ;; invoke profile stop procedure
+ endif ;; (doesn't trash DX:AX)
+ endif
+ mpop a ;;restore autosaved registers
+ if f ;;if to use the "makeframe" procedure
+ db 0c3h ;; near return to user's makeframe @
+ else
+ if w ;;if far win proc, use special epilog
+ ife ?nx ;;if not ATOMIC, bp was pushed
+ ife ?COW ;; restore DS not needed for CW
+ if (?TF eq 0) or (???+r) ;;if cannot assume valid sp
+ lea sp,-2[bp] ;; or locals or parmR's, get valid SP @
+ endif
+ pop ds ;;restore saved ds and bp @
+ else
+ if (?TF eq 0) or (???+r) ;;if cannot assume valid sp
+ mov sp,bp
+ endif
+ endif
+ pop IBP ;; @
+ ife ?DOS5 ;;if not DOS5, bp was
+ dec IBP ;; incremented to mark far frame @
+ endif
+ else ;;ATOMIC frame was set up
+ if memS32
+ leave
+ else
+ if (?TF eq 0) or (???+r) ;;if cannot assume valid sp
+ mov ISP,IBP ;; or locals or parmR's, get valid SP @
+ endif
+ if ???+?po+r
+ pop IBP ;@
+ endif
+ endif
+ endif
+ else ;;non-windows standard epilog
+ if ?ff+???+?po+r ;;if any parameters
+ if (?TF eq 0) or (???+r) ;;if cannot assume valid SP
+ mov ISP,IBP ;; or locals or parmR's, get valid SP;@
+ endif
+ pop IBP ;@
+ endif
+ endif
+ if ?cbe ne 4 ;;Don't generate ret if ??cleanframe?? e
+ ife cc ;;if C calling convention
+ ret ;; return ;@
+ else ;;else
+ ret o ;; return and remove paramteres ;@
+ endif
+ endif
+ endif
+ endif
+ if ?cbe ne 4 ;;Don't delete macro if ??cleanframe?? e
+ n endp ;;end of process
+ .cref
+ purge cEnd ;;remove the macro
+ else
+ .cref
+ endif
+ &endm
+ .cref
+endm
+
+
+;; cleanframe
+;;
+;; cleanframe removes a cMacros generated frame, invoking cEnd
+;; with a special keyword which will keep the cEnd macro from
+;; generating a return statement and purging itself.
+
+.xcref
+.xcref cleanframe
+cleanframe macro
+ cEnd <??cleanframe??>
+endm
+.cref
+
+
+
+;; The following macros are used to speed up the processing of the
+;; command allowed on a cProc command line. They simply set or clear
+;; the correct flag as needed.
+
+.xcref
+.xcref ??_cproc_FAR,??_cproc_NEAR,??_cproc_PUBLIC,??_cproc_SMALL
+.xcref ??_cproc_DATA,??_cproc_NODATA,??_cproc_ATOMIC,??_cproc_C
+.xcref ??_cproc_PLM,??_cproc_PASCAL,??_cproc_WIN,??_cproc_NONWIN
+.xcref ??_cproc_NO_BP,??_cproc_BP
+
+.xcref ??_cproc_far,??_cproc_near,??_cproc_public,??_cproc_small
+.xcref ??_cproc_data,??_cproc_nodata,??_cproc_atomic,??_cproc_c
+.xcref ??_cproc_plm,??_cproc_pascal,??_cproc_win,??_cproc_nonwin
+.xcref ??_cproc_no_bp,??_cproc_bp
+.cref
+
+??_cproc_FAR macro
+ ?pc=1
+endm
+
+??_cproc_NEAR macro
+ ?pc=0
+endm
+
+??_cproc_PUBLIC macro
+ ?pu=1
+endm
+
+??_cproc_SMALL macro
+ ?uf=1
+endm
+
+??_cproc_DATA macro
+ ?nd=0
+endm
+
+??_cproc_NODATA macro
+ ?nd=1
+endm
+
+??_cproc_ATOMIC macro
+ ?nx=1
+endm
+
+??_cproc_C macro
+ ?pcc=0
+endm
+
+??_cproc_PLM macro
+ ?pcc=1
+endm
+
+??_cproc_PASCAL macro
+ ?pcc=1
+endm
+
+??_cproc_WIN macro
+ ?wfp=1
+endm
+
+??_cproc_NONWIN macro
+ ?wfp=0
+endm
+
+??_cproc_NO_BP macro
+ ?no_bp2=1
+endm
+
+??_cproc_BP macro
+ ?no_bp2=0
+endm
+
+??_cproc_far macro
+ ?pc=1
+endm
+
+??_cproc_near macro
+ ?pc=0
+endm
+
+??_cproc_public macro
+ ?pu=1
+endm
+
+??_cproc_small macro
+ ?uf=1
+endm
+
+??_cproc_data macro
+ ?nd=0
+endm
+
+??_cproc_nodata macro
+ ?nd=1
+endm
+
+??_cproc_atomic macro
+ ?nx=1
+endm
+
+??_cproc_c macro
+ ?pcc=0
+endm
+
+??_cproc_plm macro
+ ?pcc=1
+endm
+
+??_cproc_pascal macro
+ ?pcc=1
+endm
+
+??_cproc_win macro
+ ?wfp=1
+endm
+
+??_cproc_nonwin macro
+ ?wfp=0
+endm
+
+??_cproc_no_bp macro
+ ?no_bp2=1
+endm
+
+??_cproc_bp macro
+ ?no_bp2=0
+endm
+
+
+; ?pcbe is the macro which processes the text on cBegin/cEnd
+; The text is allowed to be:
+;
+; NOGEN nogen
+; PARTIAL partial
+; the procedure name as given on the cProc line
+;
+; usage:
+; ?pcbe <g>,<nnu>,<mt>
+; where:
+; g is the text on the cBegin/cEnd line
+; nnu is the procedure name without any underscores
+; mt macro type (cBegin/cEnd)
+;
+; The variable ?cbe is set to the following value
+;
+; 0 = invalid (defualt action>
+; 1 = nogen
+; 2 = partial frame
+; 4 = clean frame
+
+
+?pcbe macro g,nnu,mt
+ ifidn <g>,<NOGEN>
+ ?cbe = 1
+ else
+ ifidn <g>,<nogen>
+ ?cbe = 1
+ else
+ ifidn <mt>,<cBegin>
+ ifidn <g>,<PARTIAL>
+ ?cbe = 2
+ else
+ ifidn <g>,<partial>
+ ?cbe = 2
+ else
+ ifdif <g>,<nnu>
+ ??error2 <mt - unknown keyword g>
+ endif
+ endif
+ endif
+ else
+ ifidn <g>,<??cleanframe??>
+ ?cbe = 4
+ else
+ ifdif <g>,<nnu>
+ ??error2 <mt - unknown keyword g>
+ endif
+ endif
+ endif
+ endif
+ endif
+endm
+
+
+
+; assumes is a macro that will set up the assumes for a segment
+; or group created with the createSeg macro. If the assumed
+; value passed in isn't known, then a normal assume is made.
+;
+; usage:
+; assumes s,g
+;
+; where:
+; s is the register to make the assumption about
+; g is the value to assume is in it
+;
+; as a hack, substitute FLAT for g if memF32 is set
+
+
+assumes macro s,ln
+ if memF32
+ assume s:FLAT
+ endif
+ ife memF32
+ ifndef ln&_assumes
+ assume s:ln
+ else
+ ln&_assumes s
+ endif
+ endif
+endm
+
+
+
+; createSeg is a macro that sets up a segment definition and
+; a logical name for that segment. The logical name can be
+; used to enter the segment, but it cannot be used for anything
+; else.
+;
+; usage:
+; createSeg n,ln,a,co,cl,grp
+; where:
+; n is the physical name of the segment
+; ln is the name it is to be invoked by
+; a is the alignment, and is optional
+; co is the combine type, and is optional
+; cl is the class, and is optional
+; grp is the name of the group that contains this segment
+
+
+createSeg macro n,ln,a,co,cl,grp
+ ifnb <cl>
+ n segment a co '&cl'
+ else
+ n segment a co
+ endif
+ n ends
+ ifnb <grp>
+ addseg grp,n
+ else
+ ln&OFFSET equ offset n:
+ ln&BASE equ n
+ ?cs3 <ln>,<n>
+ endif
+ ?cs1 <ln>,<n>
+endm
+
+
+addseg macro grp,seg
+ .xcref
+ .xcref grp&_def
+ .cref
+ ifndef grp&_def
+ grp&_def=0
+ endif
+ if grp&_def ne ASMpass
+ .xcref
+ .xcref grp&_add
+ .cref
+ grp&_add &macro s
+ grp&_in <seg>,s
+ &endm
+ .xcref
+ .xcref grp&_in
+ .cref
+ grp&_in &macro sl,s
+ ifb <s>
+ grp group sl
+ else
+ grp&_add &macro ns
+ grp&_in <sl,s>,ns
+ &endm
+ endif
+ &endm
+ grp&_def=ASMpass
+ else
+ grp&_add seg
+ endif
+endm
+
+
+defgrp macro grp,ln
+ addseg grp
+ ifnb <ln>
+ irp x,<ln>
+ ?cs3 <&x>,<grp>
+ x&&OFFSET equ offset grp:
+ x&&BASE equ grp
+ endm
+ endif
+endm
+
+
+?cs1 macro ln,n
+ .xcref
+ .xcref ln&_sbegin
+ .cref
+ ln&_sbegin &macro
+ .xcref
+ .xcref ?mf
+ .cref
+ ?mf &&macro c,l,p ;;when sBegin is invoked, generate
+ if c ;; the makeframe macro
+ extrn n&_FARFRAME:near ;; make frame for far procedures ;@
+ call n&_FARFRAME ;@
+ else
+ extrn n&_NEARFRAME:near ;; make frame for near procedures ;@
+ call n&_NEARFRAME ;@
+ endif
+ db l shr 1 ;;define number of locals ;@
+ db p shr 1 ;;define number of parameters ;@
+ &&endm
+ ?cs2 <ln>,<n>
+ n segment
+ &endm
+endm
+
+
+?cs2 macro ln,n
+ .xcref
+ .xcref sEnd
+ .cref
+ sEnd &macro
+ n ends
+ purge ?mf ;;delete the makeframe macro
+ purge sEnd
+ &endm
+endm
+
+
+?cs3 macro ln,n
+ .xcref
+ .xcref ln&_assumes
+ .cref
+ ln&_assumes &macro s
+ assume s:&n
+ &endm
+endm
+
+
+
+; sBegin is the macro that opens up the definition of a segment.
+; The segment must have already been defined with the createSeg
+; macro.
+;
+; usage:
+; sBegin ln
+;
+; where:
+; ln is the logical name given to the segment when
+; it was declared.
+
+.xcref
+.xcref sBegin
+.cref
+sBegin macro ln
+ ln&_sbegin
+endm
+
+BeginDATA macro
+ ife memF32
+ sBegin DATA
+ else
+ .data
+ endif
+endm
+
+BeginCODE macro
+ ife memF32
+ sBegin CODE
+ else
+ .code
+ endif
+endm
+
+EndDATA macro
+ ife memF32
+ sEnd DATA
+ endif
+endm
+
+EndCODE macro
+ ife memF32
+ sEnd CODE
+ endif
+endm
+
+ife ?DF
+
+ ; Define all segments that will be used. This will allow the
+ ; assume and groups to be set up at one given place, and also
+ ; allow quick changes to be made
+ ;
+ ; createSeg name,logname,align,combine,class,group
+
+ife ?DFCODE
+ createSeg _TEXT,CODE,%wordI,public,CODE
+endif
+ ife ?nodata1
+ createSeg _DATA,DATA,%wordI,public,DATA,DGROUP
+ defgrp DGROUP,DATA
+ else
+ ife ?DFDATA
+ createSeg _DATA,DATA,%wordI,public,DATA,DGROUP
+ defgrp DGROUP,DATA
+ endif
+ endif
+
+ if ?chkstk1
+ ifndef ?CHKSTKPROC
+ externp <chkstk>
+ endif
+ endif
+endif
+
+
+; errnz exp - generate error message if expression isn't zero
+;
+; The errnz will generate an error message if the expression "exp"
+; does not evaluate to zero. This macro is very useful for testing
+; relationships between items, labels, and data that was coded into
+; an application.
+;
+; errnz <offset $ - offset label> ;error if not at "label"
+; errnz <eofflag and 00000001b> ;eofflag must be bit 0
+;
+; For expressions involving more than one token, the angle brackets
+; must be used.
+;
+; The macro is only evaluated on pass 2, so forward references may be
+; used in the expression.
+
+errnz macro x ;;display error if expression is <>0
+ if2
+ if x ;;if expression is non-zero,
+ errnz1 <x>,%(x)
+ endif
+ endif
+endm
+
+errnz1 macro x1,x2
+ = *errnz* x1 = x2
+ .err
+endm
+
+
+
+; errn$ label,exp - generate error message if label (exp) <> $
+;
+; The errnz will generate an error message if the label and "exp"
+; does not evaluate to the current value of the location counter.
+; This macro is very useful for testing relationships between
+; labels and the location counter that was coded into an application.
+;
+; examples: errn$ label ;error if not at "label"
+; errn$ label,+3 ;error if not three bytes from "label"
+; errn$ label,-3 ;error if not three bytes past "label"
+;
+; If no "exp" is given, it is the same as specifying 0
+;
+; The macro is only evaluated on pass 2, so forward references may be
+; used in the expression.
+
+errn$ macro l,x ;;error if <$-label1 (exp2)> <>0
+ errnz <offset $ - offset l x>
+endm
+
+
+
+;; If profile has been specified, declare the profile routines
+;; to be external and far. It would be best if this could be done
+;; when the call is actually made, but then the fix-up would be
+;; generated as segment-relative.
+
+
+ifdef ?PROFILE
+ externFP <StartNMeas,StopNMeas>
+endif
+
+if memF32
+ .model small
+endif
+
diff --git a/private/crt32/h/cmsgs.h b/private/crt32/h/cmsgs.h
new file mode 100644
index 000000000..7aa737e3b
--- /dev/null
+++ b/private/crt32/h/cmsgs.h
@@ -0,0 +1,71 @@
+/***
+*cmsgs.h - runtime errors
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The file defines, in one place, all error message strings used within
+* the C run-time library.
+*
+*Revision History:
+* 06-04-90 GJF Module created.
+* 08-08-90 GJF Added _RT_CONIO_TXT
+* 10-11-90 GJF Added _RT_ABORT_TXT, _RT_FLOAT_TXT, _RT_HEAP_TXT.
+* 09-08-91 GJF Added _RT_ONEXIT_TXT for Win32 (_WIN32_).
+* 09-18-91 GJF Fixed _RT_NONCONT_TXT and _RT_INVALDISP_TXT to
+* avoid conflict with RTE messages in 16-bit Windows
+* libs. Also, added math error messages.
+* 10-23-92 GJF Added _RT_PUREVIRT_TXT.
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+/*
+ * runtime error and termination messages
+ */
+
+#define _RT_STACK_TXT "R6000\r\n- stack overflow\r\n"
+
+#define _RT_FLOAT_TXT "R6002\r\n- floating point not loaded\r\n"
+
+#define _RT_INTDIV_TXT "R6003\r\n- integer divide by 0\r\n"
+
+#define _RT_SPACEARG_TXT "R6008\r\n- not enough space for arguments\r\n"
+
+#define _RT_SPACEENV_TXT "R6009\r\n- not enough space for environment\r\n"
+
+#define _RT_ABORT_TXT "\r\nabnormal program termination\r\n"
+
+#define _RT_THREAD_TXT "R6016\r\n- not enough space for thread data\r\n"
+
+#define _RT_LOCK_TXT "R6017\r\n- unexpected multithread lock error\r\n"
+
+#define _RT_HEAP_TXT "R6018\r\n- unexpected heap error\r\n"
+
+#define _RT_OPENCON_TXT "R6019\r\n- unable to open console device\r\n"
+
+#define _RT_NONCONT_TXT "R6022\r\n- non-continuable exception\r\n"
+
+#define _RT_INVALDISP_TXT "R6023\r\n- invalid exception disposition\r\n"
+
+/*
+ * _RT_ONEXIT_TXT is specific to Win32 and Dosx32 platforms
+ */
+#define _RT_ONEXIT_TXT "R6024\r\n- not enough space for _onexit/atexit table"
+
+#define _RT_PUREVIRT_TXT "R6025\r\n- pure virtual function call\r\n"
+
+/*
+ * _RT_DOMAIN_TXT, _RT_SING_TXT and _RT_TLOSS_TXT are used by the floating
+ * point library.
+ */
+#define _RT_DOMAIN_TXT "DOMAIN error\r\n"
+
+#define _RT_SING_TXT "SING error\r\n"
+
+#define _RT_TLOSS_TXT "TLOSS error\r\n"
+
+
+#define _RT_CRNL_TXT "\r\n"
+
+#define _RT_BANNER_TXT "runtime error "
diff --git a/private/crt32/h/conio.h b/private/crt32/h/conio.h
new file mode 100644
index 000000000..8baadaab5
--- /dev/null
+++ b/private/crt32/h/conio.h
@@ -0,0 +1,127 @@
+/***
+*conio.h - console and port I/O declarations
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This include file contains the function declarations for
+* the MS C V2.03 compatible console I/O routines.
+*
+*Revision History:
+* 07-27-87 SKS Added inpw(), outpw()
+* 08-05-87 SKS Change outpw() from "int" return to "unsigned"
+* 11-16-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-17-87 JCR Added _MTHREAD_ONLY
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 08-19-88 GJF Modified to also work for the 386 (small model only)
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 07-27-89 GJF Cleanup, now specific to the 386
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-17-89 GJF Added const to appropriate arg types of cprintf(),
+* cputs() and cscanf().
+* 02-27-90 GJF Added #ifndef _INC_CONIO and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 or _CALLTYPE2 in
+* prototypes.
+* 07-23-90 SBM Added _getch_lk() prototype/macro
+* 01-16-91 GJF ANSI support. Also, removed prototypes for port i/o
+* functions (not supported in 32-bit).
+* 08-20-91 JCR C++ and ANSI naming
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 08-26-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_CONIO
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/* function prototypes */
+
+char * _CRTAPI1 _cgets(char *);
+int _CRTAPI2 _cprintf(const char *, ...);
+int _CRTAPI1 _cputs(const char *);
+int _CRTAPI2 _cscanf(const char *, ...);
+int _CRTAPI1 _getch(void);
+int _CRTAPI1 _getche(void);
+int _CRTAPI1 _kbhit(void);
+int _CRTAPI1 _putch(int);
+int _CRTAPI1 _ungetch(int);
+
+#ifdef MTHREAD /* _MTHREAD_ONLY */
+int _CRTAPI1 _getch_lk(void); /* _MTHREAD_ONLY */
+int _CRTAPI1 _getche_lk(void); /* _MTHREAD_ONLY */
+int _CRTAPI1 _putch_lk(int); /* _MTHREAD_ONLY */
+int _CRTAPI1 _ungetch_lk(int); /* _MTHREAD_ONLY */
+#else /* _MTHREAD_ONLY */
+#define _getch_lk() _getch() /* _MTHREAD_ONLY */
+#define _getche_lk() _getche() /* _MTHREAD_ONLY */
+#define _putch_lk(c) _putch(c) /* _MTHREAD_ONLY */
+#define _ungetch_lk(c) _ungetch(c) /* _MTHREAD_ONLY */
+#endif /* _MTHREAD_ONLY */
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#ifndef _DOSX32_
+#define cgets _cgets
+#define cprintf _cprintf
+#define cputs _cputs
+#define cscanf _cscanf
+#define getch _getch
+#define getche _getche
+#define kbhit _kbhit
+#define putch _putch
+#define ungetch _ungetch
+#else
+char * _CRTAPI1 cgets(char *);
+int _CRTAPI2 cprintf(const char *, ...);
+int _CRTAPI1 cputs(const char *);
+int _CRTAPI2 cscanf(const char *, ...);
+int _CRTAPI1 getch(void);
+int _CRTAPI1 getche(void);
+int _CRTAPI1 kbhit(void);
+int _CRTAPI1 putch(int);
+int _CRTAPI1 ungetch(int);
+#endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_CONIO
+#endif /* _INC_CONIO */
diff --git a/private/crt32/h/cruntime.h b/private/crt32/h/cruntime.h
new file mode 100644
index 000000000..de8549076
--- /dev/null
+++ b/private/crt32/h/cruntime.h
@@ -0,0 +1,277 @@
+/***
+*cruntime.h - definitions specific to the target operating system and
+* hardware
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This header file contains widely used definitions specific to the
+* host operating system and hardware. It is included by every C source
+* and most every other header file.
+* [Internal]
+*
+*Revision History:
+* 02-27-90 GJF File created
+* 03-06-90 GJF Added register macros (REG1,...,etc.)
+* 04-11-90 GJF Set _CALLTYPE1 and _CALLTYPE4 to _stdcall.
+* 10-30-90 GJF Added macros defining variable args interface.
+* 10-31-90 GJF Added definition of _JBLEN (from setjmp.h).
+* 11-13-90 GJF Revised #ifdef-s, now use symbolic constants
+* representing target OS and target processor, with
+* #error directives for unsupported targets. Note the
+* general grouping of only OS-dependent definitions
+* followed by OS and processor dependent definitions.
+* 02-25-91 SRW Move _JBLEN definition back to setjmp.h [_WIN32_]
+* 04-09-91 PNT Added _MAC_ definitions
+* 05-09-91 GJF Restored _JBLEN definitions. Also fixed the macros
+* defining the target processor so both Stevewo's stuff
+* and mine would work.
+* 05-13-91 GJF Changed _CALLTYPE1 and _CALLTYPE4 to _cdecl for
+* Cruiser (_CRUISER_).
+* 08-28-91 JCR ANSI keywords
+* 11-01-91 GDP _JBLEN back to setjmp.h, stdarg macros back to stdarg.h
+* 03-30-92 DJM POSIX support.
+* 08-07-92 GJF Revised various macros.
+* 09-08-92 GJF Restored definition of _MIPS_ (temporarily).
+* 11-09-92 GJF Revised preprocessing conditionals for MIPS.
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 02-01-93 GJF Removed support for C6-386.
+*
+****/
+
+#ifndef _INC_CRUNTIME
+
+/*
+ * Some CRT sources have code conditioned on _MIPS_. Continue to define
+ * _MIPS_ when MIPS is defined until these sources are fixed.
+ */
+#if defined(MIPS) && !defined(_MIPS_)
+#define _MIPS_
+#endif
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+#define UNALIGNED __unaligned
+#else
+#define UNALIGNED
+#endif
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl /* User-visible CRT function */
+#define _CRTAPI2 __cdecl /* User-visible CRT function */
+#define _CRTAPI3 __cdecl /* Internal CRT function */
+#define _CRTVAR1 /* C global variable */
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+#define _CRTAPI3
+#define _CRTVAR1
+
+#endif
+
+/*
+ * Old function calling type and variable type qualifier macros
+ */
+#define _CALLTYPE1 _CRTAPI1
+#define _CALLTYPE2 _CRTAPI2
+#define _CALLTYPE4 _CRTAPI3
+#define _VARTYPE1 _CRTVAR1
+
+
+#ifdef _CRUISER_
+
+/*
+ * DEFINITIONS FOR CRUISER (AKA OS/2 2.0).
+ */
+
+#define _CALLTYPE3 __syscall /* OS API functions */
+
+
+/*
+ * Macros for register variable declarations
+ */
+
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4
+#define REG5
+#define REG6
+#define REG7
+#define REG8
+#define REG9
+
+/*
+ * Macros for varargs support
+ */
+
+#define _VA_LIST_T char *
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+/*
+ * DEFINITIONS FOR WIN32
+ */
+
+#ifdef _ALPHA_
+#define _VA_LIST_T \
+ struct { \
+ char *a0; /* pointer to first homed integer argument */ \
+ int offset; /* byte offset of next parameter */ \
+ }
+#else
+#define _VA_LIST_T char *
+#endif
+
+#if defined(_M_IX86)
+/*
+ * 386/486
+ */
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4
+#define REG5
+#define REG6
+#define REG7
+#define REG8
+#define REG9
+
+#elif defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+/*
+ * MIPS or ALPHA
+ */
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4 register
+#define REG5 register
+#define REG6 register
+#define REG7 register
+#define REG8 register
+#define REG9 register
+
+#else
+
+#error ERROR - SUPPORT FOR WIN32 NT-X86, NT-MIPS, NT-ALPHA, AND NT-PPC ONLY
+
+#endif
+
+#else /* ndef _WIN32_ */
+
+#ifdef _POSIX_
+/*
+ * DEFINITIONS FOR POSIX
+ */
+
+
+#ifdef _ALPHA_
+
+#define _VA_LIST_T \
+ struct { \
+ char *a0; /* pointer to first homed integer argument */ \
+ int offset; /* byte offset of next parameter */ \
+ }
+#else
+
+#define _VA_LIST_T char *
+
+#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
+
+#define _VA_START(ap,v) ap = (va_list)&v + _INTSIZEOF(v)
+#define _VA_ARG(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
+#define _VA_END(ap) ap = (va_list)0
+
+#endif
+
+#if defined(_M_IX86)
+/*
+ * 386/486
+ */
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4
+#define REG5
+#define REG6
+#define REG7
+#define REG8
+#define REG9
+
+#elif defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+/*
+ * MIPS/Alpha/PPC
+ */
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4 register
+#define REG5 register
+#define REG6 register
+#define REG7 register
+#define REG8 register
+#define REG9 register
+
+#else
+
+#error ERROR - SUPPORT FOR POSIX NT-X86, NT-MIPS, NT-ALPHA, AND NT_PPC ONLY
+
+#endif
+
+#else /* ndef _POSIX_ */
+
+#ifdef _MAC_
+
+/*
+ * DEFINITIONS FOR MAC.
+ */
+
+/*
+ * Macros for register variable declarations
+ */
+
+#define REG1
+#define REG2
+#define REG3
+#define REG4
+#define REG5
+#define REG6
+#define REG7
+#define REG8
+#define REG9
+
+/*
+ * Macros for varargs support
+ */
+
+#define _VA_LIST_T char *
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _POSIX_ */
+
+#endif /* _CRUISER_ */
+
+#define _INC_CRUNTIME
+#endif /* _INC_CRUNTIME */
diff --git a/private/crt32/h/cruntime.inc b/private/crt32/h/cruntime.inc
new file mode 100644
index 000000000..bbd96710b
--- /dev/null
+++ b/private/crt32/h/cruntime.inc
@@ -0,0 +1,826 @@
+;***
+;cruntime.inc - multi-model assembly macros for interfacing to HLLs
+;
+; Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; This file defines the current memory model being used.
+;
+;Revision History:
+; 08-04-88 SJM Initial version to handle all four memory models
+; in 16-bit mode and small model in 32-bit mode
+; 08-08-88 JCR Added CPDIST, ?WIN, PCS, ISHIFT/LSHIFT, OS2,
+; DNPTR/DFPTR, DFLOAT/DDOUBLE/DLDOUBLE
+; 08-16-88 PHG Added FPES, LFPES, CBI, ZXAL, ZXBL, ZXCL, ZXDL
+; 08-17-88 JCR Added CAXDX, modified FPSIZE
+; 08-20-88 PHG Added diagnostic messages, removed 386 16-bit support
+; and 386 large code/data support, added mucho comments,
+; PSS now defined as es: only if SS_NEQ_GROUP defined
+; 08-24-88 JCR Added RBXSAVE and RBXONLY for use in 'proc uses'
+; 08-25-88 JCR Added savereg macro, removed rbxsave/rbxonly...
+; 08-26-88 GJF Added codeseg (text) macro
+; 09-15-88 JCR Corrected savelist/reglist macro to go with new MASM
+; 09-21-88 WAJ Added JS*, static*, global*, and label*, and lab macros
+; 09-22-88 JCR Change 'plm' to 'pascal' in label macro
+; 09-26-88 WAJ Added PUSH16 which will do a 16 bit push in a USE32 seg.
+; 09-28-88 WAJ Added CPWORD and DPWORD
+; 09-29-88 WAJ Added JMPFAR16 macro
+; 10-12-88 JCR Made PCS evaluate to 'cs:' for 16/32 stub testbed
+; 04-24-89 JCR Added 'assume seg:flat' for 386 to avoid masm/link bug
+; 05-25-89 GJF Added APIEXT, a macro that expands to the proper extrn
+; declaration for an API function
+; 06-13-89 JCR Added 'flat:' to DCPTR and DDPTR
+; 09-15-89 JCR Added DCPTR? and DDPTR?, always use "FLAT" not "flat"
+; 10-27-92 SKS Miscellaneous minor changes for MASM 6.10 compatibility
+;
+;*******************************************************************************
+
+;==============================================================================
+;
+;Use the following defines to control processor/segment model
+;
+; -DI86 8086/8088 processor
+; -DI286 80286 processor
+; -DI386 80386 processor with 32-bit code/data segment
+;
+; -Dmem_S Small memory model (near code, near data)
+; -Dmem_M Medium memory model (far code, near data)
+; -Dmem_C Compact memory model (near code, fat data)
+; -Dmem_L Large memory model (far code, far data)
+;
+; -DSS_NEQ_DGROUP SS and DS point to different segments
+;
+; default is -DI86 -Dmem_S
+;
+;==============================================================================
+;
+;The following variables are defined by this file:
+; cpu 86, 286, or 386
+; sizeC code distance; 1 = far code, 0 = near code
+; sizeD data distance; 1 = far data, 0 = near data
+; mmodel english name of the memory model, i.e. "Medium"
+; ISIZE, LSIZE, NSIZE size of ints, longs, shorts
+; FLTSIZE, DBLSIZE, LDBLSIZE size of float, double, long double
+; NPSIZE, FPSIZE size of near/far pointers
+; CPSIZE, DPSIZE size of code/data pointers
+; ISHIFT, LSHIFT bits to shift to convert byte to int/long
+;
+;The following macros allow easy writing of combined 16/32 bit code:
+;
+; 16/32 bit registers:
+; rax, rbx, rcx, rdx, expand to native registers (rax = eax or ax)
+; rsi, rdi, rsp, rbp
+; 16/32 bit register instructions:
+; JRCXZ jump when rcx is zero
+; CBI convert byte to int (al to rax)
+; CAXDX convert rax to rax:rdx
+; ZXAL, ZXBL, ZXCL, ZXDL zero extend al,bl,cl,dl to rax,rbx,rcx,rdx
+; Pointer instructions:
+; LPDS, LPES load data pointer with ES or DS
+; PDS, PES segment overrides when pointer loaded as above
+; PCS, PSS segment override to get at code/stack segment
+; LFPDS, LFPES load far pointer with ES or DS
+; FPDS, FPES segment overrides when pointer loaded as above
+; CPTR data type of code pointer
+; CPDIST distance of code (near/far)
+; DNPTR, DFPTR define near/far pointer
+; DCPTR, DDPTR define code/data pointer
+; DCPTR?, DDPTR? define uninitialized code/data pointer
+; CPWORD, DPWORD data type of code or data pointer
+; Numeric type instructions:
+; IWORD, LWORD, SWORD data type of int, long, short
+; DINT, DLONG, DSHORT define int, long, short
+; DFLOAT, DDOUBLE, DLDOUBLE define float, double, long double
+; Offsets:
+; codeoffset, dataoffset offsets from code and data segments
+; API calls:
+; APIDIST distance of API calls (near/far)
+; APIEXT ApiName extrn declaration for an API function
+;
+;The following utility macros are provided:
+; codeseg define/declare code segment
+; error <msg> stop assembly with message
+; display <msg> display a message, unless QUIET defined
+; savelist [<reg> ...] init list of regs to be save by 'proc uses'
+; _if cond <instruction> assemble instruction only if cond is TRUE
+; _ife cond <instruction> assemble instruction only if cond is FALSE
+; _ifd symbol <instruction> assemble instruction only if symbol defined
+; _ifnd symbol <instruction> assemble instruction only if symbol not defined
+;
+; lab LabelName assembles to "LabelName:" If DEBUG is defined
+; LabelName is made public
+;
+; JS* (ex. JSE,JSZ,JSB ...) assemble to "je short","jz short","jb short"
+;
+; Cmacro look alikes
+; static* Name, InitialValue, Repeat defines a static variable of type *
+; global* Name, InitialValue, Repeat defines a global variable of type *
+; label* Name, {PUBLIC,PASCAL,C} defines a label of type *
+;
+; PUSH16 SegmentReg pushes 16 bits in a use32 segment
+; JMPFAR16 label will do a far 16:16 jmp from a use32 segment
+;
+;==============================================================================
+
+; error <msg> - Output message and generate error
+
+error MACRO msg
+if2 ;; only on pass 2 can we generate errors
+ %out **********************************************************
+ %out *** E r r o r -- msg
+ %out **********************************************************
+ .err
+endif
+ ENDM
+
+; display msg - Output message unless QUIET defined
+
+display MACRO msg
+ifndef QUIET ;; only when quiet flag not set
+if1 ;; and on pass 1, then display message
+ %out msg
+endif
+endif
+ ENDM
+
+; One line conditionals:
+; here we create the capability of writing code lines like
+;
+; _if sizeD <push ds> as opposed to if sizeD
+; push ds
+; endif
+
+_if MACRO cond,text
+ if cond
+ text
+ endif
+ ENDM
+
+_ife MACRO cond,text
+ ife cond
+ text
+ endif
+ ENDM
+
+_ifd MACRO cond,text
+ ifdef cond
+ text
+ endif
+ ENDM
+
+_ifnd MACRO cond,text
+ ifndef cond
+ text
+ endif
+ ENDM
+
+; set windows flag to 0
+
+ ?WIN equ 0 ; disable windows-specific code
+
+; check for MTHREAD, requires 286 or greater processor
+
+ifdef MTHREAD
+ifndef I386
+ifndef I286
+; MTHREAD implies 286 processor
+display <Multi-thread specified - assuming 80286 processor>
+I286 equ <>
+endif
+endif
+endif
+
+; Process memory-model arguments
+
+ifdef mem_M
+ ; Medium model
+ sizeC equ 1
+ sizeD equ 0
+ mmodel equ <Medium>
+elseifdef mem_C
+ ; Compact model
+ sizeC equ 0
+ sizeD equ 1
+ mmodel equ <Compact>
+elseifdef mem_L
+ ; Large model
+ sizeC equ 1
+ sizeD equ 1
+ mmodel equ <Large>
+else
+ ; Small model - default
+ sizeC equ 0
+ sizeD equ 0
+ mmodel equ <Small>
+endif
+
+; Process processor arguments
+
+ifdef I286
+ display <Processor: 80286>
+ cpu equ 286
+ .286
+elseifdef I386
+ display <Processor: 80386>
+ cpu equ 386
+ OS2 equ <> ; Define "OS2" since 386 can only run on that OS
+ .386
+else
+ display <Processor: 8086/8088>
+ cpu equ 86
+ .8086
+endif
+
+; 386 32-bit checking. Currently we are only expecting small model
+; 32 bit segments, so we make a few checks to be sure nothing is
+; incorrectly being defined.
+
+ifdef I386
+ if sizeC or sizeD
+ error <Must use Small memory model for 386 version.>
+ endif
+
+ ifdef _LOAD_DGROUP
+ error <No loading DGROUP in 386 version.>
+ endif
+
+ ifdef SS_NEQ_DGROUP
+ error <SS always equals DGROUP in 386 version.>
+ endif
+endif
+
+; Set memory model
+
+% display <Memory model: mmodel>
+% .model mmodel, C
+
+;
+; *** Temporary Workaround ***
+; Currently, MASM will not recognize the 'FLAT' keyword unless it previously
+; appears in an 'assume' statement. Presumably, when the '.model FLAT' feature
+; is implemented, this will go away. [Use 'gs:' since we never use that
+; segment register.
+;
+
+ifdef I386
+ ; ensure that MASM recognizes 'FLAT'
+ assume gs:FLAT
+endif
+
+
+; Define registers:
+; Instead of using the "word" registers directly, we will use a set of
+; text equates. This will allow you to use the native word size instead of
+; hard coded to 16 bit words. We also have some instruction equates for
+; instruction with the register type hard coded in.
+
+ifdef I386
+
+ rax equ <eax>
+ rbx equ <ebx>
+ rcx equ <ecx>
+ rdx equ <edx>
+ rdi equ <edi>
+ rsi equ <esi>
+ rbp equ <ebp>
+ rsp equ <esp>
+
+ JRCXZ equ <jecxz>
+ CBI equ <movsx eax, al> ; convert byte to int (al to rax)
+ CAXDX equ <cdq> ; convert rax to rdx:rax
+ ZXAL equ <movzx eax, al> ; zero extend al
+ ZXBL equ <movzx ebx, bl> ; zero extend bl
+ ZXCL equ <movzx ecx, cl> ; zero extend cl
+ ZXDL equ <movzx edx, dl> ; zero extend dl
+
+else
+
+ rax equ <ax>
+ rbx equ <bx>
+ rcx equ <cx>
+ rdx equ <dx>
+ rdi equ <di>
+ rsi equ <si>
+ rbp equ <bp>
+ rsp equ <sp>
+
+ JRCXZ equ <jcxz>
+ CBI equ <cbw> ; convert byte to int (al to rax)
+ CAXDX equ <cwd> ; convert rax to rdx:rax
+ ZXAL equ <xor ah, ah> ; zero extend al
+ ZXBL equ <xor bh, bh> ; zero extend bl
+ ZXCL equ <xor ch, ch> ; zero extend cl
+ ZXDL equ <xor dh, dh> ; zero extend dl
+
+endif
+
+; The following equates deal with the differences in near versus
+; far data pointers, and segment overrides.
+;
+; Use LPES and PES when loading a default size pointer -- it loads
+; a 16-bit pointer register in 286 Small/Medium model,
+; a 16-bit pointer register and 16-bit segment register in 8086/286
+; Compact/Large model, and a 32-bit pointer register in 386 mode.
+;
+; Use LFPES and FPES when loading an always far pointer -- it loads a
+; 16-bit pointer register and 16-bit segment register in 8086/286,
+; all models; a 32-bit pointer register in 386 mode.
+
+if sizeD
+ LPES equ <les>
+ LPDS equ <lds>
+ PDS equ <ds:>
+ PES equ <es:>
+else
+ LPES equ <mov>
+ LPDS equ <mov>
+ PDS equ <>
+ PES equ <>
+endif
+
+ifdef I386
+ LFPES equ <mov>
+ LFPDS equ <mov>
+ FPES equ <>
+ FPDS equ <>
+else
+ LFPES equ <les>
+ LFPDS equ <lds>
+ FPES equ <es:>
+ FPDS equ <ds:>
+endif
+
+if sizeC or @WordSize eq 2
+ PCS equ <cs:> ; large code model or non-386
+else
+ IF 1 ;*** TEMP 16/32 TESTBED ***
+ PCS equ <cs:>
+ ELSE
+ PCS equ <> ; 386 small code model
+ ENDIF ;*** END TEMP CODE
+endif
+
+ifdef SS_NEQ_DGROUP
+ PSS equ <ss:> ; SS != DS
+else
+ PSS equ <> ; SS == DS
+endif
+
+; Define offset macros:
+; The 32-bit segments will not have 'groups'
+
+ifdef I386
+ codeoffset equ <offset FLAT:>
+ dataoffset equ <offset FLAT:>
+else
+ codeoffset equ <offset @code:>
+ dataoffset equ <offset DGROUP:>
+endif
+
+; The next set of equates deals with the size of SHORTS, INTS, LONGS, and
+; pointers in the 16 and 32 bit versions.
+
+ifdef I386 ;--- 32 bit segment ---
+
+ ; parameters and locals
+ IWORD equ <dword>
+ LWORD equ <dword>
+if @Version LT 600
+ SWORD equ <word>
+endif
+
+ ; static storage
+ DINT equ <dd>
+ DLONG equ <dd>
+ DSHORT equ <dw>
+
+ ; sizes for fixing SP, stepping through tables, etc.
+ ISIZE equ 4
+ LSIZE equ 4
+ SSIZE equ 2
+ NPSIZE equ 4
+ FPSIZE equ 4
+
+ ; bit shift count to convert byte cnt/ptr to int/long cnt/ptr
+ ISHIFT equ 2 ; byte-to-int shift count
+ LSHIFT equ 2 ; byte-to-long shift count
+
+ ; sizes dependent upon memory model. dq -vs- df is not yet clear
+ DNPTR equ <dd> ; near pointer
+ DFPTR equ <dd> ; far pointer
+
+ DCPTR equ <dd offset FLAT:>; 32 bit offset only
+ DCPTR? equ <dd> ; No seg override for uninitialized values
+ CPSIZE equ 4
+ CPDIST equ <near> ; code pointers are near
+ CPTR equ <near ptr>
+
+ DDPTR equ <dd offset FLAT:>
+ DDPTR? equ <dd>
+ DPSIZE equ 4
+
+ CPWORD equ <dword> ; code pointers are dwords
+ DPWORD equ <dword> ; data pointers are dwords
+
+ APIDIST equ <near> ; all API calls are NEAR in the 32 bit model
+
+; macro to declare API functions
+EXTAPI macro apiname
+ extrn pascal apiname:near
+endm
+
+else ;--- 16-bit segment ---
+
+ ; parameters and locals
+ IWORD equ <word>
+ LWORD equ <dword>
+if @Version LT 600
+ SWORD equ <word>
+endif
+
+ ; static storage
+ DINT equ <dw>
+ DLONG equ <dd>
+ DSHORT equ <dw>
+
+ ; sizes for fixing SP, stepping through tables, etc
+ ISIZE equ 2
+ LSIZE equ 4
+ SSIZE equ 2
+ NPSIZE equ 2
+ FPSIZE equ 4
+
+ ; bit shift count to convert byte cnt/ptr to int/long cnt/ptr
+ ISHIFT equ 1 ; byte-to-int shift count
+ LSHIFT equ 2 ; byte-to-long shift count
+
+ ; sizes dependent upon memory model
+ DNPTR equ <dw> ; near pointer
+ DFPTR equ <dd> ; far pointer
+
+ if sizeC
+ DCPTR equ <dd> ; 16 bit segment and 16 bit offset
+ DCPTR? equ <dd>
+ CPSIZE equ 4
+ CPDIST equ <far> ; code pointers are far
+ CPTR equ <far ptr>
+ CPWORD equ <dword> ; code pointers are dwords
+ else
+ DCPTR equ <dw> ; 16 bit offset only
+ DCPTR? equ <dw>
+ CPSIZE equ 2
+ CPDIST equ <near> ; code pointers are near
+ CPTR equ <near ptr>
+ CPWORD equ <word> ; code pointers are words
+ endif
+
+ if sizeD
+ DDPTR equ <dd>
+ DDPTR? equ <dd>
+ DPSIZE equ 4
+ DPWORD equ <dword> ; data pointers are dwords
+ else
+ DDPTR equ <dw>
+ DDPTR? equ <dw>
+ DPSIZE equ 2
+ DPWORD equ <word> ; data pointers are words
+ endif
+
+ APIDIST equ <far> ; API calls are FAR in 16 bit model
+
+; macro to declare API functions
+EXTAPI macro apiname
+ extrn pascal apiname:far
+endm
+
+endif ; --- 16/32 segment ---
+
+; Float/double definitions
+; (currently the same for 16- and 32-bit segments)
+
+FLTSIZE equ 4 ; float
+DBLSIZE equ 8 ; double
+LDBLSIZE equ 10 ; long double
+
+DFLOAT equ <dd>
+DDOUBLE equ <dq>
+DLDOUBLE equ <dt>
+
+;
+; savelist - Generate a list of regs to be saved by the proc 'uses' option.
+;
+; Input:
+; reg1, reg2, reg3, reg4 = registers to be saved across function
+; Output:
+; reglist = text string of registers that can be passed to the 'uses'
+; option on the 'proc' command.
+;
+
+savelist MACRO reg1, reg2, reg3, reg4
+ local ws, listsize
+ ws catstr < > ; whitespace char
+
+ IFNDEF I386
+ rbx equ <> ; 8086/286 don't save rbx
+ ENDIF
+
+ IFNB <reg4>
+ reglist catstr reg1, ws, reg2, ws, reg3, ws, reg4
+ ELSEIFNB <reg3>
+ reglist catstr reg1, ws, reg2, ws, reg3, ws
+ ELSEIFNB <reg2>
+ reglist catstr reg1, ws, reg2, ws, ws
+ ELSEIFNB <reg1>
+ reglist catstr reg1, ws, ws, ws
+ ELSE
+ reglist catstr <>
+ ENDIF
+
+ listsize sizestr reglist ; size of register list
+
+ IF listsize LE 3 ; if list is only the 3 ws chars...
+ reglist catstr <>
+ ENDIF
+
+ IFNDEF I386
+ rbx equ <bx> ; restore rbx
+ ENDIF
+
+ ENDM ; savelist
+
+;
+; codeseg - Define/declare the standard code segment. Maps to the proper
+; form of the .code directive.
+;
+; Input:
+;
+; Output:
+; .code _TEXT ; for large code models
+; .code ; for small code models
+; assume cs:FLAT ; for 386
+; assume ds:FLAT ; for 386
+; assume es:FLAT ; for 386
+; assume ss:FLAT ; for 386
+;
+
+codeseg MACRO
+
+if sizeC
+ .code _TEXT
+else
+ .code
+endif
+
+ifdef I386
+if @Version LT 600
+ assume cs:FLAT
+endif ;@Version LT 600
+ assume ds:FLAT
+ assume es:FLAT
+ assume ss:FLAT
+endif
+
+ ENDM
+
+;***************************************************************
+;*
+;* Debug lab macro
+;*
+;***************************************************************
+
+lab macro name
+ifdef DEBUG
+ public pascal name ;; define label public for Symdeb
+endif
+name:
+ endm
+
+
+;***************************************************************
+;*
+;* Conditional jump short macros
+;*
+;***************************************************************
+
+
+ irp x,<Z,NZ,E,NE,S,NS,C,NC,P,NP,PE,PO,A,AE,B,BE,NB,G,GE,L,LE>
+JS&x equ <j&x short>
+ endm
+
+
+;***************************************************************
+;*
+;* Global data definition macros
+;*
+;* Usage:
+;* globalI Name, InitialValue, Repeat
+;*
+;***************************************************************
+
+
+MakeGlobal macro suffix, DataType ;; makes all of the global* macros
+
+global&suffix macro name, data, rep
+public name
+ifb <rep>
+ _repeat = 1
+else
+ _repeat = (rep)
+endif
+
+name &DataType _repeat dup( data )
+ endm
+
+ endm
+
+
+ MakeGlobal T, dt ; globalT
+ MakeGlobal Q, dq ; globalQ
+ MakeGlobal D, dd ; globalD
+ MakeGlobal W, dw ; globalW
+ MakeGlobal B, db ; globalB
+
+% MakeGlobal I, <DINT> ; globalI
+
+% MakeGlobal DP, <DDPTR> ; globalDP
+% MakeGlobal CP, <DCPTR> ; globalCP
+% MakeGlobal FP, <DFPTR> ; globalFP
+% MakeGlobal NP, <DNPTR> ; globalNP
+
+
+
+;***************************************************************
+;*
+;* Static data definition macros
+;*
+;* Usage:
+;* staticI Name, InitialValue, Repeat
+;*
+;***************************************************************
+
+
+MakeStatic macro suffix, DataType ;; makes all of the static* macros
+
+static&suffix macro name, data, rep
+
+ifdef DEBUG
+ public pascal name ;; make statics public if DEBUG
+endif
+
+ifb <rep>
+ _repeat = 1
+else
+ _repeat = (rep)
+endif
+
+name &DataType _repeat dup( data )
+ endm
+
+ endm
+
+
+ MakeStatic T, dt ; staticT
+ MakeStatic Q, dq ; staticQ
+ MakeStatic D, dd ; staticD
+ MakeStatic W, dw ; staticW
+ MakeStatic B, db ; staticB
+
+% MakeStatic I, <DINT> ; staticI
+
+% MakeStatic DP, <DDPTR> ; staticDP
+% MakeStatic CP, <DCPTR> ; staticCP
+% MakeStatic FP, <DFPTR> ; staticFP
+% MakeStatic NP, <DNPTR> ; staticNP
+
+;***************************************************************
+;*
+;* Label definition macros
+;*
+;***************************************************************
+;*
+;* Label definition macros
+;*
+;* Usage:
+;* labelI Name, {PUBLIC, PASCAL, C}
+;*
+;***************************************************************
+
+__MakePublic macro name, option ;; decides if a label should be
+ifidni <option>, <PUBLIC> ;; made public
+ public name
+elseifidni <option>, <PASCAL>
+ public pascal name
+elseifidni <option>, <C>
+ public C name
+elseifb <option>
+ ifdef DEBUG
+ public pascal name ;; make public if DEBUG
+ endif
+endif
+ endm
+
+
+if @Version GE 600
+
+MakeLabel macro suffix, LabelType ;; makes all of the label* macros
+
+%@CatStr(<label>,<suffix>) macro name, option
+ __MakePublic <name>,<option>
+name label &LabelType
+ endm
+
+ endm
+
+else ;!(@Version GE 600)
+
+MakeLabel macro suffix, LabelType ;; makes all of the label* macros
+
+label&suffix macro name, option
+ __MakePublic <name>,<option>
+name label &LabelType
+ endm
+
+ endm
+
+endif ;!(@Version GE 600)
+
+
+ MakeLabel T, tbyte ; make labelT
+ MakeLabel Q, qword ; make labelQ
+ MakeLabel D, dword ; make labelD
+ MakeLabel W, word ; make labelW
+ MakeLabel B, byte ; make labelB
+
+ MakeLabel P, proc ; make labelP
+ MakeLabel FP, far ; make labelFP
+ MakeLabel NP, near ; make labelNP
+
+% MakeLabel I, IWORD ; make labelI
+
+
+labelDP macro name, option ;; labelDP
+ __MakePublic <name>,<option>
+ifdef I386
+ if sizeD
+ name label fword
+ else
+ name label dword
+ endif
+else ;not I386
+ if sizeD
+ name label dword
+ else
+ name label word
+ endif
+endif ;not I386
+ endm
+
+labelCP macro name, option ;; labelCP
+ __MakePublic <name>,<option>
+ifdef I386
+ if sizeC
+ name label fword
+ else
+ name label dword
+ endif
+else ;not I386
+ if sizeC
+ name label dword
+ else
+ name label word
+ endif
+endif ;not I386
+ endm
+
+
+;*
+;* PUSH16 SegReg - pushes 16 bits in a use32 segment
+;*
+
+PUSH16 macro SegReg
+
+ifdef I386
+ nop
+ db 66h ; operand size over-ride
+endif ; I386
+
+ push SegReg
+ endm
+
+
+;*
+;* JMPFAR16 label - jmps far from a use32 to a use16 segment
+;*
+
+JMPFAR16 macro label
+
+ifndef I386
+ error <JMPFAR16 can only be used in a use32 code segment>
+endif ;I386
+
+ nop
+ db 66h ;; operand size over-ride
+ db 0eah ;; jmp far immediate op code
+ dw offset label
+ dw seg label
+ endm
diff --git a/private/crt32/h/ctime.h b/private/crt32/h/ctime.h
new file mode 100644
index 000000000..c09abf17c
--- /dev/null
+++ b/private/crt32/h/ctime.h
@@ -0,0 +1,41 @@
+/***
+*ctime.h - constant for dates and times
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Include file used by the ctime routines containing definitions of
+* various constants used in determining dates and times.
+* [Internal]
+*
+*Revision History:
+* 03-??-84 RLB written
+* 05-??-84 DFW split out the constant from each routine into this file
+* 07-27-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 02-28-90 GJF Added #ifndef _INC_CTIME stuff.
+* 03-29-93 GJF Revised constants.
+*
+****/
+
+#ifndef _INC_CTIME
+
+#define _DAY_SEC (24L * 60L * 60L) /* secs in a day */
+
+#define _YEAR_SEC (365L * _DAY_SEC) /* secs in a year */
+
+#define _FOUR_YEAR_SEC (1461L * _DAY_SEC) /* secs in a 4 year interval */
+
+#define _DEC_SEC 315532800L /* secs in 1970-1979 */
+
+#define _BASE_YEAR 70L /* 1970 is the base year */
+
+#define _BASE_DOW 4 /* 01-01-70 was a Thursday */
+
+#define _LEAP_YEAR_ADJUST 17L /* Leap years 1900 - 1970 */
+
+#define _MAX_YEAR 138L /* 2038 is the max year */
+
+
+#define _INC_CTIME
+#endif /* _INC_CTIME */
diff --git a/private/crt32/h/ctype.h b/private/crt32/h/ctype.h
new file mode 100644
index 000000000..d4b746d52
--- /dev/null
+++ b/private/crt32/h/ctype.h
@@ -0,0 +1,321 @@
+/***
+*ctype.h - character conversion macros and ctype macros
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines macros for character classification/conversion.
+* [ANSI/System V]
+*
+*Revision History:
+* 07-31-87 PHG changed (unsigned char)(c) to (0xFF & (c)) to
+* suppress -W2 warning
+* 08-07-87 SKS Removed (0xFF & (c)) -- is????() functions take an (int)
+* 12-18-87 JCR Added _FAR_ to declarations
+* 01-19-87 JCR DLL routines
+* 02-10-88 JCR Cleaned up white space
+* 08-19-88 GJF Modify to also work for the 386 (small model only)
+* 12-08-88 JCR DLL now access _ctype directly (removed DLL routines)
+* 03-26-89 GJF Brought into sync with CRT\H\CTYPE.H
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 07-28-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright, removed dummy args from prototypes
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 02-28-90 GJF Added #ifndef _INC_CTYPE and #include <cruntime.h>
+* stuff. Also, removed #ifndef _CTYPE_DEFINED stuff and
+* some other (now) useless preprocessor directives.
+* 03-22-90 GJF Replaced _cdecl with _CALLTYPE1 in prototypes and
+* with _VARTYPE1 in variable declarations.
+* 01-16-91 GJF ANSI naming.
+* 03-21-91 KRS Added isleadbyte macro.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 10-11-91 ETC All under _INTL: isleadbyte/isw* macros, prototypes;
+* new is* macros; add wchar_t typedef; some intl defines.
+* 12-17-91 ETC ctype width now independent of _INTL, leave original
+* short ctype table under _NEWCTYPETABLE.
+* 01-22-92 GJF Changed definition of _ctype for users of crtdll.dll.
+* 04-06-92 KRS Changes for new ISO proposal.
+* 08-07-92 GJF Function calling type and variable type macros.
+* 10-26-92 GJF Fixed _pctype and _pwctype for crtdll.
+* 01-19-93 CFW Move to _NEWCTYPETABLE, remove switch.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 02-17-93 CFW Removed incorrect UNDONE comment and unused code.
+* 02-18-93 CFW Clean up common _WCTYPE_DEFINED section.
+* 03-25-93 CFW _toupper\_tolower now defined when _INTL.
+* 03-30-93 CFW is* functions now use MB_CUR_MAX, MB_CUR_MAX defined.
+* 05-05-93 CFW Change is_wctype to iswctype as per ISO.
+* 06-26-93 CFW Remove is_wctype macro.
+* 10-14-93 SRW Add support for _CTYPE_DISABLE_MACROS symbol
+*
+****/
+
+#ifndef _INC_CTYPE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+#ifndef _WCTYPE_T_DEFINED
+typedef wchar_t wint_t;
+typedef wchar_t wctype_t;
+#define _WCTYPE_T_DEFINED
+#endif
+
+#ifndef WEOF
+#define WEOF (wint_t)(0xFFFF)
+#endif
+
+/*
+ * This declaration allows the user access to the ctype look-up
+ * array _ctype defined in ctype.obj by simply including ctype.h
+ */
+#ifndef _CTYPE_DISABLE_MACROS
+#ifdef _DLL
+
+extern unsigned short * _CRTVAR1 _ctype;
+
+#define _pctype (*_pctype_dll)
+extern unsigned short **_pctype_dll;
+
+#define _pwctype (*_pwctype_dll)
+extern unsigned short **_pwctype_dll;
+
+#else /* _DLL */
+
+#ifdef CRTDLL
+#define _pctype _pctype_dll
+#define _pwctype _pwctype_dll
+#endif /* CRTDLL */
+
+extern unsigned short _CRTVAR1 _ctype[];
+extern unsigned short *_pctype;
+extern wctype_t *_pwctype;
+
+#endif /* _DLL */
+#endif /* _CTYPE_DISABLE_MACROS */
+
+/* set bit masks for the possible character types */
+
+#define _UPPER 0x1 /* upper case letter */
+#define _LOWER 0x2 /* lower case letter */
+#define _DIGIT 0x4 /* digit[0-9] */
+#define _SPACE 0x8 /* tab, carriage return, newline, */
+ /* vertical tab or form feed */
+#define _PUNCT 0x10 /* punctuation character */
+#define _CONTROL 0x20 /* control character */
+#define _BLANK 0x40 /* space char */
+#define _HEX 0x80 /* hexadecimal digit */
+
+#ifdef _INTL
+#define _LEADBYTE 0x8000 /* multibyte leadbyte */
+#define _ALPHA (0x0100|_UPPER|_LOWER) /* alphabetic character */
+#else
+#define _ALPHA (_UPPER|_LOWER) /* alphabetic character */
+#endif
+
+
+/* character classification function prototypes */
+
+#ifndef _CTYPE_DEFINED
+int _CRTAPI1 isalpha(int);
+int _CRTAPI1 isupper(int);
+int _CRTAPI1 islower(int);
+int _CRTAPI1 isdigit(int);
+int _CRTAPI1 isxdigit(int);
+int _CRTAPI1 isspace(int);
+int _CRTAPI1 ispunct(int);
+int _CRTAPI1 isalnum(int);
+int _CRTAPI1 isprint(int);
+int _CRTAPI1 isgraph(int);
+int _CRTAPI1 iscntrl(int);
+int _CRTAPI1 toupper(int);
+int _CRTAPI1 tolower(int);
+int _CRTAPI1 _tolower(int);
+int _CRTAPI1 _toupper(int);
+int _CRTAPI1 __isascii(int);
+int _CRTAPI1 __toascii(int);
+int _CRTAPI1 __iscsymf(int);
+int _CRTAPI1 __iscsym(int);
+#define _CTYPE_DEFINED
+#endif
+
+#ifndef _WCTYPE_DEFINED
+
+/* character classification function prototypes */
+/* also defined in wchar.h */
+
+int _CRTAPI1 iswalpha(wint_t);
+int _CRTAPI1 iswupper(wint_t);
+int _CRTAPI1 iswlower(wint_t);
+int _CRTAPI1 iswdigit(wint_t);
+int _CRTAPI1 iswxdigit(wint_t);
+int _CRTAPI1 iswspace(wint_t);
+int _CRTAPI1 iswpunct(wint_t);
+int _CRTAPI1 iswalnum(wint_t);
+int _CRTAPI1 iswprint(wint_t);
+int _CRTAPI1 iswgraph(wint_t);
+int _CRTAPI1 iswcntrl(wint_t);
+int _CRTAPI1 iswascii(wint_t);
+int _CRTAPI1 isleadbyte(int);
+
+wchar_t _CRTAPI1 towupper(wchar_t);
+wchar_t _CRTAPI1 towlower(wchar_t);
+
+int _CRTAPI1 iswctype(wint_t, wctype_t);
+
+#ifdef _INTL
+int _CRTAPI1 _isctype(int, int);
+#endif /* _INTL */
+
+#define _WCTYPE_DEFINED
+#endif
+
+/* the character classification macro definitions */
+
+#ifndef _CTYPE_DISABLE_MACROS
+
+#ifndef _INTL
+#define isalpha(_c) ( (_ctype+1)[_c] & (_UPPER|_LOWER) )
+#define isupper(_c) ( (_ctype+1)[_c] & _UPPER )
+#define islower(_c) ( (_ctype+1)[_c] & _LOWER )
+#define isdigit(_c) ( (_ctype+1)[_c] & _DIGIT )
+#define isxdigit(_c) ( (_ctype+1)[_c] & _HEX )
+#define isspace(_c) ( (_ctype+1)[_c] & _SPACE )
+#define ispunct(_c) ( (_ctype+1)[_c] & _PUNCT )
+#define isalnum(_c) ( (_ctype+1)[_c] & (_UPPER|_LOWER|_DIGIT) )
+#define isprint(_c) ( (_ctype+1)[_c] & (_BLANK|_PUNCT|_UPPER|_LOWER|_DIGIT) )
+#define isgraph(_c) ( (_ctype+1)[_c] & (_PUNCT|_UPPER|_LOWER|_DIGIT) )
+#define iscntrl(_c) ( (_ctype+1)[_c] & _CONTROL )
+
+#if !__STDC__
+#define toupper(_c) ( (islower(_c)) ? _toupper(_c) : (_c) )
+#define tolower(_c) ( (isupper(_c)) ? _tolower(_c) : (_c) )
+#endif /* __STDC__ */
+
+#else
+
+#ifndef _MB_CUR_MAX_DEFINED
+/* max mb-len for current locale */
+/* also defined in stdlib.h */
+#ifdef _DLL
+#define __mb_cur_max (*__mb_cur_max_dll)
+#define MB_CUR_MAX (*__mb_cur_max_dll)
+extern unsigned short *__mb_cur_max_dll;
+#else
+#ifdef CRTDLL
+#define __mb_cur_max __mb_cur_max_dll
+#endif
+#define MB_CUR_MAX __mb_cur_max
+extern unsigned short __mb_cur_max;
+#endif
+#define _MB_CUR_MAX_DEFINED
+#endif /* _MB_CUR_MAX_DEFINED */
+
+#define isalpha(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_ALPHA) : _pctype[_c] & _ALPHA)
+#define isupper(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_UPPER) : _pctype[_c] & _UPPER)
+#define islower(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_LOWER) : _pctype[_c] & _LOWER)
+#define isdigit(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_DIGIT) : _pctype[_c] & _DIGIT)
+#define isxdigit(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_HEX) : _pctype[_c] & _HEX)
+#define isspace(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_SPACE) : _pctype[_c] & _SPACE)
+#define ispunct(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_PUNCT) : _pctype[_c] & _PUNCT)
+#define isalnum(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_ALPHA|_DIGIT) : _pctype[_c] & (_ALPHA|_DIGIT))
+#define isprint(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_BLANK|_PUNCT|_ALPHA|_DIGIT) : _pctype[_c] & (_BLANK|_PUNCT|_ALPHA|_DIGIT))
+#define isgraph(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_PUNCT|_ALPHA|_DIGIT) : _pctype[_c] & (_PUNCT|_ALPHA|_DIGIT))
+#define iscntrl(_c) (MB_CUR_MAX > 1 ? _isctype(_c,_CONTROL) : _pctype[_c] & _CONTROL)
+#endif /* _INTL */
+
+#define _tolower(_c) ( (_c)-'A'+'a' )
+#define _toupper(_c) ( (_c)-'a'+'A' )
+
+#define __isascii(_c) ( (unsigned)(_c) < 0x80 )
+#define __toascii(_c) ( (_c) & 0x7f )
+
+#define iswalpha(_c) ( iswctype(_c,_ALPHA) )
+#define iswupper(_c) ( iswctype(_c,_UPPER) )
+#define iswlower(_c) ( iswctype(_c,_LOWER) )
+#define iswdigit(_c) ( iswctype(_c,_DIGIT) )
+#define iswxdigit(_c) ( iswctype(_c,_HEX) )
+#define iswspace(_c) ( iswctype(_c,_SPACE) )
+#define iswpunct(_c) ( iswctype(_c,_PUNCT) )
+#define iswalnum(_c) ( iswctype(_c,_ALPHA|_DIGIT) )
+#define iswprint(_c) ( iswctype(_c,_BLANK|_PUNCT|_ALPHA|_DIGIT) )
+#define iswgraph(_c) ( iswctype(_c,_PUNCT|_ALPHA|_DIGIT) )
+#define iswcntrl(_c) ( iswctype(_c,_CONTROL) )
+#define iswascii(_c) ( (unsigned)(_c) < 0x80 )
+
+#ifdef _INTL
+/* note: MS-specific routine, may evaluate its arguments more than once */
+#define isleadbyte(_c) ((_c) < 256 ? _pctype[_c] & _LEADBYTE : 0)
+#else
+#define isleadbyte(_c) (0)
+#endif /* _INTL */
+
+
+/* MS C version 2.0 extended ctype macros */
+
+#define __iscsymf(_c) (isalpha(_c) || ((_c) == '_'))
+#define __iscsym(_c) (isalnum(_c) || ((_c) == '_'))
+
+#endif /* _CTYPE_DISABLE_MACROS */
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#ifndef _DOSX32_
+#define isascii __isascii
+#define toascii __toascii
+#define iscsymf __iscsymf
+#define iscsym __iscsym
+#else
+#ifndef _CTYPE_DEFINED
+int _CRTAPI1 isascii(int);
+int _CRTAPI1 toascii(int);
+int _CRTAPI1 iscsymf(int);
+int _CRTAPI1 iscsym(int);
+#else
+#define isascii __isascii
+#define toascii __toascii
+#define iscsymf __iscsymf
+#define iscsym __iscsym
+#endif
+#endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_CTYPE
+#endif /* _INC_CTYPE */
diff --git a/private/crt32/h/cvt.h b/private/crt32/h/cvt.h
new file mode 100644
index 000000000..6b6014658
--- /dev/null
+++ b/private/crt32/h/cvt.h
@@ -0,0 +1,41 @@
+/***
+*cvt.h - definitions used by formatting routines
+*
+* Copyright (c) 1985-1990, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* cvt.h contains definitions used by the formatting routines [efg]cvt and
+* _output and _input. The value of CVTBUFSIZE is used to dimension
+* arrays used to hold the maximum size double precision number plus some
+* slop to aid in formatting.
+* [Internal]
+*
+*Revision History:
+* 12-11-87 JCR Added "_loadds" functionality
+* 02-10-88 JCR Cleaned up white space
+* 07-28-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 02-28-90 GJF Added #ifndef _INC_CVT stuff. Also, removed some
+* (now) useless preprocessor directives.
+*
+****/
+
+#ifndef _INC_CVT
+
+#define SHORT 1
+#define LONG 2
+#define USIGN 4
+#define NEAR 8
+#define FAR 16
+
+#define OCTAL 8
+#define DECIMAL 10
+#define HEX 16
+
+#define MUL10(x) ( (((x)<<2) + (x))<<1 )
+#define ISDIGIT(c) ( ((c) >= '0') && ((c) <= '9') )
+
+#define CVTBUFSIZE (309+40) /* # of digits in max. dp value + slop */
+
+#define _INC_CVT
+#endif /* _INC_CVT */
diff --git a/private/crt32/h/defsects.inc b/private/crt32/h/defsects.inc
new file mode 100644
index 000000000..a736b02a1
--- /dev/null
+++ b/private/crt32/h/defsects.inc
@@ -0,0 +1,58 @@
+;***
+;defsects.inc - defines sections.
+;
+; Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; This file defines sections for the C and C++ libs.
+;
+; NOTE: As needed, special "CRT" sections can be added into the existing
+; init/term tables. These will be for our use only -- users who put
+; stuff in here do so at their own risk.
+;
+;Revision History:
+; 03-19-92 SKS Loosely based on the 16-bit include file DEFSEGS.INC
+; 08-06-92 SKS Changed these section names from X[ICPT]$[ACLUXZ] to
+; .CRT$X[ICPT][ACLUXZ] to avoid creating too many sections
+; Also, sections are no longer defined in groups. That was
+; for use with OMF type objects where order of appearance
+; is important. With COFF, sorting is done by section name.
+;
+;******************************************************************************
+
+;*******
+;*
+;* beginSection - a macro for declaring and beginning a section
+;*
+;* endSection - a macro for ending a previously declared section
+;*
+;*******
+
+beginSection MACRO SectName
+.CRT$&SectName SEGMENT DWORD PUBLIC 'DATA'
+ ENDM
+
+endSection MACRO SectName
+.CRT$&SectName ENDS
+ ENDM
+
+; XIA Begin C Initializer Sections
+; XIC Microsoft Reserved
+; XIU User
+; XIZ End C Initializer Sections
+;
+; XCA Begin C++ Constructor Sections
+; XCC Compiler (MS)
+; XCL Library
+; XCU User
+; XCZ End C++ Constructor Sections
+;
+; XPA Begin C Pre-Terminator Sections
+; XPU User
+; XPX Microsoft Reserved
+; XPZ End C Pre-Terminator Sections
+;
+; XTA Begin C Pre-Terminator Sections
+; XTU User
+; XTX Microsoft Reserved
+; XTZ End C Pre-Terminator Sections
diff --git a/private/crt32/h/direct.h b/private/crt32/h/direct.h
new file mode 100644
index 000000000..90b82c7f9
--- /dev/null
+++ b/private/crt32/h/direct.h
@@ -0,0 +1,134 @@
+/***
+*direct.h - function declarations for directory handling/creation
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This include file contains the function declarations for the library
+* functions related to directory handling and creation.
+*
+*Revision History:
+* 12/11/87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 08-22-88 GJF Modified to also work with the 386 (small model only)
+* 01-31-89 JCR Added _chdrive, _fullpath, _getdrive, _getdcwd
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 07-28-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-17-89 GJF Moved _fullpath prototype to stdlib.h. Added const
+* attrib. to arg types for chdir, mkdir, rmdir
+* 02-28-90 GJF Added #ifndef _INC_DIRECT and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 or _CALLTYPE2 in
+* prototypes.
+* 03-30-90 GJF Now all are _CALLTYPE1.
+* 01-17-91 GJF ANSI naming.
+* 08-20-91 JCR C++ and ANSI naming
+* 08-26-91 BWM Added _diskfree_t, _getdiskfree, and
+* 09-26-91 JCR Non-ANSI alias is for getcwd, not getDcwd (oops)
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 04-29-92 GJF Added _getdcwd_lk for Win32.
+* 08-07-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_DIRECT
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+/* _getdiskfree structure for _getdiskfree() */
+
+#ifndef _DISKFREE_T_DEFINED
+
+struct _diskfree_t {
+ unsigned total_clusters;
+ unsigned avail_clusters;
+ unsigned sectors_per_cluster;
+ unsigned bytes_per_sector;
+ };
+
+#define _DISKFREE_T_DEFINED
+
+#endif
+
+/* function prototypes */
+
+int _CRTAPI1 _chdir(const char *);
+int _CRTAPI1 _chdrive(int);
+char * _CRTAPI1 _getcwd(char *, int);
+char * _CRTAPI1 _getdcwd(int, char *, int);
+int _CRTAPI1 _getdrive(void);
+int _CRTAPI1 _mkdir(const char *);
+int _CRTAPI1 _rmdir(const char *);
+unsigned _CRTAPI1 _getdiskfree(unsigned, struct _diskfree_t *);
+unsigned long _CRTAPI1 _getdrives(void);
+
+
+#ifdef MTHREAD /* _MTHREAD_ONLY */
+char * _CRTAPI1 _getdcwd_lk(int, char *, int); /* _MTHREAD_ONLY */
+#else /* _MTHREAD_ONLY */
+#define _getdcwd_lk(drv, buf, len) _getdcwd(drv, buf, len) /* _MTHREAD_ONLY */
+#endif /* _MTHREAD_ONLY */
+
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#ifndef _DOSX32_
+#define chdir _chdir
+#define getcwd _getcwd
+#define mkdir _mkdir
+#define rmdir _rmdir
+#else
+int _CRTAPI1 chdir(const char *);
+char * _CRTAPI1 getcwd(int, char *, int);
+int _CRTAPI1 mkdir(const char *);
+int _CRTAPI1 rmdir(const char *);
+#endif
+#define diskfree_t _diskfree_t
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_DIRECT
+#endif /* _INC_DIRECT */
diff --git a/private/crt32/h/dos.h b/private/crt32/h/dos.h
new file mode 100644
index 000000000..259b60d74
--- /dev/null
+++ b/private/crt32/h/dos.h
@@ -0,0 +1,222 @@
+/***
+*dos.h - definitions for MS-DOS interface routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the structs and unions used for the direct DOS interface
+* routines; includes macros to access the segment and offset
+* values of far pointers, so that they may be used by the routines; and
+* provides function prototypes for direct DOS interface functions.
+*
+*Revision History:
+* 06-11-87 JCR Added find_t
+* 06-15-87 JCR Added O_NOINHERIT
+* 06-18-87 JCR Added some DOS function prototypes
+* 06-19-87 JCR Moved O_NOINHERIT to fcntl.h
+* 06-25-87 JMB Added _HARDERR_* constants
+* 06-25-87 SKS Added diskfree_t, dosdate_t, dostime_t structures
+* 06-25-87 JCR Added _A_NORMAL, etc. constants
+* 07-17-87 JCR Added _chain_intr, also the "interrupt" type to
+* _dos_setvec and _dos_getvec.
+* 07-27-87 SKS Added several _dos_*() functions, _disable()/_enable()
+* 08-17-87 PHG Fixed bad prototype for _dos_getdiskfree()
+* 10-08-87 JCR Added _CDECL to prototypes with "interrupt" declaration
+* (needed for compiling with -Gc switch).
+* 09-27-88 JCR 386 version
+* 10-03-88 GJF Use M_I386, not I386
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 07-25-89 GJF Major cleanup. Alignment of struct fields is now
+* protected by pack pragmas. Now specific to 386.
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 02-28-90 GJF Added #ifndef _INC_DOS and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-22-90 GJF Replaced _cdecl with _CALLTYPE1 in prototype and with
+* _VARTYPE1 in variable declaration.
+* 12-28-90 SRW Added _CRUISER_ conditional around pack pragmas
+* 01-23-91 GJF Removed segread() prototype.
+* 04-04-91 GJF Added version info variables (_WIN32_).
+* 08-20-91 JCR C++ and ANSI naming
+* 08-26-91 BWM Added _peek, poke, and _getvideoaddr (_DOSX32_).
+* 08-26-91 BWM Removed _harderr constants, replaced by _seterrormode.
+* 08-26-91 BWM Removed datetime prototypes, replaced by systime functions.
+* 09-05-91 JCR Added missing #endif (bug fix), removed obsolete stuff
+* 09-16-91 BWM Fixed reversed #ifdef on screen address constants.
+* 01-22-92 GJF Fixed up definitions of global variables for build of,
+* and users of, crtdll.dll.
+* 03-30-92 DJM POSIX support.
+* 06-02-92 SKS Fix typo in DLL declaration of _osmajor
+* Add declartion of _pgmptr
+* 08-07-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_DOS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifdef _CRUISER_
+/* ensure proper alignment of struct fields */
+
+#pragma pack(4)
+#endif /* ndef _CRUISER_ */
+
+#ifdef _DOSX32_
+/* Absolute address type for _peek and _poke */
+
+#ifndef _ABSADDR_T_DEFINED
+typedef unsigned long _absaddr_t;
+#define _ABSADDR_T_DEFINED
+#endif
+#endif
+
+/* _getdiskfree structure (duplicated in DIRECT.H) */
+
+#ifndef _DISKFREE_T_DEFINED
+
+struct _diskfree_t {
+ unsigned total_clusters;
+ unsigned avail_clusters;
+ unsigned sectors_per_cluster;
+ unsigned bytes_per_sector;
+ };
+
+#define _DISKFREE_T_DEFINED
+
+#endif
+
+#ifdef _DOSX32_
+/* Region constants for _getvideoaddress() */
+
+#define _ADDR_NO_PALETTE_GRAPHICS 0x18000 /* For modes 4-6 */
+#define _ADDR_PALETTE_GRAPHICS 0x00000 /* For modes 9+ */
+#define _ADDR_COLOR_TEXT 0x18000 /* For modes 0-3 */
+#define _ADDR_MONO_TEXT 0x10000 /* For mode 7 */
+#endif
+
+#ifdef _DOSX32_
+/* Macro to convert segmented address to _absaddr_t */
+
+#define _MAKE_ABS(seg,off) ((seg << 16) | (off & 0xffff))
+#endif
+
+/* File attribute constants */
+
+#define _A_NORMAL 0x00 /* Normal file - No read/write restrictions */
+#define _A_RDONLY 0x01 /* Read only file */
+#define _A_HIDDEN 0x02 /* Hidden file */
+#define _A_SYSTEM 0x04 /* System file */
+#define _A_SUBDIR 0x10 /* Subdirectory */
+#define _A_ARCH 0x20 /* Archive file */
+
+/* external variable declarations */
+
+#if defined(_WIN32_) || defined(_POSIX_)
+
+#ifdef _DLL
+
+#define _osversion (*_osversion_dll)
+#define _osmajor (*_osmajor_dll)
+#define _osminor (*_osminor_dll)
+#define _baseversion (*_baseversion_dll)
+#define _basemajor (*_basemajor_dll)
+#define _baseminor (*_baseminor_dll)
+#define _pgmptr (*_pgmptr_dll)
+
+extern unsigned int * _CRTVAR1 _osversion_dll;
+extern unsigned int * _CRTVAR1 _osmajor_dll;
+extern unsigned int * _CRTVAR1 _osminor_dll;
+extern unsigned int * _CRTVAR1 _baseversion_dll;
+extern unsigned int * _CRTVAR1 _basemajor_dll;
+extern unsigned int * _CRTVAR1 _baseminor_dll;
+extern char ** _CRTVAR1 _pgmptr_dll;
+
+#else
+
+#ifdef CRTDLL
+#define _osversion _osversion_dll
+#define _osmajor _osmajor_dll
+#define _osminor _osminor_dll
+#define _baseversion _baseversion_dll
+#define _basemajor _basemajor_dll
+#define _baseminor _baseminor_dll
+#define _pgmptr _pgmptr_dll
+#endif
+
+extern unsigned int _CRTVAR1 _osversion;
+extern unsigned int _CRTVAR1 _osmajor;
+extern unsigned int _CRTVAR1 _osminor;
+extern unsigned int _CRTVAR1 _baseversion;
+extern unsigned int _CRTVAR1 _basemajor;
+extern unsigned int _CRTVAR1 _baseminor;
+extern char * _CRTVAR1 _pgmptr;
+
+#endif
+
+#else /* ndef (_WIN32_ || _POSIX_) */
+
+extern unsigned int _CRTVAR1 _osversion;
+
+#endif /* _WIN32_ */
+
+
+/* function prototypes */
+
+unsigned _CRTAPI1 _getdiskfree(unsigned, struct _diskfree_t *);
+#ifdef _DOSX32_
+void * _CRTAPI1 _getvideoaddr(unsigned);
+#endif
+#ifdef _DOSX32_
+void _CRTAPI1 _peek(_absaddr_t, void *, unsigned short);
+void _CRTAPI1 _poke(void *, _absaddr_t, unsigned short);
+#endif
+
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#define diskfree_t _diskfree_t
+#endif /* __STDC__ */
+
+/* restore default alignment */
+
+#ifdef _CRUISER_
+#pragma pack()
+#endif /* ndef _CRUISER_ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_DOS
+#endif /* _INC_DOS */
diff --git a/private/crt32/h/doscalls.h b/private/crt32/h/doscalls.h
new file mode 100644
index 000000000..fe573da45
--- /dev/null
+++ b/private/crt32/h/doscalls.h
@@ -0,0 +1,545 @@
+/***
+*doscalls.h - functions declarations for OS/2 function calls
+*
+* Copyright (c) 1986-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Function declarations to provide strong type checking on
+* arguments to OS/2 function calls used by the C run-time.
+* Only those functions which are referenced in the run-time
+* are included in this file. This saves compilation time,
+* reduces the amount of memory needed by the compiler, and
+* prevents recompilation due to changes that do not directly
+* affect the C run-time. This file should only be updated
+* when a change is made to BSEDOS.H which affects a
+* function used in a C module in the C run-time, or when a
+* "C" module is changed to use a new OS/2 function call.
+*
+* Note: functions reference only in ASM files are included also
+* so that this file can serve as a reference.
+* [Internal]
+*
+*Revision History:
+* 08-31-88 PHG created from BSEDOS.H, changed SHORT to INT
+* 10-10-88 GJF Made specific to 386 (changed "Dos" prefix to
+* "Sys", removed "far",...,etc.)
+* 11-09-88 JCR _DATETIME.year and _DATETIME.timezone are USHORT
+* 04-28-89 JCR Upgraded for OS/2 1.20 (32-bit)
+* 05-25-89 JCR New system calling convention = "_syscall"
+* 06-06-89 PHG Added several new systems calls, updated RESULTCODES
+* made SHANDLE/HFILE/HDIR a long
+* 07-05-89 PHG Added HDIR types, and VECTOR constants
+* 07-06-89 JCR Corrected memory calls and constants
+* 07-28-89 GJF Corrected copyright. Protected alignment of struct
+* fields with pack pragma
+* 08-10-89 JCR Changed DOS32FILELOCKS to DOS32SETFILELOCKS
+* 08-14-89 GJF Added prototypes for DOS32QUERYFHSTATE and
+* DOS32SETFILEHSTATE
+* 10-18-89 JCR Changed _NEWREGION to match change in OS2 mem APIs
+* 10-27-89 JCR Added DOS32GETTHREADINFO change (under switch DCR757)
+* 10-30-89 GJF Fixed copyright
+* 11-06-89 JCR Added DOS32FREEMEM
+* 11-10-89 JCR Added OBJ_TILE bit to _NEWREGION definition
+* 11-10-89 JCR Removed DOS32QUERYFILEMODE/SETFILEMODE (not supported),
+* Added DOS32QUERYPATHINFO/SETPATHINFO
+* 11-16-89 GJF Changed DOS32SETFILEHSTATE to DOS32SETFHSTATE
+* 11-17-89 JCR Corrected DOS32SETFILEPTR
+* 11-17-89 JCR Enabled DOS32GETTHREADINFO code (DCR757)
+* 02-28-90 GJF Added #ifndef _INC_DOSCALLS stuff
+* 05-07-90 JCR Added correct semaphore calls
+* 05-09-90 JCR Corrected CREATETHREAD, etc.
+* 05-28-90 SBM Added DOS32RESETBUFFER
+* 06-06-90 SBM Added tentative new DOS32QUERYFHSTATE flags
+* 07-02-90 GJF Fixed thread info structures to conform with MS 2012
+* (aka DCR 1024).
+* 07-23-90 SBM Removed '32' from all API names
+* 08-23-90 GJF Added prototypes for new exception/signal API, removed
+* obsolete prototypes and definitions.
+* 12-10-90 GJF Updated values of new DOSQUERYFHSTATE flags.
+* 01-28-91 GJF Updated definition of struct _FILEFINDBUF
+* 08-20-91 JCR C++ and ANSI naming
+*
+****/
+
+#ifndef _INC_DOSCALLS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ensure proper alignment of struct fields */
+
+#pragma pack(4)
+
+
+#define PASCAL pascal
+#define VOID void
+
+#define APIENTRY _syscall /* OS/2 386 system calling convention =
+ C arg passing, no leading underscore */
+
+#define CHAR char /* ch */ /* always 8-bit */
+#define SHORT short /* s */ /* always 16-bit */
+#define LONG long /* l */ /* always 32-bit */
+#define INT int /* i */ /* 286:16-bit, 386:32-bit */
+
+typedef unsigned CHAR UCHAR; /* uch */
+typedef unsigned SHORT USHORT; /* us */
+typedef unsigned LONG ULONG; /* ul */
+typedef unsigned INT UINT; /* ui */
+
+typedef unsigned CHAR BYTE; /* b */
+
+typedef CHAR *PSZ;
+
+typedef INT (PASCAL *PFN)();
+typedef INT (PASCAL **PPFN)();
+
+typedef BYTE *PBYTE;
+
+typedef CHAR *PCHAR;
+typedef SHORT *PSHORT;
+typedef LONG *PLONG;
+typedef INT *PINT;
+
+typedef UCHAR *PUCHAR;
+typedef USHORT *PUSHORT;
+typedef ULONG *PULONG;
+typedef UINT *PUINT;
+
+typedef VOID *PVOID;
+
+typedef UINT BOOL; /* f */
+typedef BOOL *PBOOL;
+
+#define FALSE 0
+#define TRUE 1
+
+typedef ULONG SHANDLE;
+
+typedef SHANDLE HFILE; /* hf */
+typedef HFILE *PHFILE;
+
+typedef ULONG HMTX; /* mutex semaphore */
+typedef HMTX *PHMTX;
+
+typedef UINT PID; /* pid */
+typedef PID *PPID;
+
+typedef UINT TID; /* tid */
+typedef TID *PTID;
+
+/* File time and date types */
+
+typedef struct _FTIME { /* ftime */
+ unsigned short twosecs : 5;
+ unsigned short minutes : 6;
+ unsigned short hours : 5;
+} FTIME;
+typedef FTIME *PFTIME;
+
+typedef struct _FDATE { /* fdate */
+ unsigned short day : 5;
+ unsigned short month : 4;
+ unsigned short year : 7;
+} FDATE;
+typedef FDATE *PFDATE;
+
+/*
+ * CCHMAXPATH is the maximum fully qualified path name length including
+ * the drive letter, colon, backslashes and terminating NULL.
+ */
+#define CCHMAXPATH 260
+
+typedef struct _FILEFINDBUF { /* findbuf */
+ ULONG oNextEntryOffset; /* new field */
+ FDATE fdateCreation;
+ FTIME ftimeCreation;
+ FDATE fdateLastAccess;
+ FTIME ftimeLastAccess;
+ FDATE fdateLastWrite;
+ FTIME ftimeLastWrite;
+ ULONG cbFile;
+ ULONG cbFileAlloc;
+ ULONG attrFile; /* widened field */
+ UCHAR cchName;
+ CHAR achName[CCHMAXPATH];
+} FILEFINDBUF;
+typedef FILEFINDBUF *PFILEFINDBUF;
+
+/* Directory handle types */
+
+#define HDIR_SYSTEM 0x0001
+#define HDIR_CREATE 0xFFFF
+
+#define EXIT_THREAD 0
+#define EXIT_PROCESS 1
+
+VOID APIENTRY DOSEXIT(ULONG, ULONG);
+
+UINT APIENTRY DOSCREATETHREAD(PTID, VOID (*)(VOID), ULONG, ULONG, ULONG);
+UINT APIENTRY DOSRESUMETHREAD(TID);
+UINT APIENTRY DOSSUSPENDTHREAD(TID);
+
+/* Wait option values */
+
+#define DCWW_WAIT 0
+#define DCWW_NOWAIT 1
+
+typedef struct _RESULTCODES { /* resc */
+ ULONG codeTerminate;
+ ULONG codeResult;
+} RESULTCODES;
+typedef RESULTCODES *PRESULTCODES;
+
+/* codeTerminate values (also passed to ExitList routines) */
+
+#define TC_EXIT 0
+#define TC_HARDERROR 1
+#define TC_TRAP 2
+#define TC_KILLPROCESS 3
+
+ULONG APIENTRY DOSWAITCHILD(ULONG, ULONG, PRESULTCODES, PPID, PID);
+UINT APIENTRY DOSSLEEP(ULONG);
+
+/* DOSEXECPGM functions */
+
+#define EXEC_SYNC 0
+#define EXEC_ASYNC 1
+#define EXEC_ASYNCRESULT 2
+#define EXEC_TRACE 3
+#define EXEC_BACKGROUND 4
+#define EXEC_LOAD 5
+
+ULONG APIENTRY DOSEXECPGM(PCHAR, ULONG, ULONG, PSZ, PSZ, PRESULTCODES, PSZ);
+
+
+typedef struct tib2_s { /* System Specific Thread Info Block */
+ ULONG tib2_ultid; /* Thread I.D. */
+ ULONG tib2_ulpri; /* Thread priority */
+ ULONG tib2_version; /* Version number for this structure */
+ USHORT tib2_usMCCount; /* Must Complete count */
+ USHORT tib2_fMCForceFlag; /* Must Complete force flag */
+} TIB2;
+typedef TIB2 *PTIB2;
+
+typedef struct tib_s { /* Thread Information Block (TIB) */
+ PVOID tib_pexchain; /* Head of exception handler chain */
+ PVOID tib_pstack; /* Pointer to base of stack */
+ PVOID tib_pstacklimit; /* Pointer to end of stack */
+ PTIB2 tib_ptib2; /* Pointer to system specific TIB */
+ ULONG tib_version; /* Version number for this TIB structure */
+ PVOID tib_arbpointer; /* A pointer for the user */
+} TIB;
+typedef TIB *PTIB;
+
+typedef struct pib_s { /* Process Information Block (PIB) */
+ ULONG pib_ulpid; /* Process I.D. */
+ ULONG pib_ulppid; /* Parent process I.D. */
+ ULONG pib_hmte; /* Program (.EXE) module handle */
+ PCHAR pib_pchcmd; /* Command line pointer */
+ PCHAR pib_pchenv; /* Environment pointer */
+ ULONG pib_flstatus; /* Process' status bits */
+ ULONG pib_ultype; /* Process' type code */
+} PIB;
+typedef PIB *PPIB;
+
+ULONG APIENTRY DOSGETTHREADINFO(PTIB *, PPIB *);
+
+
+/* Global Info Seg */
+
+typedef struct _GINFOSEG { /* gis */
+ ULONG time;
+ ULONG msecs;
+ UCHAR hour;
+ UCHAR minutes;
+ UCHAR seconds;
+ UCHAR hundredths;
+ UINT timezone;
+ UINT cusecTimerInterval;
+ UCHAR day;
+ UCHAR month;
+ UINT year;
+ UCHAR weekday;
+ UCHAR uchMajorVersion;
+ UCHAR uchMinorVersion;
+ UCHAR chRevisionLetter;
+ UCHAR sgCurrent;
+ UCHAR sgMax;
+ UCHAR cHugeShift;
+ UCHAR fProtectModeOnly;
+ UINT pidForeground;
+ UCHAR fDynamicSched;
+ UCHAR csecMaxWait;
+ UINT cmsecMinSlice;
+ UINT cmsecMaxSlice;
+ UINT bootdrive;
+ UCHAR amecRAS[32];
+} GINFOSEG;
+typedef GINFOSEG *PGINFOSEG;
+
+/* Local Info Seg */
+
+typedef struct _LINFOSEG { /* lis */
+ PID pidCurrent;
+ PID pidParent;
+ UINT prtyCurrent;
+ TID tidCurrent;
+ UINT sgCurrent;
+ UINT sgSub;
+ BOOL fForeground;
+} LINFOSEG;
+typedef LINFOSEG *PLINFOSEG;
+
+/* Process Type codes (local info seg typeProcess field) */
+
+#define PT_FULLSCREEN 0
+#define PT_REALMODE 1
+#define PT_WINDOWABLEVIO 2
+#define PT_PM 3
+#define PT_DETACHED 4
+
+UINT APIENTRY DOSGETINFOSEG(PGINFOSEG *, PLINFOSEG *); /* correct?? */
+
+/* extended attribute structures */
+
+typedef struct _GEA { /* gea */
+ BYTE cbName; /* name length not including NULL */
+ CHAR szName[1]; /* attribute name */
+} GEA;
+typedef GEA *PGEA;
+
+typedef struct _GEALIST { /* geal */
+ USHORT cbList; /* total bytes of structure including full list */
+ GEA list[1]; /* variable length GEA structures */
+} GEALIST;
+typedef GEALIST * PGEALIST;
+
+typedef struct _FEA { /* fea */
+ BYTE bRsvd; /* reserved */
+ BYTE cbName; /* name length not including NULL */
+ USHORT cbValue; /* value length */
+} FEA;
+typedef FEA *PFEA;
+
+typedef struct _FEALIST { /* feal */
+ USHORT cbList; /* total bytes of structure including full list */
+ FEA list[1]; /* variable length FEA structures */
+} FEALIST;
+typedef FEALIST * PFEALIST;
+
+typedef struct _EAOP { /* eaop */
+ PGEALIST fpGEAList; /* general EA list */
+ PFEALIST fpFEAList; /* full EA list */
+ USHORT oError;
+} EAOP;
+typedef EAOP * PEAOP;
+
+ULONG APIENTRY DOSOPEN(PSZ, PHFILE, PULONG, ULONG, ULONG, ULONG, ULONG, PEAOP, ULONG);
+ULONG APIENTRY DOSCLOSE(HFILE);
+ULONG APIENTRY DOSREAD(HFILE, PVOID, ULONG, PULONG);
+ULONG APIENTRY DOSWRITE(HFILE, PVOID, ULONG, PULONG);
+
+/* File time and date types */
+
+typedef struct _FILESTATUS { /* fsts */
+ FDATE fdateCreation;
+ FTIME ftimeCreation;
+ FDATE fdateLastAccess;
+ FTIME ftimeLastAccess;
+ FDATE fdateLastWrite;
+ FTIME ftimeLastWrite;
+ ULONG cbFile;
+ ULONG cbFileAlloc;
+ USHORT attrFile;
+} FILESTATUS;
+typedef FILESTATUS *PFILESTATUS;
+
+/* File locking/unlocking */
+typedef struct _FILELOCK {
+ LONG lOffset;
+ LONG lRange;
+} FILELOCK;
+typedef FILELOCK *PFILELOCK;
+
+typedef SHANDLE HDIR; /* hdir */
+typedef HDIR *PHDIR;
+
+/* DosOpen() open flags */
+
+#define FILE_OPEN 0x0001
+#define FILE_TRUNCATE 0x0002
+#define FILE_CREATE 0x0010
+
+/* DosOpen/DosSetFHandState flags */
+
+#define OPEN_ACCESS_READONLY 0x0000
+#define OPEN_ACCESS_WRITEONLY 0x0001
+#define OPEN_ACCESS_READWRITE 0x0002
+#define OPEN_SHARE_DENYREADWRITE 0x0010
+#define OPEN_SHARE_DENYWRITE 0x0020
+#define OPEN_SHARE_DENYREAD 0x0030
+#define OPEN_SHARE_DENYNONE 0x0040
+#define OPEN_FLAGS_NOINHERIT 0x0080
+#define OPEN_FLAGS_FAIL_ON_ERROR 0x2000
+#define OPEN_FLAGS_WRITE_THROUGH 0x4000
+#define OPEN_FLAGS_DASD 0x8000
+
+/* new DosQueryFHState flags from DCR 'Add full 32-bit support for runtime
+ libraries.' NAMES TENTATIVE AND SUBJECT TO CHANGE. STAY AWAY. */
+
+#define OPEN_FLAGS_CONSOLE 0x00080000
+#define OPEN_FLAGS_RAWMODE 0x00100000
+#define OPEN_FLAGS_EOF 0x00200000
+
+/* HANDTYPE values */
+#define HANDTYPE_FILE 0x00
+#define HANDTYPE_DEVICE 0x01
+#define HANDTYPE_PIPE 0x02
+#define HANDTYPE_NETWORK 0x80
+
+ULONG APIENTRY DOSDELETE(PSZ, ULONG);
+ULONG APIENTRY DOSDUPHANDLE(HFILE, PHFILE);
+ULONG APIENTRY DOSQUERYFHSTATE(HFILE, PULONG);
+ULONG APIENTRY DOSQUERYHTYPE(HFILE, PULONG, PULONG);
+ULONG APIENTRY DOSFINDFIRST(PSZ, PHDIR, ULONG, PFILEFINDBUF, ULONG, PULONG, ULONG);
+ULONG APIENTRY DOSFINDNEXT(HDIR, PFILEFINDBUF, ULONG, PULONG);
+ULONG APIENTRY DOSFINDCLOSE(HDIR);
+ULONG APIENTRY DOSSETFHSTATE(HFILE, ULONG);
+ULONG APIENTRY DOSSETFILESIZE(HFILE, ULONG);
+ULONG APIENTRY DOSSETFILEPTR(HFILE, ULONG, LONG, PULONG);
+ULONG APIENTRY DOSSETFILELOCKS(HFILE, PFILELOCK, PFILELOCK);
+ULONG APIENTRY DOSMOVE(PSZ, PSZ, ULONG);
+ULONG APIENTRY DOSCREATEDIR(PSZ, PEAOP, ULONG);
+ULONG APIENTRY DOSDELETEDIR(PSZ, ULONG);
+ULONG APIENTRY DOSQUERYCURRENTDISK(PULONG, PULONG);
+ULONG APIENTRY DOSSETDEFAULTDISK(ULONG);
+ULONG APIENTRY DOSSETCURRENTDIR(PSZ, ULONG);
+ULONG APIENTRY DOSQUERYCURRENTDIR(ULONG, PBYTE, PULONG);
+ULONG APIENTRY DOSSETMAXFH(ULONG);
+ULONG APIENTRY DOSQUERYFILEINFO(HFILE, ULONG, PFILESTATUS, ULONG);
+ULONG APIENTRY DOSQUERYPATHINFO(PCHAR, ULONG, PFILESTATUS, ULONG);
+ULONG APIENTRY DOSSETPATHINFO(PCHAR, ULONG, PFILESTATUS, ULONG, ULONG);
+ULONG APIENTRY DOSSETFILEINFO(HFILE, ULONG, PFILESTATUS, ULONG);
+ULONG APIENTRY DOSCREATEPIPE(PULONG, PULONG, ULONG);
+ULONG APIENTRY DOSQUERYSYSINFO(ULONG, ULONG, PBYTE, ULONG);
+ULONG APIENTRY DOSRESETBUFFER(HFILE);
+
+/* File attribute flags */
+#define FILE_NORMAL 0x0000
+#define FILE_READONLY 0x0001
+#define FILE_HIDDEN 0x0002
+#define FILE_SYSTEM 0x0004
+#define FILE_DIRECTORY 0x0010
+#define FILE_ARCHIVED 0x0020
+
+/* DosSetFilePtr() file position codes */
+
+#define FILE_BEGIN 0x0000
+#define FILE_CURRENT 0x0001
+#define FILE_END 0x0002
+
+/* 386 allocation API */
+
+/* Access protection */
+#define PAG_READ 0x00000001 /* read access */
+#define PAG_WRITE 0x00000002 /* write access */
+#define PAG_EXECUTE 0x00000004 /* execute access */
+#define PAG_GUARD 0x00000008 /* guard protection */
+
+/* Commit */
+#define PAG_COMMIT 0x00000010 /* commit storage */
+#define PAG_DECOMMIT 0x00000020 /* decommit storage */
+
+/* Allocation attributes */
+#define OBJ_TILE 0x00000040 /* tile object */
+#define OBJ_PROTECTED 0x00000080 /* protect object
+#define OBJ_GETTABLE 0x00000100 /* gettable by other processes */
+#define OBJ_GIVEABLE 0x00000200 /* giveable to other processes */
+
+/* Standard memory values for C lib (heap and mthread code) */
+#define _NEWREGION (PAG_READ | PAG_WRITE | OBJ_TILE)
+#define _COMMIT (PAG_COMMIT | PAG_READ | PAG_WRITE)
+#define _DECOMMIT (PAG_DECOMMIT)
+
+UINT APIENTRY DOSALLOCMEM(PVOID, UINT, UINT, UINT);
+UINT APIENTRY DOSFREEMEM(PVOID);
+UINT APIENTRY DOSSETMEM(PVOID, UINT, UINT);
+
+/*** Semaphore support */
+
+UINT APIENTRY DOSCREATEMUTEXSEM (PSZ, PHMTX, ULONG, ULONG);
+UINT APIENTRY DOSQUERYMUTEXSEM (HMTX, PID *, TID *, PULONG);
+UINT APIENTRY DOSREQUESTMUTEXSEM (HMTX, ULONG);
+UINT APIENTRY DOSRELEASEMUTEXSEM (HMTX);
+
+/*** Time support */
+
+typedef struct _DATETIME { /* date */
+ UCHAR hours;
+ UCHAR minutes;
+ UCHAR seconds;
+ UCHAR hundredths;
+ UCHAR day;
+ UCHAR month;
+ USHORT year;
+ SHORT timezone;
+ UCHAR weekday;
+} DATETIME;
+typedef DATETIME *PDATETIME;
+
+ULONG APIENTRY DOSGETDATETIME(PDATETIME);
+
+/* Exception/signal API */
+
+/* Argument values for DOSSETSIGNALEXCEPTIONFOCUS */
+
+#define SIG_UNSETFOCUS 0
+#define SIG_SETFOCUS 1
+
+/* Include type and constant definitions */
+
+#include <except.h>
+
+/* Prototypes */
+
+UINT APIENTRY DOSRAISEEXCEPTION(_PEXCEPTIONREPORTRECORD);
+UINT APIENTRY DOSSENDSIGNALEXCEPTION(PID, ULONG);
+UINT APIENTRY DOSUNWINDEXCEPTION(_PEXCEPTIONREGISTRATIONRECORD, PVOID, _PEXCEPTIONREPORTRECORD);
+UINT APIENTRY DOSSETSIGNALEXCEPTIONFOCUS(ULONG, PULONG);
+UINT APIENTRY DOSENTERMUSTCOMPLETE(PULONG);
+UINT APIENTRY DOSEXITMUSTCOMPLETE(PULONG);
+UINT APIENTRY DOSACKNOWLEDGESIGNALEXCEPTION(ULONG);
+
+UINT APIENTRY DOSGETVERSION(PUINT); /* correct? */
+UINT APIENTRY DOSGETMACHINEMODE(PBYTE); /* correct? */
+
+ULONG APIENTRY DOSDEVCONFIG(PULONG, ULONG, ULONG);
+
+/* indices for DosQuerySysInfo */
+#define _QSV_MAX_PATH_LENGTH 1
+#define _QSV_MAX_TEXT_SESSIONS 2
+#define _QSV_MAX_PM_SESSIONS 3
+#define _QSV_MAX_VDM_SESSIONS 4
+#define _QSV_BOOT_DRIVE 5 /* 1=A, 2=B, etc. */
+#define _QSV_DYN_PRI_VARIATION 6 /* 0=Absolute, 1=Dynamic */
+#define _QSV_MAX_WAIT 7 /* seconds */
+#define _QSV_MIN_SLICE 8 /* milli seconds */
+#define _QSV_MAX_SLICE 9 /* milli seconds */
+#define _QSV_PAGE_SIZE 10
+#define _QSV_VERSION_MAJOR 11 /* OS revision (major) */
+#define _QSV_VERSION_MINOR 12 /* OS revision (minor) */
+#define _QSV_VERSION_REVISION 13 /* Revision letter */
+
+
+/* restore default alignment */
+
+#pragma pack()
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_DOSCALLS
+#endif /* _INC_DOSCALLS */
diff --git a/private/crt32/h/dostypes.h b/private/crt32/h/dostypes.h
new file mode 100644
index 000000000..92f6771dd
--- /dev/null
+++ b/private/crt32/h/dostypes.h
@@ -0,0 +1,112 @@
+/***
+*dostypes.h - defines DOS packed date and time types
+*
+* Copyright (c) 1987-1990, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the DOS packed date and time types.
+*
+*Revision History:
+* 11-18-87 SKS Removed declaration of _dtoxtime
+* 09-27-88 JCR 386 versions of macros
+* 10-03-88 GJF Use M_I386, not I386
+* 05-01-89 JCR Fixed 386 versions for new rev of OS/2 386
+* 08-03-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 02-28-90 GJF Added #ifndef _INC_DOSTYPES stuff
+* 08-11-90 SBM Enhanced SET_DOS_* macros to compile cleanly with -W3
+* 04-09-91 PNT Added _MAC_ definitions
+*
+****/
+
+#ifndef _INC_DOSTYPES
+
+#define MASK4 0xf /* 4 bit mask */
+#define MASK5 0x1f /* 5 bit mask */
+#define MASK6 0x3f /* 6 bit mask */
+#define MASK7 0x7f /* 7 bit mask */
+
+#define DAYLOC 0 /* day value starts in bit 0 */
+#define MONTHLOC 5 /* month value starts in bit 5 */
+#define YEARLOC 9 /* year value starts in bit 9 */
+
+#define SECLOC 0 /* seconds value starts in bit 0 */
+#define MINLOC 5 /* minutes value starts in bit 5 */
+#define HOURLOC 11 /* hours value starts in bit 11 */
+
+#define _DATECAST(fd) * (unsigned short *) &(fd)
+#define _TIMECAST(ft) * (unsigned short *) &(ft)
+
+#ifdef _CRUISER_
+
+#define SET_DOS_DAY(fd, xday) fd.day = (unsigned short)((xday) & MASK5)
+#define SET_DOS_MONTH(fd, xmon) fd.month = (unsigned short)((xmon) & MASK4)
+#define SET_DOS_YEAR(fd, xyr) fd.year = (unsigned short)((xyr) & MASK7)
+
+#define SET_DOS_HOUR(ft, xhr) ft.hours = (unsigned short)((xhr) & MASK5)
+#define SET_DOS_MIN(ft, xmin) ft.minutes = (unsigned short)((xmin) & MASK6)
+#define SET_DOS_SEC(ft, xsec) ft.twosecs = (unsigned short)((xsec) & MASK5)
+
+#define DOS_DAY(fd) (fd.day)
+#define DOS_MONTH(fd) (fd.month)
+#define DOS_YEAR(fd) (fd.year)
+
+#define DOS_HOUR(ft) (ft.hours)
+#define DOS_MIN(ft) (ft.minutes)
+#define DOS_SEC(ft) (ft.twosecs)
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+#define SET_DOS_DAY(fd, xday) fd.Day = (unsigned short)((xday) & MASK5)
+#define SET_DOS_MONTH(fd, xmon) fd.Month = (unsigned short)((xmon) & MASK4)
+#define SET_DOS_YEAR(fd, xyr) fd.Year = (unsigned short)((xyr) & MASK7)
+
+#define SET_DOS_HOUR(ft, xhr) ft.Hours = (unsigned short)((xhr) & MASK5)
+#define SET_DOS_MIN(ft, xmin) ft.Minutes = (unsigned short)((xmin) & MASK6)
+#define SET_DOS_SEC(ft, xsec) ft.DoubleSeconds = (unsigned short)((xsec) & MASK5)
+
+#define DOS_DAY(fd) (fd.Day)
+#define DOS_MONTH(fd) (fd.Month)
+#define DOS_YEAR(fd) (fd.Year)
+
+#define DOS_HOUR(ft) (ft.Hours)
+#define DOS_MIN(ft) (ft.Minutes)
+#define DOS_SEC(ft) (ft.DoubleSeconds)
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+#define SET_DOS_DAY(fd, xday) fd.day = (unsigned short)((xday) & MASK5)
+#define SET_DOS_MONTH(fd, xmon) fd.month = (unsigned short)((xmon) & MASK4)
+#define SET_DOS_YEAR(fd, xyr) fd.year = (unsigned short)((xyr) & MASK7)
+
+#define SET_DOS_HOUR(ft, xhr) ft.hours = (unsigned short)((xhr) & MASK5)
+#define SET_DOS_MIN(ft, xmin) ft.minutes = (unsigned short)((xmin) & MASK6)
+#define SET_DOS_SEC(ft, xsec) ft.twosecs = (unsigned short)((xsec) & MASK5)
+
+#define DOS_DAY(fd) (fd.day)
+#define DOS_MONTH(fd) (fd.month)
+#define DOS_YEAR(fd) (fd.year)
+
+#define DOS_HOUR(ft) (ft.hours)
+#define DOS_MIN(ft) (ft.minutes)
+#define DOS_SEC(ft) (ft.twosecs)
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, _MAC_ TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#define XTIME(d,t) _dtoxtime(DOS_YEAR(d),DOS_MONTH(d),DOS_DAY(d),DOS_HOUR(t),\
+ DOS_MIN(t),DOS_SEC(t)*2)
+
+#define _INC_DOSTYPES
+#endif /* _INC_DOSTYPES */
diff --git a/private/crt32/h/errmsg.h b/private/crt32/h/errmsg.h
new file mode 100644
index 000000000..740affe75
--- /dev/null
+++ b/private/crt32/h/errmsg.h
@@ -0,0 +1,36 @@
+/***
+*errmsg.h - defines error message numbers
+*
+* Copyright (c) 1985-1990, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the constants for error message numbers.
+* Same as errmsg.inc
+* [Internal]
+*
+*Revision History:
+* 08-03-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright
+* 02-28-90 GJF Added #ifndef _INC_ERRMSG stuff
+*
+****/
+
+#ifndef _INC_ERRMSG
+
+#define STCKOVR 0
+#define NULLERR 1
+#define NOFP 2
+#define DIVZR 3
+#define BADVERS 4
+#define NOMEM 5
+#define BADFORM 6
+#define BADENV 7
+#define NOARGV 8
+#define NOENVP 9
+#define ABNORM 10
+#define UNKNOWN 11
+
+#define CRT_NERR 11
+
+#define _INC_ERRMSG
+#endif /* _INC_ERRMSG */
diff --git a/private/crt32/h/errno.h b/private/crt32/h/errno.h
new file mode 100644
index 000000000..04bcfdeb2
--- /dev/null
+++ b/private/crt32/h/errno.h
@@ -0,0 +1,127 @@
+/***
+*errno.h - system wide error numbers (set by system calls)
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the system-wide error numbers (set by
+* system calls). Conforms to the XENIX standard. Extended
+* for compatibility with Uniforum standard.
+* [System V]
+*
+*Revision History:
+* 07-15-88 JCR Added errno definition [ANSI]
+* 08-22-88 GJF Modified to also work with the 386 (small model only)
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-01-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 02-28-90 GJF Added #ifndef _INC_ERRNO and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-29-90 GJF Replaced _cdecl with _CALLTYPE1 or _VARTYPE1, as
+* appropriate.
+* 08-16-90 SBM Made MTHREAD _errno() return int *
+* 08-20-91 JCR C++ and ANSI naming
+* 08-06-92 GJF Function calling type and variable type macros.
+* 10-01-92 GJF Made compatible with POSIX. Next step is to renumber
+* to remove gaps (after next beta).
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 04-08-93 CFW Added EILSEQ 42.
+*
+****/
+
+#ifndef _INC_ERRNO
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/* declare reference to errno */
+
+#ifdef MTHREAD
+extern int * _CRTAPI1 _errno(void);
+#define errno (*_errno())
+#else
+extern int _CRTVAR1 errno;
+#endif
+
+/* Error Codes */
+
+#define EPERM 1
+#define ENOENT 2
+#define ESRCH 3
+#define EINTR 4
+#define EIO 5
+#define ENXIO 6
+#define E2BIG 7
+#define ENOEXEC 8
+#define EBADF 9
+#define ECHILD 10
+#define EAGAIN 11
+#define ENOMEM 12
+#define EACCES 13
+#define EFAULT 14
+#define EBUSY 16
+#define EEXIST 17
+#define EXDEV 18
+#define ENODEV 19
+#define ENOTDIR 20
+#define EISDIR 21
+#define EINVAL 22
+#define ENFILE 23
+#define EMFILE 24
+#define ENOTTY 25
+#define EFBIG 27
+#define ENOSPC 28
+#define ESPIPE 29
+#define EROFS 30
+#define EMLINK 31
+#define EPIPE 32
+#define EDOM 33
+#define ERANGE 34
+#define EDEADLK 36
+#define ENAMETOOLONG 38
+#define ENOLCK 39
+#define ENOSYS 40
+#define ENOTEMPTY 41
+#define EILSEQ 42
+
+/*
+ * Support EDEADLOCK for compatibiity with older MS-C versions.
+ */
+#define EDEADLOCK EDEADLK
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_ERRNO
+#endif /* _INC_ERRNO */
diff --git a/private/crt32/h/error.h b/private/crt32/h/error.h
new file mode 100644
index 000000000..174690a10
--- /dev/null
+++ b/private/crt32/h/error.h
@@ -0,0 +1,383 @@
+/***
+*error.h - DOS error codes
+*
+* Copyright (c) 1987-1990, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* DOS calls all return error codes through AX. If an error occurred then
+* the carry bit will be set and the error code is in AX. If no error occurred
+* then the carry bit is reset and AX contains returned info.
+*
+* Since the set of error codes is being extended as we extend the operating
+* system, we have provided a means for applications to ask the system for a
+* recommended course of action when they receive an error.
+*
+* The GetExtendedError system call returns a universal error, an error
+* location and a recommended course of action. The universal error code is
+* a symptom of the error REGARDLESS of the context in which GetExtendedError
+* is issued.
+*
+*Revision History:
+* 10-25-87 SKS Updated from final OS/2 v1.0 sources as of 10-25-87
+* 06-06-89 PHG Added network related errors from error.inc
+* 08-03-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 02-28-90 GJF Added #ifndef _INC_ERROR stuff
+*
+*******************************************************************************/
+
+#ifndef _INC_ERROR
+
+/*static char *SCCSID = "@(#)error.h 7.25 87/07/23";*/
+/* XENIX calls all return error codes through AX. If an error occurred then */
+/* the carry bit will be set and the error code is in AX. If no error occurred */
+/* then the carry bit is reset and AX contains returned info. */
+/* */
+/* Since the set of error codes is being extended as we extend the operating */
+/* system, we have provided a means for applications to ask the system for a */
+/* recommended course of action when they receive an error. */
+/* */
+/* The GetExtendedError system call returns a universal error, an error */
+/* location and a recommended course of action. The universal error code is */
+/* a symptom of the error REGARDLESS of the context in which GetExtendedError */
+/* is issued. */
+/* */
+/* */
+/* These are the 2.0 error codes */
+/* */
+#define NO_ERROR 0
+#define ERROR_INVALID_FUNCTION 1
+#define ERROR_FILE_NOT_FOUND 2
+#define ERROR_PATH_NOT_FOUND 3
+#define ERROR_TOO_MANY_OPEN_FILES 4
+#define ERROR_ACCESS_DENIED 5
+#define ERROR_INVALID_HANDLE 6
+#define ERROR_ARENA_TRASHED 7
+#define ERROR_NOT_ENOUGH_MEMORY 8
+#define ERROR_INVALID_BLOCK 9
+#define ERROR_BAD_ENVIRONMENT 10
+#define ERROR_BAD_FORMAT 11
+#define ERROR_INVALID_ACCESS 12
+#define ERROR_INVALID_DATA 13
+/* **** reserved 14 ; ***** */
+#define ERROR_INVALID_DRIVE 15
+#define ERROR_CURRENT_DIRECTORY 16
+#define ERROR_NOT_SAME_DEVICE 17
+#define ERROR_NO_MORE_FILES 18
+/* */
+/* These are the universal int 24 mappings for the old INT 24 set of errors */
+/* */
+#define ERROR_WRITE_PROTECT 19
+#define ERROR_BAD_UNIT 20
+#define ERROR_NOT_READY 21
+#define ERROR_BAD_COMMAND 22
+#define ERROR_CRC 23
+#define ERROR_BAD_LENGTH 24
+#define ERROR_SEEK 25
+#define ERROR_NOT_DOS_DISK 26
+#define ERROR_SECTOR_NOT_FOUND 27
+#define ERROR_OUT_OF_PAPER 28
+#define ERROR_WRITE_FAULT 29
+#define ERROR_READ_FAULT 30
+#define ERROR_GEN_FAILURE 31
+/* */
+/* These are the new 3.0 error codes reported through INT 24 */
+/* */
+#define ERROR_SHARING_VIOLATION 32
+#define ERROR_LOCK_VIOLATION 33
+#define ERROR_WRONG_DISK 34
+#define ERROR_FCB_UNAVAILABLE 35
+#define ERROR_SHARING_BUFFER_EXCEEDED 36
+/* */
+/* New OEM network-related errors are 50-79 */
+/* */
+#define ERROR_NOT_SUPPORTED 50
+/* */
+/* End of INT 24 reportable errors */
+/* */
+
+/* Network related errors */
+#define ERROR_NOT_SUPPORTED 50 /* Network request not supported */
+#define ERROR_REM_NOT_LIST 51 /* Remote computer not listening */
+#define ERROR_DUP_NAME 52 /* Duplicate name on network */
+#define ERROR_BAD_NETPATH 53 /* Network path not found */
+#define ERROR_NETWORK_BUSY 54 /* Network busy */
+#define ERROR_DEV_NOT_EXIST 55 /* Network device no longer exists */
+#define ERROR_TOO_MANY_CMDS 56 /* Net BIOS command limit exceeded */
+#define ERROR_ADAP_HDW_ERR 57 /* Network adapter hardware error */
+#define ERROR_BAD_NET_RESP 58 /* Incorrect response from network */
+#define ERROR_UNEXP_NET_ERR 59 /* Unexpected network error */
+#define ERROR_BAD_REM_ADAP 60 /* Incompatible remote adapter */
+#define ERROR_PRINTQ_FULL 61 /* Print queue full */
+#define ERROR_NO_SPOOL_SPACE 62 /* Not enough space for print file */
+#define ERROR_PRINT_CANCELLED 63 /* Print file was cancelled */
+#define ERROR_NETNAME_DELETED 64 /* Network name was deleted */
+#define ERROR_NETWORK_ACCESS_DENIED 65 /* Access denied */
+#define ERROR_BAD_DEV_TYPE 66 /* Network device type incorrect */
+#define ERROR_BAD_NET_NAME 67 /* Network name not found */
+#define ERROR_TOO_MANY_NAMES 68 /* Network name limit exceeded */
+#define ERROR_TOO_MANY_SESS 69 /* Net BIOS session limit exceeded */
+#define ERROR_SHARING_PAUSED 70 /* Sharing temporarily paused */
+#define ERROR_REQ_NOT_ACCEP 71 /* Network request not accepted */
+#define ERROR_REDIR_PAUSED 72 /* Print or disk redirection is paused */
+
+#define ERROR_FILE_EXISTS 80
+#define ERROR_DUP_FCB 81 /* ***** */
+#define ERROR_CANNOT_MAKE 82
+#define ERROR_FAIL_I24 83
+/* */
+/* New 3.0 network related error codes */
+/* */
+#define ERROR_OUT_OF_STRUCTURES 84
+#define ERROR_ALREADY_ASSIGNED 85
+#define ERROR_INVALID_PASSWORD 86
+#define ERROR_INVALID_PARAMETER 87
+#define ERROR_NET_WRITE_FAULT 88
+/* */
+/* New error codes for 4.0 */
+/* */
+#define ERROR_NO_PROC_SLOTS 89 /* no process slots available */
+#define ERROR_NOT_FROZEN 90
+#define ERR_TSTOVFL 91 /* timer service table overflow */
+#define ERR_TSTDUP 92 /* timer service table duplicate */
+#define ERROR_NO_ITEMS 93 /* There were no items to operate upon */
+#define ERROR_INTERRUPT 95 /* interrupted system call */
+
+#define ERROR_TOO_MANY_SEMAPHORES 100
+#define ERROR_EXCL_SEM_ALREADY_OWNED 101
+#define ERROR_SEM_IS_SET 102
+#define ERROR_TOO_MANY_SEM_REQUESTS 103
+#define ERROR_INVALID_AT_INTERRUPT_TIME 104
+
+#define ERROR_SEM_OWNER_DIED 105 /* waitsem found owner died */
+#define ERROR_SEM_USER_LIMIT 106 /* too many procs have this sem */
+#define ERROR_DISK_CHANGE 107 /* insert disk b into drive a */
+#define ERROR_DRIVE_LOCKED 108 /* drive locked by another process */
+#define ERROR_BROKEN_PIPE 109 /* write on pipe with no reader */
+/* */
+/* New error codes for OS/2 */
+/* */
+#define ERROR_OPEN_FAILED 110 /* open/created failed due to */
+ /* explicit fail command */
+#define ERROR_BUFFER_OVERFLOW 111 /* buffer passed to system call */
+ /* is too small to hold return */
+ /* data. */
+#define ERROR_DISK_FULL 112 /* not enough space on the disk */
+ /* (DOSNEWSIZE/w_NewSize) */
+#define ERROR_NO_MORE_SEARCH_HANDLES 113 /* can't allocate another search */
+ /* structure and handle. */
+ /* (DOSFINDFIRST/w_FindFirst) */
+#define ERROR_INVALID_TARGET_HANDLE 114 /* Target handle in DOSDUPHANDLE */
+ /* is invalid */
+#define ERROR_PROTECTION_VIOLATION 115 /* Bad user virtual address */
+#define ERROR_VIOKBD_REQUEST 116
+#define ERROR_INVALID_CATEGORY 117 /* Category for DEVIOCTL in not */
+ /* defined */
+#define ERROR_INVALID_VERIFY_SWITCH 118 /* invalid value passed for */
+ /* verify flag */
+#define ERROR_BAD_DRIVER_LEVEL 119 /* DosDevIOCTL looks for a level */
+ /* four driver. If the driver */
+ /* is not level four we return */
+ /* this code */
+#define ERROR_CALL_NOT_IMPLEMENTED 120 /* returned from stub api calls. */
+ /* This call will disappear when */
+ /* all the api's are implemented. */
+#define ERROR_SEM_TIMEOUT 121 /* Time out happened from the */
+ /* semaphore api functions. */
+#define ERROR_INSUFFICIENT_BUFFER 122 /* Some call require the */
+ /* application to pass in a buffer */
+ /* filled with data. This error is */
+ /* returned if the data buffer is too */
+ /* small. For example: DosSetFileInfo */
+ /* requires 4 bytes of data. If a */
+ /* two byte buffer is passed in then */
+ /* this error is returned. */
+ /* error_buffer_overflow is used when */
+ /* the output buffer in not big enough. */
+#define ERROR_INVALID_NAME 123 /* illegal character or malformed */
+ /* file system name */
+#define ERROR_INVALID_LEVEL 124 /* unimplemented level for info */
+ /* retrieval or setting */
+#define ERROR_NO_VOLUME_LABEL 125 /* no volume label found with */
+ /* DosQFSInfo command */
+#define ERROR_MOD_NOT_FOUND 126 /* w_getprocaddr,w_getmodhandle */
+#define ERROR_PROC_NOT_FOUND 127 /* w_getprocaddr */
+
+#define ERROR_WAIT_NO_CHILDREN 128 /* CWait finds to children */
+
+#define ERROR_CHILD_NOT_COMPLETE 129 /* CWait children not dead yet */
+
+/*This is a temporary fix for the 4-19-86 build this should be changed when */
+/* we get the file from MS */
+#define ERROR_DIRECT_ACCESS_HANDLE 130 /* handle operation is invalid */
+ /* for direct disk access */
+ /* handles */
+#define ERROR_NEGATIVE_SEEK 131 /* application tried to seek */
+ /* with negative offset */
+#define ERROR_SEEK_ON_DEVICE 132 /* application tried to seek */
+ /* on device or pipe */
+/* */
+/* The following are errors generated by the join and subst workers */
+/* */
+#define ERROR_IS_JOIN_TARGET 133
+#define ERROR_IS_JOINED 134
+#define ERROR_IS_SUBSTED 135
+#define ERROR_NOT_JOINED 136
+#define ERROR_NOT_SUBSTED 137
+#define ERROR_JOIN_TO_JOIN 138
+#define ERROR_SUBST_TO_SUBST 139
+#define ERROR_JOIN_TO_SUBST 140
+#define ERROR_SUBST_TO_JOIN 141
+#define ERROR_BUSY_DRIVE 142
+#define ERROR_SAME_DRIVE 143
+#define ERROR_DIR_NOT_ROOT 144
+#define ERROR_DIR_NOT_EMPTY 145
+#define ERROR_IS_SUBST_PATH 146
+#define ERROR_IS_JOIN_PATH 147
+#define ERROR_PATH_BUSY 148
+#define ERROR_IS_SUBST_TARGET 149
+#define ERROR_SYSTEM_TRACE 150 /* system trace error */
+#define ERROR_INVALID_EVENT_COUNT 151 /* DosMuxSemWait errors */
+#define ERROR_TOO_MANY_MUXWAITERS 152
+#define ERROR_INVALID_LIST_FORMAT 153
+#define ERROR_LABEL_TOO_LONG 154
+#define ERROR_TOO_MANY_TCBS 155
+#define ERROR_SIGNAL_REFUSED 156
+#define ERROR_DISCARDED 157
+#define ERROR_NOT_LOCKED 158
+#define ERROR_BAD_THREADID_ADDR 159
+#define ERROR_BAD_ARGUMENTS 160
+#define ERROR_BAD_PATHNAME 161
+#define ERROR_SIGNAL_PENDING 162
+#define ERROR_UNCERTAIN_MEDIA 163
+#define ERROR_MAX_THRDS_REACHED 164
+#define ERROR_MONITORS_NOT_SUPPORTED 165
+
+#define ERROR_INVALID_SEGMENT_NUMBER 180
+#define ERROR_INVALID_CALLGATE 181
+#define ERROR_INVALID_ORDINAL 182
+#define ERROR_ALREADY_EXISTS 183
+#define ERROR_NO_CHILD_PROCESS 184
+#define ERROR_CHILD_ALIVE_NOWAIT 185
+#define ERROR_INVALID_FLAG_NUMBER 186
+#define ERROR_SEM_NOT_FOUND 187
+
+/* following error codes have added to make the loader error
+ messages distinct
+*/
+
+#define ERROR_INVALID_STARTING_CODESEG 188
+#define ERROR_INVALID_STACKSEG 189
+#define ERROR_INVALID_MODULETYPE 190
+#define ERROR_INVALID_EXE_SIGNATURE 191
+#define ERROR_EXE_MARKED_INVALID 192
+#define ERROR_BAD_EXE_FORMAT 193
+#define ERROR_ITERATED_DATA_EXCEEDS_64k 194
+#define ERROR_INVALID_MINALLOCSIZE 195
+#define ERROR_DYNLINK_FROM_INVALID_RING 196
+#define ERROR_IOPL_NOT_ENABLED 197
+#define ERROR_INVALID_SEGDPL 198
+#define ERROR_AUTODATASEG_EXCEEDS_64k 199
+#define ERROR_RING2SEG_MUST_BE_MOVABLE 200
+#define ERROR_RELOC_CHAIN_XEEDS_SEGLIM 201
+#define ERROR_INFLOOP_IN_RELOC_CHAIN 202
+
+#define ERROR_ENVVAR_NOT_FOUND 203
+#define ERROR_NOT_CURRENT_CTRY 204
+#define ERROR_NO_SIGNAL_SENT 205
+#define ERROR_FILENAME_EXCED_RANGE 206 /* if filename > 8.3 */
+#define ERROR_RING2_STACK_IN_USE 207 /* for FAPI */
+#define ERROR_META_EXPANSION_TOO_LONG 208 /* if "*a" > 8.3 */
+
+#define ERROR_INVALID_SIGNAL_NUMBER 209
+#define ERROR_THREAD_1_INACTIVE 210
+#define ERROR_INFO_NOT_AVAIL 211 /*@@ PTM 5550 */
+#define ERROR_LOCKED 212
+#define ERROR_BAD_DYNALINK 213 /*@@ PTM 5760 */
+#define ERROR_TOO_MANY_MODULES 214
+#define ERROR_NESTING_NOT_ALLOWED 215
+
+/*
+ * Error codes 230 - 249 are reserved for MS Networks
+ */
+
+#define ERROR_USER_DEFINED_BASE 0xF000
+
+#define ERROR_I24_WRITE_PROTECT 0
+#define ERROR_I24_BAD_UNIT 1
+#define ERROR_I24_NOT_READY 2
+#define ERROR_I24_BAD_COMMAND 3
+#define ERROR_I24_CRC 4
+#define ERROR_I24_BAD_LENGTH 5
+#define ERROR_I24_SEEK 6
+#define ERROR_I24_NOT_DOS_DISK 7
+#define ERROR_I24_SECTOR_NOT_FOUND 8
+#define ERROR_I24_OUT_OF_PAPER 9
+#define ERROR_I24_WRITE_FAULT 0x0A
+#define ERROR_I24_READ_FAULT 0x0B
+#define ERROR_I24_GEN_FAILURE 0x0C
+#define ERROR_I24_DISK_CHANGE 0x0D
+#define ERROR_I24_WRONG_DISK 0x0F
+#define ERROR_I24_UNCERTAIN_MEDIA 0x10
+#define ERROR_I24_CHAR_CALL_INTERRUPTED 0x11
+#define ERROR_I24_NO_MONITOR_SUPPORT 0x12
+#define ERROR_I24_INVALID_PARAMETER 0x13
+
+#define ALLOWED_FAIL 0x0001
+#define ALLOWED_ABORT 0x0002
+#define ALLOWED_RETRY 0x0004
+#define ALLOWED_IGNORE 0x0008
+
+#define I24_OPERATION 0x1
+#define I24_AREA 0x6
+ /* 01 if FAT */
+ /* 10 if root DIR */
+ /* 11 if DATA */
+#define I24_CLASS 0x80
+
+
+/* Values for error CLASS */
+
+#define ERRCLASS_OUTRES 1 /* Out of Resource */
+#define ERRCLASS_TEMPSIT 2 /* Temporary Situation */
+#define ERRCLASS_AUTH 3 /* Permission problem */
+#define ERRCLASS_INTRN 4 /* Internal System Error */
+#define ERRCLASS_HRDFAIL 5 /* Hardware Failure */
+#define ERRCLASS_SYSFAIL 6 /* System Failure */
+#define ERRCLASS_APPERR 7 /* Application Error */
+#define ERRCLASS_NOTFND 8 /* Not Found */
+#define ERRCLASS_BADFMT 9 /* Bad Format */
+#define ERRCLASS_LOCKED 10 /* Locked */
+#define ERRCLASS_MEDIA 11 /* Media Failure */
+#define ERRCLASS_ALREADY 12 /* Collision with Existing Item */
+#define ERRCLASS_UNK 13 /* Unknown/other */
+#define ERRCLASS_CANT 14
+#define ERRCLASS_TIME 15
+
+/* Values for error ACTION */
+
+#define ERRACT_RETRY 1 /* Retry */
+#define ERRACT_DLYRET 2 /* Delay Retry, retry after pause */
+#define ERRACT_USER 3 /* Ask user to regive info */
+#define ERRACT_ABORT 4 /* abort with clean up */
+#define ERRACT_PANIC 5 /* abort immediately */
+#define ERRACT_IGNORE 6 /* ignore */
+#define ERRACT_INTRET 7 /* Retry after User Intervention */
+
+/* Values for error LOCUS */
+
+#define ERRLOC_UNK 1 /* No appropriate value */
+#define ERRLOC_DISK 2 /* Random Access Mass Storage */
+#define ERRLOC_NET 3 /* Network */
+#define ERRLOC_SERDEV 4 /* Serial Device */
+#define ERRLOC_MEM 5 /* Memory */
+
+/* Abnormal termination codes */
+
+#define TC_NORMAL 0
+#define TC_HARDERR 1
+#define TC_GP_TRAP 2
+#define TC_SIGNAL 3
+
+#define _INC_ERROR
+#endif /* _INC_ERROR */
diff --git a/private/crt32/h/error2.h b/private/crt32/h/error2.h
new file mode 100644
index 000000000..550449942
--- /dev/null
+++ b/private/crt32/h/error2.h
@@ -0,0 +1,277 @@
+/***
+*error2.h - OS/2 error codes
+*
+* Copyright (c) 1987-1990, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file lists the OS/2 error codes.
+*
+*Revision History:
+* 10-25-87 SKS Updated from final OS/2 v1.0 source as of 10-25-87
+* 08-03-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 02-28-90 GJF Added #ifndef _INC_ERROR2 stuff
+*
+****/
+
+#ifndef _INC_ERROR2
+
+/* SCCSID = @(#)error2.h 8.17 87/08/06 */
+/****************************************************************/
+/* */
+/* FILE NAME: ERROR2.H */
+/* */
+/* COPYRIGHT: IBM Corp., 1987 */
+/* */
+/* REVISION LEVEL: 1.0 */
+/* */
+/* WHAT THIS FILE DOES: */
+/* This file contains equates associating error codes */
+/* returned from system function calls. The equates */
+/* in this file start at 303. You must include */
+/* ERROR.H for return codes under 303. */
+/* */
+/* WHAT YOU NEED TO USE THIS FILE: */
+/* */
+/* IN YOUR SOURCE PROGRAM: */
+/* */
+/* #include <ERROR2.H> */
+/* */
+/****************************************************************/
+
+#define ERROR_INVALID_PROCID 303 /* invalid process id */
+#define ERROR_INVALID_PDELTA 304 /* invalid priority delta */
+#define ERROR_NOT_DESCENDANT 305 /* not descendant */
+#define ERROR_NOT_SESSION_MANAGER 306 /* requestor not session manager */
+#define ERROR_INVALID_PCLASS 307 /* invalid p class */
+#define ERROR_INVALID_SCOPE 308 /* invalid scope */
+#define ERROR_INVALID_THREADID 309 /* invalid thread id */
+#define ERROR_DOSSUB_SHRINK 310 /* can't shrink - MspSet */
+#define ERROR_DOSSUB_NOMEM 311 /* no memory - MspAlloc */
+#define ERROR_DOSSUB_OVERLAP 312 /* overlap - MspFree */
+#define ERROR_DOSSUB_BADSIZE 313 /* bad size parameter - MspAlloc or MspFree */
+#define ERROR_DOSSUB_BADFLAG 314 /* bad flag parameter - MspSet */
+#define ERROR_DOSSUB_BADSELECTOR 315 /* invalid MspSegment Selector */
+#define ERROR_MR_MSG_TOO_LONG 316 /* message too long for buffer */
+#define ERROR_MR_MID_NOT_FOUND 317 /* message id number not found */
+#define ERROR_MR_UN_ACC_MSGF 318 /* unable to access message file */
+#define ERROR_MR_INV_MSGF_FORMAT 319 /* invalid message file format */
+#define ERROR_MR_INV_IVCOUNT 320 /* invalid insertion variable count */
+#define ERROR_MR_UN_PERFORM 321 /* unable to perform function */
+#define ERROR_TS_WAKEUP 322 /* unable to wake up */
+#define ERROR_TS_SEMHANDLE 323 /* user passed invalid system semaphore */
+#define ERROR_TS_NOTIMER 324 /* no times available */
+#define ERROR_TS_HANDLE 326 /* invalid timer handle */
+#define ERROR_TS_DATETIME 327 /* date or time invalid */
+#define ERROR_SYS_INTERNAL 328 /* internal system error */
+#define ERROR_QUE_CURRENT_NAME 329 /* current name does not exist */
+#define ERROR_QUE_PROC_NOT_OWNED 330 /* current process does not own queue */
+#define ERROR_QUE_PROC_OWNED 331 /* current process owns queue */
+#define ERROR_QUE_DUPLICATE 332 /* duplicate name */
+#define ERROR_QUE_ELEMENT_NOT_EXIST 333 /* element does not exist */
+#define ERROR_QUE_NO_MEMORY 334 /* inadequate memory */
+#define ERROR_QUE_INVALID_NAME 335 /* invalid name */
+#define ERROR_QUE_INVALID_PRIORITY 336 /* invalid priority parameter */
+#define ERROR_QUE_INVALID_HANDLE 337 /* invalid queue handle */
+#define ERROR_QUE_LINK_NOT_FOUND 338 /* link not found */
+#define ERROR_QUE_MEMORY_ERROR 339 /* memory error */
+#define ERROR_QUE_PREV_AT_END 340 /* previous element was at end of queue */
+#define ERROR_QUE_PROC_NO_ACCESS 341 /* process does not have access to queues */
+#define ERROR_QUE_EMPTY 342 /* queue is empty */
+#define ERROR_QUE_NAME_NOT_EXIST 343 /* queue name does not exist */
+#define ERROR_QUE_NOT_INITIALIZED 344 /* queues not initialized */
+#define ERROR_QUE_UNABLE_TO_ACCESS 345 /* unable to access queues */
+#define ERROR_QUE_UNABLE_TO_ADD 346 /* unable to add new queue */
+#define ERROR_QUE_UNABLE_TO_INIT 347 /* unable to initialize queues */
+#define ERROR_VIO_INVALID_MASK 349 /* invalid replacement mask */
+#define ERROR_VIO_PTR 350 /* invalid pointer to parameter */
+#define ERROR_VIO_APTR 351 /* invalid pointer to attribute */
+#define ERROR_VIO_RPTR 352 /* invalid pointer to row */
+#define ERROR_VIO_CPTR 353 /* invalid pointer to column */
+#define ERROR_VIO_LPTR 354 /* invalid pointer to length */
+#define ERROR_VIO_MODE 355 /* unsupported screen mode */
+#define ERROR_VIO_WIDTH 356 /* invalid cursor width value */
+#define ERROR_VIO_ATTR 357 /* invalid cursor attribute value */
+#define ERROR_VIO_ROW 358 /* invalid row value */
+#define ERROR_VIO_COL 359 /* invalid column value */
+#define ERROR_VIO_TOPROW 360 /* invalid toprow value */
+#define ERROR_VIO_BOTROW 361 /* invalid botrow value */
+#define ERROR_VIO_RIGHTCOL 362 /* invalid right column value */
+#define ERROR_VIO_LEFTCOL 363 /* invalid left column value */
+#define ERROR_SCS_CALL 364 /* call issued by other than sm */
+#define ERROR_SCS_VALUE 365 /* value is not for save or restore */
+#define ERROR_VIO_WAIT_FLAG 366 /* invalid wait flag setting */
+#define ERROR_VIO_UNLOCK 367 /* screen not previously locked */
+#define ERROR_SGS_NOT_SESSION_MGR 368 /* caller not session manager */
+#define ERROR_SMG_INVALID_SGID 369 /* invalid screen group id */
+#define ERROR_SMG_INVALID_SESSION_ID 369 /* invalid session id */
+#define ERROR_SMG_NOSG 370 /* all screen groups in use */
+#define ERROR_SMG_NO_SESSIONS 370 /* no sessions available */
+#define ERROR_SMG_GRP_NOT_FOUND 371 /* screen group not found */
+#define ERROR_SMG_SESSION_NOT_FOUND 371 /* session not found */
+#define ERROR_SMG_SET_TITLE 372 /* title set by shell or parent cant be changed */
+#define ERROR_KBD_PARAMETER 373 /* invalid parameter to kbd */
+#define ERROR_KBD_NO_DEVICE 374 /* out of system handles */
+#define ERROR_KBD_INVALID_IOWAIT 375 /* invalid i/o wait specified */
+#define ERROR_KBD_INVALID_LENGTH 376 /* invalid length for keyboard */
+#define ERROR_KBD_INVALID_ECHO_MASK 377 /* invalid echo mode mask */
+#define ERROR_KBD_INVALID_INPUT_MASK 378 /* invalid input mode mask */
+#define ERROR_MON_INVALID_PARMS 379 /* invalid parameters to dos mon */
+#define ERROR_MON_INVALID_DEVNAME 380 /* invalid device name string */
+#define ERROR_MON_INVALID_HANDLE 381 /* invalid device handle */
+#define ERROR_MON_BUFFER_TOO_SMALL 382 /* buffer too small */
+#define ERROR_MON_BUFFER_EMPTY 383 /* buffer is empty */
+#define ERROR_MON_DATA_TOO_LARGE 384 /* data record too large */
+#define ERROR_MOUSE_NO_DEVICE 385 /* no mouse device attached */
+#define ERROR_MOUSE_INV_HANDLE 386 /* mouse device closed (invalid device handle) */
+#define ERROR_MOUSE_INV_PARMS 387 /* parameters invalid or out of range */
+#define ERROR_MOUSE_CANT_RESET 388 /* function assigned and cannot be reset */
+#define ERROR_MOUSE_DISPLAY_PARMS 389 /* parameters invalid for display mode */
+#define ERROR_MOUSE_INV_MODULE 390 /* module not found */
+#define ERROR_MOUSE_INV_ENTRY_PT 391 /* entry point not valid */
+#define ERROR_MOUSE_INV_MASK 392 /* function mask invalid */
+#define NO_ERROR_MOUSE_NO_DATA 393 /* no mouse data */
+#define NO_ERROR_MOUSE_PTR_DRAWN 394 /* pointer drawn */
+#define ERROR_INVALID_FREQUENCY 395 /* invalid frequency for beep */
+#define ERROR_NLS_NO_COUNTRY_FILE 396 /* can't find country.sys */
+#define ERROR_NLS_OPEN_FAILED 397 /* can't open country.sys */
+#define ERROR_NLS_NO_CTRY_CODE 398 /* country code not found */
+#define ERROR_NO_COUNTRY_OR_CODEPAGE 398 /* country code not found */
+#define ERROR_NLS_TABLE_TRUNCATED 399 /* table truncated, buffer too small */
+#define ERROR_NLS_BAD_TYPE 400 /* selector type does not exist */
+#define ERROR_NLS_TYPE_NOT_FOUND 401 /* selector type not in file */
+#define ERROR_VIO_SMG_ONLY 402 /* valid from session manager only */
+#define ERROR_VIO_INVALID_ASCIIZ 403 /* invalid asciiz length */
+#define ERROR_VIO_DEREGISTER 404 /* vio deregister disallowed */
+#define ERROR_VIO_NO_POPUP 405 /* popup not allocated */
+#define ERROR_VIO_EXISTING_POPUP 406 /* popup on screen (no wait) */
+#define ERROR_KBD_SMG_ONLY 407 /* valid from session manager only */
+#define ERROR_KBD_INVALID_ASCIIZ 408 /* invalid asciiz length */
+#define ERROR_KBD_INVALID_MASK 409 /* invalid replacement mask */
+#define ERROR_KBD_REGISTER 410 /* kbdregister disallowed */
+#define ERROR_KBD_DEREGISTER 411 /* kbdderegister disalloed */
+#define ERROR_MOUSE_SMG_ONLY 412 /* valid from session manager only */
+#define ERROR_MOUSE_INVALID_ASCIIZ 413 /* invalid asciiz length */
+#define ERROR_MOUSE_INVALID_MASK 414 /* invalid replacement mask */
+#define ERROR_MOUSE_REGISTER 415 /* mouse register disallowed */
+#define ERROR_MOUSE_DEREGISTER 416 /* mouse deregister disallowed */
+#define ERROR_SMG_BAD_ACTION 417 /* invalid action specified */
+#define ERROR_SMG_INVALID_CALL 418 /* init called more than once */
+#define ERROR_SCS_SG_NOTFOUND 419 /* new screen group # */
+#define ERROR_SCS_NOT_SHELL 420 /* caller is not shell */
+#define ERROR_VIO_INVALID_PARMS 421 /* invalid parms passed in */
+#define ERROR_VIO_FUNCTION_OWNED 422 /* save/restore already owned */
+#define ERROR_VIO_RETURN 423 /* non-destruct return (undo) */
+#define ERROR_SCS_INVALID_FUNCTION 424 /* not valid request for caller */
+#define ERROR_SCS_NOT_SESSION_MGR 425 /* caller not session manager */
+#define ERROR_VIO_REGISTER 426 /* VIO register disallowed */
+#define ERROR_VIO_NO_MODE_THREAD 427 /* No mode restore thread in SG */
+#define ERROR_VIO_NO_SAVE_RESTORE_THD 428 /* No save/rest thread in SG */
+#define ERROR_VIO_IN_BG 429 /* Physical selector requested in background */
+#define ERROR_VIO_ILLEGAL_DURING_POPUP 430 /* Function not allowed during popup */
+#define ERROR_SMG_NOT_BASESHELL 431 /* caller is not the base shell */
+#define ERROR_SMG_BAD_STATUSREQ 432 /* invalid status requested */
+#define ERROR_QUE_INVALID_WAIT 433 /* nowait parameter out of bounds */
+#define ERROR_VIO_LOCK 434 /* error returned from scrlock */
+#define ERROR_MOUSE_INVALID_IOWAIT 435 /* invalid parameters for IO wait */
+#define ERROR_VIO_INVALID_HANDLE 436 /* invalid vio handle */
+#define ERROR_VIO_ILLEGAL_DURING_LOCK 437 /* Function not allowed during screen lock */
+#define ERROR_VIO_INVALID_LENGTH 438 /* invalid vio length */
+#define ERROR_KBD_INVALID_HANDLE 439 /* invalid kbd handle */
+#define ERROR_KBD_NO_MORE_HANDLE 440 /* ran out of handles */
+#define ERROR_KBD_CANNOT_CREATE_KCB 441 /* unable to create kcb */
+#define ERROR_KBD_CODEPAGE_LOAD_INCOMPL 442 /* unsuccessful codepage load */
+#define ERROR_KBD_INVALID_CODEPAGE_ID 443 /* invalid codepage id */
+#define ERROR_KBD_NO_CODEPAGE_SUPPORT 444 /* no codepage support */
+#define ERROR_KBD_FOCUS_REQUIRED 445 /* keyboard focus required */
+#define ERROR_KBD_FOCUS_ALREADY_ACTIVE 446 /* keyboard focus exists */
+#define ERROR_KBD_KEYBOARD_BUSY 447 /* keyboard busy */
+#define ERROR_KBD_INVALID_CODEPAGE 448 /* invalid codepage */
+#define ERROR_KBD_UNABLE_TO_FOCUS 449 /* focus attempt failed */
+#define ERROR_SMG_SESSION_NON_SELECT 450 /* session is not selectable */
+#define ERROR_SMG_SESSION_NOT_FOREGRND 451 /* parent/child session not foreground */
+#define ERROR_SMG_SESSION_NOT_PARENT 452 /* not parent of requested child */
+#define ERROR_SMG_INVALID_START_MODE 453 /* invalid session start mode */
+#define ERROR_SMG_INVALID_RELATED_OPT 454 /* invalid session start related option */
+#define ERROR_SMG_INVALID_BOND_OPTION 455 /* invalid session bond option */
+#define ERROR_SMG_INVALID_SELECT_OPT 456 /* invalid session select option */
+#define ERROR_SMG_START_IN_BACKGROUND 457 /* session started in background */
+#define ERROR_SMG_INVALID_STOP_OPTION 458 /* invalid session stop option */
+#define ERROR_SMG_BAD_RESERVE 459 /* reserved parameters not zero */
+#define ERROR_SMG_PROCESS_NOT_PARENT 460 /* session parent process already exists */
+#define ERROR_SMG_INVALID_DATA_LENGTH 461 /* invalid data length */
+#define ERROR_SMG_NOT_BOUND 462 /* parent not bound */
+#define ERROR_SMG_RETRY_SUB_ALLOC 463 /* retry request block allocation */
+#define ERROR_KBD_DETACHED 464 /* this call disallawed for detached pid */
+#define ERROR_VIO_DETACHED 465 /* this call disallawed for detached pid */
+#define ERROR_MOU_DETACHED 466 /* this call disallawed for detached pid */
+#define ERROR_VIO_FONT 467 /* no font available to support mode */
+#define ERROR_VIO_USER_FONT 468 /* user font active */
+#define ERROR_VIO_BAD_CP 469 /* invalid code page specified */
+#define ERROR_VIO_NO_CP 470 /* system displays don't support code page */
+#define ERROR_VIO_NA_CP 471 /* current displays doesn't support code page */
+#define ERROR_INVALID_CODE_PAGE 472 /* invalid code page */
+#define ERROR_CPLIST_TOO_SMALL 473 /* code page list is too small */
+#define ERROR_CP_NOT_MOVED 474 /* code page not moved */
+#define ERROR_MODE_SWITCH_INIT 475 /* mode switch init error */
+#define ERROR_CODE_PAGE_NOT_FOUND 476 /* code page not found */
+#define ERROR_UNEXPECTED_SLOT_RETURNED 477 /* internal error */
+#define ERROR_SMG_INVALID_TRACE_OPTION 478 /* invalid start session trace indicator */
+#define ERROR_VIO_INTERNAL_RESOURCE 479 /* vio internal resource error */
+#define ERROR_VIO_SHELL_INIT 480 /* vio shell init error */
+#define ERROR_SMG_NO_HARD_ERRORS 481 /* no session manager hard errors */
+#define ERROR_CP_SWITCH_INCOMPLETE 482 /* dossetcp unable to set kbd/vio cp */
+#define ERROR_VIO_TRANSPARENT_POPUP 483 /* error during vio popup */
+#define ERROR_CRITSEC_OVERFLOW 484 /* critical section overflow */
+#define ERROR_CRITSEC_UNDERFLOW 485 /* critical section underflow */
+#define ERROR_VIO_BAD_RESERVE 486 /* reserved parameter is not zero */
+#define ERROR_INVALID_ADDRESS 487 /* bad physical address */
+#define ERROR_ZERO_SELECTORS_REQUESTED 488 /* must request at least on selector */
+#define ERROR_NOT_ENOUGH_SELECTORS_AVA 489 /* not enought GDT selectors to satisfy request */
+#define ERROR_INVALID_SELECTOR 490 /* not a GDT selector */
+
+/* */
+/* intercomponent error codes (from 8000H or 32768) */
+/* */
+#define ERROR_SWAPPER_NOT_ACTIVE 32768 /* swapper is not active */
+#define ERROR_INVALID_SWAPID 32769 /* invalid swap identifier */
+#define ERROR_IOERR_SWAP_FILE 32770 /* i/o error on swap file */
+#define ERROR_SWAP_TABLE_FULL 32771 /* swap control table is full */
+#define ERROR_SWAP_FILE_FULL 32772 /* swap file is full */
+#define ERROR_CANT_INIT_SWAPPER 32773 /* cannot initialize swapper */
+#define ERROR_SWAPPER_ALREADY_INIT 32774 /* swapper already initialized */
+#define ERROR_PMM_INSUFFICIENT_MEMORY 32775 /* insufficient memory */
+#define ERROR_PMM_INVALID_FLAGS 32776 /* invalid flags for phys. mem. */
+#define ERROR_PMM_INVALID_ADDRESS 32777 /* invalid address of phys. mem. */
+#define ERROR_PMM_LOCK_FAILED 32778 /* lock of storage failed */
+#define ERROR_PMM_UNLOCK_FAILED 32779 /* unlock of storage failed */
+#define ERROR_PMM_MOVE_INCOMPLETE 32780 /* move not completed */
+#define ERROR_UCOM_DRIVE_RENAMED 32781 /* drive name was renamed */
+#define ERROR_UCOM_FILENAME_TRUNCATED 32782 /* file name was truncated */
+#define ERROR_UCOM_BUFFER_LENGTH 32783 /* bad buffer length */
+#define ERROR_MON_CHAIN_HANDLE 32784 /* invalid chain handle - mon dh */
+#define ERROR_MON_NOT_REGISTERED 32785 /* monitor not registered */
+#define ERROR_SMG_ALREADY_TOP 32786 /* specified screen group is top */
+#define ERROR_PMM_ARENA_MODIFIED 32787 /* arena modified - phys mem */
+#define ERROR_SMG_PRINTER_OPEN 32788 /* printer open error on prtsc */
+#define ERROR_PMM_SET_FLAGS_FAILED 32789 /* update to arena header flags failed */
+#define ERROR_INVALID_DOS_DD 32790 /* invalid DOS mode device driver */
+#define ERROR_CPSIO_CODE_PAGE_INVALID 65026 /* code page is not available */
+#define ERROR_CPSIO_NO_SPOOLER 65027 /* spooler not started */
+#define ERROR_CPSIO_FONT_ID_INVALID 65028 /* font id is not avail (verify) */
+#define ERROR_CPSIO_INTERNAL_ERROR 65033 /* error caused by switcher internal error */
+#define ERROR_CPSIO_INVALID_PTR_NAME 65034 /* error caused by invalid printer name input */
+#define ERROR_CPSIO_NOT_ACTIVE 65037 /* got code page req - cp switcher not initialized */
+#define ERROR_CPSIO_PID_FULL 65039 /* pid table full- cannot activate another entry */
+#define ERROR_CPSIO_PID_NOT_FOUND 65040 /* received request for pid not in table */
+#define ERROR_CPSIO_READ_CTL_SEQ 65043 /* error reading font file control sequence section */
+#define ERROR_CPSIO_READ_FNT_DEF 65045 /* error reading font file font definition block */
+#define ERROR_CPSIO_WRITE_ERROR 65047 /* error writing to temp spool file */
+#define ERROR_CPSIO_WRITE_FULL_ERROR 65048 /* disk full error writing temp spool file */
+#define ERROR_CPSIO_WRITE_HANDLE_BAD 65049 /* spool file handle bad */
+#define ERROR_CPSIO_SWIT_LOAD 65074 /* switcher load error */
+#define ERROR_CPSIO_INV_COMMAND 65077 /* invalid spool command */
+#define ERROR_CPSIO_NO_FONT_SWIT 65078 /* no font switch active */
+
+#define _INC_ERROR2
+#endif /* _INC_ERROR2 */
diff --git a/private/crt32/h/except.inc b/private/crt32/h/except.inc
new file mode 100644
index 000000000..938a141b2
--- /dev/null
+++ b/private/crt32/h/except.inc
@@ -0,0 +1,100 @@
+;***
+;except.inc - definitions for exception handling
+;
+; Copyright (c) 1990-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Structure and constant definitions used by exception handling code.
+;
+;Revision History:
+; 07-19-90 GJF Module created.
+; 08-28-90 GJF Added some definitions of exceptions.
+; 10-19-90 GJF Revised some constants to agree with the definitions in
+; \\os2rel\public!2.0\h\bsexcpt.h (dated 10-1-90).
+; 07-30-91 GJF Different values of _XCPT_CONTINUE_[SEARCH|EXECUTION]
+; for Cruiser and Win32 [_WIN32_].
+;
+;*******************************************************************************
+
+; structure used by SEH support function and intrinsics. the information
+; passed by the OS exception dispatcher is repackaged in this form by the
+; runtime (_except_handler()).
+
+__EXCEPTION_INFO_PTRS struc
+ preport dd ?
+ pcontext dd ?
+__EXCEPTION_INFO_PTRS ends
+
+
+; exception registration record structure.
+
+__EXCEPTIONREGISTRATIONRECORD struc
+ prev_structure dd ?
+ ExceptionHandler dd ?
+ ExceptionFilter dd ?
+ FilterFrame dd ?
+ PExceptionInfoPtrs dd ?
+__EXCEPTIONREGISTRATIONRECORD ends
+
+; size of exception registration record in double words
+
+DWORDS_IN_XREGREC equ 5
+
+
+; exception report record
+
+__EXCEPTIONREPORTRECORD struc
+ ExceptionNum dd ?
+ fHandlerFlags dd ?
+ ExceptionReportRecord dd ?
+ ExceptionAddress dd ?
+ cParameters dd ?
+ ExceptionInfo dd 4 dup (?)
+__EXCEPTIONREPORTRECORD ends
+
+
+; setjmp/longjmp buffer (i.e., structure underlying jmp_buf array)
+
+_JMP_BUF struc
+ ebpsave dd ?
+ ebxsave dd ?
+ edisave dd ?
+ esisave dd ?
+ espsave dd ?
+ retsave dd ?
+ xcptsave dd ?
+_JMP_BUF ends
+
+
+; exceptions corresponding to C runtime errors (these are explicitly
+; referenced in the startup code)
+
+_XCPT_UNABLE_TO_GROW_STACK equ 080010001h
+_XCPT_INTEGER_DIVIDE_BY_ZERO equ 0C000009Bh
+_XCPT_NONCONTINUABLE_EXCEPTION equ 0C0000024h
+_XCPT_INVALID_DISPOSITION equ 0C0000025h
+_XCPT_SIGABRT equ 020000001h
+
+
+; unwind settings in fHandlerFlags
+
+_EH_UNWINDING equ 2
+_EH_EXIT_UNWIND equ 4
+UNWIND equ _EH_UNWINDING OR _EH_EXIT_UNWIND
+
+
+; return values (to the exception dispatcher)
+
+IFDEF _CRUISER_
+
+_XCPT_CONTINUE_SEARCH equ 000000000h
+_XCPT_CONTINUE_EXECUTION equ 0FFFFFFFFh
+
+ELSE
+IFDEF _WIN32_
+
+_XCPT_CONTINUE_SEARCH equ 000000001h
+_XCPT_CONTINUE_EXECUTION equ 000000000h
+
+ENDIF
+ENDIF
diff --git a/private/crt32/h/excpt.h b/private/crt32/h/excpt.h
new file mode 100644
index 000000000..c73e08d29
--- /dev/null
+++ b/private/crt32/h/excpt.h
@@ -0,0 +1,209 @@
+/***
+*excpt.h - defines exception values, types and routines
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the definitions and prototypes for the compiler-
+* dependent intrinsics, support functions and keywords which implement
+* the structured exception handling extensions.
+*
+*Revision History:
+* 11-01-91 GJF Module created. Basically a synthesis of except.h
+* and excpt.h and intended as a replacement for
+* both.
+* 12-13-91 GJF Fixed build for Win32.
+* 05-05-92 SRW C8 wants C6 style names for now.
+* 07-20-92 SRW Moved from winxcpt.h to excpt.h
+* 08-06-92 GJF Function calling type and variable type macros. Also
+* revised compiler/target processor macro usage.
+* 11-09-92 GJF Fixed preprocessing conditionals for MIPS. Also,
+* fixed some compiler warning (fix from/for RichardS).
+* 01-03-93 SRW Fold in ALPHA changes
+* 01-04-93 SRW Add leave keyword for x86
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 02-18-93 GJF Changed _try to __try, etc.
+* 10-04-93 SRW Fix ifdefs for MIPS and ALPHA to only check for _M_?????? defines
+*
+****/
+
+#ifndef _INC_EXCPT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/*
+ * Exception disposition return values.
+ */
+typedef enum _EXCEPTION_DISPOSITION {
+ ExceptionContinueExecution,
+ ExceptionContinueSearch,
+ ExceptionNestedException,
+ ExceptionCollidedUnwind
+} EXCEPTION_DISPOSITION;
+
+
+/*
+ * Prototype for SEH support function.
+ */
+
+#ifdef _M_IX86
+
+/*
+ * Declarations to keep MS C 8 (386/486) compiler happy
+ */
+struct _EXCEPTION_RECORD;
+struct _CONTEXT;
+
+EXCEPTION_DISPOSITION _CRTAPI2 _except_handler (
+ struct _EXCEPTION_RECORD *ExceptionRecord,
+ void * EstablisherFrame,
+ struct _CONTEXT *ContextRecord,
+ void * DispatcherContext
+ );
+
+#elif defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+
+/*
+ * Declarations to keep MIPS, ALPHA, and PPC compiler happy
+ */
+typedef struct _EXCEPTION_POINTERS *Exception_info_ptr;
+struct _EXCEPTION_RECORD;
+struct _CONTEXT;
+struct _DISPATCHER_CONTEXT;
+
+
+EXCEPTION_DISPOSITION __C_specific_handler (
+ struct _EXCEPTION_RECORD *ExceptionRecord,
+ void *EstablisherFrame,
+ struct _CONTEXT *ContextRecord,
+ struct _DISPATCHER_CONTEXT *DispatcherContext
+ );
+
+#endif
+
+
+/*
+ * Keywords and intrinsics for SEH
+ */
+
+#ifdef _MSC_VER
+
+#if !defined(__cplusplus)
+#define try __try
+#define except __except
+#define finally __finally
+#define leave __leave
+#endif
+#define GetExceptionCode() (_exception_code())
+#define exception_code() (_exception_code())
+#define GetExceptionInformation() ((struct _EXCEPTION_POINTERS *)_exception_info())
+#define exception_info() ((struct _EXCEPTION_POINTERS *)_exception_info())
+#define AbnormalTermination() (_abnormal_termination())
+#define abnormal_termination() (_abnormal_termination())
+
+unsigned long _CRTAPI1 _exception_code(void);
+void * _CRTAPI1 _exception_info(void);
+int _CRTAPI1 _abnormal_termination(void);
+
+#endif
+
+
+/*
+ * Legal values for expression in except().
+ */
+
+#define EXCEPTION_EXECUTE_HANDLER 1
+#define EXCEPTION_CONTINUE_SEARCH 0
+#define EXCEPTION_CONTINUE_EXECUTION -1
+
+
+#ifndef _INTERNAL_IFSTRIP_
+/*
+ * for convenience, define a type name for a pointer to signal-handler
+ */
+
+typedef void (_CRTAPI1 * _PHNDLR)(int);
+
+/*
+ * Exception-action table used by the C runtime to identify and dispose of
+ * exceptions corresponding to C runtime errors or C signals.
+ */
+struct _XCPT_ACTION {
+
+ /*
+ * exception code or number. defined by the host OS.
+ */
+ unsigned long XcptNum;
+
+ /*
+ * signal code or number. defined by the C runtime.
+ */
+ int SigNum;
+
+ /*
+ * exception action code. either a special code or the address of
+ * a handler function. always determines how the exception filter
+ * should dispose of the exception.
+ */
+ _PHNDLR XcptAction;
+};
+
+extern struct _XCPT_ACTION _CRTVAR1 _XcptActTab[];
+
+/*
+ * number of entries in the exception-action table
+ */
+
+extern int _CRTVAR1 _XcptActTabCount;
+
+/*
+ * size of exception-action table (in bytes)
+ */
+
+extern int _CRTVAR1 _XcptActTabSize;
+
+/*
+ * return values and prototype for the exception filter function used in the
+ * C startup
+ */
+int _CRTAPI1 _XcptFilter(unsigned long, struct _EXCEPTION_POINTERS *);
+
+#endif /* _INTERNAL_IFSTRIP_ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_EXCPT
+#endif /* _INC_EXCPT */
diff --git a/private/crt32/h/exsup.inc b/private/crt32/h/exsup.inc
new file mode 100644
index 000000000..7cf621d91
--- /dev/null
+++ b/private/crt32/h/exsup.inc
@@ -0,0 +1,79 @@
+;***
+;exsup.inc
+;
+; Copyright (C) 1993, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Common data structures & definitions for exsup.asm and other
+; Structured Exception Handling support modules.
+;
+;Revision History:
+; 04-13-93 JWM Initial version
+; 12-05-93 PML Update for C9.0
+; 01-12-94 PML Move jmp_buf struct here, add new fields
+;
+;******************************************************************************
+
+
+;handler dispositions
+DISPOSITION_DISMISS equ 0
+DISPOSITION_CONTINUE_SEARCH equ 1
+DISPOSITION_NESTED_EXCEPTION equ 2
+DISPOSITION_COLLIDED_UNWIND equ 3
+
+;filter return codes
+FILTER_ACCEPT equ 1
+FILTER_DISMISS equ -1
+FILTER_CONTINUE_SEARCH equ 0
+
+;handler flags settings..
+EXCEPTION_UNWINDING equ 2
+EXCEPTION_EXIT_UNWIND equ 4
+EXCEPTION_UNWIND_CONTEXT equ EXCEPTION_UNWINDING OR EXCEPTION_EXIT_UNWIND
+
+TRYLEVEL_NONE equ -1
+TRYLEVEL_INVALID equ -2
+
+;callback interface codes (mimimal required set)
+CB_GET_MAX_CODE equ 0
+CB_DO_LOCAL_UNWIND equ 1
+CB_GET_FRAME_EBP equ 2
+CB_GET_SCOPE_INDEX equ 3
+CB_GET_SCOPE_DATA equ 4
+MAX_CALLBACK_CODE equ 4
+
+;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION;
+;struct _EXCEPTION_REGISTRATION{
+; struct _EXCEPTION_REGISTRATION *prev;
+; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
+; struct scopetable_entry *scopetable;
+; int trylevel;
+; int _ebp;
+; PEXCEPTION_POINTERS xpointers;
+;};
+_EXCEPTION_REGISTRATION struc
+ prev dd ?
+ handler dd ?
+_EXCEPTION_REGISTRATION ends
+
+;setjmp/longjmp buffer
+_JMP_BUF struc
+ saved_ebp dd ?
+ saved_ebx dd ?
+ saved_edi dd ?
+ saved_esi dd ?
+ saved_esp dd ?
+ saved_return dd ?
+ saved_xregistration dd ?
+ saved_trylevel dd ?
+ ; following only found in C9.0 or later jmp_buf
+ version_cookie dd ?
+ unwind_func dd ?
+ unwind_data dd 6 dup(?)
+_JMP_BUF ends
+
+; Cookie placed in the jmp_buf to identify the new, longer form
+JMPBUF_COOKIE equ 'VC20'
+
+; Offset of TryLevel in a C8.0 SEH registration node
+C8_TRYLEVEL equ 12
diff --git a/private/crt32/h/fcntl.h b/private/crt32/h/fcntl.h
new file mode 100644
index 000000000..f476cc9f0
--- /dev/null
+++ b/private/crt32/h/fcntl.h
@@ -0,0 +1,84 @@
+/***
+*fcntl.h - file control options used by open()
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines constants for the file control options used
+* by the _open() function.
+* [System V]
+*
+*Revision History:
+* 06-19-87 JCR Added O_NOINHERIT
+* 08-18-88 GJF Modified (slightly) to also work for the 386.
+* 08-01-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright
+* 02-28-90 GJF Added #ifndef _INC_FCNTL stuff. Made the definition
+* of O_BINARY a 32-bit constant unconditionally.
+* 01-17-91 GJF ANSI naming.
+* 03-30-92 DJM POSIX support.
+* 05-02-92 SRW Add support for _O_TEMPORARY flag
+* 05-24-93 PML Add support for _O_SHORT_LIVED, _O_SEQUENTIAL,
+* _O_RANDOM
+*
+****/
+
+#ifndef _INC_FCNTL
+
+#define _O_RDONLY 0x0000 /* open for reading only */
+#define _O_WRONLY 0x0001 /* open for writing only */
+#define _O_RDWR 0x0002 /* open for reading and writing */
+#define _O_APPEND 0x0008 /* writes done at eof */
+
+#define _O_CREAT 0x0100 /* create and open file */
+#define _O_TRUNC 0x0200 /* open and truncate */
+#define _O_EXCL 0x0400 /* open only if file doesn't already exist */
+
+/* O_TEXT files have <cr><lf> sequences translated to <lf> on read()'s,
+** and <lf> sequences translated to <cr><lf> on write()'s
+*/
+
+#define _O_TEXT 0x4000 /* file mode is text (translated) */
+#define _O_BINARY 0x8000 /* file mode is binary (untranslated) */
+
+/* macro to translate the C 2.0 name used to force binary mode for files */
+
+#define _O_RAW _O_BINARY
+
+/* Open handle inherit bit */
+
+#define _O_NOINHERIT 0x0080 /* child process doesn't inherit file */
+
+/* Temporary file bit - file is deleted when last handle is closed */
+
+#define _O_TEMPORARY 0x0040 /* temporary file bit */
+
+/* temporary access hint */
+
+#define _O_SHORT_LIVED 0x1000 /* temporary storage file, try not to flush */
+
+/* sequential/random access hints */
+
+#define _O_SEQUENTIAL 0x0020 /* file access is primarily sequential */
+#define _O_RANDOM 0x0010 /* file access is primarily random */
+
+#if !__STDC__ || defined(_POSIX_)
+/* Non-ANSI names for compatibility */
+#define O_RDONLY _O_RDONLY
+#define O_WRONLY _O_WRONLY
+#define O_RDWR _O_RDWR
+#define O_APPEND _O_APPEND
+#define O_CREAT _O_CREAT
+#define O_TRUNC _O_TRUNC
+#define O_EXCL _O_EXCL
+#define O_TEXT _O_TEXT
+#define O_BINARY _O_BINARY
+#define O_RAW _O_BINARY
+#define O_TEMPORARY _O_TEMPORARY
+#define O_NOINHERIT _O_NOINHERIT
+#define O_SEQUENTIAL _O_SEQUENTIAL
+#define O_RANDOM _O_RANDOM
+#endif /* __STDC__ */
+
+#define _INC_FCNTL
+#endif /* _INC_FCNTL */
diff --git a/private/crt32/h/file2.h b/private/crt32/h/file2.h
new file mode 100644
index 000000000..06c2dddf2
--- /dev/null
+++ b/private/crt32/h/file2.h
@@ -0,0 +1,71 @@
+/***
+*file2.h - auxiliary file structure used internally by file run-time routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the auxiliary file structure used internally by
+* the file run time routines.
+* [Internal]
+*
+*Revision History:
+* 06-29-87 JCR Removed _OLD_IOLBF/_OLD_IOFBF and associated lbuf macro.
+* 09-28-87 JCR Added _iob_index(); modified ybuf() and tmpnum() to use it.
+* 06-03-88 JCR Added _iob2_ macro; modified ybuf()/tmpnum()/_iob_index;
+* also padded FILE2 definition to be the same size as FILE.
+* 06-10-88 JCR Added ybuf2()/bigbuf2()/anybuf2()
+* 06-14-88 JCR Added (FILE *) casts to _iob_index() macro
+* 06-29-88 JCR Added _IOFLRTN bit (flush stream on per routine basis)
+* 08-18-88 GJF Revised to also work with the 386 (small model only).
+* 12-05-88 JCR Added _IOCTRLZ bit (^Z encountered by lowio read)
+* 04-11-89 JCR Removed _IOUNGETC bit (no longer needed)
+* 07-27-89 GJF Cleanup, now specific to the 386. Struct field
+* alignment is now protected by pack pragma.
+* 10-30-89 GJF Fixed copyright
+* 02-16-90 GJF _iob[], _iob2[] merge
+* 02-21-90 GJF Restored _iob_index() macro
+* 02-28-90 GJF Added #ifndef _INC_FILE2 stuff. Also, removed some
+* (now) useless preprocessor directives.
+* 07-11-90 SBM Added _IOCOMMIT bit (lowio commit on fflush call)
+* 03-11-92 GJF Removed _tmpnum() macro for Win32.
+* 06-03-92 KRS Added extern "C" stuff.
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#ifndef _INC_FILE2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Additional _iobuf[]._flag values */
+
+#define _IOYOURBUF 0x0100
+#define _IOFEOF 0x0800
+#define _IOFLRTN 0x1000
+#define _IOCTRLZ 0x2000
+#define _IOCOMMIT 0x4000
+
+/* Macro for getting _iob[] index */
+
+#define _iob_index(s) ((FILE *)(s) - (FILE *)_iob)
+
+/* General use macros */
+
+#define inuse(s) ((s)->_flag & (_IOREAD|_IOWRT|_IORW))
+#define mbuf(s) ((s)->_flag & _IOMYBUF)
+#define nbuf(s) ((s)->_flag & _IONBF)
+#define ybuf(s) ((s)->_flag & _IOYOURBUF)
+#define bigbuf(s) ((s)->_flag & (_IOMYBUF|_IOYOURBUF))
+#define anybuf(s) ((s)->_flag & (_IOMYBUF|_IONBF|_IOYOURBUF))
+#ifdef _CRUISER_
+#define _tmpnum(s) ((s)->__tmpnum)
+#endif /* _CRUISER_ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_FILE2
+#endif /* _INC_FILE2 */
diff --git a/private/crt32/h/float.h b/private/crt32/h/float.h
new file mode 100644
index 000000000..54e9a3b7e
--- /dev/null
+++ b/private/crt32/h/float.h
@@ -0,0 +1,493 @@
+/***
+*float.h - constants for floating point values
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains defines for a number of implementation dependent
+* values which are commonly used by sophisticated numerical (floating
+* point) programs.
+* [ANSI]
+*
+*Revision History:
+* 08-05-87 PHG added comments
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 07-12-88 JCR Added some close comment delimeters (bug fix)
+* 08-22-88 GJF Modified to also work with the 386 (small model only)
+* 12-16-88 GJF Changed [FLT|DBL|LDBL]_ROUNDS to 1
+* 04-28-89 SKS Put parentheses around negative constants
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-03-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-20-89 KRS Add 'F' to FLT_MAX/MIN/EPSILON consts like in ANSI spec.
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 02-28-90 GJF Added #ifndef _INC_FLOAT and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-22-90 GJF Replaced _cdecl with _CALLTYPE2 (for now).
+* 08-17-90 WAJ Floating point routines now use _stdcall.
+* 09-25-90 GJF Added _fpecode stuff.
+* 08-20-91 JCR C++ and ANSI naming
+* 02-03-91 GDP Added definitions for MIPS
+* 04-03-92 GDP Use abstract control word definitions for all platforms
+* Removed Infinity Control, [EM|SW]_DENORMAL, SW_SQRTNEG
+* 04-14-92 GDP Added Inf. control, [EM|SW]_DENORMAL, SW_SQRTNEG again
+* 05-07-92 GDP Added IEEE recommended functions
+* 08-06-92 GJF Function calling type and variable type macros. Also
+* revised compiler/target processor macro usage.
+* 09-16-92 GJF Added _CRTAPI1 to _copysign - _fpclass prototypes.
+* 11-09-92 GJF Fixed preprocessing conditionals for MIPS.
+* 01-03-93 SRW Fold in ALPHA changes
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_FLOAT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+
+#include <cruntime.h>
+
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#define DBL_DIG 15 /* # of decimal digits of precision */
+#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */
+#define DBL_MANT_DIG 53 /* # of bits in mantissa */
+#define DBL_MAX 1.7976931348623158e+308 /* max value */
+#define DBL_MAX_10_EXP 308 /* max decimal exponent */
+#define DBL_MAX_EXP 1024 /* max binary exponent */
+#define DBL_MIN 2.2250738585072014e-308 /* min positive value */
+#define DBL_MIN_10_EXP (-307) /* min decimal exponent */
+#define DBL_MIN_EXP (-1021) /* min binary exponent */
+#define _DBL_RADIX 2 /* exponent radix */
+#define _DBL_ROUNDS 1 /* addition rounding: near */
+
+#define FLT_DIG 6 /* # of decimal digits of precision */
+#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
+#define FLT_GUARD 0
+#define FLT_MANT_DIG 24 /* # of bits in mantissa */
+#define FLT_MAX 3.402823466e+38F /* max value */
+#define FLT_MAX_10_EXP 38 /* max decimal exponent */
+#define FLT_MAX_EXP 128 /* max binary exponent */
+#define FLT_MIN 1.175494351e-38F /* min positive value */
+#define FLT_MIN_10_EXP (-37) /* min decimal exponent */
+#define FLT_MIN_EXP (-125) /* min binary exponent */
+#define FLT_NORMALIZE 0
+#define FLT_RADIX 2 /* exponent radix */
+#define FLT_ROUNDS 1 /* addition rounding: near */
+
+#define LDBL_DIG DBL_DIG /* # of decimal digits of precision */
+#define LDBL_EPSILON DBL_EPSILON /* smallest such that 1.0+LDBL_EPSILON != 1.0 */
+#define LDBL_MANT_DIG DBL_MANT_DIG /* # of bits in mantissa */
+#define LDBL_MAX DBL_MAX /* max value */
+#define LDBL_MAX_10_EXP DBL_MAX_10_EXP /* max decimal exponent */
+#define LDBL_MAX_EXP DBL_MAX_EXP /* max binary exponent */
+#define LDBL_MIN DBL_MIN /* min positive value */
+#define LDBL_MIN_10_EXP DBL_MIN_10_EXP /* min decimal exponent */
+#define LDBL_MIN_EXP DBL_MIN_EXP /* min binary exponent */
+#define _LDBL_RADIX DBL_RADIX /* exponent radix */
+#define _LDBL_ROUNDS DBL_ROUNDS /* addition rounding: near */
+
+
+#ifdef _WIN32_
+#ifndef _DOSX32_
+
+
+/* function prototypes */
+
+unsigned int _CRTAPI1 _clearfp(void);
+unsigned int _CRTAPI1 _controlfp(unsigned int,unsigned int);
+unsigned int _CRTAPI1 _statusfp(void);
+void _CRTAPI1 _fpreset(void);
+
+#define _clear87 _clearfp
+#define _status87 _statusfp
+
+/*
+ * Abstract User Control Word Mask and bit definitions
+ */
+
+#define _MCW_EM 0x0008001f /* interrupt Exception Masks */
+#define _EM_INEXACT 0x00000001 /* inexact (precision) */
+#define _EM_UNDERFLOW 0x00000002 /* underflow */
+#define _EM_OVERFLOW 0x00000004 /* overflow */
+#define _EM_ZERODIVIDE 0x00000008 /* zero divide */
+#define _EM_INVALID 0x00000010 /* invalid */
+
+#define _MCW_RC 0x00000300 /* Rounding Control */
+#define _RC_NEAR 0x00000000 /* near */
+#define _RC_DOWN 0x00000100 /* down */
+#define _RC_UP 0x00000200 /* up */
+#define _RC_CHOP 0x00000300 /* chop */
+
+/*
+ * Abstract User Status Word bit definitions
+ */
+
+#define _SW_INEXACT 0x00000001 /* inexact (precision) */
+#define _SW_UNDERFLOW 0x00000002 /* underflow */
+#define _SW_OVERFLOW 0x00000004 /* overflow */
+#define _SW_ZERODIVIDE 0x00000008 /* zero divide */
+#define _SW_INVALID 0x00000010 /* invalid */
+
+
+/*
+ * i386 specific definitions
+ */
+
+#define _MCW_PC 0x00030000 /* Precision Control */
+#define _PC_64 0x00000000 /* 64 bits */
+#define _PC_53 0x00010000 /* 53 bits */
+#define _PC_24 0x00020000 /* 24 bits */
+
+#define _MCW_IC 0x00040000 /* Infinity Control */
+#define _IC_AFFINE 0x00040000 /* affine */
+#define _IC_PROJECTIVE 0x00000000 /* projective */
+
+#define _EM_DENORMAL 0x00080000 /* denormal exception mask (_control87 only) */
+
+#define _SW_DENORMAL 0x00080000 /* denormal status bit */
+
+
+unsigned int _CRTAPI1 _control87(unsigned int,unsigned int);
+
+
+/*
+ * MIPS R4000 specific definitions
+ */
+
+#define _MCW_DN 0x01000000 /* Denormal Control (R4000) */
+#define _DN_FLUSH 0x01000000 /* flush to zero */
+#define _DN_SAVE 0x00000000 /* save */
+
+
+/* initial Control Word value */
+
+#ifdef _M_IX86
+
+#define _CW_DEFAULT ( _RC_NEAR + _PC_64 + _EM_INVALID + _EM_ZERODIVIDE + _EM_OVERFLOW + _EM_UNDERFLOW + _EM_INEXACT )
+
+#elif defined(_M_MRX000) || defined (_M_ALPHA) || defined(_M_PPC)
+
+#define _CW_DEFAULT ( _RC_NEAR + _DN_FLUSH + _EM_INVALID + _EM_ZERODIVIDE + _EM_OVERFLOW + _EM_UNDERFLOW + _EM_INEXACT )
+
+#endif
+
+/* Global variable holding floating point error code */
+
+#ifdef MTHREAD
+extern int * _CRTAPI1 __fpecode(void);
+#define _fpecode (*__fpecode())
+#else
+extern int _CRTVAR1 _fpecode;
+#endif
+
+/* invalid subconditions (_SW_INVALID also set) */
+
+#define _SW_UNEMULATED 0x0040 /* unemulated instruction */
+#define _SW_SQRTNEG 0x0080 /* square root of a neg number */
+#define _SW_STACKOVERFLOW 0x0200 /* FP stack overflow */
+#define _SW_STACKUNDERFLOW 0x0400 /* FP stack underflow */
+
+/* Floating point error signals and return codes */
+
+#define _FPE_INVALID 0x81
+#define _FPE_DENORMAL 0x82
+#define _FPE_ZERODIVIDE 0x83
+#define _FPE_OVERFLOW 0x84
+#define _FPE_UNDERFLOW 0x85
+#define _FPE_INEXACT 0x86
+
+#define _FPE_UNEMULATED 0x87
+#define _FPE_SQRTNEG 0x88
+#define _FPE_STACKOVERFLOW 0x8a
+#define _FPE_STACKUNDERFLOW 0x8b
+
+#define _FPE_EXPLICITGEN 0x8c /* raise( SIGFPE ); */
+
+
+/* IEEE recommended functions */
+
+double _CRTAPI1 _copysign (double, double);
+double _CRTAPI1 _chgsign (double);
+double _CRTAPI1 _scalb(double, long);
+double _CRTAPI1 _logb(double);
+double _CRTAPI1 _nextafter(double, double);
+int _CRTAPI1 _finite(double);
+int _CRTAPI1 _isnan(double);
+int _CRTAPI1 _fpclass(double);
+
+#define _FPCLASS_SNAN 0x0001 /* signaling NaN */
+#define _FPCLASS_QNAN 0x0002 /* quiet NaN */
+#define _FPCLASS_NINF 0x0004 /* negative infinity */
+#define _FPCLASS_NN 0x0008 /* negative normal */
+#define _FPCLASS_ND 0x0010 /* negative denormal */
+#define _FPCLASS_NZ 0x0020 /* -0 */
+#define _FPCLASS_PZ 0x0040 /* +0 */
+#define _FPCLASS_PD 0x0080 /* positive denormal */
+#define _FPCLASS_PN 0x0100 /* positive normal */
+#define _FPCLASS_PINF 0x0200 /* positive infinity */
+
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+
+#define clear87 _clear87
+#define status87 _status87
+#define control87 _control87
+#define fpreset _fpreset
+
+#define DBL_RADIX _DBL_RADIX
+#define DBL_ROUNDS _DBL_ROUNDS
+
+#define LDBL_RADIX _LDBL_RADIX
+#define LDBL_ROUNDS _LDBL_ROUNDS
+
+#define MCW_EM _MCW_EM
+#define EM_INVALID _EM_INVALID
+#define EM_DENORMAL _EM_DENORMAL
+#define EM_ZERODIVIDE _EM_ZERODIVIDE
+#define EM_OVERFLOW _EM_OVERFLOW
+#define EM_UNDERFLOW _EM_UNDERFLOW
+#define EM_INEXACT _EM_INEXACT
+
+#define MCW_IC _MCW_IC
+#define IC_AFFINE _IC_AFFINE
+#define IC_PROJECTIVE _IC_PROJECTIVE
+
+#define MCW_RC _MCW_RC
+#define RC_CHOP _RC_CHOP
+#define RC_UP _RC_UP
+#define RC_DOWN _RC_DOWN
+#define RC_NEAR _RC_NEAR
+
+#define MCW_PC _MCW_PC
+#define PC_24 _PC_24
+#define PC_53 _PC_53
+#define PC_64 _PC_64
+
+#define CW_DEFAULT _CW_DEFAULT
+
+#define SW_INVALID _SW_INVALID
+#define SW_DENORMAL _SW_DENORMAL
+#define SW_ZERODIVIDE _SW_ZERODIVIDE
+#define SW_OVERFLOW _SW_OVERFLOW
+#define SW_UNDERFLOW _SW_UNDERFLOW
+#define SW_INEXACT _SW_INEXACT
+
+#define SW_UNEMULATED _SW_UNEMULATED
+#define SW_SQRTNEG _SW_SQRTNEG
+#define SW_STACKOVERFLOW _SW_STACKOVERFLOW
+#define SW_STACKUNDERFLOW _SW_STACKUNDERFLOW
+
+#define FPE_INVALID _FPE_INVALID
+#define FPE_DENORMAL _FPE_DENORMAL
+#define FPE_ZERODIVIDE _FPE_ZERODIVIDE
+#define FPE_OVERFLOW _FPE_OVERFLOW
+#define FPE_UNDERFLOW _FPE_UNDERFLOW
+#define FPE_INEXACT _FPE_INEXACT
+
+#define FPE_UNEMULATED _FPE_UNEMULATED
+#define FPE_SQRTNEG _FPE_SQRTNEG
+#define FPE_STACKOVERFLOW _FPE_STACKOVERFLOW
+#define FPE_STACKUNDERFLOW _FPE_STACKUNDERFLOW
+
+#define FPE_EXPLICITGEN _FPE_EXPLICITGEN
+
+
+#endif /* __STDC__ */
+#else /* _DOSX32_ */
+
+/*
+ * 8087/80287 math control information
+ */
+
+
+/* User Control Word Mask and bit definitions.
+ * These definitions match the 8087/80287
+ */
+
+#define _MCW_EM 0x003f /* interrupt Exception Masks */
+#define _EM_INVALID 0x0001 /* invalid */
+#define _EM_DENORMAL 0x0002 /* denormal */
+#define _EM_ZERODIVIDE 0x0004 /* zero divide */
+#define _EM_OVERFLOW 0x0008 /* overflow */
+#define _EM_UNDERFLOW 0x0010 /* underflow */
+#define _EM_INEXACT 0x0020 /* inexact (precision) */
+
+#define _MCW_IC 0x1000 /* Infinity Control */
+#define _IC_AFFINE 0x1000 /* affine */
+#define _IC_PROJECTIVE 0x0000 /* projective */
+
+#define _MCW_RC 0x0c00 /* Rounding Control */
+#define _RC_CHOP 0x0c00 /* chop */
+#define _RC_UP 0x0800 /* up */
+#define _RC_DOWN 0x0400 /* down */
+#define _RC_NEAR 0x0000 /* near */
+
+#define _MCW_PC 0x0300 /* Precision Control */
+#define _PC_24 0x0000 /* 24 bits */
+#define _PC_53 0x0200 /* 53 bits */
+#define _PC_64 0x0300 /* 64 bits */
+
+
+/* initial Control Word value */
+
+#define _CW_DEFAULT ( _IC_AFFINE + _RC_NEAR + _PC_64 + _EM_DENORMAL + _EM_UNDERFLOW + _EM_INEXACT )
+
+/* user Status Word bit definitions */
+
+#define _SW_INVALID 0x0001 /* invalid */
+#define _SW_DENORMAL 0x0002 /* denormal */
+#define _SW_ZERODIVIDE 0x0004 /* zero divide */
+#define _SW_OVERFLOW 0x0008 /* overflow */
+#define _SW_UNDERFLOW 0x0010 /* underflow */
+#define _SW_INEXACT 0x0020 /* inexact (precision) */
+
+
+/* invalid subconditions (_SW_INVALID also set) */
+
+#define _SW_UNEMULATED 0x0040 /* unemulated instruction */
+#define _SW_SQRTNEG 0x0080 /* square root of a neg number */
+#define _SW_STACKOVERFLOW 0x0200 /* FP stack overflow */
+#define _SW_STACKUNDERFLOW 0x0400 /* FP stack underflow */
+
+
+/* function prototypes */
+
+unsigned int _CRTAPI1 _clear87(void);
+unsigned int _CRTAPI1 _control87(unsigned int,unsigned int);
+void _CRTAPI1 _fpreset(void);
+unsigned int _CRTAPI1 _status87(void);
+
+/* Global variable holding floating point error code */
+
+#ifdef MTHREAD
+extern int * _CRTAPI1 __fpecode(void);
+#define _fpecode (*__fpecode())
+#else
+extern int _CRTVAR1 _fpecode;
+#endif
+
+/* Floating point error signals and return codes */
+
+#define _FPE_INVALID 0x81
+#define _FPE_DENORMAL 0x82
+#define _FPE_ZERODIVIDE 0x83
+#define _FPE_OVERFLOW 0x84
+#define _FPE_UNDERFLOW 0x85
+#define _FPE_INEXACT 0x86
+
+#define _FPE_UNEMULATED 0x87
+#define _FPE_SQRTNEG 0x88
+#define _FPE_STACKOVERFLOW 0x8a
+#define _FPE_STACKUNDERFLOW 0x8b
+
+#define _FPE_EXPLICITGEN 0x8c /* raise( SIGFPE ); */
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+
+#define DBL_RADIX _DBL_RADIX
+#define DBL_ROUNDS _DBL_ROUNDS
+
+#define LDBL_RADIX _LDBL_RADIX
+#define LDBL_ROUNDS _LDBL_ROUNDS
+
+#define MCW_EM _MCW_EM
+#define EM_INVALID _EM_INVALID
+#define EM_DENORMAL _EM_DENORMAL
+#define EM_ZERODIVIDE _EM_ZERODIVIDE
+#define EM_OVERFLOW _EM_OVERFLOW
+#define EM_UNDERFLOW _EM_UNDERFLOW
+#define EM_INEXACT _EM_INEXACT
+
+#define MCW_IC _MCW_IC
+#define IC_AFFINE _IC_AFFINE
+#define IC_PROJECTIVE _IC_PROJECTIVE
+
+#define MCW_RC _MCW_RC
+#define RC_CHOP _RC_CHOP
+#define RC_UP _RC_UP
+#define RC_DOWN _RC_DOWN
+#define RC_NEAR _RC_NEAR
+
+#define MCW_PC _MCW_PC
+#define PC_24 _PC_24
+#define PC_53 _PC_53
+#define PC_64 _PC_64
+
+#define CW_DEFAULT _CW_DEFAULT
+
+#define SW_INVALID _SW_INVALID
+#define SW_DENORMAL _SW_DENORMAL
+#define SW_ZERODIVIDE _SW_ZERODIVIDE
+#define SW_OVERFLOW _SW_OVERFLOW
+#define SW_UNDERFLOW _SW_UNDERFLOW
+#define SW_INEXACT _SW_INEXACT
+
+#define SW_UNEMULATED _SW_UNEMULATED
+#define SW_SQRTNEG _SW_SQRTNEG
+#define SW_STACKOVERFLOW _SW_STACKOVERFLOW
+#define SW_STACKUNDERFLOW _SW_STACKUNDERFLOW
+
+#define FPE_INVALID _FPE_INVALID
+#define FPE_DENORMAL _FPE_DENORMAL
+#define FPE_ZERODIVIDE _FPE_ZERODIVIDE
+#define FPE_OVERFLOW _FPE_OVERFLOW
+#define FPE_UNDERFLOW _FPE_UNDERFLOW
+#define FPE_INEXACT _FPE_INEXACT
+
+#define FPE_UNEMULATED _FPE_UNEMULATED
+#define FPE_SQRTNEG _FPE_SQRTNEG
+#define FPE_STACKOVERFLOW _FPE_STACKOVERFLOW
+#define FPE_STACKUNDERFLOW _FPE_STACKUNDERFLOW
+
+#define FPE_EXPLICITGEN _FPE_EXPLICITGEN
+
+#endif /* __STDC__ */
+
+#endif /* _DOSX32_ */
+
+#else
+
+#error ERROR - ONLY WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_FLOAT
+#endif /* _INC_FLOAT */
diff --git a/private/crt32/h/fltintrn.h b/private/crt32/h/fltintrn.h
new file mode 100644
index 000000000..5f6cc4d19
--- /dev/null
+++ b/private/crt32/h/fltintrn.h
@@ -0,0 +1,192 @@
+/***
+*fltintrn.h - contains declarations of internal floating point types,
+* routines and variables
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Declares floating point types, routines and variables used
+* internally by the C run-time.
+* [Internal]
+*
+*Revision History:
+* 10-20-88 JCR Changed 'DOUBLE' to 'double' for 386
+* 08-15-89 GJF Fixed copyright, indents
+* 10-30-89 GJF Fixed copyright (again)
+* 03-02-90 GJF Added #ifndef _INC_STRUCT stuff. Also, cleaned up
+* the formatting a bit.
+* 03-05-90 GJF Fixed up the arg types in protoypes. Also, added
+* #include <cruntime.h>
+* 03-22-90 GJF Made _fltin(), _fltin2(), _fltout() and _fltout2()
+* _CALLTYPE2 (for now) and added a prototype for
+* _fptostr().
+* 08-01-90 SBM Moved _cftoe() and _cftof() here from internal.h
+* and _cfltcvt_tab from input.c and output.c,
+* added typedefs for _cfltcvt_tab entries,
+* renamed module from <struct.h> to <fltintrn.h> and
+* adjusted #ifndef stuff to #ifndef _INC_FLTINTRN
+* 08-29-90 SBM Changed type of _cfltcvt_tab[] to agree with
+* definition in cmiscdat.c
+* 04-26-91 SRW Removed level 3 warnings
+* 08-26-91 JCR Changed MIPS to _MIPS_, ANSI naming
+* 08-06-92 GJF Function calling type and variable type macros. Revised
+* use of target processor macros.
+* 11-09-92 GJF Fixed preprocessing conditionals for MIPS.
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 03-31-93 CFW Added #pragma warning to suppress "long double" warnings.
+*
+****/
+
+#ifndef _INC_FLTINTRN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <cruntime.h>
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+#define _CRTVAR1
+
+#endif
+
+// C4069: "long double != double"
+#pragma warning(disable:4069) // disable C4069 warning
+// #pragma warning(default:4069) // use this to reenable, if desired
+
+/*
+ * structs used to fool the compiler into not generating floating point
+ * instructions when copying and pushing [long] double values
+ */
+
+#ifndef DOUBLE
+
+typedef struct {
+ double x;
+} DOUBLE;
+
+#endif
+
+#ifndef LONGDOUBLE
+
+typedef struct {
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+ /*
+ * No long double type for MIPS, ALPHA, or PPC
+ */
+ double x;
+#else
+ /*
+ * Assume there is a long double type
+ */
+ long double x;
+#endif
+} LONGDOUBLE;
+
+#endif
+
+/*
+ * typedef for _fltout
+ */
+
+typedef struct _strflt
+{
+ int sign; /* zero if positive otherwise negative */
+ int decpt; /* exponent of floating point number */
+ int flag; /* zero if okay otherwise IEEE overflow */
+ char *mantissa; /* pointer to mantissa in string form */
+}
+ *STRFLT;
+
+
+/*
+ * typedef for _fltin
+ */
+
+typedef struct _flt
+{
+ int flags;
+ int nbytes; /* number of characters read */
+ long lval;
+ double dval; /* the returned floating point number */
+}
+ *FLT;
+
+
+/* floating point conversion routines, keep in sync with mrt32\include\convert.h */
+
+char *_cftoe(double *, char *, int, int);
+char *_cftof(double *, char *, int);
+void _CRTAPI1 _fptostr(char *, int, STRFLT);
+
+#ifdef MTHREAD
+
+STRFLT _CRTAPI2 _fltout2( double, STRFLT, char * );
+FLT _CRTAPI2 _fltin2( FLT , const char *, int, int, int );
+
+#else
+
+STRFLT _CRTAPI2 _fltout( double );
+FLT _CRTAPI2 _fltin( const char *, int, int, int );
+
+#endif
+
+
+/*
+ * table of pointers to floating point helper routines
+ *
+ * We can't specify the prototypes for the entries of the table accurately,
+ * since different functions in the table have different arglists.
+ * So we declare the functions to take and return void (which is the
+ * correct prototype for _fptrap(), which is what the entries are all
+ * initialized to if no floating point is loaded) and cast appropriately
+ * on every usage.
+ */
+
+typedef void (* PFV)(void);
+extern PFV _cfltcvt_tab[6];
+
+typedef void (* PF0)(DOUBLE*, char*, int, int, int);
+#define _cfltcvt(a,b,c,d,e) (*((PF0)_cfltcvt_tab[0]))(a,b,c,d,e)
+
+typedef void (* PF1)(char*);
+#define _cropzeros(a) (*((PF1)_cfltcvt_tab[1]))(a)
+
+typedef void (* PF2)(int, char*, char*);
+#define _fassign(a,b,c) (*((PF2)_cfltcvt_tab[2]))(a,b,c)
+
+typedef void (* PF3)(char*);
+#define _forcdecpt(a) (*((PF3)_cfltcvt_tab[3]))(a)
+
+typedef int (* PF4)(DOUBLE*);
+#define _positive(a) (*((PF4)_cfltcvt_tab[4]))(a)
+
+typedef void (* PF5)(LONGDOUBLE*, char*, int, int, int);
+#define _cldcvt(a,b,c,d,e) (*((PF5)_cfltcvt_tab[5]))(a,b,c,d,e)
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_FLTINTRN
+#endif /* _INC_FLTINTRN */
diff --git a/private/crt32/h/fpieee.h b/private/crt32/h/fpieee.h
new file mode 100644
index 000000000..6949fb522
--- /dev/null
+++ b/private/crt32/h/fpieee.h
@@ -0,0 +1,362 @@
+/***
+* fpieee.h - Definitions for floating point IEEE exception handling
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains constant and type definitions for handling
+* floating point exceptions [ANSI/IEEE std. 754]
+*
+*Revision History:
+* 03-01-92 GDP written
+* 04-05-92 GDP calling convention macros
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 01-13-94 RDL Added #ifndef _LANGUAGE_ASSEMBLY for asm includes.
+*
+*******************************************************************************/
+
+#ifndef _INC_FPIEEE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+/*
+ * Define floating point IEEE compare result values.
+ */
+
+typedef enum {
+ _FpCompareEqual,
+ _FpCompareGreater,
+ _FpCompareLess,
+ _FpCompareUnordered
+} _FPIEEE_COMPARE_RESULT;
+
+/*
+ * Define floating point format and result precision values.
+ */
+
+typedef enum {
+ _FpFormatFp32,
+ _FpFormatFp64,
+ _FpFormatFp80,
+ _FpFormatFp128,
+ _FpFormatI16,
+ _FpFormatI32,
+ _FpFormatI64,
+ _FpFormatU16,
+ _FpFormatU32,
+ _FpFormatU64,
+ _FpFormatBcd80,
+ _FpFormatCompare,
+ _FpFormatString
+} _FPIEEE_FORMAT;
+
+/*
+ * Define operation code values.
+ *
+ * NOTE: If you change this enum, change the #defines below for assembler!
+ */
+
+typedef enum {
+ _FpCodeUnspecified,
+ _FpCodeAdd,
+ _FpCodeSubtract,
+ _FpCodeMultiply,
+ _FpCodeDivide,
+ _FpCodeSquareRoot,
+ _FpCodeRemainder,
+ _FpCodeCompare,
+ _FpCodeConvert,
+ _FpCodeRound,
+ _FpCodeTruncate,
+ _FpCodeFloor,
+ _FpCodeCeil,
+ _FpCodeAcos,
+ _FpCodeAsin,
+ _FpCodeAtan,
+ _FpCodeAtan2,
+ _FpCodeCabs,
+ _FpCodeCos,
+ _FpCodeCosh,
+ _FpCodeExp,
+ _FpCodeFabs,
+ _FpCodeFmod,
+ _FpCodeFrexp,
+ _FpCodeHypot,
+ _FpCodeLdexp,
+ _FpCodeLog,
+ _FpCodeLog10,
+ _FpCodeModf,
+ _FpCodePow,
+ _FpCodeSin,
+ _FpCodeSinh,
+ _FpCodeTan,
+ _FpCodeTanh,
+ _FpCodeY0,
+ _FpCodeY1,
+ _FpCodeYn,
+ _FpCodeLogb,
+ _FpCodeNextafter,
+ _FpCodeNegate
+
+} _FP_OPERATION_CODE;
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+
+#ifndef _INTERNAL_IFSTRIP_
+
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#define OP_UNSPEC _FpCodeUnspecified
+#define OP_ADD _FpCodeAdd
+#define OP_SUB _FpCodeSubtract
+#define OP_MUL _FpCodeMultiply
+#define OP_DIV _FpCodeDivide
+#define OP_REM _FpCodeRemainder
+#define OP_COMP _FpCodeCompare
+#define OP_CVT _FpCodeConvert
+#define OP_RND _FpCodeRound
+#define OP_TRUNC _FpCodeTruncate
+
+#define OP_EXP _FpCodeExp
+
+#define OP_POW _FpCodePow
+#define OP_LOG _FpCodeLog
+#define OP_LOG10 _FpCodeLog10
+#define OP_SINH _FpCodeSinh
+#define OP_COSH _FpCodeCosh
+#define OP_TANH _FpCodeTanh
+#define OP_ASIN _FpCodeAsin
+#define OP_ACOS _FpCodeAcos
+#define OP_ATAN _FpCodeAtan
+#define OP_ATAN2 _FpCodeAtan2
+#define OP_SQRT _FpCodeSquareRoot
+#define OP_SIN _FpCodeSin
+#define OP_COS _FpCodeCos
+#define OP_TAN _FpCodeTan
+#define OP_CEIL _FpCodeCeil
+#define OP_FLOOR _FpCodeFloor
+#define OP_ABS _FpCodeFabs
+#define OP_MODF _FpCodeModf
+#define OP_LDEXP _FpCodeLdexp
+#define OP_CABS _FpCodeCabs
+#define OP_HYPOT _FpCodeHypot
+#define OP_FMOD _FpCodeFmod
+#define OP_FREXP _FpCodeFrexp
+#define OP_Y0 _FpCodeY0
+#define OP_Y1 _FpCodeY1
+#define OP_YN _FpCodeYn
+
+#define OP_LOGB _FpCodeLogb
+#define OP_NEXTAFTER _FpCodeNextafter
+
+#else /* _LANGUAGE_ASSEMBLY */
+
+/* This must be the same as the enumerator _FP_OPERATION_CODE ! */
+#define OP_UNSPEC 0
+#define OP_ADD 1
+#define OP_SUB 2
+#define OP_MUL 3
+#define OP_DIV 4
+#define OP_SQRT 5
+#define OP_REM 6
+#define OP_COMP 7
+#define OP_CVT 8
+#define OP_RND 9
+#define OP_TRUNC 10
+#define OP_FLOOR 11
+#define OP_CEIL 12
+#define OP_ACOS 13
+#define OP_ASIN 14
+#define OP_ATAN 15
+#define OP_ATAN2 16
+#define OP_CABS 17
+#define OP_COS 18
+#define OP_COSH 19
+#define OP_EXP 20
+#define OP_ABS 21 /* same as OP_FABS */
+#define OP_FABS 21 /* same as OP_ABS */
+#define OP_FMOD 22
+#define OP_FREXP 23
+#define OP_HYPOT 24
+#define OP_LDEXP 25
+#define OP_LOG 26
+#define OP_LOG10 27
+#define OP_MODF 28
+#define OP_POW 29
+#define OP_SIN 30
+#define OP_SINH 31
+#define OP_TAN 32
+#define OP_TANH 33
+#define OP_Y0 34
+#define OP_Y1 35
+#define OP_YN 36
+#define OP_LOGB 37
+#define OP_NEXTAFTER 38
+#define OP_NEG 39
+
+
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+#endif /* _INTERNAL_IFSTRIP_ */
+
+
+/*
+ * Define rounding modes.
+ */
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+typedef enum {
+ _FpRoundNearest,
+ _FpRoundMinusInfinity,
+ _FpRoundPlusInfinity,
+ _FpRoundChopped
+} _FPIEEE_ROUNDING_MODE;
+
+typedef enum {
+ _FpPrecisionFull,
+ _FpPrecision53,
+ _FpPrecision24
+} _FPIEEE_PRECISION;
+
+
+/*
+ * Define floating point context record
+ */
+
+typedef float _FP32;
+typedef double _FP64;
+typedef short _I16;
+typedef int _I32;
+typedef unsigned short _U16;
+typedef unsigned int _U32;
+
+#ifndef _INTERNAL_IFSTRIP_
+
+typedef struct {
+ unsigned long W[4];
+} _U32ARRAY;
+
+#endif /* _INTERNAL_IFSTRIP_ */
+
+typedef struct {
+ unsigned short W[5];
+} _FP80;
+
+typedef struct {
+ unsigned long W[4];
+} _FP128;
+
+typedef struct {
+ unsigned long W[2];
+} _I64;
+
+typedef struct {
+ unsigned long W[2];
+} _U64;
+
+typedef struct {
+ unsigned short W[5];
+} _BCD80;
+
+
+typedef struct {
+ union {
+ _FP32 Fp32Value;
+ _FP64 Fp64Value;
+ _FP80 Fp80Value;
+ _FP128 Fp128Value;
+ _I16 I16Value;
+ _I32 I32Value;
+ _I64 I64Value;
+ _U16 U16Value;
+ _U32 U32Value;
+ _U64 U64Value;
+ _BCD80 Bcd80Value;
+ char *StringValue;
+ int CompareValue;
+#ifndef _INTERNAL_IFSTRIP_
+ _U32ARRAY U32ArrayValue;
+#endif /* _INTERNAL_IFSTRIP_ */
+ } Value;
+
+ unsigned int OperandValid : 1;
+ unsigned int Format : 4;
+
+} _FPIEEE_VALUE;
+
+
+typedef struct {
+ unsigned int Inexact : 1;
+ unsigned int Underflow : 1;
+ unsigned int Overflow : 1;
+ unsigned int ZeroDivide : 1;
+ unsigned int InvalidOperation : 1;
+} _FPIEEE_EXCEPTION_FLAGS;
+
+
+typedef struct {
+ unsigned int RoundingMode : 2;
+ unsigned int Precision : 3;
+ unsigned int Operation :12;
+ _FPIEEE_EXCEPTION_FLAGS Cause;
+ _FPIEEE_EXCEPTION_FLAGS Enable;
+ _FPIEEE_EXCEPTION_FLAGS Status;
+ _FPIEEE_VALUE Operand1;
+ _FPIEEE_VALUE Operand2;
+ _FPIEEE_VALUE Result;
+} _FPIEEE_RECORD;
+
+
+struct _EXCEPTION_POINTERS;
+
+/*
+ * Floating point IEEE exception filter routine
+ */
+
+int _CRTAPI1 _fpieee_flt(unsigned long code,
+ struct _EXCEPTION_POINTERS *p,
+ int handler(_FPIEEE_RECORD *));
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_FPIEEE
+#endif /* _INC_FPIEEE */
diff --git a/private/crt32/h/fstream.h b/private/crt32/h/fstream.h
new file mode 100644
index 000000000..aba7b09cd
--- /dev/null
+++ b/private/crt32/h/fstream.h
@@ -0,0 +1,145 @@
+/***
+*fstream.h - definitions/declarations for filebuf and fstream classes
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the classes, values, macros, and functions
+* used by the filebuf and fstream classes.
+* [AT&T C++]
+*
+*Revision History:
+* 01-23-92 KRS Ported from 16-bit version.
+* 08-19-92 KRS Remove sh_compat for NT.
+* 02-23-93 SKS Update copyright to 1993
+* 03-23-93 CFW Modified #pragma warnings.
+*
+****/
+
+#ifndef _INC_FSTREAM
+#define _INC_FSTREAM
+
+#include <iostream.h>
+
+// C4505: "unreferenced local function has been removed"
+#pragma warning(disable:4505) // disable C4505 warning
+// #pragma warning(default:4505) // use this to reenable, if desired
+
+// C4103 : "used #pragma pack to change alignment"
+#pragma warning(disable:4103) // disable C4103 warning
+// #pragma warning(default:4103) // use this to reenable, if desired
+
+// Force word packing to avoid possible -Zp override
+#pragma pack(4)
+
+typedef int filedesc;
+
+class filebuf : public streambuf {
+public:
+static const int openprot; // default share/prot mode for open
+
+// optional share values for 3rd argument (prot) of open or constructor
+static const int sh_none; // exclusive mode no sharing
+static const int sh_read; // allow read sharing
+static const int sh_write; // allow write sharing
+// use (sh_read | sh_write) to allow both read and write sharing
+
+// options for setmode member function
+static const int binary;
+static const int text;
+
+ filebuf();
+ filebuf(filedesc);
+ filebuf(filedesc, char *, int);
+ ~filebuf();
+
+ filebuf* attach(filedesc);
+ filedesc fd() const { return (x_fd==-1) ? EOF : x_fd; }
+ int is_open() const { return (x_fd!=-1); }
+ filebuf* open(const char *, int, int = filebuf::openprot);
+ filebuf* close();
+ int setmode(int = filebuf::text);
+
+virtual int overflow(int=EOF);
+virtual int underflow();
+
+virtual streambuf* setbuf(char *, int);
+virtual streampos seekoff(streamoff, ios::seek_dir, int);
+// virtual streampos seekpos(streampos, int);
+virtual int sync();
+
+private:
+ filedesc x_fd;
+ int x_fOpened;
+};
+
+class ifstream : public istream {
+public:
+ ifstream();
+ ifstream(const char *, int =ios::in, int = filebuf::openprot);
+ ifstream(filedesc);
+ ifstream(filedesc, char *, int);
+ ~ifstream();
+
+ streambuf * setbuf(char *, int);
+ filebuf* rdbuf() const { return (filebuf*) ios::rdbuf(); }
+
+ void attach(filedesc);
+ filedesc fd() const { return rdbuf()->fd(); }
+
+ int is_open() const { return rdbuf()->is_open(); }
+ void open(const char *, int =ios::in, int = filebuf::openprot);
+ void close();
+ int setmode(int mode = filebuf::text) { return rdbuf()->setmode(mode); }
+};
+
+class ofstream : public ostream {
+public:
+ ofstream();
+ ofstream(const char *, int =ios::out, int = filebuf::openprot);
+ ofstream(filedesc);
+ ofstream(filedesc, char *, int);
+ ~ofstream();
+
+ streambuf * setbuf(char *, int);
+ filebuf* rdbuf() const { return (filebuf*) ios::rdbuf(); }
+
+ void attach(filedesc);
+ filedesc fd() const { return rdbuf()->fd(); }
+
+ int is_open() const { return rdbuf()->is_open(); }
+ void open(const char *, int =ios::out, int = filebuf::openprot);
+ void close();
+ int setmode(int mode = filebuf::text) { return rdbuf()->setmode(mode); }
+};
+
+class fstream : public iostream {
+public:
+ fstream();
+ fstream(const char *, int, int = filebuf::openprot);
+ fstream(filedesc);
+ fstream(filedesc, char *, int);
+ ~fstream();
+
+ streambuf * setbuf(char *, int);
+ filebuf* rdbuf() const { return (filebuf*) ostream::rdbuf(); }
+
+ void attach(filedesc);
+ filedesc fd() const { return rdbuf()->fd(); }
+
+ int is_open() const { return rdbuf()->is_open(); }
+ void open(const char *, int, int = filebuf::openprot);
+ void close();
+ int setmode(int mode = filebuf::text) { return rdbuf()->setmode(mode); }
+};
+
+// manipulators to dynamically change file access mode (filebufs only)
+inline ios& binary(ios& _fstrm) \
+ { ((filebuf*)_fstrm.rdbuf())->setmode(filebuf::binary); return _fstrm; }
+inline ios& text(ios& _fstrm) \
+ { ((filebuf*)_fstrm.rdbuf())->setmode(filebuf::text); return _fstrm; }
+
+// Restore default packing
+#pragma pack()
+
+#endif // !_INC_FSTREAM
diff --git a/private/crt32/h/heap.h b/private/crt32/h/heap.h
new file mode 100644
index 000000000..2650fe8b2
--- /dev/null
+++ b/private/crt32/h/heap.h
@@ -0,0 +1,433 @@
+/***
+* heap.h - Heap code include file
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains information needed by the C library heap code.
+* [Internal]
+*
+*Revision History:
+* 05-16-89 JCR Module created
+* 06-02-89 GJF Removed naming conflict
+* 06-29-89 JCR Completely new for "New heap - rev 2"
+* 06-29-89 GJF Added _HDRSIZE, fixed some minor glitches.
+* 06-29-89 GJF Added _BLKSIZE(), fixed more minor bugs.
+* 06-30-89 GJF Changed several macros to operate on a pointer to a
+* descriptor, rather than a descriptor itself.
+* 06-30-89 JCR Corrected/updated several macros
+* 07-06-89 JCR Added region support, misc improvements, etc.
+* 07-07-89 GJF Minor bug in _ROUND() macro
+* 07-07-89 JCR Added _DUMMY status
+* 07-19-89 GJF Removed _PBACKPTR macro
+* 07-20-89 JCR Region routine prototypes, _HEAPFIND values
+* 07-21-89 JCR #define _heap_growsize to _amblksiz for compatibility
+* 07-25-89 GJF Added prototypes for calloc, free and malloc
+* 07-28-89 GJF Added prototype for _msize
+* 08-28-89 JCR Added _HEAP_COALESCE value
+* 10-30-89 GJF Fixed copyright
+* 11-03-89 GJF Added _DISTTOBNDRY(), _NEXTSEGBNDRY() macros and
+* prototypes for _flat_malloc(), _heap_advance_rover(),
+* _heap_split_block() functions
+* 11-07-89 GJF Added _SEGSIZE_, added prototype for _heap_search()
+* restored function prototype for_heap_grow_region()
+* 11-08-89 JCR Added non-pow2 rounding macro
+* 11-10-89 JCR Added _heap_free_region prototype
+* 11-10-89 GJF Added prototypes and macros for multi-thread support
+* 11-16-89 JCR If DEBUG defined include <assert.h>, added sanity check
+* 12-13-89 GJF Removed prototypes duplicated in malloc.h
+* 12-20-89 GJF Removed plastdesc from _heap_desc_ struct, removed
+* _DELHEAP and _ADDHEAP macros (unused and wrong), added
+* explicit _cdecl to function prototypes
+* 01-08-89 GJF Use assert macro from assertm.h instead of assert.h
+* 03-01-90 GJF Added #ifndef _INC_HEAP and #include <cruntime.h>
+* stuff. Also, removed some unused DEBUG286 stuff.
+* 03-22-90 GJF Replaced _cdecl with _CALLTYPE1 in prototypes.
+* 07-25-90 SBM Replaced <assertm.h> by <assert.h>
+* 08-13-90 SBM Added casts to macros for clean compiles at -W3
+* 12-28-90 SRW Fixed _heap_split_block prototype to match code
+* 12-28-90 SRW Changed _HEAP_GROWSIZE to be 0x10000 [_WIN32_]
+* 03-05-91 GJF Added decl for _heap_resetsize, removed proto for
+* _heap_advance_rover (both conditioned on _OLDROVER_
+* not being #define-d).
+* 03-13-91 GJF Made _HEAP_GROWSIZE 32K for [_CRUISER_].
+* 04-09-91 PNT Added _MAC_ definitions
+* 08-20-91 JCR C++ and ANSI naming
+* 03-30-92 DJM POSIX support.
+* 08-06-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+*******************************************************************************/
+
+#ifdef _POSIX_ /* Since the heap routines are the same as WIN32 under
+ POSIX, define _WIN32_ if we are in POSIX */
+
+#define _WIN32_
+#endif
+
+#ifndef _INC_HEAP
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <cruntime.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/*
+ * Heap block descriptor
+ */
+
+struct _block_descriptor {
+ struct _block_descriptor *pnextdesc; /* ptr to next descriptor */
+ void *pblock; /* ptr to memory block */
+};
+
+#define _BLKDESC struct _block_descriptor
+#define _PBLKDESC struct _block_descriptor *
+
+
+/*
+ * Useful Constants
+ */
+
+/* size of the header in a memory block */
+#define _HDRSIZE sizeof(void *)
+
+/* _heapchk/_heapset parameter */
+#define _HEAP_NOFILL 0x7FFFFFF
+
+
+/*
+ * Descriptor status values
+ */
+
+#define _INUSE 0
+#define _FREE 1
+#define _DUMMY 2
+
+
+#if (_INUSE != 0)
+#error *** Heap code assumes _INUSE value is 0! ***
+#endif
+
+
+/*
+ * Macros for manipulating heap memory block descriptors
+ * stat = one of the status values
+ * addr = user-visible address of a heap block
+ */
+
+#define _STATUS_MASK 0x3 /* last 2 bits are status */
+
+#define _ADDRESS(pdesc) ( (void *) ((unsigned)((pdesc)->pblock) & \
+ (~_STATUS_MASK)) )
+#define _STATUS(pdesc) ( (unsigned) ((unsigned)((pdesc)->pblock) & \
+ _STATUS_MASK) )
+
+#define _SET_INUSE(pdesc) ( pdesc->pblock = (void *) \
+ ((unsigned)_ADDRESS(pdesc) | _INUSE) )
+#define _SET_FREE(pdesc) ( pdesc->pblock = (void *) \
+ ((unsigned)_ADDRESS(pdesc) | _FREE) )
+#define _SET_DUMMY(pdesc) ( pdesc->pblock = (void *) \
+ ((unsigned)_ADDRESS(pdesc) | _DUMMY) )
+
+#define _IS_INUSE(pdesc) ( _STATUS(pdesc) == _INUSE )
+#define _IS_FREE(pdesc) ( _STATUS(pdesc) == _FREE )
+#define _IS_DUMMY(pdesc) ( _STATUS(pdesc) == _DUMMY )
+
+#define _BLKSIZE(pdesc) ( (unsigned) ( \
+ (char *)_ADDRESS(pdesc->pnextdesc) - \
+ (char *)_ADDRESS(pdesc) - _HDRSIZE ) )
+
+#define _MEMSIZE(pdesc) ( (char *)_ADDRESS(pdesc->pnextdesc) - \
+ (char *)_ADDRESS(pdesc) )
+
+#define _BACKPTR(addr) ( *(_PBLKDESC*)((char *)(addr) - _HDRSIZE) )
+
+#define _CHECK_PDESC(pdesc) ( (*(_PBLKDESC*) (_ADDRESS(pdesc))) == pdesc )
+
+#define _CHECK_BACKPTR(addr) ( ((char *)(_BACKPTR(addr)->pblock) + _HDRSIZE) \
+ == addr)
+
+
+/*
+ * Heap descriptor
+ */
+
+struct _heap_desc_ {
+
+ _PBLKDESC pfirstdesc; /* pointer to first descriptor */
+ _PBLKDESC proverdesc; /* rover pointer */
+ _PBLKDESC emptylist; /* pointer to empty list */
+
+ _BLKDESC sentinel; /* Sentinel block for end of heap list */
+
+};
+
+extern struct _heap_desc_ _heap_desc;
+
+
+/*
+ * Region descriptor and heap grow data
+ */
+
+struct _heap_region_ {
+ void * _regbase; /* base address of region */
+ unsigned _currsize; /* current size of region */
+ unsigned _totalsize; /* total size of region */
+ };
+
+#ifndef _OLDROVER_
+extern unsigned int _heap_resetsize;
+#endif /* _OLDROVER_ */
+#define _heap_growsize _amblksiz
+extern unsigned int _heap_regionsize;
+extern struct _heap_region_ _heap_regions[];
+
+#ifdef _M_ALPHA
+#define _PAGESIZE_ 0x2000 /* Alpha has 8k pages */
+#else
+#define _PAGESIZE_ 0x1000 /* one page */
+#endif
+
+#define _SEGSIZE_ 0x10000 /* one segment (i.e., 64 Kb) */
+#define _HEAP_REGIONMAX 0x10 /* Max number of regions */
+#define _HEAP_REGIONSIZE 0x400000 /* Default region size (4 meg) */
+
+#ifdef _CRUISER_ /* CRUISER TARGET */
+#define _HEAP_GROWSIZE 0x8000 /* Default grow increment (32K) */
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+#define _HEAP_GROWSIZE 0x10000 /* Default grow increment (64K) */
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+#define _HEAP_GROWSIZE 0x8000 /* Default grow increment (32K) */
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#define _HEAP_GROWMIN _PAGESIZE_ /* Minimum grow inc (1 page) */
+#define _HEAP_GROWSTART _PAGESIZE_ /* Startup grow increment */
+#define _HEAP_COALESCE -1 /* Coalesce heap value */
+
+/*
+ * Values returned by _heap_findaddr() routine
+ */
+
+#define _HEAPFIND_EXACT 0 /* found address exactly */
+#define _HEAPFIND_WITHIN 1 /* address is within a block */
+#define _HEAPFIND_BEFORE -1 /* address before beginning of heap */
+#define _HEAPFIND_AFTER -2 /* address after end of heap */
+#define _HEAPFIND_EMPTY -3 /* address not found: empty heap */
+
+/*
+ * Arguments to _heap_param
+ */
+
+#define _HP_GETPARAM 0 /* get heap parameter value */
+#define _HP_SETPARAM 1 /* set heap parameter value */
+
+#define _HP_AMBLKSIZ 1 /* get/set _amblksiz value (aka */
+#define _HP_GROWSIZE _HP_AMBLKSIZ /* _heap_growsize */
+#define _HP_RESETSIZE 2 /* get/set _heap_resetsize value */
+
+
+/*
+ * Macros to round numbers
+ *
+ * _ROUND2 = rounds a number up to a power of 2
+ * _ROUND = rounds a number up to any other numer
+ *
+ * n = number to be rounded
+ * pow2 = must be a power of two value
+ * r = any number
+ */
+
+#define _ROUND2(n,pow2) \
+ ( ( n + pow2 - 1) & ~(pow2 - 1) )
+
+#define _ROUND(n,r) \
+ ( ( (n/r) + ((n%r)?1:0) ) * r)
+
+/*
+
+ Macros for accessing heap descriptor lists:
+
+ _GETEMPTY(x) = Returns a pointer to an empty heap desc
+ _PUTEMPTY(x) = Puts an empty heap desc on the empty list
+
+ (x = _PBLKDESC = pointer to heap block descriptor)
+*/
+
+#ifdef DEBUG
+
+#define _GETEMPTY(x) \
+{ \
+ if (_heap_desc.emptylist == NULL) \
+ _heap_grow_emptylist(); \
+ \
+ x = _heap_desc.emptylist; \
+ \
+ assert(("bad descriptor in empty list", x->pblock == NULL)); \
+ \
+ _heap_desc.emptylist = _heap_desc.emptylist->pnextdesc; \
+}
+
+#define _PUTEMPTY(x) \
+{ \
+ x->pnextdesc = _heap_desc.emptylist; \
+ \
+ x->pblock = NULL; \
+ \
+ _heap_desc.emptylist = x; \
+}
+
+#else
+
+#define _GETEMPTY(x) \
+{ \
+ if (_heap_desc.emptylist == NULL) \
+ _heap_grow_emptylist(); \
+ \
+ x = _heap_desc.emptylist; \
+ \
+ _heap_desc.emptylist = _heap_desc.emptylist->pnextdesc; \
+}
+
+#define _PUTEMPTY(x) \
+{ \
+ x->pnextdesc = _heap_desc.emptylist; \
+ \
+ _heap_desc.emptylist = x; \
+}
+
+#endif
+
+
+/*
+ * Macros for finding the next 64 Kb boundary from a pointer
+ */
+
+#define _NXTSEGBNDRY(p) ((void *)((unsigned)(p) & 0xffff0000 + 0x10000))
+
+#define _DISTTOBNDRY(p) ((unsigned)(0x10000 - (0x0000ffff & (unsigned)(p))))
+
+
+/*
+ * Define size_t type (if necessary)
+ */
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+
+/*
+ * Prototypes
+ */
+
+void * _CRTAPI1 _flat_malloc(size_t);
+void _CRTAPI1 _heap_abort(void);
+int _CRTAPI1 _heap_addblock(void *, unsigned int);
+
+#ifdef _OLDROVER_
+void _CRTAPI1 _heap_advance_rover(void);
+#endif /* _OLDROVER_ */
+
+void _CRTAPI1 _heap_free_region(int);
+int _CRTAPI1 _heap_findaddr(void *, _PBLKDESC *);
+int _CRTAPI1 _heap_grow(unsigned int);
+void _CRTAPI1 _heap_grow_emptylist(void);
+int _CRTAPI1 _heap_grow_region(unsigned, size_t);
+void _CRTAPI1 _heap_init(void);
+
+#ifndef _OLDROVER_
+int _CRTAPI1 _heap_param(int, int, void *);
+#endif /* _OLDROVER_ */
+
+_PBLKDESC _CRTAPI1 _heap_search(unsigned size);
+void _CRTAPI1 _heap_split_block(_PBLKDESC, size_t);
+
+#ifdef DEBUG
+void _CRTAPI1 _heap_print_all(void);
+void _CRTAPI1 _heap_print_regions(void);
+void _CRTAPI1 _heap_print_desc(void);
+void _CRTAPI1 _heap_print_emptylist(void);
+void _CRTAPI1 _heap_print_heaplist(void);
+#endif
+
+
+/*
+ * Prototypes and macros for multi-thread support
+ */
+
+#ifdef MTHREAD
+
+void _CRTAPI1 _free_lk(void *);
+void * _CRTAPI1 _malloc_lk(size_t);
+size_t _CRTAPI1 _msize_lk(void *);
+
+#ifdef DEBUG
+void _CRTAPI1 _heap_print_regions_lk(void);
+void _CRTAPI1 _heap_print_desc_lk(void);
+void _CRTAPI1 _heap_print_emptylist_lk(void);
+void _CRTAPI1 _heap_print_heaplist_lk(void);
+#endif
+
+#else /* ndef MTHREAD */
+
+#define _malloc_lk(s) malloc(s)
+#define _free_lk(p) free(p)
+#define _msize_lk(p) _msize(p)
+
+#ifdef DEBUG
+#define _heap_print_regions_lk() _heap_print_regions()
+#define _heap_print_desc_lk() _heap_print_desc()
+#define _heap_print_emptylist_lk() _heap_print_emptylist()
+#define _heap_print_heaplist_lk() _heap_print_heaplist()
+#endif
+
+#endif /* MTHREAD */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_HEAP
+#endif /* _INC_HEAP */
diff --git a/private/crt32/h/internal.h b/private/crt32/h/internal.h
new file mode 100644
index 000000000..8609f63bc
--- /dev/null
+++ b/private/crt32/h/internal.h
@@ -0,0 +1,359 @@
+/***
+*internal.h - contains declarations of internal routines and variables
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Declares routines and variables used internally by the C run-time.
+* [Internal]
+*
+*Revision History:
+* 05-18-87 SKS Module created
+* 07-15-87 JCR Added _old_pfxlen and _tempoff
+* 08-05-87 JCR Added _getbuf (corrected by SKS)
+* 11-05-87 JCR Added _buferr
+* 11-18-87 SKS Add __tzset(), made _isindst() near, remove _dtoxmode
+* 01-26-88 SKS Make __tzset, _isindst, _dtoxtime near/far for QC
+* 02-10-88 JCR Cleaned up white space
+* 06-22-88 SKS _canonic/_getcdrv are now used by all models
+* 06-29-88 JCR Removed static buffers _bufout and _buferr
+* 08-18-88 GJF Revised to also work for the 386 (small model only).
+* 09-22-88 GJF Added declarations for _freebuf, _stbuf and _ftbuf.
+* 01-31-89 JCR Removed _canonic, _getcdrv, _getcdwd (see direct.h)
+* 06-07-89 PHG Added _dosret for i860 (N10) version of libs
+* 07-05-89 PHG Changed above to _dosmaperr, added startup variables
+* 08-17-89 GJF Cleanup, removed stuff not needed for 386
+* 10-25-89 JCR Added prototype for _getpath()
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-01-90 GJF Added #ifndef _INC_INTERNAL and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessing
+* directives.
+* 03-21-90 GJF Put _CALLTYPE1 into prototypes.
+* 03-26-90 GJF Added prototypes for _output() and _input(). Filled
+* out the prototype for _openfile
+* 04-05-90 GJF Added prototype for __NMSG_WRITE() (C source build
+* only).
+* 04-10-90 GJF Added prototypes for startup functions.
+* 05-28-90 SBM Added _flush()
+* 07-11-90 SBM Added _commode, removed execload()
+* 07-20-90 SBM Changes supporting clean -W3 compiles (added _cftoe
+* and _cftof prototypes)
+* 08-01-90 SBM Moved _cftoe() and _cftof() to new header
+* <fltintrn.h>, formerly named <struct.h>
+* 08-21-90 GJF Changed prototypes for _amsg_exit() and _NMSG_WRITE().
+* 11-29-90 GJF Added some defs/decls for lowio under Win32.
+* 12-04-90 SRW Added _osfile back for win32. Changed _osfinfo from
+* an array of structures to an array of 32-bit handles
+* (_osfhnd)
+* 04-06-91 GJF Changed _heapinit to _heap_init.
+* 08-19-91 JCR Added _exitflag
+* 08-20-91 JCR C++ and ANSI naming
+* 01-05-92 GJF Added declaration for termination done flag [_WIN32_]
+* 01-08-92 GJF Added prototype for _GetMainArgs.
+* 01-18-92 GJF Added _aexit_rtn.
+* 01-22-92 GJF Fixed definitions of _acmdln and _aexit_rtn for the
+* of crtdll.dll, crtdll.lib.
+* 01-29-92 GJF Added support for linked-in options equivalent to
+* commode.obj and setargv.obj (i.e., special declarations
+* for _commode and _dowildcard).
+* 02-14-92 GJF Replace _nfile with _nhandle for Win32. Also, added
+* #define-s for _NHANDLE_.
+* 03-17-92 GJF Removed declaration of _tmpoff for Win32.
+* 03-30-92 DJM POSIX support.
+* 04-27-92 GJF Added prototypes for _ValidDrive (in stat.c).
+* 05-28-92 GJF Added prototype for _mtdeletelocks() for Win32.
+* 06-02-92 SKS Move prototype for _pgmptr to <DOS.H>
+* 06-02-92 KRS Added prototype for _woutput().
+* 08-06-92 GJF Function calling type and variable type macros.
+* 08-17-92 KRS Added prototype for _winput().
+* 08-21-92 GJF Merged last two changes above.
+* 08-24-92 PBS Added _dstoffset for posix TZ
+* 10-24-92 SKS Add a fourth parameter to _GetMainArgs: wildcard flag
+* _GetMainArgs => __GetMainArgs: 2 leading _'s = internal
+* 10-24-92 SKS Remove two unnecessary parameters from _cenvarg()
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 03-30-93 GJF __gmtotime_t supercedes _dtoxtime.
+* 04-17-93 SKS Add _mtterm
+* 05-11-93 SKS _mtinit now returns success (1) or failure (0)
+* _C_Termination_Done needed in all models (for DLLs)
+* 06-02-93 CFW Add _flswbuf, _filwbuf protos.
+* 07-15-93 SRW Added _capture_argv function prototype
+* 09-22-93 CFW Test for invalid MB chars using global preset flag.
+*
+****/
+
+#ifndef _INC_INTERNAL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <cruntime.h>
+
+/* Define function type used in several startup sources */
+
+typedef void (__cdecl *_PVFV)(void);
+
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifdef _DLL
+#define _commode (*_commode_dll)
+extern int * _commode_dll;
+#else
+#ifdef CRTDLL
+#define _commode _commode_dll
+#endif
+extern int _commode;
+#endif
+
+#ifdef _WIN32_
+
+/*
+ * Define the number of supported handles. This definition must exactly match
+ * the one in os2dll.h.
+ */
+#ifdef MTHREAD
+#define _NHANDLE_ 256
+#else
+#define _NHANDLE_ 64
+#endif
+
+extern int _nhandle; /* == _NHANDLE_, set in ioinit.c */
+
+#else /* ndef _WIN32_ */
+
+extern int _nfile;
+
+#endif /* _WIN32_ */
+
+extern char _osfile[];
+
+#ifdef _WIN32_
+extern long _osfhnd[];
+int _CRTAPI1 _alloc_osfhnd(void);
+int _CRTAPI1 _free_osfhnd(int);
+int _CRTAPI1 _set_osfhnd(int,long);
+#endif /* _WIN32_ */
+
+#ifdef _POSIX_
+extern long _dstoffset;
+#endif /* _POSIX_ */
+
+extern char __dnames[];
+extern char __mnames[];
+
+extern int _days[];
+extern int _lpdays[];
+
+#ifndef _TIME_T_DEFINED
+typedef long time_t; /* time value */
+#define _TIME_T_DEFINED /* avoid multiple def's of time_t */
+#endif
+
+extern time_t _CRTAPI1 __gmtotime_t(int, int, int, int, int, int);
+
+#ifdef _TM_DEFINED
+extern int _CRTAPI1 _isindst(struct tm *);
+#endif
+
+extern void _CRTAPI1 __tzset(void);
+#ifdef _POSIX_
+extern void _CRTAPI1 _tzset(void);
+#endif
+
+extern int _CRTAPI1 _ValidDrive(unsigned);
+
+
+/**
+** This variable is in the C start-up; the length must be kept synchronized
+** It is used by the *cenvarg.c modules
+**/
+
+extern char _acfinfo[]; /* "_C_FILE_INFO=" */
+
+#define CFI_LENGTH 12 /* "_C_FILE_INFO" is 12 bytes long */
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _VA_LIST_DEFINED
+#if defined(_ALPHA_)
+typedef struct {
+ char *a0; /* pointer to first homed integer argument */
+ int offset; /* byte offset of next parameter */
+} va_list;
+#else
+typedef char * va_list;
+#endif
+#define _VA_LIST_DEFINED
+#endif
+
+/*
+ * stdio internals
+ */
+#ifdef _FILE_DEFINED
+
+extern FILE * _lastiob;
+
+FILE * _CRTAPI1 _getstream(void);
+#ifdef _POSIX_
+FILE * _CRTAPI1 _openfile(const char *, const char *, FILE *);
+#else
+FILE * _CRTAPI1 _openfile(const char *, const char *, int, FILE *);
+#endif
+void _CRTAPI1 _getbuf(FILE *);
+int _CRTAPI1 _filwbuf (FILE *);
+int __cdecl _flswbuf(int, FILE *);
+void _CRTAPI1 _freebuf(FILE *);
+int _CRTAPI1 _stbuf(FILE *);
+void _CRTAPI1 _ftbuf(int, FILE *);
+int _CRTAPI1 _output(FILE *, const char *, va_list);
+int _CRTAPI1 _woutput(FILE *, const wchar_t *, va_list);
+int _CRTAPI1 _input(FILE *, const unsigned char *, va_list);
+int _CRTAPI1 _winput(FILE *, const wchar_t *, va_list);
+int _CRTAPI1 _flush(FILE *);
+void _CRTAPI1 _endstdio(void);
+
+#endif
+
+extern int __invalid_mb_chars;
+
+extern int _cflush;
+
+#ifdef _CRUISER_
+extern unsigned int _tmpoff;
+#endif /* _CRUISER_ */
+
+extern unsigned int _tempoff;
+
+extern unsigned int _old_pfxlen;
+
+extern int _umaskval; /* the umask value */
+
+extern char _pipech[]; /* pipe lookahead */
+
+extern char _exitflag; /* callable termination flag */
+
+#if defined(_WIN32_)
+extern int _C_Termination_Done; /* termination done flag */
+#endif /* _WIN32_ */
+
+char * _CRTAPI1 _getpath(const char *, char *, unsigned);
+
+/* startup set values */
+extern char **__argv; /* argument vector */
+extern int __argc; /* argument count */
+extern char *_aenvptr; /* environment ptr */
+
+/* command line */
+#ifdef _DLL
+#define _acmdln (*_acmdln_dll)
+extern char **_acmdln_dll;
+#else
+#ifdef CRTDLL
+#define _acmdln _acmdln_dll
+#endif
+extern char *_acmdln;
+#endif
+
+/*
+ * prototypes for internal startup functions
+ */
+int _CRTAPI1 _cwild(void); /* wild.c */
+char * _CRTAPI1 _find(char *); /* stdarg.asm or stdargv.c */
+#ifdef MTHREAD
+int _CRTAPI1 _mtinit(void); /* tidtable.asm */
+void _CRTAPI1 _mtinitlocks(void); /* mlock.asm */
+void _CRTAPI1 _mtterm(void); /* tidtable.asm */
+void _CRTAPI1 _mtdeletelocks(void); /* mlock.asm */
+#endif
+
+/*
+ * C source build only!!!!
+ *
+ * more prototypes for internal startup functions
+ */
+void _CRTAPI1 _amsg_exit(int); /* crt0.c */
+void _CRTAPI1 _cinit(void); /* crt0dat.c */
+void _CRTAPI1 __doinits(void); /* astart.asm */
+void _CRTAPI1 __doterms(void); /* astart.asm */
+void _CRTAPI1 __dopreterms(void); /* astart.asm */
+void _CRTAPI1 _FF_MSGBANNER(void);
+void _CRTAPI1 _fptrap(void); /* crt0fp.c */
+void _CRTAPI1 _heap_init(void);
+#ifdef _WIN32_
+void _CRTAPI1 _ioinit(void); /* crt0.c, crtlib.c */
+#endif /* _WIN32_ */
+void _CRTAPI1 _NMSG_WRITE(int);
+void _CRTAPI1 _setargv(void); /* setargv.c, stdargv.c */
+void _CRTAPI1 __setargv(void); /* stdargv.c */
+void _CRTAPI1 _setenvp(void); /* stdenvp.c */
+
+#ifdef _DLL
+#define _aexit_rtn (*_aexit_rtn_dll)
+extern void (_CRTAPI1 ** _aexit_rtn_dll)(int);
+#else
+#ifdef CRTDLL
+#define _aexit_rtn _aexit_rtn_dll
+#endif
+extern void (_CRTAPI1 * _aexit_rtn)(int);
+#endif
+
+#ifdef _WIN32_
+#if defined(_DLL) || defined(CRTDLL)
+void _CRTAPI1 __GetMainArgs(int *, char ***, char ***, int);
+#endif
+#endif /* _WIN32_ */
+
+/*
+ * C source build only!!!!
+ *
+ * map OS/2 errors into Xenix errno values -- for modules written in C
+ */
+extern void _CRTAPI1 _dosmaperr(unsigned long);
+
+/*
+ * internal routines used by the exec/spawn functions
+ */
+
+extern int _CRTAPI1 _dospawn(int, const char *, char *, char *);
+extern int _CRTAPI1 _cenvarg(const char * const *, const char * const *,
+ char **, char **, const char *);
+extern char ** _CRTAPI1 _capture_argv(
+ va_list *,
+ const char *,
+ char **,
+ size_t
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_INTERNAL
+#endif /* _INC_INTERNAL */
diff --git a/private/crt32/h/io.h b/private/crt32/h/io.h
new file mode 100644
index 000000000..e41025c7a
--- /dev/null
+++ b/private/crt32/h/io.h
@@ -0,0 +1,236 @@
+/***
+*io.h - declarations for low-level file handling and I/O functions
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the function declarations for the low-level
+* file handling and I/O functions.
+*
+*Revision History:
+* 10/20/87 JCR Removed "MSC40_ONLY" entries
+* 11/09/87 JCR Multi-thread support
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-17-87 JCR Added _MTHREAD_ONLY comments
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 08-19-88 GJF Modified to also work for the 386 (small model only)
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-03-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 08-14-89 GJF Added prototype for _pipe()
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-17-89 GJF read() should take "void *" not "char *", write()
+* should take "const void *" not "char *". Also,
+* added const to appropriate arg types for access(),
+* chmod(), creat(), open() and sopen()
+* 03-01-90 GJF Added #ifndef _INC_IO and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 or _CALLTYPE2 in
+* prototypes.
+* 05-28-90 SBM Added _commit()
+* 01-18-91 GJF ANSI naming.
+* 02-25-91 SRW Exposed _get_osfhandle and _open_osfhandle [_WIN32_]
+* 08-01-91 GJF No _pipe for Dosx32.
+* 08-20-91 JCR C++ and ANSI naming
+* 08-26-91 BWM Added _findfirst, etc.
+* 09-16-91 BWM Changed find handle type to long.
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 03-30-92 DJM POSIX support.
+* 06-23-92 GJF // is non-ANSI comment delimiter.
+* 08-06-92 GJF Function calling type and variable type macros.
+* 08-25-92 GJF For POSIX build, #ifdef-ed out all but some internally
+* used macros (and these are stripped out on release).
+* 09-03-92 GJF Merge two changes above.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 05-11-93 SKS Increased name buffer in finddata structure to 260 bytes.
+*
+****/
+
+#ifndef _INC_IO
+
+#ifndef _POSIX_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _TIME_T_DEFINED
+typedef long time_t; /* time value */
+#define _TIME_T_DEFINED /* avoid multiple def's of time_t */
+#endif
+
+#ifndef _FSIZE_T_DEFINED
+typedef unsigned long _fsize_t; /* Could be 64 bits for Win32 */
+#define _FSIZE_T_DEFINED
+#endif
+
+#ifndef _FINDDATA_T_DEFINED
+
+struct _finddata_t {
+ unsigned attrib;
+ time_t time_create; /* -1 for FAT file systems */
+ time_t time_access; /* -1 for FAT file systems */
+ time_t time_write;
+ _fsize_t size;
+ char name[260];
+};
+
+#define _FINDDATA_T_DEFINED
+
+#endif
+
+/* File attribute constants for _findfirst() */
+
+#define _A_NORMAL 0x00 /* Normal file - No read/write restrictions */
+#define _A_RDONLY 0x01 /* Read only file */
+#define _A_HIDDEN 0x02 /* Hidden file */
+#define _A_SYSTEM 0x04 /* System file */
+#define _A_SUBDIR 0x10 /* Subdirectory */
+#define _A_ARCH 0x20 /* Archive file */
+
+/* function prototypes */
+
+int _CRTAPI1 _access(const char *, int);
+int _CRTAPI1 _chmod(const char *, int);
+int _CRTAPI1 _chsize(int, long);
+int _CRTAPI1 _close(int);
+int _CRTAPI1 _commit(int);
+int _CRTAPI1 _creat(const char *, int);
+int _CRTAPI1 _dup(int);
+int _CRTAPI1 _dup2(int, int);
+int _CRTAPI1 _eof(int);
+long _CRTAPI1 _filelength(int);
+long _CRTAPI1 _findfirst(char *, struct _finddata_t *);
+int _CRTAPI1 _findnext(long, struct _finddata_t *);
+int _CRTAPI1 _findclose(long);
+int _CRTAPI1 _isatty(int);
+int _CRTAPI1 _locking(int, int, long);
+long _CRTAPI1 _lseek(int, long, int);
+char * _CRTAPI1 _mktemp(char *);
+int _CRTAPI2 _open(const char *, int, ...);
+#ifndef _DOSX32_
+int _CRTAPI1 _pipe(int *, unsigned int, int);
+#endif /* _DOSX32_ */
+int _CRTAPI1 _read(int, void *, unsigned int);
+int _CRTAPI1 remove(const char *);
+int _CRTAPI1 rename(const char *, const char *);
+int _CRTAPI1 _setmode(int, int);
+int _CRTAPI2 _sopen(const char *, int, int, ...);
+long _CRTAPI1 _tell(int);
+int _CRTAPI1 _umask(int);
+int _CRTAPI1 _unlink(const char *);
+int _CRTAPI1 _write(int, const void *, unsigned int);
+
+#ifdef MTHREAD /* _MTHREAD_ONLY */
+int _CRTAPI1 _chsize_lk(int,long); /* _MTHREAD_ONLY */
+int _CRTAPI1 _close_lk(int); /* _MTHREAD_ONLY */
+long _CRTAPI1 _lseek_lk(int, long, int); /* _MTHREAD_ONLY */
+int _CRTAPI1 _setmode_lk(int, int); /* _MTHREAD_ONLY */
+int _CRTAPI1 _read_lk(int, void *, unsigned int); /* _MTHREAD_ONLY */
+int _CRTAPI1 _write_lk(int, const void *, unsigned int); /* _MTHREAD_ONLY */
+#else /* not MTHREAD */ /* _MTHREAD_ONLY */
+#define _chsize_lk(fh,size) _chsize(fh,size) /* _MTHREAD_ONLY */
+#define _close_lk(fh) _close(fh) /* _MTHREAD_ONLY */
+#define _lseek_lk(fh,offset,origin) _lseek(fh,offset,origin) /* _MTHREAD_ONLY */
+#define _setmode_lk(fh,mode) _setmode(fh,mode) /* _MTHREAD_ONLY */
+#define _read_lk(fh,buff,count) _read(fh,buff,count) /* _MTHREAD_ONLY */
+#define _write_lk(fh,buff,count) _write(fh,buff,count) /* _MTHREAD_ONLY */
+#endif /* _MTHREAD_ONLY */
+
+#ifdef _WIN32_
+long _CRTAPI1 _get_osfhandle(int);
+int _CRTAPI1 _open_osfhandle(long, int);
+#endif /* _WIN32_ */
+
+#if !(__STDC__ || defined(__cplusplus))
+/* Non-ANSI names for compatibility */
+#ifndef _DOSX32_
+#define access _access
+#define chmod _chmod
+#define chsize _chsize
+#define close _close
+#define creat _creat
+#define dup _dup
+#define dup2 _dup2
+#define eof _eof
+#define filelength _filelength
+#define isatty _isatty
+#define locking _locking
+#define lseek _lseek
+#define mktemp _mktemp
+#define open _open
+#define read _read
+#define setmode _setmode
+#define sopen _sopen
+#define tell _tell
+#define umask _umask
+#define unlink _unlink
+#define write _write
+#else
+int _CRTAPI1 access(const char *, int);
+int _CRTAPI1 chmod(const char *, int);
+int _CRTAPI1 chsize(int, long);
+int _CRTAPI1 close(int);
+int _CRTAPI1 creat(const char *, int);
+int _CRTAPI1 dup(int);
+int _CRTAPI1 dup2(int, int);
+int _CRTAPI1 eof(int);
+long _CRTAPI1 filelength(int);
+int _CRTAPI1 isatty(int);
+int _CRTAPI1 locking(int, int, long);
+long _CRTAPI1 lseek(int, long, int);
+char * _CRTAPI1 mktemp(char *);
+int _CRTAPI2 open(const char *, int, ...);
+int _CRTAPI1 read(int, void *, unsigned int);
+int _CRTAPI1 setmode(int, int);
+int _CRTAPI2 sopen(const char *, int, int, ...);
+long _CRTAPI1 tell(int);
+int _CRTAPI1 umask(int);
+int _CRTAPI1 unlink(const char *);
+int _CRTAPI1 write(int, const void *, unsigned int);
+#endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* _MTHREAD_ONLY */
+#define _close_lk(fh) close(fh) /* _MTHREAD_ONLY */
+#define _lseek_lk(fh,offset,origin) lseek(fh,offset,origin) /* _MTHREAD_ONLY */
+#define _read_lk(fh,buff,count) read(fh,buff,count) /* _MTHREAD_ONLY */
+#define _write_lk(fh,buff,count) write(fh,buff,count) /* _MTHREAD_ONLY */
+
+#endif /* _POSIX_ */
+
+#define _INC_IO
+#endif /* _INC_IO */
diff --git a/private/crt32/h/iomanip.h b/private/crt32/h/iomanip.h
new file mode 100644
index 000000000..43d8980b3
--- /dev/null
+++ b/private/crt32/h/iomanip.h
@@ -0,0 +1,133 @@
+/***
+*iomanip.h - definitions/declarations for iostream's parameterized manipulators
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the classes, values, macros, and functions
+* used by the iostream classes' paramterized manipulators.
+* [AT&T C++]
+*
+*Revision History:
+* 01-23-92 KRS Ported from 16-bit version.
+* 02-23-93 SKS Update copyright to 1993
+* 06-08-93 SKS Add "const" keyword in declaration operator >> & <<
+*
+****/
+
+#ifndef _INC_IOMANIP
+#define _INC_IOMANIP
+#include <iostream.h>
+
+// Force word packing to avoid possible -Zp override
+#pragma pack(4)
+
+#pragma warning(disable:4505) // disable unwanted /W4 warning
+// #pragma warning(default:4505) // use this to reenable, if necessary
+
+// CONSIDER: use macro to define these
+// #define __MKMANIP(X) \#define X##(T) __##X##_ \#\# T
+// __MKMANIP(SMANIP);
+// __MKMANIP(SAPP);
+// __MKMANIP(IMANIP);
+// __MKMANIP(IAPP);
+// __MKMANIP(OMANIP);
+// __MKMANIP(OAPP);
+// __MKMANIP(IOMANIP);
+// __MKMANIP(IOAPP);
+
+#define SMANIP(T) __SMANIP_##T
+#define SAPP(T) __SAPP_##T
+#define IMANIP(T) __IMANIP_##T
+#define IAPP(T) __IAPP_##T
+#define OMANIP(T) __OMANIP_##T
+#define OAPP(T) __OAPP_##T
+#define IOMANIP(T) __IOMANIP_##T
+#define IOAPP(T) __IOAPP_##T
+
+#define IOMANIPdeclare(T) \
+class SMANIP(T) { \
+public: \
+ SMANIP(T)(ios& (*f)(ios&,T), T t) { _fp = f; _tp = t; } \
+ friend istream& operator>>(istream& s, const SMANIP(T) & sm) { (*(sm._fp))(s,sm._tp); return s; } \
+ friend ostream& operator<<(ostream& s, const SMANIP(T) & sm) { (*(sm._fp))(s,sm._tp); return s; } \
+private: \
+ ios& (* _fp)(ios&,T); \
+ T _tp; \
+}; \
+class SAPP(T) { \
+public: \
+ SAPP(T)( ios& (*f)(ios&,T)) { _fp = f; } \
+ SMANIP(T) operator()(T t) { return SMANIP(T)(_fp,t); } \
+private: \
+ ios& (* _fp)(ios&,T); \
+}; \
+class IMANIP(T) { \
+public: \
+ IMANIP(T)(istream& (*f)(istream&,T), T t) { _fp = f; _tp = t; } \
+ friend istream& operator>>(istream& s, IMANIP(T) & sm) { (*sm._fp)(s,sm._tp); return s; } \
+private: \
+ istream& (* _fp)(istream&,T); \
+ T _tp; \
+}; \
+class IAPP(T) { \
+public: \
+ IAPP(T)( istream& (*f)(istream&,T)) { _fp = f; } \
+ IMANIP(T) operator()(T t) { return IMANIP(T)(_fp,t); } \
+private: \
+ istream& (* _fp)(istream&,T); \
+}; \
+class OMANIP(T) { \
+public: \
+ OMANIP(T)(ostream& (*f)(ostream&,T), T t) { _fp = f; _tp = t; } \
+ friend ostream& operator<<(ostream& s, OMANIP(T) & sm) { (*sm._fp)(s,sm._tp); return s; } \
+private: \
+ ostream& (* _fp)(ostream&,T); \
+ T _tp; \
+}; \
+class OAPP(T) { \
+public: \
+ OAPP(T)(ostream& (*f)(ostream&,T)) { _fp = f; } \
+ OMANIP(T) operator()(T t) { return OMANIP(T)(_fp,t); } \
+private: \
+ ostream& (* _fp)(ostream&,T); \
+}; \
+\
+class IOMANIP(T) { \
+public: \
+ IOMANIP(T)(iostream& (*f)(iostream&,T), T t) { _fp = f; _tp = t; } \
+ friend istream& operator>>(iostream& s, IOMANIP(T) & sm) { (*sm._fp)(s,sm._tp); return s; } \
+ friend ostream& operator<<(iostream& s, IOMANIP(T) & sm) { (*sm._fp)(s,sm._tp); return s; } \
+private: \
+ iostream& (* _fp)(iostream&,T); \
+ T _tp; \
+}; \
+class IOAPP(T) { \
+public: \
+ IOAPP(T)( iostream& (*f)(iostream&,T)) { _fp = f; } \
+ IOMANIP(T) operator()(T t) { return IOMANIP(T)(_fp,t); } \
+private: \
+ iostream& (* _fp)(iostream&,T); \
+}; \
+
+
+IOMANIPdeclare(int)
+
+IOMANIPdeclare(long)
+
+inline ios& __resetiosflags(ios& s, long _flg) { s.setf(0,_flg); return s; }
+inline ios& __setfill(ios& s, int _fc) { s.fill((char)_fc); return s; }
+inline ios& __setiosflags(ios& s, long _flg) { s.setf(_flg); return s; }
+inline ios& __setprecision(ios& s, int _pre) { s.precision(_pre); return s; }
+inline ios& __setw(ios& s, int _wid) { s.width(_wid); return s; }
+
+inline SMANIP(long) resetiosflags(long _l) { return SMANIP(long)(__resetiosflags, _l); }
+inline SMANIP(int) setfill(int _m) {return SMANIP(int)(__setfill, _m); }
+inline SMANIP(long) setiosflags(long _l) {return SMANIP(long)(__setiosflags, _l); }
+inline SMANIP(int) setprecision(int _p) {return SMANIP(int)(__setprecision, _p); }
+inline SMANIP(int) setw(int _w) { return SMANIP(int)(__setw, _w); }
+
+// Restore default packing
+#pragma pack()
+
+#endif // !_INC_IOMANIP
diff --git a/private/crt32/h/ios.h b/private/crt32/h/ios.h
new file mode 100644
index 000000000..40234d308
--- /dev/null
+++ b/private/crt32/h/ios.h
@@ -0,0 +1,272 @@
+/***
+*ios.h - definitions/declarations for the ios class.
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the classes, values, macros, and functions
+* used by the ios class.
+* [AT&T C++]
+*
+*Revision History:
+* 01-23-92 KRS Ported from 16-bit version.
+* 03-02-92 KRS Added locks for multithread support.
+* 06-03-92 KRS Add NULL definition here too, for convenience.
+* 08-27-92 KRS Removed bogus 'short' defs from private section.
+* 02-23-93 SKS Update copyright to 1993
+* 03-23-93 CFW Modified #pragma warnings.
+*
+****/
+
+#ifndef _INC_IOS
+#define _INC_IOS
+
+#ifndef _INTERNAL_IFSTRIP_
+#ifdef COMBOINC
+#if defined(_DLL) && !defined(MTHREAD)
+#error Cannot define _DLL without MTHREAD
+#endif
+#endif
+
+#endif /* !_INTERNAL_IFSTRIP_ */
+
+#ifdef MTHREAD
+#ifndef _INTERNAL_IFSTRIP_
+// CONSIDER: change implementation so crit. sect. not exposed
+#include <oscalls.h> // critical section declarations
+#else /* !_INTERNAL_IFSTRIP_ */
+#include <windows.h> // critical section declarations
+#endif /* !_INTERNAL_IFSTRIP_ */
+
+extern "C" {
+void _mtlockinit(PRTL_CRITICAL_SECTION);
+void _mtlock(PRTL_CRITICAL_SECTION);
+void _mtunlock(PRTL_CRITICAL_SECTION);
+}
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef EOF
+#define EOF (-1)
+#endif
+
+// C4505: "unreferenced local function has been removed"
+#pragma warning(disable:4505) // disable C4505 warning
+// #pragma warning(default:4505) // use this to reenable, if desired
+
+// C4103 : "used #pragma pack to change alignment"
+#pragma warning(disable:4103) // disable C4103 warning
+// #pragma warning(default:4103) // use this to reenable, if desired
+
+// Force word packing to avoid possible -Zp override
+#pragma pack(4)
+
+class streambuf;
+class ostream;
+
+class ios {
+
+public:
+ enum io_state { goodbit = 0x00,
+ eofbit = 0x01,
+ failbit = 0x02,
+ badbit = 0x04 };
+
+ enum open_mode { in = 0x01,
+ out = 0x02,
+ ate = 0x04,
+ app = 0x08,
+ trunc = 0x10,
+ nocreate = 0x20,
+ noreplace = 0x40,
+ binary = 0x80 }; // CONSIDER: not in latest spec.
+
+ enum seek_dir { beg=0, cur=1, end=2 };
+
+ enum { skipws = 0x0001,
+ left = 0x0002,
+ right = 0x0004,
+ internal = 0x0008,
+ dec = 0x0010,
+ oct = 0x0020,
+ hex = 0x0040,
+ showbase = 0x0080,
+ showpoint = 0x0100,
+ uppercase = 0x0200,
+ showpos = 0x0400,
+ scientific = 0x0800,
+ fixed = 0x1000,
+ unitbuf = 0x2000,
+ stdio = 0x4000
+ };
+
+ static const long basefield; // dec | oct | hex
+ static const long adjustfield; // left | right | internal
+ static const long floatfield; // scientific | fixed
+
+ ios(streambuf*); // differs from ANSI
+ virtual ~ios();
+
+ inline long flags() const;
+ inline long flags(long _l);
+
+ inline long setf(long _f,long _m);
+ inline long setf(long _l);
+ inline long unsetf(long _l);
+
+ inline int width() const;
+ inline int width(int _i);
+
+ inline ostream* tie(ostream* _os);
+ inline ostream* tie() const;
+
+ inline char fill() const;
+ inline char fill(char _c);
+
+ inline int precision(int _i);
+ inline int precision() const;
+
+ inline int rdstate() const;
+ inline void clear(int _i = 0);
+
+// inline operator void*() const;
+ operator void *() const { if(state&(badbit|failbit) ) return 0; return (void *)this; }
+ inline int operator!() const;
+
+ inline int good() const;
+ inline int eof() const;
+ inline int fail() const;
+ inline int bad() const;
+
+ inline streambuf* rdbuf() const;
+
+ inline long & iword(int) const;
+ inline void * & pword(int) const;
+
+ static long bitalloc();
+ static int xalloc();
+ static void sync_with_stdio();
+
+#ifdef MTHREAD
+ inline void setlock();
+ inline void clrlock();
+ void lock() { if (LockFlg<0) _mtlock(lockptr()); };
+ void unlock() { if (LockFlg<0) _mtunlock(lockptr()); }
+ inline void lockbuf();
+ inline void unlockbuf();
+#else
+ void lock() { }
+ void unlock() { }
+ void lockbuf() { }
+ void unlockbuf() { }
+#endif
+
+protected:
+ ios();
+ ios(const ios&); // treat as private
+ ios& operator=(const ios&);
+ void init(streambuf*);
+
+ enum { skipping, tied };
+ streambuf* bp;
+
+ int state;
+ int ispecial; // not used
+ int ospecial; // not used
+ int isfx_special; // not used
+ int osfx_special; // not used
+ int x_delbuf; // if set, rdbuf() deleted by ~ios
+
+ ostream* x_tie;
+ long x_flags;
+ int x_precision;
+ char x_fill;
+ int x_width;
+
+ static void (*stdioflush)(); // not used
+
+#ifdef MTHREAD
+ static void lockc() { _mtlock(& x_lockc); }
+ static void unlockc() { _mtunlock( & x_lockc); }
+ PRTL_CRITICAL_SECTION lockptr() { return & x_lock; }
+#else
+ static void lockc() { }
+ static void unlockc() { }
+#endif
+
+public:
+ int delbuf() const { return x_delbuf; }
+ void delbuf(int _i) { x_delbuf = _i; }
+
+private:
+ static long x_maxbit;
+ static int x_curindex;
+// consider: make interal static to ios::sync_with_stdio()
+ static int sunk_with_stdio; // make sure sync_with done only once
+#ifdef MTHREAD
+#define MAXINDEX 7
+ static long x_statebuf[MAXINDEX+1]; // used by xalloc()
+ static int fLockcInit; // used to see if x_lockc initialized
+ static RTL_CRITICAL_SECTION x_lockc; // used to lock static (class) data members
+// consider: make pointer and allocate elsewhere
+ int LockFlg; // enable locking flag
+ RTL_CRITICAL_SECTION x_lock; // used for multi-thread lock on object
+#else
+ static long * x_statebuf; // used by xalloc()
+#endif
+};
+
+#include <streamb.h>
+
+inline ios& dec(ios& _strm) { _strm.setf(ios::dec,ios::basefield); return _strm; }
+inline ios& hex(ios& _strm) { _strm.setf(ios::hex,ios::basefield); return _strm; }
+inline ios& oct(ios& _strm) { _strm.setf(ios::oct,ios::basefield); return _strm; }
+
+inline long ios::flags() const { return x_flags; }
+inline long ios::flags(long _l){ long _lO; _lO = x_flags; x_flags = _l; return _lO; }
+
+inline long ios::setf(long _l,long _m){ long _lO; lock(); _lO = x_flags; x_flags = (_l&_m) | (x_flags&(~_m)); unlock(); return _lO; }
+inline long ios::setf(long _l){ long _lO; lock(); _lO = x_flags; x_flags |= _l; unlock(); return _lO; }
+inline long ios::unsetf(long _l){ long _lO; lock(); _lO = x_flags; x_flags &= (~_l); unlock(); return _lO; }
+
+inline int ios::width() const { return x_width; }
+inline int ios::width(int _i){ int _iO; _iO = (int)x_width; x_width = _i; return _iO; }
+
+inline ostream* ios::tie(ostream* _os){ ostream* _osO; _osO = x_tie; x_tie = _os; return _osO; }
+inline ostream* ios::tie() const { return x_tie; }
+inline char ios::fill() const { return x_fill; }
+inline char ios::fill(char _c){ char _cO; _cO = x_fill; x_fill = _c; return _cO; }
+inline int ios::precision(int _i){ int _iO; _iO = (int)x_precision; x_precision = _i; return _iO; }
+inline int ios::precision() const { return x_precision; }
+
+inline int ios::rdstate() const { return state; }
+
+// inline ios::operator void *() const { if(state&(badbit|failbit) ) return 0; return (void *)this; }
+inline int ios::operator!() const { return state&(badbit|failbit); }
+
+inline int ios::bad() const { return state & badbit; }
+// consider: are locks needed on clear() ?
+inline void ios::clear(int _i){ lock(); state = _i; unlock(); }
+inline int ios::eof() const { return state & eofbit; }
+inline int ios::fail() const { return state & (badbit | failbit); }
+inline int ios::good() const { return state == 0; }
+
+inline streambuf* ios::rdbuf() const { return bp; }
+
+inline long & ios::iword(int _i) const { return x_statebuf[_i] ; }
+inline void * & ios::pword(int _i) const { return (void * &)x_statebuf[_i]; }
+
+#ifdef MTHREAD
+ inline void ios::setlock() { LockFlg--; if (bp) bp->setlock(); }
+ inline void ios::clrlock() { if (LockFlg <= 0) LockFlg++; if (bp) bp->clrlock(); }
+ inline void ios::lockbuf() { bp->lock(); }
+ inline void ios::unlockbuf() { bp->unlock(); }
+#endif
+
+// Restore default packing
+#pragma pack()
+
+#endif // !_INC_IOS
diff --git a/private/crt32/h/iostream.h b/private/crt32/h/iostream.h
new file mode 100644
index 000000000..6c07ea39e
--- /dev/null
+++ b/private/crt32/h/iostream.h
@@ -0,0 +1,90 @@
+/***
+*iostream.h - definitions/declarations for iostream classes
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the classes, values, macros, and functions
+* used by the iostream classes.
+* [AT&T C++]
+*
+*Revision History:
+* 01-23-92 KRS Ported from 16-bit version.
+* 02-23-92 KRS Added cruntime.h.
+* 02-23-93 SKS Update copyright to 1993
+* 03-23-93 CFW Modified #pragma warnings.
+*
+****/
+
+#ifndef _INC_IOSTREAM
+#define _INC_IOSTREAM
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#ifdef COMBOINC
+#if defined(_DLL) && !defined(MTHREAD)
+#error Cannot define _DLL without MTHREAD
+#endif
+#endif
+
+// temp hack
+#ifndef _WINSTATIC
+#define _WINSTATIC
+#endif
+
+#endif /* !_INTERNAL_IFSTRIP_ */
+typedef long streamoff, streampos;
+
+#include <ios.h> // Define ios.
+
+#include <streamb.h> // Define streambuf.
+
+#include <istream.h> // Define istream.
+
+#include <ostream.h> // Define ostream.
+
+// C4505: "unreferenced local function has been removed"
+#pragma warning(disable:4505) // disable C4505 warning
+// #pragma warning(default:4505) // use this to reenable, if desired
+
+// C4103 : "used #pragma pack to change alignment"
+#pragma warning(disable:4103) // disable C4103 warning
+// #pragma warning(default:4103) // use this to reenable, if desired
+
+// Force word packing to avoid possible -Zp override
+#pragma pack(4)
+
+class iostream : public istream, public ostream {
+public:
+ iostream(streambuf*);
+ virtual ~iostream();
+protected:
+// consider: make private??
+ iostream();
+ iostream(const iostream&);
+inline iostream& operator=(streambuf*);
+inline iostream& operator=(iostream&);
+private:
+ iostream(ios&);
+ iostream(istream&);
+ iostream(ostream&);
+};
+
+inline iostream& iostream::operator=(streambuf* _sb) { istream::operator=(_sb); ostream::operator=(_sb); return *this; }
+
+inline iostream& iostream::operator=(iostream& _strm) { return operator=(_strm.rdbuf()); }
+
+class Iostream_init {
+public:
+ Iostream_init();
+ Iostream_init(ios &, int =0); // treat as private
+ ~Iostream_init();
+};
+
+// used internally
+// static Iostream_init __iostreaminit; // initializes cin/cout/cerr/clog
+
+// Restore default packing
+#pragma pack()
+
+#endif /* !_INC_IOSTREAM */
diff --git a/private/crt32/h/istream.h b/private/crt32/h/istream.h
new file mode 100644
index 000000000..b881e9181
--- /dev/null
+++ b/private/crt32/h/istream.h
@@ -0,0 +1,165 @@
+/***
+*istream.h - definitions/declarations for the istream class
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the classes, values, macros, and functions
+* used by the istream class.
+* [AT&T C++]
+*
+*Revision History:
+* 01-23-92 KRS Ported from 16-bit version.
+* 02-23-93 SKS Update copyright to 1993
+* 03-23-93 CFW Modified #pragma warnings.
+*
+****/
+
+#ifndef _INC_ISTREAM
+#define _INC_ISTREAM
+
+#include <ios.h>
+
+// C4069: "long double != double"
+#pragma warning(disable:4069) // disable C4069 warning
+// #pragma warning(default:4069) // use this to reenable, if desired
+
+// C4505: "unreferenced local function has been removed"
+#pragma warning(disable:4505) // disable C4505 warning
+// #pragma warning(default:4505) // use this to reenable, if desired
+
+// C4103 : "used #pragma pack to change alignment"
+#pragma warning(disable:4103) // disable C4103 warning
+// #pragma warning(default:4103) // use this to reenable, if desired
+
+// Force word packing to avoid possible -Zp override
+#pragma pack(4)
+
+#ifndef _INTERNAL_IFSTRIP_
+#ifdef COMBOINC
+#if defined(_DLL) && !defined(MTHREAD)
+#error Cannot define _DLL without MTHREAD
+#endif
+#endif
+
+#endif /* !_INTERNAL_IFSTRIP_ */
+
+typedef long streamoff, streampos;
+
+class istream : virtual public ios {
+
+public:
+ istream(streambuf*);
+ virtual ~istream();
+
+ int ipfx(int =0);
+ void isfx() { unlockbuf(); unlock(); }
+
+ inline istream& operator>>(istream& (*_f)(istream&));
+ inline istream& operator>>(ios& (*_f)(ios&));
+ istream& operator>>(char *);
+ inline istream& operator>>(unsigned char *);
+ inline istream& operator>>(signed char *);
+ istream& operator>>(char &);
+ inline istream& operator>>(unsigned char &);
+ inline istream& operator>>(signed char &);
+ istream& operator>>(short &);
+ istream& operator>>(unsigned short &);
+ istream& operator>>(int &);
+ istream& operator>>(unsigned int &);
+ istream& operator>>(long &);
+ istream& operator>>(unsigned long &);
+ istream& operator>>(float &);
+ istream& operator>>(double &);
+ istream& operator>>(long double &);
+ istream& operator>>(streambuf*);
+
+ int get();
+ istream& get(char *,int,char ='\n');
+ inline istream& get(unsigned char *,int,char ='\n');
+ inline istream& get(signed char *,int,char ='\n');
+ istream& get(char &);
+ inline istream& get(unsigned char &);
+ inline istream& get(signed char &);
+ istream& get(streambuf&,char ='\n');
+ inline istream& getline(char *,int,char ='\n');
+ inline istream& getline(unsigned char *,int,char ='\n');
+ inline istream& getline(signed char *,int,char ='\n');
+
+ inline istream& ignore(int =1,int =EOF);
+ istream& read(char *,int);
+ inline istream& read(unsigned char *,int);
+ inline istream& read(signed char *,int);
+
+ int gcount() const { return x_gcount; }
+ int peek();
+ istream& putback(char);
+ int sync();
+
+ istream& seekg(streampos);
+ istream& seekg(streamoff,ios::seek_dir);
+ streampos tellg();
+
+ void eatwhite(); // consider: protect and friend with manipulator ws
+protected:
+ istream();
+ istream(const istream&); // treat as private
+ istream& operator=(streambuf* _isb); // treat as private
+ istream& operator=(const istream& _is) { return operator=(_is.rdbuf()); }
+ int do_ipfx(int);
+
+private:
+ istream(ios&);
+ int getint(char *);
+ int getdouble(char *, int);
+ int _fGline;
+ int x_gcount;
+};
+
+ inline istream& istream::operator>>(istream& (*_f)(istream&)) { (*_f)(*this); return *this; }
+ inline istream& istream::operator>>(ios& (*_f)(ios&)) { (*_f)(*this); return *this; }
+
+ inline istream& istream::operator>>(unsigned char * _s) { return operator>>((char *)_s); }
+ inline istream& istream::operator>>(signed char * _s) { return operator>>((char *)_s); }
+
+ inline istream& istream::operator>>(unsigned char & _c) { return operator>>((char &) _c); }
+ inline istream& istream::operator>>(signed char & _c) { return operator>>((char &) _c); }
+
+ inline istream& istream::get(unsigned char * b, int lim ,char delim) { return get((char *)b, lim, delim); }
+ inline istream& istream::get(signed char * b, int lim, char delim) { return get((char *)b, lim, delim); }
+
+ inline istream& istream::get(unsigned char & _c) { return get((char &)_c); }
+ inline istream& istream::get(signed char & _c) { return get((char &)_c); }
+
+ inline istream& istream::getline(char * _b,int _lim,char _delim) { lock(); _fGline++; get(_b, _lim, _delim); unlock(); return *this; }
+ inline istream& istream::getline(unsigned char * _b,int _lim,char _delim) { lock(); _fGline++; get((char *)_b, _lim, _delim); unlock(); return *this; }
+ inline istream& istream::getline(signed char * _b,int _lim,char _delim) { lock(); _fGline++; get((char *)_b, _lim, _delim); unlock(); return *this; }
+
+ inline istream& istream::ignore(int _n,int delim) { lock(); _fGline++; return get((char *)0, _n+1, (char)delim); unlock(); return *this; }
+
+ inline istream& istream::read(unsigned char * _ptr, int _n) { return read((char *) _ptr, _n); }
+ inline istream& istream::read(signed char * _ptr, int _n) { return read((char *) _ptr, _n); }
+
+class istream_withassign : public istream {
+ public:
+ istream_withassign();
+ istream_withassign(streambuf*);
+ ~istream_withassign();
+ istream& operator=(const istream& _is) { return istream::operator=(_is); }
+ istream& operator=(streambuf* _isb) { return istream::operator=(_isb); }
+};
+
+#ifndef _WINDLL // Warning! Not available under Windows without QuickWin:
+extern istream_withassign cin;
+#endif
+
+inline istream& ws(istream& _ins) { _ins.eatwhite(); return _ins; }
+
+ios& dec(ios&);
+ios& hex(ios&);
+ios& oct(ios&);
+
+// Restore default packing
+#pragma pack()
+
+#endif // !_INC_ISTREAM
diff --git a/private/crt32/h/jctype.h b/private/crt32/h/jctype.h
new file mode 100644
index 000000000..74ed8cf0f
--- /dev/null
+++ b/private/crt32/h/jctype.h
@@ -0,0 +1,111 @@
+/***
+*jctype.h - kanji character conversion macros and jctype macros
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines macros for kanji character classification/conversion.
+*
+*Revision History:
+* 05-10-89 MT Got rid of conditional use of extended keywords
+* based on NO_EXT_KEYS.
+* 05-19-89 MT Added _FAR_ , MTHREAD , and DLL.
+* 05-23-89 MT Got rid of including ctype.h and defined each macro
+* directly without using macros in ctype.h.
+* Prefixed '_' onto dummy parameter names.
+* 08-11-89 GJF Changed DLL to _DLL
+* 08-22-89 GJF Fixed copyright (again)
+* 09-06-89 GJF Removed dummy parameters from prototypes
+* 03-06-90 WAJ Added extern "C".
+* 07-23-90 SBM First version for 32-bit OS/2
+* 08-20-91 JCR C++ naming
+* 08-05-92 GJF Function calling type and variable type macros.
+* 11-30-92 KRS Generalized from 16-bit version to use mbctype.h.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+*******************************************************************************/
+
+#ifndef _INC_JCTYPE
+
+#define _MBCS 1
+#define _KANJI 1
+
+#include <mbctype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/*
+ * This declaration allows the user access to the mbctype look-up
+ * array _mbctype defined in mbctype.obj by simply including jctype.h
+ */
+
+extern unsigned char _CRTVAR1 _mbctype[];
+extern unsigned char _CRTVAR1 _ctype[];
+
+/* Kanji character classification function prototypes */
+#ifndef _JCTYPE_DEFINED
+#define iskana _ismbbkana
+#define iskpun _ismbbkpunct
+#define iskmoji _ismbbkalnum
+#define isalkana _ismbbalpha
+#define ispnkana _ismbbpunct
+#define isalnmkana _ismbbalnum
+#define isprkana _ismbbprint
+#define isgrkana _ismbbgraph
+#define iskanji _ismbblead
+#define iskanji2 _ismbbtrail
+#define _JCTYPE_DEFINED
+
+#else
+
+/* the kanji character classification macro definitions */
+
+#define iskana(_c) ((_mbctype+1)[(unsigned char)(_c)] & (_MS|_MP))
+#define iskpun(_c) ((_mbctype+1)[(unsigned char)(_c)] & _MP)
+#define iskmoji(_c) ((_mbctype+1)[(unsigned char)(_c)] & _MS)
+#define isalkana(_c) (((_ctype+1)[(unsigned char)(_c)] & (_UPPER|_LOWER))||iskmoji(_c))
+#define ispnkana(_c) (((_ctype+1)[(unsigned char)(_c)] & _PUNCT)||iskpun(_c))
+#define isalnmkana(_c) (((_ctype+1)[(unsigned char)(_c)] & (_UPPER|_LOWER|_DIGIT))||iskmoji(_c))
+#define isprkana(_c) (((_ctype+1)[(unsigned char)(_c)] & (_BLANK|_PUNCT|_UPPER|_LOWER|_DIGIT))||iskana(_c))
+#define isgrkana(_c) (((_ctype+1)[(unsigned char)(_c)] & (_PUNCT|_UPPER|_LOWER|_DIGIT))||iskana(_c))
+
+#define iskanji(_c) ((_mbctype+1)[(unsigned char)(_c)] & _M1)
+#define iskanji2(_c) ((_mbctype+1)[(unsigned char)(_c)] & _M2)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_JCTYPE
+#endif /* _INC_JCTYPE */
diff --git a/private/crt32/h/limits.h b/private/crt32/h/limits.h
new file mode 100644
index 000000000..0cdde7d1f
--- /dev/null
+++ b/private/crt32/h/limits.h
@@ -0,0 +1,89 @@
+/***
+*limits.h - implementation dependent values
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains defines for a number of implementation dependent values
+* which are commonly used in C programs.
+* [ANSI]
+*
+*Revision History:
+* 06-03-87 JMB Added support for unsigned char max values
+* 08-19-88 GJF Revised to also support the 386
+* 04-28-89 SKS Put parentheses around negative constants
+* 08-17-89 GJF Cleanup, now specific to 386
+* 10-30-89 GJF Fixed copyright
+* 11-15-89 KRS Add MB_LEN_MAX, fix CHAR_MIN/MAX, order like ANSI spec.
+* 03-01-90 GJF Added #ifndef _INC_LIMITS stuff
+* 02-21-91 KRS Change MB_LEN_MAX to 2 for C 7.00.
+* 03-30-92 DJM POSIX support.
+* 08-22-92 SRW Fix value of _POSIX_ARG_MAX
+* 12-14-92 SRW Fix value of _POSIX_ARG_MAX again
+* 12-14-92 SRW Back merge MattBr's changes from 10/29/92
+* 01-15-93 CFW Added __c_lconvinit dummy variable.
+* 01-28-93 SRW MAke PATH_MAX for Posix right for Posix
+* 02-01-93 CFW Removed __c_lconvinit vars to locale.h.
+* 03-10-93 MJB More fixes for Posix.
+* 04-20-93 GJF Changed SCHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN
+*
+****/
+
+#ifndef _INC_LIMITS
+
+#define CHAR_BIT 8 /* number of bits in a char */
+#define SCHAR_MIN (-128) /* minimum signed char value */
+#define SCHAR_MAX 127 /* maximum signed char value */
+#define UCHAR_MAX 0xff /* maximum unsigned char value */
+
+#ifndef _CHAR_UNSIGNED
+#define CHAR_MIN SCHAR_MIN /* mimimum char value */
+#define CHAR_MAX SCHAR_MAX /* maximum char value */
+#else
+#define CHAR_MIN 0
+#define CHAR_MAX UCHAR_MAX
+#endif /* _CHAR_UNSIGNED */
+
+#define MB_LEN_MAX 2 /* max. # bytes in multibyte char */
+#define SHRT_MIN (-32768) /* minimum (signed) short value */
+#define SHRT_MAX 32767 /* maximum (signed) short value */
+#define USHRT_MAX 0xffff /* maximum unsigned short value */
+#define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */
+#define INT_MAX 2147483647 /* maximum (signed) int value */
+#define UINT_MAX 0xffffffff /* maximum unsigned int value */
+#define LONG_MIN (-2147483647 - 1) /* minimum (signed) long value */
+#define LONG_MAX 2147483647 /* maximum (signed) long value */
+#define ULONG_MAX 0xffffffff /* maximum unsigned long value */
+
+#ifdef _POSIX_
+
+#define _POSIX_ARG_MAX 4096
+#define _POSIX_CHILD_MAX 6
+#define _POSIX_LINK_MAX 8
+#define _POSIX_MAX_CANON 255
+#define _POSIX_MAX_INPUT 255
+#define _POSIX_NAME_MAX 14
+#define _POSIX_NGROUPS_MAX 0
+#define _POSIX_OPEN_MAX 16
+#define _POSIX_PATH_MAX 255
+#define _POSIX_PIPE_BUF 512
+#define _POSIX_SSIZE_MAX 32767
+#define _POSIX_STREAM_MAX 8
+#define _POSIX_TZNAME_MAX 3
+
+#define ARG_MAX 14500 /* 16k heap, minus overhead */
+#define MAX_CANON _POSIX_MAX_CANON
+#define MAX_INPUT _POSIX_MAX_INPUT
+#define NAME_MAX 255
+#define NGROUPS_MAX 16
+#define OPEN_MAX 32
+#define PATH_MAX 512
+#define PIPE_BUF _POSIX_PIPE_BUF
+#define SSIZE_MAX _POSIX_SSIZE_MAX
+#define STREAM_MAX 20
+#define TZNAME_MAX 10
+
+#endif /* POSIX */
+
+#define _INC_LIMITS
+#endif /* _INC_LIMITS */
diff --git a/private/crt32/h/locale.h b/private/crt32/h/locale.h
new file mode 100644
index 000000000..43e6f1615
--- /dev/null
+++ b/private/crt32/h/locale.h
@@ -0,0 +1,125 @@
+/***
+*locale.h - definitions/declarations for localization routines
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the structures, values, macros, and functions
+* used by the localization routines.
+*
+*Revision History:
+* 03-21-89 JCR Module created.
+* 03-11-89 JCR Modified for 386.
+* 04-06-89 JCR Corrected lconv definition (don't use typedef)
+* 04-18-89 JCR Added _LCONV_DEFINED so locale.h can be included twice
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-04-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright, removed dummy args from prototype
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-01-90 GJF Added #ifndef _INC_LOCALE and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-15-90 GJF Replaced _cdecl with _CALLTYPE1 in prototypes.
+* 11-12-90 GJF Changed NULL to (void *)0.
+* 02-12-91 GJF Only #define NULL if it isn't #define-d.
+* 08-20-91 JCR C++ and ANSI naming
+* 08-05-92 GJF Function calling type and variable type macros.
+* 12-29-92 CFW Added _lc_time_data definition and supporting #defines.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 02-01-93 CFW Removed __c_lconvinit vars to locale.h.
+* 02-08-93 CFW Removed time definitions to setlocal.h.
+*
+****/
+
+#ifndef _INC_LOCALE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+/* Locale categories */
+
+#define LC_ALL 0
+#define LC_COLLATE 1
+#define LC_CTYPE 2
+#define LC_MONETARY 3
+#define LC_NUMERIC 4
+#define LC_TIME 5
+
+#define LC_MIN LC_ALL
+#define LC_MAX LC_TIME
+
+/* Locale convention structure */
+
+#ifndef _LCONV_DEFINED
+struct lconv {
+ char *decimal_point;
+ char *thousands_sep;
+ char *grouping;
+ char *int_curr_symbol;
+ char *currency_symbol;
+ char *mon_decimal_point;
+ char *mon_thousands_sep;
+ char *mon_grouping;
+ char *positive_sign;
+ char *negative_sign;
+ char int_frac_digits;
+ char frac_digits;
+ char p_cs_precedes;
+ char p_sep_by_space;
+ char n_cs_precedes;
+ char n_sep_by_space;
+ char p_sign_posn;
+ char n_sign_posn;
+ };
+#define _LCONV_DEFINED
+#endif
+
+/* function prototypes */
+
+char * _CRTAPI1 setlocale(int, const char *);
+struct lconv * _CRTAPI1 localeconv(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_LOCALE
+#endif /* _INC_LOCALE */
diff --git a/private/crt32/h/malloc.h b/private/crt32/h/malloc.h
new file mode 100644
index 000000000..975f6c3fb
--- /dev/null
+++ b/private/crt32/h/malloc.h
@@ -0,0 +1,168 @@
+/***
+*malloc.h - declarations and definitions for memory allocation functions
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the function declarations for memory allocation functions;
+* also defines manifest constants and types used by the heap routines.
+* [System V]
+*
+*Revision History:
+* 01-08-87 JMB Standardized header, added heap consistency routines
+* 02-26-87 BCM added the manifest constant _HEAPBADPTR
+* 04-13-87 JCR Added size_t and "void *" to declarations
+* 04-24-87 JCR Added 'defined' statements around _heapinfo
+* 05-15-87 SKS Cleaned up _CDECL and near/far ptr declarations
+* corrected #ifdef usage, and added _amblksiz
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-05-88 JCR Added DLL _amblksiz support
+* 02-10-88 JCR Cleaned up white space
+* 04-21-88 WAJ Added _FAR_ to halloc/_fmalloc/_nmalloc
+* 05-13-88 GJF Added new heap functions
+* 05-18-88 GJF Removed #defines, added prototypes for _heapchk, _heapset
+* and _heapwalk
+* 05-25-88 GJF Added _bheapseg
+* 08-22-88 GJF Modified to also work for the 386 (small model only,
+* no far or based heap support)
+* 12-07-88 JCR DLL refers to _amlbksiz directly now
+* 01-10-89 JCR Removed sbrk() prototype
+* 04-28-89 SKS Put parentheses around negative constants
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-01-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-27-89 JCR Removed near (_n) and _freect/memavl/memmax prototypes
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-01-90 GJF Added #ifndef _INC_MALLOC and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 in prototypes.
+* 04-10-90 GJF Made stackavail() _CALLTYPE1, _amblksiz _VARTYPE1.
+* 01-17-91 GJF ANSI naming.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-23-91 JCR stackavail() not supported in WIN32
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 01-18-92 JCR put _CRTHEAP_ ifdefs in; this stuff is only needed
+* for a heap implemented in the runtime (not OS)
+* 08-05-92 GJF Function calling type and variable type macros.
+* 08-22-92 SRW Add alloca intrinsic pragma for MIPS
+* 09-03-92 GJF Merged two changes above.
+* 09-23-92 SRW Change winheap code to call NT directly always
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 02-02-93 SRW Removed bogus semicolon on #pragma
+* 06-10-93 SRW Use _MIPS_ instead of MIPS
+*
+****/
+
+#ifndef _INC_MALLOC
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+/* maximum heap request that can ever be honored */
+#define _HEAP_MAXREQ 0xFFFFFFD8
+
+/* constants for _heapchk/_heapset/_heapwalk routines */
+#define _HEAPEMPTY (-1)
+#define _HEAPOK (-2)
+#define _HEAPBADBEGIN (-3)
+#define _HEAPBADNODE (-4)
+#define _HEAPEND (-5)
+#define _HEAPBADPTR (-6)
+#define _FREEENTRY 0
+#define _USEDENTRY 1
+
+#ifndef _HEAPINFO_DEFINED
+typedef struct _heapinfo {
+ int * _pentry;
+ size_t _size;
+ int _useflag;
+ } _HEAPINFO;
+#define _HEAPINFO_DEFINED
+#endif
+
+#ifdef _CRTHEAP_
+/* external variable declarations */
+
+extern unsigned int _CRTVAR1 _amblksiz;
+
+#endif /* _CRTHEAP_ */
+
+/* function prototypes */
+void * _CRTAPI1 calloc(size_t, size_t);
+void _CRTAPI1 free(void *);
+void * _CRTAPI1 malloc(size_t);
+void * _CRTAPI1 realloc(void *, size_t);
+
+#ifndef _POSIX_
+void * _CRTAPI1 _alloca(size_t);
+void * _CRTAPI1 _expand(void *, size_t);
+#ifdef _CRTHEAP_
+int _CRTAPI1 _heapadd(void *, size_t);
+#endif
+int _CRTAPI1 _heapchk(void);
+int _CRTAPI1 _heapmin(void);
+int _CRTAPI1 _heapset(unsigned int);
+int _CRTAPI1 _heapwalk(_HEAPINFO *);
+size_t _CRTAPI1 _msize(void *);
+#ifndef _WIN32_
+size_t _CRTAPI1 _stackavail(void);
+#endif
+#endif /* !_POSIX_ */
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#ifndef _DOSX32_
+#define alloca _alloca
+#else
+void * _CRTAPI1 alloca(size_t);
+#ifndef _WIN32_
+size_t _CRTAPI1 stackavail(void);
+#endif
+#endif
+#endif /* __STDC__*/
+
+#if defined(_M_MRX000) || defined(_M_PPC)
+#pragma intrinsic(_alloca)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_MALLOC
+#endif /* _INC_MALLOC */
diff --git a/private/crt32/h/math.h b/private/crt32/h/math.h
new file mode 100644
index 000000000..2ebd5dbb7
--- /dev/null
+++ b/private/crt32/h/math.h
@@ -0,0 +1,283 @@
+/***
+*math.h - definitions and declarations for math library
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains constant definitions and external subroutine
+* declarations for the math subroutine library.
+* [ANSI/System V]
+*
+*Revision History:
+* 10/20/87 JCR Removed "MSC40_ONLY" entries
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 02-10-88 WAJ Changed HUGE and HUGE_VAL definitions for DLL libraries
+* 05-32-88 PHG Added _CDECL and _NEAR for declaration of HUGE
+* 08-22-88 GJF Modified to also work with the 386 (small model only)
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-02-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-20-89 JCR Routines are now _cdecl in both single and multi-thread
+* 12-14-89 WAJ Removed pascal from mthread version.
+* 03-01-90 GJF Added #ifndef _INC_MATH and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-29-90 GJF Replaced _cdecl with _VARTYPE1, _CALLTYPE1 or
+* _CALLTYPE2, as appropriate.
+* 07-30-90 SBM Removed special _DLL definitions of HUGE and HUGE_VAL
+* 08-17-90 WAJ Floating point routines now use _stdcall.
+* 08-08-91 GJF Added long double stuff. ANSI naming.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 10-03-91 GDP Added #pragma function(...)
+* No floating point intrinsics for WIN32/NT86
+* 10-06-91 SRW Removed long double stuff.
+* 01-24-92 GJF Fixed [_]HUGE for crtdll.dll.
+* 01-30-92 GJF Removed prototypes and macros for the ieee-to/from-
+* msbin functions (they don't exist).
+* 08-05-92 GJF Function calling type and variable type macros.
+* 12-18-92 GDP Removed #pragma function(...)
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 11-17-93 CFW Fixed HUGE (oldname) macro, now maps to _HUGE.
+* 01-13-94 RDL Added #ifndef _LANGUAGE_ASSEMBLY for asm includes.
+*
+****/
+
+#ifndef _INC_MATH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/* definition of _exception struct - this struct is passed to the matherr
+ * routine when a floating point exception is detected
+ */
+
+#ifndef _EXCEPTION_DEFINED
+struct _exception {
+ int type; /* exception type - see below */
+ char *name; /* name of function where error occured */
+ double arg1; /* first argument to function */
+ double arg2; /* second argument (if any) to function */
+ double retval; /* value to be returned by function */
+ } ;
+
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#define exception _exception
+#endif
+
+#define _EXCEPTION_DEFINED
+#endif
+
+
+/* definition of a _complex struct to be used by those who use cabs and
+ * want type checking on their argument
+ */
+
+#ifndef _COMPLEX_DEFINED
+struct _complex {
+ double x,y; /* real and imaginary parts */
+ } ;
+
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#define complex _complex
+#endif
+
+#define _COMPLEX_DEFINED
+#endif
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+
+/* Constant definitions for the exception type passed in the _exception struct
+ */
+
+#define _DOMAIN 1 /* argument domain error */
+#define _SING 2 /* argument singularity */
+#define _OVERFLOW 3 /* overflow range error */
+#define _UNDERFLOW 4 /* underflow range error */
+#define _TLOSS 5 /* total loss of precision */
+#define _PLOSS 6 /* partial loss of precision */
+
+#define EDOM 33
+#define ERANGE 34
+
+
+/* definitions of _HUGE and HUGE_VAL - respectively the XENIX and ANSI names
+ * for a value returned in case of error by a number of the floating point
+ * math routines
+ */
+#ifndef _LANGUAGE_ASSEMBLY
+#ifdef _DLL
+#define _HUGE (*_HUGE_dll)
+extern double * _CRTVAR1 _HUGE_dll;
+#else
+#ifdef CRTDLL
+#define _HUGE _HUGE_dll
+#endif
+extern double _CRTVAR1 _HUGE;
+#endif
+#endif /* _LANGUAGE_ASSEMBLY */
+
+#define HUGE_VAL _HUGE
+
+/* function prototypes */
+
+#ifndef _LANGUAGE_ASSEMBLY
+int _CRTAPI1 abs(int);
+double _CRTAPI1 acos(double);
+double _CRTAPI1 asin(double);
+double _CRTAPI1 atan(double);
+double _CRTAPI1 atan2(double, double);
+double _CRTAPI1 atof(const char *);
+double _CRTAPI1 _cabs(struct _complex);
+double _CRTAPI1 ceil(double);
+double _CRTAPI1 cos(double);
+double _CRTAPI1 cosh(double);
+double _CRTAPI1 exp(double);
+double _CRTAPI1 fabs(double);
+double _CRTAPI1 floor(double);
+double _CRTAPI1 fmod(double, double);
+double _CRTAPI1 frexp(double, int *);
+double _CRTAPI1 _hypot(double, double);
+double _CRTAPI1 _j0(double);
+double _CRTAPI1 _j1(double);
+double _CRTAPI1 _jn(int, double);
+long _CRTAPI1 labs(long);
+double _CRTAPI1 ldexp(double, int);
+double _CRTAPI1 log(double);
+double _CRTAPI1 log10(double);
+int _CRTAPI1 _matherr(struct _exception *);
+double _CRTAPI1 modf(double, double *);
+double _CRTAPI1 pow(double, double);
+double _CRTAPI1 sin(double);
+double _CRTAPI1 sinh(double);
+double _CRTAPI1 sqrt(double);
+double _CRTAPI1 tan(double);
+double _CRTAPI1 tanh(double);
+double _CRTAPI1 _y0(double);
+double _CRTAPI1 _y1(double);
+double _CRTAPI1 _yn(int, double);
+#ifdef _M_MRX000
+
+/* MIPS fast prototypes for float */
+/* ANSI C, 4.5 Mathematics */
+
+/* 4.5.2 Trigonometric functions */
+
+float __cdecl acosf( float );
+float __cdecl asinf( float );
+float __cdecl atanf( float );
+float __cdecl atan2f( float , float );
+float __cdecl cosf( float );
+float __cdecl sinf( float );
+float __cdecl tanf( float );
+
+/* 4.5.3 Hyperbolic functions */
+float __cdecl coshf( float );
+float __cdecl sinhf( float );
+float __cdecl tanhf( float );
+
+/* 4.5.4 Exponential and logarithmic functions */
+float __cdecl expf( float );
+float __cdecl logf( float );
+float __cdecl log10f( float );
+float __cdecl modff( float , float* );
+
+/* 4.5.5 Power functions */
+float __cdecl powf( float , float );
+float __cdecl sqrtf( float );
+
+/* 4.5.6 Nearest integer, absolute value, and remainder functions */
+float __cdecl ceilf( float );
+float __cdecl fabsf( float );
+float __cdecl floorf( float );
+float __cdecl fmodf( float , float );
+
+#endif /* _M_MRX000 */
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+
+#define DOMAIN _DOMAIN
+#define SING _SING
+#define OVERFLOW _OVERFLOW
+#define UNDERFLOW _UNDERFLOW
+#define TLOSS _TLOSS
+#define PLOSS _PLOSS
+
+#define matherr _matherr
+
+#define HUGE _HUGE
+
+#ifndef _DOSX32_
+#define cabs _cabs
+#define hypot _hypot
+#define j0 _j0
+#define j1 _j1
+#define jn _jn
+#define matherr _matherr
+#define y0 _y0
+#define y1 _y1
+#define yn _yn
+
+#define cabsl _cabsl
+#define hypotl _hypotl
+#else
+#ifndef _LANGUAGE_ASSEMBLY
+double _CRTAPI1 cabs(struct complex);
+double _CRTAPI1 hypot(double, double);
+double _CRTAPI1 j0(double);
+double _CRTAPI1 j1(double);
+double _CRTAPI1 jn(int, double);
+double _CRTAPI1 y0(double);
+double _CRTAPI1 y1(double);
+double _CRTAPI1 yn(int, double);
+
+#endif /* _LANGUAGE_ASSEMBLY */
+
+#endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_MATH
+#endif /* _INC_MATH */
diff --git a/private/crt32/h/mbctype.h b/private/crt32/h/mbctype.h
new file mode 100644
index 000000000..990f1a0a4
--- /dev/null
+++ b/private/crt32/h/mbctype.h
@@ -0,0 +1,146 @@
+/***
+*mbctype.h - MBCS character conversion macros
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines macros for MBCS character classification/conversion.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 02-23-93 SKS Update copyright to 1993
+* 07-09-93 KRS Fix problems with _isxxxlead/trail macros, etc.
+* 08-12-93 CFW Change _mbctype type, fix ifstrip macro name.
+*
+*******************************************************************************/
+
+/* include the standard ctype.h header file */
+
+#include <ctype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#ifdef COMBOINC
+#if defined(_DLL) && !defined(MTHREAD)
+#error Cannot define _DLL without MTHREAD
+#endif
+#endif
+
+#endif /* !_INTERNAL_IFSTRIP */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+#ifndef _MBCS
+/*
+ * SBCS - Single Byte Character Set
+ */
+
+#define _ismbblead(_c) (0)
+#define _ismbbtrail(_c) (0)
+#define _ismbslead(_s,_c) (0)
+#define _ismbstrail(_s,_c) (0)
+
+#else
+
+/*
+ * MBCS - Multi-Byte Character Set
+ */
+
+/*
+ * This declaration allows the user access the _mbctype[] look-up array.
+ */
+
+#ifdef _DLL
+extern unsigned char * _CRTVAR1 _mbctype;
+#else
+extern unsigned char _CRTVAR1 _mbctype[];
+#endif
+
+/* bit masks for MBCS character types */
+
+#define _MS 0x01 /* MBCS single-byte symbol */
+#define _MP 0x02 /* MBCS punct */
+#define _M1 0x04 /* MBCS 1st (lead) byte */
+#define _M2 0x08 /* MBCS 2nd byte*/
+
+/* byte types */
+
+#define _MBC_SINGLE 0 /* valid single byte char */
+#define _MBC_LEAD 1 /* lead byte */
+#define _MBC_TRAIL 2 /* trailing byte */
+#define _MBC_ILLEGAL (-1) /* illegal byte */
+
+
+/* MBCS character classification function prototypes */
+
+#ifndef _MBCTYPE_DEFINED
+
+/* byte routines */
+#ifdef _KANJI
+int _CRTAPI1 _ismbbkalnum( unsigned int );
+int _CRTAPI1 _ismbbkana( unsigned int );
+int _CRTAPI1 _ismbbkpunct( unsigned int );
+#endif
+int _CRTAPI1 _ismbbalpha( unsigned int );
+int _CRTAPI1 _ismbbpunct( unsigned int );
+int _CRTAPI1 _ismbbalnum( unsigned int );
+int _CRTAPI1 _ismbbprint( unsigned int );
+int _CRTAPI1 _ismbbgraph( unsigned int );
+
+#ifndef _MBLEADTRAIL_DEFINED
+int _CRTAPI1 _ismbblead( unsigned int );
+int _CRTAPI1 _ismbbtrail( unsigned int );
+int _CRTAPI1 _ismbslead( const unsigned char *, const unsigned char *);
+int _CRTAPI1 _ismbstrail( const unsigned char *, const unsigned char *);
+#define _MBLEADTRAIL_DEFINED
+#endif
+
+#define _MBCTYPE_DEFINED
+#endif
+
+/*
+ * char byte classification macros
+ */
+
+#ifdef _KANJI
+#define _ismbbkana(_c) ((_mbctype+1)[(unsigned char)(_c)] & (_MS|_MP))
+#define _ismbbkpunct(_c) ((_mbctype+1)[(unsigned char)(_c)] & _MP)
+#define _ismbbkalnum(_c) ((_mbctype+1)[(unsigned char)(_c)] & _MS)
+#define _ismbbalpha(_c) (((_ctype+1)[(unsigned char)(_c)] & (_UPPER|_LOWER))||_ismbbkalnum(_c))
+#define _ismbbpunct(_c) (((_ctype+1)[(unsigned char)(_c)] & _PUNCT)||_ismbbkpunct(_c))
+#define _ismbbalnum(_c) (((_ctype+1)[(unsigned char)(_c)] & (_UPPER|_LOWER|_DIGIT))||_ismbbkalnum(_c))
+#define _ismbbprint(_c) (((_ctype+1)[(unsigned char)(_c)] & (_BLANK|_PUNCT|_UPPER|_LOWER|_DIGIT))||_ismbbkana(_c))
+#define _ismbbgraph(_c) (((_ctype+1)[(unsigned char)(_c)] & (_PUNCT|_UPPER|_LOWER|_DIGIT))||_ismbbkana(_c))
+#endif
+
+#define _ismbblead(_c) ((_mbctype+1)[(unsigned char)(_c)] & _M1)
+#define _ismbbtrail(_c) ((_mbctype+1)[(unsigned char)(_c)] & _M2)
+
+#endif /* _MBCS */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/private/crt32/h/mbdata.h b/private/crt32/h/mbdata.h
new file mode 100644
index 000000000..4a70f682f
--- /dev/null
+++ b/private/crt32/h/mbdata.h
@@ -0,0 +1,130 @@
+/***
+*mbdata.h - MBCS lib data
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines data for use when building MBCS libs and routines
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 02-23-93 SKS Update copyright to 1993
+* 08-03-93 KRS Move _ismbbtruelead() from mbctype.h. Internal-only.
+*
+*******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP
+#ifdef COMBOINC
+#if defined(_DLL) && !defined(MTHREAD)
+#error Cannot define _DLL without MTHREAD
+#endif
+#endif
+#endif /* !_INTERNAL_IFSTRIP */
+
+/* validate MBCS defines */
+#ifdef _MBCS
+
+#if (!defined(_KANJI) && !defined(_MBCS_OS))
+#error Must specify MBCS locale.
+#endif
+
+#if (defined(_KANJI) && defined(_MBCS_OS))
+#error Can't define _KANJI and _MBCS_OS together.
+#endif
+
+#else
+
+#if defined(_KANJI)
+#error Can not specify locale without definining _MBCS.
+#endif
+
+#if defined(_MBCS_OS)
+#error Can not specify locale without definining _MBCS.
+#error *** _MBCS_OS NOT IMPLEMENTED ***
+#endif
+
+#endif
+
+
+#ifndef _MBCS
+
+/*
+ * SBCS - Single Byte Character Set
+ */
+
+#define _ISLEADBYTE(c) (0)
+#define _ISTRAILBYTE(c) (0)
+
+#define _ismbbtruelead(_lb,_ch) (0)
+
+#else
+
+/*
+ * MBCS - Multi-Byte Character Set
+ */
+
+extern unsigned int _mbascii; /* flag for handling MB ASCII chars */
+
+/*
+ * general use macros for model dependent/independet versions.
+ */
+
+#define _ISLEADBYTE(c) _ismbblead(c)
+#define _ISTRAILBYTE(c) _ismbbtrail(c)
+
+#define _ismbbtruelead(_lb,_ch) (!(_lb) && _ismbblead((_ch)))
+
+/* define char range values */
+
+#ifdef _KANJI
+
+#define _MBASCIILEAD 0x82 /* lead byte value for MB ASCII char */
+
+#define _MBUPPERLOW 0x8260 /* upper case */
+#define _MBUPPERHIGH 0x8279
+#define _MBLOWERLOW 0x8281 /* lower case */
+#define _MBLOWERHIGH 0x829a
+#define _MBCASEDIFF 0x21 /* diff between upper and lower case letters */
+
+#define _MBDIGITLOW 0x824f /* digit */
+#define _MBDIGITHIGH 0x8258
+
+#define _MBSPACECHAR 0x8140 /* space */
+
+/* Kanji-specific ranges */
+#define _MBHIRALOW 0x829f /* hiragana */
+#define _MBHIRAHIGH 0x82f1
+
+#define _MBKATALOW 0x8340 /* katakana */
+#define _MBKATAHIGH 0x8396
+#define _MBKATAEXCEPT 0x837f /* exception */
+
+#define _MBKIGOULOW 0x8141 /* kanji punctuation */
+#define _MBKIGOUHIGH 0x81ac
+#define _MBKIGOUEXCEPT 0x817f /* exception */
+
+#endif
+
+
+#ifdef _MBCS_OS
+
+/*
+ * Portable MBCS libs
+ */
+
+#ifndef _WIN32_
+extern unsigned int _CRTVAR1 _mbcsflag; /* pulls in _mbcsinit code */
+#endif
+
+#endif
+
+
+#endif /* MBCS */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/private/crt32/h/mbstring.h b/private/crt32/h/mbstring.h
new file mode 100644
index 000000000..5b05f3690
--- /dev/null
+++ b/private/crt32/h/mbstring.h
@@ -0,0 +1,227 @@
+/***
+* mbstring.h - MBCS string manipulation macros and functions
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains macros and function declarations for the MBCS
+* string manipulation functions.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 02-23-93 SKS Update copyright to 1993
+* 05-24-93 KRS Added new functions from Ikura.
+* 07-09-93 KRS Put proper switches around _ismbblead/trail.
+* 07-14-93 KRS Add new mbsnbxxx functions: byte-count versions.
+* 08-12-93 CFW Fix ifstrip macro name.
+*
+*******************************************************************************/
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#ifdef COMBOINC
+#if defined(_DLL) && !defined(MTHREAD)
+#error Cannot define _DLL without MTHREAD
+#endif
+#endif
+
+#endif /* !_INTERNAL_IFSTRIP */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _MBCS
+/*
+ * SBCS - Single Byte Character Set
+ */
+
+#define _mbscat strcat
+#define _mbschr strchr
+#define _mbscmp strcmp
+#define _mbscpy strcpy
+#define _mbscspn strcspn
+#define _mbsdec _strdec
+#define _mbsdup _strdup
+#define _mbsicmp _stricmp
+#define _mbsinc _strinc
+#define _mbslen strlen
+#define _mbslwr strlwr
+#define _mbsnbcat strncat
+#define _mbsnbcmp strncmp
+#define _mbsnbcnt _strncnt
+#define _mbsnbcpy strncpy
+#define _mbsnbicmp _strnicmp
+#define _mbsnbset _strnset
+#define _mbsncat strncat
+#define _mbsnccnt _strncnt
+#define _mbsncmp strncmp
+#define _mbsncpy strncpy
+#define _mbsnextc _strnextc
+#define _mbsnicmp _strnicmp
+#define _mbsninc _strninc
+#define _mbsnset _strnset
+#define _mbsrchr strrchr
+#define _mbsrev _strrev
+#define _mbspbrk strpbrk
+#define _mbsset _strset
+#define _mbsspn strspn
+#define _mbsspnp _strspnp
+#define _mbsstr strstr
+#define _mbstok strtok
+#define _mbsupr _strupr
+
+#define _mbclen(_cpc) (1)
+#define _mbccpy(_pc1, _cpc2) (*(_pc1) = *(_cpc2))
+#define _mbccmp(_cpc1, _cpc2) (((unsigned char)*(_cpc1)) - ((unsigned char)*(_cpc2)))
+
+/* Character function mappings. */
+
+#define _ismbcalpha isalpha
+#define _ismbcdigit isdigit
+#define _ismbclegal(_c) (1)
+#define _ismbclower islower
+#define _ismbcprint isprint
+#define _ismbcspace isspace
+#define _ismbcupper isupper
+
+#define _ismbblead(_c) (0)
+#define _ismbbtrail(_c) (0)
+#define _ismbslead(_s,_c) (0)
+#define _ismbstrail(_s,_c) (0)
+
+/* SBCS routines needed for MBCS mappings */
+
+unsigned char * _CRTAPI1 _strdec(const unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _strinc(const unsigned char *);
+size_t _CRTAPI1 _strncnt(const unsigned char *, size_t);
+unsigned int _CRTAPI1 _strnextc(const unsigned char *);
+unsigned char * _CRTAPI1 _strninc(const unsigned char *, size_t);
+unsigned char * _CRTAPI1 _strspnp(const unsigned char *, const unsigned char *);
+
+#else
+/*
+ * MBCS - Multi-Byte Character Set
+ */
+
+#ifndef _MBSTRING_DEFINED
+
+/* function prototypes */
+
+unsigned int _CRTAPI1 _mbbtombc(unsigned int);
+int _CRTAPI1 _mbbtype(unsigned char, int);
+unsigned int _CRTAPI1 _mbctombb(unsigned int);
+int _CRTAPI1 _mbsbtype(const unsigned char *, size_t);
+unsigned char * _CRTAPI1 _mbscat(unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbschr(const unsigned char *, unsigned int);
+int _CRTAPI1 _mbscmp(const unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbscpy(unsigned char *, const unsigned char *);
+size_t _CRTAPI1 _mbscspn(const unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbsdec(const unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbsdup(const unsigned char *);
+int _CRTAPI1 _mbsicmp(const unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbsinc(const unsigned char *);
+size_t _CRTAPI1 _mbslen(const unsigned char *);
+unsigned char * _CRTAPI1 _mbslwr(unsigned char *);
+unsigned char * _CRTAPI1 _mbsnbcat(unsigned char *, const unsigned char *, size_t);
+int _CRTAPI1 _mbsnbcmp(const unsigned char *, const unsigned char *, size_t);
+size_t _CRTAPI1 _mbsnbcnt(const unsigned char *, size_t);
+unsigned char * _CRTAPI1 _mbsnbcpy(unsigned char *, const unsigned char *, size_t);
+int _CRTAPI1 _mbsnbicmp(const unsigned char *, const unsigned char *, size_t);
+unsigned char * _CRTAPI1 _mbsnbset(unsigned char *, unsigned int, size_t);
+unsigned char * _CRTAPI1 _mbsncat(unsigned char *, const unsigned char *, size_t);
+size_t _CRTAPI1 _mbsnccnt(const unsigned char *, size_t);
+int _CRTAPI1 _mbsncmp(const unsigned char *, const unsigned char *, size_t);
+unsigned char * _CRTAPI1 _mbsncpy(unsigned char *, const unsigned char *, size_t);
+unsigned int _CRTAPI1 _mbsnextc (const unsigned char *);
+int _CRTAPI1 _mbsnicmp(const unsigned char *, const unsigned char *, size_t);
+unsigned char * _CRTAPI1 _mbsninc(const unsigned char *, size_t);
+unsigned char * _CRTAPI1 _mbsnset(unsigned char *, unsigned int, size_t);
+unsigned char * _CRTAPI1 _mbspbrk(const unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbsrchr(const unsigned char *, unsigned int);
+unsigned char * _CRTAPI1 _mbsrev(unsigned char *);
+unsigned char * _CRTAPI1 _mbsset(unsigned char *, unsigned int);
+size_t _CRTAPI1 _mbsspn(const unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbsspnp(const unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbsstr(const unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbstok(unsigned char *, const unsigned char *);
+unsigned char * _CRTAPI1 _mbsupr(unsigned char *);
+
+size_t _CRTAPI1 _mbclen(const unsigned char *);
+void _CRTAPI1 _mbccpy(unsigned char *, const unsigned char *);
+#define _mbccmp(_cpc1, _cpc2) _mbsncmp((_cpc1),(_cpc2),1)
+
+/* character routines */
+
+int _CRTAPI1 _ismbcalpha(unsigned int);
+int _CRTAPI1 _ismbcdigit(unsigned int);
+int _CRTAPI1 _ismbclegal(unsigned int);
+int _CRTAPI1 _ismbclower(unsigned int);
+int _CRTAPI1 _ismbcprint(unsigned int);
+int _CRTAPI1 _ismbcspace(unsigned int);
+int _CRTAPI1 _ismbcupper(unsigned int);
+
+unsigned int _CRTAPI1 _mbctolower(unsigned int);
+unsigned int _CRTAPI1 _mbctoupper(unsigned int);
+
+#define _MBSTRING_DEFINED
+#endif
+
+#ifndef _MBLEADTRAIL_DEFINED
+int _CRTAPI1 _ismbblead( unsigned int );
+int _CRTAPI1 _ismbbtrail( unsigned int );
+int _CRTAPI1 _ismbslead( const unsigned char *, const unsigned char *);
+int _CRTAPI1 _ismbstrail( const unsigned char *, const unsigned char *);
+#define _MBLEADTRAIL_DEFINED
+#endif
+
+#ifdef _KANJI
+
+/* Kanji specific prototypes. */
+
+int _CRTAPI1 _ismbchira(unsigned int);
+int _CRTAPI1 _ismbckata(unsigned int);
+int _CRTAPI1 _ismbcsymbol(unsigned int);
+int _CRTAPI1 _ismbcl0(unsigned int);
+int _CRTAPI1 _ismbcl1(unsigned int);
+int _CRTAPI1 _ismbcl2(unsigned int);
+unsigned int _CRTAPI1 _mbcjistojms(unsigned int);
+unsigned int _CRTAPI1 _mbcjmstojis(unsigned int);
+unsigned int _CRTAPI1 _mbctohira(unsigned int);
+unsigned int _CRTAPI1 _mbctokata(unsigned int);
+
+#endif /* KANJI */
+
+#endif /* MBCS */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/private/crt32/h/memory.h b/private/crt32/h/memory.h
new file mode 100644
index 000000000..0fa4e3a41
--- /dev/null
+++ b/private/crt32/h/memory.h
@@ -0,0 +1,101 @@
+/***
+*memory.h - declarations for buffer (memory) manipulation routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This include file contains the function declarations for the
+* buffer (memory) manipulation routines.
+* [System V]
+*
+*Revision History:
+* 10/20/87 JCR Removed "MSC40_ONLY" entries
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 08-22-88 GJF Modified to also work for the 386 (small model only)
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-03-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-17-89 GJF Added const to appropriate arg types for memccpy() and
+* memicmp().
+* 03-01-90 GJF Added #ifndef _INC_MEMORY and #include <cruntime.h>
+* stuff. Replace _cdecl with _CALLTYPE1 in prototypes.
+* Also, removed some (now) useless preprocessor
+* directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 in prototypes. Also,
+* got rid of movedata() prototype.
+* 01-17-91 GJF ANSI naming.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 08-05-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_MEMORY
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+
+/* function prototypes */
+
+void * _CRTAPI1 _memccpy(void *, const void *, int, unsigned int);
+void * _CRTAPI1 memchr(const void *, int, size_t);
+int _CRTAPI1 memcmp(const void *, const void *, size_t);
+void * _CRTAPI1 memcpy(void *, const void *, size_t);
+int _CRTAPI1 _memicmp(const void *, const void *, unsigned int);
+void * _CRTAPI1 memset(void *, int, size_t);
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#ifndef _DOSX32_
+#define memccpy _memccpy
+#define memicmp _memicmp
+#else
+void * _CRTAPI1 memccpy(void *, const void *, int, unsigned int);
+int _CRTAPI1 memicmp(const void *, const void *, unsigned int);
+#endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_MEMORY
+#endif /* _INC_MEMORY */
diff --git a/private/crt32/h/msdos.h b/private/crt32/h/msdos.h
new file mode 100644
index 000000000..5b7beee2a
--- /dev/null
+++ b/private/crt32/h/msdos.h
@@ -0,0 +1,83 @@
+/***
+*msdos.h - MS-DOS definitions for C runtime
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The file contains the MS-DOS definitions (function request numbers,
+* flags, etc.) used by the C runtime.
+* [Internal]
+*
+*Revision History:
+* 08-01-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 03-01-90 GJF Added #ifndef _INC_MSDOS stuff
+* 05-09-90 JCR Added _STACKSLOP (from msdos.inc)
+* 11-30-90 GJF Added Win32 support. Also removed constants that
+* are not used in Cruiser or Win32 runtimes.
+* 12-04-90 SRW Removed Win32 dependencies from this file.
+* Put them in internal.h
+* 07-01-92 GJF FRDONLY is not set or used for Win32.
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#ifndef _INC_MSDOS
+
+/* Stack slop for OS/2 system call overhead */
+
+#define _STACKSLOP 1024
+
+/* __osfile flag values for DOS file handles */
+
+#define FOPEN 0x01 /* file handle open */
+#define FEOFLAG 0x02 /* end of file has been encountered */
+#define FCRLF 0x04 /* CR-LF across read buffer (in text mode) */
+#define FPIPE 0x08 /* file handle refers to a pipe */
+
+#ifndef _WIN32_
+#define FRDONLY 0x10 /* file handle associated with read only file */
+#endif
+
+#define FAPPEND 0x20 /* file handle opened O_APPEND */
+#define FDEV 0x40 /* file handle refers to device */
+#define FTEXT 0x80 /* file handle is in text mode */
+
+/* DOS errno values for setting __doserrno in C routines */
+
+#define E_ifunc 1 /* invalid function code */
+#define E_nofile 2 /* file not found */
+#define E_nopath 3 /* path not found */
+#define E_toomany 4 /* too many open files */
+#define E_access 5 /* access denied */
+#define E_ihandle 6 /* invalid handle */
+#define E_arena 7 /* arena trashed */
+#define E_nomem 8 /* not enough memory */
+#define E_iblock 9 /* invalid block */
+#define E_badenv 10 /* bad environment */
+#define E_badfmt 11 /* bad format */
+#define E_iaccess 12 /* invalid access code */
+#define E_idata 13 /* invalid data */
+#define E_unknown 14 /* ??? unknown error ??? */
+#define E_idrive 15 /* invalid drive */
+#define E_curdir 16 /* current directory */
+#define E_difdev 17 /* not same device */
+#define E_nomore 18 /* no more files */
+#define E_maxerr2 19 /* unknown error - Version 2.0 */
+#define E_sharerr 32 /* sharing violation */
+#define E_lockerr 33 /* locking violation */
+#define E_maxerr3 34 /* unknown error - Version 3.0 */
+
+/* DOS file attributes */
+
+#define A_RO 0x1 /* read only */
+#define A_H 0x2 /* hidden */
+#define A_S 0x4 /* system */
+#define A_V 0x8 /* volume id */
+#define A_D 0x10 /* directory */
+#define A_A 0x20 /* archive */
+
+#define A_MOD (A_RO+A_H+A_S+A_A) /* changeable attributes */
+
+#define _INC_MSDOS
+#endif /* _INC_MSDOS */
diff --git a/private/crt32/h/msdos.inc b/private/crt32/h/msdos.inc
new file mode 100644
index 000000000..863642ada
--- /dev/null
+++ b/private/crt32/h/msdos.inc
@@ -0,0 +1,276 @@
+;***
+;msdos.inc - MS-DOS definitions for C runtime
+;
+; Copyright (c) 1987-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; This file contains the MS-DOS definitions (DOS function request
+; numbers, flags, etc) used by the C runtime.
+;
+;Revision History:
+; 10-22-87 JCR Removed "PROTMODE_ONLY" comments
+; 02-19-88 SKS STACKSLOP is 256 for DOS, 512 for OS/2
+; 06-02-89 JCR Added 386 OS/2 allocmem/setmem flag definitions
+; 06-07-89 JCR Bumped STACKSLOP to 1024 for 386 OS/2
+; 10-18-89 JCR Changed _NEWREGION to match change in OS2 mem APIs
+; 11-02-89 JCR Added DOS32QUERYSYSINFO offset definitions
+; 11-10-89 JCR Added OBJ_TILE bit to _NEWREGION memory request
+; 06-06-90 SBM Added DOSOPEN flags, names match doscalls.h, added
+; tentative new DOS32QUERYFHSTATE flags
+; 12-10-90 GJF Updated values of new flags introduced above.
+;
+;*******************************************************************************
+
+
+;_NFILE equ 20 ; maximum # files per process
+
+ifdef OS2
+ifdef I386
+STACKSLOP equ 1024 ; stack slop for 386 OS/2 system call overhead
+else
+STACKSLOP equ 512 ; stack slop for 286 OS/2 system call overhead
+endif
+else
+STACKSLOP equ 256 ; stack slop for DOS interrupt overhead
+endif
+
+; __osfile flag values for DOS file handles
+
+FOPEN equ 01H ; file handle open
+FEOFLAG equ 02H ; end of file has been encountered
+FCRLF equ 04H ; CR-LF across read buffer (in text mode)
+FPIPE equ 08H ; file handle refers to a pipe
+FRDONLY equ 10H ; file handle associated with read only file
+FAPPEND equ 20H ; file handle opened O_APPEND
+FDEV equ 40H ; file handle refers to device
+FTEXT equ 80H ; file handle is in text mode
+
+
+callos MACRO func
+ifnb <func>
+ mov ah,DOS_&func
+endif
+ int DOS
+ ENDM
+
+
+DOS equ 21H ; MS-DOS interrupt
+
+DOS_exit equ 00000H ; exit offset (PSP:0000)
+DOS_maxpara equ 00002H ; maximum paragraph (PSP:0002)
+DOS_envp equ 0002cH ; environment address (PSP:002c)
+DOS_cmdline equ 00080H ; command line offset (PSP:0080)
+
+DOS_kill equ 00H ; terminate
+DOS_echoread equ 01H ; read keyboard and echo
+DOS_display equ 02H ; display character
+DOS_auxinput equ 03H ; auxiliary input
+DOS_auxoutput equ 04H ; auxiliary output
+DOS_print equ 05H ; print character
+DOS_conio equ 06H ; direct console i/o
+DOS_coninput equ 07H ; direct console input
+DOS_readkbd equ 08H ; read keyboard
+DOS_message equ 09H ; display string
+DOS_bufkbdin equ 0aH ; buffered keyboard input
+DOS_kbdstatus equ 0bH ; check keyboard status
+DOS_flshread equ 0cH ; flush buffer and read keyboard
+DOS_diskreset equ 0dH ; disk reset
+DOS_selectdisk equ 0eH ; select default disk
+DOS_fcbopen equ 0fH ; open file with fcb
+DOS_fcbclose equ 10H ; close file with fcb
+DOS_fcbfirst equ 11H ; search for first entry with fcb
+DOS_fcbnext equ 12H ; search for next entry with fcb
+DOS_fcbdelete equ 13H ; delete file with fcb
+DOS_fcbsread equ 14H ; sequential read with fcb
+DOS_fcbswrite equ 15H ; sequential write with fcb
+DOS_fcbcreate equ 16H ; create file with fcb
+DOS_fcbrename equ 17H ; rename file with fcb
+DOS_currentd equ 19H ; current default disk
+DOS_setDMA equ 1aH ; set DMA
+DOS_fcbrread equ 21H ; random read with fcb
+DOS_fcbrwrite equ 22H ; random write with fcb
+DOS_fcbsize equ 23H ; file size with fcb
+DOS_fcbsetrec equ 24H ; set relative record with fcb
+DOS_setvector equ 25H ; set interrupt vector
+DOS_fcbbread equ 27H ; random block read with fcb
+DOS_fcbbwrite equ 28H ; random block write with fcb
+DOS_fcbparse equ 29H ; parse file name with fcb
+DOS_getdate equ 2aH ; get date
+DOS_setdate equ 2bH ; set date
+DOS_gettime equ 2cH ; get time
+DOS_settime equ 2dH ; set time
+DOS_verify equ 2eH ; set/reset verify flag
+DOS_getDMA equ 2fH ; get DMA
+DOS_version equ 30H ; get version number
+DOS_keep equ 31H ; keep process
+DOS_cntlc equ 33H ; Cntl-C check
+DOS_getvector equ 35H ; get interrupt vector
+DOS_getdskspc equ 36H ; get disk free space
+DOS_country equ 38H ; get country dependent info
+DOS_mkdir equ 39H ; make subdirectory
+DOS_rmdir equ 3aH ; remove subdirectory
+DOS_chdir equ 3bH ; change subdirectory
+DOS_create equ 3cH ; create pathname
+DOS_open equ 3dH ; open pathname
+DOS_close equ 3eH ; close file handle
+DOS_read equ 3fH ; read from file handle
+DOS_write equ 40H ; write from file handle
+DOS_delete equ 41H ; delete pathname
+DOS_lseek equ 42H ; move file pointer
+DOS_filemode equ 43H ; get/set attributes of pathname
+DOS_ioctl equ 44H ; ioctl for devices
+DOS_dup equ 45H ; duplicate file handle
+DOS_forcedup equ 46H ; force duplicate file handle
+DOS_curdir equ 47H ; get current directory
+DOS_allocmem equ 48H ; allocate memory block
+DOS_freemem equ 49H ; free memory block
+DOS_setmem equ 4aH ; set size of memory block
+DOS_exec equ 4bH ; load and execute program
+DOS_terminate equ 4cH ; terminate process with errorcode
+DOS_wait equ 4dH ; get child process return code
+DOS_findfirst equ 4eH ; find first file match
+DOS_findnext equ 4fH ; find next file match
+DOS_getverify equ 54H ; return current verify flag
+DOS_rename equ 56H ; rename pathname
+DOS_filedate equ 57H ; get/set file handle date/time
+DOS_createnew equ 5BH ; create new file
+DOS_locking equ 5CH ; file record locking/unlocking
+DOS_sleep equ 89H ; delay process execution
+
+
+; DOS error codes
+
+doserr MACRO num,name,text
+name equ num
+ ENDM
+
+doserr 1, E_ifunc, <invalid function code>
+doserr 2, E_nofile, <file not found>
+doserr 3, E_nopath, <path not found>
+doserr 4, E_toomany, <too many open files>
+doserr 5, E_access, <access denied>
+doserr 6, E_ihandle, <invalid handle>
+doserr 7, E_arena, <arena trashed>
+doserr 8, E_nomem, <not enough memory>
+doserr 9, E_iblock, <invalid block>
+doserr 10, E_badenv, <bad environment>
+doserr 11, E_badfmt, <bad format>
+doserr 12, E_iaccess, <invalid access code>
+doserr 13, E_idata, <invalid data>
+doserr 14, E_unknown, <??? unknown error ???>
+doserr 15, E_idrive, <invalid drive>
+doserr 16, E_curdir, <current directory>
+doserr 17, E_difdev, <not same device>
+doserr 18, E_nomore, <no more files>
+doserr 19, E_maxerr2, <unknown error - Version 2.0>
+
+; the following errors can occur only in DOS 3.0
+
+doserr 32, E_sharerr, <sharing violation>
+doserr 33, E_lockerr, <locking violation>
+doserr 34, E_maxerr3, <unknown error - Version 3.0>
+
+
+; DOS file attributes
+
+A_ro equ 01H ; read-only file
+A_h equ 02H ; hidden
+A_s equ 04H ; system
+A_v equ 08H ; volume ID
+A_d equ 10H ; directory
+A_a equ 20H ; archive
+
+A_mod equ A_ro+A_h+A_s+A_a ; modifiable attributes
+
+; OS/2 file attributes, names match doscalls.h
+
+FILE_NORMAL equ 00h
+FILE_READONLY equ 01h
+FILE_HIDDEN equ 02h
+FILE_SYSTEM equ 04h
+FILE_DIRECTORY equ 10h
+FILE_ARCHIVED equ 20h
+
+; OS/2 file creation bits
+
+F_CREATFLAG equ 10h
+F_OPENFLAG equ 01h
+F_TRUNCFLAG equ 02h
+
+; OS/2 file creation bits, names match doscalls.h
+
+FILE_OPEN equ 01h
+FILE_TRUNCATE equ 02h
+FILE_CREATE equ 10h
+
+; OS/2 DOS32OPEN/DOS32SETFHSTATE flags
+
+OPEN_ACCESS_READONLY equ 0000h
+OPEN_ACCESS_WRITEONLY equ 0001h
+OPEN_ACCESS_READWRITE equ 0002h
+OPEN_SHARE_DENYREADWRITE equ 0010h
+OPEN_SHARE_DENYWRITE equ 0020h
+OPEN_SHARE_DENYREAD equ 0030h
+OPEN_SHARE_DENYNONE equ 0040h
+OPEN_FLAGS_NOINHERIT equ 0080h
+OPEN_FLAGS_FAIL_ON_ERROR equ 2000h
+OPEN_FLAGS_WRITE_THROUGH equ 4000h
+OPEN_FLAGS_DASD equ 8000h
+
+; new DOS32QUERYFHSTATE flags from DCR 'Add full 32-bit support for
+; runtime libraries.' NAMES TENTATIVE AND SUBJECT TO CHANGE. STAY AWAY.
+
+OPEN_FLAGS_CONSOLE equ 00080000h
+OPEN_FLAGS_RAWMODE equ 00100000h
+OPEN_FLAGS_EOF equ 00200000h
+
+; OS/2 device mask
+
+IS_DEV equ 1
+IS_PIPE equ 2
+
+ifdef I386
+;
+; OS/2 System Call Flags (from bse32dos.h)
+;
+
+; Access protection
+PAG_READ equ 00000001h ; read access
+PAG_WRITE equ 00000002h ; write access
+PAG_EXECUTE equ 00000004h ; execute access
+PAG_GUARD equ 00000008h ; guard protection
+
+; Commit
+PAG_COMMIT equ 00000010h ; commit storage
+PAG_DECOMMIT equ 00000020h ; decommit storage
+
+; Allocation attributes
+OBJ_TILE equ 00000040h ; tile object
+OBJ_PROTECTED equ 00000080h ; protect object
+OBJ_GETTABLE equ 00000100h ; gettable by other processes
+OBJ_GIVEABLE equ 00000200h ; giveable to other processes
+
+; Standard memory values for C lib (heap and mthread code)
+_NEWREGION equ (PAG_READ OR PAG_WRITE OR OBJ_TILE)
+_COMMIT equ (PAG_COMMIT OR PAG_READ OR PAG_WRITE)
+_DECOMMIT equ (PAG_DECOMMIT)
+
+; Indices for DOS32QUERYSYSINFO system call (from bsedos.h)
+_QSV_MAX_PATH_LENGTH EQU 1
+_QSV_MAX_TEXT_SESSIONS EQU 2
+_QSV_MAX_PM_SESSIONS EQU 3
+_QSV_MAX_VDM_SESSIONS EQU 4
+_QSV_BOOT_DRIVE EQU 5 ; 1=A, 2=B, etc.
+_QSV_DYN_PRI_VARIATION EQU 6 ; 0=Absolute, 1=Dynamic
+_QSV_MAX_WAIT EQU 7 ; seconds
+_QSV_MIN_SLICE EQU 8 ; milli seconds
+_QSV_MAX_SLICE EQU 9 ; milli seconds
+_QSV_PAGE_SIZE EQU 10
+_QSV_VERSION_MAJOR EQU 11
+_QSV_VERSION_MINOR EQU 12
+_QSV_VERSION_REVISION EQU 13 ; Revision letter
+
+endif
+
+; end of msdos.inc
+;-----------------------------------------------------------------------
diff --git a/private/crt32/h/mtest.h b/private/crt32/h/mtest.h
new file mode 100644
index 000000000..e24b4b4af
--- /dev/null
+++ b/private/crt32/h/mtest.h
@@ -0,0 +1,68 @@
+/***
+* mtest.h - Multi-thread testing include file
+*
+* Copyright (c) 1988-1990, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This source contains prototypes and definitions used for multi-thread
+* testing. In order to use the debug flavor of these routines, you
+* MUST link special debug versions of multi-thread crt0dat.obj and
+* mlock.obj into your program. In addition, mtest.obj contains the
+* routines prototyped in this include file.
+*
+* [NOTE: This source module is NOT included in the C runtime library;
+* it is used only for testing.]
+*
+*Revision History:
+* 08-25-88 JCR Module created
+* 11-17-88 JCR Added _print_tiddata()
+* 04-04-89 JCR Added _THREADLOOPCNT_ (used in optional mtest.c code)
+* 07-11-89 JCR Added _SLEEP_ macro
+* 10-30-89 GJF Fixed copyright
+* 04-09-90 GJF Added _INC_MTEST stuff and #include <cruntime.h>.
+* Removed some leftover 16-bit support. Also, made
+* _print_tiddata() _CALLTYPE1.
+* 08-20-91 JCR C++ and ANSI naming
+*
+*******************************************************************************/
+
+#ifndef _INC_MTEST
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <cruntime.h>
+
+#ifndef _MIPS_
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#endif
+#endif
+
+/* Maximum thread count that mtest.c can handle */
+#define _THREADMAX_ 256
+
+/* Define thread loop count for mtest.c optional code path */
+#define _THREADLOOPCNT_ 5
+
+/* sleep macro */
+#define _SLEEP_(l) DOS32SLEEP(l)
+
+#ifdef DEBUG
+int printlock(int locknum);
+int print_single_locks(void);
+int print_stdio_locks(void);
+int print_lowio_locks(void);
+int print_iolocks(void);
+int print_locks(void);
+#endif
+
+void _CALLTYPE1 _print_tiddata(int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_MTEST
+#endif /* _INC_MTEST */
diff --git a/private/crt32/h/new.h b/private/crt32/h/new.h
new file mode 100644
index 000000000..ec034fe3c
--- /dev/null
+++ b/private/crt32/h/new.h
@@ -0,0 +1,67 @@
+/***
+*new.h - declarations and definitions for C++ memory allocation functions
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the declarations for C++ memory allocation functions.
+*
+*Revision History:
+*
+* 03-07-90 WAJ Initial version.
+* 04-09-91 JCR ANSI keyword conformance
+* 08-12-91 JCR Renamed new.hxx to new.h
+* 08-13-91 JCR Better set_new_handler names (ANSI, etc.).
+* 10-03-91 JCR Added _OS2_IFSTRIP switches for ifstrip'ing purposes
+* 10-30-91 JCR Changed "nhew" to "hnew" (typo in name!)
+* 11-13-91 JCR 32-bit version.
+* 06-03-92 KRS Fix CAVIAR #850: _CALLTYPE1 missing from prototype.
+* 08-05-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef __INC_NEW
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/* types and structures */
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+typedef int (_CRTAPI1 * _PNH)( size_t );
+
+/* function prototypes */
+
+_PNH _CRTAPI1 _set_new_handler( _PNH );
+
+#define __INC_NEW
+#endif
diff --git a/private/crt32/h/nlsint.h b/private/crt32/h/nlsint.h
new file mode 100644
index 000000000..b73b15d55
--- /dev/null
+++ b/private/crt32/h/nlsint.h
@@ -0,0 +1,60 @@
+/***
+*nlsint.h - national language support internal defintions
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains internal definitions/declarations for international functions,
+* shared between run-time and math libraries, in particular,
+* the localized decimal point.
+* [Internal]
+*
+*Revision History:
+* 10-16-91 ETC Created.
+* 11-15-91 JWM Added _PREPUTDECIMAL macro.
+* 02-23-93 SKS Update copyright to 1993
+* 02-23-93 CFW Added size_t definition for decimal_point_length.
+*
+****/
+
+#ifndef _INC_NLSINT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+/*
+ * Definitions for a localized decimal point.
+ * Currently, run-times only support a single character decimal point.
+ */
+#define __decimal_point _decimal_point
+extern char _decimal_point[]; /* localized decimal point string */
+
+#define __decimal_point_length _decimal_point_length
+#ifdef _INTL
+extern size_t _decimal_point_length; /* not including terminating null */
+#else
+#define _decimal_point_length 1
+#endif
+
+#ifdef _INTL
+#define _ISDECIMAL(p) (*(p) == *__decimal_point)
+#define _PUTDECIMAL(p) (*(p)++ = *__decimal_point)
+#define _PREPUTDECIMAL(p) (*(++p) = *__decimal_point)
+#else
+#define _ISDECIMAL(p) (*(p) == '.')
+#define _PUTDECIMAL(p) (*(p)++ = '.')
+#define _PREPUTDECIMAL(p) (*(++p) = '.')
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_NLSINT
+#endif /* _INC_NLSINT */
diff --git a/private/crt32/h/os2dll.h b/private/crt32/h/os2dll.h
new file mode 100644
index 000000000..f18229052
--- /dev/null
+++ b/private/crt32/h/os2dll.h
@@ -0,0 +1,260 @@
+/***
+*os2dll.h - DLL/Multi-thread include
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 10-27-87 JCR Module created.
+* 11-13-87 SKS Added _HEAP_LOCK
+* 12-15-87 JCR Added _EXIT_LOCK
+* 01-07-88 BCM Added _SIGNAL_LOCK; upped MAXTHREADID from 16 to 32
+* 02-01-88 JCR Added _dll_mlock/_dll_munlock macros
+* 05-02-88 JCR Added _BHEAP_LOCK
+* 06-17-88 JCR Corrected prototypes for special mthread debug routines
+* 08-15-88 JCR _check_lock now returns int, not void
+* 08-22-88 GJF Modified to also work for the 386 (small model only)
+* 06-05-89 JCR 386 mthread support
+* 06-09-89 JCR 386: Added values to _tiddata struc (for _beginthread)
+* 07-13-89 JCR 386: Added _LOCKTAB_LOCK
+* 08-17-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 01-02-90 JCR Moved a bunch of definitions from os2dll.inc
+* 04-06-90 GJF Added _INC_OS2DLL stuff and #include <cruntime.h>. Made
+* all function _CALLTYPE2 (for now).
+* 04-10-90 GJF Added prototypes for _[un]lockexit().
+* 08-16-90 SBM Made _terrno and _tdoserrno int, not unsigned
+* 09-14-90 GJF Added _pxcptacttab, _pxcptinfoptr and _fpecode fields
+* to _tiddata struct.
+* 10-09-90 GJF Thread ids are of type unsigned long.
+* 12-06-90 SRW Added _OSFHND_LOCK
+* 06-04-91 GJF Win32 version of multi-thread types and prototypes.
+* 08-15-91 GJF Made _tdoserrno an unsigned long for Win32.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-29-91 GJF Conditionally added prototypes for _getptd_lk
+* and _getptd1_lk for Win32 under DEBUG.
+* 10-03-91 JCR Added _cvtbuf to _tiddata structure
+* 02-17-92 GJF For Win32, replaced _NFILE_ with _NHANDLE_ and
+* _NSTREAM_.
+* 03-06-92 GJF For Win32, made _[un]mlock_[fh|stream]() macros
+* directly call _[un]lock().
+* 03-17-92 GJF Dropped _namebuf field from _tiddata structure for
+* Win32.
+* 08-05-92 GJF Function calling type and variable type macros.
+* 12-03-91 ETC Added _wtoken to _tiddata, added intl LOCK's;
+* added definition of wchar_t (needed for _wtoken).
+* 08-14-92 KRS Port ETC's _wtoken change from other tree.
+* 08-21-92 GJF Merged 08-05-92 and 08-14-92 versions.
+* 12-03-92 KRS Added _mtoken field for MTHREAD _mbstok().
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 02-25-93 GJF Purged Cruiser support and many outdated definitions
+* and declarations.
+* 12-14-93 SKS Add _freeptd(), which frees per-thread CRT data
+*
+****/
+
+#ifndef _INC_OS2DLL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <cruntime.h>
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/*
+ * Define the number of supported handles and streams. The definitions
+ * here must exactly match those in internal.h (for _NHANDLE_) and stdio.h
+ * (for _NSTREAM_).
+ */
+#ifdef MTHREAD
+#define _NHANDLE_ 256
+#define _NSTREAM_ 40
+#else
+#define _NHANDLE_ 64
+#define _NSTREAM_ 20
+#endif
+
+
+/* Lock symbols */
+
+/* ---- do not change lock #1 without changing emulator ---- */
+#define _SIGNAL_LOCK 1 /* lock for signal() & emulator SignalAddress */
+ /* emulator uses \math\include\os2dll.inc */
+
+#define _IOB_SCAN_LOCK 2 /* _iob[] table lock */
+#define _TMPNAM_LOCK 3 /* lock global tempnam variables */
+#define _INPUT_LOCK 4 /* lock for _input() routine */
+#define _OUTPUT_LOCK 5 /* lock for _output() routine */
+#define _CSCANF_LOCK 6 /* lock for _cscanf() routine */
+#define _CPRINTF_LOCK 7 /* lock for _cprintf() routine */
+#define _CONIO_LOCK 8 /* lock for conio routines */
+#define _HEAP_LOCK 9 /* lock for heap allocator routines */
+#define _BHEAP_LOCK 10 /* lock for based heap routines */
+#define _TIME_LOCK 11 /* lock for time functions */
+#define _ENV_LOCK 12 /* lock for environment variables */
+#define _EXIT_LOCK1 13 /* lock #1 for exit code */
+#define _EXIT_LOCK2 14 /* lock #2 for exit code */
+#define _THREADDATA_LOCK 15 /* lock for thread data table */
+#define _POPEN_LOCK 16 /* lock for _popen/_pclose database */
+#define _LOCKTAB_LOCK 17 /* lock to protect semaphore lock table */
+#define _OSFHND_LOCK 18 /* lock to protect _osfhnd array */
+#define _SETLOCALE_LOCK 19 /* lock for locale handles, etc. */
+#define _LC_COLLATE_LOCK 20 /* lock for LC_COLLATE locale */
+#define _LC_CTYPE_LOCK 21 /* lock for LC_CTYPE locale */
+#define _LC_MONETARY_LOCK 22 /* lock for LC_MONETARY locale */
+#define _LC_NUMERIC_LOCK 23 /* lock for LC_NUMERIC locale */
+#define _LC_TIME_LOCK 24 /* lock for LC_TIME locale */
+
+#define _STREAM_LOCKS 25 /* Table of stream locks */
+
+#ifdef _WIN32_
+#define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NSTREAM_-1) /* Last stream lock */
+#else
+#define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NFILE_-1) /* Last stream lock */
+#endif
+
+#define _FH_LOCKS (_LAST_STREAM_LOCK+1) /* Table of fh locks */
+
+#ifdef _WIN32_
+#define _LAST_FH_LOCK (_FH_LOCKS+_NHANDLE_-1) /* Last fh lock */
+#else
+#define _LAST_FH_LOCK (_FH_LOCKS+_NFILE_-1) /* Last fh lock */
+#endif
+
+#define _TOTAL_LOCKS (_LAST_FH_LOCK+1) /* Total number of locks */
+
+#define _LOCK_BIT_INTS (_TOTAL_LOCKS/(sizeof(unsigned)*8))+1 /* # of ints to hold lock bits */
+
+
+/* Multi-thread macros and prototypes */
+
+#ifdef MTHREAD
+
+
+/* need wchar_t for _wtoken field in _tiddata */
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+
+extern unsigned long _CRTAPI1 __threadid(void);
+#define _threadid (__threadid())
+extern unsigned long _CRTAPI1 __threadhandle(void);
+#define _threadhandle (__threadhandle())
+
+
+/* Structure for each thread's data */
+
+struct _tiddata {
+ unsigned long _tid; /* thread ID */
+ unsigned long _thandle; /* thread handle */
+
+ int _terrno; /* errno value */
+ unsigned long _tdoserrno; /* _doserrno value */
+ unsigned int _fpds; /* Floating Point data segment */
+ unsigned long _holdrand; /* rand() seed value */
+ char * _token; /* ptr to strtok() token */
+ wchar_t * _wtoken; /* ptr to wcstok() token */
+#ifdef _MBCS
+ unsigned char * _mtoken; /* ptr to _mbstok() token */
+#endif
+
+ /* following pointers get malloc'd at runtime */
+ char * _errmsg; /* ptr to strerror()/_strerror() buff */
+ char * _namebuf0; /* ptr to tmpnam() buffer */
+ char * _namebuf1; /* ptr to tmpfile() buffer */
+ char * _asctimebuf; /* ptr to asctime() buffer */
+ void * _gmtimebuf; /* ptr to gmtime() structure */
+ char * _cvtbuf; /* ptr to ecvt()/fcvt buffer */
+
+ /* following fields are needed by _beginthread code */
+ void * _initaddr; /* initial user thread address */
+ void * _initarg; /* initial user thread argument */
+
+ /* following three fields are needed to support signal handling and
+ * runtime errors */
+ void * _pxcptacttab; /* ptr to exception-action table */
+ void * _tpxcptinfoptrs; /* ptr to exception info pointers */
+ int _tfpecode; /* float point exception code */
+ };
+
+typedef struct _tiddata * _ptiddata;
+
+/*
+ * Declaration of TLS index used in storing pointers to per-thread data
+ * structures.
+ */
+extern unsigned long __tlsindex;
+
+
+/* macros */
+
+#define _lock_fh(fh) _lock(fh+_FH_LOCKS)
+#define _lock_str(s) _lock(s+_STREAM_LOCKS)
+#define _lock_fh_check(fh,flag) if (flag) _lock_fh(fh)
+#define _mlock(l) _lock(l)
+#define _munlock(l) _unlock(l)
+#define _unlock_fh(fh) _unlock(fh+_FH_LOCKS)
+#define _unlock_str(s) _unlock(s+_STREAM_LOCKS)
+#define _unlock_fh_check(fh,flag) if (flag) _unlock_fh(fh)
+
+
+/* multi-thread routines */
+
+void _CRTAPI1 _lock(int);
+void _CRTAPI1 _lockexit(void);
+void _CRTAPI1 _unlock(int);
+void _CRTAPI1 _unlockexit(void);
+
+_ptiddata _CRTAPI1 _getptd(void); /* return address of per-thread CRT data */
+void _CRTAPI1 _freeptd(_ptiddata); /* free up the per-thread CRT data blocks */
+
+
+#else /* not MTHREAD */
+
+
+/* macros */
+#define _lock_fh(fh)
+#define _lock_str(s)
+#define _lock_fh_check(fh,flag)
+#define _mlock(l)
+#define _munlock(l)
+#define _unlock_fh(fh)
+#define _unlock_str(s)
+#define _unlock_fh_check(fh,flag)
+
+
+#endif /* MTHREAD */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_OS2DLL
+#endif /* _INC_OS2DLL */
diff --git a/private/crt32/h/oscalls.h b/private/crt32/h/oscalls.h
new file mode 100644
index 000000000..542ad28cc
--- /dev/null
+++ b/private/crt32/h/oscalls.h
@@ -0,0 +1,141 @@
+/***
+*oscalls.h - contains declarations of Operating System types and constants.
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Declares types and constants that are defined by the target OS.
+* [Internal]
+*
+*Revision History:
+* 12-01-90 SRW Module created
+* 02-01-91 SRW Removed usage of NT header files (_WIN32_)
+* 02-28-91 SRW Removed usage of ntconapi.h (_WIN32_)
+* 04-09-91 PNT Added _MAC_ definitions
+* 04-26-91 SRW Disable min/max definitions in windows.h and added debug
+* definitions for DbgPrint and DbgBreakPoint(_WIN32_)
+* 08-05-91 GJF Use win32.h instead of windows.h for now.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-12-91 GJF Go back to using windows.h for win32 build.
+* 09-26-91 GJF Don't use error.h for Win32.
+* 11-07-91 GJF win32.h renamed to dosx32.h
+* 11-08-91 GJF Don't use windows.h, excpt.h. Add ntstatus.h.
+* 12-13-91 GJF Fixed so that exception stuff will build for Win32
+* 02-04-92 GJF Now must include ntdef.h to get LPSTR type.
+* 02-07-92 GJF Backed out change above, LPSTR also got added to
+* winnt.h
+* 03-30-92 DJM POSIX support.
+* 04-06-92 SRW Backed out 11-08-91 change and went back to using
+* windows.h only.
+* 05-12-92 DJM Moved POSIX code to it's own ifdef.
+* 08-01-92 SRW Let windows.h include excpt.h now that it replaces winxcpt.h
+* 09-30-92 SRW Use windows.h for _POSIX_ as well
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#ifndef _INC_OSCALLS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _CRUISER_ /* CRUISER TARGET */
+
+#include <doscalls.h>
+#include <error.h>
+#include <error2.h>
+#include <except.h>
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+#ifdef NULL
+#undef NULL
+#endif
+
+#if defined(DEBUG) && defined(_WIN32_)
+
+void DbgBreakPoint(void);
+int DbgPrint(char *Format, ...);
+
+#endif /* DEBUG && _WIN32_ */
+
+#define NOMINMAX 1
+
+#ifdef _DOSX32_
+
+#include <excpt.h>
+#include <dosx32.h>
+#include <error.h>
+#include <error2.h>
+
+#else
+#include <windows.h>
+#endif
+
+#undef NULL
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+/* File time and date types */
+
+typedef struct _FTIME { /* ftime */
+ unsigned short twosecs : 5;
+ unsigned short minutes : 6;
+ unsigned short hours : 5;
+} FTIME;
+typedef FTIME *PFTIME;
+
+typedef struct _FDATE { /* fdate */
+ unsigned short day : 5;
+ unsigned short month : 4;
+ unsigned short year : 7;
+} FDATE;
+typedef FDATE *PFDATE;
+
+#else /* ndef _WIN32_ */
+
+#ifdef _POSIX_
+
+#undef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+
+#include <windows.h>
+
+#else /* ndef _POSIX_ */
+
+#ifdef _MAC_
+
+#include <doscalls.h>
+#include <error.h>
+#include <error2.h>
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, POSIX, OR MAC TARGET SUPPORTED!
+
+#endif /* _POSIX_ */
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_OSCALLS
+#endif /* _INC_OSCALLS */
diff --git a/private/crt32/h/ostream.h b/private/crt32/h/ostream.h
new file mode 100644
index 000000000..a81819139
--- /dev/null
+++ b/private/crt32/h/ostream.h
@@ -0,0 +1,135 @@
+/***
+*ostream.h - definitions/declarations for the ostream class
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the classes, values, macros, and functions
+* used by the ostream class.
+* [AT&T C++]
+*
+*Revision History:
+* 01-23-92 KRS Ported from 16-bit version.
+* 06-03-92 KRS CAV #1183: Add 'const' to ptr output function.
+* 02-23-93 SKS Update copyright to 1993
+* 03-23-93 CFW Modified #pragma warnings.
+* 06-22-93 CFW Enable operator<<(long double)
+*
+****/
+
+#ifndef _INC_OSTREAM
+#define _INC_OSTREAM
+
+#include <ios.h>
+
+// C4505: "unreferenced local function has been removed"
+#pragma warning(disable:4505) // disable C4505 warning
+// #pragma warning(default:4505) // use this to reenable, if desired
+
+// C4103 : "used #pragma pack to change alignment"
+#pragma warning(disable:4103) // disable C4103 warning
+// #pragma warning(default:4103) // use this to reenable, if desired
+
+// Force word packing to avoid possible -Zp override
+#pragma pack(4)
+
+typedef long streamoff, streampos;
+
+class ostream : virtual public ios {
+
+public:
+ ostream(streambuf*);
+ virtual ~ostream();
+
+ ostream& flush();
+ int opfx();
+ void osfx();
+
+inline ostream& operator<<(ostream& (*f)(ostream&));
+inline ostream& operator<<(ios& (*f)(ios&));
+ ostream& operator<<(const char *);
+inline ostream& operator<<(const unsigned char *);
+inline ostream& operator<<(const signed char *);
+inline ostream& operator<<(char);
+ ostream& operator<<(unsigned char);
+inline ostream& operator<<(signed char);
+ ostream& operator<<(short);
+ ostream& operator<<(unsigned short);
+ ostream& operator<<(int);
+ ostream& operator<<(unsigned int);
+ ostream& operator<<(long);
+ ostream& operator<<(unsigned long);
+inline ostream& operator<<(float);
+ ostream& operator<<(double);
+ ostream& operator<<(long double);
+ ostream& operator<<(const void *);
+ ostream& operator<<(streambuf*);
+inline ostream& put(char);
+ ostream& put(unsigned char);
+inline ostream& put(signed char);
+ ostream& write(const char *,int);
+inline ostream& write(const unsigned char *,int);
+inline ostream& write(const signed char *,int);
+ ostream& seekp(streampos);
+ ostream& seekp(streamoff,ios::seek_dir);
+ streampos tellp();
+
+protected:
+ ostream();
+ ostream(const ostream&); // treat as private
+ ostream& operator=(streambuf*); // treat as private
+ ostream& operator=(const ostream& _os) {return operator=(_os.rdbuf()); }
+ int do_opfx(int); // not used
+ void do_osfx(); // not used
+
+private:
+ ostream(ios&);
+ ostream& writepad(const char *, const char *);
+ int x_floatused;
+};
+
+inline ostream& ostream::operator<<(ostream& (*f)(ostream&)) { (*f)(*this); return *this; }
+inline ostream& ostream::operator<<(ios& (*f)(ios& )) { (*f)(*this); return *this; }
+
+inline ostream& ostream::operator<<(char c) { return operator<<((unsigned char) c); }
+inline ostream& ostream::operator<<(signed char c) { return operator<<((unsigned char) c); }
+
+inline ostream& ostream::operator<<(const unsigned char * s) { return operator<<((const char *) s); }
+inline ostream& ostream::operator<<(const signed char * s) { return operator<<((const char *) s); }
+
+inline ostream& ostream::operator<<(float f) { x_floatused = 1; return operator<<((double) f); }
+
+inline ostream& ostream::put(char c) { return put((unsigned char) c); }
+inline ostream& ostream::put(signed char c) { return put((unsigned char) c); }
+
+inline ostream& ostream::write(const unsigned char * s, int n) { return write((char *) s, n); }
+inline ostream& ostream::write(const signed char * s, int n) { return write((char *) s, n); }
+
+
+class ostream_withassign : public ostream {
+ public:
+ ostream_withassign();
+ ostream_withassign(streambuf* _is);
+ ~ostream_withassign();
+ ostream& operator=(const ostream& _os) { return ostream::operator=(_os.rdbuf()); }
+ ostream& operator=(streambuf* _sb) { return ostream::operator=(_sb); }
+};
+
+#ifndef _WINDLL // Warning! Not available under Windows without QuickWin:
+extern ostream_withassign cout;
+extern ostream_withassign cerr;
+extern ostream_withassign clog;
+#endif
+
+inline ostream& flush(ostream& _outs) { return _outs.flush(); }
+inline ostream& endl(ostream& _outs) { return _outs << '\n' << flush; }
+inline ostream& ends(ostream& _outs) { return _outs << char('\0'); }
+
+ios& dec(ios&);
+ios& hex(ios&);
+ios& oct(ios&);
+
+// Restore default packing
+#pragma pack()
+
+#endif // !_INC_OSTREAM
diff --git a/private/crt32/h/process.h b/private/crt32/h/process.h
new file mode 100644
index 000000000..946545f7c
--- /dev/null
+++ b/private/crt32/h/process.h
@@ -0,0 +1,244 @@
+/***
+*process.h - definition and declarations for process control functions
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the modeflag values for spawnxx calls.
+* Only P_WAIT and P_OVERLAY are currently implemented on MS-DOS.
+* Also contains the function argument declarations for all
+* process control related routines.
+*
+*Revision History:
+* 08/24/87 JCR Added P_NOWAITO
+* 10/20/87 JCR Removed "MSC40_ONLY" entries and "MSSDK_ONLY" comments
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 01-11-88 JCR Added _beginthread/_endthread
+* 01-15-88 JCR Got rid of _p_overlay for MTRHEAD/DLL
+* 02-10-88 JCR Cleaned up white space
+* 05-08-88 SKS Removed bogus comment about "DOS 4"; Added "P_DETACH"
+* 08-22-88 GJF Modified to also work for the 386 (small model only)
+* 09-14-88 JCR Added _cexit and _c_exit declarations
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 06-08-89 JCR 386 _beginthread does NOT take a stackpointer arg
+* 08-01-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-17-89 GJF Added const attribute to appropriate arg types
+* 03-01-90 GJF Added #ifndef _INC_PROCESS and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 or _CALLTYPE2 in
+* prototypes.
+* 04-10-90 GJF Replaced remaining instances of _cdecl (with _CALLTYPE1
+* or _VARTYPE1, as appropriate).
+* 10-12-90 GJF Changed return type of _beginthread() to unsigned long.
+* 01-17-91 GJF ANSI naming.
+* 08-20-91 JCR C++ and ANSI naming
+* 08-26-91 BWM Added prototypes for _loaddll, unloaddll, and
+* _getdllprocaddr.
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 07-22-92 GJF Deleted references to _wait for Win32.
+* 08-05-92 GJF Function calling type and variable type macros.
+* 08-28-92 GJF #ifdef-ed out for POSIX.
+* 09-03-92 GJF Merged two changes above.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_PROCESS
+
+#ifndef _POSIX_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/* modeflag values for _spawnxx routines */
+
+#ifndef MTHREAD
+extern int _CRTVAR1 _p_overlay;
+#endif
+
+#define _P_WAIT 0
+#define _P_NOWAIT 1
+#ifdef MTHREAD
+#define _P_OVERLAY 2
+#else
+#define _P_OVERLAY _p_overlay
+#endif
+#define _OLD_P_OVERLAY 2
+#define _P_NOWAITO 3
+#define _P_DETACH 4
+
+
+/* Action codes for _cwait(). The action code argument to _cwait is ignored
+ on Win32 though it is accepted for compatibilty with OS/2 */
+
+#define _WAIT_CHILD 0
+#define _WAIT_GRANDCHILD 1
+
+
+/* function prototypes */
+
+#ifdef MTHREAD
+unsigned long _CRTAPI1 _beginthread (void (_CRTAPI1 *) (void *),
+ unsigned, void *);
+void _CRTAPI1 _endthread(void);
+#endif
+void _CRTAPI1 abort(void);
+void _CRTAPI1 _cexit(void);
+void _CRTAPI1 _c_exit(void);
+int _CRTAPI1 _cwait(int *, int, int);
+int _CRTAPI2 _execl(const char *, const char *, ...);
+int _CRTAPI2 _execle(const char *, const char *, ...);
+int _CRTAPI2 _execlp(const char *, const char *, ...);
+int _CRTAPI2 _execlpe(const char *, const char *, ...);
+int _CRTAPI1 _execv(const char *, const char * const *);
+int _CRTAPI1 _execve(const char *, const char * const *, const char * const *);
+int _CRTAPI1 _execvp(const char *, const char * const *);
+int _CRTAPI1 _execvpe(const char *, const char * const *, const char * const *);
+void _CRTAPI1 exit(int);
+void _CRTAPI1 _exit(int);
+int _CRTAPI1 _getpid(void);
+int _CRTAPI2 _spawnl(int, const char *, const char *, ...);
+int _CRTAPI2 _spawnle(int, const char *, const char *, ...);
+int _CRTAPI2 _spawnlp(int, const char *, const char *, ...);
+int _CRTAPI2 _spawnlpe(int, const char *, const char *, ...);
+int _CRTAPI1 _spawnv(int, const char *, const char * const *);
+int _CRTAPI1 _spawnve(int, const char *, const char * const *,
+ const char * const *);
+int _CRTAPI1 _spawnvp(int, const char *, const char * const *);
+int _CRTAPI1 _spawnvpe(int, const char *, const char * const *,
+ const char * const *);
+int _CRTAPI1 system(const char *);
+#ifndef _WIN32_
+int _CRTAPI1 _wait(int *);
+#endif
+int _CRTAPI1 _loaddll(char *);
+int _CRTAPI1 _unloaddll(int);
+int (_CRTAPI1 * _CRTAPI1 _getdllprocaddr(int, char *, int))();
+
+#ifdef _DECL_DLLMAIN
+/*
+ * Declare DLL notification (initialization/termination) routines
+ * The preferred method is for the user to provide DllMain() which will
+ * be called automatically by the DLL entry point defined by the C run-
+ * time library code. If the user wants to define the DLL entry point
+ * routine, the user's entry point must call _CRT_INIT on all types of
+ * notifications, as the very first thing on attach notifications and
+ * as the very last thing on detach notifications.
+ */
+#ifdef _WINDOWS_ /* Use types from WINDOWS.H */
+BOOL WINAPI DllMain(HANDLE, DWORD, LPVOID);
+BOOL WINAPI _CRT_INIT(HANDLE, DWORD, LPVOID);
+#else
+#ifdef _M_IX86
+int __stdcall DllMain(void *, unsigned, void *);
+int __stdcall _CRT_INIT(void *, unsigned, void *);
+#else
+int DllMain(void *, unsigned, void *);
+int _CRT_INIT(void *, unsigned, void *);
+#endif
+#endif /* _WINDOWS_ */
+#endif /* _DECL_DLLMAIN */
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+
+#define P_WAIT _P_WAIT
+#define P_NOWAIT _P_NOWAIT
+#define P_OVERLAY _P_OVERLAY
+#define OLD_P_OVERLAY _OLD_P_OVERLAY
+#define P_NOWAITO _P_NOWAITO
+#define P_DETACH _P_DETACH
+
+#define WAIT_CHILD _WAIT_CHILD
+#define WAIT_GRANDCHILD _WAIT_GRANDCHILD
+
+#ifndef _DOSX32_
+#define cwait _cwait
+#define execl _execl
+#define execle _execle
+#define execlp _execlp
+#define execlpe _execlpe
+#define execv _execv
+#define execve _execve
+#define execvp _execvp
+#define execvpe _execvpe
+#define getpid _getpid
+#define spawnl _spawnl
+#define spawnle _spawnle
+#define spawnlp _spawnlp
+#define spawnlpe _spawnlpe
+#define spawnv _spawnv
+#define spawnve _spawnve
+#define spawnvp _spawnvp
+#define spawnvpe _spawnvpe
+#ifndef _WIN32_
+#define wait _wait
+#endif
+#else
+int _CRTAPI1 cwait(int *, int, int);
+int _CRTAPI2 execl(const char *, const char *, ...);
+int _CRTAPI2 execle(const char *, const char *, ...);
+int _CRTAPI2 execlp(const char *, const char *, ...);
+int _CRTAPI2 execlpe(const char *, const char *, ...);
+int _CRTAPI1 execv(const char *, const char * const *);
+int _CRTAPI1 execve(const char *, const char * const *, const char * const *);
+int _CRTAPI1 execvp(const char *, const char * const *);
+int _CRTAPI1 execvpe(const char *, const char * const *, const char * const *);
+int _CRTAPI1 getpid(void);
+int _CRTAPI2 spawnl(int, const char *, const char *, ...);
+int _CRTAPI2 spawnle(int, const char *, const char *, ...);
+int _CRTAPI2 spawnlp(int, const char *, const char *, ...);
+int _CRTAPI2 spawnlpe(int, const char *, const char *, ...);
+int _CRTAPI1 spawnv(int, const char *, const char * const *);
+int _CRTAPI1 spawnve(int, const char *, const char * const *,
+ const char * const *);
+int _CRTAPI1 spawnvp(int, const char *, const char * const *);
+int _CRTAPI1 spawnvpe(int, const char *, const char * const *,
+ const char * const *);
+#ifndef _WIN32_
+int _CRTAPI1 wait(int *);
+#endif
+#endif
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _POSIX_ */
+
+#define _INC_PROCESS
+#endif /* _INC_PROCESS */
diff --git a/private/crt32/h/pversion.inc b/private/crt32/h/pversion.inc
new file mode 100644
index 000000000..b53a0eb8c
--- /dev/null
+++ b/private/crt32/h/pversion.inc
@@ -0,0 +1,28 @@
+; SCCSID = "@(#)pversion.inc:1.8"
+?PLM = 1
+?WIN = 0
+REALFAR = 0 ; used for QC only
+ifdef large
+ ?LARGE equ 1
+endif
+ifdef compact
+ ?COMPACT equ 1
+endif
+ifdef medium
+ ?MEDIUM equ 1
+endif
+ifdef small
+ ?SMALL equ 1
+endif
+ifdef small32
+ ?SMALL32 equ 1
+ memS32 = 1
+else
+ memS32 = 0
+endif
+ifdef flat32
+ ?FLAT32 equ 1
+ memF32 = 1
+else
+ memF32 = 0
+endif
diff --git a/private/crt32/h/rterr.h b/private/crt32/h/rterr.h
new file mode 100644
index 000000000..e8d6b11c3
--- /dev/null
+++ b/private/crt32/h/rterr.h
@@ -0,0 +1,76 @@
+/***
+*rterr.h - runtime errors
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the C runtime errors
+*
+*Revision History:
+* 06-01-90 GJF Module created.
+* 08-08-90 GJF Added _RT_CONIO, redefined _RT_NONCONT and
+* _RT_INVALDISP.
+* 09-08-91 GJF Added _RT_ONEXIT for Win32 (_WIN32_).
+* 09-28-91 GJF Fixed conflict with RTEs in 16-bit Win support. Also,
+* added three math errors.
+* 10-23-92 GJF Added _RT_PUREVIRT.
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#define _RT_STACK 0 /* stack overflow */
+#define _RT_NULLPTR 1 /* null pointer assignment */
+#define _RT_FLOAT 2 /* floating point not loaded */
+#define _RT_INTDIV 3 /* integer divide by 0 */
+
+/*
+ * the following three errors must be in the given order!
+ */
+#define _RT_EXECMEM 5 /* not enough memory on exec */
+#define _RT_EXECFORM 6 /* bad format on exec */
+#define _RT_EXECENV 7 /* bad environment on exec */
+
+#define _RT_SPACEARG 8 /* not enough space for arguments */
+#define _RT_SPACEENV 9 /* not enough space for environment */
+#define _RT_ABORT 10 /* Abnormal program termination */
+
+#define _RT_NPTR 12 /* illegal near pointer use */
+#define _RT_FPTR 13 /* illegal far pointer use */
+#define _RT_BREAK 14 /* control-BREAK encountered */
+#define _RT_INT 15 /* unexpected interrupt */
+#define _RT_THREAD 16 /* not enough space for thread data */
+#define _RT_LOCK 17 /* unexpected multi-thread lock error */
+#define _RT_HEAP 18 /* unexpected heap error */
+#define _RT_OPENCON 19 /* unable to open console device */
+
+/*
+ * _RT_QWIN and _RT_NOMAIN are used in 16-bit Windows support
+ */
+#define _RT_QWIN 20 /* unexpected QuickWin error */
+#define _RT_NOMAIN 21 /* no main procedure */
+
+
+#define _RT_NONCONT 22 /* non-continuable exception */
+#define _RT_INVALDISP 23 /* invalid disposition of exception */
+
+
+/*
+ * _RT_ONEXIT is specific to Win32 and Dosx32 platforms
+ */
+#define _RT_ONEXIT 24 /* insufficient heap to allocate
+ * initial table of funct. ptrs
+ * used by _onexit()/atexit(). */
+
+#define _RT_PUREVIRT 25 /* pure virtual function call attempted
+ * (C++ error) */
+
+/*
+ * _RT_DOMAIN, _RT_SING and _RT_TLOSS are generated by the floating point
+ * library.
+ */
+#define _RT_DOMAIN 120
+#define _RT_SING 121
+#define _RT_TLOSS 122
+
+#define _RT_CRNL 252
+#define _RT_BANNER 255
diff --git a/private/crt32/h/search.h b/private/crt32/h/search.h
new file mode 100644
index 000000000..107f99801
--- /dev/null
+++ b/private/crt32/h/search.h
@@ -0,0 +1,104 @@
+/***
+*search.h - declarations for searcing/sorting routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the declarations for the sorting and
+* searching routines.
+* [System V]
+*
+*Revision History:
+* 10/20/87 JCR Removed "MSC40_ONLY" entries
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 01-21-88 JCR Removed _LOAD_DS from declarations
+* 02-10-88 JCR Cleaned up white space
+* 08-22-88 GJF Modified to also work for the 386 (small model only)
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-01-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-17-89 GJF Changed arg types to be consistently "[const] void *"
+* (same as 06-05-89 change to CRT version)
+* 03-01-90 GJF Added #ifndef _INC_SEARCH and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 in prototypes.
+* 01-17-91 GJF ANSI naming.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 08-05-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_SEARCH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+
+/* function prototypes */
+
+void * _CRTAPI1 bsearch(const void *, const void *, size_t, size_t,
+ int (_CRTAPI1 *)(const void *, const void *));
+void * _CRTAPI1 _lfind(const void *, const void *, unsigned int *, unsigned int,
+ int (_CRTAPI1 *)(const void *, const void *));
+void * _CRTAPI1 _lsearch(const void *, void *, unsigned int *, unsigned int,
+ int (_CRTAPI1 *)(const void *, const void *));
+void _CRTAPI1 qsort(void *, size_t, size_t, int (_CRTAPI1 *)(const void *,
+ const void *));
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#ifndef _DOSX32_
+#define lfind _lfind
+#define lsearch _lsearch
+#else
+void * _CRTAPI1 lfind(const void *, const void *, unsigned int *, unsigned int,
+ int (_CRTAPI1 *)(const void *, const void *));
+void * _CRTAPI1 lsearch(const void *, void *, unsigned int *, unsigned int,
+ int (_CRTAPI1 *)(const void *, const void *));
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_SEARCH
+#endif /* _INC_SEARCH */
diff --git a/private/crt32/h/setjmp.h b/private/crt32/h/setjmp.h
new file mode 100644
index 000000000..0bf778e6c
--- /dev/null
+++ b/private/crt32/h/setjmp.h
@@ -0,0 +1,299 @@
+/***
+*setjmp.h - definitions/declarations for setjmp/longjmp routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the machine-dependent buffer used by
+* setjmp/longjmp to save and restore the program state, and
+* declarations for those routines.
+* [ANSI/System V]
+*
+*Revision History:
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-15-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-01-90 GJF Added #ifndef _INC_SETJMP and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 04-10-90 GJF Replaced _cdecl with _CALLTYPE1.
+* 05-18-90 GJF Revised for SEH.
+* 10-30-90 GJF Moved definition of _JBLEN into cruntime.h.
+* 02-25-91 SRW Moved definition of _JBLEN back here [_WIN32_]
+* 04-09-91 PNT Added _MAC_ definitions
+* 04-17-91 SRW Fixed definition of _JBLEN for i386 and MIPS to not
+* include the * sizeof(int) factor [_WIN32_]
+* 05-09-91 GJF Moved _JBLEN defs back to cruntime.h. Also, turn on
+* intrinsic _setjmp for Dosx32.
+* 08-27-91 GJF #ifdef out everything for C++.
+* 08-29-91 JCR ANSI naming
+* 11-01-91 GDP MIPS compiler support -- Moved _JBLEN back here
+* 01-16-92 GJF Fixed _JBLEN and map to _setjmp intrinsic for i386
+* target [_WIN32_].
+* 05-08-92 GJF Changed _JBLEN to support C8-32 (support for C6-386 has
+* been dropped).
+* 08-06-92 GJF Function calling type and variable type macros. Revised
+* use of compiler/target processor macros.
+* 11-09-92 GJF Fixed some preprocessing conditionals.
+* 01-03-93 SRW Fold in ALPHA changes
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 02-20-93 GJF Per ChuckG and MartinO, setjmp/longjmp to used in
+* C++ programs.
+* 03-23-93 SRW Change _JBLEN for MIPS in preparation for SetJmpEx
+* 04-23-93 SRW Added _JBTYPE and finalized setjmpex support.
+* 06-09-93 SRW Missing one line in previous merge.
+* 10-04-93 SRW Fix ifdefs for MIPS and ALPHA to only check for _M_?????? defines
+* 01-12-93 PML Increased x86 _JBLEN from 8 to 16. Added new fields
+* to _JUMP_BUFFER for use with C9.0.
+*
+****/
+
+#ifndef _INC_SETJMP
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/*
+ * Definitions specific to particular setjmp implementations.
+ */
+#if defined(_M_IX86)
+
+/*
+ * MS C8-32 or older MS C6-386 compilers
+ */
+#ifndef _INC_SETJMPEX
+#define setjmp _setjmp
+#endif
+#define _JBLEN 16
+#define _JBTYPE int
+
+/*
+ * Define jump buffer layout for x86 setjmp/longjmp.
+ */
+
+typedef struct __JUMP_BUFFER {
+ unsigned long Ebp;
+ unsigned long Ebx;
+ unsigned long Edi;
+ unsigned long Esi;
+ unsigned long Esp;
+ unsigned long Eip;
+ unsigned long Registration;
+ unsigned long TryLevel;
+ unsigned long Cookie;
+ unsigned long UnwindFunc;
+ unsigned long UnwindData[6];
+} _JUMP_BUFFER;
+
+#elif defined(_M_MRX000)
+
+/*
+ * All MIPS implementations need _JBLEN of 16
+ */
+#define _JBLEN 16
+#define _JBTYPE double
+#define _setjmp setjmp
+
+/*
+ * Define jump buffer layout for MIPS setjmp/longjmp.
+ */
+
+typedef struct __JUMP_BUFFER {
+ unsigned long FltF20;
+ unsigned long FltF21;
+ unsigned long FltF22;
+ unsigned long FltF23;
+ unsigned long FltF24;
+ unsigned long FltF25;
+ unsigned long FltF26;
+ unsigned long FltF27;
+ unsigned long FltF28;
+ unsigned long FltF29;
+ unsigned long FltF30;
+ unsigned long FltF31;
+ unsigned long IntS0;
+ unsigned long IntS1;
+ unsigned long IntS2;
+ unsigned long IntS3;
+ unsigned long IntS4;
+ unsigned long IntS5;
+ unsigned long IntS6;
+ unsigned long IntS7;
+ unsigned long IntS8;
+ unsigned long IntSp;
+ unsigned long Type;
+ unsigned long Fir;
+} _JUMP_BUFFER;
+
+#elif defined(_M_ALPHA)
+
+/*
+ * The Alpha C8/GEM C compiler uses an intrinsic _setjmp.
+ * The Alpha acc compiler implements setjmp as a function.
+ */
+
+#define _setjmp setjmp
+
+#ifdef _MSC_VER
+#ifndef _INC_SETJMPEX
+#undef _setjmp
+#define setjmp _setjmp
+#endif
+#endif
+
+/*
+ * Alpha implementations use a _JBLEN of 24 quadwords.
+ * A double is used only to obtain quadword size and alignment.
+ */
+
+#define _JBLEN 24
+#define _JBTYPE double
+
+/*
+ * Define jump buffer layout for Alpha setjmp/longjmp.
+ * A double is used only to obtain quadword size and alignment.
+ */
+
+typedef struct __JUMP_BUFFER {
+ unsigned long Fp;
+ unsigned long Pc;
+ unsigned long Seb;
+ unsigned long Type;
+ double FltF2;
+ double FltF3;
+ double FltF4;
+ double FltF5;
+ double FltF6;
+ double FltF7;
+ double FltF8;
+ double FltF9;
+ double IntS0;
+ double IntS1;
+ double IntS2;
+ double IntS3;
+ double IntS4;
+ double IntS5;
+ double IntS6;
+ double IntSp;
+ double Fir;
+ double Fill[5];
+} _JUMP_BUFFER;
+
+#elif defined(_M_PPC)
+
+/*
+ * Min length is 240 bytes; round to 256 bytes.
+ * Since this is allocated as an array of "double", the
+ * number of entries required is 32.
+ *
+ * All PPC implementations need _JBLEN of 32
+ */
+
+#define _JBLEN 32
+#define _JBTYPE double
+#define _setjmp setjmp
+
+/*
+ * Define jump buffer layout for PowerPC setjmp/longjmp.
+ */
+
+typedef struct __JUMP_BUFFER {
+ double Fpr14;
+ double Fpr15;
+ double Fpr16;
+ double Fpr17;
+ double Fpr18;
+ double Fpr19;
+ double Fpr20;
+ double Fpr21;
+ double Fpr22;
+ double Fpr23;
+ double Fpr24;
+ double Fpr25;
+ double Fpr26;
+ double Fpr27;
+ double Fpr28;
+ double Fpr29;
+ double Fpr30;
+ double Fpr31;
+ unsigned long Gpr1;
+ unsigned long Gpr2;
+ unsigned long Gpr13;
+ unsigned long Gpr14;
+ unsigned long Gpr15;
+ unsigned long Gpr16;
+ unsigned long Gpr17;
+ unsigned long Gpr18;
+ unsigned long Gpr19;
+ unsigned long Gpr20;
+ unsigned long Gpr21;
+ unsigned long Gpr22;
+ unsigned long Gpr23;
+ unsigned long Gpr24;
+ unsigned long Gpr25;
+ unsigned long Gpr26;
+ unsigned long Gpr27;
+ unsigned long Gpr28;
+ unsigned long Gpr29;
+ unsigned long Gpr30;
+ unsigned long Gpr31;
+ unsigned long Cr;
+ unsigned long Iar;
+ unsigned long Type;
+} _JUMP_BUFFER;
+
+#endif
+
+/* define the buffer type for holding the state information */
+
+#ifndef _JMP_BUF_DEFINED
+typedef _JBTYPE jmp_buf[_JBLEN];
+#define _JMP_BUF_DEFINED
+#endif
+
+
+/* function prototypes */
+
+int _CRTAPI1 setjmp(jmp_buf);
+void _CRTAPI1 longjmp(jmp_buf, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_SETJMP
+#endif /* _INC_SETJMP */
diff --git a/private/crt32/h/setjmpex.h b/private/crt32/h/setjmpex.h
new file mode 100644
index 000000000..68d9486c9
--- /dev/null
+++ b/private/crt32/h/setjmpex.h
@@ -0,0 +1,41 @@
+/***
+*setjmpex.h - definitions/declarations for setjmp/longjmp routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file causes _setjmpex to be called which will enable safe
+* setjmp/longjmp that work correctly with try/except/finally.
+*
+*Revision History:
+* 03-23-93 SRW Created.
+* 04-23-93 SRW Modified to not use a global variable.
+* 01-13-94 PML #define longjmp on x86 so setjmp still an intrinsic
+*
+****/
+
+#ifndef _INC_SETJMPEX
+#define _INC_SETJMPEX
+
+/*
+ * Definitions specific to particular setjmp implementations.
+ */
+
+#if defined(_M_IX86)
+
+/*
+ * MS compiler for x86
+ */
+
+#define setjmp _setjmp
+#define longjmp _longjmpex
+
+#else
+
+#define setjmp _setjmpex
+
+#endif
+
+#include <setjmp.h>
+
+#endif /* _INC_SETJMPEX */
diff --git a/private/crt32/h/setlocal.h b/private/crt32/h/setlocal.h
new file mode 100644
index 000000000..f69b2b430
--- /dev/null
+++ b/private/crt32/h/setlocal.h
@@ -0,0 +1,142 @@
+/***
+*setlocal.h - internal definitions used by locale-dependent functions.
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains internal definitions/declarations for locale-dependent
+* functions, in particular those required by setlocale().
+* [Internal]
+*
+*Revision History:
+* 10-16-91 ETC 32-bit version created from 16-bit setlocal.c
+* 12-20-91 ETC Removed GetLocaleInfo structure definitions.
+* 08-18-92 KRS Make _CLOCALEHANDLE == LANGNEUTRAL HANDLE = 0.
+* 12-17-92 CFW Added LC_ID, LCSTRINGS, and GetQualifiedLocale
+* 12-17-92 KRS Change value of NLSCMPERROR from 0 to INT_MAX.
+* 01-08-93 CFW Added LC_*_TYPE and _getlocaleinfo (wrapper) prototype.
+* 01-13-93 KRS Change LCSTRINGS back to LC_STRINGS for consistency.
+* Change _getlocaleinfo prototype again.
+* 02-08-93 CFW Added time defintions from locale.h, added 'const' to
+* GetQualifiedLocale prototype, added _lconv_static_*.
+* 02-16-93 CFW Changed time defs to long and short.
+* 03-17-93 CFW Add language and country info definitions.
+* 03-23-93 CFW Add _ to GetQualifiedLocale prototype.
+* 03-24-93 CFW Change to _get_qualified_locale.
+*
+****/
+
+#ifndef _INC_SETLOCAL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <limits.h>
+
+#define ERR_BUFFER_TOO_SMALL 1 // should be in windef.h
+
+#define NLSCMPERROR INT_MAX // Return value for *cmp and *coll
+ // functions when NLSAPI call fails
+
+#define _CLOCALEHANDLE 0 /* "C" locale handle */
+#define _CLOCALECP CP_ACP /* "C" locale Code page (ANSI 8859) */
+
+/* Define the max length for each string type including space for a null. */
+
+#define _MAX_WDAY_ABBR 4
+#define _MAX_WDAY 10
+#define _MAX_MONTH_ABBR 4
+#define _MAX_MONTH 10
+#define _MAX_AMPM 3
+
+#define _DATE_LENGTH 8 /* mm/dd/yy (null not included) */
+#define _TIME_LENGTH 8 /* hh:mm:ss (null not included) */
+
+/* LC_TIME localization structure */
+
+struct _lc_time_data {
+ char *wday_abbr[7];
+ char *wday[7];
+ char *month_abbr[12];
+ char *month[12];
+ char *ampm[2];
+#ifdef _INTL
+ char *ww_sdatefmt;
+ char *ww_ldatefmt;
+ char *ww_timefmt;
+#endif
+ };
+
+
+#define MAX_LANG_LEN 64 /* max language name length */
+#define MAX_CTRY_LEN 64 /* max country name length */
+#define MAX_MODIFIER_LEN 0 /* max modifier name length - n/a */
+#define MAX_LC_LEN (MAX_LANG_LEN+MAX_CTRY_LEN+MAX_MODIFIER_LEN+3)
+ /* max entire locale string length */
+#define MAX_CP_LEN 5 /* max code page name length */
+#define CATNAMES_LEN 57 /* "LC_COLLATE=;LC_CTYPE=;..." length */
+
+#define LC_INT_TYPE 0
+#define LC_STR_TYPE 1
+
+#define QF_STRINGS 1
+#define QF_LCID 2
+
+typedef struct tagLC_ID {
+ WORD wLanguage;
+ WORD wCountry;
+ WORD wCodePage;
+} LC_ID, *LPLC_ID;
+
+typedef struct tagLC_STRINGS {
+ char szLanguage[MAX_LANG_LEN];
+ char szCountry[MAX_CTRY_LEN];
+ char szCodePage[MAX_CP_LEN];
+} LC_STRINGS, *LPLC_STRINGS;
+
+extern LC_ID _lc_id[]; /* complete info from GetQualifiedLocale */
+extern LCID _lc_handle[]; /* locale "handles" -- ignores country info */
+extern UINT _lc_codepage; /* code page */
+
+BOOL _CRTAPI1 _get_qualified_locale(
+ const DWORD dwType,
+ const LPVOID lpInput,
+ LPLC_ID lpOutId,
+ LPLC_STRINGS lpOutStr
+ );
+
+int _CRTAPI3 _getlocaleinfo (
+ int lc_type,
+ LCID localehandle,
+ LCTYPE fieldtype,
+ void *address
+ );
+
+/* initial values for lconv structure */
+extern char _lconv_static_decimal[];
+extern char _lconv_static_null[];
+
+/* language and country string definitions */
+typedef struct tagLANGREC
+{
+ CHAR szLanguage[MAX_LANG_LEN];
+ WORD wLanguage;
+} LANGREC;
+extern LANGREC __rg_lang_rec[];
+
+typedef struct tagCTRYREC
+{
+ CHAR szCountry[MAX_CTRY_LEN];
+ WORD wCountry;
+} CTRYREC;
+extern CTRYREC __rg_ctry_rec[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_SETLOCAL
+#endif /* _INC_SETLOCAL */
diff --git a/private/crt32/h/share.h b/private/crt32/h/share.h
new file mode 100644
index 000000000..346ec3c5a
--- /dev/null
+++ b/private/crt32/h/share.h
@@ -0,0 +1,35 @@
+/***
+*share.h - defines file sharing modes for sopen
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the file sharing modes for sopen().
+*
+*Revision History:
+* 08-15-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 03-01-90 GJF Added #ifndef _INC_SHARE stuff
+* 01-18-91 GJF ANSI naming
+* 08-11-92 GJF Removed SH_COMPAT (no such mode except in DOS).
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#ifndef _INC_SHARE
+
+#define _SH_DENYRW 0x10 /* deny read/write mode */
+#define _SH_DENYWR 0x20 /* deny write mode */
+#define _SH_DENYRD 0x30 /* deny read mode */
+#define _SH_DENYNO 0x40 /* deny none mode */
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#define SH_DENYRW _SH_DENYRW
+#define SH_DENYWR _SH_DENYWR
+#define SH_DENYRD _SH_DENYRD
+#define SH_DENYNO _SH_DENYNO
+#endif
+
+#define _INC_SHARE
+#endif /* _INC_SHARE */
diff --git a/private/crt32/h/signal.h b/private/crt32/h/signal.h
new file mode 100644
index 000000000..86367e3bd
--- /dev/null
+++ b/private/crt32/h/signal.h
@@ -0,0 +1,129 @@
+/***
+*signal.h - defines signal values and routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the signal values and declares the signal functions.
+* [ANSI/System V]
+*
+*Revision History:
+* 06-03-87 JMB Added MSSDK_ONLY comment on OS/2 related constants
+* 06-08-87 JCR Changed SIG_RRR to SIG_SGE
+* 08-07-87 SKS Signal handlers are now of type "void", not "int"
+* 10/20/87 JCR Removed "MSC40_ONLY" entries and "MSSDK_ONLY" comments
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 08-22-88 GJF Modified to also work for the 386 (small model only)
+* 12-06-88 SKS Add _CDECL to SIG_DFL, SIG_IGN, SIG_SGE, SIG_ACK
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-15-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-01-90 GJF Added #ifndef _INC_SIGNAL and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-15-90 GJF Replaced _cdecl with _CALLTYPE1 in #defines and
+* prototypes.
+* 07-27-90 GJF Added definition for SIG_DIE (internal action code,
+* not valid as an argument to signal()).
+* 09-25-90 GJF Added _pxcptinfoptrs stuff.
+* 10-09-90 GJF Added arg type specification (int) to pointer-to-
+* signal-handler-type usages
+* 08-20-91 JCR C++ and ANSI naming
+* 07-17-92 GJF Removed unsupported signals: SIGUSR1, SIGUSR2, SIGUSR3.
+* 08-05-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_SIGNAL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _SIG_ATOMIC_T_DEFINED
+typedef int sig_atomic_t;
+#define _SIG_ATOMIC_T_DEFINED
+#endif
+
+#define NSIG 23 /* maximum signal number + 1 */
+
+/* signal types */
+
+#define SIGINT 2 /* interrupt */
+#define SIGILL 4 /* illegal instruction - invalid function image */
+#define SIGFPE 8 /* floating point exception */
+#define SIGSEGV 11 /* segment violation */
+#define SIGTERM 15 /* Software termination signal from kill */
+#define SIGBREAK 21 /* Ctrl-Break sequence */
+#define SIGABRT 22 /* abnormal termination triggered by abort call */
+
+
+/* signal action codes */
+
+#define SIG_DFL (void (_CRTAPI1 *)(int))0 /* default signal action */
+#define SIG_IGN (void (_CRTAPI1 *)(int))1 /* ignore signal */
+#define SIG_SGE (void (_CRTAPI1 *)(int))3 /* signal gets error */
+#define SIG_ACK (void (_CRTAPI1 *)(int))4 /* acknowledge */
+
+#ifndef _INTERNAL_IFSTRIP_
+/* internal use only! not valid as an argument to signal() */
+
+#define SIG_GET (void (_CRTAPI1 *)(int))2 /* accept signal */
+#define SIG_DIE (void (_CRTAPI1 *)(int))5 /* terminate process */
+#endif
+
+/* signal error value (returned by signal call on error) */
+
+#define SIG_ERR (void (_CRTAPI1 *)(int))-1 /* signal error value */
+
+/* pointer to exception information pointers structure */
+
+#ifdef MTHREAD
+extern void * * _CRTAPI1 __pxcptinfoptrs(void);
+#define _pxcptinfoptrs (*__pxcptinfoptrs())
+#else
+extern void * _CRTVAR1 _pxcptinfoptrs;
+#endif
+
+/* function prototypes */
+
+void (_CRTAPI1 * _CRTAPI1 signal(int, void (_CRTAPI1 *)(int)))(int);
+int _CRTAPI1 raise(int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_SIGNAL
+#endif /* _INC_SIGNAL */
diff --git a/private/crt32/h/sizeptr.h b/private/crt32/h/sizeptr.h
new file mode 100644
index 000000000..735622819
--- /dev/null
+++ b/private/crt32/h/sizeptr.h
@@ -0,0 +1,45 @@
+/***
+*sizeptr.h - defines constants based on memory model
+*
+* Copyright (c) 1985-1990, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the constants SIZEC, SIZED, DIST, BDIST based
+* on the current memory model.
+* SIZEC is for far code models (medium, large).
+* SIZED is for large data models (compact, large).
+* [Internal]
+*
+*Revision History:
+* 08-15-89 GJF Fixed copyright, changed far to _far, near to _near
+* 10-30-89 GJF Fixed copyright (again)
+*
+****/
+
+
+#ifdef M_I86MM
+#undef SIZED
+#define SIZEC
+#endif
+
+#ifdef M_I86CM
+#undef SIZEC
+#define SIZED
+#endif
+
+#ifdef M_I86LM
+#define SIZEC
+#define SIZED
+#endif
+
+#ifdef SS_NE_DS
+#define SIZED
+#endif
+
+#ifdef SIZED
+#define DIST _far
+#define BDIST _near /*bizzare distance*/
+#else
+#define DIST _near
+#define BDIST _far /*bizzare distance*/
+#endif
diff --git a/private/crt32/h/stdarg.h b/private/crt32/h/stdarg.h
new file mode 100644
index 000000000..66c88a1f1
--- /dev/null
+++ b/private/crt32/h/stdarg.h
@@ -0,0 +1,153 @@
+/***
+*stdarg.h - defines ANSI-style macros for variable argument functions
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines ANSI-style macros for accessing arguments
+* of functions which take a variable number of arguments.
+* [ANSI]
+*
+*Revision History:
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-15-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 01-05-90 JCR Added NULL definition
+* 03-02-90 GJF Added #ifndef _INC_STDARG stuff. Also, removed some
+* (now) useless preprocessor directives.
+* 05-29-90 GJF Replaced sizeof() with _INTSIZEOF() and revised the
+* va_arg() macro (fixes PTM 60)
+* 05-31-90 GJF Revised va_end() macro (propagated 5-25-90 change to
+* crt7 version by WAJ)
+* 10-30-90 GJF Moved the real definitions into cruntime.h (for NT
+* folks) and relinc.sed (to release ANSI compatible
+* version). Ugly compromise.
+* 08-20-91 JCR C++ and ANSI naming
+* 11-01-91 GDP MIPS Compiler support. Moved real definitions back here
+* 10-16-92 SKS Replaced "#ifdef i386" with "#ifdef _M_IX86".
+* 11-03-92 GJF Fixed several conditionals, dropped _DOSX32_ support.
+* 01-03-93 SRW Fold in ALPHA changes
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 01-25-93 GJF Fix va_list definition.
+* 10-04-93 SRW Fix ifdefs for MIPS and ALPHA to only check for _M_?????? defines
+*
+****/
+
+#ifndef _INC_STDARG
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+
+#ifndef _VA_LIST_DEFINED
+#ifdef _M_ALPHA
+typedef struct {
+ char *a0; /* pointer to first homed integer argument */
+ int offset; /* byte offset of next parameter */
+} va_list;
+#else
+typedef char * va_list;
+#endif
+#define _VA_LIST_DEFINED
+#endif
+
+#if defined(_M_IX86)
+
+/* Use these types and definitions if generating code for x86 */
+
+#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
+
+#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
+#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
+#define va_end(ap) ( ap = (va_list)0 )
+
+#elif defined(_M_MRX000)
+
+/* Use these types and definitions if generating code for MIPS */
+
+#define va_start(ap,v) ap = (va_list)&v + sizeof(v)
+#define va_end(list)
+#define va_arg(list, mode) ((mode *)(list =\
+ (char *) ((((int)list + (__builtin_alignof(mode)<=4?3:7)) &\
+ (__builtin_alignof(mode)<=4?-4:-8))+sizeof(mode))))[-1]
+
+/* +++++++++++++++++++++++++++++++++++++++++++
+ Because of parameter passing conventions in C:
+ use mode=int for char, and short types
+ use mode=double for float types
+ use a pointer for array types
+ +++++++++++++++++++++++++++++++++++++++++++ */
+
+
+#elif defined(_M_ALPHA)
+
+
+/* Use these types and definitions if generating code for ALPHA */
+
+/*
+ * The Alpha compiler supports two builtin functions that are used to
+ * implement stdarg/varargs. The __builtin_va_start function is used
+ * by va_start to initialize the data structure that locates the next
+ * argument. The __builtin_isfloat function is used by va_arg to pick
+ * which part of the home area a given register argument is stored in.
+ * The home area is where up to six integer and/or six floating point
+ * register arguments are stored down (so they can also be referenced
+ * by a pointer like any arguments passed on the stack).
+ */
+
+extern void * __builtin_va_start(va_list, ...);
+
+#ifdef _CFRONT
+#define __builtin_isfloat(a) __builtin_alignof(a)
+#endif
+
+#define va_start(list, v) __builtin_va_start(list, v, 1)
+#define va_end(list)
+#define va_arg(list, mode) \
+ ( *( ((list).offset += ((int)sizeof(mode) + 7) & -8) , \
+ (mode *)((list).a0 + (list).offset - \
+ ((__builtin_isfloat(mode) && (list).offset <= (6 * 8)) ? \
+ (6 * 8) + 8 : ((int)sizeof(mode) + 7) & -8) \
+ ) \
+ ) \
+ )
+
+#elif defined(_M_PPC)
+
+/* Microsoft C8 front end (used in Motorola Merged compiler) */
+/* bytes that a type occupies in the argument list */
+#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
+/* return 'ap' adjusted for type 't' in arglist */
+#define _ALIGNIT(ap,t) \
+ ((((int)(ap))+(sizeof(t)<8?3:7)) & (sizeof(t)<8?~3:~7))
+
+#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
+#define va_arg(ap,t) ( *(t *)((ap = (char *) (_ALIGNIT(ap, t) + _INTSIZEOF(t))) - _INTSIZEOF(t)) )
+#define va_end(ap) ( ap = (va_list)0 )
+
+#else
+
+/* A guess at the proper definitions for other platforms */
+
+#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
+
+#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
+#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
+#define va_end(ap) ( ap = (va_list)0 )
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STDARG
+#endif /* _INC_STDARG */
diff --git a/private/crt32/h/stddef.h b/private/crt32/h/stddef.h
new file mode 100644
index 000000000..a9abd9563
--- /dev/null
+++ b/private/crt32/h/stddef.h
@@ -0,0 +1,153 @@
+/***
+*stddef.h - definitions/declarations for common constants, types, variables
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains definitions and declarations for some commonly
+* used constants, types, and variables.
+* [ANSI]
+*
+*Revision History:
+* 10-02-87 JCR Changed NULL definition #else to #elif (C || L || H)
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-16-87 JCR Added threadid definition
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 08-19-88 GJF Revised to also work for the 386
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 06-06-89 JCR 386: Made _threadid a function
+* 08-01-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also added parens to *_errno definition
+* (same as 11-14-88 change to CRT version).
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-02-90 GJF Added #ifndef _INC_STDDEF and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 04-10-90 GJF Replaced _cdecl with _VARTYPE1 or _CALLTYPE1, as
+* appropriate.
+* 08-16-90 SBM Made MTHREAD _errno return int *
+* 10-09-90 GJF Changed return type of __threadid() to unsigned long *.
+* 11-12-90 GJF Changed NULL to (void *)0.
+* 02-11-91 GJF Added offsetof() macro.
+* 02-12-91 GJF Only #define NULL if it isn't #define-d.
+* 03-21-91 KRS Added wchar_t typedef, also in stdlib.h.
+* 06-27-91 GJF Revised __threadid, added __threadhandle, both
+* for Win32 [_WIN32_].
+* 08-20-91 JCR C++ and ANSI naming
+* 01-29-92 GJF Got rid of silly macro defining _threadhandle to be
+* __threadhandle (no reason for the former name to be
+* be defined).
+* 08-05-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_STDDEF
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/* define NULL pointer value and the offset() macro */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+
+#define offsetof(s,m) (size_t)&(((s *)0)->m)
+
+
+/* declare reference to errno */
+
+#ifdef MTHREAD
+extern int * _CRTAPI1 _errno(void);
+#define errno (*_errno())
+#else
+extern int _CRTVAR1 errno;
+#endif
+
+
+/* define the implementation dependent size types */
+
+#ifndef _PTRDIFF_T_DEFINED
+typedef int ptrdiff_t;
+#define _PTRDIFF_T_DEFINED
+#endif
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+/* define pointer to thread id value */
+extern unsigned long * _CRTAPI1 __threadid(void);
+#define _threadid (__threadid())
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+extern unsigned long _CRTAPI1 __threadid(void);
+#define _threadid (__threadid())
+extern unsigned long _CRTAPI1 __threadhandle(void);
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STDDEF
+#endif /* _INC_STDDEF */
diff --git a/private/crt32/h/stdio.h b/private/crt32/h/stdio.h
new file mode 100644
index 000000000..37fbe9c28
--- /dev/null
+++ b/private/crt32/h/stdio.h
@@ -0,0 +1,503 @@
+/***
+*stdio.h - definitions/declarations for standard I/O routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the structures, values, macros, and functions
+* used by the level 2 I/O ("standard I/O") routines.
+* [ANSI/System V]
+*
+*Revision History:
+* 06-24-87 JMB Added char cast to putc macro
+* 07-20-87 SKS Fixed declaration of _flsbuf
+* 08-10-87 JCR Modified P_tmpdir/L_tmpdir
+* 08-17-87 PHG Fixed prototype for puts to take const char * per ANSI.
+* 10-02-87 JCR Changed NULL from #else to #elif (C || L || H)
+* 10/20/87 JCR Removed "MSC40_ONLY" entries
+* 11/09/87 JCR Multi-thread support
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-17-87 JCR Added _MTHREAD_ONLY comments
+* 12-18-87 JCR Added _FAR_ to declarations
+* 01-07-88 JCR _NFILE = 40 for mthread includes
+* 01-13-88 JCR Removed mthread _fileno_lk/_feof_lk/_ferror_lk declarations
+* 01-15-88 JCR DLL versions of stdin/stdout/stderr
+* 01-18-88 SKS Change _stdio() to __iob()
+* 01-20-88 SKS Change __iob() to _stdin(), _stdout(), _stderr()
+* 02-10-88 JCR Cleaned up white space
+* 04-21-88 WAJ Added _FAR_ to tempnam/_tmpnam_lk
+* 05-31-88 SKS Add FILENAME_MAX and FOPEN_MAX
+* 06-01-88 JCR Removed clearerr_lk macro
+* 07-28-88 GJF Added casts to fileno() so the file handle is zero
+* extended instead of sign extended
+* 08-18-88 GJF Revised to also work with the 386 (in small model only).
+* 11-14-88 GJF Added _fsopen()
+* 12-07-88 JCR DLL _iob[] references are now direct
+* 03-27-89 GJF Brought into sync with CRT\H\STDIO.H
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 07-24-89 GJF Changed FILE and fpos_t to be type names rather than
+* macros (ANSI requirement). Same as 04-06-89 change in
+* CRT
+* 07-25-89 GJF Cleanup. Alignment of struct fields is now protected
+* by pack pragmas. Now specific to 386.
+* 10-30-89 GJF Fixed copyright, removed dummy args from prototypes
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-17-89 GJF Added const to appropriate arg type for fdopen() and
+* _popen().
+* 02-16-90 GJF _iob[], _iob2[] merge
+* 03-02-90 GJF Added #ifndef _INC_STDIO and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives and pragmas.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 or _CALLTYPE2 in
+* prototypes.
+* 04-10-90 GJF Made _iob[] _VARTYPE1.
+* 10-30-90 GJF Moved actual type for va_list into cruntime.h
+* 11-12-90 GJF Changed NULL to (void *)0.
+* 01-21-91 GJF ANSI naming.
+* 02-12-91 GJF Only #define NULL if it isn't #define-d.
+* 08-01-91 GJF No _popen(), _pclose() for Dosx32.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-24-91 JCR Added _snprintf, _vsnprintf
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 01-22-92 GJF Changed definition of _iob for users of crtdll.dll.
+* 02-14-92 GJF Replaced _NFILE by _NSTREAM_ for Win32. _NFILE is
+* still supported for now, for backwards compatibility.
+* 03-17-92 GJF Replaced __tmpnum field in _iobuf structure with
+* _tmpfname, altered L_tmpnam definition for Win32.
+* 03-30-92 DJM POSIX support.
+* 06-02-92 KRS Added Unicode printf versions.
+* 08-05-92 GJF Fun. calling type and var. type macro.
+* 08-20-92 GJF Some small changes for POSIX.
+* 08-20-92 GJF Some small changes for POSIX.
+* 09-04-92 GJF Merged changes from 8-5-92 on.
+* 11-05-92 GJF Replaced #ifndef __STDC__ with #if !__STDC__. Also,
+* undid my ill-advised change to _P_tmpdir.
+* 12-12-92 SRW Add L_cuserid constant for _POSIX_
+* 01-03-93 SRW Fold in ALPHA changes
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 01-25-93 GJF Cosmetic change to va_list definition.
+* 02-01-93 GJF Made FILENAME_MAX 260.
+* 03-18-93 CFW Changed BUFSIZ from 512 to 4096
+* 03-22-93 CFW Changed BUFSIZ from 4096 to 512 (binaries frozen).
+* 04-29-93 CFW Add wide char get/put support.
+* 04-30-93 CFW Fixed wide char get/put support.
+* 05-04-93 CFW Remove uneeded _filwbuf, _flswbuf protos.
+* 06-02-93 CFW Wide get/put use wint_t.
+* 10-04-93 SRW Fix ifdefs for MIPS and ALPHA to only check for _M_?????? defines
+*
+****/
+
+#ifndef _INC_STDIO
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+#ifndef _WCTYPE_T_DEFINED
+typedef wchar_t wint_t;
+typedef wchar_t wctype_t;
+#define _WCTYPE_T_DEFINED
+#endif
+
+#ifndef _VA_LIST_DEFINED
+#ifdef _M_ALPHA
+typedef struct {
+ char *a0; /* pointer to first homed integer argument */
+ int offset; /* byte offset of next parameter */
+} va_list;
+#else
+typedef char * va_list;
+#endif
+#define _VA_LIST_DEFINED
+#endif
+
+
+/* buffered I/O macros */
+
+#define BUFSIZ 512
+
+#ifdef _WIN32_
+/*
+ * Number of supported streams. _NFILE is confusing and obsolete, but
+ * supported anyway for backwards compatibility.
+ */
+#define _NFILE _NSTREAM_
+#ifdef MTHREAD
+#define _NSTREAM_ 40
+#else
+#define _NSTREAM_ 20
+#endif
+
+#else
+
+#ifdef MTHREAD
+#define _NFILE 40
+#else
+#define _NFILE 20
+#endif
+
+#endif
+
+#define EOF (-1)
+
+#ifndef _FILE_DEFINED
+struct _iobuf {
+ char *_ptr;
+ int _cnt;
+ char *_base;
+ int _flag;
+ int _file;
+ int _charbuf;
+ int _bufsiz;
+#ifdef _CRUISER_
+ int __tmpnum;
+#else /* ndef _CRUISER_ */
+ char *_tmpfname;
+#endif /* _CRUISER_ */
+ };
+typedef struct _iobuf FILE;
+#define _FILE_DEFINED
+#endif
+
+/* Directory where temporary files may be created. */
+#ifdef _POSIX_
+#define _P_tmpdir "/"
+#else
+#define _P_tmpdir "\\"
+#endif
+
+#ifdef _CRUISER_
+/* L_tmpnam size = size of P_tmpdir
+ * + 1 (in case P_tmpdir does not end in "/")
+ * + 6 (for the temp number string)
+ * + 1 (for the null terminator)
+ */
+#define L_tmpnam sizeof(_P_tmpdir)+8
+#else /* ndef _CRUISER_ */
+/* L_tmpnam = size of P_tmpdir
+ * + 1 (in case P_tmpdir does not end in "/")
+ * + 12 (for the filename string)
+ * + 1 (for the null terminator)
+ */
+#define L_tmpnam sizeof(_P_tmpdir)+12
+#endif /* _CRUISER_ */
+
+
+#ifdef _POSIX_
+#define L_ctermid 9
+#define L_cuserid 32
+#endif
+
+#define SEEK_CUR 1
+#define SEEK_END 2
+#define SEEK_SET 0
+
+#define FILENAME_MAX 260
+#define FOPEN_MAX 20
+#define _SYS_OPEN 20
+#define TMP_MAX 32767
+
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+
+/* declare _iob[] array */
+
+#ifndef _STDIO_DEFINED
+#ifdef _DLL
+extern FILE * _CRTVAR1 _iob;
+#else
+extern FILE _CRTVAR1 _iob[];
+#endif
+#endif
+
+
+/* define file position type */
+
+#ifndef _FPOS_T_DEFINED
+typedef long fpos_t;
+#define _FPOS_T_DEFINED
+#endif
+
+
+#define stdin (&_iob[0])
+#define stdout (&_iob[1])
+#define stderr (&_iob[2])
+
+
+#define _IOREAD 0x0001
+#define _IOWRT 0x0002
+
+#define _IOFBF 0x0000
+#define _IOLBF 0x0040
+#define _IONBF 0x0004
+
+#define _IOMYBUF 0x0008
+#define _IOEOF 0x0010
+#define _IOERR 0x0020
+#define _IOSTRG 0x0040
+#define _IORW 0x0080
+#ifdef _POSIX_
+#define _IOAPPEND 0x0200
+#endif
+
+/* function prototypes */
+
+#ifndef _STDIO_DEFINED
+int _CRTAPI1 _filbuf(FILE *);
+int _CRTAPI1 _flsbuf(int, FILE *);
+
+#ifdef _POSIX_
+FILE * _CRTAPI1 _fsopen(const char *, const char *);
+#else
+FILE * _CRTAPI1 _fsopen(const char *, const char *, int);
+#endif
+
+void _CRTAPI1 clearerr(FILE *);
+int _CRTAPI1 fclose(FILE *);
+int _CRTAPI1 _fcloseall(void);
+#ifdef _POSIX_
+FILE * _CRTAPI1 fdopen(int, const char *);
+#else
+FILE * _CRTAPI1 _fdopen(int, const char *);
+#endif
+int _CRTAPI1 feof(FILE *);
+int _CRTAPI1 ferror(FILE *);
+int _CRTAPI1 fflush(FILE *);
+int _CRTAPI1 fgetc(FILE *);
+int _CRTAPI1 _fgetchar(void);
+int _CRTAPI1 fgetpos(FILE *, fpos_t *);
+char * _CRTAPI1 fgets(char *, int, FILE *);
+#ifdef _POSIX_
+int _CRTAPI1 fileno(FILE *);
+#else
+int _CRTAPI1 _fileno(FILE *);
+#endif
+int _CRTAPI1 _flushall(void);
+FILE * _CRTAPI1 fopen(const char *, const char *);
+int _CRTAPI2 fprintf(FILE *, const char *, ...);
+int _CRTAPI1 fputc(int, FILE *);
+int _CRTAPI1 _fputchar(int);
+int _CRTAPI1 fputs(const char *, FILE *);
+size_t _CRTAPI1 fread(void *, size_t, size_t, FILE *);
+FILE * _CRTAPI1 freopen(const char *, const char *, FILE *);
+int _CRTAPI2 fscanf(FILE *, const char *, ...);
+int _CRTAPI1 fsetpos(FILE *, const fpos_t *);
+int _CRTAPI1 fseek(FILE *, long, int);
+long _CRTAPI1 ftell(FILE *);
+size_t _CRTAPI1 fwrite(const void *, size_t, size_t, FILE *);
+int _CRTAPI1 getc(FILE *);
+int _CRTAPI1 getchar(void);
+char * _CRTAPI1 gets(char *);
+int _CRTAPI1 _getw(FILE *);
+void _CRTAPI1 perror(const char *);
+#ifndef _DOSX32_
+int _CRTAPI1 _pclose(FILE *);
+FILE * _CRTAPI1 _popen(const char *, const char *);
+#endif /* _DOSX32_ */
+int _CRTAPI2 printf(const char *, ...);
+int _CRTAPI1 putc(int, FILE *);
+int _CRTAPI1 putchar(int);
+int _CRTAPI1 puts(const char *);
+int _CRTAPI1 _putw(int, FILE *);
+int _CRTAPI1 remove(const char *);
+int _CRTAPI1 rename(const char *, const char *);
+void _CRTAPI1 rewind(FILE *);
+int _CRTAPI1 _rmtmp(void);
+int _CRTAPI2 scanf(const char *, ...);
+void _CRTAPI1 setbuf(FILE *, char *);
+int _CRTAPI1 setvbuf(FILE *, char *, int, size_t);
+int _CRTAPI2 _snprintf(char *, size_t, const char *, ...);
+int _CRTAPI2 sprintf(char *, const char *, ...);
+int _CRTAPI2 sscanf(const char *, const char *, ...);
+char * _CRTAPI1 _tempnam(char *, char *);
+FILE * _CRTAPI1 tmpfile(void);
+char * _CRTAPI1 tmpnam(char *);
+int _CRTAPI1 ungetc(int, FILE *);
+int _CRTAPI1 _unlink(const char *);
+int _CRTAPI1 vfprintf(FILE *, const char *, va_list);
+int _CRTAPI1 vprintf(const char *, va_list);
+int _CRTAPI1 _vsnprintf(char *, size_t, const char *, va_list);
+int _CRTAPI1 vsprintf(char *, const char *, va_list);
+
+#if !__STDC__
+#ifndef _WSTDIO_DEFINED
+
+/* declared in wchar.h, officially */
+wint_t _CRTAPI1 fgetwc(FILE *);
+wint_t _CRTAPI1 _fgetwchar(void);
+wint_t _CRTAPI1 fputwc(wint_t, FILE *);
+wint_t _CRTAPI1 _fputwchar(wint_t);
+wint_t _CRTAPI1 getwc(FILE *);
+wint_t _CRTAPI1 getwchar(void);
+wint_t _CRTAPI1 putwc(wint_t, FILE *);
+wint_t _CRTAPI1 putwchar(wint_t);
+wint_t _CRTAPI1 ungetwc(wint_t, FILE *);
+
+int _CRTAPI2 fwprintf(FILE *, const wchar_t *, ...);
+int _CRTAPI2 wprintf(const wchar_t *, ...);
+int _CRTAPI2 _snwprintf(wchar_t *, size_t, const wchar_t *, ...);
+int _CRTAPI2 swprintf(wchar_t *, const wchar_t *, ...);
+int _CRTAPI1 vfwprintf(FILE *, const wchar_t *, va_list);
+int _CRTAPI1 vwprintf(const wchar_t *, va_list);
+int _CRTAPI1 _vsnwprintf(wchar_t *, size_t, const wchar_t *, va_list);
+int _CRTAPI1 vswprintf(wchar_t *, const wchar_t *, va_list);
+int _CRTAPI2 fwscanf(FILE *, const wchar_t *, ...);
+int _CRTAPI2 swscanf(const wchar_t *, const wchar_t *, ...);
+int _CRTAPI2 wscanf(const wchar_t *, ...);
+
+#define getwchar() fgetwc(stdin)
+#define putwchar(_c) fputwc((_c),stdout)
+#define getwc(_stm) fgetwc(_stm)
+#define putwc(_c,_stm) fputwc(_c,_stm)
+
+#ifdef MTHREAD /* _MTHREAD_ONLY */
+wint_t _CRTAPI1 _getwc_lk(FILE *); /* _MTHREAD_ONLY */
+wint_t _CRTAPI1 _putwc_lk(wint_t, FILE *); /* _MTHREAD_ONLY */
+wint_t _CRTAPI1 _ungetwc_lk(wint_t, FILE *); /* _MTHREAD_ONLY */
+ /* _MTHREAD_ONLY */
+#else /*MTHREAD */ /* _MTHREAD_ONLY */
+#define _getwc_lk(_stm) fgetwc(_stm) /* _MTHREAD_ONLY */
+#define _putwc_lk(_c,_stm) fputwc(_c,_stm) /* _MTHREAD_ONLY */
+#define _ungetwc_lk(_c,_stm) ungetwc(_c,_stm) /* _MTHREAD_ONLY */
+#endif /*MTHREAD */ /* _MTHREAD_ONLY */
+
+#define _WSTDIO_DEFINED
+#endif
+#endif /* !__STDC__ */
+#define _STDIO_DEFINED
+#endif
+
+
+/* macro definitions */
+
+#define feof(_stream) ((_stream)->_flag & _IOEOF)
+#define ferror(_stream) ((_stream)->_flag & _IOERR)
+#define _fileno(_stream) ((_stream)->_file)
+#define getc(_stream) (--(_stream)->_cnt >= 0 ? 0xff & *(_stream)->_ptr++ \
+ : _filbuf(_stream))
+#define putc(_c,_stream) (--(_stream)->_cnt >= 0 \
+ ? 0xff & (*(_stream)->_ptr++ = (char)(_c)) : _flsbuf((_c),(_stream)))
+#define getchar() getc(stdin)
+#define putchar(_c) putc((_c),stdout)
+ /* _MTHREAD_ONLY */
+#define _getc_lk(_stream) (--(_stream)->_cnt >= 0 ? 0xff & *(_stream)->_ptr++ : _filbuf(_stream)) /* _MTHREAD_ONLY */
+#define _putc_lk(_c,_stream) (--(_stream)->_cnt >= 0 ? 0xff & (*(_stream)->_ptr++ = (char)(_c)) : _flsbuf((_c),(_stream))) /* _MTHREAD_ONLY */
+#define _getchar_lk() _getc_lk(stdin) /* _MTHREAD_ONLY */
+#define _putchar_lk(_c) _putc_lk((_c),stdout) /* _MTHREAD_ONLY */
+
+
+#ifdef MTHREAD
+#undef getc
+#undef putc
+#undef getchar
+#undef putchar
+#endif
+ /* _MTHREAD_ONLY */
+#ifdef MTHREAD /* _MTHREAD_ONLY */
+int _CRTAPI1 _fclose_lk(FILE *); /* _MTHREAD_ONLY */
+int _CRTAPI1 _fflush_lk(FILE *); /* _MTHREAD_ONLY */
+size_t _CRTAPI1 _fread_lk(void *, size_t, size_t, FILE *); /* _MTHREAD_ONLY */
+int _CRTAPI1 _fseek_lk(FILE *, long, int); /* _MTHREAD_ONLY */
+long _CRTAPI1 _ftell_lk(FILE *); /* _MTHREAD_ONLY */
+size_t _CRTAPI1 _fwrite_lk(const void *, size_t, size_t, FILE *); /* _MTHREAD_ONLY */
+char * _CRTAPI1 _tmpnam_lk(char *); /* _MTHREAD_ONLY */
+int _CRTAPI1 _ungetc_lk(int, FILE *); /* _MTHREAD_ONLY */
+#else /* not MTHREAD */ /* _MTHREAD_ONLY */
+#define _fclose_lk(_stream) fclose(_stream) /* _MTHREAD_ONLY */
+#define _fflush_lk(_stream) fflush(_stream) /* _MTHREAD_ONLY */
+#define _fread_lk(_buffer,_size,_count,_stream) fread(_buffer,_size,_count,_stream) /* _MTHREAD_ONLY */
+#define _fseek_lk(_stream,_offset,_origin) fseek(_stream,_offset,_origin) /* _MTHREAD_ONLY */
+#define _ftell_lk(_stream) ftell(_stream) /* _MTHREAD_ONLY */
+#define _fwrite_lk(_buffer,_size,_count,_stream) fwrite(_buffer,_size,_count,_stream) /* _MTHREAD_ONLY */
+#define _tmpnam_lk(_string) tmpnam(_string) /* _MTHREAD_ONLY */
+#define _ungetc_lk(_c,_stream) ungetc(_c,_stream) /* _MTHREAD_ONLY */
+#endif /* _MTHREAD_ONLY */
+
+#if !__STDC__ && !defined(_POSIX_)
+/* Non-ANSI names for compatibility */
+
+#define P_tmpdir _P_tmpdir
+#define SYS_OPEN _SYS_OPEN
+
+#ifndef _DOSX32_
+#define fcloseall _fcloseall
+#define fdopen _fdopen
+#define fgetchar _fgetchar
+#define fileno _fileno
+#define flushall _flushall
+#define fputchar _fputchar
+#define getw _getw
+#define putw _putw
+#define rmtmp _rmtmp
+#define tempnam _tempnam
+#define unlink _unlink
+#else
+int _CRTAPI1 fcloseall(void);
+FILE * _CRTAPI1 fdopen(int, const char *);
+int _CRTAPI1 fgetchar(void);
+int _CRTAPI1 fileno(FILE *);
+int _CRTAPI1 flushall(void);
+int _CRTAPI1 fputchar(int);
+int _CRTAPI1 getw(FILE *);
+int _CRTAPI1 putw(int, FILE *);
+int _CRTAPI1 rmtmp(void);
+char * _CRTAPI1 tempnam(char *, char *);
+int _CRTAPI1 unlink(const char *);
+#endif
+
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STDIO
+#endif /* _INC_STDIO */
diff --git a/private/crt32/h/stdiostr.h b/private/crt32/h/stdiostr.h
new file mode 100644
index 000000000..ff71bfaba
--- /dev/null
+++ b/private/crt32/h/stdiostr.h
@@ -0,0 +1,59 @@
+/***
+*stdiostr.h - definitions/declarations for stdiobuf, stdiostream
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the classes, values, macros, and functions
+* used by the stdiostream and stdiobuf classes.
+* [AT&T C++]
+*
+*Revision History:
+* 01-23-92 KRS Ported from 16-bit version.
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#include <iostream.h>
+#include <stdio.h>
+
+// Force word packing to avoid possible -Zp override
+#pragma pack(4)
+
+#pragma warning(disable:4505) // disable unwanted /W4 warning
+// #pragma warning(default:4505) // use this to reenable, if necessary
+
+#ifndef _INC_STDIOSTREAM
+#define _INC_STDIOSTREAM
+class stdiobuf : public streambuf {
+public:
+ stdiobuf(FILE* f);
+FILE * stdiofile() { return _str; }
+
+virtual int pbackfail(int c);
+virtual int overflow(int c = EOF);
+virtual int underflow();
+virtual streampos seekoff( streamoff, ios::seek_dir, int =ios::in|ios::out);
+virtual int sync();
+ ~stdiobuf();
+ int setrwbuf(int _rsize, int _wsize); // CONSIDER: move to ios::
+// protected:
+// virtual int doallocate();
+private:
+ FILE * _str;
+};
+
+// obsolescent
+class stdiostream : public iostream { // note: spec.'d as : public IOS...
+public:
+ stdiostream(FILE *);
+ ~stdiostream();
+ stdiobuf* rdbuf() const { return (stdiobuf*) ostream::rdbuf(); }
+
+private:
+};
+
+// Restore default packing
+#pragma pack()
+
+#endif // !_INC_STDIOSTREAM
diff --git a/private/crt32/h/stdlib.h b/private/crt32/h/stdlib.h
new file mode 100644
index 000000000..04595b01b
--- /dev/null
+++ b/private/crt32/h/stdlib.h
@@ -0,0 +1,552 @@
+/***
+*stdlib.h - declarations/definitions for commonly used library functions
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This include file contains the function declarations for
+* commonly used library functions which either don't fit somewhere
+* else, or, like toupper/tolower, can't be declared in the normal
+* place for other reasons.
+* [ANSI]
+*
+*Revision History:
+* 06-03-87 JMB Added MSSDK_ONLY switch to OS2_MODE, DOS_MODE
+* 06-30-87 SKS Added MSSDK_ONLY switch to _osmode
+* 08-17-87 PHG Removed const from params to _makepath, _splitpath,
+* _searchenv to conform with spec and documentation.
+* 10/20/87 JCR Removed "MSC40_ONLY" entries and "MSSDK_ONLY" comments
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 01-04-88 WAJ Increased _MAX_PATH and _MAX_DIR
+* 01-21-88 JCR Removed _LOAD_DS from search routine declarations
+* 02-10-88 JCR Cleaned up white space
+* 05-31-88 SKS Added EXIT_SUCCESS and EXIT_FAILURE
+* 08-19-88 GJF Modified to also work for the 386 (small model only)
+* 09-29-88 JCR onexit/atexit user routines must be _loadds in DLL
+* 09-30-88 JCR environ is a routine for DLL (bug fix)
+* 12-08-88 JCR DLL environ is resolved directly (no __environ call)
+* 12-15-88 GJF Added definition of NULL (ANSI)
+* 12-27-88 JCR Added _fileinfo, also DLL support for _fmode entry
+* 05-03-89 JCR Corrected _osmajor/_osminor for 386
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 07-24-89 GJF Gave names to the structs for div_t and ldiv_t types
+* 08-01-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also added parens to *_errno and *_doserrno
+* definitions (same as 11-14-88 change to CRT version).
+* 10-25-89 JCR Upgraded _MAX values for long filename support
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL", removed superfluous _DLL defs
+* 11-17-89 GJF Moved _fullpath prototype here (from direct.h). Also,
+* added const to appropriate arg types for _makepath(),
+* putenv(), _searchenv() and _splitpath().
+* 11-20-89 JCR Routines are now _cdecl in both single and multi-thread
+* 11-27-89 KRS Fixed _MAX_PATH etc. to match current OS/2 limits.
+* 03-02-90 GJF Added #ifndef _INC_STDLIB and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-22-90 GJF Replaced _cdecl with _CALLTYPE1 in prototypes and
+* with _VARTYPE1 in variable declarations.
+* 04-10-90 GJF Made _errno() and __doserrno() _CALLTYPE1.
+* 08-15-90 SBM Made MTHREAD _errno() and __doserrno() return int *
+* 10-31-90 JCR Added WINR_MODE and WINP_MODE for consistency
+* 11-12-90 GJF Changed NULL to (void *)0.
+* 11-30-90 GJF Conditioned definition of _doserrno on _CRUISER_ or
+* _WIN32_
+* 01-21-91 GJF ANSI naming.
+* 02-12-91 GJF Only #define NULL if it isn't #define-d.
+* 03-21-91 KRS Added wchar_t type, MB_CUR_MAX macro, and mblen,
+* mbtowc, mbstowcs, wctomb, and wcstombs functions.
+* 04-09-91 PNT Added _MAC_ definitions
+* 05-21-91 GJF #define onexit_t to _onexit_t if __STDC__ is not
+* not defined
+* 08-08-91 GJF Added prototypes for _atold and _strtold.
+* 08-20-91 JCR C++ and ANSI naming
+* 08-26-91 BWM Added prototypes for _beep, _sleep, _seterrormode.
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 11-15-91 GJF Changed definitions of min and max to agree with
+* windef.h
+* 01-22-92 GJF Fixed up definitions of global variables for build of,
+* and users of, crtdll.dll. Also, deleted declaration
+* of _psp (has no meaning outside of DOS).
+* 01-30-92 GJF Removed prototype for _strtold (no such function yet).
+* 03-30-92 DJM POSIX support.
+* 04-29-92 GJF Added _putenv_lk and _getenv_lk for Win32.
+* 06-16-92 KRS Added prototypes for wcstol and wcstod.
+* 06-29-92 GJF Removed bogus #define.
+* 08-05-92 GJF Function calling type and variable type macros. Also,
+* replaced ref. to i386 with ref to _M_IX86.
+* 08-18-92 KRS Add _mblen_lk.
+* 08-21-92 GJF Conditionally removed _atold for Win32 (no long double
+* in Win32).
+* 08-21-92 GJF Moved _mblen_lk into area that is stripped out by
+* release scripts.
+* 08-23-92 GJF Exposed _itoa, _ltoa, _ultoa, mblen, mbtowc, mbstowcs
+* for POSIX.
+* 08-26-92 SKS Add _osver, _winver, _winmajor, _winminor, _pgmptr
+* 09-03-92 GJF Merged changes from 8-5-92 on.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 03-01-93 SKS Add __argc and __argv
+* 03-30-93 CFW Protect with _MB_CUR_MAX_DEFINED, also defined in ctype.h.
+* 06-03-93 KRS Change _mbslen to _mbstrlen, returning type size_t.
+* 09-13-93 CFW Add _wtox and _xtow function prototypes.
+*
+****/
+
+#ifndef _INC_STDLIB
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+
+/* definition of the return type for the onexit() function */
+
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+
+
+#ifndef _ONEXIT_T_DEFINED
+typedef int (_CRTAPI1 * _onexit_t)(void);
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#define onexit_t _onexit_t
+#endif
+#define _ONEXIT_T_DEFINED
+#endif
+
+
+/* Data structure definitions for div and ldiv runtimes. */
+
+#ifndef _DIV_T_DEFINED
+
+typedef struct _div_t {
+ int quot;
+ int rem;
+} div_t;
+
+typedef struct _ldiv_t {
+ long quot;
+ long rem;
+} ldiv_t;
+
+#define _DIV_T_DEFINED
+#endif
+
+/* Maximum value that can be returned by the rand function. */
+
+#define RAND_MAX 0x7fff
+
+#ifndef _MB_CUR_MAX_DEFINED
+/* max mb-len for current locale */
+/* also defined in ctype.h */
+#ifdef _DLL
+#define __mb_cur_max (*__mb_cur_max_dll)
+#define MB_CUR_MAX (*__mb_cur_max_dll)
+extern unsigned short *__mb_cur_max_dll;
+#else
+#ifdef CRTDLL
+#define __mb_cur_max __mb_cur_max_dll
+#endif
+#define MB_CUR_MAX __mb_cur_max
+extern unsigned short __mb_cur_max;
+#endif
+#define _MB_CUR_MAX_DEFINED
+#endif /* _MB_CUR_MAX_DEFINED */
+
+/* min and max macros */
+
+#define __max(a,b) (((a) > (b)) ? (a) : (b))
+#define __min(a,b) (((a) < (b)) ? (a) : (b))
+
+
+/* sizes for buffers used by the _makepath() and _splitpath() functions.
+ * note that the sizes include space for 0-terminator
+ */
+
+#define _MAX_PATH 260 /* max. length of full pathname */
+#define _MAX_DRIVE 3 /* max. length of drive component */
+#define _MAX_DIR 256 /* max. length of path component */
+#define _MAX_FNAME 256 /* max. length of file name component */
+#define _MAX_EXT 256 /* max. length of extension component */
+
+/* constants for _seterrormode() */
+#define _CRIT_ERROR_PROMPT 0
+#define _CRIT_ERROR_FAIL 1
+
+/* constants for _sleep() */
+#define _SLEEP_MINIMUM 0
+#define _SLEEP_FOREVER -1
+
+/* external variable declarations */
+
+#ifdef MTHREAD
+extern int * _CRTAPI1 _errno(void);
+#ifdef _CRUISER_
+extern int * _CRTAPI1 __doserrno(void);
+#else /* ndef _CRUISER_ */
+#ifdef _WIN32_
+extern unsigned long * _CRTAPI1 __doserrno(void);
+#else /* ndef _WIN32_ */
+#error ERROR - ONLY CRUISER OR WIN32 MTHREAD TARGET SUPPORTED!
+#endif /* _WIN32_ */
+#endif /* _CRUISER_ */
+#define errno (*_errno())
+#define _doserrno (*__doserrno())
+#else /* ndef MTHREAD */
+extern int _CRTVAR1 errno; /* XENIX style error number */
+#ifdef _CRUISER_
+extern int _CRTVAR1 _doserrno; /* OS system error value */
+#else /* ndef _CRUISER_ */
+#ifdef _WIN32_
+extern unsigned long _CRTVAR1 _doserrno; /* OS system error value */
+#else /* ndef _WIN32_ */
+#ifdef _MAC_
+extern int _CRTVAR1 _doserrno; /* OS system error value */
+#else /* ndef _MAC_ */
+#ifdef _POSIX_
+#else
+#error ERROR - ONLY CRUISER, WIN32, POSIX, OR MAC TARGET SUPPORTED!
+#endif /* _POSIX_ */
+#endif /* _MAC_ */
+#endif /* _WIN32_ */
+#endif /* _CRUISER_ */
+#endif /* MTHREAD */
+
+#ifdef _DLL
+
+extern char ** _CRTVAR1 _sys_errlist; /* perror error message table */
+
+#define _sys_nerr (*_sys_nerr_dll)
+#define __argc (*__argc_dll)
+#define __argv (*__argv_dll)
+#define _environ (*_environ_dll)
+#define _fmode (*_fmode_dll)
+#define _fileinfo (*_fileinfo_dll)
+
+extern int * _CRTVAR1 _sys_nerr_dll; /* # of entries in sys_errlist table */
+extern int * _CRTVAR1 __argc_dll; /* count of cmd line args */
+extern char *** _CRTVAR1 __argv_dll; /* pointer to table of cmd line args */
+extern char *** _CRTVAR1 _environ_dll; /* pointer to environment table */
+extern int * _CRTVAR1 _fmode_dll; /* default file translation mode */
+extern int * _CRTVAR1 _fileinfo_dll; /* open file info mode (for spawn) */
+
+#define _pgmptr (*_pgmptr_dll)
+
+#define _osver (*_osver_dll)
+#define _winver (*_winver_dll)
+#define _winmajor (*_winmajor_dll)
+#define _winminor (*_winminor_dll)
+
+extern char ** _CRTVAR1 _pgmptr_dll;
+
+extern unsigned int * _CRTVAR1 _osver_dll;
+extern unsigned int * _CRTVAR1 _winver_dll;
+extern unsigned int * _CRTVAR1 _winmajor_dll;
+extern unsigned int * _CRTVAR1 _winminor_dll;
+
+/* --------- The following block is OBSOLETE --------- */
+
+/* DOS major/minor version numbers */
+
+#define _osmajor (*_osmajor_dll)
+#define _osminor (*_osminor_dll)
+
+extern unsigned int * _CRTVAR1 _osmajor_dll;
+extern unsigned int * _CRTVAR1 _osminor_dll;
+
+/* --------- The preceding block is OBSOLETE --------- */
+
+#else
+
+#ifdef CRTDLL
+#define _sys_nerr _sys_nerr_dll
+#define __argc __argc_dll
+#define __argv __argv_dll
+#define _environ _environ_dll
+#define _fmode _fmode_dll
+#define _fileinfo _fileinfo_dll
+#define _pgmptr _pgmptr_dll
+#define _osver _osver_dll
+#define _winver _winver_dll
+#define _winmajor _winmajor_dll
+#define _winminor _winminor_dll
+/* --------- The following block is OBSOLETE --------- */
+#define _osmajor _osmajor_dll
+#define _osminor _osminor_dll
+/* --------- The preceding block is OBSOLETE --------- */
+#endif
+
+extern char * _CRTVAR1 _sys_errlist[]; /* perror error message table */
+extern int _CRTVAR1 _sys_nerr; /* # of entries in sys_errlist table */
+
+extern int _CRTVAR1 __argc; /* count of cmd line args */
+extern char ** _CRTVAR1 __argv; /* pointer to table of cmd line args */
+
+#ifdef _POSIX_
+extern char ** _CRTVAR1 environ; /* pointer to environment table */
+#else
+extern char ** _CRTVAR1 _environ; /* pointer to environment table */
+#endif
+
+extern int _CRTVAR1 _fmode; /* default file translation mode */
+extern int _CRTVAR1 _fileinfo; /* open file info mode (for spawn) */
+
+extern char * _CRTVAR1 _pgmptr; /* points to the module (EXE) name */
+
+/* Windows major/minor and O.S. version numbers */
+
+extern unsigned int _CRTVAR1 _osver;
+extern unsigned int _CRTVAR1 _winver;
+extern unsigned int _CRTVAR1 _winmajor;
+extern unsigned int _CRTVAR1 _winminor;
+
+/* --------- The following block is OBSOLETE --------- */
+
+/* DOS major/minor version numbers */
+
+extern unsigned int _CRTVAR1 _osmajor;
+extern unsigned int _CRTVAR1 _osminor;
+
+/* --------- The preceding block is OBSOLETE --------- */
+
+#endif
+
+/* --------- The following block is OBSOLETE --------- */
+
+/* OS API mode */
+
+#define _DOS_MODE 0 /* DOS */
+#define _OS2_MODE 1 /* OS/2 */
+#define _WIN_MODE 2 /* Windows */
+#define _OS2_20_MODE 3 /* OS/2 2.0 */
+#define _DOSX32_MODE 4 /* DOSX32 */
+#define _POSIX_MODE_ 5 /* POSIX */
+
+#ifdef _DLL
+#define _osmode (*_osmode_dll)
+extern unsigned char * _CRTVAR1 _osmode_dll;
+#else
+#ifdef CRTDLL
+#define _osmode _osmode_dll
+#endif
+extern unsigned char _CRTVAR1 _osmode;
+#endif
+
+/* CPU addressing mode */
+
+#define _REAL_MODE 0 /* real mode */
+#define _PROT_MODE 1 /* protect mode */
+#define _FLAT_MODE 2 /* flat mode */
+
+#ifdef _DLL
+#define _cpumode (*_cpumode_dll)
+extern unsigned char * _CRTVAR1 _cpumode_dll;
+#else
+#ifdef CRTDLL
+#define _cpumode _cpumode_dll
+#endif
+extern unsigned char _CRTVAR1 _cpumode;
+#endif
+
+/* --------- The preceding block is OBSOLETE --------- */
+
+/* function prototypes */
+
+void _CRTAPI1 abort(void);
+int _CRTAPI1 abs(int);
+int _CRTAPI1 atexit(void (_CRTAPI1 *)(void));
+double _CRTAPI1 atof(const char *);
+int _CRTAPI1 atoi(const char *);
+long _CRTAPI1 atol(const char *);
+void * _CRTAPI1 bsearch(const void *, const void *, size_t, size_t,
+ int (_CRTAPI1 *)(const void *, const void *));
+void * _CRTAPI1 calloc(size_t, size_t);
+div_t _CRTAPI1 div(int, int);
+void _CRTAPI1 exit(int);
+void _CRTAPI1 free(void *);
+char * _CRTAPI1 getenv(const char *);
+char * _CRTAPI1 _itoa(int, char *, int);
+long _CRTAPI1 labs(long);
+ldiv_t _CRTAPI1 ldiv(long, long);
+char * _CRTAPI1 _ltoa(long, char *, int);
+void * _CRTAPI1 malloc(size_t);
+int _CRTAPI1 mblen(const char *, size_t);
+size_t _CRTAPI1 _mbstrlen(const char *s);
+int _CRTAPI1 mbtowc(wchar_t *, const char *, size_t);
+size_t _CRTAPI1 mbstowcs(wchar_t *, const char *, size_t);
+void _CRTAPI1 qsort(void *, size_t, size_t, int (_CRTAPI1 *)
+ (const void *, const void *));
+int _CRTAPI1 rand(void);
+void * _CRTAPI1 realloc(void *, size_t);
+void _CRTAPI1 srand(unsigned int);
+double _CRTAPI1 strtod(const char *, char **);
+long _CRTAPI1 strtol(const char *, char **, int);
+unsigned long _CRTAPI1 strtoul(const char *, char **, int);
+int _CRTAPI1 system(const char *);
+char * _CRTAPI1 _ultoa(unsigned long, char *, int);
+int _CRTAPI1 wctomb(char *, wchar_t);
+size_t _CRTAPI1 wcstombs(char *, const wchar_t *, size_t);
+#if !__STDC__
+#ifndef _WSTDLIB_DEFINED
+/* defined in wchar.h officially */
+double _CRTAPI1 wcstod(const wchar_t *, wchar_t **);
+long _CRTAPI1 wcstol(const wchar_t *, wchar_t **, int);
+unsigned long _CRTAPI1 wcstoul(const wchar_t *, wchar_t **, int);
+wchar_t * _CRTAPI1 _itow (int val, wchar_t *buf, int radix);
+wchar_t * _CRTAPI1 _ltow (long val, wchar_t *buf, int radix);
+wchar_t * _CRTAPI1 _ultow (unsigned long val, wchar_t *buf, int radix);
+long _CRTAPI1 _wtol(const wchar_t *nptr);
+int _CRTAPI1 _wtoi(const wchar_t *nptr);
+#define _WSTDLIB_DEFINED
+#endif
+#endif /* !__STDC__ */
+
+#ifndef _POSIX_
+#ifndef _WIN32_
+#ifdef _M_IX86
+long double _CRTAPI1 _atold(const char *);
+#endif
+#endif
+char * _CRTAPI1 _ecvt(double, int, int *, int *);
+void _CRTAPI1 _exit(int);
+char * _CRTAPI1 _fcvt(double, int, int *, int *);
+char * _CRTAPI1 _fullpath(char *, const char *, size_t);
+char * _CRTAPI1 _gcvt(double, int, char *);
+unsigned long _CRTAPI1 _lrotl(unsigned long, int);
+unsigned long _CRTAPI1 _lrotr(unsigned long, int);
+void _CRTAPI1 _makepath(char *, const char *, const char *, const char *,
+ const char *);
+_onexit_t _CRTAPI1 _onexit(_onexit_t);
+void _CRTAPI1 perror(const char *);
+int _CRTAPI1 _putenv(const char *);
+unsigned int _CRTAPI1 _rotl(unsigned int, int);
+unsigned int _CRTAPI1 _rotr(unsigned int, int);
+void _CRTAPI1 _searchenv(const char *, const char *, char *);
+void _CRTAPI1 _splitpath(const char *, char *, char *, char *, char *);
+void _CRTAPI1 _swab(char *, char *, int);
+void _CRTAPI1 _seterrormode(int);
+void _CRTAPI1 _beep(unsigned, unsigned);
+void _CRTAPI1 _sleep(unsigned long);
+#endif
+
+#ifndef tolower /* tolower has been undefined - use function */
+int _CRTAPI1 tolower(int);
+#endif /* tolower */
+
+#ifndef toupper /* toupper has been undefined - use function */
+int _CRTAPI1 toupper(int);
+#endif /* toupper */
+
+#ifdef MTHREAD /* _MTHREAD_ONLY */
+char * _CRTAPI1 _getenv_lk(const char *); /* _MTHREAD_ONLY */
+int _CRTAPI1 _putenv_lk(const char *); /* _MTHREAD_ONLY */
+int _CRTAPI1 _mblen_lk(const char *, size_t); /* _MTHREAD_ONLY */
+int _CRTAPI1 _mbtowc_lk(wchar_t*,const char*,size_t); /* _MTHREAD_ONLY */
+size_t _CRTAPI1 _mbstowcs_lk(wchar_t*,const char*,size_t); /* _MTHREAD_ONLY */
+int _CRTAPI1 _wctomb_lk(char*,wchar_t); /* _MTHREAD_ONLY */
+size_t _CRTAPI1 _wcstombs_lk(char*,const wchar_t*,size_t); /* _MTHREAD_ONLY */
+#else /* _MTHREAD_ONLY */
+#define _getenv_lk(envvar) getenv(envvar) /* _MTHREAD_ONLY */
+#define _putenv_lk(envvar) _putenv(envvar) /* _MTHREAD_ONLY */
+#define _mblen_lk(s,n) mblen(s,n) /* _MTHREAD_ONLY */
+#define _mbtowc_lk(pwc,s,n) mbtowc(pwc,s,n) /* _MTHREAD_ONLY */
+#define _mbstowcs_lk(pwcs,s,n) mbstowcs(pwcs,s,n) /* _MTHREAD_ONLY */
+#define _wctomb_lk(s,wchar) wctomb(s,wchar) /* _MTHREAD_ONLY */
+#define _wcstombs_lk(s,pwcs,n) wcstombs(s,pwcs,n) /* _MTHREAD_ONLY */
+#endif /* _MTHREAD_ONLY */
+
+#if (!__STDC__ && !defined(_POSIX_))
+/* Non-ANSI names for compatibility */
+
+#ifndef __cplusplus
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define sys_errlist _sys_errlist
+#define sys_nerr _sys_nerr
+#define environ _environ
+
+#define DOS_MODE _DOS_MODE
+#define OS2_MODE _OS2_MODE
+
+#ifndef _DOSX32_
+#define ecvt _ecvt
+#define fcvt _fcvt
+#define gcvt _gcvt
+#define itoa _itoa
+#define ltoa _ltoa
+#define onexit _onexit
+#define putenv _putenv
+#define swab _swab
+#define ultoa _ultoa
+#else
+char * _CRTAPI1 ecvt(double, int, int *, int *);
+char * _CRTAPI1 fcvt(double, int, int *, int *);
+char * _CRTAPI1 gcvt(double, int, char *);
+char * _CRTAPI1 itoa(int, char *, int);
+char * _CRTAPI1 ltoa(long, char *, int);
+onexit_t _CRTAPI1 onexit(onexit_t);
+int _CRTAPI1 putenv(const char *);
+void _CRTAPI1 swab(char *, char *, int);
+char * _CRTAPI1 ultoa(unsigned long, char *, int);
+#endif
+
+#endif /* !__STDC__ && !_POSIX_ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STDLIB
+#endif /* _INC_STDLIB */
diff --git a/private/crt32/h/streamb.h b/private/crt32/h/streamb.h
new file mode 100644
index 000000000..9c927e124
--- /dev/null
+++ b/private/crt32/h/streamb.h
@@ -0,0 +1,184 @@
+/***
+*streamb.h - definitions/declarations for the streambuf class
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the classes, values, macros, and functions
+* used by the streambuf class.
+* [AT&T C++]
+*
+*Revision History:
+* 01-23-92 KRS Ported from 16-bit version.
+* 03-02-92 KRS Added locks for multithread support.
+* 06-03-92 KRS For convenience, add NULL here too.
+* 02-23-93 SKS Update copyright to 1993
+* 03-23-93 CFW Modified #pragma warnings.
+*
+****/
+
+#ifndef _INC_STREAMB
+#define _INC_STREAMB
+
+#ifndef _INTERNAL_IFSTRIP_
+#ifdef COMBOINC
+#if defined(_DLL) && !defined(MTHREAD)
+#error Cannot define _DLL without MTHREAD
+#endif
+#endif
+
+#endif /* !_INTERNAL_IFSTRIP_ */
+
+#include <ios.h> // need ios::seek_dir definition
+#ifdef MTHREAD // defined in ios.h
+extern "C" {
+void _mtlockinit(PRTL_CRITICAL_SECTION);
+void _mtlock(PRTL_CRITICAL_SECTION);
+void _mtunlock(PRTL_CRITICAL_SECTION);
+}
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef EOF
+#define EOF (-1)
+#endif
+
+// C4505: "unreferenced local function has been removed"
+#pragma warning(disable:4505) // disable C4505 warning
+// #pragma warning(default:4505) // use this to reenable, if desired
+
+// C4103 : "used #pragma pack to change alignment"
+#pragma warning(disable:4103) // disable C4103 warning
+// #pragma warning(default:4103) // use this to reenable, if desired
+
+// Force word packing to avoid possible -Zp override
+#pragma pack(4)
+
+typedef long streampos, streamoff;
+
+class ios;
+
+class streambuf {
+public:
+
+ virtual ~streambuf();
+
+ inline int in_avail() const;
+ inline int out_waiting() const;
+ int sgetc();
+ int snextc();
+ int sbumpc();
+ void stossc();
+
+ inline int sputbackc(char);
+
+ inline int sputc(int);
+ inline int sputn(const char *,int);
+ inline int sgetn(char *,int);
+
+ virtual int sync();
+
+// enum seek_dir { beg=0, cur=1, end=2 }; // CONSIDER: needed ???
+
+ virtual streambuf* setbuf(char *, int);
+ virtual streampos seekoff(streamoff,ios::seek_dir,int =ios::in|ios::out);
+ virtual streampos seekpos(streampos,int =ios::in|ios::out);
+
+ virtual int xsputn(const char *,int);
+ virtual int xsgetn(char *,int);
+
+ virtual int overflow(int =EOF) = 0; // pure virtual function
+ virtual int underflow() = 0; // pure virtual function
+
+ virtual int pbackfail(int);
+
+ void dbp();
+
+#ifdef MTHREAD
+ void setlock() { LockFlg--; } // <0 indicates lock required;
+ void clrlock() { if (LockFlg <= 0) LockFlg++; }
+ void lock() { if (LockFlg<0) _mtlock(lockptr()); };
+ void unlock() { if (LockFlg<0) _mtunlock(lockptr()); }
+#else
+ void lock() { }
+ void unlock() { }
+#endif
+
+protected:
+ streambuf();
+ streambuf(char *,int);
+
+ inline char * base() const;
+ inline char * ebuf() const;
+ inline char * pbase() const;
+ inline char * pptr() const;
+ inline char * epptr() const;
+ inline char * eback() const;
+ inline char * gptr() const;
+ inline char * egptr() const;
+ inline int blen() const;
+ inline void setp(char *,char *);
+ inline void setg(char *,char *,char *);
+ inline void pbump(int);
+ inline void gbump(int);
+
+ void setb(char *,char *,int =0);
+ inline int unbuffered() const;
+ inline void unbuffered(int);
+ int allocate();
+ virtual int doallocate();
+#ifdef MTHREAD
+ PRTL_CRITICAL_SECTION lockptr() { return & x_lock; }
+#endif
+
+private:
+ int _fAlloc;
+ int _fUnbuf;
+ int x_lastc;
+ char * _base;
+ char * _ebuf;
+ char * _pbase;
+ char * _pptr;
+ char * _epptr;
+ char * _eback;
+ char * _gptr;
+ char * _egptr;
+#ifdef MTHREAD
+ int LockFlg; // <0 indicates locking required
+ RTL_CRITICAL_SECTION x_lock; // lock needed only for multi-thread operation
+#endif
+};
+
+inline int streambuf::in_avail() const { return (gptr()<_egptr) ? (_egptr-gptr()) : 0; }
+inline int streambuf::out_waiting() const { return (_pptr>=_pbase) ? (_pptr-_pbase) : 0; }
+
+inline int streambuf::sputbackc(char _c){ return (_eback<gptr()) ? *(--_gptr)=_c : pbackfail(_c); }
+
+inline int streambuf::sputc(int _i){ return (_pptr<_epptr) ? (unsigned char)(*(_pptr++)=(char)_i) : overflow(_i); }
+
+inline int streambuf::sputn(const char * _str,int _n) { return xsputn(_str, _n); }
+inline int streambuf::sgetn(char * _str,int _n) { return xsgetn(_str, _n); }
+
+inline char * streambuf::base() const { return _base; }
+inline char * streambuf::ebuf() const { return _ebuf; }
+inline int streambuf::blen() const {return ((_ebuf > _base) ? (_ebuf-_base) : 0); }
+inline char * streambuf::pbase() const { return _pbase; }
+inline char * streambuf::pptr() const { return _pptr; }
+inline char * streambuf::epptr() const { return _epptr; }
+inline char * streambuf::eback() const { return _eback; }
+inline char * streambuf::gptr() const { return _gptr; }
+inline char * streambuf::egptr() const { return _egptr; }
+inline void streambuf::gbump(int n) { if (_egptr) _gptr += n; }
+inline void streambuf::pbump(int n) { if (_epptr) _pptr += n; }
+inline void streambuf::setg(char * eb, char * g, char * eg) {_eback=eb; _gptr=g; _egptr=eg; x_lastc=EOF; }
+inline void streambuf::setp(char * p, char * ep) {_pptr=_pbase=p; _epptr=ep; }
+inline int streambuf::unbuffered() const { return _fUnbuf; }
+inline void streambuf::unbuffered(int fUnbuf) { _fUnbuf = fUnbuf; }
+
+// Restore default packing
+#pragma pack()
+
+#endif /* !_INC_STREAMB */
diff --git a/private/crt32/h/string.h b/private/crt32/h/string.h
new file mode 100644
index 000000000..7d3fe1e9a
--- /dev/null
+++ b/private/crt32/h/string.h
@@ -0,0 +1,228 @@
+/***
+*string.h - declarations for string manipulation functions
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the function declarations for the string
+* manipulation functions.
+* [ANSI/System V]
+*
+*Revision History:
+* 10/20/87 JCR Removed "MSC40_ONLY" entries
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 08-19-88 GJF Modified to also work for the 386 (small model only)
+* 03-22-88 JCR Added strcoll and strxfrm
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-03-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright, removed dummy args from strcoll and
+* strxfrm
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-17-89 GJF Added const to appropriate arg types for memccpy(),
+* memicmp() and _strerror().
+* 02-27-90 GJF Added #ifndef _INC_STRING, #include <cruntime.h>
+* and _CALLTYPE1 stuff. Also, some cleanup.
+* 03-21-90 GJF Got rid of movedata() prototype.
+* 08-14-90 SBM Added NULL definition for ANSI compliance
+* 11-12-90 GJF Changed NULL to (void *)0.
+* 01-18-91 GJF ANSI naming.
+* 02-12-91 GJF Only #define NULL if it isn't #define-d.
+* 03-21-91 KRS Added wchar_t type, also in stdlib.h and stddef.h.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 10-07-91 ETC Prototypes for wcs functions and _stricoll under _INTL.
+* 04-06-92 KRS Rip out _INTL switches again.
+* 06-23-92 GJF // is non-ANSI comment limiter.
+* 08-05-92 GJF Function calling type and variable type macros.
+* 08-18-92 KRS Activate wcstok.
+* 08-21-92 GJF Merged last two changes.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_STRING
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+
+/* function prototypes */
+
+void * _CRTAPI1 _memccpy(void *, const void *, int, unsigned int);
+void * _CRTAPI1 memchr(const void *, int, size_t);
+int _CRTAPI1 memcmp(const void *, const void *, size_t);
+int _CRTAPI1 _memicmp(const void *, const void *, unsigned int);
+void * _CRTAPI1 memcpy(void *, const void *, size_t);
+void * _CRTAPI1 memmove(void *, const void *, size_t);
+void * _CRTAPI1 memset(void *, int, size_t);
+char * _CRTAPI1 strcat(char *, const char *);
+char * _CRTAPI1 strchr(const char *, int);
+int _CRTAPI1 strcmp(const char *, const char *);
+int _CRTAPI1 _strcmpi(const char *, const char *);
+int _CRTAPI1 _stricmp(const char *, const char *);
+int _CRTAPI1 strcoll(const char *, const char *);
+#ifdef _MAC_
+char * _CRTAPI1 _c2pstr(const char *);
+char * _CRTAPI1 _p2cstr(const char *);
+#endif
+int _CRTAPI1 _stricoll(const char *, const char *);
+char * _CRTAPI1 strcpy(char *, const char *);
+size_t _CRTAPI1 strcspn(const char *, const char *);
+char * _CRTAPI1 _strdup(const char *);
+char * _CRTAPI1 _strerror(const char *);
+char * _CRTAPI1 strerror(int);
+size_t _CRTAPI1 strlen(const char *);
+char * _CRTAPI1 _strlwr(char *);
+char * _CRTAPI1 strncat(char *, const char *, size_t);
+int _CRTAPI1 strncmp(const char *, const char *, size_t);
+int _CRTAPI1 _strnicmp(const char *, const char *, size_t);
+char * _CRTAPI1 strncpy(char *, const char *, size_t);
+char * _CRTAPI1 _strnset(char *, int, size_t);
+char * _CRTAPI1 strpbrk(const char *, const char *);
+char * _CRTAPI1 strrchr(const char *, int);
+char * _CRTAPI1 _strrev(char *);
+char * _CRTAPI1 _strset(char *, int);
+size_t _CRTAPI1 strspn(const char *, const char *);
+char * _CRTAPI1 strstr(const char *, const char *);
+char * _CRTAPI1 strtok(char *, const char *);
+char * _CRTAPI1 _strupr(char *);
+size_t _CRTAPI1 strxfrm (char *, const char *, size_t);
+
+#ifndef _WSTRING_DEFINED
+wchar_t * _CRTAPI1 wcscat(wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcschr(const wchar_t *, wchar_t);
+int _CRTAPI1 wcscmp(const wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcscpy(wchar_t *, const wchar_t *);
+size_t _CRTAPI1 wcscspn(const wchar_t *, const wchar_t *);
+size_t _CRTAPI1 wcslen(const wchar_t *);
+wchar_t * _CRTAPI1 wcsncat(wchar_t *, const wchar_t *, size_t);
+int _CRTAPI1 wcsncmp(const wchar_t *, const wchar_t *, size_t);
+wchar_t * _CRTAPI1 wcsncpy(wchar_t *, const wchar_t *, size_t);
+wchar_t * _CRTAPI1 wcspbrk(const wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcsrchr(const wchar_t *, wchar_t);
+size_t _CRTAPI1 wcsspn(const wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcsstr(const wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcstok(wchar_t *, const wchar_t *);
+
+wchar_t * _CRTAPI1 _wcsdup(const wchar_t *);
+int _CRTAPI1 _wcsicmp(const wchar_t *, const wchar_t *);
+int _CRTAPI1 _wcsnicmp(const wchar_t *, const wchar_t *, size_t);
+wchar_t * _CRTAPI1 _wcsnset(wchar_t *, wchar_t, size_t);
+wchar_t * _CRTAPI1 _wcsrev(wchar_t *);
+wchar_t * _CRTAPI1 _wcsset(wchar_t *, wchar_t);
+
+wchar_t * _CRTAPI1 _wcslwr(wchar_t *);
+wchar_t * _CRTAPI1 _wcsupr(wchar_t *);
+size_t _CRTAPI1 wcsxfrm(wchar_t *, const wchar_t *, size_t);
+int _CRTAPI1 wcscoll(const wchar_t *, const wchar_t *);
+int _CRTAPI1 _wcsicoll(const wchar_t *, const wchar_t *);
+
+/* old names */
+#define wcswcs wcsstr
+
+#define _WSTRING_DEFINED
+#endif
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#ifndef _DOSX32_
+#define memccpy _memccpy
+#define memicmp _memicmp
+#define strcmpi _strcmpi
+#define stricmp _stricmp
+#define strdup _strdup
+#define strlwr _strlwr
+#define strnicmp _strnicmp
+#define strnset _strnset
+#define strrev _strrev
+#define strset _strset
+#define strupr _strupr
+#define stricoll _stricoll
+
+#ifdef _MAC_
+#define c2pstr _c2pstr
+#define p2cstr _p2cstr
+#endif
+#else
+void * _CRTAPI1 memccpy(void *, const void *, int, unsigned int);
+int _CRTAPI1 memicmp(const void *, const void *, unsigned int);
+int _CRTAPI1 strcmpi(const char *, const char *);
+int _CRTAPI1 stricmp(const char *, const char *);
+char * _CRTAPI1 strdup(const char *);
+char * _CRTAPI1 strlwr(char *);
+int _CRTAPI1 strnicmp(const char *, const char *, size_t);
+char * _CRTAPI1 strnset(char *, int, size_t);
+char * _CRTAPI1 strrev(char *);
+char * _CRTAPI1 strset(char *, int);
+char * _CRTAPI1 strupr(char *);
+#endif /* !_DOSX32_ */
+
+#define wcsdup _wcsdup
+#define wcsicmp _wcsicmp
+#define wcsnicmp _wcsnicmp
+#define wcsnset _wcsnset
+#define wcsrev _wcsrev
+#define wcsset _wcsset
+#define wcslwr _wcslwr
+#define wcsupr _wcsupr
+#define wcsicoll _wcsicoll
+#endif /* !__STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STRING
+#endif /* _INC_STRING */
diff --git a/private/crt32/h/strstrea.h b/private/crt32/h/strstrea.h
new file mode 100644
index 000000000..0021d99df
--- /dev/null
+++ b/private/crt32/h/strstrea.h
@@ -0,0 +1,93 @@
+/***
+*strstream.h - definitions/declarations for strstreambuf, strstream
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the classes, values, macros, and functions
+* used by the strstream and strstreambuf classes.
+* [AT&T C++]
+*
+*Revision History:
+* 01-23-92 KRS Ported from 16-bit version.
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#ifndef _INC_STRSTREAM
+#define _INC_STRSTREAM
+
+#include <iostream.h>
+
+// Force word packing to avoid possible -Zp override
+#pragma pack(4)
+
+#pragma warning(disable:4505) // disable unwanted /W4 warning
+// #pragma warning(default:4505) // use this to reenable, if necessary
+
+class strstreambuf : public streambuf {
+public:
+ strstreambuf();
+ strstreambuf(int);
+ strstreambuf(char *, int, char * = 0);
+ strstreambuf(unsigned char *, int, unsigned char * = 0);
+ strstreambuf(signed char *, int, signed char * = 0);
+ strstreambuf(void * (*a)(long), void (*f) (void *));
+ ~strstreambuf();
+
+ void freeze(int =1);
+ char * str();
+
+virtual int overflow(int);
+virtual int underflow();
+virtual streambuf* setbuf(char *, int);
+virtual streampos seekoff(streamoff, ios::seek_dir, int);
+virtual int sync(); // not in spec.
+
+protected:
+virtual int doallocate();
+private:
+ int x_dynamic;
+ int x_bufmin;
+ int _fAlloc;
+ int x_static;
+ void * (* x_alloc)(long);
+ void (* x_free)(void *);
+};
+
+class istrstream : public istream {
+public:
+ istrstream(char *);
+ istrstream(char *, int);
+ ~istrstream();
+
+inline strstreambuf* rdbuf() const { return (strstreambuf*) ios::rdbuf(); }
+inline char * str() { return rdbuf()->str(); }
+};
+
+class ostrstream : public ostream {
+public:
+ ostrstream();
+ ostrstream(char *, int, int = ios::out);
+ ~ostrstream();
+
+inline int pcount() const { return rdbuf()->out_waiting(); }
+inline strstreambuf* rdbuf() const { return (strstreambuf*) ios::rdbuf(); }
+inline char * str() { return rdbuf()->str(); }
+};
+
+class strstream : public iostream { // strstreambase ???
+public:
+ strstream();
+ strstream(char *, int, int);
+ ~strstream();
+
+inline int pcount() const { return rdbuf()->out_waiting(); } // not in spec.
+inline strstreambuf* rdbuf() const { return (strstreambuf*) ostream::rdbuf(); }
+inline char * str() { return rdbuf()->str(); }
+};
+
+// Restore default packing
+#pragma pack()
+
+#endif // !_INC_STRSTREAM
diff --git a/private/crt32/h/sys/locking.h b/private/crt32/h/sys/locking.h
new file mode 100644
index 000000000..d6a22a605
--- /dev/null
+++ b/private/crt32/h/sys/locking.h
@@ -0,0 +1,38 @@
+/***
+*sys/locking.h - flags for locking() function
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the flags for the locking() function.
+* [System V]
+*
+*Revision History:
+* 08-22-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 03-21-90 GJF Added #ifndef _INC_LOCKING stuff
+* 01-21-91 GJF ANSI naming.
+* 09-16-92 SKS Fix copyright, clean up backslash
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#ifndef _INC_LOCKING
+
+#define _LK_UNLCK 0 /* unlock the file region */
+#define _LK_LOCK 1 /* lock the file region */
+#define _LK_NBLCK 2 /* non-blocking lock */
+#define _LK_RLCK 3 /* lock for writing */
+#define _LK_NBRLCK 4 /* non-blocking lock for writing */
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#define LK_UNLCK _LK_UNLCK
+#define LK_LOCK _LK_LOCK
+#define LK_NBLCK _LK_NBLCK
+#define LK_RLCK _LK_RLCK
+#define LK_NBRLCK _LK_NBRLCK
+#endif
+
+#define _INC_LOCKING
+#endif /* _INC_LOCKING */
diff --git a/private/crt32/h/sys/stat.h b/private/crt32/h/sys/stat.h
new file mode 100644
index 000000000..19e9b3fa1
--- /dev/null
+++ b/private/crt32/h/sys/stat.h
@@ -0,0 +1,151 @@
+/***
+*sys/stat.h - defines structure used by stat() and fstat()
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the structure used by the _stat() and _fstat()
+* routines.
+* [System V]
+*
+*Revision History:
+* 07-28-87 SKS Fixed TIME_T_DEFINED to be _TIME_T_DEFINED
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 08-22-88 GJF Modified to also work for the 386 (small model only)
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-22-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-09-90 GJF Added #ifndef _INC_STAT and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1.
+* 01-18-91 GJF ANSI naming.
+* 01-25-91 GJF Protect _stat struct with pack pragma.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 08-07-92 GJF Function calling type and variable type macros. Also
+* #include <types.h> (common user request).
+* 11-10-92 SKS Need #pragma pack(4) around definition of struct _stat
+* in case the user has specified non-default packing
+* 12-15-92 GJF Added _S_IFIFO for pipes (based on Unix/Posix def.
+* for FIFO special files and pipes).
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 04-07-93 GJF Changed type of first arg to _stat to const char *.
+* 09-27-93 SRW Make pack pragma conditional on MIPS and ALPHA too.
+*
+****/
+
+#ifndef _INC_STAT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+#include <sys/types.h>
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _TIME_T_DEFINED
+typedef long time_t;
+#define _TIME_T_DEFINED
+#endif
+
+/* define structure for returning status information */
+
+#ifndef _STAT_DEFINED
+
+#ifdef _MSC_VER
+#pragma pack(4)
+#endif
+
+struct _stat {
+ _dev_t st_dev;
+ _ino_t st_ino;
+ unsigned short st_mode;
+ short st_nlink;
+ short st_uid;
+ short st_gid;
+ _dev_t st_rdev;
+ _off_t st_size;
+ time_t st_atime;
+ time_t st_mtime;
+ time_t st_ctime;
+ };
+
+#ifdef _MSC_VER
+#pragma pack()
+#endif
+
+#define _STAT_DEFINED
+#endif
+
+#define _S_IFMT 0170000 /* file type mask */
+#define _S_IFDIR 0040000 /* directory */
+#define _S_IFCHR 0020000 /* character special */
+#define _S_IFIFO 0010000 /* pipe */
+#define _S_IFREG 0100000 /* regular */
+#define _S_IREAD 0000400 /* read permission, owner */
+#define _S_IWRITE 0000200 /* write permission, owner */
+#define _S_IEXEC 0000100 /* execute/search permission, owner */
+
+
+/* function prototypes */
+
+int _CRTAPI1 _fstat(int, struct _stat *);
+int _CRTAPI1 _stat(const char *, struct _stat *);
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+
+#define S_IFMT _S_IFMT
+#define S_IFDIR _S_IFDIR
+#define S_IFCHR _S_IFCHR
+#define S_IFREG _S_IFREG
+#define S_IREAD _S_IREAD
+#define S_IWRITE _S_IWRITE
+#define S_IEXEC _S_IEXEC
+
+#ifndef _DOSX32_
+#define fstat _fstat
+#define stat _stat
+#else
+int _CRTAPI1 fstat(int, struct stat *);
+int _CRTAPI1 stat(const char *, struct stat *);
+#endif
+
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STAT
+#endif /* _INC_STAT */
diff --git a/private/crt32/h/sys/timeb.h b/private/crt32/h/sys/timeb.h
new file mode 100644
index 000000000..0ee9b414f
--- /dev/null
+++ b/private/crt32/h/sys/timeb.h
@@ -0,0 +1,129 @@
+/***
+*sys/timeb.h - definition/declarations for _ftime()
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file define the _ftime() function and the types it uses.
+* [System V]
+*
+*Revision History:
+* 07-28-87 SKS Fixed TIME_T_DEFINED to be _TIME_T_DEFINED
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-22-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-21-90 GJF Added #ifndef _INC_TIMEB stuff, added #include
+* <cruntime.h> and replaced _cdecl with _CALLTYPE1 in
+* prototype. Also, removed some (now) useless
+* preprocessor directives.
+* 01-21-91 GJF ANSI naming.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 01-23-92 GJF Had to change name of time zone field in timeb struct
+* to "tmzone" to make global time zone variable work in
+* crtdll.dll. INCOMPATIBLE CHANGE! OLD NAMING CANNOT BE
+* SUPPORTED BY A MACRO!
+* 08-07-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 06-08-93 SKS Change "tmzone" back to "timezone". This solution
+* was as much trouble as it was help. We simply cannot
+* support the old name "timezone" of the global variable
+* "_timezone", especially in CRTDLL model, where it must
+* be #defined to be (*_timezone_dll), because to do so
+* means that breaking the "struct _timeb" field names.
+*
+****/
+
+#ifndef _INC_TIMEB
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _TIME_T_DEFINED
+typedef long time_t;
+#define _TIME_T_DEFINED
+#endif
+
+/* structure returned by _ftime system call */
+
+#ifndef _TIMEB_DEFINED
+#ifdef _WIN32_
+struct _timeb {
+ time_t time;
+ unsigned short millitm;
+ short timezone;
+ short dstflag;
+ };
+#else /* ndef _WIN32_ */
+struct _timeb {
+ time_t time;
+ unsigned short millitm;
+ short _timezone;
+ short dstflag;
+ };
+
+/* must be same name as extern declared in time.h */
+#define timezone _timezone
+
+#endif /* _WIN32_ */
+
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#define timeb _timeb
+#endif
+
+#define _TIMEB_DEFINED
+#endif
+
+
+/* function prototypes */
+
+void _CRTAPI1 _ftime(struct _timeb *);
+
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#ifndef _DOSX32_
+#define ftime _ftime
+#else
+void _CRTAPI1 ftime(struct timeb *);
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_TIMEB
+#endif /* _INC_TIMEB */
diff --git a/private/crt32/h/sys/types.h b/private/crt32/h/sys/types.h
new file mode 100644
index 000000000..88c93f067
--- /dev/null
+++ b/private/crt32/h/sys/types.h
@@ -0,0 +1,58 @@
+/***
+*sys/types.h - types returned by system level calls for file and time info
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines types used in defining values returned by system
+* level calls for file status and time information.
+* [System V]
+*
+*Revision History:
+* 07-28-87 SKS Fixed TIME_T_DEFINED to be _TIME_T_DEFINED
+* 08-22-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 03-21-90 GJF Added #ifndef _INC_TYPES stuff.
+* 01-18-91 GJF ANSI naming.
+* 01-20-91 JCR Fixed dev_t definition
+* 09-16-92 SKS Fix copyright, clean up backslash
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#ifndef _INC_TYPES
+
+#ifndef _TIME_T_DEFINED
+typedef long time_t;
+#define _TIME_T_DEFINED
+#endif
+
+#ifndef _INO_T_DEFINED
+typedef unsigned short _ino_t; /* i-node number (not used on DOS) */
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#define ino_t _ino_t
+#endif
+#define _INO_T_DEFINED
+#endif
+
+#ifndef _DEV_T_DEFINED
+typedef short _dev_t; /* device code */
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#define dev_t _dev_t
+#endif
+#define _DEV_T_DEFINED
+#endif
+
+#ifndef _OFF_T_DEFINED
+typedef long _off_t; /* file offset value */
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#define off_t _off_t
+#endif
+#define _OFF_T_DEFINED
+#endif
+
+#define _INC_TYPES
+#endif /* _INC_TYPES */
diff --git a/private/crt32/h/sys/utime.h b/private/crt32/h/sys/utime.h
new file mode 100644
index 000000000..57b6712cf
--- /dev/null
+++ b/private/crt32/h/sys/utime.h
@@ -0,0 +1,106 @@
+/***
+*sys/utime.h - definitions/declarations for utime()
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the structure used by the utime routine to set
+* new file access and modification times. NOTE - MS-DOS
+* does not recognize access time, so this field will
+* always be ignored and the modification time field will be
+* used to set the new time.
+*
+*Revision History:
+* 07-28-87 SKS Fixed TIME_T_DEFINED to be _TIME_T_DEFINED
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 02-10-88 JCR Cleaned up white space
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-22-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-21-90 GJF Added #ifndef _INC_UTIME and #include <cruntime.h>
+* stuff, and replaced _cdecl with _CALLTYPE1 in the
+* prototype.
+* 01-22-91 GJF ANSI naming.
+* 08-20-91 JCR C++ and ANSI naming
+* 08-26-91 BWM Added prototype for _futime.
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 08-07-92 GJF Function calling type and variable type macros.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_UTIME
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _TIME_T_DEFINED
+typedef long time_t;
+#define _TIME_T_DEFINED
+#endif
+
+/* define struct used by _utime() function */
+
+#ifndef _UTIMBUF_DEFINED
+struct _utimbuf {
+ time_t actime; /* access time */
+ time_t modtime; /* modification time */
+ };
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#define utimbuf _utimbuf
+#endif
+
+#define _UTIMBUF_DEFINED
+#endif
+
+/* function prototypes */
+
+int _CRTAPI1 _utime(char *, struct _utimbuf *);
+int _CRTAPI1 _futime(int, struct _utimbuf *);
+
+#if !__STDC__
+/* Non-ANSI name for compatibility */
+#ifndef _DOSX32_
+#define utime _utime
+#else
+int _CRTAPI1 utime(char *, struct utimbuf *);
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_UTIME
+#endif /* _INC_UTIME */
diff --git a/private/crt32/h/syserr.h b/private/crt32/h/syserr.h
new file mode 100644
index 000000000..86110449f
--- /dev/null
+++ b/private/crt32/h/syserr.h
@@ -0,0 +1,44 @@
+/***
+*syserr.h - constants/macros for error message routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains macros/constants for perror, strerror,
+* and _strerror.
+* [Internal]
+*
+*Revision History:
+* 08-15-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 03-02-90 GJF Added #ifndef _INC_SYSERR stuff
+* 01-22-91 GJF ANSI naming.
+* 01-23-92 GJF Added support for crtdll.dll (have to redefine
+* _sys_nerr).
+* 10-01-92 GJF Increased _SYS_MSGMAX.
+* 02-23-93 SKS Update copyright to 1993
+*
+****/
+
+#ifndef _INC_SYSERR
+
+#ifdef _DLL
+#define _sys_nerr (*_sys_nerr_dll)
+#else
+#ifdef CRTDLL
+#define _sys_nerr _sys_nerr_dll
+#endif
+#endif
+
+/* Macro for perror, strerror, and _strerror */
+
+#define _sys_err_msg(m) _sys_errlist[(((m)<0)||((m)>=_sys_nerr)?_sys_nerr:(m))]
+
+/* Maximum length of an error message.
+ NOTE: This parameter value must be correspond to the length of the longest
+ message in sys_errlist (source module syserr.c). */
+
+#define _SYS_MSGMAX 38
+
+#define _INC_SYSERR
+#endif /* _INC_SYSERR */
diff --git a/private/crt32/h/tchar.h b/private/crt32/h/tchar.h
new file mode 100644
index 000000000..6f20ac50e
--- /dev/null
+++ b/private/crt32/h/tchar.h
@@ -0,0 +1,587 @@
+/***
+*tchar.h - definitions for generic international text functions
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions for generic international functions, mostly defines
+* which map string/formatted-io/ctype functions to char, wchar_t, or
+* MBCS versions. To be used for compatibility between single-byte,
+* multi-byte and Unicode text models.
+*
+*
+*
+*Revision History:
+* 11-21-91 ETC Created.
+* 12-13-91 ETC Changed names of formatted i/o functions.
+* 04-02-92 KRS Renamed file tchar.h to match ISO's wchar.h.
+* 06-03-92 KRS Add full printf family of functions. Remove _tflag.
+* 06-16-92 KRS Add strtol/strtod functions.
+* 07-06-92 KRS Put TCHAR typedef under switches.
+* 08-18-92 KRS Added _tscanf and _tcstok under _UNICODE switches.
+* 01-26-93 KRS Rip out _TSTART macro. Added _TEXT() macro.
+* 03-03-93 KRS Added _TEXT macro and _MBCS support.
+* 03-23-93 KRS Added model-independent string functions.
+* 04-06-93 KRS Added MBCS-specific functions.
+* 04-29-93 CFW Add/correct a few macros.
+* 05-12-93 KRS Change type TCHAR to _TCHAR if not __STDC__ for ANSI.
+* Added _tclen, _tccpy, use __inline.
+* 05-29-93 CFW Add another layer of indirection to _TEXT macros.
+* 06-03-93 KRS Change definition of _strinc/dec and tccpy.
+* 06-15-93 KRS Merge 16- and 32-bit versions.
+* 07-14-93 KRS Make _tcslen, all _tcsnxxx functions use _TCHARS, not
+* "logical characters". Add _tcsclen, tcsncxxx versions
+* for "logical char" versions.
+* 07-28-93 KRS Improve macros to eliminate /W4 warnings.
+* 08-11-93 CFW Grabbed from Ikura - currently *identical* to Ikura.
+* 09-28-93 SRW Protect RC compiler from #pragma
+* 10-13-93 GJF Merged NT and Cuda versions. Deleted old 16-bit
+* support. Replaced defined(__STDC__) with __STDC__ in
+* preprocessor statements.
+* 10-19-93 CFW Add missing mappings.
+* 10-19-93 CFW Fix _tcscspn bug.
+* 10-22-93 CFW Missing mappings use new functions.
+* 11-09-93 SRW Add definition lf wchar_t if needed.
+*
+****/
+
+#ifndef _INC_TCHAR
+
+#ifdef _MSC_VER
+#pragma warning(disable:4505) /* disable unwanted C++ /W4 warning */
+/* #pragma warning(default:4505) */ /* use this to reenable, if necessary */
+#endif /* _MSC_VER */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* No Model-independent functions under Win32 */
+
+#define __far
+
+
+/* Default for Win32 is no inlining. Define _USE_INLINING to overide */
+
+#ifndef _USE_INLINING
+#define _NO_INLINING
+#endif
+
+
+/* No model-independent string functions for Win32 */
+
+#define _ftcscat _tcscat
+#define _ftcschr _tcschr
+#define _ftcscmp _tcscmp
+#define _ftcscpy _tcscpy
+#define _ftcscspn _tcscspn
+#define _ftcslen _tcslen
+#define _ftcsncat _tcsncat
+#define _ftcsncmp _tcsncmp
+#define _ftcsncpy _tcsncpy
+#define _ftcspbrk _tcspbrk
+#define _ftcsrchr _tcsrchr
+#define _ftcsspn _tcsspn
+#define _ftcsstr _tcsstr
+#define _ftcstok _tcstok
+
+#define _ftcsdup _tcsdup
+#define _ftcsicmp _tcsicmp
+#define _ftcsnicmp _tcsnicmp
+#define _ftcsnset _tcsnset
+#define _ftcsrev _tcsrev
+#define _ftcsset _tcsset
+
+
+/* Redundant "logical-character" mappings */
+
+#define _ftcsclen _tcsclen
+#define _ftcsnccat _tcsnccat
+#define _ftcsnccpy _tcsnccpy
+#define _ftcsnccmp _tcsnccmp
+#define _ftcsncicmp _tcsncicmp
+#define _ftcsncset _tcsncset
+
+#define _ftcsdec _tcsdec
+#define _ftcsinc _tcsinc
+#define _ftcsnbcnt _tcsncnt
+#define _ftcsnccnt _tcsncnt
+#define _ftcsnextc _tcsnextc
+#define _ftcsninc _tcsninc
+#define _ftcsspnp _tcsspnp
+
+#define _ftcslwr _tcslwr
+#define _ftcsupr _tcsupr
+
+#define _ftclen _tclen
+#define _ftccpy _tccpy
+#define _ftccmp _tccmp
+
+
+#ifdef _UNICODE
+
+
+#ifndef _WCTYPE_T_DEFINED
+typedef wchar_t wint_t;
+typedef wchar_t wctype_t;
+#define _WCTYPE_T_DEFINED
+#endif
+
+#ifndef __TCHAR_DEFINED
+typedef wchar_t _TCHAR;
+typedef wint_t _TINT;
+#define __TCHAR_DEFINED
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if !__STDC__
+typedef wchar_t TCHAR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+#define _TEOF WEOF
+
+#define __T(x) L ## x
+
+
+/* Formatted i/o */
+
+#define _tprintf wprintf
+#define _ftprintf fwprintf
+#define _stprintf swprintf
+#define _sntprintf _snwprintf
+#define _vtprintf vwprintf
+#define _vftprintf vfwprintf
+#define _vstprintf vswprintf
+#define _vsntprintf _vsnwprintf
+#define _tscanf wscanf
+#define _ftscanf fwscanf
+#define _stscanf swscanf
+
+
+/* Unformatted i/o */
+
+#define _fgettc fgetwc
+#define _fgettchar _fgetwchar
+#define _fgetts fgetws
+#define _fputtc fputwc
+#define _fputtchar _fputwchar
+#define _fputts fputws
+#define _gettc getwc
+#define _gettchar getwchar
+#define _puttc putwc
+#define _puttchar putwchar
+#define _ungettc ungetwc
+
+
+/* String conversion functions */
+
+#define _tcstod wcstod
+#define _tcstol wcstol
+#define _tcstoul wcstoul
+
+
+/* String functions */
+
+#define _tcscat wcscat
+#define _tcschr wcschr
+#define _tcscmp wcscmp
+#define _tcscpy wcscpy
+#define _tcscspn wcscspn
+#define _tcslen wcslen
+#define _tcsncat wcsncat
+#define _tcsncmp wcsncmp
+#define _tcsncpy wcsncpy
+#define _tcspbrk wcspbrk
+#define _tcsrchr wcsrchr
+#define _tcsspn wcsspn
+#define _tcsstr wcsstr
+#define _tcstok wcstok
+
+#define _tcsdup _wcsdup
+#define _tcsicmp _wcsicmp
+#define _tcsnicmp _wcsnicmp
+#define _tcsnset _wcsnset
+#define _tcsrev _wcsrev
+#define _tcsset _wcsset
+
+
+/* Redundant "logical-character" mappings */
+
+#define _tcsclen wcslen
+#define _tcsnccat wcsncat
+#define _tcsnccpy wcsncpy
+#define _tcsnccmp wcsncmp
+#define _tcsncicmp _wcsnicmp
+#define _tcsncset _wcsnset
+
+#define _tcsdec _wcsdec
+#define _tcsinc _wcsinc
+#define _tcsnbcnt _wcsncnt
+#define _tcsnccnt _wcsncnt
+#define _tcsnextc _wcsnextc
+#define _tcsninc _wcsninc
+#define _tcsspnp _wcsspnp
+
+#define _tcslwr _wcslwr
+#define _tcsupr _wcsupr
+#define _tcsxfrm wcsxfrm
+#define _tcscoll wcscoll
+#define _tcsicoll _wcsicoll
+
+
+#if !__STDC__ || defined(_NO_INLINING)
+#define _tclen(_pc) (1)
+#define _tccpy(_pc1,_cpc2) ((*(_pc1) = *(_cpc2)))
+#define _tccmp(_cpc1,_cpc2) ((*(_cpc1))-(*(_cpc2)))
+#else
+__inline size_t _tclen(const wchar_t *_cpc) { return (_cpc,1); }
+__inline void _tccpy(wchar_t *_pc1, const wchar_t *_cpc2) { *_pc1 = (wchar_t)*_cpc2; }
+__inline int _tccmp(const wchar_t *_cpc1, const wchar_t *_cpc2) { return (int) ((*_cpc1)-(*_cpc2)); }
+#endif
+
+
+/* ctype functions */
+
+#define _istalpha iswalpha
+#define _istupper iswupper
+#define _istlower iswlower
+#define _istdigit iswdigit
+#define _istxdigit iswxdigit
+#define _istspace iswspace
+#define _istpunct iswpunct
+#define _istalnum iswalnum
+#define _istprint iswprint
+#define _istgraph iswgraph
+#define _istcntrl iswcntrl
+#define _istascii iswascii
+
+#define _totupper towupper
+#define _totlower towlower
+
+#define _istlegal (1)
+
+
+#if !__STDC__ || defined(_NO_INLINING)
+#define _wcsdec(_cpc, _pc) ((_pc)-1)
+#define _wcsinc(_pc) ((_pc)+1)
+#define _wcsnextc(_cpc) ((unsigned int) *(_cpc))
+#define _wcsninc(_pc, _sz) (((_pc)+(_sz)))
+#define _wcsncnt(_cpc, _sz) ((wcslen(_cpc)>_sz) ? _sz : wcslen(_cpc))
+#define _wcsspnp(_cpc1, _cpc2) ((*((_cpc1)+wcsspn(_cpc1,_cpc2))) ? ((_cpc1)+wcsspn(_cpc1,_cpc2)) : NULL)
+#else
+__inline wchar_t * _wcsdec(const wchar_t * _cpc, const wchar_t * _pc) { return (wchar_t *)(_cpc,(_pc-1)); }
+__inline wchar_t * _wcsinc(const wchar_t * _pc) { return (wchar_t *)(_pc+1); }
+__inline unsigned int _wcsnextc(const wchar_t * _cpc) { return (unsigned int)*_cpc; }
+__inline wchar_t * _wcsninc(const wchar_t * _pc, size_t _sz) { return (wchar_t *)(_pc+_sz); }
+__inline size_t _wcsncnt( const wchar_t * _cpc, size_t _sz) { size_t len; len = wcslen(_cpc); return (len>_sz) ? _sz : len; }
+__inline wchar_t * _wcsspnp( const wchar_t * _cpc1, const wchar_t * _cpc2) { return (*(_cpc1 += wcsspn(_cpc1,_cpc2))!='\0') ? (wchar_t*)_cpc1 : NULL; }
+#endif
+
+
+#else /* ndef _UNICODE */
+
+
+#if !defined(_CHAR_UNSIGNED) && !defined(_JWARNING_DEFINED)
+/* #pragma message("TCHAR.H: Warning: The /J option is recommended for international compilation") */
+#define _JWARNING_DEFINED
+#endif
+
+
+#include <string.h>
+
+
+#define __T(x) x
+
+
+/* Formatted i/o */
+
+#define _tprintf printf
+#define _ftprintf fprintf
+#define _stprintf sprintf
+#define _sntprintf _snprintf
+#define _vtprintf vprintf
+#define _vftprintf vfprintf
+#define _vstprintf vsprintf
+#define _vsntprintf _vsnprintf
+#define _tscanf scanf
+#define _ftscanf fscanf
+#define _stscanf sscanf
+
+
+/* Unformatted i/o */
+
+#define _fgettc(_f) (_TINT)fgetc((_f))
+#define _fgettchar (_TINT)_fgetchar
+#define _fgetts(_s,_i,_f) fgets((_s),(_i),(_f))
+#define _fputtc(_i,_f) (_TINT)fputc((int)(_i),(_f))
+#define _fputtchar(_i) (_TINT)_fputchar((int)(_i))
+#define _fputts(_s,_f) (_TINT)fputs((_s),(_f))
+#define _gettc(_f) (_TINT)getc((_f))
+#define _gettchar (_TINT)getchar
+#define _puttc(_i,_f) (_TINT)putc((int)(_i),(_f))
+#define _puttchar(_i) (_TINT)putchar((int)(_i))
+#define _ungettc(_i,_f) (_TINT)ungetc((int)(_i),(_f))
+
+
+/* String conversion functions */
+
+#define _tcstod strtod
+#define _tcstol strtol
+#define _tcstoul strtoul
+
+
+#ifdef _MBCS
+
+#ifndef __TCHAR_DEFINED
+typedef char _TCHAR;
+typedef unsigned int _TINT;
+#define __TCHAR_DEFINED
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if !__STDC__
+typedef char TCHAR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+#define _TEOF EOF
+
+
+#include <mbstring.h>
+
+
+/* Helper macros for MB casts */
+
+#define _MB(_s) ((unsigned char *)(_s))
+#define _CMB(_s) ((const unsigned char *)(_s))
+
+
+/* String functions */
+
+#define _tcscat(_s1,_s2) (_TCHAR*)_mbscat(_MB(_s1),_CMB(_s2))
+#define _tcschr(_s,_i) (_TCHAR*)_mbschr(_CMB(_s),(_i))
+#define _tcscmp(_s1,_s2) _mbscmp(_CMB(_s1),_CMB(_s2))
+#define _tcscpy(_s1,_s2) (_TCHAR*)_mbscpy(_MB(_s1),_CMB(_s2))
+#define _tcscspn(_s1,_s2) _mbscspn(_CMB(_s1),_CMB(_s2))
+#define _tcslen(_s) strlen((_s))
+#define _tcsncat(_s1,_s2,_n) (_TCHAR*)_mbsnbcat(_MB(_s1),_CMB(_s2),(_n))
+#define _tcsncmp(_s1,_s2,_n) _mbsnbcmp(_CMB(_s1),_CMB(_s2),(_n))
+#define _tcsncpy(_s1,_s2,_n) (_TCHAR*)_mbsnbcpy(_MB(_s1),_CMB(_s2),(_n))
+#define _tcspbrk(_s1,_s2) (_TCHAR*)_mbspbrk(_CMB(_s1),_CMB(_s2))
+#define _tcsrchr(_s,_i) (_TCHAR*)_mbsrchr(_CMB(_s),(_i))
+#define _tcsspn(_s1,_s2) _mbsspn(_CMB(_s1),_CMB(_s2))
+#define _tcsstr(_s1,_s2) (_TCHAR*)_mbsstr(_CMB(_s1),_CMB(_s2))
+#define _tcstok(_s1,_s2) (_TCHAR*)_mbstok(_MB(_s1),_CMB(_s2))
+
+#define _tcsdup(_s) (_TCHAR*)_mbsdup(_CMB(_s))
+#define _tcsicmp(_s1,_s2) _mbsicmp(_CMB(_s1),_CMB(_s2))
+#define _tcsnicmp(_s1,_s2,_n) _mbsnbicmp(_CMB(_s1),_CMB(_s2),(_n))
+#define _tcsnset(_s,_i,_n) (_TCHAR*)_mbsnbset(_MB(_s),(_i),(_n))
+#define _tcsrev(_s) (_TCHAR*)_mbsrev(_MB(_s))
+#define _tcsset(_s,_i) (_TCHAR*)_mbsset(_MB(_s),(_i))
+
+
+/* "logical-character" mappings */
+
+#define _tcsclen(_s) _mbslen(_MB(_s))
+#define _tcsnccat(_s1,_s2,_n) (_TCHAR*)_mbsncat(_MB(_s1),_CMB(_s2),(_n))
+#define _tcsnccpy(_s1,_s2,_n) (_TCHAR*)_mbsncpy(_MB(_s1),_CMB(_s2),(_n))
+#define _tcsnccmp(_s1,_s2,_n) _mbsncmp(_CMB(_s1),_CMB(_s2),(_n))
+#define _tcsncicmp(_s1,_s2,_n) _mbsnicmp(_CMB(_s1),_CMB(_s2),(_n))
+#define _tcsncset(_s,_i,_n) (_TCHAR*)_mbsnset(_MB(_s),(_i),(_n))
+
+
+/* MBCS-specific mappings */
+
+#define _tcsdec(_s1,_s2) (_TCHAR*)_mbsdec(_CMB(_s1),_CMB(_s2))
+#define _tcsinc(_s) (_TCHAR*)_mbsinc(_CMB(_s))
+#define _tcsnbcnt(_s,_n) _mbsnbcnt(_CMB(_s),(_n))
+#define _tcsnccnt(_s,_n) _mbsnccnt(_CMB(_s),(_n))
+#define _tcsnextc(_s) _mbsnextc(_CMB(_s))
+#define _tcsninc(_s,_n) (_TCHAR*)_mbsninc(_CMB(_s),(_n))
+#define _tcsspnp(_s1,_s2) (_TCHAR*)_mbsspnp(_CMB(_s1),_CMB(_s2))
+
+#define _tcslwr(_s) (_TCHAR*)_mbslwr(_MB(_s))
+#define _tcsupr(_s) (_TCHAR*)_mbsupr(_MB(_s))
+#define _tcsxfrm(_d,_s,_n) (strncpy((_d),(_s),(_n)),strlen((_s)))
+#define _tcscoll _tcscmp
+#define _tcsicoll _tcsicmp
+
+#define _tclen(_s) _mbclen(_CMB(_s))
+#define _tccpy(_s1,_s2) _mbccpy(_MB(_s1),_CMB(_s2))
+#define _tccmp(_s1,_s2) _tcsnccmp((_s1),(_s2),1)
+
+
+/* ctype functions */
+
+#define _istalpha _ismbcalpha
+#define _istupper _ismbcupper
+#define _istlower _ismbclower
+#define _istdigit _ismbcdigit
+#define _istxdigit _isxdigit
+#define _istspace _ismbcspace
+#define _istprint _ismbcprint
+#define _istcntrl _iscntrl
+#define _istascii _isascii
+
+#define _totupper _mbctoupper
+#define _totlower _mbctolower
+
+#define _istlegal _ismbclegal
+
+
+#else /* !_MBCS */
+
+
+#ifndef __TCHAR_DEFINED
+typedef char _TCHAR;
+typedef int _TINT;
+#define __TCHAR_DEFINED
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if !__STDC__
+typedef char TCHAR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+#define _TEOF EOF
+
+
+/* String functions */
+
+#define _tcscat strcat
+#define _tcschr strchr
+#define _tcscmp strcmp
+#define _tcscpy strcpy
+#define _tcscspn strcspn
+#define _tcslen strlen
+#define _tcsncat strncat
+#define _tcsncmp strncmp
+#define _tcsncpy strncpy
+#define _tcspbrk strpbrk
+#define _tcsrchr strrchr
+#define _tcsspn strspn
+#define _tcsstr strstr
+#define _tcstok strtok
+
+#define _tcsdup _strdup
+#define _tcsicmp _stricmp
+#define _tcsnicmp _strnicmp
+#define _tcsnset _strnset
+#define _tcsrev _strrev
+#define _tcsset _strset
+
+
+/* "logical-character" mappings */
+
+#define _tcsclen strlen
+#define _tcsnccat strncat
+#define _tcsnccpy strncpy
+#define _tcsnccmp strncmp
+#define _tcsncicmp _strnicmp
+#define _tcsncset _strnset
+
+
+/* MBCS-specific functions */
+
+#define _tcsdec _strdec
+#define _tcsinc _strinc
+#define _tcsnbcnt _strncnt
+#define _tcsnccnt _strncnt
+#define _tcsnextc _strnextc
+#define _tcsninc _strninc
+#define _tcsspnp _strspnp
+
+#define _tcslwr _strlwr
+#define _tcsupr _strupr
+#define _tcsxfrm strxfrm
+#define _tcscoll strcoll
+#define _tcsicoll _stricoll
+
+
+#if !__STDC__ || defined(_NO_INLINING)
+#define _tclen(_pc) (1)
+#define _tccpy(_pc1,_cpc2) (*(_pc1) = *(_cpc2))
+#define _tccmp(_cpc1,_cpc2) (((unsigned char)*(_cpc1))-((unsigned char)*(_cpc2)))
+#else
+__inline size_t _tclen(const char *_cpc) { return (_cpc,1); }
+__inline void _tccpy(char *_pc1, const char *_cpc2) { *_pc1 = *_cpc2; }
+__inline int _tccmp(const char *_cpc1, const char *_cpc2) { return (int) (((unsigned char)*_cpc1)-((unsigned char)*_cpc2)); }
+#endif
+
+
+/* ctype-functions */
+
+#define _istalpha isalpha
+#define _istupper isupper
+#define _istlower islower
+#define _istdigit isdigit
+#define _istxdigit isxdigit
+#define _istspace isspace
+#define _istpunct ispunct
+#define _istalnum isalnum
+#define _istprint isprint
+#define _istgraph isgraph
+#define _istcntrl iscntrl
+#define _istascii isascii
+
+#define _totupper toupper
+#define _totlower tolower
+
+#define _istlegal (1)
+
+
+/* the following is optional if functional versions are available */
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+
+#if !__STDC__ || defined(_NO_INLINING)
+#define _strdec(_cpc, _pc) ((_pc)-1)
+#define _strinc(_pc) ((_pc)+1)
+#define _strnextc(_cpc) ((unsigned int) *(_cpc))
+#define _strninc(_pc, _sz) (((_pc)+(_sz)))
+#define _strncnt(_cpc, _sz) ((strlen(_cpc)>_sz) ? _sz : strlen(_cpc))
+#define _strspnp(_cpc1, _cpc2) ((*((_cpc1)+strspn(_cpc1,_cpc2))) ? ((_cpc1)+strspn(_cpc1,_cpc2)) : NULL)
+#else /* __STDC__ */
+__inline char * _strdec(const char * _cpc, const char * _pc) { return (char *)(_cpc,(_pc-1)); }
+__inline char * _strinc(const char * _pc) { return (char *)(_pc+1); }
+__inline unsigned int _strnextc(const char * _cpc) { return (unsigned int)*_cpc; }
+__inline char * _strninc(const char * _pc, size_t _sz) { return (char *)(_pc+_sz); }
+__inline size_t _strncnt( const char * _cpc, size_t _sz) { size_t len; len = strlen(_cpc); return (len>_sz) ? _sz : len; }
+__inline char * _strspnp( const char * _cpc1, const char * _cpc2) { return (*(_cpc1 += strspn(_cpc1,_cpc2))!='\0') ? (char*)_cpc1 : NULL; }
+#endif /* __STDC__ */
+
+
+#endif /* _MBCS */
+
+#endif /* _UNICODE */
+
+
+/* Generic text macros to be used with string literals and character constants.
+ Will also allow symbolic constants that resolve to same. */
+
+#define _T(x) __T(x)
+#define _TEXT(x) __T(x)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_TCHAR
+#endif /* _INC_TCHAR */
diff --git a/private/crt32/h/time.h b/private/crt32/h/time.h
new file mode 100644
index 000000000..038587f37
--- /dev/null
+++ b/private/crt32/h/time.h
@@ -0,0 +1,242 @@
+/***
+*time.h - definitions/declarations for time routines
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file has declarations of time routines and defines
+* the structure returned by the localtime and gmtime routines and
+* used by asctime.
+* [ANSI/System V]
+*
+*Revision History:
+* 07-27-87 SKS Added _strdate(), _strtime()
+* 10-20-87 JCR Removed "MSC40_ONLY" entries
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 01-16-88 JCR Added function versions of daylight/timezone/tzset
+* 01-20-88 SKS Change _timezone(n) to _timezone(), _daylight()
+* 02-10-88 JCR Cleaned up white space
+* 12-07-88 JCR DLL timezone/daylight/tzname now directly refers to data
+* 03-14-89 JCR Added strftime() prototype and size_t definition
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-15-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright, removed dummy args from prototypes
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-20-89 JCR difftime() always _cdecl (not pascal even under mthread)
+* 03-02-90 GJF Added #ifndef _INC_TIME and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-29-90 GJF Replaced _cdecl with _CALLTYPE1 in prototypes and with
+* _VARTYPE1 in variable declarations.
+* 08-16-90 SBM Added NULL definition for ANSI compliance
+* 11-12-90 GJF Changed NULL to (void *)0.
+* 01-21-91 GJF ANSI naming.
+* 02-12-91 GJF Only #define NULL if it isn't #define-d.
+* 08-20-91 JCR C++ and ANSI naming
+* 08-26-91 BWM Added prototypes for _getsystime and _setsystem.
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 01-22-92 GJF Fixed up definitions of global variables for build of,
+* and users of, crtdll.dll.
+* 03-25-92 DJM POSIX support.
+* 08-05-92 GJF Function calling type and variable type macros.
+* 08-24-92 PBS Support for Posix TZ variable.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 03-10-93 MJB Fixes for Posix TZ stuff.
+* 05-05-93 CFW Add wcsftime proto.
+* 06-08-93 SKS Cannot #define the old name "timezone" to "_timezone"
+* because of conflict conflict with the timezone field
+* in struct timeb in <sys/timeb.h>.
+*
+****/
+
+#ifndef _INC_TIME
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+/* define the implementation defined time type */
+
+#ifndef _TIME_T_DEFINED
+typedef long time_t; /* time value */
+#define _TIME_T_DEFINED /* avoid multiple def's of time_t */
+#endif
+
+#ifndef _CLOCK_T_DEFINED
+typedef long clock_t;
+#define _CLOCK_T_DEFINED
+#endif
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+
+#ifndef _TM_DEFINED
+struct tm {
+ int tm_sec; /* seconds after the minute - [0,59] */
+ int tm_min; /* minutes after the hour - [0,59] */
+ int tm_hour; /* hours since midnight - [0,23] */
+ int tm_mday; /* day of the month - [1,31] */
+ int tm_mon; /* months since January - [0,11] */
+ int tm_year; /* years since 1900 */
+ int tm_wday; /* days since Sunday - [0,6] */
+ int tm_yday; /* days since January 1 - [0,365] */
+ int tm_isdst; /* daylight savings time flag */
+ };
+#define _TM_DEFINED
+#endif
+
+
+/* clock ticks macro - ANSI version */
+
+#define CLOCKS_PER_SEC 1000
+
+
+/* extern declarations for the global variables used by the ctime family of
+ * routines.
+ */
+
+#ifdef _DLL
+
+#define _daylight (*_daylight_dll)
+#define _timezone (*_timezone_dll)
+
+/* non-zero if daylight savings time is used */
+extern int * _CRTVAR1 _daylight_dll;
+
+/* difference in seconds between GMT and local time */
+extern long * _CRTVAR1 _timezone_dll;
+
+/* standard/daylight savings time zone names */
+extern char ** _CRTVAR1 _tzname;
+
+#else
+
+#ifdef CRTDLL
+#define _daylight _daylight_dll
+#define _timezone _timezone_dll
+#endif
+
+#ifdef _POSIX_
+extern char _CRTVAR1 * _rule;
+#endif
+
+/* non-zero if daylight savings time is used */
+extern int _CRTVAR1 _daylight;
+
+/* difference in seconds between GMT and local time */
+extern long _CRTVAR1 _timezone;
+
+/* standard/daylight savings time zone names */
+#ifdef _POSIX_
+extern char * _VARTYPE1 tzname[2];
+#else
+extern char * _VARTYPE1 _tzname[2];
+#endif
+
+#endif
+
+/* function prototypes */
+
+char * _CRTAPI1 asctime(const struct tm *);
+char * _CRTAPI1 ctime(const time_t *);
+clock_t _CRTAPI1 clock(void);
+double _CRTAPI1 difftime(time_t, time_t);
+struct tm * _CRTAPI1 gmtime(const time_t *);
+struct tm * _CRTAPI1 localtime(const time_t *);
+time_t _CRTAPI1 mktime(struct tm *);
+size_t _CRTAPI1 strftime(char *, size_t, const char *, const struct tm *);
+char * _CRTAPI1 _strdate(char *);
+char * _CRTAPI1 _strtime(char *);
+time_t _CRTAPI1 time(time_t *);
+#ifdef _POSIX_
+void _CRTAPI1 tzset(void);
+#else
+void _CRTAPI1 _tzset(void);
+#endif
+unsigned _CRTAPI1 _getsystime(struct tm *);
+unsigned _CRTAPI1 _setsystime(struct tm *, unsigned);
+
+#if !__STDC__
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+#ifndef _WTIME_DEFINED
+size_t _CRTAPI1 wcsftime(wchar_t *, size_t, const char *, const struct tm *);
+#define _WTIME_DEFINED
+#endif
+#endif /* __STDC__ */
+
+#if !__STDC__ || defined(_POSIX_)
+/* Non-ANSI names for compatibility */
+
+#define CLK_TCK CLOCKS_PER_SEC
+
+#define daylight _daylight
+/* timezone cannot be #defined to _timezone because of <sys/timeb.h> */
+
+#ifndef _POSIX_
+#define tzname _tzname
+
+#ifndef _DOSX32_
+#define tzset _tzset
+#else
+void _CRTAPI1 tzset(void);
+#endif
+#endif /* _POSIX_ */
+
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_TIME
+#endif /* _INC_TIME */
diff --git a/private/crt32/h/timeb.inc b/private/crt32/h/timeb.inc
new file mode 100644
index 000000000..1f36f85a1
--- /dev/null
+++ b/private/crt32/h/timeb.inc
@@ -0,0 +1,37 @@
+;***
+;timeb.inc - definition of the C Run-Time Library "timeb" structure
+;
+; Copyright (c) 1992-1993, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Analog of <sys/timeb.h> for assembler routines.
+;
+;Notes:
+; This file must reflect the structure "timeb" defined in <sys/timeb.h>
+; and is dependent on the alignment characteristics of the Intel 386;
+; namely, that words ("shorts") are aligned on even addresses and
+; dwords ("longs") are aligned on quad addresses.
+;
+; Important: MIPS follows the Intel 386 convention as well.
+;
+;Revision History:
+; 03-13-92 SKS Initial version
+; 06-08-93 SKS Cosmetic change - _tmzone becomes _timezone_
+; to match the corrected C source code naming.
+;
+;******************************************************************************
+
+;struct _timeb {
+; time_t time;
+; unsigned short millitm;
+; short tmzone;
+; short dstflag;
+; };
+
+_timeb STRUC
+ _time dd ?
+ _millitm dw ?
+ _timezone_ dw ?
+ _dstflag dw ?
+ __padding__ dw ? ; pad the structure out to
+_timeb ENDS ; an even number of DWORDs
diff --git a/private/crt32/h/v2tov3.h b/private/crt32/h/v2tov3.h
new file mode 100644
index 000000000..12b573f2e
--- /dev/null
+++ b/private/crt32/h/v2tov3.h
@@ -0,0 +1,74 @@
+/***
+*v2tov3.h - macros for porting MS C v.2 to v.3 and later
+*
+* Copyright (c) 1985-1990, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines macros which can be used to ease the problems
+* of porting MS C version 2.0 programs to MS C versions 3.0 and later.
+* [Internal]
+*
+*Revision History:
+* 08-15-89 GJF Fixed copyright
+* 10-30-89 GJF Fixed copyright (again)
+* 03-02-90 GJF Added #ifndef _INC_V2TOV3 stuff
+*
+****/
+
+#ifndef _INC_V2TOV3
+
+/* macro to translate the names used to force binary mode for files */
+
+#define O_RAW O_BINARY
+
+/* macro to translate setnbuf calls to the equivalent setbuf call */
+
+#define setnbuf(stream) setbuf(stream, NULL)
+
+/* macro to translate stclen calls to the equivalent strlen call */
+
+#define stclen(s) strlen(s)
+
+/* macro to translate stscmp calls to the equivalent strcmp call */
+
+#define stscmp(s,t) strcmp(s,t)
+
+/* macro to translate stpchr calls to the equivalent strchr call */
+
+#define stpchr(s,c) strchr(s,c)
+
+/* macro to translate stpbrk calls to the equivalent strpbrk call */
+
+#define stpbrk(s,b) strpbrk(s,b)
+
+/* macro to translate stcis calls to the equivalent strspn call */
+
+#define stcis(s1,s2) strspn(s1,s2)
+
+/* macro to translate stcisn calls to the equivalent strcspn call */
+
+#define stcisn(s1,s2) strcspn(s1,s2)
+
+/* macro to translate setmem calls to the equivalent memset call */
+
+#define setmem(p, n, c) memset(p, c, n)
+
+/* macro to translate movmem calls to the equivalent memcpy call */
+
+#define movmem(s, d, n) memcpy(d, s, n)
+
+/* MS C version 2.0 min, max, and abs macros */
+
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#define abs(a) (((a) < 0) ? -(a) : (a))
+
+/* macros which implement MS C version 2.0's extended ctype macros, iscym and
+ * iscysmf
+ */
+
+#define iscsymf(c) (isalpha(c) || ((c) == '_'))
+#define iscsym(c) (isalnum(c) || ((c) == '_'))
+
+#define _INC_V2TOV3
+#endif /* _INC_V2TOV3 */
diff --git a/private/crt32/h/varargs.h b/private/crt32/h/varargs.h
new file mode 100644
index 000000000..d38029e36
--- /dev/null
+++ b/private/crt32/h/varargs.h
@@ -0,0 +1,160 @@
+/***
+*varargs.h - XENIX style macros for variable argument functions
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines XENIX style macros for accessing arguments of a
+* function which takes a variable number of arguments.
+* [System V]
+*
+*Revision History:
+* 08-22-88 GJF Modified to also work for the 386 (small model only)
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 08-15-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 01-05-90 JCR Added NULL definition
+* 03-02-90 GJF Added #ifndef _INC_VARARGS stuff. Also, removed some
+* (now) useless preprocessor directives.
+* 05-29-90 GJF Replaced sizeof() with _INTSIZEOF() and revised the
+* va_arg() macro (fixes PTM 60)
+* 05-31-90 GJF Revised va_end() macro (propagated 5-25-90 change to
+* crt7 version by WAJ)
+* 01-24-91 JCR Generate an error on ANSI compilations
+* 08-20-91 JCR C++ and ANSI naming
+* 11-01-91 GDP MIPS Compiler support
+* 10-16-92 SKS Replaced "#ifdef i386" with "#ifdef _M_IX86".
+* 11-03-92 GJF Fixed several conditionals, dropped _DOSX32_ support.
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 10-04-93 SRW Fix ifdefs for MIPS and ALPHA to only check for _M_?????? defines
+*
+****/
+
+#ifndef _INC_VARARGS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __STDC__
+#error varargs.h incompatible with ANSI (use stdarg.h)
+#endif
+
+#ifndef _VA_LIST_DEFINED
+
+#ifdef _M_ALPHA
+typedef struct {
+ char *a0; /* pointer to first homed integer argument */
+ int offset; /* byte offset of next parameter */
+} va_list;
+#else
+typedef char *va_list;
+#endif
+
+#define _VA_LIST_DEFINED
+#endif
+
+#ifdef _M_ALPHA
+
+/*
+ * The Alpha compiler supports two builtin functions that are used to
+ * implement stdarg/varargs. The __builtin_va_start function is used
+ * by va_start to initialize the data structure that locates the next
+ * argument. The __builtin_isfloat function is used by va_arg to pick
+ * which part of the home area a given register argument is stored in.
+ * The home area is where up to six integer and/or six floating point
+ * register arguments are stored down (so they can also be referenced
+ * by a pointer like any arguments passed on the stack).
+ */
+
+#define va_dcl long va_alist;
+#define va_start(list) __builtin_va_start(list, va_alist, 0)
+#define va_end(list)
+#define va_arg(list, mode) \
+ ( *( ((list).offset += ((int)sizeof(mode) + 7) & -8) , \
+ (mode *)((list).a0 + (list).offset - \
+ ((__builtin_isfloat(mode) && (list).offset <= (6 * 8)) ? \
+ (6 * 8) + 8 : ((int)sizeof(mode) + 7) & -8) \
+ ) \
+ ) \
+ )
+
+#else
+
+#ifdef _WIN32_
+
+#ifdef _M_IX86
+/*
+ * define a macro to compute the size of a type, variable or expression,
+ * rounded up to the nearest multiple of sizeof(int). This number is its
+ * size as function argument (Intel architecture). Note that the macro
+ * depends on sizeof(int) being a power of 2!
+ */
+#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
+
+#define va_dcl va_list va_alist;
+#define va_start(ap) ap = (va_list)&va_alist
+#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
+#define va_end(ap) ap = (va_list)0
+
+#elif defined(_M_MRX000)
+
+#define va_dcl int va_alist;
+#define va_start(list) list = (char *) &va_alist
+#define va_end(list)
+#define va_arg(list, mode) ((mode *)(list =\
+ (char *) ((((int)list + (__builtin_alignof(mode)<=4?3:7)) &\
+ (__builtin_alignof(mode)<=4?-4:-8))+sizeof(mode))))[-1]
+/* +++++++++++++++++++++++++++++++++++++++++++
+ Because of parameter passing conventions in C:
+ use mode=int for char, and short types
+ use mode=double for float types
+ use a pointer for array types
+ +++++++++++++++++++++++++++++++++++++++++++ */
+
+#elif defined(_M_PPC)
+
+/*
+ * define a macro to compute the size of a type, variable or expression,
+ * rounded up to the nearest multiple of sizeof(int). This number is its
+ * size as function argument (PPC architecture). Note that the macro
+ * depends on sizeof(int) being a power of 2!
+ */
+/* this is for LITTLE-ENDIAN PowerPC */
+
+/* bytes that a type occupies in the argument list */
+#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
+/* return 'ap' adjusted for type 't' in arglist */
+#define _ALIGNIT(ap,t) \
+ ((((int)(ap))+(sizeof(t)<8?3:7)) & (sizeof(t)<8?~3:~7))
+
+#define va_dcl va_list va_alist;
+#define va_start(ap) ap = (va_list)&va_alist
+#define va_arg(ap,t) ( *(t *)((ap = (char *) (_ALIGNIT(ap, t) + _INTSIZEOF(t))) - _INTSIZEOF(t)) )
+#define va_end(ap) ap = (va_list)0
+
+#else
+
+/* A guess at the proper definitions for other platforms */
+
+#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
+
+#define va_dcl va_list va_alist;
+#define va_start(ap) ap = (va_list)&va_alist
+#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
+#define va_end(ap) ap = (va_list)0
+
+#endif // MIPS/X86/PPC
+
+#endif // __WIN32__
+
+#endif /* _M_ALPHA */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_VARARGS
+#endif /* _INC_VARARGS */
diff --git a/private/crt32/h/wchar.h b/private/crt32/h/wchar.h
new file mode 100644
index 000000000..8221eae95
--- /dev/null
+++ b/private/crt32/h/wchar.h
@@ -0,0 +1,352 @@
+/***
+*wchar.h - declarations for wide character functions
+*
+* Copyright (c) 1992-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the types, macros and function declarations for
+* all wide character-related functions. They may also be declared in
+* individual header files on a functional basis.
+* [ISO]
+*
+* Note: keep in sync with ctype.h, stdio.h, stdlib.h, string.h, time.h.
+*
+*Revision History:
+* 04-06-92 KRS Created.
+* 06-02-92 KRS Added stdio wprintf functions.
+* 06-16-92 KRS Added stdlib wcstol/wcstod functions.
+* 08-05-92 GJF Function calling type and variable type macros.
+* 08-18-92 KRS Added stdio wscanf functions, wcstok.
+* 09-04-92 GJF Merged changes from 8-5-92 on.
+* 01-03-93 SRW Fold in ALPHA changes
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 01-19-03 CFW Move to _NEWCTYPETABLE, remove switch.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 01-25-93 GJF Cosmetic change to va_list definition.
+* 02-17-93 CFW Removed incorrect UNDONE comment.
+* 02-18-93 CFW Clean up common _WCTYPE_DEFINED section.
+* 04-12-93 CFW Change isw* to evaluate args only once.
+* 04-29-93 CFW Add wide char get/put.
+* 04-30-93 CFW Fixed wide char get/put support.
+* 05-05-93 CFW Change is_wctype to iswctype as per ISO.
+* 05-10-93 CFW Remove uneeded _filwbuf, _flswbuf protos.
+* 06-02-93 CFW Wide get/put use wint_t.
+* 06-26-93 CFW Remove is_wctype macro.
+* 09-13-93 CFW Add _wtox and _xtow function prototypes.
+* 10-04-93 SRW Fix ifdefs for MIPS and ALPHA to only check for _M_?????? defines
+*
+****/
+
+#ifndef _INC_WCHAR
+#define _INC_WCHAR
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+#ifndef _WCTYPE_T_DEFINED
+typedef wchar_t wint_t;
+typedef wchar_t wctype_t;
+#define _WCTYPE_T_DEFINED
+#endif
+
+#ifndef _VA_LIST_DEFINED
+#ifdef _M_ALPHA
+typedef struct {
+ char *a0; /* pointer to first homed integer argument */
+ int offset; /* byte offset of next parameter */
+} va_list;
+#else
+typedef char * va_list;
+#endif
+#define _VA_LIST_DEFINED
+#endif
+
+#ifndef WEOF
+#define WEOF (wint_t)(0xFFFF)
+#endif
+
+#ifndef _FILE_DEFINED
+struct _iobuf {
+ char *_ptr;
+ int _cnt;
+ char *_base;
+ int _flag;
+ int _file;
+ int _charbuf;
+ int _bufsiz;
+ char *_tmpfname;
+ };
+typedef struct _iobuf FILE;
+#define _FILE_DEFINED
+#endif
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+/*
+ * This declaration allows the user access to the ctype look-up
+ * array _ctype defined in ctype.obj by simply including ctype.h
+ */
+
+#ifdef _DLL
+
+extern unsigned short * _CRTVAR1 _ctype;
+
+#define _pctype (*_pctype_dll)
+extern unsigned short **_pctype_dll;
+
+#define _pwctype (*_pwctype_dll)
+extern unsigned short **_pwctype_dll;
+
+#else /* _DLL */
+
+#ifdef CRTDLL
+#define _pctype _pctype_dll
+#define _pwctype _pwctype_dll
+#endif
+
+extern unsigned short _CRTVAR1 _ctype[];
+extern unsigned short *_pctype;
+extern wctype_t *_pwctype;
+
+#endif /* _DLL */
+
+/* set bit masks for the possible character types */
+
+#define _UPPER 0x1 /* upper case letter */
+#define _LOWER 0x2 /* lower case letter */
+#define _DIGIT 0x4 /* digit[0-9] */
+#define _SPACE 0x8 /* tab, carriage return, newline, */
+ /* vertical tab or form feed */
+#define _PUNCT 0x10 /* punctuation character */
+#define _CONTROL 0x20 /* control character */
+#define _BLANK 0x40 /* space char */
+#define _HEX 0x80 /* hexadecimal digit */
+
+#ifdef _INTL
+#define _LEADBYTE 0x8000 /* multibyte leadbyte */
+#define _ALPHA (0x0100|_UPPER|_LOWER) /* alphabetic character */
+#else
+#define _ALPHA (_UPPER|_LOWER) /* alphabetic character */
+#endif
+
+
+/* function prototypes */
+
+#ifndef _WCTYPE_DEFINED
+
+/* character classification function prototypes */
+/* also defined in ctype.h */
+
+int _CRTAPI1 iswalpha(wint_t);
+int _CRTAPI1 iswupper(wint_t);
+int _CRTAPI1 iswlower(wint_t);
+int _CRTAPI1 iswdigit(wint_t);
+int _CRTAPI1 iswxdigit(wint_t);
+int _CRTAPI1 iswspace(wint_t);
+int _CRTAPI1 iswpunct(wint_t);
+int _CRTAPI1 iswalnum(wint_t);
+int _CRTAPI1 iswprint(wint_t);
+int _CRTAPI1 iswgraph(wint_t);
+int _CRTAPI1 iswcntrl(wint_t);
+int _CRTAPI1 iswascii(wint_t);
+int _CRTAPI1 isleadbyte(int);
+
+wchar_t _CRTAPI1 towupper(wchar_t);
+wchar_t _CRTAPI1 towlower(wchar_t);
+
+int _CRTAPI1 iswctype(wint_t, wctype_t);
+
+#ifdef _INTL
+int _CRTAPI1 _isctype(int, int);
+#endif /* _INTL */
+
+#define _WCTYPE_DEFINED
+#endif
+
+#define iswalpha(_c) ( iswctype(_c,_ALPHA) )
+#define iswupper(_c) ( iswctype(_c,_UPPER) )
+#define iswlower(_c) ( iswctype(_c,_LOWER) )
+#define iswdigit(_c) ( iswctype(_c,_DIGIT) )
+#define iswxdigit(_c) ( iswctype(_c,_HEX) )
+#define iswspace(_c) ( iswctype(_c,_SPACE) )
+#define iswpunct(_c) ( iswctype(_c,_PUNCT) )
+#define iswalnum(_c) ( iswctype(_c,_ALPHA|_DIGIT) )
+#define iswprint(_c) ( iswctype(_c,_BLANK|_PUNCT|_ALPHA|_DIGIT) )
+#define iswgraph(_c) ( iswctype(_c,_PUNCT|_ALPHA|_DIGIT) )
+#define iswcntrl(_c) ( iswctype(_c,_CONTROL) )
+#define iswascii(_c) ( (unsigned)(_c) < 0x80 )
+
+#ifdef _INTL
+/* note: MS-specific routine, may evaluate its arguments more than once */
+#define isleadbyte(_c) ((_c) < 256 ? _pctype[_c] & _LEADBYTE : 0)
+#else
+#define isleadbyte(_c) (0)
+#endif /* _INTL */
+
+
+#ifndef _WSTDIO_DEFINED
+
+wint_t _CRTAPI1 fgetwc(FILE *);
+wint_t _CRTAPI1 _fgetwchar(void);
+wint_t _CRTAPI1 fputwc(wint_t, FILE *);
+wint_t _CRTAPI1 _fputwchar(wint_t);
+wint_t _CRTAPI1 getwc(FILE *);
+wint_t _CRTAPI1 getwchar(void);
+wint_t _CRTAPI1 putwc(wint_t, FILE *);
+wint_t _CRTAPI1 putwchar(wint_t);
+wint_t _CRTAPI1 ungetwc(wint_t, FILE *);
+
+int _CRTAPI2 fwprintf(FILE *, const wchar_t *, ...);
+int _CRTAPI2 wprintf(const wchar_t *, ...);
+int _CRTAPI2 _snwprintf(wchar_t *, size_t, const wchar_t *, ...);
+int _CRTAPI2 swprintf(wchar_t *, const wchar_t *, ...);
+int _CRTAPI1 vfwprintf(FILE *, const wchar_t *, va_list);
+int _CRTAPI1 vwprintf(const wchar_t *, va_list);
+int _CRTAPI1 _vsnwprintf(wchar_t *, size_t, const wchar_t *, va_list);
+int _CRTAPI1 vswprintf(wchar_t *, const wchar_t *, va_list);
+int _CRTAPI2 fwscanf(FILE *, const wchar_t *, ...);
+int _CRTAPI2 swscanf(const wchar_t *, const wchar_t *, ...);
+int _CRTAPI2 wscanf(const wchar_t *, ...);
+
+#define getwchar() fgetwc(stdin)
+#define putwchar(_c) fputwc((_c),stdout)
+#define getwc(_stm) fgetwc(_stm)
+#define putwc(_c,_stm) fputwc(_c,_stm)
+
+#ifdef MTHREAD /* _MTHREAD_ONLY */
+wint_t _CRTAPI1 _getwc_lk(FILE *); /* _MTHREAD_ONLY */
+wint_t _CRTAPI1 _putwc_lk(wint_t, FILE *); /* _MTHREAD_ONLY */
+wint_t _CRTAPI1 _ungetwc_lk(wint_t, FILE *); /* _MTHREAD_ONLY */
+ /* _MTHREAD_ONLY */
+#else /*MTHREAD */ /* _MTHREAD_ONLY */
+#define _getwc_lk(_stm) fgetwc(_stm) /* _MTHREAD_ONLY */
+#define _putwc_lk(_c,_stm) fputwc(_c,_stm) /* _MTHREAD_ONLY */
+#define _ungetwc_lk(_c,_stm) ungetwc(_c,_stm) /* _MTHREAD_ONLY */
+#endif /*MTHREAD */ /* _MTHREAD_ONLY */
+
+#define _WSTDIO_DEFINED
+#endif
+
+
+#ifndef _WSTDLIB_DEFINED
+/* also defined in stdlib.h */
+double _CRTAPI1 wcstod(const wchar_t *, wchar_t **);
+long _CRTAPI1 wcstol(const wchar_t *, wchar_t **, int);
+unsigned long _CRTAPI1 wcstoul(const wchar_t *, wchar_t **, int);
+wchar_t * _CRTAPI1 _itow (int val, wchar_t *buf, int radix);
+wchar_t * _CRTAPI1 _ltow (long val, wchar_t *buf, int radix);
+wchar_t * _CRTAPI1 _ultow (unsigned long val, wchar_t *buf, int radix);
+long _CRTAPI1 _wtol(const wchar_t *nptr);
+int _CRTAPI1 _wtoi(const wchar_t *nptr);
+#define _WSTDLIB_DEFINED
+#endif
+
+
+#ifndef _WSTRING_DEFINED
+wchar_t * _CRTAPI1 wcscat(wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcschr(const wchar_t *, wchar_t);
+int _CRTAPI1 wcscmp(const wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcscpy(wchar_t *, const wchar_t *);
+size_t _CRTAPI1 wcscspn(const wchar_t *, const wchar_t *);
+size_t _CRTAPI1 wcslen(const wchar_t *);
+wchar_t * _CRTAPI1 wcsncat(wchar_t *, const wchar_t *, size_t);
+int _CRTAPI1 wcsncmp(const wchar_t *, const wchar_t *, size_t);
+wchar_t * _CRTAPI1 wcsncpy(wchar_t *, const wchar_t *, size_t);
+wchar_t * _CRTAPI1 wcspbrk(const wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcsrchr(const wchar_t *, wchar_t);
+size_t _CRTAPI1 wcsspn(const wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcsstr(const wchar_t *, const wchar_t *);
+wchar_t * _CRTAPI1 wcstok(wchar_t *, const wchar_t *);
+
+wchar_t * _CRTAPI1 _wcsdup(const wchar_t *);
+int _CRTAPI1 _wcsicmp(const wchar_t *, const wchar_t *);
+int _CRTAPI1 _wcsnicmp(const wchar_t *, const wchar_t *, size_t);
+wchar_t * _CRTAPI1 _wcsnset(wchar_t *, wchar_t, size_t);
+wchar_t * _CRTAPI1 _wcsrev(wchar_t *);
+wchar_t * _CRTAPI1 _wcsset(wchar_t *, wchar_t);
+
+wchar_t * _CRTAPI1 _wcslwr(wchar_t *);
+wchar_t * _CRTAPI1 _wcsupr(wchar_t *);
+size_t _CRTAPI1 wcsxfrm(wchar_t *, const wchar_t *, size_t);
+int _CRTAPI1 wcscoll(const wchar_t *, const wchar_t *);
+int _CRTAPI1 _wcsicoll(const wchar_t *, const wchar_t *);
+
+/* old names */
+#define wcswcs wcsstr
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+#define wcsdup _wcsdup
+#define wcsicmp _wcsicmp
+#define wcsnicmp _wcsnicmp
+#define wcsnset _wcsnset
+#define wcsrev _wcsrev
+#define wcsset _wcsset
+#define wcslwr _wcslwr
+#define wcsupr _wcsupr
+#define wcsicoll _wcsicoll
+#endif
+
+#define _WSTRING_DEFINED
+#endif
+
+
+#ifndef _WTIME_DEFINED
+size_t _CRTAPI1 wcsftime(wchar_t *, size_t, const char *, const struct tm *);
+#define _WTIME_DEFINED
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _INC_WCHAR */
diff --git a/private/crt32/h/winheap.h b/private/crt32/h/winheap.h
new file mode 100644
index 000000000..c636ad103
--- /dev/null
+++ b/private/crt32/h/winheap.h
@@ -0,0 +1,25 @@
+/***
+* winheap.h - Private include file for winheap directory.
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains information needed by the C library heap code.
+* [Internal]
+*
+*Revision History:
+* 10-01-92 SRW Created.
+* 10-28-92 SRW Change winheap code to call Heap????Ex calls
+* 11-05-92 SKS Change name of variable "CrtHeap" to "_crtheap"
+* 11-07-92 SRW _NTIDW340 replaced by linkopts\betacmp.c
+* 02-23-93 SKS Update copyright to 1993
+*
+*******************************************************************************/
+
+#ifndef _INC_HEAP
+#define _INC_HEAP
+
+#include <windows.h>
+extern HANDLE _crtheap;
+
+#endif // _INC_HEAP
diff --git a/private/crt32/hack/makefile b/private/crt32/hack/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/hack/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/hack/sources b/private/crt32/hack/sources
new file mode 100644
index 000000000..656c001d7
--- /dev/null
+++ b/private/crt32/hack/sources
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=hack
+
+TARGETNAME=hack
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=stubs.c
diff --git a/private/crt32/hack/stubs.c b/private/crt32/hack/stubs.c
new file mode 100644
index 000000000..deec7ae30
--- /dev/null
+++ b/private/crt32/hack/stubs.c
@@ -0,0 +1,42 @@
+/***
+*stubs.c - extdef stubs
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module resolves external references made by the libs
+* in the "non-SYSCALL" version (i.e., the stripped down library
+* that has only routines that don't make system calls).
+*
+*Revision History:
+* ??-??-?? SRW initial version
+* 09-29-91 JCR added _read (ANSI-compatible symbol)
+* 09-04-92 GJF replaced _CALLTYPE3 with WINAPI
+* 06-02-92 SRW added errno definition
+* 06-15-92 SRW __mb_cur_max supplied by ..\misc\nlsdata1.obj
+* 07-16-93 SRW ALPHA Merge
+* 11-04-93 SRW _getbuf and ungetc now work in _NTSUBSET_ version
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+
+//
+// referenced by crt (output)
+//
+
+int _fltused = 0x9875;
+int _ldused = 0x9873;
+int __fastflag = 0;
+int _iob;
+char _osfile[20];
+int errno;
+
+void fflush( void ){}
+void fprintf( void ){}
+void abort( void ){}
+void read( void ){}
+void _read( void ){}
+void _assert( void ) {}
+void _amsg_exit( void ) {}
diff --git a/private/crt32/heap/calloc.c b/private/crt32/heap/calloc.c
new file mode 100644
index 000000000..1dba04cd2
--- /dev/null
+++ b/private/crt32/heap/calloc.c
@@ -0,0 +1,88 @@
+/***
+*calloc.c - allocate storage for an array from the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the calloc() function.
+*
+*Revision History:
+* 07-25-89 GJF Module created
+* 11-13-89 GJF Added MTHREAD support. Also fixed copyright and got
+* rid of DEBUG286 stuff.
+* 12-04-89 GJF Renamed header file (now heap.h). Added register
+* declarations
+* 12-18-89 GJF Added explicit _cdecl to function definition
+* 03-09-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 09-27-90 GJF New-style function declarator.
+* 05-28-91 GJF Tuned a bit.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stddef.h>
+
+
+/***
+*void *calloc(size_t num, size_t size) - allocate storage for an array from
+* the heap
+*
+*Purpose:
+* Allocate a block of memory from heap big enough for an array of num
+* elements of size bytes each, initialize all bytes in the block to 0
+* and return a pointer to it.
+*
+*Entry:
+* size_t num - number of elements in the array
+* size_t size - size of each element
+*
+*Exit:
+* Success: void pointer to allocated block block
+* Failure: NULL
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 calloc (
+ size_t num,
+ size_t size
+ )
+{
+ void *retptr;
+ REG1 size_t *startptr;
+ REG2 size_t *lastptr;
+
+ /* lock the heap
+ */
+ _mlock(_HEAP_LOCK);
+
+ /* try to malloc the requested space
+ */
+ retptr = _malloc_lk(num *= size);
+
+ /* if malloc() succeeded, initialize the allocated space to zeros.
+ * note the assumptions that the size of the allocation block is an
+ * integral number of sizeof(size_t) bytes and that (size_t)0 is
+ * sizeof(size_t) bytes of 0.
+ */
+ if ( retptr != NULL ) {
+ startptr = (size_t *)retptr;
+ lastptr = startptr + ((num + sizeof(size_t) - 1) /
+ sizeof(size_t));
+ while ( startptr < lastptr )
+ *(startptr++) = 0;
+ }
+
+ /* release the heap lock
+ */
+ _munlock(_HEAP_LOCK);
+
+ return(retptr);
+}
diff --git a/private/crt32/heap/delete.cxx b/private/crt32/heap/delete.cxx
new file mode 100644
index 000000000..bc2d73e7a
--- /dev/null
+++ b/private/crt32/heap/delete.cxx
@@ -0,0 +1,28 @@
+/***
+*delete.cxx - defines C++ delete routine
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines C++ delete routine.
+*
+*Revision History:
+* 05-07-90 WAJ Initial version.
+* 08-30-90 WAJ new now takes unsigned ints.
+* 08-08-91 JCR call _halloc/_hfree, not halloc/hfree
+* 08-13-91 KRS Change new.hxx to new.h. Fix copyright.
+* 08-13-91 JCR ANSI-compatible _set_new_handler names
+* 10-30-91 JCR Split new, delete, and handler into seperate sources
+* 11-13-91 JCR 32-bit version
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <new.h>
+
+
+void operator delete( void * p )
+{
+ free( p );
+}
diff --git a/private/crt32/heap/findaddr.c b/private/crt32/heap/findaddr.c
new file mode 100644
index 000000000..d7e9c699c
--- /dev/null
+++ b/private/crt32/heap/findaddr.c
@@ -0,0 +1,108 @@
+/***
+*findaddr.c - Find a heap entry
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the _heap_findaddr routine
+*
+*Revision History:
+* 07-06-89 JCR Module created.
+* 07-18-89 JCR Return -1 if nothing in heap
+* 11-13-89 GJF Fixed copyright
+* 12-04-89 GJF Renamed header file (now heap.h). Also, some tuning.
+* 12-18-89 GJF Added explicit _cdecl to function definition
+* 03-09-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 09-27-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <stddef.h>
+
+#define TRUE 1
+
+/***
+*int _heap_findaddr() - Find a heap entry
+*
+*Purpose:
+* Given an address, find the corresponding heap entry.
+*
+*Entry:
+* void * address = address to look for
+* PBLKDESC * ppdesc = pointer to pointer to heap descriptor to be
+* filled in by this routine.
+*
+*Exit:
+*
+* _HEAPFIND_EXACT = 0 = exact fit, pdesc holds heap descriptor address
+* _HEAPFIND_WITHIN = 1 = not exact fit, pdesc holds previous heap
+* descriptor address
+*
+* _HEAPFIND_BEFORE = -1 = address is before the heap (pdesc NOT filled in)
+* _HEAPFIND_AFTER = -2 = address is after the heap (pdesc NOT filled in)
+* _HEAPFIND_EMPTY = -3 = no memory in heap (pdesc NOT filled in)
+*
+* [If return is negative, supplied pdesc is NOT filled in.]
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heap_findaddr (
+ void * address,
+ _PBLKDESC * ppdesc
+ )
+{
+ REG1 _PBLKDESC pcurr;
+
+ /*
+ * See if heap there's anything in the heap
+ */
+
+ if (_heap_desc.pfirstdesc == &_heap_desc.sentinel)
+ return(_HEAPFIND_EMPTY);
+
+ /*
+ * See if entry is in the heap or not
+ */
+
+ if (_ADDRESS(_heap_desc.pfirstdesc) > address)
+ return(_HEAPFIND_BEFORE);
+
+ if (_ADDRESS(&_heap_desc.sentinel) <= address)
+ return(_HEAPFIND_AFTER);
+
+ /*
+ * Find the entry
+ */
+
+#ifdef DEBUG
+ for (pcurr = _heap_desc.pfirstdesc; pcurr != &_heap_desc.sentinel;
+ pcurr = pcurr->pnextdesc) {
+#else
+ for (pcurr = _heap_desc.pfirstdesc; TRUE; pcurr = pcurr->pnextdesc) {
+#endif
+
+ if ( _ADDRESS(pcurr->pnextdesc) > address ) {
+
+ /* Address is contained in this entry */
+ *ppdesc = pcurr;
+
+ /* Check for an exact fit */
+ if ( _ADDRESS(pcurr) == address)
+ return(_HEAPFIND_EXACT);
+ else
+ return(_HEAPFIND_WITHIN);
+ }
+ }
+
+#ifdef DEBUG
+ /* Should never reach here! */
+ _heap_abort();
+#endif
+}
diff --git a/private/crt32/heap/free.c b/private/crt32/heap/free.c
new file mode 100644
index 000000000..44e44475a
--- /dev/null
+++ b/private/crt32/heap/free.c
@@ -0,0 +1,171 @@
+/***
+*free.c - free an entry in the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the following functions:
+* free() - free a memory block in the heap
+* _free_lk() - non-locking from of free() (multi-thread only)
+*
+*Revision History:
+* 06-30-89 JCR Module created
+* 07-07-89 GJF Fixed test for resetting proverdesc
+* 11-10-89 GJF Added MTHREAD support. Also, a little cleanup.
+* 12-18-89 GJF Change header file name to heap.h, added register
+* declarations and added explicit _cdecl to function
+* definitions
+* 03-09-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 09-27-90 GJF New-style function declarators. Also, rewrote expr.
+* so that a cast was not used as an lvalue.
+* 03-05-91 GJF Changed strategy for rover - old version available
+* by #define-ing _OLDROVER_.
+* 04-08-91 GJF Temporary hack for Win32/DOS folks - special version
+* of free that just calls HeapFree. Change conditioned
+* on _WIN32DOS_.
+*
+*******************************************************************************/
+
+#ifndef _WIN32DOS_
+
+#include <cruntime.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stdlib.h>
+
+/***
+*void free(pblock) - free a block in the heap
+*
+*Purpose:
+* Free a memory block in the heap.
+*
+* Special Notes For Multi-thread: The non-multi-thread version is renamed
+* to _free_lk(). The multi-thread free() simply locks the heap, calls
+* _free_lk(), then unlocks the heap and returns.
+*
+*Entry:
+* void *pblock - pointer to a memory block in the heap
+*
+*Return:
+* <void>
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+void _CALLTYPE1 free (
+ void *pblck
+ )
+{
+ /* lock the heap
+ */
+ _mlock(_HEAP_LOCK);
+
+ /* free the block
+ */
+ _free_lk(pblck);
+
+ /* unlock the heap
+ */
+ _munlock(_HEAP_LOCK);
+}
+
+
+/***
+*void _free_lk(pblock) - non-locking form of free
+*
+*Purpose:
+* Same as free() except that no locking is performed
+*
+*Entry:
+* See free
+*
+*Return:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _free_lk (
+
+#else /* ndef MTHREAD */
+
+void _CALLTYPE1 free (
+
+#endif /* MTHREAD */
+
+ REG1 void *pblck
+ )
+{
+ REG2 _PBLKDESC pdesc;
+
+ /*
+ * If the pointer is NULL, just return [ANSI].
+ */
+
+ if (pblck == NULL)
+ return;
+
+ /*
+ * Point to block header and get the pointer back to the heap desc.
+ */
+
+ pblck = (char *)pblck - _HDRSIZE;
+ pdesc = *(_PBLKDESC*)pblck;
+
+ /*
+ * Validate the back pointer.
+ */
+
+ if (_ADDRESS(pdesc) != pblck)
+ _heap_abort();
+
+ /*
+ * Pointer is ok. Mark block free.
+ */
+
+ _SET_FREE(pdesc);
+
+ /*
+ * Back up rover pointer, if appropriate.
+ */
+#ifdef _OLDROVER_
+
+ if (_heap_desc.proverdesc->pblock > pdesc->pblock)
+ _heap_desc.proverdesc = pdesc;
+
+#else /* ndef _OLDROVER_ */
+
+ if ( (_heap_resetsize != 0xffffffff) &&
+ (_heap_desc.proverdesc->pblock > pdesc->pblock) &&
+ (_BLKSIZE(pdesc) >= _heap_resetsize) )
+ _heap_desc.proverdesc = pdesc;
+
+#endif /* _OLDROVER_ */
+
+}
+
+
+#else /* _WIN32DOS_ */
+
+/*
+ * TEMPORARY HACK! THE CODE BELOW IS INTENDED TO ALLOW LIMITED USE OF THE
+ * C RUNTIME ON WIN32/DOS. IT WILL BE DELETED AS SOON AS THEY IMPLEMENT
+ * VirtualAlloc()!
+ */
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <malloc.h>
+
+extern HANDLE _HeapHandle;
+
+void _CALLTYPE1 free (
+ void *pblck
+ )
+{
+ HeapFree(_HeapHandle, pblck);
+ return;
+}
+
+#endif /* _WIN32DOS_ */
diff --git a/private/crt32/heap/handler.cxx b/private/crt32/heap/handler.cxx
new file mode 100644
index 000000000..91db57522
--- /dev/null
+++ b/private/crt32/heap/handler.cxx
@@ -0,0 +1,53 @@
+/***
+*handler.cxx - defines C++ setHandler routine
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines C++ setHandler routine.
+*
+*Revision History:
+* 05-07-90 WAJ Initial version.
+* 08-30-90 WAJ new now takes unsigned ints.
+* 08-08-91 JCR call _halloc/_hfree, not halloc/hfree
+* 08-13-91 KRS Change new.hxx to new.h. Fix copyright.
+* 08-13-91 JCR ANSI-compatible _set_new_handler names
+* 10-30-91 JCR Split new, delete, and handler into seperate sources
+* 11-13-91 JCR 32-bit version
+* 06-15-92 KRS Break MTHREAD support for NT BETA
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <os2dll.h>
+#include <new.h>
+
+/* Warning! MTHREAD is broken! */
+/* Warning! MTHREAD is broken! */
+/* Warning! MTHREAD is broken! */
+
+/* #ifndef MTHREAD */
+/* pointer to C++ new handler */
+extern "C" _PNH _pnhHeap;
+/* #endif */
+
+_PNH _set_new_handler( _PNH pnh )
+{
+_PNH pnhOld;
+
+/* #ifdef MTHREAD
+
+ _pptiddata tdata;
+ tdata = _getptd();
+ pnhOld = ((*tdata)->_tpnhHeap);
+ ((*tdata)->_tpnhHeap) = pnh;
+
+#else */ /* ndef MTHREAD */
+
+ pnhOld = _pnhHeap;
+ _pnhHeap = pnh;
+
+/* #endif */
+
+ return(pnhOld);
+}
diff --git a/private/crt32/heap/heapadd.c b/private/crt32/heap/heapadd.c
new file mode 100644
index 000000000..587e4cb1e
--- /dev/null
+++ b/private/crt32/heap/heapadd.c
@@ -0,0 +1,413 @@
+/***
+*heapadd.c - Add a block of memory to the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Add a block of memory to the heap.
+*
+*Revision History:
+* 07-07-89 JCR Module created.
+* 07-20-89 JCR Re-use dummy descriptor on exact fit (dummy collection)
+* 11-09-89 JCR Corrected plastdesc updating code
+* 11-13-89 GJF Added MTHREAD support, also fixed copyright
+* 11-15-89 JCR Minor improvement (got rid of a local variable)
+* 11-16-89 JCR Bug fix - squirrly case in _HEAPFIND_EXACT
+* 12-04-89 GJF A little tuning and cleanup. Also, changed header file
+* name to heap.h.
+* 12-18-89 GJF Removed DEBUG286 stuff. Also, added explicit _cdecl to
+* function definitions.
+* 12-19-89 GJF Removed references and uses of plastdesc (revising
+* code as necessary)
+* 03-09-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-29-90 GJF Made _before() _CALLTYPE4.
+* 07-24-90 SBM Compiles cleanly with -W3 (tentatively removed
+* unreferenced label)
+* 09-27-90 GJF New-style function declarators.
+* 03-05-91 GJF Changed strategy for rover - old version available
+* by #define-ing _OLDROVER_.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stdlib.h>
+
+static void _CALLTYPE4 _before(_PBLKDESC, size_t, _PBLKDESC);
+
+/***
+*int _heapadd(block, size) - Add a block of memory to the heap
+*
+*Purpose:
+* Add a block of user memory the heap.
+*
+* NOTE: The reason for the level of indirection between _heapadd
+* and _heap_addblock is (1) to validate the input, and (2) for
+* mthread locking/unlocking purposes.
+*
+* NOTE: _heapadd() DOES NOT enter the block of memory into the region
+* table! This is the cleanest way to avoid nasty bugs such as attempting
+* to grow, shrink or free static memory (e.g., a block that started out
+* being a static array). If the memory block does in fact belong in the
+* region table, it is the caller's responsibility to do it (internal
+* routines only, user programs should NEVER do this).
+*
+*Entry:
+* void * block = block of memory
+* size_t size = size of memory block
+*
+*Exit:
+* 0 = success
+* -1 = failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heapadd (
+ void * block,
+ size_t size
+ )
+{
+ int retval;
+
+ /*
+ * Validate user's input
+ */
+
+ if ( (size == 0) ||
+ ((unsigned)block & (sizeof(int)-1)) ||
+ (size & (sizeof(int)-1))
+ )
+ return(-1);
+
+ /*
+ * Add the block to the heap.
+ */
+
+ _mlock(_HEAP_LOCK);
+ retval = _heap_addblock(block, size);
+ _munlock(_HEAP_LOCK);
+
+ return(retval);
+
+}
+
+
+/***
+*int _heap_addblock(block, size) - Add a block of memory to the heap
+*
+*Purpose:
+* Add a block of memory to the heap.
+*
+* Notes:
+* (1) Must handle case where new memory is already in heap
+* (i.e., could be the address of a previous 'dummy' entry).
+*
+*Entry:
+* void * block = address of memory block
+* size_t size = size of memory block
+*
+*Exit:
+* 0 = success
+* -1 = failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heap_addblock (
+ void * block,
+ size_t size
+ )
+{
+ _PBLKDESC pdesc;
+ REG1 _PBLKDESC pnewdesc;
+ size_t lastsize;
+ int find;
+
+
+ /*
+ * Find where the address fits into the heap.
+ */
+
+ find = _heap_findaddr(block, &pdesc);
+
+
+ /*
+ * Fill in the new heap descriptor.
+ * (1) If the new address is an exact fit, use the dummy
+ * descriptor that already exists for it.
+ * (2) If the address is NOT in the heap, allocate a new one.
+ */
+
+ if (find == _HEAPFIND_EXACT) {
+
+ if (!(_IS_DUMMY(pdesc)))
+ goto error1;
+
+ pnewdesc = pdesc;
+ }
+
+ else {
+ _GETEMPTY(pnewdesc);
+ }
+
+ pnewdesc->pblock = block; /* pointer to block */
+ _SET_FREE(pnewdesc); /* set me free (why don't ya, babe) */
+ *(_PBLKDESC*)block = pnewdesc; /* init back pointer */
+
+
+ /*
+ * Put the block in the heap
+ * find = result of _heap_findaddr() call
+ * pnewdesc = points to desc to be inserted
+ * pdesc = filled in by _heap_findaddr() call as appropriate
+ */
+
+ switch (find) {
+
+
+ case(_HEAPFIND_EMPTY):
+
+ /*
+ * No memory in heap yet
+ */
+
+ _heap_desc.sentinel.pblock = (char *) block + size;
+ _before(pnewdesc, size, &_heap_desc.sentinel);
+
+ _heap_desc.pfirstdesc = _heap_desc.proverdesc =
+ pnewdesc;
+
+ break;
+
+
+ case(_HEAPFIND_BEFORE):
+
+ /*
+ * New block is before the heap
+ */
+
+ _before(pnewdesc, size, _heap_desc.pfirstdesc);
+ _heap_desc.pfirstdesc = pnewdesc;
+ break;
+
+
+ case(_HEAPFIND_AFTER):
+
+ /*
+ * New block is after the heap
+ *
+ * Find the current last block in the heap
+ */
+
+ if ( _heap_findaddr((void *)((char *)
+ (_heap_desc.sentinel.pblock) - 1), &pdesc) !=
+ _HEAPFIND_WITHIN )
+ _heap_abort();
+
+ lastsize = _MEMSIZE(pdesc);
+
+ /*
+ * Start insertion by placing new block immediately
+ * in front of the sentinel
+ */
+
+ _heap_desc.sentinel.pblock = (char *) block + size;
+ pnewdesc->pnextdesc = &_heap_desc.sentinel;
+
+ /*
+ * Finish insertion by placing new block after the
+ * old last block (with a possible intervening dummy
+ * block being created)
+ */
+
+ _before(pdesc, lastsize, pnewdesc);
+ break;
+
+
+ case(_HEAPFIND_EXACT):
+
+ /*
+ * Block is already in the heap (and we've checked
+ * that it was a "dummy" before this call).
+ *
+ * [NOTES: (1) pnewdesc and pdesc are the same,
+ * (2) pnewdesc is already linked to the previous
+ * heap entry, (3) pdesc->pnextdesc is still valid!
+ * (4) Also, if pdesc->pnextdesc is the sentinel,
+ * then simply update the sentinel size (calling
+ * before will cause an error if the previous last
+ * block was bigger than the current one!).
+ * (see code at top of this routine).]
+ */
+
+ if (pdesc->pnextdesc == &_heap_desc.sentinel)
+
+ _heap_desc.sentinel.pblock =
+ (char *) _ADDRESS(pdesc) + size;
+
+ else
+ _before(pnewdesc, size, pdesc->pnextdesc);
+
+ break;
+
+#ifdef DEBUG
+ case(_HEAPFIND_WITHIN):
+#else
+ default:
+#endif
+ /*
+ * New block is within heap
+ */
+
+ if (!(_IS_DUMMY(pdesc)))
+ goto error0;
+
+ _before(pnewdesc, size, pdesc->pnextdesc);
+ _before(pdesc, _MEMSIZE(pdesc), pnewdesc);
+ break;
+
+#ifdef DEBUG
+ /*
+ * Return value unknown -- abort!
+ */
+
+ default:
+ _heap_abort();
+#endif
+
+ }
+
+ /*
+ * Update rover, if appropriate
+ */
+#ifdef _OLDROVER_
+
+ if (block < _ADDRESS(_heap_desc.proverdesc))
+ _heap_desc.proverdesc = pnewdesc;
+
+#else /* ndef _OLDROVER_ */
+
+ if ( (block < _ADDRESS(_heap_desc.proverdesc)) &&
+ (_BLKSIZE(pnewdesc) >= _heap_resetsize) )
+ _heap_desc.proverdesc = pnewdesc;
+
+#endif /* _OLDROVER_ */
+
+ /*
+ * Good return
+ */
+
+ /* good: unreferenced label to be removed */
+ return(0);
+
+ /*
+ * Error return
+ */
+
+ error0:
+ _PUTEMPTY(pnewdesc);
+ error1:
+ return(-1);
+
+}
+
+
+/***
+*static void _before(pdesc1, size, pdesc2) - Insert a block before a
+* supplied descriptor
+*
+*Purpose:
+* This routine inserts a new descriptor before
+* another descriptor.
+*
+* Notes:
+* (1) A dummy descriptor will be inserted into the heap as
+* necessary.
+* (2) This routine only updates FORWARD links. Call this
+* routine twice to update links in both directions.
+*
+*Entry:
+* _PBLKDESC pdesc1 = new descriptor to insert in the heap
+* size_t size = size of pdesc1 block
+* _PBLKDESC pdesc2 = descriptor before which block should go
+*
+*Exit:
+* (void)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CALLTYPE4 _before (
+ REG1 _PBLKDESC pdesc1,
+ size_t size,
+ REG2 _PBLKDESC pdesc2
+ )
+{
+ size_t diff;
+ _PBLKDESC pdummydesc;
+ void * dummyaddr;
+
+ /*
+ * Check for dummy descriptors:
+ * (1) If first block is dummy, no adjustement needed.
+ * (2) If second block is dummy, simply adjust size.
+ */
+
+ if (_IS_DUMMY(pdesc1))
+ goto link;
+
+ if (_IS_DUMMY(pdesc2)) {
+ pdesc2->pblock = (char *)_ADDRESS(pdesc1) + size;
+ _SET_DUMMY(pdesc2);
+ goto link;
+ }
+
+
+ /*
+ * See how much space is between this block and the next one.
+ */
+
+ diff = ( (char *) _ADDRESS(pdesc2) -
+ (char *) (dummyaddr = (char *) _ADDRESS(pdesc1) + size) );
+
+ if (diff != 0) {
+
+#ifdef DEBUG
+ /*
+ * Internal bogosity check
+ */
+
+ if ((int)diff < 0)
+ _heap_abort();
+#endif
+ /*
+ * There is some space between the two blocks. Insert
+ * a fake "in use" block. Remember, there is no 'back
+ * pointer' in dummy blocks.
+ */
+
+ _GETEMPTY(pdummydesc);
+
+ pdummydesc->pblock = (char *) dummyaddr;
+ _SET_DUMMY(pdummydesc);
+
+ pdesc1->pnextdesc = pdummydesc;
+ pdesc1 = pdummydesc;
+
+ }
+
+ /*
+ * Put the new block in the heap.
+ */
+
+ link:
+ pdesc1->pnextdesc = pdesc2;
+
+}
diff --git a/private/crt32/heap/heapchk.c b/private/crt32/heap/heapchk.c
new file mode 100644
index 000000000..872b124d5
--- /dev/null
+++ b/private/crt32/heap/heapchk.c
@@ -0,0 +1,330 @@
+/***
+*heapchk.c - perform a consistency check on the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the _heapchk() and _heapset() functions
+*
+*Revision History:
+* 06-30-89 JCR Module created.
+* 07-28-89 GJF Added check for free block preceding the rover
+* 11-13-89 GJF Added MTHREAD support, also fixed copyright
+* 12-13-89 GJF Added check for descriptor order, did some tuning,
+* changed header file name to heap.h
+* 12-15-89 GJF Purged DEBUG286 stuff. Also added explicit _cdecl to
+* function definitions.
+* 12-19-89 GJF Got rid of checks involving plastdesc (revised check
+* of proverdesc and DEBUG errors accordingly)
+* 03-09-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-29-90 GJF Made _heap_checkset() _CALLTYPE4.
+* 09-27-90 GJF New-style function declarators.
+* 03-05-91 GJF Changed strategy for rover - old version available
+* by #define-ing _OLDROVER_.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stddef.h>
+#include <string.h>
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+static int _CALLTYPE4 _heap_checkset(unsigned int _fill);
+
+/* Debug error values */
+#define _EMPTYHEAP 0
+#define _BADROVER 1
+#define _BADRANGE 2
+#define _BADSENTINEL 3
+#define _BADEMPTY 4
+#define _EMPTYLOOP 5
+#define _BADFREE 6
+#define _BADORDER 7
+
+#ifdef DEBUG
+
+static char *errmsgs[] = {
+ "_heap_desc.pfirstdesc == NULL",
+ "_heap_desc.proverdesc not found in desc list",
+ "address is outside the heap",
+ "sentinel descriptor corrupted",
+ "empty desc pblock != NULL (debug version)",
+ "header ptr found twice in emptylist",
+ "free block precedes rover",
+ "adjacent descriptors in reverse order from heap blocks"
+ };
+
+#define _PRINTERR(msg) \
+ printf("\n*** HEAP ERROR: %s ***\n", errmsgs[(msg)]); \
+ fflush(stdout);
+
+#else /* !DEBUG */
+
+#define _PRINTERR(msg)
+
+#endif /* DEBUG */
+
+
+/***
+*int _heapchk() - Validate the heap
+*int _heapset(_fill) - Validate the heap and fill in free entries
+*
+*Purpose:
+* Performs a consistency check on the heap.
+*
+*Entry:
+* For heapchk()
+* No arguments
+* For heapset()
+* int _fill - value to be used as filler in free entries
+*
+*Exit:
+* Returns one of the following values:
+*
+* _HEAPOK - completed okay
+* _HEAPEMPTY - heap not initialized
+* _HEAPBADBEGIN - can't find initial header info
+* _HEAPBADNODE - malformed node somewhere
+*
+* Debug version prints out a diagnostic message if an error is found
+* (see errmsg[] above).
+*
+* NOTE: Add code to support memory regions.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heapchk(void)
+{
+ return(_heap_checkset((unsigned int)_HEAP_NOFILL));
+}
+
+/******************************************************************************/
+
+int _CALLTYPE1 _heapset (
+ unsigned int _fill
+ )
+{
+ return(_heap_checkset(_fill));
+}
+
+
+/***
+*static int _heap_checkset(_fill) - check the heap and fill in the
+* free entries
+*
+*Purpose:
+* Workhorse routine for both _heapchk() and _heapset().
+*
+*Entry:
+* int _fill - either _HEAP_NOFILL or a value to be used as filler in
+* free entries
+*
+*Exit:
+* See description of _heapchk()/_heapset()
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 _heap_checkset (
+ unsigned int _fill
+ )
+{
+ REG1 _PBLKDESC pdesc;
+ REG2 _PBLKDESC pnext;
+ int roverfound=0;
+ int retval = _HEAPOK;
+
+ /*
+ * lock the heap
+ */
+
+ _mlock(_HEAP_LOCK);
+
+ /*
+ * Validate the sentinel
+ */
+
+ if (_heap_desc.sentinel.pnextdesc != NULL) {
+ _PRINTERR(_BADSENTINEL);
+ retval = _HEAPBADNODE;
+ goto done;
+ }
+
+ /*
+ * Test for an empty heap
+ */
+
+ if ( (_heap_desc.pfirstdesc == &_heap_desc.sentinel) &&
+ (_heap_desc.proverdesc == &_heap_desc.sentinel) ) {
+ retval = _HEAPEMPTY;
+ goto done;
+ }
+
+ /*
+ * Get and validate the first descriptor
+ */
+
+ if ((pdesc = _heap_desc.pfirstdesc) == NULL) {
+ _PRINTERR(_EMPTYHEAP);
+ retval = _HEAPBADBEGIN;
+ goto done;
+ }
+
+ /*
+ * Walk the heap descriptor list
+ */
+
+ while (pdesc != &_heap_desc.sentinel) {
+
+ /*
+ * Make sure address for this entry is in range.
+ */
+
+ if ( (_ADDRESS(pdesc) < _ADDRESS(_heap_desc.pfirstdesc)) ||
+ (_ADDRESS(pdesc) > _heap_desc.sentinel.pblock) ) {
+ _PRINTERR(_BADRANGE);
+ retval = _HEAPBADNODE;
+ goto done;
+ }
+
+ pnext = pdesc->pnextdesc;
+
+ /*
+ * Make sure the blocks corresponding to pdesc and pnext are
+ * in proper order.
+ */
+
+ if ( _ADDRESS(pdesc) >= _ADDRESS(pnext) ) {
+ _PRINTERR(_BADORDER);
+ retval = _HEAPBADNODE;
+ goto done;
+ }
+
+ /*
+ * Check the backpointer.
+ */
+
+ if (_IS_INUSE(pdesc) || _IS_FREE(pdesc)) {
+
+ if (!_CHECK_PDESC(pdesc)) {
+ retval = _HEAPBADPTR;
+ goto done;
+ }
+ }
+
+ /*
+ * Check for proverdesc
+ */
+
+ if (pdesc == _heap_desc.proverdesc)
+ roverfound++;
+
+#ifdef _OLDROVER_
+
+ /*
+ * If it is free, make sure it doesn't precede the rover
+ * block and fill it in if appropriate
+ */
+
+ if ( _IS_FREE(pdesc) ) {
+
+ if ( roverfound == 0 ) {
+ _PRINTERR(_BADFREE);
+ retval = _HEAPBADNODE;
+ goto done;
+ }
+
+ if ( _fill != _HEAP_NOFILL )
+ memset( (void *)((unsigned)_ADDRESS(pdesc)+_HDRSIZE),
+ _fill, _BLKSIZE(pdesc) );
+ }
+
+#else /* ndef _OLDROVER_ */
+
+ /*
+ * If it is free, fill it in if appropriate
+ */
+
+ if ( _IS_FREE(pdesc) && (_fill != _HEAP_NOFILL) )
+ memset( (void *)((unsigned)_ADDRESS(pdesc)+_HDRSIZE),
+ _fill, _BLKSIZE(pdesc) );
+
+#endif /* _OLDROVER_ */
+
+ /*
+ * Onto the next block
+ */
+
+ pdesc = pnext;
+ }
+
+ /*
+ * Make sure we found 1 and only 1 rover
+ */
+
+ if (_heap_desc.proverdesc == &_heap_desc.sentinel)
+ roverfound++;
+
+ if (roverfound != 1) {
+ _PRINTERR(_BADROVER);
+ retval = _HEAPBADBEGIN;
+ goto done;
+ }
+
+ /*
+ * Walk the empty list. We can't really compare values against
+ * anything but we may loop forever or may cause a fault.
+ */
+
+ pdesc = _heap_desc.emptylist;
+
+ while (pdesc != NULL) {
+
+#ifdef DEBUG
+ if (pdesc->pblock != NULL) {
+ _PRINTERR(_BADEMPTY)
+ retval = _HEAPBADPTR;
+ goto done;
+ }
+#endif
+
+ pnext = pdesc->pnextdesc;
+
+ /*
+ * Header should only appear once
+ */
+
+ if (pnext == _heap_desc.emptylist) {
+ _PRINTERR(_EMPTYLOOP)
+ retval = _HEAPBADPTR;
+ goto done;
+ }
+
+ pdesc = pnext;
+
+ }
+
+
+ /*
+ * Common return
+ */
+
+done:
+ /*
+ * release the heap lock
+ */
+
+ _munlock(_HEAP_LOCK);
+
+ return(retval);
+
+}
diff --git a/private/crt32/heap/heapdump.c b/private/crt32/heap/heapdump.c
new file mode 100644
index 000000000..1255b44c8
--- /dev/null
+++ b/private/crt32/heap/heapdump.c
@@ -0,0 +1,334 @@
+/***
+*heapdump.c - Output the heap data bases
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Display the heap data bases.
+*
+* NOTE: This module is NOT released with the C libs. It is for
+* debugging purposes only.
+*
+*Revision History:
+* 06-28-89 JCR Module created.
+* 07-18-89 JCR Added _heap_print_regions() routine
+* 11-13-89 GJF Added MTHREAD support, also fixed copyright
+* 12-13-89 GJF Changed name of include file to heap.h
+* 12-19-89 GJF Removed references to plastdesc
+* 03-11-90 GJF Made the calling type _CALLTYPE1 and added #include
+* <cruntime.h>.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stdio.h>
+
+#ifdef DEBUG
+
+/***
+*_heap_print_all - Print the whole heap
+*
+*Purpose:
+*
+*Entry:
+* <void>
+*
+*Exit:
+* <void>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _heap_print_all(void)
+{
+ /* lock the heap
+ */
+ _mlock(_HEAP_LOCK);
+
+ _heap_print_regions_lk();
+ _heap_print_desc_lk();
+ _heap_print_emptylist_lk();
+ _heap_print_heaplist_lk();
+
+ /* release the heap lock
+ */
+ _munlock(_HEAP_LOCK);
+}
+
+
+/***
+*_heap_print_regions - Print the heap region table
+*
+*Purpose:
+*
+*Entry:
+* <void>
+*
+*Exit:
+* <void>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+void _CALLTYPE1 _heap_print_regions(void)
+{
+ /* lock the heap
+ */
+ _mlock(_HEAP_LOCK);
+
+ _heap_print_regions_lk();
+
+ /* release the heap lock
+ */
+ _munlock(_HEAP_LOCK);
+}
+
+void _CALLTYPE1 _heap_print_regions_lk(void)
+
+#else /* ndef MTHREAD */
+
+void _CALLTYPE1 _heap_print_regions(void)
+
+#endif /* MTHREAD */
+{
+ int i;
+
+ printf("\n--- Heap Regions ---\n\n");
+
+ printf("\t_heap_growsize (_amblksiz) = \t%x\n", _heap_growsize);
+ printf("\t_heap_regionsize = \t%x\n\n", _heap_regionsize);
+
+ printf("\t_regbase\t_currsize\t_totalsize\n");
+ printf("\t--------\t---------\t----------\n");
+ for (i=0; i < _HEAP_REGIONMAX; i++) {
+ printf("\t%x\t\t%x\t\t%x\n",
+ _heap_regions[i]._regbase,
+ _heap_regions[i]._currsize,
+ _heap_regions[i]._totalsize);
+ }
+}
+
+
+/***
+*_heap_print_desc - Print the heap descriptor
+*
+*Purpose:
+*
+*Entry:
+* <void>
+*
+*Exit:
+* <void>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+void _CALLTYPE1 _heap_print_desc(void)
+{
+ _mlock(_HEAP_LOCK);
+
+ _heap_print_desc_lk();
+
+ _munlock(_HEAP_LOCK);
+}
+
+void _CALLTYPE1 _heap_print_desc_lk(void)
+
+#else /* ndef MTHREAD */
+
+void _CALLTYPE1 _heap_print_desc(void)
+
+#endif /* MTHREAD */
+{
+
+ printf("\n--- Heap Descriptor ---\n\n");
+ printf("\tpfirstdesc = %p\n", _heap_desc.pfirstdesc);
+ printf("\tproverdesc = %p\n", _heap_desc.proverdesc);
+ printf("\temptylist = %p\n", _heap_desc.emptylist);
+ printf("\t&sentinel = %p\n", &(_heap_desc.sentinel));
+
+}
+
+
+/***
+*_heap_print_emptylist - Print out the empty heap desc list
+*
+*Purpose:
+*
+*Entry:
+* <void>
+*
+*Exit:
+* <void>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+void _CALLTYPE1 _heap_print_emptylist(void)
+{
+ /* lock the heap
+ */
+ _mlock(_HEAP_LOCK);
+
+ _heap_print_emptylist_lk();
+
+ /* release the heap lock
+ */
+ _munlock(_HEAP_LOCK);
+}
+
+void _CALLTYPE1 _heap_print_emptylist_lk(void)
+
+#else /* ndef MTHREAD */
+
+void _CALLTYPE1 _heap_print_emptylist(void)
+
+#endif /* MTHREAD */
+{
+
+ _PBLKDESC p;
+ int i;
+
+ printf("\n--- Heap Empty Descriptor List ---\n\n");
+
+ if ((p = _heap_desc.emptylist) == NULL) {
+ printf("\t *** List is empty ***\n");
+ return;
+ }
+
+ for (i=1; p != NULL; p=p->pnextdesc, i++) {
+
+ printf("\t(%i) Address = %p\n", i, p);
+ printf("\t\tpnextdesc = %p, pblock = %p\n\n",
+ p->pnextdesc, p->pblock);
+
+ }
+
+ printf("\t--- End of table ---\n");
+
+}
+
+
+/***
+*_heap_print_heaplist - Print out the heap desc list
+*
+*Purpose:
+*
+*Entry:
+* <void>
+*
+*Exit:
+* <void>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+void _CALLTYPE1 _heap_print_heaplist(void)
+{
+ /* lock the heap
+ */
+ _mlock(_HEAP_LOCK);
+
+ _heap_print_heaplist_lk();
+
+ /* release the heap lock
+ */
+ _munlock(_HEAP_LOCK);
+}
+
+void _CALLTYPE1 _heap_print_heaplist_lk(void)
+
+#else /* ndef MTHREAD */
+
+void _CALLTYPE1 _heap_print_heaplist(void)
+
+#endif /* MTHREAD */
+{
+
+ _PBLKDESC p;
+ _PBLKDESC next;
+ int i;
+ int error = 0;
+
+ printf("\n--- Heap Descriptor List ---\n\n");
+
+ if ((p = _heap_desc.pfirstdesc) == NULL) {
+ printf("\t *** List is empty ***\n");
+ return;
+ }
+
+ for (i=1; p != NULL; i++) {
+
+ next = p->pnextdesc;
+
+ /* Print descriptor address */
+
+ printf("\t(%i) Address = %p ", i, p);
+
+ if (p == &_heap_desc.sentinel)
+ printf("<SENTINEL>\n");
+ else if (p == _heap_desc.proverdesc)
+ printf("<ROVER>\n");
+ else
+ printf("\n");
+
+
+
+ /* Print descriptor contents */
+
+ printf("\t\tpnextdesc = %p, pblock = %p",
+ p->pnextdesc, p->pblock);
+
+ if (p == &_heap_desc.sentinel) {
+ if (next != NULL) {
+ printf("\n\t*** ERROR: sentinel.pnextdesc != NULL ***\n");
+ error++;
+ }
+ }
+ else if (_IS_INUSE(p))
+ printf(", usersize = %u <INUSE>", _BLKSIZE(p));
+
+ else if (_IS_FREE(p))
+ printf(", usersize = %u <FREE>", _BLKSIZE(p));
+
+ else if (_IS_DUMMY(p))
+ printf(", size = %u <DUMMY>", _MEMSIZE(p));
+
+ else {
+ printf(",\n\t*** ERROR: unknown status ***\n");
+ error++;
+ }
+
+ printf("\n\n");
+
+ if (_heap_desc.pfirstdesc == &_heap_desc.sentinel) {
+ printf("[No memory in heap]\n");
+ }
+
+ p = next;
+ }
+
+ if (error)
+ printf("\n\t *** ERRORS IN HEAP TABLE ***\n");
+
+ printf("\t--- End of table ---\n");
+
+}
+
+#endif /* DEBUG */
diff --git a/private/crt32/heap/heapgrow.c b/private/crt32/heap/heapgrow.c
new file mode 100644
index 000000000..a9bdb7b59
--- /dev/null
+++ b/private/crt32/heap/heapgrow.c
@@ -0,0 +1,490 @@
+/***
+*heapgrow.c - Grow the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Get memory from OS and add to the heap.
+*
+*Revision History:
+* 06-06-89 JCR Module created.
+* 07-19-89 JCR Added region support
+* 11-07-89 JCR Region table is no longer "packed"
+* 11-08-89 JCR Use new _ROUND/_ROUND2 macros
+* 11-10-89 JCR Don't abort on ERROR_NOT_ENOUGH_MEMORY
+* 11-13-89 GJF Fixed copyright
+* 12-18-89 GJF Removed DEBUG286 stuff, a little tuning, cleaned up
+* the formatting a bit, changed header file name to
+* heap.h, also added _cdecl to functions (that didn't
+* already have explicit calling type)
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-29-90 GJF Made _heap_new_region() _CALLTYPE4.
+* 07-24-90 SBM Compiles cleanly with -W3 (tentatively removed
+* unreferenced labels), removed '32' from API names
+* 09-28-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 02-01-91 SRW Changed for new VirtualAlloc interface (_WIN32_)
+* 04-09-91 PNT Added _MAC_ conditional
+* 04-26-91 SRW Removed level 3 warnings
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <heap.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+static int _CALLTYPE4 _heap_new_region(unsigned, size_t);
+
+
+/***
+*_heap_grow() - Grow the heap
+*
+*Purpose:
+* Get memory from the OS and add it to the heap.
+*
+*Entry:
+* size_t _size = user's block request
+*
+*Exit:
+* 0 = success, new mem is in the heap
+* -1 = failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heap_grow (
+ REG1 size_t size
+ )
+{
+ REG2 int index;
+ int free_entry = -1;
+
+ /*
+ * Bump size to include header and round to nearest page boundary.
+ */
+
+ size += _HDRSIZE;
+ size = _ROUND2(size,_PAGESIZE_);
+
+ /*
+ * Loop through the region table looking for an existing region
+ * we can grow. Remember the index of the first null region entry.
+ *
+ * size = size of grow request
+ */
+
+ for (index = 0; index < _HEAP_REGIONMAX; index++) {
+
+ if ( (_heap_regions[index]._totalsize -
+ _heap_regions[index]._currsize) >= size )
+
+ /*
+ * Grow this region to satisfy the request.
+ */
+
+ return( _heap_grow_region(index, size) );
+
+
+ if ( (free_entry == -1) &&
+ (_heap_regions[index]._regbase == NULL) )
+
+ /*
+ * Remember 1st free table entry for later
+ */
+
+ free_entry = index;
+
+ }
+
+ /*
+ * Could not find any existing regions to grow. Try to
+ * get a new region.
+ *
+ * size = size of grow request
+ * free_entry = index of first free entry in table
+ */
+
+ if ( free_entry >= 0 )
+
+ /*
+ * Get a new region to satisfy the request.
+ */
+
+ return( _heap_new_region(free_entry, size) );
+
+ else
+ /*
+ * No free table entries: return an error.
+ */
+
+ return(-1);
+
+}
+
+
+/***
+*_heap_new_region() - Get a new heap region
+*
+*Purpose:
+* Get a new heap region and put it in the region table.
+* Also, grow it large enough to support the caller's
+* request.
+*
+* NOTES:
+* (1) Caller has verified that there is room in the _heap_region
+* table for another region.
+* (2) The caller must have rounded the size to a page boundary.
+*
+*Entry:
+* int index = index in table where new region data should go
+* size_t size = size of request (this has been rounded to a
+* page-sized boundary)
+*
+*Exit:
+* 0 = success
+* -1 = failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 _heap_new_region (
+ REG1 unsigned index,
+ size_t size
+ )
+{
+ void * region;
+ REG2 unsigned int regsize;
+
+#ifdef DEBUG
+
+ int i;
+
+ /*
+ * Make sure the size has been rounded to a page boundary
+ */
+
+ if (size & (_PAGESIZE_-1))
+ _heap_abort();
+
+ /*
+ * Make sure there's a free slot in the table
+ */
+
+ for (i=0; i < _HEAP_REGIONMAX; i++) {
+ if (_heap_regions[i]._regbase == NULL)
+ break;
+ }
+
+ if (i >= _HEAP_REGIONMAX)
+ _heap_abort();
+
+#endif
+
+ /*
+ * Round the heap region size to a page boundary (in case
+ * the user played with it).
+ */
+
+ regsize = _ROUND2(_heap_regionsize, _PAGESIZE_);
+
+ /*
+ * See if region is big enough for request
+ */
+
+ if (regsize < size)
+ regsize = size;
+
+ /*
+ * Go get the new region
+ */
+
+#ifdef _CRUISER_
+
+ if ( DOSALLOCMEM(&region, regsize, _NEWREGION, 0) != 0)
+ goto error;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (!(region = VirtualAlloc(NULL, regsize, MEM_RESERVE,
+ PAGE_READWRITE)))
+ goto error;
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+ /*
+ * Put the new region in the table.
+ */
+
+ _heap_regions[index]._regbase = region;
+ _heap_regions[index]._totalsize = regsize;
+ _heap_regions[index]._currsize = 0;
+
+
+ /*
+ * Grow the region to satisfy the size request.
+ */
+
+ if (_heap_grow_region(index, size) != 0) {
+
+ /*
+ * Ouch. Allocated a region but couldn't commit
+ * any pages in it. Free region and return error.
+ */
+
+ _heap_free_region(index);
+ goto error;
+ }
+
+
+ /*
+ * Good return
+ */
+
+ /* done: unreferenced label to be removed */
+ return(0);
+
+ /*
+ * Error return
+ */
+
+ error:
+ return(-1);
+
+}
+
+
+/***
+*_heap_grow_region() - Grow a heap region
+*
+*Purpose:
+* Grow a region and add the new memory to the heap.
+*
+* NOTES:
+* (1) The caller must have rounded the size to a page boundary.
+*
+*Entry:
+* unsigned index = index of region in the _heap_regions[] table
+* size_t size = size of request (this has been rounded to a
+* page-sized boundary)
+*
+*Exit:
+* 0 = success
+* -1 = failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heap_grow_region (
+ REG1 unsigned index,
+ size_t size
+ )
+{
+ size_t left;
+ REG2 size_t growsize;
+ void * base;
+ unsigned dosretval;
+
+
+ /*
+ * Init some variables
+ * left = space left in region
+ * base = base of next section of region to validate
+ */
+
+ left = _heap_regions[index]._totalsize -
+ _heap_regions[index]._currsize;
+
+ base = (char *) _heap_regions[index]._regbase +
+ _heap_regions[index]._currsize;
+
+ /*
+ * Make sure we can satisfy request
+ */
+
+ if (left < size)
+ goto error;
+
+ /*
+ * Round size up to next _heap_growsize boundary.
+ * (Must round _heap_growsize itself to page boundary, in
+ * case user set it himself).
+ */
+
+ growsize = _ROUND2(_heap_growsize, _PAGESIZE_);
+ growsize = _ROUND(size, growsize);
+
+ if (left < growsize)
+ growsize = left;
+
+ /*
+ * Validate the new portion of the region
+ */
+
+#ifdef _CRUISER_
+
+ dosretval = DOSSETMEM(base, growsize, _COMMIT);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (!VirtualAlloc(base, growsize, MEM_COMMIT, PAGE_READWRITE))
+ dosretval = GetLastError();
+ else
+ dosretval = 0;
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ if (dosretval)
+ /*
+ * Error committing pages. If out of memory, return
+ * error, else abort.
+ */
+
+ if (dosretval == ERROR_NOT_ENOUGH_MEMORY)
+ goto error;
+ else
+ _heap_abort();
+
+
+ /*
+ * Update the region data base
+ */
+
+ _heap_regions[index]._currsize += growsize;
+
+
+#ifdef DEBUG
+ /*
+ * The current size should never be greater than the total size
+ */
+
+ if (_heap_regions[index]._currsize > _heap_regions[index]._totalsize)
+ _heap_abort();
+#endif
+
+
+ /*
+ * Add the memory to the heap
+ */
+
+ if (_heap_addblock(base, growsize) != 0)
+ _heap_abort();
+
+
+ /*
+ * Good return
+ */
+
+ /* done: unreferenced label to be removed */
+ return(0);
+
+ /*
+ * Error return
+ */
+
+ error:
+ return(-1);
+
+}
+
+
+/***
+*_heap_free_region() - Free up a region
+*
+*Purpose:
+* Return a heap region to the OS and zero out
+* corresponding region data entry.
+*
+*Entry:
+* int index = index of region to be freed
+*
+*Exit:
+* void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _heap_free_region (
+ REG1 int index
+ )
+{
+
+ /*
+ * Give the memory back to the OS
+ */
+
+#ifdef _CRUISER_
+
+ if (DOSFREEMEM(_heap_regions[index]._regbase))
+ _heap_abort();
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (!VirtualFree(_heap_regions[index]._regbase, 0, MEM_RELEASE))
+ _heap_abort();
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /*
+ * Zero out the heap region entry
+ */
+
+ _heap_regions[index]._regbase = NULL;
+ _heap_regions[index]._currsize =
+ _heap_regions[index]._totalsize = 0;
+
+}
diff --git a/private/crt32/heap/heapinit.c b/private/crt32/heap/heapinit.c
new file mode 100644
index 000000000..6658596fe
--- /dev/null
+++ b/private/crt32/heap/heapinit.c
@@ -0,0 +1,266 @@
+/***
+*heapinit.c - Initialze the heap
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 06-28-89 JCR Module created.
+* 06-30-89 JCR Added _heap_grow_emptylist
+* 11-13-89 GJF Fixed copyright
+* 11-15-89 JCR Moved _heap_abort routine to another module
+* 12-15-89 GJF Removed DEBUG286 stuff, did some tuning, changed header
+* file name to heap.h and made functions explicitly
+* _cdecl.
+* 12-19-89 GJF Removed plastdesc field from _heap_desc_ struct
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-24-90 SBM Removed '32' from API names
+* 10-03-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 02-01-91 SRW Changed for new VirtualAlloc interface (_WIN32_)
+* 03-05-91 GJF Added definition of _heap_resetsize (conditioned on
+* _OLDROVER_ not being #define-d).
+* 04-04-91 GJF Reduce _heap_regionsize to 1/2 a meg for Dosx32
+* (_WIN32_).
+* 04-05-91 GJF Temporary hack for Win32/DOS folks - special version
+* of _heap_init which calls HeapCreate. The change
+* conditioned on _WIN32DOS_.
+* 04-09-91 PNT Added _MAC_ conditional
+* 02-23-93 SKS Remove DOSX32 support under WIN32 ifdef
+*
+*******************************************************************************/
+
+#ifndef _WIN32DOS_
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <dos.h>
+#include <heap.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#define _HEAP_EMPTYLIST_SIZE (1 * _PAGESIZE_)
+
+/*
+ * Heap descriptor
+ */
+
+struct _heap_desc_ _heap_desc = {
+ &_heap_desc.sentinel, /* pfirstdesc */
+ &_heap_desc.sentinel, /* proverdesc */
+ NULL, /* emptylist */
+ NULL, /* sentinel.pnextdesc */
+ NULL /* sentinel.pblock */
+ };
+
+/*
+ * Array of region structures
+ * [Note: We count on the fact that this is always initialized to zero
+ * by the compiler.]
+ */
+
+struct _heap_region_ _heap_regions[_HEAP_REGIONMAX];
+
+/*
+ * Control parameter locations
+ */
+
+#ifndef _OLDROVER_
+unsigned int _heap_resetsize = 0xffffffff;
+#endif /* _OLDROVER_ */
+
+/* NOTE: Currenlty, _heap_growsize is a #define to _amblksiz */
+unsigned int _heap_growsize = _HEAP_GROWSIZE; /* region inc size */
+unsigned int _heap_regionsize = _HEAP_REGIONSIZE; /* region size */
+
+
+/***
+*_heap_init() - Initialize the heap
+*
+*Purpose:
+* Setup the initial C library heap. All necessary memory and
+* data bases are init'd appropriately so future requests work
+* correctly.
+*
+* NOTES:
+* (1) This routine should only be called once!
+* (2) This routine must be called before any other heap requests.
+*
+*
+*Entry:
+* <void>
+*Exit:
+* <void>
+*
+*Exceptions:
+* If heap cannot be initialized, the program will be terminated
+* with a fatal runtime error.
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _heap_init (
+ void
+ )
+{
+#ifdef _CRUISER_
+
+ /*
+ * Currently nothing to do to init the 386 heap!!!
+ * If this stays true, we can get rid of the _heapinit call
+ * in startup and remove this module!
+ */
+
+#else /* ndef _CRUISER*/
+
+#ifdef _WIN32_
+
+ /*
+ * Currently nothing to do to init the 386 heap!!!
+ * If this stays true, we can get rid of the _heapinit call
+ * in startup and remove this module!
+ */
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
+
+
+
+/***
+* _heap_grow_emptylist() - Grow the empty heap descriptor list
+*
+*Purpose:
+* (1) Get memory from OS
+* (2) Form it into a linked list of empty heap descriptors
+* (3) Attach it to the master empty list
+*
+* NOTE: This routine assumes that the emptylist is NULL
+* when called (i.e., there are no available empty heap descriptors).
+*
+*Entry:
+* (void)
+*
+*Exit:
+* (void)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _heap_grow_emptylist (
+ void
+ )
+{
+ REG1 _PBLKDESC first;
+ REG2 _PBLKDESC next;
+ _PBLKDESC last;
+
+
+ /*
+ * Get memory for the new empty heap descriptors
+ *
+ * Note that last is used to hold the returned pointer because
+ * first (and next) are register class.
+ */
+
+#ifdef _CRUISER_
+
+ if ( DOSALLOCMEM(&last, _HEAP_EMPTYLIST_SIZE, _COMMIT, 0) != 0 )
+ _heap_abort();
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (!(last = VirtualAlloc(NULL, _HEAP_EMPTYLIST_SIZE, MEM_COMMIT,
+ PAGE_READWRITE)))
+ _heap_abort();
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /*
+ * Init the empty heap descriptor list.
+ */
+
+ _heap_desc.emptylist = first = last;
+
+
+ /*
+ * Carve the memory into an empty list
+ */
+
+ last = (_PBLKDESC) ((char *) first + _HEAP_EMPTYLIST_SIZE - sizeof(_BLKDESC));
+ next = (_PBLKDESC) ((char *) first + sizeof(_BLKDESC));
+
+ while ( first < last ) {
+
+ /* Init this descriptor */
+#ifdef DEBUG
+ first->pblock = NULL;
+#endif
+ first->pnextdesc = next;
+
+ /* onto the next block */
+
+ first = next++;
+
+ }
+
+ /*
+ * Take care of the last descriptor (end of the empty list)
+ */
+
+ last->pnextdesc = NULL;
+
+#ifdef DEBUG
+ last->pblock = NULL;
+#endif
+
+}
+
+#else /* _WIN32DOS_ */
+
+/*
+ * TEMPORARY HACK! THE CODE BELOW IS INTENDED TO ALLOW LIMITED USE OF THE
+ * C RUNTIME ON WIN32/DOS. IT WILL BE DELETED AS SOON AS THEY IMPLEMENT
+ * VirtualAlloc()!
+ */
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <heap.h>
+
+HANDLE _HeapHandle;
+
+void _CALLTYPE1 _heap_init (
+ void
+ )
+{
+ if ( (_HeapHandle = HeapCreate(HEAP_SERIALIZE, 0x10000, 0)) == NULL )
+ _heap_abort();
+}
+
+#endif /* _WIN32DOS_ */
diff --git a/private/crt32/heap/heapmin.c b/private/crt32/heap/heapmin.c
new file mode 100644
index 000000000..dade55a47
--- /dev/null
+++ b/private/crt32/heap/heapmin.c
@@ -0,0 +1,520 @@
+/***
+*heapmin.c - Minimize the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Minimize the heap freeing as much memory as possible back
+* to the OS.
+*
+*Revision History:
+* 08-28-89 JCR Module created.
+* 11-06-89 JCR Improved, partitioned
+* 11-13-89 GJF Added MTHREAD support, also fixed copyright
+* 12-14-89 GJF Couple of bug fixes, some tuning, cleaned up the
+* formatting a bit and changed header file name to
+* heap.h
+* 12-20-89 GJF Removed references to plastdesc
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-29-90 GJF Made _heapmin_region() and _free_partial_region()
+* _CALLTYPE4.
+* 07-24-90 SBM Compiles cleanly with -W3 (tentatively removed
+* unreferenced labels and unreachable code), removed
+* '32' from API names
+* 09-28-90 GJF New-style function declarators. Also, rewrote expr.
+* to avoid using cast as lvalue.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 03-05-91 GJF Changed strategy for rover - old version available
+* by #define-ing _OLDROVER_.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stdlib.h>
+
+static int _CALLTYPE4 _heapmin_region(int, void *, _PBLKDESC);
+static void _CALLTYPE4 _free_partial_region(_PBLKDESC, unsigned, int);
+
+
+/***
+*_heapmin() - Minimize the heap
+*
+*Purpose:
+* Minimize the heap freeing as much memory as possible back
+* to the OS.
+*
+*Entry:
+* (void)
+*
+*Exit:
+*
+* 0 = no error has occurred
+* -1 = an error has occurred (errno is set)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heapmin(void)
+{
+ REG1 int index;
+ _PBLKDESC pdesc;
+
+#ifdef _OLDROVER_
+ REG2 _PBLKDESC pprev;
+#else /* ndef _OLDROVER_ */
+ REG2 _PBLKDESC pdesc2;
+#endif /* _OLDROVER_ */
+
+ void * regend;
+ int region_min_count = 0;
+
+ /*
+ * Lock the heap
+ */
+
+ _mlock(_HEAP_LOCK);
+
+ /*
+ * Coalesce the heap (should return NULL)
+ */
+
+ if ( _heap_search(_HEAP_COALESCE) != NULL )
+ _heap_abort();
+
+ /*
+ * Loop through the region descriptor table freeing as much
+ * memory to the OS as possible.
+ */
+
+ for ( index=0 ; index < _HEAP_REGIONMAX ; index++ ) {
+
+ if ( _heap_regions[index]._regbase == NULL )
+ continue; /* region entry is empty */
+
+ /*
+ * Get the entry that contains the last address of
+ * the region (allocated so far, that is).
+ */
+
+ regend = (char *) _heap_regions[index]._regbase +
+ _heap_regions[index]._currsize - 1;
+
+ if ( _heap_findaddr(regend, &pdesc) != _HEAPFIND_WITHIN )
+ _heap_abort(); /* last address not within a block */
+
+ /*
+ * See if the containing block is free
+ */
+
+ if ( !(_IS_FREE(pdesc)) )
+ continue; /* block is not free */
+
+
+ /*
+ * Region ends with a free block, go free as much mem
+ * as possible.
+ */
+
+ region_min_count += _heapmin_region(index, regend, pdesc);
+
+
+ } /* region loop */
+
+ /*
+ * By minimizing the heap, we've likely invalidated the rover and
+ * may have produced contiguous dummy blocks so:
+ *
+ * (1) reset the rover
+ * (2) coalesce contiguous dummy blocks
+ */
+
+ if ( region_min_count ) {
+
+#ifdef _OLDROVER_
+
+ for ( _heap_desc.proverdesc = pprev = pdesc =
+ _heap_desc.pfirstdesc ; pdesc != &_heap_desc.sentinel ;
+ pprev = pdesc, pdesc = pdesc->pnextdesc ) {
+
+ /*
+ * set rover to first free block
+ */
+
+ if ( _IS_FREE(pdesc) &&
+ !_IS_FREE(_heap_desc.proverdesc) )
+ _heap_desc.proverdesc = pdesc;
+
+ /*
+ * Check and remove consecutive dummy blocks
+ */
+
+ if ( _IS_DUMMY(pprev) ) {
+
+ while ( _IS_DUMMY(pdesc) ) {
+
+ /*
+ * be sure that pdesc and pprev are
+ * not the same (i.e., not both equal
+ * to pfirstdesc)
+ */
+
+ if ( pdesc == pprev )
+ break;
+
+ /*
+ * coalesce the dummy blocks
+ */
+
+ pprev->pnextdesc = pdesc->pnextdesc;
+ _PUTEMPTY(pdesc);
+
+ /*
+ * advance pdesc and check for the
+ * sentinel
+ */
+
+ if ( (pdesc = pprev->pnextdesc)
+ == &_heap_desc.sentinel )
+ goto endloop;
+
+ } /* dummy loop */
+
+ } /* if */
+
+ } /* heap loop */
+
+ /*
+ * If still necessary, reset the rover descriptor pointer
+ */
+
+ endloop:
+
+ if ( !_IS_FREE(_heap_desc.proverdesc) )
+ _heap_desc.proverdesc = &_heap_desc.sentinel;
+
+#else /* ndef _OLDROVER_ */
+
+ /*
+ * Set proverdesc to pfirstdesc
+ */
+
+ _heap_desc.proverdesc = _heap_desc.pfirstdesc;
+
+ for ( pdesc = _heap_desc.pfirstdesc ; pdesc !=
+ &_heap_desc.sentinel ; pdesc = pdesc->pnextdesc ) {
+
+ /*
+ * Check and remove consecutive dummy blocks
+ */
+
+ if ( _IS_DUMMY(pdesc) ) {
+
+ for ( pdesc2 = pdesc->pnextdesc ;
+ _IS_DUMMY(pdesc2) ;
+ pdesc2 = pdesc->pnextdesc ) {
+
+ /*
+ * coalesce the dummy blocks
+ */
+
+ pdesc->pnextdesc = pdesc2->pnextdesc;
+ _PUTEMPTY(pdesc2);
+
+ } /* dummy loop */
+
+ } /* if */
+
+ } /* heap loop */
+
+#endif /* _OLDROVER_ */
+
+ } /* region_min_count */
+
+ /*
+ * Good return
+ */
+
+ /* goodrtn: unreferenced label to be removed */
+ /*
+ * Release the heap lock
+ */
+
+ _munlock(_HEAP_LOCK);
+
+ return(0);
+
+#if 0
+ /* unreachable code tentatively removed */
+
+ /*
+ * Error return
+ */
+
+ errrtn:
+ /*
+ * Release the heap lock
+ */
+
+ _munlock(_HEAP_LOCK);
+
+ /* *** SET ERRNO *** */
+ return(-1);
+#endif
+}
+
+
+/***
+*_heapmin_region() - Minimize a region
+*
+*Purpose:
+* Free as much of a region back to the OS as possible.
+*
+*Entry:
+* int index = index of the region in the region table
+* void * regend = last valid address in region
+* pdesc = pointer to the last block of memory in the region
+* (it has already been determined that this block is free)
+*
+*Exit:
+* int 1 = minimized region
+* 0 = no change to region
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 _heapmin_region (
+ int index,
+ void * regend,
+ REG1 _PBLKDESC pdesc
+ )
+{
+ unsigned size;
+ REG2 _PBLKDESC pnew;
+
+
+ /*
+ * Init some variables
+ *
+ * regend = 1st address AFTER region
+ * size = amount of free memory at end of current region
+ */
+
+ regend = (char *) regend + 1; /* "regend++" give compiler error... */
+ size = ((char *)regend - (char *)_ADDRESS(pdesc));
+
+
+ /*
+ * See if there's enough free memory to release to the OS.
+ * (NOTE: Need more than a page since we may need a back pointer.)
+ */
+
+ if ( size <= _PAGESIZE_ )
+ return(0); /* 0 = no change to region */
+
+ /*
+ * We're going to free some memory to the OS. See if the
+ * free block crosses the end of the region and, if so,
+ * split up the block appropriately.
+ */
+
+ if ( (_MEMSIZE(pdesc) - size) != 0 ) {
+
+ /*
+ * The free block spans the end of the region.
+ * Divide it up.
+ */
+
+ _GETEMPTY(pnew); /* get a new block */
+
+ pnew->pblock = regend; /* init block pointer */
+ * (_PBLKDESC*)regend = pnew; /* init back pointer */
+ _SET_FREE(pnew); /* set the block free */
+
+ pnew->pnextdesc = pdesc->pnextdesc; /* link it in */
+ pdesc->pnextdesc = pnew;
+
+ }
+
+
+ /*
+ * At this point, we have a free block of memory that goes
+ * up to (but not exceeding) the end of the region.
+ *
+ * pdesc = descriptor of the last free block in region
+ * size = amount of free mem at end of region (i.e., _MEMSIZE(pdesc))
+ * regend = 1st address AFTER end of region
+ */
+
+
+ /*
+ * See if we should return the whole region of only part of it.
+ */
+
+ if ( _ADDRESS(pdesc) == _heap_regions[index]._regbase ) {
+
+ /*
+ * Whole region is free, return it to OS
+ */
+
+ _heap_free_region(index);
+
+ /*
+ * Put a dummy block in the heap to hold space for
+ * the memory we just freed up.
+ */
+
+ _SET_DUMMY(pdesc);
+
+ }
+
+ else {
+
+ /*
+ * Whole region is NOT free, return part of it to OS
+ */
+
+ _free_partial_region(pdesc, size, index);
+
+ }
+
+ /*
+ * Exit paths
+ */
+
+ return(1); /* 1 = minimized region */
+
+}
+
+
+/***
+*_free_partial_region() - Free part of a region to the OS
+*
+*Purpose:
+* Free a portion of a region to the OS
+*
+*Entry:
+* pdesc = descriptor of last free block in region
+* size = amount of free mem at end of region (i.e., _MEMSIZE(pdesc))
+* index = index of region
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CALLTYPE4 _free_partial_region (
+ REG1 _PBLKDESC pdesc,
+ unsigned size,
+ int index
+ )
+{
+ unsigned left;
+ void * base;
+ REG2 _PBLKDESC pnew;
+
+ /*
+ * Init a few variables.
+ */
+
+ left = (size & (_PAGESIZE_-1));
+ base = (char *)_ADDRESS(pdesc);
+
+ /*
+ * We return memory to the OS in page multiples. If the
+ * free block is not page aligned, we'll insert a new free block
+ * to fill in the difference.
+ */
+
+ if ( left != 0 ) {
+
+ /*
+ * The block is not a multiple of pages so we need
+ * to adjust variables accordingly.
+ */
+
+ size -= left;
+ base = (char *)base + left;
+ }
+
+
+ /*
+ * Return the free pages to the OS.
+ */
+
+#ifdef _CRUISER_
+
+ if ( DOSSETMEM(base, size, _DECOMMIT) != 0 )
+ _heap_abort();
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if (!VirtualFree(base, size, MEM_DECOMMIT))
+ _heap_abort();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /*
+ * Adjust the region table entry
+ */
+
+ _heap_regions[index]._currsize -= size;
+
+
+ /*
+ * Adjust the heap according to whether we released the whole
+ * free block or not. (Don't worry about consecutive dummies,
+ * we'll coalesce them later.)
+ *
+ * base = address of block we just gave back to OS
+ * size = size of block we gave back to OS
+ * left = size of block we did NOT give back to OS
+ */
+
+ if ( left == 0 ) {
+
+ /*
+ * The free block was released to the OS in its
+ * entirety. Make the free block a dummy place holder.
+ */
+
+ _SET_DUMMY(pdesc);
+
+ }
+
+ else {
+
+ /*
+ * Did NOT release the whole free block to the OS.
+ * There's a block of free memory we want to leave
+ * in the heap. Insert a dummy entry after it.
+ */
+
+ _GETEMPTY(pnew);
+
+ pnew->pblock = (char *)base;
+ _SET_DUMMY(pnew);
+
+ pnew->pnextdesc = pdesc->pnextdesc;
+ pdesc->pnextdesc = pnew;
+
+ }
+
+}
diff --git a/private/crt32/heap/heapprm.c b/private/crt32/heap/heapprm.c
new file mode 100644
index 000000000..c0d810ecc
--- /dev/null
+++ b/private/crt32/heap/heapprm.c
@@ -0,0 +1,87 @@
+/***
+*heapprm.c - Set/report heap parameters
+*
+* Copyright (c) 1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Set or report the values of certain parameters in the heap.
+*
+*Revision History:
+* 03-04-91 GJF Module created.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+
+/***
+*_heap_param(int flag, int param_id, void *pparam) - set or report the values
+* of the specified heap parameter.
+*
+*Purpose:
+* Get or set certain parameters which affect the behavior of the heap.
+* The supported parameters vary implementation to implementation and
+* version to version. See description of entry conditions for the
+* currently supported parameters.
+*
+*Entry:
+* int flag - _HP_GETPARAM, to get a parameter value, or _HP_SETPARAM,
+* to set a parameter value
+*
+* int param_id - identifier for the heap parameter. values supported in
+* this release are:
+*
+* _HP_AMBLKSIZ - _amblksiz (aka _heap_growsize) parameter
+* _HP_GROWSIZE - same as _HP_AMBLKSIZ
+* _HP_RESETSIZE - _heap_resetsize parameter
+*
+* void *pparam - pointer to variable of appropriate type for the heap
+* parameter to be fetched/set
+*
+*Exit:
+* 0 = no error has occurred
+* -1 = an error has occurred (errno is set)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heap_param (
+ int flag,
+ int param_id,
+ void *pparam
+ )
+{
+
+ switch ( param_id ) {
+
+ case _HP_RESETSIZE:
+ if ( flag == _HP_SETPARAM ) {
+ _mlock(_HEAP_LOCK);
+ _heap_resetsize = *(unsigned *)pparam;
+ _munlock(_HEAP_LOCK);
+ }
+ else
+ *(unsigned *)pparam = _heap_resetsize;
+ break;
+
+ case _HP_AMBLKSIZ:
+ if ( flag == _HP_SETPARAM )
+ /*
+ * the only references to _amblksiz (aka
+ * _heap_growsize) are atomic. therefore, the
+ * heap does not need to be locked.
+ */
+ _amblksiz = *(unsigned *)pparam;
+ else
+ *(unsigned *)pparam = _amblksiz;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/private/crt32/heap/heapsrch.c b/private/crt32/heap/heapsrch.c
new file mode 100644
index 000000000..2b07277cd
--- /dev/null
+++ b/private/crt32/heap/heapsrch.c
@@ -0,0 +1,150 @@
+/***
+*heapsrch.c - search the heap for a free block
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the _heap_search() function.
+*
+*Revision History:
+* 06-30-89 GJF Module created. Yea, it's ugly, but it seems to work.
+* 07-21-89 GJF Now assumes proverdesc points to the descriptor for
+* first free block in the heap, if any, or is plastdesc,
+* if there are no free blocks
+* 11-08-89 GJF Fixed copyright, added register attribute to vars
+* 12-18-89 GJF Removed some redundant code, updated the description,
+* changed include file name to heap.h, added explicit
+* _cdecl to function definition.
+* 12-19-89 GJF Got rid of code to maintain plastdesc
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 09-28-90 GJF New-style function declarator.
+* 03-05-91 GJF Changed strategy for rover - old version available
+* by #define-ing _OLDROVER_.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <stddef.h>
+
+#define LOOP_FOREVER while(1)
+
+/***
+*_PBLKDESC _heap_search(unsigned size) - Find a free block of a least size
+* bytes.
+*
+*Purpose:
+* Finds a free block of at least size bytes. Searches the list of block
+* descriptors from *proverdesc to the end (marked by the sentinel). The
+* search is strictly first fit. Adjacent free blocks are coalesced as
+* they are encountered during the search.
+*
+*Entry:
+* unsigned size - size of block requested
+*
+*Exit:
+* Success: Pointer to descriptor for free memory block of at least size
+* bytes
+* Failure: NULL
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+_PBLKDESC _CALLTYPE1 _heap_search (
+ unsigned size
+ )
+{
+ REG1 _PBLKDESC pdesc;
+ REG2 _PBLKDESC pdesc2;
+ _PBLKDESC pretdesc = NULL;
+
+ /* search from proverdesc thru plastdesc, looking for free block of
+ * at least size bytes. coalesce adjacent free blocks during the
+ * search. the search is strictly first fit. that is, it terminates
+ * when the first block is found of adequate size.
+ */
+ for ( pdesc = _heap_desc.proverdesc ; pdesc != &(_heap_desc.sentinel) ;
+ pdesc = pdesc->pnextdesc )
+ /* is pdesc free?
+ */
+ if ( _IS_FREE(pdesc) )
+ /* coalesce loop
+ */
+ LOOP_FOREVER {
+ /* if pdesc is big enough, return it
+ */
+ if ( _BLKSIZE(pdesc) >= size ) {
+ pretdesc = pdesc;
+ goto searchdone;
+ }
+
+ /* see if the next block is free and, if so,
+ * coalesce it with pdesc
+ */
+ pdesc2 = pdesc->pnextdesc;
+ if ( _IS_FREE(pdesc2) ) {
+ /* coalesce pdesc2 with pdesc
+ */
+ pdesc->pnextdesc = pdesc2->pnextdesc;
+ _PUTEMPTY(pdesc2);
+ }
+ else
+ break;
+ } /* end LOOP_FOREVER */
+
+#ifndef _OLDROVER_
+
+ for ( pdesc = _heap_desc.pfirstdesc ; pdesc != _heap_desc.proverdesc ;
+ pdesc = pdesc->pnextdesc )
+ /* is pdesc free?
+ */
+ if ( _IS_FREE(pdesc) )
+ /* coalesce loop
+ */
+ LOOP_FOREVER {
+ /* if pdesc is big enough, return it
+ */
+ if ( _BLKSIZE(pdesc) >= size ) {
+ pretdesc = pdesc;
+ goto searchdone;
+ }
+
+ /* see if the next block is free and, if so,
+ * coalesce it with pdesc
+ */
+ pdesc2 = pdesc->pnextdesc;
+ if ( _IS_FREE(pdesc2) ) {
+ /* coalesce pdesc2 with pdesc
+ */
+ pdesc->pnextdesc = pdesc2->pnextdesc;
+ _PUTEMPTY(pdesc2);
+
+ /* special handling for the case where
+ * the rover has been coalesced (search
+ * ends)
+ */
+ if ( _heap_desc.proverdesc == pdesc2 )
+ {
+ _heap_desc.proverdesc = pdesc;
+ if ( _BLKSIZE(pdesc) >= size )
+ pretdesc = pdesc;
+ goto searchdone;
+ }
+ }
+ else
+ break;
+ } /* end LOOP_FOREVER */
+
+#endif /* _OLDROVER_ */
+
+searchdone:
+
+ /* common exit for all code paths. win, lose or draw, this is the
+ * only code path back to the caller.
+ */
+ return(pretdesc);
+}
diff --git a/private/crt32/heap/heapwalk.c b/private/crt32/heap/heapwalk.c
new file mode 100644
index 000000000..8dc6067ca
--- /dev/null
+++ b/private/crt32/heap/heapwalk.c
@@ -0,0 +1,170 @@
+/***
+*heapwalk.c - walk the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the _heapwalk() function
+*
+*Revision History:
+* 07-05-89 JCR Module created.
+* 11-13-89 GJF Added MTHREAD support, also fixed copyright.
+* 11-14-89 JCR Fixed bug -- returned address was off by HDRSIZE
+* 12-18-89 GJF Removed DEBUG286 stuff, also some tuning, cleaned up
+* format a bit, changed header file name to heap.h, added
+* explicit _cdecl to function definition
+* 12-20-89 GJF Removed references to plastdesc
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 09-28-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stddef.h>
+
+
+/***
+*int _heapwalk() - Walk the heap
+*
+*Purpose:
+* Walk the heap returning information on one entry at a time.
+*
+*Entry:
+* struct _heapinfo {
+* int * _pentry; heap entry pointer
+* size_t size; size of heap entry
+* int _useflag; free/inuse flag
+* } *entry;
+*
+*Exit:
+* Returns one of the following values:
+*
+* _HEAPOK - completed okay
+* _HEAPEMPTY - heap not initialized
+* _HEAPBADPTR - _pentry pointer is bogus
+* _HEAPBADBEGIN - can't find initial header info
+* _HEAPBADNODE - malformed node somewhere
+* _HEAPEND - end of heap successfully reached
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heapwalk (
+ struct _heapinfo *_entry
+ )
+{
+ REG1 _PBLKDESC pdesc;
+ _PBLKDESC polddesc;
+ int retval = _HEAPOK;
+
+ /*
+ * Lock the heap
+ */
+
+ _mlock(_HEAP_LOCK);
+
+ /*
+ * Quick header check
+ */
+
+ if ( (_heap_desc.pfirstdesc == NULL) ||
+ (_heap_desc.proverdesc == NULL) ||
+ (_heap_desc.sentinel.pnextdesc != NULL) ) {
+ retval = _HEAPBADBEGIN;
+ goto done;
+ }
+
+ /*
+ * Check for an empty heap
+ */
+
+ if ( _heap_desc.pfirstdesc == &_heap_desc.sentinel ) {
+ retval = _HEAPEMPTY;
+ goto done;
+ }
+
+ /*
+ * If _pentry is NULL, return info about the first entry.
+ * Else, get info about the next entry in the heap.
+ */
+
+ if ( _entry->_pentry == NULL ) {
+ pdesc = _heap_desc.pfirstdesc;
+ }
+ else {
+ /*
+ * Find the entry we gave to the user last time around
+ */
+
+ if ( _heap_findaddr( (void *)((char *)(_entry->_pentry) -
+ _HDRSIZE), &polddesc) != _HEAPFIND_EXACT ) {
+ retval = _HEAPBADPTR;
+ goto done;
+ }
+
+ pdesc = polddesc->pnextdesc;
+
+ } /* else */
+
+
+ /*
+ * pdesc = entry to return info about
+ */
+
+ /*
+ * Skip over dummy entries
+ */
+
+ while ( _IS_DUMMY(pdesc) )
+ pdesc = pdesc->pnextdesc;
+
+
+ /*
+ * See if we're at the end of the heap
+ */
+
+ if ( pdesc == &_heap_desc.sentinel ) {
+ retval = _HEAPEND;
+ goto done;
+ }
+
+ /*
+ * Check back pointer (note that pdesc cannot point to a dummy
+ * descriptor since we have skipped over them)
+ */
+
+ if (!_CHECK_PDESC(pdesc)) {
+ retval = _HEAPBADPTR;
+ goto done;
+ }
+
+ /*
+ * Return info on the next block
+ */
+
+ _entry->_pentry = ( (void *)((char *)_ADDRESS(pdesc) + _HDRSIZE) );
+ _entry->_size = _BLKSIZE(pdesc);
+ _entry->_useflag = ( _IS_INUSE(pdesc) ? _USEDENTRY : _FREEENTRY );
+
+
+ /*
+ * Common return
+ */
+
+done:
+ /*
+ * Release the heap lock
+ */
+
+ _munlock(_HEAP_LOCK);
+
+ return(retval);
+
+}
diff --git a/private/crt32/heap/hpabort.c b/private/crt32/heap/hpabort.c
new file mode 100644
index 000000000..9227a5b4b
--- /dev/null
+++ b/private/crt32/heap/hpabort.c
@@ -0,0 +1,47 @@
+/***
+* hpabort.c - Abort process due to fatal heap error
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 11-13-89 JCR Module created
+* 12-18-89 GJF #include-ed heap.h, also added explicit _cdecl to
+* function definition.
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 10-03-90 GJF New-style function declarator.
+* 10-11-90 GJF Changed interface to _amsg_exit().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <internal.h>
+#include <rterr.h>
+
+
+/***
+* _heap_abort() - Abort process due to fatal heap error
+*
+*Purpose:
+* Terminate the process and output a heap error message
+*
+*Entry:
+* Void
+*
+*Exit:
+* Never returns
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _heap_abort (
+ void
+ )
+{
+ _amsg_exit(_RT_HEAP); /* heap error */
+ /*** PROCESS TERMINATED ***/
+}
diff --git a/private/crt32/heap/makefile b/private/crt32/heap/makefile
new file mode 100644
index 000000000..9e18c9a05
--- /dev/null
+++ b/private/crt32/heap/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+BLDCRT=1
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/heap/malloc.c b/private/crt32/heap/malloc.c
new file mode 100644
index 000000000..85148301b
--- /dev/null
+++ b/private/crt32/heap/malloc.c
@@ -0,0 +1,474 @@
+/***
+*malloc.c - Get a block of memory from the heap
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the malloc() function. Also defines the internal utility
+* functions _flat_malloc(), _heap_split_block(), _heap_advance_rover()
+* and, for multi-thread, _malloc_lk().
+*
+*Revision History:
+* 06-29-89 GJF Module created (no rest for the wicked).
+* 07-07-89 GJF Several bug fixes
+* 07-21-89 GJF Added code to maintain proverdesc such that proverdesc
+* either points to the descriptor for the first free
+* block in the heap or, if there are no free blocks, is
+* the same as plastdesc.
+* 11-07-89 GJF Substantially revised to cope with 'tiling'.
+* 11-09-89 GJF Embarrassing bug (didn't bother to assign pdesc)
+* 11-10-89 GJF Added MTHREAD support.
+* 11-17-89 GJF Oops, must call _free_lk() instead of free()!
+* 12-18-89 GJF Changed name of header file to heap.h, also added
+* explicit _cdecl to function definitions.
+* 12-19-89 GJF Got rid of plastdesc from _heap_split_block() and
+* _heap_advance_rover().
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-25-90 SBM Replaced <stdio.h> by <stddef.h>, replaced
+* <assertm.h> by <assert.h>
+* 09-28-90 GJF New-style function declarators.
+* 02-26-91 SRW Optimize heap rover for _WIN32_.
+* 03-07-91 FAR Fix bug in heap rover
+* 03-11-91 FAR REALLY Fix bug in heap rover
+* 03-14-91 GJF Changed strategy for rover - old version available
+* by #define-ing _OLDROVER_.
+* 04-05-91 GJF Temporary hack for Win32/DOS folks - special version
+* of malloc that just calls HeapAlloc. Change conditioned
+* on _WIN32DOS_.
+* 05-28-91 GJF Removed M_I386 conditionals and put in _CRUISER_
+* conditionals so the 'tiling' version is built only for
+* Cruiser.
+* 03-03-93 SKS Add new handler support (_pnhHeap and related code)
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stddef.h>
+
+#ifndef _POSIX_
+#include <new.h>
+_PNH _pnhHeap = NULL; /* pointer to new() handler */
+#endif
+
+/***
+*void *malloc(size_t size) - Get a block of memory from the heap
+*
+*Purpose:
+* Allocate of block of memory of at least size bytes from the heap and
+* return a pointer to it.
+*
+* Special Notes For Cruiser Implementaton: For OS/2 2.0, malloc() is
+* required to ensure that allocations of not more than 64 Kb do not
+* cross 64 Kb boundaries in the address space. For this implementation,
+* the straightforward, flat-model malloc is renamed to _flat_malloc()
+* and a malloc() that worries about 'tiling' is built on top of this.
+*
+* Special Notes For Multi-thread: The non-multi-thread version is
+* renamed to _malloc_lk(). The multi-thread malloc() simply locks the
+* heap calls _malloc_lk, released the heap lock and returns.
+*
+*Entry:
+* size_t size - size of block requested
+*
+*Exit:
+* Success: Pointer to memory block
+* Failure: NULL (or some error value)
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+void * _CALLTYPE1 malloc (
+ size_t size
+ )
+{
+ void *pret;
+
+#ifndef _POSIX_
+ for (;;)
+ {
+#endif
+ /* lock the heap
+ */
+ _mlock(_HEAP_LOCK);
+
+ /* do the allocation
+ */
+ pret = _malloc_lk(size);
+
+ /* unlock the heap
+ */
+ _munlock(_HEAP_LOCK);
+
+#ifndef _POSIX_
+ if (pret || _pnhHeap == NULL || (*_pnhHeap)(size) == 0)
+#endif
+ return(pret);
+
+#ifndef _POSIX_
+ }
+#endif /* ndef _POSIX_ */
+}
+
+
+/***
+*void *_malloc_lk(size_t size) - non-locking form of malloc
+*
+*Purpose:
+* Same as malloc() except that no locking or unlocking is performed.
+*
+*Entry:
+* See malloc
+*
+*Exit:
+* See malloc
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 _malloc_lk (
+ size_t size
+ )
+
+#else /* ndef MTHREAD */
+
+void * _CALLTYPE1 malloc (
+ size_t size
+ )
+
+#endif /* MTHREAD */
+
+#ifdef _CRUISER_
+
+{
+ char *pblck;
+ _PBLKDESC pdesc;
+ size_t dist;
+
+ /* round size up to the nearest whole number of dwords
+ */
+ size = _ROUND2(size, 4);
+
+ /* first try allocating a block of size bytes
+ */
+ if ( ((pblck = _flat_malloc(size)) == NULL) || (size > _SEGSIZE_) ||
+ (_DISTTOBNDRY(pblck) >= size) )
+ /* all done!
+ */
+ goto done;
+ else
+ /* doesn't meet requirements, free the allocation back to the
+ * heap
+ */
+ _free_lk(pblck);
+
+ /* now, try allocating a block of 2*size bytes. if successful, the
+ * allocated block is guaranteed to contain a region of size bytes
+ * which does not cross a 64 K boundary.
+ */
+ if ( (pblck = _flat_malloc(2*size)) == NULL )
+ /* allocation failed, return NULL to the caller
+ */
+ goto done;
+
+ /* set pdesc to point to the descriptor for the allocation block
+ */
+ pdesc = _BACKPTR(pblck);
+
+ /* find a subregion of at least size bytes which does not cross a
+ * 64 Kb boundary and build a heap block around it. set pblck to
+ * point to to allocation area of the block and pdesc to point to
+ * its descriptor
+ */
+ if ( (dist = _DISTTOBNDRY(pblck)) < size ) {
+ /* the subregion from pblck to (pblck + size) crosses a 64 Kb
+ * boundary, but the subregion from (pblck + dist) to (pblck +
+ * dist + size) cannot (it starts on one). therefore, split
+ * the block into two heap blocks, with the later block
+ * starting at (pblck + dist - _HDRSIZE), and free the first
+ * block.
+ */
+ _heap_split_block(pdesc, dist - _HDRSIZE);
+ _free_lk(pblck);
+ pdesc = pdesc->pnextdesc;
+ _SET_INUSE(pdesc);
+ pblck += dist;
+ }
+
+ /* pblck and pdesc are now bound to allocation block whose first size
+ * bytes do not cross any 64 Kb boundary. only detail is the block
+ * may be too large so...
+ */
+#ifdef _OLDROVER_
+
+ _heap_split_block(pdesc, size);
+ _SET_FREE(pdesc->pnextdesc);
+ _heap_advance_rover();
+
+#else /* ndef _OLDROVER_ */
+
+ if ( _BLKSIZE(pdesc) > size ) {
+ _heap_split_block(pdesc, size);
+ _SET_FREE(pdesc->pnextdesc);
+ _heap_desc.proverdesc = pdesc->pnextdesc;
+ }
+
+#endif /* _OLDROVER_ */
+
+done:
+ return(pblck);
+}
+
+
+/***
+*void *_flat_malloc(size_t size) - Get a block of memory from the heap
+*
+*Purpose:
+* Allocate of block of memory of at least size bytes from the heap,
+* without regard to whether or not it crosses a 64 Kb boundary, and
+* return a pointer to it.
+*
+*Entry:
+* size_t size - size of block requested
+*
+*Exit:
+* Success: Pointer to memory block
+* Failure: NULL (or some error value)
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+void * _CALLTYPE1 _flat_malloc (
+ size_t size
+ )
+
+#endif /* _CRUISER_ */
+
+{
+ _PBLKDESC pdesc;
+
+ /* validate size
+ */
+ /***** COMMENTED OUT UNTIL _HEAP_MAXREQ IS DEFINED
+ if ( size > _HEAP_MAXREQ )
+ return(NULL);
+ *****/
+
+ /* round requested size
+ */
+ size = _ROUND2(size, 4);
+
+#if !defined(_POSIX_) && !defined(MTHREAD)
+ for (;;)
+ {
+#endif /* !_POSIX && !MTHREAD */
+ /* try to find a big enough free block
+ */
+ if ( (pdesc = _heap_search(size)) == NULL )
+ if ( _heap_grow(size) != -1 ) {
+ /* try finding a big enough free block again. the
+ * success of the call to _heap_grow should guarantee
+ * it, but...
+ */
+ if ( (pdesc = _heap_search(size)) == NULL )
+ /* something unexpected, and very bad, has
+ * happened. abort!
+ */
+ _heap_abort();
+ }
+#if !defined(_POSIX_) && !defined(MTHREAD)
+ else if (!_pnhHeap || (*_pnhHeap)(size) == 0)
+ return(NULL);
+ else
+ continue;
+ else
+ break; /* success! */
+ }
+#else /* _POSIX || MTHREAD */
+ else
+ return(NULL);
+#endif /* !_POSIX && !MTHREAD */
+
+ /* carve the block into two pieces (if necessary). the first piece
+ * shall be of the exact requested size, marked inuse and returned to
+ * the caller. the leftover piece is to be marked free.
+ */
+ if ( _BLKSIZE(pdesc) != size ) {
+ /* split up the block and free the leftover piece back to
+ * the heap
+ */
+ _heap_split_block(pdesc, size);
+ _SET_FREE(pdesc->pnextdesc);
+ }
+
+ /* mark pdesc inuse
+ */
+ _SET_INUSE(pdesc);
+
+ /* check proverdesc and reset, if necessary
+ */
+#ifdef _OLDROVER_
+
+ _heap_advance_rover();
+
+#else /* ndef _OLDROVER_ */
+
+ _heap_desc.proverdesc = pdesc->pnextdesc;
+
+#endif /* _OLDROVER_ */
+
+ return( (void *)((char *)_ADDRESS(pdesc) + _HDRSIZE) );
+}
+
+
+/***
+*void _heap_split_block(pdesc, newsize) - split a heap allocation block into
+* two allocation blocks
+*
+*Purpose:
+* Split the allocation block described by pdesc into two blocks, the
+* first one being of newsize bytes.
+*
+* Notes: It is caller's responsibilty to set the status (i.e., free
+* or inuse) of the two new blocks, and to check and reset proverdesc
+* if necessary. See Exceptions (below) for additional requirements.
+*
+*Entry:
+* _PBLKDESC pdesc - pointer to the allocation block descriptor
+* size_t newsize - size for the first of the two sub-blocks (i.e.,
+* (i.e., newsize == _BLKSIZE(pdesc), on exit)
+*
+*Exit:
+* There is no return value.
+*
+*Exceptions:
+* It is assumed pdesc points to a valid allocation block descriptor and
+* newsize is a valid heap block size as is (i.e., WITHOUT rounding). If
+* either of these of assumption is violated, _heap_split_block() will
+* likely corrupt the heap. Note also that _heap_split_block will simply
+* return to the caller if newsize >= _BLKSIZE(pdesc), on entry.
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _heap_split_block (
+ REG1 _PBLKDESC pdesc,
+ size_t newsize
+ )
+{
+ REG2 _PBLKDESC pdesc2;
+
+ assert(("_heap_split_block: bad pdesc arg", _CHECK_PDESC(pdesc)));
+ assert(("_heap_split_block: bad newsize arg", _ROUND2(newsize,4) == newsize));
+
+ /* carve the block into two pieces (if possible). the first piece
+ * is to be exactly newsize bytes.
+ */
+ if ( _BLKSIZE(pdesc) > newsize ) {
+ /* get an empty decriptor
+ */
+ _GETEMPTY(pdesc2)
+
+ /* set it up to manage the second piece and link it in to
+ * the list
+ */
+ pdesc2->pblock = (void *)((char *)_ADDRESS(pdesc) + newsize +
+ _HDRSIZE);
+ *(void **)(pdesc2->pblock) = pdesc2;
+ pdesc2->pnextdesc = pdesc->pnextdesc;
+ pdesc->pnextdesc = pdesc2;
+ }
+}
+
+#ifdef _OLDROVER_
+
+/***
+*void _heap_advance_rover(void) - check proverdesc and advance it, if necessary
+*
+*Purpose:
+* Check proverdesc. If it is not pointing to the descriptor of a free
+* block and is not equal to &sentinel, then walk up the list of heap
+* block descriptors until the descriptor of a free block is reached
+* and reset proverdesc to point to this descriptor, or until the end
+* of the heap is reached and reset proverdesc to &sentinel.
+*
+*Entry:
+* No arguments.
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _heap_advance_rover(void)
+{
+ REG1 _PBLKDESC pdesc;
+
+ /* check proverdesc and advance it, if necessary
+ */
+
+#ifdef _CRUISER_ /* CRUISER TARGET */
+
+ if ( !_IS_FREE(_heap_desc.proverdesc) && (_heap_desc.proverdesc !=
+ &_heap_desc.sentinel) ) {
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if ( _heap_desc.proverdesc != &_heap_desc.sentinel &&
+ (!_IS_FREE(_heap_desc.proverdesc) ||
+ _BLKSIZE(_heap_desc.proverdesc) <= 8)) {
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* set pdesc to point to the descriptor for the next free
+ * block, if any, or &sentinel, otherwise.
+ */
+ for ( pdesc = (_heap_desc.proverdesc)->pnextdesc ;
+#ifdef _CRUISER_ /* CRUISER TARGET */
+ !(_IS_FREE(pdesc)) && (pdesc != &_heap_desc.sentinel) ;
+#else /* ndef _CRUISER_ */
+#ifdef _WIN32_
+ pdesc != &_heap_desc.sentinel &&
+ (!(_IS_FREE(pdesc)) || _BLKSIZE(pdesc) <= 8) ;
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+ pdesc = pdesc->pnextdesc )
+ ;
+
+ /* update proverdesc with pdesc
+ */
+ _heap_desc.proverdesc = pdesc;
+ }
+}
+
+#endif /* _OLDROVER_ */
diff --git a/private/crt32/heap/msize.c b/private/crt32/heap/msize.c
new file mode 100644
index 000000000..103f2af9d
--- /dev/null
+++ b/private/crt32/heap/msize.c
@@ -0,0 +1,112 @@
+/***
+*msize.c - calculate the size of a memory block in the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the following function:
+* _msize() - calculate the size of a block in the heap
+*
+*Revision History:
+* 07-18-89 GJF Module created
+* 11-13-89 GJF Added MTHREAD support. Also fixed copyright and got
+* rid of DEBUG286 stuff.
+* 12-18-89 GJF Changed name of header file to heap.h, also added
+* explicit _cdecl to function definitions.
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1 and added #include
+* <cruntime.h>
+* 07-30-90 SBM Added return statement to MTHREAD _msize function
+* 09-28-90 GJF New-style function declarators.
+* 04-08-91 GJF Temporary hack for Win32/DOS folks - special version
+* of _msize that calls HeapSize. Change conditioned on
+* _WIN32DOS_.
+*
+*******************************************************************************/
+
+#ifndef _WIN32DOS_
+
+#include <cruntime.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stdlib.h>
+
+/***
+*size_t _msize(pblck) - calculate the size of specified block in the heap
+*
+*Purpose:
+* Calculates the size of memory block (in the heap) pointed to by
+* pblck.
+*
+*Entry:
+* void *pblck - pointer to a memory block in the heap
+*
+*Return:
+* size of the block
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+size_t _CALLTYPE1 _msize (
+ void *pblck
+ )
+{
+ size_t retval;
+
+ /* lock the heap
+ */
+ _mlock(_HEAP_LOCK);
+
+ retval = _msize_lk(pblck);
+
+ /* release the heap lock
+ */
+ _munlock(_HEAP_LOCK);
+
+ return retval;
+}
+
+size_t _CALLTYPE1 _msize_lk (
+
+#else /* ndef MTHREAD */
+
+size_t _CALLTYPE1 _msize (
+
+#endif /* MTHREAD */
+
+ void *pblck
+ )
+{
+#ifdef DEBUG
+ if (!_CHECK_BACKPTR(pblck))
+ _heap_abort();
+#endif
+
+ return( (size_t) ((char *)_ADDRESS(_BACKPTR(pblck)->pnextdesc) -
+ (char *)pblck) );
+}
+
+
+#else /* _WIN32DOS_ */
+
+/*
+ * TEMPORARY HACK! THE CODE BELOW IS INTENDED TO ALLOW LIMITED USE OF THE
+ * C RUNTIME ON WIN32/DOS. IT WILL BE DELETED AS SOON AS THEY IMPLEMENT
+ * VirtualAlloc()!
+ */
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <malloc.h>
+
+extern HANDLE _HeapHandle;
+
+size_t _CALLTYPE1 _msize (
+ void *pblck
+ )
+{
+ return( (size_t)HeapSize(_HeapHandle, pblck) );
+}
+
+#endif /* _WIN32DOS_ */
diff --git a/private/crt32/heap/new.cxx b/private/crt32/heap/new.cxx
new file mode 100644
index 000000000..4a47fb1c5
--- /dev/null
+++ b/private/crt32/heap/new.cxx
@@ -0,0 +1,28 @@
+/***
+*new.cxx - defines C++ new routine
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines C++ new routine.
+*
+*Revision History:
+* 05-07-90 WAJ Initial version.
+* 08-30-90 WAJ new now takes unsigned ints.
+* 08-08-91 JCR call _halloc/_hfree, not halloc/hfree
+* 08-13-91 KRS Change new.hxx to new.h. Fix copyright.
+* 08-13-91 JCR ANSI-compatible _set_new_handler names
+* 10-30-91 JCR Split new, delete, and handler into seperate sources
+* 11-13-91 JCR 32-bit version
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <new.h>
+
+
+void * operator new( unsigned int cb )
+{
+ return malloc( cb );
+}
diff --git a/private/crt32/heap/realloc.c b/private/crt32/heap/realloc.c
new file mode 100644
index 000000000..53d5a23b5
--- /dev/null
+++ b/private/crt32/heap/realloc.c
@@ -0,0 +1,477 @@
+/***
+*realloc.c - Reallocate a block of memory in the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the realloc() and _expand() functions.
+*
+*Revision History:
+* 10-25-89 GJF Module created.
+* 11-06-89 GJF Massively revised to handle 'tiling' and to properly
+* update proverdesc.
+* 11-10-89 GJF Added MTHREAD support.
+* 11-17-89 GJF Fixed pblck validation (i.e., conditional call to
+* _heap_abort())
+* 12-18-89 GJF Changed header file name to heap.h, also added explicit
+* _cdecl or _pascal to function defintions
+* 12-20-89 GJF Removed references to plastdesc
+* 01-04-90 GJF Fixed a couple of subtle and nasty bugs in _expand().
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-29-90 GJF Made _heap_expand_block() _CALLTYPE4.
+* 07-25-90 SBM Replaced <stdio.h> by <stddef.h>, replaced
+* <assertm.h> by <assert.h>
+* 09-28-90 GJF New-style function declarators.
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 03-05-91 GJF Changed strategy for rover - old version available
+* by #define-ing _OLDROVER_.
+* 04-08-91 GJF Temporary hack for Win32/DOS folks - special version
+* of realloc that uses just malloc, _msize, memcpy and
+* free. Change conditioned on _WIN32DOS_.
+* 05-28-91 GJF Removed M_I386 conditionals and put in _WIN32_
+* conditionals to build non-tiling heap for Win32.
+*
+*******************************************************************************/
+
+#ifndef _WIN32DOS_
+
+#include <cruntime.h>
+#include <assert.h>
+#include <heap.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stddef.h>
+#include <string.h>
+
+/* useful macro to compute the size of an allocation block given both a
+ * pointer to the descriptor and a pointer to the user area of the block
+ * (more efficient variant of _BLKSIZE macro, given the extra information)
+ */
+#define BLKSZ(pdesc,pblk) ((unsigned)_ADDRESS((pdesc)->pnextdesc) - \
+ (unsigned)(pblck))
+
+/* expand an allocation block, in place, up to or beyond a specified size
+ * by coalescing it with subsequent free blocks (if possible)
+ */
+static int _CALLTYPE4 _heap_expand_block(_PBLKDESC, size_t *, size_t);
+
+/***
+*void *realloc(void *pblck, size_t newsize) - reallocate a block of memory in
+* the heap
+*
+*Purpose:
+* Re-allocates a block in the heap to newsize bytes. newsize may be
+* either greater or less than the original size of the block. The
+* re-allocation may result in moving the block as well as changing
+* the size. If the block is moved, the contents of the original block
+* are copied over.
+*
+* Special ANSI Requirements:
+*
+* (1) realloc(NULL, newsize) is equivalent to malloc(newsize)
+*
+* (2) realloc(pblck, 0) is equivalent to free(pblck) (except that
+* NULL is returned)
+*
+* (3) if the realloc() fails, the object pointed to by pblck is left
+* unchanged
+*
+* Special Notes For Cruiser Implementaton: For OS/2 2.0, realloc() is
+* required to ensure that the re-allocated block does not cross a 64 Kb
+* boundary unless the new size is more than 64 Kb or the original block
+* already crossed such a boundary.
+*
+* Special Notes For Multi-thread: The heap is locked immediately prior
+* to assigning pdesc. This is after special cases (1) and (2), listed
+* above, are taken care of. The lock is released immediately prior to
+* the final return statement.
+*
+*Entry:
+* void *pblck - pointer to block in the heap previously allocated
+* by a call to malloc(), realloc() or _expand().
+*
+* size_t newsize - requested size for the re-allocated block
+*
+*Exit:
+* Success: Pointer to the re-allocated memory block
+* Failure: NULL
+*
+*Uses:
+*
+*Exceptions:
+* If pblck does not point to a valid allocation block in the heap,
+* realloc() will behave unpredictably and probably corrupt the heap.
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 realloc (
+ REG1 void *pblck,
+ size_t newsize
+ )
+{
+ REG2 _PBLKDESC pdesc;
+ void *pretblck;
+ size_t oldsize;
+ size_t currsize;
+
+ /* special cases, handling mandated by ANSI
+ */
+ if ( pblck == NULL )
+ /* just do a malloc of newsize bytes and return a pointer to
+ * the new block
+ */
+ return( malloc(newsize) );
+
+ if ( newsize == 0 ) {
+ /* free the block and return NULL
+ */
+ free(pblck);
+ return( NULL );
+ }
+
+ /* make newsize a valid allocation block size (i.e., round up to the
+ * nearest whole number of dwords)
+ */
+ newsize = _ROUND2(newsize,4);
+
+ /* if multi-thread support enabled, lock the heap here
+ */
+ _mlock(_HEAP_LOCK);
+
+ /* set pdesc to point to the descriptor for *pblck
+ */
+ pdesc = _BACKPTR(pblck);
+
+ if ( _ADDRESS(pdesc) != ((char *)pblck - _HDRSIZE) )
+ _heap_abort();
+
+ /* see if pblck is big enough already, or can be expanded (in place)
+ * to be big enough.
+ */
+#ifdef _CRUISER_
+
+ /* if the block was expanded in place, ensure that it does not cross
+ * a 64 Kb boundary unless it already did so or newsize is greater
+ * than 64 Kb
+ */
+ if ( ((oldsize = currsize = BLKSZ(pdesc, pblck)) >= newsize) ||
+ ((_heap_expand_block(pdesc, &currsize, newsize) == 0) &&
+ ((newsize > _SEGSIZE_) || (_DISTTOBNDRY(pdesc) >= newsize) ||
+ (_DISTTOBNDRY(pdesc) < oldsize))) ) {
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if ( ((oldsize = currsize = BLKSZ(pdesc, pblck)) > newsize) ||
+ (_heap_expand_block(pdesc, &currsize, newsize) == 0) ) {
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* if necessary, mark pdesc as inuse
+ */
+ if ( _IS_FREE(pdesc) ) {
+ _SET_INUSE(pdesc);
+#ifdef _OLDROVER_
+ _heap_advance_rover();
+#endif /* _OLDROVER_ */
+ }
+
+ /* trim pdesc down to be exactly newsize bytes, if necessary
+ */
+ if ( currsize > newsize ) {
+ _heap_split_block(pdesc, newsize);
+ _free_lk((char *)pblck + newsize + _HDRSIZE);
+ }
+
+ pretblck = pblck;
+ goto realloc_done;
+ }
+
+ /* try malloc-ing a new block of the requested size. if successful,
+ * copy over the data from the original block and free it.
+ */
+ if ( (pretblck = _malloc_lk(newsize)) != NULL ) {
+ memcpy(pretblck, pblck, oldsize);
+ _free_lk(pblck);
+ }
+ else {
+ /* restore pblck to its orignal size
+ */
+ _heap_split_block(pdesc, oldsize);
+ _free_lk((char *)pblck + oldsize + _HDRSIZE);
+ }
+
+realloc_done:
+ /* if multi-thread support is enabled, unlock the heap here
+ */
+ _munlock(_HEAP_LOCK);
+
+ return(pretblck);
+}
+
+
+/***
+*void *_expand(void *pblck, size_t newsize) - expand/contract a block of memory
+* in the heap
+*
+*Purpose:
+* Resizes a block in the heap to newsize bytes. newsize may be either
+* greater (expansion) or less (contraction) than the original size of
+* the block. The block is NOT moved. In the case of expansion, if the
+* block cannot be expanded to newsize bytes, it is expanded as much as
+* possible.
+*
+* Special Notes For Cruiser Implementaton: For OS/2 2.0, _expand() is
+* required to ensure the resized block does not cross a 64 Kb boundary
+* unless the requested new size is more than 64 Kb or the block already
+* did so. Note that, because of the peculiar semantics of _expand(), it
+* may produce block of less than 64 Kb in size which does cross a 64 Kb
+* boundary.
+*
+* Special Notes For Multi-thread: The heap is locked just before pdesc
+* is assigned and unlocked immediately prior to the return statement.
+*
+*Entry:
+* void *pblck - pointer to block in the heap previously allocated
+* by a call to malloc(), realloc() or _expand().
+*
+* size_t newsize - requested size for the resized block
+*
+*Exit:
+* Success: Pointer to the resized memory block (i.e., pblck)
+* Failure: NULL
+*
+*Uses:
+*
+*Exceptions:
+* If pblck does not point to a valid allocation block in the heap,
+* _expand() will behave unpredictably and probably corrupt the heap.
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 _expand (
+ REG1 void *pblck,
+ size_t newsize
+ )
+{
+ REG2 _PBLKDESC pdesc;
+ void *pretblck = pblck;
+ size_t oldsize;
+ size_t currsize;
+ unsigned index;
+#ifdef _CRUISER_
+ size_t dist;
+#endif /* _CRUISER_ */
+
+ /* make newsize a valid allocation block size (i.e., round up to the
+ * nearest whole number of dwords)
+ */
+ newsize = _ROUND2(newsize,4);
+
+ /* if multi-thread support enabled, lock the heap here
+ */
+ _mlock(_HEAP_LOCK);
+
+ /* set pdesc to point to the descriptor for *pblck
+ */
+ pdesc = _BACKPTR(pblck);
+
+ /* see if pblck is big enough already, or can be expanded (in place)
+ * to be big enough.
+ */
+ if ( ((oldsize = currsize = BLKSZ(pdesc, pblck)) >= newsize) ||
+ (_heap_expand_block(pdesc, &currsize, newsize) == 0) ) {
+ /* pblck is (now) big enough. trim it down, if necessary
+ */
+ if ( currsize > newsize ) {
+ _heap_split_block(pdesc, newsize);
+ _free_lk((char *)pblck + newsize + _HDRSIZE);
+ currsize = newsize;
+ }
+ goto expand_done;
+ }
+
+ /* if the heap block is at the end of a region, attempt to grow the
+ * region
+ */
+ if ( (pdesc->pnextdesc == &_heap_desc.sentinel) ||
+ _IS_DUMMY(pdesc->pnextdesc) ) {
+
+ /* look up the region index
+ */
+ for ( index = 0 ; index < _HEAP_REGIONMAX ; index++ )
+ if ( (_heap_regions[index]._regbase < pblck) &&
+ (((char *)(_heap_regions[index]._regbase) +
+ _heap_regions[index]._currsize) >= (char *)pblck) )
+ break;
+
+ /* make sure a valid region index was obtained (pblck could
+ * lie in a portion of heap memory donated by a user call to
+ * _heapadd(), which therefore would not appear in the region
+ * table)
+ */
+ if ( index == _HEAP_REGIONMAX ) {
+ pretblck = NULL;
+ goto expand_done;
+ }
+
+ /* try growing the region. the difference between newsize and
+ * the current size of the block, rounded up to the nearest
+ * whole number of pages, is the amount the region needs to
+ * be grown. if successful, try expanding the block again
+ */
+ if ( (_heap_grow_region(index, _ROUND2(newsize - currsize,
+ _PAGESIZE_)) == 0) &&
+ (_heap_expand_block(pdesc, &currsize, newsize) == 0) ) {
+ /* pblck is (now) big enough. trim it down to be
+ * exactly size bytes, if necessary
+ */
+ if ( currsize > newsize ) {
+ _heap_split_block(pdesc, newsize);
+ _free_lk((char *)pblck + newsize + _HDRSIZE);
+ currsize = newsize;
+ }
+ }
+ else
+ pretblck = NULL;
+ }
+ else
+ pretblck = NULL;
+
+expand_done:
+#ifdef _CRUISER_
+ /* check for crossing of 64 Kb boundaries. the resized allocation
+ * block must be trimmed down if the following conditions all hold
+ * true:
+ * (1) the block was grown
+ * (2) the requested new size was less than 64 Kb
+ * (3) the block now crosses a 64 Kb boundary
+ * (4) the block did not originally cross a 64 Kb
+ * boundary
+ */
+ if ( (currsize > oldsize) && (newsize <= _SEGSIZE_) &&
+ (currsize > (dist = _DISTTOBNDRY(pblck))) && (oldsize <= dist) ) {
+ _heap_split_block(pdesc, dist);
+ _free_lk((char *)pblck + dist + _HDRSIZE);
+ pretblck = NULL;
+ }
+#endif /* _CRUISER_ */
+
+ /* if multi-thread support is enabled, unlock the heap here
+ */
+ _munlock(_HEAP_LOCK);
+
+ return(pretblck);
+}
+
+
+/***
+*int _heap_expand_block(pdesc, pcurrsize, newsize) - expand an allocation block
+* in place (without trying to 'grow' the heap)
+*
+*Purpose:
+*
+*Entry:
+* _PBLKDESC pdesc - pointer to the allocation block descriptor
+* size_t *pcurrsize - pointer to size of the allocation block (i.e.,
+* *pcurrsize == _BLKSIZE(pdesc), on entry)
+* size_t newsize - requested minimum size for the expanded allocation
+* block (i.e., newsize >= _BLKSIZE(pdesc), on exit)
+*
+*Exit:
+* Success: 0
+* Failure: -1
+* In either case, *pcurrsize is updated with the new size of the block
+*
+*Exceptions:
+* It is assumed that pdesc points to a valid allocation block descriptor.
+* It is also assumed that _BLKSIZE(pdesc) == *pcurrsize on entry. If
+* either of these assumptions is violated, _heap_expand_block will almost
+* certainly trash the heap.
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 _heap_expand_block (
+ REG1 _PBLKDESC pdesc,
+ REG3 size_t *pcurrsize,
+ size_t newsize
+ )
+{
+ REG2 _PBLKDESC pdesc2;
+
+ assert(("_heap_expand_block: bad pdesc arg", _CHECK_PDESC(pdesc)));
+ assert(("_heap_expand_block: bad pcurrsize arg", *pcurrsize == _BLKSIZE(pdesc)));
+
+ for ( pdesc2 = pdesc->pnextdesc ; _IS_FREE(pdesc2) ;
+ pdesc2 = pdesc->pnextdesc ) {
+
+ /* coalesce with pdesc. check for special case of pdesc2
+ * being proverdesc.
+ */
+ pdesc->pnextdesc = pdesc2->pnextdesc;
+
+ if ( pdesc2 == _heap_desc.proverdesc )
+#ifdef _OLDROVER_
+ /* temporarily set proverdesc to pdesc
+ */
+#endif /* _OLDROVER_ */
+ _heap_desc.proverdesc = pdesc;
+
+ /* update *pcurrsize, place *pdesc2 on the empty descriptor
+ * list and see if the coalesced block is now big enough
+ */
+ *pcurrsize += _MEMSIZE(pdesc2);
+
+ _PUTEMPTY(pdesc2)
+ }
+
+#ifdef _OLDROVER_
+ if ( pdesc == _heap_desc.proverdesc )
+ _heap_advance_rover();
+#endif /* _OLDROVER_ */
+
+ if ( *pcurrsize >= newsize )
+ return(0);
+ else
+ return(-1);
+}
+
+#else /* _WIN32DOS_ */
+
+/*
+ * TEMPORARY HACK! THE CODE BELOW IS INTENDED TO ALLOW LIMITED USE OF THE
+ * C RUNTIME ON WIN32/DOS. IT WILL BE DELETED AS SOON AS THEY IMPLEMENT
+ * VirtualAlloc()!
+ */
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+void * _CALLTYPE1 realloc (
+ REG1 void *pblck,
+ size_t newsize
+ )
+{
+ void *pnew;
+ size_t oldsize;
+
+ if ( (pnew = malloc(newsize)) != NULL ) {
+ oldsize = _msize(pblck);
+ memcpy(pnew, pblck, min(newsize, oldsize));
+ free(pblck);
+ }
+
+ return pnew;
+}
+
+#endif /* _WIN32DOS_ */
diff --git a/private/crt32/heap/sources b/private/crt32/heap/sources
new file mode 100644
index 000000000..11d18fa85
--- /dev/null
+++ b/private/crt32/heap/sources
@@ -0,0 +1,71 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=heap
+
+TARGETNAME=heap
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+!IFDEF 386_BLDCRT
+SOURCES=calloc.c \
+ findaddr.c \
+ free.c \
+ heapadd.c \
+ heapchk.c \
+ heapgrow.c \
+ heapinit.c \
+ heapmin.c \
+ heapprm.c \
+ heapsrch.c \
+ hpabort.c \
+ heapwalk.c \
+ malloc.c \
+ msize.c \
+ realloc.c \
+ handler.cxx \
+ delete.cxx \
+ new.cxx
+!ELSE
+SOURCES=calloc.c \
+ findaddr.c \
+ free.c \
+ heapadd.c \
+ heapchk.c \
+ heapgrow.c \
+ heapinit.c \
+ heapmin.c \
+ heapprm.c \
+ heapsrch.c \
+ hpabort.c \
+ heapwalk.c \
+ malloc.c \
+ msize.c \
+ realloc.c
+!ENDIF
diff --git a/private/crt32/helper/empty.c b/private/crt32/helper/empty.c
new file mode 100644
index 000000000..b93113c48
--- /dev/null
+++ b/private/crt32/helper/empty.c
@@ -0,0 +1,5 @@
+//
+// This empty file is here to force build to make this directory.
+//
+
+
diff --git a/private/crt32/helper/makefile b/private/crt32/helper/makefile
new file mode 100644
index 000000000..aa4bbc1a6
--- /dev/null
+++ b/private/crt32/helper/makefile
@@ -0,0 +1,8 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+
diff --git a/private/crt32/helper/mips/llabsdiv.c b/private/crt32/helper/mips/llabsdiv.c
new file mode 100644
index 000000000..3a00d9143
--- /dev/null
+++ b/private/crt32/helper/mips/llabsdiv.c
@@ -0,0 +1,62 @@
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1991, 1990 MIPS Computer Systems, Inc. |
+ * | All Rights Reserved |
+ * |-----------------------------------------------------------|
+ * | Restricted Rights Legend |
+ * | Use, duplication, or disclosure by the Government is |
+ * | subject to restrictions as set forth in |
+ * | subparagraph (c)(1)(ii) of the Rights in Technical |
+ * | Data and Computer Software Clause of DFARS 252.227-7013. |
+ * | MIPS Computer Systems, Inc. |
+ * | 950 DeGuigne Avenue |
+ * | Sunnyvale, California 94088-3650, USA |
+ * |-----------------------------------------------------------|
+ */
+#ident "$Header: llabsdiv.c,v 3010.1 92/05/15 17:22:16 murphy Exp $"
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+/* This is loosely based on: */
+/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
+/* The copyright notice above does not evidence any */
+/* actual or intended publication of such source code. */
+
+/*LINTLIBRARY*/
+#include <stdlib.h>
+#include "lldefs.h"
+
+typedef struct {
+ long_long quot;
+ long_long rem;
+} lldiv_t;
+
+/* ANSI 4.10.6.1 */
+long_long
+llabs(arg)
+long_long arg;
+{
+ return (arg >= 0 ? arg : -arg);
+}
+
+/* ANSI 4.10.6.2 */
+lldiv_t lldiv(numer, denom)
+long_long numer;
+long_long denom;
+{
+ lldiv_t sd;
+
+ if (numer >= 0 && denom < 0) {
+ numer = -numer;
+ sd.quot = -(numer / denom);
+ sd.rem = -(numer % denom);
+ } else if (numer < 0 && denom > 0) {
+ denom = -denom;
+ sd.quot = -(numer / denom);
+ sd.rem = numer % denom;
+ } else {
+ sd.quot = numer / denom;
+ sd.rem = numer % denom;
+ }
+ return(sd);
+}
diff --git a/private/crt32/helper/mips/llbit.c b/private/crt32/helper/mips/llbit.c
new file mode 100644
index 000000000..e79a2c662
--- /dev/null
+++ b/private/crt32/helper/mips/llbit.c
@@ -0,0 +1,127 @@
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1991 MIPS Computer Systems, Inc. |
+ * | All Rights Reserved |
+ * |-----------------------------------------------------------|
+ * | Restricted Rights Legend |
+ * | Use, duplication, or disclosure by the Government is |
+ * | subject to restrictions as set forth in |
+ * | subparagraph (c)(1)(ii) of the Rights in Technical |
+ * | Data and Computer Software Clause of DFARS 52.227-7013. |
+ * | MIPS Computer Systems, Inc. |
+ * | 950 DeGuigne Drive |
+ * | Sunnyvale, CA 94086 |
+ * |-----------------------------------------------------------|
+ */
+/* $Header: llbit.c,v 3010.2 91/12/20 10:24:03 murphy Exp $ */
+
+#include <limits.h>
+#define BITS_PER_LONGLONG 64
+#include "lldefs.h"
+
+/* Disable bit shift intrinsics so this code will work properly. */
+#pragma function(__ll_lshift)
+#pragma function(__ll_rshift)
+#pragma function(__ull_rshift)
+
+extern ulonglong_t
+__ull_bit_extract (ulonglong_t *addr, unsigned start_bit, unsigned length)
+{
+ /* assume 32 < length < 64 */
+
+ unsigned words = start_bit / BITS_PER_LONGLONG;
+ unsigned lbits = start_bit % BITS_PER_LONGLONG;
+ unsigned rbits = BITS_PER_LONGLONG - (lbits + length);
+ llvalue llval, addrval, mask, one;
+
+ addr += words;
+ addrval.ull = *addr;
+ SET_LL(one, 1);
+ SET_LL(mask, 1);
+ mask.ull = __ll_lshift(mask.ull, length);
+ LL_SUB(mask, mask, one);
+ mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */
+ LL_AND(llval, addrval, mask);
+ llval.ull = __ull_rshift(llval.ull, lbits+rbits);
+ return llval.ull;
+}
+
+extern ulonglong_t
+__ull_bit_insert (ulonglong_t *addr, unsigned start_bit, unsigned length, ulonglong_t val)
+{
+ /* assume 32 < length < 64 */
+
+ unsigned words = start_bit / BITS_PER_LONGLONG;
+ unsigned lbits = start_bit % BITS_PER_LONGLONG;
+ unsigned rbits = BITS_PER_LONGLONG - (lbits + length);
+ llvalue llval, addrval, mask, nmask, one;
+
+ addr += words;
+ llval.ull = val;
+ addrval.ull = *addr;
+ SET_LL(one, 1);
+ SET_LL(mask, 1);
+ mask.ull = __ll_lshift(mask.ull, length);
+ LL_SUB(mask, mask, one);
+ mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */
+ LL_NOT(nmask, mask);
+ LL_AND(addrval, addrval, nmask); /* clear the field */
+ llval.ull = __ll_lshift(llval.ull, lbits+rbits);/* clear lhs, rhs */
+ llval.ull = __ull_rshift(llval.ull, rbits);
+ LL_OR(addrval, addrval, llval);
+ *addr = addrval.ull;
+ llval.ull = __ull_rshift(llval.ull, lbits); /* truncated val */
+ return llval.ull;
+}
+
+extern longlong_t
+__ll_bit_extract (ulonglong_t *addr, unsigned start_bit, unsigned length)
+{
+ /* assume 32 < length < 64 */
+
+ unsigned words = start_bit / BITS_PER_LONGLONG;
+ unsigned lbits = start_bit % BITS_PER_LONGLONG;
+ unsigned rbits = BITS_PER_LONGLONG - (lbits + length);
+ llvalue llval, addrval, mask, one;
+
+ addr += words;
+ addrval.ull = *addr;
+ SET_LL(one, 1);
+ SET_LL(mask, 1);
+ mask.ull = __ll_lshift(mask.ull, length);
+ LL_SUB(mask, mask, one);
+ mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */
+ LL_AND(llval, addrval, mask);
+ llval.ull = __ll_lshift(llval.ull, rbits);
+ llval.ull = __ll_rshift(llval.ull, lbits+rbits);
+ return llval.ull;
+}
+
+extern longlong_t
+__ll_bit_insert (ulonglong_t *addr,unsigned start_bit, unsigned length, longlong_t val)
+{
+ /* assume 32 < length < 64 */
+
+ unsigned words = start_bit / BITS_PER_LONGLONG;
+ unsigned lbits = start_bit % BITS_PER_LONGLONG;
+ unsigned rbits = BITS_PER_LONGLONG - (lbits + length);
+ llvalue llval, addrval, mask, nmask, one;
+
+ addr += words;
+ llval.ull = val;
+ addrval.ull = *addr;
+ SET_LL(one, 1);
+ SET_LL(mask, 1);
+ mask.ull = __ll_lshift(mask.ull, length);
+ LL_SUB(mask, mask, one);
+ mask.ull = __ll_lshift(mask.ull, lbits); /* all 1's in field */
+ LL_NOT(nmask, mask);
+ LL_AND(addrval, addrval, nmask); /* clear the field */
+ llval.ull = __ll_lshift(llval.ull, lbits+rbits);/* clear lhs, rhs */
+ llval.ull = __ull_rshift(llval.ull, rbits);
+ LL_OR(addrval, addrval, llval);
+ *addr = addrval.ull;
+ llval.ull = __ll_rshift(llval.ull, lbits); /* truncated val */
+ return llval.ull;
+}
+
diff --git a/private/crt32/helper/mips/llcvt.s b/private/crt32/helper/mips/llcvt.s
new file mode 100644
index 000000000..8a014eb1b
--- /dev/null
+++ b/private/crt32/helper/mips/llcvt.s
@@ -0,0 +1,364 @@
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1991 MIPS Computer Systems, Inc. |
+ * | All Rights Reserved |
+ * |-----------------------------------------------------------|
+ * | Restricted Rights Legend |
+ * | Use, duplication, or disclosure by the Government is |
+ * | subject to restrictions as set forth in |
+ * | subparagraph (c)(1)(ii) of the Rights in Technical |
+ * | Data and Computer Software Clause of DFARS 52.227-7013. |
+ * | MIPS Computer Systems, Inc. |
+ * | 950 DeGuigne Drive |
+ * | Sunnyvale, CA 94086 |
+ * |-----------------------------------------------------------|
+ */
+/* $Header: llcvt.s,v 3010.2 91/12/10 13:24:31 murphy Exp $ */
+
+#include <ksmips.h>
+
+#ifdef _MIPSEL
+# define PLSW a0
+# define PMSW a1
+# define RLSW v0
+# define RMSW v1
+#else /* _MIPSEB */
+# define PMSW a0
+# define PLSW a1
+# define RMSW v0
+# define RLSW v1
+#endif
+
+/* Convert from 64-bit signed integer to double precision. */
+/* double ll_to_d(ll) */
+
+.globl __ll_to_d
+.ent __ll_to_d
+__ll_to_d:
+ .frame sp, 0, ra
+ mtc1 PMSW, $f0
+ mtc1 PLSW, $f2
+ move t0, PLSW
+ li.d $f8, 4294967296.0 /* 2^32 */
+ cvt.d.w $f0
+ cvt.d.w $f2
+ mul.d $f0, $f8
+ bgez t0, 12f
+ /* sign bit of LSW was set */
+ add.d $f2, $f8 /* correct LSW conversion */
+12: add.d $f0, $f2 /* add low part to high */
+ j ra
+.end __ll_to_d
+
+/* Convert from 64-bit unsigned integer to double precision. */
+/* double ull_to_d(ll) */
+
+.globl __ull_to_d
+.ent __ull_to_d
+__ull_to_d:
+ .frame sp, 0, ra
+ mtc1 PMSW, $f0
+ mtc1 PLSW, $f2
+ move t0, PLSW
+ move t1, PMSW
+ li.d $f8, 4294967296.0 /* 2^32 */
+ cvt.d.w $f0
+ cvt.d.w $f2
+ bgez t1, 12f
+ /* sign bit of MSW was set */
+ add.d $f0, $f8 /* correct MSW conversion */
+12: mul.d $f0, $f8
+ bgez t0, 14f
+ /* sign bit of LSW was set */
+ add.d $f2, $f8 /* correct LSW conversion */
+14: add.d $f0, $f2 /* add low part to high */
+ j ra
+.end __ull_to_d
+
+/* Convert from 64-bit signed integer to single precision. */
+/* float ll_to_f(ll) */
+
+.globl __ll_to_f
+.ent __ll_to_f
+__ll_to_f:
+ .frame sp, 0, ra
+ cfc1 t4, $31 /* save FCSR */
+ ctc1 $0, $31 /* set safe FCSR */
+ mtc1 PMSW, $f2
+ mtc1 PLSW, $f4
+ move t0, PLSW
+ li.d $f8, 4294967296.0 /* 2^32 */
+ cvt.d.w $f2
+ cvt.d.w $f4
+ mul.d $f2, $f8 /* shift up MSW value */
+ bgez t0, 12f
+ /* sign bit of LSW was set */
+ add.d $f4, $f8 /* correct LSW convert */
+12: add.d $f0, $f2, $f4 /* add low part to high */
+ cfc1 t1, $31 /* check for inexact */
+ and t1, 4
+ bne t1, 0, 14f
+ /* conversion to double was exact */
+ ctc1 t4, $31
+ cvt.s.d $f0
+ j ra
+14: /* conversion to double was not exact, so cvt.s.d would be double round */
+ li t0, 1 /* mode = round-to-0 */
+ ctc1 t0, $31
+ cvt.s.d $f0, $f2 /* move 8 bits from high to low double */
+ cvt.d.s $f0
+ sub.d $f6, $f2, $f0
+ add.d $f4, $f6
+ mfc1 t2, $f1 /* add value that pushes high 24 bits */
+ srl t2, 20 /* to low end of double */
+ addu t2, (53-24)
+ sll t2, 20
+ mtc1 t2, $f9
+ mtc1 $0, $f8
+ ctc1 t4, $31 /* restore FCSR */
+ add.d $f0, $f8 /* add bias */
+ add.d $f0, $f4 /* add low part with round to 24
+ bits of precision */
+ sub.d $f0, $f8 /* remove bias */
+ cvt.s.d $f0
+ j ra
+.end __ll_to_f
+
+/* Convert from 64-bit unsigned integer to single precision. */
+/* float ull_to_f(ll) */
+
+.globl __ull_to_f
+.ent __ull_to_f
+__ull_to_f:
+ .frame sp, 0, ra
+ cfc1 t4, $31 /* save FCSR */
+ ctc1 $0, $31 /* set safe FCSR */
+ mtc1 PMSW, $f2
+ mtc1 PLSW, $f4
+ move t0, PLSW
+ move t1, PMSW
+ li.d $f8, 4294967296.0 /* 2^32 */
+ cvt.d.w $f2
+ cvt.d.w $f4
+ bgez t1, 12f
+ /* sign bit of MSW was set */
+ add.d $f2, $f8 /* correct MSW convert */
+12: mul.d $f2, $f8 /* shift up MSW value */
+ bgez t0, 14f
+ /* sign bit of LSW was set */
+ add.d $f4, $f8 /* correct LSW convert */
+14: add.d $f0, $f2, $f4 /* add low part to high */
+ cfc1 t1, $31 /* check for inexact */
+ and t1, 4
+ bne t1, 0, 14f
+ /* conversion to double was exact */
+ ctc1 t4, $31
+ cvt.s.d $f0
+ j ra
+14: /* conversion to double was not exact, so cvt.s.d would be double round */
+ li t0, 1 /* mode = round-to-0 */
+ ctc1 t0, $31
+ cvt.s.d $f0, $f2 /* move 8 bits from high to low double */
+ cvt.d.s $f0
+ sub.d $f6, $f2, $f0
+ add.d $f4, $f6
+ mfc1 t2, $f1 /* add value that pushes high 24 bits */
+ srl t2, 20 /* to low end of double */
+ addu t2, (53-24)
+ sll t2, 20
+ mtc1 t2, $f9
+ mtc1 $0, $f8
+ ctc1 t4, $31 /* restore FCSR */
+ add.d $f0, $f8 /* add bias */
+ add.d $f0, $f4 /* add low part with round to 24
+ bits of precision */
+ sub.d $f0, $f8 /* remove bias */
+ cvt.s.d $f0
+ j ra
+.end __ull_to_f
+
+/* Convert from double precision to 64-bit integer. */
+/* This is a common routine for signed and unsigned case;
+ * the only difference is the max value, which is passed in $f4. */
+/* C rules require truncating the value */
+/* longlong dtoll (double); */
+.globl __dtoll
+.ent __dtoll
+__dtoll:
+ .frame sp, 0, ra
+ cfc1 t6, $31
+ li t7, 1 /* round to zero (truncate) */
+ ctc1 t7, $31
+ mfc1 t8, $f13
+ li.d $f2, 4.5035996273704960e+15 /* 2^52 */
+ bltz t8, 10f
+
+ /* x >= 0 */
+ c.ult.d $f12, $f2
+ bc1f 20f
+
+ /* 0 <= x < 2^52 -- needs rounding */
+ /* x + 2^52 may be = 2^53 after rounding -- this still works */
+ add.d $f0, $f12, $f2 /* round */
+ mfc1 RLSW, $f0
+ mfc1 RMSW, $f1
+ subu RMSW, ((52+1023)<<20)
+ b 50f
+
+10: /* x < 0 */
+ neg.d $f2
+ c.ult.d $f2, $f12
+ bc1f 30f
+
+ /* -2^52 < x < 0 -- needs rounding */
+ /* x - 2^52 may be = -2^53 after rounding -- this still works */
+ add.d $f0, $f12, $f2 /* round */
+ mfc1 RLSW, $f0
+ mfc1 RMSW, $f1
+ subu RMSW, ((52+1023+2048)<<20)
+ /* double word negate */
+ sltu t3, RLSW, 1
+ negu RLSW
+ not RMSW
+ addu RMSW, t3
+ b 50f
+
+20: /* x >= 2^52 or NaN */
+ /* compare against $f4, which is either 2^63-1 or 2^64-1 */
+ mfc1 RLSW, $f12
+ mfc1 t1, $f13
+ c.ult.d $f12, $f4
+ bc1f 40f
+
+ /* 2^52 <= x < 2^63/4 */
+ li t2, (1<<20) /* hidden bit in high word */
+ subu t3, t2, 1 /* mask for high word */
+ and RMSW, t1, t3 /* mask out exponent */
+ or RMSW, t2 /* add back hidden bit */
+ srl t0, t1, 20 /* shift = exponent - (52+bias) */
+ subu t0, 1023+52 /* ... */
+ negu t4, t0 /* high |= low >> (32-shift) */
+ srl t5, RLSW, t4 /* ... */
+ sll RMSW, t0 /* high <<= shift */
+ sll RLSW, t0 /* low <<= shift */
+ beq t0, 0, 50f /* if shift = 0, that's all */
+ or RMSW, t5 /* else add bits shifted out of low */
+ b 50f
+
+30: /* x <= -2^52 or NaN */
+
+ li.d $f2, -9.2233720368547758e+18 /* -2^63 */
+ mfc1 RLSW, $f12
+ mfc1 t1, $f13
+ c.ule.d $f2, $f12
+ bc1f 40f
+
+ /* -2^63 <= x <= -2^52 */
+ li t2, (1<<20) /* hidden bit in high word */
+ subu t3, t2, 1 /* mask for high word */
+ and RMSW, t1, t3 /* mask out exponent */
+ or RMSW, t2 /* add back hidden bit */
+ srl t0, t1, 20 /* shift = exponent - (52+bias) */
+ subu t0, 52+1023+2048 /* ... */
+ negu t4, t0 /* high |= low >> (32-shift) */
+ srl t5, RLSW, t4 /* ... */
+ sll RMSW, t0 /* high <<= shift */
+ sll RLSW, t0 /* low <<= shift */
+ beq t0, 0, 32f /* if shift = 0, that's all */
+ or RMSW, t5 /* else add bits shifted out of low */
+32: /* double word negate */
+ sltu t3, RLSW, 1
+ negu RLSW
+ not RMSW
+ addu RMSW, t3
+ b 50f
+
+40: /* x is NaN or x < -2^63 or x >= 2^63/4 */
+ /* raise Invalid */
+ li RMSW, 0x7fffffff /* signed case */
+ li RLSW, 0xffffffff
+ li.d $f2, 9.223372036854775807e+18 /* 2^63-1 */
+ c.ueq.d $f2, $f4
+ bc1t 42f
+ li RMSW, 0xffffffff /* unsigned case */
+42:
+ cfc1 t0, $31
+ or t0, ((1<<12)|(1<<2))
+ ctc1 t0, $31
+ b 50f
+50:
+ cfc1 t7, $31
+ and t7, -4
+ or t6, t7
+ ctc1 t6, $31
+ j ra
+.end __dtoll
+
+/* Convert from double precision to 64-bit signed integer. */
+/* C rules require truncating the value */
+/* longlong d_to_ll (double); */
+.globl __d_to_ll
+.ent __d_to_ll
+__d_to_ll:
+ subu sp, 32
+ sw ra, 28(sp)
+ .mask 0x80000000, -4
+ .frame sp, 32, ra
+ li.d $f4, 9.223372036854775807e+18 /* 2^63-1 */
+ jal __dtoll
+ /* use v0,v1 that are already set */
+ lw ra, 28(sp)
+ addu sp, 32
+ j ra
+.end __d_to_ll
+
+/* longlong f_to_ll (float) */
+.globl __f_to_ll
+.ent __f_to_ll
+__f_to_ll:
+ subu sp, 32
+ sw ra, 28(sp)
+ .mask 0x80000000, -4
+ .frame sp, 32, ra
+ cvt.d.s $f12, $f12
+ jal __d_to_ll
+ /* use v0,v1 that are already set */
+ lw ra, 28(sp)
+ addu sp, 32
+ j ra
+.end __f_to_ll
+
+/* Convert from double precision to 64-bit unsigned integer. */
+/* C rules require truncating the value */
+/* ulonglong d_to_ull (double); */
+.globl __d_to_ull
+.ent __d_to_ull
+__d_to_ull:
+ subu sp, 32
+ sw ra, 28(sp)
+ .mask 0x80000000, -4
+ .frame sp, 32, ra
+ li.d $f4, 1.8446744073709551615e+19 /* 2^64-1 */
+ jal __dtoll
+ /* use v0,v1 that are already set */
+ lw ra, 28(sp)
+ addu sp, 32
+ j ra
+.end __d_to_ull
+
+/* ulonglong f_to_ull (float) */
+.globl __f_to_ull
+.ent __f_to_ull
+__f_to_ull:
+ subu sp, 32
+ sw ra, 28(sp)
+ .mask 0x80000000, -4
+ .frame sp, 32, ra
+ cvt.d.s $f12, $f12
+ jal __d_to_ull
+ /* use v0,v1 that are already set */
+ lw ra, 28(sp)
+ addu sp, 32
+ j ra
+.end __f_to_ull
+
diff --git a/private/crt32/helper/mips/lldefs.h b/private/crt32/helper/mips/lldefs.h
new file mode 100644
index 000000000..41e6ee5ad
--- /dev/null
+++ b/private/crt32/helper/mips/lldefs.h
@@ -0,0 +1,92 @@
+
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1991 MIPS Computer Systems, Inc. |
+ * | All Rights Reserved |
+ * |-----------------------------------------------------------|
+ * | Restricted Rights Legend |
+ * | Use, duplication, or disclosure by the Government is |
+ * | subject to restrictions as set forth in |
+ * | subparagraph (c)(1)(ii) of the Rights in Technical |
+ * | Data and Computer Software Clause of DFARS 52.227-7013. |
+ * | MIPS Computer Systems, Inc. |
+ * | 950 DeGuigne Drive |
+ * | Sunnyvale, CA 94086 |
+ * |-----------------------------------------------------------|
+ */
+/* $Header: lldefs.h,v 3010.4 92/01/23 13:50:07 murphy Exp $ */
+
+/* define double-word (long long) simulation routines for 32-bit code. */
+
+#define long_long __int64
+typedef long_long longlong_t;
+typedef unsigned long_long ulonglong_t;
+
+typedef struct {
+/* _MIPSEL */
+ unsigned lsw;
+ unsigned msw;
+} dword;
+
+typedef union {
+ longlong_t ll;
+ ulonglong_t ull;
+ dword dw;
+} llvalue; /* 64-bit integer values */
+
+#define MSW(x) (x).dw.msw
+#define LSW(x) (x).dw.lsw
+
+#define LL_ISNEG(x) ((signed)MSW(x) < 0) /* returns boolean */
+
+/* relational operations; all take two llvalues and return boolean */
+#define LL_EQ(x,y) (LSW(x) == LSW(y) && MSW(x) == MSW(y))
+#define LL_NEQ(x,y) (LSW(x) != LSW(y) || MSW(x) != MSW(y))
+#define MSW_EQ(x,y) (MSW(x) == MSW(y))
+#define LL_LT(x,y) (MSW_EQ(x,y) ? (LSW(x) < LSW(y)) : ((int)MSW(x) < (int)MSW(y)))
+#define ULL_LT(x,y) (MSW_EQ(x,y) ? (LSW(x) < LSW(y)) : (MSW(x) < MSW(y)))
+#define LL_LE(x,y) (MSW_EQ(x,y) ? (LSW(x) <= LSW(y)) : ((int)MSW(x) < (int)MSW(y)))
+#define ULL_LE(x,y) (MSW_EQ(x,y) ? (LSW(x) <= LSW(y)) : (MSW(x) < MSW(y)))
+#define LL_GT(x,y) (MSW_EQ(x,y) ? (LSW(x) > LSW(y)) : ((int)MSW(x) > (int)MSW(y)))
+#define ULL_GT(x,y) (MSW_EQ(x,y) ? (LSW(x) > LSW(y)) : (MSW(x) > MSW(y)))
+#define LL_GE(x,y) (MSW_EQ(x,y) ? (LSW(x) >= LSW(y)) : ((int)MSW(x) > (int)MSW(y)))
+#define ULL_GE(x,y) (MSW_EQ(x,y) ? (LSW(x) >= LSW(y)) : (MSW(x) > MSW(y)))
+
+/* these routines are actually statements! */
+#define LL_AND(r,x,y) MSW(r) = MSW(x) & MSW(y), LSW(r) = LSW(x) & LSW(y)
+#define LL_OR(r,x,y) MSW(r) = MSW(x) | MSW(y), LSW(r) = LSW(x) | LSW(y)
+#define LL_XOR(r,x,y) MSW(r) = MSW(x) ^ MSW(y), LSW(r) = LSW(x) ^ LSW(y)
+#define LL_NOT(r,x) MSW(r) = ~MSW(x), LSW(r) = ~LSW(x)
+#define LL_ADD(r,x,y) MSW(r) = MSW(x) + MSW(y) + ((LSW(x)+LSW(y)) < LSW(y)); LSW(r) = LSW(x) + LSW(y)
+#define LL_SUB(r,x,y) MSW(r) = MSW(x) - MSW(y) - (LSW(x) < LSW(y)); LSW(r) = LSW(x) - LSW(y)
+#define LL_NEG(r,x) MSW(r) = ~MSW(x) + (LSW(x) == 0); LSW(r) = -LSW(x)
+#define SET_LL(x,i) LSW(x) = i, MSW(x) = (i < 0 ? -1 : 0)
+
+/* external routines */
+extern longlong_t __ll_mul (longlong_t ll_value, longlong_t multiplier);
+extern longlong_t __ll_lshift (longlong_t ll_value, long ll_lshift);
+extern longlong_t __ll_rshift (longlong_t ll_value, long ll_rshift);
+extern longlong_t __ull_rshift (ulonglong_t ull_value, long ll_rshift);
+extern longlong_t __ll_div (longlong_t divident, longlong_t divisor);
+extern ulonglong_t __ull_div (ulonglong_t divident, ulonglong_t divisor);
+extern longlong_t __ll_rem (longlong_t divident, longlong_t divisor);
+extern ulonglong_t __ull_rem (ulonglong_t divident, ulonglong_t divisor);
+extern void __ull_divremi (ulonglong_t *quotient, ulonglong_t *remainder, ulonglong_t dividend, unsigned short divisor);
+extern longlong_t __ll_mod (longlong_t ll_value, longlong_t modulus);
+extern longlong_t __d_to_ll (double);
+extern longlong_t __f_to_ll (float);
+extern ulonglong_t __d_to_ull (double);
+extern ulonglong_t __f_to_ull (float);
+extern double __ll_to_d (longlong_t);
+extern float __ll_to_f (longlong_t);
+extern double __ull_to_d (ulonglong_t);
+extern float __ull_to_f (ulonglong_t);
+extern ulonglong_t __ull_bit_extract (ulonglong_t *addr,
+ unsigned start_bit, unsigned length);
+extern ulonglong_t __ull_bit_insert (ulonglong_t *addr,
+ unsigned start_bit, unsigned length, ulonglong_t val);
+extern longlong_t __ll_bit_extract (ulonglong_t *addr,
+ unsigned start_bit, unsigned length);
+extern longlong_t __ll_bit_insert (ulonglong_t *addr,
+ unsigned start_bit, unsigned length, longlong_t val);
+
diff --git a/private/crt32/helper/mips/lldiv.c b/private/crt32/helper/mips/lldiv.c
new file mode 100644
index 000000000..140dffabb
--- /dev/null
+++ b/private/crt32/helper/mips/lldiv.c
@@ -0,0 +1,251 @@
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1991 MIPS Computer Systems, Inc. |
+ * | All Rights Reserved |
+ * |-----------------------------------------------------------|
+ * | Restricted Rights Legend |
+ * | Use, duplication, or disclosure by the Government is |
+ * | subject to restrictions as set forth in |
+ * | subparagraph (c)(1)(ii) of the Rights in Technical |
+ * | Data and Computer Software Clause of DFARS 52.227-7013. |
+ * | MIPS Computer Systems, Inc. |
+ * | 950 DeGuigne Drive |
+ * | Sunnyvale, CA 94086 |
+ * |-----------------------------------------------------------|
+ */
+/* $Header: lldiv.c,v 3010.7 92/01/29 16:02:33 murphy Exp $ */
+
+#include "lldefs.h"
+
+/*
+ Make sure that the intrinsic bit shift routines are not used!
+ They are guaranteed to work only for shifts of 0-31 bits.
+ */
+#pragma function(__ll_lshift)
+#pragma function(__ll_rshift)
+#pragma function(__ull_rshift)
+
+extern void __ull_divrem_6416 (ulonglong_t *q, ulonglong_t *r, ulonglong_t n, ulonglong_t d);
+extern void __ull_divrem_5353 (ulonglong_t *q, ulonglong_t *r, ulonglong_t n, ulonglong_t d);
+static void __ull_divrem_6464 (llvalue *aquo, llvalue *arem, llvalue num, llvalue denom);
+
+#define pow2_16 65536 /* 2^16 */
+#define pow2_21 2097152 /* 2^(53-32) */
+
+/* Given an unsigned64 number, return the number of left-shifts required
+ to normalize it (causing high-order digit to be 1) */
+static
+unsigned
+ll_firstbit(llvalue number)
+{
+ unsigned bias = 0;
+
+ if (MSW(number) == 0)
+ {
+ if (LSW(number) != 0)
+ {
+ bias = 32;
+ while ((LSW(number) & 0x80000000) == 0)
+ {
+ bias++;
+ LSW(number) <<= 1;
+ }
+ }
+ }
+ else
+ {
+ while ((MSW(number) & 0x80000000) == 0)
+ {
+ bias++;
+ MSW(number) <<= 1;
+ }
+ }
+
+ return bias;
+}
+
+/*
+ * General (i.e., difficult) case of 64-bit unsigned division.
+ * Use this to handle cases where values are greater than can be
+ * represented with 53-bits of double floats.
+ * Modified from pl1 library.
+ */
+static
+void
+__ull_divrem_6464 (llvalue *aquo, llvalue *arem, llvalue num, llvalue denom)
+{
+ llvalue quo;
+ int n_bias, d_bias;
+
+ /* Shift denom left so its first bit lines up with that of numerator */
+ n_bias = ll_firstbit(num);
+ d_bias = ll_firstbit(denom);
+ if ((d_bias -= n_bias) > 0) {
+ denom.ll = __ll_lshift(denom.ll, d_bias);
+ }
+
+ /*
+ "Long division" just like you did in elementary school, except that
+ by virtue of doing it in binary, we can guess the next digit simply
+ by comparing numerator and divisor.
+
+ quo = 0;
+ repeat (1 + amount_we_shifted_denom_left)
+ {
+ quo <<= 1;
+ if (!(num < denom))
+ {
+ num -= denom;
+ quo |= 1;
+ }
+ denom >>= 1;
+ }
+ */
+ MSW(quo) = LSW(quo) = 0;
+ while (d_bias-- >= 0)
+ {
+ quo.ll = __ll_lshift(quo.ll, 1);
+
+ if (ULL_GE(num, denom))
+ {
+ LL_SUB(num, num, denom); /* num -= denom */
+ LSW(quo) |= 1;
+ }
+ denom.ll = __ull_rshift(denom.ll, 1);
+ }
+
+ *aquo = quo;
+ *arem = num;
+}
+
+
+extern longlong_t
+__ll_div (longlong_t left, longlong_t right)
+{
+ llvalue a,b,q,r;
+ llvalue ll_2_16, ll_2_53;
+ int negate = 0;
+ a.ll = left;
+ b.ll = right;
+ SET_LL(ll_2_16, pow2_16);
+ MSW(ll_2_53) = pow2_21; LSW(ll_2_53) = 0;
+ if (LL_ISNEG(a)) {
+ /* make positive, but later negate the quotient */
+ negate = !negate;
+ LL_NEG(a,a);
+ }
+ if (LL_ISNEG(b)) {
+ /* make positive, but later negate the quotient */
+ negate = !negate;
+ LL_NEG(b,b);
+ }
+ /* dividend is positive */
+ if (ULL_LT(b,ll_2_16)) {
+ /* divide 64 bits by 16 bits */
+ __ull_divrem_6416(&q.ull,&r.ull,a.ull,b.ull);
+ } else if (ULL_LE(a,ll_2_53) && ULL_LE(b,ll_2_53)) {
+ /* do fp double divide */
+ __ull_divrem_5353(&q.ull,&r.ull,a.ull,b.ull);
+ } else {
+ /* do full 64-bit divide */
+ __ull_divrem_6464(&q,&r, a, b);
+ }
+ if (negate) {
+ LL_NEG(q,q);
+ }
+ return q.ll;
+}
+
+extern ulonglong_t
+__ull_div (ulonglong_t left, ulonglong_t right)
+{
+ llvalue a,b,q,r;
+ llvalue ll_2_16, ll_2_53;
+ a.ull = left;
+ b.ull = right;
+ SET_LL(ll_2_16, pow2_16);
+ MSW(ll_2_53) = pow2_21; LSW(ll_2_53) = 0;
+ if (ULL_LT(b,ll_2_16)) {
+ __ull_divrem_6416(&q.ull,&r.ull,left,right);
+ } else if (ULL_LE(a,ll_2_53) && ULL_LE(b,ll_2_53)) {
+ __ull_divrem_5353(&q.ull,&r.ull,left,right);
+ } else {
+ __ull_divrem_6464(&q,&r,a,b);
+ }
+ return q.ull;
+}
+
+extern longlong_t
+__ll_rem (longlong_t left, longlong_t right)
+{
+ llvalue a,b,q,r;
+ llvalue ll_2_16, ll_2_53;
+ int negate = 0;
+ a.ll = left;
+ b.ll = right;
+ SET_LL(ll_2_16, pow2_16);
+ MSW(ll_2_53) = pow2_21; LSW(ll_2_53) = 0;
+ if (LL_ISNEG(a)) {
+ /* make positive, but later negate the remainder */
+ negate = !negate;
+ LL_NEG(a,a);
+ }
+ if (LL_ISNEG(b)) {
+ /* make positive, remainder only depends on sign of num */
+ LL_NEG(b,b);
+ }
+ /* dividend is positive */
+ if (ULL_LT(b,ll_2_16)) {
+ /* divide 64 bits by 16 bits */
+ __ull_divrem_6416(&q.ull,&r.ull,a.ull,b.ull);
+ } else if (ULL_LE(a,ll_2_53) && ULL_LE(b,ll_2_53)) {
+ /* do fp double divide */
+ __ull_divrem_5353(&q.ull,&r.ull,a.ull,b.ull);
+ } else {
+ /* do full 64-bit divide */
+ __ull_divrem_6464(&q,&r, a, b);
+ }
+ if (negate) {
+ LL_NEG(r,r);
+ }
+ return r.ll;
+}
+
+extern ulonglong_t
+__ull_rem (ulonglong_t left, ulonglong_t right)
+{
+ llvalue a,b,q,r;
+ llvalue ll_2_16, ll_2_53;
+ a.ll = left;
+ b.ll = right;
+ SET_LL(ll_2_16, pow2_16);
+ MSW(ll_2_53) = pow2_21; LSW(ll_2_53) = 0;
+ if (ULL_LT(b,ll_2_16)) {
+ __ull_divrem_6416(&q.ull,&r.ull,left,right);
+ } else if (ULL_LE(a,ll_2_53) && ULL_LE(b,ll_2_53)) {
+ __ull_divrem_5353(&q.ull,&r.ull,left,right);
+ } else {
+ __ull_divrem_6464(&q,&r,a,b);
+ }
+ return r.ull;
+}
+
+extern
+longlong_t
+__ll_mod (longlong_t left, longlong_t right)
+{
+ /* mod is similar to rem except that:
+ * 11 rem 5 == 1 == 11 mod 5
+ * 11 rem -5 == 1, 11 mod -5 == -4
+ * -11 rem 5 == -1, -11 mod 5 == 4
+ * -11 rem -5 == -1 == -11 mod -5
+ */
+ llvalue b,r;
+ b.ll = right;
+ r.ll = __ll_rem(left,right);
+ if (LL_ISNEG(r) != LL_ISNEG(b)) {
+ LL_ADD(r,r,b);
+ }
+ return r.ll;
+}
+
diff --git a/private/crt32/helper/mips/lldivrem.s b/private/crt32/helper/mips/lldivrem.s
new file mode 100644
index 000000000..83320a490
--- /dev/null
+++ b/private/crt32/helper/mips/lldivrem.s
@@ -0,0 +1,237 @@
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1991 MIPS Computer Systems, Inc. |
+ * | All Rights Reserved |
+ * |-----------------------------------------------------------|
+ * | Restricted Rights Legend |
+ * | Use, duplication, or disclosure by the Government is |
+ * | subject to restrictions as set forth in |
+ * | subparagraph (c)(1)(ii) of the Rights in Technical |
+ * | Data and Computer Software Clause of DFARS 52.227-7013. |
+ * | MIPS Computer Systems, Inc. |
+ * | 950 DeGuigne Drive |
+ * | Sunnyvale, CA 94086 |
+ * |-----------------------------------------------------------|
+ */
+/* $Header: lldivrem.s,v 3010.3 92/01/29 15:27:35 murphy Exp $ */
+
+#include <ksmips.h>
+
+/* __ull_divrem (unsigned long long *quotient, *remainder, dividend, divisor) */
+
+#ifdef _MIPSEL
+# define LSH 0
+# define MSH 2
+# define LQUO 0(a0)
+# define MQUO 4(a0)
+# define LREM 0(a1)
+# define MREM 4(a1)
+# define LDEN a2
+# define MDEN a3
+# define LSOR 16(sp)
+# define MSOR 20(sp)
+#endif
+#ifdef _MIPSEB
+# define MSH 0
+# define LSH 2
+# define MQUO 0(a0)
+# define LQUO 4(a0)
+# define MREM 0(a1)
+# define LREM 4(a1)
+# define MDEN a2
+# define LDEN a3
+# define MSOR 16(sp)
+# define LSOR 20(sp)
+#endif
+
+.text
+
+/* ulldivrem (unsigned long long *quotient, unsigned long long *remainder,
+ * unsigned long long dividend, unsigned long long divisor); */
+/* unsigned division */
+/* assume that dividend is 64bit positive value;
+ * divisor is 16bit positive value. */
+.globl __ull_divrem_6416
+.ent __ull_divrem_6416
+__ull_divrem_6416:
+ .frame sp, 0, ra
+ move t0, LDEN /* dividend */
+ move t1, MDEN
+ lw t2, LSOR /* divisor */
+ lw t3, MSOR
+ divu zero, t0, t2 /* early start for first case */
+ /* test if both dividend and divisor are 32-bit values */
+ sra t4, t0, 31
+ bnez t3, 3f /* divisor not 32-bit */
+ /* divisor is 32-bit */
+ bnez t1, 1f /* dividend not 32-bit */
+ /* simply use 32-bit divide instruction */
+ mflo v0
+ mfhi t4
+ sw v0, LQUO
+ sw zero, MQUO
+ sw t4, LREM
+ sw zero, MREM
+ j ra
+
+ /* divisor 32-bit, dividend not */
+1: srl t4, t2, 16
+ bne t4, 0, 3f
+
+ /* dividing 64-bit positive value by 16-bit unsigned value */
+/*#ifdef _MIPSEL*/
+/* sll v0, MDEN, 16*/
+/*#else*/
+ move v0, MDEN
+/*#endif*/
+ srl v0, v0, 16 /* get 16-bit MSH value from MDEN */
+ divu zero, v0, t2
+ mflo v1
+ mfhi v0
+ sh v1, MSH+MQUO
+ sll v0, 16
+/*#ifdef _MIPSEB*/
+ sll t0, MDEN, 16
+/*#else*/
+/* move t0, MDEN*/
+/*#endif*/
+ srl t0, t0, 16 /* get 16-bit LSH value from MDEN */
+ or v0, t0
+ divu zero, v0, t2
+ mflo v1
+ mfhi v0
+ sh v1, LSH+MQUO
+ sll v0, 16
+/*#ifdef _MIPSEL*/
+/* sll t0, LDEN, 16*/
+/*#else*/
+ move t0, LDEN
+/*#endif*/
+ srl t0, t0, 16 /* get 16-bit MSH value from LDEN */
+ or v0, t0
+ divu zero, v0, t2
+ mflo v1
+ mfhi v0
+ sh v1, MSH+LQUO
+ sll v0, 16
+/*#ifdef _MIPSEB*/
+ sll t0, LDEN, 16
+/*#else*/
+/* move t0, LDEN*/
+/*#endif*/
+ srl t0, t0, 16 /* get 16-bit LSH value from LDEN */
+ or v0, t0
+ divu zero, v0, t2
+ mflo v1
+ mfhi v0
+ sh v1, LSH+LQUO
+ sw zero, MREM
+ sw v0, LREM
+ j ra
+
+ /* if dividend < divisor then quo = 0, rem = dividend */
+3: lw t0, MSOR
+ bgtu MDEN, t0, 36f
+ bltu MDEN, t0, 32f
+ /* MDEN == MSOR */
+ lw t0, LSOR
+ bgeu LDEN, t0, 36f
+32: sw zero, LQUO
+ sw zero, MQUO
+ sw LDEN, LREM
+ sw MDEN, MREM
+ j ra
+
+ /* dividend or divisor too big; have to do division the hard way */
+36: break 0
+.end __ull_divrem_6416
+
+/* ulldivrem (unsigned long long *quotient, unsigned long long *remainder,
+ * unsigned long long dividend, unsigned long long divisor); */
+/* unsigned division */
+/* assume that dividend and divisor both fit in 53 bits,
+ * so do double fp divide. */
+.globl __ull_divrem_5353
+.ent __ull_divrem_5353
+__ull_divrem_5353:
+ .frame sp, 0, ra
+ move t0, LDEN /* dividend */
+ move t1, MDEN
+ lw t2, LSOR /* divisor */
+ lw t3, MSOR
+
+2: li.d $f8, 4294967296.0
+ cfc1 v1, $31
+ li t5, 1
+ ctc1 t5, $31
+
+ mtc1 t0, $f0
+ mtc1 t1, $f2
+ cvt.d.w $f0
+ cvt.d.w $f2
+ bgez t0, 22f
+ add.d $f0, $f8
+22: mul.d $f2, $f8
+ add.d $f0, $f2
+
+ mtc1 t2, $f4
+ mtc1 t3, $f6
+ cvt.d.w $f4
+ cvt.d.w $f6
+ bgez t2, 24f
+ add.d $f4, $f8
+24: mul.d $f6, $f8
+ add.d $f4, $f6
+ cfc1 t9, $31
+ and t9, 4
+ bne t9, 0, 3f
+
+ div.d $f2, $f0, $f4
+ li.d $f6, 4503599627370496.0
+ mfc1 t9, $f3
+ bgez t9, 26f
+ neg.d $f6
+26: add.d $f2, $f6
+ mfc1 t4, $f2
+ mfc1 t5, $f3
+ and t5, 0x000fffff
+
+ multu t4, t2
+ mflo t6
+ mfhi t7
+ multu t4, t3
+ mflo t8
+ addu t7, t8
+ multu t5, t2
+ mflo t8
+ addu t7, t8
+
+ sltu t9, t0, t6
+ subu t6, t0, t6
+ subu t7, t1, t7
+ subu t7, t9
+
+ sw t4, LQUO
+ sw t5, MQUO
+ sw t6, LREM
+ sw t7, MREM
+
+ ctc1 v1, $31
+ j ra
+
+ /* if dividend < divisor then quo = 0, rem = dividend */
+3: lw t0, MSOR
+ bgtu MDEN, t0, 36f
+ bltu MDEN, t0, 32f
+ /* MDEN == MSOR */
+ lw t0, LSOR
+ bgeu LDEN, t0, 36f
+32: sw zero, LQUO
+ sw zero, MQUO
+ sw LDEN, LREM
+ sw MDEN, MREM
+ j ra
+
+ /* dividend or divisor too big; have to do division the hard way */
+36: break 0
+.end __ull_divrem_5353
diff --git a/private/crt32/helper/mips/llmul.s b/private/crt32/helper/mips/llmul.s
new file mode 100644
index 000000000..612b2384c
--- /dev/null
+++ b/private/crt32/helper/mips/llmul.s
@@ -0,0 +1,57 @@
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1991 MIPS Computer Systems, Inc. |
+ * | All Rights Reserved |
+ * |-----------------------------------------------------------|
+ * | Restricted Rights Legend |
+ * | Use, duplication, or disclosure by the Government is |
+ * | subject to restrictions as set forth in |
+ * | subparagraph (c)(1)(ii) of the Rights in Technical |
+ * | Data and Computer Software Clause of DFARS 52.227-7013. |
+ * | MIPS Computer Systems, Inc. |
+ * | 950 DeGuigne Drive |
+ * | Sunnyvale, CA 94086 |
+ * |-----------------------------------------------------------|
+ */
+/* $Header: llmul.s,v 3010.1 91/09/05 17:13:51 murphy Exp $ */
+
+#include <ksmips.h>
+
+/* long long __ll_mul (long long a, long long b) */
+
+#ifdef _MIPSEL
+# define RLSW v0
+# define RMSW v1
+# define ALSW a0
+# define AMSW a1
+# define BLSW a2
+# define BMSW a3
+#else /* _MIPSEB */
+# define RMSW v0
+# define RLSW v1
+# define AMSW a0
+# define ALSW a1
+# define BMSW a2
+# define BLSW a3
+#endif
+
+.text
+
+/* note that result of AMSW * BMSW overflows 64bits, so it is ignored. */
+
+.globl __ll_mul
+.ent __ll_mul
+__ll_mul:
+ .frame sp, 0, ra
+ multu ALSW, BLSW
+ mflo RLSW
+ mfhi RMSW
+ multu AMSW, BLSW
+ mflo t0
+ addu RMSW, t0
+ multu ALSW, BMSW
+ mflo t0
+ addu RMSW, t0
+ j ra
+.end __ll_mul
+
diff --git a/private/crt32/helper/mips/llshift.s b/private/crt32/helper/mips/llshift.s
new file mode 100644
index 000000000..e0f61cbc6
--- /dev/null
+++ b/private/crt32/helper/mips/llshift.s
@@ -0,0 +1,226 @@
+// TITLE("Large Integer Arithmetic")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+//
+// Module Name:
+//
+// largeint.s
+//
+// Abstract:
+//
+// This module implements __int64 arithmetic helper routines for the MIPS Compiler.
+//
+//
+// Author:
+//
+// David N. Cutler (davec) 18-Apr-1990
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// This module is derived from largeint.s in ntos\rtl\mips\largeint.s
+//
+//--
+
+#include "ksmips.h"
+
+ SBTTL("int64 Shift Left")
+
+//++
+//
+// LARGE_INTEGER
+// RtlLargeIntegerShiftLeft (
+// IN LARGE_INTEGER LargeInteger,
+// IN CCHAR ShiftCount
+// )
+//
+// Routine Description:
+//
+// This function shifts a signed large integer left by an unsigned
+// integer modulo 64 and returns the shifted signed large integer
+// result.
+//
+// N.B. No test is made for significant bits shifted out of the result.
+//
+// Arguments:
+//
+// LargeInteger (a0=LSW, a1=MSW) - Supplies the large integer to be shifted.
+//
+// ShiftCount (a2) - bits to shift
+//
+// Return Value:
+//
+// The large integer result is stored into (v0=LSW,v1=MSW).
+//
+//--
+
+ LEAF_ENTRY(__ll_lshift)
+
+ and a2,a2,0x3f // truncate shift count mod 64
+
+//
+// Left shift the operand by the specified shift count.
+//
+
+ li t1,32 // compute right shift count
+ subu t1,t1,a2 //
+ bgtz t1,10f // if gtz, shift less that 32-bits
+
+//
+// Shift count is greater than or equal 32 bits - low half of result is zero,
+// high half is the low half shifted left by remaining count.
+//
+
+ sll v1,a0,a2 // set high half of result
+ move v0,zero // store low part of reuslt
+ j ra // return
+
+//
+// Shift count is less than 32-bits - high half of result is the high half
+// of operand shifted left by count combined with the low half of the operand
+// shifted right, low half of result is the low half shifted left.
+//
+
+10: move v0,a0 // set low half of result
+ sll v1,a1,a2 // shift high half left count bits
+ beq zero,a2,20f // if eq, no more shifts necessary
+ srl t0,v0,t1 // isolate shifted out bits of low half
+ sll v0,v0,a2 // shift low half left count bits
+ or v1,v1,t0 // combine bits for high half of result
+20: j ra // return
+
+ .end __ll_rshift
+
+ SBTTL("int64 Logical Shift Right")
+//++
+//
+// LARGE_INTEGER
+// RtlLargeIntegerShiftRight (
+// IN LARGE_INTEGER LargeInteger,
+// IN CCHAR ShiftCount
+// )
+//
+// Routine Description:
+//
+// This function shifts an unsigned large integer right by an unsigned
+// integer modulo 64 and returns the shifted unsigned large integer
+// result.
+//
+// Arguments:
+//
+// LargeInteger (a0=LSW, a1=MSW) - Supplies the large integer to be shifted.
+//
+// ShiftCount (a2) - Supplies the right shift count.
+//
+// Return Value:
+//
+// The large integer result is stored into (v0=LSW,v1=MSW).
+//
+//--
+
+ LEAF_ENTRY(__ull_rshift)
+
+ and a2,a2,0x3f // truncate shift count mod 64
+
+//
+// Right shift the operand by the specified shift count.
+//
+
+ li t1,32 // compute left shift count
+ subu t1,t1,a2 //
+ bgtz t1,10f // if gtz, shift less that 32-bits
+
+//
+// Shift count is greater than or equal 32 bits - high half of result is
+// zero, low half is the high half shifted right by remaining count.
+//
+
+ srl v0,a1,a2 // set low half of result
+ move v1,zero // store high part of result
+ j ra // return
+
+//
+// Shift count is less than 32-bits - high half of result is the high half
+// of operand shifted right by count, low half of result is the shifted out
+// bits of the high half combined with the right shifted low half of the
+// operand.
+//
+
+10: move v1,a1 // set high half of result
+ srl v0,a0,a2 // shift low half right count bits
+ beq zero,a2,20f // if eq, no more shifts necessary
+ sll t0,a1,t1 // isolate shifted out bits of high half
+ srl v1,a1,a2 // shift high half right count bits
+ or v0,v0,t0 // combine bits for low half of result
+20: j ra // return
+
+ .end __ull_rshift
+
+ SBTTL("int64 Arithmetic Shift Right")
+//++
+//
+// LARGE_INTEGER
+// RtlLargeIntegerArithmeticShift (
+// IN LARGE_INTEGER LargeInteger,
+// IN CCHAR ShiftCount
+// )
+//
+// Routine Description:
+//
+// This function shifts a signed large integer right by an unsigned
+// integer modulo 64 and returns the shifted signed large integer
+// result.
+//
+// Arguments:
+//
+// LargeInteger (a0=LSW, a1=MSW) - Supplies the large integer to be shifted.
+//
+// ShiftCount (a2) - Supplies the right shift count.
+//
+// Return Value:
+//
+// The large integer result is stored into (v0=LSW,v1=MSW).
+//
+//--
+
+ LEAF_ENTRY(__ll_rshift)
+
+ and a2,a2,0x3f // truncate shift count mod 64
+
+//
+// Right shift the operand by the specified shift count.
+//
+
+ li t1,32 // compute left shift count
+ subu t1,t1,a2 //
+ bgtz t1,10f // if gtz, shift less that 32-bits
+
+//
+// Shift count is greater than or equal 32 bits - high half of result is
+// bit63 sign-extended, low half is the high half shifted right by remaining count.
+//
+
+ sra v0,a1,a2 // set low half of result
+ sra v1,a1,31 // set high half of result
+ j ra // return
+
+//
+// Shift count is less than 32-bits - high half of result is the high half
+// of operand shifted right by count, low half of result is the shifted out
+// bits of the high half combined with the right shifted low half of the
+// operand.
+//
+
+10: move v1, a1 // set high half of result
+ srl v0,a0,a2 // shift low half right count bits
+ beq zero,a2,20f // if eq, no more shifts necessary
+ sll t0,a1,t1 // isolate shifted out bits of high half
+ sra v1,a1,a2 // shift high half right count bits
+ or v0,v0,t0 // combine bits for low half of result
+20: j ra // return
+
+ .end __ll_rshift
diff --git a/private/crt32/helper/mips/llshiftt.c b/private/crt32/helper/mips/llshiftt.c
new file mode 100644
index 000000000..8c46e8a4f
--- /dev/null
+++ b/private/crt32/helper/mips/llshiftt.c
@@ -0,0 +1,146 @@
+typedef __int64 longlong_t;
+typedef unsigned __int64 ulonglong_t;
+
+typedef struct {
+
+ unsigned lsw;
+ unsigned msw;
+} dword;
+
+typedef union {
+ longlong_t ll;
+ ulonglong_t ull;
+ dword dw;
+} llvalue;
+
+extern longlong_t __ll_mul (longlong_t ll_value, longlong_t multiplier);
+extern longlong_t __ll_lshift (longlong_t ll_value, long ll_lshift);
+extern longlong_t __ll_rshift (longlong_t ll_value, long ll_rshift);
+extern longlong_t __ull_rshift (ulonglong_t ull_value, long ll_rshift);
+extern longlong_t __ll_div (longlong_t divident, longlong_t divisor);
+extern ulonglong_t __ull_div (ulonglong_t divident, ulonglong_t divisor);
+extern longlong_t __ll_rem (longlong_t divident, longlong_t divisor);
+extern ulonglong_t __ull_rem (ulonglong_t divident, ulonglong_t divisor);
+extern void __ull_divremi (ulonglong_t *quotient, ulonglong_t *remainder, ulonglong_t dividend, unsigned short divisor);
+extern longlong_t __ll_mod (longlong_t ll_value, longlong_t modulus);
+extern longlong_t __d_to_ll (double);
+extern longlong_t __f_to_ll (float);
+extern ulonglong_t __d_to_ull (double);
+extern ulonglong_t __f_to_ull (float);
+extern double __ll_to_d (longlong_t);
+extern float __ll_to_f (longlong_t);
+extern double __ull_to_d (ulonglong_t);
+extern float __ull_to_f (ulonglong_t);
+extern ulonglong_t __ull_bit_extract (ulonglong_t *addr,
+ unsigned start_bit, unsigned length);
+extern ulonglong_t __ull_bit_insert (ulonglong_t *addr,
+ unsigned start_bit, unsigned length, ulonglong_t val);
+extern longlong_t __ll_bit_extract (ulonglong_t *addr,
+ unsigned start_bit, unsigned length);
+extern longlong_t __ll_bit_insert (ulonglong_t *addr,
+ unsigned start_bit, unsigned length, longlong_t val);
+
+#define MSW(x) (x).dw.msw
+#define LSW(x) (x).dw.lsw
+
+llvalue llval;
+
+int main(int argc, char *argv[], char *env[])
+{
+ int n,i,k, kk = 0;
+ llvalue lltmp1;
+ llvalue lltmp2;
+
+ for (n = 0; n < 64; n++) {
+
+ if (n < 32) {
+ MSW(llval) = 0;
+ LSW(llval) = 1 << i;
+ } else {
+ MSW(llval) = 1 << (i-32);
+ LSW(llval) = 0;
+ }
+
+ /* Test left shift */
+ for (i = 0, k = 0; i < 64; i++) {
+ lltmp1.ll = llval.ll << i;
+ if (i == 0) {
+ MSW(lltmp2) = MSW(llval);
+ LSW(lltmp2) = LSW(llval);
+ } else if (i < 32) {
+ MSW(lltmp2) = (MSW(llval) << i) | (((unsigned long)LSW(llval)) >> (32-i));
+ LSW(lltmp2) = LSW(llval) << i;
+ } else {
+ MSW(lltmp2) = LSW(llval) << (i-32);
+ LSW(lltmp2) = 0;
+ }
+ if (lltmp1.ll != lltmp2.ll) {
+ if (!k++)
+ printf("\n");
+ printf("(0x%8.8x%8.8x) << %d\t(0x%8.8x%8.8x) != (0x%8.8x%8.8x)\n", MSW(llval), LSW(llval), i, MSW(lltmp1), LSW(lltmp1), MSW(lltmp2), LSW(lltmp2) );
+ }
+ }
+
+ if (k) {
+ printf("\n\tLeft logical shift failed %d tests\n",k);
+ kk += k;
+ }
+
+ /* Test right unsigned shift */
+ for (i = 0, k = 0; i < 64; i++) {
+ lltmp1.ull = llval.ull >> i;
+ if (i == 0) {
+ MSW(lltmp2) = MSW(llval);
+ LSW(lltmp2) = LSW(llval);
+ } else if (i < 32) {
+ LSW(lltmp2) = (LSW(llval) >> i) | (((unsigned long)MSW(llval)) << (32-i));
+ MSW(lltmp2) = ((unsigned long)MSW(llval)) >> i;
+ } else {
+ MSW(lltmp2) = 0;
+ LSW(lltmp2) = ((unsigned long)MSW(llval)) >> (i-32);
+ }
+ if (lltmp1.ll != lltmp2.ll) {
+ if (!k++)
+ printf("\n");
+ printf("(0x%8.8x%8.8x) >> %d\t(0x%8.8x%8.8x) != (0x%8.8x%8.8x)\n", MSW(llval), LSW(llval), i, MSW(lltmp1), LSW(lltmp1), MSW(lltmp2), LSW(lltmp2) );
+ }
+ }
+
+ if (k) {
+ printf("\n\tRight logical shift failed %d tests\n",k);
+ k += k;
+ }
+
+ /* Test right arithmetic shift */
+ for (i = 0, k = 0; i < 64; i++) {
+ lltmp1.ll = llval.ll >> i;
+ if (i == 0) {
+ MSW(lltmp2) = MSW(llval);
+ LSW(lltmp2) = LSW(llval);
+ } else if (i < 32) {
+ LSW(lltmp2) = (LSW(llval) >> i) | ((MSW(llval) << (32-i)));
+ MSW(lltmp2) = MSW(llval) >> i;
+ } else {
+ MSW(lltmp2) = 0;
+ LSW(lltmp2) = MSW(llval) >> (i-32);
+ }
+ if (lltmp1.ll != lltmp2.ll) {
+ if (!k++)
+ printf("\n");
+ printf("(0x%8.8x%8.8x) >> %d\t(0x%8.8x%8.8x) != (0x%8.8x%8.8x)\n", MSW(llval), LSW(llval), i, MSW(lltmp1), LSW(lltmp1), MSW(lltmp2), LSW(lltmp2) );
+ }
+ }
+
+ if (k) {
+ printf("\n\tRight arithmetic shift failed %d tests\n",k);
+ k += k;
+ }
+
+ }
+
+ if (kk)
+ printf("\n\t'%s' failed a total of %d tests...\n", argv[0], kk);
+ else
+ printf("\n\t'%s' passed all tests...\n", argv[0]);
+
+}
diff --git a/private/crt32/helper/sources b/private/crt32/helper/sources
new file mode 100644
index 000000000..93e496902
--- /dev/null
+++ b/private/crt32/helper/sources
@@ -0,0 +1,65 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=helper
+
+TARGETNAME=helper
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+C_DEFINES= $(C_DEFINES) -D_MIPSEL -D_WIN32_
+
+SOURCES=empty.c
+
+MIPS_SOURCES= lldiv.c \
+ llbit.c \
+ llabsdiv.c \
+ llcvt.s \
+ lldivrem.s \
+ llmul.s\
+ llshift.s
+
+
+PPC_SOURCES= dtoi.s \
+ dtoi64.s \
+ dtou.s \
+ dtou64.s \
+ i64div.s \
+ i64rem.s \
+ i64tod.s \
+ itod.s \
+ itof.s \
+ restfpr.s \
+ restgpr.s \
+ savefpr.s \
+ savegpr.s \
+ svgprarg.s \
+ u64div.s \
+ u64rem.s \
+ u64tod.s \
+ utod.s \
+ utof.s
diff --git a/private/crt32/iostream/cerrinit.cxx b/private/crt32/iostream/cerrinit.cxx
new file mode 100644
index 000000000..5f5d75f5e
--- /dev/null
+++ b/private/crt32/iostream/cerrinit.cxx
@@ -0,0 +1,28 @@
+/***
+*cerrinit.cxx - definitions and initialization for predefined stream cerr.
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions and initialization of predefined stream cerr.
+*
+*Revision History:
+* 11 18-91 KRS Created.
+*
+*******************************************************************************/
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#include <fstream.h>
+#pragma hdrstop
+
+// put contructors in special MS-specific XIFM segment
+#pragma warning(disable:4074) // ignore init_seg warning
+#pragma init_seg(compiler)
+
+#if ((!defined(_WINDOWS)) || defined(_QWIN))
+ostream_withassign cerr(new filebuf(2));
+
+static Iostream_init __InitCerr(cerr,1);
+
+#endif
diff --git a/private/crt32/iostream/cininit.cxx b/private/crt32/iostream/cininit.cxx
new file mode 100644
index 000000000..7a8c6762d
--- /dev/null
+++ b/private/crt32/iostream/cininit.cxx
@@ -0,0 +1,28 @@
+/***
+*cininit.cxx - definitions and initialization for predefined stream cin.
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions and initialization of predefined stream cin.
+*
+*Revision History:
+* 11 18-91 KRS Created.
+*
+*******************************************************************************/
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#include <fstream.h>
+#pragma hdrstop
+
+// put contructors in special MS-specific XIFM segment
+#pragma warning(disable:4074) // ignore init_seg warning
+#pragma init_seg(compiler)
+
+#if ((!defined(_WINDOWS)) || defined(_QWIN))
+istream_withassign cin(new filebuf(0));
+
+static Iostream_init __InitCin(cin);
+
+#endif
diff --git a/private/crt32/iostream/cloginit.cxx b/private/crt32/iostream/cloginit.cxx
new file mode 100644
index 000000000..f1f0a064a
--- /dev/null
+++ b/private/crt32/iostream/cloginit.cxx
@@ -0,0 +1,28 @@
+/***
+*cloginit.cxx - definitions and initialization for predefined stream clog.
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions and initialization of predefined stream clog.
+*
+*Revision History:
+* 11 18-91 KRS Created.
+*
+*******************************************************************************/
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#include <fstream.h>
+#pragma hdrstop
+
+// put contructors in special MS-specific XIFM segment
+#pragma warning(disable:4074) // ignore init_seg warning
+#pragma init_seg(compiler)
+
+#if ((!defined(_WINDOWS)) || defined(_QWIN))
+ostream_withassign clog(new filebuf(2));
+
+static Iostream_init __InitClog(clog);
+
+#endif
diff --git a/private/crt32/iostream/filebuf.cxx b/private/crt32/iostream/filebuf.cxx
new file mode 100644
index 000000000..35980c4bb
--- /dev/null
+++ b/private/crt32/iostream/filebuf.cxx
@@ -0,0 +1,460 @@
+/***
+*filebuf.cxx - core filebuf member functions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the core member functions for filebuf class.
+*
+*Revision History:
+* 08-08-91 KRS Created.
+* 08-20-91 KRS Added virtual xsgetn()/xsputn() functions.
+* 08-21-91 KRS Fix circular reference between sync() and seekoff().
+* Close file in destructor only if we opened it!
+* 09-06-91 KRS Fix ios::ate case in filebuf::open().
+* 09-09-91 KRS Add support for ios::binary in filebuf::open().
+* 09-10-91 KRS Remove virtual xsputn()/xsgetn().
+* 09-11-91 KRS Fix filebuf::seekoff() for ios::cur and in_avail().
+* 09-12-91 KRS Make sure close() always closes even if sync() fails.
+* Fix seekoff call in filebuf::sync() and pbackfail().
+* 09-16-91 KRS Make virtual filebuf::setbuf() more robust.
+* 09-19-91 KRS Add calls to delbuf(1) in constructors.
+* 09-20-91 KRS C700 #4453: Improve efficiency in overflow().
+* 09-29-91 KRS Granularity split. Move fstream into separate file.
+* 10-24-91 KRS Avoid virtual calls from virtual functions.
+* 11-13-91 KRS Use allocate() properly in overflow() and underflow().
+* Fix constructor.
+* 01-03-92 KRS Remove virtual keyword. Add function headers and PCH.
+* 01-20-92 KRS In text mode, account for CR/LF pairs in sync().
+* 02-03-92 KRS Change for new compiler destructor behavior.
+* 08-19-92 KRS Remove sh_compat for NT.
+* 08-27-92 KRS Fix bug in close() introduced in MTHREAD work.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys\types.h>
+#include <io.h>
+#include <fstream.h>
+#pragma hdrstop
+
+#include <msdos.h>
+#include <sys\stat.h>
+
+const int filebuf::openprot = 0644; // CONSIDER: meaning?
+
+const int filebuf::sh_none = 04000; // deny rw
+const int filebuf::sh_read = 05000; // deny wr
+const int filebuf::sh_write = 06000; // deny rd
+
+const int filebuf::binary = O_BINARY;
+const int filebuf::text = O_TEXT;
+
+/***
+*filebuf::filebuf() - filebuf default constructor
+*
+*Purpose:
+* Default constructor.
+*
+*Entry:
+*
+*******************************************************************************/
+ filebuf::filebuf()
+: streambuf()
+{
+ x_fOpened = 0;
+ x_fd = -1;
+}
+
+
+/***
+*filebuf::filebuf(filedesc fd) - filebuf constructor
+*
+*Purpose:
+* Constructor. Initialize filebuf and attach to file descriptor.
+*
+*Entry:
+* fd = file descriptor to attach to filebuf
+*
+*******************************************************************************/
+ filebuf::filebuf(filedesc fd)
+: streambuf()
+{
+ x_fOpened = 0;
+ x_fd=fd;
+}
+
+
+/***
+*filebuf::filebuf(filedesc fd, char* p, int len) - filebuf constructor
+*
+*Purpose:
+* Constructor. Initialize filebuf and attach to file descriptor.
+*
+*Entry:
+* fd = file descriptor to attach to filebuf
+* p = user-supplied buffer
+* len = length of buffer
+*
+*******************************************************************************/
+ filebuf::filebuf(filedesc fd, char* p, int len)
+: streambuf()
+{
+ filebuf::setbuf(p,len);
+ x_fOpened = 0;
+ x_fd=fd;
+}
+
+
+/***
+*filebuf::~filebuf() - filebuf destructor
+*
+*Purpose:
+* Destructor. Close attached file only if we opened it.
+*
+*Entry:
+* None.
+*
+*******************************************************************************/
+ filebuf::~filebuf()
+{
+ lock(); // no need to unlock...
+ if (x_fOpened)
+ close(); // calls filebuf::sync()
+ else
+ filebuf::sync();
+}
+
+
+/***
+*filebuf* filebuf::close() - close an attached file
+*
+*Purpose:
+* Close attached file.
+*
+*Entry:
+* None.
+*Exit:
+* Returns NULL if error, otherwise returns "this" pointer.
+*
+*******************************************************************************/
+filebuf* filebuf::close()
+{
+ int retval;
+ if (x_fd==-1)
+ return NULL;
+
+ lock();
+ retval = sync();
+
+ if ((_close(x_fd)==-1) || (retval==EOF))
+ {
+ unlock();
+ return NULL;
+ }
+ x_fd = -1;
+ unlock();
+ return this;
+}
+
+/***
+*virtual int filebuf::overflow(int c) - overflow virtual function
+*
+*Purpose:
+* flush any characters in the reserve area and handle 'c'.
+*
+*Entry:
+* c = character to output (if not EOF)
+*
+*Exit:
+* Returns EOF if error, otherwise returns something else.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+int filebuf::overflow(int c)
+{
+ if (allocate()==EOF) // make sure there is a reserve area
+ return EOF;
+ if (filebuf::sync()==EOF) // sync before new buffer created below
+ return EOF;
+
+ if (!unbuffered())
+ setp(base(),ebuf());
+
+ if (c!=EOF)
+ {
+ if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
+ sputc(c);
+ else
+ {
+ if (_write(x_fd,&c,1)!=1)
+ return(EOF);
+ }
+ }
+ return(1); // return something other than EOF if successful
+}
+
+/***
+*virtual int filebuf::underflow() - underflow virtual function
+*
+*Purpose:
+* return next character in get area, or get more characters from source.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns current character in file. Does not advance get pointer.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+int filebuf::underflow()
+{
+ int count;
+ unsigned char tbuf;
+
+ if (in_avail())
+ return (int)(unsigned char) *gptr();
+
+ if (allocate()==EOF) // make sure there is a reserve area
+ return EOF;
+ if (filebuf::sync()==EOF)
+ return EOF;
+
+ if (unbuffered())
+ {
+ if (_read(x_fd,(void *)&tbuf,1)<=0)
+ return EOF;
+ return (int)tbuf;
+ }
+
+ if ((count=_read(x_fd,(void *)base(),blen())) <= 0)
+ return EOF; // reached EOF
+ setg(base(),base(),base()+count);
+ return (int)(unsigned char) *gptr(); // CONSIDER: possible recursion
+}
+
+
+/***
+*virtual streampos filebuf::seekoff() - seekoff virtual function
+*
+*Purpose:
+* Seeks to given absolute or relative file offset.
+*
+*Entry:
+* off = offset to seek to relative to beginning, end or current
+* position in the file.
+* dir = one of ios::beg, ios::cur, or ios::end
+*
+*Exit:
+* Returns current file position after seek.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+streampos filebuf::seekoff(streamoff off, ios::seek_dir dir, int)
+{
+
+ int fdir;
+ long retpos;
+ switch (dir) {
+ case ios::beg :
+ fdir = SEEK_SET;
+ break;
+ case ios::cur :
+ fdir = SEEK_CUR;
+ break;
+ case ios::end :
+ fdir = SEEK_END;
+ break;
+ default:
+ // error
+ return(EOF);
+ }
+
+ if (filebuf::sync()==EOF)
+ return EOF;
+ if ((retpos=_lseek(x_fd, off, fdir))==-1L)
+ return (EOF);
+ return((streampos)retpos);
+}
+
+/* NOT IN SPEC.
+int filebuf::pbackfail(int c)
+{
+ if (eback()<gptr()) return sputbackc(c); // CONSIDER: should never happen
+
+ if (filebuf::seekoff( -1, ios::cur, ios::in)==EOF)
+ return EOF;
+ if (!unbuffered())
+ filebuf::underflow();
+ // assert c = underflow()
+ }
+ return(c);
+}
+*/
+
+#if 0
+// NOT IN SPEC.
+// UNDONE: consider removing this?
+int filebuf::xsgetn(char * ptr, int n)
+{
+ int retval;
+ int oldmode;
+
+ if (x_fd==-1)
+ return 0;
+ if (filebuf::sync()!=EOF)
+ {
+ // set to BINARY and save old mode.
+ oldmode = _setmode(x_fd,O_BINARY);
+ }
+ retval = sgetn(ptr,n);
+ filebuf::sync(); // put back any excess (ignore errors)
+
+ if (oldmode==O_TEXT) // check != -1
+ {
+ _setmode(x_fd,oldmode);
+ }
+ return retval;
+}
+
+// NOT IN SPEC.
+// UNDONE: consider removing this?
+int filebuf::xsputn(const char * ptr, int n)
+{
+ int retval;
+ int oldmode;
+
+ if (x_fd==-1)
+ return 0;
+ if (filebuf::sync()!=EOF)
+ {
+ // set to BINARY and save old mode.
+ oldmode = _setmode(x_fd,O_BINARY);
+ }
+
+ retval = sputn(ptr,n);
+ filebuf::sync(); // flush output;
+
+ if (oldmode==O_TEXT) // check != -1
+ {
+ _setmode(x_fd,oldmode);
+ }
+ return retval;
+}
+#endif
+
+
+/***
+*virtual int filebuf::sync() - synchronize buffers with external file postion.
+*
+*Purpose:
+* Synchronizes buffer with external file, by flushing any output and/or
+* discarding any unread input data. Discards any get or put area(s).
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns EOF if error, else 0.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+int filebuf::sync()
+{
+ long count, nout;
+ char * p;
+ if (x_fd==-1)
+ return(EOF);
+// lock(); // CONSIDER: do we need/want locking here?
+ if (!unbuffered())
+ {
+ if ((count=out_waiting())!=0)
+ {
+ if ((nout =_write(x_fd,(void *) pbase(),(unsigned int)count)) != count)
+ {
+ // should set _pptr -= nout
+ pbump(-(int)nout);
+ memmove(pbase(), pbase()+nout, (int)(count-nout));
+// unlock();
+ return(EOF);
+ }
+ }
+ setp(0,0); // empty put area
+
+ if ((count=in_avail()) > 0)
+ {
+ // can't use seekoff here!!
+ if (_osfile[x_fd] & FTEXT)
+ {
+ // If text mode, need to account for CR/LF etc.
+ for (p = gptr(); p < egptr(); p++)
+ if (*p == '\n')
+ count++;
+
+ // account for EOF if read, not counted by _read
+ // UNDONE: is this necessary / useful?
+ if ((_osfile[x_fd] & FEOFLAG))
+ count++;
+#if 0
+ // UNDONE: is this correct?
+ if ((gptr()==eback()) && (_osfile[x_fd] & FCRLF))
+ count--;
+#endif
+ }
+ if (_lseek(x_fd, -count, SEEK_CUR)==-1L)
+ {
+// unlock();
+ return (EOF);
+ }
+ }
+ setg(0,0,0); // empty get area
+ }
+// unlock();
+ return(0);
+}
+
+/***
+*virtual streambuf* filebuf::setbuf(char* ptr, int len) - set reserve area.
+*
+*Purpose:
+* Synchronizes buffer with external file, by flushing any output and/or
+* discarding any unread input data. Discards any get or put area(s).
+*
+*Entry:
+* ptr = requested reserve area. If NULL, request is for unbuffered.
+* len = size of reserve area. If <= 0, request is for unbuffered.
+*
+*Exit:
+* Returns this pointer if request is honored, else NULL.
+*
+*Exceptions:
+* Returns NULL if request is not honored.
+*
+*******************************************************************************/
+streambuf * filebuf::setbuf(char * ptr, int len)
+{
+ if (is_open() && (ebuf()))
+ return NULL;
+ if ((!ptr) || (len <= 0))
+ unbuffered(1);
+ else
+ {
+ lock(); // consider: necessary?
+ setb(ptr, ptr+len, 0);
+ unlock();
+ }
+ return this;
+}
diff --git a/private/crt32/iostream/filebuf1.cxx b/private/crt32/iostream/filebuf1.cxx
new file mode 100644
index 000000000..6079d69e2
--- /dev/null
+++ b/private/crt32/iostream/filebuf1.cxx
@@ -0,0 +1,231 @@
+/***
+*filebuf1.cxx - non-core filebuf member functions.
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains optional member functions for filebuf class.
+*
+*Revision History:
+* 09-21-91 KRS Created. Split off from fstream.cxx.
+* 10-24-91 KRS C700 #4909: Typo/logic bug in setmode().
+* 11-06-91 KRS Add support for share mode in open(). Use _sopen().
+* 08-19-92 KRS Use _SH_DENYNO for default mode for NT.
+* 03-02-93 SKS Avoid setting _O_TRUNC when noreplace is specified
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <share.h>
+#include <sys\types.h>
+#include <io.h>
+#include <fstream.h>
+#pragma hdrstop
+
+#include <sys\stat.h>
+
+/***
+*filebuf* filebuf::attach(filedesc fd) - filebuf attach function
+*
+*Purpose:
+* filebuf attach() member function. Attach filebuf object to the
+* given file descriptor previously obtained from _open() or _sopen().
+*
+*Entry:
+* fd = file descriptor.
+*
+*Exit:
+* Returns this pointer or NULL if error.
+*
+*Exceptions:
+* Returns NULL if fd = -1.
+*
+*******************************************************************************/
+filebuf* filebuf::attach(filedesc fd)
+{
+ if (x_fd!=-1)
+ return NULL; // error if already attached
+
+ lock();
+ x_fd = fd;
+ if ((fd!=-1) && (!unbuffered()) && (!ebuf()))
+ {
+ char * sbuf = new char[BUFSIZ];
+ if (!sbuf)
+ {
+ unbuffered(1);
+ }
+ else
+ {
+ streambuf::setb(sbuf,sbuf+BUFSIZ,1);
+ }
+ }
+ unlock();
+ return this;
+}
+
+/***
+*filebuf* filebuf::open(const char* name, int mode, int share) - filebuf open
+*
+*Purpose:
+* filebuf open() member function. Open a file and attach to filebuf
+* object.
+*
+*Entry:
+* name = file name string.
+* mode = open mode: Combination of ios:: in, out, binary, nocreate, app,
+* ate, noreplace and trunc. See spec. for details on behavior.
+* share = share mode (optional). sh_compat, sh_none, sh_read, sh_write.
+*
+*Exit:
+* Returns this pointer or NULL if error.
+*
+*Exceptions:
+* Returns NULL if filebuf is already attached to an open file, or if
+* invalid mode options, or if call to _sopen or filebuf::seekoff() fails.
+*
+*******************************************************************************/
+filebuf* filebuf::open(const char* name, int mode, int share)
+{
+ int dos_mode;
+ int smode;
+ if (x_fd!=-1)
+ return NULL; // error if already open
+// translate mode argument
+ dos_mode = (mode & ios::binary) ? O_BINARY : O_TEXT;
+ if (!(mode & ios::nocreate))
+ dos_mode |= O_CREAT;
+ if (mode & ios::noreplace)
+ dos_mode |= O_EXCL;
+ if (mode & ios::app)
+ {
+ mode |= ios::out;
+ dos_mode |= O_APPEND;
+ }
+ if (mode & ios::trunc)
+ {
+ mode |= ios::out; // IMPLIED
+ dos_mode |= O_TRUNC;
+ }
+ if (mode & ios::out)
+ {
+ if (mode & ios::in)
+ {
+ dos_mode |= O_RDWR;
+ }
+ else
+ {
+ dos_mode |= O_WRONLY;
+ }
+ // CONSIDER: a bit weaker treatment than in spec.
+ if (!(mode & (ios::in|ios::app|ios::ate|ios::noreplace)))
+ {
+ mode |= ios::trunc; // IMPLIED
+ dos_mode |= O_TRUNC;
+ }
+ }
+ else if (mode & ios::in)
+ dos_mode |= O_RDONLY;
+ else
+ return NULL; // error if not ios:in or ios::out
+
+ smode = _SH_DENYNO; // default for NT
+ share &= (sh_read|sh_write|sh_none); // ignore other bits
+ if (share) // optimization openprot serves as default
+ {
+ switch (share)
+ {
+/* case 03000 : Reserved for sh_compat */
+
+// case sh_none :
+ case 04000 :
+ smode = _SH_DENYRW;
+ break;
+// case sh_read :
+ case 05000 :
+ smode = _SH_DENYWR;
+ break;
+// case sh_write :
+ case 06000 :
+ smode = _SH_DENYRD;
+ break;
+// case (sh_read|sh_write) :
+ case 07000 :
+ smode = _SH_DENYNO;
+ break;
+ default : // unrecognized value same as default
+ break;
+ };
+ }
+
+ x_fd = _sopen(name, dos_mode, smode, S_IREAD|S_IWRITE);
+ if (x_fd==-1)
+ return NULL;
+ lock();
+ x_fOpened = 1;
+ if ((!unbuffered()) && (!ebuf()))
+ {
+ char * sbuf = new char[BUFSIZ];
+ if (!sbuf)
+ {
+ unbuffered(1);
+ }
+ else
+ {
+ streambuf::setb(sbuf,sbuf+BUFSIZ,1);
+ }
+ }
+ if (mode & ios::ate)
+ if (seekoff(0,ios::end,mode)==EOF)
+ {
+ close();
+ unlock();
+ return NULL;
+ }
+ unlock();
+ return this;
+}
+
+/***
+*int filebuf::setmode(int mode) - filebuf setmode function
+*
+*Purpose:
+* filebuf setmode() member function. Set binary or text access mode.
+* Calls _setmode().
+*
+* MS-specific extension.
+*
+*Entry:
+* mode = filebuf::binary or filebuf::text.
+*
+*Exit:
+* Returns previous mode, or -1 error.
+*
+*Exceptions:
+* Return -1 (EOF) if invalid argument or _setmode fails.
+*
+*******************************************************************************/
+int filebuf::setmode(int mode)
+{
+ int retval;
+ if ((mode!=filebuf::binary) && (mode!=filebuf::text))
+ return -1;
+
+ lock();
+ if ((x_fd==-1) || (sync()==EOF))
+ {
+ retval = -1;
+ }
+ else
+ {
+ retval = _setmode(x_fd,mode);
+ }
+
+ unlock();
+ return retval;
+}
diff --git a/private/crt32/iostream/fstream.cxx b/private/crt32/iostream/fstream.cxx
new file mode 100644
index 000000000..8cecf6c8e
--- /dev/null
+++ b/private/crt32/iostream/fstream.cxx
@@ -0,0 +1,261 @@
+/***
+*fstream.cxx -
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member functions for the fstream class.
+*
+*Revision History:
+* 09-21-91 KRS Created. Split off from filebuf.cxx for granularity.
+* 10-22-91 KRS C700 #4883: fix error status of fstream::open().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys\types.h>
+#include <io.h>
+#include <fstream.h>
+#pragma hdrstop
+
+#include <sys\stat.h>
+
+/***
+*fstream::fstream() - fstream default constructor
+*
+*Purpose:
+* Default constructor for fstream objects.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ fstream::fstream()
+: iostream(new filebuf)
+{
+ istream::delbuf(1);
+ ostream::delbuf(1);
+ // CONSIDER: do anything else?
+}
+
+/***
+*fstream::fstream(const char * name, int mode, int prot) - fstream constructor
+*
+*Purpose:
+* Constructor for fstream objects. Creates an associated filebuf object,
+* opens a named file and attaches it to the new filebuf.
+*
+*Entry:
+* name = filename to open.
+* mode = see filebuf::open mode argument
+* prot = see filebuf::open share argument
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if open fails.
+*
+*******************************************************************************/
+ fstream::fstream(const char * name, int mode, int prot)
+: iostream(new filebuf)
+{
+ istream::delbuf(1);
+ ostream::delbuf(1);
+ if (!(rdbuf()->open(name, mode, prot)))
+ {
+ istream::state = istream::failbit;
+ ostream::state = ostream::failbit;
+ }
+}
+
+/***
+*fstream::fstream(filedesc fd) - fstream constructor
+*
+*Purpose:
+* Constructor for fstream objects. Creates an associated filebuf object
+* and attaches it to the given file descriptor.
+*
+*Entry:
+* fd = file descriptor of file previously opened using _open or _sopen.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ fstream::fstream(filedesc _fd)
+: iostream(new filebuf(_fd))
+{
+ istream::delbuf(1);
+ ostream::delbuf(1);
+}
+
+/***
+*fstream::fstream(filedesc fd, char * sbuf, int len) - fstream constructor
+*
+*Purpose:
+* Constructor for fstream objects. Creates an associated filebuf object
+* and attaches it to the given file descriptor. Filebuf object uses
+* user-supplied buffer or is unbuffered if sbuf or len = 0.
+*
+*Entry:
+* fd = file descriptor of file previously opened using _open or _sopen.
+* sbuf = pointer to character buffer or NULL if request for unbuffered.
+* len = lenght of character buffer sbuf or 0 if request for unbuffered.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ fstream::fstream(filedesc _fd, char * sbuf, int len)
+: iostream(new filebuf(_fd, sbuf, len))
+{
+ istream::delbuf(1);
+ ostream::delbuf(1);
+}
+
+/***
+*fstream::~fstream() - fstream destructor
+*
+*Purpose:
+* fstream destructor.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ fstream::~fstream()
+{
+ // CONSIDER: do anything else?
+}
+
+/***
+*streambuf* fstream::setbuf(char * ptr, int len) - setbuf function
+*
+*Purpose:
+* fstream setbuf function
+*
+*Entry:
+* ptr = pointer to buffer or NULL for unbuffered.
+* len = length of buffer or zero for unbuffered.
+*
+*Exit:
+* Returns rdbuf() or NULL if error.
+*
+*Exceptions:
+* If fstream is already open or if rdbuf()->setbuf fails, sets failbit
+* and returns NULL.
+*
+*******************************************************************************/
+streambuf * fstream::setbuf(char * ptr, int len)
+{
+ if ((is_open()) || (!(rdbuf()->setbuf(ptr, len))))
+ {
+ istream::clear(istream::state | istream::failbit);
+ ostream::clear(ostream::state | ostream::failbit);
+ return NULL;
+ }
+ return rdbuf();
+}
+
+/***
+*void fstream::attach(filedesc _fd) - attach member function
+*
+*Purpose:
+* fstream attach member function. Just calls rdbuf()->attach().
+*
+*Entry:
+* _fd = file descriptor of previously opened file.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if rdbuf()->attach fails.
+*
+*******************************************************************************/
+void fstream::attach(filedesc _fd) // CONSIDER: inline?
+{
+ if (!(rdbuf()->attach(_fd)))
+ {
+ istream::clear(istream::state | istream::failbit);
+ ostream::clear(ostream::state | ostream::failbit);
+ }
+}
+
+/***
+*void fstream::open(const char * name, int mode, int prot) - fstream open()
+*
+*Purpose:
+* Opens a named file and attaches it to the associated filebuf.
+* Just calls rdbuf()->open().
+*
+*Entry:
+* name = filename to open.
+* mode = see filebuf::open mode argument
+* prot = see filebuf::open share argument
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if already open or rdbuf()->open() fails.
+*
+*******************************************************************************/
+void fstream::open(const char * name, int mode, int prot)
+{
+ if (is_open() || !(rdbuf()->open(name, mode, prot)))
+ {
+ istream::clear(istream::state | istream::failbit);
+ ostream::clear(ostream::state | ostream::failbit);
+ }
+}
+
+/***
+*void fstream::close() - close member function
+*
+*Purpose:
+* fstream close member function. Just calls rdbuf()->close().
+* Clears rdstate() error bits if successful.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if rdbuf()->close fails.
+*
+*******************************************************************************/
+void fstream::close()
+{
+ if (rdbuf()->close())
+ {
+ istream::clear();
+ ostream::clear();
+ }
+ else
+ {
+ istream::clear(istream::state | istream::failbit);
+ ostream::clear(ostream::state | ostream::failbit);
+ }
+}
diff --git a/private/crt32/iostream/ifstream.cxx b/private/crt32/iostream/ifstream.cxx
new file mode 100644
index 000000000..e49e26d40
--- /dev/null
+++ b/private/crt32/iostream/ifstream.cxx
@@ -0,0 +1,240 @@
+/***
+*ifstream.cxx - ifstream member function definitions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member functions for the ifstream class.
+*
+*Revision History:
+* 09-21-91 KRS Created. Split up fstream.cxx for granularity.
+* 10-22-91 KRS C700 #4883: fix error status for ifstream::open().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys\types.h>
+#include <io.h>
+#include <fstream.h>
+#pragma hdrstop
+
+#include <sys\stat.h>
+
+/***
+*ifstream::ifstream() - ifstream default constructor
+*
+*Purpose:
+* Default constructor for ifstream objects.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ ifstream::ifstream()
+: istream(new filebuf)
+{
+ delbuf(1); // schedule automatic deletion too...
+ // CONSIDER: do anything else?
+}
+
+/***
+*ifstream::ifstream(const char * name, int mode, int prot) - ifstream ctor
+*
+*Purpose:
+* Constructor for ifstream objects. Creates an associated filebuf object,
+* opens a named file and attaches it to the new filebuf.
+*
+*Entry:
+* name = filename to open.
+* mode = see filebuf::open mode argument. ios::in is implied.
+* prot = see filebuf::open share argument
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if open fails.
+*
+*******************************************************************************/
+ ifstream::ifstream(const char * name, int mode, int prot)
+: istream(new filebuf)
+{
+ delbuf(1); // schedule automatic deletion too...
+ if (!(rdbuf()->open(name, (mode|ios::in), prot)))
+ state |= ios::failbit;
+}
+
+/***
+*ifstream::ifstream(filedesc fd) - ifstream constructor
+*
+*Purpose:
+* Constructor for ifstream objects. Creates an associated filebuf object
+* and attaches it to the given file descriptor.
+*
+*Entry:
+* fd = file descriptor of file previously opened using _open or _sopen.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ ifstream::ifstream(filedesc _fd)
+: istream(new filebuf(_fd))
+{
+ delbuf(1);
+}
+
+/***
+*ifstream::ifstream(filedesc fd, char * sbuf, int len) - ifstream constructor
+*
+*Purpose:
+* Constructor for ifstream objects. Creates an associated filebuf object
+* and attaches it to the given file descriptor. Filebuf object uses
+* user-supplied buffer or is unbuffered if sbuf or len = 0.
+*
+*Entry:
+* fd = file descriptor of file previously opened using _open or _sopen.
+* sbuf = pointer to character buffer or NULL if request for unbuffered.
+* len = lenght of character buffer sbuf or 0 if request for unbuffered.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ ifstream::ifstream(filedesc _fd, char * sbuf, int len)
+: istream(new filebuf(_fd, sbuf, len))
+//: istream(new filebuf);
+{
+ delbuf(1);
+}
+
+/***
+*ifstream::~ifstream() - ifstream destructor
+*
+*Purpose:
+* ifstream destructor.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ ifstream::~ifstream()
+{
+ // CONSIDER: do anything else?
+}
+
+/***
+*streambuf* ifstream::setbuf(char * ptr, int len) - setbuf function
+*
+*Purpose:
+* ifstream setbuf function
+*
+*Entry:
+* ptr = pointer to buffer or NULL for unbuffered.
+* len = length of buffer or zero for unbuffered.
+*
+*Exit:
+* Returns rdbuf() or NULL if error.
+*
+*Exceptions:
+* If ifstream is already open or if rdbuf()->setbuf fails, sets failbit
+* and returns NULL.
+*
+*******************************************************************************/
+streambuf * ifstream::setbuf(char * ptr, int len)
+{
+ if ((is_open()) || (!(rdbuf()->setbuf(ptr, len))))
+ {
+ clear(state | ios::failbit);
+ return NULL;
+ }
+ // UNDONE: turn off output buffer??
+ return rdbuf();
+}
+
+/***
+*void ifstream::attach(filedesc _fd) - attach member function
+*
+*Purpose:
+* ifstream attach member function. Just calls rdbuf()->attach().
+*
+*Entry:
+* _fd = file descriptor of previously opened file.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if rdbuf()->attach fails.
+*
+*******************************************************************************/
+void ifstream::attach(filedesc _fd) // CONSIDER: inline?
+{
+ if (!(rdbuf()->attach(_fd)))
+ clear(state | ios::failbit);
+}
+
+/***
+*void ifstream::open(const char * name, int mode, int prot) - ifstream open()
+*
+*Purpose:
+* Opens a named file and attaches it to the associated filebuf.
+* Just calls rdbuf()->open().
+*
+*Entry:
+* name = filename to open.
+* mode = see filebuf::open mode argument. ios::in is implied.
+* prot = see filebuf::open share argument
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if already open or rdbuf()->open() fails.
+*
+*******************************************************************************/
+void ifstream::open(const char * name, int mode, int prot)
+{
+ if (is_open() || !(rdbuf()->open(name, (mode|ios::in), prot)))
+ clear(state | ios::failbit);
+}
+
+/***
+*void ifstream::close() - close member function
+*
+*Purpose:
+* ifstream close member function. Just calls rdbuf()->close().
+* Clears rdstate() error bits if successful.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if rdbuf()->close fails.
+*
+*******************************************************************************/
+void ifstream::close()
+{
+ clear((rdbuf()->close()) ? 0 : (state | ios::failbit));
+}
diff --git a/private/crt32/iostream/ios.cxx b/private/crt32/iostream/ios.cxx
new file mode 100644
index 000000000..6fc3468dc
--- /dev/null
+++ b/private/crt32/iostream/ios.cxx
@@ -0,0 +1,323 @@
+/***
+*ios.cxx - fuctions for ios class.
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Functions for ios class.
+*
+*Revision History:
+* 09-10-90 WAJ Initial version.
+* 07-02-91 KRS Initial version completed.
+* 09-19-91 KRS Make use of delbuf() in destructor.
+* 11-04-91 KRS Change init(). Add operator=. Fix constructors.
+* 11-11-91 KRS Change xalloc() to conform to AT&T usage.
+* 11-20-91 KRS Add copy constructor.
+* 02-12-92 KRS Fix init of delbuf in ios::ios(streambuf*).
+* 03-30-92 KRS Add MTHREAD lock init calls to constructors.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <iostream.h>
+#pragma hdrstop
+
+const long ios::basefield = (ios::dec | ios::oct | ios::hex);
+const long ios::adjustfield = (ios::left | ios::right | ios::internal);
+const long ios::floatfield = (ios::scientific | ios::fixed);
+
+long ios::x_maxbit = 0x8000; // ios::openprot
+int ios::x_curindex = -1;
+
+#ifdef MTHREAD
+// UNDONE: enough? 15?
+#define MAXINDEX 7
+long ios::x_statebuf[MAXINDEX+1] = { 0,0,0,0,0,0,0,0 }; // MAXINDEX * 0
+int ios::fLockcInit = 0; // nonzero = static lock initialized
+RTL_CRITICAL_SECTION ios::x_lockc;
+#else // MTHREAD
+long * ios::x_statebuf = NULL;
+#endif // MTHREAD
+
+/***
+*ios::ios() - default constructor.
+*
+*Purpose:
+* Initializes an ios.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+ios::ios()
+{
+ bp = NULL;
+ state = ios::badbit;
+
+ ispecial = 0;
+ ospecial = 0;
+ x_tie = (0);
+ x_flags = 0;
+ x_precision = 6;
+ x_fill = ' ';
+ x_width = 0;
+ x_delbuf = 0;
+
+#ifdef MTHREAD
+ LockFlg = 1; // default is no locking
+ _mtlockinit(lockptr());
+ if (!fLockcInit) // UNDONE: find a cheaper way to do this
+ {
+ _mtlockinit(&x_lockc);
+ fLockcInit++;
+ }
+#endif /* MTHREAD */
+
+}
+
+
+
+/***
+*ios::ios( streambuf* pSB ) - constructor.
+*
+*Purpose:
+* Initializes an ios.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+ios::ios( streambuf* pSB )
+{
+// this->ios();
+
+ bp = pSB;
+ state = (bp) ? 0 : ios::badbit;
+
+ ispecial = 0;
+ ospecial = 0;
+ x_tie = (0);
+ x_flags = 0;
+ x_precision = 6;
+ x_fill = ' ';
+ x_width = 0;
+ x_delbuf = 0;
+
+#ifdef MTHREAD
+ LockFlg = 1; // default is no locking
+ _mtlockinit(lockptr());
+ if (!fLockcInit) // UNDONE: find a cheaper way to do this
+ {
+ _mtlockinit(&x_lockc);
+ fLockcInit++;
+ }
+#endif /* MTHREAD */
+
+}
+
+/***
+*ios::ios(const ios& _strm) - copy constructor.
+*
+*Purpose:
+* Copy constructor.
+*
+*Entry:
+* _strm = ios to copy data members from.
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+ios::ios(const ios& _strm) // copy constructor
+{
+ bp = NULL;
+ x_delbuf = 0;
+
+// init(_strm.rdbuf());
+// delbuf(_strm.delbuf());
+
+ *this = _strm; // invoke assignment operator
+// state = (bp) ? 0 : ios::badbit;
+
+#ifdef MTHREAD
+ LockFlg = 1; // default is no locking
+ _mtlockinit(lockptr());
+ if (!fLockcInit) // UNDONE: find a cheaper way to do this
+ {
+ _mtlockinit(&x_lockc);
+ fLockcInit++;
+ }
+#endif /* MTHREAD */
+
+}
+
+
+/***
+*virtual ios::~ios() - default destructor.
+*
+*Purpose:
+* Terminates an ios.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+ios::~ios()
+{
+ lock(); // make sure no one else is using it
+ if ((x_delbuf) && (bp))
+ delete bp;
+ bp = NULL;
+ state = badbit;
+
+}
+
+
+/***
+*void ios::init( streambuf* pSB ) - initializes ios
+*
+*Purpose:
+* Initializes an ios.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void ios::init( streambuf* pSB )
+{
+ if (delbuf() && (bp)) // delete previous bp if necessary
+ delete bp;
+ bp = pSB;
+ if (bp)
+ state &= ~ios::badbit;
+ else
+ state |= ios::badbit;
+}
+
+
+
+/***
+*ios& ios::operator=( const ios& _strm ) - copy an ios.
+*
+*Purpose:
+* Copy an ios.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+ios& ios::operator=(const ios& _strm)
+{
+ x_tie = _strm.tie();
+ x_flags = _strm.flags();
+ x_precision = (char)_strm.precision();
+ x_fill = _strm.fill();
+ x_width = (char)_strm.width();
+
+ state = _strm.rdstate();
+ if (!bp)
+ state |= ios::badbit; // adjust state for uninitialized bp
+
+// init(_strm.rdbuf());
+// delbuf(_strm.delbuf());
+
+ return *this;
+}
+
+/***
+*int ios::xalloc() - ios xalloc member function
+*
+*Purpose:
+* UNDONE:
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns index of of new entry in new buffer, or EOF if error.
+*
+*Exceptions:
+* Returns EOF if OM error.
+*
+*******************************************************************************/
+int ios::xalloc()
+{
+#ifdef MTHREAD
+ // buffer must be static if multithread, since thread can't keep track of
+ // validity of pointer otherwise
+ int index;
+ lockc();
+ if (x_curindex >= MAXINDEX)
+ index = EOF;
+ else
+ {
+ index = ++x_curindex;
+// x_statebuf[index] = 0;
+ }
+ unlockc();
+ return index;
+#else // MTHREAD
+ long * tptr;
+ int i;
+
+ if (!(tptr=new long[x_curindex+2])) // allocate new buffer
+ return EOF;
+
+ for (i=0; i <= x_curindex; i++) // copy old buffer, if any
+ tptr[i] = x_statebuf[i];
+
+ tptr[++x_curindex] = 0L; // init new entry, bump size
+
+ if (x_statebuf) // delete old buffer, if any
+ delete x_statebuf;
+ x_statebuf = tptr; // and assign new buffer
+ return x_curindex;
+#endif // MTHREAD
+}
+
+/***
+*long ios::bitalloc() - ios bitalloc member function
+*
+*Purpose:
+* Returns a unused bit mask for flags().
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns next available bit maskf.
+*
+*Exceptions:
+*
+*******************************************************************************/
+long ios::bitalloc() // CONSIDER: make inline?
+{
+ long b;
+ lockc(); // lock to make sure mask in unique (MTHREAD)
+ b = (x_maxbit<<=1);
+ unlockc();
+ return b;
+}
diff --git a/private/crt32/iostream/iostream.cxx b/private/crt32/iostream/iostream.cxx
new file mode 100644
index 000000000..1ae765423
--- /dev/null
+++ b/private/crt32/iostream/iostream.cxx
@@ -0,0 +1,83 @@
+/***
+* iostream.cxx - definitions for iostream classes
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definitions for iostream classes. Also,
+* precompile all header files used by iostream lib into iostream.pch.
+*
+*Revision History:
+* 09-23-91 KRS Created.
+* 11-13-91 KRS Rearranged.
+* 11-20-91 KRS Added copy constructor and assignment operators.
+* 01-23-92 KRS Merge pch.cxx into this file.
+*
+*******************************************************************************/
+
+// NOTE: the follow must include ALL header files used by any of the iostream
+// source files which we want built into iostream.pch. It is necessary
+// to have the pch associated with exactly one of the library modules
+// for efficient storage of Codeview info.
+
+#include <cruntime.h>
+#include <internal.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <share.h>
+#include <fcntl.h>
+#include <io.h>
+// #include <sys\stat.h> // compile problems
+#include <sys\types.h>
+#include <float.h>
+#include <iostream.h>
+// #include <ios.h>
+// #include <streamb.h>
+// #include <istream.h>
+// #include <ostream.h>
+#include <fstream.h>
+#include <strstrea.h>
+#include <stdiostr.h>
+
+#pragma hdrstop // end of headers to precompile
+
+// CONSIDER: not used, is this required???
+ iostream::iostream()
+: istream(), ostream()
+{
+// CONSIDER: do anything else?
+}
+
+ iostream::iostream(streambuf * _sb)
+: istream(_sb), ostream(_sb)
+{
+// CONSIDER: do anything else?
+}
+
+ iostream::iostream(const iostream& _strm)
+: istream(_strm), ostream(_strm)
+{
+// CONSIDER: do anything else?
+}
+
+iostream::~iostream()
+{
+// if both input and output share the same streambuf, but not the same ios,
+// make sure only deleted once
+if ((istream::bp==ostream::bp) && (&istream::bp!=&ostream::bp))
+ istream::bp = NULL; // let ostream::ios::~ios() do it
+// CONSIDER: do anything else?
+}
+
+/* done inline
+iostream& iostream::operator=(streambuf* _sb)
+{
+ istream::operator=(_sb);
+ ostream::operator=(_sb);
+ return *this;
+}
+*/
diff --git a/private/crt32/iostream/iostrini.cxx b/private/crt32/iostream/iostrini.cxx
new file mode 100644
index 000000000..e6bb83ba2
--- /dev/null
+++ b/private/crt32/iostream/iostrini.cxx
@@ -0,0 +1,83 @@
+/***
+*iostrini.cxx - definition and initialization for predefined stream cout.
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definition and initialization of and predefined iostream cout.
+*
+*Revision History:
+* 11-18-91 KRS Created.
+*
+*******************************************************************************/
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#include <fstream.h>
+#pragma hdrstop
+
+// put contructors in special MS-specific XIFM segment
+#pragma warning(disable:4074) // disable init_seg warning
+#pragma init_seg(compiler)
+
+#if ((!defined(_WINDOWS)) || defined(_QWIN))
+ostream_withassign cout(new filebuf(1));
+
+static Iostream_init __InitCout(cout,-1);
+
+#endif
+
+/***
+*Iostream_init::Iostream_init() - initialize predefined streams
+*
+*Purpose:
+* For compatibility only. Not used.
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+ Iostream_init::Iostream_init() { } // do nothing
+
+/***
+*Iostream_init::Iostream_init() - initialize predefined streams
+*
+*Purpose:
+* Initializes predefined streams: cin, cout, cerr, clog;
+*Entry:
+* pstrm = cin, cout, cerr, or clog
+* sflg = 1 if cerr (unit buffered)
+* sflg = -1 if cout
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+ Iostream_init::Iostream_init(ios& pstrm, int sflg)
+{
+#if ((!defined(_WINDOWS)) || defined(_QWIN))
+ pstrm.delbuf(1);
+ if (sflg>=0) // make sure not cout
+ pstrm.tie(&cout);
+ if (sflg>0)
+ pstrm.setf(ios::unitbuf);
+#endif
+}
+
+/***
+*Iostream_init::~Iostream_init() - destroy predefined streams on exit
+*
+*Purpose:
+* Destroy predefined streams: cin, cout, cerr, clog;
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+ Iostream_init::~Iostream_init() { } // do nothing
+
diff --git a/private/crt32/iostream/istrchar.cxx b/private/crt32/iostream/istrchar.cxx
new file mode 100644
index 000000000..0896a3e9d
--- /dev/null
+++ b/private/crt32/iostream/istrchar.cxx
@@ -0,0 +1,40 @@
+/***
+* istrchar.cxx - definitions for istream class operator>>(char&)
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of member function for istream operator>>(char&).
+* [AT&T C++]
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from istream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// CONSIDER: validify all these maximum lengths...
+
+istream& istream::operator>>(char& c)
+{
+ int tchar;
+ if (ipfx(0))
+ {
+ tchar=bp->sbumpc();
+ if (tchar==EOF)
+ {
+ state |= ios::eofbit|ios::badbit;
+ }
+ else
+ {
+ c = (char)tchar;
+ }
+ isfx();
+ }
+ return *this;
+}
diff --git a/private/crt32/iostream/istrdbl.cxx b/private/crt32/iostream/istrdbl.cxx
new file mode 100644
index 000000000..a129d4d20
--- /dev/null
+++ b/private/crt32/iostream/istrdbl.cxx
@@ -0,0 +1,46 @@
+/***
+* istrdbl.cxx - definition for operator>>(double) member funct for istream class
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definition of operator>>(double) member function for istream class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+* 12-30-92 KRS Fix indirection problem with **endptr.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <iostream.h>
+#pragma hdrstop
+
+#pragma check_stack(on) // large buffer(s)
+
+// CONSIDER: validate this maximum length
+#define MAXDBLSIZ 28
+
+istream& istream::operator>>(double& n)
+{
+_WINSTATIC char ibuffer[MAXDBLSIZ];
+ char ** endptr = (char**)NULL;
+ if (ipfx(0))
+ {
+ if (getdouble(ibuffer, MAXDBLSIZ)>0)
+ {
+ n = strtod(ibuffer, endptr);
+#if 0
+ if (**endptr)
+ {
+ //UNDONE: put back any unread characters, if possible
+ }
+#endif
+ }
+ isfx();
+ }
+return *this;
+}
diff --git a/private/crt32/iostream/istream.cxx b/private/crt32/iostream/istream.cxx
new file mode 100644
index 000000000..d5916001d
--- /dev/null
+++ b/private/crt32/iostream/istream.cxx
@@ -0,0 +1,278 @@
+/***
+* istream.cxx - definitions for istream and istream_withassign classes
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of member functions for istream and istream_withassign
+* classes.
+* [AT&T C++]
+*
+*Revision History:
+* 07-15-91 KRS Created.
+* 08-15-91 KRS Fix handling of 1-length strings in get(char*,int,int)
+* 08-20-91 KRS Make read() not do text translation (for filebufs)
+* 08-21-91 KRS Fix >>(streambuf *) to advance pointer properly.
+* 08-22-91 KRS Fix octal error in getint().
+* 08-26-91 KRS Fix for Windows DLL's and set max. ibuffer[] lengths.
+* 09-05-91 KRS Don't special-case 0x in getint(). Spec. conformance...
+* 09-10-91 KRS Reinstate text translation (by default) for read().
+* 09-12-91 KRS Treat count as unsigned in get() and read().
+* 09-16-91 KRS Fix get(char *, int lim, char) for lim=0 case.
+* 09-23-91 KRS Split up flie for granularity purposes.
+* 10-21-91 KRS Make eatwhite() return void again.
+* 10-24-91 KRS Move istream_withassign::operator=(streambuf*) here.
+* 11-04-91 KRS Make constructors work with virtual base.
+* Fix whitespace error handling in ipfx().
+* 11-20-91 KRS Add/fix copy constructor and assignment operators.
+* 01-23-92 KRS C700 #5883: Fix behaviour of peek() to call ipfx(1).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <iostream.h>
+#pragma hdrstop
+
+ istream::istream()
+// : ios()
+{
+ x_flags |= ios::skipws;
+ x_gcount = 0;
+ _fGline = 0;
+ // CONSIDER: do anything else?
+}
+
+ istream::istream(streambuf* _inistbf)
+// : ios()
+{
+ init(_inistbf);
+
+ x_flags |= ios::skipws;
+ x_gcount = 0;
+ _fGline = 0;
+ // CONSIDER: do anything else?
+}
+
+ istream::istream(const istream& _istrm)
+// : ios()
+{
+ init(_istrm.rdbuf());
+
+ x_flags |= ios::skipws;
+ x_gcount = 0;
+ _fGline = 0;
+ // CONSIDER: do anything else?
+}
+
+ istream::~istream()
+// : ~ios()
+{
+ // CONSIDER: do anything else?
+}
+
+// used by ios::sync_with_stdio()
+istream& istream::operator=(streambuf * _sbuf)
+{
+// consider: may be some redundency here, depending on spec.
+ if (delbuf() && rdbuf())
+ delete rdbuf();
+ bp = 0;
+
+ this->ios::operator=(ios()); // initialize ios members
+ delbuf(0); // important!
+ init(_sbuf); // set up bp
+
+ x_flags |= ios::skipws; // init istream members too
+ x_gcount = 0;
+// _fGline = 0; // not necessary
+
+ return *this;
+}
+int istream::ipfx(int need)
+{
+ lock();
+ if (need) // reset gcount if unformatted input
+ x_gcount = 0;
+ if (state) // return 0 iff error condition
+ {
+ state |= ios::failbit; // solves cin>>buf problem
+ unlock();
+ return 0;
+ }
+ if (x_tie && ((need==0) || (need > bp->in_avail())))
+ {
+ x_tie->flush();
+ }
+ lockbuf();
+ if ((need==0) && (x_flags & ios::skipws))
+ {
+ eatwhite();
+ if (state) // eof or error
+ {
+ state |= ios::failbit;
+ unlockbuf();
+ unlock();
+ return 0;
+ }
+ }
+ // leave locked ; isfx() will unlock
+ return 1; // return nz if okay
+}
+
+// formatted input functions
+
+istream& istream::operator>>(char * s)
+{
+ int c;
+ unsigned int i, lim;
+ if (ipfx(0))
+ {
+ lim = (unsigned)(x_width-1);
+ x_width = 0;
+ if (!s)
+ {
+ state |= ios::failbit;
+ }
+ else
+ {
+ for (i=0; i< lim; i++)
+ {
+ c=bp->sgetc();
+ if (c==EOF)
+ {
+ state |= ios::eofbit;
+ if (!i)
+ state |= ios::failbit|ios::badbit;
+ break;
+ }
+ else if (isspace(c))
+ {
+ break;
+ }
+ else
+ {
+ s[i] = (char)c;
+ bp->stossc(); // advance pointer
+ }
+ }
+ if (!i)
+ state |= ios::failbit;
+ else
+ s[i] = '\0';
+ }
+ isfx();
+ }
+ return *this;
+}
+
+#if 0
+istream& istream::operator>>(char& c)
+{
+ int tchar;
+ if (ipfx(0))
+ {
+ tchar=bp->sbumpc();
+ if (tchar==EOF)
+ {
+ state |= ios::eofbit|ios::badbit;
+ }
+ else
+ {
+ c = (char)tchar;
+ }
+ isfx();
+ }
+ return *this;
+}
+#endif
+
+int istream::peek()
+{
+int retval;
+ if (ipfx(1))
+ {
+ retval = (bp->sgetc());
+ isfx();
+ }
+ else
+ retval = EOF;
+ return retval;
+}
+
+istream& istream::putback(char c)
+{
+// if (!bad()) // CONSIDER: just return if bad error?
+ if (good()) // this is how it's spec.ed out...
+ {
+ lockbuf();
+
+ if (bp->sputbackc(c)==EOF)
+ {
+ clear(state | ios::failbit);
+ }
+// else
+// clear(state & ~(ios::eof)); // no longer at end of file, if we were...
+
+ unlockbuf();
+ }
+ return *this;
+}
+
+int istream::sync()
+{
+ int retval;
+ lockbuf();
+
+ if ((retval=bp->sync())==EOF)
+ {
+ clear(state | (ios::failbit|ios::badbit));
+ }
+
+ unlockbuf();
+ return retval;
+}
+
+void istream::eatwhite()
+{
+ int c;
+ lockbuf();
+ c = bp->sgetc();
+ for ( ; ; )
+ {
+ if (c==EOF)
+ {
+ clear(state | ios::eofbit);
+ break;
+ }
+ if (isspace(c))
+ {
+ c = bp->snextc();
+ }
+ else
+ {
+ break;
+ }
+ }
+ unlockbuf();
+}
+
+ istream_withassign::istream_withassign()
+: istream()
+{
+ // CONSIDER: do anything else?
+}
+
+ istream_withassign::istream_withassign(streambuf* _is)
+: istream(_is)
+{
+ // CONSIDER: do anything else?
+}
+
+ istream_withassign::~istream_withassign()
+// : ~istream()
+{
+ // CONSIDER: do anything else?
+}
diff --git a/private/crt32/iostream/istream1.cxx b/private/crt32/iostream/istream1.cxx
new file mode 100644
index 000000000..ff2bc8098
--- /dev/null
+++ b/private/crt32/iostream/istream1.cxx
@@ -0,0 +1,98 @@
+/***
+* istream1.cxx - non-core definitions for istream & istream_withassign classes
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of non-core member functions for istream and
+* istream_withassign classes.
+* [AT&T C++]
+*
+*Revision History:
+* 09-23-91 KRS Created. Split off from istream.cxx for granularity.
+* 10-07-91 KRS Increment x_gcount in get(sb).
+* 10-24-91 KRS Fix istream_withassign::operator=() functions.
+* 11-20-91 KRS Make operator= inline.
+* 03-30-92 KRS Add multithread locking.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <iostream.h>
+#pragma hdrstop
+
+istream& istream::operator>>(streambuf* _sbuf)
+{
+ int c;
+ if (ipfx(0))
+ {
+ while ((c=bp->sbumpc())!=EOF)
+ {
+ if (_sbuf->sputc(c)==EOF)
+ {
+ state |= ios::failbit;
+ }
+ }
+ isfx();
+ }
+return *this;
+}
+
+
+// unformatted input functions
+
+istream& istream::get( streambuf& sbuf, char delim)
+{
+ int c;
+ if (ipfx(1)) // resets x_gcount
+ {
+ while ((c = bp->sgetc())!=delim)
+ {
+ if (c==EOF) // stop if EOF encountered
+ {
+ state |= ios::eofbit;
+ break;
+ }
+ bp->stossc(); // advance get pointer
+ x_gcount++; // and increment count
+
+ // store c into sbuf // UNDONE: is this what they meant???
+ if (sbuf.sputc(c)==EOF)
+ state |= ios::failbit;
+ }
+ isfx();
+ }
+ return *this;
+}
+
+istream& istream::seekg(streampos _strmp)
+{
+ lockbuf();
+ if (bp->seekpos(_strmp, ios::in)==EOF)
+ {
+ clear(state | failbit);
+ }
+ unlockbuf();
+ return(*this);
+}
+
+istream& istream::seekg(streamoff _strmf, seek_dir _sd)
+{
+ lockbuf();
+ if (bp->seekoff(_strmf, _sd, ios::in)==EOF)
+ clear(state | failbit);
+ unlockbuf();
+ return(*this);
+}
+
+streampos istream::tellg()
+{
+ streampos retval;
+ lockbuf();
+ if ((retval=bp->seekoff(streamoff(0), ios::cur, ios::in))==EOF)
+ clear(state | failbit);
+ unlockbuf();
+ return(retval);
+}
diff --git a/private/crt32/iostream/istrflt.cxx b/private/crt32/iostream/istrflt.cxx
new file mode 100644
index 000000000..79c04a11b
--- /dev/null
+++ b/private/crt32/iostream/istrflt.cxx
@@ -0,0 +1,58 @@
+/***
+* istrflt.cxx - definitions for istream operator>>(float) member function
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of operator>>(float) member function for istream class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split out from istream.cxx for granularity.
+* 12-30-92 KRS Fix indirection problem with **endptr.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <float.h>
+#include <iostream.h>
+#pragma hdrstop
+
+#pragma check_stack(on) // large buffer(s)
+
+// CONSIDER: validate this maximum length
+#define MAXFLTSIZ 20
+
+istream& istream::operator>>(float& n)
+{
+_WINSTATIC char ibuffer[MAXFLTSIZ];
+ double d;
+ char ** endptr = (char**)NULL;
+ if (ipfx(0))
+ {
+ if (getdouble(ibuffer, MAXFLTSIZ)>0)
+ {
+ d = strtod(ibuffer, endptr);
+#if 0
+ if (**endptr)
+ {
+ //UNDONE: put back any unread characters, if possible
+ }
+#endif
+ if (d > FLT_MAX)
+ n = FLT_MAX;
+ else if (d < -FLT_MAX)
+ n = -FLT_MAX;
+ else if ((d>0) && (d< FLT_MIN))
+ n = FLT_MIN;
+ else if ((d<0) && (d> -FLT_MIN))
+ n = - FLT_MIN;
+ else
+ n = (float) d;
+ }
+ isfx();
+ }
+return *this;
+}
diff --git a/private/crt32/iostream/istrgdbl.cxx b/private/crt32/iostream/istrgdbl.cxx
new file mode 100644
index 000000000..e3bb18b2b
--- /dev/null
+++ b/private/crt32/iostream/istrgdbl.cxx
@@ -0,0 +1,105 @@
+/***
+* istrgdbl.cxx - definitions for istream class core double routine
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of member function for istream getdouble().
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <ctype.h>
+#include <iostream.h>
+#pragma hdrstop
+
+/***
+*int istream::getdouble(char * buffer, int buflen) - get a double
+*
+*Purpose:
+* Get a double from stream.
+*
+*Entry:
+* char * buffer = area for number to be copied.
+* int buflen = max. length of buffer
+*
+*Exit:
+* Returns 0 if fatal error
+* Otherwise, returns length of buffer filled.
+* Sets ios::failbit on error forming number.
+* If successful, buffer[] contains the number, followed by \0.
+*
+*Exceptions:
+*
+*******************************************************************************/
+int istream::getdouble(char * buffer, int buflen) // returns length
+{
+ int c;
+ int i = 0;
+ int fDigit = 0; // true if legal digit encountered
+ int fDecimal=0; // true if '.' encountered or no longer valid
+ int fExp=0; // true if 'E' or 'e' encounted
+
+ if (ipfx(0))
+ {
+ c=bp->sgetc();
+ for (; i<buflen; buffer[i] = (char)c,c=bp->snextc(),i++)
+ {
+ if (c==EOF)
+ {
+ state |= ios::eofbit;
+ break;
+ }
+ if ((!i) || (fExp==1))
+ {
+ if ((c=='-') || (c=='+'))
+ {
+ continue;
+ }
+ }
+ // UNDONE: use locale-dependent decimal point character!!!
+ if ((c=='.') && (!fExp) && (!fDecimal))
+ {
+ fDecimal++;
+ continue;
+ }
+ if (((c=='E') || (c=='e')) && (!fExp))
+ {
+ fDecimal++; // can't allow decimal now
+ fExp++;
+ continue;
+ }
+ if (!isdigit(c))
+ break;
+ if (fExp)
+ fExp++;
+ else
+ fDigit++;
+ }
+ if (fExp==1) // E or e with no number after it
+ {
+ if (bp->sputbackc(buffer[i])!=EOF)
+ {
+ i--;
+ state &= ~(ios::eofbit);
+ }
+ else
+ {
+ state |= ios::failbit; // CONSIDER: correct?
+ }
+ }
+ if ((!fDigit) || (i==buflen))
+ state |= ios::failbit;
+
+ // buffer contains a valid number or '\0'
+ buffer[i] = '\0';
+ isfx();
+ }
+ // UNDONE: check for errors, return EOF
+ return i;
+}
diff --git a/private/crt32/iostream/istrget.cxx b/private/crt32/iostream/istrget.cxx
new file mode 100644
index 000000000..7b099cda7
--- /dev/null
+++ b/private/crt32/iostream/istrget.cxx
@@ -0,0 +1,65 @@
+/***
+* istrget.cxx - definitions for istream class get() member functions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of get() member functions for istream class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// unformatted input functions
+
+int istream::get()
+{
+ int c;
+ if (ipfx(1)) // resets x_gcount
+ {
+ if ((c=bp->sbumpc())==EOF)
+ state |= ios::eofbit;
+ else
+ x_gcount++;
+ isfx();
+ return c;
+ }
+ return EOF;
+}
+
+// signed and unsigned char make inline calls to this:
+istream& istream::get( char& c)
+{
+ int temp;
+ if (ipfx(1)) // resets x_gcount
+ {
+ if ((temp=bp->sbumpc())==EOF)
+ state |= (ios::failbit|ios::eofbit); // UNDONE ??
+ else
+ x_gcount++;
+ c = (char) temp;
+ isfx();
+ }
+ return *this;
+}
+
+
+// called by signed and unsigned char versions
+istream& istream::read(char * ptr, int n)
+{
+ if (ipfx(1)) // resets x_gcount
+ {
+ x_gcount = bp->sgetn(ptr, n);
+ if ((unsigned)x_gcount < (unsigned)n)
+ state |= (ios::failbit|ios::eofbit);
+ isfx();
+ }
+ return *this;
+}
diff --git a/private/crt32/iostream/istrgetl.cxx b/private/crt32/iostream/istrgetl.cxx
new file mode 100644
index 000000000..a8ce283cf
--- /dev/null
+++ b/private/crt32/iostream/istrgetl.cxx
@@ -0,0 +1,70 @@
+/***
+* istrgetl.cxx - definitions for istream class getl() member function
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of get and getline member functions istream class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+* 01-23-92 KRS C700 #5880: Add cast to fix comparison in get().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// unformatted input functions
+
+// signed and unsigned char make inline calls to this:
+// all versions of getline also share this code:
+
+istream& istream::get( char *b, int lim, char delim)
+{
+ int c;
+ unsigned int i = 0;
+ if (ipfx(1)) // resets x_gcount
+ {
+ if (lim--)
+ {
+ while (i < (unsigned)lim)
+ {
+ c=bp->sgetc();
+ if (c==EOF)
+ {
+ state |= ios::eofbit;
+ if (!i)
+ state |= ios::failbit;
+ break;
+ }
+ else if (c==(int)(unsigned char)delim)
+ {
+ if (_fGline)
+ {
+ x_gcount++;
+ bp->stossc(); // extract delim if called from getline
+ }
+ break;
+ }
+ else
+ {
+ if (b)
+ b[i] = (char)c;
+ bp->stossc(); // advance pointer
+ }
+ i++;
+ }
+ x_gcount += i; // set gcount()
+ }
+ isfx();
+ lim++; // restore lim for test below
+ }
+ if ((b) && (lim)) // always null-terminate, if possible
+ b[i] = '\0';
+ _fGline = 0;
+ return *this;
+}
diff --git a/private/crt32/iostream/istrgint.cxx b/private/crt32/iostream/istrgint.cxx
new file mode 100644
index 000000000..0f4997483
--- /dev/null
+++ b/private/crt32/iostream/istrgint.cxx
@@ -0,0 +1,145 @@
+/***
+* istrgint.cxx - definitions for istream class core integer routines
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of member function getint() for istream class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+* 01-06-92 KRS Remove buflen argument.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <ctype.h>
+#include <iostream.h>
+#pragma hdrstop
+
+#define MAXLONGSIZE 16
+
+/***
+*int istream::getint(char * buffer) - get an int
+*
+*Purpose:
+* Get an int from stream.
+*
+*Entry:
+* char * buffer = area for number to be copied.
+*
+*Exit:
+* Returns base for conversion: (0, 2, 8, or 16).
+* If successful, buffer[] contains the number, followed by \0.
+*
+*Exceptions:
+* Sets ios::failbit on error forming number.
+* Sets ios::badbit on error after failbit
+* Sets ios::eofbit if at EOF at return
+*
+*******************************************************************************/
+int istream::getint(char * buffer) // returns length
+{
+ int base, i;
+ int c;
+ int fDigit = 0;
+ int bindex = 1;
+
+ if (x_flags & ios::dec)
+ base = 10;
+ else if (x_flags & ios::hex)
+ base = 16;
+ else if (x_flags & ios::oct)
+ base = 8;
+ else
+ base = 0;
+
+ if (ipfx(0))
+ {
+ c=bp->sgetc();
+ for (i = 0; i<MAXLONGSIZE; buffer[i] = (char)c,c=bp->snextc(),i++)
+ {
+ if (c==EOF)
+ {
+ state |= ios::eofbit;
+ break;
+ }
+ if (!i)
+ {
+ if ((c=='-') || (c=='+'))
+ {
+ bindex++;
+ continue;
+ }
+ }
+ if ((i==bindex) && (buffer[i-1]=='0'))
+ {
+ if (((c=='x') || (c=='X')) && ((base==0) || (base==16)))
+ {
+ base = 16; // simplifies matters
+ fDigit = 0;
+ continue;
+ }
+ else if (base==0)
+ {
+ base = 8;
+ }
+ }
+
+
+ // now simply look for a digit and set fDigit if found else break
+
+ if (base==16)
+ {
+ if (!isxdigit(c))
+ break;
+ }
+ else if ((!isdigit(c)) || ((base==8) && (c>'7')))
+ break;
+
+ fDigit++;
+ }
+ if (!fDigit)
+ {
+#if 0
+ if ((i==bindex+1) && ((buffer[bindex]=='x') || (buffer[bindex]=='X')))
+ {
+ // found 0x but no number, so back up one and return '0'
+ if (bp->sputbackc(buffer[bindex])!=EOF)
+ {
+ i--;
+ state &= ~(ios::eofbit);
+ // fDigit++;
+ }
+ else
+ state |= (ios::failbit|ios::badbit); // CONSIDER: correct?
+ }
+ else
+#endif
+ {
+ state |= ios::failbit;
+ while (i--)
+ {
+ if(bp->sputbackc(buffer[i])==EOF)
+ {
+ state |= ios::badbit; // CONSIDER: correct?
+ break;
+ }
+ else
+ state &= ~(ios::eofbit);
+ }
+ i=0;
+ }
+ }
+ // buffer contains a valid number or '\0'
+ buffer[i] = '\0';
+ isfx();
+ }
+ if (i==MAXLONGSIZE)
+ {
+ state |= ios::failbit;
+ }
+ return base;
+}
diff --git a/private/crt32/iostream/istrint.cxx b/private/crt32/iostream/istrint.cxx
new file mode 100644
index 000000000..30c8eae48
--- /dev/null
+++ b/private/crt32/iostream/istrint.cxx
@@ -0,0 +1,71 @@
+/***
+* istrint.cxx - definitions for istream class operaotor>>(int) member functions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of operator>>(int) member function(s) for istream class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split out from istream.cxx for granularity.
+* 12-30-92 KRS Fix indirection problem with **endptr.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// CONSIDER: validify all this maximum length
+#define MAXLONGSIZ 16
+
+/***
+*istream& istream::operator>>(int& n) - extract int
+*
+*Purpose:
+* Extract int value from stream
+*
+*Entry:
+* n = value to update
+*
+*Exit:
+* n updated, or ios::failbit & n=INT_MAX/INT_MIN on overflow/underflow
+*
+*Exceptions:
+* Stream error on entry or value out of range
+*
+*******************************************************************************/
+istream& istream::operator>>(int& n)
+{
+_WINSTATIC char ibuffer[MAXLONGSIZ];
+ long value;
+ char ** endptr = (char**)NULL;
+ if (ipfx(0))
+ {
+ value = strtol(ibuffer, endptr, getint(ibuffer));
+ if (value>INT_MAX)
+ {
+ n = INT_MAX;
+ state |= ios::failbit;
+ }
+ else if (value<INT_MIN)
+ {
+ n = INT_MIN;
+ state |= ios::failbit;
+ }
+ else
+ n = (int) value;
+#if 0
+ if (**endptr)
+ {
+ // UNDONE: put back any unread characters, if possible
+ }
+#endif
+ isfx();
+ }
+return *this;
+}
diff --git a/private/crt32/iostream/istrldbl.cxx b/private/crt32/iostream/istrldbl.cxx
new file mode 100644
index 000000000..6059685b2
--- /dev/null
+++ b/private/crt32/iostream/istrldbl.cxx
@@ -0,0 +1,48 @@
+/***
+* istrldbl.cxx - definitions for istream class operator>>(long double) funct
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of operator>>(long double) member function for istream
+* class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+* 12-30-92 KRS Fix indirection problem with **endptr.
+* 05-10-93 CFW Re-enable function, use strtod since no _strtold.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <iostream.h>
+#pragma hdrstop
+
+#pragma check_stack(on) // large buffer(s)
+
+// CONSIDER: validate this maximum length
+#define MAXLDBLSIZ 32
+
+istream& istream::operator>>(long double& n)
+{
+_WINSTATIC char ibuffer[MAXLDBLSIZ];
+ char ** endptr = (char**)NULL;
+ if (ipfx(0))
+ {
+ if (getdouble(ibuffer, MAXLDBLSIZ)>0)
+ {
+ n = (long double)strtod(ibuffer, endptr);
+#if 0
+ if (**endptr)
+ {
+ //UNDONE: put back any unread characters, if possible
+ }
+#endif
+ }
+ isfx();
+ }
+return *this;
+}
diff --git a/private/crt32/iostream/istrlong.cxx b/private/crt32/iostream/istrlong.cxx
new file mode 100644
index 000000000..1a701da0b
--- /dev/null
+++ b/private/crt32/iostream/istrlong.cxx
@@ -0,0 +1,63 @@
+/***
+* istrlong.cxx - definitions for istream class operator>>(long) member function
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of operator>>(long) member function(s) for istream class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+* 01-06-92 KRS Added check of errno.
+* 12-30-92 KRS Fix indirection problem with **endptr.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// CONSIDER: validify this maximum length
+#define MAXLONGSIZ 16
+
+/***
+*istream& istream::operator>>(long& n) - extract long
+*
+*Purpose:
+* Extract long value from stream
+*
+*Entry:
+* n = value to update
+*
+*Exit:
+* n updated, or ios::failbit & n=LONG_MAX/LONG_MIN on overflow/underflow
+*
+*Exceptions:
+* Stream error on entry or value out of range
+*
+*******************************************************************************/
+istream& istream::operator>>(long& n)
+{
+_WINSTATIC char ibuffer[MAXLONGSIZ];
+ char ** endptr = (char**)NULL;
+ if (ipfx(0)) {
+ n = strtol(ibuffer, endptr, getint(ibuffer));
+ if (errno==ERANGE)
+ {
+ state |= ios::failbit;
+ }
+#if 0
+ if (**endptr)
+ {
+ //UNDONE: put back any unread characters, if possible
+ }
+#endif
+ isfx();
+ }
+return *this;
+}
diff --git a/private/crt32/iostream/istrshrt.cxx b/private/crt32/iostream/istrshrt.cxx
new file mode 100644
index 000000000..e61a71dbf
--- /dev/null
+++ b/private/crt32/iostream/istrshrt.cxx
@@ -0,0 +1,71 @@
+/***
+* istrshrt.cxx - definitions for istream class operator>>(short) function(s)
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of operator>>(short) member function(s) for istream class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+* 12-30-92 KRS Fix indirection problem with **endptr.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// CONSIDER: validify this maximum length
+#define MAXLONGSIZ 16
+
+/***
+*istream& istream::operator>>(short& n) - extract short
+*
+*Purpose:
+* Extract short value from stream
+*
+*Entry:
+* n = value to update
+*
+*Exit:
+* n updated, or ios::failbit & n=SHRT_MAX/SHRT_MIN on overflow/underflow
+*
+*Exceptions:
+* Stream error on entry or value out of range
+*
+*******************************************************************************/
+istream& istream::operator>>(short& n)
+{
+_WINSTATIC char ibuffer[MAXLONGSIZ];
+ long value;
+ char ** endptr = (char**)NULL;
+ if (ipfx(0))
+ {
+ value = strtol(ibuffer, endptr, getint(ibuffer));
+ if (value>SHRT_MAX)
+ {
+ n = SHRT_MAX;
+ state |= ios::failbit;
+ }
+ else if (value<SHRT_MIN)
+ {
+ n = SHRT_MIN;
+ state |= ios::failbit;
+ }
+ else
+ n = (short) value;
+#if 0
+ if (**endptr)
+ {
+ //UNDONE: put back any unread characters, if possible
+ }
+#endif
+ isfx();
+ }
+return *this;
+}
diff --git a/private/crt32/iostream/istruint.cxx b/private/crt32/iostream/istruint.cxx
new file mode 100644
index 000000000..9432b08f4
--- /dev/null
+++ b/private/crt32/iostream/istruint.cxx
@@ -0,0 +1,72 @@
+/***
+* istruint.cxx - definitions for istream class operaotor>>(unsigned int) funct
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of operator>>(unsigned int) member function for istream
+* class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split out from istream.cxx for granularity.
+* 01-06-92 KRS Improve error handling.
+* 12-30-92 KRS Fix indirection problem with **endptr.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// CONSIDER: validify all this maximum length
+#define MAXLONGSIZ 16
+
+/***
+*istream& istream::operator>>(unsigned int& n) - extract unsigned int
+*
+*Purpose:
+* Extract unsigned int value from stream
+* Valid range is INT_MIN to UINT_MAX.
+*
+*Entry:
+* n = value to update
+*
+*Exit:
+* n updated, or ios::failbit and n=UINT_MAX if error
+*
+*Exceptions:
+* Stream error on entry or value out of range
+*
+*******************************************************************************/
+istream& istream::operator>>(unsigned int& n)
+{
+_WINSTATIC char ibuffer[MAXLONGSIZ];
+ unsigned long value;
+ char ** endptr = (char**)NULL;
+ if (ipfx(0)) {
+ value = strtoul(ibuffer, endptr, getint(ibuffer));
+
+ // CONSIDER: all but the first check is to emulate strtoul behavior
+ if (((value>UINT_MAX) && (value<=(ULONG_MAX-(-INT_MIN))))
+ || ((value==ULONG_MAX) && (errno==ERANGE)))
+ {
+ n = UINT_MAX;
+ state |= ios::failbit;
+ }
+ else
+ n = (unsigned int) value;
+#if 0
+ if (**endptr)
+ {
+ //UNDONE: put back any unread characters, if possible
+ }
+#endif
+ isfx();
+ }
+return *this;
+}
diff --git a/private/crt32/iostream/istrulng.cxx b/private/crt32/iostream/istrulng.cxx
new file mode 100644
index 000000000..f57d2572a
--- /dev/null
+++ b/private/crt32/iostream/istrulng.cxx
@@ -0,0 +1,65 @@
+/***
+* istrulng.cxx - definitions for istream class operator>>(unsigned long) funct
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of operator>>(unsigned long) member function(s) for istream
+* class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+* 01-06-91 KRS Added check of errno.
+* 12-30-92 KRS Fix indirection problem with **endptr.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <iostream.h>
+#pragma hdrstop
+
+
+// CONSIDER: validify this maximum length
+#define MAXLONGSIZ 16
+
+/***
+*istream& istream::operator>>(unsigned long& n) - extract unsigned long
+*
+*Purpose:
+* Extract unsigned long value from stream
+*
+*Entry:
+* n = value to update
+*
+*Exit:
+* n updated, or ios::failbit and n=ULONG_MAX if error
+*
+*Exceptions:
+* Stream error on entry or value out of range
+*
+*******************************************************************************/
+istream& istream::operator>>(unsigned long& n)
+{
+_WINSTATIC char ibuffer[MAXLONGSIZ];
+ char ** endptr = (char**)NULL;
+ if (ipfx(0)) {
+ n = strtoul(ibuffer, endptr, getint(ibuffer));
+ if ((n==ULONG_MAX) && (errno==ERANGE))
+ {
+ state |= ios::failbit;
+ }
+#if 0
+ if (**endptr)
+ {
+ //UNDONE: put back any unread characters, if possible
+ }
+#endif
+ isfx();
+ }
+return *this;
+}
diff --git a/private/crt32/iostream/istrusht.cxx b/private/crt32/iostream/istrusht.cxx
new file mode 100644
index 000000000..a464dedbb
--- /dev/null
+++ b/private/crt32/iostream/istrusht.cxx
@@ -0,0 +1,73 @@
+/***
+* istrusht.cxx - definitions for istream class operator>>(unsigned short) funct
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions of operator>>(unsigned short) member function for istream
+* class.
+* [AT&T C++]
+*
+*Revision History:
+* 09-26-91 KRS Created. Split off from istream.cxx for granularity.
+* 01-06-92 KRS Improved error handling.
+* 12-30-92 KRS Fix indirection problem with **endptr.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// CONSIDER: validify this maximum length
+#define MAXLONGSIZ 16
+
+/***
+*istream& istream::operator>>(unsigned short& n) - extract unsigned short
+*
+*Purpose:
+* Extract unsigned short value from stream
+* Valid range is SHRT_MIN to USHRT_MAX.
+*
+*Entry:
+* n = value to update
+*
+*Exit:
+* n updated, or ios::failbit and n=USHRT_MAX if error
+*
+*Exceptions:
+* Stream error on entry or value out of range
+*
+*******************************************************************************/
+istream& istream::operator>>(unsigned short& n)
+{
+_WINSTATIC char ibuffer[MAXLONGSIZ];
+ unsigned long value;
+ char ** endptr = (char**)NULL;
+ if (ipfx(0))
+ {
+ value = strtoul(ibuffer, endptr, getint(ibuffer));
+
+ // CONSIDER: all but the first check is to emulate strtoul behavior
+ if (((value>USHRT_MAX) && (value<=(ULONG_MAX-(-SHRT_MIN))))
+ || ((value==ULONG_MAX) && (errno==ERANGE)))
+ {
+ n = USHRT_MAX;
+ state |= ios::failbit;
+ }
+ else
+ n = (unsigned short) value;
+#if 0
+ if (**endptr)
+ {
+ //UNDONE: put back any unread characters, if possible
+ }
+#endif
+ isfx();
+ }
+return *this;
+}
diff --git a/private/crt32/iostream/makefile b/private/crt32/iostream/makefile
new file mode 100644
index 000000000..9e18c9a05
--- /dev/null
+++ b/private/crt32/iostream/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+BLDCRT=1
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/iostream/mtlock.c b/private/crt32/iostream/mtlock.c
new file mode 100644
index 000000000..78201917d
--- /dev/null
+++ b/private/crt32/iostream/mtlock.c
@@ -0,0 +1,943 @@
+/***
+*mtlock.c - Multi-thread locking routines
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains definitions for general-purpose multithread locking functions.
+* _mtlockinit()
+* _mtlock()
+* _mtunlock()
+*
+*Revision History:
+* 03-10-92 KRS Created from mlock.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <rterr.h>
+#include <stddef.h>
+#include <limits.h>
+
+#ifdef MTHREAD
+
+void _CALLTYPE2 _mtlockinit( PRTL_CRITICAL_SECTION pLk)
+{
+
+#ifdef _CRUISER_
+ if ( DOSCREATEMUTEXSEM(NULL, pLk, 0, 0) != 0)
+ _FATAL;
+#else /* ndef _CRUISER_ */
+#ifdef _WIN32_
+ /*
+ * Initialize the critical section.
+ */
+ InitializeCriticalSection( pLk );
+#else /* ndef _WIN32_ */
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+#endif /* _WIN32_ */
+#endif /* _CRUISER_ */
+
+}
+
+void _CALLTYPE2 _mtlock ( PRTL_CRITICAL_SECTION pLk)
+{
+#ifdef _CRUISER_
+
+ if (DOSREQUESTMUTEXSEM(pLk,-1) != 0)
+ _FATAL;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ * Enter the critical section.
+ */
+ EnterCriticalSection( pLk );
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
+
+void _CALLTYPE2 _mtunlock ( PRTL_CRITICAL_SECTION pLk)
+{
+#ifdef _CRUISER_
+ /*
+ * Release the lock
+ */
+ if (DOSRELEASEMUTEXSEM(pLk) != 0)
+ _FATAL;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ * leave the critical section.
+ */
+ LeaveCriticalSection( pLk );
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
+
+#endif /* MTHREAD */
+
+
+
+
+
+
+
+
+
+
+
+/* history: mlock.c */
+
+#if 0
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+/*
+ * Local routines
+ */
+
+static void _CALLTYPE1 _lock_create (unsigned);
+
+#ifdef DEBUG
+static struct _debug_lock * _CALLTYPE1 _lock_validate(int);
+#endif
+
+
+/*
+ * Global Data
+ */
+
+#ifdef _CRUISER_
+/*
+ * Lock Table
+ * This table contains the semaphore handle for each lock (lock number
+ * is used as an index into the table).
+ */
+
+unsigned _locktable[_TOTAL_LOCKS]; /* array of locks */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+/*
+ * Lock Table
+ * This table contains the critical section management structure of each
+ * lock.
+ */
+
+RTL_CRITICAL_SECTION _locktable[_TOTAL_LOCKS]; /* array of locks */
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+/*
+ * Lock Bit Map
+ * This table contains one bit for each lock (i.e., each entry in the
+ * _locktable[] array).
+ *
+ * If bit = 0, lock has not been created/opened
+ * If bit = 1, lock has been created/opened
+ */
+
+char _lockmap[(_TOTAL_LOCKS/CHAR_BIT)+1]; /* lock bit map */
+
+
+#ifdef _LOCKCOUNT
+/*
+ * Total number of locks held
+ */
+
+unsigned _lockcnt = 0;
+#endif
+
+
+#ifdef DEBUG
+/*
+ * Lock Debug Data Table Segment
+ * Contains debugging data for each lock.
+ */
+
+struct _debug_lock _debug_locktable[_TOTAL_LOCKS];
+
+#endif
+
+#define _FATAL _amsg_exit(_RT_LOCK)
+
+/***
+* Bit map macros
+*
+*Purpose:
+* _CLEARBIT() - Clear the specified bit
+* _SETBIT() - Set the specified bit
+* _TESTBIT() - Test the specified bit
+*
+*Entry:
+* char a[] = character array
+* unsigned b = bit number (0-based, range from 0 to whatever)
+* unsigned x = bit number (0-based, range from 0 to 31)
+*
+*Exit:
+* _CLEARBIT() = void
+* _SETBIT() = void
+* _TESTBIT() = 0 or 1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+/*
+ * Macros for use when managing a bit in a character array (e.g., _lockmap)
+ * a = character array
+ * b = bit number (0-based)
+ */
+
+#define _CLEARBIT(a,b) \
+ ( a[b>>3] &= (~(1<<(b&7))) )
+
+#define _SETBIT(a,b) \
+ ( a[b>>3] |= (1<<(b&7)) )
+
+#define _TESTBIT(a,b) \
+ ( a[b>>3] & (1<<(b&7)) )
+
+/*
+ * Macros for use when managing a bit in an unsigned int
+ * x = bit number (0-31)
+ */
+
+#define _BIT_INDEX(x) (1 << (x & 0x1F))
+
+
+/***
+*_mtinitlocks() - Initialize the semaphore lock data base
+*
+*Purpose:
+* Initialize the mthread semaphore lock data base.
+*
+* NOTES:
+* (1) Only to be called ONCE at startup
+* (2) Must be called BEFORE any mthread requests are made
+*
+* Schemes for creating the mthread locks:
+*
+* Create the locks one at a time on demand the first
+* time the lock is attempted. This is more complicated but
+* is much faster than creating them all at startup time.
+* These is currently the default scheme.
+*
+* Create and open the semaphore that protects the lock data
+* base.
+*
+*Entry:
+* <none>
+*
+*Exit:
+* returns on success
+* calls _amsg_exit on failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _mtinitlocks (
+ void
+ )
+{
+
+ /*
+ * All we need to do is create the lock table lock
+ */
+
+ _lock_create(_LOCKTAB_LOCK);
+
+ /*
+ * Make sure the assumptions we make in this source are correct.
+ * The following is a tricky way to validate sizeof() assumptions
+ * at compile time without generating any runtime code (can't
+ * use sizeof() in an #ifdef). If the assumption fails, the
+ * compiler will generate a divide by 0 error.
+ *
+ * This here only because it must be inside a subroutine.
+ */
+
+ ( (sizeof(char) == 1) ? 1 : (1/0) );
+ ( (sizeof(int) == 4) ? 1 : (1/0) );
+
+}
+
+
+/***
+*_lock_create() - Create and open a lock
+*
+*Purpose:
+* Create and open a mthread lock.
+*
+* NOTES:
+*
+* (1) The caller must have previously determined that the lock
+* needs to be created/opened (and this hasn't already been done).
+*
+* (2) The caller must have aquired the _LOCKTAB_LOCK, if needed.
+* (The only time this isn't required is at init time.)
+*
+*Entry:
+* unsigned locknum = lock to create
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CALLTYPE1 _lock_create (
+ unsigned locknum
+ )
+{
+
+#ifdef DEBUG
+ /*
+ * See if the lock already exists; if so, die.
+ */
+
+ if (_TESTBIT(_lockmap, locknum))
+ _FATAL;
+#endif
+
+ /*
+ * Convert the lock number into a lock address
+ * and create the semaphore.
+ */
+#ifdef _CRUISER_
+
+ if ( DOSCREATEMUTEXSEM(NULL, &_locktable[locknum], 0, 0) != 0)
+ _FATAL;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ * Convert the lock number into a lock address
+ * and initialize the critical section.
+ */
+ InitializeCriticalSection( &_locktable[locknum] );
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /*
+ * Set the appropriate bit in the lock bit map.
+ */
+
+ _SETBIT(_lockmap, locknum);
+
+}
+
+
+/***
+* _lock_stream, etc. - Routines to lock/unlock streams, files, etc.
+*
+*Purpose:
+* _lock_stream = Lock a stdio stream
+* _unlock_stream = Unlock a stdio stream
+* _lock_file = Lock a lowio file
+* _unlock_file = Unlock a lowio file
+*
+*Entry:
+* stream/file identifier
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE2 _lock_stream (
+ int stream_id
+ )
+{
+ _lock(stream_id+_STREAM_LOCKS);
+}
+
+void _CALLTYPE2 _unlock_stream (
+ int stream_id
+ )
+{
+ _unlock(stream_id+_STREAM_LOCKS);
+}
+
+void _CALLTYPE2 _lock_file (
+ int fh
+ )
+{
+ _lock(fh+_FH_LOCKS);
+}
+
+void _CALLTYPE2 _unlock_file (
+ int fh
+ )
+{
+ _unlock(fh+_FH_LOCKS);
+}
+
+
+/***
+* _lock - Acquire a multi-thread lock
+*
+*Purpose:
+* Note that it is legal for a thread to aquire _EXIT_LOCK1
+* multiple times.
+*
+*Entry:
+* locknum = number of the lock to aquire
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE2 _lock (
+ int locknum
+ )
+{
+
+#ifdef DEBUG
+ struct _debug_lock *deblock;
+ unsigned tidbit;
+#endif
+
+ /*
+ * Create/open the lock, if necessary
+ */
+
+ if (!_TESTBIT(_lockmap, locknum)) {
+
+ _mlock(_LOCKTAB_LOCK); /*** WARNING: Recursive lock call ***/
+
+ /* if lock still doesn't exist, create it */
+
+ if (!_TESTBIT(_lockmap, locknum))
+ _lock_create(locknum);
+
+ _munlock(_LOCKTAB_LOCK);
+
+ }
+
+#ifdef DEBUG
+ /*
+ * Validate the lock and get pointer to debug lock structure, etc.
+ */
+
+ deblock = _lock_validate(locknum);
+
+#ifdef _CRUISER_
+
+ tidbit = _BIT_INDEX(*_threadid);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ * Set tidbit to 2**(index of ptd[] entry).
+ *
+ * call non-locking form of _getptd to avoid recursing
+ */
+ tidbit = _getptd_lk() - _ptd; /* index of _ptd[] entry */
+
+ tidbit = _BIT_INDEX(tidbit);
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /*
+ * Make sure we're not trying to get lock we already have
+ * (except for _EXIT_LOCK1).
+ */
+
+ if (locknum != _EXIT_LOCK1)
+ if ((deblock->holder) & tidbit)
+ _FATAL;
+
+ /*
+ * Set waiter bit for this thread
+ */
+
+ deblock->waiters |= tidbit;
+
+#endif /* DEBUG */
+
+ /*
+ * Get the lock
+ */
+
+#ifdef _LOCKCOUNT
+ _lockcnt++;
+#endif
+
+#ifdef _CRUISER_
+
+ if (DOSREQUESTMUTEXSEM(_locktable[locknum],-1) != 0)
+ _FATAL;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ * Enter the critical section.
+ */
+ EnterCriticalSection( &_locktable[locknum] );
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#ifdef DEBUG
+ /*
+ * Clear waiter bit
+ */
+
+ deblock->waiters &= (~tidbit);
+
+ /*
+ * Make sure there are no lock holders (unless this is
+ * _EXIT_LOCK1); then set holder bit and bump lock count.
+ */
+
+ assert(THREADINTS==1);
+
+ if (locknum != _EXIT_LOCK1)
+ if ( (unsigned) deblock->holder != 0)
+ _FATAL;
+
+ deblock->holder &= tidbit;
+ deblock->lockcnt++;
+
+#endif
+
+}
+
+
+/***
+* _unlock - Release multi-thread lock
+*
+*Purpose:
+* Note that it is legal for a thread to aquire _EXIT_LOCK1
+* multiple times.
+*
+*Entry:
+* locknum = number of the lock to release
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE2 _unlock (
+ int locknum
+ )
+{
+#ifdef DEBUG
+ struct _debug_lock *deblock;
+ unsigned tidbit;
+#endif
+
+#ifdef DEBUG
+ /*
+ * Validate the lock and get pointer to debug lock structure, etc.
+ */
+
+ deblock = _lock_validate(locknum);
+
+#ifdef _CRUISER_
+
+ tidbit = _BIT_INDEX(*_threadid);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ * Set tidbit to 2**(index of ptd[] entry).
+ */
+ tidbit = _getptd_lk() - _ptd; /* index of _ptd[] entry */
+
+ tidbit = _BIT_INDEX(tidbit);
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /*
+ * Make sure we hold this lock then clear holder bit.
+ * [Note: Since it is legal to aquire _EXIT_LOCK1 several times,
+ * it's possible the holder bit is already clear.]
+ */
+
+ if (locknum != _EXIT_LOCK1)
+ if (!((deblock->holder) & tidbit))
+ _FATAL;
+
+ deblock->holder &= (~tidbit);
+
+ /*
+ * See if anyone else is waiting for this lock.
+ */
+
+ assert(THREADINTS==1);
+
+ if ((unsigned) deblock->waiters != 0)
+ deblock->collcnt++;
+
+#endif
+
+#ifdef _CRUISER_
+
+ /*
+ * Release the lock
+ */
+ if (DOSRELEASEMUTEXSEM(_locktable[locknum]) != 0)
+ _FATAL;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ * leave the critical section.
+ */
+ LeaveCriticalSection( &_locktable[locknum] );
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#ifdef _LOCKCOUNT
+ _lockcnt--;
+#endif
+
+}
+
+
+/*
+ * Debugging code
+ */
+
+#ifdef DEBUG
+
+/***
+*_lock_validate() - Validate a lock
+*
+*Purpose:
+* Debug lock validations common to both lock and unlock.
+*
+*Entry:
+* lock number
+*
+*Exit:
+* ptr to lock's debug structure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static struct _debug_lock * _CALLTYPE1 _lock_validate (
+ int locknum
+ )
+{
+ /*
+ * Make sure lock is legal
+ */
+
+ if (locknum > _TOTAL_LOCKS)
+ _FATAL;
+
+#ifdef _CRUISER_
+
+ /*
+ * Make sure threadid is in range
+ */
+
+ if (*_threadid > MAXTHREADID)
+ _FATAL;
+
+#endif /* _CRUISER_ */
+
+ /*
+ * Return pointer to this lock's debug structure
+ */
+
+ return(&_debug_locktable[locknum]);
+
+}
+
+
+/***
+*_fh_locknum() - Return the lock number for a file handle
+*
+*Purpose:
+*
+*Entry:
+* int fh = file handle
+*
+*Exit:
+* int locknum = corresponding lock number
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _fh_locknum (
+ int fh
+ )
+{
+ return(fh+_FH_LOCKS);
+}
+
+
+/***
+*_stream_locknum() - Return the lock number for a stream
+*
+*Purpose:
+*
+*Entry:
+* int stream = stream number (i.e., offset of the stream
+* in the _iob table)
+*
+*Exit:
+* int locknum = corresponding lock number
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _stream_locknum (
+ int stream
+ )
+{
+ return(stream+_STREAM_LOCKS);
+}
+
+
+#ifdef _CRUISER_
+
+/***
+*_check_lock() - Make sure a lock is in good shape
+*
+*Purpose:
+* This routine checks to make sure that a lock is in a 'good'
+* released state. That is, abort if any of the following
+* are true:
+* (1) lock is held
+* (2) holder bits are set
+* (3) waiter bits are set
+*
+* NOTE: This routine does NOT aquire the lock but simply looks
+* at the lock data bases.
+*
+*Entry:
+* locknum = number of the lock to aquire
+*
+*Exit:
+* success = 0
+* failure = !0
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _check_lock (
+ int locknum
+ )
+{
+ unsigned pid;
+ unsigned long tid;
+ unsigned cnt;
+ struct _debug_lock *deblock;
+
+ /*
+ * See if lock exists.
+ */
+
+ if (_TESTBIT(_lockmap, locknum)) {
+
+ /*
+ * Lock exists. Ask the OS about the lock and
+ * make sure lock isn't held.
+ */
+
+ if (DOSQUERYMUTEXSEM(_locktable[locknum], &pid, &tid, &cnt) != 0)
+ goto error_return;
+
+ if (cnt != 0)
+ goto error_return;
+ }
+
+ else {
+
+ /*
+ * Lock doesn't exist, handle better be 0.
+ */
+
+ if (_locktable[locknum] != 0)
+ goto error_return;
+ }
+
+
+ /*
+ * Make sure there are no lock waiters or holders.
+ */
+
+ assert(THREADINTS==1);
+
+ if ((deblock->waiters != 0) || (deblock->holder != 0))
+ goto error_return;
+
+ /*
+ * Good Return
+ */
+
+ return(0);
+
+ /*
+ * Error return
+ */
+
+error_return:
+ return(-1);
+
+}
+
+#endif /* _CRUISER_ */
+
+
+/***
+*_collide_cnt() - Return the collision count for a lock
+*
+*Purpose:
+*
+*Entry:
+* int lock = lock number
+*
+*Exit:
+* int count = collision count
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _collide_cnt (
+ int locknum
+ )
+{
+ return(_debug_locktable[locknum].collcnt);
+}
+
+
+/***
+*_lock_cnt() - Return the lock count for a lock
+*
+*Purpose:
+*
+*Entry:
+* int lock = lock number
+*
+*Exit:
+* int count = lock count
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _lock_cnt (
+ int locknum
+ )
+{
+ return(_debug_locktable[locknum].lockcnt);
+}
+
+
+/***
+*_lock_exist() - Check to see if a lock exists
+*
+*Purpose:
+* Test lock bit map to see if the lock has
+* been created or not.
+*
+*Entry:
+* int lock = lock number
+*
+*Exit:
+* int 0 = lock has NOT been created
+* 1 = lock HAS been created
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _lock_exist (
+ int locknum
+ )
+{
+ if (_TESTBIT(_lockmap, locknum))
+ return(1);
+ else
+ return(0);
+}
+
+#endif
+#endif
diff --git a/private/crt32/iostream/ofstream.cxx b/private/crt32/iostream/ofstream.cxx
new file mode 100644
index 000000000..cf915082b
--- /dev/null
+++ b/private/crt32/iostream/ofstream.cxx
@@ -0,0 +1,239 @@
+/***
+*ofstream.cxx -
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member functions for the ofstream class.
+*
+*Revision History:
+* 09-21-91 KRS Created. Split up fstream.cxx for granularity.
+* 10-22-91 KRS C700 #4883: fix error status for ofstream::open().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys\types.h>
+#include <io.h>
+#include <fstream.h>
+#pragma hdrstop
+
+#include <sys\stat.h>
+
+/***
+*ofstream::ofstream() - ofstream default constructor
+*
+*Purpose:
+* Default constructor for ofstream objects.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ ofstream::ofstream()
+: ostream(new filebuf)
+{
+ delbuf(1);
+ // CONSIDER: do anything else?
+}
+
+/***
+*ofstream::ofstream(const char * name, int mode, int prot) - ofstream ctor
+*
+*Purpose:
+* Constructor for ofstream objects. Creates an associated filebuf object,
+* opens a named file and attaches it to the new filebuf.
+*
+*Entry:
+* name = filename to open.
+* mode = see filebuf::open mode argument. ios::out is implied.
+* prot = see filebuf::open share argument
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if open fails.
+*
+*******************************************************************************/
+ ofstream::ofstream(const char * name, int mode, int prot)
+: ostream(new filebuf)
+{
+ delbuf(1);
+ if (!(rdbuf()->open(name, (mode|ios::out), prot)))
+ state |= ios::failbit;
+}
+
+/***
+*ofstream::ofstream(filedesc fd) - ofstream constructor
+*
+*Purpose:
+* Constructor for ofstream objects. Creates an associated filebuf object
+* and attaches it to the given file descriptor.
+*
+*Entry:
+* fd = file descriptor of file previously opened using _open or _sopen.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ ofstream::ofstream(filedesc _fd)
+: ostream(new filebuf(_fd))
+{
+ delbuf(1);
+}
+
+/***
+*ofstream::ofstream(filedesc fd, char * sbuf, int len) - ofstream constructor
+*
+*Purpose:
+* Constructor for ofstream objects. Creates an associated filebuf object
+* and attaches it to the given file descriptor. Filebuf object uses
+* user-supplied buffer or is unbuffered if sbuf or len = 0.
+*
+*Entry:
+* fd = file descriptor of file previously opened using _open or _sopen.
+* sbuf = pointer to character buffer or NULL if request for unbuffered.
+* len = lenght of character buffer sbuf or 0 if request for unbuffered.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ ofstream::ofstream(filedesc _fd, char * sbuf, int len)
+: ostream(new filebuf(_fd, sbuf, len))
+{
+ delbuf(1);
+}
+
+/***
+*ofstream::~ofstream() - ofstream destructor
+*
+*Purpose:
+* ofstream destructor.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+ ofstream::~ofstream()
+{
+ // CONSIDER: do anything else?
+}
+
+/***
+*streambuf* ofstream::setbuf(char * ptr, int len) - setbuf function
+*
+*Purpose:
+* ofstream setbuf function
+*
+*Entry:
+* ptr = pointer to buffer or NULL for unbuffered.
+* len = length of buffer or zero for unbuffered.
+*
+*Exit:
+* Returns rdbuf() or NULL if error.
+*
+*Exceptions:
+* If ofstream is already open or if rdbuf()->setbuf fails, sets failbit
+* and returns NULL.
+*
+*******************************************************************************/
+streambuf * ofstream::setbuf(char * ptr, int len)
+{
+ if ((is_open()) || (!(rdbuf()->setbuf(ptr, len))))
+ {
+ clear(state | ios::failbit);
+ return NULL;
+ }
+ // UNDONE: turn off input buffer??
+ return rdbuf();
+}
+
+/***
+*void ofstream::attach(filedesc _fd) - attach member function
+*
+*Purpose:
+* ofstream attach member function. Just calls rdbuf()->attach().
+*
+*Entry:
+* _fd = file descriptor of previously opened file.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if rdbuf()->attach fails.
+*
+*******************************************************************************/
+void ofstream::attach(filedesc _fd) // CONSIDER: inline?
+{
+ if (!(rdbuf()->attach(_fd)))
+ clear(state | ios::failbit);
+}
+
+/***
+*void ofstream::open(const char * name, int mode, int prot) - ofstream open()
+*
+*Purpose:
+* Opens a named file and attaches it to the associated filebuf.
+* Just calls rdbuf()->open().
+*
+*Entry:
+* name = filename to open.
+* mode = see filebuf::open mode argument. ios::out is implied.
+* prot = see filebuf::open share argument
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if already open or rdbuf()->open() fails.
+*
+*******************************************************************************/
+void ofstream::open(const char * name, int mode, int prot)
+{
+ if (is_open() || !(rdbuf()->open(name, (mode|ios::out), prot)))
+ clear(state | ios::failbit);
+}
+
+/***
+*void ofstream::close() - close member function
+*
+*Purpose:
+* ofstream close member function. Just calls rdbuf()->close().
+* Clears rdstate() error bits if successful.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+* Sets failbit if rdbuf()->close fails.
+*
+*******************************************************************************/
+void ofstream::close()
+{
+ clear((rdbuf()->close()) ? 0 : (state | ios::failbit));
+}
diff --git a/private/crt32/iostream/ostrchar.cxx b/private/crt32/iostream/ostrchar.cxx
new file mode 100644
index 000000000..3e8bb07a2
--- /dev/null
+++ b/private/crt32/iostream/ostrchar.cxx
@@ -0,0 +1,39 @@
+/***
+* ostrchar.cxx - definitions for ostream class operator<<(char) functions.
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definitions for ostream operator<<(char).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// note: called inline by char and signed char versions:
+ostream& ostream::operator<<(unsigned char c)
+{
+ if (opfx())
+ {
+ if (x_width)
+ {
+ _WINSTATIC char outc[2];
+ outc[0] = c;
+ outc[1] = '\0';
+ writepad("",outc);
+ }
+ else if (bp->sputc(c)==EOF)
+ {
+ if (bp->overflow(c)==EOF)
+ state |= (badbit|failbit); // fatal error?
+ }
+ osfx();
+ }
+ return *this;
+}
diff --git a/private/crt32/iostream/ostrdbl.cxx b/private/crt32/iostream/ostrdbl.cxx
new file mode 100644
index 000000000..1d8f22060
--- /dev/null
+++ b/private/crt32/iostream/ostrdbl.cxx
@@ -0,0 +1,65 @@
+/***
+* ostrdbl.cxx - definitions for ostream class operator<<(double) functions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definitions for ostream operator<<(double).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+* 10-24-91 KRS Combine float version with double.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <float.h>
+#include <iostream.h>
+#pragma hdrstop
+
+#pragma check_stack(on) // large buffer(s)
+
+ostream& ostream::operator<<(double f)
+{
+_WINSTATIC char obuffer[24];
+_WINSTATIC char fmt[8];
+_WINSTATIC char leader[4];
+ char * optr = obuffer;
+ int x = 0;
+
+ // x_floatused nonzero indicates called for float, not double
+ unsigned int curprecision = (x_floatused) ? FLT_DIG : DBL_DIG;
+ x_floatused = 0; // reset for next call
+
+ curprecision = __min((unsigned)x_precision,curprecision);
+
+ if (opfx()) {
+ if (x_flags & ios::showpos)
+ leader[x++] = '+';
+ if (x_flags & ios::showpoint)
+ leader[x++] = '#'; // show decimal and trailing zeros
+ leader[x] = '\0';
+ x = sprintf(fmt,"%%%s.%.0ug",leader,curprecision) - 1;
+ if ((x_flags & ios::floatfield)==ios::fixed)
+ fmt[x] = 'f';
+ else
+ {
+ if ((x_flags & ios::floatfield)==ios::scientific)
+ fmt[x] = 'e';
+ if (x_flags & uppercase)
+ fmt[x] = (char)toupper(fmt[x]);
+ }
+
+ sprintf(optr,fmt,f);
+ x = 0;
+ if (*optr=='+' || *optr=='-')
+ leader[x++] = *(optr++);
+ leader[x] = '\0';
+ writepad(leader,optr);
+ osfx();
+ }
+ return *this;
+}
diff --git a/private/crt32/iostream/ostream.cxx b/private/crt32/iostream/ostream.cxx
new file mode 100644
index 000000000..69eaefabe
--- /dev/null
+++ b/private/crt32/iostream/ostream.cxx
@@ -0,0 +1,229 @@
+/***
+* ostream.cxx - definitions for ostream and ostream_withassign classes
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the core member function definitions for ostream and
+* ostream_withassign classes.
+*
+*Revision History:
+* 07-01-91 KRS Created.
+* 08-19-91 KRS Corrected my interpretation of the spec. for negative
+* hex or octal integers.
+* 08-20-91 KRS Replace 'clear(x)' with 'state |= x'.
+* Skip text translation for write().
+* 08-26-91 KRS Modify to work with DLL's/MTHREAD.
+* 09-05-91 KRS Fix opfx() to flush tied ostream, not current one.
+* 09-09-91 KRS Remove sync_with_stdio() call from Iostream_init().
+* Reinstate text-translation (by default) for write().
+* 09-19-91 KRS Add opfx()/osfx() calls to put() and write().
+* Schedule destruction of predefined streams.
+* 09-23-91 KRS Split up for granularity.
+* 10-04-91 KRS Use bp->sputc, not put(), in writepad().
+* 10-24-91 KRS Added initialization of x_floatused.
+* 11-04-91 KRS Make constructors work with virtual base.
+* 11-20-91 KRS Add/fix copy constructor and assignment operators.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream.h>
+#pragma hdrstop
+
+int ostream::opfx()
+{
+ lock();
+ if (state)
+ {
+ state |= ios::failbit; // CONSIDER???
+ unlock();
+ return 0;
+ }
+ if (x_tie)
+ {
+ x_tie->flush();
+ }
+ lockbuf();
+ return(1); // return non-zero
+}
+
+void ostream::osfx()
+{
+ x_width = 0;
+ if (x_flags & unitbuf)
+ {
+ if (bp->sync()==EOF)
+ state = failbit | badbit;
+ }
+#ifndef _WINDLL
+ if (x_flags & ios::stdio)
+ {
+ if (fflush(stdout)==EOF)
+ state |= failbit;
+ if (fflush(stderr)==EOF)
+ state |= failbit;
+ }
+#endif
+ unlockbuf();
+ unlock();
+}
+
+// note: called inline by char and signed char versions:
+#if 0
+ostream& ostream::operator<<(unsigned char c)
+{
+ if (opfx())
+ {
+ if (x_width)
+ {
+ _WINSTATIC char outc[2];
+ outc[0] = c;
+ outc[1] = '\0';
+ writepad("",outc);
+ }
+ else if (bp->sputc(c)==EOF)
+ {
+ if (bp->overflow(c)==EOF)
+ state |= (badbit|failbit); // fatal error?
+ }
+ osfx();
+ }
+ return *this;
+}
+#endif
+
+// note: called inline by unsigned char * and signed char * versions:
+ostream& ostream::operator<<(const char * s)
+{
+ if (opfx()) {
+ writepad("",s);
+ osfx();
+ }
+ return *this;
+}
+
+ostream& ostream::flush()
+{
+ lock();
+ lockbuf();
+ if (bp->sync()==EOF)
+ state |= ios::failbit;
+ unlockbuf();
+ unlock();
+ return(*this);
+}
+
+ ostream::ostream()
+// : ios()
+{
+ x_floatused = 0;
+ // CONSIDER: do anything else?
+}
+
+ ostream::ostream(streambuf* _inistbf)
+// : ios()
+{
+ init(_inistbf);
+
+ x_floatused = 0;
+ // CONSIDER: do anything else?
+}
+
+ ostream::ostream(const ostream& _ostrm)
+// : ios()
+{
+ init(_ostrm.rdbuf());
+
+ x_floatused = 0;
+ // CONSIDER: do anything else?
+}
+
+ ostream::~ostream()
+// : ~ios()
+{
+ // CONSIDER: do anything else?
+}
+
+// used in ios::sync_with_stdio()
+ostream& ostream::operator=(streambuf * _sbuf)
+{
+// consider: may be some redundency here, depending on spec.
+
+ if (delbuf() && rdbuf())
+ delete rdbuf();
+ bp = 0;
+
+ this->ios::operator=(ios()); // initialize ios members
+ delbuf(0); // important!
+ init(_sbuf);
+
+// x_floatused = 0; // not necessary
+
+ return *this;
+}
+
+
+ ostream_withassign::ostream_withassign()
+: ostream()
+{
+ // CONSIDER: do anything else?
+}
+
+ ostream_withassign::ostream_withassign(streambuf* _os)
+: ostream(_os)
+{
+ // CONSIDER: do anything else?
+}
+
+ ostream_withassign::~ostream_withassign()
+// : ~ostream()
+{
+; // CONSIDER: do anything else?
+}
+
+ostream& ostream::writepad(const char * leader, const char * value)
+
+ {
+unsigned int len, leadlen;
+long padlen;
+ leadlen = strlen(leader);
+ len = strlen(value);
+ padlen = (((unsigned)x_width) > (len+leadlen)) ? ((unsigned)x_width) - (len + leadlen) : 0;
+ if (!(x_flags & (left|internal))) // default is right-adjustment
+ {
+ while (padlen-- >0)
+ {
+ if (bp->sputc((unsigned char)x_fill)==EOF)
+ state |= (ios::failbit|ios::badbit);
+ }
+ }
+ if (leadlen)
+ {
+ if ((unsigned)bp->sputn(leader,leadlen)!=leadlen)
+ state |= (failbit|badbit); // CONSIDER: right error?
+ }
+ if (x_flags & internal)
+ {
+ while (padlen-- >0)
+ {
+ if (bp->sputc((unsigned char)x_fill)==EOF)
+ state |= (ios::failbit|ios::badbit);
+ }
+ }
+ if ((unsigned)bp->sputn(value,len)!=len)
+ state |= (failbit|badbit); // CONSIDER: right error?
+ if (x_flags & left)
+ {
+ while ((padlen--)>0) // left-adjust if necessary
+ {
+ if (bp->sputc((unsigned char)x_fill)==EOF)
+ state |= (ios::failbit|ios::badbit);
+ }
+ }
+ return (*this);
+ }
diff --git a/private/crt32/iostream/ostream1.cxx b/private/crt32/iostream/ostream1.cxx
new file mode 100644
index 000000000..5f486537e
--- /dev/null
+++ b/private/crt32/iostream/ostream1.cxx
@@ -0,0 +1,70 @@
+/***
+* ostream1.cxx - definitions for ostream class non-core member functions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the non-core member function definitions for ostream class.
+*
+*Revision History:
+* 07-01-91 KRS Created. Split out from ostream.cxx for granularity.
+* 11-20-91 KRS Make operator= inline.
+* 03-30-92 KRS Add multithread locks.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#pragma hdrstop
+
+ostream& ostream::seekp(streampos _strmp)
+{
+ lockbuf();
+
+ if (bp->seekpos(_strmp, ios::out)==EOF)
+ clear(state | failbit);
+
+ unlockbuf();
+ return(*this);
+}
+
+ostream& ostream::seekp(streamoff _strmf, seek_dir _sd)
+{
+ lockbuf();
+
+ if (bp->seekoff(_strmf, _sd, ios::out)==EOF)
+ clear(state | failbit);
+
+ unlockbuf();
+ return(*this);
+}
+
+streampos ostream::tellp()
+{
+ streampos retval;
+ lockbuf();
+
+ if ((retval=bp->seekoff(streamoff(0), ios::cur, ios::out))==EOF)
+ clear(state | failbit);
+
+ unlockbuf();
+ return(retval);
+}
+
+ostream& ostream::operator<<(streambuf * instm)
+{
+ int c;
+ if (opfx())
+ {
+ while ((c=instm->sbumpc())!=EOF)
+ if (bp->sputc(c) == EOF)
+ {
+ state |= failbit; // CONSIDER: is this redundent?
+ break;
+ }
+// CONSIDER: not very efficient in many cases
+ osfx();
+ }
+ return *this;
+}
diff --git a/private/crt32/iostream/ostrint.cxx b/private/crt32/iostream/ostrint.cxx
new file mode 100644
index 000000000..09cb6490e
--- /dev/null
+++ b/private/crt32/iostream/ostrint.cxx
@@ -0,0 +1,55 @@
+/***
+* ostrint.cxx - definitions for ostream class operator<<(int) member functions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definitions for ostream operator<<(int).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdio.h>
+#include <iostream.h>
+#pragma hdrstop
+
+ostream& ostream::operator<<(int n)
+{
+_WINSTATIC char obuffer[12];
+_WINSTATIC char fmt[4] = "%d";
+_WINSTATIC char leader[4] = "\0\0";
+ if (opfx()) {
+
+ if (n)
+ {
+ if (x_flags & (hex|oct))
+ {
+ if (x_flags & hex)
+ {
+ if (x_flags & uppercase)
+ fmt[1] = 'X';
+ else
+ fmt[1] = 'x';
+ leader[1] = fmt[1]; // 0x or 0X (or \0X)
+ }
+ else
+ fmt[1] = 'o';
+ if (x_flags & showbase)
+ leader[0] = '0';
+ }
+ else if ((n>0) && (x_flags & showpos))
+ {
+ leader[0] = '+';
+ }
+ }
+ sprintf(obuffer,fmt,n);
+ writepad(leader,obuffer);
+ osfx();
+ }
+ return *this;
+
+}
diff --git a/private/crt32/iostream/ostrldbl.cxx b/private/crt32/iostream/ostrldbl.cxx
new file mode 100644
index 000000000..0bb3fbfc7
--- /dev/null
+++ b/private/crt32/iostream/ostrldbl.cxx
@@ -0,0 +1,61 @@
+/***
+* ostrldbl.cxx - definitions for ostream class operator<<(long double) functs
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definitions for ostream
+* operator<<(long double).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+* 10-24-91 KRS Minor robustness work.
+* 05-10-93 CFW Re-enable function.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <float.h>
+#include <iostream.h>
+#pragma hdrstop
+
+#pragma check_stack(on) // large buffer(s)
+
+ostream& ostream::operator<<(long double f)
+{
+_WINSTATIC char obuffer[28];
+_WINSTATIC char fmt[12];
+_WINSTATIC char leader[4];
+ char * optr = obuffer;
+ int x = 0;
+ unsigned int curprecision = __min((unsigned)x_precision,LDBL_DIG);
+ if (opfx()) {
+ if (x_flags & ios::showpos)
+ leader[x++] = '+';
+ if (x_flags & ios::showpoint)
+ leader[x++] = '#'; // show decimal and trailing zeros
+ leader[x] = '\0';
+ x = sprintf(fmt,"%%%s.%.0uLg",leader,curprecision) - 1;
+ if ((x_flags & ios::floatfield)==ios::fixed)
+ fmt[x] = 'f';
+ else
+ {
+ if ((x_flags & ios::floatfield)==ios::scientific)
+ fmt[x] = 'e';
+ if (x_flags & uppercase)
+ fmt[x] = (char)toupper(fmt[x]);
+ }
+
+ sprintf(optr,fmt,f);
+ x = 0;
+ if (*optr=='+' || *optr=='-')
+ leader[x++] = *(optr++);
+ leader[x] = '\0';
+ writepad(leader,optr);
+ osfx();
+ }
+ return *this;
+}
diff --git a/private/crt32/iostream/ostrlong.cxx b/private/crt32/iostream/ostrlong.cxx
new file mode 100644
index 000000000..959c5fb94
--- /dev/null
+++ b/private/crt32/iostream/ostrlong.cxx
@@ -0,0 +1,55 @@
+/***
+* ostrlong.cxx - definitions for ostream class operator<<(long) member functions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definitions for ostream operator<<(long).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdio.h>
+#include <iostream.h>
+#pragma hdrstop
+
+ostream& ostream::operator<<(long n)
+{
+_WINSTATIC char obuffer[12];
+_WINSTATIC char fmt[4] = "%ld";
+_WINSTATIC char leader[4] = "\0\0";
+ if (opfx()) {
+
+ if (n)
+ {
+ if (x_flags & (hex|oct))
+ {
+ if (x_flags & hex)
+ {
+ if (x_flags & uppercase)
+ fmt[2] = 'X';
+ else
+ fmt[2] = 'x';
+ leader[1] = fmt[2]; // 0x or 0X (or \0X)
+ }
+ else
+ fmt[2] = 'o';
+ if (x_flags & showbase)
+ leader[0] = '0';
+ }
+ else if ((n>0) && (x_flags & showpos))
+ {
+ leader[0] = '+';
+ }
+ }
+ sprintf(obuffer,fmt,n);
+ writepad(leader,obuffer);
+ osfx();
+ }
+ return *this;
+
+}
diff --git a/private/crt32/iostream/ostrptr.cxx b/private/crt32/iostream/ostrptr.cxx
new file mode 100644
index 000000000..adbb51607
--- /dev/null
+++ b/private/crt32/iostream/ostrptr.cxx
@@ -0,0 +1,41 @@
+/***
+* ostrptr.cxx - definitions for ostream operator<<(const void*) member function
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Member function definition for ostream operator<<(const void*).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+* 06-03-92 KRS CAV #1183: add 'const' to ptr output argument.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdio.h>
+#include <iostream.h>
+#pragma hdrstop
+
+ostream& ostream::operator<<(const void * ptr)
+{
+_WINSTATIC char obuffer[12];
+_WINSTATIC char fmt[4] = "%p";
+_WINSTATIC char leader[4] = "0x";
+ if (opfx())
+ {
+ if (ptr)
+ {
+ if (x_flags & uppercase)
+ leader[1] = 'X';
+// else // initialized above by default
+// leader[1] = 'x';
+ }
+//CONSIDER: can we use and depend on out %p conversion to do this???
+ sprintf(obuffer,fmt,ptr);
+ writepad(leader,obuffer);
+ osfx();
+ }
+ return *this;
+}
diff --git a/private/crt32/iostream/ostrput.cxx b/private/crt32/iostream/ostrput.cxx
new file mode 100644
index 000000000..d1a51a5f8
--- /dev/null
+++ b/private/crt32/iostream/ostrput.cxx
@@ -0,0 +1,42 @@
+/***
+* ostrput.cxx - definitions for ostream classes put() and write() functions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definitions for ostream put() and write().
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#pragma hdrstop
+
+// note: called inline by char and signed char versions:
+ostream& ostream::put(unsigned char c)
+{
+ if (opfx()) // CONSIDER: needed??
+ {
+ if (bp->sputc((int)c)==EOF)
+ state |= (failbit|badbit); // CONSIDER: right error?
+ osfx();
+ }
+ return(*this);
+}
+
+// note: called inline by unsigned char * and signed char * versions:
+ostream& ostream::write(const char * s, int n)
+{
+ if (opfx()) // CONSIDER: needed??
+ {
+// Note: 'n' treated as unsigned
+ if (bp->sputn(s,n)!=n)
+ state |= (failbit|badbit); // CONSIDER: right error?
+ osfx();
+ }
+ return(*this);
+}
diff --git a/private/crt32/iostream/ostrshrt.cxx b/private/crt32/iostream/ostrshrt.cxx
new file mode 100644
index 000000000..e4818c15d
--- /dev/null
+++ b/private/crt32/iostream/ostrshrt.cxx
@@ -0,0 +1,56 @@
+/***
+* ostrshrt.cxx - definitions for ostream class operator<<(short) member functions
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definitions for ostream operator<<(short).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream.h>
+#pragma hdrstop
+
+ostream& ostream::operator<<(short n)
+{
+_WINSTATIC char obuffer[8]; // CONSIDER: assumes max int is 65535
+_WINSTATIC char fmt[4] = "%hd";
+_WINSTATIC char leader[4] = "\0\0";
+ if (opfx()) {
+
+ if (n)
+ {
+ if (x_flags & (hex|oct))
+ {
+ if (x_flags & hex)
+ {
+ if (x_flags & uppercase)
+ fmt[2] = 'X';
+ else
+ fmt[2] = 'x';
+ leader[1] = fmt[2]; // 0x or 0X (or \0X)
+ }
+ else
+ fmt[2] = 'o';
+ if (x_flags & showbase)
+ leader[0] = '0';
+ }
+ else if ((n>0) && (x_flags & showpos))
+ {
+ leader[0] = '+';
+ }
+ }
+ sprintf(obuffer,fmt,n);
+ writepad(leader,obuffer);
+ osfx();
+ }
+ return *this;
+
+}
diff --git a/private/crt32/iostream/ostruint.cxx b/private/crt32/iostream/ostruint.cxx
new file mode 100644
index 000000000..f528fcc63
--- /dev/null
+++ b/private/crt32/iostream/ostruint.cxx
@@ -0,0 +1,55 @@
+/***
+* ostruint.cxx - definitions for ostream class operator<<(unsigned int) funct
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definitions for ostream
+* operator<<(unsigned int).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdio.h>
+#include <iostream.h>
+#pragma hdrstop
+
+ostream& ostream::operator<<(unsigned int n)
+{
+_WINSTATIC char obuffer[12];
+_WINSTATIC char fmt[4] = "%u";
+_WINSTATIC char leader[4] = "\0\0";
+ if (opfx()) {
+ if (n)
+ {
+ if (x_flags & (hex|oct))
+ {
+ if (x_flags & hex)
+ {
+ if (x_flags & uppercase)
+ fmt[1] = 'X';
+ else
+ fmt[1] = 'x';
+ leader[1] = fmt[1]; // 0x or 0X (or \0X)
+ }
+ else
+ fmt[1] = 'o';
+ if (x_flags & showbase)
+ leader[0] = '0';
+ }
+ else if (x_flags & showpos)
+ {
+ leader[0] = '+';
+ }
+ }
+ sprintf(obuffer,fmt,n);
+ writepad(leader,obuffer);
+ osfx();
+ }
+ return *this;
+
+}
diff --git a/private/crt32/iostream/ostrulng.cxx b/private/crt32/iostream/ostrulng.cxx
new file mode 100644
index 000000000..d09a5c9de
--- /dev/null
+++ b/private/crt32/iostream/ostrulng.cxx
@@ -0,0 +1,55 @@
+/***
+* ostrulng.cxx - definitions for ostream class operator<<(unsigned long) funct
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definition for ostream
+* operator<<(unsigned long).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdio.h>
+#include <iostream.h>
+#pragma hdrstop
+
+ostream& ostream::operator<<(unsigned long n)
+{
+_WINSTATIC char obuffer[12];
+_WINSTATIC char fmt[4] = "%lu";
+_WINSTATIC char leader[4] = "\0\0";
+ if (opfx()) {
+ if (n)
+ {
+ if (x_flags & (hex|oct))
+ {
+ if (x_flags & hex)
+ {
+ if (x_flags & uppercase)
+ fmt[2] = 'X';
+ else
+ fmt[2] = 'x';
+ leader[1] = fmt[2]; // 0x or 0X (or \0X)
+ }
+ else
+ fmt[2] = 'o';
+ if (x_flags & showbase)
+ leader[0] = '0';
+ }
+ else if (x_flags & showpos)
+ {
+ leader[0] = '+';
+ }
+ }
+ sprintf(obuffer,fmt,n);
+ writepad(leader,obuffer);
+ osfx();
+ }
+ return *this;
+
+}
diff --git a/private/crt32/iostream/ostrusht.cxx b/private/crt32/iostream/ostrusht.cxx
new file mode 100644
index 000000000..796ff3caf
--- /dev/null
+++ b/private/crt32/iostream/ostrusht.cxx
@@ -0,0 +1,56 @@
+/***
+* ostrusht.cxx - definition for ostream class operator<<(unsigned short) funct
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the member function definition for ostream
+* operator<<(unsigned short).
+*
+*Revision History:
+* 09-23-91 KRS Created. Split out from ostream.cxx for granularity.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream.h>
+#pragma hdrstop
+
+ostream& ostream::operator<<(unsigned short n)
+{
+_WINSTATIC char obuffer[8];
+_WINSTATIC char fmt[4] = "%hu";
+_WINSTATIC char leader[4] = "\0\0";
+ if (opfx()) {
+ if (n)
+ {
+ if (x_flags & (hex|oct))
+ {
+ if (x_flags & hex)
+ {
+ if (x_flags & uppercase)
+ fmt[2] = 'X';
+ else
+ fmt[2] = 'x';
+ leader[1] = fmt[2]; // 0x or 0X (or \0X)
+ }
+ else
+ fmt[2] = 'o';
+ if (x_flags & showbase)
+ leader[0] = '0';
+ }
+ else if (x_flags & showpos)
+ {
+ leader[0] = '+';
+ }
+ }
+ sprintf(obuffer,fmt,n);
+ writepad(leader,obuffer);
+ osfx();
+ }
+ return *this;
+
+}
diff --git a/private/crt32/iostream/sources b/private/crt32/iostream/sources
new file mode 100644
index 000000000..7c58ffce1
--- /dev/null
+++ b/private/crt32/iostream/sources
@@ -0,0 +1,83 @@
+!IF 0
+
+Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+ Set MAKEFILE. for BLDCRT=1 definition that forces use of MS C8 C++ compiler
+ for all platforms to compile these files.
+
+Author:
+
+ karlsi 15-Jun-1992, Created.
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=iostream
+
+TARGETNAME=iostream
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+_AXPACC_=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=iostream.cxx \
+ iostrini.cxx \
+ cerrinit.cxx \
+ cininit.cxx \
+ cloginit.cxx \
+ filebuf.cxx \
+ filebuf1.cxx \
+ fstream.cxx \
+ ifstream.cxx \
+ ios.cxx \
+ istrchar.cxx \
+ istrdbl.cxx \
+ istream.cxx \
+ istream1.cxx \
+ istrflt.cxx \
+ istrgdbl.cxx \
+ istrget.cxx \
+ istrgetl.cxx \
+ istrgint.cxx \
+ istrint.cxx \
+ istrldbl.cxx \
+ istrlong.cxx \
+ istrshrt.cxx \
+ istruint.cxx \
+ istrulng.cxx \
+ istrusht.cxx \
+ mtlock.c \
+ ofstream.cxx \
+ ostrchar.cxx \
+ ostrdbl.cxx \
+ ostream.cxx \
+ ostream1.cxx \
+ ostrint.cxx \
+ ostrldbl.cxx \
+ ostrlong.cxx \
+ ostrptr.cxx \
+ ostrput.cxx \
+ ostrshrt.cxx \
+ ostruint.cxx \
+ ostrulng.cxx \
+ ostrusht.cxx \
+ stdiostr.cxx \
+ streamb.cxx \
+ streamb1.cxx \
+ strmbdbp.cxx \
+ strstrea.cxx
diff --git a/private/crt32/iostream/stdiostr.cxx b/private/crt32/iostream/stdiostr.cxx
new file mode 100644
index 000000000..58c385a78
--- /dev/null
+++ b/private/crt32/iostream/stdiostr.cxx
@@ -0,0 +1,266 @@
+/***
+*stdiostr.cxx -
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+*
+* 07-10-91 KRS Created.
+* 08-26-91 KRS Switch out cout/cerr. etc. for Windows non-QuickWin.
+* 09-09-91 KRS Modify sync_with_stdio() for filebuf defaults.
+* 09-12-91 KRS Add stdiostream class.
+* 09-19-91 KRS Use delbuf(1) in stdiostream constructor.
+* 09-20-91 KRS C700 #4453: Improve efficiency in overflow().
+* 10-21-91 KRS Eliminate last use of default iostream constructor.
+* 10-24-91 KRS Avoid virtual calls from virtual functions.
+* 11-13-91 KRS Split out streambuf::dbp() into separate file.
+* Improve default buffer handling in underflow/overflow.
+* Fix bug in sync().
+* 01-20-92 KRS C700 #5803: account for CR/LF pairs in ssync().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <string.h>
+#include <stdiostr.h>
+#pragma hdrstop
+
+extern "C" {
+#include <file2.h>
+#include <msdos.h>
+}
+#include <dos.h>
+
+ stdiobuf::stdiobuf(FILE * f)
+: streambuf()
+{
+ unbuffered(1); // initially unbuffered
+ _str = f;
+}
+
+ stdiobuf::~stdiobuf()
+// : ~streambuf()
+{
+ stdiobuf::sync(); // make sure buffer flushed
+// _str = 0;
+}
+
+ int stdiobuf::setrwbuf(int readsize, int writesize)
+{
+ char * tbuf;
+ unbuffered(!(readsize+writesize));
+ if (unbuffered())
+ return(0);
+
+ tbuf = new char[(readsize+writesize)];
+ if (!tbuf)
+ return(EOF);
+
+ setb( tbuf, tbuf + (readsize+writesize), 1);
+
+ if (readsize)
+ {
+ setg(base(),base()+readsize,base()+readsize);
+ }
+ else
+ {
+ setg(0,0,0);
+ }
+
+ if (writesize)
+ {
+ setp(base()+readsize,ebuf());
+ }
+ else
+ {
+ setp(0,0);
+ }
+
+ return(1);
+}
+
+int stdiobuf::overflow(int c) {
+ long count, nout;
+ if (allocate()==EOF) // make sure there is a reserve area
+ return EOF;
+ if (!unbuffered() && epptr())
+ {
+ if ((count = pptr() - pbase()) > 0)
+ {
+ nout=fwrite((void *) pbase(), 1, (int)count, _str);
+ pbump(-(int)nout);
+ if (nout != count)
+ {
+ memmove(pbase(),pbase()+nout,(int)(count-nout));
+ return(EOF);
+ }
+ }
+ }
+ if ((!unbuffered()) && (!epptr()))
+ setp(base()+(blen()>>1),ebuf()); // hack: default to 2nd half
+ if (c!=EOF)
+ {
+ if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
+ sputc(c);
+ else
+ return fputc(c, _str);
+ }
+ return(1); // return something other than EOF if successful
+}
+
+int stdiobuf::underflow()
+{
+ int count;
+ if (allocate()==EOF) // make sure there is a reserve area
+ return EOF;
+ if ((!unbuffered()) && (!egptr()))
+ setg(base(),(base()+(blen()>>1)),(base()+(blen()>>1))); // hack: default
+
+ if (unbuffered() || (!egptr()))
+ return fgetc(_str);
+ if (gptr() >= egptr())
+// buffer empty, try for more
+ {
+ if (!(count = fread((void *)eback(), 1, (size_t)(egptr()-eback()), _str)))
+ return(EOF); // reach EOF, nothing read
+ setg(eback(),(egptr()-count),egptr()); // _gptr = _egptr - count
+ if (gptr()!=eback())
+ {
+ // CONSIDER: expensive, is there a better sol'n?
+ memmove(gptr(), eback(), count); // overlapping memory!
+ }
+ }
+ return sbumpc(); // CONSIDER: possible recursion
+}
+
+streampos stdiobuf::seekoff(streamoff off, ios::seek_dir dir, int)
+{
+
+ int fdir;
+ long retpos;
+ switch (dir) {
+ case ios::beg :
+ fdir = SEEK_SET;
+ break;
+ case ios::cur :
+ fdir = SEEK_CUR;
+ break;
+ case ios::end :
+ fdir = SEEK_END;
+ break;
+ default:
+ // error
+ return(EOF);
+ }
+
+// CONSIDER: is this needed?
+ stdiobuf::overflow(EOF);
+ if (fseek(_str, off, fdir))
+ return (EOF);
+ if ((retpos=ftell(_str))==-1L)
+ return(EOF);
+ return((streampos)retpos);
+}
+
+int stdiobuf::pbackfail(int c)
+{
+ if (eback()<gptr()) return sputbackc((char)c); // CONSIDER: should never happen
+
+ if (stdiobuf::seekoff( -1, ios::cur, ios::in)==EOF)
+ return EOF;
+ if (!unbuffered() && egptr())
+ {
+ memmove((gptr()+1),gptr(),(egptr()-(gptr()+1)));
+ *gptr()=(char)c;
+ }
+ return(c);
+}
+
+int stdiobuf::sync()
+{
+ long count;
+ char * p;
+ char flags;
+ if (!unbuffered())
+ {
+ if (stdiobuf::overflow(EOF)==EOF)
+ return(EOF);
+ if ((count=in_avail())>0)
+ {
+ flags = _osfile[_fileno(_str)];
+ if (flags & FTEXT)
+ {
+ // If text mode, need to account for CR/LF etc.
+ for (p = gptr(); p < egptr(); p++)
+ if (*p == '\n')
+ count++;
+
+ // account for EOF if read, not counted by _read
+ // UNDONE: is this necessary?
+ if (_str->_flag & _IOCTRLZ)
+ count++;
+#if 0
+ // UNDONE: is this correct?
+ if ((gptr()==eback()) && (flags & FCRLF))
+ count--;
+#endif
+ }
+ if (stdiobuf::seekoff( -count, ios::cur, ios::in)==EOF)
+ return(EOF);
+
+ setg(eback(),egptr(),egptr()); // empty get area (_gptr = _egptr;)
+ }
+ }
+ return(0);
+}
+
+ stdiostream::stdiostream(FILE * file)
+: iostream(new stdiobuf(file))
+{
+istream::delbuf(1);
+ostream::delbuf(1);
+// CONSIDER: do anything else?
+}
+
+ stdiostream::~stdiostream()
+{
+// CONSIDER: do anything else?
+}
+
+// include here for better granularity
+
+int ios::sunk_with_stdio = 0;
+
+void ios::sync_with_stdio()
+{
+#if ((!defined(_WINDOWS)) || defined(_QWIN))
+ if (!sunk_with_stdio) // first time only
+ {
+// printf("In sync_with_stdio\n");
+
+ cin = new stdiobuf(stdin);
+ cin.delbuf(1);
+ cin.setf(ios::stdio);
+
+ cout = new stdiobuf(stdout);
+ cout.delbuf(1);
+ cout.setf(ios::stdio|ios::unitbuf);
+ ((stdiobuf*)(cout.rdbuf()))->setrwbuf(0,80); // UNDONE: size??
+
+ cerr = new stdiobuf(stderr);
+ cerr.delbuf(1);
+ cerr.setf(ios::stdio|ios::unitbuf);
+ ((stdiobuf*)(cerr.rdbuf()))->setrwbuf(0,80); // UNDONE: size??
+
+ clog = new stdiobuf(stderr);
+ clog.delbuf(1);
+ clog.setf(ios::stdio);
+ ((stdiobuf*)(clog.rdbuf()))->setrwbuf(0,BUFSIZ);
+
+ sunk_with_stdio++;
+ }
+#endif
+}
diff --git a/private/crt32/iostream/streamb.cxx b/private/crt32/iostream/streamb.cxx
new file mode 100644
index 000000000..bcfb9a1eb
--- /dev/null
+++ b/private/crt32/iostream/streamb.cxx
@@ -0,0 +1,514 @@
+/***
+*streamb.cxx - fuctions for streambuf class.
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Functions for streambuf class.
+*
+*Revision History:
+* 09-10-90 WAJ Initial version.
+* 07-02-91 KRS Initial version completed.
+* 08-20-91 KRS Treat chars as unsigned; fix sgetn() function.
+* 09-06-91 KRS Do a sync() in ~streambuf before destroying buffer.
+* 11-18-91 KRS Split off stream1.cxx for input-specific code.
+* 12-09-91 KRS Fix up xsputn/xsgetn usage.
+* 03-03-92 KRS Added mthread lock init calls to constructors.
+* 06-02-92 KRS CAV #1745: Don't confuse 0xFF with EOF in xsputn()
+* call to overflow().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <iostream.h>
+#pragma hdrstop
+
+
+#ifndef BUFSIZ
+#define BUFSIZ 512
+#endif
+
+/***
+*streambuf::streambuf() -
+*
+*Purpose:
+* Default constructor.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+streambuf::streambuf()
+{
+ _fAlloc = 0;
+ _fUnbuf = 0;
+ x_lastc = EOF;
+ _base = NULL;
+ _ebuf = NULL;
+ _pbase = NULL;
+ _pptr = NULL;
+ _epptr = NULL;
+ _eback = NULL;
+ _gptr = NULL;
+ _egptr = NULL;
+
+#ifdef MTHREAD
+ LockFlg = 1; // default is no locking
+ _mtlockinit(lockptr());
+#endif /* MTHREAD */
+
+}
+
+/***
+*streambuf::streambuf(char* pBuf, int cbBuf) -
+*
+*Purpose:
+* Constructor which specifies a buffer area.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+streambuf::streambuf( char* pBuf, int cbBuf )
+{
+ _fAlloc = 0;
+ _fUnbuf = 0;
+ x_lastc = EOF;
+ _base = pBuf;
+ _ebuf = pBuf + (unsigned)cbBuf;
+ _pbase = NULL;
+ _pptr = NULL;
+ _epptr = NULL;
+ _eback = NULL;
+ _gptr = NULL;
+ _egptr = NULL;
+
+ if( pBuf == NULL || cbBuf == 0 ){
+ _fUnbuf = 1;
+ _base = NULL;
+ _ebuf = NULL;
+ }
+
+#ifdef MTHREAD
+ LockFlg = 1; // default is no locking
+ _mtlockinit(lockptr());
+#endif /* MTHREAD */
+
+}
+
+
+/***
+*virtual streambuf::~streambuf() -
+*
+*Purpose:
+* Destructor.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+streambuf::~streambuf()
+{
+ lock(); // make sure no one else still using it
+// x_lastc = EOF;
+ sync(); // make sure buffer empty before possibly destroying it
+ if( (_fAlloc) && (_base) )
+ delete _base;
+}
+
+
+/***
+* virtual streambuf * streambuf::setbuf(char * p, int len) -
+*
+*Purpose:
+* Offers the array at p with len bytes to be used as a reserve area.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+streambuf * streambuf::setbuf(char * p, int len)
+{
+ if (!_base)
+ {
+ if ((!p) || (!len))
+ _fUnbuf = 1; // mark as unbuffered
+ else
+ {
+ _base = p;
+ _ebuf = p + (unsigned)len;
+ _fUnbuf = 0;
+ }
+ return (this);
+ }
+ return((streambuf *)NULL);
+}
+
+
+/***
+*virtual int streambuf::xsputn( char* pBuf, int cbBuf ) -
+*
+*Purpose:
+* Tries to output cbBuf characters. Returns number of characters
+* that were outputted.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::xsputn( const char* pBuf, int cbBuf )
+{
+ int cbOut;
+#if 0
+ if (!this)
+ printf("xsputn: this = NULL\n");
+#endif
+ for (cbOut = 0; cbBuf--; cbOut++)
+ {
+ if ((_fUnbuf) || (_pptr >= _epptr))
+ {
+// UNDONE: can be optimized like sgetn !!
+ if (overflow((unsigned char)*pBuf)==EOF) // 0-extend 0xFF !=EOF
+ break;
+ }
+ else
+ {
+ *(_pptr++) = *pBuf;
+ }
+ pBuf++;
+ }
+ return cbOut;
+}
+
+/***
+*virtual int streambuf::xsgetn( char* pBuf, int cbBuf ) -
+*
+*Purpose:
+* Tries to input cbBuf characters. Returns number of characters
+* that were read from streambuf.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+// #pragma intrinsic(memcpy,__min)
+
+int streambuf::xsgetn( char * pBuf, int cbBuf)
+{
+ int count;
+ int cbIn = 0;
+ if (_fUnbuf)
+ {
+ if (x_lastc==EOF)
+ x_lastc=underflow();
+
+ while (cbBuf--)
+ {
+ if (x_lastc==EOF)
+ break;
+ *(pBuf++) = (char)x_lastc;
+ cbIn++;
+ x_lastc=underflow();
+ }
+ }
+ else
+ {
+ while (cbBuf)
+ {
+ if (underflow()==EOF) // make sure something to read
+ break;
+ count = __min(egptr() - gptr(),cbBuf);
+ if (count>0)
+ {
+ memcpy(pBuf,gptr(),count);
+ pBuf += count;
+ _gptr += count;
+ cbIn += count;
+ cbBuf -= count;
+ }
+ }
+ }
+ return cbIn;
+}
+// #pragma function(memcpy, __min)
+
+/***
+*virtual int streambuf::sync() -
+*
+*Purpose:
+* Tries to flush all data in put area and give back any data in the
+* get area (if possible), leaving both areas empty on exit.
+* Default behavior is to fail unless buffers empty.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::sync()
+{
+ if ((gptr() <_egptr) || (_pptr > _pbase))
+ {
+ return EOF;
+ }
+ return 0;
+}
+
+#if 0
+/***
+*int streambuf::sputn( char* pBuf, int cbBuf ) -
+*
+*Purpose:
+* Tries to output cbBuf characters. Returns number of characters
+* that were output.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::sputn( const char* pBuf, int cbBuf )
+{
+// UNDONE:
+ return xsputn(pBuf, cbBuf);
+}
+
+/***
+*int streambuf::sgetn( char* pBuf, int cbBuf ) -
+*
+*Purpose:
+* Tries to input cbBuf characters. Returns number of characters
+* that were read from streambuf.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::sgetn( char * pBuf, int cbBuf)
+{
+// UNDONE:
+ return xsgetn(pBuf, cbBuf);
+}
+#endif
+
+/***
+*int streambuf::allocate() -
+*
+*Purpose:
+* Tries to set up a Reserve Area. If one already exists, or if
+* unbuffered, just returns 0.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::allocate()
+{
+ if ((_fUnbuf) || (_base))
+ return 0;
+ if (doallocate()==EOF) return EOF;
+
+ return(1);
+}
+
+/***
+*virtual int streambuf::doallocate() -
+*
+*Purpose:
+* Tries to set up a Reserve Area. Returns EOF if unsuccessful.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::doallocate()
+{
+ char * tptr;
+ if (!( tptr = new char[BUFSIZ]))
+ return(EOF);
+ setb(tptr, tptr + BUFSIZ, 1);
+ return(1);
+}
+
+/***
+*void streambuf::unbuffered(int fUnbuf) -
+*
+*Purpose:
+* Sets unbuffered status.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+// void streambuf::unbuffered(int fUnbuf)
+// {
+// _fUnbuf = fUnbuf;
+// if ((_fUnbuf) && (_base)) delete _base; // UNDONE: not doc'd as such ??
+// }
+
+/***
+*void streambuf::setb(char * b, char * eb, int a = 0) -
+*
+*Purpose:
+* Sets up reserve area.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void streambuf::setb(char * b, char * eb, int a )
+{
+ if ((_fAlloc) && (_base)) delete _base;
+ _base = b;
+ _fAlloc = a;
+ _ebuf = eb;
+}
+
+#if 0
+int streambuf::overflow(int d)
+{
+ printf("Error: *%p streambuf::overflow(%d) called!\n",this,d);
+ return EOF;
+}
+
+int streambuf::underflow()
+{
+ printf("Error: *%p streambuf::underflow() called!\n",this);
+ return EOF;
+}
+#endif
+
+/***
+*virtual streampos streambuf::seekoff(streamoff off, ios::seekdir dir, int mode)
+*
+*Purpose:
+* seekoff member function. seek forward or backward in the stream.
+* Default behavior: returns EOF.
+*
+*Entry:
+* off = offset (+ or -) to seek by
+* dir = one of ios::beg, ios::end, or ios::cur.
+* mode = ios::in or ios::out.
+*
+*Exit:
+* Returns new file position or EOF if error or seeking not supported.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+streampos streambuf::seekoff(streamoff,ios::seek_dir,int)
+{
+return EOF;
+}
+
+/***
+*virtual streampos streambuf::seekpos(streampos pos, int mode) -
+*
+*Purpose:
+* seekoff member function. seek to absolute file position.
+* Default behavior: returns seekoff(streamoff(pos), ios::beg, mode).
+*
+*Entry:
+* pos = absolute offset to seek to
+* mode = ios::in or ios::out.
+*
+*Exit:
+* Returns new file position or EOF if error or seeking not supported.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+streampos streambuf::seekpos(streampos pos,int mode)
+{
+return seekoff(streamoff(pos), ios::beg, mode);
+}
+
+/***
+*virtual int streambuf::pbackfail(int c) - handle failure of putback
+*
+*Purpose:
+* pbackfail member function. Handle exception of pback function.
+* Default behavior: returns EOF. See spec. for details.
+*
+* Note: the following implementation gives default behavior, thanks
+* to the default seekoff, but also supports derived classes properly:
+*
+*Entry:
+* c = character to put back
+*
+*Exit:
+* Returns c if successful or EOF on error.
+*
+*Exceptions:
+* Returns EOF if error. Behavior is undefined if c was not the
+* previous character in the stream.
+*
+*******************************************************************************/
+int streambuf::pbackfail(int c)
+{
+ if (eback()<gptr()) return sputbackc((char)c); // CONSIDER: should never happen
+
+ if (seekoff( -1, ios::cur, ios::in)==EOF) // always EOF for streambufs
+ return EOF;
+ if (!unbuffered() && egptr())
+ {
+ memmove((gptr()+1),gptr(),(egptr()-(gptr()+1)));
+ *gptr()=(char)c;
+ }
+ return(c);
+}
diff --git a/private/crt32/iostream/streamb1.cxx b/private/crt32/iostream/streamb1.cxx
new file mode 100644
index 000000000..d6899ea79
--- /dev/null
+++ b/private/crt32/iostream/streamb1.cxx
@@ -0,0 +1,165 @@
+/***
+*streamb1.cxx - non-core functions for streambuf class.
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* None-core functions for streambuf class.
+*
+*Revision History:
+* 11-18-91 KRS Split off from streamb.cxx.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <iostream.h>
+#pragma hdrstop
+
+
+/***
+*int streambuf::snextc() -
+*
+*Purpose:
+* Increments get_pointer and returns the character following the new
+* get_pointer.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns the next character or EOF.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+int streambuf::snextc()
+{
+ if (_fUnbuf)
+ {
+ if (x_lastc==EOF)
+ underflow(); // skip 1st character
+ return x_lastc = underflow(); // return next character, or EOF
+ }
+ else
+ {
+ if ((!egptr()) || (gptr()>=egptr()))
+ underflow(); // make sure buffer
+
+ if ((++_gptr) < egptr())
+ return (int)(unsigned char) *gptr();
+ return underflow(); // returns next character, or EOF
+ }
+}
+
+
+/***
+*int streambuf::sbumpc() -
+*
+*Purpose:
+* Increments get_pointer and returns the character that the previous
+* get_pointer pointed to.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns current character before bumping get pointer.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+int streambuf::sbumpc()
+{
+ int c;
+ if (_fUnbuf) // no buffer
+ {
+ if (x_lastc==EOF)
+ {
+ c = underflow();
+ }
+ else
+ {
+ c = x_lastc;
+ x_lastc = EOF;
+ }
+ }
+ else
+ {
+ if( gptr() < egptr() )
+ {
+ c = (int)(unsigned char)*(gptr());
+ }
+ else
+ {
+ // UNDONE: possible recursion
+ c = underflow();
+ }
+ _gptr++;
+ }
+ return c;
+}
+
+/***
+*void streambuf::stossc() - advance get pointer
+*
+*Purpose:
+* Advances the get pointer. Does not check for EOF.
+*
+*Entry:
+* None.
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+void streambuf::stossc()
+{
+ if (_fUnbuf)
+ {
+ if (x_lastc==EOF)
+ underflow(); // throw away current character
+ else
+ x_lastc=EOF; // discard current cached character
+ }
+ else
+ {
+ if (gptr() >= egptr())
+ underflow();
+ if (gptr() < egptr())
+ _gptr++;
+ }
+}
+
+/***
+*int streambuf::sgetc() -
+*
+*Purpose:
+* Returns the character that the previous get_pointer points to.
+* DOES NOT advance the get pointer.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns current character or EOF if error.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+int streambuf::sgetc()
+{
+ if (_fUnbuf) // no buffer
+ {
+ if (x_lastc==EOF)
+ x_lastc = underflow();
+ return x_lastc;
+ }
+ else
+ return underflow();
+}
diff --git a/private/crt32/iostream/strmbdbp.cxx b/private/crt32/iostream/strmbdbp.cxx
new file mode 100644
index 000000000..2f209a67f
--- /dev/null
+++ b/private/crt32/iostream/strmbdbp.cxx
@@ -0,0 +1,48 @@
+/***
+*strmbdbp.cxx - streambuf::dbp() debug routine
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Dump debug info about streambuf to stdout.
+*
+*Revision History:
+*
+* 11-13-91 KRS Created.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <io.h>
+#include <stdio.h>
+#include <iostream.h>
+#pragma hdrstop
+
+#pragma check_stack(on) // large buffer(s)
+
+void streambuf::dbp()
+{
+#if ((!defined(_WINDOWS)) || defined(_QWIN))
+int olen;
+_WINSTATIC char obuffer[256]; // CONSIDER: size? (198 bytes?)
+ if (unbuffered())
+ olen = sprintf(obuffer,
+ "\nSTREAMBUF DEBUG INFO: this=%p, unbuffered\n",
+ (void *) this);
+ else
+ {
+ olen = sprintf(obuffer,
+ "\nSTREAMBUF DEBUG INFO: this=%p, _fAlloc=%d\n"
+ " base()=%p, ebuf()=%p, blen()=%d\n"
+ " pbase()=%p, pptr()=%p, epptr()=%p\n"
+ " eback()=%p, gptr()=%p, egptr()=%p\n",
+ (void *) this, (_fAlloc),
+ base(), ebuf(), blen(),
+ pbase(), pptr(), epptr(),
+ eback(), gptr(), egptr());
+ }
+ _write(1,obuffer,olen); // direct write to stdout
+ // CONSIDER: add more info?
+#endif
+}
diff --git a/private/crt32/iostream/strstrea.cxx b/private/crt32/iostream/strstrea.cxx
new file mode 100644
index 000000000..fba8e0126
--- /dev/null
+++ b/private/crt32/iostream/strstrea.cxx
@@ -0,0 +1,440 @@
+
+/***
+*strstream.cxx - definitions for strstreambuf, strstream
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the functions used by strstream and strstrembuf
+* classes.
+*
+*Revision History:
+* 08-14-91 KRS Initial version.
+* 08-23-91 KRS Initial version completed.
+* 09-03-91 KRS Fix typo in strstreambuf::seekoff(,ios::in,)
+* 09-04-91 KRS Added virtual sync() to fix flush(). Fix underflow().
+* 09-05-91 KRS Change str() and freeze() to match spec.
+* 09-19-91 KRS Add calls to delbuf(1) in constructors.
+* 10-24-91 KRS Avoid virtual calls from virtual functions.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strstrea.h>
+#pragma hdrstop
+
+/***
+*strstreambuf::strstreambuf() - default constructor for strstreambuf
+*
+*Purpose:
+* Default constructor for class strstreambuf.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+ strstreambuf::strstreambuf()
+: streambuf()
+{
+x_bufmin = x_dynamic = 1;
+x_static = 0;
+x_alloc = (0);
+x_free = (0);
+// CONSIDER: do anything else??
+}
+
+/***
+*strstreambuf::strstreambuf(int n) - constructor for strstreambuf
+*
+*Purpose:
+* Constructor for class strstreambuf. Created in dynamic mode.
+*
+*Entry:
+* n = minimum size for initial allocation.
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+strstreambuf::strstreambuf(int n)
+: streambuf()
+{
+x_dynamic = 1;
+x_static = 0;
+x_alloc = (0);
+x_free = (0);
+setbuf(0,n);
+// CONSIDER: do anything else??
+}
+
+/***
+*strstreambuf::strstreambuf(void* (*_a)(long), void (*_f)(void*)) - constructor for strstreambuf
+*
+*Purpose:
+* Construct a strstreambuf in dynamic mode. Use specified allocator
+* and deallocator instead of new and delete.
+*
+*Entry:
+* *_a = allocator: void * (*_a)(long)
+* *_f = deallocator: void (*_f)(void *)
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+strstreambuf::strstreambuf(void* (*_a)(long), void (*_f)(void*))
+: streambuf()
+{
+// CONSIDER: do anything else??
+x_dynamic = x_bufmin = 1;
+x_static = 0;
+x_alloc = _a;
+x_free = _f;
+}
+
+/***
+*strstreambuf::strstreambuf(char * ptr, int size, char * pstart = 0) -
+*
+*Purpose:
+* Construct a strstreambuf in static mode. Buffer used is of 'size'
+* bytes. If 'size' is 0, uses a null-terminated string as buffer.
+* If negative, size is considered infinite. Get starts at ptr.
+* If pstart!=0, put buffer starts at pstart. Otherwise, no output.
+*
+*Entry:
+* char * ptr; pointer to buffer base()
+* int size; size of buffer, or 0= use strlen to calculate size
+* or if negative size is 'infinite'.
+* char * pstart; pointer to put buffer of NULL if none.
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+strstreambuf::strstreambuf( char * ptr, int size, char * pstart)
+: streambuf()
+{
+ x_static = 1;
+ x_dynamic = 0;
+ char * pend;
+
+ if (!size)
+ pend = ptr + strlen(ptr);
+ else if (size < 0)
+ {
+ // size = 32767 - (unsigned short)ptr; // UNDONE: fix for 32-bit
+ // UNDONE: bogus segment math
+ pend = (char*)-1L;
+ }
+ else
+ pend = ptr + size;
+
+ setb(ptr, pend,0);
+// CONSIDER: is this right? Not quite what spec. says...
+ if (pstart)
+ {
+ setg(ptr,ptr,pstart);
+ setp(pstart, pend);
+ }
+ else
+ {
+ setg(ptr,ptr,pend);
+ setp(0, 0);
+ }
+}
+
+strstreambuf::~strstreambuf()
+{
+ if ((x_dynamic) && (base()))
+ {
+ if (x_free)
+ {
+ (*x_free)(base());
+ }
+ else
+ {
+ delete base();
+ }
+ }
+// x_dynamic = 0;
+// x_static = 1;
+}
+
+void strstreambuf::freeze(int n)
+{
+ if (!x_static)
+ x_dynamic = (!n);
+}
+
+char * strstreambuf::str()
+{
+// x_static = 1; // CONSIDER: disallow further dynamic changes?
+
+ x_dynamic = 0; // freeze();
+
+ return base();
+}
+
+int strstreambuf::doallocate()
+{
+ char * bptr;
+ int size;
+ size = __max(x_bufmin,blen()+1);
+ long offset = 0;
+
+ if (x_alloc)
+ {
+ bptr = (char*)(*x_alloc)(size);
+ }
+ else
+ {
+ bptr = new char[size];
+ }
+ if (!bptr)
+ return EOF;
+
+ if (blen())
+ {
+ memcpy(bptr, base(), blen());
+ offset = bptr - base(); // amount to adjust pointers by
+ }
+ if (x_free)
+ {
+ (*x_free)(base());
+ }
+ else
+ {
+ delete base();
+ }
+ setb(bptr,bptr+size,0); // we handle deallocation
+
+ // adjust get/put pointers too, if necessary
+ if (offset)
+ if (egptr())
+ {
+ setg(eback()+offset,gptr()+offset,egptr()+offset);
+ }
+ if (epptr())
+ {
+ size = pptr() - pbase();
+ setp(pbase()+offset,epptr()+offset);
+ pbump(size);
+ }
+ return(1);
+}
+
+streambuf * strstreambuf::setbuf( char *, int l)
+{
+ if (l)
+ x_bufmin = l;
+ return this;
+}
+
+int strstreambuf::overflow(int c)
+{
+/*
+- if no room and not dynamic, give error
+- if no room and dynamic, allocate (1 more or min) and store
+- if and when the buffer has room, store c if not EOF
+*/
+ int temp;
+ if (pptr() >= epptr())
+ {
+ if (!x_dynamic)
+ return EOF;
+
+ if (strstreambuf::doallocate()==EOF)
+ return EOF;
+
+ if (!epptr()) // init if first time through
+ {
+ setp(base() + (egptr() - eback()),ebuf());
+ }
+ else
+ {
+ temp = pptr()-pbase();
+ setp(pbase(),ebuf());
+ pbump(temp);
+ }
+ }
+
+ if (c!=EOF)
+ {
+ *pptr() = (char)c;
+ pbump(1); // UNDONE:
+ }
+ return(1);
+}
+
+int strstreambuf::underflow()
+{
+ char * tptr;
+ if (gptr() >= egptr())
+ {
+ // try to grow get area if we can...
+ if (egptr()<pptr())
+ {
+ tptr = base() + (gptr()-eback());
+ setg(base(),tptr,pptr());
+ }
+ if (gptr() >= egptr())
+ return EOF;
+ }
+
+ return *gptr();
+}
+
+int strstreambuf::sync()
+{
+// a strstreambuf is always in sync, by definition!
+return 0;
+}
+
+streampos strstreambuf::seekoff(streamoff off, ios::seek_dir dir, int mode)
+{
+char * tptr;
+long offset = EOF; // default return value
+ if (mode & ios::in)
+ {
+ strstreambuf::underflow(); // makes sure entire buffer available
+ switch (dir) {
+ case ios::beg :
+ tptr = eback();
+ break;
+ case ios::cur :
+ tptr = gptr();
+ break;
+ case ios::end :
+ tptr = egptr();
+ break;
+ default:
+ return EOF;
+ }
+ tptr += off;
+ offset = tptr - eback();
+ if ((tptr < eback()) || (tptr > egptr()))
+ {
+ return EOF;
+ }
+ gbump(tptr-gptr());
+ }
+ if (mode & ios::out)
+ {
+ if (!epptr())
+ {
+ if (strstreambuf::overflow(EOF)==EOF) // make sure there's a put buffer
+ return EOF;
+ }
+ switch (dir) {
+ case ios::beg :
+ tptr = pbase();
+ break;
+ case ios::cur :
+ tptr = pptr();
+ break;
+ case ios::end :
+ tptr = epptr();
+ break;
+ default:
+ return EOF;
+ }
+ tptr += off;
+ offset = tptr - pbase();
+ if (tptr < pbase())
+ return EOF;
+ if (tptr > epptr())
+ {
+ if (x_dynamic)
+ {
+ x_bufmin = __max(x_bufmin, (tptr-pbase()));
+ if (strstreambuf::doallocate()==EOF)
+ return EOF;
+ // _epptr = ebuf();
+ }
+ else
+ return EOF;
+ }
+ pbump(tptr-pptr());
+ }
+ return offset; // note: if both in and out set, returns out offset
+}
+
+
+ istrstream::istrstream(char * pszStr)
+: istream(new strstreambuf(pszStr,0))
+{
+ delbuf(1);
+ // CONSIDER: do anything else?
+}
+
+ istrstream::istrstream(char * pStr, int len)
+: istream(new strstreambuf(pStr,len))
+{
+ delbuf(1);
+ // CONSIDER: do anything else?
+// CONSIDER: do anything else?
+}
+
+ istrstream::~istrstream()
+{
+// CONSIDER: do anything else?
+}
+
+ ostrstream::ostrstream()
+: ostream(new strstreambuf)
+{
+ delbuf(1);
+ // CONSIDER: do anything else?
+// CONSIDER: do anything else?
+}
+
+ ostrstream::ostrstream(char * str, int size, int mode)
+: ostream(new strstreambuf(str,size,str))
+{
+ delbuf(1);
+ if (mode & (ios::app|ios::ate))
+ seekp(strlen(str),ios::beg);
+// CONSIDER: needed?
+// rdbuf()->setg(0,0,0); // no input allowed
+// CONSIDER: do anything else?
+}
+
+ ostrstream::~ostrstream()
+{
+// CONSIDER: do anything else?
+}
+
+ strstream::strstream()
+: iostream(new strstreambuf)
+{
+ istream::delbuf(1);
+ ostream::delbuf(1);
+ // CONSIDER: do anything else?
+}
+
+ strstream::strstream(char * str, int size, int mode)
+: iostream(new strstreambuf(str,size,str))
+{
+// UNDONE: not quite correct!
+
+ istream::delbuf(1);
+ ostream::delbuf(1);
+ if ((mode & ostream::out) && (mode & (ostream::app|ostream::ate)))
+ seekp(strlen(str),ostream::beg);
+// rdbuf()->setg(rdbuf()->base(),rdbuf()->base(),rdbuf()->ebuf()); // UNDONE: how is input handled???
+// CONSIDER: do anything else?
+}
+
+ strstream::~strstream()
+{
+// CONSIDER: do anything else?
+}
diff --git a/private/crt32/linkopts/binmode.c b/private/crt32/linkopts/binmode.c
new file mode 100644
index 000000000..81ed8787c
--- /dev/null
+++ b/private/crt32/linkopts/binmode.c
@@ -0,0 +1,28 @@
+/***
+*binmode.c - set global file mode to binary
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Sets the global file mode flag to binary. Linking with this file
+* sets all files to be opened in binary mode.
+*
+*Revision History:
+* 06-08-89 PHG Module created, based on asm version.
+* 04-04-90 GJF Added #include <cruntime.h>. Also, fixed the copyright.
+* 01-17-91 GJF ANSI naming.
+* 01-23-92 GJF Added #include <stdlib.h> (contains decl of _fmode).
+* 08-27-92 GJF Don't build for POSIX.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+/* set default file mode */
+int _fmode = _O_BINARY;
+
+#endif
diff --git a/private/crt32/linkopts/commode.c b/private/crt32/linkopts/commode.c
new file mode 100644
index 000000000..0faa595a0
--- /dev/null
+++ b/private/crt32/linkopts/commode.c
@@ -0,0 +1,26 @@
+/***
+*commode.c - set global file commit mode to commit
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Sets the global file commit mode flag to commit. Linking with
+* this file sets all files to be opened in commit mode by default.
+*
+*Revision History:
+* 07-11-90 SBM Module created, based on asm version.
+* 08-27-92 GJF Don't build for POSIX.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <file2.h>
+#include <internal.h>
+
+/* set default file commit mode to commit */
+int _commode = _IOCOMMIT;
+
+
+#endif
diff --git a/private/crt32/linkopts/makefile b/private/crt32/linkopts/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/linkopts/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/linkopts/setargv.c b/private/crt32/linkopts/setargv.c
new file mode 100644
index 000000000..ca344acbe
--- /dev/null
+++ b/private/crt32/linkopts/setargv.c
@@ -0,0 +1,43 @@
+/***
+*setargv.c - generic _setargv routine
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Linking in this module replaces the normal setargv with the
+* wildcard setargv.
+*
+*Revision History:
+* 06-28-89 PHG Module created, based on asm version.
+* 04-09-90 GJF Added #include <cruntime.h>. Made calling type
+* _CALLTYPE1. Also, fixed the copyright.
+* 10-08-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+
+/***
+*_setargv - sets argv by calling __setargv
+*
+*Purpose:
+* Routine directly transfers to __setargv (defined in stdargv.asm).
+*
+*Entry:
+* See __setargv.
+*
+*Exit:
+* See __setargv.
+*
+*Exceptions:
+* See __setargv.
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _setargv (
+ void
+ )
+{
+ __setargv();
+}
diff --git a/private/crt32/linkopts/sources b/private/crt32/linkopts/sources
new file mode 100644
index 000000000..f22a5fc0d
--- /dev/null
+++ b/private/crt32/linkopts/sources
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=lowio
+
+TARGETNAME=linkopts
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=binmode.c \
+ commode.c \
+ setargv.c
diff --git a/private/crt32/lowio/cgets.c b/private/crt32/lowio/cgets.c
new file mode 100644
index 000000000..ad2a7f1c0
--- /dev/null
+++ b/private/crt32/lowio/cgets.c
@@ -0,0 +1,129 @@
+/***
+*cgets.c - buffered keyboard input
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _cgets() - read a string directly from console
+*
+*Revision History:
+* 06-09-89 PHG Module created, based on asm version
+* 03-12-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed copyright. Also, cleaned
+* up the formatting a bit.
+* 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits
+* 07-24-90 SBM Removed '32' from API names
+* 08-13-90 SBM Compiles cleanly with -W3
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-13-90 GJF Fixed a couple of bugs.
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+* 01-25-91 SRW Get/SetConsoleMode parameters changed (_WIN32_)
+* 02-18-91 SRW Get/SetConsoleMode required read/write access (_WIN32_)
+* 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_)
+* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
+* 07-26-91 GJF Took out init. stuff and cleaned up the error
+* handling [_WIN32_].
+* 04-19-93 GJF Use ReadConsole instead of ReadFile.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <os2dll.h>
+#include <conio.h>
+#include <stdlib.h>
+
+/*
+ * mask to clear the bits required to be 0 in the handle state passed to
+ * DOSSETFHSTATE.
+ */
+#define FHSTATEMASK 0xffd07888
+
+/*
+ * declaration for console handle
+ */
+
+extern int _coninpfh;
+
+/***
+*char *_cgets(string) - read string from console
+*
+*Purpose:
+* Reads a string from the console via DOSREAD on a cooked console
+* handle. string[0] must contain the maximum length of the
+* string. Returns pointer to str[2].
+*
+* NOTE: _cgets() does NOT check the pushback character buffer (i.e.,
+* _chbuf). Thus, _cgets() will not return any character that is
+* pushed back by the _ungetch() call.
+*
+*Entry:
+* char *string - place to store read string, str[0] = max length.
+*
+*Exit:
+* returns pointer to str[2], where the string starts.
+* returns NULL if error occurs
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * __cdecl _cgets (
+ char *string
+ )
+{
+ ULONG oldstate;
+ ULONG num_read;
+ char *result;
+
+ _mlock(_CONIO_LOCK); /* lock the console */
+
+ string[1] = 0; /* no chars read yet */
+ result = &string[2];
+
+ if ( _coninpfh == -1 ) {
+ _munlock(_CONIO_LOCK); /* unlock the console */
+ return(NULL); /* return failure */
+ }
+
+ GetConsoleMode( (HANDLE)_coninpfh, &oldstate );
+ SetConsoleMode( (HANDLE)_coninpfh, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT |
+ ENABLE_ECHO_INPUT );
+
+ if ( !ReadConsole( (HANDLE)_coninpfh,
+ (LPVOID)result,
+ (unsigned char)string[0],
+ &num_read,
+ NULL )
+ )
+ result = NULL;
+
+ if ( result != NULL ) {
+
+ /* set length of string and null terminate it */
+
+ if (string[num_read] == '\r') {
+ string[1] = (char)(num_read - 2);
+ string[num_read] = '\0';
+ } else if ( (num_read == (ULONG)(unsigned char)string[0]) &&
+ (string[num_read + 1] == '\r') ) {
+ /* special case 1 - \r\n straddles the boundary */
+ string[1] = (char)(num_read -1);
+ string[1 + num_read] = '\0';
+ } else if ( (num_read == 1) && (string[2] == '\n') ) {
+ /* special case 2 - read a single '\n'*/
+ string[1] = string[2] = '\0';
+ } else {
+ string[1] = (char)num_read;
+ string[2 + num_read] = '\0';
+ }
+ }
+
+ SetConsoleMode( (HANDLE)_coninpfh, oldstate );
+
+ _munlock(_CONIO_LOCK); /* unlock the console */
+
+ return result;
+}
diff --git a/private/crt32/lowio/chsize.c b/private/crt32/lowio/chsize.c
new file mode 100644
index 000000000..d25278023
--- /dev/null
+++ b/private/crt32/lowio/chsize.c
@@ -0,0 +1,231 @@
+/***
+*chsize.c - OS/2 change size of a file
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains the _chsize() function - changes the size of a file.
+*
+*Revision History:
+* 03-13-84 RN initial version
+* 05-17-86 SKS ported to OS/2
+* 07-07-87 JCR Added (_doserrno == 5) check that is in DOS 3.2 version
+* 10-29-87 JCR Multi-thread support; also, re-wrote for efficiency
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-25-88 PHG Merged DLL and normal versions
+* 10-03-88 GJF Changed DOSNEWSIZE to SYSNEWSIZE
+* 10-10-88 GJF Made API names match DOSCALLS.H
+* 04-13-89 JCR New syscall interface
+* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
+* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and fixed
+* the copyright. Also, cleaned up the formatting a bit.
+* 04-04-90 GJF Added #include <string.h>, removed #include <dos.h>.
+* 05-21-90 GJF Fixed stack checking pragma syntax.
+* 07-24-90 SBM Replaced <assertm.h> by <assert.h>, removed '32'
+* from API names
+* 09-28-90 GJF New-style function declarator.
+* 12-03-90 GJF Appended Win32 version of the function. It is based
+* on the Cruiser version and probably could be merged
+* in later (much later).
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragma
+* 01-16-91 GJF ANSI naming. Also, fixed _chsize_lk parameter decls.
+* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
+* 04-09-91 PNT Added _MAC_ conditional
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+* 05-01-92 GJF Fixed embarrassing bug (didn't work for Win32)!
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <msdos.h>
+#include <io.h>
+#include <string.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <os2dll.h>
+
+#ifdef _CRUISER_
+#pragma check_stack(on) /* turn stack probes on */
+#endif /* ndef _CRUISER_ */
+
+/***
+*int _chsize(filedes, size) - change size of a file
+*
+*Purpose:
+* Change file size. Assume file is open for writing, or we can't do it.
+* The DOS way to do this is to go to the right spot and write 0 bytes. The
+* Xenix way to do this is to make a system call. We write '\0' bytes because
+* DOS won't do this for you if you lseek beyond eof, though Xenix will.
+*
+*Entry:
+* int filedes - file handle to change size of
+* long size - new size of file
+*
+*Exit:
+* return 0 if successful
+* returns -1 and sets errno if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+/* define normal version that locks/unlocks, validates fh */
+
+int _CALLTYPE1 _chsize (
+ REG1 int filedes,
+ long size
+ )
+{
+ int r; /* return value */
+
+#ifdef _WIN32_
+ if ( (unsigned)filedes >= (unsigned)_nhandle ) {
+#else
+ if (filedes < 0 || filedes >= _nfile) {
+#endif
+ errno = EBADF;
+ return(-1);
+ }
+ _lock_fh(filedes);
+ r = _chsize_lk(filedes,size);
+ _unlock_fh(filedes);
+
+ return r;
+}
+
+/* now define version that doesn't lock/unlock, validate fh */
+int _CALLTYPE1 _chsize_lk (
+ REG1 int filedes,
+ long size
+ )
+{
+ long filend;
+ long extend;
+ long place;
+ int cnt;
+ char blanks[BUFSIZ];
+ REG2 char *bl = blanks;
+ int oldmode;
+ int retval = 0; /* assume good return */
+
+#else
+
+/* now define normal version */
+
+int _CALLTYPE1 _chsize (
+ REG1 int filedes,
+ long size
+ )
+{
+ long filend;
+ long extend;
+ long place;
+ int cnt;
+ char blanks[BUFSIZ];
+ REG2 char *bl = blanks;
+ int oldmode;
+ int retval = 0; /* assume good return */
+
+#ifdef _WIN32_
+ if ( (unsigned)filedes >= (unsigned)_nhandle ) {
+#else
+ if (filedes < 0 || filedes >= _nfile) {
+#endif
+ errno = EBADF;
+ return(-1);
+ }
+
+#endif
+ assert(size >= 0);
+
+ /* Get current file position and seek to end */
+ if ( ((place = _lseek_lk(filedes, 0L, SEEK_CUR)) == -1L) ||
+ ((filend = _lseek_lk(filedes, 0L, SEEK_END)) == -1L) )
+ return -1;
+
+ extend = size - filend;
+
+ /* Grow or shrink the file as necessary */
+
+ if (extend > 0L) {
+
+ /* extending the file */
+
+ memset(bl, '\0', BUFSIZ);
+ oldmode = _setmode_lk(filedes, _O_BINARY);
+
+ /* pad out with nulls */
+ do {
+ cnt = (extend >= (long)BUFSIZ ) ? BUFSIZ : (int)extend;
+ if ( ( cnt = _write_lk( filedes, bl, (extend >=
+ (long)BUFSIZ ) ? BUFSIZ : (int)extend)) == -1 ) {
+ /* Error on write */
+ if (_doserrno == ERROR_ACCESS_DENIED)
+ errno = EACCES;
+ retval = cnt;
+ break; /* leave write loop */
+ }
+ }
+ while ((extend -= (long)cnt) > 0L);
+
+ _setmode_lk(filedes, oldmode);
+ /* retval set correctly */
+ }
+
+ else if (extend < 0L) {
+ /* shortening the file */
+#ifdef _CRUISER_
+
+ retval = ( DOSSETFILESIZE(filedes, size) ? -1 : 0 );
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ /*
+ * Set file pointer to new eof...and truncate it there.
+ */
+ _lseek_lk(filedes, size, SEEK_SET);
+
+ if ( (retval = SetEndOfFile((HANDLE)_get_osfhandle(filedes)) ?
+ 0 : -1) == -1 ) {
+ errno = EACCES;
+ _doserrno = GetLastError();
+ }
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+ }
+
+ /* else */
+ /* no file change needed */
+ /* retval = 0; */
+
+
+/* Common return code */
+
+ _lseek_lk(filedes, place, SEEK_SET);
+ return retval;
+}
diff --git a/private/crt32/lowio/close.c b/private/crt32/lowio/close.c
new file mode 100644
index 000000000..c96a8a4b9
--- /dev/null
+++ b/private/crt32/lowio/close.c
@@ -0,0 +1,135 @@
+/***
+*close.c - close file handle for Windows NT
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _close() - close a file handle
+*
+*Revision History:
+* 06-09-89 PHG Module created, based on asm version
+* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned up
+* the formatting a bit.
+* 04-03-90 GJF Now CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 08-14-90 SBM Compiles cleanly with -W3
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s.
+* It is enough different that there is little point in
+* trying to more closely merge the two versions.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 01-16-91 GJF ANSI naming.
+* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
+* 04-09-91 PNT Added _MAC_ conditional
+* 07-17-91 GJF Syntax error in multi-thread build [_WIN32_]
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+* 02-21-92 GJF Removed bogus _unlock_fh() call.
+* 03-22-93 GJF Check for STDOUT and STDERR being mapped to the same
+* OS file handle. Also, purged Cruiser support.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <io.h>
+#include <os2dll.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <internal.h>
+
+/***
+*int _close(fh) - close a file handle
+*
+*Purpose:
+* Closes the file associated with the file handle fh.
+*
+*Entry:
+* int fh - file handle to close
+*
+*Exit:
+* returns 0 if successful, -1 (and sets errno) if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+/* define normal version that locks/unlocks, validates fh */
+
+int _CRTAPI1 _close (
+ int fh
+ )
+{
+ int r; /* return value */
+
+ /* validate file handle */
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+ /* bad file handle, set errno and abort */
+ errno = EBADF;
+ _doserrno = 0; /* no OS/2 error */
+ return -1;
+ }
+
+ _lock_fh(fh); /* lock file */
+ r = _close_lk(fh);
+ _unlock_fh(fh); /* unlock the file */
+
+ return r;
+}
+
+/* now define version that doesn't lock/unlock, validate fh */
+int _CRTAPI1 _close_lk (
+ int fh
+ )
+{
+ DWORD dosretval;
+
+#else
+
+/* now define normal version */
+int _CRTAPI1 _close (
+ int fh
+ )
+{
+ DWORD dosretval;
+
+ /* validate file handle */
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+ /* bad file handle, set errno and abort */
+ errno = EBADF;
+ _doserrno = 0; /* no OS/2 error */
+ return -1;
+ }
+#endif
+ /*
+ * Close the underlying OS file handle. Note that if fh is STDOUT
+ * or STDERR, and if STDOUT and STDERR are mapped to the same OS
+ * file handle, the close is skipped (without error). STDOUT and
+ * STDERR are the only handles for which this support is provided.
+ * Other handles are mapped to the same OS file handle only at the
+ * programmer's risk.
+ */
+ if ( ( ((fh == 1) || (fh == 2)) &&
+ (_get_osfhandle(1) == _get_osfhandle(2)) ) ||
+ CloseHandle( (HANDLE)_get_osfhandle(fh) ) )
+ {
+
+ dosretval = 0L;
+ }
+ else
+ dosretval = GetLastError();
+
+ _free_osfhnd(fh);
+
+ if (dosretval) {
+ /* OS error */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+ _osfile[fh] = 0; /* clear file flags */
+
+ return 0; /* good return */
+}
diff --git a/private/crt32/lowio/commit.c b/private/crt32/lowio/commit.c
new file mode 100644
index 000000000..1393907f4
--- /dev/null
+++ b/private/crt32/lowio/commit.c
@@ -0,0 +1,115 @@
+/***
+*commit.c - flush buffer to disk
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains _commit() - flush buffer to disk
+*
+*Revision History:
+* 05-25-90 SBM initial version
+* 07-24-90 SBM Removed '32' from API names
+* 09-28-90 GJF New-style function declarator.
+* 12-03-90 GJF Appended Win32 version onto the source with #ifdef-s.
+* It is close enough to the Cruiser version that it
+* should be more closely merged with it later on (much
+* later on).
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
+* 04-09-91 PNT Added _MAC_ conditional
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h> /* for RESETBUFFER */
+#include <errno.h>
+#include <io.h>
+#include <internal.h>
+#include <msdos.h> /* for FOPEN */
+#include <os2dll.h>
+#include <stdlib.h> /* for _doserrno */
+
+/***
+*int _commit(filedes) - flush buffer to disk
+*
+*Purpose:
+* Flushes cache buffers for the specified file handle to disk
+*
+*Entry:
+* int filedes - file handle of file
+/*
+*Exit:
+* returns success code
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _commit (
+ REG1 int filedes
+ )
+{
+ REG2 int retval;
+
+ /* if filedes out of range, complain */
+#ifdef _WIN32_
+ if ( (unsigned)filedes >= (unsigned)_nhandle ) {
+#else
+ if (filedes < 0 || filedes >= _nfile) {
+#endif
+ errno = EBADF;
+ return (-1);
+ }
+
+ _lock_fh(filedes);
+
+ /* if filedes open, try to commit, else fall through to bad */
+ if (_osfile[filedes] & FOPEN) {
+
+#ifdef _CRUISER_
+
+ retval = DOSRESETBUFFER(filedes);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if ( !FlushFileBuffers((HANDLE)_get_osfhandle(filedes)) ) {
+ retval = GetLastError();
+ } else {
+ retval = 0; /* return success */
+ }
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+ /* map the OS return code to C errno value and return code */
+ if (retval == 0) {
+ goto good;
+ } else {
+ _doserrno = retval;
+ goto bad;
+ }
+
+ }
+
+bad :
+ errno = EBADF;
+ retval = -1;
+good :
+ _unlock_fh(filedes);
+ return (retval);
+}
diff --git a/private/crt32/lowio/cputs.c b/private/crt32/lowio/cputs.c
new file mode 100644
index 000000000..cc19b79a3
--- /dev/null
+++ b/private/crt32/lowio/cputs.c
@@ -0,0 +1,100 @@
+/***
+*cputs.c - direct console output
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _cputs() - write string directly to console
+*
+*Revision History:
+* 06-09-89 PHG Module created, based on asm version
+* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned up
+* the formatting a bit.
+* 04-10-90 GJF Now _CALLTYPE1.
+* 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits
+* 07-24-90 SBM Removed '32' from API names
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+* 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_)
+* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
+* 07-26-91 GJF Took out init. stuff and cleaned up the error
+* handling [_WIN32_].
+* 04-19-93 GJF Use WriteConsole instead of WriteFile.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <os2dll.h>
+#include <conio.h>
+#include <stdio.h>
+#include <string.h>
+
+/*
+ * declaration for console handle
+ */
+extern int _confh;
+
+/***
+*int _cputs(string) - put a string to the console
+*
+*Purpose:
+* Writes the string directly to the console. No newline
+* is appended.
+*
+*Entry:
+* char *string - string to write
+*
+*Exit:
+* Good return = 0
+* Error return = !0
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _cputs (
+ const char *string
+ )
+{
+ ULONG num_written;
+ int error = 0; /* error occurred? */
+
+ _mlock(_CONIO_LOCK); /* acquire console lock */
+
+ /* write string to console file handle */
+
+#ifdef _CRUISER_
+
+ if (DOSWRITE(_confh, (char*)string, strlen(string), &num_written)) {
+ /* OS/2 error, return error indicator */
+ error = -1;
+ }
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if ( (_confh == -1) || !WriteConsole( (HANDLE)_confh,
+ (LPVOID)string,
+ strlen(string),
+ &num_written,
+ NULL )
+ )
+ /* return error indicator */
+ error = -1;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ _munlock(_CONIO_LOCK); /* release console lock */
+
+ return error;
+}
diff --git a/private/crt32/lowio/creat.c b/private/crt32/lowio/creat.c
new file mode 100644
index 000000000..fe1437989
--- /dev/null
+++ b/private/crt32/lowio/creat.c
@@ -0,0 +1,52 @@
+/***
+*creat.c - create a new file or truncate existing file
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _creat() - create new file
+*
+*Revision History:
+* 06-08-89 PHG Module created, based on asm version
+* 03-12-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h>, fixed compiler warning and fixed the
+* copyright. Also, cleaned up the formatting a bit.
+* 09-28-90 GJF New-style function declarator.
+* 01-16-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <io.h>
+#include <fcntl.h>
+
+/***
+*int _creat(path, pmode) - create a new file
+*
+*Purpose:
+* If file specified does not exist, _creat creates a new file
+* with the given permission setting and opens it for writing.
+* If the file already exists and its permission allows writing,
+* _creat truncates it to 0 length and open it for writing.
+* The only Xenix mode bit supprted by DOS is user write (S_IWRITE).
+*
+*Entry:
+* char *path - filename to create
+* int pmode - permission mode setting for new file
+*
+*Exit:
+* returns handle for created file
+* returns -1 and sets errno if fails.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _creat (
+ const char *path,
+ int pmode
+ )
+{
+ /* creat is just the same as open... */
+ return _open(path, _O_CREAT + _O_TRUNC + _O_RDWR, pmode);
+}
diff --git a/private/crt32/lowio/dup.c b/private/crt32/lowio/dup.c
new file mode 100644
index 000000000..1eaa12597
--- /dev/null
+++ b/private/crt32/lowio/dup.c
@@ -0,0 +1,156 @@
+/***
+*dup.c - OS/2 duplicate file handles
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _dup() - duplicate file handles
+*
+*Revision History:
+* 06-09-89 PHG Module created, based on asm version
+* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned up
+* the formatting a bit.
+* 04-03-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 08-14-90 SBM Compiles cleanly with -W3
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s.
+* It is enough different that there is little point in
+* trying to more closely merge the two versions.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 01-16-91 GJF ANSI naming.
+* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
+* 02-18-91 SRW Changed to call _free_osfhnd [_WIN32_]
+* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_]
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+* 09-03-92 GJF Added explicit check for unopened handles [_WIN32_].
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <errno.h>
+#include <os2dll.h>
+#include <io.h>
+#include <msdos.h>
+#include <internal.h>
+#include <stdlib.h>
+
+/***
+*int _dup(fh) - duplicate a file handle
+*
+*Purpose:
+* Assigns another file handle to the file associated with the
+* handle fh. The next available file handle is assigned.
+*
+* Multi-thread: Be sure not to hold two file handle locks
+* at the same time!
+*
+*Entry:
+* int fh - file handle to duplicate
+*
+*Exit:
+* returns new file handle if successful
+* returns -1 (and sets errno) if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _dup (
+ int fh
+ )
+{
+ ULONG dosretval; /* OS/2 return value */
+ int newfh; /* variable for new file handle */
+ char fileinfo; /* _osfile info for file */
+
+ /* validate file handle */
+#ifdef _WIN32_
+ if ( ((unsigned)fh >= (unsigned)_nhandle) ||
+ !(_osfile[fh] & FOPEN) ) {
+#else
+ if ((unsigned)fh >= (unsigned)_nfile) {
+#endif
+ errno = EBADF;
+ _doserrno = 0; /* no OS/2 error */
+ return -1;
+ }
+
+ _lock_fh(fh); /* lock file handle */
+ fileinfo = _osfile[fh]; /* get file info for file */
+
+ /* create duplicate handle */
+
+#ifdef _CRUISER_
+
+ newfh = -1; /* ask for new handle */
+ dosretval = DOSDUPHANDLE(fh, &newfh);
+
+ /* validate range of new handle */
+ if (dosretval == 0 && (unsigned)newfh >= (unsigned)_nfile) {
+ /* file handle is not in range -- close it and return error */
+ _doserrno = DOSCLOSE(newfh);
+ errno = EMFILE;
+ _unlock_fh(fh);
+ return -1;
+ }
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ {
+ long new_osfhandle;
+
+ if ( (newfh = _alloc_osfhnd()) == -1 ) {
+ errno = EMFILE; /* too many files error */
+ _doserrno = 0L; /* not an OS error */
+ _unlock_fh(fh);
+ return -1; /* return error to caller */
+ }
+
+ /*
+ * duplicate the file handle
+ */
+
+ if ( !(DuplicateHandle(GetCurrentProcess(),
+ (HANDLE)_get_osfhandle(fh),
+ GetCurrentProcess(),
+ (PHANDLE)&new_osfhandle,
+ 0L,
+ TRUE,
+ DUPLICATE_SAME_ACCESS)) )
+ {
+ dosretval = GetLastError();
+ }
+ else {
+ _set_osfhnd(newfh, new_osfhandle);
+ dosretval = 0;
+ }
+ }
+
+ _unlock_fh(newfh);
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ _unlock_fh(fh); /* unlock file handle */
+
+ if (dosretval) {
+ /* OS/2 error -- map and return */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ /* copy _osfile info */
+ _osfile[newfh] = fileinfo;
+
+ return newfh;
+}
diff --git a/private/crt32/lowio/dup2.c b/private/crt32/lowio/dup2.c
new file mode 100644
index 000000000..dfa6724ec
--- /dev/null
+++ b/private/crt32/lowio/dup2.c
@@ -0,0 +1,200 @@
+/***
+*dup2.c - Duplicate file handles
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _dup2() - duplicate file handles
+*
+*Revision History:
+* 06-09-89 PHG Module created, based on asm version
+* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned up
+* the formatting a bit.
+* 04-03-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 08-14-90 SBM Compiles cleanly with -W3
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s.
+* It is enough different that there is little point in
+* trying to more closely merge the two versions.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 01-16-91 GJF ANSI naming.
+* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
+* 02-18-91 SRW Changed to call _free_osfhnd [_WIN32_]
+* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_]
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+* 09-04-92 GJF Check for unopened fh1 and gracefully handle fh1 ==
+* fh2.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <io.h>
+#include <oscalls.h>
+#include <msdos.h>
+#include <os2dll.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <internal.h>
+
+/***
+*int _dup2(fh1, fh2) - force handle 2 to refer to handle 1
+*
+*Purpose:
+* Forces file handle 2 to refer to the same file as file
+* handle 1. If file handle 2 referred to an open file, that file
+* is closed.
+*
+* Multi-thread: We must hold 2 lowio locks at the same time
+* to ensure multi-thread integrity. In order to prevent deadlock,
+* we always get the lower file handle lock first. Order of unlocking
+* does not matter. If you modify this routine, make sure you don't
+* cause any deadlocks! Scary stuff, kids!!
+*
+*Entry:
+* int fh1 - file handle to duplicate
+* int fh2 - file handle to assign to file handle 1
+*
+*Exit:
+* returns 0 if successful, -1 (and sets errno) if fails.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _dup2 (
+ int fh1,
+ int fh2
+ )
+{
+ ULONG dosretval; /* OS/2 return code */
+
+ /* validate file handles */
+#ifdef _WIN32_
+ if ( ((unsigned)fh1 >= (unsigned)_nhandle) ||
+ ((unsigned)fh2 >= (unsigned)_nhandle) ) {
+#else
+ if ((unsigned)fh1 >= (unsigned)_nfile ||
+ (unsigned)fh2 >= (unsigned)_nfile ) {
+#endif
+ /* handle out of range */
+ errno = EBADF;
+ _doserrno = 0; /* not an OS error */
+ return -1;
+ }
+
+#ifdef MTHREAD
+ /* get the two file handle locks; in order to prevent deadlock,
+ get the lowest handle lock first. */
+ if ( fh1 < fh2 ) {
+ _lock_fh(fh1);
+ _lock_fh(fh2);
+ }
+ else if ( fh1 > fh2 ) {
+ _lock_fh(fh2);
+ _lock_fh(fh1);
+ }
+#endif
+
+ /*
+ * Take care of case of equal handles.
+ */
+ if ( fh1 == fh2 ) {
+ /*
+ * Two handles are the same. Return success or failure
+ * depending on whether or not the handle is open. This is
+ * conformance with the POSIX specification for dup2().
+ */
+ if ( _osfile[fh1] & FOPEN )
+ return 0;
+ else
+ return -1;
+ }
+
+ /*
+ * Take care of case of unopened source handle.
+ */
+ if ( !(_osfile[fh1] & FOPEN) ) {
+ /*
+ * Source handle isn't open, release locks and bail out with
+ * an error. Note that the DuplicateHandle API will not detect
+ * this error since it implies that _osfhnd[fh1] ==
+ * INVALID_HANDLE_VALUE, and this is a legal HANDLE value (it's
+ * the HANDLE for the current process).
+ */
+ _unlock_fh(fh1);
+ _unlock_fh(fh2);
+ errno = EBADF;
+ _doserrno = 0; /* not an OS error */
+ return -1;
+ }
+
+
+ /*
+ * if fh2 is open, close it.
+ */
+ if ( _osfile[fh2] & FOPEN )
+ /*
+ * close the handle. ignore the possibility of an error - an
+ * error simply means that an OS handle value may remain bound
+ * for the duration of the process. Use _close_lk as we
+ * already own lock
+ */
+ (void) _close_lk(fh2);
+
+
+ /* Duplicate source file onto target file */
+#ifdef _CRUISER_
+
+ dosretval = DOSDUPHANDLE(fh1, &fh2);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ {
+ long new_osfhandle;
+
+ if ( !(DuplicateHandle(GetCurrentProcess(),
+ (HANDLE)_get_osfhandle(fh1),
+ GetCurrentProcess(),
+ (PHANDLE)&new_osfhandle,
+ 0L,
+ TRUE,
+ DUPLICATE_SAME_ACCESS)
+ ) ) {
+
+ dosretval = GetLastError();
+ } else {
+ _set_osfhnd(fh2, new_osfhandle);
+ dosretval = 0;
+ }
+ }
+
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ if (dosretval) {
+ _dosmaperr(dosretval);
+ _unlock_fh(fh1);
+ _unlock_fh(fh2);
+ return -1;
+ }
+
+ /* copy _osfile information */
+ _osfile[fh2] = _osfile[fh1];
+
+ /* unlock file handles */
+ _unlock_fh(fh1);
+ _unlock_fh(fh2);
+
+ return 0;
+}
diff --git a/private/crt32/lowio/eof.c b/private/crt32/lowio/eof.c
new file mode 100644
index 000000000..e4e2f7a2c
--- /dev/null
+++ b/private/crt32/lowio/eof.c
@@ -0,0 +1,90 @@
+/***
+*eof.c - test a handle for end of file
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _eof() - determine if a file is at eof
+*
+*Revision History:
+* 09-07-83 RN initial version
+* 10-28-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-25-88 PHG DLL replaces normal version
+* 07-11-88 JCR Added REG allocation to declarations
+* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and fixed
+* the copyright. Also, cleaned up the formatting a bit.
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 GJF Improved range check of file handle.
+* 01-16-91 GJF ANSI naming.
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <io.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int _eof(filedes) - test a file for eof
+*
+*Purpose:
+* see if the file length is the same as the present position. if so, return
+* 1. if not, return 0. if an error occurs, return -1
+*
+*Entry:
+* int filedes - handle of file to test
+*
+*Exit:
+* returns 1 if at eof
+* returns 0 if not at eof
+* returns -1 and sets errno if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _eof (
+ REG1 int filedes
+ )
+{
+ long here;
+ long end;
+ REG2 int retval;
+#ifdef _WIN32_
+ if ( (unsigned)filedes >= (unsigned)_nhandle ) {
+#else
+ if ( (unsigned)filedes >= (unsigned)_nfile ) {
+#endif
+ errno = EBADF;
+ _doserrno = 0;
+ return(-1);
+ }
+
+ /* Lock the file */
+ _lock_fh(filedes);
+
+ /* See if the current position equals the end of the file. */
+
+ if ( ((here = _lseek_lk(filedes, 0L, SEEK_CUR)) == -1L)
+ || ((end = _lseek_lk(filedes, 0L, SEEK_END)) == -1L) )
+ retval = -1;
+ else if ( here == end )
+ retval = 1;
+ else {
+ _lseek_lk(filedes, here, SEEK_SET);
+ retval = 0;
+ }
+
+ /* Unlock the file */
+ _unlock_fh(filedes);
+
+ /* Done */
+ return(retval);
+}
diff --git a/private/crt32/lowio/flength.c b/private/crt32/lowio/flength.c
new file mode 100644
index 000000000..9b81ced8c
--- /dev/null
+++ b/private/crt32/lowio/flength.c
@@ -0,0 +1,84 @@
+/***
+*flength.c - find length of a file
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _filelength() - find the length of a file
+*
+*Revision History:
+* 10-22-84 RN initial version
+* 10-27-87 JCR Multi-thread support; also, cleaned up code to save
+* an lseek() in some cases.
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-25-88 PHG Merged DLL and normal versions
+* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and fixed
+* the copyright. Also, cleaned up the formatting a bit.
+* 07-23-90 SBM Removed #include <assertm.h>
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 GJF Improved range check of file handle. Also, replaced
+* numeric values with symbolic constants for seek
+* methods.
+* 01-16-91 GJF ANSI naming.
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <errno.h>
+#include <io.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/***
+*long _filelength(filedes) - find length of a file
+*
+*Purpose:
+* Returns the length in bytes of the specified file.
+*
+*Entry:
+* int filedes - handle referring to file to find length of
+*
+*Exit:
+* returns length of file in bytes
+* returns -1L if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+long _CALLTYPE1 _filelength (
+ REG1 int filedes
+ )
+{
+ long length;
+ long here;
+#ifdef _WIN32_
+ if ( (unsigned)filedes >= (unsigned)_nhandle ) {
+#else
+ if ( (unsigned)filedes >= (unsigned)_nfile ) {
+#endif
+ errno = EBADF;
+ _doserrno = 0L; /* not an OS error */
+ return(-1L);
+ }
+
+ _lock_fh(filedes);
+
+ /* Seek to end to get length of file. */
+ if ( (here = _lseek_lk(filedes, 0L, SEEK_CUR)) == -1L )
+ length = -1L; /* return error */
+ else {
+ length = _lseek_lk(filedes, 0L, SEEK_END);
+ if ( here != length )
+ _lseek_lk(filedes, here, SEEK_SET);
+ }
+
+ _unlock_fh(filedes);
+
+ return(length);
+}
diff --git a/private/crt32/lowio/fstat.c b/private/crt32/lowio/fstat.c
new file mode 100644
index 000000000..dcb013203
--- /dev/null
+++ b/private/crt32/lowio/fstat.c
@@ -0,0 +1,352 @@
+/***
+*fstat.c - OS/2 return file status info
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fstat() - return file status info
+*
+*Revision History:
+* 03-??-84 RLB Module created
+* 05-??-84 DCW Added register variables
+* 05-19-86 SKS Ported to OS/2
+* 05-21-87 SKS Cleaned up declarations and include files
+* 11-01-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-25-88 PHG Merged DLL and normal version
+* 10-03-88 GJF Adapted for new DOSCALLS.H, DOSTYPES.H.
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 10-10-88 GJF Made API names match DOSCALLS.H
+* 11-07-88 GJF Cleanup, now specific to 386
+* 04-13-89 JCR New syscall interface
+* 05-23-89 PHG Added mask to ignore network bit when testing handle
+* type
+* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
+* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and fixed
+* the copyright. Also, cleaned up the formatting a bit.
+* 04-04-90 GJF Removed #include <dos.h>.
+* 07-24-90 SBM Removed '32' from API names
+* 08-13-90 SBM Compiles cleanly with -W3
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-21-91 GJF ANSI naming.
+* 04-26-91 SRW Implemented fstat for _WIN32_ and removed level 3
+* warnings.
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+* 05-27-92 SKS File Creation and File Last Access timestamps may be 0
+* on some file systems (e.g. FAT) in which case the
+* File Last Write time should be used instead.
+* 06-04-92 SKS Changed comment that used to say "This is a BUG!"
+* to explain that this value cannot be computed on
+* OS/2 or NT. Only MS-DOS provides this functionality.
+* The drive number is not valid for UNC names.
+* 06-25-92 GJF Use GetFileInformationByHandle API, also cleaned up
+* formatting of Win32 verson [_WIN32_].
+* 08-18-92 SKS Add a call to FileTimeToLocalFileTime
+* as a temporary fix until _dtoxtime takes UTC
+* 08-20-92 GJF Merged two changes above.
+* 12-16-92 GJF Win32 GetFileInformationByHandle API doesn't like
+* device or pipe handles. Use _S_IFIFO for pipes.
+* 04-06-93 GJF Made computation of file times consistent with _stat().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <msdos.h>
+#include <dostypes.h>
+#include <io.h>
+#include <internal.h>
+#include <stddef.h>
+#include <oscalls.h>
+#include <stdio.h>
+#include <os2dll.h>
+
+#ifndef _CRUISER_
+#include <time.h>
+#endif
+
+#define IO_DEVNBR 0x3f
+
+/***
+*int _fstat(fildes, buf) - fills supplied buffer with status info
+*
+*Purpose:
+* Fills the supplied buffer with status information on the
+* file represented by the specified file designator.
+* WARNING: the dev/rdev fields are zero for files. This is
+* incompatible with DOS 3 version of this routine.
+*
+*Entry:
+* int fildes - file descriptor
+* struct stat *buf - buffer to store result in
+*
+*Exit:
+* fills in buffer pointed to by buf
+* returns 0 if successful
+* returns -1 and sets errno if unsuccessful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef _CRUISER_
+
+int _CRTAPI1 _fstat (
+ REG2 int fildes,
+ REG1 struct _stat *buf
+ )
+{
+
+ long cpos;
+ int isdev; /* 0 for a file, 1 for a device */
+ int retval = 0; /* assume good return */
+ if (fildes < 0 || fildes >= _nfile) {
+ errno = EBADF;
+ return(-1);
+ }
+
+ /* Lock the file */
+
+ _lock_fh(fildes);
+
+ /* Issue the get-device-info call. */
+ {
+ int descrip; /* device descriptor word */
+
+ if (DOSQUERYHTYPE(fildes, (unsigned *)&isdev, (unsigned *)&descrip))
+ {
+ errno = EBADF;
+ retval = -1; /* error from DOS call - bad file designator */
+ goto done; /* join common return code */
+ }
+
+ /* set the common fields */
+
+ buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0;
+ buf->st_nlink = 1;
+
+ buf->st_mode |= (_osfile[fildes] & FRDONLY)
+ ? (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6))
+ : ((_S_IREAD|_S_IWRITE) +
+ ((_S_IREAD|_S_IWRITE) >> 3)
+ + ((_S_IREAD|_S_IWRITE) >> 6));
+
+ /* set file date fields - NOTE for code below, it should be
+ * remembered that calls to QFILEINFO cannot fail since the file
+ * handle is known to be good since we got by the QHANDTYPE call.
+ */
+
+ {
+ FILESTATUS fs;
+
+ (void)DOSQUERYFILEINFO(fildes, 1, (FILESTATUS *) & fs, sizeof(fs));
+
+ buf->st_mtime = XTIME(fs.fdateLastWrite, fs.ftimeLastWrite);
+
+ if ( _DATECAST(fs.fdateLastAccess) || _TIMECAST(fs.ftimeLastAccess) )
+ buf->st_atime = XTIME(fs.fdateLastAccess, fs.ftimeLastAccess);
+ else
+ buf->st_atime = buf->st_mtime ;
+
+ if ( _DATECAST(fs.fdateCreation) || _TIMECAST(fs.ftimeCreation) )
+ buf->st_ctime = XTIME(fs.fdateCreation, fs.ftimeCreation);
+ else
+ buf->st_ctime = buf->st_mtime ;
+
+ buf->st_mtime = XTIME(fs.fdateLastWrite, fs.ftimeLastWrite);
+ }
+
+ /* check for device or file */
+
+ if (isdev & 0xFF) {
+ /* file designator refers to a device - set file size to 0 */
+
+ buf->st_size = 0;
+ buf->st_mode |= _S_IFCHR;
+ buf->st_rdev = buf->st_dev = (_dev_t)fildes;
+ }
+ else {
+ /* file designator refers to a file - set actual file size */
+
+ cpos = _lseek_lk(fildes, 0L, 1);
+ buf->st_size = _lseek_lk(fildes, 0L, 2);
+ _lseek_lk(fildes, cpos, 0);
+
+ buf->st_mode |= _S_IFREG;
+
+ /*
+ * On DOS, this field contains the drive number, but
+ * the drive number is not available on this platform.
+ * Also, for UNC network names, there is no drive number.
+ */
+ buf->st_rdev = buf->st_dev = 0;
+ }
+
+/* Common return code */
+
+done:
+ _unlock_fh(fildes);
+ return(retval);
+}
+
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+
+int _CRTAPI1 _fstat (
+ int fildes,
+ struct _stat *buf
+ )
+{
+ int isdev; /* 0 for a file, 1 for a device */
+ int retval = 0; /* assume good return */
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ SYSTEMTIME SystemTime;
+
+ if ( (unsigned)fildes >= (unsigned)_nhandle ) {
+ errno = EBADF;
+ return(-1);
+ }
+
+ /* Lock the file */
+
+ _lock_fh(fildes);
+
+ /* Find out what kind of handle underlies filedes
+ */
+ isdev = GetFileType((HANDLE)_osfhnd[fildes]) & ~FILE_TYPE_REMOTE;
+
+ if ( isdev != FILE_TYPE_DISK ) {
+
+ /* not a disk file. probably a device or pipe
+ */
+ if ( (isdev == FILE_TYPE_CHAR) || (isdev == FILE_TYPE_PIPE) ) {
+ /* treat pipes and devices similarly. no further info is
+ * available from any API, so set the fields as reasonably
+ * as possible and return.
+ */
+ if ( isdev == FILE_TYPE_CHAR )
+ buf->st_mode = _S_IFCHR;
+ else
+ buf->st_mode = _S_IFIFO;
+
+ buf->st_rdev = buf->st_dev = (_dev_t)fildes;
+ buf->st_nlink = 1;
+ buf->st_uid = buf->st_gid = buf->st_ino = 0;
+ buf->st_atime = buf->st_mtime = buf->st_ctime = buf->st_size
+ = 0;
+
+ goto done;
+
+ }
+ else if ( isdev == FILE_TYPE_UNKNOWN ) {
+ errno = EBADF;
+ retval = -1;
+ goto done; /* join common return code */
+ }
+ else {
+ /* according to the documentation, this cannot happen, but
+ * play it safe anyway.
+ */
+ _dosmaperr(GetLastError());
+ retval = -1;
+ goto done;
+ }
+ }
+
+
+ /* set the common fields
+ */
+ buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0;
+ buf->st_nlink = 1;
+
+ /* use the file handle to get all the info about the file
+ */
+ if ( !GetFileInformationByHandle((HANDLE)_osfhnd[fildes], &bhfi) ) {
+ _dosmaperr(GetLastError());
+ retval = -1;
+ goto done;
+ }
+
+ if ( bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY )
+ buf->st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
+ else
+ buf->st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3)
+ + ((_S_IREAD|_S_IWRITE) >> 6));
+
+ /* set file date fields
+ */
+ FileTimeToSystemTime( &(bhfi.ftLastWriteTime), &SystemTime );
+
+ buf->st_mtime = __gmtotime_t(SystemTime.wYear,
+ SystemTime.wMonth,
+ SystemTime.wDay,
+ SystemTime.wHour,
+ SystemTime.wMinute,
+ SystemTime.wSecond
+ );
+
+ if ( bhfi.ftLastAccessTime.dwLowDateTime || bhfi.ftLastAccessTime.
+ dwHighDateTime ) {
+
+ FileTimeToSystemTime( &(bhfi.ftLastAccessTime), &SystemTime );
+
+ buf->st_atime = __gmtotime_t(SystemTime.wYear,
+ SystemTime.wMonth,
+ SystemTime.wDay,
+ SystemTime.wHour,
+ SystemTime.wMinute,
+ SystemTime.wSecond
+ );
+ }
+ else
+ buf->st_atime = buf->st_mtime;
+
+ if ( bhfi.ftCreationTime.dwLowDateTime || bhfi.ftCreationTime.
+ dwHighDateTime ) {
+
+ FileTimeToSystemTime( &(bhfi.ftCreationTime), &SystemTime );
+
+ buf->st_ctime = __gmtotime_t(SystemTime.wYear,
+ SystemTime.wMonth,
+ SystemTime.wDay,
+ SystemTime.wHour,
+ SystemTime.wMinute,
+ SystemTime.wSecond
+ );
+ }
+ else
+ buf->st_ctime = buf->st_mtime;
+
+
+ buf->st_size = bhfi.nFileSizeLow;
+
+ buf->st_mode |= _S_IFREG;
+
+ /* On DOS, this field contains the drive number, but
+ * the drive number is not available on this platform.
+ * Also, for UNC network names, there is no drive number.
+ */
+ buf->st_rdev = buf->st_dev = 0;
+
+/* Common return code */
+
+done:
+ _unlock_fh(fildes);
+ return(retval);
+}
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
diff --git a/private/crt32/lowio/getch.c b/private/crt32/lowio/getch.c
new file mode 100644
index 000000000..db7d2c585
--- /dev/null
+++ b/private/crt32/lowio/getch.c
@@ -0,0 +1,672 @@
+/***
+*getch.c - contains _getch(), _getche(), _ungetch() and kbhit for Windows NT
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the "direct console" functions listed above.
+*
+* NOTE: The real-mode DOS versions of these functions read from
+* standard input and are therefore redirected when standard input
+* is redirected. However, these versions ALWAYS read from the console,
+* even when standard input is redirected.
+*
+*Revision History:
+* 06-08-89 PHG Module created, based on asm version
+* 03-12-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits
+* 07-24-90 SBM Removed '32' from API names
+* 10-03-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+* 01-25-91 SRW Get/SetConsoleMode parameters changed (_WIN32_)
+* 02-18-91 SRW Get/SetConsoleMode required read/write access (_WIN32_)
+* 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_)
+* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
+* 07-26-91 GJF Took out init. stuff and cleaned up the error
+* handling [_WIN32_].
+* 12-11-92 GJF Initialize character buffer to 0 (int ch = 0;) and
+* use ReadConsole instead of ReadFile.
+* 03-20-93 GJF Completely rewritten, Cruiser support purged, _kbhit
+* (also rewritten) and _ungetch also merged in.
+* 05-10-93 GJF Fixed bug in _kbhit, pointer passed to free no
+* longer pointed to the allocated block.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <conio.h>
+#include <os2dll.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct {
+ unsigned char LeadChar;
+ unsigned char SecondChar;
+ } CharPair;
+
+typedef struct {
+ unsigned short ScanCode;
+ CharPair RegChars;
+ CharPair ShiftChars;
+ CharPair CtrlChars;
+ CharPair AltChars;
+ } EnhKeyVals;
+
+typedef struct {
+ CharPair RegChars;
+ CharPair ShiftChars;
+ CharPair CtrlChars;
+ CharPair AltChars;
+ } NormKeyVals;
+
+/*
+ * Table of key values for enhanced keys
+ */
+static EnhKeyVals EnhancedKeys[] = {
+ { 28, { 13, 0 }, { 13, 0 }, { 10, 0 }, { 0, 166 } },
+ { 53, { 47, 0 }, { 63, 0 }, { 0, 149 }, { 0, 164 } },
+ { 71, { 224, 71 }, { 224, 71 }, { 224, 119 }, { 0, 151 } },
+ { 72, { 224, 72 }, { 224, 72 }, { 224, 141 }, { 0, 152 } },
+ { 73, { 224, 73 }, { 224, 73 }, { 224, 134 }, { 0, 153 } },
+ { 75, { 224, 75 }, { 224, 75 }, { 224, 115 }, { 0, 155 } },
+ { 77, { 224, 77 }, { 224, 77 }, { 224, 116 }, { 0, 157 } },
+ { 79, { 224, 79 }, { 224, 79 }, { 224, 117 }, { 0, 159 } },
+ { 80, { 224, 80 }, { 224, 80 }, { 224, 145 }, { 0, 160 } },
+ { 81, { 224, 81 }, { 224, 81 }, { 224, 118 }, { 0, 161 } },
+ { 82, { 224, 82 }, { 224, 82 }, { 224, 146 }, { 0, 162 } },
+ { 83, { 224, 83 }, { 224, 83 }, { 224, 147 }, { 0, 163 } }
+ };
+
+/*
+ * macro for the number of elements of in EnhancedKeys[]
+ */
+#define NUM_EKA_ELTS ( sizeof( EnhancedKeys ) / sizeof( EnhKeyVals ) )
+
+/*
+ * Table of key values for normal keys. Note that the table is padded so
+ * that the key scan code serves as an index into the table.
+ */
+static NormKeyVals NormalKeys[] = {
+
+ /* padding */
+ { /* 0 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+
+ { /* 1 */ { 27, 0 }, { 27, 0 }, { 27, 0 }, { 0, 1 } },
+ { /* 2 */ { 49, 0 }, { 33, 0 }, { 0, 0 }, { 0, 120 } },
+ { /* 3 */ { 50, 0 }, { 64, 0 }, { 0, 3 }, { 0, 121 } },
+ { /* 4 */ { 51, 0 }, { 35, 0 }, { 0, 0 }, { 0, 122 } },
+ { /* 5 */ { 52, 0 }, { 36, 0 }, { 0, 0 }, { 0, 123 } },
+ { /* 6 */ { 53, 0 }, { 37, 0 }, { 0, 0 }, { 0, 124 } },
+ { /* 7 */ { 54, 0 }, { 94, 0 }, { 30, 0 }, { 0, 125 } },
+ { /* 8 */ { 55, 0 }, { 38, 0 }, { 0, 0 }, { 0, 126 } },
+ { /* 9 */ { 56, 0 }, { 42, 0 }, { 0, 0 }, { 0, 127 } },
+ { /* 10 */ { 57, 0 }, { 40, 0 }, { 0, 0 }, { 0, 128 } },
+ { /* 11 */ { 48, 0 }, { 41, 0 }, { 0, 0 }, { 0, 129 } },
+ { /* 12 */ { 45, 0 }, { 95, 0 }, { 31, 0 }, { 0, 130 } },
+ { /* 13 */ { 61, 0 }, { 43, 0 }, { 0, 0 }, { 0, 131 } },
+ { /* 14 */ { 8, 0 }, { 8, 0 }, { 127, 0 }, { 0, 14 } },
+ { /* 15 */ { 9, 0 }, { 0, 15 }, { 0, 148 }, { 0, 15 } },
+ { /* 16 */ { 113, 0 }, { 81, 0 }, { 17, 0 }, { 0, 16 } },
+ { /* 17 */ { 119, 0 }, { 87, 0 }, { 23, 0 }, { 0, 17 } },
+ { /* 18 */ { 101, 0 }, { 69, 0 }, { 5, 0 }, { 0, 18 } },
+ { /* 19 */ { 114, 0 }, { 82, 0 }, { 18, 0 }, { 0, 19 } },
+ { /* 20 */ { 116, 0 }, { 84, 0 }, { 20, 0 }, { 0, 20 } },
+ { /* 21 */ { 121, 0 }, { 89, 0 }, { 25, 0 }, { 0, 21 } },
+ { /* 22 */ { 117, 0 }, { 85, 0 }, { 21, 0 }, { 0, 22 } },
+ { /* 23 */ { 105, 0 }, { 73, 0 }, { 9, 0 }, { 0, 23 } },
+ { /* 24 */ { 111, 0 }, { 79, 0 }, { 15, 0 }, { 0, 24 } },
+ { /* 25 */ { 112, 0 }, { 80, 0 }, { 16, 0 }, { 0, 25 } },
+ { /* 26 */ { 91, 0 }, { 123, 0 }, { 27, 0 }, { 0, 26 } },
+ { /* 27 */ { 93, 0 }, { 125, 0 }, { 29, 0 }, { 0, 27 } },
+ { /* 28 */ { 13, 0 }, { 13, 0 }, { 10, 0 }, { 0, 28 } },
+
+ /* padding */
+ { /* 29 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+
+ { /* 30 */ { 97, 0 }, { 65, 0 }, { 1, 0 }, { 0, 30 } },
+ { /* 31 */ { 115, 0 }, { 83, 0 }, { 19, 0 }, { 0, 31 } },
+ { /* 32 */ { 100, 0 }, { 68, 0 }, { 4, 0 }, { 0, 32 } },
+ { /* 33 */ { 102, 0 }, { 70, 0 }, { 6, 0 }, { 0, 33 } },
+ { /* 34 */ { 103, 0 }, { 71, 0 }, { 7, 0 }, { 0, 34 } },
+ { /* 35 */ { 104, 0 }, { 72, 0 }, { 8, 0 }, { 0, 35 } },
+ { /* 36 */ { 106, 0 }, { 74, 0 }, { 10, 0 }, { 0, 36 } },
+ { /* 37 */ { 107, 0 }, { 75, 0 }, { 11, 0 }, { 0, 37 } },
+ { /* 38 */ { 108, 0 }, { 76, 0 }, { 12, 0 }, { 0, 38 } },
+ { /* 39 */ { 59, 0 }, { 58, 0 }, { 0, 0 }, { 0, 39 } },
+ { /* 40 */ { 39, 0 }, { 34, 0 }, { 0, 0 }, { 0, 40 } },
+ { /* 41 */ { 96, 0 }, { 126, 0 }, { 0, 0 }, { 0, 41 } },
+
+ /* padding */
+ { /* 42 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+
+ { /* 43 */ { 92, 0 }, { 124, 0 }, { 28, 0 }, { 0, 0 } },
+ { /* 44 */ { 122, 0 }, { 90, 0 }, { 26, 0 }, { 0, 44 } },
+ { /* 45 */ { 120, 0 }, { 88, 0 }, { 24, 0 }, { 0, 45 } },
+ { /* 46 */ { 99, 0 }, { 67, 0 }, { 3, 0 }, { 0, 46 } },
+ { /* 47 */ { 118, 0 }, { 86, 0 }, { 22, 0 }, { 0, 47 } },
+ { /* 48 */ { 98, 0 }, { 66, 0 }, { 2, 0 }, { 0, 48 } },
+ { /* 49 */ { 110, 0 }, { 78, 0 }, { 14, 0 }, { 0, 49 } },
+ { /* 50 */ { 109, 0 }, { 77, 0 }, { 13, 0 }, { 0, 50 } },
+ { /* 51 */ { 44, 0 }, { 60, 0 }, { 0, 0 }, { 0, 51 } },
+ { /* 52 */ { 46, 0 }, { 62, 0 }, { 0, 0 }, { 0, 52 } },
+ { /* 53 */ { 47, 0 }, { 63, 0 }, { 0, 0 }, { 0, 53 } },
+
+ /* padding */
+ { /* 54 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+
+ { /* 55 */ { 42, 0 }, { 0, 0 }, { 114, 0 }, { 0, 0 } },
+
+ /* padding */
+ { /* 56 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+
+ { /* 57 */ { 32, 0 }, { 32, 0 }, { 32, 0 }, { 32, 0 } },
+
+ /* padding */
+ { /* 58 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+
+ { /* 59 */ { 0, 59 }, { 0, 84 }, { 0, 94 }, { 0, 104 } },
+ { /* 60 */ { 0, 60 }, { 0, 85 }, { 0, 95 }, { 0, 105 } },
+ { /* 61 */ { 0, 61 }, { 0, 86 }, { 0, 96 }, { 0, 106 } },
+ { /* 62 */ { 0, 62 }, { 0, 87 }, { 0, 97 }, { 0, 107 } },
+ { /* 63 */ { 0, 63 }, { 0, 88 }, { 0, 98 }, { 0, 108 } },
+ { /* 64 */ { 0, 64 }, { 0, 89 }, { 0, 99 }, { 0, 109 } },
+ { /* 65 */ { 0, 65 }, { 0, 90 }, { 0, 100 }, { 0, 110 } },
+ { /* 66 */ { 0, 66 }, { 0, 91 }, { 0, 101 }, { 0, 111 } },
+ { /* 67 */ { 0, 67 }, { 0, 92 }, { 0, 102 }, { 0, 112 } },
+ { /* 68 */ { 0, 68 }, { 0, 93 }, { 0, 103 }, { 0, 113 } },
+
+ /* padding */
+ { /* 69 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+ { /* 70 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+
+ { /* 71 */ { 0, 71 }, { 55, 0 }, { 0, 119 }, { 0, 0 } },
+ { /* 72 */ { 0, 72 }, { 56, 0 }, { 0, 141 }, { 0, 0 } },
+ { /* 73 */ { 0, 73 }, { 57, 0 }, { 0, 132 }, { 0, 0 } },
+ { /* 74 */ { 0, 0 }, { 45, 0 }, { 0, 0 }, { 0, 0 } },
+ { /* 75 */ { 0, 75 }, { 52, 0 }, { 0, 115 }, { 0, 0 } },
+ { /* 76 */ { 0, 0 }, { 53, 0 }, { 0, 0 }, { 0, 0 } },
+ { /* 77 */ { 0, 77 }, { 54, 0 }, { 0, 116 }, { 0, 0 } },
+ { /* 78 */ { 0, 0 }, { 43, 0 }, { 0, 0 }, { 0, 0 } },
+ { /* 79 */ { 0, 79 }, { 49, 0 }, { 0, 117 }, { 0, 0 } },
+ { /* 80 */ { 0, 80 }, { 50, 0 }, { 0, 145 }, { 0, 0 } },
+ { /* 81 */ { 0, 81 }, { 51, 0 }, { 0, 118 }, { 0, 0 } },
+ { /* 82 */ { 0, 82 }, { 48, 0 }, { 0, 146 }, { 0, 0 } },
+ { /* 83 */ { 0, 83 }, { 46, 0 }, { 0, 147 }, { 0, 0 } },
+
+ /* padding */
+ { /* 84 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+ { /* 85 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+ { /* 86 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
+
+ { /* 87 */ { 224, 133 }, { 224, 135 }, { 224, 137 }, { 224, 139 } },
+ { /* 88 */ { 224, 134 }, { 224, 136 }, { 224, 138 }, { 224, 140 } }
+
+};
+
+
+/*
+ * This is the one character push-back buffer used by _getch(), _getche()
+ * and _ungetch().
+ */
+static int chbuf = EOF;
+
+
+/*
+ * Declaration for console handle
+ */
+extern int _coninpfh;
+
+/*
+ * Function that looks up the extended key code for a given event.
+ */
+static CharPair * _CRTAPI3 GetExtendedKeyCode(KEY_EVENT_RECORD *);
+
+
+/***
+*int _getch(), _getche() - read one char. from console (without and with echo)
+*
+*Purpose:
+* If the "_ungetch()" push-back buffer is not empty (empty==-1) Then
+* Mark it empty (-1) and RETURN the value that was in it
+* Read a character using DOSREAD in RAW mode
+* Return the Character Code
+* _getche(): Same as _getch() except that the character value returned
+* is echoed (via "_putch()")
+*
+* No _ext_code buffer is required (unlike the DOS & 16 bit OS/2 world,)
+* since OS/2 buffers the extended code for us.
+*
+*Entry:
+* None, reads from console.
+*
+*Exit:
+* If an error is returned from the API
+* Then EOF
+* Otherwise
+* next byte from console
+* Static variable "chbuf" may be altered
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+int _CRTAPI1 _getch (
+ void
+ )
+{
+ int ch;
+
+ _mlock(_CONIO_LOCK); /* secure the console lock */
+ ch = _getch_lk(); /* input the character */
+ _munlock(_CONIO_LOCK); /* release the console lock */
+
+ return ch;
+}
+
+int _CRTAPI1 _getche (
+ void
+ )
+{
+ int ch;
+
+ _mlock(_CONIO_LOCK); /* secure the console lock */
+ ch = _getche_lk(); /* input and echo the character */
+ _munlock(_CONIO_LOCK); /* unlock the console */
+
+ return ch;
+}
+
+#endif /* MTHREAD */
+
+
+#ifdef MTHREAD
+int _CRTAPI1 _getch_lk (
+#else
+int _CRTAPI1 _getch (
+#endif
+ void
+ )
+{
+ INPUT_RECORD ConInpRec;
+ DWORD NumRead;
+ CharPair *pCP;
+ int ch = 0; /* single character buffer */
+ DWORD oldstate;
+
+ /*
+ * check pushback buffer (chbuf) a for character
+ */
+ if ( chbuf != EOF ) {
+ /*
+ * something there, clear buffer and return the character.
+ */
+ ch = (unsigned char)(chbuf & 0xFF);
+ chbuf = EOF;
+ return ch;
+ }
+
+ if (_coninpfh == -1)
+ return EOF;
+
+ /*
+ * Switch to raw mode (no line input, no echo input)
+ */
+ GetConsoleMode( (HANDLE)_coninpfh, &oldstate );
+ SetConsoleMode( (HANDLE)_coninpfh, 0L );
+
+ for ( ; ; ) {
+
+ /*
+ * Get a console input event.
+ */
+ if ( !ReadConsoleInput( (HANDLE)_coninpfh,
+ &ConInpRec,
+ 1L,
+ &NumRead )
+ || (NumRead == 0L) )
+ {
+ ch = EOF;
+ break;
+ }
+
+ /*
+ * Look for, and decipher, key events.
+ */
+ if ( (ConInpRec.EventType == KEY_EVENT) &&
+ ConInpRec.Event.KeyEvent.bKeyDown ) {
+ /*
+ * Easy case: if uChar.AsciiChar is non-zero, just stuff it
+ * into ch and quit.
+ */
+ if ( ch = (unsigned char)ConInpRec.Event.KeyEvent.uChar.AsciiChar )
+ break;
+
+ /*
+ * Hard case: either an extended code or an event which should
+ * not be recognized. let GetExtendedKeyCode() do the work...
+ */
+ if ( pCP = GetExtendedKeyCode( &(ConInpRec.Event.KeyEvent) ) ) {
+ ch = pCP->LeadChar;
+ chbuf = pCP->SecondChar;
+ break;
+ }
+ }
+ }
+
+
+ /*
+ * Restore previous console mode.
+ */
+ SetConsoleMode( (HANDLE)_coninpfh, oldstate );
+
+ return ch;
+}
+
+
+/*
+ * getche is just getch followed by a putch if no error occurred
+ */
+
+#ifdef MTHREAD
+int _CRTAPI1 _getche_lk (
+#else
+int _CRTAPI1 _getche (
+#endif
+ void
+ )
+{
+ int ch; /* character read */
+
+ ch = _getch_lk(); /* read character */
+ if (ch != EOF) {
+ if (_putch_lk(ch) != EOF) {
+ return ch; /* if no error, return char */
+ }
+ }
+ return EOF; /* get or put failed, return EOF */
+}
+
+
+/***
+*int _kbhit() - return flag if a keystroke is already waiting to be read
+*
+*Purpose:
+* If the "_ungetch()" push-back buffer is not empty (empty==-1) Then
+* Return TRUE
+* Otherwise get the Keyboard Status (via DOSQUERYFHSTATE)
+* No _ext_code buffer is required (unlike the DOS & 16 bit OS/2 world,)
+* since OS/2 buffers the extended code for us.
+*
+*Entry:
+* None, tests console.
+*
+*Exit:
+* returns 0 if no key waiting
+* = !0 if key waiting
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+int _CRTAPI1 _kbhit_lk(void);
+
+int _CRTAPI1 _kbhit (
+ void
+ )
+{
+ int retval;
+
+ _mlock(_CONIO_LOCK); /* secure the console lock */
+ retval = _kbhit_lk(); /* determine if a key is waiting */
+ _munlock(_CONIO_LOCK); /* release the console lock */
+
+ return retval;
+}
+
+int _CRTAPI1 _kbhit_lk (
+
+#else
+
+int _CRTAPI1 _kbhit (
+
+#endif
+ void
+ )
+{
+ void *pblk;
+ PINPUT_RECORD pIRBuf;
+ DWORD NumPending;
+ DWORD NumPeeked;
+
+ /*
+ * if a character has been pushed back, return TRUE
+ */
+ if ( chbuf != -1 )
+ return TRUE;
+
+ /*
+ * Peek all pending console events
+ */
+ if ( (_coninpfh == -1) ||
+
+ !GetNumberOfConsoleInputEvents((HANDLE)_coninpfh, &NumPending) ||
+
+ ((pblk = malloc( NumPending * sizeof(INPUT_RECORD) )) == NULL) )
+ {
+ return FALSE;
+ }
+
+ /*
+ * Keep pblk unmodified, for use in a later call to free()
+ */
+ pIRBuf = (PINPUT_RECORD)pblk;
+
+ if ( PeekConsoleInput( (HANDLE)_coninpfh,
+ pIRBuf,
+ NumPending,
+ &NumPeeked ) &&
+
+ (NumPeeked != 0L) &&
+
+ (NumPeeked <= NumPending) )
+ {
+
+ /*
+ * Scan all of the peeked events to determine if any is a key event
+ * which should be recognized.
+ */
+ for ( ; NumPeeked > 0 ; NumPeeked--, pIRBuf++ ) {
+
+ if ( (pIRBuf->EventType == KEY_EVENT) &&
+
+ (pIRBuf->Event.KeyEvent.bKeyDown) &&
+
+ ( pIRBuf->Event.KeyEvent.uChar.AsciiChar ||
+ GetExtendedKeyCode( &(pIRBuf->Event.KeyEvent) ) ) )
+ {
+ /*
+ * Key event corresponding to an ASCII character or an
+ * extended code. In either case, success!
+ */
+ free(pblk);
+ return TRUE;
+ }
+ }
+ }
+
+ free(pblk);
+ return FALSE;
+}
+
+
+/***
+*int _ungetch(c) - push back one character for "_getch()" or "_getche()"
+*
+*Purpose:
+* If the Push-back buffer "chbuf" is -1 Then
+* Set "chbuf" to the argument and return the argument
+* Else
+* Return EOF to indicate an error
+*
+*Entry:
+* int c - Character to be pushed back
+*
+*Exit:
+* If successful
+* returns character that was pushed back
+* Else if error
+* returns EOF
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+int _CRTAPI1 _ungetch (
+ int c
+ )
+{
+ int retval;
+
+ _mlock(_CONIO_LOCK); /* lock the console */
+ retval = _ungetch_lk(c); /* pushback character */
+ _munlock(_CONIO_LOCK); /* unlock the console */
+
+ return retval;
+}
+int _CRTAPI1 _ungetch_lk (
+
+#else
+
+int _CRTAPI1 _ungetch (
+
+#endif
+ int c
+ )
+{
+ /*
+ * Fail if the char is EOF or the pushback buffer is non-empty
+ */
+ if ( (c == EOF) || (chbuf != EOF) )
+ return EOF;
+
+ chbuf = (c & 0xFF);
+ return chbuf;
+}
+
+
+
+
+/***
+* static CharPair * GetExtendedKeyCode(pKE) - return extended code (if any)
+* for key event.
+*
+*Purpose:
+* Core function for _getch (and getche) and essential to _kbhit. This
+* is the function that determines whether or not a key event NOT
+* accompanied by an ASCII character has an extended code and returns
+* that code.
+*
+*Entry:
+* None, tests console.
+*
+*Exit:
+* if successful, returns a pointer to a CharPair value holding the lead
+* and second characters of the extended code.
+*
+* if unsuccesful, returns NULL
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+static CharPair * _CRTAPI3 GetExtendedKeyCode (
+ KEY_EVENT_RECORD *pKE
+ )
+{
+ DWORD CKS; /* hold dwControlKeyState value */
+ CharPair *pCP; /* pointer to CharPair containing extended
+ code */
+ int i;
+
+ // printf("pKE->wVirtualScanCode = %d\n", (int) (pKE->wVirtualScanCode) );
+ // printf("pKE->dwControlKeyState = %lx\n\n", pKE->dwControlKeyState);
+
+ if ( (CKS = pKE->dwControlKeyState) & ENHANCED_KEY ) {
+
+ /*
+ * Find the appropriate entry in EnhancedKeys[]
+ */
+ for ( pCP = NULL, i = 0 ; i < NUM_EKA_ELTS ; i++ ) {
+
+ if ( EnhancedKeys[i].ScanCode == pKE->wVirtualScanCode ) {
+
+ if ( CKS & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) )
+
+ pCP = &(EnhancedKeys[i].AltChars);
+
+ else if ( CKS & (LEFT_CTRL_PRESSED | LEFT_CTRL_PRESSED) )
+
+ pCP = &(EnhancedKeys[i].CtrlChars);
+
+ else if ( CKS & SHIFT_PRESSED)
+
+ pCP = &(EnhancedKeys[i].ShiftChars);
+
+ else
+
+ pCP = &(EnhancedKeys[i].RegChars);
+
+ break;
+
+ }
+ }
+
+ }
+
+ else {
+
+ /*
+ * Regular key or a keyboard event which shouldn't be recognized.
+ * Determine which by getting the proper field of the proper
+ * entry in NormalKeys[], and examining the extended code.
+ */
+ if ( CKS & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) )
+
+ pCP = &(NormalKeys[pKE->wVirtualScanCode].AltChars);
+
+ else if ( CKS & (LEFT_CTRL_PRESSED | LEFT_CTRL_PRESSED) )
+
+ pCP = &(NormalKeys[pKE->wVirtualScanCode].CtrlChars);
+
+ else if ( CKS & SHIFT_PRESSED)
+
+ pCP = &(NormalKeys[pKE->wVirtualScanCode].ShiftChars);
+
+ else
+
+ pCP = &(NormalKeys[pKE->wVirtualScanCode].RegChars);
+
+ if ( ((pCP->LeadChar != 0) && (pCP->LeadChar != 224)) ||
+ (pCP->SecondChar == 0) )
+ /*
+ * Must be a keyboard event which should not be recognized
+ * (e.g., shift key was pressed)
+ */
+ pCP = NULL;
+
+ }
+
+ return(pCP);
+}
diff --git a/private/crt32/lowio/i386/_initcon.asm b/private/crt32/lowio/i386/_initcon.asm
new file mode 100644
index 000000000..3ec35d9b6
--- /dev/null
+++ b/private/crt32/lowio/i386/_initcon.asm
@@ -0,0 +1,17 @@
+ page ,132
+
+;*******
+;
+; Alternate form of CINITCON.ASM
+;
+; The MIPS C Compiler does not prepend underscores to C
+; variables and functions like the I386 C Compiler does.
+;
+; The EQUate below will yield an object file
+; which will be appropriate for MIPS COFF format.
+;
+;*******
+
+NO_UNDERSCORE equ 1
+
+include i386\cinitcon.asm
diff --git a/private/crt32/lowio/i386/cinitcon.asm b/private/crt32/lowio/i386/cinitcon.asm
new file mode 100644
index 000000000..aa6f8074a
--- /dev/null
+++ b/private/crt32/lowio/i386/cinitcon.asm
@@ -0,0 +1,99 @@
+ page ,132
+ title cinitcon - C Run-Time Startup Initialization for Console I/O
+;***
+;cinitcon.asm - C Run-Time Startup Initialization for WIN32
+;
+; Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Initialization and Termination for console I/O
+;
+;Notes:
+; _confh and _coninpfh are defined in this module to force the
+; inclusion of this module if any console I/O is performed.
+; This module places the address of _initcon() in the initializer
+; table and the address of _termcon() in the pre-terminator table.
+;
+;Revision History:
+; 03-19-92 SKS Module created.
+; 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+; 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+; 08-06-92 SKS Revised to use new section names and macros
+;
+;*******************************************************************************
+
+.xlist
+include cruntime.inc
+include defsects.inc
+.list
+
+ifndef _WIN32_
+.err
+%out _WIN32_ MUST be defined!
+endif
+
+
+ifndef NO_UNDERSCORE ; I386 VERSION *************************
+
+
+ extrn _initcon:NEAR
+ extrn _termcon:NEAR
+
+
+beginSection XIC
+
+ dd offset FLAT: _initcon
+
+endSection XIC
+
+
+beginSection XPX
+
+ dd offset FLAT: _termcon
+
+endSection XPX
+
+
+ .DATA
+
+ public _coninpfh
+ public _confh
+
+_coninpfh dd -1 ; console input
+_confh dd -1 ; console output
+
+
+else ; NO_UNDERSCORE ; MIPS VERSION *************************
+
+
+ extrn initcon:NEAR
+ extrn termcon:NEAR
+
+
+beginSection XIC
+
+ dd offset FLAT: initcon
+
+endSection XIC
+
+
+beginSection XPX
+
+ dd offset FLAT: termcon
+
+endSection XPX
+
+
+ .DATA
+
+ public coninpfh
+ public confh
+
+coninpfh dd -1 ; console input
+confh dd -1 ; console output
+
+
+endif ; NO_UNDERSCORE ; **** VERSION *************************
+
+
+ end
diff --git a/private/crt32/lowio/initcon.c b/private/crt32/lowio/initcon.c
new file mode 100644
index 000000000..0302e5d84
--- /dev/null
+++ b/private/crt32/lowio/initcon.c
@@ -0,0 +1,113 @@
+/***
+*_initcon.c - direct console I/O initialization and termination for Win32
+*
+* Copyright (c) 1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines _initcon() and _termcon() routines.
+*
+* NOTE: The _initcon() and _termcon() routines are called indirectly
+* by the startup and termination code, thru the pointers _pinitcon
+* and _ptermcon.
+*
+*Revision History:
+* 07-26-91 GJF Module created. Based on the original code by Stevewo
+* (which was distributed across several sources).
+* 03-12-92 SKS Split out initializer
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+
+void __cdecl _initcon(void);
+void __cdecl _termcon(void);
+
+#ifdef _MSC_VER
+
+#pragma data_seg(".CRT$XIC")
+static void (__cdecl *pinit)(void) = _initcon;
+
+#pragma data_seg(".CRT$XPX")
+static void (__cdecl *pterm)(void) = _termcon;
+
+#pragma data_seg()
+
+#endif /* _MSC_VER */
+
+/*
+ * define console handles. these definitions cause this file to be linked
+ * in if one of the direct console I/O functions is referenced.
+ */
+int _coninpfh = -1; /* console input */
+int _confh = -1; /* console output */
+
+/***
+*void _initcon(void) - open handles for console I/O
+*
+*Purpose:
+* Opens handles for console input and output.
+*
+*Entry:
+* None.
+*
+*Exit:
+* No return value. If successful, handle values are copied into the
+* global variables _coninpfh and _confh.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __cdecl _initcon (
+ void
+ )
+{
+ _coninpfh = (int)CreateFile( "CONIN$",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ _confh = (int)CreateFile( "CONOUT$",
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+}
+
+
+/***
+*void _termcon(void) - close console I/O handles
+*
+*Purpose:
+* Closes _coninpfh and _confh.
+*
+*Entry:
+* None.
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __cdecl _termcon (
+ void
+ )
+{
+ if ( _confh != -1 ) {
+ CloseHandle( (HANDLE)_confh );
+ }
+
+ if ( _coninpfh != -1 ) {
+ CloseHandle( (HANDLE)_coninpfh );
+ }
+}
diff --git a/private/crt32/lowio/ioinit.c b/private/crt32/lowio/ioinit.c
new file mode 100644
index 000000000..d359f9686
--- /dev/null
+++ b/private/crt32/lowio/ioinit.c
@@ -0,0 +1,242 @@
+/***
+*ioinit.c - Initialization for lowio functions
+*
+* Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains all initialization for lowio functions. Currently, this
+* includes:
+* 1. Definitions of _nhandle, _osfhnd[], _osfile[] and _pipech[],
+* including initial values.
+* 2. Processing of inherited file info from parent process.
+* 3. Initialization of _osfhnd[] and _osfile[] entries for
+* standard input/output/error.
+*
+*Revision History:
+* 02-14-92 GJF Module created.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <msdos.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Number of allowable file handles. The static initialization of the
+ * _osfhnd[] and _pipech[] arrays (below) supports only two values of
+ * _NHANDLE, 64 (for single-thread) and 256 (for multi-thread)!
+ */
+int _nhandle = _NHANDLE_;
+
+/*
+ * File handle database
+ */
+char _osfile[_NHANDLE_] = { 0 };
+
+/*
+ * Array of OS file handles. Statically initialized to INVALID_HANDLE_VALUE.
+ * Note that if _NHANDLE_ differs from 64 for single-thread, or differs from
+ * 256 for multi-thread, this initialization needs to be revised.
+ */
+#define NOHNDL (long)INVALID_HANDLE_VALUE
+
+long _osfhnd[_NHANDLE_] = {
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+#ifdef MTHREAD
+ NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+ NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL,
+#endif
+ NOHNDL };
+
+/*
+ * Peek-ahead buffers for pipes, each initialized to a newline. Note that if
+ * _NHANDLE_ differs from 64 for single-thread, or differs from 256 for
+ * multi-thread, this initialization needs to be revised.
+ */
+char _pipech[_NHANDLE_] = {
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+#ifdef MTHREAD
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+#endif
+ 10 };
+
+/*
+ * macro used to map 0, 1 and 2 to right value for call to GetStdHandle
+ */
+#define stdhndl(fh) ( (fh == 0) ? STD_INPUT_HANDLE : ((fh == 1) ? \
+ STD_OUTPUT_HANDLE : STD_ERROR_HANDLE) )
+
+/***
+*_ioinit() -
+*
+*Purpose:
+* First, _ioinit() obtains and processes information on inherited file
+* handles from the parent process (e.g., cmd.exe)
+*
+* Obtains the StartupInfo structure from the OS. The inherited file
+* handle information is pointed to by the lpReserved2 field. The format
+* of the information is as follows:
+*
+* bytes 0 thru 3 - integer value, say N, which is the number of handles
+* information is passed about.
+*
+* bytes 4 thru N+3 - values for _osfile[0] thru _osfile[N-1]
+*
+* bytes N+4 thru 5*N+3 - N double-words, the N OS handle values being
+* passed.
+*
+* Next, _osfhnd[i] and _osfile[i] are initialized for i = 0, 1, 2, as
+* follows:
+*
+* If the value in _osfhnd[i] is INVALID_HANDLE_VALUE, then try to
+* obtain a handle by calling GetStdHandle, and call GetFileType to
+* help set _osfile[i]. Otherwise, assume _osfhndl[i] and _osfile[i]
+* are valid, but force it to text mode (standard input/output/error
+* are to always start out in text mode).
+*
+* Notes:
+* 1. In general, not all of the passed info from the parent process
+* will describe open handles! If, for example, only C handle 1
+* (STDOUT) and C handle 6 are open in the parent, info for C
+* handles 0 thru 6 is passed to the the child.
+*
+* 2. Care is taken not to 'overflow' _osfhnd[] and _osfile[]. Only
+* info on the first _NHANDLE_ handles from the parent process is
+* used.
+*
+* 3. See exec\dospawn.c for the encodes of the file handle info
+* to be passed to a child process.
+*
+*Entry:
+* No parameters: reads the environment.
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _ioinit (
+ void
+ )
+{
+ STARTUPINFO StartupInfo;
+ int cfi_len;
+ int fh;
+ DWORD htype;
+
+ /*
+ * Process inherited file handle information, if any
+ */
+
+ GetStartupInfo( &StartupInfo );
+
+ if ( StartupInfo.cbReserved2 != 0 && StartupInfo.lpReserved2 != NULL ) {
+ /*
+ * Get the number of handles inherited.
+ */
+ memcpy( &cfi_len,
+ StartupInfo.lpReserved2,
+ sizeof( int )
+ );
+ /*
+ * Now, get one byte of info (_osfile[] entry) for each
+ * inherited handle. Be careful not to overflow the _osfile[]
+ * array.
+ */
+ memcpy( _osfile,
+ StartupInfo.lpReserved2 + sizeof( int ),
+ __min(_NHANDLE_, cfi_len) * sizeof( char )
+ );
+ /*
+ * Finally, copy each each inherited handle into _osfhnd[].
+ * Be careful not to overflow _osfile[].
+ */
+ memcpy( _osfhnd,
+ StartupInfo.lpReserved2 + sizeof( int ) +
+ (cfi_len * sizeof( char )),
+ __min(_NHANDLE_, cfi_len) * sizeof( long )
+ );
+ }
+
+ /*
+ * If handles for standard input, output and error were not inherited,
+ * try to obtain them directly from the OS. Also, set appropriate bits
+ * in _osfile[0], _osfile[1] and _osfile[2].
+ */
+
+ for ( fh = 0 ; fh <= 2 ; ++fh ) {
+
+ if ( _osfhnd[fh] == (long)INVALID_HANDLE_VALUE ) {
+ if ( (_osfhnd[fh] = (long)GetStdHandle( stdhndl(fh) ))
+ != (long)INVALID_HANDLE_VALUE ) {
+ /*
+ * mark the stream as open in text mode.
+ * determine if it isa char device or pipe.
+ */
+ _osfile[fh] = (char)(FOPEN | FTEXT);
+ htype = GetFileType( (HANDLE)_osfhnd[fh] );
+ if ( (htype & 0xFF) == FILE_TYPE_CHAR )
+ _osfile[fh] |= FDEV;
+ else if ( (htype & 0xFF) == FILE_TYPE_PIPE )
+ _osfile[fh] |= FPIPE;
+ }
+ }
+ else
+ /*
+ * handle was passed to us by parent process. make
+ * sure it is text mode.
+ */
+ _osfile[fh] |= FTEXT;
+ }
+
+
+}
diff --git a/private/crt32/lowio/isatty.c b/private/crt32/lowio/isatty.c
new file mode 100644
index 000000000..9bb931d18
--- /dev/null
+++ b/private/crt32/lowio/isatty.c
@@ -0,0 +1,62 @@
+/***
+*isatty.c - check if file handle refers to a device
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _isatty() - check if file handle refers to a device
+*
+*Revision History:
+* 06-08-89 PHG Module created
+* 03-12-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 08-14-90 SBM Compiles cleanly with -W3, minor optimization
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s.
+* It's not worth it to try to merge the versions more
+* closely.
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 01-16-91 GJF ANSI naming.
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <msdos.h>
+#include <internal.h>
+#include <io.h>
+
+/***
+*int _isatty(handle) - check if handle is a device
+*
+*Purpose:
+* Checks if the given handle is associated with a character device
+* (terminal, console, printer, serial port)
+*
+*Entry:
+* int handle - handle of file to be tested
+*
+*Exit:
+* returns non-0 if handle refers to character device,
+* returns 0 otherwise
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _isatty (
+ int fh
+ )
+{
+ /* see if file handle is valid, otherwise return FALSE */
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle )
+#else
+ if ((unsigned)fh >= (unsigned)_nfile)
+#endif
+ return 0;
+
+ /* check file handle database to see if device bit set */
+ return (int)(_osfile[fh] & FDEV);
+}
diff --git a/private/crt32/lowio/locking.c b/private/crt32/lowio/locking.c
new file mode 100644
index 000000000..8eca84b29
--- /dev/null
+++ b/private/crt32/lowio/locking.c
@@ -0,0 +1,187 @@
+/***
+*locking.c - OS/2 file locking function
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defined the _locking() function - file locking and unlocking
+*
+*Revision History:
+* 06-09-89 PHG Module created, based on asm version
+* 08-10-89 JCR Changed DOS32FILELOCKS to DOS32SETFILELOCKS
+* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned up
+* the formatting a bit.
+* 04-03-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 08-14-90 SBM Compiles cleanly with -W3
+* 09-28-90 GJF New-style function declarator.
+* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s.
+* It is enough different that there is little point in
+* trying to more closely merge the two versions.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 01-16-91 GJF ANSI naming.
+* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
+* 12-05-91 GJF Fixed usage of [Un]LockFile APIs [_WIN32_].
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+* 05-06-92 SRW WIN32 LockFile API changed. [_WIN32_].
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <errno.h>
+#include <sys\locking.h>
+#include <io.h>
+#include <stdlib.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int _locking(fh,lmode,nbytes) - file record locking function
+*
+*Purpose:
+* Locks or unlocks nbytes of a specified file
+*
+* Multi-thread - Must lock/unlock the file handle to prevent
+* other threads from working on the file at the same time as us.
+* [NOTE: We do NOT release the lock during the 1 second delays
+* since some other thread could get in and do something to the
+* file. The DOSFILELOCK call locks out other processes, not
+* threads, so there is no multi-thread deadlock at the DOS file
+* locking level.]
+*
+*Entry:
+* int fh - file handle
+* int lmode - locking mode:
+* _LK_LOCK/_LK_RLCK -> lock, retry 10 times
+* _LK_NBLCK/_LK_N_BRLCK -> lock, don't retry
+* _LK_UNLCK -> unlock
+* long nbytes - number of bytes to lock/unlock
+*
+*Exit:
+* returns 0 if successful
+* returns -1 and sets errno if unsuccessful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _locking (
+ int fh,
+ int lmode,
+ long nbytes
+ )
+{
+ ULONG dosretval; /* OS/2 return code */
+ LONG lockoffset;
+ int retry; /* retry count */
+
+ /* validate file handle */
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+#else
+ if ((unsigned)fh >= (unsigned)_nfile) {
+#endif
+ /* fh out of range */
+ errno = EBADF;
+ _doserrno = 0; /* not an OS/2 error */
+ return -1;
+ }
+
+ _lock_fh(fh); /* acquire file handle lock */
+
+ /* obtain current position in file by calling _lseek */
+ /* Use _lseek_lk as we already own lock */
+ lockoffset = _lseek_lk(fh, 0L, 1);
+ if (lockoffset == -1) {
+ _unlock_fh(fh);
+ return -1;
+ }
+
+
+ /* set retry count based on mode */
+ if (lmode == _LK_LOCK || lmode == _LK_RLCK)
+ retry = 9; /* retry 9 times */
+ else
+ retry = 0; /* don't retry */
+
+ /* ask OS/2 to lock the file until success or retry count finished */
+ /* note that the only error possible is a locking violation, since */
+ /* an invalid handle would have already failed above */
+ for (;;) {
+#ifdef _CRUISER_
+ FILELOCK filelock; /* OS/2 file locking structure */
+
+ filelock.lOffset = lockoffset;
+ filelock.lRange = nbytes;
+
+ if (lmode == _LK_UNLCK)
+ dosretval = DOSSETFILELOCKS(fh, &filelock, NULL);
+ else
+ dosretval = DOSSETFILELOCKS(fh, NULL, &filelock);
+
+ if (retry <= 0 || dosretval == 0)
+ break; /* exit loop on success or retry exhausted */
+
+ DOSSLEEP(1000); /* wait 1 sec until try again */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ dosretval = 0;
+ if (lmode == _LK_UNLCK) {
+ if ( !(UnlockFile((HANDLE)_get_osfhandle(fh),
+ lockoffset,
+ 0L,
+ nbytes,
+ 0L))
+ )
+ dosretval = GetLastError();
+
+ } else {
+ if ( !(LockFile((HANDLE)_get_osfhandle(fh),
+ lockoffset,
+ 0L,
+ nbytes,
+ 0L))
+ )
+ dosretval = GetLastError();
+ }
+
+ if (retry <= 0 || dosretval == 0)
+ break; /* exit loop on success or retry exhausted */
+
+ Sleep(1000L);
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ --retry;
+ }
+
+ _unlock_fh(fh); /* release the file handle lock */
+
+ if (dosretval != 0) {
+ /* OS/2 error occurred -- file was already locked; if a
+ blocking call, then return EDEADLOCK, otherwise map
+ error normally */
+ if (lmode == _LK_LOCK || lmode == _LK_RLCK) {
+ errno = EDEADLOCK;
+ _doserrno = dosretval;
+ }
+ else {
+ _dosmaperr(dosretval);
+ }
+ return -1;
+ }
+ else
+ return 0;
+}
diff --git a/private/crt32/lowio/lseek.c b/private/crt32/lowio/lseek.c
new file mode 100644
index 000000000..bf3524e5f
--- /dev/null
+++ b/private/crt32/lowio/lseek.c
@@ -0,0 +1,187 @@
+/***
+*lseek.c - OS/2 change file position
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _lseek() - move the file pointer
+*
+*Revision History:
+* 06-20-89 PHG Module created, based on asm version
+* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned up
+* the formatting a bit.
+* 04-03-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 08-14-90 SBM Compiles cleanly with -W3
+* 09-28-90 GJF New-style function declarators.
+* 12-04-90 GJF Appended Win32 version with #ifdef-s. It's probably
+* worth coming back and doing a more complete merge later
+* (much later).
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 01-16-91 GJF ANSI naming.
+* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
+* 04-09-91 PNT Added _MAC_ conditional
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <os2dll.h>
+#include <io.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <msdos.h>
+#include <stdio.h>
+
+/***
+*long _lseek(fh,pos,mthd) - move the file pointer
+*
+*Purpose:
+* Moves the file pointer associated with fh to a new position.
+* The new position is pos bytes (pos may be negative) away
+* from the origin specified by mthd.
+*
+* If mthd == SEEK_SET, the origin in the beginning of file
+* If mthd == SEEK_CUR, the origin is the current file pointer position
+* If mthd == SEEK_END, the origin is the end of the file
+*
+* Multi-thread:
+* _lseek() = locks/unlocks the file
+* _lseek_lk() = does NOT lock/unlock the file (it is assumed that
+* the caller has the aquired the file lock,if needed).
+*
+*Entry:
+* int fh - file handle to move file pointer on
+* long pos - position to move to, relative to origin
+* int mthd - specifies the origin pos is relative to (see above)
+*
+*Exit:
+* returns the offset, in bytes, of the new position from the beginning
+* of the file.
+* returns -1L (and sets errno) if fails.
+* Note that seeking beyond the end of the file is not an error.
+* (although seeking before the beginning is.)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+/* define locking/validating lseek */
+long _CALLTYPE1 _lseek (
+ int fh,
+ long pos,
+ int mthd
+ )
+{
+ int r;
+
+ /* validate fh */
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+#else
+ if ((unsigned)fh >= (unsigned)_nfile) {
+#endif
+ /* bad file handle */
+ errno = EBADF;
+ _doserrno = 0; /* not OS/2 error */
+ return -1;
+ }
+
+ _lock_fh(fh); /* lock file handle */
+ r = _lseek_lk(fh, pos, mthd); /* seek */
+ _unlock_fh(fh); /* unlock file handle */
+
+ return r;
+}
+
+/* define core _lseek -- doesn't lock or validate fh */
+long _CALLTYPE1 _lseek_lk (
+ int fh,
+ long pos,
+ int mthd
+ )
+{
+ ULONG newpos; /* new file position */
+ ULONG dosretval; /* OS/2 return value */
+
+#else
+
+/* define normal _lseek */
+long _CALLTYPE1 _lseek (
+ int fh,
+ long pos,
+ int mthd
+ )
+{
+ ULONG newpos; /* new file position */
+ ULONG dosretval; /* OS/2 return value */
+
+ /* validate fh */
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+#else
+ if ((unsigned)fh >= (unsigned)_nfile) {
+#endif
+ /* bad file handle */
+ errno = EBADF;
+ _doserrno = 0; /* not OS/2 error */
+ return -1;
+ }
+
+#endif
+
+ /* tell OS/2 to seek */
+
+#ifdef _CRUISER_
+
+#if SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END
+ #error Xenix and OS/2 seek constants not compatible
+#endif
+
+ dosretval = DOSSETFILEPTR(fh, pos, mthd, &newpos);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+#if SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END
+ #error Xenix and Win32 seek constants not compatible
+#endif
+
+ if ((newpos = SetFilePointer((HANDLE)_get_osfhandle(fh),
+ pos, NULL, mthd)) == -1)
+ dosretval = GetLastError();
+ else
+ dosretval = 0;
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ if (dosretval) {
+ /* OS/2 error */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ _osfile[fh] &= ~FEOFLAG; /* clear the ctrl-z flag on the file */
+ return newpos; /* return */
+}
diff --git a/private/crt32/lowio/makefile b/private/crt32/lowio/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/lowio/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/lowio/mktemp.c b/private/crt32/lowio/mktemp.c
new file mode 100644
index 000000000..a4d827ecf
--- /dev/null
+++ b/private/crt32/lowio/mktemp.c
@@ -0,0 +1,115 @@
+/***
+*mktemp.c - create a unique file name
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _mktemp() - create a unique file name
+*
+*Revision History:
+* 06-02-86 JMB eliminated unneccesary routine exits
+* 05-26-87 JCR fixed bug where mktemp was incorrectly modifying
+* the errno value.
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 07-11-88 JCR Optimized REG allocation
+* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 04-04-90 GJF Added #include <process.h> and #include <io.h>. Removed
+* #include <sizeptr.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 08-13-90 SBM Compiles cleanly with -W3
+* 09-28-90 GJF New-style function declarator.
+* 01-16-91 GJF ANSI naming.
+* 11-30-92 KRS Ported _MBCS code from 16-bit tree.
+* 06-18-93 KRS MBCS-only bug fix ported from 16-bit tree.
+* 08-03-93 KRS Call _ismbstrail instead of isdbcscode.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <io.h>
+#include <process.h>
+#include <errno.h>
+#include <assert.h>
+#include <stddef.h>
+#ifdef _MBCS
+#include <mbctype.h>
+#include <mbdata.h>
+#endif
+
+/***
+*char *_mktemp(template) - create a unique file name
+*
+*Purpose:
+* given a template of the form "fnamXXXXXX", insert number on end
+* of template, insert unique letter if needed until unique filename
+* found or run out of letters
+#ifdef OS2_COMMENT
+* Note: this version can be used for both DOS 3 and OS/2
+#endif
+*
+*Entry:
+* char *template - template of form "fnamXXXXXX"
+*
+*Exit:
+* return pointer to modifed template
+* returns NULL if template malformed or no more unique names
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _mktemp (
+ char *template
+ )
+{
+ REG1 char *string = template;
+ REG3 unsigned number;
+ int letter = 'a';
+ REG2 int xcount = 0;
+ int olderrno;
+
+ assert(template != NULL);
+ assert(*template != '\0');
+
+ number = _getpid();
+
+ while (*string)
+ string++;
+
+#ifdef _MBCS
+ while ((--string>=template) && (!_ismbstrail(template,string))
+ && (*string == 'X'))
+#else
+ while (*--string == 'X')
+#endif
+ {
+ xcount++;
+ *string = (char)((number % 10) + '0');
+ number /= 10;
+ }
+
+ if (*++string == '\0' || xcount != 6 )
+ return(NULL);
+
+ olderrno = errno; /* save current errno */
+ errno = 0; /* make sure errno isn't EACCESS */
+
+ while ((_access(template,0) == 0) || (errno == EACCES))
+ /* while file exists */
+ {
+ errno = 0;
+ if (letter == 'z'+1) {
+ errno = olderrno;
+ return(NULL);
+ }
+
+ *string = (char)letter++;
+ }
+
+ errno = olderrno;
+ return(template);
+}
diff --git a/private/crt32/lowio/open.c b/private/crt32/lowio/open.c
new file mode 100644
index 000000000..a365f4aac
--- /dev/null
+++ b/private/crt32/lowio/open.c
@@ -0,0 +1,590 @@
+/***
+*open.c - file open
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _open() and _sopen() - open or create a file
+*
+*Revision History:
+* 06-13-89 PHG Module created, based on asm version
+* 11-11-89 JCR Replaced DOS32QUERYFILEMODE with DOS32QUERYPATHINFO
+* 03-13-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h>, fixed some compiler warnings and fixed
+* copyright. Also, cleaned up the formatting a bit.
+* 07-24-90 SBM Removed '32' from API names
+* 08-14-90 SBM Compiles cleanly with -W3
+* 09-07-90 SBM Added stdarg code (inside #if 0..#endif) to make
+* open and sopen match prototypes. Test and use this
+* someday.
+* 10-01-90 GJF New-style function declarators.
+* 11-16-90 GJF Wrote version for Win32 API and appended it via an
+* #ifdef. The Win32 version is similar to the old DOS
+* version (though in C) and far different from either
+* the Cruiser or OS/2 versions.
+* 12-03-90 GJF Fixed a dozen or so minor errors in the Win32 version.
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 12-31-90 SRW Fixed spen to call CreateFile instead of OpenFile
+* 01-16-91 GJF ANSI naming.
+* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
+* 02-19-91 SRW Adapt to OpenFile/CreateFile changes [_WIN32_]
+* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_]
+* 04-09-91 PNT Added _MAC_ conditional
+* 07-10-91 GJF Store fileflags into _osfile array before call to
+* _lseek_lk (bug found by LarryO) [_WIN32_].
+* 01-02-92 GJF Fixed Win32 version (not Cruiser!) so that pmode is not
+* referenced unless _O_CREAT has been specified.
+* 02-04-92 GJF Make better use of CreateFile options.
+* 04-06-92 SRW Pay attention to _O_NOINHERIT flag in oflag parameter
+* 05-02-92 SRW Add support for _O_TEMPORARY flag in oflag parameter.
+* Causes FILE_ATTRIBUTE_TEMPORARY flag to be set in call
+* to the Win32 CreateFile API.
+* 07-01-92 GJF Close handle in case of error. Also, don't try to set
+* FRDONLY bit anymore - no longer needed/used. [_WIN32_].
+* 01-03-93 SRW Fix va_arg/va_end usage
+* 05-24-93 PML Add support for _O_SEQUENTIAL, _O_RANDOM,
+* and _O_SHORT_LIVED
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <msdos.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <internal.h>
+#include <io.h>
+#include <share.h>
+#include <stdlib.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <os2dll.h>
+#include <stdarg.h>
+
+/***
+*int _open(path, flag, pmode) - open or create a file
+*
+*Purpose:
+* Opens the file and prepares for subsequent reading or writing.
+* the flag argument specifies how to open the file:
+* _O_APPEND - reposition file ptr to end before every write
+* _O_BINARY - open in binary mode
+* _O_CREAT - create a new file* no effect if file already exists
+* _O_EXCL - return error if file exists, only use with O_CREAT
+* _O_RDONLY - open for reading only
+* _O_RDWR - open for reading and writing
+* _O_TEXT - open in text mode
+* _O_TRUNC - open and truncate to 0 length (must have write permission)
+* _O_WRONLY - open for writing only
+* _O_NOINHERIT -handle will not be inherited by child processes.
+* exactly one of _O_RDONLY, _O_WRONLY, _O_RDWR must be given
+*
+* The pmode argument is only required when _O_CREAT is specified. Its
+* flag settings:
+* _S_IWRITE - writing permitted
+* _S_IREAD - reading permitted
+* _S_IREAD | _S_IWRITE - both reading and writing permitted
+* The current file-permission maks is applied to pmode before
+* setting the permission (see umask).
+*
+* The oflag and mode parameter have different meanings under DOS. See
+* the A_xxx attributes in msdos.inc
+*
+* Note, the _creat() function also uses this function but setting up the
+* correct arguments and calling _open(). _creat() sets the __creat_flag
+* to 1 prior to calling _open() so _open() can return correctly. _open()
+* returns the file handle in eax in this case.
+*
+*Entry:
+* char *path - file name
+* int flag - flags for _open()
+* int pmode - permission mode for new files
+*
+*Exit:
+* returns file handle of open file if successful
+* returns -1 (and sets errno) if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI2 _open (
+ const char *path,
+ int oflag,
+ ...
+ )
+{
+ va_list ap;
+ int pmode;
+
+ va_start(ap, oflag);
+ pmode = va_arg(ap, int);
+ va_end(ap);
+
+ /* default sharing mode is DENY NONE */
+ return _sopen(path, oflag, _SH_DENYNO, pmode);
+}
+
+/***
+*int _sopen(path, oflag, shflag, pmode) - opne a file with sharing
+*
+*Purpose:
+* Opens the file with possible file sharing.
+* shflag defines the sharing flags:
+* _SH_COMPAT - set compatability mode
+* _SH_DENYRW - deny read and write access to the file
+* _SH_DENYWR - deny write access to the file
+* _SH_DENYRD - deny read access to the file
+* _SH_DENYNO - permit read and write access
+*
+* Other flags are the same as _open().
+*
+* SOPEN is the routine used when file sharing is desired.
+*
+*Entry:
+* char *path - file to open
+* int oflag - open flag
+* int shflag - sharing flag
+* int pmode - permission mode (needed only when creating file)
+*
+*Exit:
+* returns file handle for the opened file
+* returns -1 and sets errno if fails.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI2 _sopen (
+ const char *path,
+ int oflag,
+ int shflag,
+ ...
+ )
+{
+
+ int fh; /* handle of opened file */
+ int filepos; /* length of file - 1 */
+ char ch; /* character at end of file */
+ char fileflags; /* _osfile flags */
+ va_list ap; /* variable argument (pmode) */
+ int pmode;
+
+#ifdef _CRUISER_
+ int t; /* temp */
+ int dosretval; /* OS/2 return value */
+ int isdev; /* device indicator in low byte */
+ int attrib; /* attribute */
+ int openflag; /* OS/2 open flag */
+ int openmode; /* OS/2 open mode */
+#endif /* _CRUISER_ */
+
+#ifdef _WIN32_
+ HANDLE osfh; /* OS handle of opened file */
+ DWORD fileaccess; /* OS file access (requested) */
+ DWORD fileshare; /* OS file sharing mode */
+ DWORD filecreate; /* OS method of opening/creating */
+ DWORD fileattrib; /* OS file attribute flags */
+ DWORD isdev; /* device indicator in low byte */
+ SECURITY_ATTRIBUTES SecurityAttributes;
+
+ SecurityAttributes.nLength = sizeof( SecurityAttributes );
+ SecurityAttributes.lpSecurityDescriptor = NULL;
+ if (oflag & _O_NOINHERIT) {
+ SecurityAttributes.bInheritHandle = FALSE;
+ }
+ else {
+ SecurityAttributes.bInheritHandle = TRUE;
+ }
+
+#endif /* _WIN32_ */
+#ifdef _CRUISER_
+/* Set up variable argument list stuff */
+
+ va_start(ap, shflag);
+ pmode = va_arg(ap, int);
+ va_end(ap);
+#endif
+
+ /* figure out binary/text mode */
+ if (oflag & _O_BINARY)
+ fileflags = 0;
+ else if (oflag & _O_TEXT)
+ fileflags = (char)FTEXT;
+ else if (_fmode == _O_BINARY) /* check default mode */
+ fileflags = 0;
+ else
+ fileflags = (char)FTEXT;
+
+#ifdef _CRUISER_ /* CRUISER TARGET */
+
+/* code requires below conditions */
+#if _O_RDONLY != OPEN_ACCESS_READONLY || _O_WRONLY != OPEN_ACCESS_WRITEONLY || _O_RDWR != OPEN_ACCESS_READWRITE
+ #error OS/2 and XENIX flags not compatible
+#endif
+#if _O_RDWR != 2 || _O_RDONLY != 0 || _O_WRONLY != 1
+ #error access flags are wrong
+#endif
+
+/*
+ Set up the OpenMode and OpenFlag parameters for the DOSOPEN call
+
+ OpenMode fields will be set as follows:
+ high byte
+ DASD 0 (normal file)
+ File Write-through 0 (use buffer cache)
+ Fail-Errors 0 (use hard error handler)
+ low byte
+ Inheritance 0 (child inherits files)
+ Sharing Mode <from shflag param>
+ Access Mode <from oflag parameter>
+
+ OpenFlag bytes are set as follows:
+ high byte
+ 0x00
+ low byte - low nibble
+ 0x0 _O_EXCL specified
+ 0x2 _O_TRUNC specified
+ 0x1 otherwise
+ low byte - high nibble
+ 0x1 _O_CREAT specified
+ 0x0 otherwise
+*/
+
+
+ /* first, convert the permission mode to the DOS attribute byte */
+ if ((pmode & ~_umaskval) & _S_IWRITE)
+ attrib = 0; /* writable */
+ else
+ attrib = FILE_READONLY; /* read-only */
+
+ if ((oflag & _O_EXCL) && !(oflag & _O_CREAT))
+ oflag &= ~_O_EXCL; /* _O_EXCL only works with _O_CREAT */
+
+ if (oflag & _O_EXCL) {
+ openflag = 0; /* just create */
+ }
+ else if (oflag & _O_TRUNC) {
+ FILESTATUS fs; /* File Status structure */
+
+ openflag = FILE_TRUNCATE; /* truncate file */
+
+ /* if the file exists, don't change its attribute */
+ if (!DOSQUERYPATHINFO((char *)path, 1, &fs, sizeof(fs)))
+ /* file exists, use current attribute */
+ attrib = fs.attrFile;
+ }
+ else
+ openflag = FILE_OPEN; /* open the file */
+
+ if (oflag & _O_CREAT)
+ openflag |= FILE_CREATE;
+
+ /* here we take advantage of the fact that OS/2 and XENIX access flags
+ are the same bits -- the bottom two */
+ openmode = shflag | (oflag & 3);
+
+ /* OK, we're now ready to open the file */
+ if (dosretval = DOSOPEN((char *)path, &fh, &t, 0, attrib, openflag,
+ openmode, 0, 0)) {
+ /* OS/2 error occured */
+ if (dosretval == ERROR_OPEN_FAILED) {
+ _doserrno = dosretval;
+ if (openflag & FILE_CREATE)
+ errno = EEXIST; /* file existed */
+ else
+ errno = ENOENT; /* file didn't exist */
+ return -1;
+ }
+ else {
+ _dosmaperr(dosretval); /* map error */
+ return -1;
+ }
+ }
+
+ if ((unsigned)fh >= (unsigned)_nfile) {
+ /* handle is out of range; close and return EMFILE */
+ DOSCLOSE(fh);
+ errno = EMFILE;
+ _doserrno = 0; /* not OS/2 error */
+ return -1;
+ }
+
+ _lock_fh(fh); /* lock the file handle */
+
+ /* find out what type of file (file/device/pipe) */
+ if (dosretval = DOSQUERYHTYPE(fh, &isdev, &t)) {
+ /* OS/2 error */
+ _unlock_fh(fh);
+ _dosmaperr(dosretval); /* map error */
+ return -1;
+ }
+
+ /* is isdev value to set flags */
+ if ((isdev & 0xFF) == HANDTYPE_DEVICE)
+ fileflags |= FDEV;
+ else if ((isdev & 0xFF) == HANDTYPE_PIPE)
+ fileflags |= FPIPE;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /*
+ * decode the access flags
+ */
+ switch( oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR) ) {
+
+ case _O_RDONLY: /* read access */
+ fileaccess = GENERIC_READ;
+ break;
+ case _O_WRONLY: /* write access */
+ fileaccess = GENERIC_WRITE;
+ break;
+ case _O_RDWR: /* read and write access */
+ fileaccess = GENERIC_READ | GENERIC_WRITE;
+ break;
+ default: /* error, bad oflag */
+ errno = EINVAL;
+ _doserrno = 0L; /* not an OS error */
+ return -1;
+ }
+
+ /*
+ * decode sharing flags
+ */
+ switch ( shflag ) {
+
+ case _SH_DENYRW: /* exclusive access */
+ fileshare = 0L;
+ break;
+
+ case _SH_DENYWR: /* share read access */
+ fileshare = FILE_SHARE_READ;
+ break;
+
+ case _SH_DENYRD: /* share write access */
+ fileshare = FILE_SHARE_WRITE;
+ break;
+
+ case _SH_DENYNO: /* share read and write access */
+ fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ break;
+
+ default: /* error, bad shflag */
+ errno = EINVAL;
+ _doserrno = 0L; /* not an OS error */
+ return -1;
+ }
+
+ /*
+ * decode open/create method flags
+ */
+ switch ( oflag & (_O_CREAT | _O_EXCL | _O_TRUNC) ) {
+ case 0:
+ filecreate = OPEN_EXISTING;
+ break;
+
+ case _O_CREAT:
+ filecreate = OPEN_ALWAYS;
+ break;
+
+ case _O_CREAT | _O_EXCL:
+ filecreate = CREATE_NEW;
+ break;
+
+ case _O_TRUNC:
+ filecreate = TRUNCATE_EXISTING;
+ break;
+
+ case _O_CREAT | _O_TRUNC:
+ filecreate = CREATE_ALWAYS;
+ break;
+
+ default:
+ errno = EINVAL;
+ _doserrno = 0L;
+ return -1;
+ }
+
+ /*
+ * decode file attribute flags if _O_CREAT was specified
+ */
+ fileattrib = FILE_ATTRIBUTE_NORMAL; /* default */
+
+ if ( oflag & _O_CREAT ) {
+ /*
+ * set up variable argument list stuff
+ */
+ va_start(ap, shflag);
+ pmode = va_arg(ap, int);
+ va_end(ap);
+
+ if ( !((pmode & ~_umaskval) & _S_IWRITE) )
+ fileattrib = FILE_ATTRIBUTE_READONLY;
+ }
+
+ /*
+ * Set temporary file (delete-on-close) attribute if requested.
+ */
+ if ( oflag & _O_TEMPORARY ) {
+ fileattrib |= FILE_FLAG_DELETE_ON_CLOSE;
+ fileaccess |= DELETE;
+ }
+
+ /*
+ * Set temporary file (delay-flush-to-disk) attribute if requested.
+ */
+ if ( oflag & _O_SHORT_LIVED )
+ fileattrib |= FILE_ATTRIBUTE_TEMPORARY;
+
+ /*
+ * Set sequential or random access attribute if requested.
+ */
+ if ( oflag & _O_SEQUENTIAL )
+ fileattrib |= FILE_FLAG_SEQUENTIAL_SCAN;
+ else if ( oflag & _O_RANDOM )
+ fileattrib |= FILE_FLAG_RANDOM_ACCESS;
+
+ /*
+ * get an available handle.
+ *
+ * multi-thread note: the returned handle is locked!
+ */
+ if ( (fh = _alloc_osfhnd()) == -1 ) {
+ errno = EMFILE; /* too many open files */
+ _doserrno = 0L; /* not an OS error */
+ return -1; /* return error to caller */
+ }
+
+ /*
+ * try to open/create the file
+ */
+ if ( (osfh = CreateFile((LPSTR)path,
+ fileaccess,
+ fileshare,
+ &SecurityAttributes,
+ filecreate,
+ fileattrib,
+ NULL
+ ))
+ == (HANDLE)0xffffffff ) {
+ /*
+ * OS call to open/create file failed! map the error, release
+ * the lock, and return -1. note that it's not necessary to
+ * call _free_osfhnd (it hasn't been used yet).
+ */
+ _dosmaperr(GetLastError()); /* map error */
+ _unlock_fh(fh);
+ return -1; /* return error to caller */
+ }
+
+ /* find out what type of file (file/device/pipe) */
+ if ( (isdev = GetFileType(osfh)) == FILE_TYPE_UNKNOWN ) {
+ CloseHandle(osfh);
+ _dosmaperr(GetLastError()); /* map error */
+ _unlock_fh(fh);
+ return -1;
+ }
+
+ /* is isdev value to set flags */
+ if (isdev == FILE_TYPE_CHAR)
+ fileflags |= FDEV;
+ else if (isdev == FILE_TYPE_PIPE)
+ fileflags |= FPIPE;
+
+ /*
+ * the file is open. now, set the info in _osfhnd array
+ */
+ _set_osfhnd(fh, (long)osfh);
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /*
+ * mark the handle as open. store flags gathered so far in _osfile
+ * array.
+ */
+ fileflags |= FOPEN;
+ _osfile[fh] = fileflags;
+
+ if (!(fileflags & (FDEV|FPIPE)) && (fileflags & FTEXT) &&
+ (oflag & _O_RDWR)) {
+ /* We have a text mode file. If it ends in CTRL-Z, we wish to
+ remove the CTRL-Z character, so that appending will work.
+ We do this by seeking to the end of file, reading the last
+ byte, and shortening the file if it is a CTRL-Z. */
+
+ if ((filepos = _lseek_lk(fh, -1, FILE_END)) == -1) {
+ /* OS error -- should ignore negative seek error,
+ since that means we had a zero-length file. */
+ if (_doserrno != ERROR_NEGATIVE_SEEK) {
+ _close(fh);
+ _unlock_fh(fh);
+ return -1;
+ }
+ }
+ else {
+ /* seek was OK, read the last char in file */
+ if (_read_lk(fh, &ch, 1) == 1 && ch == 26) {
+ /* read was OK and we got CTRL-Z! Wipe it
+ out! */
+ if (_chsize_lk(fh,filepos) == -1)
+ {
+ _close(fh);
+ _unlock_fh(fh);
+ return -1;
+ }
+ }
+
+ /* now rewind the file to the beginning */
+ if ((filepos = _lseek_lk(fh, 0, FILE_BEGIN)) == -1) {
+ _close(fh);
+ _unlock_fh(fh);
+ return -1;
+ }
+ }
+ }
+
+#ifdef _CRUISER_
+ /* We want to know if we have write access to set the FRDONLY flag
+ in the _osfile entry. We also set the FAPPEND flag.
+ Don't do this for pipes or devices. */
+
+ if (!(fileflags & (FDEV|FPIPE))) {
+ if (_access((char *)path, 2) == -1)
+ _osfile[fh] |= FRDONLY;
+
+ if (oflag & _O_APPEND)
+ _osfile[fh] |= FAPPEND;
+ }
+#else /* ndef _CRUISER_ */
+#ifdef _WIN32_
+
+ /*
+ * Set FAPPEND flag if appropriate. Don't do this for devices or pipes.
+ */
+ if ( !(fileflags & (FDEV|FPIPE)) && (oflag & _O_APPEND) )
+ _osfile[fh] |= FAPPEND;
+
+#endif /* _WIN32_ */
+#endif /* _CRUISER_*/
+
+ _unlock_fh(fh); /* unlock handle */
+
+ return fh; /* return handle */
+}
diff --git a/private/crt32/lowio/osfinfo.c b/private/crt32/lowio/osfinfo.c
new file mode 100644
index 000000000..8ccff39c4
--- /dev/null
+++ b/private/crt32/lowio/osfinfo.c
@@ -0,0 +1,319 @@
+/***
+*osfinfo.c - Win32 _osfhnd[] support routines
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the internally used routine _alloc_osfhnd()
+* and the user visible routine _get_osfhandle().
+*
+*Revision History:
+* 11-16-90 GJF What can I say? The custom heap business was getting
+* a little slow...
+* 12-03-90 GJF Fixed my stupid syntax errors.
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 02-18-91 SRW Fixed bug in _alloc_osfhnd with setting FOPEN bit
+* (only caller should do that) [_WIN32_]
+* 02-18-91 SRW Fixed bug in _alloc_osfhnd with checking against
+* _NFILE_ instead of _nfile [_WIN32_]
+* 02-18-91 SRW Added debug output to _alloc_osfhnd if out of
+* file handles. [_WIN32_]
+* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_]
+* 02-25-91 SRW Exposed _get_osfhandle and _open_osfhandle [_WIN32_]
+* 08-08-91 GJF Use ANSI-fied form of constant names.
+* 11-25-91 GJF Lock fh before checking whether it's free.
+* 12-31-91 GJF Improved multi-thread lock usage [_WIN32_].
+* 02-13-92 GJF Replaced _nfile with _nhandle
+* 07-15-92 GJF Fixed setting of flags in _open_osfhnd.
+* 02-19-93 GJF If GetFileType fails in _open_osfhandle, don't unlock
+* fh (it wasn't locked)!
+*
+*******************************************************************************/
+
+#ifdef _WIN32_
+
+#include <cruntime.h>
+#include <errno.h>
+#include <internal.h>
+#include <fcntl.h>
+#include <msdos.h>
+#include <os2dll.h>
+#include <stdlib.h>
+#include <oscalls.h>
+
+/***
+*int _alloc_osfhnd() - get free _osfhnd[] entry
+*
+*Purpose:
+* Finds the first free entry in _osfhnd[], mark it in use and return
+* the index of the entry to the caller.
+*
+*Entry:
+* none
+*
+*Exit:
+* returns index of entry in fh, if successful
+* return -1, if no free entry is found in _osfhnd[].
+*
+* MULTITHREAD NOTE: IF SUCCESSFUL, THE HANDLE IS LOCKED WHEN IT IS
+* RETURNED TO THE CALLER!
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _alloc_osfhnd(
+ void
+ )
+{
+ int fh; /* _osfhnd[] index */
+
+ _mlock(_OSFHND_LOCK); /* lock the _osfhnd[] table */
+
+ /*
+ * search _osfhnd[] for an entry that is not currently being used.
+ * if one is found, mark it in use and set the _osfhandle field to
+ * INVALID_HANDLE_VALUE.
+ */
+ for ( fh = 0 ; fh < _nhandle ; fh++ ) {
+ if ( (_osfile[fh] & FOPEN) == 0 ) {
+#ifdef MTHREAD
+ _lock_fh(fh);
+
+ /*
+ * make sure the entry is still free
+ */
+ if ( (_osfile[fh] & FOPEN) != 0 ) {
+ /*
+ * entry now in use! release the lock and
+ * continue looping.
+ */
+ _unlock_fh(fh);
+ continue;
+ }
+#endif
+
+ /*
+ * free entry found! initialize it and
+ * break out of the loop
+ */
+ _osfhnd[fh] = (long)INVALID_HANDLE_VALUE;
+ break;
+ }
+ }
+
+ _munlock(_OSFHND_LOCK); /* unlock the _osfhnd[] table */
+
+#if defined(DEBUG) && defined(_WIN32_)
+ if (fh >= _nhandle) {
+ DbgPrint( "WINCRT: more than %d open files\n", _nhandle );
+ }
+#endif
+
+ /*
+ * return the index of the previously free table entry, if one was
+ * found. return -1 otherwise.
+ */
+ return( (fh >= _nhandle) ? -1 : fh );
+}
+
+
+/***
+*int _set_osfhnd(int fh) - set OS file handle table value
+*
+*Purpose:
+* If fh is in range and if _osfhnd[fh] is marked with
+* INVALID_HANDLE_VALUE then set _osfhnd[fh] to the passed value.
+*
+*Entry:
+* int fh - index of _osfhnd[] entry
+* long fh - new value of this handle entry
+*
+*Exit:
+* Returns zero if successful.
+* Returns -1 and sets errno to EBADF otherwise.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _set_osfhnd (
+ int fh, /* index into _osfhnd[] (user's file handle) */
+ long value
+ )
+{
+ if ( ((unsigned)fh < (unsigned)_nhandle) &&
+ (_osfhnd[fh] == (long)INVALID_HANDLE_VALUE)
+ ) {
+ switch (fh) {
+ case 0: SetStdHandle( STD_INPUT_HANDLE, (HANDLE)value ); break;
+ case 1: SetStdHandle( STD_OUTPUT_HANDLE, (HANDLE)value ); break;
+ case 2: SetStdHandle( STD_ERROR_HANDLE, (HANDLE)value ); break;
+ }
+
+ _osfhnd[fh] = value;
+ return(0);
+ } else {
+ errno = EBADF; /* bad handle */
+ _doserrno = 0L; /* not an OS error */
+ return -1;
+ }
+}
+
+
+/***
+*int _free_osfhnd(int fh) - free OS file handle table entry
+*
+*Purpose:
+* If fh is in range and if _osfhnd[fh] is in use and NOT marked
+* with 0xfffffff
+*
+*Entry:
+* int fh - index of _osfhnd[] entry
+*
+*Exit:
+* Returns zero if successful.
+* Returns -1 and sets errno to EBADF otherwise.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _free_osfhnd (
+ int fh /* index into _osfhnd[] (user's file handle) */
+ )
+{
+ if ( ((unsigned)fh < (unsigned)_nhandle) &&
+ (_osfile[fh] & FOPEN) &&
+ (_osfhnd[fh] != (long)INVALID_HANDLE_VALUE)
+ ) {
+ switch (fh) {
+ case 0: SetStdHandle( STD_INPUT_HANDLE, NULL ); break;
+ case 1: SetStdHandle( STD_OUTPUT_HANDLE, NULL ); break;
+ case 2: SetStdHandle( STD_ERROR_HANDLE, NULL ); break;
+ }
+
+ _osfhnd[fh] = (long)INVALID_HANDLE_VALUE;
+ return(0);
+ } else {
+ errno = EBADF; /* bad handle */
+ _doserrno = 0L; /* not an OS error */
+ return -1;
+ }
+}
+
+
+/***
+*long _get_osfhandle(int fh) - get OS file handle
+*
+*Purpose:
+* If fh is in range and if _osfhnd[fh] is marked free, return
+* _osfhnd[fh]
+*
+*Entry:
+* int fh - index of _osfhnd[] entry
+*
+*Exit:
+* Returns the OS file handle if successful.
+* Returns -1 and sets errno to EBADF otherwise.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+long _CRTAPI1 _get_osfhandle (
+ int fh /* index into _osfhnd[] (user's file handle) */
+ )
+{
+ if ( ((unsigned)fh < (unsigned)_nhandle) && (_osfile[fh] & FOPEN) )
+ return(_osfhnd[fh]);
+ else {
+ errno = EBADF; /* bad handle */
+ _doserrno = 0L; /* not an OS error */
+ return -1;
+ }
+}
+
+/***
+*int _open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
+*
+*Purpose:
+* This function allocates a free C Runtime file handle and sets it
+* to point to the Win32 file handle specified by the first parameter.
+*
+*Entry:
+* long osfhandle -Win32 file handle to associate with C Runtime file handle.
+* int flags - flags to associate with C Runtime file handle.
+*
+*Exit:
+* returns index of entry in fh, if successful
+* return -1, if no free entry is found in _osfhnd[].
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _open_osfhandle(
+ long osfhandle,
+ int flags
+ )
+{
+ int fh;
+ char fileflags; /* _osfile flags */
+ DWORD isdev; /* device indicator in low byte */
+
+ /* copy relevant flags from second parameter */
+
+ fileflags = 0;
+
+ if ( flags & _O_APPEND )
+ fileflags |= FAPPEND;
+
+ if ( flags & _O_TEXT )
+ fileflags |= FTEXT;
+
+ /* find out what type of file (file/device/pipe) */
+
+ isdev = GetFileType((HANDLE)osfhandle);
+ if (isdev == FILE_TYPE_UNKNOWN) {
+ /* OS error */
+ _dosmaperr( GetLastError() ); /* map error */
+ return -1;
+ }
+
+ /* is isdev value to set flags */
+ if (isdev == FILE_TYPE_CHAR)
+ fileflags |= FDEV;
+ else if (isdev == FILE_TYPE_PIPE)
+ fileflags |= FPIPE;
+
+
+ /* attempt to allocate a C Runtime file handle */
+
+ if ( (fh = _alloc_osfhnd()) == -1 ) {
+ errno = EMFILE; /* too many open files */
+ _doserrno = 0L; /* not an OS error */
+ return -1; /* return error to caller */
+ }
+
+ /*
+ * the file is open. now, set the info in _osfhnd array
+ */
+
+ _set_osfhnd(fh, osfhandle);
+
+ fileflags |= FOPEN; /* mark as open */
+
+ _osfile[fh] = fileflags; /* set osfile entry */
+
+ _unlock_fh(fh); /* unlock handle */
+
+ return fh; /* return handle */
+}
+
+#else
+
+#error ERROR - WIN32 TARGET ONLY!
+
+#endif
diff --git a/private/crt32/lowio/pipe.c b/private/crt32/lowio/pipe.c
new file mode 100644
index 000000000..a414d1c40
--- /dev/null
+++ b/private/crt32/lowio/pipe.c
@@ -0,0 +1,180 @@
+/***
+*pipe.c - create a pipe
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _pipe() - creates a pipe (i.e., an I/O channel for interprocess
+* communication)
+*
+*Revision History:
+* 06-20-89 PHG Module created, based on asm version
+* 03-13-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed copyright. Also, cleaned up the
+* formatting a bit.
+* 04-03-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-01-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-18-91 GJF ANSI naming.
+* 02-18-91 SRW Added _WIN32_ implementation [_WIN32_]
+* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_]
+* 03-13-91 SRW Fixed _pipe so it works [_WIN32_]
+* 03-18-91 SRW Fixed _pipe NtCreatePipe handles are inherited [_WIN32_]
+* 04-06-92 SRW Pay attention to _O_NOINHERIT flag in oflag parameter
+* 01-10-93 GJF Fixed bug in checking for _O_BINARY (inadvertently
+* introduced by SRW's change above).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <os2dll.h>
+#include <io.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <msdos.h>
+#include <fcntl.h>
+
+/***
+*int _pipe(phandles, psize, textmode) - open a pipe
+*
+*Purpose:
+* Checks if the given handle is associated with a character device
+* (terminal, console, printer, serial port)
+*
+* Multi-thread notes: No locking is performed or deemed necessary. The
+* handles returned by DOSCREATEPIPE are newly opened and, therefore,
+* should not be referenced by any thread until after the _pipe call is
+* complete. The function is not protected from some thread of the caller
+* doing, say, output to a previously invalid handle that becomes one of
+* the pipe handles. However, any such program is doomed anyway and
+* protecting the _pipe function such a case would be of little value.
+*
+*Entry:
+* int phandle[2] - array to hold returned read (phandle[0]) and write
+* (phandle[1]) handles
+*
+* unsigned psize - amount of memory, in bytes, to ask OS/2 to reserve
+* for the pipe
+*
+* int textmode - _O_TEXT, _O_BINARY, _O_NOINHERIT, or 0 (use default)
+*
+*Exit:
+* returns 0 if successful
+* returns -1 if an error occurs in which case, errno is set to:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _pipe (
+ int phandles[2],
+ unsigned psize,
+ int textmode
+ )
+{
+ ULONG dosretval; /* OS/2 return value */
+
+#ifdef _CRUISER_
+
+ if (dosretval = DOSCREATEPIPE(&phandles[0], &phandles[1], psize)) {
+ /* OS/2 error */
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ if ((unsigned)phandles[0] >= (unsigned)_nfile ||
+ (unsigned)phandles[1] >= (unsigned)_nfile)
+ {
+ /* one or both of the handles are too large -- close both */
+ DOSCLOSE(phandles[0]);
+ DOSCLOSE(phandles[1]);
+ errno = EMFILE; /* too many files */
+ _doserrno = 0; /* not an OS/2 error */
+ return -1;
+ }
+
+ /* now we must set the _osfile values */
+ if (textmode == _O_BINARY || (textmode == 0 && _fmode == _O_BINARY)) {
+ /* binary mode */
+ _osfile[phandles[0]] = _osfile[phandles[1]] = FOPEN | FPIPE;
+ }
+ else {
+ /* text mode */
+ _osfile[phandles[0]] = _osfile[phandles[1]] = FOPEN | FPIPE |
+ FTEXT;
+ }
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ HANDLE ReadHandle, WriteHandle;
+ SECURITY_ATTRIBUTES SecurityAttributes;
+
+ SecurityAttributes.nLength = sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor = NULL;
+ if (textmode & _O_NOINHERIT) {
+ SecurityAttributes.bInheritHandle = FALSE;
+ }
+ else {
+ SecurityAttributes.bInheritHandle = TRUE;
+ }
+ if (!CreatePipe(&ReadHandle, &WriteHandle, &SecurityAttributes, psize)) {
+ /* OS/2 error */
+ dosretval = GetLastError();
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+ /* now we must allocate C Runtime handles for Read and Write handles */
+ if ((phandles[0] = _alloc_osfhnd()) != -1) {
+ _osfile[phandles[0]] = (char)(FOPEN | FPIPE | FTEXT);
+ if ((phandles[1] = _alloc_osfhnd()) != -1) {
+ _osfile[phandles[1]] = (char)(FOPEN | FPIPE | FTEXT);
+ if ( (textmode & _O_BINARY) ||
+ ((textmode & _O_TEXT == 0) &&
+ (_fmode == _O_BINARY)) ) {
+ /* binary mode */
+ _osfile[phandles[0]] &= ~FTEXT;
+ _osfile[phandles[1]] &= ~FTEXT;
+ }
+
+ _set_osfhnd(phandles[0], (long)ReadHandle);
+ _set_osfhnd(phandles[1], (long)WriteHandle);
+ errno = 0;
+
+ _unlock_fh(phandles[1]); /* unlock handle */
+ }
+ else {
+ _osfile[phandles[0]] = 0;
+ errno = EMFILE; /* too many files */
+ }
+
+ _unlock_fh(phandles[0]); /* unlock handle */
+ }
+ else {
+ errno = EMFILE; /* too many files */
+ }
+
+ /* If error occurred, close Win32 handles and return -1 */
+ if (errno != 0) {
+ CloseHandle(ReadHandle);
+ CloseHandle(WriteHandle);
+ _doserrno = 0; /* not an OS/2 error */
+ return -1;
+ }
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ return 0;
+}
diff --git a/private/crt32/lowio/ppc/cinitcon.s b/private/crt32/lowio/ppc/cinitcon.s
new file mode 100644
index 000000000..5e5b71e6b
--- /dev/null
+++ b/private/crt32/lowio/ppc/cinitcon.s
@@ -0,0 +1,53 @@
+// page ,132
+// title cinitcon - C Run-Time Startup Initialization for Console I/O
+//
+//cinitcon.asm - C Run-Time Startup Initialization for WIN32
+//
+// Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+//
+//Purpose:
+// Initialization and Termination for console I/O
+//
+//Notes:
+// _confh and _coninpfh are defined in this module to force the
+// inclusion of this module if any console I/O is performed.
+// This module places the address of _initcon() in the initializer
+// table and the address of _termcon() in the pre-terminator table.
+//
+//Revision History:
+// 03-19-92 SKS Module created.
+// 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+// 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+// 08-06-92 SKS Revised to use new section names and macros
+//
+// ****************************************************************************
+
+#include "kxppc.h"
+
+ .extern _initcon
+ .extern _termcon
+
+
+beginSection(XIC)
+
+ .long _initcon
+
+endSection(XIC)
+
+
+beginSection(XPX)
+
+ .long _termcon
+
+endSection(XPX)
+
+
+ .data
+ .align 2
+
+ .globl _coninpfh
+ .globl _confh
+
+_coninpfh: .long -1 // console input
+_confh: .long -1 // console output
+
diff --git a/private/crt32/lowio/putch.c b/private/crt32/lowio/putch.c
new file mode 100644
index 000000000..addd0c6b2
--- /dev/null
+++ b/private/crt32/lowio/putch.c
@@ -0,0 +1,129 @@
+/***
+*putch.c - contains the _putch() routine for OS/2 Protected Mode
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved
+*
+*Purpose:
+* The routine "_putch()" writes a single character to the console.
+*
+* NOTE: In real-mode DOS the character is actually written to standard
+* output, and is therefore redirected when standard output is redirected.
+* However, in Protected-Mode OS/2 the character is ALWAYS written
+* to the console, even when standard output has been redirected.
+*
+*Revision History:
+* 06-08-89 PHG Module created, based on asm version
+* 03-13-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed copyright. Also, cleaned up
+* the formatting a bit.
+* 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits
+* 07-24-90 SBM Removed '32' from API names
+* 10-01-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-16-91 GJF ANSI naming.
+* 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_)
+* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
+* 07-26-91 GJF Took out init. stuff and cleaned up the error
+* handling [_WIN32_].
+* 03-20-93 GJF Use WriteConsole instead of WriteFile.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <conio.h>
+#include <os2dll.h>
+#include <stdio.h>
+
+/*
+ * declaration for console handle
+ */
+extern int _confh;
+
+/***
+*int _putch(c) - write a character to the console
+*
+*Purpose:
+* Calls DOSWRITE to output the character
+* Note: in OS/2 protect mode always writes to console even
+* when stdout redirected
+*
+*Entry:
+* c - Character to be output
+*
+*Exit:
+* If an error is returned from DOSWRITE
+* Then returns EOF
+* Otherwise
+* returns character that was output
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+/* normal version lock and unlock the console, and then call the _lk version
+ which directly accesses the console without locking. */
+
+int _CRTAPI1 _putch (
+ int c
+ )
+{
+ int ch;
+
+ _mlock(_CONIO_LOCK); /* secure the console lock */
+ ch = _putch_lk(c); /* output the character */
+ _munlock(_CONIO_LOCK); /* release the console lock */
+
+ return ch;
+}
+#endif /* MTHREAD */
+
+/* define version which accesses the console directly - normal version in
+ non-MTHREAD situations, special _lk version in MTHREAD */
+
+#ifdef MTHREAD
+int _CRTAPI1 _putch_lk (
+#else
+int _CRTAPI1 _putch (
+#endif
+ int c
+ )
+{
+ /* can't use ch directly unless sure we have a big-endian machine */
+ unsigned char ch = (unsigned char)c;
+ ULONG num_written;
+
+ /* write character to console file handle */
+
+#ifdef _CRUISER_
+
+ if (DOSWRITE(_confh, &ch, 1L, &num_written)) {
+ /* OS/2 error, return error indicator */
+ return EOF;
+ }
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if ( (_confh == -1) || !WriteConsole( (HANDLE)_confh,
+ (LPVOID)&ch,
+ 1,
+ &num_written,
+ NULL )
+ )
+ /* return error indicator */
+ return EOF;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ return ch;
+}
diff --git a/private/crt32/lowio/read.c b/private/crt32/lowio/read.c
new file mode 100644
index 000000000..d11805761
--- /dev/null
+++ b/private/crt32/lowio/read.c
@@ -0,0 +1,349 @@
+/***
+*read.c - OS/2 read from a file handle
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _read() - read from a file handle
+*
+*Revision History:
+* 06-19-89 PHG Module created, based on asm version
+* 03-13-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h> and fixed compiler warnings. Also, fixed
+* the copyright.
+* 04-03-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-01-90 GJF New-style function declarator.
+* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s.
+* It is enough different that there is little point in
+* trying to more closely merge the two versions.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 01-16-91 GJF ANSI naming.
+* 01-29-91 SRW Changed to not read ahead on char devices [_WIN32_]
+* 02-01-91 SRW Changed to use ERROR_HANDLE_EOF error code (_WIN32_)
+* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
+* 04-09-91 PNT Added _MAC_ conditional
+* 04-16-91 SRW Character device bug fix [_WIN32_]
+* 05-23-91 GJF Don't set FEOFLAG if handle corresponds to a device.
+* 10-24-91 GJF Added LPDWORD casts to make MIPS compiler happy.
+* ASSUMES THAT sizeof(int) == sizeof(DWORD).
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+* 06-16-92 GJF Bug fix - if CR was the very last char read, and the
+* last char in the file, CRLF was getting written to
+* user's buffer.
+* 12-18-93 GJF Don't treat ERROR_BROKEN_PIPE as an error. Instead,
+* just return 0.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <os2dll.h>
+#include <io.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <msdos.h>
+
+#define LF 10 /* line feed */
+#define CR 13 /* carriage return */
+#define CTRLZ 26 /* ctrl-z means eof for text */
+
+/***
+*int _read(fh, buf, cnt) - read bytes from a file handle
+*
+*Purpose:
+* Attempts to read cnt bytes from fh into a buffer.
+* If the file is in text mode, CR-LF's are mapped to LF's, thus
+* affecting the number of characters read. This does not
+* affect the file pointer.
+*
+* NOTE: The stdio _IOCTRLZ flag is tied to the use of FEOFLAG.
+* Cross-reference the two symbols before changing FEOFLAG's use.
+*
+*Entry:
+* int fh - file handle to read from
+* char *buf - buffer to read into
+* int cnt - number of bytes to read
+*
+*Exit:
+* Returns number of bytes read (may be less than the number requested
+* if the EOF was reached or the file is in text mode).
+* returns -1 (and sets errno) if fails.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+/* define normal version that locks/unlocks, validates fh */
+int _CALLTYPE1 _read (
+ int fh,
+ void *buf,
+ unsigned cnt
+ )
+{
+ int r; /* return value */
+
+ /* validate handle */
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+#else
+ if ((unsigned)fh >= (unsigned)_nfile) {
+#endif
+ /* out of range -- return error */
+ errno = EBADF;
+ _doserrno = 0; /* not OS/2 error */
+ return -1;
+ }
+
+ _lock_fh(fh); /* lock file */
+ r = _read_lk(fh, buf, cnt); /* read bytes */
+ _unlock_fh(fh); /* unlock file */
+
+ return r;
+}
+
+/* now define version that doesn't lock/unlock, validate fh */
+int _CALLTYPE1 _read_lk (
+ int fh,
+ void *buf,
+ unsigned cnt
+ )
+{
+ int bytes_read; /* number of bytes read */
+ char *buffer; /* buffer to read to */
+ int os_read; /* bytes read on OS call */
+ char *p, *q; /* pointers into buffer */
+ char peekchr; /* peek-ahead character */
+ ULONG filepos; /* file position after seek */
+ ULONG dosretval; /* OS/2 return value */
+
+
+#else
+
+/* now define normal version */
+int _CALLTYPE1 _read (
+ int fh,
+ void *buf,
+ unsigned cnt
+ )
+{
+ int bytes_read; /* number of bytes read */
+ char *buffer; /* buffer to read to */
+ int os_read; /* bytes read on OS call */
+ char *p, *q; /* pointers into buffer */
+ char peekchr; /* peek-ahead character */
+ ULONG filepos; /* file position after seek */
+ ULONG dosretval; /* OS/2 return value */
+
+ /* validate fh */
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+#else
+ if ((unsigned)fh >= (unsigned)_nfile) {
+#endif
+ /* bad file handle */
+ errno = EBADF;
+ _doserrno = 0; /* not OS/2 error */
+ return -1;
+ }
+
+#endif
+
+ bytes_read = 0; /* nothing read yet */
+ buffer = buf;
+
+ if (cnt == 0 || (_osfile[fh] & FEOFLAG)) {
+ /* nothing to read or at EOF, so return 0 read */
+ return 0;
+ }
+
+ if ((_osfile[fh] & (FPIPE|FDEV)) && _pipech[fh] != LF) {
+ /* a pipe/device and pipe lookahead non-empty: read the lookahead char */
+ *buffer++ = _pipech[fh];
+ ++bytes_read;
+ --cnt;
+ _pipech[fh] = LF; /* mark as empty */
+ }
+
+ /* read the data */
+#ifdef _CRUISER_
+
+ if ( dosretval = DOSREAD(fh, buffer, cnt, &os_read) ) {
+ /* OS error, map it and return */
+ if (dosretval == ERROR_ACCESS_DENIED) {
+ /* wrong read/write mode should return EBADF, not EACCES */
+ errno = EBADF;
+ _doserrno = dosretval;
+ }
+ else
+ _dosmaperr(dosretval);
+ return -1;
+ }
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if ( !ReadFile((HANDLE)_osfhnd[fh], buffer, cnt, (LPDWORD)&os_read,
+ NULL) ) {
+
+ /* ReadFile has reported an error. recognize two special cases.
+ *
+ * 1. map ERROR_ACCESS_DENIED to EBADF
+ *
+ * 2. just return 0 if ERROR_BROKEN_PIPE has occurred. it
+ * means the handle is a read-handle on a pipe for which
+ * all write-handles have been closed and all data has been
+ * read. */
+
+ if ( (dosretval = GetLastError()) == ERROR_ACCESS_DENIED ) {
+ /* wrong read/write mode should return EBADF, not EACCES */
+ errno = EBADF;
+ _doserrno = dosretval;
+ return -1;
+ }
+ else if ( dosretval == ERROR_BROKEN_PIPE ) {
+ return 0;
+ }
+ else {
+ _dosmaperr(dosretval);
+ return -1;
+ }
+ }
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ bytes_read += os_read; /* update bytes read */
+
+ if (_osfile[fh] & FTEXT) {
+ /* now must translate CR-LFs to LFs in the buffer */
+
+ /* set CRLF flag to indicate LF at beginning of buffer */
+ if (*(char *)buf == LF)
+ _osfile[fh] |= FCRLF;
+ else
+ _osfile[fh] &= ~FCRLF;
+
+ /* convert chars in the buffer: p is src, q is dest */
+ p = q = buf;
+ while (p < (char *)buf + bytes_read) {
+ if (*p == CTRLZ) {
+ /* if fh is not a device, set ctrl-z flag */
+ if ( !(_osfile[fh] & FDEV) )
+ _osfile[fh] |= FEOFLAG;
+ break; /* stop translating */
+ }
+ else if (*p != CR)
+ *q++ = *p++;
+ else {
+ /* *p is CR, so must check next char for LF */
+ if (p < (char *)buf + bytes_read - 1) {
+ if (*(p+1) == LF) {
+ p += 2;
+ *q++ = LF; /* convert CR-LF to LF */
+ }
+ else
+ *q++ = *p++; /* store char normally */
+ }
+ else {
+ /* This is the hard part. We found a CR at end of
+ buffer. We must peek ahead to see if next char
+ is an LF. */
+ ++p;
+#ifdef _CRUISER_
+
+ dosretval = DOSREAD(fh, &peekchr, 1, &os_read);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ dosretval = 0;
+ if ( !ReadFile((HANDLE)_osfhnd[fh], &peekchr, 1,
+ (LPDWORD)&os_read, NULL) )
+ dosretval = GetLastError();
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+ if (dosretval != 0 || os_read == 0) {
+ /* couldn't read ahead, store CR */
+ *q++ = CR;
+ }
+ else {
+ /* peekchr now has the extra character -- we now have
+ several possibilities:
+ 1. disk file and char is not LF; just seek back
+ and copy CR
+ 2. disk file and char is LF; seek back and discard CR
+ 3. disk file, char is LF but this is a one-byte read:
+ store LF, don't seek back
+ 4. pipe/device and char is LF; store LF.
+ 5. pipe/device and char isn't LF, store CR and put
+ char in pipe lookahead buffer. */
+ if (_osfile[fh] & (FDEV|FPIPE)) {
+ /* non-seekable device */
+ if (peekchr == LF)
+ *q++ = LF;
+ else {
+ *q++ = CR;
+ _pipech[fh] = peekchr;
+ }
+ }
+ else {
+ /* disk file */
+ if (q == buf && peekchr == LF) {
+ /* nothing read yet; must make some progress */
+ *q++ = LF;
+ }
+ else {
+ /* seek back */
+ filepos = _lseek_lk(fh, -1, FILE_CURRENT);
+ if (peekchr != LF)
+ *q++ = CR;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* we now change bytes_read to reflect the true number of chars
+ in the buffer */
+ bytes_read = q - (char *)buf;
+ }
+
+ return bytes_read; /* and return */
+}
diff --git a/private/crt32/lowio/setmode.c b/private/crt32/lowio/setmode.c
new file mode 100644
index 000000000..a9bf34e8e
--- /dev/null
+++ b/private/crt32/lowio/setmode.c
@@ -0,0 +1,155 @@
+/***
+*setmode.c - set file translation mode
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defined _setmode() - set file translation mode of a file
+*
+*Revision History:
+* 08-16-84 RN initial version
+* 10-29-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-25-88 PHG Merged DLL and normal versions
+* 03-13-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 04-04-90 GJF Added #include <io.h>.
+* 10-01-90 GJF New-style function declarators.
+* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s.
+* Two versions should be merged together, the differences
+* are trivial.
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 01-17-91 GJF ANSI naming.
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <msdos.h>
+#include <os2dll.h>
+#include <stddef.h>
+#include <internal.h>
+
+/***
+*int _setmode(fh, mode) - set file translation mode
+*
+*Purpose:
+* changes file mode to text/binary, depending on mode arg. this affects
+* whether read's and write's on the file translate between CRLF and LF
+* or is untranslated
+*
+*Entry:
+* int fh - file handle to change mode on
+* int mode - file translation mode (one of O_TEXT and O_BINARY)
+*
+*Exit:
+* returns old file translation mode
+* returns -1 and sets errno if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD /* multi-thread code calls _lk_setmode() */
+
+int _CALLTYPE1 _setmode (
+ int fh,
+ int mode
+ )
+{
+ int retval;
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+#else
+ if (fh < 0 || fh >= _nfile) {
+#endif
+ errno = EBADF;
+ return(-1);
+ }
+
+ /* lock the file */
+ _lock_fh(fh);
+
+ /* set the text/binary mode */
+ retval = _setmode_lk(fh, mode);
+
+ /* unlock the file */
+ _unlock_fh(fh);
+
+ /* Return to user (_setmode_lk sets errno, if needed) */
+ return(retval);
+
+}
+
+/***
+*_setmode_lk() - Perform core setmode operation
+*
+*Purpose:
+* Core setmode code. Assumes:
+* (1) Caller has validated fh to make sure it's in range.
+* (2) Caller has locked the file handle.
+*
+* [See _setmode() description above.]
+*
+*Entry: [Same as _setmode()]
+*
+*Exit: [Same as _setmode()]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _setmode_lk (
+ REG1 int fh,
+ int mode
+ )
+{
+ int oldmode;
+
+#else /* non multi-thread code */
+
+int _CALLTYPE1 _setmode (
+ REG1 int fh,
+ int mode
+ )
+{
+ int oldmode;
+
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+#else
+ if (fh < 0 || fh >= _nfile) {
+#endif
+ errno = EBADF;
+ return(-1);
+ }
+
+#endif /* now join common code */
+
+ if (!(_osfile[fh] & FOPEN)) {
+ errno = EBADF;
+ return(-1);
+ }
+
+ else {
+ oldmode = _osfile[fh] & FTEXT;
+
+ if (mode == _O_BINARY)
+ _osfile[fh] &= ~FTEXT;
+ else if (mode == _O_TEXT)
+ _osfile[fh] |= FTEXT;
+ else {
+ errno = EINVAL;
+ return(-1);
+ }
+ }
+
+ return(oldmode ? _O_TEXT : _O_BINARY);
+
+}
diff --git a/private/crt32/lowio/sources b/private/crt32/lowio/sources
new file mode 100644
index 000000000..6c95035f2
--- /dev/null
+++ b/private/crt32/lowio/sources
@@ -0,0 +1,62 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=lowio
+
+TARGETNAME=lowio
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=chsize.c \
+ close.c \
+ commit.c \
+ creat.c \
+ dup.c \
+ dup2.c \
+ eof.c \
+ flength.c \
+ fstat.c \
+ initcon.c \
+ ioinit.c \
+ isatty.c \
+ locking.c \
+ lseek.c \
+ mktemp.c \
+ open.c \
+ osfinfo.c \
+ pipe.c \
+ read.c \
+ setmode.c \
+ tell.c \
+ txtmode.c \
+ write.c \
+ cgets.c \
+ cputs.c \
+ getch.c \
+ putch.c
diff --git a/private/crt32/lowio/tell.c b/private/crt32/lowio/tell.c
new file mode 100644
index 000000000..0f8a2a497
--- /dev/null
+++ b/private/crt32/lowio/tell.c
@@ -0,0 +1,46 @@
+/***
+*tell.c - find file position
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains _tell() - find file position
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 03-13-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 10-01-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <io.h>
+
+/***
+*long _tell(filedes) - find file position
+*
+*Purpose:
+* Gets the current position of the file pointer (no adjustment
+* for buffering).
+*
+*Entry:
+* int filedes - file handle of file
+*
+*Exit:
+* returns file position or -1L (sets errno) if bad file descriptor or
+* pipe
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+long _CALLTYPE1 _tell (
+ int filedes
+ )
+{
+ return(_lseek(filedes,0L,1));
+}
diff --git a/private/crt32/lowio/txtmode.c b/private/crt32/lowio/txtmode.c
new file mode 100644
index 000000000..b40b0db61
--- /dev/null
+++ b/private/crt32/lowio/txtmode.c
@@ -0,0 +1,19 @@
+/***
+*txtmode.c - set global text mode flag
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Sets the global file mode to text. This is the default.
+*
+*Revision History:
+* 06-08-89 PHG Module created, based on asm version.
+* 04-04-90 GJF Added #include <cruntime.h>. Also, fixed the copyright.
+* 01-23-92 GJF Added #include <stdlib.h> (contains decl of _fmode).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+
+int _fmode = 0; /* set text mode */
diff --git a/private/crt32/lowio/write.c b/private/crt32/lowio/write.c
new file mode 100644
index 000000000..73d57bba1
--- /dev/null
+++ b/private/crt32/lowio/write.c
@@ -0,0 +1,324 @@
+/***
+*write.c - write to a file handle
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _write() - write to a file handle
+*
+*Revision History:
+* 06-14-89 PHG Module created, based on asm version
+* 03-13-90 GJF Made calling type _CALLTYPE2 (for now), added #include
+* <cruntime.h>, fixed compiler warnings and fixed the
+* copyright. Also, cleaned up the formatting a bit.
+* 04-03-90 GJF Now _CALLTYPE1.
+* 07-24-90 SBM Removed '32' from API names
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-01-90 GJF New-style function declarators.
+* 12-04-90 GJF Appended Win32 version onto source with #ifdef-s.
+* Should come back latter and do a better merge.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
+* 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragma
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 01-17-91 GJF ANSI naming.
+* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
+* 04-09-91 PNT Added _MAC_ conditional
+* 07-18-91 GJF Removed unreferenced local variable from _write_lk
+* routine [_WIN32_].
+* 10-24-91 GJF Added LPDWORD casts to make MIPS compiler happy.
+* ASSUMES THAT sizeof(int) == sizeof(DWORD).
+* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
+* 02-15-92 GJF Increased BUF_SIZE and simplified LF translation code
+* for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <io.h>
+#include <errno.h>
+#include <msdos.h>
+#include <os2dll.h>
+#include <stdlib.h>
+#include <string.h>
+#include <internal.h>
+
+#ifdef _WIN32_
+#define BUF_SIZE 1025 /* size of LF translation buffer */
+#else /* ndef _WIN32_ */
+#define BUF_SIZE 513 /* size of LF translation buffer, sector size+1 is ok */
+#endif /* _WIN32_ */
+
+#define LF '\n' /* line feed */
+#define CR '\r' /* carriage return */
+#define CTRLZ 26 /* ctrl-z */
+
+#ifdef _CRUISER_
+#pragma check_stack(on)
+#endif /* ndef _CRUISER_ */
+
+/***
+*int _write(fh, buf, cnt) - write bytes to a file handle
+*
+*Purpose:
+* Writes count bytes from the buffer to the handle specified.
+* If the file was opened in text mode, each LF is translated to
+* CR-LF. This does not affect the return value. In text
+* mode ^Z indicates end of file.
+*
+* Multi-thread notes:
+* (1) _write() - Locks/unlocks file handle
+* _write_lk() - Does NOT lock/unlock file handle
+*
+*Entry:
+* int fh - file handle to write to
+* char *buf - buffer to write from
+* unsigned int cnt - number of bytes to write
+*
+*Exit:
+* returns number of bytes actually written.
+* This may be less than cnt, for example, if out of disk space.
+* returns -1 (and set errno) if fails.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+/* define normal version that locks/unlocks, validates fh */
+int _CALLTYPE1 _write (
+ int fh,
+ const void *buf,
+ unsigned cnt
+ )
+{
+ int r; /* return value */
+
+ /* validate handle */
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+#else
+ if ((unsigned)fh >= (unsigned)_nfile) {
+#endif
+ /* out of range -- return error */
+ errno = EBADF;
+ _doserrno = 0; /* not OS/2 error */
+ return -1;
+ }
+
+ _lock_fh(fh); /* lock file */
+ r = _write_lk(fh, buf, cnt); /* write bytes */
+ _unlock_fh(fh); /* unlock file */
+
+ return r;
+}
+
+/* now define version that doesn't lock/unlock, validate fh */
+int _CALLTYPE1 _write_lk (
+ int fh,
+ const void *buf,
+ unsigned cnt
+ )
+{
+ int lfcount; /* count of line feeds */
+ int charcount; /* count of chars written so far */
+ int written; /* count of chars written on this write */
+#ifdef _CRUISER_
+ int error; /* error occured */
+#endif
+ ULONG dosretval; /* OS/2 return value */
+ char ch; /* current character */
+ char *p, *q; /* pointers into buf and lfbuf resp. */
+ char lfbuf[BUF_SIZE]; /* lf translation buffer */
+
+#else
+
+/* now define normal version */
+int _CALLTYPE1 _write (
+ int fh,
+ const void *buf,
+ unsigned cnt
+ )
+{
+ int lfcount; /* count of line feeds */
+ int charcount; /* count of chars written so far */
+ int written; /* count of chars written on this write */
+#ifdef _CRUISER_
+ int error; /* error occured */
+#endif
+ ULONG dosretval; /* OS/2 return value */
+ char ch; /* current character */
+ char *p, *q; /* pointers into buf and lfbuf resp. */
+ char lfbuf[BUF_SIZE]; /* lf translation buffer */
+
+ /* validate handle */
+#ifdef _WIN32_
+ if ( (unsigned)fh >= (unsigned)_nhandle ) {
+#else
+ if ((unsigned)fh >= (unsigned)_nfile) {
+#endif
+ /* out of range -- return error */
+ errno = EBADF;
+ _doserrno = 0; /* not OS/2 error */
+ return -1;
+ }
+
+#endif
+
+ lfcount = charcount = 0; /* nothing written yet */
+
+ if (cnt == 0)
+ return 0; /* nothing to do */
+
+
+ if (_osfile[fh] & FAPPEND) {
+ /* appending - seek to end of file; ignore error, because maybe
+ file doesn't allow seeking */
+ (void)_lseek_lk(fh, 0, FILE_END);
+ }
+
+ /* check for text mode with LF's in the buffer */
+
+#ifdef _CRUISER_
+ if ((_osfile[fh] & FTEXT) && memchr(buf, LF, cnt)) {
+ /* text mode, translate LF's to CR/LF's on output */
+
+ p = (char *)buf; /* start at beginning of buffer */
+ error = 0; /* no error yet */
+
+ while ((unsigned)(p - (char *)buf) < cnt && !error) {
+ q = lfbuf; /* start at beginning of lfbuf */
+
+ /* fill the lf buf, except maybe last char */
+ while (q - lfbuf < BUF_SIZE - 1 && (unsigned)(p - (char *)buf) < cnt) {
+ ch = *p++;
+ if (ch == LF) {
+ ++lfcount;
+ *q++ = CR;
+ *q++ = LF; /* store CR-LF */
+ }
+ else
+ *q++ = ch;
+ }
+
+ /* write the lf buf and update total */
+ if (dosretval = DOSWRITE(fh, lfbuf, q - lfbuf,
+ &written))
+ error = 1;
+ else {
+ charcount += written;
+ if (written < q - lfbuf)
+ error = 1;
+ }
+ }
+ }
+ else {
+ /* binary mode, no translation */
+ if (!(dosretval = DOSWRITE(fh, (char *)buf, cnt, &written)))
+ charcount = written;
+ }
+
+#else /* _CRUISER_ */
+
+#ifdef _WIN32_
+ if ( _osfile[fh] & FTEXT ) {
+ /* text mode, translate LF's to CR/LF's on output */
+
+ p = (char *)buf; /* start at beginning of buffer */
+ dosretval = 0; /* no OS error yet */
+
+ while ( (unsigned)(p - (char *)buf) < cnt ) {
+ q = lfbuf; /* start at beginning of lfbuf */
+
+ /* fill the lf buf, except maybe last char */
+ while ( q - lfbuf < BUF_SIZE - 1 &&
+ (unsigned)(p - (char *)buf) < cnt ) {
+ ch = *p++;
+ if ( ch == LF ) {
+ ++lfcount;
+ *q++ = CR;
+ }
+ *q++ = ch;
+ }
+
+ /* write the lf buf and update total */
+ if ( WriteFile( (HANDLE)_osfhnd[fh],
+ lfbuf,
+ q - lfbuf,
+ (LPDWORD)&written,
+ NULL) )
+ {
+ charcount += written;
+ if (written < q - lfbuf)
+ break;
+ }
+ else {
+ dosretval = GetLastError();
+ break;
+ }
+ }
+ }
+ else {
+ /* binary mode, no translation */
+ if ( WriteFile( (HANDLE)_osfhnd[fh],
+ (LPVOID)buf,
+ cnt,
+ (LPDWORD)&written,
+ NULL) )
+ {
+ dosretval = 0;
+ charcount = written;
+ }
+ else
+ dosretval = GetLastError();
+ }
+
+#else /* ndef _WIN32_ */
+
+#ifdef _MAC_
+
+ }
+ }
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ if (charcount == 0) {
+ /* If nothing was written, first check if an OS/2 error,
+ otherwise we return -1 and set errno to ENOSPC,
+ unless a device and first char was CTRL-Z */
+ if (dosretval != 0) {
+ /* OS/2 error happened, map error */
+ if (dosretval == ERROR_ACCESS_DENIED) {
+ /* wrong read/write mode should return EBADF, not
+ EACCES */
+ errno = EBADF;
+ _doserrno = dosretval;
+ }
+ else
+ _dosmaperr(dosretval);
+ return -1;
+ }
+ else if ((_osfile[fh] & FDEV) && *(char *)buf == CTRLZ)
+ return 0;
+ else {
+ errno = ENOSPC;
+ _doserrno = 0; /* no OS/2 error */
+ return -1;
+ }
+ }
+ else
+ /* return adjusted bytes written */
+ return charcount - lfcount;
+}
diff --git a/private/crt32/makefile b/private/crt32/makefile
new file mode 100644
index 000000000..53b1e7e6b
--- /dev/null
+++ b/private/crt32/makefile
@@ -0,0 +1,597 @@
+####
+#crt32\makefile - makefile for crt32 NT build
+#
+# Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+#
+#Purpose:
+#
+#Revision History:
+# 09-29-91 JCR File created.
+# 10-04-91 JCR Added mt vs st build
+# 01-07-92 GJF Added dll build, revised rest.
+# 01-16-92 JCR use winheap (not heap)
+# 01-29-92 GJF Support for link options for DLL
+# 02-06-92 GJF Fixed non-dll builds.
+# 06-06-92 KRS Added wchar_t printf functions, _snprintf.
+# 01-18-93 KRS Integrate MBCS into standard makefile.
+#
+################################################################################
+
+!INCLUDE crt32.def
+
+!IFNDEF 386
+386=0
+!ENDIF
+!IFNDEF MIPS
+MIPS=0
+!ENDIF
+!IFNDEF ALPHA
+ALPHA=0
+!ENDIF
+!IFNDEF PPC
+PPC=0
+!ENDIF
+
+#
+# Default to building for i386 target, if no targets specified.
+#
+
+!IF !$(386)
+! IF !$(MIPS)
+! IF !$(ALPHA)
+! IF !$(PPC)
+! IFDEF NTMIPSDEFAULT
+ MIPS=1
+! ELSE
+! IFDEF NTALPHADEFAULT
+ ALPHA=1
+! ELSE
+! IFDEF NTPPCDEFAULT
+ PPC=1
+! ELSE
+ 386=1
+! ENDIF
+! ENDIF
+! ENDIF
+! ENDIF
+! ENDIF
+! ENDIF
+!ENDIF
+
+!IF $(MIPS)
+HELPER_OBJECTS=helper\obj\*.obj
+!ELSEIF $(PPC)
+HELPER_OBJECTS=helper\obj\*.obj
+!ELSE
+HELPER_OBJECTS=
+!ENDIF
+
+!IF "$(TARGETNAMESUFFIX)" == "nt"
+INITOBJECTS=
+
+!ELSEIF "$(TARGETNAMESUFFIX)" == "psx"
+INITOBJECTS=\
+ startup\obj\*\crt0init.obj \
+
+!ELSE
+CRT_OBJECTS=
+INITOBJECTS=\
+ startup\obj\*\crt0init.obj \
+!ENDIF
+
+!IF "$(TARGETNAMESUFFIX)" == "dll"
+OBJECTS=startup\obj\chkstk.obj \
+startup\obj\crt0dat.obj \
+startup\obj\crt0fp.obj \
+startup\obj\crt0msg.obj \
+startup\obj\mlock.obj \
+startup\obj\_setargv.obj \
+startup\obj\stdargv.obj \
+startup\obj\stdenvp.obj \
+startup\obj\thread.obj \
+startup\obj\tidtable.obj \
+startup\obj\wild.obj \
+convert\obj\*.obj \
+direct\obj\*.obj \
+dllstuff\obj\crtlib.obj \
+dos\obj\*.obj \
+exec\obj\*.obj \
+winheap\obj\*.obj \
+lowio\obj\*.obj \
+mbstring\obj\*.obj \
+$(HELPER_OBJECTS) \
+misc\obj\*.obj \
+stdio\obj\*.obj \
+string\obj\*.obj \
+time\obj\*.obj
+!ELSEIF "$(TARGETNAMESUFFIX)" == "psx"
+OBJECTS=convert\obj\*.obj \
+mbstring\obj\*.obj \
+$(HELPER_OBJECTS) \
+misc\obj\*.obj \
+startup\obj\*.obj \
+stdio\obj\*.obj \
+string\obj\*.obj \
+time\obj\*.obj \
+winheap\obj\*.obj
+!ELSEIF "$(TARGETNAMESUFFIX)" == "nt"
+OBJECTS=convert\obj\*.obj \
+ $(HELPER_OBJECTS) \
+ misc\obj\abs.obj \
+ misc\obj\bsearch.obj \
+ misc\obj\ctype.obj \
+ misc\obj\div.obj \
+ misc\obj\ldiv.obj \
+ misc\obj\labs.obj \
+ misc\obj\lconv.obj \
+ misc\obj\lfind.obj \
+ misc\obj\lsearch.obj \
+ misc\obj\makepath.obj \
+ misc\obj\nlsdata1.obj \
+ misc\obj\nlsdata2.obj \
+ misc\obj\qsort.obj \
+ misc\obj\rand.obj \
+ misc\obj\rotl.obj \
+ misc\obj\rotr.obj \
+ misc\obj\setlocal.obj \
+ misc\obj\splitpat.obj \
+ misc\obj\cmiscdat.obj \
+ startup\obj\crt0fp.obj \
+ string\obj\memicmp.obj \
+ string\obj\strcspn.obj \
+ string\obj\strlwr.obj \
+ string\obj\strupr.obj \
+ string\obj\strncat.obj \
+ string\obj\strncmp.obj \
+ string\obj\strncpy.obj \
+ string\obj\strnicmp.obj \
+ string\obj\strnset.obj \
+ string\obj\strpbrk.obj \
+ string\obj\strrev.obj \
+ string\obj\strset.obj \
+ string\obj\strspn.obj \
+ string\obj\strstr.obj \
+ string\obj\wcscat.obj \
+ string\obj\wcschr.obj \
+ string\obj\wcscmp.obj \
+ string\obj\wcsicmp.obj \
+ string\obj\wcscspn.obj \
+ string\obj\wcslen.obj \
+ string\obj\wcslwr.obj \
+ string\obj\wcsupr.obj \
+ string\obj\wcsncat.obj \
+ string\obj\wcsncmp.obj \
+ string\obj\wcsncpy.obj \
+ string\obj\wcsnicmp.obj \
+ string\obj\wcsnset.obj \
+ string\obj\wcspbrk.obj \
+ string\obj\wcsrchr.obj \
+ string\obj\wcsrev.obj \
+ string\obj\wcsset.obj \
+ string\obj\wcsspn.obj \
+ string\obj\wcsstr.obj \
+ string\obj\wcstok.obj \
+ stdio\obj\sprintf.obj \
+ stdio\obj\snprintf.obj \
+ stdio\obj\vsprintf.obj \
+ stdio\obj\vsnprint.obj \
+ stdio\obj\output.obj \
+ stdio\obj\sscanf.obj \
+ stdio\obj\input.obj \
+ stdio\obj\swprintf.obj \
+ stdio\obj\snwprint.obj \
+ stdio\obj\vswprint.obj \
+ stdio\obj\vsnwprnt.obj \
+ stdio\obj\woutput.obj \
+ stdio\obj\winput.obj \
+ stdio\obj\swscanf.obj \
+ stdio\obj\fgetwchr.obj \
+ stdio\obj\fgetwc.obj \
+ stdio\obj\fputwchr.obj \
+ stdio\obj\fputwc.obj \
+ stdio\obj\_filbuf.obj \
+ stdio\obj\_filwbuf.obj \
+ stdio\obj\_flsbuf.obj \
+ stdio\obj\_flswbuf.obj \
+ stdio\obj\_getbuf.obj \
+ stdio\obj\ungetc.obj \
+ hack\obj\*.obj
+
+!IF $(386)
+CRT_OBJECTS=misc\obj\*\exsup.obj \
+ misc\obj\*\exsup2.obj \
+ misc\obj\*\exsup3.obj \
+ misc\obj\*\longjmp.obj \
+ misc\obj\*\sehsupp.obj \
+ misc\obj\*\setjmp.obj \
+ misc\obj\*\setjmp3.obj \
+ misc\obj\*\setjmpex.obj \
+ startup\obj\*\chkstk.obj \
+ string\obj\*\memccpy.obj \
+ string\obj\*\memchr.obj \
+ string\obj\*\memcmp.obj \
+ string\obj\*\memcpy.obj \
+ string\obj\*\memmove.obj \
+ string\obj\*\memset.obj \
+ string\obj\*\strcat.obj \
+ string\obj\*\strchr.obj \
+ string\obj\*\stricmp.obj \
+ string\obj\*\strcmp.obj \
+ string\obj\*\strlen.obj \
+ string\obj\*\strrchr.obj
+
+!ELSEIF $(MIPS)
+CRT_OBJECTS=startup\obj\*\chkstk.obj \
+ misc\obj\*\chandler.obj \
+ misc\obj\*\jmpuwind.obj \
+ misc\obj\*\longjmp.obj \
+ misc\obj\*\setjmp.obj \
+ misc\obj\*\setjmpex.obj \
+ string\obj\*\memccpy.obj \
+ string\obj\*\memchr.obj \
+ string\obj\*\strcatm.obj \
+ string\obj\*\memorym.obj \
+ string\obj\*\strchrm.obj \
+ string\obj\*\stricmp.obj \
+ string\obj\*\strcmpm.obj \
+ string\obj\*\strcpym.obj \
+ string\obj\*\strlenm.obj \
+ string\obj\*\strrchrm.obj
+
+!ELSEIF $(PPC)
+CRT_OBJECTS=startup\obj\*\chkstk.obj \
+ misc\obj\*\chandler.obj \
+ misc\obj\*\jmpuwind.obj \
+ misc\obj\*\longjmp.obj \
+ misc\obj\*\setjmp.obj \
+ misc\obj\*\setjmpex.obj \
+ misc\obj\*\miscasm.obj \
+ string\obj\*\memccpyp.obj \
+ string\obj\*\memcmpp.obj \
+ string\obj\*\memcpy.obj \
+ string\obj\*\memchrp.obj \
+ string\obj\*\memmove.obj \
+ string\obj\*\memset.obj \
+ string\obj\*\strcatp.obj \
+ string\obj\*\stricmpp.obj \
+ string\obj\*\strchrp.obj \
+ string\obj\*\strcmpp.obj \
+ string\obj\*\strlenp.obj \
+ string\obj\*\strrchrp.obj
+
+!ELSEIF $(ALPHA)
+CRT_OBJECTS=startup\obj\*\chkstk.obj \
+ misc\obj\*\chandler.obj \
+ misc\obj\*\divdat.obj \
+ misc\obj\*\divide2.obj \
+ misc\obj\*\extv.obj \
+ misc\obj\*\extvvol.obj \
+ misc\obj\*\extzv.obj \
+ misc\obj\*\extzvvol.obj \
+ misc\obj\*\ghandler.obj \
+ misc\obj\*\insv.obj \
+ misc\obj\*\insvvol.obj \
+ misc\obj\*\jmpuwind.obj \
+ misc\obj\*\longjmp.obj \
+ misc\obj\*\otsdiv.obj \
+ misc\obj\*\otsdiv.obj \
+ misc\obj\*\otsjmp.obj \
+ misc\obj\*\otsjmpex.obj \
+ misc\obj\*\otsuwind.obj \
+ misc\obj\*\scmpeql.obj \
+ misc\obj\*\scmpeqlp.obj \
+ misc\obj\*\scmpleq.obj \
+ misc\obj\*\scmpleqp.obj \
+ misc\obj\*\scmplss.obj \
+ misc\obj\*\scmplssp.obj \
+ misc\obj\*\setjmp.obj \
+ misc\obj\*\setjmpex.obj \
+ misc\obj\*\sfill.obj \
+ misc\obj\*\sloc.obj \
+ misc\obj\*\smove.obj \
+ misc\obj\*\smovem.obj \
+ misc\obj\*\strans.obj \
+ misc\obj\*\strcmp_.obj \
+ misc\obj\*\strcpy_.obj \
+ misc\obj\*\strlen_.obj \
+ misc\obj\*\szero.obj \
+ convert\obj\*\strtoq.obj \
+ string\obj\*\memccpy.obj \
+ string\obj\*\memchr.obj \
+ string\obj\*\memcmp.obj \
+ string\obj\*\memcpy.obj \
+ string\obj\*\memmove.obj \
+ string\obj\*\memset.obj \
+ string\obj\*\strcat.obj \
+ string\obj\*\strchr.obj \
+ string\obj\*\stricmp.obj \
+ string\obj\*\strcmps.obj \
+ string\obj\*\strcpys.obj \
+ string\obj\*\strlens.obj \
+ string\obj\*\strrchr.obj
+!ENDIF # 386/MIPS/Alpha/PPC & Target = NT
+
+!ELSE
+OBJECTS=convert\obj\*.obj \
+direct\obj\*.obj \
+dos\obj\*.obj \
+exec\obj\*.obj \
+iostream\obj\*.obj \
+winheap\obj\*.obj \
+lowio\obj\*.obj \
+mbstring\obj\*.obj \
+$(HELPER_OBJECTS) \
+misc\obj\*.obj \
+startup\obj\*.obj \
+stdio\obj\*.obj \
+string\obj\*.obj \
+time\obj\*.obj
+!ENDIF
+
+TARGETLIB=
+LIBC=obj\*\libc$(TARGETNAMESUFFIX).lib
+
+#define list of extra objects (not built into lib)
+
+!IF "$(TARGETNAMESUFFIX)" == "dll"
+
+CRTEXE=obj\*\crtexe.obj
+CRTEXEW=obj\*\crtexew.obj
+CRTDLL=obj\*\crtdll.obj
+DLLARGV=obj\*\dllargv.obj
+DLLMAIN=obj\*\dllmain.obj
+CINITEXE=obj\*\cinitexe.obj
+
+!IF $(386)
+DLLSUPP386=obj\i386\dllsupp.obj
+!ELSE
+DLLSUPP386=
+!ENDIF
+
+EXTRAOBJS=\
+ $(CRTEXE) \
+ $(CRTEXEW) \
+ $(CRTDLL) \
+ $(DLLARGV) \
+ $(DLLMAIN) \
+ $(CINITEXE) \
+ $(DLLSUPP386)
+
+!ELSEIF "$(TARGETNAMESUFFIX)" == ""
+
+BINMODE=obj\*\binmode.obj
+COMMODE=obj\*\commode.obj
+SETARGV=obj\*\setargv.obj
+CHKSTK=obj\*\chkstk.obj
+EXTRAOBJS=\
+ $(BINMODE) \
+ $(COMMODE) \
+ $(SETARGV) \
+ $(CHKSTK)
+
+!ELSE
+
+EXTRAOBJS=
+
+!ENDIF
+
+
+!IF $(386)
+TARGETLIBS=$(TARGETLIBS) \
+ $(LIBC:*=i386) \
+ $(EXTRAOBJS:*=i386)
+!ENDIF
+
+!IF $(MIPS)
+TARGETLIBS=$(TARGETLIBS) \
+ $(LIBC:*=mips) \
+ $(EXTRAOBJS:*=mips)
+!ENDIF
+
+!IF $(ALPHA)
+TARGETLIBS=$(TARGETLIBS) \
+ $(LIBC:*=alpha) \
+ $(EXTRAOBJS:*=alpha)
+!ENDIF
+
+!IF $(PPC)
+TARGETLIBS=$(TARGETLIBS) \
+ $(LIBC:*=ppc) \
+ $(EXTRAOBJS:*=ppc)
+!ENDIF
+
+all: $(TARGETLIBS)
+!IF "$(BUILDMSG)" != ""
+ echo $(BUILDMSG)
+!ENDIF
+
+clean: cleanlib all
+
+cleanlib:
+ -erase $(TARGETLIBS)
+
+# get needed Win include files
+wininc:
+ copy \\idwtest\sources\public\sdk\inc\winbase.h \nt\public\sdk\inc\winbase.h
+ copy \\idwtest\sources\public\sdk\inc\winnt.h \nt\public\sdk\inc\winnt.h
+ copy \\idwtest\sources\public\sdk\inc\wingdi.h \nt\public\sdk\inc\wingdi.h
+ copy \\idwtest\sources\public\sdk\inc\winerror.h \nt\public\sdk\inc\winerror.h
+ copy \\idwtest\sources\public\sdk\inc\winuser.h \nt\public\sdk\inc\winuser.h
+
+$(LIBC:*=i386): $(OBJECTS:obj\=obj\i386\) $(HELPER_OBJECTS:obj\=obj\i386\) $(CRT_OBJECTS:*=i386) $(INITOBJECTS:*=i386) makefile.
+ lib -out:$@ @<<
+$(OBJECTS:obj\=obj\i386\)
+$(CRT_OBJECTS:*=i386)
+$(INITOBJECTS:*=i386)
+<<
+
+$(LIBC:*=mips): $(OBJECTS:obj\=obj\mips\) $(HELPER_OBJECTS:obj\=obj\mips\) $(CRT_OBJECTS:*=mips) $(INITOBJECTS:*=mips) makefile.
+ lib -out:$@ @<<
+$(OBJECTS:obj\=obj\mips\)
+$(CRT_OBJECTS:*=mips)
+$(INITOBJECTS:*=mips)
+<<
+
+$(LIBC:*=alpha): $(OBJECTS:obj\=obj\alpha\) $(HELPER_OBJECTS:obj\=obj\alpha\) $(CRT_OBJECTS:*=alpha) $(INITOBJECTS:*=alpha) makefile.
+ lib -out:$@ @<<
+$(OBJECTS:obj\=obj\alpha\)
+$(CRT_OBJECTS:*=alpha)
+$(INITOBJECTS:*=alpha)
+<<
+
+$(LIBC:*=ppc): $(OBJECTS:obj\=obj\ppc\) $(HELPER_OBJECTS:obj\=obj\ppc\) $(CRT_OBJECTS:*=ppc) $(INITOBJECTS:*=ppc) makefile.
+ lib -out:$@ @<<
+-machine:ppc
+$(OBJECTS:obj\=obj\ppc\)
+$(CRT_OBJECTS:*=ppc)
+$(INITOBJECTS:*=ppc)
+<<
+
+
+!IF "$(TARGETNAMESUFFIX)" == "dll"
+
+!IF $(386)
+
+$(CRTEXE:*=i386): $(CRTEXE:obj\*=dllstuff\obj\i386)
+ -copy $** $@
+
+$(CRTEXEW:*=i386): $(CRTEXEW:obj\*=dllstuff\obj\i386)
+ -copy $** $@
+
+$(CRTDLL:*=i386): $(CRTDLL:obj\*=dllstuff\obj\i386)
+ -copy $** $@
+
+$(CINITEXE:*=i386): $(CINITEXE:obj\*=dllstuff\obj\i386)
+ -copy $** $@
+
+$(DLLARGV:*=i386): $(DLLARGV:obj\*=dllstuff\obj\i386)
+ -copy $** $@
+
+$(DLLMAIN:*=i386): $(DLLMAIN:obj\*=startup\obj\i386)
+ -copy $** $@
+
+$(DLLSUPP386): $(DLLSUPP386:obj\i386=dllstuff\obj\i386)
+ -copy $** $@
+
+!ELSEIF $(MIPS)
+
+$(CRTEXE:*=mips): $(CRTEXE:obj\*=dllstuff\obj\mips)
+ -copy $** $@
+
+$(CRTEXEW:*=mips): $(CRTEXEW:obj\*=dllstuff\obj\mips)
+ -copy $** $@
+
+$(CRTDLL:*=mips): $(CRTDLL:obj\*=dllstuff\obj\mips)
+ -copy $** $@
+
+$(CINITEXE:*=mips): $(CINITEXE:obj\*=dllstuff\obj\mips)
+ -copy $** $@
+
+$(DLLARGV:*=mips): $(DLLARGV:obj\*=dllstuff\obj\mips)
+ -copy $** $@
+
+$(DLLMAIN:*=mips): $(DLLMAIN:obj\*=startup\obj\mips)
+ -copy $** $@
+
+!ELSEIF $(PPC)
+
+$(CRTEXE:*=ppc): $(CRTEXE:obj\*=dllstuff\obj\ppc)
+ -copy $** $@
+
+$(CRTEXEW:*=ppc): $(CRTEXEW:obj\*=dllstuff\obj\ppc)
+ -copy $** $@
+
+$(CRTDLL:*=ppc): $(CRTDLL:obj\*=dllstuff\obj\ppc)
+ -copy $** $@
+
+$(CINITEXE:*=ppc): $(CINITEXE:obj\*=dllstuff\obj\ppc)
+ -copy $** $@
+
+$(DLLARGV:*=ppc): $(DLLARGV:obj\*=dllstuff\obj\ppc)
+ -copy $** $@
+
+$(DLLMAIN:*=ppc): $(DLLMAIN:obj\*=startup\obj\ppc)
+ -copy $** $@
+
+!ELSE
+
+$(CRTEXE:*=alpha): $(CRTEXE:obj\*=dllstuff\obj\alpha)
+ -copy $** $@
+
+$(CRTEXEW:*=alpha): $(CRTEXEW:obj\*=dllstuff\obj\alpha)
+ -copy $** $@
+
+$(CRTDLL:*=alpha): $(CRTDLL:obj\*=dllstuff\obj\alpha)
+ -copy $** $@
+
+$(CINITEXE:*=alpha): $(CINITEXE:obj\*=dllstuff\obj\alpha)
+ -copy $** $@
+
+$(DLLARGV:*=alpha): $(DLLARGV:obj\*=dllstuff\obj\alpha)
+ -copy $** $@
+
+$(DLLMAIN:*=alpha): $(DLLMAIN:obj\*=startup\obj\alpha)
+ -copy $** $@
+
+!ENDIF
+
+!ELSEIF "$(TARGETNAMESUFFIX)" == ""
+
+!IF $(386)
+
+$(BINMODE:*=i386): $(BINMODE:obj\*=linkopts\obj\i386)
+ -copy $** $@
+
+$(COMMODE:*=i386): $(COMMODE:obj\*=linkopts\obj\i386)
+ -copy $** $@
+
+$(SETARGV:*=i386): $(SETARGV:obj\*=linkopts\obj\i386)
+ -copy $** $@
+
+$(CHKSTK:*=i386): $(CHKSTK:obj\*=startup\obj\i386)
+ -copy $** $@
+
+!ELSEIF $(MIPS)
+
+$(BINMODE:*=mips): $(BINMODE:obj\*=linkopts\obj\mips)
+ -copy $** $@
+
+$(COMMODE:*=mips): $(COMMODE:obj\*=linkopts\obj\mips)
+ -copy $** $@
+
+$(SETARGV:*=mips): $(SETARGV:obj\*=linkopts\obj\mips)
+ -copy $** $@
+
+$(CHKSTK:*=mips): $(CHKSTK:obj\*=startup\obj\mips)
+ -copy $** $@
+
+!ELSEIF $(PPC)
+
+$(BINMODE:*=ppc): $(BINMODE:obj\*=linkopts\obj\ppc)
+ -copy $** $@
+
+$(COMMODE:*=ppc): $(COMMODE:obj\*=linkopts\obj\ppc)
+ -copy $** $@
+
+$(SETARGV:*=ppc): $(SETARGV:obj\*=linkopts\obj\ppc)
+ -copy $** $@
+
+$(CHKSTK:*=ppc): $(CHKSTK:obj\*=startup\obj\ppc)
+ -copy $** $@
+
+!ELSE
+
+$(BINMODE:*=alpha): $(BINMODE:obj\*=linkopts\obj\alpha)
+ -copy $** $@
+
+$(COMMODE:*=alpha): $(COMMODE:obj\*=linkopts\obj\alpha)
+ -copy $** $@
+
+$(SETARGV:*=alpha): $(SETARGV:obj\*=linkopts\obj\alpha)
+ -copy $** $@
+
+$(CHKSTK:*=alpha): $(CHKSTK:obj\*=startup\obj\alpha)
+ -copy $** $@
+
+!ENDIF
+!ENDIF
diff --git a/private/crt32/mbstring/i386/ismbbyte.sav b/private/crt32/mbstring/i386/ismbbyte.sav
new file mode 100644
index 000000000..7953a7886
--- /dev/null
+++ b/private/crt32/mbstring/i386/ismbbyte.sav
@@ -0,0 +1,205 @@
+ page ,132
+ title ismbbyte - Function versions of MBCS ctype macros
+;***
+;ismbbyte.asm - Function versions of MBCS ctype macros.
+;
+; Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; This files provides function versions of the character
+; classification and conversion macros in mbctype.h.
+;
+;Revision History:
+; 06-12-90 YSO Created
+; 06-13-90 YSO Added support for model-independent function
+; (internal function)
+; 04-24-91 JCR MBCS generalization/enhancement
+; 07-17-91 JLM Generalized _MK (Kana moji bit mask) to _MS (MBCS
+; single byte symbol).
+; 08-09-91 JLM Changed file name from _mbctype.asm to mbscfcn.asm
+; 08-15-91 JLM Standardized ifdefs for model-independent function.
+; 08-20-91 JLM Changed ismb* to ismbb*.
+; 08-28-91 JLM Changed file/function names to MBCS spec.
+;
+;*******************************************************************************
+
+.xlist
+include version.inc
+include cmacros.inc
+.list
+
+
+; Define masks
+
+; set bit masks for the possible kanji character types
+; (all MBCS bit masks start with "_M")
+
+_MS equ 01h ; MBCS non-ascii single byte char
+_MP equ 02h ; MBCS punct
+_M1 equ 04h ; MBCS 1st (lead) byte
+_M2 equ 08h ; MBCS 2nd byte
+
+; set bit masks for the possible character types
+
+_UPPER equ 01h ; upper case letter
+_LOWER equ 02h ; lower case letter
+_DIGIT equ 04h ; digit[0-9]
+_SPACE equ 08h ; tab, carriage return, newline,
+ ; vertical tab or form feed
+_PUNCT equ 10h ; punctuation character
+_CONTROL equ 20h ; control character
+_BLANK equ 40h ; space char
+_HEX equ 80h ; hexadecimal digit
+
+sBegin data
+ assumes ds,data
+ extrn __mbctype:byte ; MBCS ctype table
+ extrn __ctype_:byte ; ANSI/ASCII ctype table
+sEnd
+
+
+sBegin code
+
+ assumes cs,code
+ assumes ds,data
+
+page
+;***
+; ismbbyte - Function versions of mbctype macros
+;
+;Purpose:
+;
+;Entry:
+; int = character to be tested
+;Exit:
+; ax = non-zero = character is of the requested type
+; = 0 = character is NOT of the requested type
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ifndef MODELINDEP
+
+ifdef _KANJI
+
+ public __ismbbkalnum
+__ismbbkalnum:
+ mov ax, _MS
+ jmp short mbctype
+
+ public __ismbbkpunct
+__ismbbkpunct:
+ mov ax, _MP
+ jmp short mbctype
+
+ public __ismbbkana
+__ismbbkana:
+ mov ax, (_MS OR _MP)
+ jmp short mbctype
+
+endif
+
+
+ public __ismbbalpha
+__ismbbalpha:
+ mov ah, (_UPPER OR _LOWER)
+ mov al, _MS
+ jmp short mbctype
+
+ public __ismbbpunct
+__ismbbpunct:
+ mov ah, _PUNCT
+ mov al, _MP
+ jmp short mbctype
+
+ public __ismbbalnum
+__ismbbalnum:
+ mov ah, (_UPPER OR _LOWER OR _DIGIT)
+ mov al, _MS
+ jmp short mbctype
+
+ public __ismbbprint
+__ismbbprint:
+ mov ah, (_BLANK OR _PUNCT OR _UPPER OR _LOWER OR _DIGIT)
+ mov al, (_MS OR _MP)
+ jmp short mbctype
+
+ public __ismbbgraph
+__ismbbgraph:
+ mov ah, (_PUNCT OR _UPPER OR _LOWER OR _DIGIT)
+ mov al, (_MS OR _MP)
+ jmp short mbctype
+
+ public __ismbblead
+__ismbblead:
+ mov ax,_M1
+ jmp short mbctype
+
+ public __ismbbtrail
+__ismbbtrail:
+ mov ax,_M2
+ jmp short mbctype
+
+else ; MODELINDEP
+
+ public __fismbblead
+__fismbblead:
+ mov ax,_M1
+ jmp short mbctype
+
+ public __fismbbtrail
+__fismbbtrail:
+ mov ax,_M2
+ jmp short mbctype
+
+endif ; MODELINDEP
+
+;
+; Common code
+;
+; ax = character mask
+;
+; al = mask for _mbctype[] table
+; ah = mask for _ctype[] table
+;
+
+cProc mbctype,<LOCAL>,<>
+
+ parmW char
+
+cBegin
+
+ifdef _LOAD_DGROUP
+ push ds
+ mov bx,DGROUP
+ mov ds,bx
+else
+ifdef MODELINDEP
+ push ds
+ mov bx,DGROUP
+ mov ds,bx
+endif
+endif
+
+ mov bx,[char] ; get input character
+ cmp ah, 0 ; any non-MBCS comparison?
+ jz @F ; jump, if not
+ and ah, [bx + __ctype_ + 1] ; test _ctype[] entry
+@@:
+ and al, [bx + __mbctype + 1] ; test _mbctype[] entry
+ifdef _LOAD_DGROUP
+ pop ds
+else
+ifdef MODELINDEP
+ pop ds
+endif
+endif
+
+cEnd <nolocals>
+
+sEnd
+
+ end
diff --git a/private/crt32/mbstring/i386/mbcsinit.os2 b/private/crt32/mbstring/i386/mbcsinit.os2
new file mode 100644
index 000000000..cb8efab35
--- /dev/null
+++ b/private/crt32/mbstring/i386/mbcsinit.os2
@@ -0,0 +1,55 @@
+ page ,132
+ title mbcsinit - Initialize MBCS
+;***
+;mbcsinit.asm - Initialize MBCS
+;
+; Copyright (c) 1991-1992, Microsoft Corporation. All Rights Reserved.
+;
+;Purpose:
+; This routine is necessary for the startup code to save the
+; initial the MBCS package (get lead byte table from OS, etc.).
+;
+; [Only used in _MBCS_OS builds.]
+;
+;Revision History:
+; 02-05-92 JCR Module created
+;
+;*******************************************************************************
+
+IFDEF _MBCS_OS
+
+?DF = 1 ; tell cmacros.inc we want to define our own segments
+
+include version.inc
+.xlist
+include cmacros.inc
+include defsegs.inc
+.list
+
+CrtDefSegs <code, data>
+CrtDefSegs <xiseg>
+
+page
+
+sBegin data
+assumes ds,data
+
+ globalW _mbcsflag,0
+
+sEnd
+
+externP _mbcsinit
+
+sBegin xiseg
+
+if sizeC
+ dd _mbcsinit
+else
+ dw _mbcsinit
+endif
+
+sEnd
+
+ENDIF ;_MBCS_OS
+
+ end
diff --git a/private/crt32/mbstring/i386/mbscat.asm b/private/crt32/mbstring/i386/mbscat.asm
new file mode 100644
index 000000000..b0c042fe9
--- /dev/null
+++ b/private/crt32/mbstring/i386/mbscat.asm
@@ -0,0 +1,18 @@
+;***
+;mbscat.asm - contains mbscat() and mbscpy() routines
+;
+; Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; STRCAT concatenates (appends) a copy of the source string to the
+; end of the destination string, returning the destination string.
+;
+;Revision History:
+; 11-18-92 KRS Identical to strcat/strcpy. Could use alias records.
+;
+;*******************************************************************************
+
+strcat EQU <_mbscat>
+strcpy EQU <_mbscpy>
+ include ..\string\i386\strcat.asm
+ end
diff --git a/private/crt32/mbstring/i386/mbsdup.asm b/private/crt32/mbstring/i386/mbsdup.asm
new file mode 100644
index 000000000..e818a4cde
--- /dev/null
+++ b/private/crt32/mbstring/i386/mbsdup.asm
@@ -0,0 +1,16 @@
+;***
+;mbsdup.asm - duplicate a string in malloc'd memory
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _mbsdup() - grab new memory, and duplicate the string into it.
+;
+;Revision History:
+; 11-18-92 KRS Identical to strdup. Could just use alias records.
+;
+;*******************************************************************************
+
+_strdup EQU <_mbsdup>
+ include ..\string\i386\strdup.asm
+ end
diff --git a/private/crt32/mbstring/ismbalph.c b/private/crt32/mbstring/ismbalph.c
new file mode 100644
index 000000000..28c8b1cd3
--- /dev/null
+++ b/private/crt32/mbstring/ismbalph.c
@@ -0,0 +1,67 @@
+/***
+*ismbalph.c - Test if character is alphabetic (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Test if character is alphabetic (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _ismbcalpha - Test if character is alphabetic (MBCS)
+*
+*Purpose:
+* Test if character is alphabetic.
+* Handles MBCS chars correctly.
+*
+* Note: Use test against 0x00FF instead of _ISLEADBYTE
+* to ensure that we don't call SBCS routine with a two-byte
+* value.
+*
+*Entry:
+* unsigned int c = character to test
+*
+*Exit:
+* Returns TRUE if c is alphabetic, else FALSE
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbcalpha(c)
+unsigned int c;
+{
+ if (c > 0x00FF)
+
+#ifdef _MBCS_OS
+ return (0);
+#else
+ {
+ if (_mbascii)
+ return (
+ ((c >= _MBLOWERLOW) && (c <= _MBLOWERHIGH)) ||
+ ((c >= _MBUPPERLOW) && (c <= _MBUPPERHIGH))
+ );
+ else
+ return (0);
+ }
+#endif
+
+ else
+
+ return (isalpha(c)); // macro version
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/ismbbyte.c b/private/crt32/mbstring/ismbbyte.c
new file mode 100644
index 000000000..b494284d3
--- /dev/null
+++ b/private/crt32/mbstring/ismbbyte.c
@@ -0,0 +1,148 @@
+/***
+*ismbbyte.c - Function versions of MBCS ctype macros
+*
+* Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This files provides function versions of the character
+* classification a*d conversion macros in mbctype.h.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit assembler sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+#if (_MSC_VER<800)
+#define __fastcall _CRTAPI3
+#endif
+
+/* defined in mbctype.h
+; Define masks
+
+; set bit masks for the possible kanji character types
+; (all MBCS bit masks start with "_M")
+
+_MS equ 01h ; MBCS non-ascii single byte char
+_MP equ 02h ; MBCS punct
+_M1 equ 04h ; MBCS 1st (lead) byte
+_M2 equ 08h ; MBCS 2nd byte
+
+*/
+
+/* defined in ctype.h
+; set bit masks for the possible character types
+
+_UPPER equ 01h ; upper case letter
+_LOWER equ 02h ; lower case letter
+_DIGIT equ 04h ; digit[0-9]
+_SPACE equ 08h ; tab, carriage return, newline,
+ ; vertical tab or form feed
+_PUNCT equ 10h ; punctuation character
+_CONTROL equ 20h ; control character
+_BLANK equ 40h ; space char
+_HEX equ 80h ; hexadecimal digit
+
+*/
+
+/* defined in ctype.h, mbdata.h
+ extrn __mbctype:byte ; MBCS ctype table
+ extrn __ctype_:byte ; ANSI/ASCII ctype table
+*/
+
+
+/***
+* ismbbyte - Function versions of mbctype macros
+*
+*Purpose:
+*
+*Entry:
+* int = character to be tested
+*Exit:
+* ax = non-zero = character is of the requested type
+* = 0 = character is NOT of the requested type
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef _KANJI
+
+int __fastcall x_ismbctype(unsigned int, int, int);
+
+int (_CRTAPI1 _ismbbkalnum) (unsigned int tst)
+{
+ return x_ismbctype(tst,0,_MS);
+}
+
+int (_CRTAPI1 _ismbbkpunct) (unsigned int tst)
+{
+ return x_ismbctype(tst,0,_MP);
+}
+
+int (_CRTAPI1 _ismbbkana) (unsigned int tst)
+{
+ return x_ismbctype(tst,0,(_MS | _MP));
+}
+
+int (_CRTAPI1 _ismbbalpha) (unsigned int tst)
+{
+ return x_ismbctype(tst,_ALPHA, _MS);
+}
+
+int (_CRTAPI1 _ismbbpunct) (unsigned int tst)
+{
+ return x_ismbctype(tst,_PUNCT, _MP);
+}
+
+int (_CRTAPI1 _ismbbalnum) (unsigned int tst)
+{
+ return x_ismbctype(tst,(_ALPHA | _DIGIT), _MS);
+}
+
+int (_CRTAPI1 _ismbbprint) (unsigned int tst)
+{
+ return x_ismbctype(tst,(_BLANK | _PUNCT | _ALPHA | _DIGIT),(_MS | _MP));
+}
+
+int (_CRTAPI1 _ismbbgraph) (unsigned int tst)
+{
+ return x_ismbctype(tst,(_PUNCT | _ALPHA | _DIGIT),(_MS | _MP));
+}
+
+int (_CRTAPI1 _ismbblead) (unsigned int tst)
+{
+ return x_ismbctype(tst,0,_M1);
+}
+
+int (_CRTAPI1 _ismbbtrail) (unsigned int tst)
+{
+ return x_ismbctype(tst,0,_M2);
+}
+
+/***
+* Common code
+*
+* cmask = mask for _ctype[] table
+* kmask = mask for _mbctype[] table
+*
+*******************************************************************************/
+
+static int __fastcall x_ismbctype (unsigned int tst, int cmask, int kmask)
+{
+ tst = (unsigned int)(unsigned char)tst; /* get input character
+ and make sure < 256 */
+ return ((*(_mbctype+1+tst)) & kmask) ||
+ ((cmask) ? ((*(_ctype+1+tst)) & cmask) : 0);
+}
+#endif /* _KANJI */
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/ismbdgt.c b/private/crt32/mbstring/ismbdgt.c
new file mode 100644
index 000000000..e5733261e
--- /dev/null
+++ b/private/crt32/mbstring/ismbdgt.c
@@ -0,0 +1,60 @@
+/***
+*ismbdgt.c - Test if character is a digit (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Test if character is a digit (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* _ismbcdigit - Test if character is a digit (MBCS)
+*
+*Purpose:
+* Tests the character to see if it is a digit.
+* Handles MBCS chars correctly.
+*
+* Note: Use test against 0x00FF instead of _ISLEADBYTE
+* to ensure that we don't call SBCS routine with a two-byte
+* value.
+*
+*Entry:
+* unsigned int *c = character to test
+*
+*Exit:
+* Returns TRUE if character is a digit, else FALSE
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbcdigit(c)
+unsigned int c;
+{
+
+ if (c > 0x00FF)
+
+#ifdef _MBCS_OS
+ return (0);
+#else
+ if (_mbascii)
+ return ((c >= _MBDIGITLOW) && (c <= _MBDIGITHIGH));
+ else
+ return (0);
+#endif
+
+ else
+ return (isdigit(c));
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/ismbknj.c b/private/crt32/mbstring/ismbknj.c
new file mode 100644
index 000000000..f71f55674
--- /dev/null
+++ b/private/crt32/mbstring/ismbknj.c
@@ -0,0 +1,93 @@
+/***
+*ismbcknj.c - contains the Kanji specific is* functions.
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Provide non-portable Kanji support for MBCS libs.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#ifdef _KANJI
+
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+
+
+/***
+*int _ismbchira(c) - test character for hiragana (Japanese)
+*
+*Purpose:
+* Test if the character c is a hiragana character.
+*
+*Entry:
+* unsigned int c - character to test
+*
+*Exit:
+* returns TRUE if character is hiragana, else FALSE
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbchira(c)
+unsigned int c;
+{
+ return(c >= 0x829f && c <= 0x82f1);
+}
+
+
+/***
+*int _ismbckata(c) - test character for katakana (Japanese)
+*
+*Purpose:
+* Tests to see if the character c is a katakana character.
+*
+*Entry:
+* unsigned int c - character to test
+*
+*Exit:
+* Returns TRUE if c is a katakana character, else FALSE.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbckata(c)
+unsigned int c;
+{
+ return(c >= 0x8340 && c <= 0x8396 && c != 0x837f);
+}
+
+
+/***
+*int _ismbcsymbol(c) - Tests if char is punctuation or symbol of Microsoft Kanji
+* code.
+*
+*Purpose:
+* Returns non-zero if the character is kanji punctuation.
+*
+*Entry:
+* unsigned int c - character to be tested
+*
+*Exit:
+* Returns non-zero if the specified char is punctuation or symbol of
+* Microsoft Kanji code, else 0.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbcsymbol(c)
+unsigned int c;
+{
+ return(c >= 0x8141 && c <= 0x81ac && c != 0x817f);
+}
+
+#endif /* _KANJI */
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/ismblgl.c b/private/crt32/mbstring/ismblgl.c
new file mode 100644
index 000000000..d08249b7a
--- /dev/null
+++ b/private/crt32/mbstring/ismblgl.c
@@ -0,0 +1,42 @@
+/***
+*ismblgl.c - Tests to see if a given character is a legal MBCS char.
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Tests to see if a given character is a legal MBCS character.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+*int _ismbclegal(c) - tests for a valid MBCS character.
+*
+*Purpose:
+* Tests to see if a given character is a legal MBCS character.
+*
+*Entry:
+* unsigned int c - character to test
+*
+*Exit:
+* returns non-zero if Microsoft Kanji code, else 0
+*
+*Exceptions:
+*
+******************************************************************************/
+
+int _CRTAPI1 _ismbclegal(c)
+unsigned int c;
+{
+ return((_ISLEADBYTE(c>>8)) && (_ISTRAILBYTE(c&0377)));
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/ismblwr.c b/private/crt32/mbstring/ismblwr.c
new file mode 100644
index 000000000..e88658ad4
--- /dev/null
+++ b/private/crt32/mbstring/ismblwr.c
@@ -0,0 +1,63 @@
+/***
+*ismblwr - Test if character is lower case (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Test if character is lower case (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _ismbclower - Test if character is lower case (MBCS)
+*
+*Purpose:
+* Test if the supplied character is lower case or not.
+* Handles MBCS characters correctly.
+*
+* Note: Use test against 0x00FF instead of _ISLEADBYTE
+* to ensure that we don't call SBCS routine with a two-byte
+* value.
+*
+*Entry:
+* unsigned int c = character to test
+*
+*Exit:
+* returns TRUE if character is lower case, else FALSE
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbclower(c)
+unsigned int c;
+{
+
+ if (c > 0x00FF)
+
+#ifdef _MBCS_OS
+ return (0);
+#else
+ {
+ if (_mbascii)
+ return ((c >= _MBLOWERLOW) && (c <= _MBLOWERHIGH));
+ else
+ return (0);
+ }
+#endif
+
+ else
+ return (islower(c));
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/ismbprn.c b/private/crt32/mbstring/ismbprn.c
new file mode 100644
index 000000000..8bd2b858a
--- /dev/null
+++ b/private/crt32/mbstring/ismbprn.c
@@ -0,0 +1,60 @@
+/***
+*ismbprn.c - Test character for display character (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Test character for display character (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _ismbcprint - Test character for display character (MBCS)
+*
+*Purpose:
+* Test if the character is a display character.
+* Handles MBCS chars correctly.
+*
+* Note: Use test against 0x00FF to ensure that we don't
+* call SBCS routine with a two-byte value.
+*
+*Entry:
+* unsigned int c = character to test
+*
+*Exit:
+* Returns TRUE if character is display character, else FALSE
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbcprint(c)
+unsigned int c;
+{
+
+ if (_ISLEADBYTE(c>>8))
+ return (_ISTRAILBYTE(c&0x00ff));
+
+ else {
+ if (c > 0x00FF)
+ return(0);
+ else
+#ifdef _KANJI
+ return ((isprint(c)) || (_ismbbkana(c)));
+#else
+ return (isprint(c));
+#endif
+ }
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/ismbsle.c b/private/crt32/mbstring/ismbsle.c
new file mode 100644
index 000000000..c4f9a0d02
--- /dev/null
+++ b/private/crt32/mbstring/ismbsle.c
@@ -0,0 +1,58 @@
+/***
+*ismbslead.c - True _ismbslead function
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the function _ismbslead, which is a true context-sensitive
+* MBCS lead-byte function. While much less efficient than _ismbblead,
+* it is also much more sophisticated, in that it determines whether a
+* given sub-string pointer points to a lead byte or not, taking into
+* account the context in the string.
+*
+*Revision History:
+*
+* 08-03-93 KRS Ported from 16-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <stddef.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* int _ismbslead(const unsigned char *string, const unsigned char *current);
+*
+*Purpose:
+*
+* _ismbslead - Check, in context, for MBCS lead byte
+*
+*Entry:
+* unsigned char *string - ptr to start of string or previous known lead byte
+* unsigned char *current - ptr to position in string to be tested
+*
+*Exit:
+* TRUE : -1
+* FALSE : 0
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbslead(const unsigned char *string, const unsigned char *current)
+{
+ while (string <= current && *string) {
+ if (_ISLEADBYTE((*string))) {
+ if (string++ == current) /* check lead byte */
+ return -1;
+ if (!(*string))
+ return 0;
+ }
+ ++string;
+ }
+ return 0;
+}
+#endif
diff --git a/private/crt32/mbstring/ismbspc.c b/private/crt32/mbstring/ismbspc.c
new file mode 100644
index 000000000..8cdfdf158
--- /dev/null
+++ b/private/crt32/mbstring/ismbspc.c
@@ -0,0 +1,61 @@
+/***
+*ismbspc.c - Test is character is whitespace (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Test is character is whitespace (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _ismbcspace - Test is character is whitespace (MBCS)
+*
+*Purpose:
+* Test if the character is a whitespace character.
+* Handles MBCS chars correctly.
+*
+* Note: Use test against 0x00FF instead of _ISLEADBYTE
+* to ensure that we don't call SBCS routine with a two-byte
+* value.
+*
+*Entry:
+* unsigned int c = character to test
+*
+*Exit:
+* Returns TRUE if character is whitespace, else FALSE
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbcspace(c)
+unsigned int c;
+{
+
+ if (c > 0x00FF)
+
+#ifdef _MBCS_OS
+ return (0);
+#else
+ if (_mbascii)
+ return (c == _MBSPACECHAR);
+ else
+ return (0);
+#endif
+
+ else
+ return (isspace(c));
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/ismbstr.c b/private/crt32/mbstring/ismbstr.c
new file mode 100644
index 000000000..628296702
--- /dev/null
+++ b/private/crt32/mbstring/ismbstr.c
@@ -0,0 +1,58 @@
+/***
+*ismbstrail.c - True _ismbstrail function
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the function _ismbstrail, which is a true context-sensitive
+* MBCS trail-byte function. While much less efficient than _ismbbtrail,
+* it is also much more sophisticated, in that it determines whether a
+* given sub-string pointer points to a trail byte or not, taking into
+* account the context in the string.
+*
+*Revision History:
+*
+* 08-03-93 KRS Ported from 16-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <stddef.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* int _ismbstrail(const unsigned char *string, const unsigned char *current);
+*
+*Purpose:
+*
+* _ismbstrail - Check, in context, for MBCS trail byte
+*
+*Entry:
+* unsigned char *string - ptr to start of string or previous known lead byte
+* unsigned char *current - ptr to position in string to be tested
+*
+*Exit:
+* TRUE : -1
+* FALSE : 0
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbstrail(const unsigned char *string, const unsigned char *current)
+{
+ while (string <= current && *string) {
+ if (_ISLEADBYTE((*string))) {
+ if (++string == current) /* check trail byte */
+ return -1;
+ if (!(*string))
+ return 0;
+ }
+ ++string;
+ }
+ return 0;
+}
+#endif
diff --git a/private/crt32/mbstring/ismbupr.c b/private/crt32/mbstring/ismbupr.c
new file mode 100644
index 000000000..3286754d0
--- /dev/null
+++ b/private/crt32/mbstring/ismbupr.c
@@ -0,0 +1,63 @@
+/***
+*ismbupr - Test if character is upper case (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Test if character is upper case (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _ismbcupper - Test if character is upper case (MBCS)
+*
+*Purpose:
+* Test if the supplied character is upper case or not.
+* Handles MBCS characters correctly.
+*
+* Note: Use test against 0x00FF instead of _ISLEADBYTE
+* to ensure that we don't call SBCS routine with a two-byte
+* value.
+*
+*Entry:
+* unsigned int c = character to test
+*
+*Exit:
+* Returns TRUE if c is an upper case character; else FALSE
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbcupper(c)
+unsigned int c;
+{
+
+ if (c > 0x00FF)
+
+#ifdef _MBCS_OS
+ return (0);
+#else
+ {
+ if (_mbascii)
+ return ((c >= _MBUPPERLOW) && (c <= _MBUPPERHIGH));
+ else
+ return (0);
+ }
+#endif
+
+ else
+ return (isupper(c));
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/makefile b/private/crt32/mbstring/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/mbstring/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/mbstring/makefile.knj b/private/crt32/mbstring/makefile.knj
new file mode 100644
index 000000000..b16e9fd9d
--- /dev/null
+++ b/private/crt32/mbstring/makefile.knj
@@ -0,0 +1,508 @@
+#################################################
+# #
+# MBSTRING Directory Makefile #
+# #
+#################################################
+
+#################################################
+# #
+# Macros defining the C compiler and its flags #
+# #
+#################################################
+
+
+# Common objects
+COMM_O= \
+ $(LIBC)\mbcsinit.obj \
+ $(LIBC)\mbascii0.obj \
+ ..\mbascii1.obj \
+ \
+ $(LIBC)\ismbbyt.obj \
+ $(LIBC)\mbbtype.obj \
+ $(LIBC)\mbsbtyp.obj \
+ $(LIBC)\mbscat.obj \
+ $(LIBC)\mbschr.obj \
+ $(LIBC)\mbscmp.obj \
+ $(LIBC)\mbscpy.obj \
+ $(LIBC)\mbscspn.obj \
+ $(LIBC)\mbsdec.obj \
+ $(LIBC)\mbsdup.obj \
+ $(LIBC)\mbsicmp.obj \
+ $(LIBC)\mbsinc.obj \
+ $(LIBC)\mbslen.obj \
+ $(LIBC)\mbslwr.obj \
+ $(LIBC)\mbsnbcn.obj \
+ $(LIBC)\mbsncat.obj \
+ $(LIBC)\mbsnccn.obj \
+ $(LIBC)\mbsncmp.obj \
+ $(LIBC)\mbsncpy.obj \
+ $(LIBC)\mbsnext.obj \
+ $(LIBC)\mbsnicm.obj \
+ $(LIBC)\mbsninc.obj \
+ $(LIBC)\mbsnset.obj \
+ $(LIBC)\mbsrchr.obj \
+ $(LIBC)\mbsrev.obj \
+ $(LIBC)\mbsset.obj \
+ $(LIBC)\mbsspn.obj \
+ $(LIBC)\mbsspnp.obj \
+ $(LIBC)\mbspbrk.obj \
+ $(LIBC)\mbsstr.obj \
+ $(LIBC)\mbstok.obj \
+ $(LIBC)\mbsupr.obj \
+ \
+ $(LIBC)\strdec.obj \
+ $(LIBC)\strinc.obj \
+ $(LIBC)\strncnt.obj \
+ $(LIBC)\strspnp.obj \
+ $(LIBC)\strnext.obj \
+ $(LIBC)\strninc.obj \
+ \
+ $(LIBC)\ismbalph.obj \
+ $(LIBC)\ismbdgt.obj \
+ $(LIBC)\ismblgl.obj \
+ $(LIBC)\ismblwr.obj \
+ $(LIBC)\ismbprn.obj \
+ $(LIBC)\ismbspc.obj \
+ $(LIBC)\ismbupr.obj \
+ \
+ $(LIBC)\mbtolwr.obj \
+ $(LIBC)\mbtoupr.obj \
+ \
+ $(LIBC)\ismbknj.obj \
+ $(LIBC)\tojisjms.obj \
+ $(LIBC)\mbclevel.obj \
+ $(LIBC)\mbtohira.obj \
+ $(LIBC)\mbtokata.obj \
+ \
+ $(LIBC)\tombbmbc.obj
+
+# The following functions are Kanji specific, but at this time, the build
+# process will not allow a switch:
+# ismbknj.obj
+# tojisjms.obj
+# mbclevel.obj
+# mbtohira.obj
+# mbtokata.obj
+
+
+LIBH_O= \
+ $(LIBC)\fismbbyt.obj \
+ $(LIBC)\fmbbtype.obj \
+ $(LIBC)\fmbsbtyp.obj \
+ $(LIBC)\fmbscat.obj \
+ $(LIBC)\fmbschr.obj \
+ $(LIBC)\fmbscmp.obj \
+ $(LIBC)\fmbscpy.obj \
+ $(LIBC)\fmbscspn.obj \
+ $(LIBC)\fmbsdec.obj \
+ $(LIBC)\fmbsdup.obj \
+ $(LIBC)\fmbsicmp.obj \
+ $(LIBC)\fmbsinc.obj \
+ $(LIBC)\fmbslen.obj \
+ $(LIBC)\fmbslwr.obj \
+ $(LIBC)\fmbsnbcn.obj \
+ $(LIBC)\fmbsncat.obj \
+ $(LIBC)\fmbsnccn.obj \
+ $(LIBC)\fmbsncmp.obj \
+ $(LIBC)\fmbsncpy.obj \
+ $(LIBC)\fmbsnext.obj \
+ $(LIBC)\fmbsnicm.obj \
+ $(LIBC)\fmbsninc.obj \
+ $(LIBC)\fmbsnset.obj \
+ $(LIBC)\fmbsrchr.obj \
+ $(LIBC)\fmbsrev.obj \
+ $(LIBC)\fmbsset.obj \
+ $(LIBC)\fmbsspn.obj \
+ $(LIBC)\fmbsspnp.obj \
+ $(LIBC)\fmbspbrk.obj \
+ $(LIBC)\fmbsstr.obj \
+ $(LIBC)\fmbstok.obj \
+ $(LIBC)\fmbsupr.obj \
+ \
+ $(LIBC)\fstrdec.obj \
+ $(LIBC)\fstrinc.obj \
+ $(LIBC)\fstrncnt.obj \
+ $(LIBC)\fstrnext.obj \
+ $(LIBC)\fstrninc.obj \
+ $(LIBC)\fstrspnp.obj
+
+# DOS 3.x objects
+DOS_O= \
+ $(LIBC)\dos\mbctype.obj
+
+# Model-Independent Objects not specially built for libhcrt
+MI_O= \
+
+####### OS/2 BEGIN #######
+
+# OS/2 objects
+OS2_O= \
+ $(LIBC)\os2\mbctype.obj
+
+####### OS/2 END #######
+
+####### MTHREAD BEGIN #######
+
+# Multi-Thread and CRTDLL objects
+MTCRT_O= \
+# $(LIBC)\mbstok.obj \ ## Not supported yet. ##
+
+# Multi-Thread objects
+MT_O=
+
+# CRTDLL objects
+CRT_O= \
+ $(LIBC)\ismbbyt.obj \
+# $(LIBC)\mbstok.obj \ ## Not supported yet. ##
+
+
+####### MTHREAD END #######
+
+####### WINDOWS BEGIN #######
+
+# Windows objects
+WIN_O= \
+ $(LIBC)\mbcsinit.obj \
+ $(LIBC)\mbascii0.obj \
+ ..\mbascii1.obj \
+ \
+ $(LIBC)\mbbtype.obj \
+ $(LIBC)\mbsbtyp.obj \
+ $(LIBC)\mbscat.obj \
+ $(LIBC)\mbschr.obj \
+ $(LIBC)\mbscmp.obj \
+ $(LIBC)\mbscpy.obj \
+ $(LIBC)\mbscspn.obj \
+ $(LIBC)\mbsdec.obj \
+ $(LIBC)\mbsdup.obj \
+ $(LIBC)\mbsicmp.obj \
+ $(LIBC)\mbsinc.obj \
+ $(LIBC)\mbslen.obj \
+ $(LIBC)\mbslwr.obj \
+ $(LIBC)\mbsnbcn.obj \
+ $(LIBC)\mbsncat.obj \
+ $(LIBC)\mbsnccn.obj \
+ $(LIBC)\mbsnext.obj \
+ $(LIBC)\mbsnicm.obj \
+ $(LIBC)\mbsninc.obj \
+ $(LIBC)\mbsncmp.obj \
+ $(LIBC)\mbsncpy.obj \
+ $(LIBC)\mbsnset.obj \
+ $(LIBC)\mbsrchr.obj \
+ $(LIBC)\mbsrev.obj \
+ $(LIBC)\mbsset.obj \
+ $(LIBC)\mbsspn.obj \
+ $(LIBC)\mbsspnp.obj \
+ $(LIBC)\mbspbrk.obj \
+ $(LIBC)\mbsstr.obj \
+ $(LIBC)\mbstok.obj \
+ $(LIBC)\mbsupr.obj \
+ \
+ $(LIBC)\strdec.obj \
+ $(LIBC)\strinc.obj \
+ $(LIBC)\strncnt.obj \
+ $(LIBC)\strnext.obj \
+ $(LIBC)\strninc.obj \
+ $(LIBC)\strspnp.obj \
+ \
+ $(LIBC)\ismbalph.obj \
+ $(LIBC)\ismbdgt.obj \
+ $(LIBC)\ismblwr.obj \
+ $(LIBC)\ismbprn.obj \
+ $(LIBC)\ismbspc.obj \
+ $(LIBC)\ismbupr.obj \
+ \
+ $(LIBC)\ismbknj.obj \
+ $(LIBC)\mbclevel.obj \
+ $(LIBC)\mbtohira.obj \
+ $(LIBC)\mbtokata.obj \
+ $(LIBC)\tojisjms.obj \
+ \
+ $(LIBC)\mbtolwr.obj \
+ $(LIBC)\mbtoupr.obj \
+ \
+ $(LIBC)\tombbmbc.obj
+
+#
+# The functions/files
+# ismbknj.obj
+# mbclevel.obj
+# mbtohira.obj
+# mbtokata.obj
+# tojisjms.obj
+# are Kanji specific, and should not be included in other natural language
+# builds.
+#
+
+WINDLL_O=
+
+####### WINDOWS END #######
+
+#########################################################
+# #
+# Target Dependency listings #
+# #
+#########################################################
+
+libc: $(COMM_O) $(DOS_O) $(OS2_O)
+
+libh: $(LIBH_O) $(MI_O)
+
+libhcrt: $(LIBH_O)
+
+####### MTHREAD BEGIN #######
+
+libcmt: $(MT_O) $(MTCRT_O)
+
+libccrt: $(CRT_O) $(MTCRT_O)
+
+####### MTHREAD END #######
+
+####### WINDOWS BEGIN #######
+
+libcw: $(WIN_O) $(DOS_O)
+
+libcwdll: $(WINDLL_O)
+
+####### WINDOWS END #######
+
+#########################################################
+# #
+# Dependencies and rules for making local objects #
+# #
+#########################################################
+
+# Note: Some of the obj names are abbreviated so that
+# "f" versions will fit in the 8.3 filename space.
+
+#
+# MBCS init modules
+#
+
+$(LIBC)\mbcsinit.obj: mbcsinit.asm $(ASMSTD) $(ASMINC)\defsegs.inc
+ $(MM) -Fo$(LIBC)\mbcsinit.obj mbcsinit.asm
+
+$(LIBC)\mbascii0.obj: mbascii0.c $(INCLUDE)\mbdata.h
+ $(CC) $(MEM) -Fo$(LIBC)\mbascii0.obj mbascii0.c
+
+..\mbascii1.obj: mbascii1.c $(INCLUDE)\mbdata.h
+ $(CC) $(MEM) -Fo..\mbascii1.obj mbascii1.c
+
+#
+# MBCS "is" routines
+#
+
+$(LIBC)\ismbalph.obj: ismbalph.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\ctype.h
+ $(CC) $(MEM) -Fo$(LIBC)\ismbalph.obj ismbalph.c
+
+$(LIBC)\ismbdgt.obj: ismbdgt.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\ctype.h
+ $(CC) $(MEM) -Fo$(LIBC)\ismbdgt.obj ismbdgt.c
+
+$(LIBC)\ismblwr.obj: ismblwr.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\ctype.h
+ $(CC) $(MEM) -Fo$(LIBC)\ismblwr.obj ismblwr.c
+
+$(LIBC)\ismbprn.obj: ismbprn.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\ctype.h
+ $(CC) $(MEM) -Fo$(LIBC)\ismbprn.obj ismbprn.c
+
+$(LIBC)\ismbspc.obj: ismbspc.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\ctype.h
+ $(CC) $(MEM) -Fo$(LIBC)\ismbspc.obj ismbspc.c
+
+$(LIBC)\ismbupr.obj: ismbupr.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\ctype.h
+ $(CC) $(MEM) -Fo$(LIBC)\ismbupr.obj ismbupr.c
+
+#
+# Kanji specific "is" routines
+#
+
+$(LIBC)\ismbknj.obj: ismbknj.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\ctype.h
+ $(CC) $(MEM) -Fo$(LIBC)\ismbknj.obj ismbknj.c
+
+$(LIBC)\mbclevel.obj: mbclevel.c $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\mbclevel.obj mbclevel.c
+
+$(LIBC)\tojisjms.obj: tojisjms.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\tojisjms.obj tojisjms.c
+
+$(LIBC)\ismblgl.obj: ismblgl.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\ismblgl.obj ismblgl.c
+
+
+#
+# MBCS "to" routines
+#
+
+$(LIBC)\mbtolwr.obj: mbtolwr.c mbtolwr.c $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\mbtolwr.obj mbtolwr.c
+
+$(LIBC)\mbtoupr.obj: mbtoupr.c mbtoupr.c $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\mbtoupr.obj mbtoupr.c
+
+$(LIBC)\mbtohira.obj: mbtohira.c ismbknj.c $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\mbtohira.obj mbtohira.c
+
+$(LIBC)\mbtokata.obj: mbtokata.c ismbknj.c $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\mbtokata.obj mbtokata.c
+
+$(LIBC)\tombbmbc.obj: tombbmbc.c $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\tombbmbc.obj tombbmbc.c
+
+
+#
+# MBCS string routines
+#
+
+$(LIBC)\$(F)ismbbyt.obj: ismbbyte.asm $(ASMSTD)
+ $(MM) -Fo$(LIBC)\$(F)ismbbyt.obj ismbbyte.asm
+
+$(LIBC)\$(F)mbbtype.obj: mbbtype.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbbtype.obj mbbtype.c
+
+$(LIBC)\$(F)mbsbtyp.obj: mbsbtype.c $(INCLUDE)\mbstring.h $(INCLUDE)\mbctype.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsbtyp.obj mbsbtype.c
+
+$(LIBC)\$(F)mbscat.obj: mbscat.asm $(ASMSTD)
+ $(MM) -Fo$(LIBC)\$(F)mbscat.obj mbscat.asm
+
+$(LIBC)\$(F)mbschr.obj: mbschr.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbschr.obj mbschr.c
+
+$(LIBC)\$(F)mbscmp.obj: mbscmp.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbscmp.obj mbscmp.c
+
+$(LIBC)\$(F)mbscpy.obj: mbscpy.asm $(ASMSTD)
+ $(MM) -Fo$(LIBC)\$(F)mbscpy.obj mbscpy.asm
+
+$(LIBC)\$(F)mbscspn.obj: mbscspn.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbscspn.obj mbscspn.c
+
+$(LIBC)\$(F)mbsdec.obj: mbsdec.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsdec.obj mbsdec.c
+
+$(LIBC)\$(F)mbsdup.obj: mbsdup.asm $(ASMSTD)
+ $(MM) -Fo$(LIBC)\$(F)mbsdup.obj mbsdup.asm
+
+$(LIBC)\$(F)mbsicmp.obj: mbsicmp.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsicmp.obj mbsicmp.c
+
+$(LIBC)\$(F)mbsinc.obj: mbsinc.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsinc.obj mbsinc.c
+
+$(LIBC)\$(F)mbslen.obj: mbslen.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbslen.obj mbslen.c
+
+$(LIBC)\$(F)mbslwr.obj: mbslwr.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbslwr.obj mbslwr.c
+
+$(LIBC)\$(F)mbsncat.obj: mbsncat.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsncat.obj mbsncat.c
+
+$(LIBC)\$(F)mbsnbcn.obj: mbsnbcnt.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsnbcn.obj mbsnbcnt.c
+
+$(LIBC)\$(F)mbsnccn.obj: mbsnccnt.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsnccn.obj mbsnccnt.c
+
+$(LIBC)\$(F)mbsncmp.obj: mbsncmp.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsncmp.obj mbsncmp.c
+
+$(LIBC)\$(F)mbsncpy.obj: mbsncpy.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsncpy.obj mbsncpy.c
+
+$(LIBC)\$(F)mbsnext.obj: mbsnextc.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsnext.obj mbsnextc.c
+
+$(LIBC)\$(F)mbsnicm.obj: mbsnicmp.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsnicm.obj mbsnicmp.c
+
+$(LIBC)\$(F)mbsninc.obj: mbsninc.c $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsninc.obj mbsninc.c
+
+$(LIBC)\$(F)mbsnset.obj: mbsnset.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsnset.obj mbsnset.c
+
+$(LIBC)\$(F)mbsrchr.obj: mbsrchr.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsrchr.obj mbsrchr.c
+
+$(LIBC)\$(F)mbsrev.obj: mbsrev.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsrev.obj mbsrev.c
+
+$(LIBC)\$(F)mbsset.obj: mbsset.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsset.obj mbsset.c
+
+$(LIBC)\$(F)mbsspn.obj: mbsspn.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsspn.obj mbsspn.c
+
+$(LIBC)\$(F)mbsspnp.obj: mbsspn.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -D_RETURN_PTR -Fo$(LIBC)\$(F)mbsspnp.obj mbsspn.c
+
+$(LIBC)\$(F)mbspbrk.obj: mbscspn.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h
+ $(CC) $(MEM) -D_RETURN_PTR -Fo$(LIBC)\$(F)mbspbrk.obj mbscspn.c
+
+$(LIBC)\$(F)mbsstr.obj: mbsstr.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h $(INCLUDE)\string.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsstr.obj mbsstr.c
+
+$(LIBC)\$(F)mbstok.obj: mbstok.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbstok.obj mbstok.c
+
+$(LIBC)\$(F)mbsupr.obj: mbsupr.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)mbsupr.obj mbsupr.c
+
+#
+# SBCS equivilent MBCS-mapped routines
+#
+
+$(LIBC)\$(F)strdec.obj: strdec.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)strdec.obj strdec.c
+
+$(LIBC)\$(F)strinc.obj: strinc.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)strinc.obj strinc.c
+
+$(LIBC)\$(F)strncnt.obj: strncnt.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)strncnt.obj strncnt.c
+
+$(LIBC)\$(F)strnext.obj: strnextc.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)strnext.obj strnextc.c
+
+$(LIBC)\$(F)strninc.obj: strninc.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)strninc.obj strninc.c
+
+$(LIBC)\$(F)strspnp.obj: strspnp.c $(INCLUDE)\mbctype.h $(INCLUDE)\mbstring.h \
+ $(INCLUDE)\stddef.h
+ $(CC) $(MEM) -Fo$(LIBC)\$(F)strspnp.obj strspnp.c
+
+####### DOS BEGIN #######
+
+$(LIBC)\dos\mbctype.obj: mbctype.c $(INCLUDE)\mbctype.h
+ $(CC) $(MEM) -Fo$(LIBC)\dos\mbctype.obj mbctype.c
+
+####### DOS END #######
+
+####### OS2 BEGIN #######
+
+$(LIBC)\os2\mbctype.obj: mbctype.c $(INCLUDE)\mbctype.h $(INCLUDE)\doscalls.h
+ $(CC) $(MEM) -DOS2 -Fo$(LIBC)\os2\mbctype.obj mbctype.c
+
+####### OS2 END #######
diff --git a/private/crt32/mbstring/mbascii0.c b/private/crt32/mbstring/mbascii0.c
new file mode 100644
index 000000000..ca9a3bcf4
--- /dev/null
+++ b/private/crt32/mbstring/mbascii0.c
@@ -0,0 +1,33 @@
+/***
+*mbascii0.c - Disable MB ASCII Support
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Disable MB ASCII support (set _mbascii flag to 0).
+*
+* The _mbascii flag indicates whether the lib routines and
+* macros should operate on MB ASCII characters (i.e., the
+* double-byte versions of the ASCII characters that exist
+* in certain MBCS representations such as Kanji).
+*
+* In some cases, people want these to be worked on by the
+* various MB is/to/cmp routines. However, in most cases,
+* you do NOT want to do this (e.g., when modifying filenames,
+* you do NOT want to change the case of the MB ASCII chars
+* even though you DO want to change the case of the SB
+* ASCII chars.)
+*
+* [Also see mbascii1.C.]
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+
+unsigned int _mbascii = 0; /* 0 = do NOT operate on MB ASCII chars */
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbascii1.opt b/private/crt32/mbstring/mbascii1.opt
new file mode 100644
index 000000000..ef702d389
--- /dev/null
+++ b/private/crt32/mbstring/mbascii1.opt
@@ -0,0 +1,19 @@
+/***
+*mbascii1.c - Enable MB ASCII Support
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Enable MB ASCII support (set _mbascii flag to 1).
+*
+* [For complete description, see mbascii0.c.]
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <mbdata.h>
+
+unsigned int _mbascii = 1; /* !0 = operate on MB ASCII chars */
diff --git a/private/crt32/mbstring/mbbtype.c b/private/crt32/mbstring/mbbtype.c
new file mode 100644
index 000000000..4527b3a2d
--- /dev/null
+++ b/private/crt32/mbstring/mbbtype.c
@@ -0,0 +1,70 @@
+/***
+*mbbtype.c - Return type of byte based on previous byte (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Return type of byte based on previous byte (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+*int _mbbtype(c, ctype) - Return type of byte based on previous byte (MBCS)
+*
+*Purpose:
+* Returns type of supplied byte. This decision is context
+* sensitive so a control test condition is supplied. Normally,
+* this is the type of the previous byte in the string.
+*
+*Entry:
+* unsigned char c = character to be checked
+* int ctype = control test condition (i.e., type of previous char)
+*
+*Exit:
+* _MBC_LEAD = if 1st byte of MBCS char
+* _MBC_TRAIL = if 2nd byte of MBCS char
+* _MBC_SINGLE = valid single byte char
+*
+* _MBC_ILLEGAL = if illegal char
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mbbtype(c, ctype)
+unsigned char c;
+int ctype;
+{
+
+ switch(ctype) {
+
+ case(_MBC_LEAD):
+ if (_ISTRAILBYTE(c))
+ return(_MBC_TRAIL);
+ else
+ return(_MBC_ILLEGAL);
+
+ case(_MBC_TRAIL):
+ case(_MBC_SINGLE):
+ case(_MBC_ILLEGAL):
+ if (_ISLEADBYTE(c))
+ return(_MBC_LEAD);
+ else if (_ismbbprint(c))
+ return(_MBC_SINGLE);
+ else
+ return(_MBC_ILLEGAL);
+
+
+ }
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbccpy.c b/private/crt32/mbstring/mbccpy.c
new file mode 100644
index 000000000..e2fccb169
--- /dev/null
+++ b/private/crt32/mbstring/mbccpy.c
@@ -0,0 +1,47 @@
+/***
+*mbccpy.c - Copy one character to another (MBCS)
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Copy one MBCS character to another (1 or 2 bytes)
+*
+*Revision History:
+* 04-12-93 KRS Created.
+* 06-03-93 KRS Change return type to void.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+#include <stddef.h>
+
+/***
+* _mbccpy - Copy one character to another (MBCS)
+*
+*Purpose:
+* Copies exactly one MBCS character from src to dst. Copies _mbclen(src)
+* bytes from src to dst.
+*
+*Entry:
+* unsigned char *dst = destination for copy
+* unsigned char *src = source for copy
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _mbccpy(dst, src)
+unsigned char *dst;
+const unsigned char *src;
+{
+ *dst = *src;
+ if (_ISLEADBYTE(*src))
+ {
+ *++dst = *++src;
+ }
+}
diff --git a/private/crt32/mbstring/mbclen.c b/private/crt32/mbstring/mbclen.c
new file mode 100644
index 000000000..4d67a8e81
--- /dev/null
+++ b/private/crt32/mbstring/mbclen.c
@@ -0,0 +1,42 @@
+/***
+*mbclen.c - Find length of MBCS character
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Find length of MBCS character
+*
+*Revision History:
+* 04-12-93 KRS Created.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+#include <stddef.h>
+
+
+/***
+* _mbclen - Find length of MBCS character
+*
+*Purpose:
+* Find the length of the MBCS character (in bytes).
+*
+*Entry:
+* unsigned char *c = MBCS character
+*
+*Exit:
+* Returns the number of bytes in the MBCS character
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 _mbclen(c)
+const unsigned char *c;
+
+{
+ return (_ISLEADBYTE(*c)) ? 2 : 1;
+}
diff --git a/private/crt32/mbstring/mbclevel.c b/private/crt32/mbstring/mbclevel.c
new file mode 100644
index 000000000..340f734d1
--- /dev/null
+++ b/private/crt32/mbstring/mbclevel.c
@@ -0,0 +1,92 @@
+/***
+*mbclevel.c - Tests if char is hiragana, katakana, alphabet or digit.
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Tests for the various industry defined levels of Microsoft Kanji
+* Code.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#ifdef _KANJI
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+
+
+/***
+*int _ismbcl0(c) - Tests if char is hiragana, katakana, alphabet or digit.
+*
+*Purpose:
+* Tests if a given char is hiragana, katakana, alphabet, digit or symbol
+* of Microsoft Kanji code.
+*
+*Entry:
+* unsigned int c - Character to test.
+*
+*Exit:
+* Returns non-zero if 0x8140 <= c <= 0x889E, else 0.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbcl0(c)
+unsigned int c;
+{
+ return(_ismbclegal(c) && c < 0x889f);
+}
+
+
+/***
+*int _ismbcl1(c) - Tests for 1st-level Microsoft Kanji code set.
+*
+*Purpose:
+* Tests if a given char belongs to Microsoft 1st-level Kanji code set.
+*
+*Entry:
+* unsigned int c - character to test.
+*
+*Exit:
+* Returns non-zero if 1st-level, else 0.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbcl1(c)
+unsigned int c;
+{
+ return(_ismbclegal(c) && c >= 0x889f && c <= 0x9872);
+}
+
+
+/***
+*int _ismbcl2(c) - Tests for a 2nd-level Microsoft Kanji code character.
+*
+*Purpose:
+* Tests if a given char belongs to the Microsoft 2nd-level Kanji code set.
+*
+*Entry:
+* unsigned int c - character to test.
+*
+*Exit:
+* Returns non-zero if 2nd-level, else 0.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ismbcl2(c)
+unsigned int c;
+{
+ return(_ismbclegal(c) && c >= 0x989f && c <= 0xea9e);
+}
+
+#endif /* _KANJI */
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbctype.c b/private/crt32/mbstring/mbctype.c
new file mode 100644
index 000000000..7abdb1d34
--- /dev/null
+++ b/private/crt32/mbstring/mbctype.c
@@ -0,0 +1,318 @@
+/***
+*mbctype.c - MBCS table used by the functions that test for types of char
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* table used to determine the type of char
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-12-93 CFW Change _mbctype to _VARTYPE1 to allow DLL export.
+* 08-13-93 CFW Remove OS2 and rework for _WIN32_.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+
+#include <cruntime.h>
+#include <mbdata.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef _MBCS_OS
+
+#ifdef _WIN32_
+#include <windows.h>
+#endif /* _WIN32_ */
+
+/* local routines */
+static char * _mbcs_getlead(void);
+
+#endif /* _MBCS_OS */
+
+
+/*
+ * make sure this is being compiled correctly
+ */
+
+#if (!defined(_KANJI) && !defined(_MBCS_OS))
+#error Must specify MBCS locale.
+#endif
+
+#if (defined(_KANJI) && defined(_MBCS_OS))
+#error Can't define _KANJI and _MBCS_OS together.
+#endif
+
+
+/*
+ * set bit masks for the possible MBCS types
+ * (all MBCS bit masks start with "_M")
+ */
+
+#define _MS 0x01 /* MBCS single byte symbol */
+#define _MP 0x02 /* MBCS punct */
+#define _M1 0x04 /* MBCS 1st (lead) byte */
+#define _M2 0x08 /* MBCS 2nd byte*/
+
+/*
+ * MBCS ctype array
+ */
+
+#ifdef _KANJI
+
+/*
+ * Kanji Table: PreInitialized
+ */
+
+unsigned char _VARTYPE1 _mbctype[257] = {
+
+ 0,
+
+/* 0 1 2 3 4 5 6 7 */
+/*--------------+-------+-------+-------+-------+-------+-------+-------*/
+/*00*/ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*10*/ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*20*/ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*30*/ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*40*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*50*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*60*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*70*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, 0,
+/*80*/ _M2,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,
+ _M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,
+/*90*/ _M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,
+ _M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,
+/*A0*/ _M2,_M2|_MP,_M2|_MP,_M2|_MP,_M2|_MP,_M2|_MP,_M2|_MS,_M2|_MS,
+ _M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,
+/*B0*/ _M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,
+ _M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,
+/*C0*/ _M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,
+ _M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,
+/*D0*/ _M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,
+ _M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,_M2|_MS,
+/*E0*/ _M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,
+ _M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,
+/*F0*/ _M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,
+ _M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1,_M2|_M1, 0, 0, 0,
+
+};
+
+#endif
+
+
+#ifdef _MBCS_OS
+
+/*
+ * Generic Table - All bytes except NUL are legal trailing bytes
+ */
+
+unsigned char _VARTYPE1 _mbctype[257] = {
+
+ 0,
+
+/* 0 1 2 3 4 5 6 7 */
+/*--------------+-------+-------+-------+-------+-------+-------+-------*/
+/*00*/ 0, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*10*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*20*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*30*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*40*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*50*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*60*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*70*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*80*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*90*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*A0*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*B0*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*C0*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*D0*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*E0*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+/*F0*/ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+ _M2, _M2, _M2, _M2, _M2, _M2, _M2, _M2,
+
+};
+
+
+/***
+*_mbcsinit() - Init MBCS data
+*
+*Purpose:
+* Get MBCS data from the OS and init our table with it.
+*
+* (1) DOS: check for version 3.3 or later.
+* (2) call OS to get table
+*
+* This routine is meant to be called once (and only once)
+* at startup time.
+*Entry:
+* void
+*Exit:
+* void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _mbcsinit(void)
+{
+
+ unsigned char * lbtab;
+ unsigned char first, last, curr;
+
+
+#ifndef _WIN32_
+ /*
+ * DOS version must be 3.3 or better
+ */
+
+ if ( (_osmajor < 3) ||
+ (_osmajor == 3) && (_osminor < 3)
+ )
+ _mbfatal();
+#endif
+
+ /*
+ * get the lead byte table from OS
+ */
+
+ if ((lbtab = _mbcs_getlead()) == NULL)
+ return; // leave table all zeroes
+
+ /*
+ * walk through OS lead byte table flipping bits
+ * in the _mbctype[] table appropriately.
+ */
+
+ for (;;) {
+ first = *lbtab++;
+ last = *lbtab++;
+ if ((first == 0) && (last == 0))
+ break;
+
+ for (curr=first; curr<=last; curr++)
+ _mbctype[curr+1] |= _M1;
+
+ }
+}
+
+/***
+*_mbcs_getlead() - Get lead byte pairs from OS
+*
+*Purpose:
+* Gets the pairs of lead byte values from the OS.
+*
+*Entry:
+* void
+*
+*Exit:
+* void * = pointer to lead byte pairs
+* = NULL = error
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static char * _mbcs_getlead(void)
+{
+
+#ifdef _WIN32_
+
+ /* maximum # of leadbyte values */
+ #define _MAXLBVALS 12
+
+ static CPINFO info;
+ char *ev;
+ int cp;
+
+ if ((ev = getenv("MBCS_CP")) == NULL) {
+ cp = CP_ACP;
+ } else {
+ cp = atoi(ev);
+ }
+
+ /*
+ * get lead byte table from OS
+ */
+
+ if (!GetCPInfo(cp, &info))
+ return(NULL); /* failure */
+
+ return((unsigned char *)info.LeadByte); /* success */
+
+#else /* DOS */
+
+ _asm {
+ push ds
+
+ xor si,si
+ mov ds,si
+ mov ax,6300h
+ int 21h ; get lead byte table
+ jnc ok
+
+ xor si,si ; error: return NULL
+ mov ds,si
+ ok:
+ mov ax,si ; success: return ptr to table
+ mov dx,ds
+
+ pop ds
+ }
+
+#endif
+
+}
+
+#ifndef _WIN32_
+
+/***
+*_mbfatal() - Fatal MBCS error
+*
+*Purpose:
+* Terminate program
+*
+*Entry:
+* void
+*Exit:
+* void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 _mbfatal(void)
+{
+
+_asm {
+ mov ax,_RT_ABORT
+ jmp _amsg_exit
+ }
+}
+
+#endif /* _WIN32_ */
+#endif /* _MBCS_OS */
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsbtype.c b/private/crt32/mbstring/mbsbtype.c
new file mode 100644
index 000000000..cd87b273a
--- /dev/null
+++ b/private/crt32/mbstring/mbsbtype.c
@@ -0,0 +1,64 @@
+/***
+*mbsbtype.c - Return type of byte within a string (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Return type of byte within a string (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <mbctype.h>
+
+#define _MBBTYPE(p,c) _mbbtype(p,c)
+
+/***
+* _mbsbtype - Return type of byte within a string
+*
+*Purpose:
+* Test byte within a string for MBCS char type.
+* This function requires the start of the string because
+* context must be taken into account.
+*
+*Entry:
+* const unsigned char *string = pointer to string
+* size_t len = position of the char in string
+*
+*Exit:
+* returns one of the following values:
+*
+* _MBC_LEAD = if 1st byte of MBCS char
+* _MBC_TRAIL = if 2nd byte of MBCS char
+* _MBC_SINGLE = valid single byte char
+*
+* _MBC_ILLEGAL = if illegal char
+*
+*Exceptions:
+* returns _MBC_ILLEGAL if len is bigger than string length
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mbsbtype( string, len )
+const unsigned char *string;
+size_t len;
+{
+ int chartype = _MBC_ILLEGAL;
+
+ do {
+ if (*string == '\0')
+ return(_MBC_ILLEGAL);
+
+ chartype = _MBBTYPE(*string++, chartype);
+
+ } while (len--);
+
+ return(chartype);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbscat.c b/private/crt32/mbstring/mbscat.c
new file mode 100644
index 000000000..21430a5b3
--- /dev/null
+++ b/private/crt32/mbstring/mbscat.c
@@ -0,0 +1,21 @@
+/***
+*mbscat.c - contains mbscat() and mbscpy()
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* mbscpy() copies one string onto another.
+*
+* mbscat() concatenates (appends) a copy of the source string to the
+* end of the destination string, returning the destination string.
+*
+*Revision History:
+* 11-18-92 KRS Identical to strcat/strcpy--could use alias records.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#define strcat _mbscat
+#define strcpy _mbscpy
+#include "..\string\strcat.c"
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbschr.c b/private/crt32/mbstring/mbschr.c
new file mode 100644
index 000000000..a42109344
--- /dev/null
+++ b/private/crt32/mbstring/mbschr.c
@@ -0,0 +1,67 @@
+/***
+* mbschr.c - Search MBCS string for character
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Search MBCS string for a character
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 05-12-93 KRS Fix handling of c=='\0'.
+* 08-20-93 CFW Change param type to int, use new style param declarators.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+#include <stddef.h>
+
+/***
+* _mbschr - Search MBCS string for character
+*
+*Purpose:
+* Search the given string for the specified character.
+* MBCS characters are handled correctly.
+*
+*Entry:
+* unsigned char *string = string to search
+* int c = character to search for
+*
+*Exit:
+* returns a pointer to the first occurence of the specified char
+* within the string.
+*
+* returns NULL if the character is not found n the string.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+unsigned char * _CRTAPI1 _mbschr(
+ const unsigned char *string,
+ unsigned int c
+ )
+{
+ unsigned short cc;
+
+ for (; (cc = *string); string++) {
+
+ if (_ISLEADBYTE(cc)) {
+ if (*++string == '\0')
+ return NULL; /* error */
+ if ( c == (unsigned int)((cc << 8) | *string) ) /* DBCS match */
+ return (unsigned char *)(string - 1);
+ }
+ else if (c == (unsigned int)cc)
+ break; /* SBCS match */
+ }
+ if (c == (unsigned int)cc) /* check for SBCS match--handles NUL char */
+ return (unsigned char *)(string);
+ return NULL;
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbscmp.c b/private/crt32/mbstring/mbscmp.c
new file mode 100644
index 000000000..8011f1dda
--- /dev/null
+++ b/private/crt32/mbstring/mbscmp.c
@@ -0,0 +1,61 @@
+/***
+*mbscmp.c - Compare MBCS strings
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare MBCS strings
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* _mbscmp - Compare MBCS strings
+*
+*Purpose:
+* Compares two strings for lexical order. Strings
+* are compared on a character basis, not a byte basis.
+*
+*Entry:
+* char *s1, *s2 = strings to compare
+*
+*Exit:
+* returns <0 if s1 < s2
+* returns 0 if s1 == s2
+* returns >0 if s1 > s2
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mbscmp( s1, s2 )
+const unsigned char *s1;
+const unsigned char *s2;
+{
+ unsigned short c1, c2;
+
+ for (;;) {
+ c1 = *s1++;
+ if (_ISLEADBYTE(c1))
+ c1 = ( (*s1 == '\0') ? 0 : ((c1<<8) | *s1++) );
+
+ c2 = *s2++;
+ if (_ISLEADBYTE(c2))
+ c2 = ( (*s2 == '\0') ? 0 : ((c2<<8) | *s2++) );
+
+ if (c1 != c2)
+ return( (c1 > c2) ? 1 : -1);
+ if (c1 == 0)
+ return(0);
+ }
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbscspn.c b/private/crt32/mbstring/mbscspn.c
new file mode 100644
index 000000000..083e20033
--- /dev/null
+++ b/private/crt32/mbstring/mbscspn.c
@@ -0,0 +1,105 @@
+/***
+*mbscspn.c - Find first string char in charset (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Find first string char in charset (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+#include <stddef.h>
+
+
+/***
+#ifndef _RETURN_PTR
+* _mbscspn - Find first string char in charset (MBCS)
+#else
+* _mbspbrk - Find first string char in charset, pointer return (MBCS)
+#endif
+*
+*Purpose:
+* Returns maximum leading segment of string
+* which consists solely of characters NOT from charset.
+* Handles MBCS chars correctly.
+*
+*Entry:
+* char *string = string to search in
+* char *charset = set of characters to scan over
+*
+*Exit:
+*
+#ifndef _RETURN_PTR
+* Returns the index of the first char in string
+* that is in the set of characters specified by control.
+*
+* Returns 0, if string begins with a character in charset.
+#else
+* Returns pointer to first character in charset.
+*
+* Returns NULL if string consists entirely of characters
+* not from charset.
+#endif
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifndef _RETURN_PTR
+
+size_t _mbscspn( string, charset )
+const unsigned char *string;
+const unsigned char *charset;
+
+#else
+
+unsigned char * _CRTAPI1 _mbspbrk( string, charset )
+const unsigned char *string;
+const unsigned char *charset;
+
+#endif
+
+{
+ unsigned char *p, *q;
+
+ /* loop through the string to be inspected */
+ for (q = (char *)string; *q ; q++) {
+
+ /* loop through the charset */
+ for (p = (char *)charset; *p ; p++) {
+
+ if (_ISLEADBYTE(*p)) {
+ if (((*p == *q) && (p[1] == q[1])) || p[1] == '\0')
+ break;
+ p++;
+ }
+
+ else
+ if (*p == *q)
+ break;
+ }
+
+ if (*p != '\0') /* end of charset? */
+ break; /* no, match on this char */
+
+ if (_ISLEADBYTE(*q))
+ if (*++q == '\0')
+ break;
+ }
+
+#ifndef _RETURN_PTR
+ return((size_t) (q - string)); /* index */
+#else
+ return((*q) ? q : NULL); /* pointer */
+#endif
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsdec.c b/private/crt32/mbstring/mbsdec.c
new file mode 100644
index 000000000..c678f6492
--- /dev/null
+++ b/private/crt32/mbstring/mbsdec.c
@@ -0,0 +1,84 @@
+/***
+*mbsdec.c - Move MBCS string pointer backward one charcter.
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Move MBCS string pointer backward one character.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-03-93 KRS Fix prototypes.
+* 08-20-93 CFW Remove test for NULL string, use new function parameters.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <mbctype.h>
+#include <stddef.h>
+
+/***
+*_mbsdec - Move MBCS string pointer backward one charcter.
+*
+*Purpose:
+* Move the supplied string pointer backwards by one
+* character. MBCS characters are handled correctly.
+*
+*Entry:
+* const unsigned char *string = pointer to beginning of string
+* const unsigned char *current = current char pointer (legal MBCS boundary)
+*
+*Exit:
+* Returns pointer after moving it.
+* Returns NULL if string >= current.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsdec(
+ const unsigned char *string,
+ const unsigned char *current
+ )
+{
+ const unsigned char *temp;
+
+ if (string >= current)
+ return(NULL);
+
+ temp = current - 1;
+
+/*
+ * If (current-1) returns true from _ISLEADBTYE, it is a trail byte, because
+ * it is not a legal single byte MBCS character. Therefore, is so, return
+ * (current-2) because it is the trailbyte's lead.
+ */
+
+ if (_ISLEADBYTE(*temp))
+ return (unsigned char *)(temp - 1);
+
+/*
+ * It is unknown whether (current - 1) is a single byte character or a
+ * trail. Now decrement temp until
+ * a) The beginning of the string is reached, or
+ * b) A non-lead byte (either single or trail) is found.
+ * The difference between (current-1) and temp is the number of non-single
+ * byte characters preceding (current-1). There are two cases for this:
+ * a) (current - temp) is odd, and
+ * b) (current - temp) is even.
+ * If odd, then there are an odd number of "lead bytes" preceding the
+ * single/trail byte (current - 1), indicating that it is a trail byte.
+ * If even, then there are an even number of "lead bytes" preceding the
+ * single/trail byte (current - 1), indicating a single byte character.
+ */
+
+ while ((string <= --temp) && (_ISLEADBYTE(*temp)))
+ ;
+
+ return (unsigned char *)(current - 1 - ((current - temp) & 0x01) );
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsdup.c b/private/crt32/mbstring/mbsdup.c
new file mode 100644
index 000000000..0e283a04e
--- /dev/null
+++ b/private/crt32/mbstring/mbsdup.c
@@ -0,0 +1,18 @@
+/***
+*mbsdup.c - duplicate a string in malloc'd memory
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _mbsdup() - grab new memory, and duplicate the string into it.
+*
+*Revision History:
+* 11-18-92 KRS Identical to strdup--could just use alias record.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#define _strdup _mbsdup
+#include <..\string\strdup.c>
+
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsicmp.c b/private/crt32/mbstring/mbsicmp.c
new file mode 100644
index 000000000..ef2007b7a
--- /dev/null
+++ b/private/crt32/mbstring/mbsicmp.c
@@ -0,0 +1,90 @@
+/***
+*mbsicmp.c - Case-insensitive string comparision routine (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Case-insensitive string comparision routine (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 10-12-93 CFW Compare lower case, not upper.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _mbsicmp - Case-insensitive string comparision routine (MBCS)
+*
+*Purpose:
+* Compares two strings for lexical order without regard to case.
+* Strings are compared on a character basis, not a byte basis.
+*
+*Entry:
+* char *s1, *s2 = strings to compare
+*
+*Exit:
+* returns <0 if s1 < s2
+* returns 0 if s1 == s2
+* returns >0 if s1 > s2
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mbsicmp(s1, s2)
+const unsigned char *s1, *s2;
+{
+ unsigned short c1, c2;
+
+ for (;;) {
+
+ c1 = *s1++;
+ if (_ISLEADBYTE(c1)) {
+ if (*s1 == '\0')
+ c1 = 0;
+ else {
+ c1 = ((c1<<8) | *s1++);
+#ifndef _MBCS_OS
+ if ( (_mbascii) &&
+ ((c1 >= _MBUPPERLOW) && (c1 <= _MBUPPERHIGH))
+ )
+ c1 += _MBCASEDIFF;
+#endif
+ }
+ }
+ else
+ c1 = tolower(c1);
+
+ c2 = *s2++;
+ if (_ISLEADBYTE(c2)) {
+ if (*s2 == '\0')
+ c2 = 0;
+ else {
+ c2 = ((c2<<8) | *s2++);
+#ifndef _MBCS_OS
+ if ( (_mbascii) &&
+ ((c2 >= _MBUPPERLOW) && (c2 <= _MBUPPERHIGH))
+ )
+ c2 += _MBCASEDIFF;
+#endif
+ }
+ }
+ else
+ c2 = tolower(c2);
+
+ if (c1 != c2)
+ return( (c1 > c2) ? 1 : -1);
+ if (c1 == 0)
+ return(0);
+
+ }
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsinc.c b/private/crt32/mbstring/mbsinc.c
new file mode 100644
index 000000000..451810485
--- /dev/null
+++ b/private/crt32/mbstring/mbsinc.c
@@ -0,0 +1,48 @@
+/***
+*mbsinc.c - Move MBCS string pointer ahead one charcter.
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Move MBCS string pointer ahead one character.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-03-93 KRS Fix prototypes.
+* 08-20-93 CFW Remove test for NULL string, use new function parameters.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <mbctype.h>
+#include <stddef.h>
+
+/***
+*_mbsinc - Move MBCS string pointer ahead one charcter.
+*
+*Purpose:
+* Move the supplied string pointer ahead by one
+* character. MBCS characters are handled correctly.
+*
+*Entry:
+* const unsigned char *current = current char pointer (legal MBCS boundary)
+*
+*Exit:
+* Returns pointer after moving it.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsinc(
+ const unsigned char *current
+ )
+{
+ if (_ISLEADBYTE(*(current++)))
+ current++;
+ return (unsigned char *)current;
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbslen.c b/private/crt32/mbstring/mbslen.c
new file mode 100644
index 000000000..fbea20ce8
--- /dev/null
+++ b/private/crt32/mbstring/mbslen.c
@@ -0,0 +1,51 @@
+/***
+*mbslen.c - Find length of MBCS string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Find length of MBCS string
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _mbslen - Find length of MBCS string
+*
+*Purpose:
+* Find the length of the MBCS string (in characters).
+*
+*Entry:
+* unsigned char *s = string
+*
+*Exit:
+* Returns the number of MBCS chars in the string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 _mbslen(s)
+const unsigned char *s;
+{
+ int n;
+
+ for (n = 0; *s; n++, s++) {
+ if (_ISLEADBYTE(*s)) {
+ if (*++s == '\0')
+ break;
+ }
+ }
+
+ return(n);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbslwr.c b/private/crt32/mbstring/mbslwr.c
new file mode 100644
index 000000000..f25f5e409
--- /dev/null
+++ b/private/crt32/mbstring/mbslwr.c
@@ -0,0 +1,76 @@
+/***
+*mbslwr.c - Convert string lower case (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert string lower case (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <mbctype.h>
+
+/***
+* _mbslwr - Convert string lower case (MBCS)
+*
+*Purpose:
+* Convrts all the upper case characters in a string
+* to lower case in place. MBCS chars are handled
+* correctly.
+*
+* Note: Use test against 0x00FF instead of _ISLEADBYTE
+* to ensure that we don't call SBCS routine with a two-byte
+* value.
+*
+*Entry:
+* unsigned char *string = pointer to string
+*
+*Exit:
+* Returns a pointer to the input string; no error return.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbslwr( string )
+unsigned char *string;
+{
+ unsigned char *cp;
+
+ for (cp=string; *cp; cp++) {
+
+ if (_ISLEADBYTE(*cp)) {
+
+#ifdef _MBCS_OS
+ cp++; /* bump pointer */
+#else
+ if ((_mbascii) && (*cp == _MBASCIILEAD)) {
+
+ if ( (*(cp+1) >= (_MBUPPERLOW & 0x00FF))
+ && (*(cp+1) <= (_MBUPPERHIGH & 0x00FF))
+ )
+ *(cp+1) += _MBCASEDIFF;
+ }
+
+ cp++;
+#endif
+
+ }
+
+ else
+ /* single byte, macro version */
+ *cp = (unsigned char) tolower(*cp);
+
+ }
+
+ return( string );
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnbcat.c b/private/crt32/mbstring/mbsnbcat.c
new file mode 100644
index 000000000..b2da5d812
--- /dev/null
+++ b/private/crt32/mbstring/mbsnbcat.c
@@ -0,0 +1,99 @@
+/***
+*mbsnbcat.c - concatenate string2 onto string1, max length n bytes
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines mbsnbcat() - concatenate maximum of n bytes
+*
+*Revision History:
+* 08-03-93 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Update _MBCS_OS support.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+#define _MBSBTYPE(str,len) _mbsbtype(str,len)
+
+/***
+* _mbsnbcat - concatenate max cnt bytes onto dst
+*
+*Purpose:
+* Concatenates src onto dst, with a maximum of cnt bytes copied.
+* Handles 2-byte MBCS characters correctly.
+*
+*Entry:
+* unsigned char *dst - string to concatenate onto
+* unsigned char *src - string to concatenate from
+* int cnt - number of bytes to copy
+*
+*Exit:
+* returns dst, with src (at least part) concatenated on
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsnbcat(dst, src, cnt)
+unsigned char *dst;
+const unsigned char *src;
+size_t cnt;
+{
+ unsigned char *start;
+
+ if (!cnt)
+ return(dst);
+
+ start = dst;
+ while (*dst++)
+ ;
+ --dst; // dst now points to end of dst string
+
+
+ /* if last char in string is a lead byte, back up pointer */
+
+#ifdef _KANJI
+ if (_MBSBTYPE(start, (int) ((dst - start) - 1)) == _MBC_LEAD)
+ --dst;
+#else /* _MBCS_OS */
+ if (_ismbslead(start, dst))
+ --dst;
+#endif
+
+ /* copy over the characters */
+
+ while (cnt--) {
+
+ if (_ISLEADBYTE(*src)) {
+ *dst++ = *src++;
+ if (!cnt--) { /* write nul if cnt exhausted */
+ dst[-1] = '\0';
+ break;
+ }
+ if ((*dst++ = *src++)=='\0') { /* or if no trail byte */
+ dst[-2] = '\0';
+ break;
+ }
+ }
+
+ else if ((*dst++ = *src++) == '\0')
+ break;
+
+ }
+
+ /* enter final nul, if necessary */
+
+ if (_MBSBTYPE(start, (int) ((dst - start) - 1)) == _MBC_LEAD)
+ dst[-1] = '\0';
+ else
+ *dst = '\0';
+
+
+ return(start);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnbcmp.c b/private/crt32/mbstring/mbsnbcmp.c
new file mode 100644
index 000000000..f9aa9521a
--- /dev/null
+++ b/private/crt32/mbstring/mbsnbcmp.c
@@ -0,0 +1,75 @@
+/***
+*mbsnbcmp.c - Compare n bytes of two MBCS strings
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare n bytes of two MBCS strings
+*
+*Revision History:
+* 08-03-93 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+*int mbsnbcmp(s1, s2, n) - Compare n bytes of two MBCS strings
+*
+*Purpose:
+* Compares up to n bytes of two strings for lexical order.
+* Strings are compared on a character basis, not a byte basis.
+*
+*Entry:
+* unsigned char *s1, *s2 = strings to compare
+* size_t n = maximum number of bytes to compare
+*
+*Exit:
+* returns <0 if s1 < s2
+* returns 0 if s1 == s2
+* returns >0 if s1 > s2
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mbsnbcmp( s1, s2, n )
+const unsigned char *s1;
+const unsigned char *s2;
+size_t n;
+{
+ unsigned short c1, c2;
+
+ if (n==0)
+ return(0);
+
+ while (n--) {
+
+ c1 = *s1++;
+ if (_ISLEADBYTE(c1)) {
+ if (n==0)
+ break;
+ c1 = ( (*s1 == '\0') ? 0 : ((c1<<8) | *s1++) );
+ }
+
+ c2 = *s2++;
+ if (_ISLEADBYTE(c2)) {
+ if (n--==0)
+ break;
+ c2 = ( (*s2 == '\0') ? 0 : ((c2<<8) | *s2++) );
+ }
+
+ if (c1 != c2)
+ return( (c1 > c2) ? 1 : -1);
+
+ if (c1 == 0)
+ return(0);
+ }
+
+ return(0);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnbcnt.c b/private/crt32/mbstring/mbsnbcnt.c
new file mode 100644
index 000000000..196eb02c7
--- /dev/null
+++ b/private/crt32/mbstring/mbsnbcnt.c
@@ -0,0 +1,62 @@
+/***
+*mbsnbcnt.c - Returns byte count of MBCS string
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Returns byte count of MBCS string
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _mbsnbcnt - Returns byte count of MBCS string
+*
+*Purpose:
+* Returns the number of bytes between the start of the supplied
+* string and the char count supplied. That is, this routine
+* indicates how many bytes are in the first "ccnt" characters
+* of the string.
+*
+*Entry:
+* unsigned char *string = pointer to string
+* unsigned int ccnt = number of characters to scan
+*
+*Exit:
+* Returns number of bytes between string and ccnt.
+*
+* If the end of the string is encountered before ccnt chars were
+* scanned, then the length of the string in bytes is returned.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 _mbsnbcnt(string, ccnt)
+const unsigned char *string;
+size_t ccnt;
+{
+ unsigned char *p;
+
+ for (p = (char *)string; (ccnt-- && *p); p++) {
+
+ if (_ISLEADBYTE(*p)) {
+ if (*++p == '\0') {
+ --p;
+ break;
+ }
+ }
+ }
+
+ return ((size_t) ((char *)p - (char *)string));
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnbcpy.c b/private/crt32/mbstring/mbsnbcpy.c
new file mode 100644
index 000000000..1f193f5a5
--- /dev/null
+++ b/private/crt32/mbstring/mbsnbcpy.c
@@ -0,0 +1,79 @@
+/***
+*mbsnbcpy.c - Copy one string to another, n bytes only (MBCS)
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Copy one string to another, n bytes only (MBCS)
+*
+*Revision History:
+* 05-19-93 KRS Created from mbsncpy.
+* 08-03-93 KRS Fix logic bug.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* _mbsnbcpy - Copy one string to another, n bytes only (MBCS)
+*
+*Purpose:
+* Copies exactly cnt bytes from src to dst. If strlen(src) < cnt, the
+* remaining character are padded with null bytes. If strlen >= cnt, no
+* terminating null byte is added. 2-byte MBCS characters are handled
+* correctly.
+*
+*Entry:
+* unsigned char *dst = destination for copy
+* unsigned char *src = source for copy
+* int cnt = number of characters to copy
+*
+*Exit:
+* returns dst = destination of copy
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsnbcpy(dst, src, cnt)
+unsigned char *dst;
+const unsigned char *src;
+size_t cnt;
+{
+
+ unsigned char *start = dst;
+
+ while (cnt) {
+
+ cnt--;
+ if (_ISLEADBYTE(*src)) {
+ *dst++ = *src++;
+ if (!cnt) {
+ dst[-1] = '\0';
+ break;
+ }
+ cnt--;
+ if ((*dst++ = *src++) == '\0') {
+ dst[-2] = '\0';
+ break;
+ }
+ }
+
+ else
+ if ((*dst++ = *src++) == '\0')
+ break;
+
+ }
+
+ /* pad with nulls as needed */
+
+ while (cnt--)
+ *dst++ = '\0';
+
+ return start;
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnbicm.c b/private/crt32/mbstring/mbsnbicm.c
new file mode 100644
index 000000000..3ee1d9ba9
--- /dev/null
+++ b/private/crt32/mbstring/mbsnbicm.c
@@ -0,0 +1,101 @@
+/***
+*mbsnbicmp.c - Compare n bytes of strings, ignoring case (MBCS)
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare n bytes of strings, ignoring case (MBCS)
+*
+*Revision History:
+* 08-03-93 KRS Ported from 16-bit sources.
+* 10-12-93 CFW Compare lower case, not upper.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _mbsnbicmp - Compare n bytes of strings, ignoring case (MBCS)
+*
+*Purpose:
+* Compares up to n bytes of two strings for lexical order.
+* Strings are compared on a character basis, not a byte basis.
+* Case of characters is not considered.
+*
+*Entry:
+* unsigned char *s1, *s2 = strings to compare
+* size_t n = maximum number of bytes to compare
+*
+*Exit:
+* returns <0 if s1 < s2
+* returns 0 if s1 == s2
+* returns >0 if s1 > s2
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mbsnbicmp(s1, s2, n)
+const unsigned char *s1, *s2;
+size_t n;
+{
+ unsigned short c1, c2;
+
+ if (n==0)
+ return(0);
+
+ while (n--) {
+
+ c1 = *s1++;
+ if (_ISLEADBYTE(c1)) {
+ if (n==0)
+ break;
+ if (*s1 == '\0')
+ c1 = 0;
+ else {
+ c1 = ((c1<<8) | *s1++);
+#ifndef _MBCS_OS
+ if ( (_mbascii) &&
+ ((c1 >= _MBUPPERLOW) && (c1 <= _MBUPPERHIGH))
+ )
+ c1 += _MBCASEDIFF;
+#endif
+ }
+ }
+ else
+ c1 = tolower(c1);
+
+ c2 = *s2++;
+ if (_ISLEADBYTE(c2)) {
+ if (n--==0)
+ break;
+ if (*s2 == '\0')
+ c2 = 0;
+ else {
+ c2 = ((c2<<8) | *s2++);
+#ifndef _MBCS_OS
+ if ( (_mbascii) &&
+ ((c2 >= _MBUPPERLOW) && (c2 <= _MBUPPERHIGH))
+ )
+ c2 += _MBCASEDIFF;
+#endif
+ }
+ }
+ else
+ c2 = tolower(c2);
+
+ if (c1 != c2)
+ return( (c1 > c2) ? 1 : -1);
+
+ if (c1 == 0)
+ return(0);
+ }
+
+ return(0);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnbset.c b/private/crt32/mbstring/mbsnbset.c
new file mode 100644
index 000000000..36efbb26a
--- /dev/null
+++ b/private/crt32/mbstring/mbsnbset.c
@@ -0,0 +1,102 @@
+/***
+*mbsnbset.asm - Sets first n bytes of string to given character (MBCS)
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Sets first n bytes of string to given character (MBCS)
+*
+*Revision History:
+* 08-03-93 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* _mbsnbset - Sets first n bytes of string to given character (MBCS)
+*
+*Purpose:
+* Sets the first n bytes of string to the supplied
+* character value. If the length of string is less than n,
+* the length of string is used in place of n. Handles
+* MBCS chars correctly.
+*
+* There are several factors that make this routine complicated:
+* (1) The fill value may be 1 or 2 bytes long.
+* (2) The fill operation may end by hitting the count value
+* or by hitting the end of the string.
+* (3) A null terminating char is NOT placed at the end of
+* the string.
+*
+* Cases to be careful of (both of these can occur at once):
+* (1) Leaving an "orphaned" trail byte in the string (e.g.,
+* overwriting a lead byte but not the corresponding trail byte).
+* (2) Writing only the 1st byte of a 2-byte fill value because the
+* end of string was encountered.
+*
+*Entry:
+* unsigned char *string = string to modify
+* unsigned int val = value to fill string with
+* size_t count = count of characters to fill
+*
+*
+*Exit:
+* Returns string = now filled with char val
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsnbset(
+ unsigned char *string,
+ unsigned int val,
+ size_t count
+ )
+{
+ unsigned char *start = string;
+ unsigned char highval, lowval;
+
+ /*
+ * leadbyte flag indicates if the last byte we overwrote was
+ * a lead byte or not.
+ */
+
+ if (highval = (unsigned char)(val>>8)) {
+
+ /* double byte value */
+
+ lowval = (unsigned char)(val & 0x00ff);
+
+ while ((count--) && *string) {
+
+ /* pad with ' ' if no room for both bytes -- odd len */
+ if ((!count--) || (!*(string+1))) {
+ *string = ' ';
+ break;
+ }
+
+ *string++ = highval;
+ *string++ = lowval;
+ }
+ }
+
+ else {
+ /* single byte value */
+
+ while (count-- && *string) {
+ *string++ = (unsigned char)val;
+ }
+
+ }
+
+ return( start );
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsncat.c b/private/crt32/mbstring/mbsncat.c
new file mode 100644
index 000000000..343bf39af
--- /dev/null
+++ b/private/crt32/mbstring/mbsncat.c
@@ -0,0 +1,95 @@
+/***
+*mbsncat.c - concatenate string2 onto string1, max length n
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines mbsncat() - concatenate maximum of n characters
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Update _MBCS_OS support.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+#define _MBSBTYPE(str,len) _mbsbtype(str,len)
+
+/***
+* _mbsncat - concatenate max cnt characters onto dst
+*
+*Purpose:
+* Concatenates src onto dst, with a maximum of cnt characters copied.
+* Handles 2-byte MBCS characters correctly.
+*
+*Entry:
+* unsigned char *dst - string to concatenate onto
+* unsigned char *src - string to concatenate from
+* int cnt - number of characters to copy
+*
+*Exit:
+* returns dst, with src (at least part) concatenated on
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsncat(dst, src, cnt)
+unsigned char *dst;
+const unsigned char *src;
+size_t cnt;
+{
+ unsigned char *start;
+
+ if (!cnt)
+ return(dst);
+
+ start = dst;
+ while (*dst++)
+ ;
+ --dst; // dst now points to end of dst string
+
+
+ /* if last char in string is a lead byte, back up pointer */
+
+#ifdef _KANJI
+ if (_MBSBTYPE(start, (int) ((dst - start) - 1)) == _MBC_LEAD)
+ --dst;
+#else /* _MBCS_OS */
+ if (_ismbslead(start, dst))
+ --dst;
+#endif
+
+ /* copy over the characters */
+
+ while (cnt--) {
+
+ if (_ISLEADBYTE(*src)) {
+ *dst++ = *src++;
+ if ((*dst++ = *src++) == '\0') {
+ dst[-2] = '\0';
+ break;
+ }
+ }
+
+ else if ((*dst++ = *src++) == '\0')
+ break;
+
+ }
+
+ /* enter final nul, if necessary */
+
+ if (_MBSBTYPE(start, (int) ((dst - start) - 1)) == _MBC_LEAD)
+ dst[-1] = '\0';
+ else
+ *dst = '\0';
+
+
+ return(start);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnccnt.c b/private/crt32/mbstring/mbsnccnt.c
new file mode 100644
index 000000000..f6e87f0bc
--- /dev/null
+++ b/private/crt32/mbstring/mbsnccnt.c
@@ -0,0 +1,59 @@
+/***
+*mbsnccnt.c - Return char count of MBCS string
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Return char count of MBCS string
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* _mbsnccnt - Return char count of MBCS string
+*
+*Purpose:
+* Returns the number of chars between the start of the supplied
+* string and the byte count supplied. That is, this routine
+* indicates how many chars are in the first "bcnt" bytes
+* of the string.
+*
+*Entry:
+* const unsigned char *string = pointer to string
+* unsigned int bcnt = number of bytes to scan
+*
+*Exit:
+* Returns number of chars between string and bcnt.
+*
+* If the end of the string is encountered before bcnt chars were
+* scanned, then the length of the string in chars is returned.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 _mbsnccnt(string, bcnt)
+const unsigned char *string;
+size_t bcnt;
+{
+ unsigned int n;
+
+ for (n = 0; (bcnt-- && *string); n++, string++) {
+
+ if (_ISLEADBYTE(*string)) {
+ if ( (!bcnt--) || (*++string == '\0'))
+ break;
+ }
+ }
+
+ return(n);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsncmp.c b/private/crt32/mbstring/mbsncmp.c
new file mode 100644
index 000000000..d9bbcdfaa
--- /dev/null
+++ b/private/crt32/mbstring/mbsncmp.c
@@ -0,0 +1,69 @@
+/***
+*mbsncmp.c - Compare n characters of two MBCS strings
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare n characters of two MBCS strings
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+*int mbsncmp(s1, s2, n) - Compare n characters of two MBCS strings
+*
+*Purpose:
+* Compares up to n charcters of two strings for lexical order.
+* Strings are compared on a character basis, not a byte basis.
+*
+*Entry:
+* unsigned char *s1, *s2 = strings to compare
+* size_t n = maximum number of characters to compare
+*
+*Exit:
+* returns <0 if s1 < s2
+* returns 0 if s1 == s2
+* returns >0 if s1 > s2
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mbsncmp( s1, s2, n )
+const unsigned char *s1;
+const unsigned char *s2;
+size_t n;
+{
+ unsigned short c1, c2;
+
+ if (n==0)
+ return(0);
+
+ while (n--) {
+
+ c1 = *s1++;
+ if (_ISLEADBYTE(c1))
+ c1 = ( (*s1 == '\0') ? 0 : ((c1<<8) | *s1++) );
+
+ c2 = *s2++;
+ if (_ISLEADBYTE(c2))
+ c2 = ( (*s2 == '\0') ? 0 : ((c2<<8) | *s2++) );
+
+ if (c1 != c2)
+ return( (c1 > c2) ? 1 : -1);
+
+ if (c1 == 0)
+ return(0);
+ }
+
+ return(0);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsncpy.c b/private/crt32/mbstring/mbsncpy.c
new file mode 100644
index 000000000..0ce2b471b
--- /dev/null
+++ b/private/crt32/mbstring/mbsncpy.c
@@ -0,0 +1,74 @@
+/***
+*mbsncpy.c - Copy one string to another, n chars only (MBCS)
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Copy one string to another, n chars only (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-03-93 KRS Fix logic bug.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* _mbsncpy - Copy one string to another, n chars only (MBCS)
+*
+*Purpose:
+* Copies exactly cnt character from src to dst. If strlen(src) < cnt, the
+* remaining character are padded with null bytes. If strlen >= cnt, no
+* terminating null byte is added. 2-byte MBCS characters are handled
+* correctly.
+*
+*Entry:
+* unsigned char *dst = destination for copy
+* unsigned char *src = source for copy
+* int cnt = number of characters to copy
+*
+*Exit:
+* returns dst = destination of copy
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsncpy(dst, src, cnt)
+unsigned char *dst;
+const unsigned char *src;
+size_t cnt;
+{
+
+ unsigned char *start = dst;
+
+ while (cnt) {
+
+ cnt--;
+ if (_ISLEADBYTE(*src)) {
+ *dst++ = *src++;
+ if ((*dst++ = *src++) == '\0') {
+ dst[-2] = '\0';
+ break;
+ }
+ }
+
+ else
+ if ((*dst++ = *src++) == '\0')
+ break;
+
+ }
+
+ /* pad with nulls as needed */
+
+ while (cnt--)
+ *dst++ = '\0';
+
+ return start;
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnextc.c b/private/crt32/mbstring/mbsnextc.c
new file mode 100644
index 000000000..6ab8f9b12
--- /dev/null
+++ b/private/crt32/mbstring/mbsnextc.c
@@ -0,0 +1,50 @@
+/***
+*mbsnextc.c - Get the next character in an MBCS string.
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* To return the value of the next character in an MBCS string.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+*_mbsnextc: Returns the next character in a string.
+*
+*Purpose:
+* To return the value of the next character in an MBCS string.
+* Does not advance pointer to the next character.
+*
+*Entry:
+* unsigned char *s = string
+*
+*Exit:
+* unsigned int next = next character.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _mbsnextc(s)
+const unsigned char *s;
+{
+ unsigned int next = 0;
+
+ if (_ISLEADBYTE(*s))
+ next = ((unsigned int) *s++) << 8;
+
+ next += (unsigned int) *s;
+
+ return(next);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnicmp.c b/private/crt32/mbstring/mbsnicmp.c
new file mode 100644
index 000000000..4cc335dac
--- /dev/null
+++ b/private/crt32/mbstring/mbsnicmp.c
@@ -0,0 +1,97 @@
+/***
+*mbsnicmp.c - Compare n characters of strings, ignoring case (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare n characters of strings, ignoring case (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 10-12-93 CFW Compare lower case, not upper.
+N*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _mbsnicmp - Compare n characters of strings, ignoring case (MBCS)
+*
+*Purpose:
+* Compares up to n charcters of two strings for lexical order.
+* Strings are compared on a character basis, not a byte basis.
+* Case of characters is not considered.
+*
+*Entry:
+* unsigned char *s1, *s2 = strings to compare
+* size_t n = maximum number of characters to compare
+*
+*Exit:
+* returns <0 if s1 < s2
+* returns 0 if s1 == s2
+* returns >0 if s1 > s2
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mbsnicmp(s1, s2, n)
+const unsigned char *s1, *s2;
+size_t n;
+{
+ unsigned short c1, c2;
+
+ if (n==0)
+ return(0);
+
+ while (n--) {
+
+ c1 = *s1++;
+ if (_ISLEADBYTE(c1)) {
+ if (*s1 == '\0')
+ c1 = 0;
+ else {
+ c1 = ((c1<<8) | *s1++);
+#ifndef _MBCS_OS
+ if ( (_mbascii) &&
+ ((c1 >= _MBUPPERLOW) && (c1 <= _MBUPPERHIGH))
+ )
+ c1 += _MBCASEDIFF;
+#endif
+ }
+ }
+ else
+ c1 = tolower(c1);
+
+ c2 = *s2++;
+ if (_ISLEADBYTE(c2)) {
+ if (*s2 == '\0')
+ c2 = 0;
+ else {
+ c2 = ((c2<<8) | *s2++);
+#ifndef _MBCS_OS
+ if ( (_mbascii) &&
+ ((c2 >= _MBUPPERLOW) && (c2 <= _MBUPPERHIGH))
+ )
+ c2 += _MBCASEDIFF;
+#endif
+ }
+ }
+ else
+ c2 = tolower(c2);
+
+ if (c1 != c2)
+ return( (c1 > c2) ? 1 : -1);
+
+ if (c1 == 0)
+ return(0);
+ }
+
+ return(0);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsninc.c b/private/crt32/mbstring/mbsninc.c
new file mode 100644
index 000000000..8cb30313c
--- /dev/null
+++ b/private/crt32/mbstring/mbsninc.c
@@ -0,0 +1,50 @@
+/***
+*mbsninc.c - Increment MBCS string pointer by specified char count.
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Increment MBCS string pointer by specified char count.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-03-93 KRS Fix return value logic.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <stddef.h>
+
+/***
+*_mbsninc - Increment MBCS string pointer by specified char count.
+*
+*Purpose:
+* Increment the supplied string pointer by the specified number
+* of characters. MBCS characters are handled correctly.
+*
+*Entry:
+* const unsigned char *string = pointer to string
+* unsigned int ccnt = number of char to advance the pointer
+*
+*Exit:
+* Returns pointer after advancing it.
+* Returns pointer to end of string if string is not ccnt chars long.
+* Returns NULL is supplied pointer is NULL.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsninc(string, ccnt)
+const unsigned char *string;
+size_t ccnt;
+{
+ if (string == NULL)
+ return(NULL);
+
+ return((char *)string + (unsigned int)_mbsnbcnt(string, ccnt));
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsnset.c b/private/crt32/mbstring/mbsnset.c
new file mode 100644
index 000000000..4b24cd5c1
--- /dev/null
+++ b/private/crt32/mbstring/mbsnset.c
@@ -0,0 +1,110 @@
+/***
+*mbsnset.asm - Sets first n charcaters of string to given character (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Sets first n charcaters of string to given character (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* _mbsnset - Sets first n charcaters of string to given character (MBCS)
+*
+*Purpose:
+* Sets the first n characters of string to the supplied
+* character value. If the length of string is less than n,
+* the length of string is used in place of n. Handles
+* MBCS chars correctly.
+*
+* There are several factors that make this routine complicated:
+* (1) The fill value may be 1 or 2 bytes long.
+* (2) The fill operation may end by hitting the count value
+* or by hitting the end of the string.
+* (3) A null terminating char is NOT placed at the end of
+* the string.
+*
+* Cases to be careful of (both of these can occur at once):
+* (1) Leaving an "orphaned" trail byte in the string (e.g.,
+* overwriting a lead byte but not the corresponding trail byte).
+* (2) Writing only the 1st byte of a 2-byte fill value because the
+* end of string was encountered.
+*
+*Entry:
+* unsigned char *string = string to modify
+* unsigned int val = value to fill string with
+* size_t count = count of characters to fill
+*
+*
+*Exit:
+* Returns string = now filled with char val
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsnset(
+ unsigned char *string,
+ unsigned int val,
+ size_t count
+ )
+{
+ unsigned char *start = string;
+ unsigned int leadbyte = 0;
+ unsigned char highval, lowval;
+
+ /*
+ * leadbyte flag indicates if the last byte we overwrote was
+ * a lead byte or not.
+ */
+
+ if (highval = (unsigned char)(val>>8)) {
+
+ /* double byte value */
+
+ lowval = (unsigned char)(val & 0x00ff);
+
+ while (count-- && *string) {
+
+ leadbyte = _ismbbtruelead(leadbyte, *string);
+ *string++ = highval;
+
+ if (*string) {
+ leadbyte = _ismbbtruelead(leadbyte, *string);
+ *string++ = lowval;
+ }
+ else
+ /* overwrite orphaned highval byte */
+ *(string-1) = ' ';
+ }
+ }
+
+ else {
+ /* single byte value */
+
+ while (count-- && *string) {
+ leadbyte = _ismbbtruelead(leadbyte, *string);
+ *string++ = (unsigned char)val;
+ }
+
+ }
+
+ /* overwrite orphaned trailing byte, if necessary */
+ if(leadbyte && *string)
+ *string = ' ';
+
+ return( start );
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbspbrk.c b/private/crt32/mbstring/mbspbrk.c
new file mode 100644
index 000000000..3bae1f375
--- /dev/null
+++ b/private/crt32/mbstring/mbspbrk.c
@@ -0,0 +1,18 @@
+/***
+*mbspbrk.c - Find first string char in charset, pointer return (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Find first string char in charset, pointer return (MBCS)
+* Shares common source file with mbscspn.c.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#define _RETURN_PTR
+#include "mbscspn.c"
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsrchr.c b/private/crt32/mbstring/mbsrchr.c
new file mode 100644
index 000000000..bbbcc8c51
--- /dev/null
+++ b/private/crt32/mbstring/mbsrchr.c
@@ -0,0 +1,67 @@
+/***
+*mbsrchr.c - Search for last occurence of character (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Search for last occurence of character (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+#include <stddef.h>
+
+/***
+* _mbsrchr - Search for last occurence of character (MBCS)
+*
+*Purpose:
+* Find the last occurrence of the specified character in
+* the supplied string. Handles MBCS chars/strings correctly.
+*
+*Entry:
+* unsigned char *str = string to search in
+* unsigned int c = character to search for
+*
+*Exit:
+* returns pointer to last occurrence of c in str
+* returns NULL if c not found
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsrchr(
+ const unsigned char *str,
+ unsigned int c
+ )
+{
+ char *r = NULL;
+ unsigned int cc;
+
+ do {
+ cc = *str;
+ if (_ISLEADBYTE(cc)) {
+ if(*++str) {
+ if (c == ((cc<<8)|*str))
+ r = (char *)str - 1;
+ }
+ else if(!r)
+ /* return pointer to '\0' */
+ r = (char *)str;
+ }
+ else if (c == cc)
+ r = (char *)str;
+ }
+ while (*str++);
+
+ return(r);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsrev.c b/private/crt32/mbstring/mbsrev.c
new file mode 100644
index 000000000..8c0a0f62a
--- /dev/null
+++ b/private/crt32/mbstring/mbsrev.c
@@ -0,0 +1,72 @@
+/***
+*mbsrev.c - Reverse a string in place (MBCS)
+*
+* Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Reverse a string in place (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _mbsrev - Reverse a string in place (MBCS)
+*
+*Purpose:
+* Reverses the order of characters in the string. The terminating
+* null character remains in place. The order of MBCS characters
+* is not changed.
+*
+*Entry:
+* unsigned char *string = string to reverse
+*
+*Exit:
+* returns string - now with reversed characters
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsrev(string)
+unsigned char *string;
+{
+
+ unsigned char *start = string;
+ unsigned char *left = string;
+ unsigned char c;
+
+ /* first go through and reverse the bytes in MBCS chars */
+ while ( *string ) {
+
+ if ( _ISLEADBYTE(*string++) ) {
+ if ( *string ) {
+ c = *string;
+ *string = *(string - 1);
+ *(string - 1) = c;
+ string++;
+ }
+ else /* second byte is EOS */
+ break;
+ }
+ }
+
+ /* now reverse the whole string */
+ string--;
+ while ( left < string ) {
+ c = *left;
+ *left++ = *string;
+ *string-- = c;
+ }
+
+ return ( start );
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsset.c b/private/crt32/mbstring/mbsset.c
new file mode 100644
index 000000000..0884f0e6a
--- /dev/null
+++ b/private/crt32/mbstring/mbsset.c
@@ -0,0 +1,76 @@
+/***
+*mbsset.asm - Sets all charcaters of string to given character (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Sets all charcaters of string to given character (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* mbsset - Sets all charcaters of string to given character (MBCS)
+*
+*Purpose:
+* Sets all of characters in string (except the terminating '/0'
+* character) equal to the supplied character. Handles MBCS
+* chars correctly.
+*
+*Entry:
+* unsigned char *string = string to modify
+* unsigned int val = value to fill string with
+*
+*Exit:
+* returns string = now filled with the specified char
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsset( string, val )
+unsigned char *string;
+unsigned int val;
+{
+ unsigned char *start = string;
+ unsigned char highval, lowval;
+
+ if (highval = (unsigned char) (val>>8)) {
+
+ /* 2-byte value */
+
+ lowval = (unsigned char)(val & 0x00ff);
+
+ while (*string) {
+
+ *string++ = highval;
+ if (*string)
+ *string++ = lowval;
+ else
+ /* don't orphan lead byte */
+ string[-1] = ' ';
+ }
+
+ }
+
+ else {
+ /* single byte value */
+
+ while (*string)
+ *string++ = (unsigned char)val;
+ }
+
+ return(start);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsspn.c b/private/crt32/mbstring/mbsspn.c
new file mode 100644
index 000000000..40cdb662e
--- /dev/null
+++ b/private/crt32/mbstring/mbsspn.c
@@ -0,0 +1,101 @@
+/***
+*mbsspn.c - Search for init substring of chars from control string (MBCS).
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Search for init substring of chars from control string (MBCS).
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+#include <stddef.h>
+
+
+/***
+#ifndef _RETURN_PTR
+* _mbsspn - Find first string char not in charset (MBCS)
+#else
+* _mbsspnp - Find first string char not in charset, return pointer (MBCS)
+#endif
+*
+*Purpose:
+* Returns maximum leading segment of string consisting solely
+* of characters from charset. Handles MBCS characters correctly.
+*
+*Entry:
+* unsigned char *string = string to search in
+* unsigned char *charset = set of characters to scan over
+*
+*Exit:
+*
+#ifndef _RETURN_PTR
+* Returns index of first char in string not in control.
+* Returns 0, if string begins with a character not in charset.
+#else
+* Returns pointer to first character not in charset.
+* Returns NULL if string consists entirely of characters from charset.
+#endif
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifndef _RETURN_PTR
+
+size_t _CRTAPI1 _mbsspn( string, charset )
+const unsigned char *string;
+const unsigned char *charset;
+
+#else
+
+unsigned char * _CRTAPI1 _mbsspnp( string, charset )
+const unsigned char *string;
+const unsigned char *charset;
+
+#endif
+
+{
+ unsigned char *p, *q;
+
+ /* loop through the string to be inspected */
+ for (q = (char *)string; *q; q++) {
+
+ /* loop through the charset */
+ for (p = (char *)charset; *p; p++) {
+
+ if (_ISLEADBYTE(*p)) {
+ if (((*p == *q) && (p[1] == q[1])) || p[1] == '\0')
+ break;
+ p++;
+ }
+
+ else
+ if (*p == *q)
+ break;
+ }
+
+ if (*p == '\0') /* end of charset? */
+ break; /* yes, no match on this char */
+
+ if (_ISLEADBYTE(*q))
+ if (*++q == '\0')
+ break;
+ }
+
+#ifndef _RETURN_PTR
+ return((size_t) (q - string)); /* index */
+#else
+ return((*q) ? q : NULL); /* pointer */
+#endif
+
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsspnp.c b/private/crt32/mbstring/mbsspnp.c
new file mode 100644
index 000000000..cf410ca4a
--- /dev/null
+++ b/private/crt32/mbstring/mbsspnp.c
@@ -0,0 +1,18 @@
+/***
+*mbsspnp.c - Find first string char in charset, pointer return (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Returns maximum leading segment of string consisting solely
+* of characters from charset. Handles MBCS characters correctly.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#define _RETURN_PTR
+#include "mbsspn.c"
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsstr.c b/private/crt32/mbstring/mbsstr.c
new file mode 100644
index 000000000..b2ca4881d
--- /dev/null
+++ b/private/crt32/mbstring/mbsstr.c
@@ -0,0 +1,80 @@
+/***
+* mbsstr.c - Search for one MBCS string inside another
+*
+* Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Search for one MBCS string inside another
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+#include <stddef.h>
+#include <string.h>
+
+#define _BYTELEN(s) (strlen(s))
+#define _MBSINC(s) (_mbsinc(s))
+#define PCHAR char *
+
+/***
+* _mbsstr - Search for one MBCS string inside another
+*
+*Purpose:
+* Find the first occurrence of str2 in str1.
+*
+*Entry:
+* unsigned char *str1 = beginning of string
+* unsigned char *str2 = string to search for
+*
+*Exit:
+* Returns a pointer to the first occurrence of str2 in
+* str1, or NULL if str2 does not occur in str1
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsstr( str1, str2 )
+const unsigned char *str1;
+const unsigned char *str2;
+{
+ unsigned char *cp = (unsigned char *) str1;
+ unsigned char *s1, *s2, *endp;
+
+ endp = (unsigned PCHAR) (str1 + (_BYTELEN(str1) - _BYTELEN(str2)));
+
+ while (*cp && (cp <= endp))
+ {
+ s1 = cp;
+ s2 = (PCHAR) str2;
+
+ /*
+ * MBCS: ok to ++ since doing equality comparison.
+ * [This depends on MBCS strings being "legal".]
+ */
+
+ while ( *s1 && *s2 && (*s1 == *s2) )
+ s1++, s2++;
+
+ if (!(*s2))
+ return(cp); /* success! */
+
+ /*
+ * bump pointer to next char
+ */
+
+ cp = _MBSINC(cp);
+
+ }
+
+ return(NULL);
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbstok.c b/private/crt32/mbstring/mbstok.c
new file mode 100644
index 000000000..9c1093fb6
--- /dev/null
+++ b/private/crt32/mbstring/mbstok.c
@@ -0,0 +1,174 @@
+/***
+*mbstok.c - Break string into tokens (MBCS)
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Break string into tokens (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 12-04-92 KRS Added MTHREAD support.
+* 02-17-93 GJF Changed for new _getptd().
+* 07-14-93 KRS Fix: all references should be to _mtoken, not _token.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+#include <stddef.h>
+#ifdef MTHREAD
+#include <os2dll.h>
+#endif
+
+#define _MBSSPNP(p,s) _mbsspnp(p,s)
+#define _MBSPBRK(q,s) _mbspbrk(q,s);
+
+/***
+* _mbstok - Break string into tokens (MBCS)
+*
+*Purpose:
+* strtok considers the string to consist of a sequence of zero or more
+* text tokens separated by spans of one or more control chars. the first
+* call, with string specified, returns a pointer to the first char of the
+* first token, and will write a null char into string immediately
+* following the returned token. subsequent calls with zero for the first
+* argument (string) will work thru the string until no tokens remain. the
+* control string may be different from call to call. when no tokens remain
+* in string a NULL pointer is returned. remember the control chars with a
+* bit map, one bit per ascii char. the null char is always a control char.
+*
+* MBCS chars supported correctly.
+*
+*Entry:
+* char *string = string to break into tokens.
+* char *sepset = set of characters to use as seperators
+*
+*Exit:
+* returns pointer to token, or NULL if no more tokens
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbstok( string, sepset )
+unsigned char * string;
+const unsigned char * sepset;
+
+{
+ unsigned char *nextsep;
+
+#ifdef MTHREAD
+#ifdef _CRUISER_
+
+ struct _tiddata * tdata;
+
+ tdata = _gettidtab(); /* init tid's data address */
+
+#else /* ndef _CRUISER_ */
+#ifdef _WIN32_
+
+ _ptiddata ptd = _getptd();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+#endif /* _CRUISER_ */
+
+ unsigned char *nextoken;
+
+#else /* MTHREAD */
+
+ static unsigned char *nextoken;
+
+#endif /* MTHREAD */
+
+
+ /* init start of scan */
+
+ if (string)
+ nextoken = string;
+ else
+ /* If string==NULL, continue with previous string */
+ {
+
+#ifdef MTHREAD
+#ifdef _CRUISER_
+
+ nextoken = tdata->_mtoken;
+
+#else /* ndef _CRUISER_ */
+#ifdef _WIN32_
+
+ nextoken = ptd->_mtoken;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+#endif /* _CRUISER_ */
+#endif /* MTHREAD */
+
+ if (!nextoken)
+ return NULL;
+ }
+
+ /* skip over lead seperators */
+
+ if ((string = _MBSSPNP(nextoken, sepset)) == NULL)
+ return(NULL);
+
+
+ /* test for end of string */
+
+ if ( (*string == '\0') ||
+ ( (_ISLEADBYTE(*string)) && (string[1] == '\0') )
+ )
+ return(NULL);
+
+
+ /* find next seperator */
+
+ nextsep = _MBSPBRK(string, sepset);
+
+ if ((nextsep == NULL) || (*nextsep == '\0'))
+ nextoken = NULL;
+ else {
+ if (_ISLEADBYTE(*nextsep))
+ *nextsep++ = '\0';
+ *nextsep = '\0';
+ nextoken = ++nextsep;
+ }
+
+#ifdef MTHREAD
+ /* Update the corresponding field in the per-thread data * structure */
+
+#ifdef _CRUISER_
+
+ tdata->_mtoken = nextoken;
+
+#else /* _CRUISER_ */
+
+#ifdef _WIN32_
+
+ ptd->_mtoken = nextoken;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#endif /* MTHREAD */
+
+ return(string);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbsupr.c b/private/crt32/mbstring/mbsupr.c
new file mode 100644
index 000000000..36032c1b1
--- /dev/null
+++ b/private/crt32/mbstring/mbsupr.c
@@ -0,0 +1,72 @@
+/***
+*mbsupr.c - Convert string upper case (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert string upper case (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <mbctype.h>
+
+
+/***
+* _mbsupr - Convert string upper case (MBCS)
+*
+*Purpose:
+* Converts all the lower case characters in a string
+* to upper case in place. Handles MBCS chars correctly.
+*
+*Entry:
+* unsigned char *string = pointer to string
+*
+*Exit:
+* Returns a pointer to the input string; no error return.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _mbsupr( string )
+unsigned char *string;
+{
+ unsigned char *cp;
+
+ for (cp=string; *cp; cp++) {
+
+ if (_ISLEADBYTE(*cp)) {
+
+#ifdef _MBCS_OS
+ cp++; /* bump pointer */
+#else
+ if ((_mbascii) && (*cp == _MBASCIILEAD)) {
+
+ if ( (*(cp+1) >= (_MBLOWERLOW & 0x00FF))
+ && (*(cp+1) <= (_MBLOWERHIGH & 0x00FF))
+ )
+ *(cp+1) -= _MBCASEDIFF;
+ }
+
+ cp++;
+#endif
+
+ }
+
+ else
+ /* single byte, macro version */
+ *cp = (unsigned char) toupper(*cp);
+
+ }
+
+ return( string );
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbtohira.c b/private/crt32/mbstring/mbtohira.c
new file mode 100644
index 000000000..d031dc770
--- /dev/null
+++ b/private/crt32/mbstring/mbtohira.c
@@ -0,0 +1,53 @@
+#ifdef _KANJI
+
+/***
+*mbtohira.c - Convert character from katakana to hiragana (Japanese).
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _jtohira() - convert character to hiragana.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+
+
+/***
+*unsigned int _mbctohira(c) - Converts character to hiragana.
+*
+*Purpose:
+* Converts the character c from katakana to hiragana, if possible.
+*
+*Entry:
+* unsigned int c - Character to convert.
+*
+*Exit:
+* Returns the converted character.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _mbctohira(
+ unsigned int c
+ )
+{
+ if (_ismbckata(c) && c <= 0x8393) {
+ if (c < 0x837f)
+ c -= 0xa1;
+ else
+ c -= 0xa2;
+ }
+ return(c);
+}
+
+#endif /* _KANJI */
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbtokata.c b/private/crt32/mbstring/mbtokata.c
new file mode 100644
index 000000000..f86d6d2c5
--- /dev/null
+++ b/private/crt32/mbstring/mbtokata.c
@@ -0,0 +1,51 @@
+/***
+*mbtokata.c - Converts character to katakana.
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts a character from hiragana to katakana.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#ifdef _KANJI
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+
+
+/***
+*unsigned short _mbctokata(c) - Converts character to katakana.
+*
+*Purpose:
+* If the character c is hiragana, convert to katakana.
+*
+*Entry:
+* unsigned int c - Character to convert.
+*
+*Exit:
+* Returns converted character.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _mbctokata(
+ unsigned int c
+ )
+{
+ if (_ismbchira(c)) {
+ c += 0xa1;
+ if (c >= 0x837f)
+ c++;
+ }
+ return(c);
+}
+
+#endif /* _KANJI */
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbtolwr.c b/private/crt32/mbstring/mbtolwr.c
new file mode 100644
index 000000000..997fdb322
--- /dev/null
+++ b/private/crt32/mbstring/mbtolwr.c
@@ -0,0 +1,72 @@
+/***
+*mbtolwr.c - Convert character to lower case (MBCS).
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert character to lower case (MBCS).
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _mbctolower - Convert character to lower case (MBCS)
+*
+*Purpose:
+* If the given character is upper case, convert it to lower case.
+* Handles MBCS characters correctly.
+*
+* Note: Use test against 0x00FF instead of _ISLEADBYTE
+* to ensure that we don't call SBCS routine with a two-byte
+* value.
+*
+*Entry:
+* unsigned int c = character to convert
+*
+*Exit:
+* Returns converted character
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _mbctolower(
+ unsigned int c
+ )
+{
+
+#ifdef _MBCS_OS
+
+ if (c > 0x00FF)
+ return(c);
+ else
+ return((unsigned int)tolower((int)c));
+
+#else
+
+ if (c > 0x00FF) {
+
+ if ( (_mbascii) &&
+ ((c >= _MBUPPERLOW) && (c <= _MBUPPERHIGH))
+ )
+ c += _MBCASEDIFF;
+ }
+
+ else
+ return((unsigned int)tolower((int)c));
+
+#endif
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/mbtoupr.c b/private/crt32/mbstring/mbtoupr.c
new file mode 100644
index 000000000..515e7163b
--- /dev/null
+++ b/private/crt32/mbstring/mbtoupr.c
@@ -0,0 +1,72 @@
+/***
+*mbtoupr.c - Convert character to upper case (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert character to upper case (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <ctype.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+* _mbctoupper - Convert character to upper case (MBCS)
+*
+*Purpose:
+* If the given character is lower case, convert to upper case.
+* Handles MBCS chars correctly.
+*
+* Note: Use test against 0x00FF instead of _ISLEADBYTE
+* to ensure that we don't call SBCS routine with a two-byte
+* value.
+*
+*Entry:
+* unsigned int c = character to convert
+*
+*Exit:
+* Returns converted character
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _mbctoupper(
+ unsigned int c
+ )
+{
+
+#ifdef _MBCS_OS
+
+ if (c > 0x00FF)
+ return(c);
+ else
+ return((unsigned int)toupper((int)c));
+
+#else
+
+ if (c > 0x00FF) {
+
+ if ( (_mbascii) &&
+ ((c >= _MBLOWERLOW) && (c <= _MBLOWERHIGH))
+ )
+ c -= _MBCASEDIFF;
+ }
+
+ else
+ return((unsigned int)toupper((int)c));
+
+#endif
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/sources b/private/crt32/mbstring/sources
new file mode 100644
index 000000000..a25531c5a
--- /dev/null
+++ b/private/crt32/mbstring/sources
@@ -0,0 +1,105 @@
+!IF 0
+
+Copyright (c) 1989 - 1992, Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+ karlsi 15-Nov-1992, Port mb functions from 16-bit sources
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=mbstring
+
+TARGETNAME=mbstring
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=ISMBALPH.C \
+ ISMBDGT.C \
+ ISMBKNJ.C \
+ ISMBLGL.C \
+ ISMBLWR.C \
+ ISMBPRN.C \
+ ISMBSLE.C \
+ ISMBSPC.C \
+ ISMBSTR.C \
+ ISMBUPR.C \
+ MBASCII0.C \
+ MBBTYPE.C \
+ MBCCPY.C \
+ MBCLEN.C \
+ MBCLEVEL.C \
+ MBCTYPE.C \
+ MBSBTYPE.C \
+ MBSCHR.C \
+ MBSCMP.C \
+ MBSCSPN.C \
+ MBSDEC.C \
+ MBSICMP.C \
+ MBSINC.C \
+ MBSLEN.C \
+ MBSLWR.C \
+ MBSNBCAT.C \
+ MBSNBCMP.C \
+ MBSNBCNT.C \
+ MBSNBCPY.C \
+ MBSNBICM.C \
+ MBSNBSET.C \
+ MBSNCAT.C \
+ MBSNCCNT.C \
+ MBSNCMP.C \
+ MBSNCPY.C \
+ MBSNEXTC.C \
+ MBSNICMP.C \
+ MBSNINC.C \
+ MBSNSET.C \
+ MBSPBRK.C \
+ MBSRCHR.C \
+ MBSREV.C \
+ MBSSET.C \
+ MBSSPN.C \
+ MBSSPNP.C \
+ MBSSTR.C \
+ MBSUPR.C \
+ MBTOHIRA.C \
+ MBTOKATA.C \
+ MBTOLWR.C \
+ MBTOUPR.C \
+ STRDEC.C \
+ STRINC.C \
+ STRNCNT.C \
+ STRNEXTC.C \
+ STRNINC.C \
+ STRSPNP.C \
+ TOJISJMS.C \
+ TOMBBMBC.C \
+ ISMBBYTE.C \
+ MBSCAT.C \
+ MBSDUP.C \
+ MBSTOK.C
+
+i386_SOURCES=i386\MBSCAT.ASM \
+ i386\MBSDUP.ASM
+
+MIPS_SOURCES=
+
diff --git a/private/crt32/mbstring/strdec.c b/private/crt32/mbstring/strdec.c
new file mode 100644
index 000000000..d9c41e5f3
--- /dev/null
+++ b/private/crt32/mbstring/strdec.c
@@ -0,0 +1,46 @@
+/***
+*strdec.c - Move string pointer back one char (SBCS mapping of MBCS function).
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Move string pointer backward one character (SBCS mapping for MBCS lib).
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 06-03-93 KRS Remove pointer checks.
+* 08-03-93 KRS Fix prototype.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <mbctype.h>
+#include <stddef.h>
+
+/***
+*_strdec - Move SBCS string pointer backward one charcter (MBCS mapping).
+*
+*Purpose:
+* Move the supplied string pointer backwards by one character.
+*
+*Entry:
+* const unsigned char *string = pointer to beginning of string
+* const unsigned char *current = current char pointer
+*
+*Exit:
+* Returns pointer after moving it.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _strdec(string, current)
+const unsigned char *string;
+const unsigned char *current;
+{
+ return (unsigned char *)(--current);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/strinc.c b/private/crt32/mbstring/strinc.c
new file mode 100644
index 000000000..01f17efd4
--- /dev/null
+++ b/private/crt32/mbstring/strinc.c
@@ -0,0 +1,44 @@
+/***
+*strinc.c - Move SBCS string pointer ahead one charcter (MBCS mapping).
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Move SBCS string pointer ahead one character (MBCS mapping).
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 06-03-93 KRS Remove NULL pointer check.
+* 08-03-93 KRS Fix prototype.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <mbctype.h>
+#include <stddef.h>
+
+/***
+*_mbsinc - Move SBCS string pointer ahead one charcter (MBCS mapping).
+*
+*Purpose:
+* Move the supplied string pointer ahead by one character.
+*
+*Entry:
+* const unsigned char *current = current char pointer
+*
+*Exit:
+* Returns pointer after moving it.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _strinc(current)
+const unsigned char *current;
+{
+ return (unsigned char *)(++current);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/strncnt.c b/private/crt32/mbstring/strncnt.c
new file mode 100644
index 000000000..cce09115e
--- /dev/null
+++ b/private/crt32/mbstring/strncnt.c
@@ -0,0 +1,52 @@
+/***
+*strncnt.c - Return char count of string.
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Return char count of MBCS string
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+/***
+* _strncnt - Return char count of string
+*
+*Purpose:
+* Used for mapping _mbsnbcnt and _mbsnccnt to an equivilent non-MBCS
+* implementation when _MBCS is not defined. Returns the minimum of
+* strlen and bcnt.
+*
+*Entry:
+* const unsigned char *string = pointer to string
+* unsigned int bcnt = number of bytes to scan
+*
+*Exit:
+* Returns number of chars/bytes between string and bcnt.
+*
+* If the end of the string is encountered before bcnt chars were
+* scanned, then the length of the string in chars is returned.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 _strncnt(string, bcnt)
+const unsigned char *string;
+size_t bcnt;
+{
+ size_t len;
+
+ len = strlen (string);
+
+ return( (len > bcnt) ? (bcnt) : (len) );
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/strnextc.c b/private/crt32/mbstring/strnextc.c
new file mode 100644
index 000000000..ef2231ccc
--- /dev/null
+++ b/private/crt32/mbstring/strnextc.c
@@ -0,0 +1,44 @@
+/***
+*strnextc.c - Find the next character of a non-MBCS string.
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* To return the value of the next character in a non-MBCS string.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+
+
+/***
+*_strnextc: Returns the next character in a string.
+*
+*Purpose:
+* To return the value of the next character in an non-MBCS string.
+* Needed for mapping _mbsnextc to the non-MBCS case. Does not
+* advance pointer.
+*
+*Entry:
+* unsigned char *s = string
+*
+*Exit:
+* unsigned int next = next character.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _strnextc(s)
+const unsigned char *s;
+{
+ return ((unsigned int) *s);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/strninc.c b/private/crt32/mbstring/strninc.c
new file mode 100644
index 000000000..211fdbc99
--- /dev/null
+++ b/private/crt32/mbstring/strninc.c
@@ -0,0 +1,47 @@
+/***
+*strninc.c - Increment non-MBCS string pointer by specified char count.
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Increment non-MBCS string pointer by specified char count.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 06-03-93 KRS Remove NULL pointer check.
+* 08-03-93 KRS Fix return value arithmetic.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <stddef.h>
+
+/***
+*_strninc - Increment a SBCS string pointer by specified char count, used
+* for mapping _[f]mbsninc to the non-MBCS case.
+*
+*Purpose:
+* Increment the supplied string pointer by the specified number
+* of characters.
+*
+*Entry:
+* const unsigned char *string = pointer to string
+* unsigned int ccnt = number of char to advance the pointer
+*
+*Exit:
+* Returns pointer after advancing it.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned char * _CRTAPI1 _strninc(string, ccnt)
+const unsigned char *string;
+size_t ccnt;
+{
+ return((char *)string + (unsigned)ccnt);
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/strspnp.c b/private/crt32/mbstring/strspnp.c
new file mode 100644
index 000000000..2e6b9232e
--- /dev/null
+++ b/private/crt32/mbstring/strspnp.c
@@ -0,0 +1,65 @@
+/***
+*strspnp.c - Search for init substring of chars from control string (MBCS)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Search for init substring of chars from control string (MBCS)
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbctype.h>
+#include <mbstring.h>
+#include <stddef.h>
+
+
+/***
+* _strspnp - Find first string char not in charset, return pointer (MBCS)
+*
+*Purpose:
+* Returns maximum leading segment of string consisting solely
+* of characters from charset.
+*
+*Entry:
+* unsigned char *string = string to search in
+* unsigned char *charset = set of characters to scan over
+*
+*Exit:
+*
+* Returns pointer to first character not in charset.
+* Returns NULL if string consists entirely of characters from charset.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+unsigned char * _CRTAPI1 _strspnp( string, charset )
+const unsigned char *string;
+const unsigned char *charset;
+{
+ unsigned char *p, *q;
+
+ /* loop through the string to be inspected */
+ for (q = (char *)string; *q; q++) {
+
+ /* loop through the charset */
+ for (p = (char *)charset; *p; p++)
+ if (*p == *q)
+ break;
+
+ if (*p == '\0') /* end of charset? */
+ break; /* yes, no match on this char */
+
+ }
+
+ return((*q) ? q : NULL); /* pointer */
+
+}
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/tojisjms.c b/private/crt32/mbstring/tojisjms.c
new file mode 100644
index 000000000..1f6f71f07
--- /dev/null
+++ b/private/crt32/mbstring/tojisjms.c
@@ -0,0 +1,116 @@
+/***
+*tojisjms.c: Converts JIS to JMS code, and JMS to JIS code.
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Convert JIS code into Microsoft Kanji code, and vice versa.
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 05-28-93 KRS Ikura #27: Validate output is legal JIS.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#ifdef _KANJI
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+#include <mbctype.h>
+
+
+/***
+*unsigned int _mbcjistojms(c) - Converts JIS code to Microsoft Kanji Code.
+*
+*Purpose:
+* Convert JIS code to Microsoft Kanji code.
+*
+*Entry:
+* unsigned int c - JIS code to be converted. First byte is the upper
+* 8 bits, and second is the lower 8 bits.
+*
+*Exit:
+* Returns related Microsoft Kanji Code. First byte is the upper 8 bits
+* and second byte is the lower 8 bits.
+*
+*Exceptions:
+* If c is out of range, _mbcjistojms returns zero.
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _mbcjistojms(
+ unsigned int c
+ )
+{
+ unsigned int h, l;
+
+ h = (c >> 8) & 0xff;
+ l = c & 0xff;
+ if (h < 0x21 || h > 0x7e || l < 0x21 || l > 0x7e)
+ return 0;
+ if (h & 0x01) { /* first byte is odd */
+ if (l <= 0x5f)
+ l += 0x1f;
+ else
+ l += 0x20;
+ }
+ else
+ l += 0x7e;
+
+ h = ((h - 0x21) >> 1) + 0x81;
+ if (h > 0x9f)
+ h += 0x40;
+ return (h << 8) | l;
+}
+
+
+/***
+*unsigned int _mbcjmstojis(c) - Converts Microsoft Kanji code into JIS code.
+*
+*Purpose:
+* To convert Microsoft Kanji code into JIS code.
+*
+*Entry:
+* unsigned int c - Microsoft Kanji code to be converted. First byte is
+* the upper 8 bits, and the second is the lower 8 bits.
+*
+*Exit:
+* Returns related JIS Code. First byte is the upper 8 bits and the second
+* byte is the lower 8 bits. If c is out of range, return zero.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _mbcjmstojis(c)
+unsigned int c;
+{
+ unsigned int h, l;
+
+ h = (c >> 8) & 0xff;
+ l = c & 0xff;
+
+ /* make sure input is valid shift-JIS */
+ if ((!(_ISLEADBYTE(h))) || (!(_ISTRAILBYTE(l))))
+ return 0;
+
+ h -= (h >= 0xa0) ? 0xc1 : 0x81;
+ if(l >= 0x9f) {
+ c = (h << 9) + 0x2200;
+ c |= l - 0x7e;
+ } else {
+ c = (h << 9) + 0x2100;
+ c |= l - ((l <= 0x7e) ? 0x1f : 0x20);
+ }
+
+ /* not all shift-JIS maps to JIS, so make sure output is valid */
+ if ( (c>0x7E7E) || (c<0x2121) || ((c&0xFF)>0x7E) || ((c&0xFF)<0x21) )
+ return 0;
+
+ return c;
+}
+
+#endif /* _KANJI */
+#endif /* _MBCS */
diff --git a/private/crt32/mbstring/tombbmbc.c b/private/crt32/mbstring/tombbmbc.c
new file mode 100644
index 000000000..6abd94b04
--- /dev/null
+++ b/private/crt32/mbstring/tombbmbc.c
@@ -0,0 +1,312 @@
+/***
+*tombbmbc.c - convert 1-byte code to and from 2-byte code
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* _mbbtombc() - converts 1-byte code to corresponding 2-byte code
+* _mbctombb() - converts 2-byte code to corresponding 1-byte code
+*
+*Revision History:
+* 11-19-92 KRS Ported from 16-bit sources.
+* 08-20-93 CFW Change short params to int for 32-bit tree.
+*
+*******************************************************************************/
+
+#ifdef _MBCS
+#ifdef _KANJI
+#include <cruntime.h>
+#include <mbdata.h>
+#include <mbstring.h>
+
+
+#define ASCLOW 0x20
+#define ASCHIGH 0x7e
+
+#define SBLOW 0xA1
+#define SBHIGH 0xDF
+
+#define MBLIMIT 0x8396
+
+static unsigned short mbbtable[] = {
+ /*20*/ 0x8140, 0x8149, 0x8168, 0x8194, 0x8190, 0x8193, 0x8195, 0x8166,
+ 0x8169, 0x816a, 0x8196, 0x817b, 0x8143, 0x817c, 0x8144, 0x815e,
+ /*30*/ 0x824f, 0x8250, 0x8251, 0x8252, 0x8253, 0x8254, 0x8255, 0x8256,
+ 0x8257, 0x8258, 0x8146, 0x8147, 0x8183, 0x8181, 0x8184, 0x8148,
+ /*40*/ 0x8197, 0x8260, 0x8261, 0x8262, 0x8263, 0x8264, 0x8265, 0x8266,
+ 0x8267, 0x8268, 0x8269, 0x826a, 0x826b, 0x826c, 0x826d, 0x826e,
+ /*50*/ 0x826f, 0x8270, 0x8271, 0x8272, 0x8273, 0x8274, 0x8275, 0x8276,
+ 0x8277, 0x8278, 0x8279, 0x816d, 0x818f, 0x816e, 0x814f, 0x8151,
+ /*60*/ 0x8165, 0x8281, 0x8282, 0x8283, 0x8284, 0x8285, 0x8286, 0x8287,
+ 0x8288, 0x8289, 0x828a, 0x828b, 0x828c, 0x828d, 0x828e, 0x828f,
+ /*70*/ 0x8290, 0x8291, 0x8292, 0x8293, 0x8294, 0x8295, 0x8296, 0x8297,
+ 0x8298, 0x8299, 0x829a, 0x816f, 0x8162, 0x8170, 0x8150,
+};
+
+static struct {
+ unsigned char asc;
+ char synonym;
+ unsigned short mbccode;
+} mbctable[] = {
+ // ASCII Code | Synonym | KANJI Code
+//Katakana Table
+ { 0xA7, 1, 0x8340 }, // 'a'
+ { 0xB1, 1, 0x8341 }, // 'A'
+ { 0xA8, 1, 0x8342 }, // 'i'
+ { 0xB2, 1, 0x8343 }, // 'I'
+ { 0xA9, 1, 0x8344 }, // 'u'
+ { 0xB3, 1, 0x8345 }, // 'U'
+ { 0xAA, 1, 0x8346 }, // 'e'
+ { 0xB4, 1, 0x8347 }, // 'E'
+ { 0xAB, 1, 0x8348 }, // 'o'
+ { 0xB5, 1, 0x8349 }, // 'O'
+
+ { 0xB6, 2, 0x834A }, // 'KA'
+ { 0xB7, 2, 0x834C }, // 'KI'
+ { 0xB8, 2, 0x834E }, // 'KU'
+ { 0xB9, 2, 0x8350 }, // 'KE'
+ { 0xBA, 2, 0x8352 }, // 'KO'
+
+ { 0xBB, 2, 0x8354 }, // 'SA'
+ { 0xBC, 2, 0x8356 }, // 'SI'
+ { 0xBD, 2, 0x8358 }, // 'SU'
+ { 0xBE, 2, 0x835A }, // 'SE'
+ { 0xBF, 2, 0x835C }, // 'SO'
+
+ { 0xC0, 2, 0x835E }, // 'TA'
+ { 0xC1, 2, 0x8360 }, // 'CHI'
+ { 0xAF, 1, 0x8362 }, // 'tsu'
+ { 0xC2, 2, 0x8363 }, // 'TSU'
+ { 0xC3, 2, 0x8365 }, // 'TE''
+ { 0xC4, 2, 0x8367 }, // 'TO''
+
+ { 0xC5, 1, 0x8369 }, // 'NA'
+ { 0xC6, 1, 0x836A }, // 'NI'
+ { 0xC7, 1, 0x836B }, // 'NU'
+ { 0xC8, 1, 0x836C }, // 'NE'
+ { 0xC9, 1, 0x836D }, // 'NO'
+
+ { 0xCA, 3, 0x836E }, // 'HA'
+ { 0xCB, 3, 0x8371 }, // 'HI'
+ { 0xCC, 3, 0x8374 }, // 'FU'
+ { 0xCD, 3, 0x8377 }, // 'HE'
+ { 0xCE, 3, 0x837A }, // 'HO'
+
+ { 0xCF, 1, 0x837D }, // 'MA'
+ { 0xD0, 1, 0x837E }, // 'MI'
+ { 0xD1, 1, 0x8380 }, // 'MU'
+ { 0xD2, 1, 0x8381 }, // 'ME'
+ { 0xD3, 1, 0x8382 }, // 'MO'
+
+ { 0xAC, 1, 0x8383 }, // 'ya'
+ { 0xD4, 1, 0x8384 }, // 'YA'
+ { 0xAD, 1, 0x8385 }, // 'yu'
+ { 0xD5, 1, 0x8386 }, // 'YU'
+ { 0xAE, 1, 0x8387 }, // 'yo'
+ { 0xD6, 1, 0x8388 }, // 'YO'
+
+ { 0xD7, 1, 0x8389 }, // 'RA'
+ { 0xD8, 1, 0x838A }, // 'RI'
+ { 0xD9, 1, 0x838B }, // 'RU'
+ { 0xDA, 1, 0x838C }, // 'RE'
+ { 0xDB, 1, 0x838D }, // 'RO'
+
+ { 0xDC, 2, 0x838E }, // 'WA'
+ { 0xB2, 1, 0x8390 }, // 'I'
+ { 0xB4, 1, 0x8391 }, // 'E'
+
+ { 0xA6, 1, 0x8392 }, // 'WO'
+ { 0xDD, 1, 0x8393 }, // 'N'
+
+ { 0xB3, 1, 0x8394 }, // 'U'
+ { 0xB6, 1, 0x8395 }, // 'KA'
+ { 0xB9, 1, 0x8396 }, // 'KE'
+
+// Hiragana Table
+ { 0xA7, 1, 0x829F }, // 'a'
+ { 0xB1, 1, 0x82A0 }, // 'A'
+ { 0xA8, 1, 0x82A1 }, // 'i'
+ { 0xB2, 1, 0x82A2 }, // 'I'
+ { 0xA9, 1, 0x82A3 }, // 'u'
+ { 0xB3, 1, 0x82A4 }, // 'U'
+ { 0xAA, 1, 0x82A5 }, // 'e'
+ { 0xB4, 1, 0x82A6 }, // 'E'
+ { 0xAB, 1, 0x82A7 }, // 'o'
+ { 0xB5, 1, 0x82A8 }, // 'O'
+
+ { 0xB6, 2, 0x82A9 }, // 'KA'
+ { 0xB7, 2, 0x82AB }, // 'KI'
+ { 0xB8, 2, 0x82AD }, // 'KU'
+ { 0xB9, 2, 0x82AF }, // 'KE'
+ { 0xBA, 2, 0x82B1 }, // 'KO'
+
+ { 0xBB, 2, 0x82B3 }, // 'SA'
+ { 0xBC, 2, 0x82B5 }, // 'SI'
+ { 0xBD, 2, 0x82B7 }, // 'SU'
+ { 0xBE, 2, 0x82B9 }, // 'SE'
+ { 0xBF, 2, 0x82BB }, // 'SO'
+
+ { 0xC0, 2, 0x82BD }, // 'TA'
+ { 0xC1, 2, 0x82BF }, // 'CHI'
+ { 0xAF, 1, 0x82C1 }, // 'tsu'
+ { 0xC2, 2, 0x82C2 }, // 'TSU'
+ { 0xC3, 2, 0x82C4 }, // 'TE'
+ { 0xC4, 2, 0x82C6 }, // 'TO'
+
+ { 0xC5, 1, 0x82C8 }, // 'NA'
+ { 0xC6, 1, 0x82C9 }, // 'NI'
+ { 0xC7, 1, 0x82CA }, // 'NU'
+ { 0xC8, 1, 0x82CB }, // 'NE'
+ { 0xC9, 1, 0x82CC }, // 'NO'
+
+ { 0xCA, 3, 0x82CD }, // 'HA'
+ { 0xCB, 3, 0x82D0 }, // 'HI'
+ { 0xCC, 3, 0x82D3 }, // 'FU'
+ { 0xCD, 3, 0x82D6 }, // 'HE'
+ { 0xCE, 3, 0x82D9 }, // 'HO'
+
+ { 0xCF, 1, 0x82DC }, // 'MA'
+ { 0xD0, 1, 0x82DD }, // 'MI'
+ { 0xD1, 1, 0x82DE }, // 'MU'
+ { 0xD2, 1, 0x82DF }, // 'ME'
+ { 0xD3, 1, 0x82E0 }, // 'MO'
+
+ { 0xAC, 1, 0x82E1 }, // 'ya'
+ { 0xD4, 1, 0x82E2 }, // 'YA'
+ { 0xAD, 1, 0x82E3 }, // 'yu'
+ { 0xD5, 1, 0x82E4 }, // 'YU'
+ { 0xAE, 1, 0x82E5 }, // 'yo'
+ { 0xD6, 1, 0x82E6 }, // 'YO'
+
+ { 0xD7, 1, 0x82E7 }, // 'RA'
+ { 0xD8, 1, 0x82E8 }, // 'RI'
+ { 0xD9, 1, 0x82E9 }, // 'RU'
+ { 0xDA, 1, 0x82EA }, // 'RE'
+ { 0xDB, 1, 0x82EB }, // 'RO'
+
+ { 0xDC, 2, 0x82EC }, // 'WA'
+ { 0xB2, 1, 0x82EE }, // 'I'
+ { 0xB4, 1, 0x82EF }, // 'E'
+
+ { 0xA6, 1, 0x82F0 }, // 'WO'
+ { 0xDD, 1, 0x82F1 }, // 'N'
+
+ { 0x20, 1, 0x8140 }, // ' '
+// { 0xA0, 1, 0x8140 }, // ' '
+ { 0xA1, 1, 0x8142 }, //
+ { 0xA2, 1, 0x8175 }, //
+ { 0xA3, 1, 0x8176 }, //
+ { 0xA4, 1, 0x8141 }, //
+ { 0xA5, 1, 0x8145 }, //
+ { 0xB0, 1, 0x815b }, // '-'
+ { 0xDE, 1, 0x814a }, //
+ { 0xDF, 1, 0x814b }, //
+
+ { 0, 0, 0 } // == End of Table
+
+};
+
+/***
+*unsigned int _mbbtombc(c) - convert mbbvalue to mbcvalue.
+*
+*Purpose:
+* Converts mbbvalue (1-byte) to corresponding mbcvalue code (2-byte).
+*
+*Entry:
+* unsigned int c - mbbvalue character code to be converted.
+*
+*Exit:
+* Returns corresponding mbbvalue (2-byte).
+*
+*Exceptions:
+* Returns c if corresponding 2-byte code does not exist.
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _mbbtombc(
+ unsigned int c
+ )
+{
+ int i;
+
+ /* If c is in the ASCII range, then look up the corresponding value
+ * in the mbbtable. */
+
+ if (c >= ASCLOW && c <= ASCHIGH)
+ return (mbbtable[c-ASCLOW]);
+
+ /* Exception for KANJI */
+
+ if (c == 0xdc)
+ return( 0x838f );
+
+ /* If c is a Katakana character, lookup in mbctable. */
+
+ if (c >= SBLOW && c <= SBHIGH)
+ {
+ for(i = 0; mbctable[i].asc != 0; i++)
+ {
+ if ( c == (unsigned int)mbctable[i].asc ) {
+ c = (unsigned int)mbctable[i].mbccode ;
+ break;
+ }
+ }
+ }
+
+ return(c);
+}
+
+
+/***
+*unsigned int _mbctombb(c) - convert mbcvalue to mbbvalue.
+*
+*Purpose:
+* Converts mbcvalue (2-byte) to corresponding mbbvalue (1-byte).
+*
+*Entry:
+* unsigned int c - mbcvalue character code to convert.
+*
+*Exit:
+* Returns corresponding mbbvalue (1-byte).
+*
+*Exceptions:
+* Returns c if corresponding 1-byte code does not exist.
+*
+*******************************************************************************/
+
+unsigned int _CRTAPI1 _mbctombb(
+ unsigned int c
+ )
+{
+ int i;
+ int result;
+
+ /* Check to see if c is in the ASCII range. */
+
+ for (i = 0; i <= ASCHIGH - ASCLOW; i++)
+ {
+ if (c == (unsigned int)mbbtable[i])
+ return((unsigned int)i + ASCLOW);
+ }
+
+
+ /* If c is a valid MBCS value, search the mbctable for value. */
+
+ if ( c <= MBLIMIT )
+ {
+ for (i = 0; mbctable[i].asc ; i++)
+ {
+ if ( !(result = (int)c - (int)mbctable[i].mbccode) )
+ return( (unsigned int)mbctable[i].asc );
+ else if (((c & 0xff00) == (unsigned int)(mbctable[i].mbccode & 0xff00))
+ && (result > 0)
+ && ((result - mbctable[i].synonym) < 0))
+ return( (unsigned int)mbctable[i].asc );
+ }
+ }
+
+ return(c);
+}
+
+#endif /* _KANJI */
+#endif /* _MBCS */
diff --git a/private/crt32/misc/_strerr.c b/private/crt32/misc/_strerr.c
new file mode 100644
index 000000000..8863e64c5
--- /dev/null
+++ b/private/crt32/misc/_strerr.c
@@ -0,0 +1,143 @@
+/***
+*_strerr.c - routine for indexing into system error list
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Returns system error message index by errno; conforms to the
+* XENIX standard, much compatibility with 1983 uniforum draft standard.
+*
+*Revision History:
+* 02-24-87 JCR Renamed this routine from "strerror" to "_strerror"
+* for MS. The new "strerror" routine conforms to the
+* ANSI interface.
+* 11-10-87 SKS Remove IBMC20 switch
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-05-87 JCR Mthread support
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-06-89 JCR 386 mthread support
+* 11-20-89 GJF Fixed copyright, indents. Removed unreferenced local.
+* Added const attribute to type of message
+* 03-13-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>
+* 07-25-90 SBM Removed redundant include (stdio.h)
+* 10-04-90 GJF New-style function declarator.
+* 07-18-91 GJF Multi-thread support for Win32 [_WIN32_].
+* 02-17-93 GJF Changed for new _getptd().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <errmsg.h>
+#include <syserr.h>
+#include <string.h>
+#include <malloc.h>
+#include <os2dll.h>
+
+/* Max length of message = user_string(94)+system_string+2 */
+/* [NOTE: The mthread error message buffer is shared by both strerror
+ and _strerror so must be the max length of both. */
+#define _ERRMSGLEN_ 94+_SYS_MSGMAX+2
+
+/***
+*char *_strerror(message) - get system error message
+*
+*Purpose:
+* builds an error message consisting of the users error message
+* (the message parameter), followed by ": ", followed by the system
+* error message (index through errno), followed by a newline. If
+* message is NULL or a null string, returns a pointer to just
+* the system error message.
+*
+*Entry:
+* char *message - user's message to prefix system error message
+*
+*Exit:
+* returns pointer to static memory containing error message.
+* returns NULL if malloc() fails in multi-thread versions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CRTAPI1 _strerror (
+ REG1 const char *message
+ )
+{
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ struct _tiddata * tdata;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ _ptiddata ptd = _getptd();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ char *bldmsg;
+
+#else
+
+ static char bldmsg[_ERRMSGLEN_];
+
+#endif
+
+
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ /* Use per thread buffer area (malloc space, if necessary) */
+ /* [NOTE: This buffer is shared between _strerror and streror.] */
+ tdata = _gettidtab(); /* get tid's data address */
+ if (tdata->_errmsg == NULL)
+ if ( (tdata->_errmsg = malloc(_ERRMSGLEN_)) == NULL)
+ return(NULL);
+ bldmsg = tdata->_errmsg;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /* Use per thread buffer area (malloc space, if necessary) */
+ /* [NOTE: This buffer is shared between _strerror and streror.] */
+
+ if ( (ptd->_errmsg == NULL) && ((ptd->_errmsg = malloc(_ERRMSGLEN_))
+ == NULL) )
+ return(NULL);
+ bldmsg = ptd->_errmsg;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#endif
+
+ /* Build the error message */
+
+ bldmsg[0] = '\0';
+
+ if (message && *message) {
+ strcat( bldmsg, message );
+ strcat( bldmsg, ": " );
+ }
+
+ strcat( bldmsg, _sys_err_msg( errno ) );
+
+ return( strcat( bldmsg, "\n" ) );
+}
diff --git a/private/crt32/misc/abort.c b/private/crt32/misc/abort.c
new file mode 100644
index 000000000..b88d2fff0
--- /dev/null
+++ b/private/crt32/misc/abort.c
@@ -0,0 +1,96 @@
+/***
+*abort.c - abort a program by raising SIGABRT
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines abort() - print a message and raise SIGABRT.
+*
+*Revision History:
+* 06-30-89 PHG module created, based on asm version
+* 03-13-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 07-26-90 SBM Removed bogus leading underscore from _NMSG_WRITE
+* 10-04-90 GJF New-style function declarator.
+* 10-11-90 GJF Now does raise(SIGABRT). Also changed _NMSG_WRITE()
+* interface.
+* 04-10-91 PNT Added _MAC_ conditional
+* 08-26-92 GJF Include unistd.h for POSIX build.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <internal.h>
+#include <rterr.h>
+#include <signal.h>
+
+/***
+*void abort() - abort the current program by raising SIGABRT
+*
+*Purpose:
+* print out an abort message and raise the SIGABRT signal. If the user
+* hasn't defined an abort handler routine, terminate the program
+* with exit status of 3 without cleaning up.
+*
+* Multi-thread version does not raise SIGABRT -- this isn't supported
+* under multi-thread.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Does not return.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 abort (
+ void
+ )
+{
+ _NMSG_WRITE(_RT_ABORT); /* write the abort message */
+
+#ifdef _POSIX_
+
+ {
+ sigset_t set;
+
+ fflush(NULL);
+
+ signal(SIGABRT, SIG_DFL);
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGABRT);
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
+ }
+
+#endif /* _POSIX_ */
+
+
+#ifndef _MAC_
+
+ raise(SIGABRT); /* raise abort signal */
+
+#endif /* ndef _MAC_ */
+
+ /* We usually won't get here, but it's possible that
+ SIGABRT was ignored. So hose the program anyway. */
+
+#ifdef _POSIX_
+ /* SIGABRT was ignored or handled, and the handler returned
+ normally. We need open streams to be flushed here. */
+
+ exit(3);
+#else /* not _POSIX_ */
+
+ _exit(3);
+#endif /* _POSIX */
+}
diff --git a/private/crt32/misc/abs.c b/private/crt32/misc/abs.c
new file mode 100644
index 000000000..cd5f3d1be
--- /dev/null
+++ b/private/crt32/misc/abs.c
@@ -0,0 +1,51 @@
+/***
+*abs.c - find absolute value
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines abs() - find the absolute value of an int.
+*
+*Revision History:
+* 04-22-87 JMB added function pragma for conversion to C 5.0 compiler
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 03-14-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned up
+* the formatting a bit.
+* 10-04-90 GJF New-style function declarator.
+* 12-28-90 SRW Added _CRUISER_ conditional around function pragma
+* 04-01-91 SRW Enable #pragma function for i386 _WIN32_ builds too.
+* 03-09-94 RDL Enable #pragma function for MIPS _WIN32_ builds too.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+#pragma function(abs)
+#endif
+
+/***
+*int abs(number) - find absolute value of number
+*
+*Purpose:
+* Returns the absolute value of number (if number >= 0, returns number,
+* else returns -number).
+*
+*Entry:
+* int number - number to find absolute value of
+*
+*Exit:
+* returns the aboslute value of number
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 abs (
+ int number
+ )
+{
+ return( number>=0 ? number : -number );
+}
diff --git a/private/crt32/misc/alpha/chandler.c b/private/crt32/misc/alpha/chandler.c
new file mode 100644
index 000000000..68251f1ca
--- /dev/null
+++ b/private/crt32/misc/alpha/chandler.c
@@ -0,0 +1,296 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ chandler.c
+
+Abstract:
+
+ This module implements the C specific exception handler that provides
+ structured condition handling for the C language.
+
+Author:
+
+ David N. Cutler (davec) 11-Sep-1990
+
+Environment:
+
+ Any mode.
+
+Revision History:
+
+ Thomas Van Baak (tvb) 29-Apr-1992
+
+ Adapted for Alpha AXP.
+
+--*/
+
+#include "nt.h"
+
+//
+// Define procedure prototypes for exception filter and termination handler
+// execution routines defined in jmpuwind.s.
+//
+
+LONG
+__C_ExecuteExceptionFilter (
+ PEXCEPTION_POINTERS ExceptionPointers,
+ EXCEPTION_FILTER ExceptionFilter,
+ ULONG EstablisherFrame
+ );
+
+VOID
+__C_ExecuteTerminationHandler (
+ BOOLEAN AbnormalTermination,
+ TERMINATION_HANDLER TerminationHandler,
+ ULONG EstablisherFrame
+ );
+
+EXCEPTION_DISPOSITION
+__C_specific_handler (
+ IN struct _EXCEPTION_RECORD *ExceptionRecord,
+ IN void *EstablisherFrame,
+ IN OUT struct _CONTEXT *ContextRecord,
+ IN OUT struct _DISPATCHER_CONTEXT *DispatcherContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function scans the scope tables associated with the specified
+ procedure and calls exception and termination handlers as necessary.
+
+ This language specific exception handler function is called on a
+ per-frame basis and in two different cases:
+
+ First, the IS_DISPATCHING case, it is called by the exception
+ dispatcher, RtlDispatchException, via the short assembler routine,
+ __C_ExecuteHandlerForException, when trying to locate exception
+ filters within the given frame.
+
+ Second, the IS_UNWINDING case, it is called by the frame unwinder,
+ RtlUnwind, via the short assembler routine, __C_ExecuteHandlerForUnwind,
+ when unwinding the stack and trying to locate termination handlers
+ within the given frame.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ EstablisherFrame - Supplies a pointer to frame of the establisher function.
+
+ ContextRecord - Supplies a pointer to a context record.
+
+ DispatcherContext - Supplies a pointer to the exception dispatcher or
+ unwind dispatcher context.
+
+Return Value:
+
+ If the exception is handled by one of the exception filter routines, then
+ there is no return from this routine and RtlUnwind is called. Otherwise,
+ an exception disposition value of continue execution or continue search is
+ returned.
+
+--*/
+
+{
+
+ ULONG ControlPc;
+ EXCEPTION_FILTER ExceptionFilter;
+ EXCEPTION_POINTERS ExceptionPointers;
+ PRUNTIME_FUNCTION FunctionEntry;
+ ULONG Index;
+ PSCOPE_TABLE ScopeTable;
+ ULONG TargetPc;
+ TERMINATION_HANDLER TerminationHandler;
+ LONG Value;
+
+ //
+ // Get the address of where control left the establisher, the address of
+ // the function table entry that describes the function, and the address of
+ // the scope table.
+ //
+
+ ControlPc = DispatcherContext->ControlPc;
+ FunctionEntry = DispatcherContext->FunctionEntry;
+ ScopeTable = (PSCOPE_TABLE)(FunctionEntry->HandlerData);
+
+ //
+ // The scope table HandlerAddress is either the address of an exception
+ // filter or a termination handler. The C compiler wraps the code in the
+ // exception filter expression or the termination handler clause within
+ // an internal C function. The value of the scope table JumpTarget field
+ // is used to distinguish an exception filter function (JumpTarget non zero)
+ // from a termination handler function (JumpTarget is zero).
+ //
+
+ //
+ // If an unwind is not in progress, then scan the scope table and call
+ // the appropriate exception filter routines. Otherwise, scan the scope
+ // table and call the appropriate termination handlers using the target
+ // PC obtained from the context record.
+ //
+
+ if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) {
+
+ //
+ // Set up the ExceptionPointers structure that is passed as the argument
+ // to the exception filter. It is used by the compiler to implement the
+ // intrinsic functions exception_code() and exception_info().
+ //
+
+ ExceptionPointers.ExceptionRecord = ExceptionRecord;
+ ExceptionPointers.ContextRecord = ContextRecord;
+
+ //
+ // Scan the scope table and call the appropriate exception filter
+ // routines. The scope table entries are known to be sorted by
+ // increasing EndAddress order. Thus a linear scan will naturally
+ // hit inner scope exception clauses before outer scope clauses.
+ //
+
+ for (Index = 0; Index < ScopeTable->Count; Index += 1) {
+ if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) &&
+ (ScopeTable->ScopeRecord[Index].JumpTarget != 0)) {
+
+ //
+ // Call the exception filter routine.
+ //
+
+ ExceptionFilter =
+ (EXCEPTION_FILTER)ScopeTable->ScopeRecord[Index].HandlerAddress;
+ Value = __C_ExecuteExceptionFilter(&ExceptionPointers,
+ ExceptionFilter,
+ (ULONG)EstablisherFrame);
+
+ //
+ // If the return value is less than zero, then dismiss the
+ // exception. Otherwise, if the value is greater than zero,
+ // then unwind to the target exception handler corresponding
+ // to the exception filter. Otherwise, continue the search for
+ // an exception filter.
+ //
+
+ //
+ // Exception filters will usually return one of the following
+ // defines, although the decision below is made only by sign:
+ //
+ // #define EXCEPTION_EXECUTE_HANDLER 1
+ // #define EXCEPTION_CONTINUE_SEARCH 0
+ // #define EXCEPTION_CONTINUE_EXECUTION -1
+ //
+
+ if (Value < 0) {
+ return ExceptionContinueExecution;
+
+ } else if (Value > 0) {
+
+ //
+ // Set the return value for the unwind to the exception
+ // code so the exception handler clause can retrieve it
+ // from v0. This is how GetExceptionCode() is implemented
+ // in exception handler clauses.
+ //
+
+ RtlUnwind(EstablisherFrame,
+ (PVOID)ScopeTable->ScopeRecord[Index].JumpTarget,
+ ExceptionRecord,
+ (PVOID)ExceptionRecord->ExceptionCode);
+ }
+ }
+ }
+
+ } else {
+
+ //
+ // Scan the scope table and call the appropriate termination handler
+ // routines.
+ //
+
+ TargetPc = (ULONG)ContextRecord->Fir;
+ for (Index = 0; Index < ScopeTable->Count; Index += 1) {
+ if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress)) {
+
+ //
+ // If the target PC is within the same scope the control PC
+ // is within, then this is an uplevel goto out of an inner try
+ // scope or a long jump back into a try scope. Terminate the
+ // scan for termination handlers - because any other handlers
+ // will be outside the scope of both the goto and its label.
+ //
+ // N.B. The target PC can be just beyond the end of the scope,
+ // in which case it is a leave from the scope.
+ //
+
+ if ((TargetPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (TargetPc <= ScopeTable->ScopeRecord[Index].EndAddress)) {
+ break;
+
+ } else {
+
+ //
+ // If the scope table entry describes an exception filter
+ // and the associated exception handler is the target of
+ // the unwind, then terminate the scan for termination
+ // handlers. Otherwise, if the scope table entry describes
+ // a termination handler, then record the address of the
+ // end of the scope as the new control PC address and call
+ // the termination handler.
+ //
+ // Recording a new control PC is necessary to ensure that
+ // termination handlers are called only once even when a
+ // collided unwind occurs.
+ //
+
+ if (ScopeTable->ScopeRecord[Index].JumpTarget != 0) {
+
+ //
+ // try/except - exception filter (JumpTarget != 0).
+ // After the exception filter is called, the exception
+ // handler clause is executed by the call to unwind
+ // above. Having reached this point in the scan of the
+ // scope tables, any other termination handlers will
+ // be outside the scope of the try/except.
+ //
+
+ if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) {
+ break;
+ }
+
+ } else {
+
+ //
+ // try/finally - termination handler (JumpTarget == 0).
+ //
+
+ //
+ // Unless the termination handler results in a long
+ // jump, execution will resume at the instruction after
+ // the exception handler clause.
+ //
+ // ## tvb - I'm still suspicious of the +4 below.
+
+ DispatcherContext->ControlPc =
+ ScopeTable->ScopeRecord[Index].EndAddress + 4;
+ TerminationHandler =
+ (TERMINATION_HANDLER)ScopeTable->ScopeRecord[Index].HandlerAddress;
+ __C_ExecuteTerminationHandler(TRUE,
+ TerminationHandler,
+ (ULONG)EstablisherFrame);
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Continue search for exception filters or termination handlers.
+ //
+
+ return ExceptionContinueSearch;
+}
diff --git a/private/crt32/misc/alpha/divdat.s b/private/crt32/misc/alpha/divdat.s
new file mode 100644
index 000000000..543d6237b
--- /dev/null
+++ b/private/crt32/misc/alpha/divdat.s
@@ -0,0 +1,597 @@
+
+ # Copyright 1992,1993, Digital Equipment Corporation
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+ # 009 15 Jul 1992 KDG - Can't have .end for Alpha/OSF - use
+ # new ots_data_end macro
+ # - Need .data for OSF
+ #
+ # 010 4 Sep 1992 KDG Switch PSECT from ots_div_data to ots_lit
+ #
+ # 011 26 Jan 1993 KDG Add underscore, OSF uses CS name
+ #
+ # 012 5 Apr 1993 WBN Use 16-byte entries, up to 512, and
+ # support computing 1/(a+x).
+
+#include "ots_defs.hs"
+
+ # Data area description
+ #
+ # The data area "ots_div_data" is an array of structures, indexed
+ # by the divisor value, with each array entry being 16 bytes in size
+ # formatted as follows:
+ #
+ # 6 1 1
+ # 3 6 5 6 5 0
+ # +-------+-------+-------+-------+-------+-------+-------+-------+
+ # | 32 bit reciprocal (48 bits) | recip^2 |shift|
+ # +-------+-------+-------+-------+-------+-------+-------+-------+
+ # | 64 bit reciprocal |
+ # +---------------------------------------------------------------+
+ #
+ # The 64-bit reciprocal has the leading '1' bit omitted, so it provides
+ # 65 bits of precision -- enough to handle unsigned 64-bit dividends.
+ #
+ # The first quadword contains the 6-bit shift amount needed to handle
+ # 64-bit cases and powers of two. For divisors between 256 and 512,
+ # this quadword also contains a 10-bit coefficient for linearly
+ # approximating larger reciprocals (1/(a+x) = 1/a - x/a^2 + ...).
+ #
+ # The 32-bit reciprocal has the shift count built in, so a UMULH gives
+ # the correct quotient without shifting. The reciprocal needs 33 bits
+ # of precision. The 10-bit reciprocal-squared, and 6-bit shift amount,
+ # are noise in the reciprocal that can be ignored for divisors less than
+ # 512. (The only possible exception is for 1/257, and it checks out OK.)
+ #
+ # Powers of two are flagged with a 32-bit reciprocal that is negative,
+ # and a 64-bit reciprocal that is zero.
+
+ # OTS division data table
+ #
+
+#ifdef VMS
+ .psect ots_lit
+ .align 4 # octaword alignment
+ots_div_data::
+#endif
+#ifdef OSF
+ .globl _OtsDivData
+ .data
+ .align 4
+_OtsDivData:
+#endif
+#ifdef WNT
+ .globl _OtsDivData
+ .data
+ .align 4
+_OtsDivData:
+#endif
+ # recip^2--. .-shift
+ #32b recip / \| 64 bit reciprocal divisor
+ .quad 0x0000000000000000, 0x0000000000000000 # 0
+ .quad 0x8000000000000000, 0x0000000000000000 # 1
+ .quad 0x8000000000000001, 0x0000000000000000 # 2
+ .quad 0x5555555555560002, 0x5555555555555556 # 3
+ .quad 0x8000000000000002, 0x0000000000000000 # 4
+ .quad 0x3333333333340003, 0x999999999999999A # 5
+ .quad 0x2AAAAAAAAAAB0003, 0x5555555555555556 # 6
+ .quad 0x24924924924A0003, 0x2492492492492493 # 7
+ .quad 0x8000000000000003, 0x0000000000000000 # 8
+ .quad 0x1C71C71C71C80004, 0xC71C71C71C71C71D # 9
+ .quad 0x19999999999A0004, 0x999999999999999A # 10
+ .quad 0x1745D1745D180004, 0x745D1745D1745D18 # 11
+ .quad 0x1555555555560004, 0x5555555555555556 # 12
+ .quad 0x13B13B13B13C0004, 0x3B13B13B13B13B14 # 13
+ .quad 0x1249249249250004, 0x2492492492492493 # 14
+ .quad 0x1111111111120004, 0x1111111111111112 # 15
+ .quad 0x8000000000000004, 0x0000000000000000 # 16
+ .quad 0x0F0F0F0F0F100005, 0xE1E1E1E1E1E1E1E2 # 17
+ .quad 0x0E38E38E38E40005, 0xC71C71C71C71C71D # 18
+ .quad 0x0D79435E50D80005, 0xAF286BCA1AF286BD # 19
+ .quad 0x0CCCCCCCCCCD0005, 0x999999999999999A # 20
+ .quad 0x0C30C30C30C40005, 0x8618618618618619 # 21
+ .quad 0x0BA2E8BA2E8C0005, 0x745D1745D1745D18 # 22
+ .quad 0x0B21642C85910005, 0x642C8590B21642C9 # 23
+ .quad 0x0AAAAAAAAAAB0005, 0x5555555555555556 # 24
+ .quad 0x0A3D70A3D70B0005, 0x47AE147AE147AE15 # 25
+ .quad 0x09D89D89D89E0005, 0x3B13B13B13B13B14 # 26
+ .quad 0x097B425ED0980005, 0x2F684BDA12F684BE # 27
+ .quad 0x0924924924930005, 0x2492492492492493 # 28
+ .quad 0x08D3DCB08D3E0005, 0x1A7B9611A7B9611B # 29
+ .quad 0x0888888888890005, 0x1111111111111112 # 30
+ .quad 0x0842108421090005, 0x0842108421084211 # 31
+ .quad 0x8000000000000005, 0x0000000000000000 # 32
+ .quad 0x07C1F07C1F080006, 0xF07C1F07C1F07C20 # 33
+ .quad 0x0787878787880006, 0xE1E1E1E1E1E1E1E2 # 34
+ .quad 0x0750750750760006, 0xD41D41D41D41D41E # 35
+ .quad 0x071C71C71C720006, 0xC71C71C71C71C71D # 36
+ .quad 0x06EB3E45306F0006, 0xBACF914C1BACF915 # 37
+ .quad 0x06BCA1AF286C0006, 0xAF286BCA1AF286BD # 38
+ .quad 0x06906906906A0006, 0xA41A41A41A41A41B # 39
+ .quad 0x0666666666670006, 0x999999999999999A # 40
+ .quad 0x063E7063E7070006, 0x8F9C18F9C18F9C19 # 41
+ .quad 0x0618618618620006, 0x8618618618618619 # 42
+ .quad 0x05F417D05F420006, 0x7D05F417D05F417E # 43
+ .quad 0x05D1745D17460006, 0x745D1745D1745D18 # 44
+ .quad 0x05B05B05B05C0006, 0x6C16C16C16C16C17 # 45
+ .quad 0x0590B21642C90006, 0x642C8590B21642C9 # 46
+ .quad 0x0572620AE4C50006, 0x5C9882B931057263 # 47
+ .quad 0x0555555555560006, 0x5555555555555556 # 48
+ .quad 0x05397829CBC20006, 0x4E5E0A72F0539783 # 49
+ .quad 0x051EB851EB860006, 0x47AE147AE147AE15 # 50
+ .quad 0x0505050505060006, 0x4141414141414142 # 51
+ .quad 0x04EC4EC4EC4F0006, 0x3B13B13B13B13B14 # 52
+ .quad 0x04D4873ECADF0006, 0x3521CFB2B78C1353 # 53
+ .quad 0x04BDA12F684C0006, 0x2F684BDA12F684BE # 54
+ .quad 0x04A7904A79050006, 0x29E4129E4129E413 # 55
+ .quad 0x04924924924A0006, 0x2492492492492493 # 56
+ .quad 0x047DC11F70480006, 0x1F7047DC11F7047E # 57
+ .quad 0x0469EE58469F0006, 0x1A7B9611A7B9611B # 58
+ .quad 0x0456C797DD4A0006, 0x15B1E5F75270D046 # 59
+ .quad 0x0444444444450006, 0x1111111111111112 # 60
+ .quad 0x04325C53EF370006, 0x0C9714FBCDA3AC11 # 61
+ .quad 0x0421084210850006, 0x0842108421084211 # 62
+ .quad 0x0410410410420006, 0x0410410410410411 # 63
+ .quad 0x8000000000000006, 0x0000000000000000 # 64
+ .quad 0x03F03F03F0400007, 0xF81F81F81F81F820 # 65
+ .quad 0x03E0F83E0F840007, 0xF07C1F07C1F07C20 # 66
+ .quad 0x03D226357E170007, 0xE9131ABF0B7672A1 # 67
+ .quad 0x03C3C3C3C3C40007, 0xE1E1E1E1E1E1E1E2 # 68
+ .quad 0x03B5CC0ED7310007, 0xDAE6076B981DAE61 # 69
+ .quad 0x03A83A83A83B0007, 0xD41D41D41D41D41E # 70
+ .quad 0x039B0AD120740007, 0xCD85689039B0AD13 # 71
+ .quad 0x038E38E38E390007, 0xC71C71C71C71C71D # 72
+ .quad 0x0381C0E070390007, 0xC0E070381C0E0704 # 73
+ .quad 0x03759F2298380007, 0xBACF914C1BACF915 # 74
+ .quad 0x0369D0369D040007, 0xB4E81B4E81B4E81C # 75
+ .quad 0x035E50D794360007, 0xAF286BCA1AF286BD # 76
+ .quad 0x03531DEC0D4D0007, 0xA98EF606A63BD81B # 77
+ .quad 0x0348348348350007, 0xA41A41A41A41A41B # 78
+ .quad 0x033D91D2A2070007, 0x9EC8E951033D91D3 # 79
+ .quad 0x0333333333340007, 0x999999999999999A # 80
+ .quad 0x0329161F9ADE0007, 0x948B0FCD6E9E0653 # 81
+ .quad 0x031F3831F3840007, 0x8F9C18F9C18F9C19 # 82
+ .quad 0x03159721ED7F0007, 0x8ACB90F6BF3A9A38 # 83
+ .quad 0x030C30C30C310007, 0x8618618618618619 # 84
+ .quad 0x0303030303040007, 0x8181818181818182 # 85
+ .quad 0x02FA0BE82FA10007, 0x7D05F417D05F417E # 86
+ .quad 0x02F149902F150007, 0x78A4C8178A4C8179 # 87
+ .quad 0x02E8BA2E8BA30007, 0x745D1745D1745D18 # 88
+ .quad 0x02E05C0B81710007, 0x702E05C0B81702E1 # 89
+ .quad 0x02D82D82D82E0007, 0x6C16C16C16C16C17 # 90
+ .quad 0x02D02D02D02E0007, 0x6816816816816817 # 91
+ .quad 0x02C8590B21650007, 0x642C8590B21642C9 # 92
+ .quad 0x02C0B02C0B030007, 0x6058160581605817 # 93
+ .quad 0x02B9310572630007, 0x5C9882B931057263 # 94
+ .quad 0x02B1DA46102C0007, 0x58ED2308158ED231 # 95
+ .quad 0x02AAAAAAAAAB0007, 0x5555555555555556 # 96
+ .quad 0x02A3A0FD5C600007, 0x51D07EAE2F8151D1 # 97
+ .quad 0x029CBC14E5E10007, 0x4E5E0A72F0539783 # 98
+ .quad 0x0295FAD40A580007, 0x4AFD6A052BF5A815 # 99
+ .quad 0x028F5C28F5C30007, 0x47AE147AE147AE15 # 100
+ .quad 0x0288DF0CAC5C0007, 0x446F86562D9FAEE5 # 101
+ .quad 0x0282828282830007, 0x4141414141414142 # 102
+ .quad 0x027C45979C960007, 0x3E22CBCE4A9027C5 # 103
+ .quad 0x0276276276280007, 0x3B13B13B13B13B14 # 104
+ .quad 0x0270270270280007, 0x3813813813813814 # 105
+ .quad 0x026A439F65700007, 0x3521CFB2B78C1353 # 106
+ .quad 0x02647C6945630007, 0x323E34A2B10BF66F # 107
+ .quad 0x025ED097B4260007, 0x2F684BDA12F684BE # 108
+ .quad 0x02593F69B0260007, 0x2C9FB4D812C9FB4E # 109
+ .quad 0x0253C8253C830007, 0x29E4129E4129E413 # 110
+ .quad 0x024E6A1710250007, 0x27350B88127350B9 # 111
+ .quad 0x0249249249250007, 0x2492492492492493 # 112
+ .quad 0x0243F6F024400007, 0x21FB78121FB78122 # 113
+ .quad 0x023EE08FB8240007, 0x1F7047DC11F7047E # 114
+ .quad 0x0239E0D5B4510007, 0x1CF06ADA2811CF07 # 115
+ .quad 0x0234F72C23500007, 0x1A7B9611A7B9611B # 116
+ .quad 0x0230230230240007, 0x1811811811811812 # 117
+ .quad 0x022B63CBEEA50007, 0x15B1E5F75270D046 # 118
+ .quad 0x0226B90226BA0007, 0x135C81135C81135D # 119
+ .quad 0x0222222222230007, 0x1111111111111112 # 120
+ .quad 0x021D9EAD7CD40007, 0x0ECF56BE69C8FDE3 # 121
+ .quad 0x02192E29F79C0007, 0x0C9714FBCDA3AC11 # 122
+ .quad 0x0214D0214D030007, 0x0A6810A6810A6811 # 123
+ .quad 0x0210842108430007, 0x0842108421084211 # 124
+ .quad 0x020C49BA5E360007, 0x0624DD2F1A9FBE77 # 125
+ .quad 0x0208208208210007, 0x0410410410410411 # 126
+ .quad 0x0204081020410007, 0x0204081020408103 # 127
+ .quad 0x8000000000000007, 0x0000000000000000 # 128
+ .quad 0x01FC07F01FC10008, 0xFC07F01FC07F01FD # 129
+ .quad 0x01F81F81F8200008, 0xF81F81F81F81F820 # 130
+ .quad 0x01F44659E4A50008, 0xF44659E4A4271580 # 131
+ .quad 0x01F07C1F07C20008, 0xF07C1F07C1F07C20 # 132
+ .quad 0x01ECC07B301F0008, 0xECC07B301ECC07B4 # 133
+ .quad 0x01E9131ABF0C0008, 0xE9131ABF0B7672A1 # 134
+ .quad 0x01E573AC901F0008, 0xE573AC901E573ACA # 135
+ .quad 0x01E1E1E1E1E20008, 0xE1E1E1E1E1E1E1E2 # 136
+ .quad 0x01DE5D6E3F890008, 0xDE5D6E3F8868A471 # 137
+ .quad 0x01DAE6076B990008, 0xDAE6076B981DAE61 # 138
+ .quad 0x01D77B654B830008, 0xD77B654B82C33918 # 139
+ .quad 0x01D41D41D41E0008, 0xD41D41D41D41D41E # 140
+ .quad 0x01D0CB58F6ED0008, 0xD0CB58F6EC07432E # 141
+ .quad 0x01CD8568903A0008, 0xCD85689039B0AD13 # 142
+ .quad 0x01CA4B3055EF0008, 0xCA4B3055EE19101D # 143
+ .quad 0x01C71C71C71D0008, 0xC71C71C71C71C71D # 144
+ .quad 0x01C3F8F01C400008, 0xC3F8F01C3F8F01C4 # 145
+ .quad 0x01C0E070381D0008, 0xC0E070381C0E0704 # 146
+ .quad 0x01BDD2B899410008, 0xBDD2B899406F74AF # 147
+ .quad 0x01BACF914C1C0008, 0xBACF914C1BACF915 # 148
+ .quad 0x01B7D6C3DDA40008, 0xB7D6C3DDA338B2B0 # 149
+ .quad 0x01B4E81B4E820008, 0xB4E81B4E81B4E81C # 150
+ .quad 0x01B2036406C90008, 0xB2036406C80D901C # 151
+ .quad 0x01AF286BCA1B0008, 0xAF286BCA1AF286BD # 152
+ .quad 0x01AC5701AC580008, 0xAC5701AC5701AC58 # 153
+ .quad 0x01A98EF606A70008, 0xA98EF606A63BD81B # 154
+ .quad 0x01A6D01A6D020008, 0xA6D01A6D01A6D01B # 155
+ .quad 0x01A41A41A41B0008, 0xA41A41A41A41A41B # 156
+ .quad 0x01A16D3F97A50008, 0xA16D3F97A4B01A17 # 157
+ .quad 0x019EC8E951040008, 0x9EC8E951033D91D3 # 158
+ .quad 0x019C2D14EE4B0008, 0x9C2D14EE4A1019C3 # 159
+ .quad 0x01999999999A0008, 0x999999999999999A # 160
+ .quad 0x01970E4F80CC0008, 0x970E4F80CB8727C1 # 161
+ .quad 0x01948B0FCD6F0008, 0x948B0FCD6E9E0653 # 162
+ .quad 0x01920FB49D0F0008, 0x920FB49D0E228D5A # 163
+ .quad 0x018F9C18F9C20008, 0x8F9C18F9C18F9C19 # 164
+ .quad 0x018D3018D3020008, 0x8D3018D3018D3019 # 165
+ .quad 0x018ACB90F6C00008, 0x8ACB90F6BF3A9A38 # 166
+ .quad 0x01886E5F0ABC0008, 0x886E5F0ABB04994C # 167
+ .quad 0x0186186186190008, 0x8618618618618619 # 168
+ .quad 0x0183C977AB2C0008, 0x83C977AB2BEDD28F # 169
+ .quad 0x0181818181820008, 0x8181818181818182 # 170
+ .quad 0x017F405FD0180008, 0x7F405FD017F405FE # 171
+ .quad 0x017D05F417D10008, 0x7D05F417D05F417E # 172
+ .quad 0x017AD2208E0F0008, 0x7AD2208E0ECC3546 # 173
+ .quad 0x0178A4C8178B0008, 0x78A4C8178A4C8179 # 174
+ .quad 0x01767DCE434B0008, 0x767DCE434A9B1018 # 175
+ .quad 0x01745D1745D20008, 0x745D1745D1745D18 # 176
+ .quad 0x01724287F46E0008, 0x724287F46DEBC05D # 177
+ .quad 0x01702E05C0B90008, 0x702E05C0B81702E1 # 178
+ .quad 0x016E1F76B4340008, 0x6E1F76B4337C6CB2 # 179
+ .quad 0x016C16C16C170008, 0x6C16C16C16C16C17 # 180
+ .quad 0x016A13CD15380008, 0x6A13CD153729043F # 181
+ .quad 0x0168168168170008, 0x6816816816816817 # 182
+ .quad 0x01661EC6A5130008, 0x661EC6A5122F9017 # 183
+ .quad 0x01642C8590B30008, 0x642C8590B21642C9 # 184
+ .quad 0x01623FA770170008, 0x623FA7701623FA78 # 185
+ .quad 0x0160581605820008, 0x6058160581605817 # 186
+ .quad 0x015E75BB8D020008, 0x5E75BB8D015E75BC # 187
+ .quad 0x015C9882B9320008, 0x5C9882B931057263 # 188
+ .quad 0x015AC056B0160008, 0x5AC056B015AC056C # 189
+ .quad 0x0158ED2308160008, 0x58ED2308158ED231 # 190
+ .quad 0x01571ED3C5070008, 0x571ED3C506B39A23 # 191
+ .quad 0x0155555555560008, 0x5555555555555556 # 192
+ .quad 0x015390948F410008, 0x5390948F40FEAC70 # 193
+ .quad 0x0151D07EAE300008, 0x51D07EAE2F8151D1 # 194
+ .quad 0x0150150150160008, 0x5015015015015016 # 195
+ .quad 0x014E5E0A72F10008, 0x4E5E0A72F0539783 # 196
+ .quad 0x014CAB88725B0008, 0x4CAB88725AF6E750 # 197
+ .quad 0x014AFD6A052C0008, 0x4AFD6A052BF5A815 # 198
+ .quad 0x0149539E3B2E0008, 0x49539E3B2D066EA3 # 199
+ .quad 0x0147AE147AE20008, 0x47AE147AE147AE15 # 200
+ .quad 0x01460CBC7F5D0008, 0x460CBC7F5CF9A1C1 # 201
+ .quad 0x01446F86562E0008, 0x446F86562D9FAEE5 # 202
+ .quad 0x0142D6625D520008, 0x42D6625D51F86EFA # 203
+ .quad 0x0141414141420008, 0x4141414141414142 # 204
+ .quad 0x013FB013FB020008, 0x3FB013FB013FB014 # 205
+ .quad 0x013E22CBCE4B0008, 0x3E22CBCE4A9027C5 # 206
+ .quad 0x013C995A47BB0008, 0x3C995A47BABE7441 # 207
+ .quad 0x013B13B13B140008, 0x3B13B13B13B13B14 # 208
+ .quad 0x013991C2C1880008, 0x3991C2C187F63372 # 209
+ .quad 0x0138138138140008, 0x3813813813813814 # 210
+ .quad 0x013698DF3DE10008, 0x3698DF3DE0747954 # 211
+ .quad 0x013521CFB2B80008, 0x3521CFB2B78C1353 # 212
+ .quad 0x0133AE45B57C0008, 0x33AE45B57BCB1E0D # 213
+ .quad 0x01323E34A2B20008, 0x323E34A2B10BF66F # 214
+ .quad 0x0130D190130E0008, 0x30D190130D190131 # 215
+ .quad 0x012F684BDA130008, 0x2F684BDA12F684BE # 216
+ .quad 0x012E025C04B90008, 0x2E025C04B8097013 # 217
+ .quad 0x012C9FB4D8130008, 0x2C9FB4D812C9FB4E # 218
+ .quad 0x012B404AD0130008, 0x2B404AD012B404AE # 219
+ .quad 0x0129E4129E420008, 0x29E4129E4129E413 # 220
+ .quad 0x01288B01288C0008, 0x288B01288B01288C # 221
+ .quad 0x0127350B88130008, 0x27350B88127350B9 # 222
+ .quad 0x0125E227080A0008, 0x25E22708092F1139 # 223
+ .quad 0x0124924924930008, 0x2492492492492493 # 224
+ .quad 0x0123456789AC0008, 0x23456789ABCDF013 # 225
+ .quad 0x0121FB7812200008, 0x21FB78121FB78122 # 226
+ .quad 0x0120B470C67D0008, 0x20B470C67C0D8876 # 227
+ .quad 0x011F7047DC120008, 0x1F7047DC11F7047E # 228
+ .quad 0x011E2EF3B3FC0008, 0x1E2EF3B3FB874432 # 229
+ .quad 0x011CF06ADA290008, 0x1CF06ADA2811CF07 # 230
+ .quad 0x011BB4A4046F0008, 0x1BB4A4046ED29012 # 231
+ .quad 0x011A7B9611A80008, 0x1A7B9611A7B9611B # 232
+ .quad 0x0119453808CB0008, 0x19453808CA29C047 # 233
+ .quad 0x0118118118120008, 0x1811811811811812 # 234
+ .quad 0x0116E06894280008, 0x16E0689427378EB5 # 235
+ .quad 0x0115B1E5F7530008, 0x15B1E5F75270D046 # 236
+ .quad 0x011485F0E0AD0008, 0x1485F0E0ACD3B68D # 237
+ .quad 0x01135C81135D0008, 0x135C81135C81135D # 238
+ .quad 0x0112358E75D40008, 0x12358E75D30336A1 # 239
+ .quad 0x0111111111120008, 0x1111111111111112 # 240
+ .quad 0x010FEF010FF00008, 0x0FEF010FEF010FF0 # 241
+ .quad 0x010ECF56BE6A0008, 0x0ECF56BE69C8FDE3 # 242
+ .quad 0x010DB20A88F50008, 0x0DB20A88F469598D # 243
+ .quad 0x010C9714FBCE0008, 0x0C9714FBCDA3AC11 # 244
+ .quad 0x010B7E6EC25A0008, 0x0B7E6EC259DC7936 # 245
+ .quad 0x010A6810A6820008, 0x0A6810A6810A6811 # 246
+ .quad 0x010953F390110008, 0x0953F39010953F3A # 247
+ .quad 0x0108421084220008, 0x0842108421084211 # 248
+ .quad 0x01073260A4800008, 0x073260A47F7C66D0 # 249
+ .quad 0x010624DD2F1B0008, 0x0624DD2F1A9FBE77 # 250
+ .quad 0x0105197F7D740008, 0x05197F7D73404147 # 251
+ .quad 0x0104104104110008, 0x0410410410410411 # 252
+ .quad 0x0103091B51F60008, 0x03091B51F5E1A4EF # 253
+ .quad 0x0102040810210008, 0x0204081020408103 # 254
+ .quad 0x0101010101020008, 0x0101010101010102 # 255
+ .quad 0x800000000000FFC8, 0x0000000000000000 # 256
+ .quad 0x00FF00FF0100FE09, 0xFE01FE01FE01FE02 # 257
+ .quad 0x00FE03F80FE1FC09, 0xFC07F01FC07F01FD # 258
+ .quad 0x00FD08E55010FA09, 0xFA11CAA01FA11CAB # 259
+ .quad 0x00FC0FC0FC10F849, 0xF81F81F81F81F820 # 260
+ .quad 0x00FB18856507F649, 0xF6310ACA0DBB574C # 261
+ .quad 0x00FA232CF253F489, 0xF44659E4A4271580 # 262
+ .quad 0x00F92FB22119F289, 0xF25F644230AB50CB # 263
+ .quad 0x00F83E0F83E1F0C9, 0xF07C1F07C1F07C20 # 264
+ .quad 0x00F74E3FC22DEF09, 0xEE9C7F8458E01EEA # 265
+ .quad 0x00F6603D9810ED09, 0xECC07B301ECC07B4 # 266
+ .quad 0x00F57403D5D1EB49, 0xEAE807ABA01EAE81 # 267
+ .quad 0x00F4898D5F86E989, 0xE9131ABF0B7672A1 # 268
+ .quad 0x00F3A0D52CBBE7C9, 0xE741AA59750E466D # 269
+ .quad 0x00F2B9D64810E649, 0xE573AC901E573ACA # 270
+ .quad 0x00F1D48BCEE1E489, 0xE3A9179DC1A733F5 # 271
+ .quad 0x00F0F0F0F0F1E2C9, 0xE1E1E1E1E1E1E1E2 # 272
+ .quad 0x00F00F00F010E109, 0xE01E01E01E01E01F # 273
+ .quad 0x00EF2EB71FC5DF89, 0xDE5D6E3F8868A471 # 274
+ .quad 0x00EE500EE501DDC9, 0xDCA01DCA01DCA01E # 275
+ .quad 0x00ED7303B5CDDC49, 0xDAE6076B981DAE61 # 276
+ .quad 0x00EC979118F4DAC9, 0xD92F2231E7F89B44 # 277
+ .quad 0x00EBBDB2A5C2D909, 0xD77B654B82C33918 # 278
+ .quad 0x00EAE56403ACD789, 0xD5CAC807572B201E # 279
+ .quad 0x00EA0EA0EA0FD609, 0xD41D41D41D41D41E # 280
+ .quad 0x00E939651FE3D489, 0xD272CA3FC5B1A6B9 # 281
+ .quad 0x00E865AC7B77D309, 0xD0CB58F6EC07432E # 282
+ .quad 0x00E79372E226D189, 0xCF26E5C44BFC61B3 # 283
+ .quad 0x00E6C2B4481DD009, 0xCD85689039B0AD13 # 284
+ .quad 0x00E5F36CB00FCE89, 0xCBE6D9601CBE6D97 # 285
+ .quad 0x00E525982AF8CD09, 0xCA4B3055EE19101D # 286
+ .quad 0x00E45932D7DDCBC9, 0xC8B265AFB8A4201D # 287
+ .quad 0x00E38E38E38FCA49, 0xC71C71C71C71C71D # 288
+ .quad 0x00E2C4A6886BC8C9, 0xC5894D10D4985C20 # 289
+ .quad 0x00E1FC780E20C789, 0xC3F8F01C3F8F01C4 # 290
+ .quad 0x00E135A9C976C609, 0xC26B5392EA01C26C # 291
+ .quad 0x00E070381C0FC4C9, 0xC0E070381C0E0704 # 292
+ .quad 0x00DFAC1F7435C389, 0xBF583EE868D8AEBF # 293
+ .quad 0x00DEE95C4CA1C209, 0xBDD2B899406F74AF # 294
+ .quad 0x00DE27EB2C42C0C9, 0xBC4FD65883E7B3A3 # 295
+ .quad 0x00DD67C8A60EBF89, 0xBACF914C1BACF915 # 296
+ .quad 0x00DCA8F158C8BE49, 0xB951E2B18FF23571 # 297
+ .quad 0x00DBEB61EED2BD09, 0xB7D6C3DDA338B2B0 # 298
+ .quad 0x00DB2F171DF8BBC9, 0xB65E2E3BEEE05232 # 299
+ .quad 0x00DA740DA741BA89, 0xB4E81B4E81B4E81C # 300
+ .quad 0x00D9BA4256C1B949, 0xB37484AD806CDD22 # 301
+ .quad 0x00D901B20365B809, 0xB2036406C80D901C # 302
+ .quad 0x00D84A598ECAB6C9, 0xB094B31D922A3E86 # 303
+ .quad 0x00D79435E50EB589, 0xAF286BCA1AF286BD # 304
+ .quad 0x00D6DF43FCA5B449, 0xADBE87F94905E01B # 305
+ .quad 0x00D62B80D62CB349, 0xAC5701AC5701AC58 # 306
+ .quad 0x00D578E97C40B209, 0xAAF1D2F87EBFCAA2 # 307
+ .quad 0x00D4C77B0354B0C9, 0xA98EF606A63BD81B # 308
+ .quad 0x00D417328988AFC9, 0xA82E65130E158A5C # 309
+ .quad 0x00D3680D3681AE89, 0xA6D01A6D01A6D01B # 310
+ .quad 0x00D2BA083B45AD89, 0xA574107688A4A157 # 311
+ .quad 0x00D20D20D20EAC49, 0xA41A41A41A41A41B # 312
+ .quad 0x00D161543E29AB49, 0xA2C2A87C51CA04E9 # 313
+ .quad 0x00D0B69FCBD3AA49, 0xA16D3F97A4B01A17 # 314
+ .quad 0x00D00D00D00EA909, 0xA01A01A01A01A01B # 315
+ .quad 0x00CF6474A882A809, 0x9EC8E951033D91D3 # 316
+ .quad 0x00CEBCF8BB5CA709, 0x9D79F176B682D396 # 317
+ .quad 0x00CE168A7726A609, 0x9C2D14EE4A1019C3 # 318
+ .quad 0x00CD712752A9A4C9, 0x9AE24EA5510DA484 # 319
+ .quad 0x00CCCCCCCCCDA3C9, 0x999999999999999A # 320
+ .quad 0x00CC29786C77A2C9, 0x9852F0D8EC0FF33E # 321
+ .quad 0x00CB8727C066A1C9, 0x970E4F80CB8727C1 # 322
+ .quad 0x00CAE5D85F1CA0C9, 0x95CBB0BE377AD92B # 323
+ .quad 0x00CA4587E6B89FC9, 0x948B0FCD6E9E0653 # 324
+ .quad 0x00C9A633FCDA9EC9, 0x934C67F9B2CE601A # 325
+ .quad 0x00C907DA4E889DC9, 0x920FB49D0E228D5A # 326
+ .quad 0x00C86A78900D9D09, 0x90D4F120190D4F13 # 327
+ .quad 0x00C7CE0C7CE19C09, 0x8F9C18F9C18F9C19 # 328
+ .quad 0x00C73293D78A9B09, 0x8E6527AF1373F071 # 329
+ .quad 0x00C6980C69819A09, 0x8D3018D3018D3019 # 330
+ .quad 0x00C5FE7403189949, 0x8BFCE8062FF3A019 # 331
+ .quad 0x00C565C87B609849, 0x8ACB90F6BF3A9A38 # 332
+ .quad 0x00C4CE07B00D9749, 0x899C0F601899C0F7 # 333
+ .quad 0x00C4372F855E9689, 0x886E5F0ABB04994C # 334
+ .quad 0x00C3A13DE6059589, 0x87427BCC092B8EE7 # 335
+ .quad 0x00C30C30C30D9489, 0x8618618618618619 # 336
+ .quad 0x00C2780613C193C9, 0x84F00C2780613C04 # 337
+ .quad 0x00C1E4BBD59692C9, 0x83C977AB2BEDD28F # 338
+ .quad 0x00C152500C169209, 0x82A4A0182A4A0183 # 339
+ .quad 0x00C0C0C0C0C19149, 0x8181818181818182 # 340
+ .quad 0x00C0300C03019049, 0x8060180601806019 # 341
+ .quad 0x00BFA02FE80C8F89, 0x7F405FD017F405FE # 342
+ .quad 0x00BF112A8AD38E89, 0x7E225515A4F1D1BA # 343
+ .quad 0x00BE82FA0BE98DC9, 0x7D05F417D05F417E # 344
+ .quad 0x00BDF59C91718D09, 0x7BEB3922E017BEB4 # 345
+ .quad 0x00BD691047088C49, 0x7AD2208E0ECC3546 # 346
+ .quad 0x00BCDD535DB28B49, 0x79BAA6BB6398B6F7 # 347
+ .quad 0x00BC52640BC68A89, 0x78A4C8178A4C8179 # 348
+ .quad 0x00BBC8408CD789C9, 0x77908119AC60D342 # 349
+ .quad 0x00BB3EE721A68909, 0x767DCE434A9B1018 # 350
+ .quad 0x00BAB656100C8849, 0x756CAC201756CAC3 # 351
+ .quad 0x00BA2E8BA2E98789, 0x745D1745D1745D18 # 352
+ .quad 0x00B9A7862A1086C9, 0x734F0C541FE8CB10 # 353
+ .quad 0x00B92143FA378609, 0x724287F46DEBC05D # 354
+ .quad 0x00B89BC36CE48549, 0x713786D9C7C08A75 # 355
+ .quad 0x00B81702E05D8489, 0x702E05C0B81702E1 # 356
+ .quad 0x00B79300B79483C9, 0x6F26016F26016F27 # 357
+ .quad 0x00B70FBB5A1A8309, 0x6E1F76B4337C6CB2 # 358
+ .quad 0x00B68D31340F8249, 0x6D1A62681C860FB1 # 359
+ .quad 0x00B60B60B60C8189, 0x6C16C16C16C16C17 # 360
+ .quad 0x00B58A48551980C9, 0x6B1490AA31A3CFC8 # 361
+ .quad 0x00B509E68A9C8009, 0x6A13CD153729043F # 362
+ .quad 0x00B48A39D4477F49, 0x691473A88D0BFD2E # 363
+ .quad 0x00B40B40B40C7E89, 0x6816816816816817 # 364
+ .quad 0x00B38CF9B00C7E09, 0x6719F36016719F37 # 365
+ .quad 0x00B30F63528A7D49, 0x661EC6A5122F9017 # 366
+ .quad 0x00B2927C29DB7C89, 0x6524F853B4AA339F # 367
+ .quad 0x00B21642C85A7C09, 0x642C8590B21642C9 # 368
+ .quad 0x00B19AB5C4577B49, 0x63356B88AC0DE017 # 369
+ .quad 0x00B11FD3B80C7A89, 0x623FA7701623FA78 # 370
+ .quad 0x00B0A59B418E7A09, 0x614B36831AE93AA7 # 371
+ .quad 0x00B02C0B02C17949, 0x6058160581605817 # 372
+ .quad 0x00AFB321A14A7889, 0x5F66434292DFBE1D # 373
+ .quad 0x00AF3ADDC6817809, 0x5E75BB8D015E75BC # 374
+ .quad 0x00AEC33E1F687749, 0x5D867C3ECE2A534A # 375
+ .quad 0x00AE4C415C9976C9, 0x5C9882B931057263 # 376
+ .quad 0x00ADD5E632407609, 0x5BABCC647FA9150D # 377
+ .quad 0x00AD602B580B7589, 0x5AC056B015AC056C # 378
+ .quad 0x00ACEB0F891F74C9, 0x59D61F123CCAA377 # 379
+ .quad 0x00AC7691840B7449, 0x58ED2308158ED231 # 380
+ .quad 0x00AC02B00AC17389, 0x5805601580560159 # 381
+ .quad 0x00AB8F69E2847309, 0x571ED3C506B39A23 # 382
+ .quad 0x00AB1CBDD3E37249, 0x56397BA7C52E1EC0 # 383
+ .quad 0x00AAAAAAAAAB71C9, 0x5555555555555556 # 384
+ .quad 0x00AA392F35DD7149, 0x54725E6BB82FE016 # 385
+ .quad 0x00A9C84A47A17089, 0x5390948F40FEAC70 # 386
+ .quad 0x00A957FAB5417009, 0x52AFF56A8054ABFE # 387
+ .quad 0x00A8E83F57186F89, 0x51D07EAE2F8151D1 # 388
+ .quad 0x00A87917088F6EC9, 0x50F22E111C4C56DF # 389
+ .quad 0x00A80A80A80B6E49, 0x5015015015015016 # 390
+ .quad 0x00A79C7B16EB6DC9, 0x4F38F62DD4C9A845 # 391
+ .quad 0x00A72F0539796D49, 0x4E5E0A72F0539783 # 392
+ .quad 0x00A6C21DF6E26CC9, 0x4D843BEDC2C4B900 # 393
+ .quad 0x00A655C4392E6C09, 0x4CAB88725AF6E750 # 394
+ .quad 0x00A5E9F6ED356B89, 0x4BD3EDDA68FE0E43 # 395
+ .quad 0x00A57EB502966B09, 0x4AFD6A052BF5A815 # 396
+ .quad 0x00A513FD6BB16A89, 0x4A27FAD76014A280 # 397
+ .quad 0x00A4A9CF1D976A09, 0x49539E3B2D066EA3 # 398
+ .quad 0x00A44029100B6989, 0x4880522014880523 # 399
+ .quad 0x00A3D70A3D7168C9, 0x47AE147AE147AE15 # 400
+ .quad 0x00A36E71A2CC6849, 0x46DCE34596066251 # 401
+ .quad 0x00A3065E3FAF67C9, 0x460CBC7F5CF9A1C1 # 402
+ .quad 0x00A29ECF163C6749, 0x453D9E2C776CA015 # 403
+ .quad 0x00A237C32B1766C9, 0x446F86562D9FAEE5 # 404
+ .quad 0x00A1D13985606649, 0x43A2730ABEE4D1DC # 405
+ .quad 0x00A16B312EA965C9, 0x42D6625D51F86EFA # 406
+ .quad 0x00A105A932F36549, 0x420B5265E595123E # 407
+ .quad 0x00A0A0A0A0A164C9, 0x4141414141414142 # 408
+ .quad 0x00A03C1688746449, 0x40782D10E6566065 # 409
+ .quad 0x009FD809FD8163C9, 0x3FB013FB013FB014 # 410
+ .quad 0x009F747A152E6349, 0x3EE8F42A5AF06DA1 # 411
+ .quad 0x009F1165E72662C9, 0x3E22CBCE4A9027C5 # 412
+ .quad 0x009EAECC8D546249, 0x3D5D991AA75C5BBE # 413
+ .quad 0x009E4CAD23DE6209, 0x3C995A47BABE7441 # 414
+ .quad 0x009DEB06C91A6189, 0x3BD60D923295482D # 415
+ .quad 0x009D89D89D8A6109, 0x3B13B13B13B13B14 # 416
+ .quad 0x009D2921C3D76089, 0x3A524387AC822610 # 417
+ .quad 0x009CC8E160C46009, 0x3991C2C187F63372 # 418
+ .quad 0x009C69169B315F89, 0x38D22D366088DBF4 # 419
+ .quad 0x009C09C09C0A5F09, 0x3813813813813814 # 420
+ .quad 0x009BAADE8E4B5EC9, 0x3755BD1C945EDC20 # 421
+ .quad 0x009B4C6F9EF15E49, 0x3698DF3DE0747954 # 422
+ .quad 0x009AEE72FCFA5DC9, 0x35DCE5F9F2AF821F # 423
+ .quad 0x009A90E7D95C5D49, 0x3521CFB2B78C1353 # 424
+ .quad 0x009A33CD67015D09, 0x34679ACE0134679B # 425
+ .quad 0x0099D722DABE5C89, 0x33AE45B57BCB1E0D # 426
+ .quad 0x00997AE76B515C09, 0x32F5CED6A1DFA014 # 427
+ .quad 0x00991F1A51595B89, 0x323E34A2B10BF66F # 428
+ .quad 0x0098C3BAC7505B49, 0x3187758E9EBB6014 # 429
+ .quad 0x009868C809875AC9, 0x30D190130D190131 # 430
+ .quad 0x00980E4156215A49, 0x301C82AC40260391 # 431
+ .quad 0x0097B425ED0A5A09, 0x2F684BDA12F684BE # 432
+ .quad 0x00975A750FF75989, 0x2EB4EA1FED14B15F # 433
+ .quad 0x0097012E025D5909, 0x2E025C04B8097013 # 434
+ .quad 0x0096A850096B58C9, 0x2D50A012D50A012E # 435
+ .quad 0x00964FDA6C0A5849, 0x2C9FB4D812C9FB4E # 436
+ .quad 0x0095F7CC72D257C9, 0x2BEF98E5A3710FD2 # 437
+ .quad 0x0095A025680A5789, 0x2B404AD012B404AE # 438
+ .quad 0x009548E4979F5709, 0x2A91C92F3C1053FA # 439
+ .quad 0x0094F2094F2156C9, 0x29E4129E4129E413 # 440
+ .quad 0x00949B92DDC15649, 0x293725BB804A4DCA # 441
+ .quad 0x0094458094465609, 0x288B01288B01288C # 442
+ .quad 0x0093EFD1C50F5589, 0x27DFA38A1CE4D6F9 # 443
+ .quad 0x00939A85C40A5509, 0x27350B88127350B9 # 444
+ .quad 0x0093459BE6B154C9, 0x268B37CD601268B4 # 445
+ .quad 0x0092F11384055449, 0x25E22708092F1139 # 446
+ .quad 0x00929CEBF48C5409, 0x2539D7E9177B21CB # 447
+ .quad 0x00924924924A5389, 0x2492492492492493 # 448
+ .quad 0x0091F5BCB8BC5349, 0x23EB79717605B39A # 449
+ .quad 0x0091A2B3C4D652C9, 0x23456789ABCDF013 # 450
+ .quad 0x0091500915015289, 0x22A0122A0122A013 # 451
+ .quad 0x0090FDBC09105209, 0x21FB78121FB78122 # 452
+ .quad 0x0090ABCC024351C9, 0x21579804855E6013 # 453
+ .quad 0x00905A38633F5189, 0x20B470C67C0D8876 # 454
+ .quad 0x00900900900A5109, 0x2012012012012013 # 455
+ .quad 0x008FB823EE0950C9, 0x1F7047DC11F7047E # 456
+ .quad 0x008F67A1E3FE5049, 0x1ECF43C7FB84C2F1 # 457
+ .quad 0x008F1779D9FE5009, 0x1E2EF3B3FB874432 # 458
+ .quad 0x008EC7AB39734FC9, 0x1D8F5672E4ABC83B # 459
+ .quad 0x008E78356D154F49, 0x1CF06ADA2811CF07 # 460
+ .quad 0x008E2917E0E84F09, 0x1C522FC1CE058D9B # 461
+ .quad 0x008DDA5202384E89, 0x1BB4A4046ED29012 # 462
+ .quad 0x008D8BE33F964E49, 0x1B17C67F2BAE2B21 # 463
+ .quad 0x008D3DCB08D44E09, 0x1A7B9611A7B9611B # 464
+ .quad 0x008CF008CF014D89, 0x19E0119E0119E012 # 465
+ .quad 0x008CA29C04664D49, 0x19453808CA29C047 # 466
+ .quad 0x008C55841C824D09, 0x18AB083902BDAB95 # 467
+ .quad 0x008C08C08C094C89, 0x1811811811811812 # 468
+ .quad 0x008BBC50C8DF4C49, 0x1778A191BD684181 # 469
+ .quad 0x008B70344A144C09, 0x16E0689427378EB5 # 470
+ .quad 0x008B246A87E24BC9, 0x1648D50FC3201165 # 471
+ .quad 0x008AD8F2FBAA4B49, 0x15B1E5F75270D046 # 472
+ .quad 0x008A8DCD1FEF4B09, 0x151B9A3FDD5C8CB9 # 473
+ .quad 0x008A42F870574AC9, 0x1485F0E0ACD3B68D # 474
+ .quad 0x0089F87469A34A49, 0x13F0E8D3447241C1 # 475
+ .quad 0x0089AE4089AF4A09, 0x135C81135C81135D # 476
+ .quad 0x0089645C4F6F49C9, 0x12C8B89EDC0ABBD8 # 477
+ .quad 0x00891AC73AEA4989, 0x12358E75D30336A1 # 478
+ .quad 0x0088D180CD3B4909, 0x11A3019A748267AF # 479
+ .quad 0x00888888888948C9, 0x1111111111111112 # 480
+ .quad 0x00883FDDF0094889, 0x107FBBE01107FBBF # 481
+ .quad 0x0087F78087F84849, 0x0FEF010FEF010FF0 # 482
+ .quad 0x0087AF6FD59A4809, 0x0F5EDFAB325A1A81 # 483
+ .quad 0x008767AB5F354789, 0x0ECF56BE69C8FDE3 # 484
+ .quad 0x00872032AC144749, 0x0E40655826010E41 # 485
+ .quad 0x0086D905447B4709, 0x0DB20A88F469598D # 486
+ .quad 0x00869222B1AD46C9, 0x0D24456359E39D2D # 487
+ .quad 0x00864B8A7DE74689, 0x0C9714FBCDA3AC11 # 488
+ .quad 0x0086053C345B4649, 0x0C0A7868B41708E7 # 489
+ .quad 0x0085BF37612D4609, 0x0B7E6EC259DC7936 # 490
+ .quad 0x0085797B91784589, 0x0AF2F722EECB5713 # 491
+ .quad 0x0085340853414549, 0x0A6810A6810A6811 # 492
+ .quad 0x0084EEDD357D4509, 0x09DDBA6AF836010A # 493
+ .quad 0x0084A9F9C80944C9, 0x0953F39010953F3A # 494
+ .quad 0x0084655D9BAC4489, 0x08CABB37565E2011 # 495
+ .quad 0x0084210842114449, 0x0842108421084211 # 496
+ .quad 0x0083DCF94DC84409, 0x07B9F29B8EAE19C2 # 497
+ .quad 0x00839930524043C9, 0x073260A47F7C66D0 # 498
+ .quad 0x008355ACE3C94389, 0x06AB59C7912FB620 # 499
+ .quad 0x0083126E978E4309, 0x0624DD2F1A9FBE77 # 500
+ .quad 0x0082CF75039442C9, 0x059EEA0727586633 # 501
+ .quad 0x00828CBFBEBA4289, 0x05197F7D73404147 # 502
+ .quad 0x00824A4E60B44249, 0x04949CC1664C578A # 503
+ .quad 0x0082082082094209, 0x0410410410410411 # 504
+ .quad 0x0081C635BC1341C9, 0x038C6B78247FBF1D # 505
+ .quad 0x0081848DA8FB4189, 0x03091B51F5E1A4EF # 506
+ .quad 0x00814327E3BA4149, 0x02864FC7729E8C5F # 507
+ .quad 0x0081020408114109, 0x0204081020408103 # 508
+ .quad 0x0080C121B28C40C9, 0x0182436517A37530 # 509
+ .quad 0x0080808080814089, 0x0101010101010102 # 510
+ .quad 0x0080402010094049, 0x0080402010080403 # 511
+ .quad 0x8000000000004009, 0x0000000000000000 # 512
+
diff --git a/private/crt32/misc/alpha/divide.s b/private/crt32/misc/alpha/divide.s
new file mode 100644
index 000000000..cff0254e7
--- /dev/null
+++ b/private/crt32/misc/alpha/divide.s
@@ -0,0 +1,1319 @@
+// TITLE("Slow Integer Division and Remainder")
+//++
+//
+// Copyright (c) 1992 Digital Equipment Corporation
+//
+// Module Name:
+//
+// divide.s
+//
+// Abstract:
+//
+// This module implements integer division and remainder routines that are
+// called by assembler pseudo-ops.
+//
+// Author:
+//
+// Ken Lesniak (lesniak) 15-Jun-1990
+// Thomas Van Baak (tvb) 13-Jun-1992
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksalpha.h"
+
+//
+// Implementation Notes:
+//
+// There are no Alpha machine instructions for performing integer division
+// (divl, divlu, divq, divqu) or remainder (reml, remlu, remq, remqu). The
+// machine instructions generated for these assembler pseudo instructions
+// are dependent on the operands.
+//
+// Division and remainder by constant values are replaced with a sequence
+// of instructions that depend on the data type and the value of the
+// constant. Shifting or reciprocal multiplication are used in most cases
+// to generate the result.
+//
+// Division and remainder by non-constant values are replaced with a
+// procedure call to a library routine to perform the operation. This file
+// contains those routines.
+//
+// This code is adapted from the Alpha/OSF versions by Ken Lesniak and are
+// based on a simple shift/subtract algorithm. Higher performance versions
+// are available and so these functions are now obsolete.
+//
+// Longword register arguments are explicitly converted to canonical form
+// because these functions, with their non-standard calling sequence, act
+// more like instructions than procedure calls. Longword instructions do
+// not require canonical longword operands, but standard procedures with
+// longword register arguments, may assume the caller has passed canonical
+// longwords.
+//
+
+//
+// Define common stack frame for all the functions in this file.
+//
+
+ .struct 0
+
+DiS0: .space 8 // save register s0
+DiS1: .space 8 // save register s1
+
+DiS2: .space 8 // save register s2
+DiS3: .space 8 // save register s3
+
+DiTy: .space 8 // save register t11
+DiTr: .space 8 // save register t9
+
+DiRa: .space 8 // save register ra
+ .space 8 // ensure 16-byte stack alignment
+
+DiFrameLength: // length of stack frame
+
+//
+// Define non-standard calling standard arguments.
+//
+// These have been changed more than once so until they are permanent,
+// symbolic names will be used instead of conventional register names.
+//
+
+#define Tr t9 // return address
+#define Tx t10 // dividend and result
+#define Ty t11 // divisor
+
+ SBTTL("Signed Long Integer Division")
+//++
+//
+// LONG
+// __divl (
+// IN LONG Dividend,
+// IN LONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides a signed 32-bit integer by a signed 32-bit integer
+// and returns the signed 32-bit integer result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 32-bit integer result (quotient) is returned in register t10.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__divl, DiFrameLength, Tr)
+
+ lda sp, -DiFrameLength(sp) // allocate stack frame
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ stq ra, DiRa(sp) // save ra register
+ stq ra, DiTr(sp) // backtrace return address
+ stq Tr, DiTr(sp) // save actual return address
+
+ stq Ty, DiTy(sp) // save original divisor
+ stq s2, DiS2(sp) // save non volatile registers
+ stq s1, DiS1(sp) //
+ stq s0, DiS0(sp) //
+
+ PROLOGUE_END
+
+//
+// Check for division by zero.
+//
+
+ beq Ty, 20f // die if divisor is zero
+
+ addl Tx, 0, Tx // make sure dividend is in canonical form
+ addl Ty, 0, Ty // make sure divisor is in canonical form
+
+//
+// Check for division of the most negative integer (INT_MIN) by the least
+// negative (-1). The result would be an integer which is one greater than the
+// maximum positive integer. Since this cannot be represented, an overflow must
+// be generated.
+//
+
+ addl Ty, 1, s0 // 0 if Ty == -1; != 0 otherwise
+ mov Tx, s1 // copy dividend
+ cmovne s0, 0, s1 // replace w/ 0 if divisor != -1
+ sublv zero, s1, s1 // trap if dividend = INT_MIN
+
+//
+// Save sign of quotient for later. Convert negative arguments to positive for
+// the division algorithm.
+//
+
+ xor Tx, Ty, s2 // compute sign of quotient
+ cmplt Tx, 0, s0 // sign of dividend is sign of remainder
+ bic s2, 1, s2 // use low bit for remainder sign
+ bis s0, s2, s2 // merge in with quotient sign
+
+ subl zero, Tx, s0 // negate dividend
+ cmovlt Tx, s0, Tx // get absolute value of dividend
+ subl zero, Ty, s0 // negate divisor
+ cmovlt Ty, s0, Ty // get absolute value of divisor
+
+//
+// Perform the shift/subtract loop 8 times and 4 bits per loop.
+//
+
+ ldiq s0, 32/4 // loop iterations
+
+ sll Ty, 32, Ty // move divisor up to high 32 bits
+ zap Tx, 0xf0, Tx // zero-extend dividend to 64 bits
+
+10: addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ subq s0, 1, s0 // any more iterations?
+ bne s0, 10b //
+
+//
+// Restore sign of quotient and return value in Tx.
+//
+
+ addl Tx, 0, Tx // get quotient into canonical form
+
+ subl zero, Tx, s0 // negate quotient into a temp
+ cmovlt s2, s0, Tx // if quotient should be negative copy temp
+
+ ldq s0, DiS0(sp) // restore saved registers
+ ldq s1, DiS1(sp) //
+ ldq s2, DiS2(sp) //
+ ldq Ty, DiTy(sp) // restore original divisor
+
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+//
+// Generate an exception for divide by zero. Return a zero quotient if the
+// caller continues execution.
+//
+
+20: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
+
+ GENERATE_TRAP
+
+ ldil Tx, 0 // return zero quotient
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+ .end __divl
+
+ SBTTL("Unsigned Long Integer Division")
+//++
+//
+// ULONG
+// __divlu (
+// IN ULONG Dividend,
+// IN ULONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides an unsigned 32-bit integer by an unsigned 32-bit
+// integer and returns the unsigned 32-bit integer result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 32-bit integer result (quotient) is returned in register t10.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__divlu, DiFrameLength, Tr)
+
+ lda sp, -DiFrameLength(sp) // allocate stack frame
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ stq ra, DiRa(sp) // save ra register
+ stq ra, DiTr(sp) // backtrace return address
+ stq Tr, DiTr(sp) // save actual return address
+
+ stq Ty, DiTy(sp) // save original divisor
+ stq s1, DiS1(sp) // save non volatile registers
+ stq s0, DiS0(sp) //
+
+ PROLOGUE_END
+
+//
+// Check for division by zero.
+//
+
+ beq Ty, 20f // die if divisor is zero
+
+//
+// Perform the shift/subtract loop 8 times and 4 bits per loop.
+//
+
+ ldiq s0, 32/4 // set iteration count
+
+ sll Ty, 32, Ty // move divisor up to high 32 bits
+ zap Tx, 0xf0, Tx // zero-extend dividend to 64 bits
+
+10: addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ subq s0, 1, s0 // any more iterations?
+ bne s0, 10b //
+
+//
+// Finished with return value in Tx.
+//
+
+ addl Tx, 0, Tx // get quotient into canonical form
+
+ ldq s0, DiS0(sp) // restore saved registers
+ ldq s1, DiS1(sp) //
+ ldq Ty, DiTy(sp) // restore original divisor
+
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+//
+// Generate an exception for divide by zero. Return a zero quotient if the
+// caller continues execution.
+//
+
+20: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
+
+ GENERATE_TRAP
+
+ ldil Tx, 0 // return zero quotient
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+ .end __divlu
+
+ SBTTL("Signed Quad Integer Division")
+//++
+//
+// QUAD
+// __divq (
+// IN QUAD Dividend,
+// IN QUAD Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides a signed 64-bit integer by a signed 64-bit integer
+// and returns the signed 64-bit integer result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 64-bit integer result (quotient) is returned in register t10.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__divq, DiFrameLength, Tr)
+
+ lda sp, -DiFrameLength(sp) // allocate stack frame
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ stq ra, DiRa(sp) // save ra register
+ stq ra, DiTr(sp) // backtrace return address
+ stq Tr, DiTr(sp) // save actual return address
+
+ stq Ty, DiTy(sp) // save original divisor
+ stq s3, DiS3(sp) // save non volatile registers
+ stq s2, DiS2(sp) //
+ stq s1, DiS1(sp) //
+ stq s0, DiS0(sp) //
+
+ PROLOGUE_END
+
+//
+// Check for division by zero.
+//
+
+ beq Ty, 20f // die if divisor is zero
+
+//
+// Check for division of the most negative integer (QUAD_MIN) by the least
+// negative (-1). The result would be an integer which is one greater than the
+// maximum positive integer. Since this cannot be represented, an overflow must
+// be generated.
+//
+
+ addq Ty, 1, s0 // 0 if Ty == -1; != 0 otherwise
+ mov Tx, s1 // copy dividend
+ cmovne s0, 0, s1 // replace w/ 0 if divisor != -1
+ subqv zero, s1, s1 // trap if dividend = LONG_MIN
+
+//
+// Save sign of quotient for later. Convert negative arguments to positive for
+// the division algorithm.
+//
+
+ xor Tx, Ty, s2 // compute sign of quotient
+ cmplt Tx, 0, s0 // sign of dividend is sign of remainder
+ bic s2, 1, s2 // use low bit for remainder sign
+ bis s0, s2, s2 // merge in with quotient sign
+
+ subq zero, Tx, s0 // negate dividend
+ cmovlt Tx, s0, Tx // get absolute value of dividend
+ subq zero, Ty, s0 // negate divisor
+ cmovlt Ty, s0, Ty // get absolute value of divisor
+
+//
+// Perform the shift/subtract loop 16 times and 4 bits per loop.
+//
+
+ ldiq s1, 0 // zero-extend dividend to 128 bits
+
+ ldiq s3, 64/4 // loop iterations
+
+10: cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ subq s3, 1, s3 // any more iterations?
+ bne s3, 10b //
+
+//
+// Restore sign of quotient and return value in Tx.
+//
+
+ subq zero, Tx, s0 // negate quotient into a temp
+ cmovlt s2, s0, Tx // if quotient should be negative copy temp
+
+ ldq s0, DiS0(sp) // restore saved registers
+ ldq s1, DiS1(sp) //
+ ldq s2, DiS2(sp) //
+ ldq s3, DiS3(sp) //
+ ldq Ty, DiTy(sp) // restore original divisor
+
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+//
+// Generate an exception for divide by zero. Return a zero quotient if the
+// caller continues execution.
+//
+
+20: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
+
+ GENERATE_TRAP
+
+ ldil Tx, 0 // return zero quotient
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+ .end __divq
+
+ SBTTL("Unsigned Quad Integer Division")
+//++
+//
+// UQUAD
+// __divqu (
+// IN UQUAD Dividend,
+// IN UQUAD Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides an unsigned 64-bit integer by an unsigned 64-bit
+// integer and returns the unsigned 64-bit integer result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 64-bit integer result (quotient) is returned in register t10.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__divqu, DiFrameLength, Tr)
+
+ lda sp, -DiFrameLength(sp) // allocate stack frame
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ stq ra, DiRa(sp) // save ra register
+ stq ra, DiTr(sp) // backtrace return address
+ stq Tr, DiTr(sp) // save actual return address
+
+ stq s2, DiS2(sp) // save non volatile registers
+ stq s1, DiS1(sp) //
+ stq s0, DiS0(sp) //
+
+ PROLOGUE_END
+
+//
+// Check for division by zero.
+//
+
+ beq Ty, 20f // die if divisor is zero
+
+//
+// Perform the shift/subtract loop 16 times and 4 bits per loop.
+//
+
+ ldiq s2, 64/4 // set iteration count
+
+ ldiq s1, 0 // zero-extend dividend to 128 bits
+
+10: cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ subq s2, 1, s2 // any more iterations?
+ bne s2, 10b //
+
+//
+// Finished with return value in Tx.
+//
+
+ ldq s0, DiS0(sp) // restore saved registers
+ ldq s1, DiS1(sp) //
+ ldq s2, DiS2(sp) //
+
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+//
+// Generate an exception for divide by zero. Return a zero quotient if the
+// caller continues execution.
+//
+
+20: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
+
+ GENERATE_TRAP
+
+ ldil Tx, 0 // return zero quotient
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+ .end __divqu
+
+ SBTTL("Signed Long Integer Remainder")
+//++
+//
+// LONG
+// __reml (
+// IN LONG Dividend,
+// IN LONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides a signed 32-bit integer by a signed 32-bit integer
+// and returns the signed 32-bit integer remainder result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 32-bit integer result (remainder) is returned in register t10.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__reml, DiFrameLength, Tr)
+
+ lda sp, -DiFrameLength(sp) // allocate stack frame
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ stq ra, DiRa(sp) // save ra register
+ stq ra, DiTr(sp) // backtrace return address
+ stq Tr, DiTr(sp) // save actual return address
+
+ stq Ty, DiTy(sp) // save original divisor
+ stq s2, DiS2(sp) // save non volatile registers
+ stq s1, DiS1(sp) //
+ stq s0, DiS0(sp) //
+
+ PROLOGUE_END
+
+//
+// Check for division by zero.
+//
+
+ beq Ty, 20f // die if divisor is zero
+
+ addl Tx, 0, Tx // make sure dividend is in canonical form
+ addl Ty, 0, Ty // make sure divisor is in canonical form
+
+//
+// Check for division of the most negative integer (INT_MIN) by the least
+// negative (-1). The result would be an integer which is one greater than the
+// maximum positive integer. Since this cannot be represented, an overflow must
+// be generated.
+//
+
+ addl Ty, 1, s0 // 0 if Ty == -1; != 0 otherwise
+ mov Tx, s1 // copy dividend
+ cmovne s0, 0, s1 // replace w/ 0 if divisor != -1
+ sublv zero, s1, s1 // trap if dividend = INT_MIN
+
+//
+// Save sign of quotient for later. Convert negative arguments to positive for
+// the division algorithm.
+//
+
+ xor Tx, Ty, s2 // compute sign of quotient
+ cmplt Tx, 0, s0 // sign of dividend is sign of remainder
+ bic s2, 1, s2 // use low bit for remainder sign
+ bis s0, s2, s2 // merge in with quotient sign
+
+ subl zero, Tx, s0 // negate dividend
+ cmovlt Tx, s0, Tx // get absolute value of dividend
+ subl zero, Ty, s0 // negate divisor
+ cmovlt Ty, s0, Ty // get absolute value of divisor
+
+//
+// Perform the shift/subtract loop 8 times and 4 bits per loop.
+//
+
+ ldiq s0, 32/4 // loop iterations
+
+ sll Ty, 32, Ty // move divisor up to high 32 bits
+ zap Tx, 0xf0, Tx // zero-extend dividend to 64 bits
+
+10: addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ subq s0, 1, s0 // any more iterations?
+ bne s0, 10b //
+
+//
+// Restore sign of remainder and return value in Tx.
+//
+
+ sra Tx, 32, Tx // extract remainder in canonical form
+ subl zero, Tx, s0 // negate remainder into a temp
+ cmovlbs s2, s0, Tx // if remainder should be negative copy temp
+
+ ldq s0, DiS0(sp) // restore saved registers
+ ldq s1, DiS1(sp) //
+ ldq s2, DiS2(sp) //
+ ldq Ty, DiTy(sp) // restore original divisor
+
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+//
+// Generate an exception for divide by zero. Return a zero quotient if the
+// caller continues execution.
+//
+
+20: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
+
+ GENERATE_TRAP
+
+ ldil Tx, 0 // return zero quotient
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+ .end __reml
+
+ SBTTL("Unsigned Long Integer Remainder")
+//++
+//
+// ULONG
+// __remlu (
+// IN ULONG Dividend,
+// IN ULONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides an unsigned 32-bit integer by an unsigned 32-bit
+// integer and returns the unsigned 32-bit integer remainder result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 32-bit integer result (remainder) is returned in register t10.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__remlu, DiFrameLength, Tr)
+
+ lda sp, -DiFrameLength(sp) // allocate stack frame
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ stq ra, DiRa(sp) // save ra register
+ stq ra, DiTr(sp) // backtrace return address
+ stq Tr, DiTr(sp) // save actual return address
+
+ stq Ty, DiTy(sp) // save original divisor
+ stq s1, DiS1(sp) // save non volatile registers
+ stq s0, DiS0(sp) //
+
+ PROLOGUE_END
+
+//
+// Check for division by zero.
+//
+
+ beq Ty, 20f // die if divisor is zero
+
+//
+// Perform the shift/subtract loop 8 times and 4 bits per loop.
+//
+
+ ldiq s0, 32/4 // set iteration count
+
+ sll Ty, 32, Ty // move divisor up to high 32 bits
+ zap Tx, 0xf0, Tx // zero-extend dividend to 64 bits
+
+10: addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ addq Tx, Tx, Tx // shift dividend left a bit
+
+ cmpule Ty, Tx, s1 // is dividend >= divisor?
+ addq Tx, s1, Tx // set quotient bit if dividend >= divisor
+ subq Tx, Ty, s1 // subtract divisor from dividend...
+ cmovlbs Tx, s1, Tx // ...if dividend >= divisor
+
+ subq s0, 1, s0 // any more iterations?
+ bne s0, 10b //
+
+//
+// Finished with return value in Tx.
+//
+
+ sra Tx, 32, Tx // extract remainder in canonical form
+
+ ldq s0, DiS0(sp) // restore saved registers
+ ldq s1, DiS1(sp) //
+ ldq Ty, DiTy(sp) // restore original divisor
+
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+//
+// Generate an exception for divide by zero. Return a zero quotient if the
+// caller continues execution.
+//
+
+20: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
+
+ GENERATE_TRAP
+
+ ldil Tx, 0 // return zero quotient
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+ .end __remlu
+
+ SBTTL("Signed Quad Integer Remainder")
+//++
+//
+// QUAD
+// __remq (
+// IN QUAD Dividend,
+// IN QUAD Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides a signed 64-bit integer by a signed 64-bit integer
+// and returns the signed 64-bit integer remainder result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 64-bit integer result (remainder) is returned in register t10.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__remq, DiFrameLength, Tr)
+
+ lda sp, -DiFrameLength(sp) // allocate stack frame
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ stq ra, DiRa(sp) // save ra register
+ stq ra, DiTr(sp) // backtrace return address
+ stq Tr, DiTr(sp) // save actual return address
+
+ stq Ty, DiTy(sp) // save original divisor
+ stq s3, DiS3(sp) // save non volatile registers
+ stq s2, DiS2(sp) //
+ stq s1, DiS1(sp) //
+ stq s0, DiS0(sp) //
+
+ PROLOGUE_END
+
+//
+// Check for division by zero.
+//
+
+ beq Ty, 20f // die if divisor is zero
+
+//
+// Check for division of the most negative integer (QUAD_MIN) by the least
+// negative (-1). The result would be an integer which is one greater than the
+// maximum positive integer. Since this cannot be represented, an overflow must
+// be generated.
+//
+
+ addq Ty, 1, s0 // 0 if Ty == -1; != 0 otherwise
+ mov Tx, s1 // copy dividend
+ cmovne s0, 0, s1 // replace w/ 0 if divisor != -1
+ subqv zero, s1, s1 // trap if dividend = LONG_MIN
+
+//
+// Save sign of quotient for later. Convert negative arguments to positive for
+// the division algorithm.
+//
+
+ xor Tx, Ty, s2 // compute sign of quotient
+ cmplt Tx, 0, s0 // sign of dividend is sign of remainder
+ bic s2, 1, s2 // use low bit for remainder sign
+ bis s0, s2, s2 // merge in with quotient sign
+
+ subq zero, Tx, s0 // negate dividend
+ cmovlt Tx, s0, Tx // get absolute value of dividend
+ subq zero, Ty, s0 // negate divisor
+ cmovlt Ty, s0, Ty // get absolute value of divisor
+
+//
+// Perform the shift/subtract loop 16 times and 4 bits per loop.
+//
+
+ ldiq s1, 0 // zero-extend dividend to 128 bits
+
+ ldiq s3, 64/4 // loop iterations
+
+10: cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ subq s3, 1, s3 // any more iterations?
+ bne s3, 10b //
+
+//
+// Restore sign of remainder and return value in Tx.
+//
+
+ subq zero, s1, Tx // copy negated remainder to return register
+ cmovlbc s2, s1, Tx // if positive remainder then overwrite
+
+ ldq s0, DiS0(sp) // restore saved registers
+ ldq s1, DiS1(sp) //
+ ldq s2, DiS2(sp) //
+ ldq s3, DiS3(sp) //
+ ldq Ty, DiTy(sp) // restore original divisor
+
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+//
+// Generate an exception for divide by zero. Return a zero quotient if the
+// caller continues execution.
+//
+
+20: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
+
+ GENERATE_TRAP
+
+ ldil Tx, 0 // return zero quotient
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+ .end __remq
+
+ SBTTL("Unsigned Quad Integer Remainder")
+//++
+//
+// UQUAD
+// __remqu (
+// IN UQUAD Dividend,
+// IN UQUAD Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides an unsigned 64-bit integer by an unsigned 64-bit
+// integer and returns the unsigned 64-bit integer remainder result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 64-bit integer result (remainder) is returned in register t10.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__remqu, DiFrameLength, Tr)
+
+ lda sp, -DiFrameLength(sp) // allocate stack frame
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ stq ra, DiRa(sp) // save ra register
+ stq ra, DiTr(sp) // backtrace return address
+ stq Tr, DiTr(sp) // save actual return address
+
+ stq s2, DiS2(sp) // save non volatile registers
+ stq s1, DiS1(sp) //
+ stq s0, DiS0(sp) //
+
+ PROLOGUE_END
+
+//
+// Check for division by zero.
+//
+
+ beq Ty, 20f // die if divisor is zero
+
+//
+// Perform the shift/subtract loop 16 times and 4 bits per loop.
+//
+
+ ldiq s2, 64/4 // set iteration count
+
+ ldiq s1, 0 // zero-extend dividend to 128 bits
+
+10: cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ cmplt Tx, 0, s0 // predict carry-out of low-dividend shift
+ addq Tx, Tx, Tx // shift low-dividend left
+ addq s1, s1, s1 // shift high-dividend left
+ bis s1, s0, s1 // merge in carry-out of low-dividend
+
+ cmpule Ty, s1, s0 // is dividend >= divisor?
+ addq Tx, s0, Tx // set quotient bit if dividend >= divisor
+ subq s1, Ty, s0 // subtract divisor from dividend...
+ cmovlbs Tx, s0, s1 // ...if dividend >= divisor
+
+ subq s2, 1, s2 // any more iterations?
+ bne s2, 10b //
+
+//
+// Finished with return value in Tx.
+//
+
+ mov s1, Tx // get remainder
+
+ ldq s0, DiS0(sp) // restore saved registers
+ ldq s1, DiS1(sp) //
+ ldq s2, DiS2(sp) //
+
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+//
+// Generate an exception for divide by zero. Return a zero quotient if the
+// caller continues execution.
+//
+
+20: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
+
+ GENERATE_TRAP
+
+ ldil Tx, 0 // return zero quotient
+ lda sp, DiFrameLength(sp) // deallocate stack frame
+ ret zero, (Tr) // return
+
+ .end __remqu
diff --git a/private/crt32/misc/alpha/divide2.s b/private/crt32/misc/alpha/divide2.s
new file mode 100644
index 000000000..2eb50c2ba
--- /dev/null
+++ b/private/crt32/misc/alpha/divide2.s
@@ -0,0 +1,1002 @@
+// TITLE("Fast Integer Division and Remainder")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// divide2.s
+//
+// Abstract:
+//
+// This module implements high-performance versions of the integer divide
+// and remainder routines that are called by assembler pseudo-ops.
+//
+// Author:
+//
+// Thomas Van Baak (tvb) 12-Jan-1993
+// Ken Lesniak (lesniak) 04-Nov-1992
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksalpha.h"
+
+//
+// Implementation Notes:
+//
+// There are no Alpha machine instructions for performing integer division
+// (divl, divlu, divq, divqu) or remainder (reml, remlu, remq, remqu). The
+// machine instructions generated for these assembler pseudo instructions
+// are dependent on the type of operands.
+//
+// Division and remainder by constant values are replaced with a sequence
+// of instructions that depend on the data type and the value of the
+// constant. Shifting or reciprocal multiplication are used in most cases
+// to generate the result. No run-time code is necessary in these cases.
+//
+// Division and remainder by non-constant values are replaced with a
+// procedure call to a library routine to perform the operation. This file
+// contains those routines.
+//
+// This code is adapted from the Alpha/OSF version by Ken Lesniak.
+//
+// There are two sets of these eight functions. The __div set were used
+// by an earlier version of the acc compiler. This is the new __2div set.
+// The new functions are about an order of magnitude faster.
+//
+// The new function names differ from the original set of functions so
+// that the old and new compilers can co-exist for a time.
+//
+// Both the division algorithm code and the large division tables used by
+// the code are contained in the fastdiv.s file which is included several
+// times from this file.
+//
+
+//
+// Define common stack frame for functions in this file.
+//
+
+ .struct 0
+DvRa: .space 8 // save register ra
+DvJr: .space 8 // save register t9
+
+DvNu: .space 8 // save register t10
+DvDi: .space 8 // save register t11
+
+DvT0: .space 8 // save register t0
+DvT1: .space 8 // save register t1
+
+DvT2: .space 8 // save register t2
+DvT3: .space 8 // save register t3
+
+DvT4: .space 8 // save register a0
+ .space 8 // ensure 16-byte stack alignment
+DvFrameLength: // length of stack frame
+
+//
+// Define non-standard calling convention required by the compiler.
+//
+// The compiler uses t9, t10, t11, t12 as indicated below. All other
+// registers (except AT) must be preserved by this calling convention.
+//
+// For the fastdiv code, since register a0 must be preserved anyway (it
+// is used by gentrap), define temp register T4 to be a0. Similarly,
+// register J4 must be preserved, so define temp register T5 to be Jr.
+// And the fastdiv code allows Qu to also be temp register T6.
+//
+
+#define Jr t9 // ($23) return address
+#define Nu t10 // ($24) dividend (numerator)
+#define Di t11 // ($25) divisor (denominator)
+#define Qu t12 // ($27) result (quotient)
+#define Re Qu // ($27) result (remainder)
+
+#define T0 t0 // standard temp
+#define T1 t1 // standard temp
+#define T2 t2 // standard temp
+#define T3 t3 // standard temp
+#define T4 a0 // may use a0 as temp
+#define T5 Jr // may use Jr as temp
+#define T6 Qu // may overload Qu as temp T6 only
+
+#ifdef DIV2_DEBUG
+
+//
+// In order to debug locally, re-define some of the registers so that
+// these functions can be called using a standard calling convention.
+//
+
+#undef Jr
+#define Jr ra // standard return address register
+#undef Nu
+#define Nu a0 // dividend argument in a0
+#undef Di
+#define Di a1 // divisor argument in a1
+#undef Qu
+#define Qu v0 // quotient result in v0
+#undef Re
+#define Re v0 // remainder result in v0
+#undef T4
+#define T4 t4 // normal temp
+
+#endif
+
+ SBTTL("Signed Long Integer Division")
+//++
+//
+// LONG
+// __2divl (
+// IN LONG Dividend,
+// IN LONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides a signed 32-bit integer by a signed 32-bit integer
+// and returns the signed 32-bit integer result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 32-bit integer result (quotient) is returned in register t12.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__2divl, DvFrameLength, Jr)
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ .set noreorder
+ .set noat
+ lda sp, -DvFrameLength(sp) // allocate stack frame
+
+ stq ra, DvRa(sp) // save ra register
+ stq ra, DvJr(sp) // backtrace return address
+ stq Jr, DvJr(sp) // save actual return address
+
+ stq Nu, DvNu(sp) // save original dividend
+ stq Di, DvDi(sp) // save original divisor
+ stq t0, DvT0(sp) // save temp registers
+ stq t1, DvT1(sp) //
+ stq t2, DvT2(sp) //
+ stq t3, DvT3(sp) //
+ stq T4, DvT4(sp) //
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+ addl Nu, 0, Nu // convert LONG dividend to quadword
+ addl Di, 0, Di // convert LONG divisor to quadword
+
+//
+// Check for division of the most negative integer (0x800...00) by the least
+// negative (-1). The result would be an integer which is one greater than the
+// maximum positive integer. Since this cannot be represented, an overflow must
+// be generated.
+//
+
+ addl Di, 1, t0 // 0 if Di == -1; != 0 otherwise
+ mov Nu, t1 // copy dividend
+ cmovne t0, 0, t1 // replace w/ 0 if divisor != -1
+ sublv zero, t1, t1 // trap if dividend == 0x800..00
+
+//
+// Convert negative arguments to positive for the division algorithm.
+//
+
+ subq zero, Nu, t0 // negate dividend
+ cmovlt Nu, t0, Nu // get absolute value of dividend
+ subq zero, Di, t0 // negate divisor
+ cmovlt Di, t0, Di // get absolute value of divisor
+
+//
+// Set up defines and include the main body of the division code.
+//
+
+#define FASTDIV_OPTIONS (THIRTY_TWO_BIT | SIGNED | DIVISION)
+
+#include "fastdiv.s"
+
+//
+// Restore some registers and set the correct sign of the quotient.
+//
+
+ ldq Jr, DvJr(sp) // restore return address
+ ldq Nu, DvNu(sp) // restore original dividend
+ ldq Di, DvDi(sp) // restore original divisor
+
+ addl Qu, 0, Qu // ensure quotient is in canonical form
+ subl zero, Qu, t1 // negate LONG quotient
+ xor Nu, Di, t0 // compute sign of quotient
+ addl t0, 0, t0 // ensure quotient is in canonical form
+ cmovlt t0, t1, Qu // use negated quotient if necessary
+
+//
+// Restore other saved registers and return with quotient in register Qu.
+//
+
+ ldq t0, DvT0(sp) // restore temp registers
+ ldq t1, DvT1(sp) //
+ ldq t2, DvT2(sp) //
+ ldq t3, DvT3(sp) //
+ ldq T4, DvT4(sp) //
+
+ lda sp, DvFrameLength(sp) // deallocate stack frame
+ ret zero, (Jr) // return
+
+ .end __2divl
+
+ SBTTL("Unsigned Long Integer Division")
+//++
+//
+// ULONG
+// __2divlu (
+// IN ULONG Dividend,
+// IN ULONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides an unsigned 32-bit integer by an unsigned 32-bit
+// integer and returns the unsigned 32-bit integer result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 32-bit integer result (quotient) is returned in register t12.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__2divlu, DvFrameLength, Jr)
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ .set noreorder
+ .set noat
+ lda sp, -DvFrameLength(sp) // allocate stack frame
+
+ stq ra, DvRa(sp) // save ra register
+ stq ra, DvJr(sp) // backtrace return address
+ stq Jr, DvJr(sp) // save actual return address
+
+ stq Nu, DvNu(sp) // save original dividend
+ stq Di, DvDi(sp) // save original divisor
+ stq t0, DvT0(sp) // save temp registers
+ stq t1, DvT1(sp) //
+ stq t2, DvT2(sp) //
+ stq t3, DvT3(sp) //
+ stq T4, DvT4(sp) //
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+ zap Nu, 0xf0, Nu // convert ULONG dividend to quadword
+ zap Di, 0xf0, Di // convert ULONG divisor to quadword
+
+//
+// Set up defines and include the main body of the division code.
+//
+
+#define FASTDIV_OPTIONS (THIRTY_TWO_BIT | UNSIGNED | DIVISION)
+
+#include "fastdiv.s"
+
+//
+// Restore all saved registers and return with quotient in register Qu.
+//
+
+ ldq Jr, DvJr(sp) // restore return address
+ ldq Nu, DvNu(sp) // restore original dividend
+ ldq Di, DvDi(sp) // restore original divisor
+
+ ldq t0, DvT0(sp) // restore temp registers
+ ldq t1, DvT1(sp) //
+ ldq t2, DvT2(sp) //
+ ldq t3, DvT3(sp) //
+ ldq T4, DvT4(sp) //
+
+ lda sp, DvFrameLength(sp) // deallocate stack frame
+ ret zero, (Jr) // return
+
+ .end __2divlu
+
+ SBTTL("Signed Quad Integer Division")
+//++
+//
+// LONGLONG
+// __2divq (
+// IN LONGLONG Dividend,
+// IN LONGLONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides a signed 64-bit integer by a signed 64-bit integer
+// and returns the signed 64-bit integer result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 64-bit integer result (quotient) is returned in register t12.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__2divq, DvFrameLength, Jr)
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ .set noreorder
+ .set noat
+ lda sp, -DvFrameLength(sp) // allocate stack frame
+
+ stq ra, DvRa(sp) // save ra register
+ stq ra, DvJr(sp) // backtrace return address
+ stq Jr, DvJr(sp) // save actual return address
+
+ stq Nu, DvNu(sp) // save original dividend
+ stq Di, DvDi(sp) // save original divisor
+ stq t0, DvT0(sp) // save temp registers
+ stq t1, DvT1(sp) //
+ stq t2, DvT2(sp) //
+ stq t3, DvT3(sp) //
+ stq T4, DvT4(sp) //
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+//
+// Check for division of the most negative integer (0x800..00) by the least
+// negative (-1). The result would be an integer which is one greater than the
+// maximum positive integer. Since this cannot be represented, an overflow must
+// be generated.
+//
+
+ addq Di, 1, t0 // 0 if Di == -1; != 0 otherwise
+ mov Nu, t1 // copy dividend
+ cmovne t0, 0, t1 // replace w/ 0 if divisor != -1
+ subqv zero, t1, t1 // trap if dividend == 0x800..00
+
+//
+// Convert negative arguments to positive for the division algorithm.
+//
+
+ subq zero, Nu, t0 // negate dividend
+ cmovlt Nu, t0, Nu // get absolute value of dividend
+ subq zero, Di, t0 // negate divisor
+ cmovlt Di, t0, Di // get absolute value of divisor
+
+//
+// Set up defines and include the main body of the division code.
+//
+
+#define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | SIGNED | DIVISION)
+
+#include "fastdiv.s"
+
+//
+// Restore some registers and set the correct sign of the quotient.
+//
+
+ ldq Jr, DvJr(sp) // restore return address
+ ldq Nu, DvNu(sp) // restore original dividend
+ ldq Di, DvDi(sp) // restore original divisor
+
+ subq zero, Qu, t1 // negate quadword quotient
+ xor Nu, Di, t0 // compute sign of quotient
+ cmovlt t0, t1, Qu // use negated quotient if necessary
+
+//
+// Restore other saved registers and return with quotient in register Qu.
+//
+
+ ldq t0, DvT0(sp) // restore temp registers
+ ldq t1, DvT1(sp) //
+ ldq t2, DvT2(sp) //
+ ldq t3, DvT3(sp) //
+ ldq T4, DvT4(sp) //
+
+ lda sp, DvFrameLength(sp) // deallocate stack frame
+ ret zero, (Jr) // return
+
+ .end __2divq
+
+ SBTTL("Unsigned Quad Integer Division")
+//++
+//
+// ULONGLONG
+// __2divqu (
+// IN ULONGLONG Dividend,
+// IN ULONGLONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides an unsigned 64-bit integer by an unsigned 64-bit
+// integer and returns the unsigned 64-bit integer result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 64-bit integer result (quotient) is returned in register t12.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__2divqu, DvFrameLength, Jr)
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ .set noreorder
+ .set noat
+ lda sp, -DvFrameLength(sp) // allocate stack frame
+
+ stq ra, DvRa(sp) // save ra register
+ stq ra, DvJr(sp) // backtrace return address
+ stq Jr, DvJr(sp) // save actual return address
+
+ stq t0, DvT0(sp) // save temp registers
+ stq t1, DvT1(sp) //
+ stq t2, DvT2(sp) //
+ stq t3, DvT3(sp) //
+ stq T4, DvT4(sp) //
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+//
+// Set up defines and include the main body of the division code.
+//
+
+#define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | UNSIGNED | DIVISION)
+
+#include "fastdiv.s"
+
+//
+// Restore all saved registers and return with quotient in register Qu.
+//
+
+ ldq Jr, DvJr(sp) // restore return address
+
+ ldq t0, DvT0(sp) // restore temp registers
+ ldq t1, DvT1(sp) //
+ ldq t2, DvT2(sp) //
+ ldq t3, DvT3(sp) //
+ ldq T4, DvT4(sp) //
+
+ lda sp, DvFrameLength(sp) // deallocate stack frame
+ ret zero, (Jr) // return
+
+ .end __2divqu
+
+ SBTTL("Signed Long Integer Remainder")
+//++
+//
+// LONG
+// __2reml (
+// IN LONG Dividend,
+// IN LONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides a signed 32-bit integer by a signed 32-bit integer
+// and returns the signed 32-bit integer remainder result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 32-bit integer result (remainder) is returned in register t12.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__2reml, DvFrameLength, Jr)
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ .set noreorder
+ .set noat
+ lda sp, -DvFrameLength(sp) // allocate stack frame
+
+ stq ra, DvRa(sp) // save ra register
+ stq ra, DvJr(sp) // backtrace return address
+ stq Jr, DvJr(sp) // save actual return address
+
+ stq Nu, DvNu(sp) // save original dividend
+ stq Di, DvDi(sp) // save original divisor
+ stq t0, DvT0(sp) // save temp registers
+ stq t1, DvT1(sp) //
+ stq t2, DvT2(sp) //
+ stq t3, DvT3(sp) //
+ stq T4, DvT4(sp) //
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+ addl Nu, 0, Nu // convert LONG dividend to quadword
+ addl Di, 0, Di // convert LONG divisor to quadword
+
+//
+// Check for division of the most negative integer (0x800..00) by the least
+// negative (-1). The result would be an integer which is one greater than the
+// maximum positive integer. Since this cannot be represented, an overflow must
+// be generated.
+//
+
+ addl Di, 1, t0 // 0 if Di == -1; != 0 otherwise
+ mov Nu, t1 // copy dividend
+ cmovne t0, 0, t1 // replace w/ 0 if divisor != -1
+ sublv zero, t1, t1 // trap if dividend == 0x800..00
+
+//
+// Convert negative arguments to positive for the division algorithm.
+//
+
+ subq zero, Nu, t0 // negate dividend
+ cmovlt Nu, t0, Nu // get absolute value of dividend
+ subq zero, Di, t0 // negate divisor
+ cmovlt Di, t0, Di // get absolute value of divisor
+
+//
+// Set up defines and include the main body of the division code.
+//
+
+#define FASTDIV_OPTIONS (THIRTY_TWO_BIT | SIGNED | REMAINDER)
+
+#include "fastdiv.s"
+
+//
+// Restore some registers and set the correct sign of the remainder.
+//
+
+ ldq Jr, DvJr(sp) // restore return address
+ ldq Nu, DvNu(sp) // restore original dividend
+ ldq Di, DvDi(sp) // restore original divisor
+
+ addl Qu, 0, Qu // ensure remainder is in canonical form
+ subl zero, Qu, t1 // negate LONG remainder
+ addl Nu, 0, t0 // get dividend in canonical form
+ cmovlt t0, t1, Qu // use negated remainder if necessary
+
+//
+// Restore other saved registers and return with remainder in register Qu.
+//
+
+ ldq t0, DvT0(sp) // restore temp registers
+ ldq t1, DvT1(sp) //
+ ldq t2, DvT2(sp) //
+ ldq t3, DvT3(sp) //
+ ldq T4, DvT4(sp) //
+
+ lda sp, DvFrameLength(sp) // deallocate stack frame
+ ret zero, (Jr) // return
+
+ .end __2reml
+
+ SBTTL("Unsigned Long Integer Remainder")
+//++
+//
+// ULONG
+// __2remlu (
+// IN ULONG Dividend,
+// IN ULONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides an unsigned 32-bit integer by an unsigned 32-bit
+// integer and returns the unsigned 32-bit integer remainder result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 32-bit integer result (remainder) is returned in register t12.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__2remlu, DvFrameLength, Jr)
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ .set noreorder
+ .set noat
+ lda sp, -DvFrameLength(sp) // allocate stack frame
+
+ stq ra, DvRa(sp) // save ra register
+ stq ra, DvJr(sp) // backtrace return address
+ stq Jr, DvJr(sp) // save actual return address
+
+ stq Nu, DvNu(sp) // save original dividend
+ stq Di, DvDi(sp) // save original divisor
+ stq t0, DvT0(sp) // save temp registers
+ stq t1, DvT1(sp) //
+ stq t2, DvT2(sp) //
+ stq t3, DvT3(sp) //
+ stq T4, DvT4(sp) //
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+ zap Nu, 0xf0, Nu // convert ULONG dividend to quadword
+ zap Di, 0xf0, Di // convert ULONG divisor to quadword
+
+//
+// Set up defines and include the main body of the division code.
+//
+
+#define FASTDIV_OPTIONS (THIRTY_TWO_BIT | UNSIGNED | REMAINDER)
+
+#include "fastdiv.s"
+
+//
+// Restore all saved registers and return with remainder in register Qu.
+//
+
+ ldq Jr, DvJr(sp) // restore return address
+ ldq Nu, DvNu(sp) // restore original dividend
+ ldq Di, DvDi(sp) // restore original divisor
+
+ ldq t0, DvT0(sp) // restore temp registers
+ ldq t1, DvT1(sp) //
+ ldq t2, DvT2(sp) //
+ ldq t3, DvT3(sp) //
+ ldq T4, DvT4(sp) //
+
+ lda sp, DvFrameLength(sp) // deallocate stack frame
+ ret zero, (Jr) // return
+
+ .end __2remlu
+
+ SBTTL("Signed Quad Integer Remainder")
+//++
+//
+// LONGLONG
+// __2remq (
+// IN LONGLONG Dividend,
+// IN LONGLONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides a signed 64-bit integer by a signed 64-bit integer
+// and returns the signed 64-bit integer remainder result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 64-bit integer result (remainder) is returned in register t12.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__2remq, DvFrameLength, Jr)
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ .set noreorder
+ .set noat
+ lda sp, -DvFrameLength(sp) // allocate stack frame
+
+ stq ra, DvRa(sp) // save ra register
+ stq ra, DvJr(sp) // backtrace return address
+ stq Jr, DvJr(sp) // save actual return address
+
+ stq Nu, DvNu(sp) // save original dividend
+ stq Di, DvDi(sp) // save original divisor
+ stq t0, DvT0(sp) // save temp registers
+ stq t1, DvT1(sp) //
+ stq t2, DvT2(sp) //
+ stq t3, DvT3(sp) //
+ stq T4, DvT4(sp) //
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+//
+// Check for division of the most negative integer (0x800..00) by the least
+// negative (-1). The result would be an integer which is one greater than the
+// maximum positive integer. Since this cannot be represented, an overflow must
+// be generated.
+//
+
+ addq Di, 1, t0 // 0 if Di == -1; != 0 otherwise
+ mov Nu, t1 // copy dividend
+ cmovne t0, 0, t1 // replace w/ 0 if divisor != -1
+ subqv zero, t1, t1 // trap if dividend == 0x800..00
+
+//
+// Convert negative arguments to positive for the division algorithm.
+//
+
+ subq zero, Nu, t0 // negate dividend
+ cmovlt Nu, t0, Nu // get absolute value of dividend
+ subq zero, Di, t0 // negate divisor
+ cmovlt Di, t0, Di // get absolute value of divisor
+
+//
+// Set up defines and include the main body of the division code.
+//
+
+#define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | SIGNED | REMAINDER)
+
+#include "fastdiv.s"
+
+//
+// Restore some registers and set the correct sign of the remainder.
+//
+
+ ldq Jr, DvJr(sp) // restore return address
+ ldq Nu, DvNu(sp) // restore original dividend
+ ldq Di, DvDi(sp) // restore original divisor
+
+ subq zero, Qu, t1 // negate quadword remainder
+ cmovlt Nu, t1, Qu // use negated remainder if necessary
+
+//
+// Restore other saved registers and return with remainder in register Qu.
+//
+
+ ldq t0, DvT0(sp) // restore temp registers
+ ldq t1, DvT1(sp) //
+ ldq t2, DvT2(sp) //
+ ldq t3, DvT3(sp) //
+ ldq T4, DvT4(sp) //
+
+ lda sp, DvFrameLength(sp) // deallocate stack frame
+ ret zero, (Jr) // return
+
+ .end __2remq
+
+ SBTTL("Unsigned Quad Integer Remainder")
+//++
+//
+// ULONGLONG
+// __2remqu (
+// IN ULONGLONG Dividend,
+// IN ULONGLONG Divisor
+// )
+//
+// Routine Description:
+//
+// This function divides an unsigned 64-bit integer by an unsigned 64-bit
+// integer and returns the unsigned 64-bit integer remainder result.
+//
+// Arguments:
+//
+// Dividend (t10) - Supplies the dividend (numerator) value.
+//
+// Divisor (t11) - Supplies the divisor (denominator) value.
+//
+// Return Value:
+//
+// The 64-bit integer result (remainder) is returned in register t12.
+//
+// Note:
+//
+// This function uses a non-standard calling procedure. The return address
+// is stored in the t9 register and the return value is in the t10 register.
+// No other registers are modified.
+//
+//--
+
+ NESTED_ENTRY(__2remqu, DvFrameLength, Jr)
+
+//
+// This prologue is magic. When executed during a call, it will save the
+// value of register ra (twice) and register t9 in the stack frame, even
+// though these registers are not modified by this function. The stores
+// appear to unnecessary.
+//
+// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
+// is reverse executed by virtual unwind to reset the stack pointer and to
+// obtain the return address. The return address is the value of RA the
+// first time it is restored, which will be the saved value of t9.
+//
+
+ .set noreorder
+ .set noat
+ lda sp, -DvFrameLength(sp) // allocate stack frame
+
+ stq ra, DvRa(sp) // save ra register
+ stq ra, DvJr(sp) // backtrace return address
+ stq Jr, DvJr(sp) // save actual return address
+
+ stq t0, DvT0(sp) // save temp registers
+ stq t1, DvT1(sp) //
+ stq t2, DvT2(sp) //
+ stq t3, DvT3(sp) //
+ stq T4, DvT4(sp) //
+ .set at
+ .set reorder
+
+ PROLOGUE_END
+
+//
+// Set up defines and include the main body of the division code.
+//
+
+#define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | UNSIGNED | REMAINDER)
+
+#include "fastdiv.s"
+
+//
+// Restore all saved registers and return with remainder in register Qu.
+//
+
+ ldq Jr, DvJr(sp) // restore return address
+
+ ldq t0, DvT0(sp) // restore temp registers
+ ldq t1, DvT1(sp) //
+ ldq t2, DvT2(sp) //
+ ldq t3, DvT3(sp) //
+ ldq T4, DvT4(sp) //
+
+ lda sp, DvFrameLength(sp) // deallocate stack frame
+ ret zero, (Jr) // return
+
+ .end __2remqu
+
+//
+// Now get one copy of the tables needed by the division code.
+//
+
+#define FASTDIV_TABLES
+
+#include "fastdiv.s"
diff --git a/private/crt32/misc/alpha/extv.s b/private/crt32/misc/alpha/extv.s
new file mode 100644
index 000000000..bd7e1b754
--- /dev/null
+++ b/private/crt32/misc/alpha/extv.s
@@ -0,0 +1,82 @@
+ #++
+ # Copyright 1991, Digital Equipment Corporation
+ #
+ # int ots_extv(char *addr, int position, unsigned size)
+ #
+ # Arbitrary signed bitfield extraction
+ #
+ # Special conventions: No stack space, r0, r16-r18 and r26-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # See also: ots_extv (just uses srl in place of sra in some cases...)
+ #
+ # 001 16 Aug 1991 KDG Initial version
+ #
+ # 002 4 Sep 1991 KDG Bugfix/improvements
+ #
+ # 003 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 004 22 Sep 1992 KDG Case-sensitive name
+ #
+ # 005 26 Jan 1993 KDG Add underscore
+
+#include "ots_defs.hs"
+
+ # Totally general field extract - arbitrary run-time field of 0-64 bits
+ # at an unknown alignment target.
+ #
+ # Conceptually, this operation takes a 67 bit bit-address, which is the sum
+ # of a byte-aligned memory address and the bit offset (which is signed).
+ #
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|Q|L|W|B|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|b|b|b|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ #
+ # Inputs:
+ # r16 - input address
+ # r17 - input bit offset
+ # r18 - input size
+ #
+ # This is based on the code GEM generates when not using an out-of-line
+ # routine.
+ #
+ .globl _OtsFieldExtractSigned
+ .ent _OtsFieldExtractSigned
+_OtsFieldExtractSigned:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+ sra r17, 3, r27 # get byte part of bit offset (signed!)
+ ble r18, zero # check for zero size - no memory access
+ addq r16, r27, r16 # add to initial base addr.
+ ldq_u r0, (r16) # start load first or only quadword
+ and r16, 7, r27 # get byte-in-quadword of first bit
+ and r17, 7, r17 # get bit-in-byte from bit offset
+ s8addq r27, r17, r17 # form the true bit offset in the quadword
+ addq r17, r18, r27 # get bit offset of bit following field
+ cmpule r27, 64, r28 # if <=64, field is contained in 1 quadword
+ beq r28, double # handle double case if not
+ # common case - fall through, load result hopefully already available
+single: negq r27, r27 # <5:0> = bits for right shift
+ sll r0, r27, r0 # move to high bits
+ addq r27, r17, r27 # bits for left shift
+ sra r0, r27, r0 # and shift into final position
+ ret r31, (r26)
+double: ldq_u r28, 8(r16) # load second quadword
+ srl r0, r27, r0 # move top piece over
+ negq r27, r27 # get shift bits for piece in 2nd word
+ sll r28, r27, r28 # move field in 2nd lw to high bits
+ bis r0, r28, r0 # form final value
+ negq r18, r27 # <5:0> = bits for right shift
+ sra r0, r27, r0 # and shift into final position
+ ret r31, (r26)
+zero: mov 0, r0 # zero-sized field extracts return 0
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsFieldExtractSigned
diff --git a/private/crt32/misc/alpha/extvvol.s b/private/crt32/misc/alpha/extvvol.s
new file mode 100644
index 000000000..f64dfa2a2
--- /dev/null
+++ b/private/crt32/misc/alpha/extvvol.s
@@ -0,0 +1,98 @@
+ #++
+ # Copyright 1992, Digital Equipment Corporation
+ #
+ # int ots_extv_vol(char *addr, int position, unsigned size)
+ #
+ # Arbitrary signed bitfield extraction for volatile cases
+ #
+ # Special conventions: No stack space, r0, r16-r18 and r26-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # See also: ots_extv_vol (just uses srl in place of sra in some cases...)
+ #
+ # 001 16 Aug 1991 KDG Initial version
+ #
+ # 002 4 Sep 1991 KDG Bugfix/improvements
+ #
+ # 003 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 004 6 Oct 1992 KDG Initial volatile version (just add longword
+ # test)
+ #
+ # 005 10 Nov 1992 KDG Case-sensitive name
+ #
+ # 006 26 Jan 1993 KDG Add underscore
+ #
+ # 007 1 Sep 1994 RBG Fix aligned longword case
+ # check for bit 0 within byte GEM_BUGS #3545
+
+#include "ots_defs.hs"
+
+ # Totally general field extract - arbitrary run-time field of 0-64 bits
+ # at an unknown alignment target.
+ #
+ # This volatile version always uses exactly LDL for aligned 32 bit field
+ # extracts, and quadword operations for all other.
+ #
+ # Conceptually, this operation takes a 67 bit bit-address, which is the sum
+ # of a byte-aligned memory address and the bit offset (which is signed).
+ #
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|Q|L|W|B|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|b|b|b|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ #
+ # Inputs:
+ # r16 - input address
+ # r17 - input bit offset
+ # r18 - input size
+ #
+ # This is based on the code GEM generates when not using an out-of-line
+ # routine.
+ #
+ .globl _OtsFieldExtractSignedVolatile
+ .ent _OtsFieldExtractSignedVolatile
+_OtsFieldExtractSignedVolatile:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+ .prologue 0
+ sra r17, 3, r27 # get byte part of bit offset (signed!)
+ ble r18, zero # check for zero size - no memory access
+ cmpeq r17, 32, r0 # exactly longword size?
+ addq r16, r27, r16 # add to initial base addr.
+ and r16, 3, r28 # aligned longword?
+ cmpult r28, r0, r28 # true if ((addr & 3) == 0) && (size == 32) && ...
+ and r17, 7, r17 # get bit-in-byte from bit offset
+ cmpult r17, r28, r28 # ... && (bit_in_byte == 0)
+ bne r28, longwd # go handle longword case specially
+ ldq_u r0, (r16) # start load first or only quadword
+ and r16, 7, r27 # get byte-in-quadword of first bit
+ s8addq r27, r17, r17 # form the true bit offset in the quadword
+ addq r17, r18, r27 # get bit offset of bit following field
+ cmpule r27, 64, r28 # if <=64, field is contained in 1 quadword
+ beq r28, double # handle double case if not
+ # common case - fall through, load result hopefully already available
+single: negq r27, r27 # <5:0> = bits for right shift
+ sll r0, r27, r0 # move to high bits
+ addq r27, r17, r27 # bits for left shift
+ sra r0, r27, r0 # and shift into final position
+ ret r31, (r26)
+double: ldq_u r28, 8(r16) # load second quadword
+ srl r0, r27, r0 # move top piece over
+ negq r27, r27 # get shift bits for piece in 2nd word
+ sll r28, r27, r28 # move field in 2nd lw to high bits
+ bis r0, r28, r0 # form final value
+ negq r18, r27 # <5:0> = bits for right shift
+ sra r0, r27, r0 # and shift into final position
+ ret r31, (r26)
+zero: mov 0, r0 # zero-sized field extracts return 0
+ ret r31, (r26)
+longwd: ldl r0, (r16) # load sign-extended aligned longword
+ ret r31, (r26)
+ .set at
+ .set reorder
+ .end _OtsFieldExtractSignedVolatile
diff --git a/private/crt32/misc/alpha/extzv.s b/private/crt32/misc/alpha/extzv.s
new file mode 100644
index 000000000..fb73dfb8e
--- /dev/null
+++ b/private/crt32/misc/alpha/extzv.s
@@ -0,0 +1,83 @@
+ #++
+ # Copyright 1991, Digital Equipment Corporation
+ #
+ # int ots_extzv(char *addr, int position, unsigned size)
+ #
+ # Arbitrary unsigned bitfield extraction
+ #
+ # Special conventions: No stack space, r0, r16-r18 and r26-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # See also: ots_extv (just uses sra in place of srl in some cases...)
+ #
+ # 001 16 Aug 1991 KDG Initial version
+ #
+ # 002 4 Sep 1991 KDG Bugfix/improvements
+ #
+ # 003 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 004 22 Sep 1992 KDG Add case-sensitive name
+ #
+ # 005 26 Jan 1993 KDG Add underscore
+
+#include "ots_defs.hs"
+
+ #
+ # Totally general field extract - arbitrary run-time field of 0-64 bits
+ # at an unknown alignment target.
+ #
+ # Conceptually, this operation takes a 67 bit bit-address, which is the sum
+ # of a byte-aligned memory address and the bit offset (which is signed).
+ #
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|Q|L|W|B|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|b|b|b|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ #
+ # Inputs:
+ # r16 - input address
+ # r17 - input bit offset
+ # r18 - input size
+ #
+ # This is based on the code GEM generates when not using an out-of-line
+ # routine.
+ #
+ .globl _OtsFieldExtractUnsigned
+ .ent _OtsFieldExtractUnsigned
+_OtsFieldExtractUnsigned:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+ sra r17, 3, r27 # get byte part of bit offset (signed!)
+ ble r18, zero # check for zero size - no memory access
+ addq r16, r27, r16 # add to initial base addr.
+ ldq_u r0, (r16) # start load first or only quadword
+ and r16, 7, r27 # get byte-in-quadword of first bit
+ and r17, 7, r17 # get bit-in-byte from bit offset
+ s8addq r27, r17, r17 # form the true bit offset in the quadword
+ addq r17, r18, r27 # get bit offset of bit following field
+ cmpule r27, 64, r28 # if <=64, field is contained in 1 quadword
+ beq r28, double # handle double case if not
+ # common case - fall through, load result hopefully already available
+single: negq r27, r27 # <5:0> = bits for right shift
+ sll r0, r27, r0 # move to high bits
+ addq r27, r17, r27 # bits for left shift
+ srl r0, r27, r0 # and shift into final position
+ ret r31, (r26)
+double: ldq_u r28, 8(r16) # load second quadword
+ srl r0, r27, r0 # move top piece over
+ negq r27, r27 # get shift bits for piece in 2nd word
+ sll r28, r27, r28 # move field in 2nd lw to high bits
+ bis r0, r28, r0 # form final value
+ negq r18, r27 # <5:0> = bits for right shift
+ srl r0, r27, r0 # and shift into final position
+ ret r31, (r26)
+zero: mov 0, r0 # zero-sized field extracts return 0
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsFieldExtractUnsigned
diff --git a/private/crt32/misc/alpha/extzvvol.s b/private/crt32/misc/alpha/extzvvol.s
new file mode 100644
index 000000000..7d3969561
--- /dev/null
+++ b/private/crt32/misc/alpha/extzvvol.s
@@ -0,0 +1,101 @@
+ #++
+ # Copyright 1991, Digital Equipment Corporation
+ #
+ # int ots_extzv_vol(char *addr, int position, unsigned size)
+ #
+ # Arbitrary unsigned bitfield extraction for volatile cases
+ #
+ # Special conventions: No stack space, r0, r16-r18 and r26-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # See also: ots_extv_vol (just uses sra in place of srl in some cases...)
+ #
+ # 001 16 Aug 1991 KDG Initial version
+ #
+ # 002 4 Sep 1991 KDG Bugfix/improvements
+ #
+ # 003 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 004 6 Oct 1992 KDG Initial volatile version (just add longword
+ # test)
+ #
+ # 005 10 Oct 1992 KDG Case-sensitive name
+ #
+ # 006 26 Jan 1993 KDG Add underscore
+ #
+ # 007 1 Sep 1994 RBG Fix aligned longword case
+ # check for bit 0 within byte GEM_BUGS #3545
+
+#include "ots_defs.hs"
+
+ #
+ # Totally general field extract - arbitrary run-time field of 0-64 bits
+ # at an unknown alignment target.
+ #
+ # This volatile version always uses exactly LDL for aligned 32 bit field
+ # extracts, and quadword operations for all other.
+ #
+ # Conceptually, this operation takes a 67 bit bit-address, which is the sum
+ # of a byte-aligned memory address and the bit offset (which is signed).
+ #
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|Q|L|W|B|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|b|b|b|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ #
+ # Inputs:
+ # r16 - input address
+ # r17 - input bit offset
+ # r18 - input size
+ #
+ # This is based on the code GEM generates when not using an out-of-line
+ # routine.
+ #
+ .globl _OtsFieldExtractUnsignedVolatile
+ .ent _OtsFieldExtractUnsignedVolatile
+_OtsFieldExtractUnsignedVolatile:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+ .prologue 0
+ sra r17, 3, r27 # get byte part of bit offset (signed!)
+ ble r18, zero # check for zero size - no memory access
+ cmpeq r17, 32, r0 # exactly longword size?
+ addq r16, r27, r16 # add to initial base addr.
+ and r16, 3, r28 # aligned longword?
+ cmpult r28, r0, r28 # true if ((addr & 3) == 0) && (size == 32) && ...
+ and r17, 7, r17 # get bit-in-byte from bit offset
+ cmpult r17, r28, r28 # ... && (bit_in_byte == 0)
+ bne r28, longwd # go handle longword case specially
+ ldq_u r0, (r16) # start load first or only quadword
+ and r16, 7, r27 # get byte-in-quadword of first bit
+ s8addq r27, r17, r17 # form the true bit offset in the quadword
+ addq r17, r18, r27 # get bit offset of bit following field
+ cmpule r27, 64, r28 # if <=64, field is contained in 1 quadword
+ beq r28, double # handle double case if not
+ # common case - fall through, load result hopefully already available
+single: negq r27, r27 # <5:0> = bits for right shift
+ sll r0, r27, r0 # move to high bits
+ addq r27, r17, r27 # bits for left shift
+ srl r0, r27, r0 # and shift into final position
+ ret r31, (r26)
+double: ldq_u r28, 8(r16) # load second quadword
+ srl r0, r27, r0 # move top piece over
+ negq r27, r27 # get shift bits for piece in 2nd word
+ sll r28, r27, r28 # move field in 2nd lw to high bits
+ bis r0, r28, r0 # form final value
+ negq r18, r27 # <5:0> = bits for right shift
+ srl r0, r27, r0 # and shift into final position
+ ret r31, (r26)
+zero: mov 0, r0 # zero-sized field extracts return 0
+ ret r31, (r26)
+longwd: ldl r0, (r16) # load sign-extended aligned longword
+ zapnot r0, 15, r0
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsFieldExtractUnsignedVolatile
diff --git a/private/crt32/misc/alpha/fastdiv.s b/private/crt32/misc/alpha/fastdiv.s
new file mode 100644
index 000000000..600c89ef9
--- /dev/null
+++ b/private/crt32/misc/alpha/fastdiv.s
@@ -0,0 +1,662 @@
+// TITLE("High-Performance Division")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// fastdiv.s
+//
+// Abstract:
+//
+// This module implements a high-performance integer division routine
+// whose source is included from each of the division and remainder
+// functions.
+//
+// Author:
+//
+// Thomas Van Baak (tvb) 12-Jan-1993
+// Ken Lesniak (lesniak) 04-Nov-1992
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+//
+// Implementation Notes:
+//
+// This code is the main "guts" of the eight divide and remainder routines
+// in the C library. It is intended to be included by a wrapper function
+// that defines options to control 32 vs. 64-bit, division vs. remainder,
+// and signed vs. unsigned. The wrapper function is responsible for the
+// prologue and epilogue sequences, as well as overflow checking and sign
+// adjustment on both input arguments and the return value.
+//
+// The algorithm used here is based on long division and a table for
+// approximating inverses as discussed in the paper "Division by a Constant"
+// by Mary Payne and Robert Gries. If the divisor inverse can be constructed
+// from the table without an error, the division is performed as described
+// in the paper with a multiplication and a shift.
+//
+// If the inverse can not be found in the table, we improve the inverse with
+// a linear approximation, "I". A multiplication by "I" and a shift by
+// log2(y) is used to obtain an approximate quotient, "Q". Now, like long
+// division, the most significant bits are correct, therefore if we
+// calculate the remainder R = x-Q*y, R will be smaller than x, and R will
+// contain the true remainder and the error in Q, "e" multiplied by y.
+//
+// So if we do the same multiplication and shift, we will get an
+// approximation for e. This is just long division, and it will finish
+// when R, the remainder, is less than y.
+//
+// Both the division algorithm code and the large division tables used by
+// the code are contained in this source file (to keep them together).
+//
+
+//
+// The code below requires that the wrapper function define register numbers
+// for each of the following symbolic register names:
+//
+// Nu dividend (numerator)
+// Di divisor (denominator)
+// Qu quotient
+// Re remainder (may be the same as Qu)
+//
+// T0 temp
+// T1 temp
+// T2 temp
+// T3 temp
+// T4 temp
+// T5 temp
+// T6 temp (may be shared with Qu)
+//
+
+//
+// The code below requires that the wrapper function define the symbol
+// FASTDIV_OPTIONS as the logical sum of the following names:
+//
+
+#define THIRTY_TWO_BIT 1 // perform 32-bit computations, otherwise
+#define SIXTY_FOUR_BIT 0 // perform 64-bit computations
+
+#define UNSIGNED 2 // treat operands as unsigned, otherwise
+#define SIGNED 0 // treat operands as signed
+
+#define DIVISION 4 // return quotient in Qu register, and/or
+#define REMAINDER 8 // return remainder in Re register
+
+//
+// Define the symbols that actually control the code generation.
+//
+
+#define _THIRTYTWOBIT (FASTDIV_OPTIONS & THIRTY_TWO_BIT)
+#define _SIXTYFOURBIT (!(FASTDIV_OPTIONS & THIRTY_TWO_BIT))
+#define _UNSIGNED (FASTDIV_OPTIONS & UNSIGNED)
+#define _REMAINDER (FASTDIV_OPTIONS & REMAINDER)
+#define _QUOTIENT (FASTDIV_OPTIONS & DIVISION)
+
+//
+// These constants give the algorithm the best performance.
+//
+
+#define BIT_LENGTH 8
+#define BIT_VALUE (1 << BIT_LENGTH)
+#define BIT_MASK (BIT_VALUE - 1)
+
+#define K_BIT_LENGTH 8
+#define K_BIT_VALUE (1 << K_BIT_LENGTH)
+#define K_BIT_MASK (K_BIT_VALUE - 1)
+
+#define TABLE_BIAS 16384
+
+#define LOG2TAB -16384
+#define INV_FLAG -15360
+#define INV -14848
+#define INV_M -14840
+
+#ifndef FASTDIV_TABLES
+
+ .set noat
+
+ lda T3, __2divdata + TABLE_BIAS // set address of table
+ beq Di, 30f // if zero divisor, generate trap
+
+ cmpule Nu, Di, T0 // check if dividend <= divisor
+#if _THIRTYTWOBIT
+ addl Di, 0, T1 // sign extend longword to quadword
+ blt T1, 20f // high bit set so quotient <= 1
+#endif
+#if _SIXTYFOURBIT
+ blt Di, 20f // high bit set so quotient <= 1
+#endif
+
+ cmpbge zero, Di, T2 // perform 8 byte parallel compare
+ bne T0, 20f // dividend <= divisor so quotient <= 1
+
+ xor T2, 0xff, T0 //
+ s4addq T0, T3, T0 //
+ ldl AT, LOG2TAB(T0) //
+ extbl Di, AT, T0 //
+ s4addq T0, T3, T0 //
+ ldl T0, LOG2TAB(T0) //
+ s8addq AT, T0, AT //
+ ornot zero, AT, T0 //
+ sll Di, T0, T0 //
+ sll T0, BIT_LENGTH + 1, T1 //
+ bne T1, 40f //
+
+//
+// Short case.
+//
+
+ subq Di, 1, T1 // compute divisor - 1
+ and Di, T1, T2 // divisor & (divisor - 1)
+ srl T0, 63 - (BIT_LENGTH + 1), T6 //
+ beq T2, 10f // divisor is a power of two
+
+ subq T6, BIT_VALUE + BIT_VALUE, T6 //
+ bic T6, 1, T4 //
+ s8addq T4, T3, T4 //
+ ldq T5, INV(T4) //
+ ldq T4, INV_M(T4) //
+ subq T5, T4, T4 //
+ cmovlbs T6, T4, T5 //
+ addq T6, T3, T2 //
+ ldq_u T0, INV_FLAG(T2) //
+ extbl T0, T2, T2 //
+ addq Nu, T2, T1 //
+ umulh T1, T5, T3 //
+#if _SIXTYFOURBIT && _UNSIGNED
+ cmoveq T1, T5, T3 //
+#endif
+ srl T3, AT, Qu //
+#if _REMAINDER
+ mulq Qu, Di, T0 //
+ subq Nu, T0, Re //
+#endif
+ br zero, 90f // all done, branch to epilogue code
+
+10:
+
+//
+// The divisor is now known to be a power of two.
+//
+// - The quotient is the dividend shifted right by exponent bits and
+// the remainder is the low order exponent bits of the dividend.
+//
+// AT = log2(divisor)
+// T1 = divisor - 1
+//
+
+#if _REMAINDER
+ and Nu, T1, Re //
+#endif
+#if _QUOTIENT
+ srl Nu, AT, Qu //
+#endif
+ br zero, 90f // all done, branch to epilogue code
+
+20:
+
+//
+// The quotient is now known to be either 0 or 1.
+//
+// - if the high bit of the divisor is set, the quotient must be less
+// than 2, so the quotient is 0 or 1.
+//
+// - if the dividend is less than the divisor, the quotient is 0 and
+// the remainder is the dividend.
+//
+// - if the dividend is equal to the divisor, the quotient is 1 and
+// the remainder is 0.
+//
+// - if the dividend is greater than the divisor, the quotient is 1
+// and the remainder is the dividend minus the divisor.
+//
+
+#if _REMAINDER
+ cmpule Di, Nu, T0 // if divisor <= dividend
+ subq Nu, Di, Re // then remainder is dividend,
+ cmoveq T0, Nu, Re // else remainder is dividend - divisor
+#endif
+#if _QUOTIENT
+ cmpule Di, Nu, Qu // if divisor <= dividend, 1, else 0
+#endif
+ br zero, 90f // all done, branch to epilogue code
+
+//
+// Generate divide by zero exception. If execution is continued, return
+// a zero result.
+//
+
+30: ldiq a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
+
+ GENERATE_TRAP
+
+ ldiq Qu, 0 // supply 0 result if continued
+ br zero, 90f // branch to epilogue code
+
+//
+// Long case.
+//
+
+40: srl T0, 63-(BIT_LENGTH+K_BIT_LENGTH), T6 //
+ srl T6, K_BIT_LENGTH, T0 //
+ and T6, K_BIT_MASK, T6 //
+ addq T0, T0, T0 //
+ s8addq T0, T3, T1 //
+ ldq T2, INV-(16*BIT_VALUE)(T1) //
+ ldq T0, INV_M-(16*BIT_VALUE)(T1) //
+ mulq T0, T6, T0 //
+ srl T0, K_BIT_LENGTH-1, T0 //
+ subq T2, T0, T6 //
+ umulh Nu, T6, T4 //
+ srl T4, AT, T4 //
+ mulq T4, Di, T5 //
+ mov zero, T3 //
+#if _SIXTYFOURBIT
+ xor Nu, T5, T0 //
+ bge T0, 50f //
+
+ umulh Di, T4, T3 //
+50:
+#endif
+ subq Nu, T5, T5 //
+ beq T4, 70f //
+
+ cmpult Nu, T5, T0 //
+ or T0, T3, T3 //
+ negq T5, T1 //
+ cmovne T3, T1, T5 //
+ addq Di, Di, T0 //
+ cmpule T0, T5, T0 //
+ beq T0, 70f //
+
+//
+// do {
+//
+
+60: umulh T5, T6, T2 //
+ srl T2, AT, T2 //
+ negq T2, T0 //
+ cmoveq T3, T2, T0 //
+ addq T4, T0, T4 //
+ mulq T2, Di, T1 //
+ subq T5, T1, T5 //
+#if _SIXTYFOURBIT
+ ldiq T0, 1 //
+ cmovne T3, 0, T0 //
+ negq T5, T2 //
+ cmovlt T5, T0, T3 //
+ cmovlt T5, T2, T5 //
+#endif
+ addq Di, Di, T0 //
+ cmpule T5, T0, T0 //
+ cmovne T0, 0, T1 //
+ bne T1, 60b //
+
+//
+// } while
+//
+
+70: cmpule Di, T5, T0 //
+ beq T0, 80f //
+
+ subq T5, Di, T5 //
+ subq T4, 1, T0 //
+ addq T4, 1, T4 //
+ cmovne T3, T0, T4 //
+80:
+ cmoveq T5, 0, T3 //
+#if _REMAINDER
+ subq Di, T5, Re //
+ cmoveq T3, T5, Re //
+#endif
+#if _QUOTIENT
+ subq T4, 1, Qu //
+ cmoveq T3, T4, Qu //
+#endif
+
+90:
+ .set at
+
+#undef FASTDIV_OPTIONS
+
+#else
+
+//
+// The following data was machine generated. DO NOT EDIT MANUALLY.
+//
+
+ .globl __2divdata
+ .rdata
+ .align 4
+__2divdata:
+
+//
+// LOG2TAB
+//
+
+ .align 2
+ .long 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
+ .long 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+ .long 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+ .long 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+ .long 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+ .long 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+ .long 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+ .long 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
+ .long 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+ .long 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+ .long 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+ .long 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+ .long 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+ .long 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+ .long 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+ .long 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+
+//
+// INV_FLAG
+//
+
+ .align 3
+ .byte 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1
+ .byte 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0
+ .byte 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1
+ .byte 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0
+ .byte 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0
+ .byte 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0
+ .byte 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1
+ .byte 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0
+ .byte 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1
+ .byte 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1
+ .byte 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1
+ .byte 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1
+ .byte 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1
+ .byte 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0
+ .byte 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1
+ .byte 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0
+ .byte 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1
+ .byte 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0
+ .byte 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1
+ .byte 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0
+ .byte 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1
+ .byte 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1
+ .byte 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1
+ .byte 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
+ .byte 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1
+ .byte 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0
+ .byte 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1
+ .byte 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1
+ .byte 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1
+ .byte 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1
+ .byte 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1
+ .byte 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1
+
+//
+// INV INV_M
+//
+
+ .align 4
+ .quad 0xffffffffffffffff, 0x007fc01ff007fc01, // 0
+ .quad 0xff00ff00ff00ff01, 0x007ec25bf68dabfe, // 1
+ .quad 0xfe03f80fe03f80fe, 0x007dc78930f5b971, // 2
+ .quad 0xfd08e5500fd08e55, 0x007ccf9c05f3157c, // 3
+ .quad 0xfc0fc0fc0fc0fc10, 0x007bda891528a983, // 4
+ .quad 0xfb18856506ddaba6, 0x007ae84535db391c, // 5
+ .quad 0xfa232cf252138ac0, 0x0079f8c575ac2ab0, // 6
+ .quad 0xf92fb2211855a865, 0x00790bff175cf1bf, // 7
+ .quad 0xf83e0f83e0f83e10, 0x007821e7919ad7f4, // 8
+ .quad 0xf74e3fc22c700f75, 0x00773a748dd2e48d, // 9
+ .quad 0xf6603d980f6603da, 0x0076559be70da3cb, // 10
+ .quad 0xf57403d5d00f5740, 0x00757353a8d2921b, // 11
+ .quad 0xf4898d5f85bb3950, 0x007493920e12f0da, // 12
+ .quad 0xf3a0d52cba872336, 0x0073b64d801bcc4b, // 13
+ .quad 0xf2b9d6480f2b9d65, 0x0072db7c958efc82, // 14
+ .quad 0xf1d48bcee0d399fa, 0x007203161162ec7b, // 15
+ .quad 0xf0f0f0f0f0f0f0f1, 0x00712d10e1e8f4b3, // 16
+ .quad 0xf00f00f00f00f00f, 0x007059641fda17d7, // 17
+ .quad 0xef2eb71fc4345238, 0x006f88070d69f229, // 18
+ .quad 0xee500ee500ee500f, 0x006eb8f1155fad72, // 19
+ .quad 0xed7303b5cc0ed730, 0x006dec19ca34cd01, // 20
+ .quad 0xec979118f3fc4da2, 0x006d2178e539a6a8, // 21
+ .quad 0xebbdb2a5c1619c8c, 0x006c590645bf5ef6, // 22
+ .quad 0xeae56403ab95900f, 0x006b92b9f0474060, // 23
+ .quad 0xea0ea0ea0ea0ea0f, 0x006ace8c0db7463d, // 24
+ .quad 0xe939651fe2d8d35c, 0x006a0c74ea93b5ce, // 25
+ .quad 0xe865ac7b7603a197, 0x00694c6cf63da0af, // 26
+ .quad 0xe79372e225fe30d9, 0x00688e6cc2362d3c, // 27
+ .quad 0xe6c2b4481cd85689, 0x0067d26d016682a0, // 28
+ .quad 0xe5f36cb00e5f36cb, 0x00671866876c373e, // 29
+ .quad 0xe525982af70c880e, 0x0066605247ea214c, // 30
+ .quad 0xe45932d7dc52100e, 0x0065aa2955dd6a6f, // 31
+ .quad 0xe38e38e38e38e38e, 0x0064f5e4e2f6c80c, // 32
+ .quad 0xe2c4a6886a4c2e10, 0x0064437e3ef7bb1b, // 33
+ .quad 0xe1fc780e1fc780e2, 0x006392eed713bb0b, // 34
+ .quad 0xe135a9c97500e136, 0x0062e43035553040, // 35
+ .quad 0xe070381c0e070382, 0x0062373c00062374, // 36
+ .quad 0xdfac1f74346c575f, 0x00618c0bf91c8837, // 37
+ .quad 0xdee95c4ca037ba57, 0x0060e299fdaa0972, // 38
+ .quad 0xde27eb2c41f3d9d1, 0x00603ae0054f3f9c, // 39
+ .quad 0xdd67c8a60dd67c8a, 0x005f94d821b23932, // 40
+ .quad 0xdca8f158c7f91ab8, 0x005ef07c7df83e6e, // 41
+ .quad 0xdbeb61eed19c5958, 0x005e4dc75e42ba41, // 42
+ .quad 0xdb2f171df7702919, 0x005dacb31f2f32ed, // 43
+ .quad 0xda740da740da740e, 0x005d0d3a355a3d88, // 44
+ .quad 0xd9ba4256c0366e91, 0x005c6f572ce55811, // 45
+ .quad 0xd901b2036406c80e, 0x005bd304a8ff968c, // 46
+ .quad 0xd84a598ec9151f43, 0x005b383d63711014, // 47
+ .quad 0xd79435e50d79435e, 0x005a9efc2c28f962, // 48
+ .quad 0xd6df43fca482f00d, 0x005a073be8ce5ae4, // 49
+ .quad 0xd62b80d62b80d62c, 0x005970f7945350f4, // 50
+ .quad 0xd578e97c3f5fe551, 0x0058dc2a3e8ac544, // 51
+ .quad 0xd4c77b03531dec0d, 0x005848cf0bc0912f, // 52
+ .quad 0xd4173289870ac52e, 0x0057b6e13453f8e0, // 53
+ .quad 0xd3680d3680d3680d, 0x0057265c04546fe2, // 54
+ .quad 0xd2ba083b445250ab, 0x0056973adb20982b, // 55
+ .quad 0xd20d20d20d20d20d, 0x005609792b076ce1, // 56
+ .quad 0xd161543e28e50274, 0x00557d1278eb8ad3, // 57
+ .quad 0xd0b69fcbd2580d0b, 0x0054f2025be888c5, // 58
+ .quad 0xd00d00d00d00d00d, 0x005468447cfa5248, // 59
+ .quad 0xcf6474a8819ec8e9, 0x0053dfd496a67807, // 60
+ .quad 0xcebcf8bb5b4169cb, 0x005358ae74a768fd, // 61
+ .quad 0xce168a7725080ce1, 0x0052d2cdf3998842, // 62
+ .quad 0xcd712752a886d242, 0x00524e2f00aa138f, // 63
+ .quad 0xcccccccccccccccd, 0x0051cacd9947cecc, // 64
+ .quad 0xcc29786c7607f99f, 0x005148a5cad5697f, // 65
+ .quad 0xcb8727c065c393e0, 0x0050c7b3b25d9315, // 66
+ .quad 0xcae5d85f1bbd6c95, 0x005047f37c48b368, // 67
+ .quad 0xca4587e6b74f0329, 0x004fc96164143d25, // 68
+ .quad 0xc9a633fcd967300d, 0x004f4bf9b40b9000, // 69
+ .quad 0xc907da4e871146ad, 0x004ecfb8c50260f1, // 70
+ .quad 0xc86a78900c86a789, 0x004e549afe109ef0, // 71
+ .quad 0xc7ce0c7ce0c7ce0c, 0x004dda9cd44fcaee, // 72
+ .quad 0xc73293d789b9f838, 0x004d61baca99ba10, // 73
+ .quad 0xc6980c6980c6980c, 0x004ce9f17148b95b, // 74
+ .quad 0xc5fe740317f9d00c, 0x004c733d65f90a5a, // 75
+ .quad 0xc565c87b5f9d4d1c, 0x004bfd9b534bb06e, // 76
+ .quad 0xc4ce07b00c4ce07b, 0x004b8907f0aa86ab, // 77
+ .quad 0xc4372f855d824ca6, 0x004b1580020d9680, // 78
+ .quad 0xc3a13de60495c773, 0x004aa30057c1a767, // 79
+ .quad 0xc30c30c30c30c30c, 0x004a3185ce30004a, // 80
+ .quad 0xc2780613c0309e02, 0x0049c10d4da7534b, // 81
+ .quad 0xc1e4bbd595f6e947, 0x00495193ca25cceb, // 82
+ .quad 0xc152500c152500c1, 0x0048e31643243fb8, // 83
+ .quad 0xc0c0c0c0c0c0c0c1, 0x00487591c36265c8, // 84
+ .quad 0xc0300c0300c0300c, 0x0048090360b4318c, // 85
+ .quad 0xbfa02fe80bfa02ff, 0x00479d683bd0279f, // 86
+ .quad 0xbf112a8ad278e8dd, 0x004732bd801ebb67, // 87
+ .quad 0xbe82fa0be82fa0bf, 0x0046c900638aa88c, // 88
+ .quad 0xbdf59c91700bdf5a, 0x0046602e26524361, // 89
+ .quad 0xbd69104707661aa3, 0x0045f84412d9ba97, // 90
+ .quad 0xbcdd535db1cc5b7b, 0x0045913f7d7e44a5, // 91
+ .quad 0xbc52640bc52640bc, 0x00452b1dc46a3383, // 92
+ .quad 0xbbc8408cd63069a1, 0x0044c5dc4f69e972, // 93
+ .quad 0xbb3ee721a54d880c, 0x004461788fc1a9a5, // 94
+ .quad 0xbab656100bab6561, 0x0043fdf000043fdf, // 95
+ .quad 0xba2e8ba2e8ba2e8c, 0x00439b4023ea7a13, // 96
+ .quad 0xb9a7862a0ff46588, 0x00433966882b6f4f, // 97
+ .quad 0xb92143fa36f5e02e, 0x0042d860c2558f4d, // 98
+ .quad 0xb89bc36ce3e0453a, 0x0042782c70a87632, // 99
+ .quad 0xb81702e05c0b8170, 0x004218c739ef8000, // 100
+ .quad 0xb79300b79300b793, 0x0041ba2ecd5d1788, // 101
+ .quad 0xb70fbb5a19be3659, 0x00415c60e266bc99, // 102
+ .quad 0xb68d31340e4307d8, 0x0040ff5b38a1bd6e, // 103
+ .quad 0xb60b60b60b60b60b, 0x0040a31b97a09f52, // 104
+ .quad 0xb58a485518d1e7e4, 0x0040479fced1329a, // 105
+ .quad 0xb509e68a9b94821f, 0x003fece5b55b4e37, // 106
+ .quad 0xb48a39d44685fe97, 0x003f92eb2a002f2f, // 107
+ .quad 0xb40b40b40b40b40b, 0x003f39ae12fa7858, // 108
+ .quad 0xb38cf9b00b38cf9b, 0x003ee12c5ddecee8, // 109
+ .quad 0xb30f63528917c80b, 0x003e8963ff7d1056, // 110
+ .quad 0xb2927c29da5519cf, 0x003e3252f3c21e56, // 111
+ .quad 0xb21642c8590b2164, 0x003ddbf73d9a3d87, // 112
+ .quad 0xb19ab5c45606f00b, 0x003d864ee6d403ca, // 113
+ .quad 0xb11fd3b80b11fd3c, 0x003d31580003d316, // 114
+ .quad 0xb0a59b418d749d53, 0x003cdd10a067ddc1, // 115
+ .quad 0xb02c0b02c0b02c0b, 0x003c8976e5ccb15f, // 116
+ .quad 0xafb321a1496fdf0e, 0x003c3688f472452e, // 117
+ .quad 0xaf3addc680af3ade, 0x003be444f6f1897b, // 118
+ .quad 0xaec33e1f671529a5, 0x003b92a91e2274fb, // 119
+ .quad 0xae4c415c9882b931, 0x003b41b3a1028dad, // 120
+ .quad 0xadd5e6323fd48a86, 0x003af162bc9bea7b, // 121
+ .quad 0xad602b580ad602b6, 0x003aa1b4b3ecab20, // 122
+ .quad 0xaceb0f891e6551bb, 0x003a52a7cfcee3c6, // 123
+ .quad 0xac7691840ac76918, 0x003a043a5ee0fa15, // 124
+ .quad 0xac02b00ac02b00ac, 0x0039b66ab56e7112, // 125
+ .quad 0xab8f69e28359cd11, 0x003969372d5921bb, // 126
+ .quad 0xab1cbdd3e2970f60, 0x00391c9e2602ddfa, // 127
+ .quad 0xaaaaaaaaaaaaaaab, 0x0038d09e04377bbb, // 128
+ .quad 0xaa392f35dc17f00b, 0x003885353217460a, // 129
+ .quad 0xa9c84a47a07f5638, 0x00383a621f01d214, // 130
+ .quad 0xa957fab5402a55ff, 0x0037f0233f8135f4, // 131
+ .quad 0xa8e83f5717c0a8e8, 0x0037a6770d359f5a, // 132
+ .quad 0xa87917088e262b6f, 0x00375d5c06c14806, // 133
+ .quad 0xa80a80a80a80a80b, 0x003714d0afb4c633, // 134
+ .quad 0xa79c7b16ea64d422, 0x0036ccd3907bb709, // 135
+ .quad 0xa72f05397829cbc1, 0x003685633649c151, // 136
+ .quad 0xa6c21df6e1625c80, 0x00363e7e3307ee8e, // 137
+ .quad 0xa655c4392d7b73a8, 0x0035f8231d4258ba, // 138
+ .quad 0xa5e9f6ed347f0721, 0x0035b25090162b0e, // 139
+ .quad 0xa57eb50295fad40a, 0x00356d052b1ff400, // 140
+ .quad 0xa513fd6bb00a5140, 0x0035283f926a46f2, // 141
+ .quad 0xa4a9cf1d96833751, 0x0034e3fe6e5cabea, // 142
+ .quad 0xa44029100a440291, 0x0034a0406baadbcc, // 143
+ .quad 0xa3d70a3d70a3d70a, 0x00345d043b44478a, // 144
+ .quad 0xa36e71a2cb033128, 0x00341a489243e8ca, // 145
+ .quad 0xa3065e3fae7cd0e0, 0x0033d80c29e05a93, // 146
+ .quad 0xa29ecf163bb6500a, 0x0033964dbf5c3891, // 147
+ .quad 0xa237c32b16cfd772, 0x0033550c13f6c382, // 148
+ .quad 0xa1d139855f7268ee, 0x00331445ecdcc986, // 149
+ .quad 0xa16b312ea8fc377d, 0x0032d3fa1319d0d6, // 150
+ .quad 0xa105a932f2ca891f, 0x00329427538983c8, // 151
+ .quad 0xa0a0a0a0a0a0a0a1, 0x003254cc7ec95ca2, // 152
+ .quad 0xa03c1688732b3032, 0x003215e8692a9028, // 153
+ .quad 0x9fd809fd809fd80a, 0x0031d779eaa43595, // 154
+ .quad 0x9f747a152d7836d0, 0x0031997fdec5aad6, // 155
+ .quad 0x9f1165e7254813e2, 0x00315bf924a933d8, // 156
+ .quad 0x9eaecc8d53ae2ddf, 0x00311ee49ee6d3cb, // 157
+ .quad 0x9e4cad23dd5f3a20, 0x0030e24133875f2f, // 158
+ .quad 0x9deb06c9194aa416, 0x0030a60dcbf7c5aa, // 159
+ .quad 0x9d89d89d89d89d8a, 0x00306a4954fc927a, // 160
+ .quad 0x9d2921c3d6411308, 0x00302ef2bea5a284, // 161
+ .quad 0x9cc8e160c3fb19b9, 0x002ff408fc420f05, // 162
+ .quad 0x9c69169b30446dfa, 0x002fb98b04544bcd, // 163
+ .quad 0x9c09c09c09c09c0a, 0x002f7f77d086781f, // 164
+ .quad 0x9baade8e4a2f6e10, 0x002f45ce5d9ee128, // 165
+ .quad 0x9b4c6f9ef03a3caa, 0x002f0c8dab74b53e, // 166
+ .quad 0x9aee72fcf957c10f, 0x002ed3b4bce4e6d7, // 167
+ .quad 0x9a90e7d95bc609a9, 0x002e9b4297c73e6e, // 168
+ .quad 0x9a33cd67009a33cd, 0x002e633644e39a62, // 169
+ .quad 0x99d722dabde58f06, 0x002e2b8ecfe75c01, // 170
+ .quad 0x997ae76b50efd00a, 0x002df44b475b00d8, // 171
+ .quad 0x991f1a515885fb37, 0x002dbd6abc97e780, // 172
+ .quad 0x98c3bac74f5db00a, 0x002d86ec43be3f17, // 173
+ .quad 0x9868c809868c8098, 0x002d50cef3ab208e, // 174
+ .quad 0x980e4156201301c8, 0x002d1b11e5eed122, // 175
+ .quad 0x97b425ed097b425f, 0x002ce5b436c32d10, // 176
+ .quad 0x975a750ff68a58af, 0x002cb0b5050239fa, // 177
+ .quad 0x97012e025c04b809, 0x002c7c13721ce019, // 178
+ .quad 0x96a850096a850097, 0x002c47cea211c9a1, // 179
+ .quad 0x964fda6c0964fda7, 0x002c13e5bb646783, // 180
+ .quad 0x95f7cc72d1b887e9, 0x002be057e7141b13, // 181
+ .quad 0x95a02568095a0257, 0x002bad24509383a7, // 182
+ .quad 0x9548e4979e0829fd, 0x002b7a4a25bfefbe, // 183
+ .quad 0x94f2094f2094f209, 0x002b47c896d8f0df, // 184
+ .quad 0x949b92ddc02526e5, 0x002b159ed67811bb, // 185
+ .quad 0x9445809445809446, 0x002ae3cc1988adbb, // 186
+ .quad 0x93efd1c50e726b7c, 0x002ab24f973fe99c, // 187
+ .quad 0x939a85c40939a85c, 0x002a81288914cc5b, // 188
+ .quad 0x93459be6b009345a, 0x002a50562ab877df, // 189
+ .quad 0x92f113840497889c, 0x002a1fd7ba0e80df, // 190
+ .quad 0x929cebf48bbd90e5, 0x0029efac7725656b, // 191
+ .quad 0x9249249249249249, 0x0029bfd3a42f218e, // 192
+ .quad 0x91f5bcb8bb02d9cd, 0x0029904c8579e17d, // 193
+ .quad 0x91a2b3c4d5e6f809, 0x002961166168d0d3, // 194
+ .quad 0x9150091500915009, 0x00293230806d0653, // 195
+ .quad 0x90fdbc090fdbc091, 0x0029039a2cfe8bab, // 196
+ .quad 0x90abcc0242af3009, 0x0028d552b39580c2, // 197
+ .quad 0x905a38633e06c43b, 0x0028a75962a35a0f, // 198
+ .quad 0x9009009009009009, 0x002879ad8a8c397c, // 199
+ .quad 0x8fb823ee08fb823f, 0x00284c4e7da06171, // 200
+ .quad 0x8f67a1e3fdc26178, 0x00281f3b9015c16f, // 201
+ .quad 0x8f1779d9fdc3a219, 0x0027f27418019bf5, // 202
+ .quad 0x8ec7ab397255e41d, 0x0027c5f76d52450e, // 203
+ .quad 0x8e78356d1408e783, 0x002799c4e9c8f94d, // 204
+ .quad 0x8e2917e0e702c6cd, 0x00276ddbe8f3cca0, // 205
+ .quad 0x8dda520237694809, 0x0027423bc827b0a6, // 206
+ .quad 0x8d8be33f95d71590, 0x002716e3e67a921c, // 207
+ .quad 0x8d3dcb08d3dcb08d, 0x0026ebd3a4bd8d01, // 208
+ .quad 0x8cf008cf008cf009, 0x0026c10a657736fa, // 209
+ .quad 0x8ca29c046514e023, 0x002696878cddffb1, // 210
+ .quad 0x8c55841c815ed5ca, 0x00266c4a80d2a6b2, // 211
+ .quad 0x8c08c08c08c08c09, 0x00264252a8dac681, // 212
+ .quad 0x8bbc50c8deb420c0, 0x0026189f6e1b7473, // 213
+ .quad 0x8b70344a139bc75a, 0x0025ef303b53f50e, // 214
+ .quad 0x8b246a87e19008b2, 0x0025c6047cd8847d, // 215
+ .quad 0x8ad8f2fba9386823, 0x00259d1ba08d32c5, // 216
+ .quad 0x8a8dcd1feeae465c, 0x0025747515e0d378, // 217
+ .quad 0x8a42f8705669db46, 0x00254c104dc80080, // 218
+ .quad 0x89f87469a23920e0, 0x002523ecbab82fae, // 219
+ .quad 0x89ae4089ae4089ae, 0x0024fc09d0a2dace, // 220
+ .quad 0x89645c4f6e055dec, 0x0024d46704f0b9de, // 221
+ .quad 0x891ac73ae9819b50, 0x0024ad03ce7d0f24, // 222
+ .quad 0x88d180cd3a4133d7, 0x002485dfa59104dc, // 223
+ .quad 0x8888888888888889, 0x00245efa03df1c1d, // 224
+ .quad 0x883fddf00883fddf, 0x00243852647eaccb, // 225
+ .quad 0x87f78087f78087f8, 0x002411e843e77632, // 226
+ .quad 0x87af6fd5992d0d40, 0x0023ebbb1fed4014, // 227
+ .quad 0x8767ab5f34e47ef1, 0x0023c5ca77bb8be3, // 228
+ .quad 0x872032ac13008720, 0x0023a015cbd155d3, // 229
+ .quad 0x86d905447a34acc6, 0x00237a9c9dfce59b, // 230
+ .quad 0x869222b1acf1ce96, 0x0023555e7157ae8e, // 231
+ .quad 0x864b8a7de6d1d608, 0x0023305aca423ed8, // 232
+ .quad 0x86053c345a0b8473, 0x00230b912e603d96, // 233
+ .quad 0x85bf37612cee3c9b, 0x0022e70124947795, // 234
+ .quad 0x85797b917765ab89, 0x0022c2aa34fcfa72, // 235
+ .quad 0x8534085340853408, 0x00229e8be8ef3de8, // 236
+ .quad 0x84eedd357c1b0085, 0x00227aa5caf45b0a, // 237
+ .quad 0x84a9f9c8084a9f9d, 0x002256f766c5512f, // 238
+ .quad 0x84655d9bab2f1008, 0x002233804947585d, // 239
+ .quad 0x8421084210842108, 0x0022104000884100, // 240
+ .quad 0x83dcf94dc7570ce1, 0x0021ed361bbae0a0, // 241
+ .quad 0x839930523fbe3368, 0x0021ca622b338b7a, // 242
+ .quad 0x8355ace3c897db10, 0x0021a7c3c0649abe, // 243
+ .quad 0x83126e978d4fdf3b, 0x0021855a6ddaff33, // 244
+ .quad 0x82cf750393ac3319, 0x00216325c73ae026, // 245
+ .quad 0x828cbfbeb9a020a3, 0x00214125613c4656, // 246
+ .quad 0x824a4e60b3262bc5, 0x00211f58d1a7d2cb, // 247
+ .quad 0x8208208208208208, 0x0020fdbfaf538145, // 248
+ .quad 0x81c635bc123fdf8e, 0x0020dc59921f7638, // 249
+ .quad 0x81848da8faf0d277, 0x0020bb2612f2d806, // 250
+ .quad 0x814327e3b94f462f, 0x00209a24cbb8b365, // 251
+ .quad 0x8102040810204081, 0x00207955575ceaab, // 252
+ .quad 0x80c121b28bd1ba98, 0x002058b751c92feb, // 253
+ .quad 0x8080808080808081, 0x0020384a57e209a8, // 254
+ .quad 0x8040201008040201, 0x0020180e0783e1f9, // 255
+
+#endif // FASTDIV_TABLES
diff --git a/private/crt32/misc/alpha/ghandler.c b/private/crt32/misc/alpha/ghandler.c
new file mode 100644
index 000000000..712d15fe4
--- /dev/null
+++ b/private/crt32/misc/alpha/ghandler.c
@@ -0,0 +1,435 @@
+/*++
+
+Copyright (c) 1993 Digital Equipment Corporation
+
+Module Name:
+
+ ghandler.c
+
+Abstract:
+
+ This module implements the C specific exception handler that provides
+ structured exception handling for code generated by the GEM compiler.
+
+Author:
+
+ John Parks (parks) 12-Jan-1993
+ Thomas Van Baak (tvb) 28-Jan-1993
+
+Environment:
+
+ Any mode.
+
+Revision History:
+
+--*/
+
+#include "nt.h"
+
+//
+// Define procedure prototypes for exception filter and termination handler
+// execution routines defined in jmpunwnd.s.
+//
+
+LONG
+__C_ExecuteExceptionFilter (
+ PEXCEPTION_POINTERS ExceptionPointers,
+ EXCEPTION_FILTER ExceptionFilter,
+ ULONG EstablisherFrame
+ );
+
+ULONG
+__C_ExecuteTerminationHandler (
+ BOOLEAN AbnormalTermination,
+ TERMINATION_HANDLER TerminationHandler,
+ ULONG EstablisherFrame
+ );
+
+//
+// Define local procedure prototypes.
+//
+
+EXCEPTION_DISPOSITION
+_OtsCSpecificHandler (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PVOID EstablisherFrame,
+ IN OUT PCONTEXT ContextRecord,
+ IN OUT PDISPATCHER_CONTEXT DispatcherContext
+ );
+
+ULONG
+_OtsLocalFinallyUnwind (
+ IN PSEH_CONTEXT SehContext,
+ IN PSEH_BLOCK TargetSeb,
+ IN PVOID RealFramePointer
+ );
+
+//
+// Define local macros.
+//
+
+#define IS_EXCEPT(Seb) ((Seb)->JumpTarget != 0)
+#define IS_FINALLY(Seb) ((Seb)->JumpTarget == 0)
+
+//
+// Initialize an exception record for the unwind with the SEB of the target
+// included as one information parameter. This is done so that the target
+// frame of the unwind may execute all the finally handlers necessary given
+// the SEB pointer at the unwind target.
+//
+
+#define MODIFY_UNWIND_EXCEPTION_RECORD(ExceptionRecord, Seb) { \
+ ExceptionRecord->ExceptionCode = STATUS_UNWIND; \
+ ExceptionRecord->ExceptionFlags = EXCEPTION_UNWINDING; \
+ ExceptionRecord->ExceptionRecord = NULL; \
+ ExceptionRecord->ExceptionAddress = 0; \
+ ExceptionRecord->NumberParameters = 1; \
+ ExceptionRecord->ExceptionInformation[0] = (ULONG)(Seb); \
+ }
+
+EXCEPTION_DISPOSITION
+_OtsCSpecificHandler (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PVOID EstablisherFrame,
+ IN OUT PCONTEXT ContextRecord,
+ IN OUT PDISPATCHER_CONTEXT DispatcherContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function walks up the list of SEB's associated with the specified
+ procedure and calls except filters and finally handlers as necessary.
+
+ It is called in two different contexts:
+ (i) by the exception dispatcher after an exception is raised
+ (ii) by the unwinder during an unwind operation
+
+ In the first case, is searches the SEB list for except filters to evaluate.
+ In the second case, it searches for finally handlers to execute.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ EstablisherFrame - Supplies a (virtual frame) pointer to the frame of the
+ establisher function.
+
+ ContextRecord - Supplies a pointer to a context record.
+
+ DispatcherContext - Supplies a pointer to the exception dispatcher or
+ unwind dispatcher context.
+
+Return Value:
+
+ If the exception is handled by one of the exception filter routines, then
+ there is no return from this routine and RtlUnwind is called. Otherwise,
+ an exception disposition value of continue execution or continue search is
+ returned.
+
+Notes:
+ In context (i) there are 3 possibilities:
+
+ (a) If an exception filter returns a value greater that 0 (meaning
+ that the associated handler should be invoked) there is no
+ return from this function. RtlUnwind is called to unwind the
+ stack to the exception handler corresponding to that filter.
+
+ (b) If an exception filter returns a value less than 0 (meaning
+ that the exception should be dismissed), this routine returns
+ value ExceptionContinueExecution.
+
+ (c) If every filter returns value 0 (meaning that the search for a
+ handler should continue elsewhere), this function returns
+ ExceptionContinueSearch.
+
+ In context (ii) there are 2 possibilities:
+
+ (d) If no branches are detected out of finally handlers, this
+ function returns ExceptionContinueSearch.
+
+ (e) If a branch is detected out of a finally handler, there is no
+ return from this routine. RtlUnwind is called to unwind to the
+ branch target (and cancel the current unwind).
+
+ There may be long jumps out of both except filters and finally handlers
+ in which case this routine will be peeled off the stack without returning.
+
+--*/
+
+{
+
+ ULONG ContinuationAddress;
+ EXCEPTION_FILTER ExceptionFilter;
+ PVOID ExceptionHandler;
+ EXCEPTION_POINTERS ExceptionPointers;
+ LONG FilterValue;
+ ULONG RealFramePointer;
+ PSEH_BLOCK Seb;
+ PSEH_CONTEXT SehContext;
+ PSEH_BLOCK TargetSeb;
+ TERMINATION_HANDLER TerminationHandler;
+
+ //
+ // Get the address of the SEH context which is at some negative offset
+ // from the virtual frame pointer. For GEM, the handler data field of
+ // the function entry contains that offset. The current SEB pointer and
+ // the RFP (static link) are obtained from the SEH context.
+ //
+
+ SehContext = (PSEH_CONTEXT)((ULONG)EstablisherFrame +
+ (LONG)DispatcherContext->FunctionEntry->HandlerData);
+ RealFramePointer = SehContext->RealFramePointer;
+
+ //
+ // If this is a dispatching context, walk up the list of SEBs evaluating
+ // except filters.
+ //
+
+ if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) {
+
+ //
+ // Set up the ExceptionPointers structure that is used by except
+ // filters to obtain data for the GetExceptionInformation intrinsic
+ // function. Copy the current SEB pointer into a local variable
+ // because the real SEB pointer is only modified in unwind contexts.
+ //
+
+ ExceptionPointers.ExceptionRecord = ExceptionRecord;
+ ExceptionPointers.ContextRecord = ContextRecord;
+
+ for (Seb = SehContext->CurrentSeb; Seb != NULL; Seb = Seb->ParentSeb) {
+ if (IS_EXCEPT(Seb)) {
+
+ //
+ // This is an except filter. Get the addresses of the filter
+ // and exception handler from the SEB, then call the except
+ // filter.
+ //
+
+ ExceptionFilter = (EXCEPTION_FILTER)Seb->HandlerAddress;
+ ExceptionHandler = (PVOID)Seb->JumpTarget;
+
+ FilterValue = __C_ExecuteExceptionFilter(&ExceptionPointers,
+ ExceptionFilter,
+ RealFramePointer);
+
+ //
+ // If the except filter < 0, dismiss the exception. If > 0,
+ // store the exception code on the stack for the except
+ // handler, modify the given ExceptionRecord so that finally
+ // handlers will be called properly during the unwind, then
+ // unwind down to the except handler. If = 0, resume the
+ // search for except filters.
+ //
+
+ if (FilterValue < 0) {
+ return ExceptionContinueExecution;
+
+ } else if (FilterValue > 0) {
+ SehContext->ExceptionCode = ExceptionRecord->ExceptionCode;
+ MODIFY_UNWIND_EXCEPTION_RECORD(ExceptionRecord,
+ Seb->ParentSeb);
+ RtlUnwind(EstablisherFrame,
+ ExceptionHandler,
+ ExceptionRecord,
+ 0);
+ }
+ }
+ }
+
+ } else if (!IS_TARGET_UNWIND(ExceptionRecord->ExceptionFlags)) {
+
+ //
+ // This is an unwind but is not the target frame. Since the function
+ // is being terminated, finally handlers for all try bodies that are
+ // presently in scope must be executed. Walk up the SEB list all the
+ // way to the top executing finally handlers. This corresponds to
+ // exiting all try bodies that are presently in scope.
+ //
+
+ while (SehContext->CurrentSeb != NULL) {
+
+ //
+ // Get the address of the SEB and then update the SEH context.
+ //
+
+ Seb = SehContext->CurrentSeb;
+ SehContext->CurrentSeb = Seb->ParentSeb;
+
+ if (IS_FINALLY(Seb)) {
+
+ //
+ // This is a finally handler. Get the address of the handler
+ // from the SEB and call the finally handler.
+ //
+
+ TerminationHandler = (TERMINATION_HANDLER)Seb->HandlerAddress;
+ ContinuationAddress =
+ __C_ExecuteTerminationHandler(TRUE,
+ TerminationHandler,
+ RealFramePointer);
+
+ //
+ // If the finally handler returns a non-zero result, there
+ // was a branch out of the handler (to that address) and this
+ // routine should unwind to that target.
+ //
+
+ if (ContinuationAddress != 0) {
+ MODIFY_UNWIND_EXCEPTION_RECORD(ExceptionRecord,
+ SehContext->CurrentSeb);
+ RtlUnwind(EstablisherFrame,
+ (PVOID)ContinuationAddress,
+ ExceptionRecord,
+ 0);
+ }
+ }
+ }
+
+ } else {
+
+ //
+ // This is the target frame of an unwind. Since the target may be
+ // in a different try scope than the one defined by the current SEB
+ // pointer, finally handlers between the two scopes must execute.
+ // Walk up the SEB list from the current SEB to the target SEB and
+ // execute all finally handlers encountered.
+ //
+
+ TargetSeb = (PSEH_BLOCK)ExceptionRecord->ExceptionInformation[0];
+ ContinuationAddress = _OtsLocalFinallyUnwind(SehContext,
+ TargetSeb,
+ (PVOID)RealFramePointer);
+ if (ContinuationAddress != 0) {
+
+ //
+ // A non-zero result indicates there was a branch out of a
+ // finally handler that was being executed during the unwind.
+ // This routine should unwind to that address.
+ //
+
+ MODIFY_UNWIND_EXCEPTION_RECORD(ExceptionRecord,
+ SehContext->CurrentSeb);
+ RtlUnwind(EstablisherFrame,
+ (PVOID)ContinuationAddress,
+ ExceptionRecord,
+ 0);
+ }
+ }
+
+ //
+ // Continue search for exception or termination handlers.
+ //
+
+ return ExceptionContinueSearch;
+}
+
+ULONG
+_OtsLocalFinallyUnwind (
+ IN PSEH_CONTEXT SehContext,
+ IN PSEH_BLOCK TargetSeb,
+ IN PVOID RealFramePointer
+ )
+
+/*++
+
+Routine Description:
+
+ This function walks up the SEB tree of the current procedure from the
+ current SEB to the target SEB and executes all the finally handlers it
+ encounters.
+
+ Calls to this function are inserted into user code by the compiler when
+ there are branches out of guarded regions that may require finally
+ handlers to execute.
+
+ This function is also called from _OtsCSpecificHandler when the target
+ frame is reached during an unwind operation. There may be finally handlers
+ that should execute before resuming execution at the unwind target.
+
+Arguments:
+
+ SehContext - Supplies the address of the SEH context structure which is
+ located in the stack frame.
+
+ TargetSeb - Supplies the address of the SEB corresponding to the branch
+ target address.
+
+ RealFramePointer - Supplies the (real frame) pointer of the establisher
+ frame, which is the current stack frame. This is used to set up the
+ static link if a finally handler is invoked.
+
+Return Value:
+
+ If a branch out of a finally handler is detected, the function value is
+ the address of the branch target. Otherwise, the function value is zero.
+
+--*/
+
+{
+
+ ULONG ContinuationAddress;
+ BOOLEAN Nested;
+ PSEH_BLOCK Seb;
+ TERMINATION_HANDLER TerminationHandler;
+
+ //
+ // If the SEB pointers are the same, no finally handlers need to execute.
+ // The branch is to a target location in the same guarded scope.
+ //
+
+ if (SehContext->CurrentSeb == TargetSeb) {
+ return 0;
+ }
+
+ //
+ // If the current SEB scope is not nested within the target SEB scope, no
+ // finally handlers need to execute. Reset the current SEB pointer to the
+ // target SEB pointer and return.
+ //
+
+ Nested = FALSE;
+ Seb = SehContext->CurrentSeb;
+
+ while (Seb != NULL) {
+ Seb = Seb->ParentSeb;
+ if (Seb == TargetSeb) {
+ Nested = TRUE;
+ break;
+ }
+ }
+ if (Nested == FALSE) {
+ SehContext->CurrentSeb = TargetSeb;
+ return 0;
+ }
+
+ //
+ // Walk up the list of SEB blocks executing finally handlers. If a branch
+ // out of a finally is encountered along the way, return the target
+ // address, otherwise return 0.
+ //
+
+ while (SehContext->CurrentSeb != TargetSeb) {
+
+ //
+ // Get the address of the SEB and then update the SEH context.
+ //
+
+ Seb = SehContext->CurrentSeb;
+ SehContext->CurrentSeb = Seb->ParentSeb;
+
+ if (IS_FINALLY(Seb)) {
+ TerminationHandler = (TERMINATION_HANDLER)Seb->HandlerAddress;
+ ContinuationAddress =
+ __C_ExecuteTerminationHandler(TRUE,
+ TerminationHandler,
+ (ULONG)RealFramePointer);
+ if (ContinuationAddress != 0) {
+ return ContinuationAddress;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/private/crt32/misc/alpha/insv.s b/private/crt32/misc/alpha/insv.s
new file mode 100644
index 000000000..7d0956103
--- /dev/null
+++ b/private/crt32/misc/alpha/insv.s
@@ -0,0 +1,158 @@
+ #+
+ # Copyright 1991, 1994 Digital Equipment Corporation
+ #
+ # int ots_insv(char *addr, int position, unsigned size, int value)
+ #
+ # Arbitrary bitfield insertion, longword granularity
+ #
+ # Special conventions: No stack space, r0-r1, r16-r19 and r26-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # See also: ots_ext[z]v
+ #
+ # 001 5 Sep 1991 KDG Initial version
+ #
+ # 002 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 003 22 Sep 1992 KDG Add case-sensitive name
+ #
+ # 004 26 Jan 1993 KDG Add underscore
+ #
+ # 005 19 Apr 1994 kdg Longword granularity version based on quadword
+ # granularity version 004
+
+#include "ots_defs.hs"
+
+ # Totally general field insertion - arbitrary run-time field of 0-64 bits
+ # at an unknown alignment target. Longword granularity.
+ #
+ # Conceptually, this operation takes a 67 bit bit-address, which is the sum
+ # of a byte-aligned memory address and the bit offset (which is signed).
+ #
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|Q|L|W|B|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|b|b|b|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ #
+ # Inputs:
+ # r16 - input address
+ # r17 - input bit offset
+ # r18 - input size
+ # r19 - input value
+ #
+ # This is based on the original insert routine modified for longword
+ # granularity. This routine could probably be improved. (It does
+ # a "reasonable" job, but hasn't had as much attention as the quadword
+ # granularity version. Fields contained in a single longword are
+ # roughly the same cost as the quadword granularity version. Fields
+ # contained in two longwords in the same quadword are somewhat slower,
+ # while the two longword spanning a quadword case is roughly comparable.
+ # The 3 longword case is relatively slow [2 mispredicted branches,
+ # on unnecessary safe speculative load, could potentially use better
+ # scheduling too.])
+ #
+ .globl _OtsFieldInsert
+ .ent _OtsFieldInsert
+_OtsFieldInsert:
+ .set noat
+ .set noreorder
+ ble r18, noacc # check for zero size - no memory access
+ sra r17, 3, r27 # get byte part of bit offset (signed!)
+ addq r16, r27, r16 # add to initial base addr.
+ and r17, 7, r17 # get bit-in-byte from bit offset
+ and r16, 3, r27 # get byte-in-longword (must be clean for compares)
+ bic r16, 3, r16 # get a longword aligned address
+ s8addq r27, r17, r17 # form the true bit offset in the longword
+ ldl r28, (r16) # load first or only longword
+ addq r17, r18, r27 # get bit offset of bit following field
+ subq r27, 32, r0 # if <=32, field is contained in 1 longword
+ bgt r0, multiple # handle multi-longword case if not
+ # Common case of field in single LW - fall through
+ negq r27, r27 # <5:0> = bits for right shift
+ negq r18, r0 # bits for left shift (wordlength-is)
+ not r31, r1 # all ones
+ sll r1, r0, r1 # shift mask to high bits
+ sll r19, r0, r19 # shift source to high bits (hand interleaving for better sched)
+ srl r1, r27, r1 # and into position
+ srl r19, r27, r19 # and into position
+ bic r28, r1, r28 # clear the bits...
+ bis r28, r19, r28 # insert them
+ stl r28, (r16) # put the value back...
+noacc: ret r31, (r26)
+
+ # At this point:
+ # Field is known to be contained in at least 2 longwords
+ # r0 is bit position past end of field, -32
+ # r1 junk
+ # r16 is longword aligned
+ # r17 is bit offset in longword
+ # r18 is field size
+ # r19 is value to store
+ # r27 is bit position past end of field
+ # r28 first lw from memory
+ #
+multiple:
+ subq r0, 32, r27 # if <=64, the field is contained in 2 longwords
+ ldl r1, 4(r16) # load the 2nd longword (safe)
+ bgt r27, three # handle 3 longword case (rare...)
+ not r31, r27 # all ones
+ sll r27, r17, r27 # get mask in correct place
+ sll r19, r17, r17 # get insert value to top of register
+ bic r28, r27, r28 # clear bits in target
+ bis r28, r17, r28 # merge the field in
+ srl r1, r0, r1 # clear bits in target
+ negq r18, r27 #
+ sll r19, r27, r19 # shift to high bits
+ negq r0, r27 #
+ srl r19, r27, r19 # and into position
+ sll r1, r0, r1 #
+ stl r28, (r16) # store the first longword
+ bis r1, r19, r1 # merge
+ stl r1, 4(r16) # store back the second longword
+ ret r31, (r26)
+
+ # At this point:
+ # Field is known to be contained in exactly 3 longwords
+ # r0 is bit position past end of field, -32
+ # r1 value loaded for 2nd longword (which will be totally overwritten - i.e. junk)
+ # r16 is longword aligned
+ # r17 is bit offset in longword
+ # r18 is field size
+ # r19 is value to store
+ # r27 is bit position past end of field -64
+ # r28 first lw from memory
+ #
+ # Three word case is roughly similar to two word case, except
+ # the middle store isn't a merge, just a real store, and the offsets
+ # for the 3rd word need to be adjusted. (This case hasn't
+ # received much attention and could probably be improved by
+ # at least a few instructions...)
+ #
+three:
+ not r31, r0 # all ones
+ sll r0, r17, r0 # get mask in correct place
+ sll r19, r17, r1 # get insert value to top of register
+ bic r28, r0, r28 # clear bits in target
+ bis r28, r1, r28 # merge the field in
+ ldl r1, 8(r16) # load the 3rd longword
+ lda r0, 32(r31) # load 32
+ stl r28, (r16) # store the first longword
+ subq r0, r17, r0 # shift amount
+ srl r19, r0, r28 # discard bits already stored
+ negq r18, r0 #
+ srl r1, r27, r1 # clear bits in target
+ sll r19, r0, r19 # shift to high bits
+ negq r27, r0 #
+ srl r19, r0, r19 # and into position
+ sll r1, r27, r1 #
+ stl r28, 4(r16) # store second complete longword
+ bis r1, r19, r1 # merge
+ stl r1, 8(r16) # store back the third longword
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsFieldInsert
diff --git a/private/crt32/misc/alpha/insvvol.s b/private/crt32/misc/alpha/insvvol.s
new file mode 100644
index 000000000..11c0c3eed
--- /dev/null
+++ b/private/crt32/misc/alpha/insvvol.s
@@ -0,0 +1,137 @@
+ #+
+ # Copyright 1991, Digital Equipment Corporation
+ #
+ # int ots_insv_vol(char *addr, int position, unsigned size, int value)
+ #
+ # Arbitrary signed bitfield extraction for volatile cases
+ #
+ # Special conventions: No stack space, r0-r1, r16-r19 and r26-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # See also: ots_ext[z]v
+ #
+ # 001 5 Sep 1991 KDG Initial version
+ #
+ # 002 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 003 5 Oct 1992 KDG Initial volatile version based on non-volatile
+ # version
+ #
+ # 004 10 Nov 1992 KDG Case-sensitive name
+ #
+ # 005 26 Jan 1993 KDG Add underscore
+ #
+ # 006 1 Sep 1994 RBG Fix aligned longword and quadword cases,
+ # check for bit 0 within byte GEM_BUGS #3545
+
+#include "ots_defs.hs"
+
+ # Totally general field insertion - arbitrary run-time field of 0-64 bits
+ # at an unknown alignment target.
+ #
+ # Volatile/byte granularity version notes:
+ #
+ # - Aligned quadword stores must be done using exactly STQ
+ #
+ # - Aligned longword stores must be done using exactly STL
+ #
+ # - All other stores must be done using LDx_L/STx_C to avoid
+ # corrupting any adjacent data and provide atomic updates
+ # for aligned data
+ #
+ # The first two items are required in case this routine is called for
+ # volatile references so that I/O space accesses are handled correctly.
+ # (Normally, those references are handled in-line, but if for some
+ # reason they wind up coming through here, they must still be correct.)
+ #
+ # Conceptually, this operation takes a 67 bit bit-address, which is the sum
+ # of a byte-aligned memory address and the bit offset (which is signed).
+ #
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|Q|L|W|B|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|b|b|b|
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ #
+ # Inputs:
+ # r16 - input address
+ # r17 - input bit offset
+ # r18 - input size
+ # r19 - input value
+ #
+ # This is based on the code GEM generates when not using an out-of-line
+ # routine, though it has better by-hand register packing to allow
+ # multiple issue.
+ #
+ .globl _OtsFieldInsertVolatile
+ .ent _OtsFieldInsertVolatile
+_OtsFieldInsertVolatile:
+ .set noat
+ .set noreorder
+ sra r17, 3, r27 # get byte part of bit offset (signed!)
+ ble r18, noacc # check for zero size - no memory access
+ cmpeq r18, 32, r28 # Aligned longword(1) - is the size exactly 32b?
+ addq r16, r27, r16 # add to initial base addr.
+ and r16, 3, r27 # check for special case of an aligned longword
+ cmpult r27, r28, r28 # Aligned longword(2) - byte 0 within longword
+ and r17, 7, r17 # get bit-in-byte from bit offset
+ cmpult r17, r28, r28 # Aligned longword(3) - bit 0 within byte
+ cmpeq r18, 64, r0 # Aligned quadword(1) - is the size exactly 64b?
+ and r16, 7, r27 # get byte-in-quadword (must be clean for cmpule)
+ bne r28, longwd # if aligned longword, store exactly a longword using stl
+ cmpult r27, r0, r0 # Aligned quadword(2) - byte 0 within quadword
+ cmpult r17, r0, r0 # Aligned quadword(3) - bit 0 within byte
+ s8addq r27, r17, r17 # form the true bit offset in the quadword
+ bne r0, quadwd # if aligned quadword, store exactly a quadword using stq
+ addq r17, r18, r27 # get bit offset of bit following field
+ cmpule r27, 64, r0 # if <=64, field is contained in 1 quadword
+ bic r16, 7, r16 # clear unaligned bits in address for locked operations
+ not r31, r1 # all ones
+ beq r0, double # handle double case if not
+ # Common case of field in single QW - fall through
+ negq r27, r27 # <5:0> = bits for right shift
+ addq r27, r17, r0 # bits for left shift (wordlength-is)
+ sll r1, r0, r1 # shift mask to high bits
+ sll r19, r0, r19 # shift source to high bits (hand interleaving for better sched)
+ srl r1, r27, r1 # and into position
+ srl r19, r27, r19 # and into position
+sinrty: ldq_l r28, (r16) # load first or only quadword
+ bic r28, r1, r28 # clear the bits...
+ bis r28, r19, r28 # insert them
+ stq_c r28, (r16) # put the value back...
+ blbc r28, sinfl # check for failing interlock/retry
+noacc: ret r31, (r26)
+
+double:
+ sll r1, r17, r0 # get mask in correct place
+ sll r19, r17, r17 # get insert value to top of register
+ negq r18, r1 #
+ sll r19, r1, r19 # shift to high bits
+ negq r27, r1 #
+ srl r19, r1, r19 # and into position
+firrty: ldq_l r28, (r16) # load first or only quadword
+ bic r28, r0, r28 # clear bits in target
+ bis r28, r17, r28 # merge the field in
+ stq_c r28, (r16) # store the first word
+ blbc r28, firfl # check for failing interlock/retry
+secrty: ldq_l r28, 8(r16) # load the 2nd quadword
+ srl r28, r27, r28 # clear bits in target
+ sll r28, r27, r28 #
+ bis r28, r19, r28 # merge
+ stq_c r28, 8(r16) # store back
+ blbc r28, secfl # check for failing interlock/retry
+ ret r31, (r26)
+longwd: stl r19, (r16) # store aligned longword
+ ret r31, (r26)
+quadwd: stq r19, (r16) # store aligned quadword
+ ret r31, (r26)
+ # out-of-line retry cases
+sinfl: br r31, sinrty # re-try the locked operation for the single case
+firfl: br r31, firrty # re-try the locked operation for the 1st part of the two-part case
+secfl: br r31, secrty # re-try the locked operation for the 2nd part of the two-part case
+
+ .set at
+ .set reorder
+ .end _OtsFieldInsertVolatile
diff --git a/private/crt32/misc/alpha/jmpuwind.s b/private/crt32/misc/alpha/jmpuwind.s
new file mode 100644
index 000000000..934b9d549
--- /dev/null
+++ b/private/crt32/misc/alpha/jmpuwind.s
@@ -0,0 +1,167 @@
+// TITLE("Handler Stubs and Jump to Unwind")
+//++
+//
+// Copyright (c) 1992 Microsoft Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// jmpuwind.s
+//
+// Abstract:
+//
+// This module implements the Alpha acc compiler specific routines to call
+// exception handlers and to jump to the runtime library unwind routines.
+//
+// Author:
+//
+// David N. Cutler (davec) 12-Sep-1990
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Thomas Van Baak (tvb) 30-Apr-1992
+//
+// Adapted for Alpha AXP.
+//
+//--
+
+#include "ksalpha.h"
+
+ SBTTL("Execute Exception Filter")
+//++
+//
+// ULONG
+// __C_ExecuteExceptionFilter (
+// PEXCEPTION_POINTERS ExceptionPointers,
+// EXCEPTION_FILTER ExceptionFilter,
+// ULONG EstablisherFrame
+// )
+//
+// Routine Description:
+//
+// This function sets the static link and transfers control to the specified
+// exception filter routine.
+//
+// Arguments:
+//
+// ExceptionPointers (a0) - Supplies a pointer to the exception pointers
+// structure.
+//
+// ExceptionFilter (a1) - Supplies the address of the exception filter
+// routine.
+//
+// EstablisherFrame (a2) - Supplies the establisher frame pointer.
+//
+// Return Value:
+//
+// The value returned by the exception filter routine.
+//
+//--
+
+ LEAF_ENTRY(__C_ExecuteExceptionFilter)
+
+//
+// The protocol for calling exception filters used by the acc compiler is
+// that the uplevel frame pointer is passed in register v0 and the pointer
+// to the exception pointers structure is passed in register a0. The GEM
+// C compiler expects the static link in t0. Here both registers are set.
+//
+
+ mov a2, v0 // set static link
+ mov a2, t0 // set alternate static link
+ jmp zero, (a1) // transfer control to exception filter
+
+ .end __C_ExecuteExceptionFilter
+
+ SBTTL("Execute Termination Handler")
+//++
+//
+// ULONG
+// __C_ExecuteTerminationHandler (
+// BOOLEAN AbnormalTermination,
+// TERMINATION_HANDLER TerminationHandler,
+// ULONG EstablisherFrame
+// )
+//
+// Routine Description:
+//
+// This function sets the static link and transfers control to the specified
+// termination handler routine.
+//
+// Arguments:
+//
+// AbnormalTermination (a0) - Supplies a boolean value that determines
+// whether the termination is abnormal.
+//
+// TerminationHandler (a1) - Supplies the address of the termination handler
+// routine.
+//
+// EstablisherFrame (a2) - Supplies the establisher frame pointer.
+//
+// Return Value:
+//
+// The value returned by the termination handler routine, if any.
+//
+//--
+
+ LEAF_ENTRY(__C_ExecuteTerminationHandler)
+
+//
+// The protocol for calling termination handlers used by the acc compiler
+// is that the uplevel frame pointer is passed in register v0 and the boolean
+// abnormal termination value is passed in register a0. The GEM C compiler
+// expects the static link in t0. Here both registers are set.
+//
+
+ mov a2, v0 // set static link
+ mov a2, t0 // set alternate static link
+ jmp zero, (a1) // transfer control to termination handler
+
+ .end __C_ExecuteTerminationHandler
+
+ SBTTL("Jump to Unwind")
+//++
+//
+// VOID
+// __jump_unwind (
+// IN PVOID EstablishFrame,
+// IN PVOID TargetPc
+// )
+//
+// Routine Description:
+//
+// This function transfers control to unwind. It is used by the acc
+// compiler when a goto out of the body of a try statement occurs.
+//
+// Arguments:
+//
+// EstablishFrame (a0) - Supplies the establisher frame pointer of the
+// target of the unwind.
+//
+// TargetPc (a1) - Supplies the target instruction address where control
+// is to be transferred to after the unwind operation is complete.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(__jump_unwind)
+
+//
+// The first two arguments are the same as those required by unwind. Set the
+// second two arguments and jump to unwind. This thunk is necessary to avoid
+// name space pollution. The compiler should not generate a call directly to
+// RtlUnwind.
+//
+
+ mov zero, a2 // set NULL exception record address
+ mov zero, a3 // set target return value of 0
+ br zero, RtlUnwind // unwind to specified target
+
+ .end __jump_unwind
diff --git a/private/crt32/misc/alpha/longjmp.s b/private/crt32/misc/alpha/longjmp.s
new file mode 100644
index 000000000..412e3e655
--- /dev/null
+++ b/private/crt32/misc/alpha/longjmp.s
@@ -0,0 +1,192 @@
+// TITLE("Long Jump")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// longjmp.s
+//
+// Abstract:
+//
+// This module implements the Alpha specific routine to perform a long
+// jump operation. Three jump buffer types are supported: unsafe, safe
+// acc-style (virtual frame pointer, PC mapped SEH scope), and safe
+// GEM-style (real frame pointer, SEB-based SEH context).
+//
+// N.B. This routine conditionally provides UNSAFE handling of longjmp
+// which is NOT integrated with structured exception handling. The
+// determination is made based on whether an unitialized variable
+// has been set to a nonzero value.
+//
+// Author:
+//
+// David N. Cutler (davec) 2-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Thomas Van Baak (tvb) 22-Apr-1993
+//
+// Adapted for Alpha AXP.
+//
+//--
+
+#include "ksalpha.h"
+
+//
+// Define jump buffer types.
+//
+// _JMPBUF_TYPE_ZERO was used for Beta2 which functions the same as
+// _JMPBUF_TYPE_ACC.
+//
+// _JMPBUF_TYPE_FAST is for jump buffers containing the set of
+// non-volatile integer and floating registers. This form
+// of setjmp/longjmp is not compatible with SEH.
+//
+// _JMPBUF_TYPE_ACC is for setjmp/longjmp compatible with SEH.
+// The Alpha acc compiler uses a virtual frame pointer.
+//
+// _JMPBUF_TYPE_GEM is for setjmp/longjmp compatible with SEH.
+// The Alpha GEM C compiler uses a real frame pointer, and
+// SEH scope is maintained with a SEB pointer.
+//
+
+#define _JMPBUF_TYPE_ZERO 0
+#define _JMPBUF_TYPE_FAST 1
+#define _JMPBUF_TYPE_ACC 2
+#define _JMPBUF_TYPE_GEM 3
+
+ SBTTL("Long Jump")
+//++
+//
+// int
+// longjmp (
+// IN jmp_buf JumpBuffer,
+// IN int ReturnValue
+// )
+//
+// Routine Description:
+//
+// This function performs a long jump to the context specified by the
+// jump buffer.
+//
+// Arguments:
+//
+// JumpBuffer (a0) - Supplies the address of a jump buffer that contains
+// jump information.
+//
+// ReturnValue (a1) - Supplies the value that is to be returned to the
+// caller of set jump.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(longjmp)
+
+ ldil t0, 1 // force nonzero value, if
+ cmoveq a1, t0, a1 // given return value is zero
+
+ ldl t1, JbType(a0) // get setjmp context type flag
+ subq t1, 1, t2 // if eq 1, fast, unsafe longjmp
+ bne t2, 10f // otherwise, provide safe longjmp
+
+//
+// Type 0x1: Provide unsafe handling of longjmp.
+//
+
+ mov a1, v0 // set return value
+
+ ldt f2, JbFltF2(a0) // restore floating registers f2 - f9
+ ldt f3, JbFltF3(a0) //
+ ldt f4, JbFltF4(a0) //
+ ldt f5, JbFltF5(a0) //
+ ldt f6, JbFltF6(a0) //
+ ldt f7, JbFltF7(a0) //
+ ldt f8, JbFltF8(a0) //
+ ldt f9, JbFltF9(a0) //
+
+ ldq s0, JbIntS0(a0) // restore integer registers s0 - s6/fp
+ ldq s1, JbIntS1(a0) //
+ ldq s2, JbIntS2(a0) //
+ ldq s3, JbIntS3(a0) //
+ ldq s4, JbIntS4(a0) //
+ ldq s5, JbIntS5(a0) //
+ ldq fp, JbIntS6(a0) //
+
+ ldq a1, JbFir(a0) // get setjmp return address
+ ldq sp, JbIntSp(a0) // restore stack pointer
+ jmp zero, (a1) // jump back to setjmp site
+
+//
+// Type 0x0: Provide safe handling of longjmp (idw 404 style).
+// Type 0x2: Provide safe handling of longjmp (acc style).
+//
+
+10: bic t1, 0x2, t2 // if 0 or 2, safe acc longjmp
+ bne t2, longjmpRfp // if not, safe GEM longjmp
+
+ mov a1, a3 // set return value
+ mov zero, a2 // set exception record addres
+ ldl a1, JbPc(a0) // set target instruction address
+ ldl a0, JbFp(a0) // set target virtual frame pointer
+ br zero, RtlUnwind // finish in common code
+
+ .end longjmp
+
+ SBTTL("Long Jump - GEM")
+
+ .struct 0
+LjRa: .space 8 // saved return address
+ .space 8 // padding for 16-byte stack alignment
+LjEr: .space ExceptionRecordLength // local exception record
+LongjmpFrameLength:
+
+//
+// Type 0x3: Provide safe handling of longjmp (GEM style).
+//
+
+ NESTED_ENTRY(longjmpRfp, LongjmpFrameLength, ra)
+
+ lda sp, -LongjmpFrameLength(sp) // allocate stack frame
+ stq ra, LjRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Set up the following local exception record:
+//
+// ExceptionRecord.ExceptionCode = STATUS_UNWIND;
+// ExceptionRecord.ExceptionFlags = EXCEPTION_UNWINDING;
+// ExceptionRecord.ExceptionRecord = NULL;
+// ExceptionRecord.ExceptionAddress = 0;
+// ExceptionRecord.NumberParameters = 1;
+// ExceptionRecord.ExceptionInformation[0] = Seb;
+//
+
+10: mov a1, a3 // set return value
+ lda a2, LjEr(sp) // set exception record address
+
+ ldil t0, STATUS_UNWIND // get status code
+ stl t0, ErExceptionCode(a2) // store in exception record
+ ldil t1, EXCEPTION_UNWINDING // get exception flags
+ stl t1, ErExceptionFlags(a2) // store in exception record
+ stl zero, ErExceptionRecord(a2) // store in exception record
+ stl zero, ErExceptionAddress(a2) // store in exception record
+ ldil t2, 1 // get number of parameters
+ stl t2, ErNumberParameters(a2) // store in exception record
+ ldl t3, JbSeb(a0) // get SEB pointer
+ stl t3, ErExceptionInformation(a2) // store in exception record
+ ldl a1, JbPc(a0) // set target instruction address
+ ldl a0, JbFp(a0) // set target real frame pointer
+
+ bsr ra, RtlUnwindRfp // finish in common code
+
+ .end longjmpRfp
diff --git a/private/crt32/misc/alpha/ots_as.hs b/private/crt32/misc/alpha/ots_as.hs
new file mode 100644
index 000000000..127fe6382
--- /dev/null
+++ b/private/crt32/misc/alpha/ots_as.hs
@@ -0,0 +1,38 @@
+/* Definitions common to all systems using the "as" assembler (OSF,WNT) */
+/* Define mov to be bis from $31 so it can take a literal... */
+#define mov bis $31,
+#define not ornot $31,
+/* Define register aliases */
+#define r0 $0
+#define r1 $1
+#define r2 $2
+#define r3 $3
+#define r4 $4
+#define r5 $5
+#define r6 $6
+#define r7 $7
+#define r8 $8
+#define r9 $9
+#define r10 $10
+#define r11 $11
+#define r12 $12
+#define r13 $13
+#define r14 $14
+#define r15 $15
+#define r16 $16
+#define r17 $17
+#define r18 $18
+#define r19 $19
+#define r20 $20
+#define r21 $21
+#define r22 $22
+#define r23 $23
+#define r24 $24
+#define r25 $25
+#define r26 $26
+#define r27 $27
+#define r28 $28
+#define r29 $29
+#define sp $sp
+#define gp $gp
+#define r31 $31
diff --git a/private/crt32/misc/alpha/ots_defs.hs b/private/crt32/misc/alpha/ots_defs.hs
new file mode 100644
index 000000000..d3a62a478
--- /dev/null
+++ b/private/crt32/misc/alpha/ots_defs.hs
@@ -0,0 +1,3 @@
+/* OSF-specific definitions */
+#define WNT 1
+#include "ots_as.hs"
diff --git a/private/crt32/misc/alpha/otsdiv.s b/private/crt32/misc/alpha/otsdiv.s
new file mode 100644
index 000000000..cafb9b87e
--- /dev/null
+++ b/private/crt32/misc/alpha/otsdiv.s
@@ -0,0 +1,1178 @@
+
+ # Copyright 1992, Digital Equipment Corporation
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+ # 008 17 Jun 1992 KDG/wbn Most of initial tailored version. (See
+ # commentary below.)
+ #
+ # 009 4 Jul 1992 KDG Continue work on initial tailored version,
+ # including bugfixes and mod entry points
+ #
+ # 010 15 Jul 1992 KDG - Final touches for V1 (other than any bugfixes)
+ # - .aligns commented out to allow older assembler versions
+ #
+ # 011 16 Jul 1992 KDG - Bugfix for ots_div_l for -maxint dividend
+ # - OSF-only source changes for BL7
+ #
+ # 012 10 Aug 1992 KDG Fix overflow division entry points
+ #
+ # 013 23 Sep 1992 KDG Add case-sensitive entry names
+ #
+ # 014 4 Jan 1993 KDG Tweak for OSF assembler
+ #
+ # 015 26 Jan 1993 KDG Add underscore prefix, OSF uses CS names
+ #
+ # 016 5 Apr 1993 WBN Speed up core 64-bit, shrink table entry to 2 QWs
+
+ #++
+ # Entry points defined in this module:
+ #
+ # -- 32 bit division/remainder support
+ # unsigned ots_rem_ui(unsigned dividend, unsigned divisor)
+ # unsigned ots_div_ui(unsigned dividend, unsigned divisor)
+ # int ots_mod_i(int dividend, int modulus)
+ # int ots_rem_i(int dividend, int divisor)
+ # int ots_div_i_o(int dividend, int divisor)
+ # int ots_div_i(int dividend, int divisor) | "hot spot"
+ # {core routine - div32} |
+ #
+ # -- 64 bit division support
+ # {core routine - div64} | (uses div32 for 32b cases)
+ # long ots_div_l_o(long dividend, long divisor)
+ # long ots_div_l(long dividend, long divisor) | "hot spot"
+ # long ots_rem_l(long dividend, long divisor)
+ # long ots_mod_l(long dividend, long modulus)
+ # unsigned long ots_div_ul(unsigned long dividend, unsigned long divisor)
+ # unsigned long ots_rem_ul(unsigned long dividend, unsigned long divisor)
+ #
+ # Special conventions: No stack space, r0-r1, r16-r19 and r26-r28 ONLY.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # NOTE: This set of routines may start using stack space at some
+ # future point in time.
+ #
+ # -- Possible future entry points include:
+ # (These all return results in r0/r1)
+ # {int quotient, int remainder} ots_div_mod_i(int dividend, int divisor)
+ # {int quotient, int remainder} ots_div_mod_i_o(int dividend, int divisor)
+ # {int quotient, int remainder} ots_div_rem_i(int dividend, int divisor)
+ # {int quotient, int remainder} ots_div_rem_i_o(int dividend, int divisor)
+ # {unsigned quotient, unsigned remainder} ots_div_rem_ui(unsigned dividend, unsigned divisor)
+ #
+ # {long quotient, long remainder} ots_div_mod_i(long dividend, long divisor)
+ # {long quotient, long remainder} ots_div_mod_i_o(long dividend, long divisor)
+ # {long quotient, long remainder} ots_div_rem_i(long dividend, long divisor)
+ # {long quotient, long remainder} ots_div_rem_i_o(long dividend, long divisor)
+ # {unsigned long quotient, unsigned long remainder}
+ # ots_div_rem_ui(unsigned long dividend, unsigned long divisor)
+ #
+ #
+ # General commentary:
+ #
+ # This is an attempt at a fairly high performance version using relatively
+ # straightforward algorithms. Note that the code is intended to be scheduled
+ # well for EV4, but still reasonably for LCA/EV5.
+ #
+ # Also, note that there was only so much time available for this, so it
+ # is far from "perfect". "Better is the enemy of done"...
+ #
+ # Possible future areas of improvement (and unfinished business):
+ #
+ # - Another possible way of doing things for the "slow" (divnn cases)
+ # is to use an approximate inverse and convergence. Given the speed
+ # of the multiplier on EV4, and given "time to market", this wasn't
+ # done for V1.) I have some mail with the algorithm from Bob Gries
+ # (through Scott Robinson).
+ #
+ # - When the divisor is too large for the table, but has n low-order zero
+ # bits, see if divisor/2^n fits in the table, and use that entry with
+ # dividend/2^n
+ #
+ # - Use UMULH for the 'mod' routines.
+ #
+ # This version can do a table lookup division (divisors with <=tablesize)
+ # in roughly 32 cycles on an EV4 (with cache hits for all loads), of which
+ # 21 are for the umulh. There is a strong bias toward the table-lookup case.
+ # Note that for many cases, the umulh is the last thing before the return,
+ # so the multiply can occur in parallel with the procedure return.
+ # (It is interesting that the R3000 hardware divide instruction takes 33
+ # cycles and the R4000 takes 76(!) ...) Small powers of 2 are retired in
+ # roughly 20 cycles. Larger divisors take considerably longer at this point.
+ #
+
+#include "ots_defs.hs"
+
+#ifdef OSF
+ # to get the PAL_gentrap literal
+#include <alpha/pal.h>
+#endif
+
+ # Data area description
+ #
+ # The data area "ots_div_data" is an array of structures, indexed
+ # by the divisor value, with each array entry being 16 bytes in size
+ # formatted as follows:
+ #
+ # 6
+ # 3 6 0
+ # +-------+-------+-------+-------+-------+-------+-------+-------+
+ # | 32 bit reciprocal (58 bits) |shift|
+ # +-------+-------+-------+-------+-------+-------+-------+-------+
+ # | 64 bit reciprocal |
+ # +---------------------------------------------------------------+
+ #
+ # The 64-bit reciprocal has the leading '1' bit omitted, so it provides
+ # 65 bits of precision -- enough to handle unsigned 64-bit values.
+ #
+ # The first longword contains the 6-bit shift amount needed to handle
+ # 64-bit cases and powers of two.
+ #
+ # The 32-bit reciprocal has the shift count built in, so a UMULH gives
+ # the correct quotient without shifting. The reciprocal needs 33 bits
+ # of precision. The 6-bit shift amount is noise in the reciprocal that
+ # can be ignored.
+ #
+ # (Oh, you want proof?) For divisors up to 2^k, we store k-1 leading
+ # zero bits, 33 bits of fraction, (25-k) more bits of fraction, and
+ # 6 bits of noise. The standard method would round at the 33rd fraction
+ # bit. We need to ensure that the value actually stored is geq the
+ # infinite reciprocal, but leq the standard value. For divisors up to
+ # 2^k, there will be a zero bit somewhere in the k bits below the 33rd,
+ # so as long as we round below the (33+k)th bit, the rounded value
+ # plus any noise is still less than the standard value. This requires
+ # k < 12.
+ #
+ # The actual data is declared in ots_div_data_alpha.
+ #
+ # Offsets to the various fields in the data structure
+ #
+#define shift_o 0
+#define recip64_o 8
+#define recip32_o 0
+ #
+ # Note that the shift/add ops used to compute the table entries
+ # "know" that the table size is 16. (i.e. addq -> s8addq -> ldq)
+ # By changing the first instruction, it's fairly easy to change the
+ # table entry size to 24, 32, or 40 bytes (using s4add/sub), or
+ # 56/64/72 bytes using s8add/sub, should that be desirable.
+
+ # Maximum divisor present in the table
+ #
+#define table_max 512
+
+ # Division by zero gentrap code
+ #
+#define GEN_INTDIV -2
+
+ # Address of division data area (shared by all entry points)
+ #
+#ifdef VMS
+ .psect ots_link
+ots_div_addr:
+ .address ots_div_data
+ .psect ots_code
+#endif
+
+ # Dummy entry point for the module
+ #
+ .globl _OtsDivide
+ .ent _OtsDivide
+_OtsDivide:
+ .set noat
+ .set noreorder
+#ifdef OSF
+ .frame sp, 0, r26
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+#endif
+
+
+ # unsigned ots_rem_ui(unsigned dividend, unsigned divisor)
+ # unsigned 32 bit remainder support
+ #
+ #.align 4
+ .globl _OtsRemainder32Unsigned
+ .aent _OtsRemainder32Unsigned
+_OtsRemainder32Unsigned:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_rem_ui>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+ lda r28, -table_max(r17) # test for table lookup
+ subl r17, 1, r1 # first part of power-of-2 check
+ blt r17, rui_big # big divisors can (must) be handled by a simple comparison
+ and r17, r1, r18 # second part of power-of-2 check
+ bgt r28, rui_lrgdiv # branch if large divisor
+ addq r17, r17, r0 # compute divisor*2 for table lookup
+ beq r18, rui_pwr2 # if zero, divisor is a power of 2
+ s8addq r0, r27, r27 # finish computing table entry addr (table addr+divisor*16)
+ ldq r1, recip32_o(r27) # load approximate reciprocal
+ cmpult r16, r17, r18 # is the dividend < divisor?
+ zap r16, 0xF0, r0 # kill the propagated sign bit
+ bne r18, rui_lss # if dividend < divisor, fast exit
+ umulh r0, r1, r0 # multiplication for division step
+ mull r0, r17, r0 # multiply back to get value to subtract
+ subl r16, r0, r0
+ ret r31, (r26) # and return
+
+rui_pwr2:
+ beq r17, divzer # check for 0
+ and r16, r1, r0 # use x-1 to mask
+ ret r31, (r26)
+
+rui_lss:
+ mov r16, r0
+ ret r31, (r26)
+
+rui_lrgdiv:
+ zap r16, 0xf0, r16 # zero-extend the dividend
+ bsr r28, div32 # use the core routine getting the remainder in r1
+ sextl r1, r0
+ ret r31, (r26)
+
+ # divisors with the sign bit set. two possible results,
+ # dividend if dividend < divisor, or dividend-divisor otherwise
+rui_big:
+ cmpult r16, r17, r1
+ subl r16, r17, r0
+ cmovne r1, r16, r0
+ ret r31, (r26)
+
+
+ # unsigned ots_div_ui(unsigned dividend, unsigned divisor)
+ # unsigned 32 bit division support
+ #
+
+ #.align 4
+ .globl _OtsDivide32Unsigned
+ .aent _OtsDivide32Unsigned
+_OtsDivide32Unsigned:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_div_ui>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+ lda r28, -table_max(r17) # test for table lookup
+ blt r17, dui_big # big divisors can (must) be handled by a simple comparison
+ addq r17, r17, r18 # compute divisor*2
+ cmpule r17, r16, r0 # is the dividend < divisor?
+ beq r17, divzer # check for 0
+ s8addq r18, r27, r27 # finish computing table entry addr (table addr+divisor*16)
+ beq r0, dui_end # fast out for divisor > dividend
+ bgt r28, dui_lrgdiv # branch if large divisor
+ ldq r1, recip32_o(r27) # load approximate reciprocal
+ zap r16, 0xF0, r16 # kill the propagated sign bit
+ blt r1, dui_smpwr2 # go handle powers of 2 specially
+ umulh r16, r1, r0 # start multiplication for division step
+dui_end:ret r31, (r26) # and return
+ nop
+dui_smpwr2:
+ srl r16, r1, r0 # shift the result into place
+ sextl r0, r0 # reinsert sign if dividing by 1
+ ret r31, (r26) #
+dui_lrgdiv:
+ zap r16, 0xf0, r16 # zero-extend the dividend
+ bsr r28, div32 # use the core routine getting the remainder in r1
+ sextl r0, r0 # make sure the result is in normal form for uint32
+ ret r31, (r26)
+
+ # divisor with the sign bit set. two possible results,
+ # 1 if divisor <= dividend, or 0 otherwise
+dui_big:
+ cmpule r17, r16, r0
+ ret r31, (r26)
+
+
+ # int ots_mod_i(int dividend, int modulus)
+ # signed 32 bit modulus support
+ #
+ # This entry could be MUCH more optimized. It doesn't even try to use
+ # UMULH division currently... (A casualty of time-to-market.)
+ # Note that mod is only used by Ada and PL/I.
+ #
+ #.align 4
+ .globl _OtsModulus32
+ .aent _OtsModulus32
+_OtsModulus32:
+ negq r17, r18 # first part of abs(divisor)
+ cmovge r17, r17, r18 # second part of abs(divisor)
+ subq r18, 1, r1 # start checking for power of 2
+ beq r17, divzer # check for 0
+ and r18, r1, r0 # second part of power-of-2 check
+ beq r0, mi_p2 # for powers of two, simply do a mask
+ # (note that the power-of-2 case MUST be used to handle
+ # the -maxint case due to the way the fix-up info is
+ # saved across the core routine call)
+ xor r16, r17, r28 # get xor of signs
+ clr r19 # don't need a bias if dividend and divisor have same sign
+ cmovlt r28, r17, r19 # bias is original divisor for different sign case
+ and r16, r17, r27 # if both dividend & divisor were neg. need to negate result
+ mov r18, r17 # move abs(divisor) into r17
+ negq r16, r18 # first part of abs(dividend)
+ cmovlt r16, r18, r16 # second part of abs(dividend)
+ cmplt r27, r31, r0 # get 1 if both operands were <0
+ sll r0, 63, r0 # get bit as the high bit
+ bis r0, r19, r19 # and MERGE with bias (0 -> no fixup, -maxint -> negate result,
+ # divisor > 0 - subtract remainder if non-zero, divisor < 0 -
+ # add remainder if non-zero)
+ bsr r28, div32 # use the core routine getting the remainder in r1
+ cmoveq r1, r31, r19 # don't do any fix-up if the remainder was zero
+ addq r19, r19, r18 # check to see if this is the negative/negative case, which just gets a negated remainder
+ subq r19, 1, r28 # wrap -maxint to positive
+ negl r1, r0 # move negated value, may abort later
+ cmovlt r28, r1, r0 # if both positive, or negative divisor, keep positive remainder
+ cmoveq r18, r31, r19 # now that negation is done, treat -maxint case as 0
+ addl r19, r0, r0 # add any bias (original divisor or 0)
+ ret r31, (r26) # and return
+
+mi_p2: cmovge r17, r31, r17 # no bias if divisor was >= 0
+ and r16, r1, r1 # use the divisor-1 mask that's already in r1
+ cmoveq r1, r31, r17 # use zero if result was zero
+ addl r17, r1, r0 # do any biasing, and ensure the result is sign ext
+ ret r31, (r26) # and return
+
+ # int ots_rem_i(int dividend, int divisor)
+ # signed 32 bit remainder support
+ #
+ #.align 4
+ .globl _OtsRemainder32
+ .aent _OtsRemainder32
+_OtsRemainder32:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_rem_i>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+ negq r17, r18 # first part of abs(divisor)
+ cmovlt r17, r18, r17 # second part of abs(divisor)
+ subq r17, 1, r1 # start checking for power of 2
+ and r17, r1, r0 # finish check for power of 2
+ sra r16, 63, r19 # get -1/0 if dividend was negative
+ negq r16, r18 # first part of abs(dividend)
+ cmovlt r16, r18, r16 # second part of abs(dividend)
+ beq r0, ri_pwr2 # for powers of two, simply do a mask (not power of 2 include 0 and 80000000)
+ lda r28, -table_max(r17) # test for table lookup
+ bgt r28, ri_lrgdiv # branch if large divisor
+ addq r17, r17, r0 # compute divisor*2 for table lookup
+ s8addq r0, r27, r27 # finish computing table entry addr (table addr+divisor*16)
+ ldq r1, recip32_o(r27) # load approximate reciprocal
+ umulh r16, r1, r0 # multiplication for division step
+ mull r0, r17, r0 # multiply back to get value to subtract
+ subl r16, r0, r0 # get abs of final result
+ xor r0, r19, r0 # start compliment if original dividend was <0
+ subl r0, r19, r0 # finish compliement
+ ret r31, (r26) # and return
+
+ # Handle powers of 2, including 0 and 80000000
+ri_pwr2:
+ and r16, r1, r0 # use the divisor-1 mask in r1
+ beq r17, divzer # division by zero
+ xor r0, r19, r0 # start compliment if original dividend was <0
+ subl r0, r19, r0 # finish compliement
+ ret r31, (r26)
+
+ nop
+ri_lrgdiv:
+ bsr r28, div32 # use the core routine getting the remainder in r1
+ xor r1, r19, r0 # start compliment if original dividend was <0
+ subl r0, r19, r0 # finish compliement
+ ret r31, (r26)
+
+
+ # int ots_div_i_o(int dividend, int divisor)
+ # signed 32 bit division support, overflow detection
+ #
+ #.align 4
+ .globl _OtsDivide32Overflow
+ .aent _OtsDivide32Overflow
+_OtsDivide32Overflow:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_div_i_o>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+ not r17, r1 # is the divisor -1?
+ bne r1, di_skip # continue if not
+ neglv r16, r0 # quotient = -dividend, overflow on ^x800000000
+ ret r31, (r26)
+
+ # int ots_div_i(int dividend, int divisor)
+ # signed 32 bit division support, no overflow detection
+ #
+ nop #.align 4
+ .globl _OtsDivide32
+ .aent _OtsDivide32
+_OtsDivide32:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_div_i>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+di_skip:
+di_retry:
+ lda r28, -table_max(r17) # test for table lookup
+ ble r17, di_notpos # not a positive divisor case
+ addq r17, r17, r0 # compute divisor*2
+ negq r16, r18 # part 1 of abs(dividend) -> r18. (Note 0xffffffff 80000000 => 0x00000000 80000000)
+ bgt r28, di_lrgdiv # branch if large divisor
+ s8addq r0, r27, r27 # finish computing table entry addr (table addr+divisor*16)
+ cmpule r17, r18, r0 # divisor <= dividend?
+ cmovge r16, r16, r18 # part 2 abs. val of the dividend -> r18
+ beq r0, di_end # if not, result is zero
+ ldq r1, recip32_o(r27) # load approximate reciprocal
+ blt r1, di_smpwr2 # go handle powers of 2 specially
+ umulh r18, r1, r0 # start multiplication
+ blt r16, di_negres # negate result? (done as a branch to allow umulh to "hang out" over end for common case)
+di_end: ret r31, (r26) # return for same-sign (common) case
+di_negres:
+ negl r0, r0 # different signs - compliment result
+ ret r31, (r26) # return for different-sign (uncommon) case
+di_smpwr2:
+ srl r18, r1, r18 # shift the result into place
+ sra r16, 63, r16 # get 0/-1 based on sign of dividend
+ xor r18, r16, r18 # conditionally compliment
+ subl r18, r16, r0 # and increment for the final value
+ ret r31, (r26) # (note subl is required for sign ext for %x80000000/1 case)
+
+ # Zero or negative divisor case. If just a negative divisor,
+ # compliment both dividend and divisor and do things again.
+di_notpos:
+ beq r17, divzer # division by zero
+ negl r17, r17 # |divisor|, note that 0x80000000 still appears negative
+ negq r16, r16 # compliment dividend (negq so that 0xffffffff 80000000 => 0x00000000 80000000
+ bgt r17, di_retry # dispatch back for normal case (not 0x80000000 or 0)
+ sextl r16, r16 #
+ cmpeq r16, r17, r0 # -maxint/-maxint = 1, all others 0
+ ret r31, (r26) # done
+
+ # Large divisor for signed 32/32 case
+ #
+ nop #.align 3
+di_lrgdiv:
+ sra r16, 63, r19 # get 0/-1 based on sign of dividend
+ cmovlt r16, r18, r16 #
+ bsr r28, div32 # go use core routine
+ xor r0, r19, r0 # conditionally compliment
+ subl r0, r19, r0 # and increment for the final value (subl ensures normalized result)
+ ret r31, (r26) # done
+
+
+ # Large divisor case core routine for 32b
+ # (wbn)
+ #
+ # r0 - quotient (output)
+ # r1 - remainder (output)
+ # r16 - dividend (range 0..2^32-1, zero extended)
+ # r17 - divisor (range 1..2^31-1 - overwritten)
+ # r18 - scratch
+ # r19 - not used (one temp for 'caller')
+ # r26 - not used (expected to contain main return address)
+ # [r27 - scratch] (not currently written)
+ # r28 - this "subroutine" return address
+ #
+ # Some tightened up bit-at-a-time code for dividing 32-bit integers.
+ # It uses two tricks: keep the running remainder and the quotient in
+ # the same 64-bit register (MQ?), and add 1 while subtracting the divisor,
+ # so that a single CMOV sets both the new remainder and the new quotient.
+ # I start off by trying to skip 8 bits at a time; should this skip a
+ # smaller amount, so the main loop iterates less often? If the divisor
+ # is already known to be large enough, the last case in this test is never
+ # used...
+ #
+ # This code expects as input two integers in the range 0 <= x < 2^31
+ # (that is, it doesn't work for general unsigned longwords, and doesn't
+ # include sign manipulation.)
+ #
+ # The code here takes about 34n+11 cycles for a quotient occupying n bytes.
+ #
+ # Inputs: dividend in r16, divisor in r17
+ # Outputs: quotient in r0, remainder in r1
+ # Destroys: [r16,]r17,r18,[r27]
+ #
+ # How many quotient bytes will there be: 0, 1, 2, 3, 4?
+ #
+ #.align 4
+div32: cmpule r17, r16, r0 # Divisor leq dividend?
+ sll r17, 32, r18 # Position divisor for loop
+ sll r17, 8, r1 # Prepare for next compare
+ beq r0, d32end # Dividend less, quotient is zero.
+ediv32: mov 8-3, r17 # Hope to skip 3 bytes of loop
+ cmpule r1, r16, r0 # Shifted divisor still leq dividend?
+ sll r1, 8, r1 # Prepare for next compare
+ beq r0, d32ent # Go loop over just one byte
+ mov 8-2, r17 # Hope to skip 2 bytes of loop
+ cmpule r1, r16, r0 # Shifted divisor still leq dividend?
+ sll r1, 8, r1 # Prepare for next compare
+ beq r0, d32ent # Go loop over just two bytes
+ mov 8-1, r17 # Hope to skip 1 byte of loop
+ cmpule r1, r16, r0 # Shifted divisor still leq dividend?
+ nop # stall - align d32ent and d32loop
+ cmovne r0, 8, r17 # If we can't skip any bytes
+
+ # start loop generating quotient bits. NOTE: The loop setup requires
+ # an even number of iterations.
+ #
+d32ent: extqh r16, r17, r0 # Shift dividend left for skipped bytes
+ subq r18, 1, r1 # Divisor in high LW - 1 in low LW
+ s8subq r17, 34, r17 # Convert bytes to bits and adjust
+
+ addq r0, r0, r0 # Shift left to start first iteration
+d32loop:subq r0, r1, r18 # Can we subtract divisor from it?
+ cmovge r18, r18, r0 # If so, set new remainder & quotient
+ # stall
+ addq r0, r0, r0 # Shift remainder and quotient left
+ subq r0, r1, r18 # Can we subtract divisor from it?
+ cmovge r18, r18, r0 # If so, set new remainder & quotient
+ subq r17, 2, r17 # Loop counter
+ addq r0, r0, r0 # Shift remainder and quotient left
+ bgt r17, d32loop # Repeat
+ subq r0, r1, r18 # Can we subtract divisor from it?
+ cmovge r18, r18, r0 # If so, set new remainder & quotient
+ # stall
+ addq r0, r0, r0 # Shift remainder and quotient left
+ subq r0, r1, r18 # Finish last iteration
+ cmovge r18, r18, r0
+ # stall
+ srl r0, 32, r1 # Get remainder in r1
+ zap r0, 0xf0, r0 # Keep only quotient in r0
+ nop # for alignment
+d32end: cmoveq r0, r16, r1 # Move remainder to r1 for quotient=0 case
+ ret r31, (r28) # Not a real software procedure return
+
+
+ # Large divisor case core routine for 64b
+ #
+ # r0 - quotient (output)
+ # r1 - remainder (output)
+ # r16 - dividend (range 0..2^64-1 - overwritten)
+ # r17 - divisor (range 1..2^63-1 - overwritten)
+ # r18 - scratch
+ # r19 - not used (one temp for 'caller')
+ # r26 - not used (expected to contain main return address)
+ # r27 - points to table of inverses (overwritten)
+ # r28 - this "subroutine" return address
+ #
+ # Inputs: dividend in r16, divisor in r17
+ # Outputs: quotient in r0, remainder in r1
+ # Destroys: r16,r17,r18,r27
+ #
+ # Note- this routine could save a few cycles if we could use
+ # another scratch register -- perhaps by pushing one on the stack?
+ #
+ #.align 4
+div64: sll r17, 32, r18 # Position for ediv32
+ cmpule r17, r16, r0 # Is divisor leq dividend?
+ srl r17, 31, r1 # Is divisor geq 2^31?
+ beq r0, d64end # If divisor > dividend, quotient=0
+ cmpule r18, r16, r0 # Is divisor*2^32 leq dividend?
+ sll r17, 8, r1 # Position for ediv32 checking
+ or r1, r0, r0 # 0 if divisor & quotient fit in 32 bits
+ beq r0, ediv32 # Use 32-bit routine if OK
+
+ # Full 64-bit divide needed. Use the table of shift amounts to compute
+ # the number of leading zero bits in the divisor. Find the leftmost
+ # nonzero byte, then the leftmost nonzero bit in that byte. Table entry
+ # #n+1 contains the number of bits needed to hold n (1..8). We know the
+ # divisor is nonzero here.
+ #
+ cmpbge r31, r17, r0 # Get a zero bit for each nonzero byte
+ #stall
+ sll r0, 4, r0 # *16 bytes per table entry
+ #stall
+ subq r27, r0, r0 # table base plus complement...
+ #stall
+ ldq r1, 256*16(r0) # get position of first nonzero
+ #2 stalls
+ subq r1, 1, r1 # byte number of first nonzero
+ extbl r17, r1, r0 # get first nonzero byte
+ #stall
+ addq r0, r0, r0 # *2
+ s8addq r0, r27, r0 # *16 bytes per table entry
+ #stall
+ ldq r0, 16(r0) # bit number of first nonzero
+ negq r1, r1 # 1 + #leading zero bytes (mod 8)
+ #stall
+ s8subq r1, r0, r0 # number of leading zero bits
+ and r0, 0x3F, r0 # discard other junk
+
+ # The following code does a similar normalize calculation without the table.
+ #===
+ # extll r17, #4, r18 ; Normalize the divisor and
+ # mov #63, r0 ; count leading zeros
+ # cmovne r18, #31, r0
+ # cmoveq r18, r17, r18
+ # ;stall
+ # extwl r18, #2, r1
+ # ;stall
+ # cmovne r1, r1, r18
+ # cmovne r1, #16, r1
+ # ;stall
+ # subq r0, r1, r0
+ # extbl r18, #1, r1
+ # ;stall
+ # cmovne r1, r1, r18
+ # cmovne r1, #8, r1
+ # ;stall
+ # subq r0, r1, r0
+ # andnot r18, #^x0f, r1
+ # cmovne r1, r1, r18
+ # cmovne r1, #4, r1
+ # ;stall
+ # subq r0, r1, r0
+ # andnot r18, #^x33, r1
+ # cmovne r1, r1, r18
+ # cmovne r1, #2, r1
+ # ;stall
+ # subq r0, r1, r0
+ # andnot r18, #^x55, r1
+ # cmovne r1, #1, r1
+ # ;stall
+ # subq r0, r1, r0
+ #===
+
+ # R0 contains number of leading zero bits in the divisor.
+
+ sll r17, r0, r17 # Normalize: MSB is set.
+
+ # Now break divisor into pieces a+x, where a is the leading
+ # 9 bits, rounded, and x is the rest. Use a linear
+ # approximation for 1/divisor = 1/a - x/a^2 [+ x^2/a^3 -...]
+ #
+ srl r17, 64-10, r1 # Keep 10 bits of divisor
+ #stall
+ addq r1, 1, r1 # Round to form 'a'
+ andnot r1, 1, r1
+ s8addq r1, r27, r27 # Index table of 1/a and 1/a^2
+ sll r1, 64-10, r1 # shift 'a' to match divisor
+ ldq r18, (r27) # Load QW containing 1/a^2
+ subq r1, r17, r1 # -x = a - divisor
+ beq r1, d64_easy # Use table directly if x=0
+ inswl r18, 6, r18 # position 1/a^2
+ blt r1, d64_sub # correct for sign of -x
+ umulh r1, r18, r1 # -x/a^2
+ ldq r27, 8(r27) # Load QW containing 1/a - 1
+ br r31, d64_cont
+
+d64_sub:umulh r1, r18, r1 # -x/a^2
+ ldq r27, 8(r27) # load QW containing 1/a - 1
+ # 2 stalls
+ s4addq r18, 0, r18
+ subq r27, r18, r27 # correct for sign of -x
+d64_cont:
+ # many stalls
+ s4addq r1, r27, r18 # 1/divisor approx= 1/a - x/a^2
+
+ # Now one or two Newton iterations to get 24 or 56 good bits of the inverse.
+ # Each computes inv = inv * (2 - inv*divisor). We could skip out early
+ # here or above if the dividend and/or quotient is small enough for the
+ # amount of precision we've developed...
+ #
+ # We handle quadwords with the radix point on the left. The divisor has
+ # been normalized to the range 0.5 < divisor < 1.0; the inverses are in
+ # the range 1.0 < inverse < 2.0, and are represented without the leading 1.
+ #
+ umulh r18, r17, r1 # (inv0 - 1) * divisor
+ # many stalls
+ addq r1, r17, r1 # add hidden bit * divisor
+ negq r1, r1 # 2 - inv0*divisor, very near 1.0
+ umulh r18, r1, r27 # (inv0 - 1) * (2 - inv0*divisor)
+ cmovlt r1, 0, r18 # keep inv0 if (2-inv0*divisor) > 1.0
+ #stall
+ addq r18, r1, r1 # add it to hidden bit * (2-inv0*divisor)
+ # many stalls
+ addq r27, r1, r18 # inv1 = inv0 * (2 - inv0*divisor)
+
+ umulh r18, r17, r1 # (inv1 - 1) * divisor
+ # many stalls
+ addq r1, r17, r1 # add hidden bit * divisor
+ negq r1, r1 # 2 - inv1*divisor, very near 1.0
+ umulh r18, r1, r27 # (inv1 - 1) * (2 - inv1*divisor)
+ cmovlt r1, 0, r18 # keep inv1 if (2-inv1*divisor) > 1.0
+ addq r18, r1, r1 # add it to hidden bit * (2-inv1*divisor)
+ # many stalls
+ addq r27, r1, r1 # inverse = inv1 * (2 - inv1*divisor)
+ umulh r1, r16, r18 # dividend * (1/divisor - 1)
+ srl r17, r0, r17 # un-normalize divisor
+ negq r0, r0
+ subq r0, 8, r0 # how far right after first byte
+ # many stalls
+ addq r18, r16, r18 # add hidden bit * dividend
+ cmpult r18, r16, r1 # did it carry?
+ srl r18, 8, r18 # start to shift
+ sll r1, 56, r1 # position the carry
+ #stall
+ addq r1, r18, r1 # add the carry
+ srl r1, r0, r0 # final shift
+ mulq r17, r0, r1 # try out this quotient
+ # many stalls
+ subq r16, r1, r1 # form remainder
+ cmpule r17, r1, r18 # must be less than divisor
+ subq r1, r17, r27
+ cmovne r18, r27, r1 # if not, decrement remainder
+ addq r0, r18, r0 # and increment quotient
+ ret r31, (r28) # done
+
+d64_easy:
+ ldq r1, 8(r27) # get 1/divisor, except hidden bit
+ srl r17, r0, r17 # un-normalize divisor again
+ blt r18, d64_pow2 # skip if power of 2
+ umulh r1, r16, r18 # dividend/divisor
+ negq r0, r0 # how far right to shift
+ and r16, 0x0ff, r1 # pieces of dividend
+ subq r0, 8, r0 # how far right after first byte
+ srl r16, 8, r27
+ # many stalls
+ addq r18, r1, r1 # add low piece of dividend, no carry
+ srl r1, 8, r1 # make room for high piece
+ #stall
+ addq r1, r27, r1 # finish adding hidden bit * dividend
+ srl r1, r0, r0 # final shift
+ mulq r17, r0, r1 # need to compute remainder too
+ # many stalls
+ subq r16, r1, r1
+ ret r31, (r28) # done
+
+d64_pow2:
+ not r0, r0 # how far right to shift quotient
+ subq r17, 1, r1 # mask for remainder
+ srl r16, r0, r0 # shift for quotient
+ and r16, r1, r1 # get remainder
+ ret r31, (r28) # done
+
+d64end: mov r16, r1 # Remainder to r1 for small quotient case
+ ret r31, (r28) # Not a real software procedure return
+
+ # long ots_div_l_o(long dividend, long divisor)
+ # signed 64 bit division support, overflow detection
+ #
+ #.align 4
+ .globl _OtsDivide64Overflow
+ .aent _OtsDivide64Overflow
+_OtsDivide64Overflow:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_div_l_o>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+ not r17, r1 # is the divisor -1?
+ bne r1, dl_skip # continue if not
+ negqv r16, r0 # q = -dividend, oflow on ^x800000000 00000000
+ ret r31, (r26)
+ nop
+
+ # long ots_div_l(long dividend, long divisor)
+ # signed 64 bit division support, no overflow detection
+ #
+ .globl _OtsDivide64
+ .aent _OtsDivide64
+_OtsDivide64:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_div_l>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+dl_skip:
+ xor r16, r17, r19 # sign bit = result needs to be complimented (here to handle -maxint correctly)
+dl_retry:
+ lda r28, -table_max(r17) # test for table lookup
+ ble r17, dl_notpos # not a positive divisor case
+ addq r17, r17, r0 # compute divisor*2
+ negq r16, r18 # part 1 of abs(dividend) -> r18
+ bgt r28, dl_lrgdiv # branch if large divisor
+ s8addq r0, r27, r27 # finish computing table entry addr (table addr+divisor*16)
+ srl r16, 33, r1 # can this be handled via a 32 bit case?
+ cmpule r17, r18, r0 # divisor <= dividend?
+ bne r1, dl_64bit # does this need to be a real 64 bit case?
+ cmovge r16, r16, r18 # part 2 abs. val of the dividend -> r18
+ beq r0, dl_end # if not, result is zero
+ ldq r27, recip32_o(r27) # load 32b approximate reciprocal
+ sra r19, 63, r19 # get 0/-1
+ blt r27, dl_smpwr2 # skip umulh for powers of 2 specially
+ umulh r18, r27, r0 # start multiplication
+ beq r19, dl_end # if compliment not required, let umulh "hang out"
+ negq r0, r0 # compliment case
+ ret r31, (r26) #
+dl_64bit:
+ cmovge r16, r16, r18 # part 2 abs. val of the dividend -> r18
+ beq r0, dl_end # if not, result is zero
+ ldq r1, recip64_o(r27) # load approximate reciprocal
+ sra r19, 63, r19 # get 0/-1
+ ldq r27, shift_o(r27) # load shift count (low 6 bits are all that matters)
+ beq r1, dl_smpwr2 # skip umulh for powers of 2 specially
+ umulh r18, r1, r0 # start multiplication
+ addq r0, r18, r18 # add hidden bit
+dl_smpwr2:
+ srl r18, r27, r18 # shift the result into place
+ xor r18, r19, r18 # conditionally compliment
+ subq r18, r19, r0 # and increment for the final value
+dl_end: ret r31, (r26) #
+
+ # Zero or negative divisor case. If just a negative divisor,
+ # compliment both dividend and divisor and do things again.
+dl_notpos:
+ beq r17, divzer # division by zero
+ negq r17, r17 # |divisor|, note that 0x80000000 00000000 still appears negative
+ negq r16, r16 # compliment dividend
+ bgt r17, dl_retry # dispatch back for normal case (not 0x80000000 00000000 or 0)
+ cmpeq r16, r17, r0 # -maxint/-maxint = 1, all others 0
+ ret r31, (r26) # done
+
+ # Large divisor for signed 64/64 case
+ #
+dl_lrgdiv:
+ sra r19, 63, r19 # get 0/-1
+ cmovlt r16, r18, r16 #
+ bsr r28, div64 # go use core routine
+ xor r0, r19, r0 # conditionally compliment
+ subq r0, r19, r0 # and increment for the final value
+ ret r31, (r26) # done
+
+
+ # long ots_rem_l(long dividend, long divisor)
+ # signed 64 bit remainder support
+ #
+ #.align 4
+ .globl _OtsRemainder64
+ .aent _OtsRemainder64
+_OtsRemainder64:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_rem_l>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+ negq r17, r18 # first part of abs(divisor)
+ cmovlt r17, r18, r17 # second part of abs(divisor)
+ subq r17, 1, r1 # start checking for power of 2
+ and r17, r1, r0 # finish check for power of 2
+ sra r16, 63, r19 # get -1/0 if dividend was negative
+ negq r16, r18 # first part of abs(dividend)
+ cmovlt r16, r18, r16 # second part of abs(dividend)
+ beq r0, rl_pwr2 # for powers of two, simply do a mask (not power of 2 include 0 and 80000000)
+ lda r28, -table_max(r17) # test for table lookup
+ bgt r28, rl_lrgdiv # branch if large divisor
+ addq r17, r17, r0 # compute divisor*2 for table lookup
+ s8addq r0, r27, r27 # finish computing table entry addr (table addr+divisor*16)
+ ldq r1, recip64_o(r27) # load approximate reciprocal
+ ldq r18, shift_o(r27) # load shift amount
+ umulh r16, r1, r0 # multiplication for division step
+ addq r0, r16, r0 # add hidden bit
+ srl r0, r18, r0
+ mulq r0, r17, r0 # multiply back to get value to subtract
+ subq r16, r0, r0 # get abs of final result
+ xor r0, r19, r0 # start compliment if original dividend was <0
+ subq r0, r19, r0 # finish compliement
+ ret r31, (r26) # and return
+
+ # Handle powers of 2, including 0 and 80000000 00000000
+rl_pwr2:
+ negq r16, r18 # first part of abs(dividend)
+ cmovlt r16, r18, r16 # second part of abs(dividend)
+ and r16, r1, r0 # use the divisor-1 mask in r1
+ beq r17, divzer # division by zero
+ xor r0, r19, r0 # start compliment if original dividend was <0
+ subq r0, r19, r0 # finish compliement
+ ret r31, (r26)
+
+rl_lrgdiv:
+ bsr r28, div64 # use the core routine getting the remainder in r1
+ xor r1, r19, r0 # start compliment if original dividend was <0
+ subq r0, r19, r0 # finish complement
+ ret r31, (r26)
+
+ # long ots_mod_l(long dividend, long modulus)
+ # signed 64 bit modulus support
+ #
+ # This entry could be MUCH more optimized. It doesn't even try to use
+ # UMULH division currently... (A casualty of time-to-market.)
+ # Note that mod is only used by Ada and PL/I.
+ #
+ #.align 4
+ .globl _OtsModulus64
+ .aent _OtsModulus64
+_OtsModulus64:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_rem_l>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+ negq r17, r18 # first part of abs(divisor)
+ cmovge r17, r17, r18 # second part of abs(divisor)
+ subq r18, 1, r1 # start checking for power of 2
+ beq r17, divzer # check for 0
+ and r18, r1, r0 # second part of power-of-2 check
+ beq r0, ml_p2 # for powers of two, simply do a mask
+ # (note that the power-of-2 case MUST be used to handle
+ # the -maxint case due to the way the fix-up info is
+ # saved across the core routine call)
+ xor r16, r17, r28 # get xor of signs
+ clr r19 # don't need a bias if dividend and divisor have same sign
+ cmovlt r28, r17, r19 # bias is original divisor for different sign case
+ and r16, r17, r28 # if both dividend & divisor were neg. need to negate result
+ mov r18, r17 # move abs(divisor) into r17
+ negq r16, r18 # first part of abs(dividend)
+ cmovlt r16, r18, r16 # second part of abs(dividend)
+ cmplt r28, r31, r0 # get 1 if both operands were <0
+ sll r0, 63, r0 # get bit as the high bit
+ bis r0, r19, r19 # and MERGE with bias (0 -> no fixup, -maxint -> negate result,
+ # divisor > 0 - subtract remainder if non-zero, divisor < 0 -
+ # add remainder if non-zero)
+ bsr r28, div64 # use the core routine getting the remainder in r1
+ cmoveq r1, r31, r19 # don't do any fix-up if the remainder was zero
+ addq r19, r19, r18 # check to see if this is the negative/negative case, which just gets a negated remainder
+ subq r19, 1, r28 # wrap -maxint to positive
+ negq r1, r0 # move negated value, may abort later
+ cmovlt r28, r1, r0 # if both positive, or negative divisor, keep positive remainder
+ cmoveq r18, r31, r19 # now that negation is done, treat -maxint case as 0
+ addq r19, r0, r0 # add any bias (original divisor or 0)
+ ret r31, (r26) # and return
+
+ml_p2: cmovge r17, r31, r17 # no bias if divisor was >= 0
+ and r16, r1, r1 # use the divisor-1 mask that's already in r1
+ cmoveq r1, r31, r17 # use zero if result was zero
+ addq r17, r1, r0 # do any biasing
+ ret r31, (r26) # and return
+
+
+ # unsigned long ots_div_ul(unsigned long dividend, unsigned long divisor)
+ # unsigned 64 bit division support
+ #
+ nop #.align 4
+ .globl _OtsDivide64Unsigned
+ .aent _OtsDivide64Unsigned
+_OtsDivide64Unsigned:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_div_ul>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+ lda r28, -table_max(r17) # test for table lookup
+ blt r17, dul_big # big divisors can (must) be handled by a simple comparison
+ addq r17, r17, r18 # compute divisor*2
+ srl r16, 33, r19 # can this be handled via the fast path for 31 bit dividends?
+ beq r17, divzer # check for 0
+ s8addq r18, r27, r18 # finish computing table entry addr (table addr+divisor*16)
+ bgt r28, dul_lrgdiv # branch if large divisor
+ cmpule r17, r16, r0 # is the dividend < divisor?
+ bne r19, dul_64bit # if the dividend doesn't fit in 31 bits, use the larger umulh form
+ ldq r27, recip32_o(r18) # load approximate 32b reciprocal & shift count
+ beq r0, dul_end # fast out for divisor > dividend
+ blt r27, dul_smpwr2 # go handle powers of 2 specially
+ umulh r16, r27, r0 # 32b recip
+ ret r31, (r26) #
+
+ # the 64 bit case is at a disadvantage to the 32b case because it needs
+ # a fix-up at the end, which prevents the latency of the umulh from
+ # being partially absorbed by the procedure return and anything that
+ # immediately follows that doesn't interlock.
+ nop
+dul_64bit:
+ ldq r1, recip64_o(r18) # load approximate 64b reciprocal
+ ldq r27, shift_o(r18) # load shift count (low 6 bits are all that matters)
+ beq r0, dul_end # fast out for divisor > dividend
+ beq r1, dul_smpwr2 # go handle powers of 2 specially
+ umulh r16, r1, r0 # start multiplication for division step
+ zap r16, 0x0f, r18 # split dividend into two parts
+ zapnot r16, 0x0f, r16
+ srl r18, r27, r18 # position the high part
+ addq r0, r16, r0 # add hidden * low dividend (no carry)
+ srl r0, r27, r0 # shift into place
+ addq r0, r18, r0 # add hidden * high dividend
+ ret r31, (r26)
+
+dul_smpwr2:
+ srl r16, r27, r0 # shift the result into place
+dul_end: ret r31, (r26) #
+
+dul_lrgdiv:
+ bsr r28, div64 # use the core routine
+ ret r31, (r26)
+
+ # divisor with the sign bit set. two possible results,
+ # 1 if divisor <= dividend, or 0 otherwise
+dul_big:
+ cmpule r17, r16, r0
+ ret r31, (r26)
+
+
+ # long unsigned ots_rem_ul(long unsigned dividend, long unsigned divisor)
+ # unsigned 64 bit remainder support
+ #
+ #.align 4
+ .globl _OtsRemainder64Unsigned
+ .aent _OtsRemainder64Unsigned
+_OtsRemainder64Unsigned:
+#ifdef VMS
+ ldq r27, <ots_div_addr-ots_rem_ul>(r27)# start loading address of division data area
+#endif
+#ifdef OSF
+ ldgp gp, 0(r27) # load the global pointer
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # start loading address of the division data area
+#endif
+#ifdef WNT
+ .frame sp, 0, r26
+ lda r27, _OtsDivData # load the division data table address
+#endif
+ lda r28, -table_max(r17) # test for table lookup
+ subq r17, 1, r1 # first part of power-of-2 check
+ blt r17, rul_big # big divisors can (must) be handled by a simple comparison
+ and r17, r1, r18 # second part of power-of-2 check
+ bgt r28, rul_lrgdiv # branch if large divisor
+ addq r17, r17, r0 # compute divisor*2 for table lookup
+ beq r18, rul_pwr2 # if zero, divisor is a power of 2
+ s8addq r0, r27, r27 # finish computing table entry addr (table addr+divisor*16)
+ ldq r1, recip64_o(r27) # load approximate reciprocal
+ cmpult r16, r17, r18 # is the dividend < divisor?
+ bne r18, rul_lss # if so, fast exit
+ ldq r19, shift_o(r27) # load the shift count
+ umulh r16, r1, r0 # multiplication for division step
+ blt r16, rul_carry # careful handling if >= 2^63
+ addq r0, r16, r0 # add hidden bit * dividend
+ srl r0, r19, r0
+ mulq r0, r17, r0 # multiply back to get value to subtract
+ subq r16, r0, r0
+ ret r31, (r26) # and return
+
+rul_carry:
+ zap r16, 0x0f, r18 # split dividend into two parts
+ zapnot r16, 0x0f, r1
+ srl r18, r19, r18 # position the high part
+ addq r0, r1, r0 # add hidden * low dividend (no carry)
+ srl r0, r19, r0 # shift into place
+ addq r0, r18, r0 # add hidden * high dividend
+ mulq r0, r17, r0 # multiply back to get value to subtract
+ subq r16, r0, r0
+ ret r31, (r26)
+
+rul_pwr2:
+ beq r17, divzer # check for 0
+ and r16, r1, r0 # use x-1 to mask
+ ret r31, (r26)
+
+rul_lss:
+ mov r16, r0
+ ret r31, (r26)
+
+ # divisors with the sign bit set. two possible results,
+ # dividend if dividend < divisor, or dividend-divisor otherwise
+rul_big:
+ cmpult r16, r17, r1
+ subq r16, r17, r0
+ cmovne r1, r16, r0
+ ret r31, (r26)
+
+ nop
+rul_lrgdiv:
+ bsr r28, div64 # use the core routine getting the remainder in r1
+ mov r1, r0 # return remainder as the result in r0
+ ret r31, (r26)
+
+
+ # Division-by-zero handling
+ # (forward branch from all routines, out of the way here as well.)
+ #
+divzer: lda r16, GEN_INTDIV(r31) # load GENTRAP code for division by zero
+ clr r0 # return 0 for the result
+ clr r1 #
+#ifdef VMS
+ gentrap # signal the error
+#endif
+#ifdef OSF
+ call_pal PAL_gentrap
+#endif
+#ifdef WNT
+ # Since I couldn't find this in a header file anywhere for NT...
+#define PAL_gentrap 0xaa
+ call_pal PAL_gentrap
+#endif
+ ret r31, (r26) # return (in case someone tries to continue)
+
+ .set at
+ .set reorder
+ .end _OtsDiv
diff --git a/private/crt32/misc/alpha/otsjmp.s b/private/crt32/misc/alpha/otsjmp.s
new file mode 100644
index 000000000..9c49751f9
--- /dev/null
+++ b/private/crt32/misc/alpha/otsjmp.s
@@ -0,0 +1,117 @@
+// TITLE("Set Jump")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// otsjmp.s
+//
+// Abstract:
+//
+// This module implements the Alpha C8/GEM C compiler specific routine to
+// perform a setjmp.
+//
+// N.B. This module conditionally provides UNSAFE handling of setjmp and
+// which is NOT integrated with structured exception handling. The
+// determination is made based on whether an uninitialized variable
+// has been set to a nonzero value.
+//
+// Author:
+//
+// Thomas Van Baak (tvb) 22-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksalpha.h"
+
+//
+// Define variable that will cause setjmp/longjmp to be safe or unsafe with
+// respect to structured exception handling.
+//
+
+ .globl _Otssetjmpexused
+ .comm _Otssetjmpexused, 4
+
+ SBTTL("Set Jump - GEM version")
+//++
+//
+// int
+// _Otssetjmp3 (
+// IN OUT jmp_buf JumpBuffer,
+// IN PVOID RealFramePointer,
+// IN PVOID SebPointer
+// )
+//
+// Routine Description:
+//
+// This function saves the current nonvolatile register state in the
+// specified jump buffer and returns a function value of zero.
+//
+// N.B. The name `_Otssetjmp3' was chosen to avoid collision with an
+// earlier implementation named _Otssetjmp. This version has three
+// arguments.
+//
+// Arguments:
+//
+// JumpBuffer (a0) - Supplies the address of a jump buffer to store the
+// jump information.
+//
+// RealFramePointer (a1) - Supplies the real frame pointer value.
+//
+// SebPointer (a2) - Supplies the pointer to the current SEB or NULL
+// if the call was made outside of any SEH scope.
+//
+// Return Value:
+//
+// A value of zero is returned.
+//
+//--
+
+ LEAF_ENTRY(_Otssetjmp3)
+
+ ldl v0, _Otssetjmpexused // get value of switch variable
+ bne v0, 10f // if ne, provide safe setjmp
+
+//
+// Provide unsafe handling of setjmp.
+//
+
+ stt f2, JbFltF2(a0) // save floating registers f2 - f9
+ stt f3, JbFltF3(a0) //
+ stt f4, JbFltF4(a0) //
+ stt f5, JbFltF5(a0) //
+ stt f6, JbFltF6(a0) //
+ stt f7, JbFltF7(a0) //
+ stt f8, JbFltF8(a0) //
+ stt f9, JbFltF9(a0) //
+
+ stq s0, JbIntS0(a0) // save integer registers s0 - s6/fp
+ stq s1, JbIntS1(a0) //
+ stq s2, JbIntS2(a0) //
+ stq s3, JbIntS3(a0) //
+ stq s4, JbIntS4(a0) //
+ stq s5, JbIntS5(a0) //
+ stq fp, JbIntS6(a0) //
+
+ ldil t0, 1 // get unsafe setjmp flag
+ stl t0, JbType(a0) // set jump buffer context type
+ stq sp, JbIntSp(a0) // save stack pointer
+ stq ra, JbFir(a0) // get setjmp return address
+
+ mov zero, v0 // set zero return value
+ ret zero, (ra) // return
+
+//
+// Provide safe handling of setjmp.
+//
+
+10: jmp zero, (v0) // finish in _setjmpex code
+
+ .end _Otssetjmp3
diff --git a/private/crt32/misc/alpha/otsjmpex.s b/private/crt32/misc/alpha/otsjmpex.s
new file mode 100644
index 000000000..eaf78190b
--- /dev/null
+++ b/private/crt32/misc/alpha/otsjmpex.s
@@ -0,0 +1,84 @@
+// TITLE("Set Jump Extended")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// otsjmpex.s
+//
+// Abstract:
+//
+// This module implements the Alpha C8/GEM C compiler specific routine to
+// provide SAFE handling of setjmp/longjmp with respect to structured
+// exception handling.
+//
+// Author:
+//
+// Thomas Van Baak (tvb) 22-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksalpha.h"
+
+//
+// Define variable that will cause setjmp/longjmp to be safe with respect
+// to structured exception handling.
+//
+
+ .globl _Otssetjmpexused
+ .data
+_Otssetjmpexused:
+ .long _Otssetjmpex3 // set address of safe setjmp routine
+
+ SBTTL("Set Jump Extended - GEM version")
+//++
+//
+// int
+// _Otssetjmpex3 (
+// IN OUT jmp_buf JumpBuffer,
+// IN PVOID RealFramePointer,
+// IN PVOID SebPointer
+// )
+//
+// Routine Description:
+//
+// This function implements a safe setjmp.
+//
+// Arguments:
+//
+// JumpBuffer (a0) - Supplies the address of a jump buffer to store the
+// jump information.
+//
+// RealFramePointer (a1) - Supplies the real frame pointer value.
+//
+// SebPointer (a2) - Supplies the pointer to the current SEB or NULL
+// if the call was made outside of any SEH scope.
+//
+// Return Value:
+//
+// A value of zero is returned.
+//
+//--
+
+ LEAF_ENTRY(_Otssetjmpex3)
+
+//
+// Save the given set jump context in the jump buffer.
+//
+
+ stl a1, JbFp(a0) // save real frame pointer
+ stl ra, JbPc(a0) // save target instruction address
+ stl a2, JbSeb(a0) // save SEB pointer
+ ldil t0, 3 // get GEM safe setjmp flag
+ stl t0, JbType(a0) // set jump buffer context type
+ mov zero, v0 // set return value
+ ret zero, (ra) // return
+
+ .end _Otssetjmpex3
diff --git a/private/crt32/misc/alpha/otsnote.txt b/private/crt32/misc/alpha/otsnote.txt
new file mode 100644
index 000000000..af99f6697
--- /dev/null
+++ b/private/crt32/misc/alpha/otsnote.txt
@@ -0,0 +1,115 @@
+Alpha AXP MSCGEM OTS C run-time library notes.
+
+- The following OTS source files were obtained from Kent Glossop on
+ 27-Jan-1993. I believe the version number is X1.0-4.
+
+ div.s
+ divdat.s
+
+ extv.s
+ extvvol.s
+ extzv.s
+ extzvvol.s
+
+ insv.s
+ insvvol.s
+
+ ots_as.hs
+ ots_defs.hs
+
+ scmpeql.s
+ scmpeqlp.s
+ scmpleq.s
+ scmpleqp.s
+ scmplss.s
+ scmplssp.s
+
+ sfill.s
+ sloc.s
+ smove.s
+ smovem.s
+ strans.s
+ szero.s
+
+- The six strcmp/cpy/len functions were obtained through Rich Peterson
+ on 25-Jan-1993.
+
+ strcmp.s
+ strcmp_.s
+ strcpy.s
+ strcpy_.s
+ strlen.s
+ strlen_.s
+
+- For now, and in the interest of maintenance, we have left the source
+ files intact in spite of the fact that they don't follow conventions
+ of all other NT/Alpha assembler code.
+
+- The following files had a non-ascii 0xa9 character instead of a (c)
+ in the copyright line. These have been fixed so slm works right.
+
+ scmpeql.s
+ scmpeqlp.s
+ scmpleq.s
+ scmpleqp.s
+ scmplss.s
+ scmplssp.s
+ sloc.s
+ strans.s
+
+- The goal is to provide compatible C runtime support for both acc and
+ GEM compilers through the existing NT C libraries.
+
+- Both compilers, header files, runtime libraries, and object files are
+ compatible with each other now, with these exceptions:
+
+ o The setjmp/longjmp functions are not compatible since the data in
+ the jump buffer differs between the two compilers. SEH is 100%
+ compatible, however.
+
+ o Calls to setjmp would actually work with acc even if setjmp.h was
+ not included. With GEM, the include file is required for proper
+ operation.
+
+ o As of 930205, small structures are still passed and returned by
+ value incompatibly between the two compilers. This will be fixed
+ by upgrading acc to follow the GEM calling standard, and/or by
+ using a GEM switch to be acc compatible.
+
+ o The above is not quite correct: as of 930217, GEM is using an option
+ to follow the acc convention, not the calling standard convention.
+ It looks like both acc and GEM will have options to handle small
+ structures both ways.
+
+- The str functions will conflict with the portable versions in the
+ ..\string directory. The portable ones should be #ifdef'ed out for
+ Alpha.
+
+- The two or three different versions of divide routines may get
+ sorted out later when we have a chance to do better performance
+ work.
+
+- A _OtsUnwindRfp was added to jmpuwind.s. This may not be used by GEM/C,
+ but will be used by GEM/Pascal.
+
+930728
+
+- _OtsUnwindRfp is permanent and is also used by C for gotos out of finally
+ handlers and by the GEM C specific handler function. All DLLs that exported
+ RtlUnwind now also export RtlUnwindRfp.
+
+- Both compilers pass and return small structures in registers. This change
+ was made some months ago. The object file magic number was changed at the
+ same time to eliminate any calling standard mismatch.
+
+- The contents of the jump buffer is not the same between the two compilers
+ but a jump buffer type field is set by setjmp and there is only one longjmp
+ function so there are now no interoperability problems between the two
+ compilers.
+
+- A new set of OTS source files was obtained from Patsy Griffin on 1-Jun-1993.
+ The version number is V1.0. The only changes are in div.s (renamed otsdiv.s
+ for NT) and divdat.s. These implement a faster division algorithm, similar
+ to the one already used in fastdiv.s for acc.
+
+tvb
diff --git a/private/crt32/misc/alpha/otsuwind.s b/private/crt32/misc/alpha/otsuwind.s
new file mode 100644
index 000000000..c53a511fa
--- /dev/null
+++ b/private/crt32/misc/alpha/otsuwind.s
@@ -0,0 +1,80 @@
+// TITLE("Jump to Unwind")
+//++
+//
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// otsuwind.s
+//
+// Abstract:
+//
+// This module implements the Alpha C8/GEM compiler specific routine to
+// jump to the runtime library unwind routine.
+//
+// Author:
+//
+// Thomas Van Baak (tvb) 30-Apr-1992
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksalpha.h"
+
+ SBTTL("Jump to Unwind - GEM version")
+//++
+//
+// VOID
+// _OtsUnwindRfp (
+// IN PVOID TargetRealFrame OPTIONAL,
+// IN PVOID TargetPc OPTIONAL,
+// IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
+// IN PVOID ReturnValue
+// )
+//
+// Routine Description:
+//
+// This function transfers control to unwind. It is used by the GEM
+// compiler when a non-local goto occurs and structured exception handling
+// is not involved. The unwind routine called is the variant that expects
+// a real frame pointer instead of the usual virtual frame pointer.
+//
+// Arguments:
+//
+// TargetRealFrame (a0) - Supplies an optional pointer to the call frame
+// that is the target of the unwind. If this parameter is not specified,
+// then an exit unwind is performed.
+//
+// TargetPc (a1) - Supplies an optional target instruction address where
+// control is to be transferred to after the unwind operation is
+// complete. This address is ignored if the target frame parameter is
+// not specified.
+//
+// ExceptionRecord (a2) - Supplies an optional pointer to an exception
+// record.
+//
+// ReturnValue (a3) - Supplies a value that is to be placed in the integer
+// function return register just before continuing execution.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(_OtsUnwindRfp)
+
+//
+// All four arguemnts are the same as those required by unwind. Just jump to
+// the unwind function. This thunk is necessary to avoid name space pollution.
+// The compiler should not generate a call directly to RtlUnwindRfp.
+//
+
+ br zero, RtlUnwindRfp // unwind to specified target
+
+ .end _OtUnwindRfp
diff --git a/private/crt32/misc/alpha/scmpeql.s b/private/crt32/misc/alpha/scmpeql.s
new file mode 100644
index 000000000..2d9f82fcc
--- /dev/null
+++ b/private/crt32/misc/alpha/scmpeql.s
@@ -0,0 +1,295 @@
+ #++
+ #
+ # Copyright (c) 1993 by
+ # Digital Equipment Corporation, Maynard, MA
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+
+ # Facility:
+ #
+ # GEM/OTS - GEM compiler system support library
+ #
+ # Abstract:
+ #
+ # OTS character string support, Alpha version
+ #
+ # Authors:
+ #
+ # Bill Noyce
+ #
+ #
+ # long ots_strcmp_eqls(char *str1, long strlen, char *str2);
+ # compares two strings of the same length.
+ # returns r0=1 if str1=str2, r0=0 otherwise.
+
+ # long ots_strcmp_eql(char *str1, long str1len, char *str2, long str2len);
+ # compares two strings of different lengths, without padding.
+ # returns r0=1 if str1=str2, r0=0 otherwise.
+ #
+ # Special conventions: No stack space, r16-r21 and r27-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # Modification history:
+ #
+ # 005 27 Aug 1991 WBN Initial version, replacing BLISS -004
+ #
+ # 006 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 007 22 Sep 1992 KDG Add case-sensitive name
+ #
+ # 008 26 Jan 1993 KDG Add underscore
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 --> A
+ # r17 = len
+ # r18 --> B
+ # returns r0=1 if equal, r0=0 if not equal
+ # destroys r16-r21, r27-r28
+
+ #.align octa
+ .globl _OtsStringCompareEqlSameLen
+ .ent _OtsStringCompareEqlSameLen
+_OtsStringCompareEqlSameLen:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+ subq r17, 8, r19 # More than 8 bytes to compare?
+ beq r17, equal # Done if empty strings
+
+join: ldq_u r20, (r16) # Get first QW containing part of A
+ addq r18, r17, r27 # Point to end of B
+
+ ldq_u r21, (r18) # Get first QW containing part of B
+ bgt r19, big # Skip if more than 8 bytes
+
+ ldq_u r27, -1(r27) # Get last QW containing part of B
+ addq r16, r17, r28 # Point to end of A
+
+ extql r20, r16, r20 # Get first part of A
+
+ ldq_u r28, -1(r28) # Get last QW containing part of A
+
+ extql r21, r18, r21 # Get first part of B
+
+ extqh r27, r18, r27 # Get last part of B
+
+ extqh r28, r16, r28 # Get last part of A
+
+ or r21, r27, r27 # Combine B
+
+ or r20, r28, r28 # Combine A
+
+ xor r28, r27, r0 # Are they different?
+
+ extqh r0, r19, r0 # Discard differences after length
+
+ nop
+
+ cmpeq r0, 0, r0 # Return 1 or 0 as xor=0 or not
+ ret r31, (r26)
+
+equal: mov 1, r0 # Return true
+ ret r31, (r26)
+
+ # r16 --> A
+ # r17 = A_len
+ # r18 --> B
+ # r19 = B_len
+ # returns r0=1 if equal, r0=0 if not equal
+ # destroys r16-r21, r27-r28
+ #
+ nop #.align octa
+ nop
+
+ .globl _OtsStringCompareEql
+ .aent _OtsStringCompareEql
+_OtsStringCompareEql:
+ .frame sp,0,r26
+ cmpeq r17, r19, r0 # Are lengths equal?
+ beq r17, done # If one is zero, no compares needed
+
+ subq r17, 8, r19 # More than 8 bytes to compare?
+ blbs r0, join # Only compare if lengths equal
+
+done: ret r31, (r26) # Return result of length comparison
+
+ #.odd
+big: and r16, 7, r0 # A alignment, or amount not compared
+
+ subq r18, r0, r18 # Back up B pointer that much
+
+ and r18, 7, r17 # Is B now aligned?
+
+ addq r19, r0, r19 # (Len-8+align) is amount left to do
+ ldq_u r27, 8(r18) # Get next QW of B
+
+ subq r19, 16, r19 # More than 2 QW's left?
+ bne r17, unalign # Skip if B alignment doesn't match
+
+ xor r20, r21, r0 # Compare first (partial) QW
+ ldq_u r28, 8(r16) # Get next QW of A
+
+ mskqh r0, r16, r0 # Discard junk preceding strings
+ ble r19, bottom # Skip if two quadwords or less to go
+
+ # stall
+
+loop: ldq_u r20, 16(r16) # Get yet another QW of A
+ bne r0, not_eq # Done if difference in prior compare
+
+ xor r28, r27, r0 # Compare prior QW's
+ ldq r21, 16(r18) # Get yet another QW of B
+
+ subq r19, 16, r19 # Decrement length
+ bne r0, not_eq # Done if difference in this compare
+
+ ldq r27, 24(r18) # Get next QW of B
+ addq r18, 16, r18 # Increment pointer
+
+ ldq_u r28, 24(r16) # Get next QW of A
+ addq r16, 16, r16 # Increment pointer
+
+ xor r20, r21, r0 # Compare QW's loaded at top of loop
+ bgt r19, loop # Repeat until two or less QWs left
+
+bottom: addq r19, 8, r19 # More than 1 QW left?
+ bne r0, not_eq # Done if difference in prior compare
+
+ xor r28, r27, r0 # Compare QW's just loaded
+ ble r19, last # Skip if this is last compare
+
+ ldq_u r28, 16(r16) # Get last QW of A
+ bne r0, not_eq # Done if difference in this compare
+
+ ldq r27, 16(r18) # Get last QW of B
+
+ #2 stalls
+
+ xor r28, r27, r0 # Compare last QW's
+
+last: extqh r0, r19, r0 # Discard diffs after length
+
+ nop
+
+ cmpeq r0, 0, r0 # Return 1 or 0 as xor=0 or not
+ ret r31, (r26)
+
+ #.align quad
+unalign:
+ extql r21, r18, r21 # Get first part of B
+
+ extqh r27, r18, r0 # Get second part of B
+
+ #stall
+
+ or r0, r21, r21 # Combine pieces of B
+
+ xor r20, r21, r0 # Compare with A
+
+ mskqh r0, r16, r0 # Trim junk preceding strings
+ blt r19, bott_u # Skip if fewer than 16 bytes left
+
+loop_u: ldq_u r21, 16(r18) # Get more B
+ subq r19, 16, r19 # Decrement length
+
+ extql r27, r18, r17 # Get piece of B from prior QW
+ bne r0, not_eq # Done if r1.ne.r2
+
+ ldq_u r27, 24(r18) # Get still more B
+ addq r18, 16, r18 # Increment B pointer
+
+ ldq_u r28, 8(r16) # Get more A
+ extqh r21, r18, r0 # Get piece of B from first QW in loop
+
+ ldq_u r20, 16(r16) # Get still more A
+ extql r21, r18, r21 # Get second piece of B from there
+
+ or r17, r0, r17 # Combine pieces for first B
+
+ xor r28, r17, r0 # Compare with first A
+
+ extqh r27, r18, r17 # Start building second B
+ bne r0, not_eq # Done if r28.ne.r17
+
+ addq r16, 16, r16 # Increment A pointer
+
+ or r17, r21, r21 # Combine pieces for second B
+
+ xor r20, r21, r0 # Compare with second A
+ bge r19, loop_u # Repeat if at least 16 more bytes
+
+bott_u: and r19, 8, r17 # At least 8 more bytes?
+ bne r0, not_eq # Done if r1.ne.r2
+
+ and r19, 7, r19 # How many odd bytes?
+ beq r17, last_u # Skip if not a whole QW
+
+ extql r27, r18, r17 # Get a piece of B
+ ldq_u r27, 16(r18) # Load another QW of B
+
+ addq r18, 8, r18 # Increment B pointer
+ ldq_u r28, 8(r16) # Load another QW of A
+
+ addq r16, 8, r16 # Increment A pointer
+
+ extqh r27, r18, r0 # Get a piece of new B QW
+
+ #stall
+
+ or r17, r0, r17 # Combine pieces
+
+ xor r28, r17, r0 # Compare with A
+
+ nop
+ bne r0, not_eq # Done if r28.ne.r17
+
+last_u: addq r18, r19, r17 # Point to end of B
+ beq r19, eql_u # Return true if no more bytes
+
+ ldq_u r28, 8(r16) # Get last QW of A
+
+ ldq_u r20, 7(r17) # Get QW containing end of B
+
+ extql r27, r18, r27 # Get piece of prior B QW
+
+ #stall
+
+ extqh r20, r18, r0 # Get a piece of last B QW
+
+ #stall
+
+ or r27, r0, r27 # Combine
+
+ xor r28, r27, r0 # Compare with A
+
+ mskql r0, r19, r0 # Discard diffs after strings
+
+ nop
+
+eql_u: cmpeq r0, 0, r0 # Return 1 or 0 as xor=0 or not
+ ret r31, (r26)
+
+
+not_eq: clr r0 # Return false
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsStringCompareEqlSameLen
diff --git a/private/crt32/misc/alpha/scmpeqlp.s b/private/crt32/misc/alpha/scmpeqlp.s
new file mode 100644
index 000000000..85836d587
--- /dev/null
+++ b/private/crt32/misc/alpha/scmpeqlp.s
@@ -0,0 +1,443 @@
+ #++
+ #
+ # Copyright (c) 1993 by
+ # Digital Equipment Corporation, Maynard, MA
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+
+ # Facility:
+ #
+ # GEM/OTS - GEM compiler system support library
+ #
+ # Abstract:
+ #
+ # OTS character string support, Alpha version
+ #
+ # Authors:
+ #
+ # Bill Noyce
+ #
+ #
+ # long ots_strcmp_eqlp(char *str1, long str1len,
+ # char *str2, long str2len, char pad);
+ # compares two strings of different lengths with padding.
+ # returns r0=1 if str1=str2, r0=0 otherwise.
+ #
+ # Special conventions: No stack space, r16-r22 and r27-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # Modification history:
+ #
+ # 006 28 May 1992 WBN Initial version, replacing BLISS -005
+ #
+ # 007 22 Sep 1992 KDG Add case-sensitive name
+ #
+ # 008 26 Jan 1993 KDG Add underscore
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 --> A
+ # r17 = A_len
+ # r18 --> B
+ # r19 = B_len
+ # r20 = pad
+ # returns r0=1 if strings equal, r0=0 if not equal
+ # destroys r16-r22, r27-r28
+ #
+ .globl _OtsStringCompareEqlPadded
+ .ent _OtsStringCompareEqlPadded
+_OtsStringCompareEqlPadded:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+
+ subq r17, r19, r21 # A length - B length
+ beq r17, a_empty # If A empty, go compare B with pad
+
+ cmovgt r21, r19, r17 # R17 = min length
+ ldq_u r0, (r16) # Get first QW of A
+
+ sll r20, 8, r28 # Start replicating pad
+ beq r19, b_empty # If B empty, go compare A with pad
+
+ subq r17, 8, r17 # Is min length > 8?
+ ldq_u r19, (r18) # Get first QW of B
+
+ or r20, r28, r20 # Pad in bytes 0,1 of R20
+ bgt r17, big # Go handle strings > 8 bytes
+
+ addq r18, r17, r18 # Point to end of B
+ addq r16, r17, r16 # Point to end of A
+
+ extql r0, r16, r0 # Position start of string A
+ ldq_u r27, 7(r18) # Get end of string B
+
+ extql r19, r18, r19 # Position start of string B
+ ldq_u r28, 7(r16) # Get end of string A
+
+ subq r31, r17, r17 # R17 = 8 - length
+ extqh r27, r18, r27 # Position end of string B
+
+ extqh r28, r16, r28 # Position end of string A
+ or r19, r27, r19 # Combine parts of B
+
+ or r0, r28, r28 # Combine parts of A
+ xor r28, r19, r27 # Are they different?
+
+ mskqh r27, r17, r27 # Clear off diffs preceding strings
+ sll r20, 16, r19 # Replicate pad while waiting
+
+ clr r0 # Prepare to return false
+ beq r27, eq_so_far # Skip if entire min_length matched
+
+ ret r31, (r26) # Strings differ, return false
+
+ # Come here if min length > 8
+ #
+ # r0 = first QW of A
+ # r16 -> A
+ # r17 = min length - 8
+ # r18 -> B
+ # r19 = first QW of B
+ # r20 = pad in bytes 0,1
+ # r21 = A length - B length
+ # r22
+ # r27
+ # r28
+ #
+ #.odd
+big: and r16, 7, r28 # A alignment, or amount not compared
+
+ subq r18, r28, r18 # Back up B pointer that much
+
+ addq r17, r28, r17 # (Len-8+align) is amount left to do
+
+ and r18, 7, r22 # Is B now aligned?
+ ldq_u r27, 8(r18) # Get next QW of B
+
+ subq r17, 16, r17 # More than 2 QW's left?
+ bne r22, unalign # Skip if B alignment doesn't match
+
+ xor r0, r19, r22 # Compare first (partial) QW
+ ldq_u r28, 8(r16) # Get next QW of A
+
+ mskqh r22, r16, r22 # Discard junk preceding strings
+ ble r17, bottom # Skip if two quadwords or less to go
+
+ # stall
+
+loop: bne r22, neq # Done if difference in prior compare
+ ldq_u r0, 16(r16) # Get yet another QW of A
+
+ xor r28, r27, r22 # Compare prior QW's
+ ldq r19, 16(r18) # Get yet another QW of B
+
+ subq r17, 16, r17 # Decrement length
+ bne r22, neq # Done if difference in this compare
+
+ ldq r27, 24(r18) # Get next QW of B
+ addq r18, 16, r18 # Increment pointer
+
+ ldq_u r28, 24(r16) # Get next QW of A
+ addq r16, 16, r16 # Increment pointer
+
+ xor r0, r19, r22 # Compare QW's loaded at top of loop
+ bgt r17, loop # Repeat until two or less QWs left
+
+bottom: addq r17, 8, r19 # More than 1 QW left?
+ bne r22, neq # Done if difference in prior compare
+
+ andnot r16, 7, r16 # Get actual A pointer
+ ble r19, last # Skip if this is last compare
+
+ xor r28, r27, r22 # Compare QW's just loaded
+ ldq r27, 16(r18) # Get last QW of B
+
+ bne r22, neq # Done if difference in this compare
+ ldq r28, 16(r16) # Get last QW of A
+
+ mov r17, r19
+
+ nop
+
+last: xor r28, r27, r22 # Compare last QW's
+ beq r19, ck_last
+
+ mskql r22, r19, r22 # Discard diffs after length
+
+ck_last:
+ bne r22, neq # See which is greater
+
+ addq r17, 16, r17 # Get actual remaining length
+ sll r20, 16, r19 # Start shifting pad some more
+
+ addq r16, r17, r16 # Point to end-8 of each string
+ addq r18, r17, r18
+
+ # Come here if strings match thru min_length
+ #
+ # r0
+ # r16 -> A[min_length-8] (8 before first uncompared byte of A)
+ # r17
+ # r18 -> B[min_length-8] (8 before first uncompared byte of B)
+ # r19 = pad in bytes 2,3
+ # r20 = pad in bytes 0,1
+ # r21 = A length - B length
+ # r22
+ # r27
+ # r28
+ #
+eq_so_far:
+ or r20, r19, r27 # Pad in bytes 0-3
+ beq r21, equal # Strings same length, return equal
+
+ sll r27, 32, r0 # Replicate pad some more
+ blt r21, b_longer # Go compare pad with B
+
+ and r16, 7, r17 # Alignment of remaining A
+ ldq_u r28, 8(r16) # Get first data to compare with pad
+
+ subq r21, 8, r21 # Length - 8
+ or r27, r0, r27 # Pad in bytes 0-7
+
+ addq r21, r17, r21 # Remaining length after this QW
+ xor r28, r27, r22 # Compare A QW with pad
+
+ mskqh r22, r16, r22 # Discard bytes preceding end of B
+ ble r21, a_last # Skip if this is last QW
+
+ ldq_u r0, 16(r16) # Get QW 2 of A
+ subq r21, 16, r21 # Are there two more QW's?
+
+ ble r21, a_bot # Skip loop if not
+a_pad: bne r22, neq # Exit if diff in R28
+
+ ldq_u r28, 24(r16) # Get next QW of A
+ xor r0, r27, r22 # Check prior QW
+
+ subq r21, 16, r21 # 2 more QW's?
+ bne r22, neq # Exit if diff in R0
+
+ ldq_u r0, 32(r16) # Get next QW of A
+ addq r16, 16, r16 # Update pointer
+
+ xor r28, r27, r22 # Compare prior QW
+ bgt r21, a_pad # Repeat if more to compare
+
+a_bot: addq r21, 8, r21 # Another QW?
+ bne r22, neq # Exit if diff in R28
+
+ mov r0, r28 # Move this QW to common location
+ ble r21, a_skip # Skip if this is last QW
+
+ ldq_u r28, 24(r16) # Next QW of A
+ xor r0, r27, r22 # Compare prior QW
+
+ subq r21, 8, r21
+ bne r22, neq # Exit if diff in R0
+
+a_skip: xor r28, r27, r22 # Compare last QW
+a_last: beq r21, a_end # Can't use MSKQL if whole QW
+
+ mskql r22, r21, r22 # Keep only up to end of string
+ nop
+
+a_end: cmpeq r22, 0, r0 # Return 1/0 for strings equal/not
+ ret r31, (r26)
+
+ # Come here if A is nonempty, but B is empty.
+ #
+b_empty:
+ subq r16, 8, r16 # Back up A pointer as expected
+ or r20, r28, r20 # Pad in bytes 0-1
+
+ sll r20, 16, r19
+ br r31, eq_so_far # Go compare A with pad
+
+ # Come here if A is empty (B might be empty too).
+ #
+ nop #.odd
+a_empty:
+ sll r20, 8, r28 # Start replicating pad
+
+ subq r18, 8, r18 # Back up B pointer as expected
+ beq r19, equal # Done if both strings empty
+
+ or r20, r28, r20 # Pad in bytes 0-1
+ sll r20, 16, r0
+
+ or r20, r0, r27 # Pad in bytes 0-3
+ sll r27, 32, r0
+
+b_longer:
+ and r18, 7, r17 # Alignment of remaining B
+ ldq_u r28, 8(r18) # Get first data to compare with pad
+
+ addq r21, 8, r21 # - Length + 8
+ or r27, r0, r0 # Pad in bytes 0-7
+
+ subq r17, r21, r21 # Remaining length after this QW
+ xor r0, r28, r22 # Compare B QW with pad
+
+ mskqh r22, r18, r22 # Discard bytes preceding end of A
+ ble r21, b_last # Skip if last QW
+
+ ldq_u r19, 16(r18) # Get QW 2 of B
+ subq r21, 16, r21 # Two more QW's?
+
+ ble r21, b_bot # Skip if not
+b_pad: bne r22, neq # Exit if diff in r28
+
+ ldq_u r28, 24(r18) # Get next QW of B
+ xor r0, r19, r22 # Check prior QW
+
+ subq r21, 16, r21 # 2 more QW's?
+ bne r22, neq # Exit if diff in R19
+
+ ldq_u r19, 32(r18) # Get next QW of B
+ addq r18, 16, r18 # Update pointer
+
+ xor r0, r28, r22 # Compare prior QW
+ bgt r21, b_pad # Repeat if more to compare
+
+b_bot: addq r21, 8, r21 # Another QW?
+ bne r22, neq # Exit if diff in R28
+
+ xor r0, r19, r22 # Check another QW
+ ble r21, b_last # Skip if that's the last one
+
+ ldq_u r28, 24(r18) # Fetch another QW
+ bne r22, neq # Exit if diff in R19
+
+ subq r21, 8, r21
+ nop
+
+ xor r0, r28, r22 # Check that QW
+b_last: beq r21, b_end # Can't use MSKQL if whole QW
+
+ mskql r22, r21, r22 # Keep only up to end of B
+ nop
+
+b_end: cmpeq r22, 0, r0 # Return 1/0 as strings equal/not
+ ret r31, (r26)
+
+equal: mov 1, r0 # Strings equal, return true
+ ret r31, (r26)
+
+ #.align quad
+unalign:
+ extql r19, r18, r19 # Get first part of B
+
+ extqh r27, r18, r22 # Get second part of B
+
+ #stall
+
+ or r22, r19, r19 # Combine pieces of B
+
+ xor r0, r19, r22 # Compare with A
+
+ mskqh r22, r16, r22 # Trim junk preceding strings
+ blt r17, bott_u # Skip if fewer than 16 bytes left
+
+loop_u: ldq_u r19, 16(r18) # Get more B
+ subq r17, 16, r17 # Decrement length
+
+ bne r22, neq # Done if r0.ne.r19
+ extql r27, r18, r0 # Get piece of B from prior QW
+
+ ldq_u r27, 24(r18) # Get still more B
+ addq r18, 16, r18 # Increment B pointer
+
+ ldq_u r28, 8(r16) # Get more A
+ extqh r19, r18, r22 # Get piece of B from first QW in loop
+
+ extql r19, r18, r19 # Get second piece of B from there
+
+ or r0, r22, r22 # Combine pieces for first B
+
+ ldq_u r0, 16(r16) # Get still more A
+ xor r28, r22, r22 # Compare with first A
+
+ bne r22, neq # Done if r28.ne.r22
+ extqh r27, r18, r22 # Start building second B
+
+ addq r16, 16, r16 # Increment A pointer
+
+ or r22, r19, r19 # Combine pieces for second B
+
+ xor r0, r19, r22 # Compare with second A
+ bge r17, loop_u # Repeat if at least 16 more bytes
+
+bott_u: and r17, 8, r28 # At least 8 more bytes?
+ bne r22, neq # Done if r0.ne.r19
+
+ and r17, 7, r17 # How many odd bytes?
+ beq r28, last_u # Skip if not a whole QW
+
+ extql r27, r18, r0 # Get a piece of B
+ ldq_u r27, 16(r18) # Load another QW of B
+
+ addq r18, 8, r18 # Increment B pointer
+ ldq_u r28, 8(r16) # Load another QW of A
+
+ addq r16, 8, r16 # Increment A pointer
+
+ extqh r27, r18, r22 # Get a piece of new B QW
+
+ # stall
+
+ or r0, r22, r0 # Combine pieces
+
+ xor r28, r0, r22 # Compare with A
+
+ bne r22, neq # Done if r28.ne.r0
+
+last_u: andnot r16, 7, r16 # What's the real address of A?
+
+ sll r20, 16, r19 # Start replicating pad
+ beq r17, eq_so_far # Check padding if no more bytes
+
+ ldq_u r28, 8(r16) # Get last QW of A
+ addq r18, r17, r0 # Point to end-8 of B
+
+ ldq_u r0, 7(r0) # Get QW containing end of B
+ extql r27, r18, r27 # Get piece of prior B QW
+
+ addq r16, r17, r16 # Point to end-8 of A
+
+ extqh r0, r18, r22 # Get a piece of last B QW
+
+ addq r18, r17, r18 # Point to end-8 of B
+
+ or r27, r22, r27 # Combine
+
+ xor r28, r27, r22 # Compare with A
+
+ mskql r22, r17, r22 # Discard diffs after strings
+
+ nop
+
+ beq r22, eq_so_far # If still equal, go check pad
+
+neq: clr r0 # Return false
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsStringCompareEqlPadded
diff --git a/private/crt32/misc/alpha/scmpleq.s b/private/crt32/misc/alpha/scmpleq.s
new file mode 100644
index 000000000..6370ac284
--- /dev/null
+++ b/private/crt32/misc/alpha/scmpleq.s
@@ -0,0 +1,338 @@
+ #++
+ #
+ # Copyright (c) 1993 by
+ # Digital Equipment Corporation, Maynard, MA
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+
+ # Facility:
+ #
+ # GEM/OTS - GEM compiler system support library
+ #
+ # Abstract:
+ #
+ # OTS character string support, Alpha version
+ #
+ # Authors:
+ #
+ # Bill Noyce
+ #
+ #
+ # long ots_strcmp_leqs(char *str1, long strlen, char *str2);
+ # compares two strings of the same length.
+ # returns r0=1 if str1<=str2, r0=0 otherwise.
+ #
+ # long ots_strcmp_leq(char *str1, long str1len, char *str2, long str2len);
+ # compares two strings of different lengths without padding.
+ # returns r0=1 if str1<=str2, r0=0 otherwise.
+ #
+ # Special conventions: No stack space, r16-r21 and r27-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # Modification history:
+ #
+ # 005 27 Aug 1991 WBN Initial version, replacing BLISS -004
+ #
+ # 006 29 Jan 1992 WBN Use .otsent macro
+ #
+ # 007 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 008 22 Sep 1992 KDG Add case-sensitive name
+ #
+ # 009 26 Jan 1993 KDG Add underscore
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 --> A
+ # r17 = A_len
+ # r18 --> B
+ # r19 = B_len
+ # returns r0=1 if A less/equal, r0=0 if A greater
+ # destroys r16-r21, r27-r28
+ #
+ .globl _OtsStringCompareLeq
+ .ent _OtsStringCompareLeq
+_OtsStringCompareLeq:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+
+ subq r17, r19, r21 # A_len - B_len
+ cmovgt r21, r19, r17 # r17 = min length
+ br r31, join
+
+ # r16 --> A
+ # r17 = len
+ # r18 --> B
+ # returns r0=1 if A less/equal, r0=0 if A greater
+ # destroys r16-r21, r27-r28
+ #
+ .globl _OtsStringCompareLeqSameLen
+ .aent _OtsStringCompareLeqSameLen
+_OtsStringCompareLeqSameLen:
+ .frame sp,0,r26
+
+ clr r21 # Lengths are equal
+
+join: subq r17, 8, r19 # More than 8 bytes to compare?
+ beq r17, equal # Done if empty strings
+
+ ldq_u r20, (r16) # Get first QW containing part of A
+ addq r18, r17, r27 # Point to end of B
+
+ ldq_u r17, (r18) # Get first QW containing part of B
+ bgt r19, big # Skip if more than 8 bytes
+
+ ldq_u r27, -1(r27) # Get last QW containing part of B
+ addq r16, r19, r28 # Point to end of A
+
+ extql r20, r16, r20 # Get first part of A
+
+ ldq_u r28, 7(r28) # Get last QW containing part of A
+
+ extql r17, r18, r17 # Get first part of B
+
+ extqh r27, r18, r27 # Get last part of B
+
+ extqh r28, r16, r28 # Get last part of A
+
+ or r17, r27, r27 # Combine B
+
+ or r20, r28, r28 # Combine A
+
+ xor r28, r27, r0 # Are they different?
+
+ beq r19, ck_leq
+ mskql r0, r19, r0 # Discard differences after length
+
+ #stall
+
+ck_leq: cmpbge r31, r0, r17 # Where is B = A?
+ beq r0, equal # (Skip if they're equal?)
+
+ cmpbge r27, r28, r28 # Where is B >= A?
+
+ addq r17, 1, r0 # Flip first difference
+
+ andnot r28, r17, r28 # Where is B > A?
+
+ and r28, r0, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ #.odd
+big: and r16, 7, r28 # A alignment, or amount not compared
+
+ subq r18, r28, r18 # Back up B pointer that much
+
+ and r18, 7, r0 # Is B now aligned?
+
+ addq r19, r28, r19 # (Len-8+align) is amount left to do
+ ldq_u r27, 8(r18) # Get next QW of B
+
+ subq r19, 16, r19 # More than 2 QW's left?
+ bne r0, unalign # Skip if B alignment doesn't match
+
+ xor r20, r17, r0 # Compare first (partial) QW
+ ldq_u r28, 8(r16) # Get next QW of A
+
+ mskqh r0, r16, r0 # Discard junk preceding strings
+ ble r19, bottom # Skip if two quadwords or less to go
+
+ # stall
+
+loop: bne r0, neq_2017 # Done if difference in prior compare
+ ldq_u r20, 16(r16) # Get yet another QW of A
+
+ xor r28, r27, r0 # Compare prior QW's
+ ldq r17, 16(r18) # Get yet another QW of B
+
+ subq r19, 16, r19 # Decrement length
+ bne r0, neq_2827 # Done if difference in this compare
+
+ ldq r27, 24(r18) # Get next QW of B
+ addq r18, 16, r18 # Increment pointer
+
+ ldq_u r28, 24(r16) # Get next QW of A
+ addq r16, 16, r16 # Increment pointer
+
+ xor r20, r17, r0 # Compare QW's loaded at top of loop
+ bgt r19, loop # Repeat until two or less QWs left
+
+bottom: addq r19, 8, r19 # More than 1 QW left?
+ bne r0, neq_2017 # Done if difference in prior compare
+
+ xor r28, r27, r0 # Compare QW's just loaded
+ ble r19, last # Skip if this is last compare
+
+ bne r0, neq_2827 # Done if difference in this compare
+ ldq_u r28, 16(r16) # Get last QW of A
+
+ ldq r27, 16(r18) # Get last QW of B
+ subq r19, 8, r19
+
+ #2 stalls
+
+ xor r28, r27, r0 # Compare last QW's
+last: beq r19, ck_last
+
+ mskql r0, r19, r0 # Discard diffs after length
+
+ck_last:
+ bne r0, neq_2827 # See which is greater
+
+equal: cmple r21, r31, r0 # Equal: return A_len <= B_len
+ ret r31, (r26)
+
+ #.align quad
+unalign:
+ extql r17, r18, r17 # Get first part of B
+
+ extqh r27, r18, r0 # Get second part of B
+
+ #stall
+
+ or r0, r17, r17 # Combine pieces of B
+
+ xor r20, r17, r0 # Compare with A
+
+ mskqh r0, r16, r0 # Trim junk preceding strings
+ blt r19, bott_u # Skip if fewer than 16 bytes left
+
+loop_u: ldq_u r17, 16(r18) # Get more B
+ subq r19, 16, r19 # Decrement length
+
+ bne r0, neq_20xx # Done if r20.ne.r17
+ extql r27, r18, r20 # Get piece of B from prior QW
+
+ ldq_u r27, 24(r18) # Get still more B
+ addq r18, 16, r18 # Increment B pointer
+
+ ldq_u r28, 8(r16) # Get more A
+ extqh r17, r18, r0 # Get piece of B from first QW in loop
+
+ extql r17, r18, r17 # Get second piece of B from there
+
+ or r20, r0, r0 # Combine pieces for first B
+
+ ldq_u r20, 16(r16) # Get still more A
+ xor r28, r0, r0 # Compare with first A
+
+ bne r0, neq_28xx # Done if r28.ne.r0
+ extqh r27, r18, r0 # Start building second B
+
+ addq r16, 16, r16 # Increment A pointer
+
+ or r0, r17, r17 # Combine pieces for second B
+
+ xor r20, r17, r0 # Compare with second A
+ bge r19, loop_u # Repeat if at least 16 more bytes
+
+bott_u: and r19, 8, r28 # At least 8 more bytes?
+ bne r0, neq_2017 # Done if r20.ne.r17
+
+ and r19, 7, r19 # How many odd bytes?
+ beq r28, last_u # Skip if not a whole QW
+
+ extql r27, r18, r20 # Get a piece of B
+ ldq_u r27, 16(r18) # Load another QW of B
+
+ addq r18, 8, r18 # Increment B pointer
+ ldq_u r28, 8(r16) # Load another QW of A
+
+ addq r16, 8, r16 # Increment A pointer
+
+ extqh r27, r18, r0 # Get a piece of new B QW
+
+ #stall
+
+ or r20, r0, r20 # Combine pieces
+
+ xor r28, r20, r0 # Compare with A
+
+ nop
+ bne r0, neq_28xx # Done if r28.ne.r20
+
+last_u: addq r18, r19, r17 # Point to end of B
+ beq r19, eql_u # Check length diff if no more bytes
+
+ ldq_u r28, 8(r16) # Get last QW of A
+
+ ldq_u r20, 7(r17) # Get QW containing end of B
+
+ extql r27, r18, r27 # Get piece of prior B QW
+
+ #stall
+
+ extqh r20, r18, r0 # Get a piece of last B QW
+
+ #stall
+
+ or r27, r0, r27 # Combine
+
+ xor r28, r27, r0 # Compare with A
+
+ mskql r0, r19, r0 # Discard diffs after strings
+
+ #stall
+
+ beq r0, eql_u # Done if they're still equal
+
+ #.align quad
+neq_28xx:
+ xor r28, r0, r27 # Recover B from A and xor
+neq_2827:
+ cmpbge r31, r0, r17 # Where is B = A?
+
+ cmpbge r27, r28, r20 # Where is B >= A?
+
+ addq r17, 1, r0 # Flip first difference
+
+ andnot r20, r17, r20 # Where is B > A?
+
+ and r20, r0, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ #.align quad
+neq_20xx:
+ xor r20, r0, r17 # Recover B from A and xor
+neq_2017:
+ cmpbge r31, r0, r27 # Where is B = A?
+
+ cmpbge r17, r20, r20 # Where is B >= A?
+
+ addq r27, 1, r0 # Flip first difference
+
+ andnot r20, r27, r20 # Where is B > A?
+
+ and r20, r0, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+
+eql_u: cmple r21, r31, r0 # Equal: return A_len <= B_len
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsStringCompareLeq
diff --git a/private/crt32/misc/alpha/scmpleqp.s b/private/crt32/misc/alpha/scmpleqp.s
new file mode 100644
index 000000000..b58fe2907
--- /dev/null
+++ b/private/crt32/misc/alpha/scmpleqp.s
@@ -0,0 +1,478 @@
+ #++
+ #
+ # Copyright (c) 1993 by
+ # Digital Equipment Corporation, Maynard, MA
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+
+ # Facility:
+ #
+ # GEM/OTS - GEM compiler system support library
+ #
+ # Abstract:
+ #
+ # OTS character string support, Alpha version
+ #
+ # Authors:
+ #
+ # Bill Noyce
+ #
+ #
+ # long ots_strcmp_leqp(char *str1, long str1len,
+ # char *str2, long str2len, char pad);
+ # compares two strings of different lengths with padding.
+ # returns r0=1 if str1<=str2, r0=0 otherwise.
+ #
+ # Special conventions: No stack space, r16-r22 and r27-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # Modification history:
+ #
+ # 006 28 May 1992 WBN Initial version, replacing BLISS -005
+ #
+ # 007 22 Sep 1992 KDG Add case-sensitive name
+ #
+ # 008 26 Jan 1993 KDG Add underscore
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 --> A
+ # r17 = A_len
+ # r18 --> B
+ # r19 = B_len
+ # r20 = pad
+ # returns r0=1 if A less/equal, r0=0 if A greater
+ # destroys r16-r22, r27-r28
+ #
+ .globl _OtsStringCompareLeqPadded
+ .ent _OtsStringCompareLeqPadded
+_OtsStringCompareLeqPadded:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+
+ subq r17, r19, r21 # A length - B length
+ beq r17, a_empty # If A empty, go compare B with pad
+
+ cmovgt r21, r19, r17 # R17 = min length
+ ldq_u r0, (r16) # Get first QW of A
+
+ sll r20, 8, r28 # Start replicating pad
+ beq r19, b_empty # If B empty, go compare A with pad
+
+ subq r17, 8, r17 # Is min length > 8?
+ ldq_u r19, (r18) # Get first QW of B
+
+ or r20, r28, r20 # Pad in bytes 0,1 of R20
+ bgt r17, big # Go handle strings > 8 bytes
+
+ addq r18, r17, r18 # Point to end of B
+ addq r16, r17, r16 # Point to end of A
+
+ extql r0, r16, r0 # Position start of string A
+ ldq_u r27, 7(r18) # Get end of string B
+
+ extql r19, r18, r19 # Position start of string B
+ ldq_u r28, 7(r16) # Get end of string A
+
+ subq r31, r17, r17 # R17 = 8 - length
+ extqh r27, r18, r27 # Position end of string B
+
+ extqh r28, r16, r28 # Position end of string A
+ or r19, r27, r19 # Combine parts of B
+
+ or r0, r28, r28 # Combine parts of A
+ xor r28, r19, r27 # Are they different?
+
+ mskqh r27, r17, r27 # Clear off diffs preceding strings
+ sll r20, 16, r0 # Replicate pad while waiting
+
+ cmpbge r31, r27, r17 # Make 1's where strings matched
+ beq r27, eq_so_far # Skip if entire min_length matched
+
+ cmpbge r19, r28, r19 # Make 1's where B >= A
+ addq r17, 1, r0 # Flip first mismatch
+
+ andnot r19, r17, r19 # 1's where A < B
+ and r19, r0, r0 # nonzero if A < B at first mismatch
+
+ cmovne r0, 1, r0 # 1 if string A < string B
+ ret r31, (r26)
+
+ # Come here if min length > 8
+ #
+ # r0 = first QW of A
+ # r16 -> A
+ # r17 = min length - 8
+ # r18 -> B
+ # r19 = first QW of B
+ # r20 = pad in bytes 0,1
+ # r21 = A length - B length
+ # r22
+ # r27
+ # r28
+ #
+ nop #.odd
+big: and r16, 7, r28 # A alignment, or amount not compared
+
+ subq r18, r28, r18 # Back up B pointer that much
+
+ addq r17, r28, r17 # (Len-8+align) is amount left to do
+
+ and r18, 7, r22 # Is B now aligned?
+ ldq_u r27, 8(r18) # Get next QW of B
+
+ subq r17, 16, r17 # More than 2 QW's left?
+ bne r22, unalign # Skip if B alignment doesn't match
+
+ xor r0, r19, r22 # Compare first (partial) QW
+ ldq_u r28, 8(r16) # Get next QW of A
+
+ mskqh r22, r16, r22 # Discard junk preceding strings
+ ble r17, bottom # Skip if two quadwords or less to go
+
+ # stall
+
+loop: bne r22, neq_019 # Done if difference in prior compare
+ ldq_u r0, 16(r16) # Get yet another QW of A
+
+ xor r28, r27, r22 # Compare prior QW's
+ ldq r19, 16(r18) # Get yet another QW of B
+
+ subq r17, 16, r17 # Decrement length
+ bne r22, neq_2827 # Done if difference in this compare
+
+ ldq r27, 24(r18) # Get next QW of B
+ addq r18, 16, r18 # Increment pointer
+
+ ldq_u r28, 24(r16) # Get next QW of A
+ addq r16, 16, r16 # Increment pointer
+
+ xor r0, r19, r22 # Compare QW's loaded at top of loop
+ bgt r17, loop # Repeat until two or less QWs left
+
+bottom: addq r17, 8, r19 # More than 1 QW left?
+ bne r22, neq_0xx # Done if difference in prior compare
+
+ andnot r16, 7, r16 # Get actual A pointer
+ ble r19, last # Skip if this is last compare
+
+ xor r28, r27, r22 # Compare QW's just loaded
+ ldq r27, 16(r18) # Get last QW of B
+
+ bne r22, neq_28xx # Done if difference in this compare
+ ldq r28, 16(r16) # Get last QW of A
+
+ mov r17, r19
+
+ nop
+
+last: xor r28, r27, r22 # Compare last QW's
+ beq r19, ck_last
+
+ mskql r22, r19, r22 # Discard diffs after length
+
+ck_last:
+ bne r22, neq_2827 # See which is greater
+
+ addq r17, 16, r17 # Get actual remaining length
+ sll r20, 16, r0 # Start shifting pad some more
+
+ addq r16, r17, r16 # Point to end-8 of each string
+ addq r18, r17, r18
+
+ # Come here if strings match thru min_length
+ #
+ # r0 = pad in bytes 2,3
+ # r16 -> A[min_length-8] (8 before first uncompared byte of A)
+ # r17
+ # r18 -> B[min_length-8] (8 before first uncompared byte of B)
+ # r19
+ # r20 = pad in bytes 0,1
+ # r21 = A length - B length
+ # r22
+ # r27
+ # r28
+ #
+eq_so_far:
+ or r20, r0, r27 # Pad in bytes 0-3
+ beq r21, equal # Strings same length, return equal
+
+ sll r27, 32, r0 # Replicate pad some more
+ blt r21, b_longer # Go compare pad with B
+
+ and r16, 7, r17 # Alignment of remaining A
+ ldq_u r28, 8(r16) # Get first data to compare with pad
+
+ subq r21, 8, r21 # Length - 8
+ or r27, r0, r27 # Pad in bytes 0-7
+
+ addq r21, r17, r21 # Remaining length after this QW
+ xor r28, r27, r22 # Compare A QW with pad
+
+ mskqh r22, r16, r22 # Discard bytes preceding end of B
+ ble r21, a_last # Skip if this is last QW
+
+ ldq_u r0, 16(r16) # Get QW 2 of A
+ subq r21, 16, r21 # Are there two more QW's?
+
+ ble r21, a_bot # Skip loop if not
+a_pad: bne r22, neq_2827 # Exit if diff in R28
+
+ ldq_u r28, 24(r16) # Get next QW of A
+ xor r0, r27, r22 # Check prior QW
+
+ subq r21, 16, r21 # 2 more QW's?
+ bne r22, neq_0xx # Exit if diff in R0
+
+ ldq_u r0, 32(r16) # Get next QW of A
+ addq r16, 16, r16 # Update pointer
+
+ xor r28, r27, r22 # Compare prior QW
+ bgt r21, a_pad # Repeat if more to compare
+
+a_bot: addq r21, 8, r21 # Another QW?
+ bne r22, neq_2827 # Exit if diff in R28
+
+ mov r0, r28 # Move this QW to common location
+ ble r21, a_skip # Skip if this is last QW
+
+ ldq_u r28, 24(r16) # Next QW of A
+ xor r0, r27, r22 # Compare prior QW
+
+ subq r21, 8, r21
+ bne r22, neq_0xx # Exit if diff in R0
+
+a_skip: xor r28, r27, r22 # Compare last QW
+a_last: beq r21, a_end # Can't use MSKQL if whole QW
+
+ mskql r22, r21, r22 # Keep only up to end of string
+a_end: bne r22, neq_2827 # Exit if diff in R28
+
+ mov 1, r0 # Strings equal, return true
+ ret r31, (r26)
+
+ # Come here if A is nonempty, but B is empty.
+ #
+b_empty:
+ subq r16, 8, r16 # Back up A pointer as expected
+ or r20, r28, r20 # Pad in bytes 0-1
+
+ sll r20, 16, r0
+ br r31, eq_so_far # Go compare A with pad
+
+ # Come here if A is empty (B might be empty too).
+ #
+ nop #.odd
+a_empty:
+ sll r20, 8, r28 # Start replicating pad
+
+ subq r18, 8, r18 # Back up B pointer as expected
+ beq r19, equal # Done if both strings empty
+
+ or r20, r28, r20 # Pad in bytes 0-1
+ sll r20, 16, r0
+
+ or r20, r0, r27 # Pad in bytes 0-3
+ sll r27, 32, r0
+
+b_longer:
+ and r18, 7, r17 # Alignment of remaining B
+ ldq_u r28, 8(r18) # Get first data to compare with pad
+
+ addq r21, 8, r21 # - Length + 8
+ or r27, r0, r0 # Pad in bytes 0-7
+
+ subq r17, r21, r21 # Remaining length after this QW
+ xor r0, r28, r22 # Compare B QW with pad
+
+ mskqh r22, r18, r22 # Discard bytes preceding end of A
+ ble r21, b_last # Skip if last QW
+
+ ldq_u r19, 16(r18) # Get QW 2 of B
+ subq r21, 16, r21 # Two more QW's?
+
+ ble r21, b_bot # Skip if not
+b_pad: bne r22, neq_0xx # Exit if diff in r28
+
+ ldq_u r28, 24(r18) # Get next QW of B
+ xor r0, r19, r22 # Check prior QW
+
+ subq r21, 16, r21 # 2 more QW's?
+ bne r22, neq_019 # Exit if diff in R19
+
+ ldq_u r19, 32(r18) # Get next QW of B
+ addq r18, 16, r18 # Update pointer
+
+ xor r0, r28, r22 # Compare prior QW
+ bgt r21, b_pad # Repeat if more to compare
+
+b_bot: addq r21, 8, r21 # Another QW?
+ bne r22, neq_0xx # Exit if diff in R28
+
+ xor r0, r19, r22 # Check another QW
+ ble r21, b_last # Skip if that's the last one
+
+ ldq_u r28, 24(r18) # Fetch another QW
+ bne r22, neq_019 # Exit if diff in R19
+
+ subq r21, 8, r21
+ nop
+
+ xor r0, r28, r22 # Check that QW
+b_last: beq r21, b_end # Can't use MSKQL if whole QW
+
+ mskql r22, r21, r22 # Keep only up to end of B
+b_end: bne r22, neq_0xx # Exit if diff seen
+
+equal: mov 1, r0 # Strings equal, return true
+ ret r31, (r26)
+
+ #.align quad
+unalign:
+ extql r19, r18, r19 # Get first part of B
+
+ extqh r27, r18, r22 # Get second part of B
+
+ #stall
+
+ or r22, r19, r19 # Combine pieces of B
+
+ xor r0, r19, r22 # Compare with A
+
+ mskqh r22, r16, r22 # Trim junk preceding strings
+ blt r17, bott_u # Skip if fewer than 16 bytes left
+
+loop_u: ldq_u r19, 16(r18) # Get more B
+ subq r17, 16, r17 # Decrement length
+
+ bne r22, neq_0xx # Done if r0.ne.r19
+ extql r27, r18, r0 # Get piece of B from prior QW
+
+ ldq_u r27, 24(r18) # Get still more B
+ addq r18, 16, r18 # Increment B pointer
+
+ ldq_u r28, 8(r16) # Get more A
+ extqh r19, r18, r22 # Get piece of B from first QW in loop
+
+ extql r19, r18, r19 # Get second piece of B from there
+
+ or r0, r22, r22 # Combine pieces for first B
+
+ ldq_u r0, 16(r16) # Get still more A
+ xor r28, r22, r22 # Compare with first A
+
+ bne r22, neq_28xx # Done if r28.ne.r22
+ extqh r27, r18, r22 # Start building second B
+
+ addq r16, 16, r16 # Increment A pointer
+
+ or r22, r19, r19 # Combine pieces for second B
+
+ xor r0, r19, r22 # Compare with second A
+ bge r17, loop_u # Repeat if at least 16 more bytes
+
+bott_u: and r17, 8, r28 # At least 8 more bytes?
+ bne r22, neq_019 # Done if r0.ne.r19
+
+ and r17, 7, r17 # How many odd bytes?
+ beq r28, last_u # Skip if not a whole QW
+
+ extql r27, r18, r0 # Get a piece of B
+ ldq_u r27, 16(r18) # Load another QW of B
+
+ addq r18, 8, r18 # Increment B pointer
+ ldq_u r28, 8(r16) # Load another QW of A
+
+ addq r16, 8, r16 # Increment A pointer
+
+ extqh r27, r18, r22 # Get a piece of new B QW
+
+ # stall
+
+ or r0, r22, r0 # Combine pieces
+
+ xor r28, r0, r22 # Compare with A
+
+ bne r22, neq_28xx # Done if r28.ne.r0
+
+last_u: andnot r16, 7, r16 # What's the real address of A?
+
+ sll r20, 16, r0 # Start replicating pad
+ beq r17, eq_so_far # Check padding if no more bytes
+
+ ldq_u r28, 8(r16) # Get last QW of A
+ addq r18, r17, r19 # Point to end-8 of B
+
+ ldq_u r19, 7(r19) # Get QW containing end of B
+ extql r27, r18, r27 # Get piece of prior B QW
+
+ addq r16, r17, r16 # Point to end-8 of A
+
+ extqh r19, r18, r22 # Get a piece of last B QW
+
+ addq r18, r17, r18 # Point to end-8 of B
+
+ or r27, r22, r27 # Combine
+
+ xor r28, r27, r22 # Compare with A
+
+ mskql r22, r17, r22 # Discard diffs after strings
+
+ nop
+
+ beq r22, eq_so_far # If still equal, go check pad
+
+ #.align quad
+neq_28xx:
+ xor r28, r22, r27 # Recover B from A and xor
+neq_2827:
+ cmpbge r31, r22, r19 # Where is B = A?
+
+ cmpbge r27, r28, r0 # Where is B >= A?
+
+ addq r19, 1, r22 # Flip first difference
+
+ andnot r0, r19, r0 # Where is B > A?
+
+ and r0, r22, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ #.align quad
+neq_0xx:
+ xor r0, r22, r19 # Recover B from A and xor
+neq_019:
+ cmpbge r31, r22, r27 # Where is B = A?
+
+ cmpbge r19, r0, r0 # Where is B >= A?
+
+ addq r27, 1, r22 # Flip first difference
+
+ andnot r0, r27, r0 # Where is B > A?
+
+ and r0, r22, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsStringCompareLeqPadded
diff --git a/private/crt32/misc/alpha/scmplss.s b/private/crt32/misc/alpha/scmplss.s
new file mode 100644
index 000000000..ab043fb8f
--- /dev/null
+++ b/private/crt32/misc/alpha/scmplss.s
@@ -0,0 +1,339 @@
+ #++
+ #
+ # Copyright (c) 1993 by
+ # Digital Equipment Corporation, Maynard, MA
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+
+ # Facility:
+ #
+ # GEM/OTS - GEM compiler system support library
+ #
+ # Abstract:
+ #
+ # OTS character string support, Alpha version
+ #
+ # Authors:
+ #
+ # Bill Noyce
+ #
+ #
+ # long ots_strcmp_lsss(char *str1, long strlen, char *str2);
+ # compares two strings of the same length.
+ # returns r0=1 if str1<str2, r0=0 otherwise.
+ #
+ # long ots_strcmp_lss(char *str1, long str1len, char *str2, long str2len);
+ # compares two strings of different lengths without padding.
+ # returns r0=1 if str1<str2, r0=0 otherwise.
+ #
+ # Special conventions: No stack space, r16-r21 and r27-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # Modification history:
+ #
+ # 005 27 Aug 1991 WBN Initial version, replacing BLISS -004
+ #
+ # 006 29 Jan 1992 WBN Use .otsent macro
+ #
+ # 007 19 May 1992 KDG Changes for common VMS/OSF sources
+ #
+ # 008 22 Sep 1992 KDG Add case-sensitive name
+ #
+ # 009 26 Jan 1993 KDG Add underscore
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 --> A
+ # r17 = A_len
+ # r18 --> B
+ # r19 = B_len
+ # returns r0=1 if A less, r0=0 if A greater/equal
+ # destroys r16-r21, r27-r28
+ #
+ .globl _OtsStringCompareLss
+ .ent _OtsStringCompareLss
+_OtsStringCompareLss:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+
+ subq r17, r19, r21 # A_len - B_len
+ cmovgt r21, r19, r17 # r17 = min length
+ br r31, join
+
+ # r16 --> A
+ # r17 = len
+ # r18 --> B
+ # returns r0=1 if A less, r0=0 if A greater/equal
+ # destroys r16-r21, r27-r28
+ #
+ .globl _OtsStringCompareLssSameLen
+ .aent _OtsStringCompareLssSameLen
+_OtsStringCompareLssSameLen:
+ .frame sp,0,r26
+
+ clr r21 # Lengths are equal
+
+join: subq r17, 8, r19 # More than 8 bytes to compare?
+ beq r17, equal # Done if empty strings
+
+ ldq_u r20, (r16) # Get first QW containing part of A
+ addq r18, r17, r27 # Point to end of B
+
+ ldq_u r17, (r18) # Get first QW containing part of B
+ bgt r19, big # Skip if more than 8 bytes
+
+ ldq_u r27, -1(r27) # Get last QW containing part of B
+ addq r16, r19, r28 # Point to end of A
+
+ extql r20, r16, r20 # Get first part of A
+
+ ldq_u r28, 7(r28) # Get last QW containing part of A
+
+ extql r17, r18, r17 # Get first part of B
+
+ extqh r27, r18, r27 # Get last part of B
+
+ extqh r28, r16, r28 # Get last part of A
+
+ or r17, r27, r27 # Combine B
+
+ or r20, r28, r28 # Combine A
+
+ xor r28, r27, r0 # Are they different?
+
+ beq r19, ck_leq
+ mskql r0, r19, r0 # Discard differences after length
+
+ #stall
+
+ck_leq: cmpbge r31, r0, r17 # Where is B = A?
+ beq r0, equal # (Skip if they're equal?)
+
+ cmpbge r27, r28, r28 # Where is B >= A?
+
+ addq r17, 1, r0 # Flip first difference
+
+ andnot r28, r17, r28 # Where is B > A?
+
+ and r28, r0, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ #.odd
+big: and r16, 7, r28 # A alignment, or amount not compared
+
+ subq r18, r28, r18 # Back up B pointer that much
+
+ and r18, 7, r0 # Is B now aligned?
+
+ addq r19, r28, r19 # (Len-8+align) is amount left to do
+ ldq_u r27, 8(r18) # Get next QW of B
+
+ subq r19, 16, r19 # More than 2 QW's left?
+ bne r0, unalign # Skip if B alignment doesn't match
+
+ xor r20, r17, r0 # Compare first (partial) QW
+ ldq_u r28, 8(r16) # Get next QW of A
+
+ mskqh r0, r16, r0 # Discard junk preceding strings
+ ble r19, bottom # Skip if two quadwords or less to go
+
+ # stall
+
+loop: bne r0, neq_2017 # Done if difference in prior compare
+ ldq_u r20, 16(r16) # Get yet another QW of A
+
+ xor r28, r27, r0 # Compare prior QW's
+ ldq r17, 16(r18) # Get yet another QW of B
+
+ subq r19, 16, r19 # Decrement length
+ bne r0, neq_2827 # Done if difference in this compare
+
+ ldq r27, 24(r18) # Get next QW of B
+ addq r18, 16, r18 # Increment pointer
+
+ ldq_u r28, 24(r16) # Get next QW of A
+ addq r16, 16, r16 # Increment pointer
+
+ xor r20, r17, r0 # Compare QW's loaded at top of loop
+ bgt r19, loop # Repeat until two or less QWs left
+
+bottom: addq r19, 8, r19 # More than 1 QW left?
+ bne r0, neq_2017 # Done if difference in prior compare
+
+ xor r28, r27, r0 # Compare QW's just loaded
+ ble r19, last # Skip if this is last compare
+
+ bne r0, neq_2827 # Done if difference in this compare
+ ldq_u r28, 16(r16) # Get last QW of A
+
+ ldq r27, 16(r18) # Get last QW of B
+ subq r19, 8, r19
+
+ #2 stalls
+
+ xor r28, r27, r0 # Compare last QW's
+last: beq r19, ck_last
+
+ mskql r0, r19, r0 # Discard diffs after length
+
+ck_last:
+ bne r0, neq_2827 # See which is greater
+
+equal: cmplt r21, r31, r0 # Equal: return A_len < B_len
+ ret r31, (r26)
+
+ #.align quad
+unalign:
+ extql r17, r18, r17 # Get first part of B
+
+ extqh r27, r18, r0 # Get second part of B
+
+ #stall
+
+ or r0, r17, r17 # Combine pieces of B
+
+ xor r20, r17, r0 # Compare with A
+
+ mskqh r0, r16, r0 # Trim junk preceding strings
+ blt r19, bott_u # Skip if fewer than 16 bytes left
+
+loop_u: ldq_u r17, 16(r18) # Get more B
+ subq r19, 16, r19 # Decrement length
+
+ bne r0, neq_20xx # Done if r20.ne.r17
+ extql r27, r18, r20 # Get piece of B from prior QW
+
+ ldq_u r27, 24(r18) # Get still more B
+ addq r18, 16, r18 # Increment B pointer
+
+ ldq_u r28, 8(r16) # Get more A
+ extqh r17, r18, r0 # Get piece of B from first QW in loop
+
+ extql r17, r18, r17 # Get second piece of B from there
+
+ or r20, r0, r0 # Combine pieces for first B
+
+ ldq_u r20, 16(r16) # Get still more A
+ xor r28, r0, r0 # Compare with first A
+
+ bne r0, neq_28xx # Done if r28.ne.r0
+ extqh r27, r18, r0 # Start building second B
+
+ addq r16, 16, r16 # Increment A pointer
+
+ or r0, r17, r17 # Combine pieces for second B
+
+ xor r20, r17, r0 # Compare with second A
+ bge r19, loop_u # Repeat if at least 16 more bytes
+
+bott_u: and r19, 8, r28 # At least 8 more bytes?
+ bne r0, neq_2017 # Done if r20.ne.r17
+
+ and r19, 7, r19 # How many odd bytes?
+ beq r28, last_u # Skip if not a whole QW
+
+ extql r27, r18, r20 # Get a piece of B
+ ldq_u r27, 16(r18) # Load another QW of B
+
+ addq r18, 8, r18 # Increment B pointer
+ ldq_u r28, 8(r16) # Load another QW of A
+
+ addq r16, 8, r16 # Increment A pointer
+
+ extqh r27, r18, r0 # Get a piece of new B QW
+
+ #stall
+
+ or r20, r0, r20 # Combine pieces
+
+ xor r28, r20, r0 # Compare with A
+
+ nop
+ bne r0, neq_28xx # Done if r28.ne.r20
+
+last_u: addq r18, r19, r17 # Point to end of B
+ beq r19, eql_u # Check length diff if no more bytes
+
+ ldq_u r28, 8(r16) # Get last QW of A
+
+ ldq_u r20, 7(r17) # Get QW containing end of B
+
+ extql r27, r18, r27 # Get piece of prior B QW
+
+ #stall
+
+ extqh r20, r18, r0 # Get a piece of last B QW
+
+ #stall
+
+ or r27, r0, r27 # Combine
+
+ xor r28, r27, r0 # Compare with A
+
+ mskql r0, r19, r0 # Discard diffs after strings
+
+ #stall
+
+ beq r0, eql_u # Done if they're still equal
+
+ #.align quad
+neq_28xx:
+ xor r28, r0, r27 # Recover B from A and xor
+neq_2827:
+ cmpbge r31, r0, r17 # Where is B = A?
+
+ cmpbge r27, r28, r20 # Where is B >= A?
+
+ addq r17, 1, r0 # Flip first difference
+
+ andnot r20, r17, r20 # Where is B > A?
+
+ and r20, r0, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ #.align quad
+neq_20xx:
+ xor r20, r0, r17 # Recover B from A and xor
+neq_2017:
+ cmpbge r31, r0, r27 # Where is B = A?
+
+ cmpbge r17, r20, r20 # Where is B >= A?
+
+ addq r27, 1, r0 # Flip first difference
+
+ andnot r20, r27, r20 # Where is B > A?
+
+ and r20, r0, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+
+eql_u: cmplt r21, r31, r0 # Equal: return A_len < B_len
+ ret r31, (r26)
+
+
+ .set at
+ .set reorder
+ .end _OtsStringCompareLss
diff --git a/private/crt32/misc/alpha/scmplssp.s b/private/crt32/misc/alpha/scmplssp.s
new file mode 100644
index 000000000..4243965d8
--- /dev/null
+++ b/private/crt32/misc/alpha/scmplssp.s
@@ -0,0 +1,478 @@
+ #++
+ #
+ # Copyright (c) 1993 by
+ # Digital Equipment Corporation, Maynard, MA
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+
+ # Facility:
+ #
+ # GEM/OTS - GEM compiler system support library
+ #
+ # Abstract:
+ #
+ # OTS character string support, Alpha version
+ #
+ # Authors:
+ #
+ # Bill Noyce
+ #
+ #
+ # long ots_strcmp_lssp(char *str1, long str1len,
+ # char *str2, long str2len, char pad);
+ # compares two strings of different lengths with padding.
+ # returns r0=1 if str1<str2, r0=0 otherwise.
+ #
+ # Special conventions: No stack space, r16-r22 and r27-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # Modification history:
+ #
+ # 006 28 May 1992 WBN Initial version, replacing BLISS -005
+ #
+ # 007 22 Sep 1992 KDG Add case-sensitive name
+ #
+ # 008 26 Jan 1993 KDG Add underscore
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 --> A
+ # r17 = A_len
+ # r18 --> B
+ # r19 = B_len
+ # r20 = pad
+ # returns r0=1 if A less, r0=0 if A greater/equal
+ # destroys r16-r22, r27-r28
+ #
+ .globl _OtsStringCompareLssPadded
+ .ent _OtsStringCompareLssPadded
+_OtsStringCompareLssPadded:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+
+ subq r17, r19, r21 # A length - B length
+ beq r17, a_empty # If A empty, go compare B with pad
+
+ cmovgt r21, r19, r17 # R17 = min length
+ ldq_u r0, (r16) # Get first QW of A
+
+ sll r20, 8, r28 # Start replicating pad
+ beq r19, b_empty # If B empty, go compare A with pad
+
+ subq r17, 8, r17 # Is min length > 8?
+ ldq_u r19, (r18) # Get first QW of B
+
+ or r20, r28, r20 # Pad in bytes 0,1 of R20
+ bgt r17, big # Go handle strings > 8 bytes
+
+ addq r18, r17, r18 # Point to end of B
+ addq r16, r17, r16 # Point to end of A
+
+ extql r0, r16, r0 # Position start of string A
+ ldq_u r27, 7(r18) # Get end of string B
+
+ extql r19, r18, r19 # Position start of string B
+ ldq_u r28, 7(r16) # Get end of string A
+
+ subq r31, r17, r17 # R17 = 8 - length
+ extqh r27, r18, r27 # Position end of string B
+
+ extqh r28, r16, r28 # Position end of string A
+ or r19, r27, r19 # Combine parts of B
+
+ or r0, r28, r28 # Combine parts of A
+ xor r28, r19, r27 # Are they different?
+
+ mskqh r27, r17, r27 # Clear off diffs preceding strings
+ sll r20, 16, r0 # Replicate pad while waiting
+
+ cmpbge r31, r27, r17 # Make 1's where strings matched
+ beq r27, eq_so_far # Skip if entire min_length matched
+
+ cmpbge r19, r28, r19 # Make 1's where B >= A
+ addq r17, 1, r0 # Flip first mismatch
+
+ andnot r19, r17, r19 # 1's where A < B
+ and r19, r0, r0 # nonzero if A < B at first mismatch
+
+ cmovne r0, 1, r0 # 1 if string A < string B
+ ret r31, (r26)
+
+ # Come here if min length > 8
+ #
+ # r0 = first QW of A
+ # r16 -> A
+ # r17 = min length - 8
+ # r18 -> B
+ # r19 = first QW of B
+ # r20 = pad in bytes 0,1
+ # r21 = A length - B length
+ # r22
+ # r27
+ # r28
+ #
+ nop #.odd
+big: and r16, 7, r28 # A alignment, or amount not compared
+
+ subq r18, r28, r18 # Back up B pointer that much
+
+ addq r17, r28, r17 # (Len-8+align) is amount left to do
+
+ and r18, 7, r22 # Is B now aligned?
+ ldq_u r27, 8(r18) # Get next QW of B
+
+ subq r17, 16, r17 # More than 2 QW's left?
+ bne r22, unalign # Skip if B alignment doesn't match
+
+ xor r0, r19, r22 # Compare first (partial) QW
+ ldq_u r28, 8(r16) # Get next QW of A
+
+ mskqh r22, r16, r22 # Discard junk preceding strings
+ ble r17, bottom # Skip if two quadwords or less to go
+
+ # stall
+
+loop: bne r22, neq_019 # Done if difference in prior compare
+ ldq_u r0, 16(r16) # Get yet another QW of A
+
+ xor r28, r27, r22 # Compare prior QW's
+ ldq r19, 16(r18) # Get yet another QW of B
+
+ subq r17, 16, r17 # Decrement length
+ bne r22, neq_2827 # Done if difference in this compare
+
+ ldq r27, 24(r18) # Get next QW of B
+ addq r18, 16, r18 # Increment pointer
+
+ ldq_u r28, 24(r16) # Get next QW of A
+ addq r16, 16, r16 # Increment pointer
+
+ xor r0, r19, r22 # Compare QW's loaded at top of loop
+ bgt r17, loop # Repeat until two or less QWs left
+
+bottom: addq r17, 8, r19 # More than 1 QW left?
+ bne r22, neq_0xx # Done if difference in prior compare
+
+ andnot r16, 7, r16 # Get actual A pointer
+ ble r19, last # Skip if this is last compare
+
+ xor r28, r27, r22 # Compare QW's just loaded
+ ldq r27, 16(r18) # Get last QW of B
+
+ bne r22, neq_28xx # Done if difference in this compare
+ ldq r28, 16(r16) # Get last QW of A
+
+ mov r17, r19
+
+ nop
+
+last: xor r28, r27, r22 # Compare last QW's
+ beq r19, ck_last
+
+ mskql r22, r19, r22 # Discard diffs after length
+
+ck_last:
+ bne r22, neq_2827 # See which is greater
+
+ addq r17, 16, r17 # Get actual remaining length
+ sll r20, 16, r0 # Start shifting pad some more
+
+ addq r16, r17, r16 # Point to end-8 of each string
+ addq r18, r17, r18
+
+ # Come here if strings match thru min_length
+ #
+ # r0 = pad in bytes 2,3
+ # r16 -> A[min_length-8] (8 before first uncompared byte of A)
+ # r17
+ # r18 -> B[min_length-8] (8 before first uncompared byte of B)
+ # r19
+ # r20 = pad in bytes 0,1
+ # r21 = A length - B length
+ # r22
+ # r27
+ # r28
+ #
+eq_so_far:
+ or r20, r0, r27 # Pad in bytes 0-3
+ beq r21, equal # Strings same length, return equal
+
+ sll r27, 32, r0 # Replicate pad some more
+ blt r21, b_longer # Go compare pad with B
+
+ and r16, 7, r17 # Alignment of remaining A
+ ldq_u r28, 8(r16) # Get first data to compare with pad
+
+ subq r21, 8, r21 # Length - 8
+ or r27, r0, r27 # Pad in bytes 0-7
+
+ addq r21, r17, r21 # Remaining length after this QW
+ xor r28, r27, r22 # Compare A QW with pad
+
+ mskqh r22, r16, r22 # Discard bytes preceding end of B
+ ble r21, a_last # Skip if this is last QW
+
+ ldq_u r0, 16(r16) # Get QW 2 of A
+ subq r21, 16, r21 # Are there two more QW's?
+
+ ble r21, a_bot # Skip loop if not
+a_pad: bne r22, neq_2827 # Exit if diff in R28
+
+ ldq_u r28, 24(r16) # Get next QW of A
+ xor r0, r27, r22 # Check prior QW
+
+ subq r21, 16, r21 # 2 more QW's?
+ bne r22, neq_0xx # Exit if diff in R0
+
+ ldq_u r0, 32(r16) # Get next QW of A
+ addq r16, 16, r16 # Update pointer
+
+ xor r28, r27, r22 # Compare prior QW
+ bgt r21, a_pad # Repeat if more to compare
+
+a_bot: addq r21, 8, r21 # Another QW?
+ bne r22, neq_2827 # Exit if diff in R28
+
+ mov r0, r28 # Move this QW to common location
+ ble r21, a_skip # Skip if this is last QW
+
+ ldq_u r28, 24(r16) # Next QW of A
+ xor r0, r27, r22 # Compare prior QW
+
+ subq r21, 8, r21
+ bne r22, neq_0xx # Exit if diff in R0
+
+a_skip: xor r28, r27, r22 # Compare last QW
+a_last: beq r21, a_end # Can't use MSKQL if whole QW
+
+ mskql r22, r21, r22 # Keep only up to end of string
+a_end: bne r22, neq_2827 # Exit if diff in R28
+
+ clr r0 # Strings equal, return false
+ ret r31, (r26)
+
+ # Come here if A is nonempty, but B is empty.
+ #
+b_empty:
+ subq r16, 8, r16 # Back up A pointer as expected
+ or r20, r28, r20 # Pad in bytes 0-1
+
+ sll r20, 16, r0
+ br r31, eq_so_far # Go compare A with pad
+
+ # Come here if A is empty (B might be empty too).
+ #
+ nop #.odd
+a_empty:
+ sll r20, 8, r28 # Start replicating pad
+
+ subq r18, 8, r18 # Back up B pointer as expected
+ beq r19, equal # Done if both strings empty
+
+ or r20, r28, r20 # Pad in bytes 0-1
+ sll r20, 16, r0
+
+ or r20, r0, r27 # Pad in bytes 0-3
+ sll r27, 32, r0
+
+b_longer:
+ and r18, 7, r17 # Alignment of remaining B
+ ldq_u r28, 8(r18) # Get first data to compare with pad
+
+ addq r21, 8, r21 # - Length + 8
+ or r27, r0, r0 # Pad in bytes 0-7
+
+ subq r17, r21, r21 # Remaining length after this QW
+ xor r0, r28, r22 # Compare B QW with pad
+
+ mskqh r22, r18, r22 # Discard bytes preceding end of A
+ ble r21, b_last # Skip if last QW
+
+ ldq_u r19, 16(r18) # Get QW 2 of B
+ subq r21, 16, r21 # Two more QW's?
+
+ ble r21, b_bot # Skip if not
+b_pad: bne r22, neq_0xx # Exit if diff in r28
+
+ ldq_u r28, 24(r18) # Get next QW of B
+ xor r0, r19, r22 # Check prior QW
+
+ subq r21, 16, r21 # 2 more QW's?
+ bne r22, neq_019 # Exit if diff in R19
+
+ ldq_u r19, 32(r18) # Get next QW of B
+ addq r18, 16, r18 # Update pointer
+
+ xor r0, r28, r22 # Compare prior QW
+ bgt r21, b_pad # Repeat if more to compare
+
+b_bot: addq r21, 8, r21 # Another QW?
+ bne r22, neq_0xx # Exit if diff in R28
+
+ xor r0, r19, r22 # Check another QW
+ ble r21, b_last # Skip if that's the last one
+
+ ldq_u r28, 24(r18) # Fetch another QW
+ bne r22, neq_019 # Exit if diff in R19
+
+ subq r21, 8, r21
+ nop
+
+ xor r0, r28, r22 # Check that QW
+b_last: beq r21, b_end # Can't use MSKQL if whole QW
+
+ mskql r22, r21, r22 # Keep only up to end of B
+b_end: bne r22, neq_0xx # Exit if diff seen
+
+equal: clr r0 # Strings equal, return false
+ ret r31, (r26)
+
+ #.align quad
+unalign:
+ extql r19, r18, r19 # Get first part of B
+
+ extqh r27, r18, r22 # Get second part of B
+
+ #stall
+
+ or r22, r19, r19 # Combine pieces of B
+
+ xor r0, r19, r22 # Compare with A
+
+ mskqh r22, r16, r22 # Trim junk preceding strings
+ blt r17, bott_u # Skip if fewer than 16 bytes left
+
+loop_u: ldq_u r19, 16(r18) # Get more B
+ subq r17, 16, r17 # Decrement length
+
+ bne r22, neq_0xx # Done if r0.ne.r19
+ extql r27, r18, r0 # Get piece of B from prior QW
+
+ ldq_u r27, 24(r18) # Get still more B
+ addq r18, 16, r18 # Increment B pointer
+
+ ldq_u r28, 8(r16) # Get more A
+ extqh r19, r18, r22 # Get piece of B from first QW in loop
+
+ extql r19, r18, r19 # Get second piece of B from there
+
+ or r0, r22, r22 # Combine pieces for first B
+
+ ldq_u r0, 16(r16) # Get still more A
+ xor r28, r22, r22 # Compare with first A
+
+ bne r22, neq_28xx # Done if r28.ne.r22
+ extqh r27, r18, r22 # Start building second B
+
+ addq r16, 16, r16 # Increment A pointer
+
+ or r22, r19, r19 # Combine pieces for second B
+
+ xor r0, r19, r22 # Compare with second A
+ bge r17, loop_u # Repeat if at least 16 more bytes
+
+bott_u: and r17, 8, r28 # At least 8 more bytes?
+ bne r22, neq_019 # Done if r0.ne.r19
+
+ and r17, 7, r17 # How many odd bytes?
+ beq r28, last_u # Skip if not a whole QW
+
+ extql r27, r18, r0 # Get a piece of B
+ ldq_u r27, 16(r18) # Load another QW of B
+
+ addq r18, 8, r18 # Increment B pointer
+ ldq_u r28, 8(r16) # Load another QW of A
+
+ addq r16, 8, r16 # Increment A pointer
+
+ extqh r27, r18, r22 # Get a piece of new B QW
+
+ # stall
+
+ or r0, r22, r0 # Combine pieces
+
+ xor r28, r0, r22 # Compare with A
+
+ bne r22, neq_28xx # Done if r28.ne.r0
+
+last_u: andnot r16, 7, r16 # What's the real address of A?
+
+ sll r20, 16, r0 # Start replicating pad
+ beq r17, eq_so_far # Check padding if no more bytes
+
+ ldq_u r28, 8(r16) # Get last QW of A
+ addq r18, r17, r19 # Point to end-8 of B
+
+ ldq_u r19, 7(r19) # Get QW containing end of B
+ extql r27, r18, r27 # Get piece of prior B QW
+
+ addq r16, r17, r16 # Point to end-8 of A
+
+ extqh r19, r18, r22 # Get a piece of last B QW
+
+ addq r18, r17, r18 # Point to end-8 of B
+
+ or r27, r22, r27 # Combine
+
+ xor r28, r27, r22 # Compare with A
+
+ mskql r22, r17, r22 # Discard diffs after strings
+
+ nop
+
+ beq r22, eq_so_far # If still equal, go check pad
+
+ #.align quad
+neq_28xx:
+ xor r28, r22, r27 # Recover B from A and xor
+neq_2827:
+ cmpbge r31, r22, r19 # Where is B = A?
+
+ cmpbge r27, r28, r0 # Where is B >= A?
+
+ addq r19, 1, r22 # Flip first difference
+
+ andnot r0, r19, r0 # Where is B > A?
+
+ and r0, r22, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ #.align quad
+neq_0xx:
+ xor r0, r22, r19 # Recover B from A and xor
+neq_019:
+ cmpbge r31, r22, r27 # Where is B = A?
+
+ cmpbge r19, r0, r0 # Where is B >= A?
+
+ addq r27, 1, r22 # Flip first difference
+
+ andnot r0, r27, r0 # Where is B > A?
+
+ and r0, r22, r0 # Keep only first difference
+
+ cmovne r0, 1, r0 # Return 1 if A < B at first difference
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsStringCompareLssPadded
diff --git a/private/crt32/misc/alpha/setjmp.s b/private/crt32/misc/alpha/setjmp.s
new file mode 100644
index 000000000..65453c8be
--- /dev/null
+++ b/private/crt32/misc/alpha/setjmp.s
@@ -0,0 +1,111 @@
+// TITLE("Set Jump")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// setjmp.s
+//
+// Abstract:
+//
+// This module implements the Alpha acc compiler specific routine to
+// perform a setjmp.
+//
+// N.B. This module conditionally provides UNSAFE handling of setjmp and
+// which is NOT integrated with structured exception handling. The
+// determination is made based on whether an uninitialized variable
+// has been set to a nonzero value.
+//
+// Author:
+//
+// David N. Cutler (davec) 7-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Thomas Van Baak (tvb) 22-Apr-1993
+//
+// Adapted for Alpha AXP.
+//
+//--
+
+#include "ksalpha.h"
+
+//
+// Define variable that will cause setjmp/longjmp to be safe or unsafe with
+// respect to structured exception handling.
+//
+
+ .globl _setjmpexused
+ .comm _setjmpexused, 4
+
+ SBTTL("Set Jump - acc version")
+//++
+//
+// int
+// setjmp (
+// IN jmp_buf JumpBuffer
+// )
+//
+// Routine Description:
+//
+// This function saves the current nonvolatile register state in the
+// specified jump buffer and returns a function value of zero.
+//
+// Arguments:
+//
+// JumpBuffer (a0) - Supplies the address of a jump buffer to store the
+// jump information.
+//
+// Return Value:
+//
+// A value of zero is returned.
+//
+//--
+
+ LEAF_ENTRY(setjmp)
+
+ ldl v0, _setjmpexused // get value of switch variable
+ bne v0, 10f // if ne, provide safe setjmp
+
+//
+// Provide unsafe handling of setjmp.
+//
+
+ stt f2, JbFltF2(a0) // save floating registers f2 - f9
+ stt f3, JbFltF3(a0) //
+ stt f4, JbFltF4(a0) //
+ stt f5, JbFltF5(a0) //
+ stt f6, JbFltF6(a0) //
+ stt f7, JbFltF7(a0) //
+ stt f8, JbFltF8(a0) //
+ stt f9, JbFltF9(a0) //
+
+ stq s0, JbIntS0(a0) // save integer registers s0 - s6/fp
+ stq s1, JbIntS1(a0) //
+ stq s2, JbIntS2(a0) //
+ stq s3, JbIntS3(a0) //
+ stq s4, JbIntS4(a0) //
+ stq s5, JbIntS5(a0) //
+ stq fp, JbIntS6(a0) //
+
+ ldil t0, 1 // get unsafe setjmp flag
+ stl t0, JbType(a0) // set jump buffer context type
+ stq sp, JbIntSp(a0) // save stack pointer
+ stq ra, JbFir(a0) // get setjmp return address
+
+ mov zero, v0 // set zero return value
+ ret zero, (ra) // return
+
+//
+// Provide safe handling of setjmp.
+//
+
+10: jmp zero, (v0) // finish in _setjmpex code
+
+ .end setjmp
diff --git a/private/crt32/misc/alpha/setjmpex.s b/private/crt32/misc/alpha/setjmpex.s
new file mode 100644
index 000000000..3f39baa7b
--- /dev/null
+++ b/private/crt32/misc/alpha/setjmpex.s
@@ -0,0 +1,147 @@
+// TITLE("Set Jump Extended")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+// Copyright (c) 1993 Digital Equipment Corporation
+//
+// Module Name:
+//
+// setjmpex.s
+//
+// Abstract:
+//
+// This module implements the Alpha acc compiler specific routine to
+// provide SAFE handling of setjmp/longjmp with respect to structured
+// exception handling.
+//
+// Author:
+//
+// David N. Cutler (davec) 2-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Thomas Van Baak (tvb) 22-Apr-1993
+//
+// Adapted for Alpha AXP.
+//
+//--
+
+#include "ksalpha.h"
+
+//
+// Define variable that will cause setjmp/longjmp to be safe with respect
+// to structured exception handling.
+//
+
+ .globl _setjmpexused
+ .data
+_setjmpexused:
+ .long _setjmpex // set address of safe setjmp routine
+
+ SBTTL("Set Jump Extended")
+//++
+//
+// int
+// _setjmpex (
+// IN jmp_buf JumpBuffer
+// )
+//
+// Routine Description:
+//
+// This function implements a safe setjmp.
+//
+// Arguments:
+//
+// JumpBuffer (a0) - Supplies the address of a jump buffer to store the
+// jump information.
+//
+// Return Value:
+//
+// A value of zero is returned.
+//
+//--
+
+ .struct 0
+SjRa: .space 8 // saved return address
+SjS0: .space 8 // saved integer register s0
+SjFl: .space 8 // InFunction flag variable
+SjEf: .space 8 // EstablisherFrame(s) structure
+SjCx: .space ContextFrameLength // context frame
+SetjmpFrameLength:
+
+ NESTED_ENTRY(_setjmpex, SetjmpFrameLength, zero)
+
+ lda sp, -SetjmpFrameLength(sp) // allocate stack frame
+ stq ra, SjRa(sp) // save return address
+ stq s0, SjS0(sp) // save integer register s0
+
+ PROLOGUE_END
+
+//
+// Save the nonvolatile machine state.
+//
+
+ lda t0, SjCx(sp) // address of context record
+
+ stt f2, CxFltF2(t0) // save floating registers f2 - f9
+ stt f3, CxFltF3(t0) //
+ stt f4, CxFltF4(t0) //
+ stt f5, CxFltF5(t0) //
+ stt f6, CxFltF6(t0) //
+ stt f7, CxFltF7(t0) //
+ stt f8, CxFltF8(t0) //
+ stt f9, CxFltF9(t0) //
+
+ stq s0, CxIntS0(t0) // save integer registers s0 - fp/s6
+ stq s1, CxIntS1(t0) //
+ stq s2, CxIntS2(t0) //
+ stq s3, CxIntS3(t0) //
+ stq s4, CxIntS4(t0) //
+ stq s5, CxIntS5(t0) //
+ stq fp, CxIntFp(t0) //
+ stq gp, CxIntGp(t0) // save integer register gp
+
+ lda v0, SetjmpFrameLength(sp) // compute stack pointer address
+ stq v0, CxIntSp(t0) // save stack pointer
+ stq ra, CxIntRa(t0) // save return address
+ stq ra, CxFir(t0) // save continuation address
+
+ ldil t1, 2 // get acc safe setjmp flag
+ stl t1, JbType(a0) // set jump buffer context type
+ stl ra, JbPc(a0) // save target instruction address
+ mov a0, s0 // preserve jump buffer address
+
+//
+// Perform unwind to determine the virtual frame pointer of the caller.
+//
+
+ subl ra, 4, a0 // compute control PC address
+ bsr RtlLookupFunctionEntry // lookup function table address
+
+ ldq a0, SjRa(sp) // get return address
+ subl a0, 4, a0 // compute control PC address
+ mov v0, a1 // set address of function entry
+ lda a2, SjCx(sp) // address of context record
+ lda a3, SjFl(sp) // set address of in function variable
+ lda a4, SjEf(sp) // set frame pointers address
+ mov zero, a5 // set context pointer array address
+ bsr RtlVirtualUnwind // compute virtual frame pointer value
+
+//
+// Set return value, restore registers, deallocate stack frame, and return.
+//
+
+ ldl t0, SjEf(sp) // get virtual frame pointer
+ stl t0, JbFp(s0) // save virtual frame pointer address
+ mov zero, v0 // set return value
+
+ ldq s0, SjS0(sp) // restore integer register s0
+ ldq ra, SjRa(sp) // restore return address
+ lda sp, SetjmpFrameLength(sp) // deallocate stack frame
+ ret zero, (ra) // return
+
+ .end _setjmpex
diff --git a/private/crt32/misc/alpha/sfill.s b/private/crt32/misc/alpha/sfill.s
new file mode 100644
index 000000000..35814b321
--- /dev/null
+++ b/private/crt32/misc/alpha/sfill.s
@@ -0,0 +1,161 @@
+ #++
+ # Copyright 1991, 1994, Digital Equipment Corporation
+ #
+ # ots_fill(char *dstptr, long dstlen, unsigned char fill)
+ #
+ # Fill dstlen bytes of memory at *dstptr with "fill"
+ #
+ # Special conventions: No stack space, r16-r19 and r27-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # This is a GEM support routine for filling memory with a specified value,
+ # basically identical to the System V routine memset, with the 2nd two
+ # parameters reversed. This is optimized for extremely high performance
+ # both for small blocks (string padding) and large blocks (memory fill).
+ # In order to reduce overhead for small cases, they are retired as quickly
+ # as possible, more case analysis is reserved for cases which will do
+ # more.
+ #
+ # This version of OTS_FILL provides longword granularity for Alpha.
+ #
+ # 011 30 Aug 1994 WBN Longword granularity version based on
+ # OTS_FILL_ALPHA.M64 edit 010.
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 = dst
+ # r17 = len
+ # r18 = fill byte
+ # destroys r16-r19, r27-r28
+
+ .globl _OtsFill
+ .ent _OtsFill
+_OtsFill:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+ .prologue 0
+
+ sll r18, 8, r19 # Start propagating byte to quadword
+ beq r17, done # No memory refs if len=0
+ subq r17, 4, r28 # Length-4
+ or r19, r18, r18 # Fill in bytes 0-1
+ sll r18, 16, r19
+ and r16, 3, r27 # Dst alignment (0-3)
+ or r19, r18, r18 # Fill in bytes 0-3
+ andnot r16, 3, r16 # LW aligned dst pointer
+ addq r27, r28, r17 # Alignment + length - 4
+ bge r28, geq4 # Lengths >= 4 may not need load
+ ldl r28, (r16) # Load first LW of dst
+ bgt r17, double # Skip if it crosses to next LW
+ addq r17, 4, r17 # Find endpoint within LW
+ xor r28, r18, r28 # Pre-flip all fill bits in dest
+ mskql r28, r27, r27 # Clear from startpoint thru 7
+ mskqh r28, r17, r28 # Clear from 0 to endpoint
+ xor r27, r18, r27 # Combine fill with masked dest
+ xor r28, r27, r27 # Result is fill in center part only
+ stl r27, (r16)
+ ret r31, (r26)
+
+double: mskqh r18, r27, r19 # Discard fill preceding startpoint
+ mskql r28, r27, r28 # Clear from startpoint in first LW
+ ldl r27, 4(r16) # Load second LW of dst
+ mskql r18, r17, r18 # Discard fill following endpoint
+ or r28, r19, r28 # Insert fill in first LW
+ stl r28, (r16)
+ mskqh r27, r17, r27 # Clear up to endpoint in second LW
+ or r27, r18, r27 # Insert fill in second LW
+ stl r27, 4(r16)
+ ret r31, (r26)
+
+ # Come here if length to be zeroed is >= 4.
+ # r16-> dst aligned to LW
+ # r17 = alignment + length - 4
+ # r18 = fill in bytes 0-3
+ # r27 = dst alignment within LW
+ # r28 = length-4
+
+ #.align quad
+
+geq4: and r16, 4, r28 # Which LW in QW to store first?
+ beq r17, simple # Go handle single aligned LW
+ sll r18, 32, r19
+ bne r28, longs # Go use QW stores
+quad: subq r17, 4, r17 # Does dest end in first QW?
+ or r18, r19, r18 # Fill in bytes 0-7
+ blt r17, shortq # Ends within first QW
+ mskqh r18, r27, r28 # Clear initial bytes of fill
+ beq r27, wh_qw # Store a whole QW
+ ldq r19, (r16) # Load first QW of dest
+ mskql r19, r27, r19 # Clear from startpoint
+ or r19, r28, r28 # Combine first QW with fill
+wh_qw: stq r28, (r16) # Store first QW of dest
+ br r31, join # Go fill rest of string
+
+simple: stl r18, (r16) # Single aligned LW
+ ret r31, (r26)
+
+shortq: ldq r28, (r16) # Load QW of dest
+ xor r28, r18, r28 # Pre-flip all fill bits in dest
+ mskql r28, r27, r27 # Clear from startpoint thru 7
+ mskqh r28, r17, r28 # Clear from 0 up to endpoint
+ xor r27, r18, r27 # Combine fill with masked dest
+ xor r28, r27, r27 # Result is fill in center part only
+ stq r27, (r16) # Store
+ ret r31, (r26)
+
+longs: mskqh r18, r27, r28 # Clear initial bytes of LW fill
+ or r18, r19, r18 # Fill in bytes 0-7
+ beq r27, wh_lw # Store a whole LW
+ ldl r19, (r16) # Load first LW of dest
+ mskql r19, r27, r19 # Clear from startpoint
+ or r19, r28, r28 # Combine first LW with fill
+wh_lw: stl r28, (r16) # Store first LW of dest
+join: subq r17, 32, r17 # At least 4 more quadwords?
+ and r17, 24, r27 # How many after multiple of 4?
+ bge r17, unroll # Taken branch for long strings
+short: and r17, 7, r17 # How many odd bytes?
+ beq r27, last # Skip if no more whole QWs
+ stq_u r18, 8(r16) # Clear one...
+ subq r27, 16, r27 # Map 8/16/24 to -8/0/8
+ addq r16, 8, r16 # Update dest pointer
+ blt r27, last # Skip if no more whole QWs
+ #stall
+ stq_u r18, 8(r16) # Clear two...
+ addq r16, 8, r16 # Update dest pointer
+ nop
+ beq r27, last # Skip if no more whole QWs
+ stq_u r18, 8(r16) # Clear three...
+ addq r16, 8, r16 # Update dest pointer
+last: beq r17, done # Finished if no odd bytes
+ ldq_u r27, 8(r16) # Load last QW of dest
+ subq r17, 4, r28 # More than a LW left?
+ andnot r16, 7, r16 # Clean pointer for STL
+ mskql r18, r17, r18 # Discard unneeded fill bytes
+ #stall
+ mskqh r27, r17, r27 # Clear up to endpoint in last QW
+ #stall
+ or r27, r18, r27 # Combine fill with last QW
+ bgt r28, lastq # Go store a QW
+ stl r27, 8(r16) # LW store for last piece
+done: ret r31, (r26)
+
+lastq: stq r27, 8(r16) # QW store for last piece
+ ret r31, (r26)
+
+
+unroll: stq_u r18, 8(r16) # Store 4 QWs per iteration
+ stq_u r18, 16(r16)
+ stq_u r18, 24(r16)
+ subq r17, 32, r17 # Decrement remaining count
+ stq_u r18, 32(r16)
+ addq r16, 32, r16 # Update dest pointer
+ bge r17, unroll # repeat until done
+ br r31, short # Then handle leftovers
+
+ .set at
+ .set reorder
+ .end _OtsFill
diff --git a/private/crt32/misc/alpha/sloc.s b/private/crt32/misc/alpha/sloc.s
new file mode 100644
index 000000000..30fda8c6e
--- /dev/null
+++ b/private/crt32/misc/alpha/sloc.s
@@ -0,0 +1,702 @@
+ #++
+ #
+ # Copyright (c) 1993 by
+ # Digital Equipment Corporation, Maynard, MA
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+
+ # Facility:
+ #
+ # GEM/OTS - GEM compiler system support library
+ #
+ # Abstract:
+ #
+ # OTS character string support, Alpha version
+ # This module provides support for string index, search, and verify.
+ #
+ # Authors:
+ #
+ # Bill Noyce
+ # Kent Glossop
+ #
+ # long ots_index(const char *str, long strlen, const char *pat, long patlen);
+ #
+ # Searches a string for a substring
+ # returns r0=zero-based position if found, or -1 if not.
+ # Register usage: r0-r1, r16-r23 and r27-r28 ONLY (r26 is ra)
+ #
+ # long ots_search(const char *str, long strlen, const char *cset, long csetlen);
+ #
+ # Searches a string for any character in a set of characters
+ # returns r0=zero-based position if found, or -1 if not.
+ # Register usage: r0-r1, r16-r23 and r27-r28 ONLY (r26 is ra)
+ #
+ # long ots_search_char(const char *str, long strlen, char pat);
+ # (also known as ots_index_char)
+ #
+ # Searches a string for a signle pattern character
+ # returns r0=zero-based position if found, or -1 if not.
+ # Register usage: r0, r16-r18 and r27-r28 ONLY (r26 is ra)
+ # (Note: GEM presumes r19 is also killed)
+ #
+ # long ots_search_mask(const char *str, long strlen, const char maskvec[], int mask)
+ #
+ # Searches a string until a character matching at least one bit
+ # in a mask is found in a table (similar to a VAX SCANC instruction.)
+ # returns r0=zero-based position if found, or -1 if not.
+ # Register usage: r0-1, r16-r21 and r27-r28 ONLY (r26 is ra)
+ #
+ # long ots_verify(char *str, long strlen, char *cset, long csetlen);
+ #
+ # Verifies a string against a set of characters
+ # returns r0=zero-based position for mismatch, or -1 if all validate.
+ # Register usage: r0-r1, r16-r23 and r27-r28 ONLY (r26 is ra)
+ #
+ # long ots_verify_char(char *str, long strlen, char pat);
+ #
+ # Verifies a string against a single character
+ # returns r0=zero-based position for mismatch, or -1 if not.
+ # Register usage: r0, r16-r18 and r27-r28 ONLY (r26 is ra)
+ # (Note: GEM presumes r19 is also killed)
+ #
+ # long ots_verify_mask(const char *str, long strlen, const char maskvec[], int mask)
+ #
+ # Verifies a string until a character not matching at least one bit
+ # in a mask is found in a table (similar to a VAX SPANC instruction.)
+ # returns r0=zero-based position if found, or -1 if not.
+ # Register usage: r0-1, r16-r21 and r27-r28 ONLY (r26 is ra)
+ #
+ # Special conventions for all:
+ # No stack space
+ # No linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # Modification history:
+ #
+ # 006 28 May 1992 WBN Initial version, replacing BLISS -005
+ #
+ # 007 22 Sep 1992 KDG Add case-sensitive names
+ #
+ # 008 14 Nov 1992 KDG - Merge modules together (allows index/search/verify
+ # to use the single-character versions w/o calls)
+ # - initial multi-character index/search/verify
+ #
+ # 009 4 Dec 1992 KDG Fix bgt that should have been bge (GEM_BUGS #2091)
+ #
+ # 010 26 Jan 1993 KDG Add underscore
+ #
+ # All of the routines other than the single character search/verify could
+ # be significantly improved at some point in the future
+ #--
+
+#include "ots_defs.hs"
+
+ # "Package"
+ #
+ .globl _OtsLocation
+ .ent _OtsLocation
+_OtsLocation:
+ .set noat
+ .set noreorder
+
+ # ots_index
+ # This is currently a primitive brute-force string index (only marginally
+ # better than the original compiled code. Should be tailored to compare
+ # up to 8 at a time, particularly for patterns <= 8 characters.)
+
+ # register use
+ # r0 - remaining match positions counter (-1)
+ # r1 - loop counter [rlen]
+ # r16 - source pointer (incremented on each match)
+ # r17 - source length
+ # r18 - pattern pointer
+ # r19 - pattern length
+ # r20 - loop source pointer [rsp]
+ # r21 - loop source temp [rs]
+ # r22 - loop pattern pointer [rpp]
+ # r23 - loop pattern temp [rp]
+ # r27 - available
+ # r28 - available
+
+ .globl _OtsStringIndex
+ .aent _OtsStringIndex
+_OtsStringIndex:
+ .frame sp,0,r26
+
+ cmpeq r19, 1, r20 # check for single-character index
+ beq r19, i_ret0 # pattern length 0 always matches @0
+ subq r17, r19, r0 # number of match positions - 1
+ bne r20, search_single # single character index
+ blt r0, i_retm1 # return -1 if no match positions
+
+ # outer loop
+i_outlp:
+ lda r20, -1(r16) # initialize source pointer
+ lda r22, -1(r18) # initialize pattern pointer
+ mov r19, r1 # initialize length counter
+
+ # core brute-force matching loop
+i_matlp:
+ ldq_u r21, 1(r20) # load qw containing source byte
+ lda r20, 1(r20) # bump source pointer
+ ldq_u r23, 1(r22) # load qw containing pattern byte
+ lda r22, 1(r22) # bump pattern pointer
+ subq r1, 1, r1 # decrement length
+ extbl r21, r20, r21 # extract source byte
+ extbl r23, r22, r23 # extract pattern byte
+ xor r21, r23, r21 # match?
+ bne r21, i_mismat # if not, try pattern at next position
+ bgt r1, i_matlp # continue matching pattern at current position?
+
+ # matched
+i_ret:
+ subq r17, r19, r1 # number of match positions - 1
+ subq r1, r0, r0 # actual position
+ ret r31, (r26)
+
+ # mismatch at current position - advance to next if more positions
+i_mismat:
+ subq r0, 1, r0 # decrement match positions
+ lda r16, 1(r16) # set r16 to next match position
+ bge r0, i_outlp # if remaining positions, attempt match
+
+i_retm1:
+ lda r0, -1(r31) # return -1
+ ret r31, (r26)
+
+i_ret0: clr r0
+ ret r31, (r26)
+
+ # ots_search
+ # R16 -> string
+ # R17 = length
+ # R18 -> character set
+ # R19 = character set length
+ # result in R0: -1 if all matched, or position in range 0..length-1
+ # destroys R0-R1, R16-R23, R27-R28
+ #
+ # This routine could definitely be improved. (It should only
+ # be necessary to go to memory for every 8th character for both
+ # the string and the character set, and for character sets
+ # <= 8 characters, it should be possible to simply keep the
+ # set in a register while the string is being processed.)
+ #
+ .globl _OtsStringSearch
+ .aent _OtsStringSearch
+_OtsStringSearch:
+ .frame sp,0,r26
+
+ cmpeq r19, 1, r0 # check for single-character search, clear r0 otherwise
+ ble r19, s_retm1 # return -1 if no characters in the match set
+ bne r0, search_single # single character search
+ nop
+
+ # outer loop
+s_outlp:
+ ldq_u r20, (r16) # load qw containing source byte
+ lda r22, -1(r18) # initialize character set pointer
+ mov r19, r1 # initialize character set length counter
+ extbl r20, r16, r20 # extract the source byte to match
+
+ # core brute-force matching loop
+s_matlp:
+ ldq_u r23, 1(r22) # load qw containing character set byte
+ lda r22, 1(r22) # bump character set pointer
+ subq r1, 1, r1 # decrement remaining cset length
+ extbl r23, r22, r23 # extract character set byte
+ xor r20, r23, r21 # match?
+ beq r21, s_match # if match, we're done
+ bgt r1, s_matlp # continue matching pattern at current position?
+
+ # no current position - advance to next if more positions
+ lda r16, 1(r16) # bump source pointer
+ addq r0, 1, r0 # increment position
+ subq r17, 1, r17 # decrement match count
+ bgt r17, s_outlp # if remaining positions, attempt match
+s_retm1:lda r0, -1(r31) # if not, return -1
+s_match:ret r31, (r26)
+
+search_single:
+ ldq_u r19, (r18) # load the quadword containing the byte
+ extbl r19, r18, r18 # extract the byte of interest
+ # and fall through to the character search rtn
+
+ # ots_search_char (ots_index_char)
+ # r16 -> string
+ # r17 = length
+ # r18 = character to find
+ # result in r0: -1 if not found, or position in range 0..length-1
+ # destroys r16-r18, r27-r28
+ #
+ .globl _OtsStringSearchChar
+ .aent _OtsStringSearchChar
+_OtsStringSearchChar:
+ .globl _OtsStringIndexChar
+ .aent _OtsStringIndexChar
+_OtsStringIndexChar:
+ .frame sp,0,r26
+search_char:
+ sll r18, 8, r28 # Replicate char in the quadword...
+ beq r17, sc_fail # Quick exit if length=0
+
+ ldq_u r27, (r16) # First quadword of string
+ addq r16, r17, r0 # Point to end of string
+
+ subq r17, 8, r17 # Length > 8?
+ or r18, r28, r18 # ...
+
+ sll r18, 16, r28 # ...
+ bgt r17, sc_long # Skip if length > 8
+
+ ldq_u r16, -1(r0) # Last quadword of string
+ extql r27, r0, r27 # Position string at high end of QW
+
+ or r18, r28, r18 # ...
+ sll r18, 32, r28 # ...
+
+ extqh r16, r0, r16 # Position string at high end of QW
+ or r18, r28, r18 # Pattern fills a quadword
+
+ or r27, r16, r27 # String fills a quadword
+ xor r27, r18, r27 # Diff betw. string and pattern
+
+ cmpbge r31, r27, r27 # Set 1's where string=pattern
+ subq r31, r17, r17 # Compute 8 - length
+
+ srl r27, r17, r27 # Shift off bits not part of string
+ clr r0 # Set return value
+
+ and r27, 0xF, r28 # One of first 4 characters?
+ blbs r27, sc_done # Return 0 if first char matched
+
+ subq r27, 1, r0 # Flip the first '1' bit
+ beq r28, sc_geq_4 # Skip if no match in first 4
+
+ andnot r27, r0, r0 # Make one-bit mask of first match
+ srl r0, 2, r0 # Map 2/4/8 -> 0/1/2
+
+ # stall
+
+ addq r0, 1, r0 # Bump by 1
+ ret r31, (r26) # return
+
+sc_geq_4:
+ andnot r27, r0, r28 # Make one-bit mask of first match
+ beq r27, sc_done # Return -1 if there were none
+
+ srl r28, 5, r27 # Map 10/20/48/80 -> 0/1/2/4
+ srl r28, 7, r28 # Map 10/20/40/80 -> 0/0/0/1
+
+ addq r27, 4, r0 # Bump by 4
+ subq r0, r28, r0 # and correct
+
+sc_done:ret r31, (r26)
+
+ # Enter here if string length > 8.
+ # R16 -> start of string
+ # R17 = length - 8
+ # R18 = fill in bytes 0,1
+ # R27 = 1st QW of string
+ # R28 = fill in bytes 2,3
+
+ #.odd
+sc_long:or r18, r28, r18 # R18 has pattern in low 4 bytes
+
+ sll r18, 32, r28 # ...
+ and r16, 7, r0 # Where in QW did we start?
+
+ or r18, r28, r18 # Pattern fills a QW
+ ldq_u r28, 8(r16) # Get next QW (string B)
+
+ xor r27, r18, r27 # Diff Betw. string and pattern
+ cmpbge r31, r27, r27 # Set 1's where string=pattern
+
+ addq r17, r0, r17 # Remaining length after 1st QW
+ srl r27, r0, r27 # Discard bits preceding string
+
+ subq r17, 16, r17 # More than two QW's to go?
+ sll r27, r0, r27 # Reposition like other bits
+
+ subq r17, r0, r0 # Remember start point to compute len
+ ble r17, sc_bottom # Skip the loop if 2 QW's or less
+
+sc_loop:xor r28, r18, r28 # Diff betw string B and pattern
+ bne r27, sc_done_a # Exit if a match in string A
+
+ cmpbge r31, r28, r28 # 1's where string B = pattern
+ ldq_u r27, 16(r16) # Load string A
+
+ subq r17, 16, r17 # Decrement remaining length
+ bne r28, sc_done_b # Exit if a match in string B
+
+ ldq_u r28, 24(r16) # Load string B
+ addq r16, 16, r16 # Increment pointer
+
+ xor r27, r18, r27 # Diff betw string A and pattern
+ cmpbge r31, r27, r27 # 1's where string A = pattern
+
+ bgt r17, sc_loop # Repeat if more than 2 QW's left
+
+ nop #.align quad
+
+sc_bottom:
+ bne r27, sc_done_a # Exit if a match in string A
+ addq r17, 8, r27 # More than 1 QW left?
+
+ xor r28, r18, r28 # Diff betw string B and pattern
+ ble r27, sc_last # Skip if this is last QW
+
+ cmpbge r31, r28, r27 # 1's where string B = pattern
+ ldq_u r28, 16(r16) # Load string A
+
+ subq r17, 8, r17 # Adjust len for final return
+ bne r27, sc_done_a # Exit if a match in string B
+
+ addq r17, 8, r27 # Ensure -7 <= (r27=len-8) <= 0
+ xor r28, r18, r28 # Diff betw string A and pattern
+
+sc_last:mskqh r27, r27, r27 # Nonzero in bytes beyond string
+ subq r17, 8, r17 # Adjust len for final return
+
+ or r28, r27, r28 # Zeros only for matches within string
+ cmpbge r31, r28, r27 # Where are the matches?
+
+ bne r27, sc_done_a # Compute index if a match found
+sc_fail:lda r0, -1(r31) # Else return -1
+
+ ret r31, (r26)
+
+ nop #.align 8
+
+sc_done_b:
+ addq r17, 8, r17 # Adjust length
+ mov r28, r27 # Put mask where it's expected
+
+sc_done_a:
+ subq r0, r17, r0 # (start - remaining) = base index
+ blbs r27, sc_exit # Return R0 if first char matched
+
+ and r27, 0xF, r16 # One of first 4 characters?
+ subq r27, 1, r28 # Flip the first '1' bit
+
+ andnot r27, r28, r28 # Make one-bit mask of first match
+ beq r16, sc_geq_4x # Skip if no match in first 4
+
+ srl r28, 2, r28 # Map 2/4/8 -> 0/1/2
+ addq r0, 1, r0 # Bump by 1
+
+ addq r0, r28, r0 # Add byte offset
+sc_exit:ret r31, (r26) # return
+
+sc_geq_4x:
+ addq r0, 4, r0 # Bump by 4
+ srl r28, 5, r27 # Map 10/20/48/80 -> 0/1/2/4
+
+ srl r28, 7, r28 # Map 10/20/40/80 -> 0/0/0/1
+ addq r0, r27, r0 # Add 0/1/2/4
+
+ subq r0, r28, r0 # and correct
+ ret r31, (r26)
+
+ # ots_search_mask
+ # This routine could be tailored by loading a longword or
+ # a quadword at a time and doing table lookups on the
+ # characters largely in parallel.
+ #
+ .globl _OtsStringSearchMask
+ .aent _OtsStringSearchMask
+_OtsStringSearchMask:
+ .frame sp,0,r26
+
+ lda r16, -1(r16) # bias initial address for better loop code
+ nop # should be lnop (unop) or fnop to dual issue
+ lda r0, -1(r31) # initialize position to -1
+ ble r17, sm_ret # return -1 if source len is zero
+ # slow way - ~14 cycles/byte
+sm_loop:
+ ldq_u r21, 1(r16) # load qw containing the byte
+ lda r16, 1(r16) # bump pointer
+ addq r0, 1, r0 # bump position
+ subq r17, 1, r17 # decrement the length
+ extbl r21, r16, r21 # extract the byte
+ addq r21, r18, r21 # get the byte in the table
+ ldq_u r20, (r21) # load qw from table containing lookup
+ extbl r20, r21, r20 # extract table byte
+ and r20, r19, r20 # check if any bits in the mask match
+ beq r17, sm_end # if last character, handle specially
+ beq r20, sm_loop # if no match, go do the loop again
+sm_ret:
+ ret r31, (r26) # if not a match, we're done
+sm_end: lda r21, -1(r31) # get -1
+ cmoveq r20, r21, r0 # -1 if last char didn't match
+ ret r31, (r26)
+
+ # ots_verify
+ # R16 -> string
+ # R17 = length
+ # R18 -> character set
+ # R19 = character set length
+ # result in R0: -1 if all matched, or position in range 0..length-1
+ # destroys R0-R1, R16-R23, R27-R28
+ #
+ # This routine could definitely be improved. (It should only
+ # be necessary to go to memory for every 8th character for both
+ # the string and the character set, and for character sets
+ # <= 8 characters, it should be possible to simply keep the
+ # set in a register while the string is being processed.)
+ #
+ .globl _OtsStringVerify
+ .aent _OtsStringVerify
+_OtsStringVerify:
+ .frame sp,0,r26
+
+ cmpeq r19, 1, r0 # check for single-character search, clear r0 otherwise
+ ble r19, v_ret0 # return 0 if no characters in the match set
+ bne r0, verify_single # single character verify
+ nop
+ # outer loop
+v_outlp:
+ ldq_u r20, (r16) # load qw containing source byte
+ lda r22, -1(r18) # initialize character set pointer
+ mov r19, r1 # initialize character set length counter
+ extbl r20, r16, r20 # extract the source byte to match
+
+ # core brute-force matching loop
+v_matlp:
+ ldq_u r23, 1(r22) # load qw containing character set byte
+ lda r22, 1(r22) # bump character set pointer
+ subq r1, 1, r1 # decrement remaining cset length
+ extbl r23, r22, r23 # extract character set byte
+ xor r20, r23, r21 # match?
+ beq r21, v_match # if match, move to the next character
+ bgt r1, v_matlp # continue matching pattern at current position?
+ # if we made it through the whole character set, this is a mismatch
+v_ret0: ret r31, (r26)
+v_match: # match at current position - advance to next if more positions
+ lda r16, 1(r16) # bump source pointer
+ addq r0, 1, r0 # increment position
+ subq r17, 1, r17 # decrement match count
+ bgt r17, v_outlp # if remaining positions, attempt match
+ lda r0, -1(r31) # if everything verified, return -1
+ ret r31, (r26)
+
+verify_single:
+ ldq_u r19, (r18) # load the quadword containing the byte
+ extbl r19, r18, r18 # extract the byte of interest
+ # and fall through to the character verify rtn
+
+ # ots_verify_char
+ # R16 -> string
+ # R17 = length
+ # R18 = character to check
+ # result in R0: -1 if all matched, or position in range 0..length-1
+ # destroys R16-R18, R27-R28
+ #
+ .globl _OtsStringVerifyChar
+ .aent _OtsStringVerifyChar
+_OtsStringVerifyChar:
+ .frame sp,0,r26
+
+ sll r18, 8, r28 # Replicate char in the quadword...
+ beq r17, vc_fail # Quick exit if length=0
+
+ ldq_u r27, (r16) # First quadword of string
+ addq r16, r17, r0 # Point to end of string
+
+ subq r17, 8, r17 # Length > 8?
+ or r18, r28, r18 # ...
+
+ sll r18, 16, r28 # ...
+ bgt r17, vc_long # Skip if length > 8
+
+ ldq_u r16, -1(r0) # Last quadword of string
+ extql r27, r0, r27 # Position string at high end of QW
+
+ or r18, r28, r18 # ...
+ sll r18, 32, r28 # ...
+
+ extqh r16, r0, r16 # Position string at high end of QW
+ or r18, r28, r18 # Pattern fills a quadword
+
+ or r27, r16, r27 # String fills a quadword
+ xor r27, r18, r18 # Diff betw. string and pattern
+
+ subq r31, r17, r17 # 8 - length
+ extql r18, r17, r28 # Shift off bytes preceding string
+
+ lda r0, -1(r31) # Prepare to return -1 for all matched
+ cmpbge r31, r28, r27 # Set 1's where string=pattern
+
+ addl r28, 0, r18 # Is first LW all zero?
+ beq r28, vc_done # Quick exit if all matched
+
+ addq r27, 1, r28 # Flip the first '0' bit
+ beq r18, vc_geq_4 # No diffs in first longword
+
+ andnot r28, r27, r28 # Make one-bit mask of first diff
+ srl r28, 2, r0 # Map 1/2/4/8 -> 0/0/1/2
+
+ and r27, 1, r27 # 1 if first character matched
+ addq r0, r27, r0 # Bump by 1 if so
+
+ ret r31, (r26) # return
+
+ nop #.align 8
+
+vc_geq_4:
+ andnot r28, r27, r28 # Make one-bit mask of first diff
+ srl r28, 5, r27 # Map 10/20/48/80 -> 0/1/2/4
+
+ srl r28, 7, r28 # Map 10/20/40/80 -> 0/0/0/1
+ addq r27, 4, r0 # Bump by 4
+
+ subq r0, r28, r0 # and correct 4/5/6/8 -> 4/5/6/7
+vc_done:ret r31, (r26)
+
+ # Enter here if string length > 8.
+ # R16 -> start of string
+ # R17 = length - 8
+ # R18 = fill in bytes 0,1
+ # R27 = 1st QW of string
+ # R28 = fill in bytes 2,3
+
+ #.align 8
+vc_long:and r16, 7, r0 # Where in QW did we start?
+ or r18, r28, r18 # R18 has pattern in low 4 bytes
+
+ sll r18, 32, r28 # ...
+ addq r17, r0, r17 # Remaining length after 1st QW
+
+ or r18, r28, r18 # Pattern fills a QW
+ ldq_u r28, 8(r16) # Get next QW (string B)
+
+ xor r27, r18, r27 # Diff Betw. string and pattern
+ mskqh r27, r0, r27 # Discard diffs before string
+
+ subq r17, 16, r17 # More than two QW's to go?
+ subq r17, r0, r0 # Remember start point to compute len
+
+ ble r17, vc_bottom # Skip the loop if 2 QW's or less
+vc_loop:bne r27, vc_done_a
+
+ ldq_u r27, 16(r16) # Load string A
+ xor r28, r18, r28 # Diff betw string B and pattern
+
+ subq r17, 16, r17 # Decrement remaining length
+ bne r28, vc_done_b # Exit if a diff in string B
+
+ ldq_u r28, 24(r16) # Load string B
+ addq r16, 16, r16 # Increment pointer
+
+ xor r27, r18, r27 # Diff betw string A and pattern
+ bgt r17, vc_loop # Repeat if more than 2 QW's left
+
+vc_bottom:
+ bne r27, vc_done_a # Exit if a match in string A
+ addq r17, 8, r17 # More than 1 QW left?
+
+ xor r28, r18, r27 # Diff betw string B and pattern
+ ble r17, vc_last # Skip if this is last QW
+
+ subq r17, 16, r17 # Adjust len for final return
+ bne r27, vc_done_a # Exit if a match in string B
+
+ ldq_u r28, 16(r16) # Load string A
+ addq r17, 8, r17 # Ensure -7 <- (r17=len-8) <= 0
+
+ nop
+ xor r28, r18, r27 # Diff betw string A and pattern
+
+vc_last:mskqh r17, r17, r28 # -1 in bytes beyond string
+ subq r17, 16, r17 # Adjust len for final return
+
+ andnot r27, r28, r27 # Nonzeros only for diffs within string
+ bne r27, vc_done_a # Compute index if a diff found
+
+vc_fail:lda r0, -1(r31) # Else return -1
+ ret r31, (r26)
+
+vc_done_b:
+ addq r17, 8, r17 # Adjust length
+ mov r28, r27 # Put difference where it's expected
+
+vc_done_a:
+ cmpbge r31, r27, r28 # 1's where they match
+ subq r0, r17, r0 # (start - remaining) = base index
+
+ addl r27, 0, r16 # First longword all zero?
+ blbc r28, vc_exit # Return R0 if first char different
+
+ addq r28, 1, r27 # Flip the first '0' bit
+ beq r16, vc_geq_4x # Skip if no match in first 4
+
+ andnot r27, r28, r28 # Make one-bit mask of first match
+ srl r28, 2, r28 # Map 2/4/8 -> 0/1/2
+
+ addq r0, 1, r0 # Bump by 1
+ addq r0, r28, r0 # Add byte offset
+
+vc_exit:ret r31, (r26) # return
+
+vc_geq_4x:
+ andnot r27, r28, r28 # Make one-bit mask of first match
+
+ srl r28, 5, r27 # Map 10/20/48/80 -> 0/1/2/4
+ addq r0, 4, r0 # Bump by 4
+
+ srl r28, 7, r28 # Map 10/20/40/80 -> 0/0/0/1
+ addq r0, r27, r0 # Add 0/1/2/4
+
+ subq r0, r28, r0 # and correct
+ ret r31, (r26)
+
+ # ots_verify_mask
+ # This routine could be tailored by loading a longword or
+ # a quadword at a time and doing table lookups on the
+ # characters largely in parallel.
+ #
+ .globl _OtsStringVerifyMask
+ .aent _OtsStringVerifyMask
+_OtsStringVerifyMask:
+ .frame sp,0,r26
+
+ lda r16, -1(r16) # bias initial address for better loop code
+ nop # should be lnop (unop) or fnop to dual issue
+ lda r0, -1(r31) # initialize position to -1
+ ble r17, vm_ret # return -1 if source len is zero
+ # slow way - ~14 cycles/byte
+vm_loop:
+ ldq_u r21, 1(r16) # load qw containing the byte
+ lda r16, 1(r16) # bump pointer
+ addq r0, 1, r0 # bump position
+ subq r17, 1, r17 # decrement the length
+ extbl r21, r16, r21 # extract the byte
+ addq r21, r18, r21 # get the byte in the table
+ ldq_u r20, (r21) # load qw from table containing lookup
+ extbl r20, r21, r20 # extract table byte
+ and r20, r19, r20 # check if any bits in the mask match
+ beq r17, vm_end # if last character, handle specially
+ bne r20, vm_loop # if match, go do the loop again
+vm_ret:
+ ret r31, (r26) # if not a match, we're done
+vm_end: lda r21, -1(r31) # get -1
+ cmovne r20, r21, r0 # -1 if last char matched
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsLocation
diff --git a/private/crt32/misc/alpha/smove.s b/private/crt32/misc/alpha/smove.s
new file mode 100644
index 000000000..7428e97a8
--- /dev/null
+++ b/private/crt32/misc/alpha/smove.s
@@ -0,0 +1,652 @@
+ #++
+ # Copyright 1991, 1994, Digital Equipment Corporation
+ #
+ # ots_move(char *dstptr INOUT, long dstlen, char *srcptr)
+ #
+ # Move dstlen characters from *srcptr to *dstptr, possibly overlapping
+ #
+ # Special conventions: No stack space, r16-r20 and r27-r28 ONLY,
+ # no linkage pointer required, r16 is INOUT and points to the address
+ # following the move. (Warning: The auto-loader potentially takes
+ # some regs across the call if this is being used in a shared lib.
+ # environment.)
+ #
+ # This is a GEM support routine for moving (possibly overlapping) memory
+ # from one address to another. This is optimized for extremely high
+ # performance both for small blocks and large moves. In order to reduce
+ # overhead for small cases, they are retired as quickly as possible,
+ # more case analysis is reserved for cases which will do more. Note
+ # that while overlapping moves are supported, (unlike Sys V memcpy)
+ # routines), they are not quite as fast.
+ #
+ # Warning - This code is basically "expanded microcode". Since it is
+ # executed so frequently in many contexts, it has been extensively "hand-
+ # optimized"...
+ #
+ # Note that this routine and ots_movem are basically similar in many
+ # respects (same basic code), so maintenance should be done both
+ # places. This routine is primarily provided for lower overhead (for
+ # short strings).
+ #
+ # This version of OTS_MOVE provides longword granularity.
+ #
+ # 015 30 Aug 1994 WBN Longword granularity version, based on
+ # OTS_MOVE_ALPHA.M64 version 014.
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 = dst --> r16 = end
+ # r17 = len
+ # r18 = src
+ # destroys r17-r20, r27-r28
+
+ .globl _OtsMove
+ .ent _OtsMove
+_OtsMove:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+ .prologue 0
+ beq r17, done # No memory accesses if length=0
+ subq r17, 4, r20 # Get length-4
+ ldq_u r28, (r18) # Load first QW of source
+ addq r17, r18, r27 # Point to end of source
+ andnot r16, 3, r19 # LW-aligned dst pointer
+ bge r20, geq4 # Go handle lengths >= 4
+ ldq_u r27, -1(r27) # Load last QW of source
+ and r16, 3, r16 # Get dst alignment within LW
+ ldl r17, (r19) # Load first LW of destination
+ addq r20, r16, r20 # Get alignment+length-4
+ extql r28, r18, r28 # Extract first bytes of source
+ bgt r20, double # Go handle LW crossing
+ extqh r27, r18, r27 # Extract last bytes of source
+ addq r20, 4, r20 # Get ending alignment in LW
+ or r27, r28, r28 # Combine halves of source
+ insql r28, r16, r28 # Position low part of source
+ mskql r17, r16, r18 # Keep low bytes of destination
+ mskql r28, r20, r28 # Trim off high bytes of source
+ mskqh r17, r20, r17 # Keep high bytes of destination
+ or r18, r28, r28 # Combine source with low dest
+ or r17, r28, r28 # Combine with high dest
+ stl r28, (r19) # Store to destination
+ addq r19, r20, r16 # Point to end of dest for return
+ ret r31, (r26)
+
+double: extqh r27, r18, r27 # Extract last bytes of source
+ ldl r18, 4(r19) # Load second LW of destination
+ mskql r17, r16, r17 # Keep low bytes of 1st dest LW
+ or r27, r28, r28 # Combine parts of source
+ insql r28, r16, r27 # Position start of source
+ addq r16, 4, r16 # Compute virtual start in LW
+ insqh r28, r16, r28 # Position end of source
+ addq r19, 4, r19 # Prepare to compute end address
+ mskqh r18, r20, r18 # Keep high bytes of 2nd dest LW
+ mskql r28, r20, r28 # Trim end of source to length
+ or r27, r17, r17 # Combine low source with 1st LW
+ stl r17, -4(r19)
+ or r28, r18, r18 # Combine high source with 2nd LW
+ stl r18, (r19)
+ addq r19, r20, r16 # Point to end of dest for return
+done: ret r31, (r26)
+
+ # Come here to move >= 4 bytes.
+ #
+ # r16-> dst
+ # r17 = length
+ # r18-> src
+ # r19-> LW-aligned dst
+ # r20 = len-4
+ # r27 = src+len
+ # r28 = first src QW
+
+geq4: subq r20, 4, r17 # At least 8 bytes to move?
+ subq r16, r27, r27 # Check if dst >= src+len
+ blt r17, lss8 # Move 4..7 bytes
+ subq r18, r16, r17 # Check if src >= dst
+ bge r27, ok1 # Forward OK if whole src precedes dst
+ blt r17, reverse # Go backwards if src < dst < src+len
+ok1: and r16, 7, r16
+ addq r16, r20, r27 # Alignment + length - 4
+ bne r16, part # Part of first QW to be skipped
+ subq r20, 4, r20 # At least 8 bytes to be stored?
+ beq r27, simple # Only low LW to be stored
+ and r18, 7, r27 # Is src address now aligned?
+ blt r20, shortq # Dst ends in first QW
+ subq r20, 32, r17 # At least 4 quadwords left to move?
+ beq r27, align # Go handle matching alignment
+
+ # Src alignment differs from dst alignment.
+ # r16 = dst alignment
+ # r17
+ # r18 = src-8 after 1st move
+ # r19 = initial dst
+ # r20 = initial length-8
+ # r27 = dst QW if dst wasn't aligned
+ # r28 = source QW
+
+misal: or r16, r19, r19 # Put alignment back with dst ptr ***
+ ldq_u r17, 8(r18) # Load same or next source QW
+ extql r28, r18, r28 # Get first part of source to store
+ addq r20, r16, r20 # Adjust length for partial move
+ mskql r27, r19, r27 # Trim destination for merge
+ extqh r17, r18, r16 # Get second part of source
+ subq r20, 24, r20 # At least 4 more quadwords?
+ or r28, r16, r28 # Combine pieces of source
+ mskqh r28, r19, r28 # Trim low junk off source
+ andnot r19, 7, r19 # Adjust dst for partial move
+ bge r20, unrol2 # Taken branch for long strings
+ addq r20, 16, r16 # Add back: how many whole QW's?
+ nop
+short2: and r20, 7, r20 # How many odd bytes?
+ blt r16, last # Skip if no more whole QW's
+ or r28, r27, r28 # Combine pieces
+ stq r28, (r19)
+ extql r17, r18, r27 # Get last part of prior src QW
+ ldq_u r17, 16(r18) # Load another src QW
+ addq r19, 8, r19 # Update dst
+ subq r16, 8, r16 # More whole QW's?
+ addq r18, 8, r18 # Update src
+ blt r16, lastx # Skip if no more whole QWs
+ extqh r17, r18, r28 # Get first part of this src QW
+ addq r18, 8, r18 # Update src again
+ or r28, r27, r28 # Combine pieces
+ stq r28, (r19)
+ extql r17, r18, r27 # Get last part of this src QW
+ ldq_u r17, 8(r18) # Load another src QW
+ addq r19, 8, r19 # Update dst
+lastx: extqh r17, r18, r28 # Get first part of this src QW
+last: addq r18, r20, r16 # Point to end-8 of src
+ beq r20, done_u # Skip if no odd bytes
+ or r28, r27, r28 # Combine parts of last whole QW
+ ldq_u r27, 7(r16) # Load final (maybe same) src QW
+ subq r20, 4, r16 # More than 4 bytes left?
+ stq r28, (r19) # Store last whole QW
+ extql r17, r18, r17 # Get last part of this src QW
+ extqh r27, r18, r27 # Get what we need from final src QW
+joinx: ldq r28, 8(r19) # Load last QW of destination
+ or r17, r27, r27 # Combine pieces of source
+ mskql r27, r20, r27 # Trim to length
+ mskqh r28, r20, r28 # Make room in destination
+ bgt r16, done_u # Go store a whole QW
+ addq r20, 8, r20 # Increment length for return
+ or r28, r27, r28 # Insert src into dst
+ stl r28, 8(r19) # Final LW
+ addq r19, r20, r16 # Point to end of dst for return
+ ret r31, (r26)
+
+ # Come here to move 4 thru 7 bytes.
+ #
+lss8: addq r18, r17, r27 # Recover src+len-8
+ and r16, 3, r16 # Dst alignment within LW
+ ldq_u r27, 7(r27) # Load last part of source
+ extql r28, r18, r28 # Extract first part of source
+ beq r16, lw # Handle LW-aligned dst
+ extqh r27, r18, r27 # Extract last part of source
+ ldl r18, (r19) # Load first LW of dst
+ addq r16, r20, r20 # align+len-4 of dst
+ or r28, r27, r28 # Complete source
+ mskql r28, r17, r28 # Trim source to length
+ mskql r18, r16, r18 # Make room in dst
+ insql r28, r16, r27 # Position src like dst
+ addq r16, r17, r17 # Align+len-8 of dst
+ or r27, r18, r18 # Merge
+ stl r18, (r19) # Store first LW of dst
+ extql r27, 4, r27 # Position next LW of src
+ blt r17, zz # Skip if not a whole LW
+ stl r27, 4(r19) # Store the whole LW
+ addq r19, 4, r19 # Adjust pointer
+ subq r20, 4, r20 # Adjust ending alignment
+ beq r17, donezz # Exit if done
+ insqh r28, r16, r27 # Position remainder of src
+zz: ldl r28, 4(r19) # Load last dst LW
+ mskqh r28, r20, r28 # Make room in dst
+ or r28, r27, r27 # Merge
+ stl r27, 4(r19) # Final store
+donezz: addq r19, r20, r16 # End address -4
+ addq r16, 4, r16
+ ret r31, (r26)
+
+lw: extqh r27, r18, r27 # Extract last part of source
+ addq r19, 4, r16 # Adjust for return value
+ beq r20, lwdone # Skip if exactly 4 bytes
+ ldl r17, 4(r19) # Load next dst LW
+ or r27, r28, r28 # Complete source
+ stl r28, (r19) # Store first LW
+ extql r28, 4, r28 # Position rest of source
+ mskqh r17, r20, r27 # Make room in dst
+ mskql r28, r20, r28 # Trim src
+ or r27, r28, r28 # Merge
+ stl r28, 4(r19)
+ addq r16, r20, r16 # Update return value
+ ret r31, (r26)
+
+lwdone: or r27, r28, r28 # Merge
+ stl r28, (r19)
+ ret r31, (r26)
+
+ # Move 4 bytes to an aligned LW.
+ #
+simple: ldq_u r27, 3(r18) # Load last QW of source
+ extql r28, r18, r28 # Position first QW
+ addq r19, 4, r16 # Point to end of dst for return
+ extqh r27, r18, r27 # Position last QW
+ or r28, r27, r28 # Merge
+ stl r28, (r19) # Store
+ ret r31, (r26)
+
+
+ # Dst is not aligned. Check whether first write is to a LW or a QW,
+ # and whether that finishes the move. Then see if src alignment
+ # matches, and read/rewrite the first dst quadword.
+ #
+ # r16 = dst alignment in QW
+ # r17
+ # r18-> src
+ # r19-> LW-aligned dst
+ # r20 = len-4
+ # r27 = QW_alignment + length - 4
+ # r28 = first src QW
+
+ #.align quad
+
+part: subq r27, 4, r17 # Does dst end in first QW?
+ ldq_u r27, (r19) # Load first dst QW
+ blt r17, shortu # Go handle short store
+ and r16, 4, r17 # Does it start in high LW?
+ subq r18, r16, r18 # Adjust src for this partial move
+ beq r17, quad # Whole QW to be touched
+ extql r28, r18, r17 # Position first part of source
+ ldq_u r28, 7(r18) # Get next (or same) src QW
+ mskql r27, r16, r27 # Trim destination for merge
+ addq r20, r16, r20 # Len + alignment...
+ extqh r28, r18, r28 # Position second part of source
+ subq r20, 4, r20 # Len+alignment-8 = remaining len
+ or r28, r17, r28 # Pieces of source
+ mskqh r28, r16, r17 # Trim junk preceding source
+ ldq_u r28, 7(r18) # Get src QW again **
+ or r27, r17, r17 # Combine other source piece
+ extql r17, 4, r17 # Get the high LW
+ stl r17, (r19) # Store just that
+
+ # Now at a QW boundary. Is there a QW left to store?
+ # Is the source QW aligned?
+
+ andnot r19, 7, r19 # Adjust dst pointer to next-8
+ subq r20, 8, r17 # Got a QW more?
+ and r18, 7, r27 # Src aligned?
+ blt r17, short3 # Too short
+ addq r19, 8, r19
+ subq r20, 8, r20
+ ldq_u r28, 8(r18)
+ addq r18, 8, r18
+ subq r20, 32, r17 # Prepare for unrolled loop
+ beq r27, align # Alignment matches
+ or r31, r31, r27
+ or r31, r31, r16
+ br r31, misal
+
+shortu: addq r18, r20, r20 # Point to end-4 of src
+ ldq_u r20, 3(r20) # Get last QW of source
+ extql r28, r18, r28 # Fetch first QW of source
+ extqh r20, r18, r20 # Fetch last QW of source
+ mskql r27, r16, r18 # Clear from start thru end of dst
+ mskqh r27, r17, r27 # Clear from 0 to end of dst
+ or r28, r20, r28 # Combine src pieces
+ insql r28, r16, r28 # Position src
+ or r27, r18, r27 # Combine dst pieces
+ mskql r28, r17, r28 # Trim src
+ addq r19, r17, r20 # Final pointer for return
+ or r28, r27, r28 # Merge src & dst
+ stq_u r28, (r19) # Store it
+ addq r20, 8, r16
+ ret r31, (r26)
+
+quad: and r18, 7, r17 # Is src address now aligned?
+ subq r20, 4, r20 # Get length-8
+ bne r17, misal # Go handle mismatched alignment
+ mskqh r28, r16, r28 # Keep desired part of source
+ addq r20, r16, r20 # Adjust count for this partial move
+ mskql r27, r16, r27 # Keep desired part of destination QW
+ subq r20, 32, r17 # At least 4 quadwords left to move?
+ or r27, r28, r28 # Merge source and destination
+
+ # Src alignment matches.
+ # r16
+ # r17 = remaining length -32
+ # r18 = next src pointer -8
+ # r19 = dst pointer
+ # r20
+ # r27
+ # r28 = dst quadword
+
+align: and r17, 24, r20 # How many after a multiple of 4?
+ bge r17, unrol1 # Taken branch for long strings
+ nop
+short1: and r17, 7, r17 # How many odd bytes?
+ beq r20, last28 # Skip if no more whole QWs after r28
+ ldq r27, 8(r18) # Load next QW
+ addq r18, 8, r18
+ stq r28, (r19) # Store prior QW
+ subq r20, 16, r20 # Map 8/16/24 to -8/0/8
+ addq r19, 8, r19
+ blt r20, last27 # Skip if no more after r27
+ ldq r28, 8(r18) # Load next QW
+ addq r18, 8, r18
+ stq r27, (r19) # Store prior QW
+ addq r19, 8, r19
+ nop
+ beq r20, last28
+ ldq r27, 8(r18) # Load next QW
+ addq r18, 8, r18
+ stq r28, (r19) # Store prior QW
+ addq r19, 8, r19
+last27: beq r17, done27 # Skip if no odd bytes
+ ldq r28, 8(r18) # Load one more src QW
+ ldq r18, 8(r19) # Load last destination QW
+ subq r17, 4, r16 # More than 4 bytes to store?
+ stq r27, (r19) # Store prior QW
+ mskql r28, r17, r27 # Trim source
+ mskqh r18, r17, r18 # Trim destination
+ ble r16, lastl # Go store just a LW
+lastq: addq r19, r17, r19 # End-8 of dst for return
+ or r27, r18, r27 # Merge src & dst
+done27: stq_u r27, 7(r19) # Store last destination QW
+ addq r19, 8, r16 # End of dst for return
+ ret r31, (r26)
+
+short3: addq r18, r20, r16 # Point to end-8 of src
+ beq r20, donexx # Completely done?
+ ldq_u r17, 7(r16) # Load final src QW
+ subq r20, 4, r16 # Got more than a LW?
+ beq r27, joinx # Don't include prior src if aligned
+ extql r28, r18, r27 # Last part of prior src QW
+ extqh r17, r18, r17 # First part of this src QW
+ br joinx
+
+donexx: addq r19, r20, r16
+ addq r16, 8, r16
+ ret r31, (r26)
+
+last28: beq r17, done28 # Skip if no odd bytes
+ ldq r27, 8(r18) # Load one more src QW
+ ldq r18, 8(r19) # Load last destination QW
+ subq r17, 4, r16 # More than 4 bytes to store?
+ stq r28, (r19) # Store prior QW
+ mskql r27, r17, r27 # Trim source
+ mskqh r18, r17, r18 # Trim destination
+ bgt r16, lastq # Go store a QW
+lastl: addq r17, 8, r17 # Increment length for return
+ or r27, r18, r27 # Merge src & dst
+ stl r27, 8(r19) # Store last destination LW
+ addq r19, r17, r16 # End of dst for return
+ ret r31, (r26)
+
+shortq: addq r18, r20, r16 # Point to end-8 of src
+ ldq r27, (r19) # Get dst QW
+ extql r28, r18, r28 # Position first src QW
+ ldq_u r17, 7(r16) # Get last QW of src
+ mskqh r27, r20, r27 # Mask dst QW
+ extqh r17, r18, r17 # Position last src QW
+ or r17, r28, r28 # Merge
+ mskql r28, r20, r28 # Trim src QW
+done_u: addq r19, r20, r19 # End-8 of dst for return
+ or r28, r27, r28 # Combine pieces
+done28: stq_u r28, 7(r19) # Store last destination QW
+ addq r19, 8, r16 # End of dst for return
+ ret r31, (r26)
+
+ # Unrolled loop for long moves with matching alignment within QW.
+ # Each iteration moves two cache blocks.
+ # We try to schedule the cache misses to avoid a double miss
+ # in EV4 pass 2.1 chips. If the source alignment within a cache
+ # block is exactly 3, alter it, since that case runs slower.
+ #
+ # R19 = dst pointer
+ # R17 = remaining length (to load) - 32
+ # R18 = src pointer
+ # R16
+ # R20 = length & 24 (needed at return)
+ # R27
+ # R28 = QW from 0(R18) to store at 0(R19), both on input and at return
+ #
+
+ #.align quad
+
+unrol1: ldq r27, 32(r18) # Cache miss here; later loads hit.
+ subq r17, 48, r16 # Six more quadwords?
+ and r18, 16, r20 # Starting in 2nd half of cache block?
+ blt r16, uent1 # If not 6 more, don't adjust.
+ ldq r16, 8(r18)
+ beq r20, utop1 # If in 1st half, don't adjust.
+ ldq r27, 48(r18) # Cache miss here
+ addq r18, 16, r18
+ stq r28, (r19) # Adjust by going ahead 1/2 block.
+ addq r19, 16, r19
+ ldq r28, (r18)
+ subq r17, 16, r17
+ stq r16, -8(r19)
+ nop
+ ldq r16, 8(r18)
+utop1: subq r17, 32, r17
+
+uloop1: ldq r20, 64(r18) # Cache miss here
+ stq r28, (r19)
+ ldq r28, 16(r18)
+ stq r16, 8(r19)
+ ldq r16, 24(r18)
+ addq r18, 64, r18
+ stq r28, 16(r19)
+ mov r20, r28
+ stq r16, 24(r19)
+ addq r19, 64, r19
+ ldq r20, -24(r18)
+ subq r17, 32, r17
+ blt r17, uexit1
+ ldq r16, 32(r18) # Cache miss here
+ stq r27, -32(r19)
+ ldq r27, -16(r18)
+ stq r20, -24(r19)
+ ldq r20, -8(r18)
+ stq r27, -16(r19)
+ mov r16, r27
+ stq r20, -8(r19)
+uent1: subq r17, 32, r17
+ ldq r16, 8(r18)
+ bge r17, uloop1
+
+ # finish last block of 4 quadwords
+ #
+ubot1: stq r28, (r19)
+ mov r27, r28 # Position last QW for return
+ ldq r27, 16(r18)
+ addq r18, 32, r18
+ stq r16, 8(r19)
+ addq r19, 32, r19
+uex1a: ldq r16, -8(r18)
+ and r17, 24, r20 # Recover count of remaining QW's
+ stq r27, -16(r19)
+ stq r16, -8(r19)
+ br r31, short1
+
+ nop
+uexit1: stq r27, -32(r19) # Here if exit from middle of loop
+ ldq r27, -16(r18)
+ stq r20, -24(r19)
+ br r31, uex1a # Join common exit sequence
+
+ #.align quad
+
+unrol2: ldq_u r16, 16(r18) # Load next src QW
+ extql r17, r18, r17 # Get last part of prior one
+ or r28, r27, r28 # Combine pieces
+ stq r28, (r19) # Store prior dst QW
+ subq r20, 24, r20 # Update loop counter
+ extqh r16, r18, r28 # Get first part of a src QW
+ ldq_u r27, 24(r18) # Load next src QW
+ extql r16, r18, r16 # Get last part of prior one
+ or r28, r17, r28 # Combine pieces
+ stq r28, 8(r19) # Store prior dst QW
+ addq r19, 24, r19 # Update dst pointer
+ extqh r27, r18, r28 # Get first part of a src QW
+ ldq_u r17, 32(r18) # Load next src QW
+ extql r27, r18, r27 # Get last part of prior one
+ or r28, r16, r28 # Combine pieces
+ stq r28, -8(r19) # Store prior dst QW
+ addq r18, 24, r18 # Update src pointer
+ extqh r17, r18, r28 # Get first part of a src QW
+ bge r20, unrol2 # Repeat as needed
+ addq r20, 16, r16 # How many whole quadwords left?
+ br r31, short2 # Go handle leftovers
+ nop
+
+ # Must move in reverse order because of overlap.
+ # r16 = dst address
+ # r17
+ # r18 = src address
+ # r19
+ # r20 = len-4 (>= 0)
+ # r27
+ # r28
+
+ # Not yet LW-granularity...
+
+reverse:
+ subq r20, 4, r20 # This code expects len-8
+ addq r20, r18, r18 # Point to end-8 of source
+ addq r20, r16, r17 # Point to end-8 of destination
+ and r17, 7, r19 # Is destination aligned?
+ ldq_u r28, 7(r18) # Get source QW
+ addq r17, 8, r16 # Point to end of dst for return
+ bne r19, rpart # Skip if partial write needed
+ and r18, 7, r27 # Is source aligned too?
+ beq r27, ralign # Skip if so
+ ldq_u r19, (r18) # Handle aligned dst, unaligned src
+ subq r20, 8, r20
+ extqh r28, r18, r28
+ extql r19, r18, r27
+ br r31, rwhole
+
+rmis: ldq_u r19, (r18) # Load same or preceding src QW
+ extqh r28, r18, r28 # Get last part of source to store
+ mskqh r27, r16, r27 # Keep high-address part of dst
+ extql r19, r18, r19
+ subq r20, 8, r20 # How many more whole QW's?
+ or r19, r28, r28
+ ldq_u r19, (r18) # Reload source QW
+ mskql r28, r16, r28 # Trim source to length
+rwhole: blt r20, rlast2 # Skip if no more whole QW's
+rloop2: or r28, r27, r28 # Combine pieces
+ stq r28, (r17)
+rent2: extqh r19, r18, r27
+ ldq_u r19, -8(r18)
+ subq r20, 8, r20
+ subq r17, 8, r17
+ extql r19, r18, r28
+ subq r18, 8, r18
+ bge r20, rloop2
+rlast2: and r20, 7, r20
+ beq r20, rdone2
+ or r28, r27, r28
+ subq r18, r20, r27
+ stq r28, (r17)
+rl2ent: subq r31, r20, r20
+ ldq_u r27, (r27)
+ extqh r19, r18, r19
+ ldq r28, -8(r17)
+ subq r17, 8, r17
+ extql r27, r18, r27
+ mskql r28, r20, r28
+ or r27, r19, r27
+ mskqh r27, r20, r27
+ and r20, 4, r19 # Ending in high LW?
+ bne r19, rdone3 # Only longword store at the end
+rdone2: or r28, r27, r28
+ stq r28, (r17)
+ ret r31, (r26)
+
+rdone3: or r28, r27, r28
+ extql r28, 4, r28
+ stl r28, 4(r17)
+ ret r31, (r26)
+
+rpart: ldq_u r27, 7(r17) # Get dst QW
+ subq r19, 8, r19 # Get negative of bytes not moved
+ subq r18, r19, r18 # From src-8, get src after partial
+ subq r20, r19, r20 # Adjust length for partial move
+ subq r17, r19, r17 # Adjust dst pointer
+ addq r19, 4, r19 # End alignment - 4
+ ble r19, r_lw # Only storing the low longword?
+ and r18, 7, r19 # Src alignment now matching dst?
+ bne r19, rmis # Go back if not
+ mskql r28, r16, r28 # Keep low addresses of src QW
+ mskqh r27, r16, r27 # Keep high address of dst QW
+ralign: subq r20, 8, r20 # How many more whole QW's?
+ or r27, r28, r28 # Combine
+ blt r20, rlast1 # Skip if this is the end
+rloop1: stq r28, (r17) # Store one QW
+rent1: subq r20, 8, r20 # Decrement length
+ ldq r28, -8(r18) # Load preceding QW
+ subq r17, 8, r17 # Decrement dst pointer
+ subq r18, 8, r18 # Decrement src pointer
+ bge r20, rloop1 # Repeat for each whole QW
+rlast1: and r20, 7, r20 # How many odd bytes?
+ beq r20, rdone # Skip if none
+ ldq r27, -8(r18) # Get another source QW
+ subq r31, r20, r20 # Get byte # to end at
+ stq r28, (r17)
+rl_ent: ldq r28, -8(r17)
+ subq r17, 8, r17 # Adjust dst pointer again
+ mskqh r27, r20, r27 # Keep top of src QW
+ and r20, 4, r19 # Ending in high LW?
+ mskql r28, r20, r28 # Keep bottom of dst QW
+ bne r19, rdone4 # Only longword store at the end
+ or r27, r28, r28 # Combine
+rdone: stq r28, (r17) # Store last QW
+ ret r31, (r26)
+
+rdone4: or r27, r28, r28 # Combine
+ extql r28, 4, r28 # Get high part
+ stl r28, 4(r17) # Store last LW
+ ret r31, (r26)
+
+r_lw: and r18, 7, r19 # Src alignment now matching dst?
+ bne r19, rmislw # Go back if not
+ mskql r28, r16, r28 # Keep low addresses of src QW
+ mskqh r27, r16, r27 # Keep high address of dst QW
+ subq r20, 8, r20 # How many more whole QW's?
+ or r27, r28, r28 # Combine
+ blt r20, rlast1_lw # Skip if this is the end
+ stl r28, (r17) # Store one QW
+ br r31, rent1
+
+rlast1_lw:
+ and r20, 7, r20 # How many odd bytes?
+ ldq r27, -8(r18) # Get another source QW
+ subq r31, r20, r20 # Get byte # to end at
+ stl r28, (r17)
+ br rl_ent
+
+rmislw: ldq_u r19, (r18) # Load same or preceding src QW
+ extqh r28, r18, r28 # Get last part of source to store
+ mskqh r27, r16, r27 # Keep high-address part of dst
+ extql r19, r18, r19
+ subq r20, 8, r20 # How many more whole QW's?
+ or r19, r28, r28
+ ldq_u r19, (r18) # Reload source QW
+ mskql r28, r16, r28 # Trim source to length
+ blt r20, rlast2_lw # Skip if no more whole QW's
+ or r28, r27, r28 # Combine pieces
+ stl r28, (r17)
+ br r31, rent2
+
+rlast2_lw:
+ and r20, 7, r20
+ or r28, r27, r28
+ subq r18, r20, r27
+ stl r28, (r17)
+ br r31, rl2ent
+
+ .set at
+ .set reorder
+ .end _OtsMove
diff --git a/private/crt32/misc/alpha/smovem.s b/private/crt32/misc/alpha/smovem.s
new file mode 100644
index 000000000..11f859f20
--- /dev/null
+++ b/private/crt32/misc/alpha/smovem.s
@@ -0,0 +1,667 @@
+ #++
+ # Copyright 1991, 1994, Digital Equipment Corporation
+ #
+ # ots_movem(char *dstptr INOUT, long dstlen INOUT,
+ # char *srcptr, long srclen)
+ #
+ # Move dstlen characters from *srcptr to *dstptr, possibly overlapping
+ #
+ # Special conventions: No stack space, r16-r21 and r27-r28 ONLY,
+ # no linkage pointer required, r16 is INOUT and points to the address
+ # following the move, r17 is INOUT and has the remaining destination
+ # length following the move.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # This is a GEM support routine for moving (possibly overlapping) memory
+ # from one address to another. This is optimized for extremely high
+ # performance both for small blocks and large moves. In order to reduce
+ # overhead for small cases, they are retired as quickly as possible,
+ # more case analysis is reserved for cases which will do more. Note
+ # that while overlapping moves are supported, (unlike Sys V memcpy)
+ # routines), they are not quite as fast.
+ #
+ # Warning - This code is basically "expanded microcode". Since it is
+ # executed so frequently in many contexts, it has been extensively "hand-
+ # optimized"...
+ #
+ # Note that this routine and ots_move are basically similar in many
+ # respects (same basic code), so maintenance should be done both
+ # places. This routine is primarily provided for lower overhead (for
+ # short strings).
+ # [Except for the first few instructions, the recipe for creating OTS_MOVEM
+ # from OTS_MOVE is to change uses of R19->R21 and then R17->R19.]
+ #
+ # This version of OTS_MOVEM provides longword granularity.
+ #
+ # 015 1 Sep 1994 WBN Longword granularity version, based on
+ # OTS_MOVEM_ALPHA.M64 version 014 and
+ # OTS_MOVE_ALPHA_WNT.M64 version 015.
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 = dst --> r16 = end
+ # r19 = dst_len --> r17 = remaining
+ # r18 = src
+ # r19 = src_len
+ # destroys r18-r21, r27-r28
+
+ .globl _OtsMoveMinimum
+ .ent _OtsMoveMinimum
+_OtsMoveMinimum:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+ .prologue 0
+ subq r17, r19, r20 # Which length is larger?
+ cmovlt r20, r17, r19 # Min to r19
+ andnot r16, 3, r21 # LW-aligned dst pointer
+ subq r19, 4, r20 # Get length-4
+ beq r19, done # No memory accesses if length=0
+ ldq_u r28, (r18) # Load first QW of source
+ addq r19, r18, r27 # Point to end of source
+ subq r17, r19, r17 # Set remaining length for return
+ bge r20, geq4 # Go handle lengths >= 4
+ ldq_u r27, -1(r27) # Load last QW of source
+ and r16, 3, r16 # Get dst alignment within LW
+ ldl r19, (r21) # Load first LW of destination
+ addq r20, r16, r20 # Get alignment+length-4
+ extql r28, r18, r28 # Extract first bytes of source
+ bgt r20, double # Go handle LW crossing
+ extqh r27, r18, r27 # Extract last bytes of source
+ addq r20, 4, r20 # Get ending alignment in LW
+ or r27, r28, r28 # Combine halves of source
+ insql r28, r16, r28 # Position low part of source
+ mskql r19, r16, r18 # Keep low bytes of destination
+ mskql r28, r20, r28 # Trim off high bytes of source
+ mskqh r19, r20, r19 # Keep high bytes of destination
+ or r18, r28, r28 # Combine source with low dest
+ or r19, r28, r28 # Combine with high dest
+ stl r28, (r21) # Store to destination
+ addq r21, r20, r16 # Point to end of dest for return
+ ret r31, (r26)
+
+double: extqh r27, r18, r27 # Extract last bytes of source
+ ldl r18, 4(r21) # Load second LW of destination
+ mskql r19, r16, r19 # Keep low bytes of 1st dest LW
+ or r27, r28, r28 # Combine parts of source
+ insql r28, r16, r27 # Position start of source
+ addq r16, 4, r16 # Compute virtual start in LW
+ insqh r28, r16, r28 # Position end of source
+ addq r21, 4, r21 # Prepare to compute end address
+ mskqh r18, r20, r18 # Keep high bytes of 2nd dest LW
+ mskql r28, r20, r28 # Trim end of source to length
+ or r27, r19, r19 # Combine low source with 1st LW
+ stl r19, -4(r21)
+ or r28, r18, r18 # Combine high source with 2nd LW
+ stl r18, (r21)
+ addq r21, r20, r16 # Point to end of dest for return
+done: ret r31, (r26)
+
+ # Come here to move >= 4 bytes.
+ #
+ # r16-> dst
+ # r17 = remaining length for return
+ # r18-> src
+ # r19 = length
+ # r20 = len-4
+ # r21-> LW-aligned dst
+ # r27 = src+len
+ # r28 = first src QW
+
+geq4: subq r20, 4, r19 # At least 8 bytes to move?
+ subq r16, r27, r27 # Check if dst >= src+len
+ blt r19, lss8 # Move 4..7 bytes
+ subq r18, r16, r19 # Check if src >= dst
+ bge r27, ok1 # Forward OK if whole src precedes dst
+ blt r19, reverse # Go backwards if src < dst < src+len
+ok1: and r16, 7, r16
+ addq r16, r20, r27 # Alignment + length - 4
+ bne r16, part # Part of first QW to be skipped
+ subq r20, 4, r20 # At least 8 bytes to be stored?
+ beq r27, simple # Only low LW to be stored
+ and r18, 7, r27 # Is src address now aligned?
+ blt r20, shortq # Dst ends in first QW
+ subq r20, 32, r19 # At least 4 quadwords left to move?
+ beq r27, align # Go handle matching alignment
+
+ # Src alignment differs from dst alignment.
+ # r16 = dst alignment
+ # r17 = remaining length for return
+ # r18 = src-8 after 1st move
+ # r19
+ # r20 = initial length-8
+ # r21 = initial dst
+ # r27 = dst QW if dst wasn't aligned
+ # r28 = source QW
+
+misal: or r16, r21, r21 # Put alignment back with dst ptr ***
+ ldq_u r19, 8(r18) # Load same or next source QW
+ extql r28, r18, r28 # Get first part of source to store
+ addq r20, r16, r20 # Adjust length for partial move
+ mskql r27, r21, r27 # Trim destination for merge
+ extqh r19, r18, r16 # Get second part of source
+ subq r20, 24, r20 # At least 4 more quadwords?
+ or r28, r16, r28 # Combine pieces of source
+ mskqh r28, r21, r28 # Trim low junk off source
+ andnot r21, 7, r21 # Adjust dst for partial move
+ bge r20, unrol2 # Taken branch for long strings
+ addq r20, 16, r16 # Add back: how many whole QW's?
+ nop
+short2: and r20, 7, r20 # How many odd bytes?
+ blt r16, last # Skip if no more whole QW's
+ or r28, r27, r28 # Combine pieces
+ stq r28, (r21)
+ extql r19, r18, r27 # Get last part of prior src QW
+ ldq_u r19, 16(r18) # Load another src QW
+ addq r21, 8, r21 # Update dst
+ subq r16, 8, r16 # More whole QW's?
+ addq r18, 8, r18 # Update src
+ blt r16, lastx # Skip if no more whole QWs
+ extqh r19, r18, r28 # Get first part of this src QW
+ addq r18, 8, r18 # Update src again
+ or r28, r27, r28 # Combine pieces
+ stq r28, (r21)
+ extql r19, r18, r27 # Get last part of this src QW
+ ldq_u r19, 8(r18) # Load another src QW
+ addq r21, 8, r21 # Update dst
+lastx: extqh r19, r18, r28 # Get first part of this src QW
+last: addq r18, r20, r16 # Point to end-8 of src
+ beq r20, done_u # Skip if no odd bytes
+ or r28, r27, r28 # Combine parts of last whole QW
+ ldq_u r27, 7(r16) # Load final (maybe same) src QW
+ subq r20, 4, r16 # More than 4 bytes left?
+ stq r28, (r21) # Store last whole QW
+ extql r19, r18, r19 # Get last part of this src QW
+ extqh r27, r18, r27 # Get what we need from final src QW
+joinx: ldq r28, 8(r21) # Load last QW of destination
+ or r19, r27, r27 # Combine pieces of source
+ mskql r27, r20, r27 # Trim to length
+ mskqh r28, r20, r28 # Make room in destination
+ bgt r16, done_u # Go store a whole QW
+ addq r20, 8, r20 # Increment length for return
+ or r28, r27, r28 # Insert src into dst
+ stl r28, 8(r21) # Final LW
+ addq r21, r20, r16 # Point to end of dst for return
+ ret r31, (r26)
+
+ # Come here to move 4 thru 7 bytes.
+ #
+lss8: addq r18, r19, r27 # Recover src+len-8
+ and r16, 3, r16 # Dst alignment within LW
+ ldq_u r27, 7(r27) # Load last part of source
+ extql r28, r18, r28 # Extract first part of source
+ beq r16, lw # Handle LW-aligned dst
+ extqh r27, r18, r27 # Extract last part of source
+ ldl r18, (r21) # Load first LW of dst
+ addq r16, r20, r20 # align+len-4 of dst
+ or r28, r27, r28 # Complete source
+ mskql r28, r19, r28 # Trim source to length
+ mskql r18, r16, r18 # Make room in dst
+ insql r28, r16, r27 # Position src like dst
+ addq r16, r19, r19 # Align+len-8 of dst
+ or r27, r18, r18 # Merge
+ stl r18, (r21) # Store first LW of dst
+ extql r27, 4, r27 # Position next LW of src
+ blt r19, zz # Skip if not a whole LW
+ stl r27, 4(r21) # Store the whole LW
+ addq r21, 4, r21 # Adjust pointer
+ subq r20, 4, r20 # Adjust ending alignment
+ beq r19, donezz # Exit if done
+ insqh r28, r16, r27 # Position remainder of src
+zz: ldl r28, 4(r21) # Load last dst LW
+ mskqh r28, r20, r28 # Make room in dst
+ or r28, r27, r27 # Merge
+ stl r27, 4(r21) # Final store
+donezz: addq r21, r20, r16 # End address -4
+ addq r16, 4, r16
+ ret r31, (r26)
+
+lw: extqh r27, r18, r27 # Extract last part of source
+ addq r21, 4, r16 # Adjust for return value
+ beq r20, lwdone # Skip if exactly 4 bytes
+ ldl r19, 4(r21) # Load next dst LW
+ or r27, r28, r28 # Complete source
+ stl r28, (r21) # Store first LW
+ extql r28, 4, r28 # Position rest of source
+ mskqh r19, r20, r27 # Make room in dst
+ mskql r28, r20, r28 # Trim src
+ or r27, r28, r28 # Merge
+ stl r28, 4(r21)
+ addq r16, r20, r16 # Update return value
+ ret r31, (r26)
+
+lwdone: or r27, r28, r28 # Merge
+ stl r28, (r21)
+ ret r31, (r26)
+
+ # Move 4 bytes to an aligned LW.
+ #
+simple: ldq_u r27, 3(r18) # Load last QW of source
+ extql r28, r18, r28 # Position first QW
+ addq r21, 4, r16 # Point to end of dst for return
+ extqh r27, r18, r27 # Position last QW
+ or r28, r27, r28 # Merge
+ stl r28, (r21) # Store
+ ret r31, (r26)
+
+
+ # Dst is not aligned. Check whether first write is to a LW or a QW,
+ # and whether that finishes the move. Then see if src alignment
+ # matches, and read/rewrite the first dst quadword.
+ #
+ # r16 = dst alignment in QW
+ # r17 = remaining length for return
+ # r18-> src
+ # r19
+ # r20 = len-4
+ # r21-> LW-aligned dst
+ # r27 = QW_alignment + length - 4
+ # r28 = first src QW
+
+ #.align quad
+
+part: subq r27, 4, r19 # Does dst end in first QW?
+ ldq_u r27, (r21) # Load first dst QW
+ blt r19, shortu # Go handle short store
+ and r16, 4, r19 # Does it start in high LW?
+ subq r18, r16, r18 # Adjust src for this partial move
+ beq r19, quad # Whole QW to be touched
+ extql r28, r18, r19 # Position first part of source
+ ldq_u r28, 7(r18) # Get next (or same) src QW
+ mskql r27, r16, r27 # Trim destination for merge
+ addq r20, r16, r20 # Len + alignment...
+ extqh r28, r18, r28 # Position second part of source
+ subq r20, 4, r20 # Len+alignment-8 = remaining len
+ or r28, r19, r28 # Pieces of source
+ mskqh r28, r16, r19 # Trim junk preceding source
+ ldq_u r28, 7(r18) # Get src QW again **
+ or r27, r19, r19 # Combine other source piece
+ extql r19, 4, r19 # Get the high LW
+ stl r19, (r21) # Store just that
+
+ # Now at a QW boundary. Is there a QW left to store?
+ # Is the source QW aligned?
+
+ andnot r21, 7, r21 # Adjust dst pointer to next-8
+ subq r20, 8, r19 # Got a QW more?
+ and r18, 7, r27 # Src aligned?
+ blt r19, short3 # Too short
+ addq r21, 8, r21
+ subq r20, 8, r20
+ ldq_u r28, 8(r18)
+ addq r18, 8, r18
+ subq r20, 32, r19 # Prepare for unrolled loop
+ beq r27, align # Alignment matches
+ or r31, r31, r27
+ or r31, r31, r16
+ br r31, misal
+
+shortu: addq r18, r20, r20 # Point to end-4 of src
+ ldq_u r20, 3(r20) # Get last QW of source
+ extql r28, r18, r28 # Fetch first QW of source
+ extqh r20, r18, r20 # Fetch last QW of source
+ mskql r27, r16, r18 # Clear from start thru end of dst
+ mskqh r27, r19, r27 # Clear from 0 to end of dst
+ or r28, r20, r28 # Combine src pieces
+ insql r28, r16, r28 # Position src
+ or r27, r18, r27 # Combine dst pieces
+ mskql r28, r19, r28 # Trim src
+ addq r21, r19, r20 # Final pointer for return
+ or r28, r27, r28 # Merge src & dst
+ stq_u r28, (r21) # Store it
+ addq r20, 8, r16
+ ret r31, (r26)
+
+quad: and r18, 7, r19 # Is src address now aligned?
+ subq r20, 4, r20 # Get length-8
+ bne r19, misal # Go handle mismatched alignment
+ mskqh r28, r16, r28 # Keep desired part of source
+ addq r20, r16, r20 # Adjust count for this partial move
+ mskql r27, r16, r27 # Keep desired part of destination QW
+ subq r20, 32, r19 # At least 4 quadwords left to move?
+ or r27, r28, r28 # Merge source and destination
+
+ # Src alignment matches.
+ # r16
+ # r17 = remaining length for return
+ # r18 = next src pointer -8
+ # r19 = remaining length -32
+ # r20
+ # r21 = dst pointer
+ # r27
+ # r28 = dst quadword
+
+align: and r19, 24, r20 # How many after a multiple of 4?
+ bge r19, unrol1 # Taken branch for long strings
+ nop
+short1: and r19, 7, r19 # How many odd bytes?
+ beq r20, last28 # Skip if no more whole QWs after r28
+ ldq r27, 8(r18) # Load next QW
+ addq r18, 8, r18
+ stq r28, (r21) # Store prior QW
+ subq r20, 16, r20 # Map 8/16/24 to -8/0/8
+ addq r21, 8, r21
+ blt r20, last27 # Skip if no more after r27
+ ldq r28, 8(r18) # Load next QW
+ addq r18, 8, r18
+ stq r27, (r21) # Store prior QW
+ addq r21, 8, r21
+ nop
+ beq r20, last28
+ ldq r27, 8(r18) # Load next QW
+ addq r18, 8, r18
+ stq r28, (r21) # Store prior QW
+ addq r21, 8, r21
+last27: beq r19, done27 # Skip if no odd bytes
+ ldq r28, 8(r18) # Load one more src QW
+ ldq r18, 8(r21) # Load last destination QW
+ subq r19, 4, r16 # More than 4 bytes to store?
+ stq r27, (r21) # Store prior QW
+ mskql r28, r19, r27 # Trim source
+ mskqh r18, r19, r18 # Trim destination
+ ble r16, lastl # Go store just a LW
+lastq: addq r21, r19, r21 # End-8 of dst for return
+ or r27, r18, r27 # Merge src & dst
+done27: stq_u r27, 7(r21) # Store last destination QW
+ addq r21, 8, r16 # End of dst for return
+ ret r31, (r26)
+
+short3: addq r18, r20, r16 # Point to end-8 of src
+ beq r20, donexx # Completely done?
+ ldq_u r19, 7(r16) # Load final src QW
+ subq r20, 4, r16 # Got more than a LW?
+ beq r27, joinx # Don't include prior src if aligned
+ extql r28, r18, r27 # Last part of prior src QW
+ extqh r19, r18, r19 # First part of this src QW
+ br joinx
+
+donexx: addq r21, r20, r16
+ addq r16, 8, r16
+ ret r31, (r26)
+
+last28: beq r19, done28 # Skip if no odd bytes
+ ldq r27, 8(r18) # Load one more src QW
+ ldq r18, 8(r21) # Load last destination QW
+ subq r19, 4, r16 # More than 4 bytes to store?
+ stq r28, (r21) # Store prior QW
+ mskql r27, r19, r27 # Trim source
+ mskqh r18, r19, r18 # Trim destination
+ bgt r16, lastq # Go store a QW
+lastl: addq r19, 8, r19 # Increment length for return
+ or r27, r18, r27 # Merge src & dst
+ stl r27, 8(r21) # Store last destination LW
+ addq r21, r19, r16 # End of dst for return
+ ret r31, (r26)
+
+shortq: addq r18, r20, r16 # Point to end-8 of src
+ ldq r27, (r21) # Get dst QW
+ extql r28, r18, r28 # Position first src QW
+ ldq_u r19, 7(r16) # Get last QW of src
+ mskqh r27, r20, r27 # Mask dst QW
+ extqh r19, r18, r19 # Position last src QW
+ or r19, r28, r28 # Merge
+ mskql r28, r20, r28 # Trim src QW
+done_u: addq r21, r20, r21 # End-8 of dst for return
+ or r28, r27, r28 # Combine pieces
+done28: stq_u r28, 7(r21) # Store last destination QW
+ addq r21, 8, r16 # End of dst for return
+ ret r31, (r26)
+
+ # Unrolled loop for long moves with matching alignment within QW.
+ # Each iteration moves two cache blocks.
+ # We try to schedule the cache misses to avoid a double miss
+ # in EV4 pass 2.1 chips. If the source alignment within a cache
+ # block is exactly 3, alter it, since that case runs slower.
+ #
+ # R16
+ # R17 = remaining length for return
+ # R18 = src pointer
+ # R19 = remaining length (to load) - 32
+ # R20 = length & 24 (needed at return)
+ # R21 = dst pointer
+ # R27
+ # R28 = QW from 0(R18) to store at 0(R21), both on input and at return
+ #
+
+ #.align quad
+
+unrol1: ldq r27, 32(r18) # Cache miss here; later loads hit.
+ subq r19, 48, r16 # Six more quadwords?
+ and r18, 16, r20 # Starting in 2nd half of cache block?
+ blt r16, uent1 # If not 6 more, don't adjust.
+ ldq r16, 8(r18)
+ beq r20, utop1 # If in 1st half, don't adjust.
+ ldq r27, 48(r18) # Cache miss here
+ addq r18, 16, r18
+ stq r28, (r21) # Adjust by going ahead 1/2 block.
+ addq r21, 16, r21
+ ldq r28, (r18)
+ subq r19, 16, r19
+ stq r16, -8(r21)
+ nop
+ ldq r16, 8(r18)
+utop1: subq r19, 32, r19
+
+uloop1: ldq r20, 64(r18) # Cache miss here
+ stq r28, (r21)
+ ldq r28, 16(r18)
+ stq r16, 8(r21)
+ ldq r16, 24(r18)
+ addq r18, 64, r18
+ stq r28, 16(r21)
+ mov r20, r28
+ stq r16, 24(r21)
+ addq r21, 64, r21
+ ldq r20, -24(r18)
+ subq r19, 32, r19
+ blt r19, uexit1
+ ldq r16, 32(r18) # Cache miss here
+ stq r27, -32(r21)
+ ldq r27, -16(r18)
+ stq r20, -24(r21)
+ ldq r20, -8(r18)
+ stq r27, -16(r21)
+ mov r16, r27
+ stq r20, -8(r21)
+uent1: subq r19, 32, r19
+ ldq r16, 8(r18)
+ bge r19, uloop1
+
+ # finish last block of 4 quadwords
+ #
+ubot1: stq r28, (r21)
+ mov r27, r28 # Position last QW for return
+ ldq r27, 16(r18)
+ addq r18, 32, r18
+ stq r16, 8(r21)
+ addq r21, 32, r21
+uex1a: ldq r16, -8(r18)
+ and r19, 24, r20 # Recover count of remaining QW's
+ stq r27, -16(r21)
+ stq r16, -8(r21)
+ br r31, short1
+
+ nop
+uexit1: stq r27, -32(r21) # Here if exit from middle of loop
+ ldq r27, -16(r18)
+ stq r20, -24(r21)
+ br r31, uex1a # Join common exit sequence
+
+ #.align quad
+
+unrol2: ldq_u r16, 16(r18) # Load next src QW
+ extql r19, r18, r19 # Get last part of prior one
+ or r28, r27, r28 # Combine pieces
+ stq r28, (r21) # Store prior dst QW
+ subq r20, 24, r20 # Update loop counter
+ extqh r16, r18, r28 # Get first part of a src QW
+ ldq_u r27, 24(r18) # Load next src QW
+ extql r16, r18, r16 # Get last part of prior one
+ or r28, r19, r28 # Combine pieces
+ stq r28, 8(r21) # Store prior dst QW
+ addq r21, 24, r21 # Update dst pointer
+ extqh r27, r18, r28 # Get first part of a src QW
+ ldq_u r19, 32(r18) # Load next src QW
+ extql r27, r18, r27 # Get last part of prior one
+ or r28, r16, r28 # Combine pieces
+ stq r28, -8(r21) # Store prior dst QW
+ addq r18, 24, r18 # Update src pointer
+ extqh r19, r18, r28 # Get first part of a src QW
+ bge r20, unrol2 # Repeat as needed
+ addq r20, 16, r16 # How many whole quadwords left?
+ br r31, short2 # Go handle leftovers
+ nop
+
+ # Must move in reverse order because of overlap.
+ # r16 = dst address
+ # r17 = remaining length for return
+ # r18 = src address
+ # r19
+ # r20 = len-4 (>= 0)
+ # r21
+ # r27
+ # r28
+
+ # Not yet LW-granularity...
+
+reverse:
+ subq r20, 4, r20 # This code expects len-8
+ addq r20, r18, r18 # Point to end-8 of source
+ addq r20, r16, r19 # Point to end-8 of destination
+ and r19, 7, r21 # Is destination aligned?
+ ldq_u r28, 7(r18) # Get source QW
+ addq r19, 8, r16 # Point to end of dst for return
+ bne r21, rpart # Skip if partial write needed
+ and r18, 7, r27 # Is source aligned too?
+ beq r27, ralign # Skip if so
+ ldq_u r21, (r18) # Handle aligned dst, unaligned src
+ subq r20, 8, r20
+ extqh r28, r18, r28
+ extql r21, r18, r27
+ br r31, rwhole
+
+rmis: ldq_u r21, (r18) # Load same or preceding src QW
+ extqh r28, r18, r28 # Get last part of source to store
+ mskqh r27, r16, r27 # Keep high-address part of dst
+ extql r21, r18, r21
+ subq r20, 8, r20 # How many more whole QW's?
+ or r21, r28, r28
+ ldq_u r21, (r18) # Reload source QW
+ mskql r28, r16, r28 # Trim source to length
+rwhole: blt r20, rlast2 # Skip if no more whole QW's
+rloop2: or r28, r27, r28 # Combine pieces
+ stq r28, (r19)
+rent2: extqh r21, r18, r27
+ ldq_u r21, -8(r18)
+ subq r20, 8, r20
+ subq r19, 8, r19
+ extql r21, r18, r28
+ subq r18, 8, r18
+ bge r20, rloop2
+rlast2: and r20, 7, r20
+ beq r20, rdone2
+ or r28, r27, r28
+ subq r18, r20, r27
+ stq r28, (r19)
+rl2ent: subq r31, r20, r20
+ ldq_u r27, (r27)
+ extqh r21, r18, r21
+ ldq r28, -8(r19)
+ subq r19, 8, r19
+ extql r27, r18, r27
+ mskql r28, r20, r28
+ or r27, r21, r27
+ mskqh r27, r20, r27
+ and r20, 4, r21 # Ending in high LW?
+ bne r21, rdone3 # Only longword store at the end
+rdone2: or r28, r27, r28
+ stq r28, (r19)
+ ret r31, (r26)
+
+rdone3: or r28, r27, r28
+ extql r28, 4, r28
+ stl r28, 4(r19)
+ ret r31, (r26)
+
+rpart: ldq_u r27, 7(r19) # Get dst QW
+ subq r21, 8, r21 # Get negative of bytes not moved
+ subq r18, r21, r18 # From src-8, get src after partial
+ subq r20, r21, r20 # Adjust length for partial move
+ subq r19, r21, r19 # Adjust dst pointer
+ addq r21, 4, r21 # End alignment - 4
+ ble r21, r_lw # Only storing the low longword?
+ and r18, 7, r21 # Src alignment now matching dst?
+ bne r21, rmis # Go back if not
+ mskql r28, r16, r28 # Keep low addresses of src QW
+ mskqh r27, r16, r27 # Keep high address of dst QW
+ralign: subq r20, 8, r20 # How many more whole QW's?
+ or r27, r28, r28 # Combine
+ blt r20, rlast1 # Skip if this is the end
+rloop1: stq r28, (r19) # Store one QW
+rent1: subq r20, 8, r20 # Decrement length
+ ldq r28, -8(r18) # Load preceding QW
+ subq r19, 8, r19 # Decrement dst pointer
+ subq r18, 8, r18 # Decrement src pointer
+ bge r20, rloop1 # Repeat for each whole QW
+rlast1: and r20, 7, r20 # How many odd bytes?
+ beq r20, rdone # Skip if none
+ ldq r27, -8(r18) # Get another source QW
+ subq r31, r20, r20 # Get byte # to end at
+ stq r28, (r19)
+rl_ent: ldq r28, -8(r19)
+ subq r19, 8, r19 # Adjust dst pointer again
+ mskqh r27, r20, r27 # Keep top of src QW
+ and r20, 4, r21 # Ending in high LW?
+ mskql r28, r20, r28 # Keep bottom of dst QW
+ bne r21, rdone4 # Only longword store at the end
+ or r27, r28, r28 # Combine
+rdone: stq r28, (r19) # Store last QW
+ ret r31, (r26)
+
+rdone4: or r27, r28, r28 # Combine
+ extql r28, 4, r28 # Get high part
+ stl r28, 4(r19) # Store last LW
+ ret r31, (r26)
+
+r_lw: and r18, 7, r21 # Src alignment now matching dst?
+ bne r21, rmislw # Go back if not
+ mskql r28, r16, r28 # Keep low addresses of src QW
+ mskqh r27, r16, r27 # Keep high address of dst QW
+ subq r20, 8, r20 # How many more whole QW's?
+ or r27, r28, r28 # Combine
+ blt r20, rlast1_lw # Skip if this is the end
+ stl r28, (r19) # Store one QW
+ br r31, rent1
+
+rlast1_lw:
+ and r20, 7, r20 # How many odd bytes?
+ ldq r27, -8(r18) # Get another source QW
+ subq r31, r20, r20 # Get byte # to end at
+ stl r28, (r19)
+ br rl_ent
+
+rmislw: ldq_u r21, (r18) # Load same or preceding src QW
+ extqh r28, r18, r28 # Get last part of source to store
+ mskqh r27, r16, r27 # Keep high-address part of dst
+ extql r21, r18, r21
+ subq r20, 8, r20 # How many more whole QW's?
+ or r21, r28, r28
+ ldq_u r21, (r18) # Reload source QW
+ mskql r28, r16, r28 # Trim source to length
+ blt r20, rlast2_lw # Skip if no more whole QW's
+ or r28, r27, r28 # Combine pieces
+ stl r28, (r19)
+ br r31, rent2
+
+rlast2_lw:
+ and r20, 7, r20
+ or r28, r27, r28
+ subq r18, r20, r27
+ stl r28, (r19)
+ br r31, rl2ent
+
+ .set at
+ .set reorder
+ .end _OtsMove
diff --git a/private/crt32/misc/alpha/strans.s b/private/crt32/misc/alpha/strans.s
new file mode 100644
index 000000000..9c738dce7
--- /dev/null
+++ b/private/crt32/misc/alpha/strans.s
@@ -0,0 +1,122 @@
+ #++
+ #
+ # Copyright (c) 1993 by
+ # Digital Equipment Corporation, Maynard, MA
+ #
+ # This software is furnished under a license and may be used and copied
+ # only in accordance with the terms of such license and with the
+ # inclusion of the above copyright notice. This software or any other
+ # copies thereof may not be provided or otherwise made available to any
+ # other person. No title to and ownership of the software is hereby
+ # transferred.
+ #
+ # The information in this software is subject to change without notice
+ # and should not be construed as a commitment by Digital Equipment
+ # Corporation.
+ #
+ # Digital assumes no responsibility for the use or reliability of its
+ # software on equipment which is not supplied by Digital.
+ #
+
+ # Facility:
+ #
+ # GEM/OTS - GEM compiler system support library
+ #
+ # Abstract:
+ #
+ # OTS character string support, Alpha version
+ #
+ # Authors:
+ #
+ # Kent Glossop
+ #
+ # void ots_translate(char *dst, long dstlen, char *src, char table[256]);
+ #
+ # Translates a string using a translation table. Handles overlap.
+ #
+ # Special conventions: No stack space, r16-r21 and r26-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # Modification history:
+ #
+ # 006 13 Nov 1992 KDG Initial non-tailored assembly version,
+ # replacing BLISS -005
+ #
+ # 007 26 Jan 1993 KDG Add underscore
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 destination address
+ # r17 length
+ # r18 source address
+ # r19 table address
+ # r20,r21,r27,r28 scratch
+ # r26 return address
+ #
+ .globl _OtsStringTranslate
+ .ent _OtsStringTranslate
+_OtsStringTranslate:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+
+ # sort out which case to use
+ addq r18, r17, r27 # get end address of source + 1 for overlap check
+ cmpult r18, r16, r28 # true if src at lower addr than dest (note trans to self is not a "slow" case)
+ cmpult r16, r27, r27 # true if dst starts before end of src
+ beq r17, done # don't touch memory if length=0
+ and r27, r28, r28 # does dst have bad overlap with src?
+ blbs r28, overlap # go handle poorly overlapping src/dst
+
+ # simple forward loop case (~16 cycles/byte EV4)
+ # (length is presumed to be at least 1)
+ subq r18, 1, r18 # one before the beginning of the source
+ subq r16, 1, r16 # one before the beginning of the destination
+forward_loop:
+ ldq_u r20, 1(r18) # load the qw containing the source
+ lda r18, 1(r18) # bump the source pointer
+ ldq_u r21, 1(r16) # load the qw containing the destination
+ lda r16, 1(r16) # bump the destination pointer
+ extbl r20 ,r18, r20 # get the byte to translate
+ addq r19, r20, r20 # get the address of the translation
+ ldq_u r27, (r20) # load the translation
+ subq r17, 1, r17 # decrement length
+ mskbl r21, r16, r21 # clear the bits in the destination
+ extbl r27, r20, r27 # extract the translation
+ insbl r27, r16, r27 # position for insertion
+ bis r27, r21, r21 # merge into the destination
+ stq_u r21, (r16) # store back
+ bgt r17, forward_loop # do another if there
+
+done: ret r31, (r26)
+ nop #.align 3
+
+ # bad overlap case (~16 cycles/byte EV4, 11c/byte EV5)
+ # (length is presumed to be at least 1)
+overlap:
+ addq r17, r18, r18 # one past the end of the source
+ addq r17, r16, r16 # one past the end of the destination
+backward_loop:
+ ldq_u r20, -1(r18) # load the qw containing the source
+ lda r18, -1(r18) # bump the source pointer
+ ldq_u r21, -1(r16) # load the qw containing the destination
+ lda r16, -1(r16) # bump the destination pointer
+ extbl r20 ,r18, r20 # get the byte to translate
+ addq r19, r20, r20 # get the address of the translation
+ ldq_u r27, (r20) # load the translation
+ subq r17, 1, r17 # decrement length
+ mskbl r21, r16, r21 # clear the bits in the destination
+ extbl r27, r20, r27 # extract the translation
+ insbl r27, r16, r27 # position for insertion
+ bis r27, r21, r21 # merge into the destination
+ stq_u r21, (r16) # store back
+ bgt r17, backward_loop # do another if there
+
+ ret r31, (r26)
+
+ .set at
+ .set reorder
+ .end _OtsStringTranslate
diff --git a/private/crt32/misc/alpha/strcmp_.s b/private/crt32/misc/alpha/strcmp_.s
new file mode 100644
index 000000000..dc25bfebc
--- /dev/null
+++ b/private/crt32/misc/alpha/strcmp_.s
@@ -0,0 +1,357 @@
+ #****************************************************************************
+ #* *
+ #* Copyright (c) 1991 by *
+ #* DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
+ #* All rights reserved. *
+ #* *
+ #* This software is furnished under a license and may be used and copied *
+ #* only in accordance with the terms of such license and with the *
+ #* inclusion of the above copyright notice. This software or any other *
+ #* copies thereof may not be provided or otherwise made available to any *
+ #* other person. No title to and ownership of the software is hereby *
+ #* transferred. *
+ #* *
+ #* The information in this software is subject to change without notice *
+ #* and should not be construed as a commitment by Digital Equipment *
+ #* Corporation. *
+ #* *
+ #* Digital assumes no responsibility for the use or reliability of its *
+ #* software on equipment which is not supplied by Digital. *
+ #* *
+ #* *
+ #****************************************************************************
+ #
+ #++
+ # Facility:
+ # DEC C Run Time Library on the Alpha/WNT Platform
+ #
+ # Abstract:
+ #
+ # Implements the C RTL function strcmp() for the compiler intrinsic.
+ #
+ # Author:
+ # Bill Noyce 9-Aug-1991
+ #
+ # Modified by:
+ #
+ # 001 Kevin Routley 10-Sep-1991
+ # Modified to C RTL Coding standards.
+ #
+ # 002 Chris Bord 30 September 1991
+ # Add decc$ prefixes.
+ #
+ # 003 Chris Bord 24 January 1992
+ # Add second parameter to .procedure_descriptor directive
+ #
+ # 004 John Parks 22 January 1993
+ # Ported to Alpha/NT.
+ #--
+
+//
+// Although the spec says the return value may be <0/0/>0, we now return
+// -1/0/+1 to reduce NT combatibility problems.
+//
+
+ .globl _Otsstrcmp
+ .ent _Otsstrcmp
+
+ # r16 = A
+ # r17 = B
+ # returns r0<0 if A<B, R0=0 if A=B, r0>0 if A>B (unsigned chars)
+ # destroys r16-r21, r27-r28
+ #
+
+_Otsstrcmp:
+ .set noat
+ .set noreorder
+
+ .frame $30, 0, $26
+
+ ldq_u $27, ($16) # Get first A QW
+ and $16, 7, $21 # Alignment of A
+
+ ldq_u $18, ($17) # Get first B QW
+ and $17, 7, $20 # Alignment of B
+
+ subq $20, $21, $0 # B_alignment geq A_alignment?
+
+ cmpbge $31, $27, $19 # Any nulls in A?
+
+ insql $27, $0, $28 # Position A like B if B_align geq
+ bgt $0, more_a # Skip if enough A bytes available
+
+ srl $19, $21, $19 # Discard nulls preceding start of A
+ bne $0, more_b # Go handle opposite mismatch
+
+match: xor $27, $18, $28 # Do A and B differ?
+
+ mskqh $28, $21, $28 # Ignore differences before start
+
+ sll $19, $21, $0 # Line up nulls with differences
+ bne $19, null # Skip out if nulls seen
+
+loop_s: bne $28, diff # Skip out if difference seen
+ ldq_u $27, 8($16) # Get next A QW
+
+ ldq_u $18, 8($17) # Get next B QW
+ addq $16, 8, $16 # Bump A pointer
+
+ addq $17, 8, $17 # Bump B pointer
+
+ cmpbge $31, $27, $0 # Any nulls in A?
+
+ xor $27, $18, $28 # Do A and B differ?
+ beq $0, loop_s # Repeat if no nulls
+
+ # Enter here if null seen.
+ # r0 = mask of nulls
+ # r27= A
+ # r18 = B
+ # r28= xor
+ #
+null: subq $0, 1, $19 # Flip bits up thru first null
+
+ cmpbge $31, $28, $28 # Mask of 1's where A=B
+
+ xor $0, $19, $0 # Mask of 1's thru first null
+
+ andnot $0, $28, $0 # Differences thru first null
+
+ cmpbge $27, $18, $27 # Mask of 1's where A >= B
+ beq $0, done # Exit with R0=0 if no differences
+
+ subq $31, $0, $19 # R19<0, first diff=1, others=0
+
+ and $27, $0, $28 # Mask of A>B thru first null
+
+ and $28, $19, $0 # Keep only first difference
+
+ cmoveq $0, $19, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+done: ret $31, ($26) # All done
+
+ # Enter here if difference seen, but no nulls.
+ # r27= A
+ # r18 = B
+ # R28= xor
+ #
+diff: cmpbge $31, $28, $21 # Where is A = B?
+
+ cmpbge $27, $18, $0 # Where is A >= B?
+
+ subq $21, 255, $19 # R19<0, first diff=1, others=0
+
+ andnot $0, $21, $28 # Mask of A > B
+
+ and $28, $19, $0 # Keep only first difference
+
+ cmoveq $0, $19, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+ ret $31, ($26)
+
+ #.align quad
+
+ # Enter here if A and B alignments differ, and B's is greater (so there are
+ # more A bytes in its first QW than B bytes in its first QW).
+
+more_a: srl $19, $21, $19 # Discard nulls preceding start of A
+
+ xor $28, $18, $21 # Do A and B differ?
+
+ mskqh $21, $20, $21 # Discard diffs preceding start of B
+ bne $19, null_a # Skip if A has nulls
+
+ mov $18, $19 # Put B where common code expects
+
+ bne $21, diff_d # Handle diffs in B
+
+ ldq_u $18, 8($17) # No nulls in A or B, get next QW of B
+ addq $17, 8, $17 # Bump B pointer
+
+ insqh $27, $0, $28 # Position high part of A like B
+
+ #stall
+
+ mskql $18, $0, $19 # Keep low part of B
+
+ # Loop comparing A and B when alignment differs.
+ # Register use:
+ # r16 --> A
+ # r17 --> B
+ # r27 = QW of A
+ # r28 = current piece of A
+ # r18 = QW of B
+ # r19 = current piece of B
+ # r0 = alignment difference (B-A)
+ # r21 = xor of pieces
+ # r20 = mask of null locations
+ #
+ # If a string contains a null, we are careful not to read the following
+ # quadword in that string. But we are willing to read the quadword that
+ # follows the first difference, because this read-ahead improves performance.
+ #
+loop_d: xor $28, $19, $21 # Do A and B pieces differ?
+ ldq_u $27, 8($16) # Get next QW of A
+
+ cmpbge $31, $18, $20 # Any nulls in B?
+ bne $21, diff_d # Skip if difference seen
+
+ent_d: mskqh $18, $0, $19 # Trim B for next compare
+
+ insql $27, $0, $28 # Position A like B
+
+ addq $16, 8, $16 # Bump A pointer
+ bne $20, null_d # Skip if null seen in B
+
+ xor $28, $19, $21 # Do A and B pieces differ?
+ ldq_u $18, 8($17) # Get next QW of B
+
+ cmpbge $31, $27, $20 # Any nulls in A?
+ bne $21, diff_d # Skip if difference seen
+
+ insqh $27, $0, $28 # Position A for next compare
+
+ mskql $18, $0, $19 # Trim B like A
+
+ addq $17, 8, $17 # Bump B pointer
+ beq $20, loop_d # Repeat if no nulls in A
+
+ # We saw a null in A. Since we've already compared the lower part with B,
+ # and B had no nulls, the null is in the upper part of A. We've moved that
+ # part of A to the lower part of r28. Re-compare so the mask of nulls will
+ # be positioned properly for the following code.
+ #
+ cmpbge $31, $28, $20 # Find nulls in repositioned A
+
+ # Null seen and alignments differ.
+ # r28 = positioned A
+ # r19 = positioned B
+ # r20 = mask of nulls
+ # r21 = xor (at entry null_e)
+ #
+ #.odd
+null_d: xor $28, $19, $21 # Where do A and B differ?
+
+null_e: subq $20, 1, $27 # Flip bits up thru first null
+
+ cmpbge $31, $21, $18 # Mask of 1's where A=B
+
+ xor $20, $27, $0 # Mask of 1's thru first null
+
+ andnot $0, $18, $0 # Differences thru first null
+
+ cmpbge $28, $19, $27 # Mask of 1's where A >= B
+ beq $0, done_d # Exit with R0=0 if no differences
+
+ subq $31, $0, $19 # R19<0, first diff=1, others=0
+
+ and $27, $0, $0 # Mask of A>B thru first null
+
+ and $0, $19, $0 # Keep only first difference
+
+ cmoveq $0, $19, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+done_d: ret $31, ($26) # All done
+
+
+ # Null seen in first QW of A, when B alignment greater.
+ # r19 = nulls in A, shifted
+ # r27 = A
+ # r28 = A positioned like B
+ # r18 = B
+ # r21 = xor, masked
+ #
+ #.odd
+null_a: sll $19, $20, $20 # Position nulls like B
+
+ mov $18, $19 # Move B for common code
+ bne $21, null_e # Comparison done if difference seen
+
+ and $20, 255, $18 # Any nulls in first part of A?
+
+ bne $18, null_e # Comparison done if so
+
+ ldq_u $19, 8($17) # Get another B QW
+ insqh $27, $0, $28 # Position A to match
+
+ srl $20, 8, $20 # Shift nulls again to match
+ br $31, null_d # Now we must be at end
+
+
+ # Enter here if A and B alignments differ, and B's is less (so there are more
+ # B bytes in its first QW than A bytes in its first QW).
+
+ #.align quad
+more_b: cmpbge $31, $18, $28 # We'll want to know about nulls in B
+ bne $19, null_b # Skip if null seen in A
+
+ extqh $18, $0, $19 # Position B like A
+
+ srl $28, $20, $28 # Discard nulls preceding start of B
+
+ xor $27, $19, $27 # Do A and B differ?
+
+ mskqh $27, $21, $21 # Discard diffs preceding start of A
+
+ sll $28, $20, $20 # Position null mask for common code
+ ldq_u $27, 8($16) # Get next QW of A
+
+ xor $19, $21, $28 # Recover A for compare
+ beq $21, ent_d # Enter loop if A=B so far
+
+
+ # Enter here if difference seen, but no nulls.
+ # r28 = A piece
+ # r19 = B piece
+ # r21 = xor
+ #
+diff_d: cmpbge $31, $21, $21 # Where is A = B?
+
+ cmpbge $28, $19, $0 # Where is A >= B?
+
+ subq $21, 255, $27 # R27<0, first diff=1, others=0
+
+ andnot $0, $21, $0 # Mask of A > B
+
+ and $0, $27, $0 # Keep only first difference
+
+ cmoveq $0, $27, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+ ret $31, ($26)
+
+ # Null seen in first QW of A, when B alignment less.
+ # r19 = nulls in A, shifted
+ # r27 = A
+ # r18 = original B
+ #
+ nop #.align 8
+null_b: sll $19, $21, $20 # Position null mask like A
+
+ extqh $18, $0, $19 # Position B like A
+
+ mov $27, $28 # Put A where common code expects
+
+ xor $27, $19, $27 # Find differences
+
+ mskqh $27, $21, $21 # Discard diffs preceding A
+ br $31, null_e # Comparison is done
+
+ .set at
+ .set reorder
+ .end _Otsstrcmp
diff --git a/private/crt32/misc/alpha/strcpy_.s b/private/crt32/misc/alpha/strcpy_.s
new file mode 100644
index 000000000..de2057715
--- /dev/null
+++ b/private/crt32/misc/alpha/strcpy_.s
@@ -0,0 +1,257 @@
+ #****************************************************************************
+ #* *
+ #* Copyright (c) 1991 by *
+ #* DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
+ #* All rights reserved. *
+ #* *
+ #* This software is furnished under a license and may be used and copied *
+ #* only in accordance with the terms of such license and with the *
+ #* inclusion of the above copyright notice. This software or any other *
+ #* copies thereof may not be provided or otherwise made available to any *
+ #* other person. No title to and ownership of the software is hereby *
+ #* transferred. *
+ #* *
+ #* The information in this software is subject to change without notice *
+ #* and should not be construed as a commitment by Digital Equipment *
+ #* Corporation. *
+ #* *
+ #* Digital assumes no responsibility for the use or reliability of its *
+ #* software on equipment which is not supplied by Digital. *
+ #* *
+ #* *
+ #****************************************************************************
+ #
+ #++
+ # Facility:
+ # DEC C Run Time Library on the Alpha/WNT Platform
+ #
+ # Abstract:
+ #
+ # Implements the C RTL function strcpy() for the compiler intrinsic.
+ #
+ # Author:
+ # Bill Noyce 9-Aug-1991
+ #
+ # Modified by:
+ #
+ # 001 Kevin Routley 10-Sep-1991
+ # Modified to C RTL Coding standards.
+ #
+ # 002 Chris Bord 30 September 1991
+ # Add decc$ prefixes.
+ #
+ # 003 Chris Bord 24 January 1992
+ # Add second parameter to .procedure_descriptor directive
+ #
+ # 004 John Parks 22 January 1993
+ # Ported to Alpha/NT.
+ #--
+
+ .globl _Otsstrcpy
+ .ent _Otsstrcpy
+
+ # r16 = dst
+ # r17 = src
+ # returns r0 = src
+ # destroys r16-r21, r27-r28
+
+_Otsstrcpy:
+ .set noat
+ .set noreorder
+
+ ldq_u $27, ($17) # Get first src QW
+ and $16, 7, $28 #/ Is dst aligned?
+ lda $18, -1($31) # Get a mask of all 1's
+ bne $28, dst_unaligned #/ Go handle unaligned dst
+ and $17, 7, $19 # Is src aligned too?
+ nop
+ mov $16, $0 # Set up function result
+ bne $19, src_unaligned #/ Go handle aligned dst, unaligned src
+
+a_loop:
+ cmpbge $31, $27, $18 # Any nulls in src QW?
+ bne $18, a_exit_1 # Finish up if so
+ ldq $21, 8($17) # Load next QW if not
+match: # Enter if src matches unaligned dst
+ addq $17, 16, $17 #/ Update src pointer for unrolled loop
+ stq_u $27, ($16) # Store a whole QW
+ addq $16, 16, $16 #/ Update dst pointer for unrolled loop
+ cmpbge $31, $21, $18 # Any nulls in src QW?
+ bne $18, a_exit_2 # Finish up if so
+ ldq $27, ($17) # Load next QW if not
+ stq_u $21, -8($16) # Store a whole QW
+ br $31, a_loop # Repeat during load latency
+
+a_exit_1:
+ ldq_u $21, ($16) # Get dst QW to update
+ subq $18, 1, $17 #/ Use location of null byte...
+ xor $18, $17, $18 # ... to compute mask of what to keep
+ zapnot $27, $18, $27 # Keep src up to & including null
+ zap $21, $18, $21 # Make room for new data
+ nop
+ or $21, $27, $21 # Combine src & dst...
+ stq_u $21, ($16) #/ ... and store
+ ret $31, ($26)
+
+ nop
+a_exit_2:
+ ldq_u $27, -8($16) # Get dst QW to update
+ subq $18, 1, $17 #/ Use location of null byte...
+ xor $18, $17, $18 # ... to compute mask of what to keep
+ zapnot $21, $18, $21 # Keep src up to & including null
+ zap $27, $18, $27 # Make room for new data
+ nop
+ or $27, $21, $27 # Combine src & dst...
+ stq_u $27, -8($16) #/ ... and store
+ ret $31, ($26)
+
+src_unaligned: # dst_unaligned code would work; is this faster?
+ mskqh $18, $17, $18 # Zeros where src to be ignored
+ ornot $27, $18, $19 # Make ignored bytes nonzero
+ cmpbge $31, $19, $21 # Any null bytes in src data?
+ extql $27, $17, $27 # Move src to position of dst
+ bne $21, short_ld #/ Finish up if nulls seen
+ ldq_u $19, 8($17) # Next src QW needed to fill dst
+ br $31, u_entry_2 # Enter loop for mismatched alignment
+
+ # Here's the hard part. Enter with
+ # r16 = dst address
+ # r17 = src address
+ # r18 = -1
+ # r27 = first src QW
+ # r28 = dst alignment (>0)
+ # Check whether the first src QW has any nulls, and load the next one.
+ # Combine these if needed to fill the first dst QW, and enter a loop
+ # that fetches src QWs and checks them, while storing dst QWs.
+
+dst_unaligned:
+ ldq_u $20, ($16) # Load dst to be updated
+ mskqh $18, $17, $18 #/ Zeros where src to be ignored
+ mov $16, $0 # Set up function result
+ ornot $27, $18, $19 # Make ignored bytes of src nonzero
+ cmpbge $31, $19, $21 # Any null bytes in src data?
+ extql $27, $17, $27 # Get only interesting src data
+ bne $21, short # Finish up if nulls seen
+ mskql $20, $16, $20 #/ Make room in dst
+ ldq_u $21, 8($17) # Load next src QW if no nulls
+ mskql $18, $16, $18 #/ Need two src QWs for first dst QW?
+ insql $27, $16, $27 # Move src data to position of dst
+ subq $17, $28, $17 # Adjust src ptr for partial move
+ and $17, 7, $28 # Is src now aligned?
+ bne $18, u_loop #/ Enter loop if one src QW fills dst
+ or $27, $20, $27 # Combine first src QW with dst
+ extqh $21, $17, $20 # Position 2nd src QW in 1st dst QW
+ cmpbge $31, $21, $18 # Any nulls in next src QW?
+ beq $28, match #/ If src aligned, use quick loop
+ mov $21, $19 # Put src QW where loop expects
+ bne $18, short_a #/ Finish up if nulls seen
+
+ # r16 = address of next dst to store
+ # r17 = address-16 of next src to load
+ # r18
+ # r19 = last loaded src QW
+ # r20 = one piece of dst QW
+ # r21
+ # r27 = other piece of dst QW
+ # r28
+
+u_loop:
+ ldq_u $28, 16($17) # Load another src QW
+ addq $17, 16, $17 #/ Update src pointer for unrolled loop
+ or $27, $20, $27 # Combine pieces
+ extql $19, $17, $20 # Get second part of prior src QW
+ stq_u $27, ($16) # Store a dst QW
+ cmpbge $31, $28, $19 #/ Any nulls in this src QW?
+ extqh $28, $17, $27 # Get first part of this src QW
+ bne $19, u_exit_2 #/ Finish up if nulls seen
+ ldq_u $19, 8($17) # Load another src QW
+ addq $16, 16, $16 #/ Update dst pointer for unrolled loop
+ or $27, $20, $20 # Combine pieces
+ extql $28, $17, $27 # Get second piece of prior src QW
+ stq_u $20, -8($16) # Store a dst QW
+u_entry_2:
+ cmpbge $31, $19, $28 #/ Any nulls in this src QW?
+ extqh $19, $17, $20 # Get first part of this src QW
+ beq $28, u_loop #/ Repeat if no nulls seen
+
+ subq $16, 8, $16 # Undo part of pointer update
+ mov $19, $28 # Move src QW to expected place
+u_exit_2:
+ or $27, $20, $27 # Combine pieces
+ ldq_u $18, 8($16) #/ Load dst to update
+ cmpbge $31, $27, $21 # Is null in first dst QW?
+ bne $21, u_exit_3 # Skip if so
+ stq_u $27, 8($16) # Store a whole dst QW
+ extql $28, $17, $27 #/ Get second part of src QW
+ ldq_u $18, 16($16) # We'll update next dst QW
+ cmpbge $31, $27, $21 # Find location of null there
+ addq $16, 8, $16 # Update dst pointer
+u_exit_3:
+ subq $21, 1, $28 # Using position of null byte...
+ xor $21, $28, $21 # ... make mask for desired src data
+ zapnot $27, $21, $27 # Trim src data after null
+ zap $18, $21, $18 # Make room for it in dst
+ nop
+ or $27, $18, $27 # Combine pieces
+ stq_u $27, 8($16) #/ Store dst QW
+ ret $31, ($26)
+short_ld:
+ ldq_u $20, ($16) # Load dst QW to update
+short:
+ cmpbge $31, $27, $17 #/ Get mask showing location of null
+ insql $27, $16, $18 # Move src data to position of dst
+ mskql $20, $16, $19 # Get dst bytes preceding string
+ sll $17, $28, $17 # Move mask in the same way
+ or $18, $19, $18 # Combine src & dst
+ and $17, 255, $28 # Null byte in first dst QW?
+ subq $17, 1, $19 # Using position of null byte...
+ xor $17, $19, $17 # ... make mask for desired src data
+ bne $28, short_2 #/ Skip if null in first dst QW
+ ldq_u $20, 8($16) # Load second dst QW
+ srl $17, 8, $17 #/ Move mask down for use
+ stq_u $18, ($16) # Store first dst QW
+ insqh $27, $16, $18 #/ Move src data to position of dst
+ addq $16, 8, $16 # Advance dst pointer
+short_2:
+ zap $20, $17, $20 # Preserve dst data following null
+ zapnot $18, $17, $18 # Trim src data after null
+ nop
+ or $18, $20, $18 # Combine pieces
+ stq_u $18, ($16) #/ Store dst QW
+ ret $31, ($26)
+
+ # r16 = dst address
+ # r17 = updated src address
+ # r18 = null position
+ # r19 = next src QW
+ # r20 = first part of r19, positioned for dst
+ # r21
+ # r27 = dst QW so far
+ # r28 = low bits of updated src address
+
+short_a:
+ sll $18, 8, $18 # Shift location of null byte...
+ ldq_u $21, ($16) #/ Reload first dst QW
+ or $27, $20, $27 # Combine pieces
+ srl $18, $28, $18 # ... to position in dst QW's
+ nop
+ and $18, 255, $20 # Is null in first dst QW?
+ subq $18, 1, $28 # Using position of null byte...
+ xor $18, $28, $18 # ... make mask for desired src data
+ bne $20, short_a1 #/ Skip if null in first QW
+ stq_u $27, ($16) # Store a whole dst QW
+ extql $19, $17, $27 #/ Prepare next piece of src
+ ldq_u $21, 8($16) # Load second dst QW for update
+ srl $18, 8, $18 #/ Look at next 8 bits of mask
+ addq $16, 8, $16 # Update dst pointer
+short_a1:
+ zapnot $27, $18, $27 # Keep src data
+ zap $21, $18, $21 # Keep end of dst QW
+ nop
+ or $27, $21, $27 # Combine pieces
+ stq_u $27, ($16) # Store last dst QW
+ ret $31, ($26)
+
+ .set at
+ .set reorder
+ .end _Otsstrcpy
diff --git a/private/crt32/misc/alpha/strlen_.s b/private/crt32/misc/alpha/strlen_.s
new file mode 100644
index 000000000..2a7979387
--- /dev/null
+++ b/private/crt32/misc/alpha/strlen_.s
@@ -0,0 +1,95 @@
+ #****************************************************************************
+ #* *
+ #* Copyright (c) 1991 by *
+ #* DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
+ #* All rights reserved. *
+ #* *
+ #* This software is furnished under a license and may be used and copied *
+ #* only in accordance with the terms of such license and with the *
+ #* inclusion of the above copyright notice. This software or any other *
+ #* copies thereof may not be provided or otherwise made available to any *
+ #* other person. No title to and ownership of the software is hereby *
+ #* transferred. *
+ #* *
+ #* The information in this software is subject to change without notice *
+ #* and should not be construed as a commitment by Digital Equipment *
+ #* Corporation. *
+ #* *
+ #* Digital assumes no responsibility for the use or reliability of its *
+ #* software on equipment which is not supplied by Digital. *
+ #* *
+ #* *
+ #****************************************************************************
+ #
+ #++
+ # Facility:
+ # DEC C Run Time Library on the Alpha/WNT Platform
+ #
+ # Abstract:
+ #
+ # Implements the C RTL function strlen() for the compiler intrinsic.
+ #
+ # Author:
+ # Bill Noyce 9-Aug-1991
+ #
+ # Modified by:
+ #
+ # 001 Kevin Routley 10-Sep-1991
+ # Modified to C RTL Coding standards.
+ #
+ # 002 Chris Bord 30 September 1991
+ #
+ # 003 Chris Bord 24 January 1992
+ # Add second parameter to .procedure_descriptor directive
+ #
+ # 004 John Parks 22 January 1993
+ # Ported to Alpha/NT.
+ #--
+
+ .globl _Otsstrlen
+ .ent _Otsstrlen
+
+ # r16 = src pointer
+ # Returns r0 = length
+ # Destroys r16,r27-r28
+
+_Otsstrlen:
+ .set noat
+ .set noreorder
+
+ ldq_u $27, ($16) # Get QW containing start of string
+ lda $28, -1($31) # Mask of all ones
+ mskql $28, $16, $28 # Nonzeros in low bytes to be ignored
+ and $16, 7, $0 # Alignment = bytes not to be counted
+ or $27, $28, $27 # Fill ignored bytes with nonzeros
+ cmpbge $31, $27, $27 # Any null bytes in this QW?
+ subq $31, $0, $0 # Initialize count to -alignment
+ bne $27, bottom # Skip if null byte seen
+
+loop: ldq_u $27, 8($16) # Load next QW of string
+ addq $16, 8, $16 # Advance pointer
+ addq $0, 8, $0 # Increment length
+ cmpbge $31, $27, $27 # Any nulls in this QW?
+ beq $27, loop # Repeat if not
+
+bottom: and $27, 0xF, $28 # Null in low longword?
+ subq $27, 1, $16 # Complement the lowest 1-bit in mask
+ blbs $27, done # Exit if null appears in first byte
+ andnot $27, $16, $27 # Make single-bit mask of null location
+ beq $28, geq_4 # Skip if null is in high longword
+ srl $27, 2, $27 # Map 2/4/8 --> 0/1/2
+ addq $0, 1, $0 # Bump length by one...
+ addq $0, $27, $0 # ... and then by null location
+
+done: ret $31, ($26)
+
+geq_4: srl $27, 5, $28 # Map 10/20/40/80 --> 0/1/2/4
+ srl $27, 7, $27 # Map 10/20/40/80 --> 0/0/0/1
+ addq $0, 4, $0 # Bump length by four
+ subq $28, $27, $28 # Compute location within high LW...
+ addq $0, $28, $0 # ... and add to length
+ ret $31, ($26)
+
+ .set at
+ .set reorder
+ .end _Otsstrlen
diff --git a/private/crt32/misc/alpha/szero.s b/private/crt32/misc/alpha/szero.s
new file mode 100644
index 000000000..c97c31df5
--- /dev/null
+++ b/private/crt32/misc/alpha/szero.s
@@ -0,0 +1,137 @@
+ #++
+ # Copyright 1991, 1994, Digital Equipment Corporation
+ #
+ # ots_zero(char *dstptr, long dstlen)
+ #
+ # Zero dstlen bytes of memory at *dstptr
+ #
+ # Special conventions: No stack space, r16-r17 and r27-r28 ONLY,
+ # no linkage pointer required.
+ # (Warning: The auto-loader potentially takes some regs across
+ # the call if this is being used in a shared lib. environment.)
+ #
+ # This is a GEM support routine for zeroing a region of memory. It is
+ # basically idential to BSD's bzero, though it has limited register
+ # convensions to allow it to work better with compiled code. (Note that
+ # this is just a stripped down version of ots_fill.)
+ #
+ # This is optimized for extremely high performance both for small and
+ # large blocks. In order to reduce overhead for small cases, they are
+ # retired as quickly as possible, more case analysis is reserved
+ # for cases which will do more.
+ #
+ # This version of OTS_ZERO provides longword granularity for Alpha.
+ #
+ # 012 30 Aug 1994 WBN Longword granularity version based on
+ # OTS_ZERO_ALPHA.M64 edit 011.
+ #--
+
+#include "ots_defs.hs"
+
+ # r16 = dst
+ # r17 = len
+ # destroys r16-r17, r27-r28
+
+ .globl _OtsZero
+ .ent _OtsZero
+_OtsZero:
+ .set noat
+ .set noreorder
+ .frame sp,0,r26
+ .prologue 0
+ beq r17, done # No memory refs if len=0
+ subq r17, 4, r28 # Length-4
+ and r16, 3, r27 # Dst alignment (0-3)
+ andnot r16, 3, r16 # LW aligned dst pointer
+ addq r27, r28, r17 # Alignment + length - 4
+ bge r28, geq4 # Lengths >= 4 may not need load
+ ldl r28, (r16) # Load first LW of dst
+ bgt r17, double # Skip if it crosses to next LW
+ addq r17, 4, r17 # Find endpoint within LW
+ mskql r28, r27, r27 # Clear from startpoint thru 7
+ mskqh r28, r17, r28 # Clear from 0 to endpoint
+ or r28, r27, r27 # Combine dest parts
+ stl r27, (r16)
+ ret r31, (r26)
+
+double: mskql r28, r27, r28 # Clear from startpoint in first LW
+ ldl r27, 4(r16) # Load second LW of dst
+ stl r28, (r16)
+ mskqh r27, r17, r27 # Clear up to endpoint in second LW
+ stl r27, 4(r16)
+ ret r31, (r26)
+
+ # Come here if length to be zeroed is >= 4.
+ # r16-> dst aligned to LW
+ # r17 = alignment + length - 4
+ # r27 = dst alignment within LW
+ # r28 = length-4
+
+ #.align quad
+
+geq4: and r16, 4, r28 # Which LW in QW to store first?
+ beq r17, simple # Go handle single aligned LW
+ bne r28, longs # Go use QW stores
+quad: subq r17, 4, r17 # Does dest end in first QW?
+ blt r17, shortq # Ends within first QW
+ beq r27, wh_qw # Store a whole QW
+ ldq r28, (r16) # Load first QW of dest
+ mskql r28, r27, r27 # Clear from startpoint
+wh_qw: stq r27, (r16) # Store first QW of dest
+ br r31, join # Go clear rest of string
+
+simple: stl r31, (r16) # Single aligned LW
+ ret r31, (r26)
+
+shortq: ldq r28, (r16) # Load QW of dest
+ mskql r28, r27, r27 # Clear from startpoint thru 7
+ mskqh r28, r17, r28 # Clear from 0 up to endpoint
+ or r28, r27, r27 # Merge
+ stq r27, (r16) # Store
+ ret r31, (r26)
+
+longs: beq r27, wh_lw # Store a whole LW
+ ldl r28, (r16) # Load first LW of dest
+ mskql r28, r27, r27 # Clear from startpoint
+wh_lw: stl r27, (r16) # Store first LW of dest
+join: subq r17, 32, r17 # At least 4 more quadwords?
+ and r17, 24, r27 # How many after multiple of 4?
+ bge r17, unroll # Taken branch for long strings
+short: and r17, 7, r17 # How many odd bytes?
+ beq r27, last # Skip if no more whole QWs
+ stq_u r31, 8(r16) # Clear one...
+ subq r27, 16, r27 # Map 8/16/24 to -8/0/8
+ addq r16, 8, r16 # Update dest pointer
+ blt r27, last # Skip if no more whole QWs
+ #stall
+ stq_u r31, 8(r16) # Clear two...
+ addq r16, 8, r16 # Update dest pointer
+ nop
+ beq r27, last # Skip if no more whole QWs
+ stq_u r31, 8(r16) # Clear three...
+ addq r16, 8, r16 # Update dest pointer
+last: beq r17, done # Finished if no odd bytes
+ ldq_u r27, 8(r16) # Load last QW of dst
+ subq r17, 4, r28 # More than a LW left?
+ andnot r16, 7, r16 # Clean pointer for STL
+ mskqh r27, r17, r27 # Clear up to endpoint
+ bgt r28, lastq # Go store a QW
+ stl r27, 8(r16) # LW store for last piece
+done: ret r31, (r26)
+
+lastq: stq r27, 8(r16) # QW store for last piece
+ ret r31, (r26)
+
+unroll: stq_u r31, 8(r16) # Store 4 QWs per iteration
+ stq_u r31, 16(r16)
+ stq_u r31, 24(r16)
+ subq r17, 32, r17 # Decrement remaining count
+ stq_u r31, 32(r16)
+ addq r16, 32, r16 # Update dest pointer
+ bge r17, unroll # Repeat until done
+ br r31, short # Then handle leftovers
+
+
+ .set at
+ .set reorder
+ .end _OtsZero
diff --git a/private/crt32/misc/assert.c b/private/crt32/misc/assert.c
new file mode 100644
index 000000000..7f7dc60a0
--- /dev/null
+++ b/private/crt32/misc/assert.c
@@ -0,0 +1,66 @@
+/***
+*assert.c - Display a message and abort
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 05-19-88 JCR Module created.
+* 08-10-88 PHG Corrected copyright date
+* 03-14-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>. Also, fixed the copyright.
+* 04-05-90 GJF Added #include <assert.h>
+* 10-04-90 GJF New-style function declarator.
+* 06-19-91 GJF Conditionally use setvbuf() on stderr to prevent
+* the implicit call to malloc() if stderr is being used
+* for the first time (assert() should work even if the
+* heap is trashed).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <file2.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#undef NDEBUG
+#include <assert.h>
+
+static char _assertstring[] = "Assertion failed: %s, file %s, line %d\n";
+
+/***
+*_assert() - Display a message and abort
+*
+*Purpose:
+* The assert macro calls this routine if the assert expression is
+* true. By placing the assert code in a subroutine instead of within
+* the body of the macro, programs that call assert multiple times will
+* save space.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _assert (
+ void *expr,
+ void *filename,
+ unsigned lineno
+ )
+{
+ if ( !anybuf(stderr) )
+ /*
+ * stderr is unused, hence unbuffered, as yet. set it to
+ * single character buffering (to avoid a malloc() of a
+ * stream buffer).
+ */
+ (void) setvbuf(stderr, NULL, _IONBF, 0);
+
+ fprintf(stderr, _assertstring, expr, filename, lineno);
+ fflush(stderr);
+ abort();
+}
diff --git a/private/crt32/misc/bsearch.c b/private/crt32/misc/bsearch.c
new file mode 100644
index 000000000..5769de6b5
--- /dev/null
+++ b/private/crt32/misc/bsearch.c
@@ -0,0 +1,99 @@
+/***
+*bsearch.c - do a binary search
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines bsearch() - do a binary search an an array
+*
+*Revision History:
+* 07-05-84 RN initial version
+* 06-19-85 TC put in ifdefs to handle case of multiplication
+* in large/huge model.
+* 04-13-87 JCR added const to declaration
+* 08-04-87 JCR Added "long" cast to mid= assignment for large/huge
+* model.
+* 11-10-87 SKS Removed IBMC20 switch
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-21-88 JCR Backed out _LOAD_DS...
+* 02-22-88 JCR Added cast to get rid of cl const warning
+* 10-20-89 JCR Added _cdecl to prototype, changed 'char' to 'void'
+* 03-14-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and fixed
+* the copyright. Also, cleaned up the formatting a bit.
+* 04-05-90 GJF Added #include <stdlib.h> and #include <search.h>.
+* Fixed some resulting compiler warnings (at -W3).
+* Also, removed #include <sizeptr.h>.
+* 07-25-90 SBM Removed redundant include (stdio.h), made args match
+* prototype
+* 10-04-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <search.h>
+
+/***
+*char *bsearch() - do a binary search on an array
+*
+*Purpose:
+* Does a binary search of a sorted array for a key.
+*
+*Entry:
+* const char *key - key to search for
+* const char *base - base of sorted array to search
+* unsigned int num - number of elements in array
+* unsigned int width - number of bytes per element
+* int (*compare)() - pointer to function that compares two array
+* elements, returning neg when #1 < #2, pos when #1 > #2, and
+* 0 when they are equal. Function is passed pointers to two
+* array elements.
+*
+*Exit:
+* if key is found:
+* returns pointer to occurrence of key in array
+* if key is not found:
+* returns NULL
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 bsearch (
+ REG4 const void *key,
+ const void *base,
+ size_t num,
+ size_t width,
+ int (_CALLTYPE1 *compare)(const void *, const void *)
+ )
+{
+ REG1 char *lo = (char *)base;
+ REG2 char *hi = (char *)base + (num - 1) * width;
+ REG3 char *mid;
+ unsigned int half;
+ int result;
+
+ while (lo <= hi)
+ if (half = num / 2)
+ {
+ mid = lo + (num & 1 ? half : (half - 1)) * width;
+ if (!(result = (*compare)(key,mid)))
+ return(mid);
+ else if (result < 0)
+ {
+ hi = mid - width;
+ num = num & 1 ? half : half-1;
+ }
+ else {
+ lo = mid + width;
+ num = half;
+ }
+ }
+ else if (num)
+ return((*compare)(key,lo) ? NULL : lo);
+ else
+ break;
+
+ return(NULL);
+}
diff --git a/private/crt32/misc/cmiscdat.c b/private/crt32/misc/cmiscdat.c
new file mode 100644
index 000000000..d1458d8f9
--- /dev/null
+++ b/private/crt32/misc/cmiscdat.c
@@ -0,0 +1,68 @@
+/***
+*cmiscdat.c - miscellaneous C run-time data
+*
+* Copyright (c) 1989-1990, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Includes floating point conversion table (for C float output),
+* a data structure used by signal/exec to tell if a SIGINT handler
+* has been installed, and the public variables _asizeC and _asizeD
+* for conveying memory-model information to the memory-model-independent
+* GRAPHICS.LIB.
+*
+* When floating point i/o conversions are done, but no floating-point
+* variables or expressions are used in the C program, we use the
+* _cfltcvt_tab[] to map these cases to the _fptrap entry point,
+* which prints "floating point not loaded" and dies.
+*
+* This table is initialized to six copies of _fptrap by default.
+* If floating-point is linked in (_fltused), these table entries
+* are reset (see input.c, output.c, fltused.asm, and fltuseda.asm).
+*
+*Revision History:
+* 06-29-89 PHG module created, based on asm version
+* 04-06-90 GJF Added #include <cruntime.h>. Also, fixed the copyright
+* and cleaned up the formatting a bit.
+* 07-31-90 SBM Updated comments slightly
+* 08-29-90 SBM Added #include <internal.h> and <fltintrn.h>,
+* removed _fptrap() prototype
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <fltintrn.h>
+
+/*
+ ... table of (model-dependent) code pointers ...
+
+ Six entries, all point to _fptrap by default,
+ but are changed to point to the appropriate
+ routine if the _fltused initializer (_cfltcvt_init)
+ is linked in.
+
+ this table is used or modified in the following
+ source files:
+
+ \clib\stdio\input.c
+ \clib\stdio\output.c
+ \math\c\fltused.asm
+ \math\c\fltuseda.asm
+
+ if the _fltused modules are linked in, then the
+ _cfltcvt_init initializer sets the 6 entries of
+ _cfltcvt_tab to:
+
+ _cfltcvt
+ _cropzeros
+ _fassign
+ _forcdecpt
+ _positive
+ _cldcvt
+*/
+
+void (*_cfltcvt_tab[6])(void) = {
+ _fptrap, _fptrap, _fptrap, _fptrap, _fptrap, _fptrap
+};
+
+void (*_sigintoff)() = 0; /* SIGINT default signal routine */
diff --git a/private/crt32/misc/ctype.c b/private/crt32/misc/ctype.c
new file mode 100644
index 000000000..382779c6d
--- /dev/null
+++ b/private/crt32/misc/ctype.c
@@ -0,0 +1,161 @@
+/***
+*ctype.c - _ctype definition file
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* _ctype definition file of character classification data. This file
+* initializes the array used by the character classification macros
+* in ctype.h.
+*
+*Revision History:
+* 06-08-89 PHG Module created, based on asm version
+* 08-28-89 JCR Corrected _ctype declaration to match ctype.h
+* 04-06-90 GJF Added #include <cruntime.h>. Also, fixed the copyright.
+* 10-08-91 ETC _ctype table is unsigned short under _INTL.
+* 11-11-91 ETC Declare _pctype and _pwctype under _INTL.
+* 12-16-91 ETC Make ctype table width independent of _INTL, use
+* _NEWCTYPETABLE for short table, else char.
+* 04-06-92 KRS Remove _INTL switches.
+* 01-19-03 CFW Move to _NEWCTYPETABLE, remove switch.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+
+unsigned short *_pctype = _ctype+1; /* pointer to table for char's */
+unsigned short *_pwctype = _ctype+1; /* pointer to table for wchar_t's */
+
+unsigned short _VARTYPE1 _ctype[257] = {
+ 0, /* -1 EOF */
+ _CONTROL, /* 00 (NUL) */
+ _CONTROL, /* 01 (SOH) */
+ _CONTROL, /* 02 (STX) */
+ _CONTROL, /* 03 (ETX) */
+ _CONTROL, /* 04 (EOT) */
+ _CONTROL, /* 05 (ENQ) */
+ _CONTROL, /* 06 (ACK) */
+ _CONTROL, /* 07 (BEL) */
+ _CONTROL, /* 08 (BS) */
+ _SPACE+_CONTROL, /* 09 (HT) */
+ _SPACE+_CONTROL, /* 0A (LF) */
+ _SPACE+_CONTROL, /* 0B (VT) */
+ _SPACE+_CONTROL, /* 0C (FF) */
+ _SPACE+_CONTROL, /* 0D (CR) */
+ _CONTROL, /* 0E (SI) */
+ _CONTROL, /* 0F (SO) */
+ _CONTROL, /* 10 (DLE) */
+ _CONTROL, /* 11 (DC1) */
+ _CONTROL, /* 12 (DC2) */
+ _CONTROL, /* 13 (DC3) */
+ _CONTROL, /* 14 (DC4) */
+ _CONTROL, /* 15 (NAK) */
+ _CONTROL, /* 16 (SYN) */
+ _CONTROL, /* 17 (ETB) */
+ _CONTROL, /* 18 (CAN) */
+ _CONTROL, /* 19 (EM) */
+ _CONTROL, /* 1A (SUB) */
+ _CONTROL, /* 1B (ESC) */
+ _CONTROL, /* 1C (FS) */
+ _CONTROL, /* 1D (GS) */
+ _CONTROL, /* 1E (RS) */
+ _CONTROL, /* 1F (US) */
+ _SPACE+_BLANK, /* 20 SPACE */
+ _PUNCT, /* 21 ! */
+ _PUNCT, /* 22 " */
+ _PUNCT, /* 23 # */
+ _PUNCT, /* 24 $ */
+ _PUNCT, /* 25 % */
+ _PUNCT, /* 26 & */
+ _PUNCT, /* 27 ' */
+ _PUNCT, /* 28 ( */
+ _PUNCT, /* 29 ) */
+ _PUNCT, /* 2A * */
+ _PUNCT, /* 2B + */
+ _PUNCT, /* 2C , */
+ _PUNCT, /* 2D - */
+ _PUNCT, /* 2E . */
+ _PUNCT, /* 2F / */
+ _DIGIT+_HEX, /* 30 0 */
+ _DIGIT+_HEX, /* 31 1 */
+ _DIGIT+_HEX, /* 32 2 */
+ _DIGIT+_HEX, /* 33 3 */
+ _DIGIT+_HEX, /* 34 4 */
+ _DIGIT+_HEX, /* 35 5 */
+ _DIGIT+_HEX, /* 36 6 */
+ _DIGIT+_HEX, /* 37 7 */
+ _DIGIT+_HEX, /* 38 8 */
+ _DIGIT+_HEX, /* 39 9 */
+ _PUNCT, /* 3A : */
+ _PUNCT, /* 3B ; */
+ _PUNCT, /* 3C < */
+ _PUNCT, /* 3D = */
+ _PUNCT, /* 3E > */
+ _PUNCT, /* 3F ? */
+ _PUNCT, /* 40 @ */
+ _UPPER+_HEX, /* 41 A */
+ _UPPER+_HEX, /* 42 B */
+ _UPPER+_HEX, /* 43 C */
+ _UPPER+_HEX, /* 44 D */
+ _UPPER+_HEX, /* 45 E */
+ _UPPER+_HEX, /* 46 F */
+ _UPPER, /* 47 G */
+ _UPPER, /* 48 H */
+ _UPPER, /* 49 I */
+ _UPPER, /* 4A J */
+ _UPPER, /* 4B K */
+ _UPPER, /* 4C L */
+ _UPPER, /* 4D M */
+ _UPPER, /* 4E N */
+ _UPPER, /* 4F O */
+ _UPPER, /* 50 P */
+ _UPPER, /* 51 Q */
+ _UPPER, /* 52 R */
+ _UPPER, /* 53 S */
+ _UPPER, /* 54 T */
+ _UPPER, /* 55 U */
+ _UPPER, /* 56 V */
+ _UPPER, /* 57 W */
+ _UPPER, /* 58 X */
+ _UPPER, /* 59 Y */
+ _UPPER, /* 5A Z */
+ _PUNCT, /* 5B [ */
+ _PUNCT, /* 5C \ */
+ _PUNCT, /* 5D ] */
+ _PUNCT, /* 5E ^ */
+ _PUNCT, /* 5F _ */
+ _PUNCT, /* 60 ` */
+ _LOWER+_HEX, /* 61 a */
+ _LOWER+_HEX, /* 62 b */
+ _LOWER+_HEX, /* 63 c */
+ _LOWER+_HEX, /* 64 d */
+ _LOWER+_HEX, /* 65 e */
+ _LOWER+_HEX, /* 66 f */
+ _LOWER, /* 67 g */
+ _LOWER, /* 68 h */
+ _LOWER, /* 69 i */
+ _LOWER, /* 6A j */
+ _LOWER, /* 6B k */
+ _LOWER, /* 6C l */
+ _LOWER, /* 6D m */
+ _LOWER, /* 6E n */
+ _LOWER, /* 6F o */
+ _LOWER, /* 70 p */
+ _LOWER, /* 71 q */
+ _LOWER, /* 72 r */
+ _LOWER, /* 73 s */
+ _LOWER, /* 74 t */
+ _LOWER, /* 75 u */
+ _LOWER, /* 76 v */
+ _LOWER, /* 77 w */
+ _LOWER, /* 78 x */
+ _LOWER, /* 79 y */
+ _LOWER, /* 7A z */
+ _PUNCT, /* 7B { */
+ _PUNCT, /* 7C | */
+ _PUNCT, /* 7D } */
+ _PUNCT, /* 7E ~ */
+ _CONTROL, /* 7F (DEL) */
+ /* and the rest are 0... */
+};
diff --git a/private/crt32/misc/div.c b/private/crt32/misc/div.c
new file mode 100644
index 000000000..de8cfa3ec
--- /dev/null
+++ b/private/crt32/misc/div.c
@@ -0,0 +1,59 @@
+/***
+*div.c - contains the div routine
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Performs a signed divide and returns quotient
+* and remainder.
+*
+*Revision History:
+* 06-02-89 PHG module created
+* 03-14-90 GJF Made calling type _CALLTYPE1 and added #include
+* <cruntime.h>. Also, fixed the copyright.
+* 10-04-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+
+/***
+*div_t div(int numer, int denom) - do signed divide
+*
+*Purpose:
+* This routine does an divide and returns the results.
+* Since we don't know how the Intel 860 does division, we'd
+* better make sure that we have done it right.
+*
+*Entry:
+* int numer - Numerator passed in on stack
+* int denom - Denominator passed in on stack
+*
+*Exit:
+* returns quotient and remainder in structure
+*
+*Exceptions:
+* No validation is done on [denom]* thus, if [denom] is 0,
+* this routine will trap.
+*
+*******************************************************************************/
+
+div_t _CALLTYPE1 div (
+ int numer,
+ int denom
+ )
+{
+ div_t result;
+
+ result.quot = numer / denom;
+ result.rem = numer % denom;
+
+ if (numer < 0 && result.rem > 0) {
+ /* did division wrong; must fix up */
+ ++result.quot;
+ result.rem -= denom;
+ }
+
+ return result;
+}
diff --git a/private/crt32/misc/getenv.c b/private/crt32/misc/getenv.c
new file mode 100644
index 000000000..7d14d2a74
--- /dev/null
+++ b/private/crt32/misc/getenv.c
@@ -0,0 +1,167 @@
+/***
+*getenv.c - get the value of an environment variable
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines getenv() - searches the environment for a string variable
+* and returns the value of it.
+*
+*Revision History:
+* 11-22-83 RN initial version
+* 04-13-87 JCR added const to declaration
+* 11-09-87 SKS avoid indexing past end of strings (add strlen check)
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 06-01-88 PHG Merged normal/DLL versions
+* 03-14-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and fixed
+* the copyright. Also, cleaned up the formatting a bit.
+* 04-05-90 GJF Added #include <string.h>.
+* 07-25-90 SBM Removed redundant include (stdio.h)
+* 08-13-90 SBM Compiles cleanly with -W3 (made length unsigned int)
+* 10-04-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 02-06-91 SRW Added _WIN32_ conditional for GetEnvironmentVariable
+* 02-18-91 SRW Removed _WIN32_ conditional for GetEnvironmentVariable
+* 01-10-92 GJF Final unlock and return statements shouldn't be in
+* if-block.
+* 03-11-92 GJF Use case-insensitive comparison for Win32.
+* 04-27-92 GJF Repackaged MTHREAD support for Win32 to create a
+* _getenv_lk.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <string.h>
+#include <os2dll.h>
+#include <oscalls.h>
+
+/***
+*char *getenv(option) - search environment for a string
+*
+*Purpose:
+* searches the environment for a string of the form "option=value",
+* if found, return value, otherwise NULL.
+*
+*Entry:
+* const char *option - variable to search for in environment
+*
+*Exit:
+* returns the value part of the environment string if found,
+* otherwise NULL
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef _CRUISER_
+
+char * _CALLTYPE1 getenv (
+ REG3 const char *option
+ )
+{
+#ifdef _POSIX_
+ REG1 char **search = environ;
+#else
+ REG1 char **search = _environ;
+#endif
+ REG2 unsigned int length;
+
+ _mlock( _ENV_LOCK );
+
+ if (search && option)
+ {
+
+ length = strlen(option);
+
+ /*
+ ** Make sure `*search' is long enough to be a candidate
+ ** (We must NOT index past the '\0' at the end of `*search'!)
+ ** and that it has an equal sign (`=') in the correct spot.
+ ** If both of these requirements are met, compare the strings.
+ */
+ while (*search)
+ {
+ if (strlen(*search) > length && (*(*search + length)
+ == '=') && (strncmp(*search, option, length) == 0)) {
+ _munlock( _ENV_LOCK );
+ return(*search + length + 1);
+ }
+
+ search++;
+ }
+ }
+
+ _munlock( _ENV_LOCK );
+ return(NULL);
+}
+
+
+#else /* ndef _CRUISER_ */
+#ifdef _WIN32_
+
+
+#ifdef MTHREAD
+
+
+char * _CALLTYPE1 getenv (
+ const char *option
+ )
+{
+ char *retval;
+
+ _mlock(_ENV_LOCK);
+
+ retval = _getenv_lk(option);
+
+ _munlock(_ENV_LOCK);
+
+ return(retval);
+
+}
+
+
+char * _CALLTYPE1 _getenv_lk (
+ const char *option
+ )
+
+#else /* ndef MTHREAD */
+
+char * _CALLTYPE1 getenv (
+ const char *option
+ )
+
+#endif /* MTHREAD */
+{
+ char **search = _environ;
+ unsigned int length;
+
+ if (search && option)
+ {
+
+ length = strlen(option);
+
+ /*
+ ** Make sure `*search' is long enough to be a candidate
+ ** (We must NOT index past the '\0' at the end of `*search'!)
+ ** and that it has an equal sign (`=') in the correct spot.
+ ** If both of these requirements are met, compare the strings.
+ */
+ while (*search)
+ {
+ if (strlen(*search) > length && (*(*search + length)
+ == '=') && (strnicmp(*search, option, length) == 0)) {
+ return(*search + length + 1);
+ }
+
+ search++;
+ }
+ }
+
+ return(NULL);
+}
+
+
+#endif /* _WIN32_ */
+#endif /* _CRUISER_ */
diff --git a/private/crt32/misc/getpath.c b/private/crt32/misc/getpath.c
new file mode 100644
index 000000000..96782f176
--- /dev/null
+++ b/private/crt32/misc/getpath.c
@@ -0,0 +1,174 @@
+/***
+*getpath.c - extract a pathname from an environment variable
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Extract pathnames from a string of semicolon delimited pathnames
+* (generally the value of an environment variable such as PATH).
+*
+*Revision History:
+* 08-25-89 GJF Module created (taken from SEARCHEN.C and revised)
+* 03-14-90 GJF Replaced near with _CALLTYPE1 and added #include
+* <cruntime.h>
+* 07-25-90 SBM Replaced <stdio.h> by <stddef.h>
+* 10-04-90 GJF New-style function declarator.
+* 04-26-91 SRW Removed level 3 warnings
+* 09-18-91 JCR Strip off leading semi-colons (bug fix)
+* 09-25-91 JCR Changed ifdef "OS2" to "_HPFS_" and defined it
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stddef.h>
+#include <internal.h>
+
+/* support HPFS file system */
+#define _HPFS_ 1
+
+/***
+*_getpath() - extract a pathname from a semicolon-delimited list of pathnames
+*
+*Purpose:
+* To extract the next pathname from a semicolon-delimited list of
+* pathnames (usually the value on an environment variable) and copy
+* it to a caller-specified buffer. No check is done to see if the path
+* is valid. The maximum number of characters copied to the buffer is
+* maxlen - 1 (and then a '\0' is appended).
+*
+#ifdef _HPFS_
+* If we hit a quoted string, then allow any characters inside.
+* For example, to put a semi-colon in a path, the user could have
+* an environment variable that looks like:
+*
+* PATH=C:\BIN;"D:\CRT\TOOLS;B1";C:\BINP
+#endif
+*
+* NOTE: Semi-colons in sequence are skipped over; pointers to 0-length
+* pathnames are NOT returned (this includes leading semi-colons).
+*
+* NOTE: If this routine is made user-callable, the near attribute
+* must be replaced by _LOAD_DS and the prototype moved from INTERNAL.H
+* to STDLIB.H. The source files MISC\SEARCHEN.C and EXEC\SPAWNVPE.C
+* will need to be recompiled, but should not require any changes.
+*
+*Entry:
+* src - Pointer to a string of 0 or more path specificiations,
+* delimited by semicolons (';'), and terminated by a null
+* character
+* dst - Pointer to the buffer where the next path specification is to
+* be copied
+* maxlen - Maximum number of characters to be copied, counting the
+* terminating null character. Note that a value of 0 is treated
+* as UINT_MAX + 1.
+*
+*Exit:
+* If a pathname is successfully extracted and copied, a pointer to the
+* first character of next pathname is returned (intervening semicolons
+* are skipped over). If the pathname is too long, as much as possible
+* is copied to the user-specified buffer and NULL is returned.
+*
+* Note that the no check is made of the validity of the copied pathname.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _getpath (
+ register const char *src,
+ register char *dst,
+ unsigned maxlen
+ )
+{
+ const char *save_src;
+
+ /*
+ * strip off leading semi colons
+ */
+ while ( *src == ';' )
+ src++;
+
+ /*
+ * Save original src pointer
+ */
+ save_src = src;
+
+ /*
+ * Decrement maxlen to allow for the terminating '\0'
+ */
+ if ( --maxlen == 0 )
+ goto appendnull;
+
+
+ /*
+ * Get the next path in src string
+ */
+ while (*src && (*src != ';')) {
+
+#ifdef _HPFS_
+
+ /*
+ * Check for quote char
+ */
+ if (*src != '"') {
+
+ *dst++ = *src++;
+
+ if ( --maxlen == 0 ) {
+ save_src = src; /* ensure NULL return */
+ goto appendnull;
+ }
+
+ }
+ else {
+
+ /*
+ * Found a quote. Copy all chars until we hit the
+ * final quote or the end of the string.
+ */
+ src++; /* skip over opening quote */
+
+ while (*src && (*src != '"')) {
+
+ *dst++ = *src++;
+
+ if ( --maxlen == 0 ) {
+ save_src = src; /* ensure NULL return */
+ goto appendnull;
+ }
+ }
+
+ if (*src)
+ src++; /* skip over closing quote */
+
+ }
+
+#else
+
+ *dst++ = *src++;
+
+ if ( --maxlen == 0 ) {
+ save_src = src; /* ensure NULL return */
+ goto appendnull;
+ }
+
+#endif
+
+ }
+
+ /*
+ * If we copied something and stopped because of a ';',
+ * skip the ';' before returning
+ */
+ while ( *src == ';' )
+ src++;
+
+ /*
+ * Store a terminating null
+ */
+appendnull:
+
+ *dst = '\0';
+
+ return((save_src != src) ? (char *)src : NULL);
+}
diff --git a/private/crt32/misc/getqloc.c b/private/crt32/misc/getqloc.c
new file mode 100644
index 000000000..b9ab3461f
--- /dev/null
+++ b/private/crt32/misc/getqloc.c
@@ -0,0 +1,736 @@
+/***
+*getqloc.c - get qualified locale
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _get_qualified_locale - get complete locale information
+*
+* NOTE: this should be a one-line call to an NT routine, but since NT does
+* not currently support the needed functionality, this will suffice,
+* it MUST be changed when NT supports changes.
+*
+* STAGE 1: convert input to internal LC_ID
+*
+* STAGE 2: qualify internal LC_ID
+* Locales in NT version 1 are really just a language and a sublanguage;
+* the language info is not useful. We therefore do not return a true
+* country code, but rather return the language for that country.
+*
+* STAGE 3: convert to proper output format
+* If output is an Id, no conversion necessary. If output is a string, call
+* NT routines to get English strings for qualified locale.
+**
+*Revision History:
+* 12-11-92 CFW initial version
+* 01-08-93 CFW cleaned up file
+* 02-02-93 CFW Added test for NULL input string fields
+* 02-08-93 CFW Casts to remove warnings.
+* 02-18-93 CFW Removed debugging support routines, changed copyright.
+* 02-18-93 CFW Removed debugging support routines, changed copyright.
+* 03-01-93 CFW Test code page validity, use ANSI comments.
+* 03-02-93 CFW Add ISO 3166 3-letter country codes, verify country table.
+* 03-04-93 CFW Call IsValidCodePage to test code page vailidity.
+* 03-10-93 CFW Protect table testing code.
+* 03-17-93 CFW Add __ to lang & ctry info tables, move defs to setlocal.h.
+* 03-23-93 CFW Make internal functions static, add _ to GetQualifiedLocale.
+* 03-24-93 CFW Change to _get_qualified_locale, support ".codepage".
+* 04-20-93 CFW Enable all strange countries.
+* 05-20-93 GJF Include windows.h, not individual win*.h files
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <setlocal.h>
+
+#define iAslpStr(i) ((LPLC_STRINGS)i)
+#define iAslpId(i) ((LPLC_ID)i)
+
+#define MAX_TEMP_STR_LEN (max(MAX_LANG_LEN, max(MAX_CTRY_LEN, MAX_CP_LEN)))
+
+static WORD trans_lang_lang(const PSZ pszLang);
+static WORD trans_ctry_ctry(const PSZ pszCtry);
+static WORD trans_ctry_lang(WORD wCtry);
+static BOOL match_ctry_lang(WORD *pwCtry, WORD *pwLang);
+static VOID pszcpywcs(PSZ pszStr, PWSTR pwStr);
+
+/* Languages supported are according to "Win32 NLSAPI Functional */
+/* Specification" of 15 September, 1992 */
+
+#define LANG_STR_NUM 92 /* number of language strings + 1 for algorithm */
+
+LANGREC __rg_lang_rec[] =
+{
+ {"", MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)},
+ {"american", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)},
+ {"american english", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)},
+ {"american-english", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)},
+ {"australian", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_AUS)},
+ {"belgian", MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH_BELGIAN)},
+ {"canadian", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_CAN)},
+ {"chinese", MAKELANGID(LANG_CHINESE, SUBLANG_DEFAULT)},
+ {"chinese-simplified", MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)},
+ {"chinese-traditional", MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)},
+ {"chs", MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)},
+ {"cht", MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)},
+ {"csy", MAKELANGID(LANG_CZECH, SUBLANG_DEFAULT)},
+ {"czech", MAKELANGID(LANG_CZECH, SUBLANG_DEFAULT)},
+ {"dan", MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT)},
+ {"danish", MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT)},
+ {"dea", MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN)},
+ {"des", MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS)},
+ {"deu", MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT)},
+ {"dutch", MAKELANGID(LANG_DUTCH, SUBLANG_DEFAULT)},
+ {"dutch-belgian", MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH_BELGIAN)},
+ {"ell", MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT)},
+ {"ena", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_AUS)},
+ {"enc", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_CAN)},
+ {"eng", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK)},
+ {"english", MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)},
+ {"english-american", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)},
+ {"english-aus", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_AUS)},
+ {"english-can", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_CAN)},
+ {"english-nz", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_NZ)},
+ {"english-uk", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK)},
+ {"english-us", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)},
+ {"english-usa", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)},
+ {"enu", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)},
+ {"enz", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_NZ)},
+ {"esm", MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MEXICAN)},
+ {"esn", MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN)},
+ {"esp", MAKELANGID(LANG_SPANISH, SUBLANG_DEFAULT)},
+ {"fin", MAKELANGID(LANG_FINNISH, SUBLANG_DEFAULT)},
+ {"finnish", MAKELANGID(LANG_FINNISH, SUBLANG_DEFAULT)},
+ {"fra", MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT)},
+ {"frb", MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_BELGIAN)},
+ {"frc", MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_CANADIAN)},
+ {"french", MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT)},
+ {"french-belgian", MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_BELGIAN)},
+ {"french-canadian", MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_CANADIAN)},
+ {"french-swiss", MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_SWISS)},
+ {"frs", MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_SWISS)},
+ {"german", MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT)},
+ {"german-austrian", MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN)},
+ {"german-swiss", MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS)},
+ {"greek", MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT)},
+ {"hun", MAKELANGID(LANG_HUNGARIAN, SUBLANG_DEFAULT)},
+ {"hungarian", MAKELANGID(LANG_HUNGARIAN, SUBLANG_DEFAULT)},
+ {"icelandic", MAKELANGID(LANG_ICELANDIC, SUBLANG_DEFAULT)},
+ {"isl", MAKELANGID(LANG_ICELANDIC, SUBLANG_DEFAULT)},
+ {"ita", MAKELANGID(LANG_ITALIAN, SUBLANG_DEFAULT)},
+ {"italian", MAKELANGID(LANG_ITALIAN, SUBLANG_DEFAULT)},
+ {"italian-swiss", MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN_SWISS)},
+ {"its", MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN_SWISS)},
+ {"japanese", MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)},
+ {"jpn", MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)},
+ {"kor", MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT)},
+ {"korean", MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT)},
+ {"nlb", MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH_BELGIAN)},
+ {"nld", MAKELANGID(LANG_DUTCH, SUBLANG_DEFAULT)},
+ {"non", MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK)},
+ {"nor", MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL)},
+ {"norwegian", MAKELANGID(LANG_NORWEGIAN, SUBLANG_DEFAULT)},
+ {"norwegian-bokmal", MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL)},
+ {"norwegian-nynorsk", MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK)},
+ {"plk", MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT)},
+ {"polish", MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT)},
+ {"portuguese", MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE)},
+ {"portuguese-brazilian", MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN)},
+ {"ptb", MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN)},
+ {"ptg", MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE)},
+ {"rus", MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT)},
+ {"russian", MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT)},
+ {"sky", MAKELANGID(LANG_SLOVAK, SUBLANG_DEFAULT)},
+ {"slovak", MAKELANGID(LANG_SLOVAK, SUBLANG_DEFAULT)},
+ {"spanish", MAKELANGID(LANG_SPANISH, SUBLANG_DEFAULT)},
+ {"spanish-mexican", MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MEXICAN)},
+ {"spanish-modern", MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN)},
+ {"sve", MAKELANGID(LANG_SWEDISH, SUBLANG_DEFAULT)},
+ {"swedish", MAKELANGID(LANG_SWEDISH, SUBLANG_DEFAULT)},
+ {"swiss", MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS)},
+ {"trk", MAKELANGID(LANG_TURKISH, SUBLANG_DEFAULT)},
+ {"turkish", MAKELANGID(LANG_TURKISH, SUBLANG_DEFAULT)},
+ {"uk", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK)},
+ {"us", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)},
+ {"usa", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)}
+};
+
+/* Countries supported are according to "Win32 NLSAPI Functional */
+/* Specification" of 15 September, 1992 */
+
+#define CTRY_STR_NUM 68 /* number of country strings + 1 for algorithm */
+
+CTRYREC __rg_ctry_rec[] =
+{
+ {"", 0},
+ {"america", CTRY_UNITED_STATES},
+ {"aus", CTRY_AUSTRALIA},
+ {"australia", CTRY_AUSTRALIA},
+ {"austria", CTRY_AUSTRIA},
+ {"aut", CTRY_AUSTRIA},
+ {"bel", CTRY_BELGIUM},
+ {"belgium", CTRY_BELGIUM},
+ {"bra", CTRY_BRAZIL},
+ {"brazil", CTRY_BRAZIL},
+ {"britain", CTRY_UNITED_KINGDOM},
+ {"can", CTRY_CANADA},
+ {"canada", CTRY_CANADA},
+ {"che", CTRY_SWITZERLAND},
+ {"china", CTRY_PRCHINA},
+ {"chn", CTRY_PRCHINA},
+ {"denmark", CTRY_DENMARK},
+ {"deu", CTRY_GERMANY},
+ {"dnk", CTRY_DENMARK},
+ {"england", CTRY_UNITED_KINGDOM},
+ {"esp", CTRY_SPAIN},
+ {"fin", CTRY_FINLAND},
+ {"finland", CTRY_FINLAND},
+ {"fra", CTRY_FRANCE},
+ {"france", CTRY_FRANCE},
+ {"gbr", CTRY_UNITED_KINGDOM},
+ {"germany", CTRY_GERMANY},
+ {"great britain", CTRY_UNITED_KINGDOM},
+ {"holland", CTRY_NETHERLANDS},
+ {"iceland", CTRY_ICELAND},
+ {"ireland", CTRY_IRELAND},
+ {"irl", CTRY_IRELAND},
+ {"isl", CTRY_ICELAND},
+ {"ita", CTRY_ITALY},
+ {"italy", CTRY_ITALY},
+ {"japan", CTRY_JAPAN},
+ {"jpn", CTRY_JAPAN},
+ {"kor", CTRY_SOUTH_KOREA},
+ {"korea", CTRY_SOUTH_KOREA},
+ {"mex", CTRY_MEXICO},
+ {"mexico", CTRY_MEXICO},
+ {"netherlands", CTRY_NETHERLANDS},
+ {"new zealand", CTRY_NEW_ZEALAND},
+ {"new-zealand", CTRY_NEW_ZEALAND},
+ {"nld", CTRY_NETHERLANDS},
+ {"nor", CTRY_NORWAY},
+ {"norway", CTRY_NORWAY},
+ {"nz", CTRY_NEW_ZEALAND},
+ {"nzl", CTRY_NEW_ZEALAND},
+ {"portugal", CTRY_PORTUGAL},
+ {"pr china", CTRY_PRCHINA},
+ {"pr-china", CTRY_PRCHINA},
+ {"prt", CTRY_PORTUGAL},
+ {"south korea", CTRY_SOUTH_KOREA},
+ {"south-korea", CTRY_SOUTH_KOREA},
+ {"spain", CTRY_SPAIN},
+ {"swe", CTRY_SWEDEN},
+ {"sweden", CTRY_SWEDEN},
+ {"switzerland", CTRY_SWITZERLAND},
+ {"taiwan", CTRY_TAIWAN},
+ {"twn", CTRY_TAIWAN},
+ {"uk", CTRY_UNITED_KINGDOM},
+ {"united kingdom", CTRY_UNITED_KINGDOM},
+ {"united states", CTRY_UNITED_STATES},
+ {"united-kingdom", CTRY_UNITED_KINGDOM},
+ {"united-states", CTRY_UNITED_STATES},
+ {"us", CTRY_UNITED_STATES},
+ {"usa", CTRY_UNITED_STATES},
+};
+
+#define MAX_LANG_PER_CTRY 3 /* Switzerland has three languages*/
+#define MAX_CTRY_NUM 86 /* Ignore high digit (Max=China[86]=Taiwan[886])*/
+WORD __rgrgwlang[MAX_CTRY_NUM + 1][MAX_LANG_PER_CTRY] =
+{
+/* 0*/
+ {0,0,0},
+ {MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),0,0},
+ {MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_CAN),
+ MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_CANADIAN),0},
+ {MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH_MEXICAN),
+ MAKELANGID(LANG_PORTUGUESE,SUBLANG_PORTUGUESE_BRAZILIAN),0},
+ {0,0,0},
+
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+/* 10*/
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+/* 20*/
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+/* 30*/
+ {0,0,0},
+ {MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH),0,0},
+ {MAKELANGID(LANG_DUTCH,SUBLANG_DUTCH_BELGIAN),
+ MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_BELGIAN),0},
+ {MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH),0,0},
+ {MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH),0,0},
+
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {MAKELANGID(LANG_ITALIAN,SUBLANG_ITALIAN),0,0},
+/* 40*/
+ {0,0,0},
+ {MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_SWISS),
+ MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH_SWISS),
+ MAKELANGID(LANG_ITALIAN,SUBLANG_ITALIAN_SWISS)},
+ {0,0,0},
+ {MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN_AUSTRIAN),0,0},
+ {MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_UK),0,0},
+
+ {MAKELANGID(LANG_DANISH,SUBLANG_DEFAULT),0,0},
+ {MAKELANGID(LANG_SWEDISH,SUBLANG_DEFAULT),0,0},
+ {MAKELANGID(LANG_NORWEGIAN,SUBLANG_DEFAULT),0,0},
+ {0,0,0},
+ {MAKELANGID(LANG_GERMAN,SUBLANG_GERMAN),0,0},
+/* 50*/
+ {0,0,0},
+ {MAKELANGID(LANG_PORTUGUESE,SUBLANG_PORTUGUESE),0,0},
+ {MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH_MEXICAN),0,0},
+ {MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_UK),0,0},
+ {MAKELANGID(LANG_ICELANDIC,SUBLANG_DEFAULT),0,0},
+
+ {MAKELANGID(LANG_PORTUGUESE,SUBLANG_PORTUGUESE_BRAZILIAN),0,0},
+ {0,0,0},
+ {0,0,0},
+ {MAKELANGID(LANG_FINNISH,SUBLANG_DEFAULT),0,0},
+ {0,0,0},
+/* 60*/
+ {0,0,0},
+ {MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_AUS),0,0},
+ {0,0,0},
+ {0,0,0},
+ {MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_NZ),0,0},
+
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+/* 70*/
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+/* 80*/
+ {0,0,0},
+ {MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT),0,0},
+ {MAKELANGID(LANG_KOREAN,SUBLANG_DEFAULT),0,0},
+ {0,0,0},
+ {0,0,0},
+ {0,0,0},
+ {MAKELANGID(LANG_CHINESE,SUBLANG_DEFAULT),0,0}
+};
+
+/***
+*void pszcpywcs - strcpy, wide char string to char string
+*
+*Purpose:
+* Copies and converts string
+*
+*Entry:
+* psz pszStr - pointer to destination char string
+* pwstr pwStr - pointer to source wide char string
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+static VOID pszcpywcs(PSZ pszStr, PWSTR pwStr)
+{
+ while (*pwStr)
+ *pszStr++ = (char)(*pwStr++);
+ *pszStr = 0;
+}
+
+/***
+*WORD trans_lang_lang - translate language string to language id
+*
+*Purpose:
+* convert string to id
+*
+*Entry:
+* pszLang - pointer to language string
+*
+*Exit:
+* translated language id
+*
+*Exceptions:
+*
+*******************************************************************************/
+static WORD trans_lang_lang(const PSZ pszLang)
+{
+ INT i, cmp, low = 0, high = LANG_STR_NUM + 1;
+
+ while (1)
+ {
+ i = (low + high) / 2;
+
+ if (!(cmp = stricmp(pszLang, (const char *)__rg_lang_rec[i].szLanguage)))
+ return __rg_lang_rec[i].wLanguage; /* found the string*/
+ else if (cmp < 0)
+ high = i; /* less than pivot*/
+ else
+ low = i; /* more than pivot*/
+ if (low + 1 == high)
+ return 0; /* not found*/
+ }
+}
+
+/***
+*WORD trans_ctry_ctry - translate country string to country id
+*
+*Purpose:
+* convert string to id
+*
+*Entry:
+* pszCtry - pointer to country string
+*
+*Exit:
+* translated country id
+*
+*Exceptions:
+*
+*******************************************************************************/
+static WORD trans_ctry_ctry(const PSZ pszCtry)
+{
+ INT i, cmp, low = 0, high = CTRY_STR_NUM + 1;
+
+ while (1)
+ {
+ i = (low + high) / 2;
+
+ if (!(cmp = stricmp(pszCtry, (const char *)__rg_ctry_rec[i].szCountry)))
+ return __rg_ctry_rec[i].wCountry; /* found the string*/
+ else if (cmp < 0)
+ high = i; /* less than pivot*/
+ else
+ low = i; /* more than pivot*/
+ if (low + 1 == high)
+ return 0; /* not found*/
+ }
+}
+
+/***
+*WORD trans_ctry_lang - get default language for a country
+*
+*Purpose:
+* convert country id to language id
+*
+*Entry:
+* wCtry - country id
+*
+*Exit:
+* translated language id
+*
+*Exceptions:
+*
+*******************************************************************************/
+static WORD trans_ctry_lang(WORD wCtry)
+{
+ wCtry %= 100;
+ if (wCtry > MAX_CTRY_NUM)
+ return 0;
+
+ return __rgrgwlang[wCtry][0];
+}
+
+/***
+*BOOL match_ctry_lang - match country with language
+*
+*Purpose:
+* ensure language and country match, choose proper values for language
+* and country when matching, country ids converted to proper language id
+*
+*Entry:
+* pwCtry - pointer to country id to match and set
+* pwLang - pointer to language id to match and set
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+static BOOL match_ctry_lang(WORD *pwCtry, WORD *pwLang)
+{
+ UINT i;
+ WORD wCtry = *pwCtry;
+ WORD wLang = *pwLang;
+ WORD wLangT;
+
+ /* only use base 10 two least significant places*/
+ wCtry = wCtry % 100;
+
+ if (wCtry > MAX_CTRY_NUM)
+ return FALSE;
+
+ /* see if any of the sublanguages for this country match*/
+ for (i = 0; i < MAX_LANG_PER_CTRY; i++)
+ {
+ if (!(wLangT = __rgrgwlang[wCtry][i]))
+ break;
+ if (PRIMARYLANGID(wLangT) == PRIMARYLANGID(wLang))
+ {
+ /* they match*/
+ if (!SUBLANGID(wLang))
+ /* don't override sublanguage*/
+ *pwLang = wLangT;
+ *pwCtry = wLangT;
+ return TRUE;
+ }
+ }
+ /* get the default language for this country*/
+ if (!(*pwCtry = __rgrgwlang[wCtry][0]))
+ /* bad country number*/
+ return FALSE;
+ return TRUE;
+}
+
+/***
+*BOOL _get_qualified_locale - return fully qualified locale
+*
+*Purpose:
+* get default locale, qualify partially complete locales
+*
+*Entry:
+* dwType - indicates type of lpInput, either QF_STRINGS or QF_LCID
+* lpInput - input string/id to be qualified
+* lpOutId - pointer to output id, may be NULL if lpOutStr is !NULL
+* lpOutStr - pointer to output string, may be NULL if lpOutId is !NULL
+*
+*Exit:
+* TRUE if success, qualified locale is valid
+* FALSE if failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+BOOL _CRTAPI1 _get_qualified_locale(
+ const DWORD dwType,
+ const LPVOID lpInput,
+ LPLC_ID lpOutId,
+ LPLC_STRINGS lpOutStr
+ )
+{
+#if defined _POSIX_
+ return FALSE;
+#else /* _POSIX_ */
+
+ LC_ID Id;
+ WCHAR wcsTemp[MAX_TEMP_STR_LEN];
+
+ if (!lpOutId && !lpOutStr)
+ return FALSE;
+
+ /* -----------------------------------------------------------------------
+ stage 1: convert input to internal LC_ID.
+ -----------------------------------------------------------------------*/
+
+ if (dwType == QF_STRINGS)
+ {
+ Id.wLanguage = (WORD)0;
+ Id.wCountry = (WORD)0;
+ Id.wCodePage = (WORD)0;
+
+ if (iAslpStr(lpInput)->szLanguage
+ && *(iAslpStr(lpInput)->szLanguage)
+ && (!(Id.wLanguage =
+ trans_lang_lang((const PSZ)iAslpStr(lpInput)->szLanguage))))
+ return FALSE;
+
+ if (iAslpStr(lpInput)->szCountry
+ && *(iAslpStr(lpInput)->szCountry)
+ && (!(Id.wCountry =
+ trans_ctry_ctry((const PSZ)iAslpStr(lpInput)->szCountry))))
+ return FALSE;
+
+ if (iAslpStr(lpInput)->szCodePage
+ && *(iAslpStr(lpInput)->szCodePage)
+ && (!(Id.wCodePage = atoi((const char *)iAslpStr(lpInput)->szCodePage))))
+ return FALSE;
+ }
+ else if (dwType == QF_LCID)
+ {
+ Id = *iAslpId(lpInput);
+ }
+
+ /* -----------------------------------------------------------------------
+ stage 2: qualify internal LC_ID
+ -----------------------------------------------------------------------*/
+
+ if (!Id.wLanguage)
+ {
+ /* language undefined*/
+ if (!Id.wCountry)
+ {
+ /* language undefined, country undefined*/
+ Id.wLanguage = Id.wCountry = LANGIDFROMLCID(GetUserDefaultLCID());
+ if (Id.wCodePage)
+ {
+ /* language undefined, country undefined and code page defined*/
+ if (IsValidCodePage(Id.wCodePage) == FALSE)
+ return FALSE;
+ }
+ else {
+ /* language, country and code page undefined*/
+ Id.wCodePage = (WORD)GetOEMCP();
+ }
+ }
+ else
+ {
+ /* language undefined, country defined*/
+ Id.wCountry = Id.wLanguage = trans_ctry_lang(Id.wCountry);
+
+ if (Id.wCodePage)
+ {
+ /* language undefined, country defined and code page defined*/
+ if (IsValidCodePage(Id.wCodePage) == FALSE)
+ return FALSE;
+ }
+ else {
+ /* language undefined, country defined and code page undefined*/
+ if (!GetLocaleInfoW(MAKELCID(Id.wCountry, SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, wcsTemp, MAX_TEMP_STR_LEN))
+ return FALSE;
+ Id.wCodePage = (WORD)wcstol(wcsTemp, NULL, 10);
+ }
+ }
+ }
+ else
+ {
+ /* language defined*/
+ if (!Id.wCountry)
+ {
+ /* language defined, country undefined*/
+ Id.wCountry = Id.wLanguage;
+
+ if (Id.wCodePage)
+ {
+ /* language defined, country undefined and code page defined*/
+ if (IsValidCodePage(Id.wCodePage) == FALSE)
+ return FALSE;
+ }
+ else {
+ /* language undefined, country undefined and code page undefined*/
+ if (!GetLocaleInfoW(MAKELCID(Id.wCountry, SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, wcsTemp, MAX_TEMP_STR_LEN))
+ return FALSE;
+ Id.wCodePage = (WORD)wcstol(wcsTemp, NULL, 10);
+ }
+ }
+ else
+ {
+ /* language defined, country defined*/
+
+ /* match and set country and language*/
+ if (!match_ctry_lang((WORD *)&Id.wCountry, (WORD *)&Id.wLanguage))
+ return FALSE;
+
+ if (Id.wCodePage)
+ {
+ /* language defined, country defined and code page defined*/
+ if (IsValidCodePage(Id.wCodePage) == FALSE)
+ return FALSE;
+ }
+ else {
+ /* language defined, country defined and code page undefined*/
+ if (!GetLocaleInfoW(MAKELCID(Id.wCountry, SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, wcsTemp, MAX_TEMP_STR_LEN))
+ return FALSE;
+ Id.wCodePage = (WORD)wcstol(wcsTemp, NULL, 10);
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
+ stage 3: convert to proper output format
+ -----------------------------------------------------------------------*/
+
+ if (lpOutId)
+ {
+ *lpOutId = Id;
+ }
+
+ if (lpOutStr)
+ {
+ if (!GetLocaleInfoW(MAKELCID(Id.wLanguage, SORT_DEFAULT), LOCALE_SENGLANGUAGE, wcsTemp, MAX_LANG_LEN))
+ return FALSE;
+ pszcpywcs((PSZ)lpOutStr->szLanguage, (PWSTR)wcsTemp);
+
+ if (!GetLocaleInfoW(MAKELCID(Id.wCountry, SORT_DEFAULT), LOCALE_SENGCOUNTRY, wcsTemp, MAX_CTRY_LEN))
+ return FALSE;
+ pszcpywcs((PSZ)lpOutStr->szCountry, (PWSTR)wcsTemp);
+
+ _itoa((int)Id.wCodePage, (char *)lpOutStr->szCodePage, 10);
+ }
+ return TRUE;
+#endif /* _POSIX_ */
+}
+
+
+/* for testing when new items added to tables */
+
+#if 0
+
+VOID _CRTAPI1 test_lang_table(VOID)
+{
+ UINT i;
+
+ printf("Testing Language Table\n");
+ printf("Real Table Size = %d entries, defined size=%d entries\n",
+ sizeof(__rg_lang_rec) / sizeof(LANGREC), LANG_STR_NUM);
+ for (i = 0; i < LANG_STR_NUM-1; i++)
+ {
+ printf("language name[%d] = '%s' number=%d\n", i, __rg_lang_rec[i].szLanguage, __rg_lang_rec[i].wLanguage);
+ if ((stricmp(__rg_lang_rec[i].szLanguage,__rg_lang_rec[i+1].szLanguage) >= 0))
+ printf("\n*********\nBad Lang Table Lang[%d]=%s Lang[%d]=%s\n\n",
+ i, __rg_lang_rec[i].szLanguage, i+1, __rg_lang_rec[i+1].szLanguage);
+ }
+ printf("language name[%d] = '%s' number=%d\n", i, __rg_lang_rec[i].szLanguage, __rg_lang_rec[i].wLanguage);
+}
+
+VOID _CRTAPI1 test_ctry_table(VOID)
+{
+ UINT i;
+
+ printf("Testing Country Table\n");
+ printf("Real Table Size = %d entries, defined size=%d entries\n",
+ sizeof(__rg_ctry_rec) / sizeof(CTRYREC), CTRY_STR_NUM);
+ for (i = 0; i < CTRY_STR_NUM-1; i++)
+ {
+ printf("country name[%d] = '%s' number=%d\n", i, __rg_ctry_rec[i].szCountry, __rg_ctry_rec[i].wCountry);
+ if ((stricmp(__rg_ctry_rec[i].szCountry,__rg_ctry_rec[i+1].szCountry) >= 0))
+ printf("\n**********\nBad Ctry Table Ctry[%d]=%s Ctry[%d]=%s\n\n",
+ i, __rg_ctry_rec[i].szCountry, i+1, __rg_ctry_rec[i+1].szCountry);
+ }
+ printf("country name[%d] = '%s' number=%d\n", i, __rg_ctry_rec[i].szCountry, __rg_ctry_rec[i].wCountry);
+}
+
+#endif
diff --git a/private/crt32/misc/i386/_initone.asm b/private/crt32/misc/i386/_initone.asm
new file mode 100644
index 000000000..90d901904
--- /dev/null
+++ b/private/crt32/misc/i386/_initone.asm
@@ -0,0 +1,17 @@
+ page ,132
+
+;*******
+;
+; Alternate form of CINITONE.ASM
+;
+; The MIPS C Compiler does not prepend underscores to C
+; variables and functions like the I386 C Compiler does.
+;
+; The EQUate below will yield an object file
+; which will be appropriate for MIPS COFF format.
+;
+;*******
+
+NO_UNDERSCORE equ 1
+
+include i386\cinitone.asm
diff --git a/private/crt32/misc/i386/cinitone.asm b/private/crt32/misc/i386/cinitone.asm
new file mode 100644
index 000000000..e4bf0ef39
--- /dev/null
+++ b/private/crt32/misc/i386/cinitone.asm
@@ -0,0 +1,78 @@
+ page ,132
+ title cinitone - C Run-Time Initialization for _onexit/atexit
+;***
+;cinitone.asm - WIN32 C Run-Time Initialization for _onexit()/atexit() routines
+;
+; Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Initialization entry for the _onexit()/atexit() functions.
+; This module adds an entry for _onexitinit() to the initializer table.
+; ONEXIT.C references the dummy variable __c_onexit in order to force
+; the loading of this module.
+;
+;Notes:
+;
+;Revision History:
+; 03-19-92 SKS Module created.
+; 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+; 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+; 08-06-92 SKS Revised to use new section names and macros
+;
+;*******************************************************************************
+
+.xlist
+include cruntime.inc
+include defsects.inc
+.list
+
+ifndef _WIN32_
+.err
+%out _WIN32_ MUST be defined!
+endif
+
+
+ifndef NO_UNDERSCORE ; I386 VERSION *************************
+
+
+ extrn _onexitinit:NEAR
+
+
+beginSection XIC
+
+ dd offset FLAT: _onexitinit
+
+endSection XIC
+
+
+ .DATA
+
+ public __c_onexit
+
+__c_onexit dd 0
+
+
+else ; NO_UNDERSCORE ; MIPS VERSION *************************
+
+
+ extrn onexitinit:NEAR
+
+
+beginSection XIC
+
+ dd offset FLAT: onexitinit
+
+endSection XIC
+
+
+ .DATA
+
+ public _c_onexit
+
+_c_onexit dd 0
+
+
+endif ; NO_UNDERSCORE ; **** VERSION *************************
+
+
+ end
diff --git a/private/crt32/misc/i386/exsup.asm b/private/crt32/misc/i386/exsup.asm
new file mode 100644
index 000000000..8e7043eca
--- /dev/null
+++ b/private/crt32/misc/i386/exsup.asm
@@ -0,0 +1,299 @@
+;***
+;exsup.asm
+;
+; Copyright (c) 1993-1994 Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Exception handling for i386. This file contains those routines
+; common to both C8.0 and C9.0.
+;
+;Notes:
+;
+;Revision History:
+; 04-13-93 JWM setjmp(), longjmp() & raisex() moved to setjmp.asm;
+; common data definitions moved to exsup.inc.
+; 10-18-93 GJF Ensure direction flag is clear in _except_handler2
+; 12-16-93 PML Accept <0,0,>0 from except filter, not just -1,0,+1
+; 01-10-94 PML Moved C8-specific __except_handler2 to exsup2.inc.
+; Only C8/C9 common routines left here.
+; 02-10-94 GJF -1 is the end-of-exception-handler chain marker, not
+; 0.
+;
+;*******************************************************************************
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+;Define small32 and flat32 since these are not defined in the NT build process
+small32 equ 1
+flat32 equ 1
+
+ifdef _WIN32_
+_WIN32_OR_POSIX_ equ 1
+endif
+ifdef _POSIX_
+_WIN32_OR_POSIX_ equ 1
+endif
+
+.xlist
+include pversion.inc
+?DFDATA = 1
+?NODATA = 1
+include cmacros.mas
+include exsup.inc
+.list
+
+;REVIEW: can we get rid of _global_unwind2, and just use
+; the C runtimes version, _global_unwind?
+
+ifdef _WIN32_OR_POSIX_
+extrn _RtlUnwind@16:near
+endif
+
+;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION;
+;struct _EXCEPTION_REGISTRATION{
+; struct _EXCEPTION_REGISTRATION *prev;
+; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
+; struct scopetable_entry *scopetable;
+; int trylevel;
+;};
+_EXCEPTION_REGISTRATION_COMMON struc ; C8.0/C9.0 common only
+ dd ? ; prev (OS-req, def'd in exsup.inc)
+ dd ? ; handler (ditto)
+scopetable dd ? ; C8/C9 common
+trylevel dd ? ; C8/C9 common
+_EXCEPTION_REGISTRATION_COMMON ends
+
+;#define EXCEPTION_MAXIMUM_PARAMETERS 4
+;typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
+;typedef EXCEPTION_RECORD *PEXCEPTION_RECORD;
+;struct _EXCEPTION_RECORD{
+; NTSTATUS ExceptionCode;
+; ULONG ExceptionFlags;
+; struct _EXCEPTION_RECORD *ExceptionRecord;
+; PVOID ExceptionAddress;
+; ULONG NumberParameters;
+; ULONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+;};
+_EXCEPTION_RECORD struc
+ exception_number dd ?
+ exception_flags dd ?
+ exception_record dd ?
+ exception_address dd ?
+ number_parameters dd ?
+ exception_information dd 4 dup(?)
+_EXCEPTION_RECORD ends
+SIZEOF_EXCEPTION_RECORD equ 36
+
+assumes DS,DATA
+assumes FS,DATA
+
+public __except_list
+__except_list equ 0
+
+;struct _SCOPETABLE_ENTRY{
+; int enclosing_level; /* lexical level of enclosing scope */
+; int (*filter)(PEXCEPTION_RECORD); /* NULL for a termination handler */
+; void (*specific_handler)(void); /* xcpt or termination handler */
+;};
+;struct _SCOPETABLE_ENTRY Scopetable[NUMTRYS];
+_SCOPETABLE_ENTRY struc
+ enclosing_level dd ?
+ filter dd ?
+ specific_handler dd ?
+_SCOPETABLE_ENTRY ends
+
+BeginCODE
+if @Version LT 600
+ifdef _WIN32_OR_POSIX_
+;this needs to go here to work around a masm5 bug. (emits wrong fixup)
+assumes CS,FLAT
+else
+assumes CS,CODE
+endif
+endif
+
+ifdef _WIN32_OR_POSIX_ ;{
+
+;NB: call to RtlUnwind appears to trash ebx! and possibly others so just
+; to be save, we save all callee save regs.
+cProc _global_unwind2,<C,PUBLIC>,<IBX,ISI,IDI,IBP>
+ parmDP stop
+cBegin
+ push 0 ; ReturnValue
+ push 0 ; ExceptionRecord
+ push offset flat:_gu_return ; TargetIp
+ push stop ; TargetFrame
+
+ call _RtlUnwind@16
+_gu_return:
+cEnd
+
+else ;}{
+
+;/* _GLOBAL_UNWIND2 - */
+;void _global_unwind2(PEXCEPTION_REGISTRATION *stop)
+;{
+; for(xr=__except_list; xr!=stop; xr=xr->prev){
+; assert(xr!=NULL);
+; /* NOTE: must set ebp to this scopes frame before call */
+; _local_unwind2(xr, -1);
+; }
+;}
+cProc _global_unwind2,<C,PUBLIC>,<ISI,IDI>
+ parmDP stop
+ localV xr,SIZEOF_EXCEPTION_RECORD
+cBegin
+ ;build an EXCEPTION_RECORD to pass to language handler for unwinding
+ lea esi, xr
+ mov [esi.exception_number], 0
+ mov [esi.exception_flags], EXCEPTION_UNWIND_CONTEXT
+ ;REVIEW: fill in the rest of the struct?
+
+ mov edi, dword ptr fs:__except_list
+_gu_top:
+ cmp edi, stop
+ je short _gu_done
+ cmp edi, -1 ; -1 means no higher-level handler
+ je short _gu_error
+
+ push edi
+ push esi
+ call [edi.handler]
+ add esp, 8
+
+ mov edi, [edi.prev]
+ mov dword ptr fs:__except_list, edi
+ jmp short _gu_top
+
+_gu_error:
+ ;assert(0);
+
+_gu_done:
+cEnd
+
+endif ;}
+
+;_unwind_handler(
+; PEXCEPTION_RECORD xr,
+; PREGISTRATION_RECORD establisher,
+; PCONTEXT context,
+; PREGISTRATION_RECORD dispatcher);
+;
+;this is a special purpose handler used to guard our local unwinder.
+; its job is to catch collided unwinds.
+;
+;NB: this code is basically stolen from the NT routine xcptmisc.asm
+; and is basically the same method used by the system unwinder (RtlUnwind).
+;
+cProc _unwind_handler,<C>
+cBegin
+ mov ecx, dword ptr [esp+4]
+ test dword ptr [ecx.exception_flags], EXCEPTION_UNWIND_CONTEXT
+ mov eax, DISPOSITION_CONTINUE_SEARCH
+ jz short _uh_return
+
+ ; We collide in a _local_unwind. We set the dispatched to the
+ ; establisher just before the local handler so we can unwind
+ ; any future local handlers.
+
+ mov eax, [esp+8] ; Our establisher is the one
+ ; in front of the local one
+
+ mov edx, [esp+16]
+ mov [edx], eax ; set dispatcher to local_unwind2
+
+ mov eax, DISPOSITION_COLLIDED_UNWIND
+_uh_return:
+cEnd
+
+;/* _LOCAL_UNWIND2 - run all termination handlers listed in the scope table
+; * associated with the given registration record, from the current lexical
+; * level through enclosing levels up to, but not including the given 'stop'
+; * level.
+; */
+;void _local_unwind2(PEXCEPTION_REGISTRATION xr, int stop)
+;{
+; int ix;
+;
+; for(ix=xr->trylevel; ix!=-1 && ix!=stop; ix=xr->xscope[i].enclosing_level){
+; /* NULL indicates that this entry is for a termination handler */
+; if(xr->xscope[i].filter==NULL){
+; /* NB: call to the termination handler may trash callee save regs */
+; (*xr->xscope[i].specific_handler)();
+; }
+; }
+; xr->trylevel=stop;
+;}
+;/* NOTE: frame (ebp) is setup by caller of __local_unwind2 */
+cProc _local_unwind2,<C,PUBLIC>
+cBegin
+ push ebx
+ push esi
+ push edi ;call to the handler may trash, so we must save it
+
+ mov eax, [esp+16] ; (eax) = PEXCEPTION_REGISTRATION
+
+ ;link in a handler to guard our unwind
+ push eax
+ push TRYLEVEL_INVALID
+ push OFFSET FLAT:__unwind_handler
+ push fs:__except_list
+ mov fs:__except_list, esp
+
+_lu_top:
+ mov eax, [esp+32] ; (eax) = PEXCEPTION_REGISTRATION
+ mov ebx, [eax.scopetable]
+ mov esi, [eax.trylevel]
+
+ cmp esi, -1 ; REVIEW: do we need this extra check?
+ je short _lu_done
+ cmp esi, [esp+36]
+ je short _lu_done
+
+ lea esi, [esi+esi*2] ; esi*= 3
+
+ mov ecx, [(ebx+esi*4).enclosing_level]
+ mov [esp+8], ecx ; save enclosing level
+ mov [eax.trylevel], ecx
+
+ cmp dword ptr [(ebx+esi*4).filter], 0
+ jnz short _lu_continue
+
+ call [(ebx+esi*4).specific_handler]
+
+_lu_continue:
+ jmp short _lu_top
+
+_lu_done:
+ pop fs:__except_list
+ add esp, 4*3 ; cleanup stack
+
+ pop edi ; restore c-runtime registers
+ pop esi
+ pop ebx
+cEnd
+
+;/* _ABNORMAL_TERMINATION - return TRUE if __finally clause entered via
+; * _local_unwind2.
+; */
+;BOOLEAN _abnormal_termination(void);
+cProc _abnormal_termination,<C,PUBLIC>
+cBegin
+ xor eax, eax ; assume FALSE
+
+ mov ecx, fs:__except_list
+ cmp [ecx.handler], offset FLAT:__unwind_handler
+ jne short _at_done ; UnwindHandler first?
+
+ mov edx, [ecx+12] ; establisher of local_unwind2
+ mov edx, [edx.trylevel] ; is trylevel the same as the
+ cmp [ecx+8], edx ; local_unwind level?
+ jne short _at_done ; no - then FALSE
+
+ mov eax, 1 ; currently in _abnormal_termination
+_at_done:
+cEnd
+
+
+EndCODE
+END
diff --git a/private/crt32/misc/i386/exsup2.asm b/private/crt32/misc/i386/exsup2.asm
new file mode 100644
index 000000000..ead56f5af
--- /dev/null
+++ b/private/crt32/misc/i386/exsup2.asm
@@ -0,0 +1,271 @@
+;***
+;exsup2.asm
+;
+; Copyright (c) 1994 Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Exception handling for i386. This is just the C8.0 version of
+; the language-specific exception handler. The C9.0 version is
+; found in exsup3.asm, and the routines common to both C8 and C9
+; are found in exsup.asm.
+;
+;Notes:
+;
+;Revision History:
+; 01-10-94 PML Created with __except_handler2 from exsup.asm
+;
+;*******************************************************************************
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+;Define small32 and flat32 since these are not defined in the NT build process
+small32 equ 1
+flat32 equ 1
+
+ifdef _WIN32_
+_WIN32_OR_POSIX_ equ 1
+endif
+ifdef _POSIX_
+_WIN32_OR_POSIX_ equ 1
+endif
+
+.xlist
+include pversion.inc
+?DFDATA = 1
+?NODATA = 1
+include cmacros.mas
+include exsup.inc
+.list
+
+;REVIEW: can we get rid of _global_unwind2, and just use
+; the C runtimes version, _global_unwind?
+
+extrn __global_unwind2:near
+extrn __local_unwind2:near
+
+;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION;
+;struct _EXCEPTION_REGISTRATION{
+; struct _EXCEPTION_REGISTRATION *prev;
+; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
+; struct scopetable_entry *scopetable;
+; int trylevel;
+; int _ebp;
+; PEXCEPTION_POINTERS xpointers;
+;};
+_C8_EXCEPTION_REGISTRATION struc ; C8.0 version
+ dd ? ; prev (common)
+ dd ? ; handler (common)
+;private:
+ scopetable dd ?
+ trylevel dd ?
+ _ebp dd ?
+ xpointers dd ?
+_C8_EXCEPTION_REGISTRATION ends
+
+;#define EXCEPTION_MAXIMUM_PARAMETERS 4
+;typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
+;typedef EXCEPTION_RECORD *PEXCEPTION_RECORD;
+;struct _EXCEPTION_RECORD{
+; NTSTATUS ExceptionCode;
+; ULONG ExceptionFlags;
+; struct _EXCEPTION_RECORD *ExceptionRecord;
+; PVOID ExceptionAddress;
+; ULONG NumberParameters;
+; ULONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+;};
+_EXCEPTION_RECORD struc
+ exception_number dd ?
+ exception_flags dd ?
+ exception_record dd ?
+ exception_address dd ?
+ number_parameters dd ?
+ exception_information dd 4 dup(?)
+_EXCEPTION_RECORD ends
+SIZEOF_EXCEPTION_RECORD equ 36
+
+;/* following is the structure returned by the _exception_info() intrinsic. */
+;typedef struct _EXCEPTION_POINTERS EXCEPTION_POINTERS;
+;typedef struct EXCEPTION_POINTERS *PEXCEPTION_POINTERS;
+;struct _EXCEPTION_POINTERS{
+; PEXCEPTION_RECORD ExceptionRecord;
+; PCONTEXT Context;
+;};
+_EXCEPTION_POINTERS struc
+ ep_xrecord dd ?
+ ep_context dd ?
+_EXCEPTION_POINTERS ends
+SIZEOF_EXCEPTION_POINTERS equ 8
+
+assumes DS,DATA
+assumes FS,DATA
+
+__except_list equ 0
+
+;struct _SCOPETABLE_ENTRY{
+; int enclosing_level; /* lexical level of enclosing scope */
+; int (*filter)(PEXCEPTION_RECORD); /* NULL for a termination handler */
+; void (*specific_handler)(void); /* xcpt or termination handler */
+;};
+;struct _SCOPETABLE_ENTRY Scopetable[NUMTRYS];
+_SCOPETABLE_ENTRY struc
+ enclosing_level dd ?
+ filter dd ?
+ specific_handler dd ?
+_SCOPETABLE_ENTRY ends
+
+BeginCODE
+if @Version LT 600
+ifdef _WIN32_OR_POSIX_
+;this needs to go here to work around a masm5 bug. (emits wrong fixup)
+assumes CS,FLAT
+else
+assumes CS,CODE
+endif
+endif
+
+;/* _EXCEPT_HANDLER2 - Try to find an exception handler listed in the scope
+; * table associated with the given registration record, that wants to accept
+; * the current exception. If we find one, run it (and never return).
+; * RETURNS: (*if* it returns)
+; * DISPOSITION_DISMISS - dismiss the exception.
+; * DISPOSITION_CONTINUE_SEARCH - pass the exception up to enclosing handlers
+; */
+;int _except_handler2(
+; PEXCEPTION_RECORD exception_record,
+; PEXCEPTION_REGISTRATION registration,
+; PCONTEXT context,
+; PEXCEPTION_REGISTRATION dispatcher)
+;{
+; int ix, filter_result;
+;
+; for(ix=registration->trylevel; ix!=-1; ix=registration->xscope[ix].enclosing_level){
+; /* if filter==NULL, then this is an entry for a termination handler */
+; if(registration->xscope[ix].filter){
+; /* NB: call to the filter may trash the callee save
+; registers. (this is *not* a standard cdecl function) */
+; filter_result=(*registration->xscope[ix].filter)(xinfo);
+; if(filter_result==FILTER_DISMISS)
+; return(-1); /* dismiss */
+; if(filter_result==FILTER_ACCEPT){
+; _global_unwind2(registration);
+; _local_unwind2(registration, ix);
+; (*registration->xscope[ix].specific_handler)(void);
+; assert(UNREACHED); /*should never return from handler*/
+; }
+; assert(filter_result==FILTER_CONTINUE_SEARCH);
+; }
+; }
+; return(0); /* didnt find one */
+;}
+ db 'VC10' ;; VC/C++ 1.0/32-bit (C8.0) version
+ db 'XC00' ;; so debugger can recognize this proc (cuda:3936)
+cProc _except_handler2,<C,PUBLIC>,<IBX,ISI,IDI,IBP>
+ parmDP xrecord
+ parmDP registration
+ parmDP context
+ parmDP dispatcher
+ localV xp,SIZEOF_EXCEPTION_POINTERS
+cBegin
+ ;4*4b for callee saves + 4b return address + 4b param = 24
+
+ ;DF in indeterminate state at time of exception, so clear it
+ cld
+
+ mov ebx, registration ;ebx= PEXCEPTION_REGISTRATION
+ mov eax, xrecord
+
+ test [eax.exception_flags], EXCEPTION_UNWIND_CONTEXT
+ jnz short _lh_unwinding
+
+ ;build the EXCEPTION_POINTERS locally store its address in the
+ ; registration record. this is the pointer that is returned by
+ ; the _eception_info intrinsic.
+ mov xp.ep_xrecord, eax
+ mov eax, context
+ mov xp.ep_context, eax
+ lea eax, xp
+ mov [ebx.xpointers], eax
+
+ mov esi, [ebx.trylevel] ;esi= try level
+ mov edi, [ebx.scopetable] ;edi= scope table base
+_lh_top:
+ cmp esi, -1
+ je short _lh_bagit
+ lea ecx, [esi+esi*2] ;ecx= trylevel*3
+ cmp dword ptr [(edi+ecx*4).filter], 0
+ je short _lh_continue ;term handler, so keep looking
+
+ ;filter may trash *all* registers, so save ebp and scopetable offset
+ push esi
+ push ebp
+
+ mov ebp, [ebx._ebp]
+ call [(edi+ecx*4).filter] ;call the filter
+
+ pop ebp
+ pop esi
+ ;ebx may have been trashed by the filter, so we must reload
+ mov ebx, registration
+
+ ; Accept <0, 0, >0 instead of just -1, 0, +1
+ or eax, eax
+ jz short _lh_continue
+ js short _lh_dismiss
+ ;assert(eax==FILTER_ACCEPT)
+
+ ;reload xscope base, cuz it was trashed by the filter call
+ mov edi, [ebx.scopetable]
+ ;load handler address before we loose components of address mode
+ push ebx ;registration*
+ call __global_unwind2 ;run term handlers
+ add esp, 4
+
+ ;setup ebp for the local unwinder and the specific handler
+ mov ebp, [ebx._ebp]
+
+ ;the stop try level == accepting except level
+ push esi ;stop try level
+ push ebx ;registration*
+ call __local_unwind2
+ add esp, 8
+
+ lea ecx, [esi+esi*2] ;ecx=trylevel*3
+; set the current trylevel to our enclosing level immediately
+; before giving control to the handler. it is the enclosing
+; level, if any, that guards the handler.
+ mov eax, [(edi+ecx*4).enclosing_level]
+ mov [ebx.trylevel], eax
+ call [(edi+ecx*4).specific_handler] ;call the except handler
+ ;assert(0) ;(NB! should not return)
+
+_lh_continue:
+ ;reload the scope table base, possibly trashed by call to filter
+ mov edi, [ebx.scopetable]
+ lea ecx, [esi+esi*2]
+ mov esi, [edi+ecx*4+0] ;load the enclosing trylevel
+ jmp short _lh_top
+
+_lh_dismiss:
+ mov eax, DISPOSITION_DISMISS ;dismiss the exception
+ jmp short _lh_return
+
+_lh_bagit:
+ mov eax, DISPOSITION_CONTINUE_SEARCH
+ jmp short _lh_return
+
+_lh_unwinding:
+ push ebp
+ mov ebp, [ebx._ebp]
+ push -1
+ push ebx
+ call __local_unwind2
+ add esp, 8
+ pop ebp
+ ;the return value is not really relevent in an unwind context
+ mov eax, DISPOSITION_CONTINUE_SEARCH
+
+_lh_return:
+cEnd
+
+EndCODE
+END
diff --git a/private/crt32/misc/i386/exsup3.asm b/private/crt32/misc/i386/exsup3.asm
new file mode 100644
index 000000000..ff8a91dfa
--- /dev/null
+++ b/private/crt32/misc/i386/exsup3.asm
@@ -0,0 +1,290 @@
+;***
+;exsup3.asm
+;
+; Copyright (c) 1994 Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Exception handling for i386. This is just the C9.0 version of
+; the language-specific exception handler. The C8.0 version is
+; found in exsup2.asm, and the routines common to both C8 and C9
+; are found in exsup.asm.
+;
+;Notes:
+;
+;Revision History:
+; 01-10-94 PML Create VC/C++ 2.0 (C9.0) version from C8.0 original
+;
+;*******************************************************************************
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+;Define small32 and flat32 since these are not defined in the NT build process
+small32 equ 1
+flat32 equ 1
+
+ifdef _WIN32_
+_WIN32_OR_POSIX_ equ 1
+endif
+ifdef _POSIX_
+_WIN32_OR_POSIX_ equ 1
+endif
+
+.xlist
+include pversion.inc
+?DFDATA = 1
+?NODATA = 1
+include cmacros.mas
+include exsup.inc
+.list
+
+;REVIEW: can we get rid of _global_unwind2, and just use
+; the C runtimes version, _global_unwind?
+
+extrn __global_unwind2:near
+extrn __local_unwind2:near
+
+;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION;
+;struct _EXCEPTION_REGISTRATION{
+;/* _esp, xpointers at negative offset */
+; int _esp;
+; PEXCEPTION_POINTERS xpointers;
+; struct _EXCEPTION_REGISTRATION *prev;
+; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
+; struct scopetable_entry *scopetable;
+; int trylevel;
+;};
+;private (at negative offsets from node ptr)
+ _esp = -8
+ xpointers = -4
+_C9_EXCEPTION_REGISTRATION struc ; C9.0 version
+;public:
+ dd ? ; prev (common)
+ dd ? ; handler (common)
+;private:
+ scopetable dd ?
+ trylevel dd ?
+_C9_EXCEPTION_REGISTRATION ends
+FRAME_EBP_OFFSET equ 16
+
+;#define EXCEPTION_MAXIMUM_PARAMETERS 4
+;typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
+;typedef EXCEPTION_RECORD *PEXCEPTION_RECORD;
+;struct _EXCEPTION_RECORD{
+; NTSTATUS ExceptionCode;
+; ULONG ExceptionFlags;
+; struct _EXCEPTION_RECORD *ExceptionRecord;
+; PVOID ExceptionAddress;
+; ULONG NumberParameters;
+; ULONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+;};
+_EXCEPTION_RECORD struc
+ exception_number dd ?
+ exception_flags dd ?
+ exception_record dd ?
+ exception_address dd ?
+ number_parameters dd ?
+ exception_information dd 4 dup(?)
+_EXCEPTION_RECORD ends
+SIZEOF_EXCEPTION_RECORD equ 36
+
+;/* following is the structure returned by the _exception_info() intrinsic. */
+;typedef struct _EXCEPTION_POINTERS EXCEPTION_POINTERS;
+;typedef struct EXCEPTION_POINTERS *PEXCEPTION_POINTERS;
+;struct _EXCEPTION_POINTERS{
+; PEXCEPTION_RECORD ExceptionRecord;
+; PCONTEXT Context;
+;};
+_EXCEPTION_POINTERS struc
+ ep_xrecord dd ?
+ ep_context dd ?
+_EXCEPTION_POINTERS ends
+SIZEOF_EXCEPTION_POINTERS equ 8
+
+assumes DS,DATA
+assumes FS,DATA
+
+__except_list equ 0
+
+;struct _SCOPETABLE_ENTRY{
+; int enclosing_level; /* lexical level of enclosing scope */
+; int (*filter)(PEXCEPTION_RECORD); /* NULL for a termination handler */
+; void (*specific_handler)(void); /* xcpt or termination handler */
+;};
+;struct _SCOPETABLE_ENTRY Scopetable[NUMTRYS];
+_SCOPETABLE_ENTRY struc
+ enclosing_level dd ?
+ filter dd ?
+ specific_handler dd ?
+_SCOPETABLE_ENTRY ends
+
+BeginCODE
+if @Version LT 600
+ifdef _WIN32_OR_POSIX_
+;this needs to go here to work around a masm5 bug. (emits wrong fixup)
+assumes CS,FLAT
+else
+assumes CS,CODE
+endif
+endif
+
+;/* _EXCEPT_HANDLER3 - Try to find an exception handler listed in the scope
+; * table associated with the given registration record, that wants to accept
+; * the current exception. If we find one, run it (and never return).
+; * RETURNS: (*if* it returns)
+; * DISPOSITION_DISMISS - dismiss the exception.
+; * DISPOSITION_CONTINUE_SEARCH - pass the exception up to enclosing handlers
+; */
+;int _except_handler3(
+; PEXCEPTION_RECORD exception_record,
+; PEXCEPTION_REGISTRATION registration,
+; PCONTEXT context,
+; PEXCEPTION_REGISTRATION dispatcher)
+;{
+; int ix, filter_result;
+;
+; for(ix=registration->trylevel; ix!=-1; ix=registration->xscope[ix].enclosing_level){
+; /* if filter==NULL, then this is an entry for a termination handler */
+; if(registration->xscope[ix].filter){
+; /* NB: call to the filter may trash the callee save
+; registers. (this is *not* a standard cdecl function) */
+; filter_result=(*registration->xscope[ix].filter)(xinfo);
+; if(filter_result==FILTER_DISMISS)
+; return(-1); /* dismiss */
+; if(filter_result==FILTER_ACCEPT){
+; _global_unwind2(registration);
+; _local_unwind2(registration, ix);
+; (*registration->xscope[ix].specific_handler)(void);
+; assert(UNREACHED); /*should never return from handler*/
+; }
+; assert(filter_result==FILTER_CONTINUE_SEARCH);
+; }
+; }
+; return(0); /* didnt find one */
+;}
+ db 'VC20' ;; VC/C++ 2.0/32-bit (C9.0) version
+ db 'XC00' ;; so debugger can recognize this proc (cuda:3936)
+cProc _except_handler3,<C,PUBLIC>,<IBX,ISI,IDI,IBP>
+ parmDP xrecord
+ parmDP registration
+ parmDP context
+ parmDP dispatcher
+ localV xp,SIZEOF_EXCEPTION_POINTERS
+cBegin
+ ;4*4b for callee saves + 4b return address + 4b param = 24
+
+ ;DF in indeterminate state at time of exception, so clear it
+ cld
+
+ mov ebx, registration ;ebx= PEXCEPTION_REGISTRATION
+ mov eax, xrecord
+
+ test [eax.exception_flags], EXCEPTION_UNWIND_CONTEXT
+ jnz short _lh_unwinding
+
+ ;build the EXCEPTION_POINTERS locally store its address in the
+ ; registration record. this is the pointer that is returned by
+ ; the _eception_info intrinsic.
+ mov xp.ep_xrecord, eax
+ mov eax, context
+ mov xp.ep_context, eax
+ lea eax, xp
+ mov [ebx.xpointers], eax
+
+ mov esi, [ebx.trylevel] ;esi= try level
+ mov edi, [ebx.scopetable] ;edi= scope table base
+_lh_top:
+ cmp esi, -1
+ je short _lh_bagit
+ lea ecx, [esi+esi*2] ;ecx= trylevel*3
+ cmp dword ptr [(edi+ecx*4).filter], 0
+ je short _lh_continue ;term handler, so keep looking
+
+ ;filter may trash *all* registers, so save ebp and scopetable offset
+ push esi
+ push ebp
+
+ lea ebp, FRAME_EBP_OFFSET[ebx]
+ call [(edi+ecx*4).filter] ;call the filter
+
+ pop ebp
+ pop esi
+ ;ebx may have been trashed by the filter, so we must reload
+ mov ebx, registration
+
+ ; Accept <0, 0, >0 instead of just -1, 0, +1
+ or eax, eax
+ jz short _lh_continue
+ js short _lh_dismiss
+ ;assert(eax==FILTER_ACCEPT)
+
+ ;reload xscope base, cuz it was trashed by the filter call
+ mov edi, [ebx.scopetable]
+ ;load handler address before we loose components of address mode
+ push ebx ;registration*
+ call __global_unwind2 ;run term handlers
+ add esp, 4
+
+ ;setup ebp for the local unwinder and the specific handler
+ lea ebp, FRAME_EBP_OFFSET[ebx]
+
+ ;the stop try level == accepting except level
+ push esi ;stop try level
+ push ebx ;registration*
+ call __local_unwind2
+ add esp, 8
+
+ lea ecx, [esi+esi*2] ;ecx=trylevel*3
+; set the current trylevel to our enclosing level immediately
+; before giving control to the handler. it is the enclosing
+; level, if any, that guards the handler.
+ mov eax, [(edi+ecx*4).enclosing_level]
+ mov [ebx.trylevel], eax
+ call [(edi+ecx*4).specific_handler] ;call the except handler
+ ;assert(0) ;(NB! should not return)
+
+_lh_continue:
+ ;reload the scope table base, possibly trashed by call to filter
+ mov edi, [ebx.scopetable]
+ lea ecx, [esi+esi*2]
+ mov esi, [edi+ecx*4+0] ;load the enclosing trylevel
+ jmp short _lh_top
+
+_lh_dismiss:
+ mov eax, DISPOSITION_DISMISS ;dismiss the exception
+ jmp short _lh_return
+
+_lh_bagit:
+ mov eax, DISPOSITION_CONTINUE_SEARCH
+ jmp short _lh_return
+
+_lh_unwinding:
+ push ebp
+ lea ebp, FRAME_EBP_OFFSET[ebx]
+ push -1
+ push ebx
+ call __local_unwind2
+ add esp, 8
+ pop ebp
+ ;the return value is not really relevent in an unwind context
+ mov eax, DISPOSITION_CONTINUE_SEARCH
+
+_lh_return:
+cEnd
+
+public __seh_longjmp_unwind@4
+__seh_longjmp_unwind@4 proc near
+ push ebp
+ mov ecx, 8[esp]
+ mov ebp, [ecx.saved_ebp]
+ mov eax, [ecx.saved_trylevel]
+ push eax
+ mov eax, [ecx.saved_xregistration]
+ push eax
+ call __local_unwind2
+ add esp, 8
+ pop ebp
+ ret 4
+__seh_longjmp_unwind@4 endp
+
+EndCODE
+END
diff --git a/private/crt32/misc/i386/longjmp.asm b/private/crt32/misc/i386/longjmp.asm
new file mode 100644
index 000000000..ae236afff
--- /dev/null
+++ b/private/crt32/misc/i386/longjmp.asm
@@ -0,0 +1,150 @@
+;***
+;longjmp.asm
+;
+; Copyright (C) 1994 Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Contains setjmp(), longjmp() & raisex() routines;
+; split from exsup.asm for granularity purposes.
+;
+;Notes:
+;
+;Revision History:
+; 01-12-94 PML Split from setjmp.asm, added C9.0 generic EH
+; callback for unwind.
+;
+;*******************************************************************************
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+;Define small32 and flat32 since these are not defined in the NT build process
+small32 equ 1
+flat32 equ 1
+
+.xlist
+include pversion.inc
+?DFDATA = 1
+?NODATA = 1
+include cmacros.mas
+include exsup.inc
+.list
+
+BeginDATA
+
+COMM __setjmpexused:dword
+
+EndDATA
+
+assumes DS,DATA
+assumes FS,DATA
+
+BeginCODE
+if @Version LT 600
+;this needs to go here to work around a masm5 bug. (emits wrong fixup)
+assumes CS,FLAT
+endif
+
+; Following symbols defined in exsup.asm, sehsupp.c
+extrn __except_list:near
+extrn __global_unwind2:near
+extrn __local_unwind2:near
+extrn __rt_probe_read4@4:near
+
+; int
+; longjmp (
+; IN jmp_buf env
+; IN int val)
+;
+; Routine Description:
+;
+; Restore the stack and register environment saved by _setjmp.
+; Reloads callee-save registers and stack pointer to that saved in
+; the jmp_buf, then returns to the point of the _setjmp call.
+;
+; If exception unwinding is enabled, also reload the exception state
+; from the jmp_buf by doing an unwind (both global and local) back
+; to the old state. Do so by checking for a new-format (C9.0)
+; jmp_buf, and call the EH longjmp unwinder saved therein if
+; found, else assume a C8.0-vintage jmp_buf and SEH.
+;
+; Arguments:
+;
+; env - Address of the buffer holding the reload state
+; val - Value to return from the _setjmp callsite (if nonzero)
+;
+; Return Value:
+;
+; None. longjmp does not return directly, but instead continues
+; execution from the point of the _setjmp used to initialize the
+; jmp_buf. That call will return the 'val' parameter if nonzero,
+; else a one.
+
+cProc longjmp,<C,PUBLIC>
+cBegin
+ mov ebx, [esp+4] ;get jmp_buf
+
+ ;restore ebp before possible call to local_unwind-er
+ ; the call to global/local unwind will preserve this (callee save).
+ mov ebp, [ebx.saved_ebp] ;set up bp
+ifdef _NTSDK
+ cmp __setjmpexused, 0
+ je short _lj_no_unwind
+endif
+ mov esi, [ebx.saved_xregistration]
+ cmp esi, dword ptr fs:__except_list
+ je short _lj_local_unwind
+
+ push esi
+ call __global_unwind2
+ add esp,4
+
+_lj_local_unwind:
+ cmp esi, 0
+ je short _lj_no_unwind
+
+ ; Check if called with old or new format jmp_buf. Look for the
+ ; version cookie that's only present in the new format.
+ lea eax, [ebx.version_cookie]
+ push eax
+ call __rt_probe_read4@4
+ or eax, eax
+ jz short _lj_old_unwind
+ mov eax, [ebx.version_cookie]
+ cmp eax, JMPBUF_COOKIE
+ jnz short _lj_old_unwind
+
+ ; Called with a new-format jmp_buf. Call unwind function supplied
+ ; to the jmp_buf at setjmp time.
+ mov eax, [ebx.unwind_func]
+ or eax, eax
+ jz short _lj_no_unwind ;no local unwind necessary
+ push ebx
+ call eax
+ jmp short _lj_no_unwind
+
+ ; Called with an old-format jmp_buf. Duplicate old longjmp behavior,
+ ; assuming there's a C8.0 SEH node at top.
+_lj_old_unwind:
+ mov eax, [ebx.saved_trylevel]
+ push eax
+ push esi
+ call __local_unwind2
+ add esp, 8
+
+_lj_no_unwind:
+ mov edx, ebx
+ mov ebx, [edx.saved_ebx] ;recover registers...
+ mov edi, [edx.saved_edi]
+ mov esi, [edx.saved_esi]
+
+ mov eax, [esp+8] ;load the return value
+ cmp eax, 1 ;make sure it's not 0
+ adc eax, 0
+
+ mov esp, [edx.saved_esp] ;here, sp gets scorched
+ add esp, 4 ;punt the (old) return address
+ jmp [edx.saved_return] ;return
+cEnd
+
+EndCODE
+END
diff --git a/private/crt32/misc/i386/sehsupp.c b/private/crt32/misc/i386/sehsupp.c
new file mode 100644
index 000000000..1dbce51bb
--- /dev/null
+++ b/private/crt32/misc/i386/sehsupp.c
@@ -0,0 +1,59 @@
+/***
+*sehsupp.c - helper functions for Structured Exception Handling support
+*
+* Copyright (C) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains _rt_probe_read. Helper for the SEH runtime support
+* routines (longjmp in particular). Much of the SEH code is written
+* in asm, so these routines are available when probing memory in ways
+* that must be guarded with __try/__except in case of access violation.
+*
+*Revision History:
+* 12-05-93 PML Module created.
+* 12-22-93 GJF Made #define WIN32_LEAN_AND_MEAN conditional.
+* 01-12-94 PML Rewritten - still need helpers, just different ones
+*
+*******************************************************************************/
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+
+#include <windows.h>
+
+/***
+*BOOL __stdcall _rt_probe_read4 - Check if a DWORD is readable
+*
+*Purpose:
+* Internal support function called by longjmp. Check if a DWORD is
+* readable under a __try/__except.
+*
+*Entry:
+* DWORD * p - Pointer to DWORD to be probed
+*
+*Exit:
+* Success: TRUE - Able to read
+* Failure: FALSE - Access violation while reading
+*
+******************************************************************************/
+
+BOOL __stdcall _rt_probe_read4(
+ DWORD * ptr)
+{
+ BOOL readable;
+
+ __try
+ {
+ *(volatile DWORD *)ptr;
+ readable = TRUE;
+ }
+ __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
+ ? EXCEPTION_EXECUTE_HANDLER
+ : EXCEPTION_CONTINUE_SEARCH)
+ {
+ readable = FALSE;
+ }
+
+ return readable;
+}
diff --git a/private/crt32/misc/i386/setjmp.asm b/private/crt32/misc/i386/setjmp.asm
new file mode 100644
index 000000000..f4015572e
--- /dev/null
+++ b/private/crt32/misc/i386/setjmp.asm
@@ -0,0 +1,151 @@
+;***
+;setjmp.asm
+;
+; Copyright (C) 1993 - 1994 Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Contains setjmp() & raisex() routines;
+; split from exsup.asm for granularity purposes.
+;
+;Notes:
+;
+;Revision History:
+; 04-13-93 JWM Module created.
+; 10-14-93 GJF Merged in NT verson.
+; 01-12-94 PML Added C9.0 generic EH callback for unwind. Split
+; into setjmp.asm, setjmp3.asm, and longjmp.asm.
+; 02-10-94 GJF -1 is the end-of-exception-handler chain marker, not
+; 0.
+;
+;*******************************************************************************
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+;Define small32 and flat32 since these are not defined in the NT build process
+small32 equ 1
+flat32 equ 1
+
+.xlist
+include pversion.inc
+?DFDATA = 1
+?NODATA = 1
+include cmacros.mas
+include exsup.inc
+.list
+
+assumes DS,DATA
+assumes FS,DATA
+
+BeginCODE
+if @Version LT 600
+;this needs to go here to work around a masm5 bug. (emits wrong fixup)
+assumes CS,FLAT
+endif
+
+; Following symbol defined in exsup.asm
+extrn __except_list:near
+
+; int
+; _setjmp (
+; OUT jmp_buf env)
+;
+; Routine Description:
+;
+; (Old) implementation of setjmp intrinsic. Saves the current
+; nonvolatile register state in the specified jump buffer and returns
+; a function value of zero.
+;
+; Saves the callee-save registers, stack pointer and return address.
+; Also saves the exception registration list head.
+;
+; This code is only present for old apps that link to the DLL runtimes,
+; or old object files compiles with C8.0. It intentionally duplicates
+; the old setjmp bugs, blindly assuming that the topmost EH node is a
+; C8.0 SEH node.
+;
+; Arguments:
+;
+; env - Address of the buffer for storing the state information
+;
+; Return Value:
+;
+; A value of zero is returned.
+
+public __setjmp
+__setjmp PROC NEAR
+ mov edx, [esp+4]
+ mov [edx.saved_ebp], ebp ; old bp and the rest
+ mov [edx.saved_ebx], ebx
+ mov [edx.saved_edi], edi
+ mov [edx.saved_esi], esi
+ mov [edx.saved_esp], esp
+
+ mov eax, [esp] ; return address
+ mov [edx.saved_return], eax
+
+ mov eax, dword ptr fs:__except_list
+ mov [edx.saved_xregistration], eax
+
+ cmp eax, -1 ; -1 means no higher-level handler
+ jnz short _sj_save_trylevel
+ mov dword ptr [edx.saved_trylevel], -1 ;something invalid
+ jmp short _sj_done
+
+_sj_save_trylevel:
+ mov eax, [eax + C8_TRYLEVEL]
+ mov [edx.saved_trylevel], eax
+
+_sj_done:
+ sub eax, eax
+ ret
+__setjmp ENDP
+
+; void
+; raisex (
+; IN PEXCEPTION_RECORD pxr)
+;
+; Routine Description:
+;
+; Unknown. This seems to duplicate the RaiseException API (sort of),
+; but I'm not sure what it's doing here. It's not documented, but
+; it's in the reserved ANSI namespace. Here it stays, in case someone
+; really counts on it.
+;
+; Arguments:
+;
+; pxr - Pointer to EXCEPTION_RECORD buffer
+;
+; Return Value:
+;
+; None.
+
+cProc raisex,<C,PUBLIC>
+ parmDP pxr
+cBegin
+ pushfd
+ pushad
+
+ mov esi, dword ptr pxr
+ mov ebx, dword ptr fs:__except_list
+_r_top:
+ or ebx, ebx
+ je short _r_error
+ push ebx ;pass address of the registration record
+ push esi ;pass the exception record
+ call [ebx.handler] ;execute language handler for this proc
+ add esp, 8
+ cmp eax, DISPOSITION_DISMISS
+ je short _r_dismiss
+ cmp eax, DISPOSITION_CONTINUE_SEARCH
+ jne short _r_error
+ mov ebx, [ebx.prev]
+ jmp short _r_top
+_r_error:
+ ;assert(UNREACHED); exit(-1);
+_r_dismiss:
+ popad
+ popfd
+cEnd
+
+EndCODE
+END
diff --git a/private/crt32/misc/i386/setjmp3.asm b/private/crt32/misc/i386/setjmp3.asm
new file mode 100644
index 000000000..9c03e9a8c
--- /dev/null
+++ b/private/crt32/misc/i386/setjmp3.asm
@@ -0,0 +1,148 @@
+;***
+;setjmp3.asm
+;
+; Copyright (C) 1994 Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Contains setjmp(), longjmp() & raisex() routines;
+; split from exsup.asm for granularity purposes.
+;
+;Notes:
+;
+;Revision History:
+; 01-12-94 PML Split from setjmp.asm, added C9.0 generic EH
+; callback for unwind.
+; 02-10-94 GJF -1 is the end-of-exception-handler chain marker, not
+; 0.
+;
+;*******************************************************************************
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+;Define small32 and flat32 since these are not defined in the NT build process
+small32 equ 1
+flat32 equ 1
+
+.xlist
+include pversion.inc
+?DFDATA = 1
+?NODATA = 1
+include cmacros.mas
+include exsup.inc
+.list
+
+assumes DS,DATA
+assumes FS,DATA
+
+BeginCODE
+if @Version LT 600
+;this needs to go here to work around a masm5 bug. (emits wrong fixup)
+assumes CS,FLAT
+endif
+
+; Following symbol defined in exsup.asm
+extrn __except_list:near
+
+; int
+; _setjmp3 (
+; OUT jmp_buf env,
+; int count,
+; ...)
+;
+; Routine Description:
+;
+; (New) implementation of setjmp intrinsic. Saves the current
+; nonvolatile register state in the specified jump buffer and returns
+; a function value of zero.
+;
+; Saves the callee-save registers, stack pointer and return address.
+; Also saves the exception registration list head. If setjmp is
+; called from a function using any form of exception handling, then
+; additional data is also saved allowing some form of local unwind
+; at longjmp time to restore the proper exception handling state.
+;
+; Arguments:
+;
+; env - Address of the buffer for storing the state information
+; count - count of additional DWORDs of information. Zero if setjmp
+; not called from a function with any form of EH.
+; ... Additional data pushed by the setjmp intrinsic if called
+; from a function with any form of EH. The first DWORD is
+; a function ptr which will be called at longjmp time to do
+; the local unwind. The second DWORD is the try level to be
+; restored (if applicable). Any further data is saved in the
+; generic data array in the jmp_buf for use by the local
+; unwind function.
+;
+; Return Value:
+;
+; A value of zero is returned.
+
+public __setjmp3
+__setjmp3 PROC NEAR
+ mov edx, [esp+4]
+ mov [edx.saved_ebp], ebp ; old bp and the rest
+ mov [edx.saved_ebx], ebx
+ mov [edx.saved_edi], edi
+ mov [edx.saved_esi], esi
+ mov [edx.saved_esp], esp
+
+ mov eax, [esp] ; return address
+ mov [edx.saved_return], eax
+
+ mov dword ptr [edx.version_cookie], JMPBUF_COOKIE
+ mov dword ptr [edx.unwind_func], 0
+
+ mov eax, dword ptr fs:__except_list
+ mov [edx.saved_xregistration], eax
+
+ cmp eax, -1 ; -1 means no higher-level handler
+ jnz short _s3_get_count
+ mov dword ptr [edx.saved_trylevel], -1 ;something invalid
+ jmp short _s3_done
+
+_s3_get_count:
+ mov ecx, [esp+8] ; count of additional data
+ or ecx, ecx
+ jz short _s3_default_trylevel
+
+ mov eax, [esp+12] ; func to do local unwind at longjmp
+ mov [edx.unwind_func], eax
+ dec ecx
+ jnz _s3_save_trylevel
+
+ ; Not called from a function with any form of EH, or no trylevel
+ ; passed. Save the TryLevel from the topmost EH node anyway,
+ ; assuming a C8.0 SEH node. If we're linked to an obsolete CRTDLL
+ ; and call the old longjmp, then we'll still do the right thing.
+_s3_default_trylevel:
+ mov eax, [eax + C8_TRYLEVEL]
+ mov [edx.saved_trylevel], eax
+ jmp short _s3_done
+
+_s3_save_trylevel:
+ mov eax, [esp+16] ; try level to unwind to
+ mov [edx.saved_trylevel], eax
+ dec ecx
+ jz short _s3_done
+
+ push esi
+ push edi
+ lea esi, [esp+20+8]
+ lea edi, [edx.unwind_data]
+ cmp ecx, 6 ; save up to 6 more DWORDs in jmp_buf
+ jbe _s3_save_data
+ mov ecx, 6
+
+_s3_save_data:
+ rep movsd
+ pop edi
+ pop esi
+
+_s3_done:
+ sub eax, eax
+ ret
+__setjmp3 ENDP
+
+EndCODE
+END
diff --git a/private/crt32/misc/i386/setjmpex.asm b/private/crt32/misc/i386/setjmpex.asm
new file mode 100644
index 000000000..dfe444b7c
--- /dev/null
+++ b/private/crt32/misc/i386/setjmpex.asm
@@ -0,0 +1,55 @@
+;***
+;setjmpex.asm
+;
+; Copyright (c) 1993 Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Contains setjmpex().
+;
+;Notes:
+;
+;Revision History:
+; 10-14-93 GJF Grabbed from NT SDK tree, cleaned up a bit and this
+; header was added.
+; 01-13-94 PML Trigger off __longjmpex instead of __setjmpex, since
+; _setjmp is an intrinsic, but longjmp isn't.
+;
+;*******************************************************************************
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+;Define small32 and flat32 since these are not defined in the NT build process
+small32 equ 1
+flat32 equ 1
+
+.xlist
+include pversion.inc
+?DFDATA = 1
+?NODATA = 1
+include cmacros.mas
+.list
+
+
+extrn _longjmp:near
+
+;
+; If setjmpex is included then set __setjmpexused = 1.
+;
+
+BeginDATA
+ public __setjmpexused
+__setjmpexused dd 1
+EndDATA
+
+BeginCODE
+if @Version LT 600
+assumes CS,FLAT
+endif
+
+public __longjmpex
+__longjmpex PROC NEAR
+ jmp _longjmp
+__longjmpex ENDP
+
+EndCODE
+END
diff --git a/private/crt32/misc/initcoll.c b/private/crt32/misc/initcoll.c
new file mode 100644
index 000000000..d2e2985a7
--- /dev/null
+++ b/private/crt32/misc/initcoll.c
@@ -0,0 +1,51 @@
+/***
+*initcoll.c - contains _init_collate
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the locale-category initialization function: _init_collate().
+*
+* Each initialization function sets up locale-specific information
+* for their category, for use by functions which are affected by
+* their locale category.
+*
+* *** For internal use by setlocale() only ***
+*
+*Revision History:
+* 12-08-91 ETC Created.
+* 12-20-91 ETC Minor beautification for consistency.
+* 12-18-92 CFW Ported to Cuda tree, changed _CALLTYPE4 to _CRTAPI3.
+* 05-20-93 GJF Include windows.h, not individual win*.h files
+*
+*******************************************************************************/
+
+#ifdef _INTL
+#include <windows.h>
+#include <locale.h>
+#include <setlocal.h>
+
+/***
+*int _init_collate() - initialization for LC_COLLATE locale category.
+*
+*Purpose:
+* The LC_COLLATE category currently requires no initialization.
+*
+*Entry:
+* None.
+*
+*Exit:
+* 0 success
+* 1 fail
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI3 _init_collate (
+ void
+ )
+{
+ return 0;
+}
+#endif /* _INTL */
diff --git a/private/crt32/misc/initctyp.c b/private/crt32/misc/initctyp.c
new file mode 100644
index 000000000..02382a1b2
--- /dev/null
+++ b/private/crt32/misc/initctyp.c
@@ -0,0 +1,212 @@
+/***
+*initctyp.c - contains _init_ctype
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the locale-category initialization function: _init_ctype().
+*
+* Each initialization function sets up locale-specific information
+* for their category, for use by functions which are affected by
+* their locale category.
+*
+* *** For internal use by setlocale() only ***
+*
+*Revision History:
+* 12-08-91 ETC Created.
+* 12-20-91 ETC Updated to use new NLSAPI GetLocaleInfo.
+* 12-18-92 CFW Ported to Cuda tree, changed _CALLTYPE4 to _CRTAPI3.
+* 01-19-03 CFW Move to _NEWCTYPETABLE, remove switch.
+* 02-08-93 CFW Bug fixes under _INTL switch.
+* 05-20-93 GJF Include windows.h, not individual win*.h files
+* 06-11-93 CFW Now inithelp takes void *.
+*
+*******************************************************************************/
+
+#ifdef _INTL
+
+#include <stdlib.h>
+#include <windows.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <limits.h>
+
+#define _CTABSIZE 257 /* size of ctype tables */
+
+/***
+*int _init_ctype() - initialization for LC_CTYPE locale category.
+*
+*Purpose:
+* In non-C locales, preread ctype tables for chars and wide-chars.
+* Old tables are freed when new tables are fully established, else
+* the old tables remain intact (as if original state unaltered).
+* The leadbyte table is implemented as the high bit in ctype1.
+*
+* In the C locale, ctype tables are freed, and pointers point to
+* the static ctype table.
+*
+* Tables contain 257 entries: -1 to 256.
+* Table pointers point to entry 0 (to allow index -1).
+*
+*Entry:
+* None.
+*
+*Exit:
+* 0 success
+* 1 fail
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI3 _init_ctype (
+ void
+ )
+{
+#if defined _POSIX_
+ return 0;
+
+#else /* _POSIX_ */
+ /* non-C locale table for char's */
+ static unsigned short *ctype1 = NULL; /* keep around until next time */
+ unsigned short *newctype1; /* temp new table */
+
+ /* non-C locale table for wchar_t's */
+ static unsigned short *wctype1 = NULL; /* keep around until next time */
+ unsigned short *newwctype1; /* temp new table */
+
+ int size; // char buffer sizes
+ int wcsize; // wide char buffer sizes
+ unsigned char *cbuffer = NULL; // char working buffer
+ wchar_t *wbuffer = NULL; // wchar_t working buffer
+
+ int i; // general purpose counter
+ unsigned char *cp; // char pointer
+ wchar_t *wcp; // wide char pointer
+ CPINFO CPInfo; // struct for use with GetCPInfo
+
+ /* allocate and set up buffers before destroying old ones */
+ /* codepage will be restored by setlocale if error */
+
+ if (_lc_handle[LC_CTYPE] != _CLOCALEHANDLE)
+ {
+ if (_lc_codepage == 0)
+ { /* code page was not specified */
+ if (_getlocaleinfo(LC_INT_TYPE, MAKELCID(_lc_id[LC_CTYPE].wLanguage, SORT_DEFAULT),
+ LOCALE_IDEFAULTCODEPAGE,
+ (void *)&_lc_codepage) == -1)
+ goto error_cleanup;
+ }
+
+ /* allocate new buffers for tables */
+ newctype1 = (unsigned short *) malloc
+ (_CTABSIZE * sizeof(unsigned short));
+ newwctype1 = (unsigned short *) malloc
+ (_CTABSIZE * sizeof(unsigned short));
+ cbuffer = (unsigned char *) malloc (_CTABSIZE * sizeof(char));
+ wbuffer = (wchar_t *) malloc (_CTABSIZE * sizeof(wchar_t));
+
+ if (!newctype1 || !newwctype1 || !cbuffer || !wbuffer)
+ goto error_cleanup;
+
+ /* construct string composed of first 256 chars in sequence */
+ for (cp=cbuffer, i=0; i<_CTABSIZE-1; i++)
+ *cp++ = (unsigned char)i;
+
+ if (GetCPInfo( _lc_codepage, &CPInfo) == FALSE)
+ goto error_cleanup;
+
+ if (CPInfo.MaxCharSize > MB_LEN_MAX)
+ goto error_cleanup;
+
+ __mb_cur_max = (unsigned short) CPInfo.MaxCharSize;
+
+ /* zero out leadbytes so MBtoWC doesn't interpret as multi-byte chars */
+ if (__mb_cur_max > 1)
+ {
+ for (cp = (unsigned char *)CPInfo.LeadByte; cp[0] && cp[1]; cp += 2)
+ {
+ for (i = cp[0]; i <= cp[1]; i++)
+ cbuffer[i] = 0;
+ }
+ }
+
+ /* convert to wide character string */
+ size = (_CTABSIZE-1) * sizeof(char);
+ wcsize = (_CTABSIZE-1) * sizeof(wchar_t);
+ if (MultiByteToWideChar (_lc_codepage, 0, (char *)cbuffer, size,
+ wbuffer, wcsize) == 0)
+ goto error_cleanup;
+
+ /* convert to newctype1 table */
+ if (GetStringTypeW (CT_CTYPE1, wbuffer, _CTABSIZE-1, newctype1+1)
+ == FALSE)
+ goto error_cleanup;
+ *newctype1 = 0; /* entry for EOF */
+
+ /* construct wide char string composed of first 256 chars in sequence */
+ for (wcp=wbuffer, i=0; i<_CTABSIZE-1; i++)
+ *wcp++ = (wchar_t)i;
+
+ /* convert to newctype1 table */
+ if (GetStringTypeW (CT_CTYPE1, wbuffer, _CTABSIZE-1, newwctype1+1)
+ == FALSE)
+ goto error_cleanup;
+ *newwctype1 = 0; /* entry for EOF */
+
+ /* ignore DefaultChar */
+
+ /* mark lead-byte entries in newctype1 table */
+ if (__mb_cur_max > 1)
+ {
+ for (cp = (unsigned char *)CPInfo.LeadByte; cp[0] && cp[1]; cp += 2)
+ {
+ for (i = cp[0]; i <= cp[1]; i++)
+ newctype1[i+1] = _LEADBYTE;
+ }
+ }
+
+ /* set pointers to point to entry 0 of tables */
+ _pctype = newctype1 + 1;
+ _pwctype = newwctype1 + 1;
+
+ /* free old tables */
+ if (ctype1)
+ free (ctype1);
+ ctype1 = newctype1;
+
+ if (wctype1)
+ free (wctype1);
+ wctype1 = newwctype1;
+
+ /* cleanup and return success */
+ free (cbuffer);
+ free (wbuffer);
+ return 0;
+
+error_cleanup:
+ free (newctype1);
+ free (newwctype1);
+ free (cbuffer);
+ free (wbuffer);
+ return 1;
+
+ } else {
+
+ /* set pointers to static C-locale table */
+ _pctype = _ctype + 1;
+ _pwctype = _ctype + 1;
+
+ /* free dynamic locale-specific tables */
+ free (ctype1);
+ free (wctype1);
+ ctype1 = NULL;
+ wctype1 = NULL;
+
+ return 0;
+ }
+#endif /* _POSIX_ */
+}
+#endif /* _INTL */
diff --git a/private/crt32/misc/inithelp.c b/private/crt32/misc/inithelp.c
new file mode 100644
index 000000000..a372b595a
--- /dev/null
+++ b/private/crt32/misc/inithelp.c
@@ -0,0 +1,143 @@
+/***
+*inithelp.c - Contains the _getlocaleinfo helper routine
+*
+* Copyright (c) 1992-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the _getlocaleinfo helper routine.
+*
+*Revision History:
+* 12-28-92 CFW Module created, _getlocaleinfo ported to Cuda tree.
+* 12-29-92 CFW Update for new GetLocaleInfoW, add LC_*_TYPE handling.
+* 01-25-93 KRS Change category argument to LCID.
+* 02-02-93 CFW Optimized INT case, bug fix in STR case.
+* 02-08-93 CFW Optimized GetQualifiedLocale call, cast to remove warnings.
+* 04-22-93 CFW Fixed cast bug.
+* 06-11-93 CFW Now inithelp takes void *, use wcstod().
+*
+*******************************************************************************/
+
+#ifdef _INTL
+
+#include <stdlib.h>
+#include <cruntime.h>
+#include <locale.h>
+#include <setlocal.h>
+
+/***
+*_getlocaleinfo - return locale data
+*
+*Purpose:
+* Return locale data appropriate for the setlocale init functions.
+* In particular, wide locale strings are converted to char strings
+* or numeric depending on the value of the first parameter.
+*
+* Memory is allocated for the char version of the data, and the
+* calling function's pointer is set to it. This pointer should later
+* be used to free the data. The wide-char data is fetched using
+* GetLocaleInfo and converted to multibyte using WideCharToMultiByte.
+*
+* *** For internal use by the _init_* functions only ***
+*
+* *** Future optimization ***
+* When converting a large number of wide-strings to multibyte, do
+* not query the size of the result, but convert them one after
+* another into a large character buffer. The entire buffer can
+* also be freed with one pointer.
+*
+*Entry:
+* int lc_type - LC_STR_TYPE for string data, LC_INT_TYPE for numeric data
+* LCID localehandle - LCID based on category and lang or ctry of _lc_id
+ LCTYPE fieldtype - int or string value
+*
+*Exit:
+* void *address - pointer to pointer to storage
+* 0 success
+* -1 failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#if NO_ERROR == -1
+#error Need to use another error return code in _getlocaleinfo
+#endif
+
+#define STR_CHAR_CNT 128
+#define INT_CHAR_CNT 4
+
+int _CRTAPI3 _getlocaleinfo (
+ int lc_type,
+ LCID localehandle,
+ LCTYPE fieldtype,
+ void *address
+ )
+{
+#if defined _POSIX_
+ return -1;
+#else /* _POSIX_ */
+ if (lc_type == LC_STR_TYPE)
+ {
+ char **straddress = (char **)address;
+
+ static wchar_t staticwcbuffer[STR_CHAR_CNT];
+ wchar_t *wcbuffer = staticwcbuffer;
+ int bufferused = 0; /* 1 indicates buffer points to malloc'ed memory */
+ int buffersize = STR_CHAR_CNT * sizeof(wchar_t);
+ int outsize;
+
+ if (GetLocaleInfoW (localehandle, fieldtype, wcbuffer, buffersize) == 0)
+ {
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ goto error;
+ /* buffersize too small, get required size and malloc new buffer */
+ if ((buffersize = GetLocaleInfoW (localehandle, fieldtype, NULL, 0))
+ == 0)
+ goto error;
+ if ((wcbuffer = (wchar_t *) malloc (buffersize)) == NULL)
+ goto error;
+ bufferused = 1;
+ if (GetLocaleInfoW (localehandle, fieldtype, wcbuffer, buffersize) == 0)
+ goto error;
+ }
+
+ if ((outsize = WideCharToMultiByte (_lc_codepage, 0, wcbuffer, -1,
+ NULL, 0, NULL, NULL)) == 0)
+ goto error;
+
+ if ((*straddress = (char *) malloc (outsize)) == NULL)
+ goto error;
+
+ if (WideCharToMultiByte (_lc_codepage, 0, wcbuffer, -1,
+ *straddress, outsize, NULL, NULL) == 0)
+ goto error;
+
+ if (bufferused)
+ free (wcbuffer);
+
+ return 0;
+
+error:
+ if (bufferused)
+ free (wcbuffer);
+ return -1;
+
+ } else if (lc_type == LC_INT_TYPE)
+ {
+ char *charaddress = (char *)address;
+ wchar_t wcbuffer[INT_CHAR_CNT];
+
+ if (GetLocaleInfoW (localehandle, fieldtype, (LPWSTR)wcbuffer, INT_CHAR_CNT) == 0)
+ return -1;
+
+ /* GetLocaleInfoW returns integer in wcstr format */
+
+ *(char *)charaddress = (char)wcstol(wcbuffer, NULL, 10);
+
+ return 0;
+ }
+ return -1;
+#endif /* _POSIX_ */
+}
+
+#endif /*_INTL*/
diff --git a/private/crt32/misc/initmon.c b/private/crt32/misc/initmon.c
new file mode 100644
index 000000000..c2b9cd3fe
--- /dev/null
+++ b/private/crt32/misc/initmon.c
@@ -0,0 +1,191 @@
+/***
+*initmon.c - contains _init_monetary
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the locale-category initialization function: _init_monetary().
+*
+* Each initialization function sets up locale-specific information
+* for their category, for use by functions which are affected by
+* their locale category.
+*
+* *** For internal use by setlocale() only ***
+*
+*Revision History:
+* 12-08-91 ETC Created.
+* 12-20-91 ETC Updated to use new NLSAPI GetLocaleInfo.
+* 12-18-92 CFW Ported to Cuda tree, changed _CALLTYPE4 to _CRTAPI3.
+* 12-29-92 CFW Updated to use new _getlocaleinfo wrapper function.
+* 01-25-93 KRS Changed _getlocaleinfo interface again.
+* 02-08-93 CFW Added _lconv_static_*.
+* 02-17-93 CFW Removed debugging print statement.
+* 05-20-93 GJF Include windows.h, not individual win*.h files
+* 06-11-93 CFW Now inithelp takes void *.
+*
+*******************************************************************************/
+
+#ifdef _INTL
+
+#include <stdlib.h>
+#include <windows.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <malloc.h>
+#include <limits.h>
+
+static int _CRTAPI3 _get_lc_lconv(struct lconv *l);
+static void _CRTAPI3 _free_lc_lconv(struct lconv *l);
+
+/* Pointer to current lconv */
+extern struct lconv *_lconv;
+
+/* C locale lconv structure */
+extern struct lconv _lconv_c;
+
+/* Pointer to non-C locale lconv */
+static struct lconv *_lconv_intl = NULL;
+
+/*
+ * Note that _lconv_c is used when the monetary category is in the C locale
+ * but the numeric category may not necessarily be in the C locale.
+ */
+
+
+/***
+*int _init_monetary() - initialization for LC_MONETARY locale category.
+*
+*Purpose:
+* In non-C locales, read the localized monetary strings into
+* _lconv_intl, and also copy the numeric strings from _lconv into
+* _lconv_intl. Set _lconv to point to _lconv_intl. The old
+* _lconv_intl is not freed until the new one is fully established.
+*
+* In the C locale, the monetary fields in lconv are filled with
+* contain C locale values. Any allocated _lconv_intl fields are freed.
+*
+* At startup, _lconv points to a static lconv structure containing
+* C locale strings. This structure is never used again if
+* _init_monetary is called.
+*
+*Entry:
+* None.
+*
+*Exit:
+* 0 success
+* 1 fail
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI3 _init_monetary (
+ void
+ )
+{
+ struct lconv *lc;
+
+ if (_lc_handle[LC_MONETARY] != _CLOCALEHANDLE) {
+
+ /* Allocate structure filled with NULL pointers */
+ if ((lc = (struct lconv *)
+ calloc (1, sizeof(struct lconv))) == NULL)
+ return 1;
+
+ if (_get_lc_lconv (lc) == -1) {
+ _free_lc_lconv (lc);
+ free ((void *)lc);
+ return 1;
+ }
+
+ /* Copy numeric locale fields */
+ lc->decimal_point = _lconv->decimal_point;
+ lc->thousands_sep = _lconv->thousands_sep;
+ lc->grouping = _lconv->grouping;
+
+ _lconv = lc; /* point to new one */
+ _free_lc_lconv (_lconv_intl); /* free the old one */
+ free ((void *)_lconv_intl);
+ _lconv_intl = lc;
+ return 0;
+
+ } else {
+ /*
+ * Copy numeric locale fields (not necessarily C locale)
+ * to static structure. Note that _lconv_c numeric locale
+ * fields may contain non-C locale information, but
+ * monetary locale fields always contain C locale info.
+ */
+ _lconv_c.decimal_point = _lconv->decimal_point;
+ _lconv_c.thousands_sep = _lconv->thousands_sep;
+ _lconv_c.grouping = _lconv->grouping;
+
+ _lconv = &_lconv_c; /* point to new one */
+
+ _free_lc_lconv (_lconv_intl); /* free the old one */
+ free ((void *)_lconv_intl);
+ _lconv_intl = NULL;
+ return 0;
+ }
+}
+
+/*
+ * Get the lconv fields.
+ */
+static int _CRTAPI3 _get_lc_lconv (
+ struct lconv *l
+ )
+{
+ int ret = 0;
+
+ /* Currency is country--not language--dependent. NT work-around. */
+ LCID ctryid=MAKELCID(_lc_id[LC_MONETARY].wCountry, SORT_DEFAULT);
+
+ if (l == NULL)
+ return -1;
+
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SINTLSYMBOL, (void *)&l->int_curr_symbol);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SCURRENCY, (void *)&l->currency_symbol);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SMONDECIMALSEP, (void *)&l->mon_decimal_point);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SMONTHOUSANDSEP, (void *)&l->mon_thousands_sep);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SMONGROUPING, (void *)&l->mon_grouping);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SPOSITIVESIGN, (void *)&l->positive_sign);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SNEGATIVESIGN, (void *)&l->negative_sign);
+
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IINTLCURRDIGITS, (void *)&l->int_frac_digits);
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_ICURRDIGITS, (void *)&l->frac_digits);
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IPOSSYMPRECEDES, (void *)&l->p_cs_precedes);
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IPOSSEPBYSPACE, (void *)&l->p_sep_by_space);
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_INEGSYMPRECEDES, (void *)&l->n_cs_precedes);
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_INEGSEPBYSPACE, (void *)&l->n_sep_by_space);
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IPOSSIGNPOSN, (void *)&l->p_sign_posn);
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_INEGSIGNPOSN, (void *)&l->n_sign_posn);
+
+ return ret;
+}
+
+/*
+ * Free the lconv strings.
+ * Numeric values do not need to be freed.
+ */
+static void _CRTAPI3 _free_lc_lconv (
+ struct lconv *l
+ )
+{
+ if (l == NULL)
+ return;
+
+ if (l->int_curr_symbol != _lconv_static_null)
+ {
+ free (l->int_curr_symbol);
+ free (l->currency_symbol);
+ free (l->mon_decimal_point);
+ free (l->mon_thousands_sep);
+ free (l->mon_grouping);
+ free (l->positive_sign);
+ free (l->negative_sign);
+ }
+ /* Don't need to make these pointers NULL */
+}
+
+#endif /* _INTL */
diff --git a/private/crt32/misc/initnum.c b/private/crt32/misc/initnum.c
new file mode 100644
index 000000000..dea832aad
--- /dev/null
+++ b/private/crt32/misc/initnum.c
@@ -0,0 +1,129 @@
+/***
+*initnum.c - contains _init_numeric
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the locale-category initialization function: _init_numeric().
+*
+* Each initialization function sets up locale-specific information
+* for their category, for use by functions which are affected by
+* their locale category.
+*
+* *** For internal use by setlocale() only ***
+*
+*Revision History:
+* 12-08-91 ETC Created.
+* 12-20-91 ETC Updated to use new NLSAPI GetLocaleInfo.
+* 12-18-92 CFW Ported to Cuda tree, changed _CALLTYPE4 to _CRTAPI3.
+* 12-29-92 CFW Updated to use new _getlocaleinfo wrapper function.
+* 01-25-93 KRS Change interface to _getlocaleinfo again.
+* 02-08-93 CFW Added _lconv_static_*.
+* 02-17-93 CFW Removed debugging print statement.
+* 03-17-93 CFW C locale thousands sep is "", not ",".
+* 05-20-93 GJF Include windows.h, not individual win*.h files
+* 06-11-93 CFW Now inithelp takes void *.
+*
+*******************************************************************************/
+
+#ifdef _INTL
+
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <malloc.h>
+#include <assert.h>
+#include <nlsint.h>
+
+/* Pointer to current lconv */
+extern struct lconv *_lconv;
+
+/***
+*int _init_numeric() - initialization for LC_NUMERIC locale category.
+*
+*Purpose:
+*
+*Entry:
+* None.
+*
+*Exit:
+* 0 success
+* 1 fail
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI3 _init_numeric (
+ void
+ )
+{
+ static char *decimal_point = NULL;
+ static char *thousands_sep = NULL;
+ static char *grouping = NULL;
+ int ret = 0;
+
+ /* Numeric data is country--not language--dependent. NT work-around. */
+ LCID ctryid = MAKELCID(_lc_id[LC_NUMERIC].wCountry, SORT_DEFAULT);
+
+ if (_lc_handle[LC_NUMERIC] != _CLOCALEHANDLE)
+ {
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SDECIMAL, (void *)&decimal_point);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_STHOUSAND, (void *)&thousands_sep);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SGROUPING, (void *)&grouping);
+
+ if (ret == -1)
+ {
+ free (decimal_point);
+ free (thousands_sep);
+ free (grouping);
+ decimal_point = NULL;
+ thousands_sep = NULL;
+ grouping = NULL;
+ return -1;
+ }
+
+ if (_lconv->decimal_point != _lconv_static_decimal)
+ {
+ free(_lconv->decimal_point);
+ free(_lconv->thousands_sep);
+ free(_lconv->grouping);
+ }
+
+ _lconv->decimal_point = decimal_point;
+ _lconv->thousands_sep = thousands_sep;
+ _lconv->grouping = grouping;
+
+
+#ifdef _DEBUG
+ assert (strlen(_lconv->decimal_point) == 1);
+#endif
+ /* set global decimal point character */
+ *_decimal_point = *_lconv->decimal_point;
+ _decimal_point_length = 1;
+
+ return 0;
+
+ } else {
+ free (decimal_point);
+ free (thousands_sep);
+ free (grouping);
+ decimal_point = NULL;
+ thousands_sep = NULL;
+ grouping = NULL;
+
+ // strdup them so we can free them
+ _lconv->decimal_point = _strdup(".");
+ _lconv->thousands_sep = _strdup("");
+ _lconv->grouping = strdup("");
+
+ /* set global decimal point character */
+ *_decimal_point = *_lconv->decimal_point;
+ _decimal_point_length = 1;
+
+ return 0;
+ }
+}
+#endif /* _INTL */
diff --git a/private/crt32/misc/inittime.c b/private/crt32/misc/inittime.c
new file mode 100644
index 000000000..7ce1dd8e7
--- /dev/null
+++ b/private/crt32/misc/inittime.c
@@ -0,0 +1,301 @@
+/***
+*inittime.c - contains _init_time
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the locale-category initialization function: _init_time().
+*
+* Each initialization function sets up locale-specific information
+* for their category, for use by functions which are affected by
+* their locale category.
+*
+* *** For internal use by setlocale() only ***
+*
+*Revision History:
+* 12-08-91 ETC Created.
+* 12-20-91 ETC Updated to use new NLSAPI GetLocaleInfo.
+* 12-18-92 CFW Ported to Cuda tree, changed _CALLTYPE4 to _CRTAPI3.
+* 12-29-92 CFW Updated to use new _getlocaleinfo wrapper function.
+* 01-25-93 KRS Adapted to use ctry or lang dependent data, as approp.
+* 02-08-93 CFW Casts to remove warnings.
+* 02-16-93 CFW Added support for date and time strings.
+* 03-09-93 CFW Use char* time_sep in storeTimeFmt.
+* 05-20-93 GJF Include windows.h, not individual win*.h files
+* 06-11-93 CFW Now inithelp takes void *.
+*
+*******************************************************************************/
+
+#ifdef _INTL
+
+#include <stdlib.h>
+#include <windows.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <malloc.h>
+
+static int _CRTAPI3 _get_lc_time(struct _lc_time_data *lc_time);
+static void _CRTAPI3 _free_lc_time(struct _lc_time_data *lc_time);
+
+/* Pointer to current time strings */
+extern struct _lc_time_data *_lc_time_curr;
+
+/* C locale time strings */
+extern struct _lc_time_data _lc_time_c;
+
+/* Pointer to non-C locale time strings */
+struct _lc_time_data *_lc_time_intl = NULL;
+
+int storeTimeFmt(
+ int ctryid,
+ struct _lc_time_data *lc_time
+);
+
+/***
+*int _init_time() - initialization for LC_TIME locale category.
+*
+*Purpose:
+* In non-C locales, read the localized time/date strings into
+* _lc_time_intl, and set _lc_time_curr to point to it. The old
+* _lc_time_intl is not freed until the new one is fully established.
+*
+* In the C locale, _lc_time_curr is made to point to _lc_time_c.
+* Any allocated _lc_time_intl structures are freed.
+*
+*Entry:
+* None.
+*
+*Exit:
+* 0 success
+* 1 fail
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI3 _init_time (
+ void
+ )
+{
+ /* Temporary date/time strings */
+ struct _lc_time_data *lc_time;
+
+ if (_lc_handle[LC_TIME] != _CLOCALEHANDLE)
+ {
+ /* Allocate structure filled with NULL pointers */
+ if ((lc_time = (struct _lc_time_data *)
+ calloc (1, sizeof(struct _lc_time_data))) == NULL)
+ return 1;
+
+ if (_get_lc_time (lc_time))
+ {
+ _free_lc_time (lc_time);
+ free ((void *)lc_time);
+ return 1;
+ }
+
+ _lc_time_curr = lc_time; /* point to new one */
+ _free_lc_time (_lc_time_intl); /* free the old one */
+ free ((void *)_lc_time_intl);
+ _lc_time_intl = lc_time;
+ return 0;
+
+ } else {
+ _lc_time_curr = &_lc_time_c; /* point to new one */
+ _free_lc_time (_lc_time_intl); /* free the old one */
+ free ((void *)_lc_time_intl);
+ _lc_time_intl = NULL;
+ return 0;
+ }
+}
+
+/*
+ * Get the localized time strings.
+ * Of course, this can be beautified with some loops!
+ */
+static int _CRTAPI3 _get_lc_time (
+ struct _lc_time_data *lc_time
+ )
+{
+ int ret = 0;
+
+/* Some things are language-dependent and some are country-dependent.
+ This works around an NT limitation and lets us distinguish the two. */
+
+ LCID langid = MAKELCID(_lc_id[LC_TIME].wLanguage, SORT_DEFAULT);
+ LCID ctryid = MAKELCID(_lc_id[LC_TIME].wCountry, SORT_DEFAULT);
+
+ if (lc_time == NULL)
+ return -1;
+
+/* All the text-strings are Language-dependent: */
+
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVDAYNAME1, (void *)&lc_time->wday_abbr[1]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVDAYNAME2, (void *)&lc_time->wday_abbr[2]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVDAYNAME3, (void *)&lc_time->wday_abbr[3]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVDAYNAME4, (void *)&lc_time->wday_abbr[4]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVDAYNAME5, (void *)&lc_time->wday_abbr[5]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVDAYNAME6, (void *)&lc_time->wday_abbr[6]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVDAYNAME7, (void *)&lc_time->wday_abbr[0]);
+
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SDAYNAME1, (void *)&lc_time->wday[1]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SDAYNAME2, (void *)&lc_time->wday[2]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SDAYNAME3, (void *)&lc_time->wday[3]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SDAYNAME4, (void *)&lc_time->wday[4]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SDAYNAME5, (void *)&lc_time->wday[5]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SDAYNAME6, (void *)&lc_time->wday[6]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SDAYNAME7, (void *)&lc_time->wday[0]);
+
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME1, (void *)&lc_time->month_abbr[0]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME2, (void *)&lc_time->month_abbr[1]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME3, (void *)&lc_time->month_abbr[2]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME4, (void *)&lc_time->month_abbr[3]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME5, (void *)&lc_time->month_abbr[4]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME6, (void *)&lc_time->month_abbr[5]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME7, (void *)&lc_time->month_abbr[6]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME8, (void *)&lc_time->month_abbr[7]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME9, (void *)&lc_time->month_abbr[8]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME10, (void *)&lc_time->month_abbr[9]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME11, (void *)&lc_time->month_abbr[10]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SABBREVMONTHNAME12, (void *)&lc_time->month_abbr[11]);
+
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME1, (void *)&lc_time->month[0]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME2, (void *)&lc_time->month[1]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME3, (void *)&lc_time->month[2]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME4, (void *)&lc_time->month[3]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME5, (void *)&lc_time->month[4]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME6, (void *)&lc_time->month[5]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME7, (void *)&lc_time->month[6]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME8, (void *)&lc_time->month[7]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME9, (void *)&lc_time->month[8]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME10, (void *)&lc_time->month[9]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME11, (void *)&lc_time->month[10]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_SMONTHNAME12, (void *)&lc_time->month[11]);
+
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_S1159, (void *)&lc_time->ampm[0]);
+ ret |= _getlocaleinfo(LC_STR_TYPE, langid, LOCALE_S2359, (void *)&lc_time->ampm[1]);
+
+
+/* The following relate to time format and are Country-dependent: */
+
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SSHORTDATE, (void *)&lc_time->ww_sdatefmt);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SLONGDATE, (void *)&lc_time->ww_ldatefmt);
+
+/* NLS API dropped time format strings, we have to make up our own */
+ ret |= storeTimeFmt(ctryid, lc_time);
+
+ return ret;
+}
+
+/*
+ * Free the localized time strings.
+ * Of course, this can be beautified with some loops!
+ */
+static void _CRTAPI3 _free_lc_time (
+ struct _lc_time_data *lc_time
+ )
+{
+ if (lc_time == NULL)
+ return;
+
+ free ((void *)lc_time->wday_abbr[1]);
+ free ((void *)lc_time->wday_abbr[2]);
+ free ((void *)lc_time->wday_abbr[3]);
+ free ((void *)lc_time->wday_abbr[4]);
+ free ((void *)lc_time->wday_abbr[5]);
+ free ((void *)lc_time->wday_abbr[6]);
+ free ((void *)lc_time->wday_abbr[0]);
+
+ free ((void *)lc_time->wday[1]);
+ free ((void *)lc_time->wday[2]);
+ free ((void *)lc_time->wday[3]);
+ free ((void *)lc_time->wday[4]);
+ free ((void *)lc_time->wday[5]);
+ free ((void *)lc_time->wday[6]);
+ free ((void *)lc_time->wday[0]);
+
+ free ((void *)lc_time->month_abbr[0]);
+ free ((void *)lc_time->month_abbr[1]);
+ free ((void *)lc_time->month_abbr[2]);
+ free ((void *)lc_time->month_abbr[3]);
+ free ((void *)lc_time->month_abbr[4]);
+ free ((void *)lc_time->month_abbr[5]);
+ free ((void *)lc_time->month_abbr[6]);
+ free ((void *)lc_time->month_abbr[7]);
+ free ((void *)lc_time->month_abbr[8]);
+ free ((void *)lc_time->month_abbr[9]);
+ free ((void *)lc_time->month_abbr[10]);
+ free ((void *)lc_time->month_abbr[11]);
+
+ free ((void *)lc_time->month[0]);
+ free ((void *)lc_time->month[1]);
+ free ((void *)lc_time->month[2]);
+ free ((void *)lc_time->month[3]);
+ free ((void *)lc_time->month[4]);
+ free ((void *)lc_time->month[5]);
+ free ((void *)lc_time->month[6]);
+ free ((void *)lc_time->month[7]);
+ free ((void *)lc_time->month[8]);
+ free ((void *)lc_time->month[9]);
+ free ((void *)lc_time->month[10]);
+ free ((void *)lc_time->month[11]);
+
+ free ((void *)lc_time->ampm[0]);
+ free ((void *)lc_time->ampm[1]);
+
+ free ((void *)lc_time->ww_sdatefmt);
+ free ((void *)lc_time->ww_ldatefmt);
+ free ((void *)lc_time->ww_timefmt);
+/* Don't need to make these pointers NULL */
+}
+
+
+/* NLS API dropped time format strings, we have to make up our own */
+int storeTimeFmt(
+ int ctryid,
+ struct _lc_time_data *lc_time
+)
+{
+ int ret = 0;
+ char *pfmt, *psep;
+ char *time_sep;
+ unsigned clock24 = 0;
+ unsigned leadzero = 0;
+
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_ITIME, (void *)&clock24);
+ ret |= _getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_ITLZERO, (void *)&leadzero);
+ ret |= _getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_STIME, (void *)&time_sep);
+
+ if (ret)
+ return ret;
+
+ /* 13 = 6 chars for hhmmss + up to three for each separator + NULL */
+
+ pfmt = lc_time->ww_timefmt = (char *)malloc(13);
+
+ if (clock24)
+ {
+ *pfmt++ = 'H';
+ if (leadzero)
+ *pfmt++ = 'H';
+ }
+ else {
+ *pfmt++ = 'h';
+ if (leadzero)
+ *pfmt++ = 'h';
+ }
+ for(psep = time_sep; *psep; *pfmt++ = *psep++) ;
+ *pfmt++ = 'm';
+ if (leadzero)
+ *pfmt++ = 'm';
+ for(psep = time_sep; *psep; *pfmt++ = *psep++) ;
+ *pfmt++ = 's';
+ *pfmt++ = 's';
+ *pfmt = '\0';
+
+ free(time_sep);
+
+ return ret;
+}
+
+#endif /* _INTL */
diff --git a/private/crt32/misc/labs.c b/private/crt32/misc/labs.c
new file mode 100644
index 000000000..e26a75115
--- /dev/null
+++ b/private/crt32/misc/labs.c
@@ -0,0 +1,52 @@
+/***
+*labs.c - find absolute value of a long integer
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines labs() - find absolute value of a long integer.
+*
+*Revision History:
+* 03-15-84 RN initial version
+* 04-22-87 JMB added function pragma for conversion to C 5.0 compiler
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 03-14-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 10-04-90 GJF New-style function declarator.
+* 12-28-90 SRW Added _CRUISER_ conditional around function pragma
+* 04-01-91 SRW Enable #pragma function for i386 _WIN32_ builds too.
+* 03-09-94 RDL Enable #pragma function for i386 _WIN32_ builds too.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+#pragma function(labs)
+#endif
+
+/***
+*long labs(lnumber) - find absolute value of long.
+*
+*Purpose:
+* Find the absolute value of a long integer (lnumber if lnumber >= 0),
+* -lnumber if lnumber < 0).
+*
+*Entry:
+* long lnumber - number to find absolute value of
+*
+*Exit:
+* returns the absolute value of lnumber
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+long _CALLTYPE1 labs (
+ long lnumber
+ )
+{
+ return( lnumber>=0L ? lnumber : -lnumber );
+}
diff --git a/private/crt32/misc/lconv.c b/private/crt32/misc/lconv.c
new file mode 100644
index 000000000..a7d18aac6
--- /dev/null
+++ b/private/crt32/misc/lconv.c
@@ -0,0 +1,86 @@
+/***
+*lconv.c - Contains the localeconv function
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the localeconv() function.
+*
+*Revision History:
+* 03-21-89 JCR Module created.
+* 06-20-89 JCR Removed _LOAD_DGROUP code
+* 03-14-90 GJF Replaced _cdecl _LOAD_DS with _CALLTYPE1 and added
+* #include <cruntime.h>. Also, fixed the copyright.
+* 10-04-90 GJF New-style function declarator.
+* 10-04-91 ETC Changed _c_lconv to _lconv (locale support).
+* _lconv no longer static.
+* 12-20-91 ETC Changed _lconv to _lconv_c (C locale structure).
+* Created _lconv pointer to point to current lconv.
+* 02-08-93 CFW Added _lconv_static_*.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <limits.h>
+#include <locale.h>
+
+
+
+/* pointer to original static to avoid freeing */
+char _lconv_static_decimal[] = ".";
+char _lconv_static_null[] = "";
+
+/* lconv settings for "C" locale */
+struct lconv _lconv_c = {
+ _lconv_static_decimal, /* decimal_point */
+ _lconv_static_null, /* thousands_sep */
+ _lconv_static_null, /* grouping */
+ _lconv_static_null, /* int_curr_symbol */
+ _lconv_static_null, /* currency_symbol */
+ _lconv_static_null, /* mon_decimal_point */
+ _lconv_static_null, /* mon_thousands_sep */
+ _lconv_static_null, /* mon_grouping */
+ _lconv_static_null, /* positive_sign */
+ _lconv_static_null, /* negative_sign */
+ CHAR_MAX, /* int_frac_digits */
+ CHAR_MAX, /* frac_digits */
+ CHAR_MAX, /* p_cs_precedes */
+ CHAR_MAX, /* p_sep_by_space */
+ CHAR_MAX, /* n_cs_precedes */
+ CHAR_MAX, /* n_sep_by_space */
+ CHAR_MAX, /* p_sign_posn */
+ CHAR_MAX /* n_sign_posn */
+ };
+
+
+/* pointer to current lconv structure */
+
+struct lconv *_lconv = &_lconv_c;
+
+
+/***
+*struct lconv *localeconv(void) - Return the numeric formatting convention
+*
+*Purpose:
+* The localeconv() routine returns the numeric formatting conventions
+* for the current locale setting. [ANSI]
+*
+*Entry:
+* void
+*
+*Exit:
+* struct lconv * = pointer to struct indicating current numeric
+* formatting conventions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+struct lconv * _CALLTYPE1 localeconv (
+ void
+ )
+{
+ /* the work is done by setlocale() */
+
+ return(_lconv);
+}
diff --git a/private/crt32/misc/ldiv.c b/private/crt32/misc/ldiv.c
new file mode 100644
index 000000000..05c92f2da
--- /dev/null
+++ b/private/crt32/misc/ldiv.c
@@ -0,0 +1,59 @@
+/***
+*ldiv.c - contains the ldiv routine
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Performs a signed divide on longs and returns quotient
+* and remainder.
+*
+*Revision History:
+* 06-02-89 PHG module created
+* 03-14-90 GJF Made calling type _CALLTYPE1 and added #include
+* <cruntime.h>. Also, fixed the copyright.
+* 10-04-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+
+/***
+*ldiv_t div(long numer, long denom) - do signed divide
+*
+*Purpose:
+* This routine does an long divide and returns the results.
+* Since we don't know how the Intel 860 does division, we'd
+* better make sure that we have done it right.
+*
+*Entry:
+* long numer - Numerator passed in on stack
+* long denom - Denominator passed in on stack
+*
+*Exit:
+* returns quotient and remainder in structure
+*
+*Exceptions:
+* No validation is done on [denom]* thus, if [denom] is 0,
+* this routine will trap.
+*
+*******************************************************************************/
+
+ldiv_t _CALLTYPE1 ldiv (
+ long numer,
+ long denom
+ )
+{
+ ldiv_t result;
+
+ result.quot = numer / denom;
+ result.rem = numer % denom;
+
+ if (numer < 0 && result.rem > 0) {
+ /* did division wrong; must fix up */
+ ++result.quot;
+ result.rem -= denom;
+ }
+
+ return result;
+}
diff --git a/private/crt32/misc/lfind.c b/private/crt32/misc/lfind.c
new file mode 100644
index 000000000..7b7443cbd
--- /dev/null
+++ b/private/crt32/misc/lfind.c
@@ -0,0 +1,79 @@
+/***
+*lfind.c - do a linear search
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _lfind() - do a linear search of an array.
+*
+*Revision History:
+* 06-19-85 TC initial version
+* 02-05-87 BM changed <= to < in while condition to fix bug
+* of looking one element too far
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-21-88 JCR Backed out _LOAD_DS...
+* 10-30-89 JCR Added _cdecl to prototypes
+* 03-14-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 04-05-90 GJF Added #include <search.h> and fixed the resulting
+* compilation errors and warnings. Also, removed an
+* unreferenced local variable.
+* 07-25-90 SBM Replaced <stdio.h> by <stddef.h>
+* 10-04-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <search.h>
+#include <stddef.h>
+
+/***
+*char *_lfind(key, base, num, width, compare) - do a linear search
+*
+*Purpose:
+* Performs a linear search on the array, looking for the value key
+* in an array of num elements of width bytes in size. Returns
+* a pointer to the array value if found, NULL if not found.
+*
+*Entry:
+* char *key - key to search for
+* char *base - base of array to search
+* unsigned *num - number of elements in array
+* int width - number of bytes in each array element
+* int (*compare)() - pointer to function that compares two
+* array values, returning 0 if they are equal and non-0
+* if they are different. Two pointers to array elements
+* are passed to this function.
+*
+*Exit:
+* if key found:
+* returns pointer to array element
+* if key not found:
+* returns NULL
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 _lfind (
+ REG2 const void *key,
+ REG1 const void *base,
+ REG3 unsigned int *num,
+ unsigned int width,
+ int (_CALLTYPE1 *compare)(const void *, const void *)
+ )
+{
+ unsigned int place = 0;
+ while (place < *num )
+ if (!(*compare)(key,base))
+ return( (void *)base );
+ else
+ {
+ base = (char *)base + width;
+ place++;
+ }
+ return( NULL );
+}
diff --git a/private/crt32/misc/lsearch.c b/private/crt32/misc/lsearch.c
new file mode 100644
index 000000000..42b870764
--- /dev/null
+++ b/private/crt32/misc/lsearch.c
@@ -0,0 +1,87 @@
+/***
+*lsearch.c - linear search of an array
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains the _lsearch() function - linear search of an array
+*
+*Revision History:
+* 06-19-85 TC initial version
+* 05-14-87 JMB added function pragma for memcpy in compact/large mode
+* for huge pointer support
+* include sizeptr.h for SIZED definition
+* 08-01-87 SKS Add include file for prototype of memcpy()
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-21-88 JCR Backed out _LOAD_DS...
+* 10-30-89 JCR Added _cdecl to prototypes
+* 03-14-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 04-05-90 GJF Added #include <search.h> and fixed the resulting
+* compiler errors and warnings. Removed unreferenced
+* local variable. Also, removed #include <sizeptr.h>.
+* 07-25-90 SBM Replaced <stdio.h> by <stddef.h>
+* 10-04-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stddef.h>
+#include <search.h>
+#include <memory.h>
+
+/***
+*char *_lsearch(key, base, num, width, compare) - do a linear search
+*
+*Purpose:
+* Performs a linear search on the array, looking for the value key
+* in an array of num elements of width bytes in size. Returns
+* a pointer to the array value if found; otherwise adds the
+* key to the end of the list.
+*
+*Entry:
+* char *key - key to search for
+* char *base - base of array to search
+* unsigned *num - number of elements in array
+* int width - number of bytes in each array element
+* int (*compare)() - pointer to function that compares two
+* array values, returning 0 if they are equal and non-0
+* if they are different. Two pointers to array elements
+* are passed to this function.
+*
+*Exit:
+* if key found:
+* returns pointer to array element
+* if key not found:
+* adds the key to the end of the list, and increments
+* *num.
+* returns pointer to new element.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 _lsearch (
+ REG2 const void *key,
+ REG1 void *base,
+ REG3 unsigned int *num,
+ unsigned int width,
+ int (_CALLTYPE1 *compare)(const void *, const void *)
+ )
+{
+ unsigned int place = 0;
+ while (place < *num )
+ if (!(*compare)(key,base))
+ return(base);
+ else
+ {
+ base = (char *)base + width;
+ place++;
+ }
+ (void) memcpy( base, key, width );
+ (*num)++;
+ return( base );
+}
diff --git a/private/crt32/misc/makefile b/private/crt32/misc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/misc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/misc/makepath.c b/private/crt32/misc/makepath.c
new file mode 100644
index 000000000..6cf245500
--- /dev/null
+++ b/private/crt32/misc/makepath.c
@@ -0,0 +1,128 @@
+/***
+*makepath.c - create path name from components
+*
+* Copyright (c) 1987-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* To provide support for creation of full path names from components
+*
+*Revision History:
+* 06-13-87 DFW initial version
+* 08-05-87 JCR Changed appended directory delimeter from '/' to '\'.
+* 09-24-87 JCR Removed 'const' from declarations (caused cl warnings).
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed copyright, indents. Added const to types of
+* appropriate args.
+* 03-14-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 10-04-90 GJF New-style function declarator.
+* 06-09-93 KRS Add _MBCS support.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#ifdef _MBCS
+#include <mbdata.h>
+#include <mbstring.h>
+#endif
+
+/***
+*void _makepath() - build path name from components
+*
+*Purpose:
+* create a path name from its individual components
+*
+*Entry:
+* char *path - pointer to buffer for constructed path
+* char *drive - pointer to drive component, may or may not contain
+* trailing ':'
+* char *dir - pointer to subdirectory component, may or may not include
+* leading and/or trailing '/' or '\' characters
+* char *fname - pointer to file base name component
+* char *ext - pointer to extension component, may or may not contain
+* a leading '.'.
+*
+*Exit:
+* path - pointer to constructed path name
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _makepath (
+ register char *path,
+ const char *drive,
+ const char *dir,
+ const char *fname,
+ const char *ext
+ )
+{
+ register const char *p;
+
+ /* we assume that the arguments are in the following form (although we
+ * do not diagnose invalid arguments or illegal filenames (such as
+ * names longer than 8.3 or with illegal characters in them)
+ *
+ * drive:
+ * A ; or
+ * A:
+ * dir:
+ * \top\next\last\ ; or
+ * /top/next/last/ ; or
+ * either of the above forms with either/both the leading
+ * and trailing / or \ removed. Mixed use of '/' and '\' is
+ * also tolerated
+ * fname:
+ * any valid file name
+ * ext:
+ * any valid extension (none if empty or null )
+ */
+
+ /* copy drive */
+
+ if (drive && *drive) {
+ *path++ = *drive;
+ *path++ = ':';
+ }
+
+ /* copy dir */
+
+ if ((p = dir) && *p) {
+ do {
+ *path++ = *p++;
+ }
+ while (*p);
+#ifdef _MBCS
+ if (*(p=_mbsdec(dir,p)) != '/' && *p != '\\') {
+#else
+ if (*(p-1) != '/' && *(p-1) != '\\') {
+#endif
+ *path++ = '\\';
+ }
+ }
+
+ /* copy fname */
+
+ if (p = fname) {
+ while (*p) {
+ *path++ = *p++;
+ }
+ }
+
+ /* copy ext, including 0-terminator - check to see if a '.' needs
+ * to be inserted.
+ */
+
+ if (p = ext) {
+ if (*p && *p != '.') {
+ *path++ = '.';
+ }
+ while (*path++ = *p++)
+ ;
+ }
+ else {
+ /* better add the 0-terminator */
+ *path = '\0';
+ }
+}
diff --git a/private/crt32/misc/mbval.c b/private/crt32/misc/mbval.c
new file mode 100644
index 000000000..aa3ad3a16
--- /dev/null
+++ b/private/crt32/misc/mbval.c
@@ -0,0 +1,22 @@
+/***
+*mbval.c - definition of __invalid_mb_chars variable
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines __invalid_mb_chars and adds a pointer to __set_invalid_mb_chars
+* to be called at runtime startup.
+*
+**
+*Revision History:
+* 10-22-93 CFW Module created.
+*
+*******************************************************************************/
+
+void __set_invalid_mb_chars(void);
+
+int __invalid_mb_chars = 0;
+
+#pragma data_seg(".CRT$XIC")
+void (*__pfn_set_invalid_mb_chars) = __set_invalid_mb_chars;
+
diff --git a/private/crt32/misc/mips/chandler.c b/private/crt32/misc/mips/chandler.c
new file mode 100644
index 000000000..4721f82b1
--- /dev/null
+++ b/private/crt32/misc/mips/chandler.c
@@ -0,0 +1,219 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ chandler.c
+
+Abstract:
+
+ This module implements the C specific exception handler that provides
+ structured condition handling for the C language.
+
+Author:
+
+ David N. Cutler (davec) 11-Sep-1990
+
+Environment:
+
+ Any mode.
+
+Revision History:
+
+--*/
+
+#include "nt.h"
+
+
+//
+// Define procedure prototypes for exception filter and termination handler
+// execution routines defined in jmpunwnd.s
+//
+
+LONG
+__C_ExecuteExceptionFilter (
+ PEXCEPTION_POINTERS ExceptionPointers,
+ EXCEPTION_FILTER ExceptionFilter,
+ ULONG EstablisherFrame
+ );
+
+VOID
+__C_ExecuteTerminationHandler (
+ BOOLEAN AbnormalTermination,
+ TERMINATION_HANDLER TerminationHandler,
+ ULONG EstablisherFrame
+ );
+
+EXCEPTION_DISPOSITION
+__C_specific_handler (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PVOID EstablisherFrame,
+ IN OUT PCONTEXT ContextRecord,
+ IN OUT PDISPATCHER_CONTEXT DispatcherContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function scans the scope tables associated with the specified
+ procedure and calls exception and termination handlers as necessary.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ EstablisherFrame - Supplies a pointer to frame of the establisher function.
+
+ ContextRecord - Supplies a pointer to a context record.
+
+ DispatcherContext - Supplies a pointer to the exception dispatcher or
+ unwind dispatcher context.
+
+Return Value:
+
+ If the exception is handled by one of the exception filter routines, then
+ there is no return from this routine and RtlUnwind is called. Otherwise,
+ an exception disposition value of continue execution or continue search is
+ returned.
+
+--*/
+
+{
+
+ ULONG ControlPc;
+ EXCEPTION_FILTER ExceptionFilter;
+ EXCEPTION_POINTERS ExceptionPointers;
+ PRUNTIME_FUNCTION FunctionEntry;
+ ULONG Index;
+ PSCOPE_TABLE ScopeTable;
+ ULONG TargetPc;
+ TERMINATION_HANDLER TerminationHandler;
+ LONG Value;
+
+ //
+ // Get address of where control left the establisher, the address of the
+ // function table entry that describes the function, and the address of
+ // the scope table.
+ //
+
+ ControlPc = DispatcherContext->ControlPc;
+ FunctionEntry = DispatcherContext->FunctionEntry;
+ ScopeTable = (PSCOPE_TABLE)(FunctionEntry->HandlerData);
+
+ //
+ // If an unwind is not in progress, then scan the scope table and call
+ // the appropriate exception filter routines. Otherwise, scan the scope
+ // table and call the appropriate termination handlers using the target
+ // PC obtained from the context record.
+ // are called.
+ //
+
+ if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) {
+
+ //
+ // Scan the scope table and call the appropriate exception filter
+ // routines.
+ //
+
+ ExceptionPointers.ExceptionRecord = ExceptionRecord;
+ ExceptionPointers.ContextRecord = ContextRecord;
+ for (Index = 0; Index < ScopeTable->Count; Index += 1) {
+ if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) &&
+ (ScopeTable->ScopeRecord[Index].JumpTarget != 0)) {
+
+ //
+ // Call the exception filter routine.
+ //
+
+ ExceptionFilter =
+ (EXCEPTION_FILTER)ScopeTable->ScopeRecord[Index].HandlerAddress;
+ Value = __C_ExecuteExceptionFilter(&ExceptionPointers,
+ ExceptionFilter,
+ (ULONG)EstablisherFrame);
+
+ //
+ // If the return value is less than zero, then dismiss the
+ // exception. Otherwise, if the value is greater than zero,
+ // then unwind to the target exception handler. Otherwise,
+ // continue the search for an exception filter.
+ //
+
+ if (Value < 0) {
+ return ExceptionContinueExecution;
+
+ } else if (Value > 0) {
+ RtlUnwind(EstablisherFrame,
+ (PVOID)ScopeTable->ScopeRecord[Index].JumpTarget,
+ ExceptionRecord,
+ (PVOID)ExceptionRecord->ExceptionCode);
+ }
+ }
+ }
+
+ } else {
+
+ //
+ // Scan the scope table and call the appropriate termination handler
+ // routines.
+ //
+
+ TargetPc = ContextRecord->Fir;
+ for (Index = 0; Index < ScopeTable->Count; Index += 1) {
+ if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress)) {
+
+ //
+ // If the target PC is within the same scope the control PC
+ // is within, then this is an uplevel goto out of an inner try
+ // scope or a long jump back into a try scope. Terminate the
+ // scan termination handlers.
+ //
+ // N.B. The target PC can be just beyond the end of the scope,
+ // in which case it is a leave from the scope.
+ //
+
+
+ if ((TargetPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (TargetPc <= ScopeTable->ScopeRecord[Index].EndAddress)) {
+ break;
+
+ } else {
+
+ //
+ // If the scope table entry describes an exception filter
+ // and the associated exception handler is the target of
+ // the unwind, then terminate the scan for termination
+ // handlers. Otherwise, if the scope table entry describes
+ // a termination handler, then record the address of the
+ // end of the scope as the new control PC address and call
+ // the termination handler.
+ //
+
+ if (ScopeTable->ScopeRecord[Index].JumpTarget != 0) {
+ if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) {
+ break;
+ }
+
+ } else {
+ DispatcherContext->ControlPc =
+ ScopeTable->ScopeRecord[Index].EndAddress + 4;
+ TerminationHandler =
+ (TERMINATION_HANDLER)ScopeTable->ScopeRecord[Index].HandlerAddress;
+ __C_ExecuteTerminationHandler(TRUE,
+ TerminationHandler,
+ (ULONG)EstablisherFrame);
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Continue search for exception or termination handlers.
+ //
+
+ return ExceptionContinueSearch;
+}
diff --git a/private/crt32/misc/mips/jmpuwind.s b/private/crt32/misc/mips/jmpuwind.s
new file mode 100644
index 000000000..8e99fcc4c
--- /dev/null
+++ b/private/crt32/misc/mips/jmpuwind.s
@@ -0,0 +1,138 @@
+// TITLE("Jump to Unwind")
+//++
+//
+// Copyright (c) 1992 Microsoft Corporation
+//
+// Module Name:
+//
+// jmpuwind.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to jump to the runtime
+// time library unwind routine.
+//
+// Author:
+//
+// David N. Cutler (davec) 12-Sep-1990
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksmips.h"
+ SBTTL("Execute Exception Filter")
+//++
+//
+// ULONG
+// __C_ExecuteExceptionFilter (
+// PEXCEPTION_POINTERS ExceptionPointers,
+// EXCEPTION_FILTER ExceptionFilter,
+// ULONG EstablisherFrame
+// )
+//
+// Routine Description:
+//
+// This function sets the static link and transfers control to the specified
+// exception filter routine.
+//
+// Arguments:
+//
+// ExceptionPointers (a0) - Supplies a pointer to the exception pointers
+// structure.
+//
+// ExceptionFilter (a1) - Supplies the address of the exception filter
+// routine.
+//
+// EstablisherFrame (a2) - Supplies the establisher frame pointer.
+//
+// Return Value:
+//
+// The value returned by the exception filter routine.
+//
+//--
+
+ LEAF_ENTRY(__C_ExecuteExceptionFilter)
+
+ move v0,a2 // set static link
+ j a1 // transfer control to exception filter
+
+ .end __C_ExecuteExceptionFilter
+
+ SBTTL("Execute Termination Handler")
+//++
+//
+// VOID
+// __C_ExecuteTerminationHandler (
+// BOOLEAN AbnormalTermination,
+// TERMINATION_HANDLER TerminationHandler,
+// ULONG EstablisherFrame
+// )
+//
+// Routine Description:
+//
+// This function sets the static link and transfers control to the specified
+// termination handler routine.
+//
+// Arguments:
+//
+// AbnormalTermination (a0) - Supplies a boolean value that determines
+// whether the termination is abnormal.
+//
+// TerminationHandler (a1) - Supplies the address of the termination handler
+// routine.
+//
+// EstablisherFrame (a2) - Supplies the establisher frame pointer.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(__C_ExecuteTerminationHandler)
+
+ move v0,a2 // set static link
+ j a1 // transfer control to termination handler
+
+ .end __C_ExecuteTerminationHandler
+
+ SBTTL("Jump to Unwind")
+//++
+//
+// VOID
+// __jump_unwind (
+// IN PVOID EstablishFrame,
+// IN PVOID TargetPc
+// )
+//
+// Routine Description:
+//
+// This function transfer control to unwind. It is used by the MIPS
+// compiler when a goto out of the body or a try statement occurs.
+//
+// Arguments:
+//
+// EstablishFrame (a0) - Supplies the establisher frame point of the
+// target of the unwind.
+//
+// TargetPc (a1) - Supplies the target instruction address where control
+// is to be transfered to after the unwind operation is complete.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(__jump_unwind)
+
+ move a2,zero // set NULL exception record address
+ move a3,zero // set destination return value
+ j RtlUnwind // unwind to specified target
+
+ .end __jump_unwind
diff --git a/private/crt32/misc/mips/longjmp.s b/private/crt32/misc/mips/longjmp.s
new file mode 100644
index 000000000..04e886570
--- /dev/null
+++ b/private/crt32/misc/mips/longjmp.s
@@ -0,0 +1,128 @@
+// TITLE("Long Jump")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// longjmp.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to perform a long
+// jump operation.
+//
+// N.B. This routine conditionally provides UNSAFE handling of longjmp
+// which is NOT integrated with structured exception handling. The
+// determination is made based on whether an unitialized variable
+// has been set to a nonzero value.
+//
+// Author:
+//
+// David N. Cutler (davec) 2-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksmips.h"
+
+ SBTTL("Long Jump")
+//++
+//
+// int
+// longjmp (
+// IN jmp_buf JumpBuffer,
+// IN int ReturnValue
+// )
+//
+// Routine Description:
+//
+// This function performs a long jump to the context specified by the
+// jump buffer.
+//
+// Arguments:
+//
+// JumpBuffer (a0) - Supplies the address of a jump buffer that contains
+// jump information.
+//
+// ReturnValue (a1) - Supplies the value that is to be returned to the
+// caller of set jump.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 4 * 4 // argument save area
+LjEr: .space ExceptionRecordLength // exception record
+ .space 4 * 3 // fill
+LjRa: .space 4 // saved return address
+LongjmpFrameLength:
+
+ NESTED_ENTRY(longjmp, LongjmpFrameLength, zero)
+
+ subu sp,sp,LongjmpFrameLength // allocate stack frame
+ sw ra,LjRa(sp) // save return address
+
+ PROLOGUE_END
+
+ bne zero,a1,10f // if ne, return value specified
+ li a1,1 // set return value to nonzero value
+10: lw v0,JbType(a0) // get safe setjmp/longjmp flag
+ bne zero,v0,20f // if ne, provide safe longjmp
+
+//
+// Provide unsafe handling of longjmp.
+//
+
+ move v0,a1 // set return value
+ ldc1 f20,JbFltF20(a0) // restore floating registers f20 - f31
+ ldc1 f22,JbFltF22(a0) //
+ ldc1 f24,JbFltF24(a0) //
+ ldc1 f26,JbFltF26(a0) //
+ ldc1 f28,JbFltF28(a0) //
+ ldc1 f30,JbFltF30(a0) //
+ lw s0,JbIntS0(a0) // restore integer registers s0 - s8
+ lw s1,JbIntS1(a0) //
+ lw s2,JbIntS2(a0) //
+ lw s3,JbIntS3(a0) //
+ lw s4,JbIntS4(a0) //
+ lw s5,JbIntS5(a0) //
+ lw s6,JbIntS6(a0) //
+ lw s7,JbIntS7(a0) //
+ lw s8,JbIntS8(a0) //
+ lw a1,JbFir(a0) // get setjmp return address
+ lw sp,JbIntSp(a0) // restore stack pointer
+ j a1 // jump back to setjmp site
+
+//
+// Provide safe handling of longjmp.
+//
+// An exception record is constructed that contains a log jump status
+// code and the first exception information parameter is a pointer to
+// the jump buffer.
+//
+
+20: li v0,STATUS_LONGJUMP // get long jump status code
+ sw v0,LjEr + ErExceptionCode(sp) // set exception code
+ sw zero,LjEr + ErExceptionFlags(sp) // clear exception flags
+ sw zero,LjEr + ErExceptionRecord(sp) // clear associate record
+ sw zero,LjEr + ErExceptionAddress(sp) // clear exception address
+ li v0,1 // set number of parameters
+ sw v0,LjEr + ErNumberParameters(sp) //
+ sw a0,LjEr + ErExceptionInformation(sp) // set jump buffer address
+ move a3,a1 // set return value
+ addu a2,sp,LjEr // compute exception record address
+ lw a1,JbFir(a0) // set target instruction address
+ lw a0,JbType(a0) // set target virtual frame address
+ jal RtlUnwind // finish in common code
+ b 20b
+
+ .end longjmp
diff --git a/private/crt32/misc/mips/setjmp.s b/private/crt32/misc/mips/setjmp.s
new file mode 100644
index 000000000..245cd4b37
--- /dev/null
+++ b/private/crt32/misc/mips/setjmp.s
@@ -0,0 +1,101 @@
+// TITLE("Set Jump")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// setjmp.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to perform a setjmp.
+//
+// N.B. This module conditionally provides UNSAFE handling of setjmp and
+// which is NOT integrated with structured exception handling. The
+// determination is made based on whether an uninitialized variable
+// has been set to a nonzero value.
+//
+// Author:
+//
+// David N. Cutler (davec) 7-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksmips.h"
+
+//
+// Define variable that will cause setjmp/longjmp to be safe or unsafe with
+// respect to structured exception handling.
+//
+
+ .globl _setjmpexused
+ .comm _setjmpexused , 4
+
+ SBTTL("Set Jump")
+//++
+//
+// int
+// setjmp (
+// IN jmp_buf JumpBuffer
+// )
+//
+// Routine Description:
+//
+// This function saved the current nonvolatile register state in the
+// specified jump buffer and returns a function vlaue of zero.
+//
+// Arguments:
+//
+// JumpBuffer (a0) - Supplies the address of a jump buffer to store the
+// jump information.
+//
+// Return Value:
+//
+// A value of zero is returned.
+//
+//--
+
+ LEAF_ENTRY(setjmp)
+
+ lw v0,_setjmpexused // get value of switch variable
+ bne zero,v0,10f // if ne, provide safe setjmp
+
+//
+// Provide unsafe handling of setjmp.
+//
+
+ sdc1 f20,JbFltF20(a0) // save floating registers f20 - f31
+ sdc1 f22,JbFltF22(a0) //
+ sdc1 f24,JbFltF24(a0) //
+ sdc1 f26,JbFltF26(a0) //
+ sdc1 f28,JbFltF28(a0) //
+ sdc1 f30,JbFltF30(a0) //
+ sw s0,JbIntS0(a0) // save integer registers s0 - s8
+ sw s1,JbIntS1(a0) //
+ sw s2,JbIntS2(a0) //
+ sw s3,JbIntS3(a0) //
+ sw s4,JbIntS4(a0) //
+ sw s5,JbIntS5(a0) //
+ sw s6,JbIntS6(a0) //
+ sw s7,JbIntS7(a0) //
+ sw s8,JbIntS8(a0) //
+ sw ra,JbFir(a0) // get setjmp return address
+ sw sp,JbIntSp(a0) // save stack pointer
+ sw zero,JbType(a0) // clean safe setjmp flag
+ move v0,zero // set return value
+ j ra // return
+
+//
+// Provide safe handling of setjmp.
+//
+
+10: j v0 // finish in common code
+
+ .end setjmp
diff --git a/private/crt32/misc/mips/setjmpex.s b/private/crt32/misc/mips/setjmpex.s
new file mode 100644
index 000000000..31385e394
--- /dev/null
+++ b/private/crt32/misc/mips/setjmpex.s
@@ -0,0 +1,156 @@
+// TITLE("Set Jump Extended")
+//++
+//
+// Copyright (c) 1993 Microsoft Corporation
+//
+// Module Name:
+//
+// setjmpex.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to provide SAFE
+// handling of setjmp/longjmp with respect to structured exception
+// handling.
+//
+// Author:
+//
+// David N. Cutler (davec) 2-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksmips.h"
+
+//
+// Define variable that will cause setjmp/longjmp to be safe with respect
+// to structured exception handling.
+//
+
+ .globl _setjmpexused
+ .data
+_setjmpexused:
+ .word _setjmpex // set address of safe setjmp routine
+
+ SBTTL("Set Jump Extended")
+//++
+//
+// int
+// _setjmpex (
+// IN jmp_buf JumpBuffer
+// )
+//
+// Routine Description:
+//
+// This function transfers control to the actual setjmp routine.
+//
+// Arguments:
+//
+// JumpBuffer (a0) - Supplies the address of a jump buffer to store the
+// jump information.
+//
+// Return Value:
+//
+// A value of zero is returned.
+//
+//--
+
+ .struct 0
+ .space 4 * 4 // argument save area
+SjS0: .space 4 // saved integer register s0
+SjFl: .space 4 // in function flag variable
+ .space 4 // fill
+SjRa: .space 4 // saved return address
+SetjmpFrameLength:
+
+ NESTED_ENTRY(_setjmpex, SetjmpFrameLength, zero)
+
+ subu sp,sp,SetjmpFrameLength // allocate stack frame
+ sw s0,SjS0(sp) // save integer register s0
+ sw ra,SjRa(sp) // save return address
+ move s0,sp // set frame pointer
+
+ PROLOGUE_END
+
+ subu sp,sp,ContextFrameLength + 16 // allocate a context frame
+
+//
+// Save the nonvolatile machine state in both the jump buffer and a context
+// record that will be used to compute the virtual frame pointer.
+//
+
+ sdc1 f20,JbFltF20(a0) // save floating registers f20 - f31
+ sdc1 f22,JbFltF22(a0) //
+ sdc1 f24,JbFltF24(a0) //
+ sdc1 f26,JbFltF26(a0) //
+ sdc1 f28,JbFltF28(a0) //
+ sdc1 f30,JbFltF30(a0) //
+ lw v0,SjS0(s0) // get saved integer register s0
+ sw v0,JbIntS0(a0) // save integer registers s0 - s8
+ sw s1,JbIntS1(a0) //
+ sw s2,JbIntS2(a0) //
+ sw s3,JbIntS3(a0) //
+ sw s4,JbIntS4(a0) //
+ sw s5,JbIntS5(a0) //
+ sw s6,JbIntS6(a0) //
+ sw s7,JbIntS7(a0) //
+ sw s8,JbIntS8(a0) //
+ sw ra,JbFir(a0) // get setjmp return address
+ addu v0,s0,SetjmpFrameLength // compute stack pointer address
+ sw v0,JbIntSp(a0) // save stack pointer
+
+ sdc1 f20,CxFltF20 + 16(sp) // save floating registers f20 - f31
+ sdc1 f22,CxFltF22 + 16(sp) //
+ sdc1 f24,CxFltF24 + 16(sp) //
+ sdc1 f26,CxFltF26 + 16(sp) //
+ sdc1 f28,CxFltF28 + 16(sp) //
+ sdc1 f30,CxFltF30 + 16(sp) //
+ lw v0,SjS0(s0) // get saved integer register s0
+ sw v0,CxIntS0 + 16(sp) // save integer registers s0 - s8
+ sw s1,CxIntS1 + 16(sp) //
+ sw s2,CxIntS2 + 16(sp) //
+ sw s3,CxIntS3 + 16(sp) //
+ sw s4,CxIntS4 + 16(sp) //
+ sw s5,CxIntS5 + 16(sp) //
+ sw s6,CxIntS6 + 16(sp) //
+ sw s7,CxIntS7 + 16(sp) //
+ sw s8,CxIntS8 + 16(sp) // save integer register s8
+ sw gp,CxIntGp + 16(sp) // save integer register gp
+ addu v0,s0,SetjmpFrameLength // compute stack pointer address
+ sw v0,CxIntSp + 16(sp) // save stack pointer
+ sw ra,CxIntRa + 16(sp) // save return address
+ sw ra,CxFir + 16(sp) // save return address
+
+//
+// Perform unwind to determine the virtual frame pointer of the caller.
+//
+
+ addu a0,a0,JbType // set virtual frame address argument
+ sw a0,4 * 4(sp) //
+ subu a0,ra,4 // compute control PC address
+ jal RtlLookupFunctionEntry // lookup function table address
+ lw a0,SjRa(s0) // get return address
+ subu a0,a0,4 // compute control PC address
+ move a1,v0 // set address of function entry
+ addu a2,sp,16 // compute address of context record
+ addu a3,s0,SjFl // set address of in function variable
+ sw zero,4 * 5(sp) // set context pointer array address
+ jal RtlVirtualUnwind // compute virtual frame pointer value
+
+//
+// Set return value, restore registers, deallocate stack frame, and return.
+//
+
+ move v0,zero // set return value
+ move sp,s0 // reset stack pointer
+ lw s0,SjS0(sp) // restore integer register s0
+ lw ra,SjRa(sp) // restore return address
+ addu sp,sp,SetjmpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end _setjmpex
diff --git a/private/crt32/misc/mtest.c b/private/crt32/misc/mtest.c
new file mode 100644
index 000000000..0e95bcee1
--- /dev/null
+++ b/private/crt32/misc/mtest.c
@@ -0,0 +1,530 @@
+/***
+* mtest.c - Multi-thread debug testing module
+*
+* Copyright (c) 19xx-1988, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This source contains a group of routines used for multi-thread
+* testing. In order to use the debug flavor of these routines, you
+* MUST link special debug versions of multi-thread crt0dat.obj and
+* mlock.obj into your program.
+*
+* [NOTE: This source module is NOT included in the C runtime library;
+* it is used only for testing and must be explicitly linked into the
+* test program.]
+*
+*Revision History:
+* 12-??-87 JCR Module created.
+* 06-17-88 JCR Misc. bug fixes.
+* 08-03-88 JCR Use the stdio.h value of _NFILE
+* 10-03-88 JCR 386: Use SYS calls, not DOS calls
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 10-10-88 GJF Made API names match DOSCALLS.H
+* 06-08-89 JCR New 386 _beginthread interface; also brought
+* lots of new options across from the C600 tree.
+* 07-11-89 JCR Added _POPEN_LOCK to _locknames[] array
+* 07-14-89 JCR Added _LOCKTAB_LOCK support
+* 07-24-90 SBM Removed '32' from API names
+*
+*******************************************************************************/
+
+#ifdef M_I386
+#ifdef STACKALLOC
+#error Can't define STACKALLOC in 386 mode
+#endif
+#endif
+
+#ifdef M_I386
+#ifdef _DOSCREATETHREAD_
+#error Currently can't define _DOSCREATETHREAD_ in 386 mode
+#endif
+#endif
+
+#ifdef _DOSCREATETHREAD_
+#ifndef STACKALLOC
+#error Can't define _DOSCREATETHREAD_ without STACKALLOC
+#endif
+#endif
+
+/*
+Multi-thread core tester module.
+*/
+#include <malloc.h>
+#include <process.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <io.h>
+#include <mtest.h>
+#ifdef DEBUG
+#include <os2dll.h>
+#include <file2.h>
+#endif
+
+/* Define FAR to be blank for the 386 and far otherwise. */
+
+#undef FAR
+#ifdef M_I386
+#define FAR
+#else
+#define FAR far
+#endif
+
+/* define stack size */
+#ifdef M_I386
+#define _STACKSIZE_ 8192
+#else
+#define _STACKSIZE_ 2048
+#endif
+
+
+/* routines */
+#ifdef M_I386
+unsigned _syscall DOSSLEEP (unsigned long) ;
+#else
+unsigned FAR pascal DOSSLEEP (unsigned long) ;
+#endif
+int main ( int argc , char * * argv ) ;
+int minit(void);
+void childcode ( void FAR * arg ) ;
+#ifdef _DOSCREATETHREAD_
+#ifndef M_I386
+void childcode ( void ) ;
+unsigned FAR pascal DOSCREATETHREAD (void FAR *, void FAR *, void FAR *);
+#endif
+#else
+void childcode ( void FAR * arg ) ;
+#endif
+int mterm(void);
+
+/* global data */
+char Result [ _THREADMAX_ ] ;
+unsigned Synchronize ;
+
+#ifdef DEBUG
+/* Array of lock names. This order must match the declarations in
+ os2dll.h and os2dll.inc. */
+
+char *_locknames[] = {
+ "** NO LOCK 0 ** ", /* lock values are 1-based */
+ "_SIGNAL_LOCK ",
+ "_IOB_SCAN_LOCK ",
+ "_TMPNAM_LOCK ",
+ "_INPUT_LOCK ",
+ "_OUTPUT_LOCK ",
+ "_CSCANF_LOCK ",
+ "_CPRINTF_LOCK ",
+ "_CONIO_LOCK ",
+ "_HEAP_LOCK ",
+ "_BHEAP_LOCK ",
+ "_TIME_LOCK ",
+ "_ENV_LOCK ",
+ "_EXIT_LOCK1 ",
+ "_EXIT_LOCK2 ",
+ "_THREADDATA_LOCK",
+ "_POPEN_LOCK ",
+ "_SSCANF_LOCK ",
+ "_SPRINTF_LOCK ",
+#ifdef M_I386
+ "_VSPRINTF_LOCK ",
+ "_LOCKTAB_LOCK "
+#else
+ "_VSPRINTF_LOCK "
+#endif
+ };
+
+/* Minimal sanity check on above array. */
+#ifdef M_I386
+
+#if ((_LOCKTAB_LOCK+1)-_STREAM_LOCKS)
+#error *** _locknames[] does agree with lock values ***
+#endif
+
+#else /* !M_I386 */
+
+#if ((_VSPRINTF_LOCK+1)-_STREAM_LOCKS)
+#error *** _locknames[] does agree with lock values ***
+#endif
+
+#endif /* M_I386 */
+
+#endif /* DEBUG */
+
+
+/***
+* main() - Main mthread testing shell
+*
+*Purpose:
+* Provides a general purpose shell for mthread testing.
+* The module does the following:
+*
+* (1) Call minit() to perform test initialization operations.
+*
+* (2) Begins one thread for each argument passed to the
+* program. Each thread is passed the corresponding argument.
+* Thread begin location is assumed to be at routine childcode();
+*
+* (3) Waits for all threads to terminate.
+*
+* (4) Calls mterm() to perform termination operations.
+*
+* Note that minit(), childcode(), and mterm() are routines that
+* are external to this source. Again, this source doesn't care
+* what their purpose or operation is.
+*
+* Also, childcode() is expected to conform to the following rules:
+*
+* (1) The childcode should not start running until
+* the variable 'Synchronize' becomes non-zero.
+*
+* (2) When the thread is done executing, it should set
+* the value Result[threadid] to a non-zero value so the
+* parent (i.e., this routine) knows it has completed.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int main ( int argc , char * * argv )
+{
+ int rc ;
+ unsigned result = 0 ;
+ long ChildCount ;
+ int NumThreads ;
+ int t ;
+ int r ;
+ int MaxThread = 0 ;
+ long LoopCount ;
+#ifdef THREADLOOP
+ char **argvsave;
+#endif
+#ifndef M_I386
+ char * stackbottom ;
+#endif
+
+#ifdef DEBUG
+ if ( argc > MAXTHREADID) {
+ printf("*** ERROR: Mthread debugging only supports %u threads ***\n", MAXTHREADID);
+ return(-1);
+ }
+#endif
+
+ if ( -- argc > (_THREADMAX_-1) )
+ {
+ printf ( "*** Error: Too many arguments***\n" ) ;
+ return (-1) ;
+ }
+
+ /* Call the initiation routine */
+
+ if (minit() != 0) {
+ printf("*** Error: From minit() routine ***\n");
+ return(-1);
+ }
+
+ /* Bring up the threads */
+
+ printf ( "Process ID = %u, Thread ID = %d, ArgCount= %d\r\n" ,
+ getpid ( ) , * _threadid , argc ) ;
+
+#ifndef M_I386
+#ifdef STACKALLOC
+ printf( "(thread stacks allocated explicilty by mtest suite)\r\n");
+#else
+ printf( "(thread stacks allocated implicitly via _beginthread)\r\n");
+#endif
+#endif
+
+#ifdef THREADLOOP
+ /* Bring up all the threads several times (so tids get re-used) */
+ argvsave=argv;
+ for (threadloop=1;threadloop<=_THREADLOOPCNT_;threadloop++) {
+ printf("\nThreadloop = %i\n", threadloop);
+ argv=argvsave;
+#endif
+
+ NumThreads = 0 ;
+
+ while ( * ++ argv )
+ {
+
+ ChildCount = atol ( * argv ) ;
+
+#ifdef M_I386
+
+ rc = _beginthread ( (void FAR *) childcode , _STACKSIZE_ ,
+ (void FAR *) ChildCount ) ;
+
+ if ( rc == -1 )
+
+#else /* !M_I386 */
+
+#ifdef STACKALLOC
+ if ( ! ( stackbottom = _fmalloc ( _STACKSIZE_ ) ) )
+ {
+ printf ( "*** Error: Could not allocate a stack ***\n" ) ;
+ break ;
+ }
+#else
+ stackbottom = (void FAR *) NULL;
+#endif
+
+#ifdef _DOSCREATETHREAD_
+ stackbottom+=_STACKSIZE_-16; /* point to end of malloc'd block */
+ rc1 = DOSCREATETHREAD( (void FAR *) childcode, &rc,
+ (void FAR *) stackbottom);
+
+ if (rc1 != 0)
+#else
+ rc = _beginthread ( (void FAR *) childcode , (void FAR *) stackbottom ,
+ _STACKSIZE_ , (void FAR *) ChildCount ) ;
+
+ if ( rc == -1 )
+#endif
+
+#endif /* M_I386 */
+
+ {
+ printf ("*** Error: Could not Spawn %d-th Thread (argument=%ld) ***\n" ,
+ NumThreads + 1 , ChildCount ) ;
+ break ;
+ }
+
+ if ( rc > MaxThread )
+ MaxThread = rc ;
+
+ printf ( "Spawning %d-th Thread %d with argument=%ld\r\n" ,
+ ++ NumThreads , rc , ChildCount ) ;
+ }
+
+ printf ( "NumThreads = %d, MaxThread = %d\r\n" ,
+ NumThreads, MaxThread ) ;
+
+ /* Let the threads begin and wait for them to term. */
+
+ LoopCount = 0L ;
+
+ Synchronize = 1 ;
+
+ for ( t = 0 ; t < NumThreads ; ++ t )
+ {
+ r = 0 ;
+ while ( ! Result [ r ] )
+ {
+ DOSSLEEP ( 0L ) ;
+ if ( ++ r > MaxThread )
+ {
+ r = 0 ;
+ printf ( "%ld\r" , LoopCount ++ ) ;
+ }
+ }
+
+ printf ( "%d: Thread %d Done.\r\n" , t , r) ;
+
+ Result [ r ] = '\0' ;
+ }
+#ifdef THREADLOOP
+ }
+#endif
+
+ /* All the threads have completed. Call the term routine and return. */
+
+ if (mterm() != 0) {
+ printf("*** Error: From mterm() routine ***\n");
+ return(-1);
+ }
+
+ printf("\nDone!\n");
+ return 0 ;
+}
+
+
+#ifdef DEBUG
+
+/***
+* Debug Print Routines - Display useful mthread lock data
+*
+*Purpose:
+* The following routines extract information from the multi-thread
+* debug data bases and print them out in various formats.
+* In order to use these routines, you MUST link special debug
+* versions of multi-thread crt0dat.obj and mlock.obj into your program.
+*
+*Entry:
+*
+*Exit:
+* 0 = success
+* 0! = failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+/*--- Print lock routine ---*/
+int printlock(int locknum)
+{
+ int retval;
+
+#ifdef _INIT_LOCKS
+ if (locknum >= _STREAM_LOCKS)
+ printf("\nValidating lock #%i (%s):\n",locknum, "not a 'single lock'");
+ else
+ printf("\nValidating lock #%i: %s\n",locknum, _locknames[locknum]);
+#else
+ printf("\nValidating lock #%i (%s, %s):\n",
+ locknum,
+ (locknum >= _STREAM_LOCKS ?
+ "not a 'single' lock" : _locknames[locknum]),
+ (_lock_exist(locknum) ?
+ "initialized" : "NOT initialized")
+ );
+#endif
+
+ retval = _check_lock(locknum);
+ printf("\tLock count = %u\r\n", _lock_cnt(locknum));
+ printf("\tCollision count = %u\r\n", _collide_cnt(locknum));
+
+ if (retval != 0)
+ printf("\t*** ERROR: Checking lock ***\n");
+
+ return(retval);
+}
+
+
+/*--- Printf single locks ---*/
+int print_single_locks(void)
+{
+ int locknum;
+ int retval=0;
+ int lockval;
+
+ printf("\n--- Single Locks ---\n");
+
+#ifdef _INIT_LOCKS
+ printf("\t\t\t\tlock count\tcollide count\n");
+ for (locknum=1;locknum<_STREAM_LOCKS;locknum++) {
+ if (lockval = (_check_lock(locknum) != 0))
+ retval++;
+ printf("#%i / %s\t\t%u\t\t%u\t%s\n",
+ locknum, _locknames[locknum], _lock_cnt(locknum),
+ _collide_cnt(locknum), (lockval ? "*LOCK ERROR*" : "") );
+ }
+#else
+ printf("\t\t\t\tlock count\tcollide count\texists?\n");
+ for (locknum=1;locknum<_STREAM_LOCKS;locknum++) {
+ if (lockval = (_check_lock(locknum) != 0))
+ retval++;
+ printf("#%i / %s\t\t%u\t\t%u\t\t%s\t%s\n",
+ locknum, _locknames[locknum], _lock_cnt(locknum),
+ _collide_cnt(locknum),
+ (_lock_exist(locknum) ? "YES" : "NO"),
+ (lockval ? "*LOCK ERROR*" : "") );
+ }
+#endif
+
+ return(retval);
+}
+
+
+/*--- Print all stdio locks ---*/
+int print_stdio_locks(void)
+{
+ int i;
+ int locknum;
+ int retval=0;
+ int lockval;
+
+ printf("\n--- Stdio Locks ---\n");
+
+#ifdef _INIT_LOCKS
+ printf("stream\t\tlock count\tcollide count\n");
+ for (i=0;i<_NFILE;i++) {
+ locknum = _stream_locknum(i);
+ if (lockval = (_check_lock(locknum) != 0))
+ retval++;
+ printf("%i\t\t%u\t\t%u\t%s\n",
+ i, _lock_cnt(locknum), _collide_cnt(locknum),
+ (lockval ? "*LOCK ERROR*" : "") );
+ }
+#else
+ printf("stream\t\tlock count\tcollide count\texists?\n");
+ for (i=0;i<_NFILE;i++) {
+ locknum = _stream_locknum(i);
+ if (lockval = (_check_lock(locknum) != 0))
+ retval++;
+ printf("%i\t\t%u\t\t%u\t\t%s\t%s\n",
+ i, _lock_cnt(locknum), _collide_cnt(locknum),
+ (_lock_exist(locknum) ? "YES" : "NO"),
+ (lockval ? "*LOCK ERROR*" : "") );
+ }
+#endif
+
+ return(retval);
+}
+
+
+/*--- Print all lowio locks ---*/
+int print_lowio_locks(void)
+{
+ int i;
+ int locknum;
+ int retval=0;
+ int lockval;
+
+ printf("\n--- Lowio locks ---\n");
+
+#ifdef _INIT_LOCKS
+ printf("fh\t\tlock count\tcollide count\n");
+ for (i=0;i<_NFILE;i++) {
+ locknum = _fh_locknum(i);
+ if (lockval = (_check_lock(locknum) != 0))
+ retval++;
+ printf("%i\t\t%u\t\t%u\t%s\n",
+ i, _lock_cnt(locknum), _collide_cnt(locknum),
+ (lockval ? "*LOCK ERROR*" : "") );
+ }
+#else
+ printf("fh\t\tlock count\tcollide count\texists?\n");
+ for (i=0;i<_NFILE;i++) {
+ locknum = _fh_locknum(i);
+ if (lockval = (_check_lock(locknum) != 0))
+ retval++;
+ printf("%i\t\t%u\t\t%u\t\t%s\t%s\n",
+ i, _lock_cnt(locknum), _collide_cnt(locknum),
+ (_lock_exist(locknum) ? "YES" : "NO"),
+ (lockval ? "*LOCK ERROR*" : "") );
+ }
+#endif
+
+ return(retval);
+}
+
+
+/*--- Print all I/O locks ---*/
+int print_iolocks(void)
+{
+ int retval=0;
+
+ retval += print_stdio_locks();
+ retval += print_lowio_locks();
+
+ return(retval);
+}
+
+
+/*--- Print all Locks ---*/
+int print_locks(void)
+{
+ int retval=0;
+
+ retval += print_single_locks();
+ retval += print_iolocks();
+
+ return(retval);
+}
+
+#endif
diff --git a/private/crt32/misc/nlsdata1.c b/private/crt32/misc/nlsdata1.c
new file mode 100644
index 000000000..6b5a9b2b7
--- /dev/null
+++ b/private/crt32/misc/nlsdata1.c
@@ -0,0 +1,38 @@
+/***
+*nlsdata1.c - globals for international library - small globals
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains the globals: __mb_cur_max, _decimal_point,
+* _decimal_point_length. This module is always required.
+* This module is separated from nlsdatax.c for granularity.
+*
+*Revision History:
+* 12-01-91 ETC Created.
+* 04-03-92 PLM Changes tdef.h to tchar.h
+* 08-18-92 KRS Rip out _tflag--not used.
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+#include <nlsint.h>
+
+/*
+ * Value of MB_CUR_MAX macro.
+ */
+unsigned short __mb_cur_max = 1;
+
+/*
+ * Localized decimal point string.
+ */
+char _decimal_point[] = ".";
+
+#ifdef _INTL
+
+/*
+ * Decimal point length, not including terminating null.
+ */
+size_t _decimal_point_length = 1;
+
+#endif /* _INTL */
diff --git a/private/crt32/misc/nlsdata2.c b/private/crt32/misc/nlsdata2.c
new file mode 100644
index 000000000..7cbca2a2f
--- /dev/null
+++ b/private/crt32/misc/nlsdata2.c
@@ -0,0 +1,34 @@
+/***
+*nlsdata2.c - globals for international library - locale handles and code page
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module defines the locale handles and code page. The handles are
+* required by almost all locale dependent functions. This module is
+* separated from nlsdatax.c for granularity.
+*
+*Revision History:
+* 12-01-91 ETC Created.
+*
+*******************************************************************************/
+
+#include <locale.h>
+#include <setlocal.h>
+
+/*
+ * Locale handles.
+ */
+LCID _lc_handle[LC_MAX-LC_MIN+1] = {
+ _CLOCALEHANDLE,
+ _CLOCALEHANDLE,
+ _CLOCALEHANDLE,
+ _CLOCALEHANDLE,
+ _CLOCALEHANDLE,
+ _CLOCALEHANDLE
+};
+
+/*
+ * Code page.
+ */
+UINT _lc_codepage = _CLOCALECP; /* CP_ACP */
diff --git a/private/crt32/misc/nlsdata3.c b/private/crt32/misc/nlsdata3.c
new file mode 100644
index 000000000..5e57d2111
--- /dev/null
+++ b/private/crt32/misc/nlsdata3.c
@@ -0,0 +1,34 @@
+/***
+*nlsdata3.c - globals for international library - locale id's
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains the definition of locale id's. These id's and
+* this file should only be visible to the _init_(locale category)
+* functions. This module is separated from nlsdatax.c for granularity.
+*
+*Revision History:
+* 12-01-91 ETC Created.
+* 01-25-93 KRS Updated.
+*
+*******************************************************************************/
+
+#ifdef _INTL
+#include <locale.h>
+#include <setlocal.h>
+
+/*
+ * Locale id's.
+ */
+/* UNDONE: define struct consisting of LCID/LANGID, CTRY ID, and CP. */
+LC_ID _lc_id[LC_MAX-LC_MIN+1] = {
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 }
+};
+
+#endif /* _INTL */
diff --git a/private/crt32/misc/onexit.c b/private/crt32/misc/onexit.c
new file mode 100644
index 000000000..13806f41a
--- /dev/null
+++ b/private/crt32/misc/onexit.c
@@ -0,0 +1,286 @@
+/***
+*onexit.c - save function for execution on exit
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _onexit(), atexit() - save function for execution at exit
+*
+* In order to save space, the table is allocated via malloc/realloc,
+* and only consumes as much space as needed. __onexittable is
+* set to point to the table if onexit() is ever called.
+*
+*Revision History:
+* 06-30-89 PHG module created, based on asm version
+* 03-15-90 GJF Replace _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also,
+* cleaned up the formatting a bit.
+* 05-21-90 GJF Fixed compiler warning.
+* 10-04-90 GJF New-style function declarators.
+* 12-28-90 SRW Added casts of func for Mips C Compiler
+* 01-21-91 GJF ANSI naming.
+* 09-09-91 GJF Revised for C++ needs.
+* 03-20-92 SKS Revamped for new initialization model
+* 04-23-92 DJM POSIX support.
+* 12-02-93 SKS Add __dllonexit for DLLs using CRTDLL.DLL
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <os2dll.h>
+#include <stdlib.h>
+#include <internal.h>
+
+void __cdecl _onexitinit(void);
+
+#ifdef _MSC_VER
+
+#pragma data_seg(".CRT$XIC")
+static void (__cdecl *pinit)(void) = _onexitinit;
+#pragma data_seg()
+
+#endif /* _MSC_VER */
+
+#include <malloc.h>
+#include <rterr.h>
+
+typedef void (_CALLTYPE1 *PF)(void); /* pointer to function */
+
+/*
+ * Define pointers to beginning and end of the table of function pointers
+ * manipulated by _onexit()/atexit().
+ */
+extern PF *__onexitbegin;
+extern PF *__onexitend;
+
+/*
+ * Define increment (in entries) for growing the _onexit/atexit table
+ */
+#define ONEXITTBLINCR 4
+
+/***
+*_onexit(func), atexit(func) - add function to be executed upon exit
+*
+*Purpose:
+* The _onexit/atexit functions are passed a pointer to a function
+* to be called when the program terminate normally. Successive
+* calls create a register of functions that are executed last in,
+* first out.
+*
+*Entry:
+* void (*func)() - pointer to function to be executed upon exit
+*
+*Exit:
+* onexit:
+* Success - return pointer to user's function.
+* Error - return NULL pointer.
+* atexit:
+* Success - return 0.
+* Error - return non-zero value.
+*
+*Notes:
+* This routine depends on the behavior of _initterm() in CRT0DAT.C.
+* Specifically, _initterm() must not skip the address pointed to by
+* its first parameter, and must also stop before the address pointed
+* to by its second parameter. This is because _onexitbegin will point
+* to a valid address, and _onexitend will point at an invalid address.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+_onexit_t _CALLTYPE1 _onexit (
+ _onexit_t func
+ )
+{
+ PF *p;
+
+#ifdef MTHREAD
+ _lockexit(); /* lock the exit code */
+#endif
+
+ /*
+ * First, make sure the table has room for a new entry
+ */
+ if ( _msize(__onexitbegin) <= (unsigned)((char *)__onexitend -
+ (char *)__onexitbegin) ) {
+ /*
+ * not enough room, try to grow the table
+ */
+ if ( (p = (PF *) realloc(__onexitbegin, _msize(__onexitbegin) +
+ ONEXITTBLINCR * sizeof(PF))) == NULL ) {
+ /*
+ * didn't work. don't do anything rash, just fail
+ */
+#ifdef MTHREAD
+ _unlockexit();
+#endif
+
+ return NULL;
+ }
+
+ /*
+ * update __onexitend and __onexitbegin
+ */
+ __onexitend = p + (__onexitend - __onexitbegin);
+ __onexitbegin = p;
+ }
+
+ /*
+ * Put the new entry into the table and update the end-of-table
+ * pointer.
+ */
+ *(__onexitend++) = (PF)func;
+
+#ifdef MTHREAD
+ _unlockexit();
+#endif
+
+ return func;
+
+}
+
+int _CALLTYPE1 atexit (
+ PF func
+ )
+{
+ return (_onexit((_onexit_t)func) == NULL) ? -1 : 0;
+}
+
+/***
+* void _onexitinit(void) - initialization routine for the function table
+* used by _onexit() and _atexit().
+*
+*Purpose:
+* Allocate the table with room for 32 entries (minimum required by
+* ANSI). Also, initialize the pointers to the beginning and end of
+* the table.
+*
+*Entry:
+* None.
+*
+*Exit:
+* No return value. A fatal runtime error is generated if the table
+* cannot be allocated.
+*
+*Notes:
+* This routine depends on the behavior of doexit() in CRT0DAT.C.
+* Specifically, doexit() must not skip the address pointed to by
+* __onexitbegin, and it must also stop before the address pointed
+* to by __onexitend. This is because _onexitbegin will point
+* to a valid address, and _onexitend will point at an invalid address.
+*
+* Since the table of onexit routines is built in forward order, it
+* must be traversed by doexit() in CRT0DAT.C in reverse order. This
+* is because these routines must be called in last-in, first-out order.
+*
+* If __onexitbegin == __onexitend, then the onexit table is empty!
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _onexitinit (
+ void
+ )
+{
+ if ( (__onexitbegin = (PF *)malloc(32 * sizeof(PF))) == NULL )
+ /*
+ * cannot allocate minimal required size. generate
+ * fatal runtime error.
+ */
+ _amsg_exit(_RT_ONEXIT);
+
+ *(__onexitbegin) = (PF) NULL;
+ __onexitend = __onexitbegin;
+}
+
+#ifdef CRTDLL
+
+/***
+*__dllonexit(func, pbegin, pend) - add function to be executed upon DLL detach
+*
+*Purpose:
+* The _onexit/atexit functions in a DLL linked with CRTDLL.LIB
+* must maintain their own atexit/_onexit list. This routine is
+* the worker that gets called by such DLLs. It is analogous to
+* the regular _onexit above except that the __onexitbegin and
+* __onexitend variables are not global variables visible to this
+* routine but rather must be passed as parameters.
+*
+*Entry:
+* void (*func)() - pointer to function to be executed upon exit
+* void (***pbegin)() - pointer to variable pointing to the beginning
+* of list of functions to execute on detach
+* void (***pend)() - pointer to variable pointing to the end of list
+* of functions to execute on detach
+*
+*Exit:
+* Success - return pointer to user's function.
+* Error - return NULL pointer.
+*
+*Notes:
+* This routine depends on the behavior of _initterm() in CRT0DAT.C.
+* Specifically, _initterm() must not skip the address pointed to by
+* its first parameter, and must also stop before the address pointed
+* to by its second parameter. This is because *pbegin will point
+* to a valid address, and *pend will point at an invalid address.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+_onexit_t _CALLTYPE1 __dllonexit (
+ _onexit_t func,
+ PF ** pbegin,
+ PF ** pend
+ )
+{
+ PF *p;
+
+#ifdef MTHREAD
+ _lockexit(); /* lock the exit code */
+#endif
+
+ /*
+ * First, make sure the table has room for a new entry
+ */
+ if ( _msize((*pbegin)) <= (unsigned)((char *)(*pend) -
+ (char *)(*pbegin)) ) {
+ /*
+ * not enough room, try to grow the table
+ */
+ if ( (p = (PF *) realloc((*pbegin), _msize((*pbegin)) +
+ ONEXITTBLINCR * sizeof(PF))) == NULL ) {
+ /*
+ * didn't work. don't do anything rash, just fail
+ */
+#ifdef MTHREAD
+ _unlockexit();
+#endif
+
+ return NULL;
+ }
+
+ /*
+ * update (*pend) and (*pbegin)
+ */
+ (*pend) = p + ((*pend) - (*pbegin));
+ (*pbegin) = p;
+ }
+
+ /*
+ * Put the new entry into the table and update the end-of-table
+ * pointer.
+ */
+ *((*pend)++) = (PF)func;
+
+#ifdef MTHREAD
+ _unlockexit();
+#endif
+
+ return func;
+
+}
+#endif /* CRTDLL */
diff --git a/private/crt32/misc/perror.c b/private/crt32/misc/perror.c
new file mode 100644
index 000000000..9e41b1c7a
--- /dev/null
+++ b/private/crt32/misc/perror.c
@@ -0,0 +1,78 @@
+/***
+*perror.c - print system error message
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines perror() - print system error message
+* System error message are indexed by errno; conforms to XENIX
+* standard, with much compatability with 1983 uniforum draft standard.
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-13-87 JCR added const to declaration
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 12-29-87 JCR Multi-thread support
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-03-88 JCR Added <io.h> to so _write_lk evaluates correctly and
+* added (char *)message casts to get rid of warnings
+* 03-15-90 GJF Replace _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and fixed
+* the copyright. Also, cleaned up the formatting a bit.
+* 04-05-90 GJF Added #include <string.h>.
+* 08-14-90 SBM Removed unneeded #include <errmsg.h>
+* 10-04-90 GJF New-style function declarator.
+* 08-26-92 GJF Include unistd.h for POSIX build.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syserr.h>
+#include <os2dll.h>
+#include <io.h>
+
+/***
+*void perror(message) - print system error message
+*
+*Purpose:
+* prints user's error message, then follows it with ": ", then the system
+* error message, then a newline. All output goes to stderr. If user's
+* message is NULL or a null string, only the system error message is
+* printer. If errno is weird, prints "Unknown error".
+*
+*Entry:
+* const char *message - users message to prefix system error message
+*
+*Exit:
+* Prints message; no return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 perror (
+ REG1 const char *message
+ )
+{
+ REG2 int fh = 2;
+
+ _lock_fh(fh); /* acquire file handle lock */
+
+ if (message && *message)
+ {
+ _write_lk(fh,(char *)message,strlen(message));
+ _write_lk(fh,": ",2);
+ }
+
+ message = _sys_err_msg( errno );
+ _write_lk(fh,(char *)message,strlen(message));
+ _write_lk(fh,"\n",1);
+
+ _unlock_fh(fh); /* release file handle lock */
+}
diff --git a/private/crt32/misc/ppc/chandler.c b/private/crt32/misc/ppc/chandler.c
new file mode 100644
index 000000000..4badd7a1d
--- /dev/null
+++ b/private/crt32/misc/ppc/chandler.c
@@ -0,0 +1,222 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ chandler.c
+
+Abstract:
+
+ This module implements the C specific exception handler that provides
+ structured condition handling for the C language.
+
+Author:
+
+ Modified for PowerPC by Rick Simpson 27-Sep-1993
+
+
+ from MIPS version by David N. Cutler (davec) 11-Sep-1990
+
+Environment:
+
+ Any mode.
+
+Revision History:
+
+ Tom Wood (twood) 1-Nov-1993
+ Use __C_ExecuteExceptionFilter and __C_ExecuteTerminationHandler
+ previously deleted from the MIPS version.
+--*/
+
+#include "nt.h"
+
+
+//
+// Define procedure prototypes for exception filter and termination handler
+// execution routines defined in jmpunwnd.s
+//
+LONG
+__C_ExecuteExceptionFilter (
+ PEXCEPTION_POINTERS ExceptionPointers,
+ EXCEPTION_FILTER ExceptionFilter,
+ ULONG EstablisherFrame
+ );
+VOID
+__C_ExecuteTerminationHandler (
+ BOOLEAN AbnormalTermination,
+ TERMINATION_HANDLER TerminationHandler,
+ ULONG EstablisherFrame
+ );
+
+EXCEPTION_DISPOSITION
+__C_specific_handler (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PVOID EstablisherFrame,
+ IN OUT PCONTEXT ContextRecord,
+ IN OUT PDISPATCHER_CONTEXT DispatcherContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function scans the scope tables associated with the specified
+ procedure and calls exception and termination handlers as necessary.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ EstablisherFrame - Supplies a pointer to frame of the establisher function.
+
+ ContextRecord - Supplies a pointer to a context record.
+
+ DispatcherContext - Supplies a pointer to the exception dispatcher or
+ unwind dispatcher context.
+
+Return Value:
+
+ If the exception is handled by one of the exception filter routines, then
+ there is no return from this routine and RtlUnwind is called. Otherwise,
+ an exception disposition value of continue execution or continue search is
+ returned.
+
+--*/
+
+{
+
+ ULONG ControlPc;
+ EXCEPTION_FILTER ExceptionFilter;
+ EXCEPTION_POINTERS ExceptionPointers;
+ PRUNTIME_FUNCTION FunctionEntry;
+ ULONG Index;
+ PSCOPE_TABLE ScopeTable;
+ ULONG TargetPc;
+ TERMINATION_HANDLER TerminationHandler;
+ LONG Value;
+
+ //
+ // Get address of where control left the establisher, the address of the
+ // function table entry that describes the function, and the address of
+ // the scope table.
+ //
+
+ ControlPc = DispatcherContext->ControlPc;
+ FunctionEntry = DispatcherContext->FunctionEntry;
+ ScopeTable = (PSCOPE_TABLE)(FunctionEntry->HandlerData);
+
+ //
+ // If an unwind is not in progress, then scan the scope table and call
+ // the appropriate exception filter routines. Otherwise, scan the scope
+ // table and call the appropriate termination handlers using the target
+ // PC obtained from the context record.
+ // are called.
+ //
+
+ if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) {
+
+ //
+ // Scan the scope table and call the appropriate exception filter
+ // routines.
+ //
+
+ ExceptionPointers.ExceptionRecord = ExceptionRecord;
+ ExceptionPointers.ContextRecord = ContextRecord;
+ for (Index = 0; Index < ScopeTable->Count; Index += 1) {
+ if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) &&
+ (ScopeTable->ScopeRecord[Index].JumpTarget != 0)) {
+
+ //
+ // Call the exception filter routine.
+ //
+
+ ExceptionFilter =
+ (EXCEPTION_FILTER)ScopeTable->ScopeRecord[Index].HandlerAddress;
+ Value = __C_ExecuteExceptionFilter(&ExceptionPointers,
+ ExceptionFilter,
+ (ULONG)EstablisherFrame);
+
+ //
+ // If the return value is less than zero, then dismiss the
+ // exception. Otherwise, if the value is greater than zero,
+ // then unwind to the target exception handler. Otherwise,
+ // continue the search for an exception filter.
+ //
+
+ if (Value < 0) {
+ return ExceptionContinueExecution;
+ } else if (Value > 0) {
+ RtlUnwind(EstablisherFrame,
+ (PVOID)ScopeTable->ScopeRecord[Index].JumpTarget,
+ ExceptionRecord,
+ (PVOID)ExceptionRecord->ExceptionCode);
+ }
+ }
+ }
+
+ } else {
+
+ //
+ // Scan the scope table and call the appropriate termination handler
+ // routines.
+ //
+
+ TargetPc = ContextRecord->Iar;
+ for (Index = 0; Index < ScopeTable->Count; Index += 1) {
+ if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress)) {
+
+ //
+ // If the target PC is within the same scope the control PC
+ // is within, then this is an uplevel goto out of an inner try
+ // scope or a long jump back into a try scope. Terminate the
+ // scan termination handlers.
+ //
+ // N.B. The target PC can be just beyond the end of the scope,
+ // in which case it is a leave from the scope.
+ //
+
+
+ if ((TargetPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (TargetPc <= ScopeTable->ScopeRecord[Index].EndAddress)) {
+ break;
+
+ } else {
+
+ //
+ // If the scope table entry describes an exception filter
+ // and the associated exception handler is the target of
+ // the unwind, then terminate the scan for termination
+ // handlers. Otherwise, if the scope table entry describes
+ // a termination handler, then record the address of the
+ // end of the scope as the new control PC address and call
+ // the termination handler.
+ //
+
+ if (ScopeTable->ScopeRecord[Index].JumpTarget != 0) {
+ if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) {
+ break;
+ }
+
+ } else {
+ DispatcherContext->ControlPc =
+ ScopeTable->ScopeRecord[Index].EndAddress + 4;
+ TerminationHandler =
+ (TERMINATION_HANDLER)ScopeTable->ScopeRecord[Index].HandlerAddress;
+ __C_ExecuteTerminationHandler(TRUE,
+ TerminationHandler,
+ (ULONG)EstablisherFrame);
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Continue search for exception or termination handlers.
+ //
+
+ return ExceptionContinueSearch;
+}
diff --git a/private/crt32/misc/ppc/cinitone.s b/private/crt32/misc/ppc/cinitone.s
new file mode 100644
index 000000000..f412234e0
--- /dev/null
+++ b/private/crt32/misc/ppc/cinitone.s
@@ -0,0 +1,41 @@
+// page ,132
+// title cinitone - C Run-Time Initialization for _onexit/atexit
+//
+// cinitone.asm - WIN32 C Run-Time Init for _onexit()/atexit() routines
+//
+// Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+//
+// Purpose:
+// Initialization entry for the _onexit()/atexit() functions.
+// This module adds an entry for _onexitinit() to the initializer table.
+// ONEXIT.C references the dummy variable __c_onexit in order to force
+// the loading of this module.
+//
+// Notes:
+//
+// Revision History:
+// 03-19-92 SKS Module created.
+// 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+// 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+// 08-06-92 SKS Revised to use new section names and macros
+//
+// *****************************************************************************
+
+#include "kxppc.h"
+
+ .extern _onexitinit
+
+beginSection(XIC)
+
+ .long _onexitinit
+
+endSection(XIC)
+
+
+ .data
+ .align 2
+
+ .globl __c_onexit
+
+__c_onexit: .long 0
+
diff --git a/private/crt32/misc/ppc/jmpuwind.s b/private/crt32/misc/ppc/jmpuwind.s
new file mode 100644
index 000000000..dcd129f29
--- /dev/null
+++ b/private/crt32/misc/ppc/jmpuwind.s
@@ -0,0 +1,162 @@
+//++
+//
+// Copyright (c) 1992 Microsoft Corporation
+//
+// Module Name:
+//
+// jmpuwind.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to jump to the runtime
+// time library unwind routine.
+//
+// Author:
+//
+// David N. Cutler (davec) 12-Sep-1990
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Tom Wood (twood) 1-Nov-1993
+// Added __C_ExecuteExceptionFilter and __C_ExecuteTerminationHandler
+// previously deleted from the MIPS version.
+//--
+
+//list(off)
+#include "ksppc.h"
+//list(on)
+ .extern ..RtlUnwind
+
+//
+// Define the call frame for calling the exception filter and termination
+// handler.
+//
+ .struct 0
+CfBackChain: .space 4 // chain to previous call frame
+CfSavedR31: .space 4 // glue-saved register
+CfSavedRtoc: .space 4 // glue-saved register
+ .space 3*4 // remaining part of the frame header
+//++
+//
+// ULONG
+// __C_ExecuteExceptionFilter (
+// PEXCEPTION_POINTERS ExceptionPointers,
+// EXCEPTION_FILTER ExceptionFilter,
+// ULONG EstablisherFrame
+// )
+//
+// Routine Description:
+//
+// This function calls the specified exception filter routine with the
+// establisher environment passed in the TOC register.
+//
+// Arguments:
+//
+// ExceptionPointers (r.3) - Supplies a pointer to the exception pointers
+// structure.
+//
+// ExceptionFilter (r.4) - Supplies the address of the exception filter
+// routine.
+//
+// EstablisherFrame (r.5) - Supplies the establisher frame pointer.
+//
+// Return Value:
+//
+// The value returned by the exception filter routine.
+//
+//--
+ SPECIAL_ENTRY(__C_ExecuteExceptionFilter)
+ stw r.31, CfSavedR31 (r.sp) // save r.31 before using it.
+ mtctr r.4 // get ready to call the filter.
+ mflr r.31 // save the link register in r.31.
+ stw r.toc, CfSavedRtoc (r.sp) // save r.toc
+ PROLOGUE_END(__C_ExecuteExceptionFilter)
+ or r.toc,r.5,r.5 // pass the establisher environment in r.toc
+ bctrl // branch and link to the filter.
+ mtlr r.31 // get ready to return
+ lwz r.31, CfSavedR31 (r.sp) // restore r.31
+ lwz r.toc, CfSavedRtoc (r.sp) // restore r.toc
+ SPECIAL_EXIT(__C_ExecuteExceptionFilter)
+
+//++
+//
+// VOID
+// __C_ExecuteTerminationHandler (
+// BOOLEAN AbnormalTermination,
+// TERMINATION_HANDLER TerminationHandler,
+// ULONG EstablisherFrame
+// )
+//
+// Routine Description:
+//
+// This function calls the specified termination handler routine with the
+// establisher environment passed in the TOC register.
+//
+// Arguments:
+//
+// AbnormalTermination (r.3) - Supplies a boolean value that determines
+// whether the termination is abnormal.
+//
+// TerminationHandler (r.4) - Supplies the address of the termination
+// handler routine.
+//
+// EstablisherFrame (r.5) - Supplies the establisher frame pointer.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ SPECIAL_ENTRY(__C_ExecuteTerminationHandler)
+ stw r.31, CfSavedR31 (r.sp) // save r.31 before using it.
+ mtctr r.4 // get ready to call the filter.
+ mflr r.31 // save the link register in r.31.
+ stw r.toc, CfSavedRtoc (r.sp) // save r.toc
+ PROLOGUE_END(__C_ExecuteTerminationHandler)
+ or r.toc,r.5,r.5 // pass the establisher environment in r.toc
+ bctrl // branch and link to the filter.
+ mtlr r.31 // get ready to return
+ lwz r.31, CfSavedR31 (r.sp) // restore r.31
+ lwz r.toc, CfSavedRtoc (r.sp) // restore r.toc
+ SPECIAL_EXIT(__C_ExecuteTerminationHandler)
+
+//++
+//
+// VOID
+// __jump_unwind (
+// IN PVOID EstablishFrame,
+// IN PVOID TargetPc
+// )
+//
+// Routine Description:
+//
+// This function transfer control to unwind. It is used by the MIPS
+// compiler when a goto out of the body or a try statement occurs.
+//
+// Arguments:
+//
+// EstablishFrame (r.3) - Supplies the establisher frame pointer of the
+// target of the unwind.
+//
+// TargetPc (r.4) - Supplies the target instruction address where control
+// is to be transfered to after the unwind operation is complete.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY (__jump_unwind, STK_MIN_FRAME+8, 0, 0)
+ PROLOGUE_END(__jump_unwind)
+
+ li r.5, 0 // set NULL exception record address
+ li r.6, 0 // set destination return value
+ bl ..RtlUnwind // unwind to specified target
+ .znop ..RtlUnwind
+
+ NESTED_EXIT (__jump_unwind, STK_MIN_FRAME+8, 0, 0)
diff --git a/private/crt32/misc/ppc/longjmp.s b/private/crt32/misc/ppc/longjmp.s
new file mode 100644
index 000000000..d5149f869
--- /dev/null
+++ b/private/crt32/misc/ppc/longjmp.s
@@ -0,0 +1,143 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation and Microsoft Corporation
+//
+// Module Name:
+//
+// longjmp.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to perform a long
+// jump operation.
+//
+// N.B. This routine conditionally provides UNSAFE handling of longjmp
+// which is NOT integrated with structured exception handling. The
+// determination is made based on whether an unitialized variable
+// has been set to a nonzero value.
+//
+// Author:
+//
+// Rick Simpson 13-Oct-1993
+//
+// based on MIPS version by David N. Cutler (davec) 2-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+//list(off)
+#include "ksppc.h"
+//list(on)
+ .extern ..RtlUnwind
+
+//++
+//
+// int
+// longjmp (
+// IN jmp_buf JumpBuffer,
+// IN int ReturnValue
+// )
+//
+// Routine Description:
+//
+// This function performs a long jump to the context specified by the
+// jump buffer.
+//
+// Arguments:
+//
+// JumpBuffer (r.3) - Supplies the address of a jump buffer that contains
+// jump information.
+//
+// ReturnValue (r.4) - Supplies the value that is to be returned to the
+// caller of setjmp().
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY (longjmp)
+
+ cmpwi cr.0, r.4, 0 // check return value for 0
+ lwz r.0, JbType (r.3) // load safe/unsafe switch
+ cmpwi cr.1, r.0, 0 // check for unsafe
+ bne cr.0, Lj10 // branch if not trying to return 0
+ li r.4, 1 // force return value to be non-zero
+Lj10: bne cr.1, ...Lj20 // branch if safe form of setjmp/longjmp
+
+//
+// Provide unsafe handling of longjmp.
+//
+
+ lfd f.14, JbFpr14 (r.3) // reload n-v floating point regs
+ lfd f.15, JbFpr15 (r.3)
+ lfd f.16, JbFpr16 (r.3)
+ lfd f.17, JbFpr17 (r.3)
+ lfd f.18, JbFpr18 (r.3)
+ lfd f.19, JbFpr19 (r.3)
+ lfd f.20, JbFpr20 (r.3)
+ lfd f.21, JbFpr21 (r.3)
+ lfd f.22, JbFpr22 (r.3)
+ lfd f.23, JbFpr23 (r.3)
+ lfd f.24, JbFpr24 (r.3)
+ lfd f.25, JbFpr25 (r.3)
+ lfd f.26, JbFpr26 (r.3)
+ lfd f.27, JbFpr27 (r.3)
+ lfd f.28, JbFpr28 (r.3)
+ lfd f.29, JbFpr29 (r.3)
+ lfd f.30, JbFpr30 (r.3)
+ lfd f.31, JbFpr31 (r.3)
+
+ lwz r.13, JbGpr13 (r.3) // reload n-v general regs
+ lwz r.14, JbGpr14 (r.3)
+ lwz r.15, JbGpr15 (r.3)
+ lwz r.16, JbGpr16 (r.3)
+ lwz r.17, JbGpr17 (r.3)
+ lwz r.18, JbGpr18 (r.3)
+ lwz r.19, JbGpr19 (r.3)
+ lwz r.20, JbGpr20 (r.3)
+ lwz r.21, JbGpr21 (r.3)
+ lwz r.22, JbGpr22 (r.3)
+ lwz r.23, JbGpr23 (r.3)
+ lwz r.24, JbGpr24 (r.3)
+ lwz r.25, JbGpr25 (r.3)
+ lwz r.26, JbGpr26 (r.3)
+ lwz r.27, JbGpr27 (r.3)
+ lwz r.28, JbGpr28 (r.3)
+ lwz r.29, JbGpr29 (r.3)
+ lwz r.30, JbGpr30 (r.3)
+ lwz r.31, JbGpr31 (r.3)
+
+ lwz r.5, JbIar (r.3) // get setjmp return address
+ lwz r.6, JbCr (r.3) // get saved CR
+ mtlr r.5 // return addr -> LR
+ lwz r.1, JbGpr1 (r.3) // restore stack pointer
+ lwz r.2, JbGpr2 (r.3) // restore TOC pointer
+ mtcrf 0xff,r.6 // saved CR -> CR
+ mr r.3, r.4 // return value from longjmp()
+ blr // jump back to setjmp() site
+
+ DUMMY_EXIT (longjmp)
+
+
+//
+// Provide safe handling of longjmp.
+//
+
+ NESTED_ENTRY(.Lj20, STK_MIN_FRAME+8, 0, 0)
+ PROLOGUE_END(.Lj20)
+
+ mr r.6, r.4 // set return value (4th arg)
+ li r.5, 0 // set exception record address (3rd arg)
+ lwz r.4, 4 (r.3) // set target instr address (2nd arg)
+ lwz r.3, 0 (r.3) // set target frame address (1st arg)
+ bl ..RtlUnwind // finish in common code
+ .znop ..RtlUnwind
+
+ NESTED_EXIT(.Lj20, STK_MIN_FRAME+8, 0, 0)
diff --git a/private/crt32/misc/ppc/miscasm.s b/private/crt32/misc/ppc/miscasm.s
new file mode 100644
index 000000000..8fab2f64e
--- /dev/null
+++ b/private/crt32/misc/ppc/miscasm.s
@@ -0,0 +1,273 @@
+//
+// Miscellaneous assembly-language routines and data for
+// PowerPC RTL
+//
+#include "ksppc.h"
+//
+// Copyright 1993 IBM Corporation
+//
+// By Rick Simpson, 17 August 1993
+//
+//-----------------------------------------------------------------------------
+//
+// These routines save and restore only the GPRs and FPRs.
+//
+// Saving and restoring of other non-volatile registers (LR, certain
+// fields of CR) is the responsibility of in-line prologue and epilogue
+// code.
+//
+//-----------------------------------------------------------------------------
+//
+// _savegpr_<n>
+// Inputs:
+// r12 = pointer to END of GPR save area
+// LR = return address to invoking prologue
+// Saves GPR<n> through GPR31 in area preceeding where r12 points
+//
+// _savefpr_<n>
+// Inputs:
+// r1 = pointer to stack frame header
+// LR = return address to invoking prologue
+// Saves FPR<m> through FPR31 in area preceeding stack frame header
+//
+//-----------------------------------------------------------------------------
+//
+// _restgpr_<n>
+// Inputs:
+// r12 = pointer to END of GPR save area
+// LR = return address to invoking prologue
+// Restores GPR<n> through GPR31 from area preceeding where r12 points
+//
+// _restfpr_<m>
+// Inputs:
+// r1 = pointer to stack frame header
+// LR = return address to invoking prologue
+// Restores FPR<m> through FPR31 from area preceeding stack frame header
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+//
+// _savegpr_<n> -- Save GPRs when FPRs are also saved
+//
+// On entry:
+// r12 = address of END of GPR save area
+// LR = return address to prologue
+//
+// Saves GPR<n> through GPR31 in area preceeding where r12 points
+//
+//-----------------------------------------------------------------------------
+
+ FN_TABLE(_savegpr_13,0,1)
+ DUMMY_ENTRY(_savegpr_13)
+ .set _savegpr_13.body,.._savegpr_13-1
+ stw r13, -4*(32-13)(r12)
+ DUMMY_ENTRY(_savegpr_14)
+ stw r14, -4*(32-14)(r12)
+ DUMMY_ENTRY(_savegpr_15)
+ stw r15, -4*(32-15)(r12)
+ DUMMY_ENTRY(_savegpr_16)
+ stw r16, -4*(32-16)(r12)
+ DUMMY_ENTRY(_savegpr_17)
+ stw r17, -4*(32-17)(r12)
+ DUMMY_ENTRY(_savegpr_18)
+ stw r18, -4*(32-18)(r12)
+ DUMMY_ENTRY(_savegpr_19)
+ stw r19, -4*(32-19)(r12)
+ DUMMY_ENTRY(_savegpr_20)
+ stw r20, -4*(32-20)(r12)
+ DUMMY_ENTRY(_savegpr_21)
+ stw r21, -4*(32-21)(r12)
+ DUMMY_ENTRY(_savegpr_22)
+ stw r22, -4*(32-22)(r12)
+ DUMMY_ENTRY(_savegpr_23)
+ stw r23, -4*(32-23)(r12)
+ DUMMY_ENTRY(_savegpr_24)
+ stw r24, -4*(32-24)(r12)
+ DUMMY_ENTRY(_savegpr_25)
+ stw r25, -4*(32-25)(r12)
+ DUMMY_ENTRY(_savegpr_26)
+ stw r26, -4*(32-26)(r12)
+ DUMMY_ENTRY(_savegpr_27)
+ stw r27, -4*(32-27)(r12)
+ DUMMY_ENTRY(_savegpr_28)
+ stw r28, -4*(32-28)(r12)
+ DUMMY_ENTRY(_savegpr_29)
+ stw r29, -4*(32-29)(r12)
+ DUMMY_ENTRY(_savegpr_30)
+ stw r30, -4*(32-30)(r12)
+ DUMMY_ENTRY(_savegpr_31)
+ stw r31, -4*(32-31)(r12)
+ SPECIAL_EXIT(_savegpr_13)
+
+//-----------------------------------------------------------------------------
+//
+// _savefpr_<n> -- Saves FPRs
+//
+// On entry:
+// r1 = pointer to stack frame header
+// LR = return address to prologue
+//
+// Saves FPR<n> through FPR31 in area preceeding stack frame header
+//
+//-----------------------------------------------------------------------------
+
+ FN_TABLE(_savefpr_14,0,1)
+ DUMMY_ENTRY(_savefpr_14)
+ .set _savefpr_14.body,.._savefpr_14-1
+ stfd f14, -8*(32-14)(r1)
+ DUMMY_ENTRY(_savefpr_15)
+ stfd f15, -8*(32-15)(r1)
+ DUMMY_ENTRY(_savefpr_16)
+ stfd f16, -8*(32-16)(r1)
+ DUMMY_ENTRY(_savefpr_17)
+ stfd f17, -8*(32-17)(r1)
+ DUMMY_ENTRY(_savefpr_18)
+ stfd f18, -8*(32-18)(r1)
+ DUMMY_ENTRY(_savefpr_19)
+ stfd f19, -8*(32-19)(r1)
+ DUMMY_ENTRY(_savefpr_20)
+ stfd f20, -8*(32-20)(r1)
+ DUMMY_ENTRY(_savefpr_21)
+ stfd f21, -8*(32-21)(r1)
+ DUMMY_ENTRY(_savefpr_22)
+ stfd f22, -8*(32-22)(r1)
+ DUMMY_ENTRY(_savefpr_23)
+ stfd f23, -8*(32-23)(r1)
+ DUMMY_ENTRY(_savefpr_24)
+ stfd f24, -8*(32-24)(r1)
+ DUMMY_ENTRY(_savefpr_25)
+ stfd f25, -8*(32-25)(r1)
+ DUMMY_ENTRY(_savefpr_26)
+ stfd f26, -8*(32-26)(r1)
+ DUMMY_ENTRY(_savefpr_27)
+ stfd f27, -8*(32-27)(r1)
+ DUMMY_ENTRY(_savefpr_28)
+ stfd f28, -8*(32-28)(r1)
+ DUMMY_ENTRY(_savefpr_29)
+ stfd f29, -8*(32-29)(r1)
+ DUMMY_ENTRY(_savefpr_30)
+ stfd f30, -8*(32-30)(r1)
+ DUMMY_ENTRY(_savefpr_31)
+ stfd f31, -8*(32-31)(r1)
+ SPECIAL_EXIT(_savefpr_14)
+
+//-----------------------------------------------------------------------------
+//
+// _restgpr_<n> -- Restore GPRs when FPRs are also restored
+//
+// On entry:
+// r12 = address of END of GPR save area
+// LR = return address
+//
+// Restores GPR<n> through GPR31 from area preceeding where r12 points
+//
+//-----------------------------------------------------------------------------
+
+ FN_TABLE(_restgpr_13,0,2)
+ DUMMY_ENTRY(_restgpr_13)
+ .set _restgpr_13.body,.._restgpr_13-2
+ lwz r13, -4*(32-13)(r12)
+ DUMMY_ENTRY(_restgpr_14)
+ lwz r14, -4*(32-14)(r12)
+ DUMMY_ENTRY(_restgpr_15)
+ lwz r15, -4*(32-15)(r12)
+ DUMMY_ENTRY(_restgpr_16)
+ lwz r16, -4*(32-16)(r12)
+ DUMMY_ENTRY(_restgpr_17)
+ lwz r17, -4*(32-17)(r12)
+ DUMMY_ENTRY(_restgpr_18)
+ lwz r18, -4*(32-18)(r12)
+ DUMMY_ENTRY(_restgpr_19)
+ lwz r19, -4*(32-19)(r12)
+ DUMMY_ENTRY(_restgpr_20)
+ lwz r20, -4*(32-20)(r12)
+ DUMMY_ENTRY(_restgpr_21)
+ lwz r21, -4*(32-21)(r12)
+ DUMMY_ENTRY(_restgpr_22)
+ lwz r22, -4*(32-22)(r12)
+ DUMMY_ENTRY(_restgpr_23)
+ lwz r23, -4*(32-23)(r12)
+ DUMMY_ENTRY(_restgpr_24)
+ lwz r24, -4*(32-24)(r12)
+ DUMMY_ENTRY(_restgpr_25)
+ lwz r25, -4*(32-25)(r12)
+ DUMMY_ENTRY(_restgpr_26)
+ lwz r26, -4*(32-26)(r12)
+ DUMMY_ENTRY(_restgpr_27)
+ lwz r27, -4*(32-27)(r12)
+ DUMMY_ENTRY(_restgpr_28)
+ lwz r28, -4*(32-28)(r12)
+ DUMMY_ENTRY(_restgpr_29)
+ lwz r29, -4*(32-29)(r12)
+ DUMMY_ENTRY(_restgpr_30)
+ lwz r30, -4*(32-30)(r12)
+ DUMMY_ENTRY(_restgpr_31)
+ lwz r31, -4*(32-31)(r12)
+ SPECIAL_EXIT(_restgpr_13)
+
+//-----------------------------------------------------------------------------
+//
+// _restfpr_<n> -- Restores FPRs
+//
+// On entry:
+// r1 = pointer to stack frame header
+// LR = return address
+//
+// Restores FPR<n> through FPR31 from area preceeding stack frame header
+//
+//-----------------------------------------------------------------------------
+
+ FN_TABLE(_restfpr_14,0,2)
+ DUMMY_ENTRY(_restfpr_14)
+ .set _restfpr_14.body,.._restfpr_14-2
+ lfd f14, -8*(32-14)(r1)
+ DUMMY_ENTRY(_restfpr_15)
+ lfd f15, -8*(32-15)(r1)
+ DUMMY_ENTRY(_restfpr_16)
+ lfd f16, -8*(32-16)(r1)
+ DUMMY_ENTRY(_restfpr_17)
+ lfd f17, -8*(32-17)(r1)
+ DUMMY_ENTRY(_restfpr_18)
+ lfd f18, -8*(32-18)(r1)
+ DUMMY_ENTRY(_restfpr_19)
+ lfd f19, -8*(32-19)(r1)
+ DUMMY_ENTRY(_restfpr_20)
+ lfd f20, -8*(32-20)(r1)
+ DUMMY_ENTRY(_restfpr_21)
+ lfd f21, -8*(32-21)(r1)
+ DUMMY_ENTRY(_restfpr_22)
+ lfd f22, -8*(32-22)(r1)
+ DUMMY_ENTRY(_restfpr_23)
+ lfd f23, -8*(32-23)(r1)
+ DUMMY_ENTRY(_restfpr_24)
+ lfd f24, -8*(32-24)(r1)
+ DUMMY_ENTRY(_restfpr_25)
+ lfd f25, -8*(32-25)(r1)
+ DUMMY_ENTRY(_restfpr_26)
+ lfd f26, -8*(32-26)(r1)
+ DUMMY_ENTRY(_restfpr_27)
+ lfd f27, -8*(32-27)(r1)
+ DUMMY_ENTRY(_restfpr_28)
+ lfd f28, -8*(32-28)(r1)
+ DUMMY_ENTRY(_restfpr_29)
+ lfd f29, -8*(32-29)(r1)
+ DUMMY_ENTRY(_restfpr_30)
+ lfd f30, -8*(32-30)(r1)
+ DUMMY_ENTRY(_restfpr_31)
+ lfd f31, -8*(32-31)(r1)
+ SPECIAL_EXIT(_restfpr_14)
+
+//
+// This is a copy of the function table entries for the millicode. It's
+// used with the PPCKD_SYMBOL_SEARCH mechanism in vunwind.c to allow
+// for older versions of miscasm.obj.
+//
+
+ .reldata
+ .globl _millicode_table
+_millicode_table:
+ .long .._savegpr_13, _savegpr_13.end, 0, 1, .._savegpr_13
+ .long .._savefpr_14, _savefpr_14.end, 0, 1, .._savefpr_14
+ .long .._restgpr_13, _restgpr_13.end, 0, 2, .._restgpr_13
+ .long .._restfpr_14, _restfpr_14.end, 0, 2, .._restfpr_14
diff --git a/private/crt32/misc/ppc/setjmp.s b/private/crt32/misc/ppc/setjmp.s
new file mode 100644
index 000000000..65b58adf5
--- /dev/null
+++ b/private/crt32/misc/ppc/setjmp.s
@@ -0,0 +1,138 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation and Microsoft Corporation
+//
+// Module Name:
+//
+// setjmp.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to perform a setjmp.
+//
+// N.B. This module conditionally provides UNSAFE handling of setjmp and
+// which is NOT integrated with structured exception handling. The
+// determination is made based on whether an uninitialized variable
+// has been set to a nonzero value.
+//
+// Author:
+//
+// Rick Simpson 13-Oct-1993
+//
+// based on MIPS version by David N. Cutler (davec) 7-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+//list(off)
+#include "ksppc.h"
+//list(on)
+
+//
+// Define variable that will cause setjmp/longjmp to be safe or unsafe with
+// respect to structured exception handling.
+//
+
+ .globl _setjmpexused
+ .comm _setjmpexused , 4
+
+//++
+//
+// int
+// setjmp (
+// IN jmp_buf JumpBuffer
+// )
+//
+// Routine Description:
+//
+// This function saved the current nonvolatile register state in the
+// specified jump buffer and returns a function vlaue of zero.
+//
+// Arguments:
+//
+// JumpBuffer (r.3) - Supplies the address of a jump buffer to store the
+// jump information.
+//
+// Return Value:
+//
+// A value of zero is returned.
+//
+//--
+
+ LEAF_ENTRY (setjmp)
+
+//
+// If _setjmpexused is non-NULL, it contains the entry point address
+// of the safe version of setjmp, ..setjmpex. We branch thru the CTR
+// using this variable rather than branching directly to the entry point
+// to avoid assembling a hard reference to ..setjmpex into this code.
+// CTR is used to avoid killing caller's LR.
+//
+
+ lwz r.4, [toc] _setjmpexused (r.toc) // get address of switch variable
+ lwz r.0, 0 (r.4) // get value of switch variable
+ cmpwi r.0, 0 // see if switch is NULL
+ mtctr r.0 // if switch is non-NULL,
+ bnectr // branch to safe setjmp() routine
+
+//
+// Provide unsafe handling of setjmp.
+//
+
+ mflr r.0 // fetch incoming LR
+ mfcr r.4 // fetch incoming CR
+
+ stfd f.14, JbFpr14 (r.3) // save n-v floating point regs
+ stfd f.15, JbFpr15 (r.3)
+ stfd f.16, JbFpr16 (r.3)
+ stfd f.17, JbFpr17 (r.3)
+ stfd f.18, JbFpr18 (r.3)
+ stfd f.19, JbFpr19 (r.3)
+ stfd f.20, JbFpr20 (r.3)
+ stfd f.21, JbFpr21 (r.3)
+ stfd f.22, JbFpr22 (r.3)
+ stfd f.23, JbFpr23 (r.3)
+ stfd f.24, JbFpr24 (r.3)
+ stfd f.25, JbFpr25 (r.3)
+ stfd f.26, JbFpr26 (r.3)
+ stfd f.27, JbFpr27 (r.3)
+ stfd f.28, JbFpr28 (r.3)
+ stfd f.29, JbFpr29 (r.3)
+ stfd f.30, JbFpr30 (r.3)
+ stfd f.31, JbFpr31 (r.3)
+
+ stw r.13, JbGpr13 (r.3) // save n-v general regs
+ stw r.14, JbGpr14 (r.3)
+ stw r.15, JbGpr15 (r.3)
+ stw r.16, JbGpr16 (r.3)
+ stw r.17, JbGpr17 (r.3)
+ stw r.18, JbGpr18 (r.3)
+ stw r.19, JbGpr19 (r.3)
+ stw r.20, JbGpr20 (r.3)
+ stw r.21, JbGpr21 (r.3)
+ stw r.22, JbGpr22 (r.3)
+ stw r.23, JbGpr23 (r.3)
+ stw r.24, JbGpr24 (r.3)
+ stw r.25, JbGpr25 (r.3)
+ stw r.26, JbGpr26 (r.3)
+ stw r.27, JbGpr27 (r.3)
+ stw r.28, JbGpr28 (r.3)
+ stw r.29, JbGpr29 (r.3)
+ stw r.30, JbGpr30 (r.3)
+ stw r.31, JbGpr31 (r.3)
+
+ stw r.0, JbIar (r.3) // setjmp return address
+ stw r.4, JbCr (r.3) // save CR (n-v part)
+ stw r.sp, JbGpr1 (r.3) // save stack pointer
+ stw r.toc, JbGpr2 (r.3) // save TOC pointer
+ li r.0, 0
+ stw r.0, JbType (r.3) // clean safe setjmp flag
+
+ li r.3, 0 // set return value
+ LEAF_EXIT (setjmp) // return
+
diff --git a/private/crt32/misc/ppc/setjmpex.s b/private/crt32/misc/ppc/setjmpex.s
new file mode 100644
index 000000000..063f8fa68
--- /dev/null
+++ b/private/crt32/misc/ppc/setjmpex.s
@@ -0,0 +1,194 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation and Microsoft Corporation
+//
+// Module Name:
+//
+// setjmpex.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to provide SAFE
+// handling of setjmp/longjmp with respect to structured exception
+// handling.
+//
+// Author:
+//
+// Rick Simpson 13-Oct-1993
+//
+// based on MIPS version by David N. Cutler (davec) 2-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Tom Wood 23-Aug-1994
+// Add stack limit parameters to RtlVirtualUnwind.
+//--
+
+//list(off)
+#include "ksppc.h"
+//list(on)
+ .extern ..RtlLookupFunctionEntry
+ .extern ..RtlVirtualUnwind
+
+//
+// Define variable that will cause setjmp/longjmp to be safe with respect
+// to structured exception handling.
+//
+
+ .globl _setjmpexused
+ .data
+_setjmpexused:
+ .long .._setjmpex // set address of safe setjmp routine
+
+//++
+//
+// int
+// _setjmpex (
+// IN jmp_buf JumpBuffer
+// )
+//
+// Routine Description:
+//
+// This function transfers control to the actual setjmp routine.
+//
+// Arguments:
+//
+// JumpBuffer (r.3) - Supplies the address of a jump buffer to store the
+// jump information.
+//
+// Return Value:
+//
+// A value of zero is returned.
+//
+//--
+
+// Stack frame definition:
+
+ .struct 0
+SjBackChain: .space 4 // chain to previous stack frame
+ .space 5*4 // rest of standard stack frame header
+
+ .space 8*4 // standard outgoing arg area
+
+ .align 3 // ensure 8-byte boundary
+SjCtxt: .space ContextFrameLength // context frame
+
+SjFl: .space 4 // in function flag variable
+
+ .align 3 // ensure that overall length
+ // will be a multiple of 8
+SjReturnAddr: .space 4 // space for saved LR (prologue will
+ // store it here)
+ .space 4 // space for saved r.31
+SetjmpFrameLength:
+
+
+
+ NESTED_ENTRY (_setjmpex,SetjmpFrameLength,1,0)
+
+ PROLOGUE_END (_setjmpex)
+
+//
+// Save the nonvolatile machine state in the context record
+//
+
+ // skip Fprs as all we are really trying to do here is prime the
+ // pump for RtlVirtualUnwind.
+
+ stw r.13, CxGpr13 + SjCtxt (r.sp) // save n-v general regs
+ stw r.14, CxGpr14 + SjCtxt (r.sp)
+ stw r.15, CxGpr15 + SjCtxt (r.sp)
+ stw r.16, CxGpr16 + SjCtxt (r.sp)
+ stw r.17, CxGpr17 + SjCtxt (r.sp)
+ stw r.18, CxGpr18 + SjCtxt (r.sp)
+ stw r.19, CxGpr19 + SjCtxt (r.sp)
+ stw r.20, CxGpr20 + SjCtxt (r.sp)
+ stw r.21, CxGpr21 + SjCtxt (r.sp)
+ stw r.22, CxGpr22 + SjCtxt (r.sp)
+ stw r.23, CxGpr23 + SjCtxt (r.sp)
+ stw r.24, CxGpr24 + SjCtxt (r.sp)
+ stw r.25, CxGpr25 + SjCtxt (r.sp)
+ stw r.26, CxGpr26 + SjCtxt (r.sp)
+ stw r.27, CxGpr27 + SjCtxt (r.sp)
+ stw r.28, CxGpr28 + SjCtxt (r.sp)
+ stw r.29, CxGpr29 + SjCtxt (r.sp)
+ stw r.30, CxGpr30 + SjCtxt (r.sp)
+ stw r.31, CxGpr31 + SjCtxt (r.sp)
+
+ mr r.31, r.3 // save incoming jump buffer pointer
+
+ lwz r.3, SjReturnAddr (r.sp) // pick up return addr to caller
+ la r.0, SetjmpFrameLength (r.sp) // save caller's stack frame pointer
+ stw r.0, CxGpr1 + SjCtxt (r.sp)
+ stw r.3, CxIar + SjCtxt (r.sp) // save resume addr in context
+ stw r.3, 4 (r.31) // save resume addr in 2nd word of jmpbuf
+ stw r.sp, JbType (r.31) // set "safe setjmp" flag in jump buffer
+
+//
+// Perform unwind to determine the virtual frame pointer of the caller.
+//
+ subi r.3, r.3, 4 // compute control PC address
+ bl ..RtlLookupFunctionEntry // lookup function table address
+ .znop ..RtlLookupFunctionEntry
+
+ mr r.4, r.3 // set returned value as 2nd arg
+ lwz r.3, SjReturnAddr (r.sp) // pick up return address again
+ la r.5, SjCtxt (r.sp) // context record addr is 3rd arg
+ la r.6, SjFl (r.sp) // addr of in-func flag is 4th arg
+ subi r.3, r.3, 4 // compute control PC address as 1st arg
+ mr r.7, r.31 // addr of 1st word of jmpbuf is 5th arg
+ // (virt frame pointer will be stored here)
+ li r.8, 0 // ctxt pointers (NULL) is 6th arg
+ li r.9, 0 // low stack limit is 7th arg
+ li r.10, -1 // high stack limit is 8th arg
+ bl ..RtlVirtualUnwind // compute virtual frame pointer value
+ .znop ..RtlVirtualUnwind
+
+//
+// If we were called via a thunk the Establisher Frame derived by
+// RtlVirtualUnwind will be equal to the current stack frame. If
+// this is the case we need to unwind one more level, also, the
+// ControlPc returned by RtlVirtualUnwind (+4) should be used as
+// the resume address.
+//
+// Note: this requirement will go away if we adopt the glue proposal
+// that returns directly to the caller (caller reloades toc).
+// (plj 3/26/94)
+
+ lwz r.7, 0(r.31) // Establisher Frame
+ addi r.8, r.sp, SetjmpFrameLength // caller's sp
+ cmplw r.7, r.8
+ bne SjDone
+
+ // Save returned value (+4) as resume address in jump buffer
+
+ addi r.8, r.3, 4
+ stw r.8, 4(r.31)
+
+ // Unwind one more level to get the "real" establisher frame.
+
+ bl ..RtlLookupFunctionEntry // lookup function table address
+ .znop ..RtlLookupFunctionEntry
+
+ mr r.4, r.3 // set returned value as 2nd arg
+ lwz r.3, 4(r.31) // pick up ControlPc again
+ la r.5, SjCtxt(r.sp) // &context record
+ la r.6, SjFl(r.sp) // addr of in-func flag
+ mr r.7, r.31 // & 1st word of jmpbuf
+ li r.8, 0 // ctxt pointers (NULL)
+ li r.9, 0 // low stack limit
+ li r.10, -1 // high stack limit
+ subi r.3, r.3, 4 // unadjust ControlPc
+ bl ..RtlVirtualUnwind // compute & frame pointer
+ .znop ..RtlVirtualUnwind
+//
+// Set return value, restore registers, deallocate stack frame, and return.
+//
+
+SjDone:
+ li r.3, 0 // set return value of 0
+ NESTED_EXIT (_setjmpex,SetjmpFrameLength,1,0)
diff --git a/private/crt32/misc/ppc/sources b/private/crt32/misc/ppc/sources
new file mode 100644
index 000000000..520ce611c
--- /dev/null
+++ b/private/crt32/misc/ppc/sources
@@ -0,0 +1,6 @@
+PPC_SOURCES=ppc\chandler.c \
+ ppc\setjmp.s \
+ ppc\setjmpex.s \
+ ppc\longjmp.s \
+ ppc\jmpuwind.s \
+ ppc\miscasm.s
diff --git a/private/crt32/misc/purevirt.c b/private/crt32/misc/purevirt.c
new file mode 100644
index 000000000..14743f517
--- /dev/null
+++ b/private/crt32/misc/purevirt.c
@@ -0,0 +1,42 @@
+/***
+*purevirt.c - stub to trap pure virtual function calls
+*
+* Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _purecall() -
+*
+*Revision History:
+* 09-30-92 GJF Module created
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <internal.h>
+#include <rterr.h>
+
+/***
+*void _purecall(void) -
+*
+*Purpose:
+*
+*Entry:
+* No arguments
+*
+*Exit:
+* Never returns
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _purecall(
+ void
+ )
+{
+ _amsg_exit(_RT_PUREVIRT);
+}
+
+#endif
diff --git a/private/crt32/misc/putenv.c b/private/crt32/misc/putenv.c
new file mode 100644
index 000000000..0e74fcbb5
--- /dev/null
+++ b/private/crt32/misc/putenv.c
@@ -0,0 +1,453 @@
+/***
+*putenv.c - put an environment variable into the environment
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _putenv() - adds a new variable to environment; does not
+* change global environment, only the process' environment.
+*
+*Revision History:
+* 08-08-84 RN initial version
+* 02-23-88 SKS check for environment containing only the NULL string
+* 05-31-88 PHG Merged DLL and normal versions
+* 07-14-88 JCR Much simplified since (1) __setenvp always uses heap, and
+* (2) envp array and env strings are in seperate heap blocks
+* 07-03-89 PHG Now "option=" string removes string from environment
+* 08-17-89 GJF Removed _NEAR_, _LOAD_DS and fixed indents.
+* 09-14-89 KRS Don't give error if 'option' not defined in "option=".
+* 11-20-89 GJF Added const to arg type. Also, fixed copyright.
+* 03-15-90 GJF Made the calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 04-05-90 GJF Made findenv() _CALLTYPE4.
+* 04-26-90 JCR Bug fix if environ is NULL (stubbed out _setenvp)
+* 07-25-90 SBM Removed redundant include (stdio.h)
+* 10-04-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 02-06-91 SRW Added _WIN32_ conditional for SetEnvironmentVariable
+* 02-18-91 SRW Changed _WIN32_ conditional for SetEnvironmentVariable
+* to be in addition to old logic instead of replacement
+* 04-23-92 GJF Made findenv insensitive to the case of name for Win32.
+* Also added support for 'current drive' environment
+* strings in Win32.
+* 04-29-92 GJF Repackaged so that _putenv_lk could be easily added for
+* for Win32.
+* 05-05-92 DJM POSIX not supported.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <memory.h>
+#include <oscalls.h>
+
+static int _CALLTYPE4 findenv(const char *name, int len);
+
+
+#ifdef _CRUISER_
+
+/***
+*int _putenv(option) - add/replace/remove variable in environment
+*
+*Purpose:
+* option should be of the form "option=value". If a string with the
+* given option part already exists, it is replaced with the given
+* string; otherwise the given string is added to the environment.
+* If the string is of the form "option=", then the string is
+* removed from the environment, if it exists. If the string has
+* no equals sign, error is returned.
+*
+*Entry:
+* char *option - option string to set in the environment list.
+* should be of the form "option=value".
+*
+*Exit:
+* returns 0 if OK, -1 if fails.
+*
+*Exceptions:
+*
+*Warning:
+* This code will not work if variables are removed from the
+* environment by deleting them from environ[]. Use _putenv("option=")
+* to remove a variable.
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _putenv (
+ REG3 const char *option
+ )
+{
+ REG1 char **env;
+ REG4 const char *equal;
+ REG2 int ix;
+ int remove; /* 1 means remove string from environment */
+
+ if (!option)
+ return(-1);
+
+ _mlock( _ENV_LOCK );
+
+ /* find the equal sign to delimit the name being searched for.
+ * If no equal sign, then return error
+ */
+
+ for (equal = option; *equal != '='; equal++)
+ if (*equal == '\0')
+ goto unlock_error;
+
+ /* see if removing or adding */
+ remove = (equal[1] == '\0');
+
+ /* see if _environ array exists */
+ if (_environ == NULL) {
+ if (remove)
+ goto unlock_good;
+ else {
+ /* get an array and init it to NULL */
+ if ( (_environ = malloc(sizeof(void *))) == NULL)
+ goto unlock_error;
+ *_environ = NULL;
+ }
+ }
+
+ /* init env pointer */
+
+ env = _environ;
+
+ /* See if the string is already in the environment */
+
+ ix = findenv(option, equal - option);
+
+ if ((ix >= 0) && (*env != NULL)) {
+ /* String is already in the environment -- overwrite/remove it.
+ */
+ if (remove) {
+ /* removing -- move all the later strings up */
+ for ( ; env[ix] != NULL; ++ix) {
+ env[ix] = env[ix+1];
+ }
+
+ /* shrink the environment memory block
+ (ix now has number of strings, including NULL) --
+ this realloc probably can't fail, since we're
+ shrinking a mem block, but we're careful anyway. */
+ if (env = (char **) realloc(env, ix * sizeof(char *)))
+ _environ = env;
+ }
+ else {
+ /* replace the option */
+ env[ix] = (char *) option;
+ }
+ }
+ else {
+ /* String is NOT in the environment */
+
+ if (!remove) { /* can't remove something that's not there */
+
+ /* Grow vector table by one */
+ if (ix < 0)
+ ix = -ix; /* ix = length of environ table */
+
+ if (!(env = (char **)realloc(env, sizeof(char *) * (ix + 2))))
+ goto unlock_error;
+
+ env[ix] = (char *)option;
+ env[ix + 1] = NULL;
+ _environ = env;
+ }
+ }
+
+unlock_good:
+ _munlock( _ENV_LOCK );
+ return(0);
+
+unlock_error:
+ _munlock( _ENV_LOCK );
+ return -1;
+}
+
+
+/***
+*int findenv(name, len) - [STATIC]
+*
+*Purpose:
+* Scan for the given string within the environment
+*
+*Entry:
+*
+*Exit:
+* Returns the offset in "environ[]" of the given variable
+* Returns the negative of the length of environ[] if not found.
+* Returns 0 if the environment is empty.
+*
+* [NOTE: That a 0 return can mean that the environment is empty
+* or that the string was found as the first entry in the array.]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 findenv (
+ const char *name,
+ int len
+ )
+{
+ REG4 char **env = _environ;
+ REG2 const char *nm;
+ REG1 char *envname;
+ REG3 int l;
+
+
+ while (envname = *env) {
+ nm = name;
+ l = len;
+ while (l && *envname++ == *nm++)
+ l--;
+
+ if (l == 0 && ( *envname == '=' || !*envname ) )
+ return(env - _environ);
+ env++;
+ }
+
+ return(-(env - _environ));
+
+}
+
+#else /* _CRUISER_ */
+
+#ifdef _WIN32_
+
+/***
+*int _putenv(option) - add/replace/remove variable in environment
+*
+*Purpose:
+* option should be of the form "option=value". If a string with the
+* given option part already exists, it is replaced with the given
+* string; otherwise the given string is added to the environment.
+* If the string is of the form "option=", then the string is
+* removed from the environment, if it exists. If the string has
+* no equals sign, error is returned.
+*
+*Entry:
+* char *option - option string to set in the environment list.
+* should be of the form "option=value".
+*
+*Exit:
+* returns 0 if OK, -1 if fails.
+*
+*Exceptions:
+*
+*Warning:
+* This code will not work if variables are removed from the
+* environment by deleting them from environ[]. Use _putenv("option=")
+* to remove a variable.
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+int _CALLTYPE1 _putenv (
+ const char *option
+ )
+{
+ int retval;
+
+ _mlock(_ENV_LOCK);
+
+ retval = _putenv_lk(option);
+
+ _munlock(_ENV_LOCK);
+
+ return retval;
+}
+
+int _CALLTYPE1 _putenv_lk (
+ const char *option
+ )
+
+#else /* ndef MTHREAD */
+
+int _CALLTYPE1 _putenv (
+ const char *option
+ )
+
+#endif /* MTHREAD */
+
+{
+ char **env;
+ const char *equal;
+ char *name, *value;
+ int ix;
+ int remove; /* 1 means remove string from environment */
+
+ /* check that the option string is valid and find the equal sign
+ */
+ if ( (option == NULL) || ((equal = strchr(option, '=')) == NULL) )
+ return(-1);
+
+ /* check for the special case of '=' being the very first character
+ * of option. though the use of '=' in an environment variable name
+ * is documented as being illegal, the 'current directory' strings
+ * all look like this:
+ *
+ * =<Drive Letter>:=<Drive Letter><fully qualified path>
+ *
+ * handle this by setting the equal pointer to point to the second
+ * '=' if it exists. Otherwise, handle as before.
+ */
+ if ( option == equal )
+ if ( (equal = strchr(option + 1, '=')) == NULL )
+ equal = option;
+
+ /* if the character following '=' is null, we are removing the
+ * the environment variable. Otherwise, we are adding or updating
+ * an environment variable.
+ */
+ remove = (*(equal + 1) == '\0');
+
+ /* see if _environ array exists */
+ if (_environ == NULL) {
+ if ( remove )
+ return 0;
+ else {
+ /* get an array and init it to NULL */
+ if ( (_environ = malloc(sizeof(void *))) == NULL)
+ return -1;
+ *_environ = NULL;
+ }
+ }
+
+ /* init env pointer */
+
+ env = _environ;
+
+ /* See if the string is already in the environment */
+
+ ix = findenv(option, equal - option);
+
+ if ((ix >= 0) && (*env != NULL)) {
+ /* String is already in the environment -- overwrite/remove it.
+ */
+ if (remove) {
+ /* removing -- move all the later strings up */
+ for ( ; env[ix] != NULL; ++ix) {
+ env[ix] = env[ix+1];
+ }
+
+ /* shrink the environment memory block
+ (ix now has number of strings, including NULL) --
+ this realloc probably can't fail, since we're
+ shrinking a mem block, but we're careful anyway. */
+ if (env = (char **) realloc(env, ix * sizeof(char *)))
+ _environ = env;
+ }
+ else {
+ /* replace the option */
+ env[ix] = (char *) option;
+ }
+ }
+ else {
+ /*
+ * String is NOT in the environment
+ */
+ if ( !remove ) {
+
+ /*
+ * Append the string to the environ table. Note that
+ * table must be grown to do this.
+ */
+ if (ix < 0)
+ ix = -ix; /* ix = length of environ table */
+
+ if ( (env = (char **)realloc(env, sizeof(char *) *
+ (ix + 2))) == NULL )
+ return -1;
+
+ env[ix] = (char *)option;
+ env[ix + 1] = NULL;
+ _environ = env;
+ }
+ else
+ /*
+ * We are asked to remove an environment var that
+ * isn't there...just return success
+ */
+ return 0;
+ }
+
+ /*
+ * Update the real environment. Don't give an error if this fails
+ * since the failure will not affect the user unless he/she is making
+ * direct API calls.
+ */
+ if ( (name = malloc(strlen(option) + 2)) != NULL ) {
+ strcpy(name, option);
+ value = name + (equal - option);
+ *value++ = '\0';
+ SetEnvironmentVariable(name, remove ? NULL : value);
+ free(name);
+ }
+
+ return 0;
+}
+
+
+/***
+*int findenv(name, len) - [STATIC]
+*
+*Purpose:
+* Scan for the given string within the environment
+*
+*Entry:
+*
+*Exit:
+* Returns the offset in "environ[]" of the given variable
+* Returns the negative of the length of environ[] if not found.
+* Returns 0 if the environment is empty.
+*
+* [NOTE: That a 0 return can mean that the environment is empty
+* or that the string was found as the first entry in the array.]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 findenv (
+ const char *name,
+ int len
+ )
+{
+ char **env;
+
+ for ( env = _environ ; *env != NULL ; env++ ) {
+ /*
+ * See if first len characters match, up to case
+ */
+ if ( _strnicmp(name, *env, len) == 0 )
+ /*
+ * the next character of the environment string must
+ * be an '=' or a '\0'
+ */
+ if ( (*env)[len] == '=' || (*env)[len] == '\0' )
+ return(env - _environ);
+//
+// We cannot break here since findenv must report the total number of strings.
+// else
+// break;
+ }
+
+ return(-(env - _environ));
+}
+
+
+#endif /* _WIN32_ */
+#endif /* _CRUISER_ */
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/misc/qsort.c b/private/crt32/misc/qsort.c
new file mode 100644
index 000000000..30e15e6fd
--- /dev/null
+++ b/private/crt32/misc/qsort.c
@@ -0,0 +1,329 @@
+/***
+*qsort.c - quicksort algorithm; qsort() library function for sorting arrays
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* To implement the qsort() routine for sorting arrays.
+*
+*Revision History:
+* 06-22-84 RN author
+* 03-25-85 RN added pre-check for elements already in order to
+* eliminate worst-case behavior.
+* 05-18-86 TC changed to recurse on the smallest piece to avoid
+* piece. unneccesary stack usage, and to iterate on
+* largest
+* 01-09-87 BCM fixed huge-array case where (num-1) * wid computation
+* was overflowing (large/compact models only)
+* 06-13-89 PHG made more efficient, many more comments, removed
+* recursion
+* 10-30-89 JCR Added _cdecl to prototypes
+* 03-15-90 GJF Replaced _cdecl with _CALLTYPE1 and added #include
+* <cruntime.h>. Also, fixed the copyright.
+* 04-05-90 GJF Made shortsort() and swap() _CALLTYPE4. Also, added
+* #include <search.h>.
+* 10-04-90 GJF New-style function declarators.
+* 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragmas
+* 01-24-91 SRW Added missing close comment in swap procedure
+* 11-19-91 GJF Do the swap one character at a time to avoid alignment
+* woes.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <search.h>
+
+/* prototypes for local routines */
+static void _CALLTYPE4 shortsort(char *lo, char *hi, unsigned width,
+ int (_CALLTYPE1 *comp)(const void *, const void *));
+static void _CALLTYPE4 swap(char *p, char *q, unsigned int width);
+
+/* this parameter defines the cutoff between using quick sort and
+ insertion sort for arrays; arrays with lengths shorter or equal to the
+ below value use insertion sort */
+
+#define CUTOFF 8 /* testing shows that this is good value */
+
+
+/***
+*qsort(base, num, wid, comp) - quicksort function for sorting arrays
+*
+*Purpose:
+* quicksort the array of elements
+* side effects: sorts in place
+*
+*Entry:
+* char *base = pointer to base of array
+* unsigned num = number of elements in the array
+* unsigned width = width in bytes of each array element
+* int (*comp)() = pointer to function returning analog of strcmp for
+* strings, but supplied by user for comparing the array elements.
+* it accepts 2 pointers to elements and returns neg if 1<2, 0 if
+* 1=2, pos if 1>2.
+*
+*Exit:
+* returns void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef _CRUISER_
+#pragma check_stack(on) /* lots of locals */
+#endif /* ndef _CRUISER_ */
+
+/* sort the array between lo and hi (inclusive) */
+
+void _CALLTYPE1 qsort (
+ void *base,
+ unsigned num,
+ unsigned width,
+ int (_CALLTYPE1 *comp)(const void *, const void *)
+ )
+{
+ char *lo, *hi; /* ends of sub-array currently sorting */
+ char *mid; /* points to middle of subarray */
+ char *loguy, *higuy; /* traveling pointers for partition step */
+ unsigned size; /* size of the sub-array */
+ char *lostk[30], *histk[30];
+ int stkptr; /* stack for saving sub-array to be processed */
+
+ /* Note: the number of stack entries required is no more than
+ 1 + log2(size), so 30 is sufficient for any array */
+
+ if (num < 2 || width == 0)
+ return; /* nothing to do */
+
+ stkptr = 0; /* initialize stack */
+
+ lo = base;
+ hi = (char *)base + width * (num-1); /* initialize limits */
+
+ /* this entry point is for pseudo-recursion calling: setting
+ lo and hi and jumping to here is like recursion, but stkptr is
+ prserved, locals aren't, so we preserve stuff on the stack */
+recurse:
+
+ size = (hi - lo) / width + 1; /* number of el's to sort */
+
+ /* below a certain size, it is faster to use a O(n^2) sorting method */
+ if (size <= CUTOFF) {
+ shortsort(lo, hi, width, comp);
+ }
+ else {
+ /* First we pick a partititioning element. The efficiency of the
+ algorithm demands that we find one that is approximately the
+ median of the values, but also that we select one fast. Using
+ the first one produces bad performace if the array is already
+ sorted, so we use the middle one, which would require a very
+ wierdly arranged array for worst case performance. Testing shows
+ that a median-of-three algorithm does not, in general, increase
+ performance. */
+
+ mid = lo + (size / 2) * width; /* find middle element */
+ swap(mid, lo, width); /* swap it to beginning of array */
+
+ /* We now wish to partition the array into three pieces, one
+ consisiting of elements <= partition element, one of elements
+ equal to the parition element, and one of element >= to it. This
+ is done below; comments indicate conditions established at every
+ step. */
+
+ loguy = lo;
+ higuy = hi + width;
+
+ /* Note that higuy decreases and loguy increases on every iteration,
+ so loop must terminate. */
+ for (;;) {
+ /* lo <= loguy < hi, lo < higuy <= hi + 1,
+ A[i] <= A[lo] for lo <= i <= loguy,
+ A[i] >= A[lo] for higuy <= i <= hi */
+
+ do {
+ loguy += width;
+ } while (loguy <= hi && comp(loguy, lo) <= 0);
+
+ /* lo < loguy <= hi+1, A[i] <= A[lo] for lo <= i < loguy,
+ either loguy > hi or A[loguy] > A[lo] */
+
+ do {
+ higuy -= width;
+ } while (higuy > lo && comp(higuy, lo) >= 0);
+
+ /* lo-1 <= higuy <= hi, A[i] >= A[lo] for higuy < i <= hi,
+ either higuy <= lo or A[higuy] < A[lo] */
+
+ if (higuy < loguy)
+ break;
+
+ /* if loguy > hi or higuy <= lo, then we would have exited, so
+ A[loguy] > A[lo], A[higuy] < A[lo],
+ loguy < hi, highy > lo */
+
+ swap(loguy, higuy, width);
+
+ /* A[loguy] < A[lo], A[higuy] > A[lo]; so condition at top
+ of loop is re-established */
+ }
+
+ /* A[i] >= A[lo] for higuy < i <= hi,
+ A[i] <= A[lo] for lo <= i < loguy,
+ higuy < loguy, lo <= higuy <= hi
+ implying:
+ A[i] >= A[lo] for loguy <= i <= hi,
+ A[i] <= A[lo] for lo <= i <= higuy,
+ A[i] = A[lo] for higuy < i < loguy */
+
+ swap(lo, higuy, width); /* put partition element in place */
+
+ /* OK, now we have the following:
+ A[i] >= A[higuy] for loguy <= i <= hi,
+ A[i] <= A[higuy] for lo <= i < higuy
+ A[i] = A[lo] for higuy <= i < loguy */
+
+ /* We've finished the partition, now we want to sort the subarrays
+ [lo, higuy-1] and [loguy, hi].
+ We do the smaller one first to minimize stack usage.
+ We only sort arrays of length 2 or more.*/
+
+ if ( higuy - 1 - lo >= hi - loguy ) {
+ if (lo + width < higuy) {
+ lostk[stkptr] = lo;
+ histk[stkptr] = higuy - width;
+ ++stkptr;
+ } /* save big recursion for later */
+
+ if (loguy < hi) {
+ lo = loguy;
+ goto recurse; /* do small recursion */
+ }
+ }
+ else {
+ if (loguy < hi) {
+ lostk[stkptr] = loguy;
+ histk[stkptr] = hi;
+ ++stkptr; /* save big recursion for later */
+ }
+
+ if (lo + width < higuy) {
+ hi = higuy - width;
+ goto recurse; /* do small recursion */
+ }
+ }
+ }
+
+ /* We have sorted the array, except for any pending sorts on the stack.
+ Check if there are any, and do them. */
+
+ --stkptr;
+ if (stkptr >= 0) {
+ lo = lostk[stkptr];
+ hi = histk[stkptr];
+ goto recurse; /* pop subarray from stack */
+ }
+ else
+ return; /* all subarrays done */
+}
+
+#ifdef _CRUISER_
+#pragma check_stack() /* revert to command line behaviour */
+#endif /* ndef _CRUISER_ */
+
+
+/***
+*shortsort(hi, lo, width, comp) - insertion sort for sorting short arrays
+*
+*Purpose:
+* sorts the sub-array of elements between lo and hi (inclusive)
+* side effects: sorts in place
+* assumes that lo < hi
+*
+*Entry:
+* char *lo = pointer to low element to sort
+* char *hi = pointer to high element to sort
+* unsigned width = width in bytes of each array element
+* int (*comp)() = pointer to function returning analog of strcmp for
+* strings, but supplied by user for comparing the array elements.
+* it accepts 2 pointers to elements and returns neg if 1<2, 0 if
+* 1=2, pos if 1>2.
+*
+*Exit:
+* returns void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CALLTYPE4 shortsort (
+ char *lo,
+ char *hi,
+ unsigned width,
+ int (_CALLTYPE1 *comp)(const void *, const void *)
+ )
+{
+ char *p, *max;
+
+ /* Note: in assertions below, i and j are alway inside original bound of
+ array to sort. */
+
+ while (hi > lo) {
+ /* A[i] <= A[j] for i <= j, j > hi */
+ max = lo;
+ for (p = lo+width; p <= hi; p += width) {
+ /* A[i] <= A[max] for lo <= i < p */
+ if (comp(p, max) > 0) {
+ max = p;
+ }
+ /* A[i] <= A[max] for lo <= i <= p */
+ }
+
+ /* A[i] <= A[max] for lo <= i <= hi */
+
+ swap(max, hi, width);
+
+ /* A[i] <= A[hi] for i <= hi, so A[i] <= A[j] for i <= j, j >= hi */
+
+ hi -= width;
+
+ /* A[i] <= A[j] for i <= j, j > hi, loop top condition established */
+ }
+ /* A[i] <= A[j] for i <= j, j > lo, which implies A[i] <= A[j] for i < j,
+ so array is sorted */
+}
+
+
+/***
+*swap(a, b, width) - swap two elements
+*
+*Purpose:
+* swaps the two array elements of size width
+*
+*Entry:
+* char *a, *b = pointer to two elements to swap
+* unsigned width = width in bytes of each array element
+*
+*Exit:
+* returns void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CALLTYPE4 swap (
+ char *a,
+ char *b,
+ unsigned width
+ )
+{
+ char tmp;
+
+ if ( a != b )
+ /* Do the swap one character at a time to avoid potential alignment
+ problems. */
+ while ( width-- ) {
+ tmp = *a;
+ *a++ = *b;
+ *b++ = tmp;
+ }
+}
diff --git a/private/crt32/misc/rand.c b/private/crt32/misc/rand.c
new file mode 100644
index 000000000..b5df0798f
--- /dev/null
+++ b/private/crt32/misc/rand.c
@@ -0,0 +1,133 @@
+/***
+*rand.c - random number generator
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines rand(), srand() - random number generator
+*
+*Revision History:
+* 03-16-84 RN initial version
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-06-89 JCR 386 mthread support
+* 03-15-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 04-05-90 GJF Added #include <stdlib.h>.
+* 10-04-90 GJF New-style function declarators.
+* 07-17-91 GJF Multi-thread support for Win32 [_WIN32_].
+* 02-17-93 GJF Changed for new _getptd().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <os2dll.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#ifndef MTHREAD
+static long holdrand = 1L;
+#endif
+
+/***
+*void srand(seed) - seed the random number generator
+*
+*Purpose:
+* Seeds the random number generator with the int given. Adapted from the
+* BASIC random number generator.
+*
+*Entry:
+* unsigned seed - seed to seed rand # generator with
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 srand (
+ unsigned int seed
+ )
+{
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ struct _tiddata * tdata;
+
+ tdata = _gettidtab(); /* get tid's data address */
+ tdata->_holdrand = (long)seed;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ _getptd()->_holdrand = (unsigned long)seed;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#else
+ holdrand = (long)seed;
+#endif
+}
+
+
+/***
+*int rand() - returns a random number
+*
+*Purpose:
+* returns a pseudo-random number 0 through 32767.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns a pseudo-random number 0 through 32767.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 rand (
+ void
+ )
+{
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ struct _tiddata * tdata;
+
+ tdata = _gettidtab(); /* get tid's data address */
+ return(((tdata->_holdrand = tdata->_holdrand * 214013L + 2531011L) >>
+ 16) & 0x7fff);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ _ptiddata ptd = _getptd();
+
+ return( ((ptd->_holdrand = ptd->_holdrand * 214013L
+ + 2531011L) >> 16) & 0x7fff );
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#else
+ return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
+#endif
+}
diff --git a/private/crt32/misc/rotl.c b/private/crt32/misc/rotl.c
new file mode 100644
index 000000000..79af5779f
--- /dev/null
+++ b/private/crt32/misc/rotl.c
@@ -0,0 +1,90 @@
+/***
+*rotl.c - rotate an unsigned integer left
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _rotl() - performs a rotate left on an unsigned integer.
+*
+*Revision History:
+* 06-02-89 PHG Module created
+* 11-03-89 JCR Added _lrotl
+* 03-15-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 10-04-90 GJF New-style function declarators.
+* 04-01-91 SRW Enable #pragma function for i386 _WIN32_ builds too.
+* 09-02-92 GJF Don't build for POSIX.
+* 03-09-94 RDL Enable #pragma function for i386 _WIN32_ builds too.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#ifdef _MSC_VER
+#pragma function(_lrotl,_rotl)
+#endif
+
+#if UINT_MAX != 0xffffffff
+#error This module assumes 32-bit integers
+#endif
+
+#if (UINT_MAX != ULONG_MAX)
+#error This module assumes sizeof(int) == sizeof(long)
+#endif
+
+/***
+*unsigned _rotl(val, shift) - int rotate left
+*
+*Purpose:
+* Performs a rotate left on an unsigned integer.
+*
+* [Note: The _lrotl entry is based on the assumption
+* that sizeof(int) == sizeof(long).]
+*Entry:
+* unsigned val: value to rotate
+* int shift: number of bits to shift by
+*
+*Exit:
+* returns rotated value
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+unsigned long _CALLTYPE1 _lrotl (
+ unsigned long val,
+ int shift
+ )
+{
+ return( (unsigned long) _rotl((unsigned) val, shift) );
+}
+
+unsigned _CALLTYPE1 _rotl (
+ unsigned val,
+ int shift
+ )
+{
+ register unsigned hibit; /* non-zero means hi bit set */
+ register unsigned num = val; /* number to rotate */
+
+ shift &= 0x1f; /* modulo 32 -- this will also make
+ negative shifts work */
+
+ while (shift--) {
+ hibit = num & 0x80000000; /* get high bit */
+ num <<= 1; /* shift left one bit */
+ if (hibit)
+ num |= 1; /* set lo bit if hi bit was set */
+ }
+
+ return num;
+}
+
+
+#endif
diff --git a/private/crt32/misc/rotr.c b/private/crt32/misc/rotr.c
new file mode 100644
index 000000000..5abe91f23
--- /dev/null
+++ b/private/crt32/misc/rotr.c
@@ -0,0 +1,90 @@
+/***
+*rotr.c - rotate an unsigned integer right
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _rotr() - performs a rotate right on an unsigned integer.
+*
+*Revision History:
+* 06-02-89 PHG Module created
+* 11-03-89 JCR Added _lrotl
+* 03-15-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 10-04-90 GJF New-style function declarators.
+* 04-01-91 SRW Enable #pragma function for i386 _WIN32_ builds too.
+* 09-02-92 GJF Don't build for POSIX.
+* 03-09-94 RDL Enable #pragma function for i386 _WIN32_ builds too.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#ifdef _MSC_VER
+#pragma function(_lrotr,_rotr)
+#endif
+
+#if UINT_MAX != 0xffffffff
+#error This module assumes 32-bit integers
+#endif
+
+#if (UINT_MAX != ULONG_MAX)
+#error This module assumes sizeof(int) == sizeof(long)
+#endif
+
+/***
+*unsigned _rotr(val, shift) - int rotate right
+*
+*Purpose:
+* Performs a rotate right on an unsigned integer.
+*
+* [Note: The _lrotl entry is based on the assumption
+* that sizeof(int) == sizeof(long).]
+*Entry:
+* unsigned val: value to rotate
+* int shift: number of bits to shift by
+*
+*Exit:
+* returns rotated values
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+unsigned long _CALLTYPE1 _lrotr (
+ unsigned long val,
+ int shift
+ )
+{
+ return( (unsigned long) _rotr((unsigned) val, shift) );
+}
+
+unsigned _CALLTYPE1 _rotr (
+ unsigned val,
+ int shift
+ )
+{
+ register unsigned lobit; /* non-zero means lo bit set */
+ register unsigned num = val; /* number to rotate */
+
+ shift &= 0x1f; /* modulo 32 -- this will also make
+ negative shifts work */
+
+ while (shift--) {
+ lobit = num & 1; /* get high bit */
+ num >>= 1; /* shift right one bit */
+ if (lobit)
+ num |= 0x80000000; /* set hi bit if lo bit was set */
+ }
+
+ return num;
+}
+
+
+#endif
diff --git a/private/crt32/misc/searchen.c b/private/crt32/misc/searchen.c
new file mode 100644
index 000000000..8b92e476f
--- /dev/null
+++ b/private/crt32/misc/searchen.c
@@ -0,0 +1,114 @@
+/***
+*searchenv.c - find a file using paths from an environment variable
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* to search a set a directories specified by an environment variable
+* for a specified file name. If found the full path name is returned.
+*
+*Revision History:
+* 06-15-87 DFW initial implementation
+* 08-06-87 JCR Changed directory delimeter from '/' to '\'.
+* 09-24-87 JCR Removed 'const' from declarations (caused cl warnings).
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 02-17-88 JCR Added 'const' copy_path local to get rid of cl warning.
+* 07-19-88 SKS Fixed bug if root directory is current directory
+* 08-03-89 JCR Allow quoted strings in file/path names
+* 08-29-89 GJF Changed copy_path() to _getpath() and moved it to it's
+* own source file. Also fixed handling of multiple semi-
+* colons.
+* 11-20-89 GJF Added const attribute to types of fname and env_var.
+* 03-15-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>. Also, cleaned up the formatting a bit.
+* 07-25-90 SBM Removed redundant include (stdio.h)
+* 10-04-90 GJF New-style function declarator.
+* 01-22-91 GJF ANSI naming.
+* 08-26-92 GJF Include unistd.h for POSIX build.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <direct.h>
+#include <io.h>
+#include <internal.h>
+
+/***
+*_searchenv() - search for file along paths from environment variable
+*
+*Purpose:
+* to search for a specified file in the directory(ies) specified by
+* a given environment variable, and, if found, to return the full
+* path name of the file. The file is first looked for in the current
+* working directory, prior to looking in the paths specified by env_var.
+*
+*Entry:
+* fname - name of file to search for
+* env_var - name of environment variable to use for paths
+* path - pointer to storage for the constructed path name
+*
+*Exit:
+* path - pointer to constructed path name, if the file is found, otherwise
+* it points to the empty string.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _searchenv (
+ const char *fname,
+ const char *env_var,
+ register char *path
+ )
+{
+ register char *p;
+ register int c;
+ char *env_p;
+
+#ifdef _POSIX_
+ if (access(fname, 0) == 0) {
+#else
+ if (_access(fname, 0) == 0) {
+#endif
+ /* exists in this directory - get cwd and concatenate file
+ name */
+ _getcwd(path, _MAX_PATH);
+ if(path[3]) /* Do NOT add `\' to root directory */
+ strcat(path, "\\");
+ strcat(path, fname);
+ return;
+ }
+ if ((env_p = getenv(env_var)) == NULL) {
+ /* no such environment var. and not in cwd, so return empty
+ string */
+ *path = '\0';
+ return;
+ }
+ while ( (env_p = _getpath(env_p, path, 0)) && *path ) {
+ /* path now holds nonempty pathname from env_p, concatenate
+ the file name and go */
+ p = path + strlen(path);
+ if (((c = *(p - 1)) != '/') && (c != '\\') && (c != ':')) {
+ /* add a trailing '\' */
+ *p++ = '\\';
+ }
+ /* p now points to character following trailing '/', '\'
+ or ':' */
+ strcpy(p, fname);
+#ifdef _POSIX_
+ if (access(path, 0) == 0) {
+#else
+ if (_access(path, 0) == 0) {
+#endif
+ /* found a match, we're done */
+ return;
+ }
+ }
+ /* if we get here, we never found it, return empty string */
+ *path = '\0';
+}
diff --git a/private/crt32/misc/setlocal.c b/private/crt32/misc/setlocal.c
new file mode 100644
index 000000000..4fa3bbc05
--- /dev/null
+++ b/private/crt32/misc/setlocal.c
@@ -0,0 +1,620 @@
+/***
+*setlocal.c - Contains the setlocale function
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the setlocale() function.
+*
+*Revision History:
+* 03-21-89 JCR Module created.
+* 09-25-89 GJF Fixed copyright. Checked for compatibility with Win 3.0
+* 09-25-90 KRS Major rewrite--support more than "C" locale if _INTL.
+* 11-05-91 ETC Get 09-25-90 working for C and "" locales; separate
+* setlocal.h; add Init functions.
+* 12-05-91 ETC Separate nlsdata.c; add mt support; remove calls to
+* itself.
+* 12-20-91 ETC Added _getlocaleinfo api interface function.
+* 09-25-92 KRS Fix for latest NLSAPI changes, etc.
+* 01-25-93 KRS Fix for latest changes, clean up code, etc.
+* 02-02-93 CFW Many modifications and bug fixes (all under _INTL).
+* 02-08-93 CFW Bug fixes and casts to avoid warnings (all under _INTL).
+* 02-17-93 CFW Removed re-call of init() functions in case of failure.
+* 03-01-93 CFW Check GetQualifiedLocale return value.
+* 03-02-93 CFW Added POSIX conformance, check environment variables.
+* 03-09-93 CFW Set CP to CP_ACP when changing to C locale.
+* 03-17-93 CFW Change expand to expandlocale, prepend _ to internal functions,
+* lots of POSIX fixup.
+* 03-23-93 CFW Add _ to GetQualifiedLocale call.
+* 03-24-93 CFW Change to _get_qualified_locale, support ".codepage".
+* 05-10-93 CFW Disallow setlocale(LC_*, ".").
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <locale.h>
+#ifdef _INTL
+#include <os2dll.h>
+#include <malloc.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h> /* for strtol */
+#include <setlocal.h>
+
+#ifdef MTHREAD
+/*
+ * Check order of locale category multithread locks.
+ * (needed by _setlocale_set_cat)
+ */
+#if _LC_COLLATE_LOCK != _SETLOCALE_LOCK + LC_COLLATE || \
+ _LC_CTYPE_LOCK != _SETLOCALE_LOCK + LC_CTYPE || \
+ _LC_MONETARY_LOCK != _SETLOCALE_LOCK + LC_MONETARY || \
+ _LC_NUMERIC_LOCK != _SETLOCALE_LOCK + LC_NUMERIC || \
+ _LC_TIME_LOCK != _SETLOCALE_LOCK + LC_TIME
+
+#error Locale category multithread locks are disordered
+#endif
+#endif /* MTHREAD */
+
+#endif /* _INTL */
+
+/* C locale */
+static char _clocalestr[] = "C";
+#ifdef _POSIX_
+static char _posixlocalestr[] = "POSIX";
+#endif
+
+
+#ifdef _INTL
+/* CONSIDER: for granularity, reference from approp component (lconv.c, etc.) */
+int _CRTAPI3 _init_collate(void);
+int _CRTAPI3 _init_ctype(void);
+int _CRTAPI3 _init_monetary(void);
+int _CRTAPI3 _init_numeric(void);
+int _CRTAPI3 _init_time(void);
+int _CRTAPI3 _init_dummy(void);
+
+static struct {
+ const char * catname;
+ char * locale;
+ int (* init)(void);
+} _lc_category[LC_MAX-LC_MIN+1] = {
+ /* code assumes locale initialization is "_clocalestr" */
+ { "LC_ALL", NULL, _init_dummy /* never called */ },
+ { "LC_COLLATE", _clocalestr, _init_collate },
+ { "LC_CTYPE", _clocalestr, _init_ctype },
+ { "LC_MONETARY", _clocalestr, _init_monetary },
+ { "LC_NUMERIC", _clocalestr, _init_numeric },
+ { "LC_TIME", _clocalestr, _init_time }
+};
+/* CONSIDER: _init_* functions should map to _init_dummy when not linked in */
+
+/* helper function prototypes */
+char * _expandlocale(char *, char *, LC_ID *, UINT *, int);
+void _strcats(char *, int, ...);
+void _lc_lctostr(char *, const LC_STRINGS *);
+int _lc_strtolc(LC_STRINGS *, const char *);
+static char * _CRTAPI3 _setlocale_set_cat(int, const char *);
+static char * _CRTAPI3 _setlocale_get_all(void);
+#endif /* _INTL */
+
+/***
+*char * setlocale(int category, char *locale) - Set one or all locale categories
+*
+*Purpose:
+* The setlocale() routine allows the user to set one or more of
+* the locale categories to the specific locale selected by the
+* user. [ANSI]
+*
+* NOTE: Under !_INTL, the C libraries only support the "C" locale.
+* Attempts to change the locale will fail.
+*
+*Entry:
+* int category = One of the locale categories defined in locale.h
+* char *locale = String identifying a specific locale or NULL to
+* query the current locale.
+*
+*Exit:
+* If supplied locale pointer == NULL:
+*
+* Return pointer to current locale string and do NOT change
+* the current locale.
+*
+* If supplied locale pointer != NULL:
+*
+* If locale string is '\0', set locale to default.
+*
+* If desired setting can be honored, return a pointer to the
+* locale string for the appropriate category.
+*
+* If desired setting can NOT be honored, return NULL.
+*
+*Exceptions:
+* Compound locale strings of the form "LC_COLLATE=xxx;LC_CTYPE=xxx;..."
+* are allowed for the LC_ALL category. This is to support the ability
+* to restore locales with the returned string, as specified by ANSI.
+* Setting the locale with a compound locale string will succeed unless
+* *all* categories failed. The returned string will reflect the current
+* locale. For example, if LC_CTYPE fails in the above string, setlocale
+* will return "LC_COLLATE=xxx;LC_CTYPE=yyy;..." where yyy is the
+* previous locale (or the C locale if restoring the previous locale
+* also failed). Unrecognized LC_* categories are ignored.
+*
+*******************************************************************************/
+char * _CRTAPI1 setlocale (
+ int _category,
+ const char *_locale
+ )
+{
+#ifdef _INTL
+char * retval;
+#endif
+
+ /* Validate category */
+ if ((_category < LC_MIN) || (_category > LC_MAX))
+ return NULL;
+
+ /* Interpret locale */
+
+#ifndef _INTL /* trivial ANSI support */
+ if ( (_locale == NULL) ||
+ (_locale[0] == '\0') ||
+ ( (_locale[0]=='C') && (_locale[1]=='\0'))
+#ifdef _POSIX_
+ || (!strcmp(_locale,"POSIX"))
+#endif
+ )
+#ifdef _POSIX_
+ return _posixlocalestr;
+#else
+ return _clocalestr;
+#endif
+ else
+ return NULL;
+
+#else /* _INTL */
+
+_mlock (_SETLOCALE_LOCK);
+
+ if (_category != LC_ALL)
+ {
+ retval = (_locale) ? _setlocale_set_cat(_category,_locale) :
+ _lc_category[_category].locale;
+
+ } else { /* LC_ALL */
+
+ char lctemp[MAX_LC_LEN];
+ int i;
+ int same = 1;
+ int fLocaleSet = 0; /* flag to indicate if anything successfully set */
+
+ if (_locale != NULL)
+ {
+ if ( (_locale[0]=='L') && (_locale[1]=='C') && (_locale[2]=='_') )
+ {
+ /* parse compound locale string */
+ size_t len;
+ const char * p = _locale; /* start of string to parse */
+ const char * s;
+
+ do {
+ s = strpbrk(p,"=;");
+ if ((s==(char *)NULL) || (!(len=s-p)) || (*s==';'))
+ {
+ _munlock (_SETLOCALE_LOCK);
+ return NULL; /* syntax error */
+ }
+
+ /* match with known LC_ strings, if possible, else ignore */
+ for (i=LC_ALL+1; i<=LC_MAX; i++)
+ {
+ if ((!strncmp(_lc_category[i].catname,p,len))
+ && (len==strlen(_lc_category[i].catname)))
+ {
+ break; /* matched i */
+ }
+ } /* no match if (i>LC_MAX) -- just ignore */
+
+ if ((!(len = strcspn(++s,";"))) && (*s!=';'))
+ {
+ _munlock (_SETLOCALE_LOCK);
+ return NULL; /* syntax error */
+ }
+
+ if (i<=LC_MAX)
+ {
+ /* CONSIDER: check for repeated categories? */
+ strncpy(lctemp, s, len);
+ lctemp[len]='\0'; /* null terminate string */
+
+ /* don't fail unless all categories fail */
+ if (_setlocale_set_cat(i,lctemp))
+ fLocaleSet++; /* record a success */
+ }
+ if (*(p = s+len)!='\0')
+ p++; /* skip ';', if present */
+
+ } while (*p);
+
+ retval = (fLocaleSet) ? _setlocale_get_all() : NULL;
+
+ /* CONSIDER: LC_CTYPE should be done first. _init_monetary for example
+ will convert wide strings to multibyte (dependent on ctype).
+ This is currently not a problem; ctype is done second; collate is done
+ first, but it does not require ctype. */
+ /* Not necessarily true when a compound locale string is used, but WE always
+ put it in the right order. */
+
+ } else { /* simple LC_ALL locale string */
+
+ /* confirm locale is supported, get expanded locale */
+ if (retval = _expandlocale((char *)_locale, lctemp, NULL, NULL, _category))
+ {
+ for (i=LC_MIN; i<=LC_MAX; i++)
+ {
+ if (i!=LC_ALL)
+ {
+ if (strcmp(lctemp, _lc_category[i].locale))
+ {
+ if (_setlocale_set_cat(i, lctemp))
+ {
+ fLocaleSet++; /* record a success */
+ }
+ else
+ {
+ same = 0; /* record a failure */
+ }
+ }
+ else
+ fLocaleSet++; /* trivial succcess */
+ }
+ }
+#ifdef _POSIX_
+ /* special case for POSIX - since LC_ALL expands,
+ one LC_ALL call may set many different categories,
+ must assume not same, get full string */
+ same = 0;
+#endif
+ if (same) /* needn't call setlocale_get_all() if all the same */
+ {
+ retval = _setlocale_get_all();
+ /* retval set above */
+ free(_lc_category[LC_ALL].locale);
+ _lc_category[LC_ALL].locale = NULL;
+ }
+ else
+ retval = (fLocaleSet) ? _setlocale_get_all() : NULL;
+ }
+ }
+ } else { /* LC_ALL & NULL */
+ retval = _setlocale_get_all ();
+ }
+ }
+
+ /* common exit point */
+ _munlock (_SETLOCALE_LOCK);
+ return retval;
+
+#endif /* _INTL */
+
+} /* setlocale */
+
+
+#ifdef _INTL /* rest are international helpers */
+static char * _CRTAPI3 _setlocale_set_cat (
+ int category,
+ const char * locale
+ )
+{
+ char * oldlocale;
+ LCID oldhandle;
+ UINT oldcodepage;
+ LC_ID oldid;
+
+ LC_ID idtemp;
+ UINT cptemp;
+ char lctemp[MAX_LC_LEN];
+ char * pch;
+
+ /* lock this category to keep other library functions */
+ /* from using locale handles, information, etc. */
+
+ _mlock (_SETLOCALE_LOCK + category);
+
+ if (!_expandlocale((char *)locale, lctemp, &idtemp, &cptemp, category))
+ {
+ _munlock (_SETLOCALE_LOCK + category);
+ return NULL; /* unrecognized locale */
+ }
+
+ if (!(pch = (char *)malloc(strlen(lctemp)+1)))
+ {
+ _munlock (_SETLOCALE_LOCK + category);
+ return NULL; /* error if malloc fails */
+ }
+
+ oldlocale = _lc_category[category].locale; /* save for possible restore*/
+ oldhandle = _lc_handle[category];
+ memcpy((void *)&oldid, (void *)&_lc_id[category], sizeof(oldid));
+ oldcodepage = _lc_codepage;
+
+ /* update locale string */
+ _lc_category[category].locale = strcpy(pch,lctemp);
+ _lc_handle[category] = MAKELCID(idtemp.wLanguage, SORT_DEFAULT);
+ memcpy((void *)&_lc_id[category], (void *)&idtemp, sizeof(idtemp));
+
+ if (category==LC_CTYPE)
+ _lc_codepage = cptemp;
+
+ if (_lc_category[category].init())
+ {
+ /* restore previous state! */
+ _lc_category[category].locale = oldlocale;
+ free(pch);
+ _lc_handle[category] = oldhandle;
+ _lc_codepage = oldcodepage;
+
+ _munlock (_SETLOCALE_LOCK + category);
+ return NULL; /* error if non-zero return */
+ }
+
+ /* locale set up successfully */
+ /* Cleanup */
+ if ((oldlocale != _clocalestr)
+#ifdef _POSIX_
+ && (oldlocale!=_posixlocalestr)
+#endif
+ )
+ free(oldlocale);
+
+ _munlock (_SETLOCALE_LOCK + category);
+
+ return _lc_category[category].locale;
+
+} /* _setlocale_set_cat */
+
+
+
+static char * _CRTAPI3 _setlocale_get_all (
+ void
+ )
+{
+ int i;
+ int same = 1;
+ /* allocate memory if necessary */
+ if (!_lc_category[LC_ALL].locale)
+ _lc_category[LC_ALL].locale = malloc((MAX_LC_LEN+1) * (LC_MAX-LC_MIN+1) + CATNAMES_LEN);
+
+ _lc_category[LC_ALL].locale[0] = '\0';
+ for (i=LC_MIN+1; ; i++)
+ {
+ _strcats(_lc_category[LC_ALL].locale, 3, _lc_category[i].catname,"=",_lc_category[i].locale);
+ if (i<LC_MAX)
+ {
+ strcat(_lc_category[LC_ALL].locale,";");
+ if (strcmp(_lc_category[i].locale, _lc_category[i+1].locale))
+ same=0;
+ }
+ else
+ {
+ if (!same)
+ return _lc_category[LC_ALL].locale;
+ else
+ {
+ free(_lc_category[LC_ALL].locale); /* free */
+ _lc_category[LC_ALL].locale = (char *)NULL;
+ return _lc_category[LC_CTYPE].locale;
+ }
+ }
+ }
+} /* _setlocale_get_all */
+
+
+char * _expandlocale (
+ char *expr,
+ char * output,
+ LC_ID * id,
+ UINT * cp,
+ int category
+ )
+{
+ static LC_ID cacheid = {0, 0, 0};
+ static UINT cachecp = 0;
+ static char cachein[MAX_LC_LEN] = "C";
+ static char cacheout[MAX_LC_LEN] = "C";
+
+ if (!expr)
+ return NULL; /* error if no input */
+
+#ifdef _POSIX_
+ if (!*expr)
+ {
+ /* POSIX: when locale=="", look first at the environment variables:
+ 1) use LC_ALL EV if defined and not null (LC_ALL expands to LC_*)
+ 2) use EV that matches category and is not null
+ 3) use LANG EV if defined and not null
+ otherwise, we fall through to get system default */
+
+ char *envar;
+
+ if (category == LC_ALL && (envar = getenv("LC_ALL")))
+ {
+ if (!*envar)
+ {
+ /* LC_ALL expands to LC_*, set output to "", each category will be
+ expanded individually */
+ *output = '\0';
+ return output;
+ }
+ else {
+ expr = envar;
+ }
+ }
+ else {
+ if ((envar = getenv(_lc_category[category].catname)) && *envar ||
+ (envar = getenv("LANG")) && *envar)
+ {
+ expr = envar;
+ }
+ }
+ }
+#endif /* _POSIX_ */
+
+ if (((*expr=='C') && (!expr[1]))
+#ifdef _POSIX_
+ || (!strcmp(expr, _posixlocalestr))
+#endif
+ ) /* for "C" locale, just return */
+ {
+#ifdef _POSIX_
+ strcpy(output, _posixlocalestr);
+#else
+ *output = 'C';
+ output[1] = '\0';
+#endif
+ if (id)
+ {
+ id->wLanguage = 0;
+ id->wCountry = 0;
+ id->wCodePage = 0;
+ }
+ if (cp)
+ {
+ *cp = CP_ACP; /* return to ANSI code page */
+ }
+ return output; /* "C" */
+ }
+
+ /* first, make sure we didn't just do this one */
+ if (strcmp(cacheout,expr) && strcmp(cachein,expr))
+ {
+ /* do some real work */
+ const LC_STRINGS names;
+
+ if (_lc_strtolc((LC_STRINGS *)&names, (const char *)expr))
+ return NULL; /* syntax error */
+
+ if (!_get_qualified_locale((const DWORD)QF_STRINGS, (const LPVOID)&names,
+ (LPLC_ID)&cacheid, (LPLC_STRINGS)&names))
+ return NULL; /* locale not recognized/supported */
+
+ /* begin: cache atomic section */
+
+ cachecp = cacheid.wCodePage;
+
+ _lc_lctostr((char *)cacheout, &names);
+
+ /* Don't cache "" empty string */
+ if (*expr)
+ strcpy(cachein, expr);
+ else
+ strcpy(cachein, cacheout);
+
+ /* end: cache atomic section */
+ }
+ if (id)
+ memcpy((void *)id, (void *)&cacheid, sizeof(cacheid)); /* possibly return LC_ID */
+ if (cp)
+ memcpy((void *)cp, (void *)&cachecp, sizeof(cachecp)); /* possibly return cp */
+
+ strcpy(output,cacheout);
+ return cacheout; /* return fully expanded locale string */
+}
+
+/* helpers */
+
+int _CRTAPI3 _init_dummy(void) /* default routine for locale initializer */
+{
+ return 0;
+}
+
+void _strcats
+ (
+ char *outstr,
+ int n,
+ ...
+ )
+{
+ int i;
+ va_list substr;
+
+ va_start (substr, n);
+
+ for (i =0; i<n; i++)
+ {
+ strcat(outstr, va_arg(substr, char *));
+ }
+ va_end(substr);
+}
+
+int _lc_strtolc
+ (
+ LC_STRINGS *names,
+ const char *locale
+ )
+{
+ int i, len;
+ char ch;
+
+ memset((void *)names, '\0', sizeof(LC_STRINGS)); /* clear out result */
+
+ if (*locale=='\0')
+ return 0; /* trivial case */
+
+ // only code page is given
+ if (locale[0] == '.' && locale[1] != '\0')
+ {
+ strcpy((char *)names->szCodePage, &locale[1]);
+ return 0;
+ }
+
+ for (i=0; ; i++)
+ {
+ if (!(len=strcspn(locale,"_.,")))
+ return -1; /* syntax error */
+
+ ch = locale[len];
+
+ if ((i==0) && (len<MAX_LANG_LEN) && (ch!='.'))
+ strncpy((char *)names->szLanguage, locale, len);
+
+ else if ((i==1) && (len<MAX_CTRY_LEN) && (ch!='_'))
+ strncpy((char *)names->szCountry, locale, len);
+
+ else if ((i==2) && (ch=='\0' || ch==','))
+ strncpy((char *)names->szCodePage, locale, len);
+
+ else
+ return -1; /* error parsing locale string */
+
+ if (ch==',')
+ {
+ /* modifier not used in current implementation, but it
+ must be parsed to for POSIX/XOpen conformance */
+ /* strncpy(names->szModifier, locale, MAX_MODIFIER_LEN-1); */
+ break;
+ }
+
+ if (!ch)
+ break;
+ locale+=(len+1);
+ }
+ return 0;
+}
+
+void _lc_lctostr
+ (
+ char *locale,
+ const LC_STRINGS *names
+ )
+{
+ strcpy(locale, (char *)names->szLanguage);
+ if (*(names->szCountry))
+ _strcats(locale, 2, "_", names->szCountry);
+ if (*(names->szCodePage))
+ _strcats(locale, 2, ".", names->szCodePage);
+ /* if (names->szModifier)
+ _strcats(locale, 2, ",", names->szModifier); */
+}
+
+#endif /* _INTL */
diff --git a/private/crt32/misc/setmbval.c b/private/crt32/misc/setmbval.c
new file mode 100644
index 000000000..bbbf48f3f
--- /dev/null
+++ b/private/crt32/misc/setmbval.c
@@ -0,0 +1,35 @@
+/***
+*setmbval.c - sets __invalid_mb_chars variable
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* sets __invalid_mb_chars flag to value apppropriate to the NLS API
+* call support. Older versions of NT do not support this flag.
+*
+**
+*Revision History:
+* 10-22-93 CFW Module created.
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <internal.h>
+
+
+void __set_invalid_mb_chars(void)
+{
+ char *astring = "a"; /* test string */
+
+ /*
+ * Determine whether API supports this flag by making a dummy call.
+ *
+ */
+
+ if (0 != MultiByteToWideChar(0, MB_ERR_INVALID_CHARS, astring, -1, NULL, 0))
+ __invalid_mb_chars = MB_ERR_INVALID_CHARS;
+ else
+ __invalid_mb_chars = 0;
+}
+
+
diff --git a/private/crt32/misc/sources b/private/crt32/misc/sources
new file mode 100644
index 000000000..cd3f28bea
--- /dev/null
+++ b/private/crt32/misc/sources
@@ -0,0 +1,129 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=misc
+
+TARGETNAME=misc
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=abort.c \
+ abs.c \
+ assert.c \
+ bsearch.c \
+ cmiscdat.c \
+ ctype.c \
+ div.c \
+ ldiv.c \
+ getenv.c \
+ getpath.c \
+ getqloc.c \
+ initcoll.c \
+ initctyp.c \
+ inithelp.c \
+ initmon.c \
+ initnum.c \
+ inittime.c \
+ labs.c \
+ lconv.c \
+ lfind.c \
+ lsearch.c \
+ makepath.c \
+ mbval.c \
+ onexit.c \
+ nlsdata1.c \
+ nlsdata2.c \
+ nlsdata3.c \
+ perror.c \
+ purevirt.c \
+ putenv.c \
+ qsort.c \
+ rand.c \
+ rotl.c \
+ rotr.c \
+ searchen.c \
+ setlocal.c \
+ setmbval.c \
+ splitpat.c \
+ _strerr.c \
+ strerror.c \
+ syserr.c \
+ umask.c \
+ winsig.c \
+ winxfltr.c \
+ wrt2err.c
+
+i386_SOURCES=i386\setjmpex.asm \
+ i386\setjmp.asm \
+ i386\setjmp3.asm \
+ i386\longjmp.asm \
+ i386\sehsupp.c \
+ i386\exsup.asm \
+ i386\exsup2.asm \
+ i386\exsup3.asm
+
+MIPS_SOURCES=mips\chandler.c \
+ mips\setjmp.s \
+ mips\setjmpex.s \
+ mips\longjmp.s \
+ mips\jmpuwind.s
+
+ALPHA_SOURCES=alpha\chandler.c \
+ alpha\divdat.s \
+ alpha\divide2.s \
+ alpha\extv.s \
+ alpha\extvvol.s \
+ alpha\extzv.s \
+ alpha\extzvvol.s \
+ alpha\ghandler.c \
+ alpha\insv.s \
+ alpha\insvvol.s \
+ alpha\jmpuwind.s \
+ alpha\longjmp.s \
+ alpha\otsdiv.s \
+ alpha\otsjmp.s \
+ alpha\otsjmpex.s \
+ alpha\otsuwind.s \
+ alpha\scmpeql.s \
+ alpha\scmpeqlp.s \
+ alpha\scmpleq.s \
+ alpha\scmpleqp.s \
+ alpha\scmplss.s \
+ alpha\scmplssp.s \
+ alpha\setjmp.s \
+ alpha\setjmpex.s \
+ alpha\sfill.s \
+ alpha\sloc.s \
+ alpha\smove.s \
+ alpha\smovem.s \
+ alpha\strans.s \
+ alpha\strcmp_.s \
+ alpha\strcpy_.s \
+ alpha\strlen_.s \
+ alpha\szero.s
diff --git a/private/crt32/misc/splitpat.c b/private/crt32/misc/splitpat.c
new file mode 100644
index 000000000..f85b26b1e
--- /dev/null
+++ b/private/crt32/misc/splitpat.c
@@ -0,0 +1,201 @@
+/***
+*splitpath.c - break down path name into components
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* To provide support for accessing the individual components of an
+* arbitrary path name
+*
+*Revision History:
+* 06-14-87 DFW initial implementation
+* 09-23-87 JCR Removed 'const' from declarations (fixed cl warnings)
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-20-89 GJF Fixed indents, copyright. Added const attribute to
+* type of path.
+* 03-15-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 07-25-90 SBM Removed redundant include (stdio.h), replaced local
+* MIN macro with standard min macro
+* 10-04-90 GJF New-style function declarator.
+* 01-22-91 GJF ANSI naming.
+* 11-20-92 KRS Port _MBCS support from 16-bit tree.
+* 05-12-93 KRS Add fix for MBCS max path handling.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _MBCS
+#include <mbstring.h>
+#include <mbctype.h>
+#include <mbdata.h>
+#endif
+
+#ifdef _MBCS
+#define STRNCPY _mbsnbcpy
+#else
+#define STRNCPY strncpy
+#endif
+
+/***
+*_splitpath() - split a path name into its individual components
+*
+*Purpose:
+* to split a path name into its individual components
+*
+*Entry:
+* path - pointer to path name to be parsed
+* drive - pointer to buffer for drive component, if any
+* dir - pointer to buffer for subdirectory component, if any
+* fname - pointer to buffer for file base name component, if any
+* ext - pointer to buffer for file name extension component, if any
+*
+*Exit:
+* drive - pointer to drive string. Includes ':' if a drive was given.
+* dir - pointer to subdirectory string. Includes leading and trailing
+* '/' or '\', if any.
+* fname - pointer to file base name
+* ext - pointer to file extension, if any. Includes leading '.'.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _splitpath (
+ register const char *path,
+ char *drive,
+ char *dir,
+ char *fname,
+ char *ext
+ )
+{
+ register char *p;
+ char *last_slash = NULL, *dot = NULL;
+ unsigned len;
+
+ /* we assume that the path argument has the following form, where any
+ * or all of the components may be missing.
+ *
+ * <drive><dir><fname><ext>
+ *
+ * and each of the components has the following expected form(s)
+ *
+ * drive:
+ * 0 to _MAX_DRIVE-1 characters, the last of which, if any, is a
+ * ':'
+ * dir:
+ * 0 to _MAX_DIR-1 characters in the form of an absolute path
+ * (leading '/' or '\') or relative path, the last of which, if
+ * any, must be a '/' or '\'. E.g -
+ * absolute path:
+ * \top\next\last\ ; or
+ * /top/next/last/
+ * relative path:
+ * top\next\last\ ; or
+ * top/next/last/
+ * Mixed use of '/' and '\' within a path is also tolerated
+ * fname:
+ * 0 to _MAX_FNAME-1 characters not including the '.' character
+ * ext:
+ * 0 to _MAX_EXT-1 characters where, if any, the first must be a
+ * '.'
+ *
+ */
+
+ /* extract drive letter and :, if any */
+
+ if (*(path + _MAX_DRIVE - 2) == ':') {
+ if (drive) {
+ strncpy(drive, path, _MAX_DRIVE - 1);
+ *(drive + _MAX_DRIVE-1) = '\0';
+ }
+ path += _MAX_DRIVE - 1;
+ }
+ else if (drive) {
+ *drive = '\0';
+ }
+
+ /* extract path string, if any. Path now points to the first character
+ * of the path, if any, or the filename or extension, if no path was
+ * specified. Scan ahead for the last occurence, if any, of a '/' or
+ * '\' path separator character. If none is found, there is no path.
+ * We will also note the last '.' character found, if any, to aid in
+ * handling the extension.
+ */
+
+ for (last_slash = NULL, p = (char *)path; *p; p++) {
+#ifdef _MBCS
+ if (_ISLEADBYTE (*p))
+ p++;
+ else {
+#endif
+ if (*p == '/' || *p == '\\')
+ /* point to one beyond for later copy */
+ last_slash = p + 1;
+ else if (*p == '.')
+ dot = p;
+#ifdef _MBCS
+ }
+#endif
+ }
+
+ if (last_slash) {
+
+ /* found a path - copy up through last_slash or max. characters
+ * allowed, whichever is smaller
+ */
+
+ if (dir) {
+ len = __min((last_slash - path), (_MAX_DIR - 1));
+ STRNCPY(dir, path, len);
+ *(dir + len) = '\0';
+ }
+ path = last_slash;
+ }
+ else if (dir) {
+
+ /* no path found */
+
+ *dir = '\0';
+ }
+
+ /* extract file name and extension, if any. Path now points to the
+ * first character of the file name, if any, or the extension if no
+ * file name was given. Dot points to the '.' beginning the extension,
+ * if any.
+ */
+
+ if (dot && (dot >= path)) {
+ /* found the marker for an extension - copy the file name up to
+ * the '.'.
+ */
+ if (fname) {
+ len = __min((dot - path), (_MAX_FNAME - 1));
+ STRNCPY(fname, path, len);
+ *(fname + len) = '\0';
+ }
+ /* now we can get the extension - remember that p still points
+ * to the terminating nul character of path.
+ */
+ if (ext) {
+ len = __min((p - dot), (_MAX_EXT - 1));
+ STRNCPY(ext, dot, len);
+ *(ext + len) = '\0';
+ }
+ }
+ else {
+ /* found no extension, give empty extension and copy rest of
+ * string into fname.
+ */
+ if (fname) {
+ len = __min((p - path), (_MAX_FNAME - 1));
+ STRNCPY(fname, path, len);
+ *(fname + len) = '\0';
+ }
+ if (ext) {
+ *ext = '\0';
+ }
+ }
+}
diff --git a/private/crt32/misc/strerror.c b/private/crt32/misc/strerror.c
new file mode 100644
index 000000000..ec8c7dd41
--- /dev/null
+++ b/private/crt32/misc/strerror.c
@@ -0,0 +1,142 @@
+/***
+*strerror.c - Contains the strerror C runtime.
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The strerror runtime accepts an error number as input
+* and returns the corresponding error string.
+*
+* NOTE: The "old" strerror C runtime resides in file _strerr.c
+* and is now called _strerror. The new strerror runtime
+* conforms to the ANSI standard.
+*
+*Revision History:
+* 02-24-87 JCR Module created.
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-04-87 JCR Improved code.
+* 01-05-87 JCR Multi-thread support
+* 05-31-88 PHG Merge DLL and normal versions
+* 06-06-89 JCR 386 mthread support
+* 03-16-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 10-04-90 GJF New-style function declarator.
+* 07-18-91 GJF Multi-thread support for Win32 [_WIN32_].
+* 02-17-93 GJF Changed for new _getptd().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <errmsg.h>
+#include <stdlib.h>
+#include <syserr.h>
+#include <string.h>
+#include <os2dll.h>
+#ifdef MTHREAD
+#include <malloc.h>
+#include <stddef.h>
+#endif
+
+/* [NOTE: The mthread error message buffer is shared by both strerror
+ and _strerror so must be the max length of both. */
+#ifdef MTHREAD
+/* Max length of message = user_string(94)+system_string+2 */
+#define _ERRMSGLEN_ 94+_SYS_MSGMAX+2
+#else
+/* Max length of message = system_string+2 */
+#define _ERRMSGLEN_ _SYS_MSGMAX+2
+#endif
+
+
+/***
+*char *strerror(errnum) - Map error number to error message string.
+*
+*Purpose:
+* The strerror runtime takes an error number for input and
+* returns the corresponding error message string. This routine
+* conforms to the ANSI standard interface.
+*
+*Entry:
+* int errnum - Integer error number (corresponding to an errno value).
+*
+*Exit:
+* char * - Strerror returns a pointer to the error message string.
+* This string is internal to the strerror routine (i.e., not supplied
+* by the user).
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+char * _CRTAPI1 strerror (
+ int errnum
+ )
+{
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ struct _tiddata * tdata;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ _ptiddata ptd = _getptd();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ char *errmsg;
+ static char errmsg_backup[_SYS_MSGMAX+2];
+
+#else
+
+ static char errmsg[_ERRMSGLEN_]; /* Longest errmsg + \0 */
+
+#endif
+
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ tdata = _gettidtab(); /* get tid's data address */
+ if (tdata->_errmsg == NULL) {
+ if ( (tdata->_errmsg = malloc(_ERRMSGLEN_)) == NULL)
+ errmsg = errmsg_backup; /* error: use backup */
+ else
+ errmsg = tdata->_errmsg;
+ }
+ else
+ errmsg = tdata->_errmsg;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ if ( (ptd->_errmsg == NULL) && ((ptd->_errmsg = malloc(_ERRMSGLEN_))
+ == NULL) )
+ errmsg = errmsg_backup; /* error: use backup */
+ else
+ errmsg = ptd->_errmsg;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#endif
+
+ strcpy(errmsg, _sys_err_msg(errnum));
+ return(errmsg);
+}
diff --git a/private/crt32/misc/syserr.c b/private/crt32/misc/syserr.c
new file mode 100644
index 000000000..ef5ee29ed
--- /dev/null
+++ b/private/crt32/misc/syserr.c
@@ -0,0 +1,85 @@
+/***
+*syserr.c - system error list
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the System Error List, containing the full messages for
+* all errno values set by the library routines.
+* Defines sys_errlist, sys_nerr.
+*
+*Revision History:
+* 08-07-87 PHG removed obsolete definition of sys_msgmax.
+* 04-06-90 GJF Added #include <cruntime.h>. Also, fixed the copyright.
+* 01-21-91 GJF ANSI naming.
+* 07-11-91 JCR Changed "core" to "memory" in ENOMEM message
+* 01-23-92 GJF Added #include <stdlib.h> (contains decl of sys_nerr).
+* 09-30-92 GJF Made POSIX compatible. Non-POSIX errno values are
+* mapped to "Unknown error" for now. Next step is to
+* delete these and renumber to eliminate the gaps, after
+* the beta release.
+* 04-08-93 CFW Added EILSEQ (42) message.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+
+char *_sys_errlist[] =
+{
+ /* 0 */ "No error",
+ /* 1 EPERM */ "Operation not permitted",
+ /* 2 ENOENT */ "No such file or directory",
+ /* 3 ESRCH */ "No such process",
+ /* 4 EINTR */ "Interrupted function call",
+ /* 5 EIO */ "Input/output error",
+ /* 6 ENXIO */ "No such device or address",
+ /* 7 E2BIG */ "Arg list too long",
+ /* 8 ENOEXEC */ "Exec format error",
+ /* 9 EBADF */ "Bad file descriptor",
+ /* 10 ECHILD */ "No child processes",
+ /* 11 EAGAIN */ "Resource temporarily unavailable",
+ /* 12 ENOMEM */ "Not enough space",
+ /* 13 EACCES */ "Permission denied",
+ /* 14 EFAULT */ "Bad address",
+ /* 15 ENOTBLK */ "Unknown error", /* not POSIX */
+ /* 16 EBUSY */ "Resource device",
+ /* 17 EEXIST */ "File exists",
+ /* 18 EXDEV */ "Improper link",
+ /* 19 ENODEV */ "No such device",
+ /* 20 ENOTDIR */ "Not a directory",
+ /* 21 EISDIR */ "Is a directory",
+ /* 22 EINVAL */ "Invalid argument",
+ /* 23 ENFILE */ "Too many open files in system",
+ /* 24 EMFILE */ "Too many open files",
+ /* 25 ENOTTY */ "Inappropriate I/O control operation",
+ /* 26 ETXTBSY */ "Unknown error", /* not POSIX */
+ /* 27 EFBIG */ "File too large",
+ /* 28 ENOSPC */ "No space left on device",
+ /* 29 ESPIPE */ "Invalid seek",
+ /* 30 EROFS */ "Read-only file system",
+ /* 31 EMLINK */ "Too many links",
+ /* 32 EPIPE */ "Broken pipe",
+ /* 33 EDOM */ "Domain error",
+ /* 34 ERANGE */ "Result too large",
+ /* 35 EUCLEAN */ "Unknown error", /* not POSIX */
+ /* 36 EDEADLK */ "Resource deadlock avoided",
+ /* 37 UNKNOWN */ "Unknown error",
+ /* 38 ENAMETOOLONG */ "Filename too long",
+ /* 39 ENOLCK */ "No locks available",
+ /* 40 ENOSYS */ "Function not implemented",
+ /* 41 ENOTEMPTY */ "Directory not empty",
+ /* 42 EILSEQ */ "Illegal byte sequence",
+ /* 43 */ "Unknown error"
+
+};
+
+int _sys_nerr = sizeof( _sys_errlist ) / sizeof( _sys_errlist[ 0 ] ) - 1;
+
+/* The above array contains all the errors including unknown error # 37
+ which is used if msg_num is unknown */
+
+
+/* ***NOTE: Parameter _SYS_MSGMAX (in file syserr.h) indicates the length of
+ the longest systerm error message in the above table. When you add or
+ modify a message, you must update the value _SYS_MSGMAX, if appropriate. */
diff --git a/private/crt32/misc/umask.c b/private/crt32/misc/umask.c
new file mode 100644
index 000000000..9ca63a876
--- /dev/null
+++ b/private/crt32/misc/umask.c
@@ -0,0 +1,55 @@
+/***
+*umask.c - set file permission mask
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _umask() - sets file permission mask of current process*
+* affecting files created by creat, open, or sopen.
+*
+*Revision History:
+* 06-02-89 PHG module created
+* 03-16-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 04-05-90 GJF Added #include <io.h>.
+* 10-04-90 GJF New-style function declarator.
+* 01-17-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <io.h>
+
+/***
+*int _umask(mode) - set the file mode mask
+*
+*Purpose:
+* Sets the file-permission mask of the current process* which
+* modifies the permission setting of new files created by creat,
+* open, or sopen.
+*
+*Entry:
+* int mode - new file permission mask
+* may contain S_IWRITE, S_IREAD, S_IWRITE | S_IREAD.
+* The S_IREAD bit has no effect under OS/2.
+*
+*Exit:
+* returns the previous setting of the file permission mask.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _umask (
+ int mode
+ )
+{
+ register int oldmode; /* old umask value */
+
+ mode &= 0x180; /* only user read/write permitted */
+ oldmode = _umaskval; /* remember old value */
+ _umaskval = mode; /* set new value */
+ return oldmode; /* return old value */
+}
diff --git a/private/crt32/misc/winsig.c b/private/crt32/misc/winsig.c
new file mode 100644
index 000000000..310f1c62f
--- /dev/null
+++ b/private/crt32/misc/winsig.c
@@ -0,0 +1,709 @@
+/***
+*winsig.c - C signal support
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved
+*
+*Purpose:
+* Defines signal(), raise() and supporting functions.
+*
+*Revision History:
+* 10-21-91 GJF Signal for Win32 and Dosx32. Copied from old signal.c
+* (the Cruiser implementation with some revisions for
+* Win32), then extensively rewritten.
+* 11-08-91 GJF Cleaned up header files usage.
+* 12-13-91 GJF Fixed multi-thread build.
+* 09-30-92 SRW Add WINAPI keyword to CtrlC handler
+* 02-17-93 GJF Changed for new _getptd().
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <errno.h>
+#include <float.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <oscalls.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * look up the first entry in the exception-action table corresponding to
+ * the given signal
+ */
+#ifdef MTHREAD
+static struct _XCPT_ACTION * _CRTAPI3 siglookup(int, struct _XCPT_ACTION *);
+#else /* not MTHREAD */
+static struct _XCPT_ACTION * _CRTAPI3 siglookup(int);
+#endif /* MTHREAD */
+
+/*
+ * variables holding action codes (and code pointers) for SIGINT, SIGBRK,
+ * SIGABRT and SIGTERM.
+ *
+ * note that the disposition (i.e., action to be taken upon receipt) of
+ * these signals is defined on a per-process basis (not per-thread)!!
+ */
+
+static _PHNDLR ctrlc_action = SIG_DFL; /* SIGINT */
+static _PHNDLR ctrlbreak_action = SIG_DFL; /* SIGBREAK */
+static _PHNDLR abort_action = SIG_DFL; /* SIGABRT */
+static _PHNDLR term_action = SIG_DFL; /* SIGTERM */
+
+/*
+ * flag indicated whether or not a handler has been installed to capture
+ * ^C and ^Break events.
+ */
+static int ConsoleCtrlHandler_Installed = 0;
+
+
+/***
+*static BOOL WINAPI ctrlevent_capture(DWORD CtrlType) - capture ^C and ^Break events
+*
+*Purpose:
+* Capture ^C and ^Break events from the console and dispose of them
+* according the values in ctrlc_action and ctrlbreak_action, resp.
+* This is the routine that evokes the user-defined action for SIGINT
+* (^C) or SIGBREAK (^Break) installed by a call to signal().
+*
+*Entry:
+* DWORD CtrlType - indicates type of event, two values:
+* CTRL_C_EVENT
+* CTRL_BREAK_EVENT
+*
+*Exit:
+* Returns TRUE to indicate the event (signal) has been handled.
+* Otherwise, returns FALSE.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static BOOL WINAPI ctrlevent_capture (
+ DWORD CtrlType
+ )
+{
+ _PHNDLR ctrl_action;
+ _PHNDLR *pctrl_action;
+ int sigcode;
+
+ _mlock(_SIGNAL_LOCK);
+
+ /*
+ * Identify the type of event and fetch the corresponding action
+ * description.
+ */
+
+ if ( CtrlType == CTRL_C_EVENT ) {
+ ctrl_action = *(pctrl_action = &ctrlc_action);
+ sigcode = SIGINT;
+ }
+ else {
+ ctrl_action = *(pctrl_action = &ctrlbreak_action);
+ sigcode = SIGBREAK;
+ }
+
+ if ( ctrl_action == SIG_DFL ) {
+ /*
+ * return FALSE, indicating the event has NOT been handled
+ */
+ _munlock(_SIGNAL_LOCK);
+ return FALSE;
+ }
+
+ if ( ctrl_action != SIG_IGN ) {
+ /*
+ * Reset the action to be SIG_DFL and call the user's handler.
+ */
+ *pctrl_action = SIG_DFL;
+ _munlock(_SIGNAL_LOCK);
+ (*ctrl_action)(sigcode);
+ }
+ else
+ /*
+ * SIG_IGN - nothing special to do except release the lock
+ */
+ _munlock(_SIGNAL_LOCK);
+
+ /*
+ * Return TRUE, indicating the event has been handled (which may
+ * mean it's being ignored)
+ */
+ return TRUE;
+}
+
+
+
+/***
+*_PHNDLR signal(signum, sigact) - Define a signal handler
+*
+*Purpose:
+* The signal routine allows the user to define what action should
+* be taken when various signals occur. The Win32/Dosx32 implementation
+* supports seven signals, divided up into three general groups
+*
+* 1. Signals corresponding to OS exceptions. These are:
+* SIGFPE
+* SIGILL
+* SIGSEGV
+* Signal actions for these signals are installed by altering the
+* XcptAction and SigAction fields for the appropriate entry in the
+* exception-action table (XcptActTab[]).
+*
+* 2. Signals corresponding to ^C and ^Break. These are:
+* SIGINT
+* SIGBREAK
+* Signal actions for these signals are installed by altering the
+* _ctrlc_action and _ctrlbreak_action variables.
+*
+* 3. Signals which are implemented only in the runtime. That is, they
+* occur only as the result of a call to raise().
+* SIGABRT
+* SIGTERM
+*
+*
+*Entry:
+* int signum signal type. recognized signal types are:
+*
+* SIGABRT (ANSI)
+* SIGBREAK
+* SIGFPE (ANSI)
+* SIGILL (ANSI)
+* SIGINT (ANSI)
+* SIGSEGV (ANSI)
+* SIGTERM (ANSI)
+*
+* _PHNDLR sigact signal handling function or action code. the action
+* codes are:
+*
+* SIG_DFL - take the default action, whatever that may
+* be, upon receipt of this type type of signal.
+*
+* SIG_DIE - *** ILLEGAL ***
+* special code used in the XcptAction field of an
+* XcptActTab[] entry to indicate that the runtime is
+* to terminate the process upon receipt of the exception.
+* not accepted as a value for sigact.
+*
+* SIG_IGN - ignore this type of signal
+*
+* [function address] - transfer control to this address
+* when a signal of this type occurs.
+*
+*Exit:
+* Good return:
+* Signal returns the previous value of the signal handling function
+* (e.g., SIG_DFL, SIG_IGN, etc., or [function address]). This value is
+* returned in DX:AX.
+*
+* Error return:
+* Signal returns -1 and errno is set to EINVAL. The error return is
+* generally taken if the user submits bogus input values.
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+_PHNDLR _CRTAPI1 signal(
+ int signum,
+ _PHNDLR sigact
+ )
+{
+ struct _XCPT_ACTION *pxcptact;
+ _PHNDLR oldsigact;
+#ifdef MTHREAD
+ _ptiddata ptd;
+#endif
+
+ /*
+ * Check for values of sigact supported on other platforms but not
+ * on this one. Also, make sure sigact is not SIG_DIE
+ */
+ if ( (sigact == SIG_ACK) || (sigact == SIG_SGE) )
+ goto sigreterror;
+
+ /*
+ * Take care of all signals which do not correspond to exceptions
+ * in the host OS. Those are:
+ *
+ * SIGINT
+ * SIGBREAK
+ * SIGABRT
+ * SIGTERM
+ *
+ */
+ if ( (signum == SIGINT) || (signum == SIGBREAK) || (signum == SIGABRT)
+ || (signum == SIGTERM) ) {
+
+ _mlock(_SIGNAL_LOCK);
+
+ /*
+ * if SIGINT or SIGBREAK, make sure the handler is installed
+ * to capture ^C and ^Break events.
+ */
+ if ( ((signum == SIGINT) || (signum == SIGBREAK)) &&
+ !ConsoleCtrlHandler_Installed )
+ if ( SetConsoleCtrlHandler(ctrlevent_capture, TRUE)
+ == TRUE )
+ ConsoleCtrlHandler_Installed = TRUE;
+ else {
+ _doserrno = GetLastError();
+ _munlock(_SIGNAL_LOCK);
+ goto sigreterror;
+ }
+
+ switch (signum) {
+
+ case SIGINT:
+ oldsigact = ctrlc_action;
+ ctrlc_action = sigact;
+ break;
+
+ case SIGBREAK:
+ oldsigact = ctrlbreak_action;
+ ctrlbreak_action = sigact;
+ break;
+
+ case SIGABRT:
+ oldsigact = abort_action;
+ abort_action = sigact;
+ break;
+
+ case SIGTERM:
+ oldsigact = term_action;
+ term_action = sigact;
+ break;
+ }
+
+ _munlock(_SIGNAL_LOCK);
+ goto sigretok;
+ }
+
+ /*
+ * If we reach here, signum is supposed to be one the signals which
+ * correspond to exceptions in the host OS. Those are:
+ *
+ * SIGFPE
+ * SIGILL
+ * SIGSEGV
+ */
+
+ /*
+ * Make sure signum is one of the remaining supported signals.
+ */
+ if ( (signum != SIGFPE) && (signum != SIGILL) && (signum != SIGSEGV) )
+ goto sigreterror;
+
+
+#ifdef MTHREAD
+ /*
+ * Fetch the tid data table entry for this thread
+ */
+ ptd = _getptd();
+
+ /*
+ * Check that there a per-thread instance of the exception-action
+ * table for this thread. if there isn't, create one.
+ */
+ if ( ptd->_pxcptacttab == _XcptActTab )
+ /*
+ * allocate space for an exception-action table
+ */
+ if ( (ptd->_pxcptacttab = malloc(_XcptActTabSize))
+ != NULL )
+ /*
+ * initialize the table by copying over the contents
+ * of _XcptActTab[]
+ */
+ (void) memcpy(ptd->_pxcptacttab, _XcptActTab,
+ _XcptActTabSize);
+ else
+ /*
+ * cannot create exception-action table, return
+ * error to caller
+ */
+ goto sigreterror;
+
+#endif /* MTHREAD */
+
+ /*
+ * look up the proper entry in the exception-action table. note that
+ * if several exceptions are mapped to the same signal, this returns
+ * the pointer to first such entry in the exception action table. it
+ * is assumed that the other entries immediately follow this one.
+ */
+#ifdef MTHREAD
+ if ( (pxcptact = siglookup(signum, ptd->_pxcptacttab)) == NULL )
+#else /* not MTHREAD */
+ if ( (pxcptact = siglookup(signum)) == NULL )
+#endif /* MTHREAD */
+ goto sigreterror;
+
+ /*
+ * SIGSEGV, SIGILL and SIGFPE all have more than one exception mapped
+ * to them. the code below depends on the exceptions corresponding to
+ * the same signal being grouped together in the exception-action
+ * table.
+ */
+
+ /*
+ * store old signal action code for return value
+ */
+ oldsigact = pxcptact->XcptAction;
+
+ /*
+ * loop through all entries corresponding to the
+ * given signal and update the SigAction and XcptAction
+ * fields as appropriate
+ *
+ * should add a test to make sure pxcptact never runs
+ * off the end of the table (works okay for now because
+ * of the order of the entries).
+ */
+ while ( pxcptact->SigNum == signum ) {
+ /*
+ * take care of the SIG_IGN and SIG_DFL action
+ * codes
+ */
+ pxcptact->XcptAction = sigact;
+ pxcptact++;
+ }
+
+sigretok:
+ return(oldsigact);
+
+sigreterror:
+ errno = EINVAL;
+ return(SIG_ERR);
+}
+
+/***
+*int raise(signum) - Raise a signal
+*
+*Purpose:
+* This routine raises a signal (i.e., performs the action currently
+* defined for this signal). The action associated with the signal is
+* evoked directly without going through intermediate dispatching or
+* handling.
+*
+*Entry:
+* int signum - signal type (e.g., SIGINT)
+*
+*Exit:
+* returns 0 on good return, -1 on bad return.
+*
+*Exceptions:
+* May not return. Raise has no control over the action
+* routines defined for the various signals. Those routines may
+* abort, terminate, etc. In particular, the default actions for
+* certain signals will terminate the program.
+*
+*******************************************************************************/
+
+
+int _CRTAPI1 raise (
+ int signum
+ )
+{
+ _PHNDLR sigact;
+ _PHNDLR *psigact;
+ PEXCEPTION_POINTERS oldpxcptinfoptrs;
+ int oldfpecode;
+
+#ifdef MTHREAD
+ int siglock = 0;
+ _ptiddata ptd;
+#endif
+
+ switch (signum) {
+
+ case SIGINT:
+ sigact = *(psigact = &ctrlc_action);
+#ifdef MTHREAD
+ siglock++;
+#endif
+ break;
+
+ case SIGBREAK:
+ sigact = *(psigact = &ctrlbreak_action);
+#ifdef MTHREAD
+ siglock++;
+#endif
+ break;
+
+ case SIGABRT:
+ sigact = *(psigact = &abort_action);
+#ifdef MTHREAD
+ siglock++;
+#endif
+ break;
+
+ case SIGTERM:
+ sigact = *(psigact = &term_action);
+#ifdef MTHREAD
+ siglock++;
+#endif
+ break;
+
+ case SIGFPE:
+ case SIGILL:
+ case SIGSEGV:
+#ifdef MTHREAD
+ ptd = _getptd();
+ sigact = *(psigact = &(siglookup( signum,
+ ptd->_pxcptacttab )->XcptAction));
+#else
+ sigact = *(psigact = &(siglookup( signum )->
+ XcptAction));
+#endif
+ break;
+
+ default:
+ /*
+ * unsupported signal, return an error
+ */
+ return (-1);
+ }
+
+#ifdef MTHREAD
+ /*
+ * if signum is one of the 'process-wide' signals (i.e., SIGINT,
+ * SIGBREAK, SIGABRT or SIGTERM), assert _SIGNAL_LOCK.
+ */
+ if ( siglock )
+ _mlock(_SIGNAL_LOCK);
+#endif
+
+ /*
+ * If the current action is SIG_IGN, just return
+ */
+ if ( sigact == SIG_IGN ) {
+
+#ifdef MTHREAD
+ if ( siglock )
+ _munlock(_SIGNAL_LOCK);
+#endif
+ return(0);
+ }
+
+ /*
+ * If the current action is SIG_DFL, take the default action
+ */
+ if ( sigact == SIG_DFL ) {
+
+#ifdef MTHREAD
+ if ( siglock )
+ _munlock(_SIGNAL_LOCK);
+#endif
+ /*
+ * The current default action for all of the supported
+ * signals is to terminate with an exit code of 3.
+ *
+ * BUG, BUG!!!! THIS IS ALMOST CERTAINLY THE WRONG EXIT
+ * CODE FOR SOME OF THE SIGNALS IN NT!
+ */
+ _exit(3);
+ }
+
+ /*
+ * From here on, sigact is assumed to be a pointer to a user-supplied
+ * handler.
+ */
+
+ /*
+ * For signals which correspond to exceptions, set the pointer
+ * to the EXCEPTION_POINTERS structure to NULL
+ */
+ if ( (signum == SIGFPE) || (signum == SIGSEGV) ||
+ (signum == SIGILL) ) {
+#ifdef MTHREAD
+ oldpxcptinfoptrs = ptd->_tpxcptinfoptrs;
+ ptd->_tpxcptinfoptrs = NULL;
+#else
+ oldpxcptinfoptrs = _pxcptinfoptrs;
+ _pxcptinfoptrs = NULL;
+#endif
+
+ /*
+ * If signum is SIGFPE, also set _fpecode to
+ * _FPE_EXPLICITGEN
+ */
+ if ( signum == SIGFPE ) {
+#ifdef MTHREAD
+ oldfpecode = ptd->_tfpecode;
+ ptd->_tfpecode = _FPE_EXPLICITGEN;
+#else
+ oldfpecode = _fpecode;
+ _fpecode = _FPE_EXPLICITGEN;
+#endif
+ }
+ }
+
+ /*
+ * Reset the action to SIG_DFL and call the user specified handler
+ * routine.
+ */
+ *psigact = SIG_DFL;
+
+#ifdef MTHREAD
+ if ( siglock )
+ _munlock(_SIGNAL_LOCK);
+#endif
+
+ if ( signum == SIGFPE )
+ /*
+ * Special hack to support old SIGFPE handlers which
+ * expect the value of _fpecode as the second argument.
+ */
+#ifdef MTHREAD
+ (*(void (* _CRTAPI1)(int,int))sigact)(SIGFPE,
+ ptd->_tfpecode);
+#else
+ (*(void (* _CRTAPI1)(int,int))sigact)(SIGFPE, _fpecode);
+#endif
+ else
+ (*sigact)(signum);
+
+ /*
+ * For signals which correspond to exceptions, restore the pointer
+ * to the EXCEPTION_POINTERS structure.
+ */
+ if ( (signum == SIGFPE) || (signum == SIGSEGV) ||
+ (signum == SIGILL) ) {
+#ifdef MTHREAD
+ ptd->_tpxcptinfoptrs = oldpxcptinfoptrs;
+#else
+ _pxcptinfoptrs = oldpxcptinfoptrs;
+#endif
+
+ /*
+ * If signum is SIGFPE, also restore _fpecode
+ */
+ if ( signum == SIGFPE )
+#ifdef MTHREAD
+ ptd->_tfpecode = oldfpecode;
+#else
+ _fpecode = oldfpecode;
+#endif
+ }
+
+ return(0);
+}
+
+
+/***
+*struct _XCPT_ACTION *siglookup(int signum) - look up exception-action table
+* entry for signal.
+*
+*Purpose:
+* Find the first entry int _XcptActTab[] whose SigNum field is signum.
+*
+*Entry:
+* int signum - C signal type (e.g., SIGINT)
+*
+*Exit:
+* If successful, pointer to the table entry. If no such entry, NULL is
+* returned.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+static struct _XCPT_ACTION * _CRTAPI3 siglookup (
+ int signum,
+ struct _XCPT_ACTION *pxcptacttab
+ )
+{
+ struct _XCPT_ACTION *pxcptact = pxcptacttab;
+
+#else /* not MTHREAD */
+
+static struct _XCPT_ACTION * _CRTAPI3 siglookup(int signum)
+{
+ struct _XCPT_ACTION *pxcptact = _XcptActTab;
+
+#endif /* MTHREAD */
+ /*
+ * walk thru the _xcptactab table looking for the proper entry. note
+ * that in the case where more than one exception corresponds to the
+ * same signal, the first such instance in the table is the one
+ * returned.
+ */
+#ifdef MTHREAD
+
+ while ( (pxcptact->SigNum != signum) && (++pxcptact <
+ pxcptacttab + _XcptActTabCount) ) ;
+
+#else /* not MTHREAD */
+
+ while ( (pxcptact->SigNum != signum) && (++pxcptact <
+ _XcptActTab + _XcptActTabCount) ) ;
+
+#endif /* MTHREAD */
+
+ if ( pxcptact->SigNum == signum )
+ /*
+ * found a table entry corresponding to the signal
+ */
+ return(pxcptact);
+ else
+ /*
+ * found no table entry corresponding to the signal
+ */
+ return(NULL);
+}
+
+#ifdef MTHREAD
+
+/***
+*int *__fpecode(void) - return pointer to _fpecode field of the tidtable entry
+* for the current thread
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int * _CRTAPI1 __fpecode (
+ void
+ )
+{
+ return( &(_getptd()->_tfpecode) );
+}
+
+
+/***
+*void **__pxcptinfoptrs(void) - return pointer to _pxcptinfoptrs field of the
+* tidtable entry for the current thread
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void ** _CRTAPI1 __pxcptinfoptrs (
+ void
+ )
+{
+ return( &(_getptd()->_tpxcptinfoptrs) );
+}
+
+#endif
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/misc/winxfltr.c b/private/crt32/misc/winxfltr.c
new file mode 100644
index 000000000..22b4f08f4
--- /dev/null
+++ b/private/crt32/misc/winxfltr.c
@@ -0,0 +1,618 @@
+/***
+*winxfltr.c - startup exception filter
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved
+*
+*Purpose:
+* Defines _XcptFilter(), the function called by the exception filter
+* expression in the startup code.
+*
+*Revision History:
+* 10-31-91 GJF Module created. Copied from the original xcptfltr.c
+* then extensively revised.
+* 11-08-91 GJF Cleaned up header files usage.
+* 12-13-91 GJF Fixed multi-thread build.
+* 01-17-92 GJF Changed default handling under Win32 - unhandled
+* exceptions are now passed to UnhandledExceptionFilter.
+* Dosx32 behavior in unchanged. Also, used a couple of
+* local macros to simplify handling of single-thread vs
+* multi-thread code [_Win32_].
+* 02-16-93 GJF Changed for new _getptd().
+* 04-27-93 GJF Removed (commented out) entries in _XcptActTab which
+* corresponded to C RTEs. These will now simply be
+* passed on through to the system exception handler.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <float.h>
+#include <os2dll.h>
+#include <oscalls.h>
+#include <signal.h>
+#include <stddef.h>
+
+
+/*
+ * special code denoting no signal.
+ */
+#define NOSIG -1
+
+
+struct _XCPT_ACTION _VARTYPE1 _XcptActTab[] = {
+
+/*
+ * Exceptions corresponding to the same signal (e.g., SIGFPE) must be grouped
+ * together.
+ *
+ * XcptNum SigNum XcptAction
+ * -------------------------------------------------------------------
+ */
+ { (unsigned long)STATUS_ACCESS_VIOLATION, SIGSEGV, SIG_DFL },
+
+ { (unsigned long)STATUS_ILLEGAL_INSTRUCTION, SIGILL, SIG_DFL },
+
+ { (unsigned long)STATUS_PRIVILEGED_INSTRUCTION, SIGILL, SIG_DFL },
+
+/* { (unsigned long)STATUS_NONCONTINUABLE_EXCEPTION, NOSIG, SIG_DIE },
+ */
+/* { (unsigned long)STATUS_INVALID_DISPOSITION, NOSIG, SIG_DIE },
+ */
+ { (unsigned long)STATUS_FLOAT_DENORMAL_OPERAND, SIGFPE, SIG_DFL },
+
+ { (unsigned long)STATUS_FLOAT_DIVIDE_BY_ZERO, SIGFPE, SIG_DFL },
+
+ { (unsigned long)STATUS_FLOAT_INEXACT_RESULT, SIGFPE, SIG_DFL },
+
+ { (unsigned long)STATUS_FLOAT_INVALID_OPERATION, SIGFPE, SIG_DFL },
+
+ { (unsigned long)STATUS_FLOAT_OVERFLOW, SIGFPE, SIG_DFL },
+
+ { (unsigned long)STATUS_FLOAT_STACK_CHECK, SIGFPE, SIG_DFL },
+
+ { (unsigned long)STATUS_FLOAT_UNDERFLOW, SIGFPE, SIG_DFL },
+
+/* { (unsigned long)STATUS_INTEGER_DIVIDE_BY_ZERO, NOSIG, SIG_DIE },
+ */
+/* { (unsigned long)STATUS_STACK_OVERFLOW, NOSIG, SIG_DIE }
+ */
+};
+
+/*
+ * size of the exception-action table (in bytes)
+ */
+int _CRTVAR1 _XcptActTabSize = sizeof _XcptActTab;
+
+/*
+ * number of entries in the exception-action table
+ */
+int _CRTVAR1 _XcptActTabCount = (sizeof _XcptActTab)/sizeof(_XcptActTab[0]);
+
+
+#ifdef MTHREAD
+
+/*
+ * the FPECODE and PXCPTINFOPTRS macros are intended to simplify some of
+ * single vs multi-thread code in the filter function. basically, each macro
+ * is conditionally defined to be a global variable or the corresponding
+ * field in the per-thread data structure. NOTE THE ASSUMPTION THAT THE
+ * _ptiddata VARIABLE IS ALWAYS NAMED ptd!!!!
+ */
+
+#define FPECODE ptd->_tfpecode
+
+#define PXCPTINFOPTRS ptd->_tpxcptinfoptrs
+
+#else
+
+/*
+ * global variable containing the floating point exception code
+ */
+int _VARTYPE1 _fpecode = _FPE_EXPLICITGEN;
+
+#define FPECODE _fpecode
+
+/*
+ * global variable holding _PEXCEPTION_INFO_PTRS value
+ */
+void * _VARTYPE1 _pxcptinfoptrs = NULL;
+
+#define PXCPTINFOPTRS _pxcptinfoptrs
+
+#endif /* MTHREAD */
+
+/*
+ * function to look up the exception action table (_XcptActTab[]) corresponding
+ * to the given exception
+ */
+
+#ifdef MTHREAD
+
+static struct _XCPT_ACTION * _CRTAPI3 xcptlookup(
+ unsigned long,
+ struct _XCPT_ACTION *
+ );
+
+#else /* ndef MTHREAD */
+
+static struct _XCPT_ACTION * _CRTAPI3 xcptlookup(
+ unsigned long
+ );
+
+#endif /* MTHREAD */
+
+#ifdef DEBUG
+
+/*
+ * prototypes for debugging routines
+ */
+void prXcptActTabEntry(struct _XCPT_ACTION *);
+void prXcptActTab(void);
+
+#endif /* DEBUG */
+
+/***
+*int _XcptFilter(xcptnum, pxcptptrs) - Identify exception and the action to
+* be taken with it
+*
+*Purpose:
+* _XcptFilter() is called by the exception filter expression of the
+* _try - _except statement, in the startup code, which guards the call
+* to the user's main(). _XcptFilter() consults the _XcptActTab[] table
+* to identify the exception and determine its disposition. The
+* is disposition of an exception corresponding to a C signal may be
+* modified by a call to signal(). There are three broad cases:
+*
+* (1) Unrecognized exceptions and exceptions for which the XcptAction
+* value is SIG_DFL.
+*
+#ifndef DOSX32
+* In both of these cases, UnhandledExceptionFilter() is called and
+* its return value is returned.
+#else
+* In both of these cases, EXCEPTION_CONTINUE_SEARCH is returned to
+* cause the OS exception dispatcher to pass the exception onto the
+* next exception handler in the chain (usually a system default
+* handler).
+#endif
+*
+* (2) Exceptions corresponding to C signals with an XcptAction value
+* NOT equal to SIG_DFL.
+*
+* These are the C signals whose disposition has been affected by a
+* call to signal() or whose default semantics differ slightly from
+* from the corresponding OS exception. In all cases, the appropriate
+* disposition of the C signal is made by the function (e.g., calling
+* a user-specified signal handler). Then, EXCEPTION_CONTINUE_EXECU-
+* TION is returned to cause the OS exception dispatcher to dismiss
+* the exception and resume execution at the point where the
+* exception occurred.
+*
+* (3) Exceptions for which the XcptAction value is SIG_DIE.
+*
+* These are the exceptions corresponding to fatal C runtime errors.
+* _XCPT_HANDLE is returned to cause control to pass into the
+* _except-block of the _try - _except statement. There, the runtime
+* error is identified, an appropriate error message is printed out
+* and the program is terminated.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+* That's what it's all about!
+*
+*******************************************************************************/
+
+int _CRTAPI1 _XcptFilter (
+ unsigned long xcptnum,
+ PEXCEPTION_POINTERS pxcptinfoptrs
+ )
+{
+ struct _XCPT_ACTION * pxcptact;
+ _PHNDLR phandler;
+ void *oldpxcptinfoptrs;
+ int oldfpecode;
+
+#ifdef MTHREAD
+ _ptiddata ptd = _getptd();
+#endif /* MTHREAD */
+
+ /*
+ * first, take care of all unrecognized exceptions and exceptions with
+ * XcptAction values of SIG_DFL.
+ */
+#ifdef MTHREAD
+ if ( ((pxcptact = xcptlookup(xcptnum, ptd->_pxcptacttab)) == NULL)
+ || (pxcptact->XcptAction == SIG_DFL) )
+#else /* not MTHREAD */
+ if ( ((pxcptact = xcptlookup(xcptnum)) == NULL) ||
+ (pxcptact->XcptAction == SIG_DFL) )
+#endif /* MTHREAD */
+
+#ifndef DOSX32
+ /*
+ * pass the buck to the UnhandledExceptionFilter
+ */
+ return( UnhandledExceptionFilter(pxcptinfoptrs) );
+#else
+ /*
+ * pass the buck to the next level exception handler
+ */
+ return(EXCEPTION_CONTINUE_SEARCH);
+#endif
+
+#ifdef DEBUG
+ prXcptActTabEntry(pxcptact);
+#endif /* DEBUG */
+
+ /*
+ * next, weed out all of the exceptions that need to be handled by
+ * dying, perhaps with a runtime error message
+ */
+ if ( pxcptact->XcptAction == SIG_DIE ) {
+ /*
+ * reset XcptAction (in case of recursion) and drop into the
+ * except-clause.
+ */
+ pxcptact->XcptAction = SIG_DFL;
+ return(EXCEPTION_EXECUTE_HANDLER);
+ }
+
+ /*
+ * next, weed out all of the exceptions that are simply ignored
+ */
+ if ( pxcptact->XcptAction == SIG_IGN )
+ /*
+ * resume execution
+ */
+ return(EXCEPTION_CONTINUE_EXECUTION);
+
+ /*
+ * the remaining exceptions all correspond to C signals which have
+ * signal handlers associated with them. for some, special setup
+ * is required before the signal handler is called. in all cases,
+ * if the signal handler returns, -1 is returned by this function
+ * to resume execution at the point where the exception occurred.
+ *
+ * before calling the signal handler, the XcptAction field of the
+ * exception-action table entry must be reset.
+ */
+ phandler = pxcptact->XcptAction;
+
+ /*
+ * reset the action to be the default
+ */
+ pxcptact->XcptAction = SIG_DFL;
+
+ /*
+ * save the old value of _pxcptinfoptrs (in case this is a nested
+ * exception/signal) and store the current one.
+ */
+ oldpxcptinfoptrs = PXCPTINFOPTRS;
+ PXCPTINFOPTRS = pxcptinfoptrs;
+
+ /*
+ * call the user-supplied signal handler
+ *
+ * floating point exceptions must be handled specially since, from
+ * the C point-of-view, there is only one signal. the exact identity
+ * of the exception is passed in the global variable _fpecode.
+ */
+ if ( pxcptact->SigNum == SIGFPE ) {
+ /*
+ * Save the current _fpecode in case it is a nested floating
+ * point exception (not clear that we need to support this,
+ * but it's easy).
+ */
+ oldfpecode = FPECODE;
+
+ /*
+ * there are no exceptions corresponding to
+ * following _FPE_xxx codes:
+ *
+ * _FPE_UNEMULATED
+ * _FPE_SQRTNEG
+ *
+ * futhermore, STATUS_FLOATING_STACK_CHECK is
+ * raised for both floating point stack under-
+ * flow and overflow. thus, the exception does
+ * not distinguish between _FPE_STACKOVERLOW
+ * and _FPE_STACKUNDERFLOW. arbitrarily, _fpecode
+ * is set to the former value.
+ *
+ * the following should be a switch statement but, alas, the
+ * compiler doesn't like switching on unsigned longs...
+ */
+ if ( pxcptact->XcptNum == STATUS_FLOAT_DIVIDE_BY_ZERO )
+
+ FPECODE = _FPE_ZERODIVIDE;
+
+ else if ( pxcptact->XcptNum == STATUS_FLOAT_INVALID_OPERATION )
+
+ FPECODE = _FPE_INVALID;
+
+ else if ( pxcptact->XcptNum == STATUS_FLOAT_OVERFLOW )
+
+ FPECODE = _FPE_OVERFLOW;
+
+ else if ( pxcptact->XcptNum == STATUS_FLOAT_UNDERFLOW )
+
+ FPECODE = _FPE_UNDERFLOW;
+
+ else if ( pxcptact->XcptNum == STATUS_FLOAT_DENORMAL_OPERAND )
+
+ FPECODE = _FPE_DENORMAL;
+
+ else if ( pxcptact->XcptNum == STATUS_FLOAT_INEXACT_RESULT )
+
+ FPECODE = _FPE_INEXACT;
+
+ else if ( pxcptact->XcptNum == STATUS_FLOAT_STACK_CHECK )
+
+ FPECODE = _FPE_STACKOVERFLOW;
+
+ /*
+ * call the SIGFPE handler. note the special hack to support
+ * old MS-C programs whose SIGFPE handlers expect two args.
+ *
+ * NOTE: THE CAST AND CALL BELOW DEPEND ON _CRTAPI1 BEING
+ * CALLER CLEANUP!
+ */
+ (*(void (* _CRTAPI1)(int, int))phandler)(SIGFPE, FPECODE);
+
+ /*
+ * restore the old value of _fpecode
+ */
+ FPECODE = oldfpecode;
+ }
+ else
+ (*phandler)(pxcptact->SigNum);
+
+ /*
+ * restore the old value of _pxcptinfoptrs
+ */
+ PXCPTINFOPTRS = oldpxcptinfoptrs;
+
+ return(EXCEPTION_CONTINUE_EXECUTION);
+
+}
+
+
+/***
+*struct _XCPT_ACTION * xcptlookup(xcptnum, pxcptrec) - look up exception-action
+* table entry for xcptnum
+*
+*Purpose:
+* Find the in _XcptActTab[] whose Xcptnum field is xcptnum.
+*
+*Entry:
+* unsigned long xcptnum - exception type
+*
+* _PEXCEPTIONREPORTRECORD pxcptrec - pointer to exception report record
+* (used only to distinguish different types of XCPT_SIGNAL)
+*
+*Exit:
+* If successful, pointer to the table entry. If no such entry, NULL is
+* returned.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+static struct _XCPT_ACTION * _CRTAPI3 xcptlookup (
+ unsigned long xcptnum,
+ struct _XCPT_ACTION * pxcptacttab
+ )
+
+#else /* not MTHREAD */
+
+static struct _XCPT_ACTION * _CRTAPI3 xcptlookup (
+ unsigned long xcptnum
+ )
+
+#endif /* MTHREAD */
+
+{
+#ifdef MTHREAD
+ struct _XCPT_ACTION *pxcptact = pxcptacttab;
+#else /* ndef MTHREAD */
+ struct _XCPT_ACTION *pxcptact = _XcptActTab;
+#endif /* MTHREAD */
+
+ /*
+ * walk thru the _xcptactab table looking for the proper entry
+ */
+#ifdef MTHREAD
+
+ while ( (pxcptact->XcptNum != xcptnum) && (++pxcptact <
+ pxcptacttab + _XcptActTabCount) ) ;
+
+#else /* not MTHREAD */
+
+ while ( (pxcptact->XcptNum != xcptnum) && (++pxcptact <
+ _XcptActTab + _XcptActTabCount) ) ;
+
+#endif /* MTHREAD */
+
+ /*
+ * if no table entry was found corresponding to xcptnum, return NULL
+ */
+ if ( pxcptact->XcptNum != xcptnum )
+ return(NULL);
+
+ return(pxcptact);
+}
+
+#ifdef DEBUG
+
+/*
+ * DEBUGGING TOOLS!
+ */
+struct xcptnumstr {
+ unsigned long num;
+ char *str;
+};
+
+struct xcptnumstr XcptNumStr[] = {
+
+ { (unsigned long)STATUS_DATATYPE_MISALIGNMENT,
+ "STATUS_DATATYPE_MISALIGNMENT" },
+
+ { (unsigned long)STATUS_ACCESS_VIOLATION,
+ "STATUS_ACCESS_VIOLATION" },
+
+ { (unsigned long)STATUS_ILLEGAL_INSTRUCTION,
+ "STATUS_ILLEGAL_INSTRUCTION" },
+
+ { (unsigned long)STATUS_NONCONTINUABLE_EXCEPTION,
+ "STATUS_NONCONTINUABLE_EXCEPTION" },
+
+ { (unsigned long)STATUS_INVALID_DISPOSITION,
+ "STATUS_INVALID_DISPOSITION" },
+
+ { (unsigned long)STATUS_FLOAT_DENORMAL_OPERAND,
+ "STATUS_FLOAT_DENORMAL_OPERAND" },
+
+ { (unsigned long)STATUS_FLOAT_DIVIDE_BY_ZERO,
+ "STATUS_FLOAT_DIVIDE_BY_ZERO" },
+
+ { (unsigned long)STATUS_FLOAT_INEXACT_RESULT,
+ "STATUS_FLOAT_INEXACT_RESULT" },
+
+ { (unsigned long)STATUS_FLOAT_INVALID_OPERATION,
+ "STATUS_FLOAT_INVALID_OPERATION" },
+
+ { (unsigned long)STATUS_FLOAT_OVERFLOW,
+ "STATUS_FLOAT_OVERFLOW" },
+
+ { (unsigned long)STATUS_FLOAT_STACK_CHECK,
+ "STATUS_FLOAT_STACK_CHECK" },
+
+ { (unsigned long)STATUS_FLOAT_UNDERFLOW,
+ "STATUS_FLOAT_UNDERFLOW" },
+
+ { (unsigned long)STATUS_INTEGER_DIVIDE_BY_ZERO,
+ "STATUS_INTEGER_DIVIDE_BY_ZERO" },
+
+ { (unsigned long)STATUS_PRIVILEGED_INSTRUCTION,
+ "STATUS_PRIVILEGED_INSTRUCTION" },
+
+ { (unsigned long)_STATUS_STACK_OVERFLOW,
+ "_STATUS_STACK_OVERFLOW" }
+};
+
+#define XCPTNUMSTR_SZ ( sizeof XcptNumStr / sizeof XcptNumStr[0] )
+
+/*
+ * return string mnemonic for exception
+ */
+char * XcptNumToStr (
+ unsigned long xcptnum
+ )
+{
+ int indx;
+
+ for ( indx = 0 ; indx < XCPTNUMSTR_SZ ; indx++ )
+ if ( XcptNumStr[indx].num == xcptnum )
+ return(XcptNumStr[indx].str);
+
+ return(NULL);
+}
+
+struct signumstr {
+ int num;
+ char *str;
+};
+
+struct signumstr SigNumStr[] = {
+ { SIGINT, "SIGINT" },
+ { SIGILL, "SIGILL" },
+ { SIGFPE, "SIGFPE" },
+ { SIGSEGV, "SIGSEGV" },
+ { SIGTERM, "SIGTERM" },
+ { SIGBREAK, "SIGBREAK" },
+ { SIGABRT, "SIGABRT" }
+};
+
+#define SIGNUMSTR_SZ ( sizeof SigNumStr / sizeof SigNumStr[0] )
+
+/*
+ * return string mnemonic for signal
+ */
+char * SigNumToStr (
+ int signum
+ )
+{
+ int indx;
+
+ for ( indx = 0 ; indx < SIGNUMSTR_SZ ; indx++ )
+ if ( SigNumStr[indx].num == signum )
+ return(SigNumStr[indx].str);
+
+ return(NULL);
+}
+
+struct actcodestr {
+ _PHNDLR code;
+ char *str;
+};
+
+struct actcodestr ActCodeStr[] = {
+ { SIG_DFL, "SIG_DFL" },
+ { SIG_IGN, "SIG_IGN" },
+ { SIG_DIE, "SIG_DIE" }
+};
+
+#define ACTCODESTR_SZ ( sizeof ActCodeStr / sizeof ActCodeStr[0] )
+
+/*
+ * return string mnemonic for action code
+ */
+char * ActCodeToStr (
+ _PHNDLR action
+ )
+{
+ int indx;
+
+ for ( indx = 0 ; indx < ACTCODESTR_SZ ; indx++ )
+ if ( ActCodeStr[indx].code == action)
+ return(ActCodeStr[indx].str);
+
+ return("FUNCTION ADDRESS");
+}
+
+/*
+ * print out exception-action table entry
+ */
+void prXcptActTabEntry (
+ struct _XCPT_ACTION *pxcptact
+ )
+{
+ printf("XcptNum = %s\n", XcptNumToStr(pxcptact->XcptNum));
+ printf("SigNum = %s\n", SigNumToStr(pxcptact->SigNum));
+ printf("XcptAction = %s\n", ActCodeToStr(pxcptact->XcptAction));
+}
+
+/*
+ * print out all entries in the exception-action table
+ */
+void prXcptActTab (
+ void
+ )
+{
+ int indx;
+
+ for ( indx = 0 ; indx < _XcptActTabCount ; indx++ ) {
+ printf("\n_XcptActTab[%d] = \n", indx);
+ prXcptActTabEntry(&_XcptActTab[indx]);
+ }
+}
+
+#endif /* DEBUG */
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/misc/wrt2err.c b/private/crt32/misc/wrt2err.c
new file mode 100644
index 000000000..40ebe675a
--- /dev/null
+++ b/private/crt32/misc/wrt2err.c
@@ -0,0 +1,84 @@
+/***
+*wrt2err.c - write an LSTRING to stderr (OS/2 version)
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains a routine __wrt2err that writes an LSTRING
+* (one byte length followed by the several bytes of the string)
+* to the standard error handle (2). This is a helper routine used
+* for MATH error messages (and also FORTRAN error messages). It
+* is in the C library rather than the math library because there
+* are separate MS-DOS and MS OS/2 versions.
+*
+*Revision History:
+* 06-30-89 PHG module created, based on asm version
+* 03-16-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 07-24-90 SBM Removed '32' from API names
+* 10-04-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 04-26-91 SRW Removed level 3 warnings
+* 07-18-91 GJF Replaced call to DbgPrint with WriteFile to standard
+* error handle [_WIN32_].
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+
+/***
+*__wrt2err(msg) - write an LSTRING to stderr
+*
+*Purpose:
+* Takes a near pointer in BX, which is a pointer to an LSTRING which
+* is to be written to standard error. An LSTRING is a one-byte length
+* followed by that many bytes for the character string (as opposed to
+* a null-terminated string).
+*
+*Entry:
+* char *msg = pointer to LSTRING to write to standard error.
+*
+*Exit:
+* Nothing returned.
+*
+*Exceptions:
+* None handled.
+*
+*******************************************************************************/
+
+void __wrt2err (
+ char *msg
+ )
+{
+ unsigned long length; /* length of string to write */
+ unsigned long numwritten; /* number of bytes written */
+
+ length = *msg++; /* 1st byte is length */
+
+ /* write the message to stderr */
+#ifdef _CRUISER_
+
+ DOSWRITE(2, msg, length, &numwritten);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ WriteFile((HANDLE)_osfhnd[2], msg, length, &numwritten, NULL);
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+}
+
+#endif /* _POSIX_ */
+
diff --git a/private/crt32/small/crt0dat.c b/private/crt32/small/crt0dat.c
new file mode 100644
index 000000000..55ca7fef3
--- /dev/null
+++ b/private/crt32/small/crt0dat.c
@@ -0,0 +1 @@
+#include "..\startup\crt0dat.c"
diff --git a/private/crt32/small/ctype.c b/private/crt32/small/ctype.c
new file mode 100644
index 000000000..a2620790d
--- /dev/null
+++ b/private/crt32/small/ctype.c
@@ -0,0 +1 @@
+#include "..\misc\ctype.c"
diff --git a/private/crt32/small/makefile b/private/crt32/small/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/small/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/small/makefile.inc b/private/crt32/small/makefile.inc
new file mode 100644
index 000000000..a83771a1e
--- /dev/null
+++ b/private/crt32/small/makefile.inc
@@ -0,0 +1,19 @@
+crt0dat.c: ..\startup\crt0dat.c
+
+ctype.c: ..\misc\ctype.c
+
+nlsdata1.c: ..\misc\nlsdata1.c
+
+nlsdata2.c: ..\misc\nlsdata2.c
+
+nlsdata3.c: ..\misc\nlsdata3.c
+
+syserr.c: ..\misc\syserr.c
+
+timeset.c: ..\time\timeset.c
+
+tlssup.c: ..\startup\tlssup.c
+
+mips\huge.s: ..\..\fp32st\tran\mips\huge.s
+
+
diff --git a/private/crt32/small/mips/huge.s b/private/crt32/small/mips/huge.s
new file mode 100644
index 000000000..a7955d283
--- /dev/null
+++ b/private/crt32/small/mips/huge.s
@@ -0,0 +1,2 @@
+#define data sdata
+#include "..\..\fp32st\tran\mips\huge.s"
diff --git a/private/crt32/small/nlsdata1.c b/private/crt32/small/nlsdata1.c
new file mode 100644
index 000000000..1a16055e5
--- /dev/null
+++ b/private/crt32/small/nlsdata1.c
@@ -0,0 +1 @@
+#include "..\misc\nlsdata1.c"
diff --git a/private/crt32/small/nlsdata2.c b/private/crt32/small/nlsdata2.c
new file mode 100644
index 000000000..442a86e5e
--- /dev/null
+++ b/private/crt32/small/nlsdata2.c
@@ -0,0 +1 @@
+#include "..\misc\nlsdata2.c"
diff --git a/private/crt32/small/nlsdata3.c b/private/crt32/small/nlsdata3.c
new file mode 100644
index 000000000..5266af099
--- /dev/null
+++ b/private/crt32/small/nlsdata3.c
@@ -0,0 +1 @@
+#include "..\misc\nlsdata3.c"
diff --git a/private/crt32/small/sources b/private/crt32/small/sources
new file mode 100644
index 000000000..22916a7d6
--- /dev/null
+++ b/private/crt32/small/sources
@@ -0,0 +1,54 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=small
+
+TARGETNAME=small
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+!INCLUDE ..\crt32.def
+
+!IF $(ALPHA)
+GPSIZE=32
+!ELSE
+GPSIZE=64
+!ENDIF
+
+SOURCES=syserr.c \
+ crt0dat.c \
+ ctype.c \
+ nlsdata1.c \
+ nlsdata2.c \
+ nlsdata3.c \
+ timeset.c \
+ tlssup.c
+
+MIPS_SOURCES=mips\huge.s
+
+NTTARGETFILE0=
+
+
diff --git a/private/crt32/small/syserr.c b/private/crt32/small/syserr.c
new file mode 100644
index 000000000..a6f4c79d2
--- /dev/null
+++ b/private/crt32/small/syserr.c
@@ -0,0 +1 @@
+#include "..\misc\syserr.c"
diff --git a/private/crt32/small/timeset.c b/private/crt32/small/timeset.c
new file mode 100644
index 000000000..f29b14564
--- /dev/null
+++ b/private/crt32/small/timeset.c
@@ -0,0 +1 @@
+#include "..\time\timeset.c"
diff --git a/private/crt32/small/tlssup.c b/private/crt32/small/tlssup.c
new file mode 100644
index 000000000..764bb3714
--- /dev/null
+++ b/private/crt32/small/tlssup.c
@@ -0,0 +1 @@
+#include "..\startup\tlssup.c"
diff --git a/private/crt32/startup/_setargv.c b/private/crt32/startup/_setargv.c
new file mode 100644
index 000000000..7b3718401
--- /dev/null
+++ b/private/crt32/startup/_setargv.c
@@ -0,0 +1,18 @@
+/***
+*_setargv.c - Wildcard argv[] expansion
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* _setargv performs wildcard argv[] expansion
+*
+* NOTE: This stub module scheme is compatible with NT build
+* procedure.
+*
+*Revision History:
+* 09-25-91 JCR Stub module created.
+*
+*******************************************************************************/
+
+#define WILDCARD 1
+#include "stdargv.c"
diff --git a/private/crt32/startup/alpha/chkstk.s b/private/crt32/startup/alpha/chkstk.s
new file mode 100644
index 000000000..104254349
--- /dev/null
+++ b/private/crt32/startup/alpha/chkstk.s
@@ -0,0 +1,131 @@
+// TITLE("Runtime Stack Checking")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+// Copyright (c) 1992 Digital Equipment Corporation
+//
+// Module Name:
+//
+// chkstk.s
+//
+// Abstract:
+//
+// This module implements runtime stack checking.
+//
+// Author:
+//
+// David N. Cutler (davec) 14-Mar-1991
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Thomas Van Baak (tvb) 7-May-1992
+//
+// Adapted for Alpha AXP.
+//
+//--
+
+#include "ksalpha.h"
+
+ SBTTL("Check Stack")
+//++
+//
+// ULONG
+// _RtlCheckStack (
+// IN ULONG Allocation
+// )
+//
+// Routine Description:
+//
+// This function provides runtime stack checking for local allocations
+// that are more than a page and for storage dynamically allocated with
+// the alloca function. Stack checking consists of probing downward in
+// the stack a page at a time. If the current stack commitment is exceeded,
+// then the system will automatically attempts to expand the stack. If the
+// attempt succeeds, then another page is committed. Otherwise, a stack
+// overflow exception is raised. It is the responsibility of the caller to
+// handle this exception.
+//
+// N.B. This routine is called using a non-standard calling sequence since
+// it is typically called from within the prologue. The allocation size
+// argument is in register t12 and it must be preserved. Register t11
+// may contain the callers saved ra and it must be preserved. The choice
+// of these registers is hard-coded into the acc C compiler. Register v0
+// may contain a static link pointer (exception handlers) and so it must
+// be preserved. Since this function is called from within the prolog,
+// the a' registers must be preserved, as well as all the s' registers.
+// Registers t8, t9, and t10 are used by this function and are not
+// preserved.
+//
+// The typical calling sequence from the prologue is:
+//
+// mov ra, t11 // save return address
+// ldil t12, SIZE // set requested stack frame size
+// bsr ra, _RtlCheckStack // check stack page allocation
+// subq sp, t12, sp // allocate stack frame
+// mov t11, ra // restore return address
+//
+// Arguments:
+//
+// Allocation (t12) - Supplies the size of the allocation on the stack.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(_RtlCheckStack)
+
+ subq sp, t12, t8 // compute requested new stack address
+ mov v0, t10 // save v0 since the PALcode uses it
+ bgt sp, 10f // if sp>0, then running on user stack
+
+//
+// Running on kernel stack - compute stack limit from initial kernel stack.
+//
+
+ GET_INITIAL_KERNEL_STACK // (PALcode) result in v0
+
+ lda t9, -KERNEL_STACK_SIZE(v0) // compute low limit of kernel stack
+ br zero, 20f // finish in common code
+
+//
+// Running on user stack - get stack limit from thread environment block.
+//
+
+10: GET_THREAD_ENVIRONMENT_BLOCK // (PALcode) put TEB address in v0
+
+ ldl t9, TeStackLimit(v0) // get low limit of user stack address
+
+//
+// The requested bottom of the stack is in t8.
+// The current low limit of the stack is in t9.
+//
+// If the new stack address is greater than the current stack limit, then the
+// pages have already been allocated, and nothing further needs to be done.
+//
+
+20: mov t10, v0 // restore v0, no further PAL calls
+ cmpult t8, t9, t10 // t8<t9? new stack base within limit?
+ beq t10, 40f // if eq [false], then t8>=t9, so yes
+
+ ldil t10, ~(PAGE_SIZE - 1) // round down new stack address
+ and t8, t10, t8 // to next page boundary
+
+//
+// Go down one page, touch one quadword in it, and repeat until we reach the
+// new stack limit.
+//
+
+30: lda t9, -PAGE_SIZE(t9) // compute next address to check
+ stq zero, 0(t9) // probe stack address with a write
+ cmpeq t8, t9, t10 // t8=t9? at the low limit yet?
+ beq t10, 30b // if eq [false], more pages to probe
+
+40: ret zero, (ra) // return
+
+ .end _RtlCheckStack
diff --git a/private/crt32/startup/crt0.c b/private/crt32/startup/crt0.c
new file mode 100644
index 000000000..bc0e4f75d
--- /dev/null
+++ b/private/crt32/startup/crt0.c
@@ -0,0 +1,594 @@
+/***
+*crt0.c - C runtime initialization routine
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This the main startup routine. It is called upon program
+* startup by a very small assembler stub.
+*
+*Revision History:
+* 06-27-89 PHG Module created, based on asm version
+* 11-02-89 JCR Added DOS32QUERYSYSINFO to get osversion
+* 04-09-90 GJF Added #include <cruntime.h>. Put in explicit calling
+* types (_CALLTYPE1 or _CALLTYPE4) for __crt0(),
+* inherit(), __amsg_exit() and _cintDIV(). Also, fixed
+* the copyright and cleaned up the formatting a bit.
+* 04-10-90 GJF Fixed compiler warnings (-W3).
+* 08-08-90 GJF Added exception handling stuff (needed to support
+* runtime errors and signal()).
+* 08-31-90 GJF Removed 32 from API names.
+* 10-08-90 GJF New-style function declarators.
+* 12-05-90 GJF Fixed off-by-one error in inherit().
+* 12-06-90 GJF Win32 version of inherit().
+* 12-06-90 SRW Added _osfile back for win32. Changed _osfinfo from
+* an array of structures to an array of 32-bit handles
+* (_osfhnd)
+* 01-21-91 GJF ANSI naming.
+* 01-25-91 SRW Changed Win32 Process Startup [_WIN32_]
+* 02-01-91 SRW Removed usage of PPEB type [_WIN32_]
+* 02-05-91 SRW Changed to pass _osfile and _osfhnd arrays as binary
+* data to child process. [_WIN32_]
+* 04-02-91 GJF Need to get version number sooner so it can be used in
+* _heap_init. Prefixed an '_' onto BaseProcessStartup.
+* Version info now stored in _os[version|major|minor] and
+* _base[version|major|minor] (_WIN32_).
+* 04-10-91 PNT Added _MAC_ conditional
+* 04-26-91 SRW Removed level 3 warnings
+* 05-14-91 GJF Turn on exception handling for Dosx32.
+* 05-22-91 GJF Fixed careless errors.
+* 07-12-91 GJF Fixed one more careless error.
+* 08-13-91 GJF Removed definitions of _confh and _coninpfh.
+* 09-13-91 GJF Incorporated Stevewo's startup variations.
+* 11-07-91 GJF Revised try-except, fixed outdated comments on file
+* handle inheritance [_WIN32_].
+* 12-02-91 SRW Fixed WinMain startup code to skip over first token
+* plus delimiters for the lpszCommandLine parameter.
+* 01-17-92 GJF Merge of NT and CRT version. Restored Stevewo's scheme
+* for unhandled exceptions.
+* 02-13-92 GJF For Win32, moved file inheritance stuff to ioinit.c.
+* Call to inherit() is replace by call to _ioinit().
+* 04-16-92 DJM POSIX support
+* 08-26-92 SKS Add _osver, _winver, _winmajor, _winminor
+* 08-26-92 GJF Deleted version number(s) fetch from POSIX startup (it
+* involved a Win32 API call).
+* 09-30-92 SRW Call _heap_init before _mtinit
+* 04-26-93 GJF Made lpszCommandLine (unsigned char *) to deal with
+* chars > 127 in the command line.
+* 04-27-93 GJF Removed support for _RT_STACK, _RT_INTDIV,
+* _RT_INVALDISP and _RT_NONCONT.
+* 05-11-93 SKS Remove obsolete variable _atopsp
+* Change _mtinit to return failure
+* 05-14-93 GJF Added support for quoted program names.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <dos.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef _POSIX_
+#include <rterr.h>
+#else
+#include <posix/sys/types.h>
+#include <posix/unistd.h>
+#include <posix/signal.h>
+#endif
+#include <oscalls.h>
+
+#ifdef _CRUISER_
+/*
+ * C file info string
+ */
+char _acfinfo[] = "_C_FILE_INFO=";
+#endif /* _CRUISER_ */
+
+/*
+ * command line, environment, and a few other globals
+ */
+char *_acmdln; /* points to command line */
+char *_aenvptr; /* points to environment block */
+
+#ifdef _POSIX_
+char *_cmdlin;
+#endif
+
+void (_CRTAPI1 * _aexit_rtn)(int) = _exit; /* RT message return procedure */
+
+#ifdef _CRUISER_
+static void _CRTAPI3 inherit(void); /* local function */
+#endif /* _CRUISER_ */
+
+#ifndef _MAC_
+
+#ifdef _POSIX_
+
+/***
+*mainCRTStartup(PVOID Peb)
+*
+*Purpose:
+* This routine does the C runtime initialization, calls main(), and
+* then exits. It never returns.
+*
+*Entry:
+* PVOID Peb - pointer to Win32 Process Environment Block (not used)
+*
+*Exit:
+* This function never returns.
+*
+*******************************************************************************/
+
+void
+mainCRTStartup(
+ void
+ )
+{
+ int mainret;
+ char **ppch;
+
+ extern char **environ;
+ extern char * __PdxGetCmdLine(void); /* a hacked API in the Posix SS */
+ extern main(int,char**);
+
+ _cmdlin = __PdxGetCmdLine();
+ ppch = (char **)_cmdlin;
+ __argv = ppch;
+
+ // normalize argv pointers
+
+ __argc = 0;
+ while (NULL != *ppch) {
+ *ppch += (int)_cmdlin;
+ ++__argc;
+ ++ppch;
+ }
+ // normalize environ pointers
+
+ ++ppch;
+ environ = ppch;
+
+ while (NULL != *ppch) {
+ *ppch = *ppch + (int)_cmdlin;
+ ++ppch;
+ }
+
+ /*
+ * If POSIX runtime needs to fetch and store POSIX verion info,
+ * it should be done here.
+ *
+ * Get_and_save_version_info;
+ */
+
+ _heap_init(); /* initialize heap */
+ _cinit(); /* do C data initialize */
+
+ try {
+ mainret = main(__argc, __argv);
+ } except (EXCEPTION_EXECUTE_HANDLER) {
+ switch (GetExceptionCode()) {
+ case STATUS_ACCESS_VIOLATION:
+ kill(getpid(), SIGSEGV);
+ break;
+ case STATUS_ILLEGAL_INSTRUCTION:
+ case STATUS_PRIVILEGED_INSTRUCTION:
+ kill(getpid(), SIGILL);
+ break;
+ case STATUS_FLOAT_DENORMAL_OPERAND:
+ case STATUS_FLOAT_DIVIDE_BY_ZERO:
+ case STATUS_FLOAT_INEXACT_RESULT:
+ case STATUS_FLOAT_OVERFLOW:
+ case STATUS_FLOAT_STACK_CHECK:
+ case STATUS_FLOAT_UNDERFLOW:
+ kill(getpid(), SIGFPE);
+ break;
+ default:
+ kill(getpid(), SIGKILL);
+ }
+
+ mainret = -1;
+ }
+ exit(mainret);
+}
+#else /* ndef _POSIX_ */
+
+#ifdef _CRUISER_
+
+/***
+*__crt0(cmdline, envptr)
+*
+*Purpose:
+* This routine does the C runtime initialization, calls main(), and
+* then exits. It never returns.
+*
+*Entry:
+* char *cmdline - pointer to OS/2 command line
+* char *envptr - pointer to OS/2 environment block
+*
+*Exit:
+* This function never returns.
+*
+*******************************************************************************/
+
+void _CRTAPI1 __crt0 (
+ char *cmdline,
+ char *envptr
+ )
+{
+ int mainret;
+
+ /* initialize pointers to command line and environment */
+ _acmdln = cmdline;
+ _aenvptr = envptr;
+
+ /* Get the OS/2 version */
+
+ /* make sure our assumptions are correct */
+
+#if (_QSV_VERSION_MAJOR+1 != _QSV_VERSION_MINOR)
+#error Invalid DosQuerySysInfo parameters
+#endif
+
+ DOSQUERYSYSINFO(_QSV_VERSION_MAJOR, _QSV_VERSION_MINOR,
+ (unsigned char *)&_osmajor, (2*sizeof(int)) );
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+/***
+*BaseProcessStartup(PVOID Peb)
+*
+*Purpose:
+* This routine does the C runtime initialization, calls main(), and
+* then exits. It never returns.
+*
+*Entry:
+* PVOID Peb - pointer to Win32 Process Environment Block (not used)
+*
+*Exit:
+* This function never returns.
+*
+*******************************************************************************/
+
+#ifdef _DOSX32_
+
+void _BaseProcessStartup (
+
+#else
+
+#ifdef _WINMAIN_
+void WinMainCRTStartup(
+#else
+void mainCRTStartup(
+#endif
+
+#endif
+ void
+ )
+
+{
+ int mainret;
+
+#ifdef _WINMAIN_
+ unsigned char *lpszCommandLine;
+ STARTUPINFOA StartupInfo;
+#endif
+ _acmdln = (char *)GetCommandLine();
+ _aenvptr = (char *)GetEnvironmentStrings();
+
+ /*
+ * Get the full Win32 version
+ */
+ _osversion = /* OBSOLETE */
+ _osver = GetVersion();
+
+ _winminor = (_osver >> 8) & 0x00FF ;
+ _winmajor = _osver & 0x00FF ;
+ _winver = (_winmajor << 8) + _winminor;
+ _osver = (_osver >> 16) & 0x00FFFF ;
+
+ /* --------- The following block is OBSOLETE --------- */
+
+ /*
+ * unpack base version info
+ */
+ _baseversion = (_osversion & 0xFFFF0000) >> 16;
+ _baseminor = _baseversion & 0x00FF;
+ _basemajor = (_baseversion & 0xFF00) >> 8;
+
+ /*
+ * unpack top-level version info (Windows version)
+ */
+ _osversion &= 0x0000FFFF;
+ _osmajor = _osversion & 0x00FF;
+ _osminor = (_osversion & 0xFF00) >> 8;
+
+ /* --------- The preceding block is OBSOLETE --------- */
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ _heap_init(); /* initialize heap */
+#ifdef MTHREAD
+ if(!_mtinit()) /* initialize multi-thread */
+ _amsg_exit(_RT_THREAD); /* write message and die */
+#endif
+#ifdef _WIN32_
+ _ioinit(); /* initialize lowio */
+#else /* ndef _WIN32_ */
+#ifdef _CRUISER_
+ inherit(); /* inherit file info */
+#endif /* _CRUISER_ */
+#endif /* _WIN32_ */
+ _setargv(); /* get cmd line info */
+ _setenvp(); /* get environ info */
+
+ _cinit(); /* do C data initialize */
+
+ /* now call the main program, and then exit with the return value
+ we get back */
+
+ /*
+ * NOTE: THERE MUST BE NO PROTOTYPE FOR THE main() FUNCTION IF THIS
+ * IS BUILT FOR THE 386 WITH _stdcall AS THE DEFAULT CALLING TYPE!
+ * OTHERWISE, THE STACK WILL NOT BE PROPERLY RESTORED AFTER THE CALL
+ * BELOW. WE MIGHT GET AWAY WITH THIS, SINCE WE EXIT RIGHT AWAY, BUT
+ * THERE IS NO POINT IN ASKING FOR TROUBLE.
+ */
+
+#ifdef _CRUISER_
+
+ _try {
+ mainret = main(__argc, __argv, _environ);
+ }
+ _except ( _XcptFilter(_exception_code(), _exception_info()) )
+ {
+ switch( _exception_code() ) {
+
+ case _XCPT_UNABLE_TO_GROW_STACK :
+ _amsg_exit(_RT_STACK);
+
+ case _XCPT_INTEGER_DIVIDE_BY_ZERO :
+ /*
+ * NOTE: THIS IS WHERE cintDIV WENT!
+ *
+ * exit via high-level exit function
+ */
+ _aexit_rtn = exit;
+ _amsg_exit(_RT_INTDIV);
+
+ case _XCPT_INVALID_DISPOSITION :
+ /*
+ * this exception should never occur. if it
+ * does, it would have to be a bug in the
+ * runtime support for signal() or SEH.
+ */
+ _amsg_exit(_RT_INVALDISP);
+
+ case _XCPT_NONCONTINUABLE_EXCEPTION :
+ /*
+ * this exception could possibly occur as the
+ * result of a bad user exception filter or
+ * an error in _XcptFilter().
+ */
+ _amsg_exit(_RT_NONCONT);
+
+ case _XCPT_SIGABRT :
+ /*
+ * no message is printed unless abort() was
+ * called in which case, abort() prints out
+ * the termination message before raising the
+ * signal
+ */
+ _exit(3);
+
+ default :
+ /*
+ * no default action, should never get here
+ */
+ ;
+ } /* end of switch */
+
+ } /* end of _try - _except */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ try {
+#ifdef _WINMAIN_
+ /*
+ * Skip past program name (first token in command line).
+ * Check for and handle quoted program name.
+ */
+ lpszCommandLine = (unsigned char *)_acmdln;
+
+ if ( *lpszCommandLine == '\"' ) {
+ /*
+ * Scan, and skip over, subsequent characters until
+ * another double-quote or a null is encountered.
+ */
+ while ( *++lpszCommandLine && (*lpszCommandLine
+ != '\"') );
+ /*
+ * If we stopped on a double-quote (usual case), skip
+ * over it.
+ */
+ if ( *lpszCommandLine == '\"' )
+ lpszCommandLine++;
+ }
+ else {
+ while (*lpszCommandLine > ' ')
+ lpszCommandLine++;
+ }
+
+ /*
+ * Skip past any white space preceeding the second token.
+ */
+ while (*lpszCommandLine && (*lpszCommandLine <= ' ')) {
+ lpszCommandLine++;
+ }
+
+ StartupInfo.dwFlags = 0;
+ GetStartupInfoA( &StartupInfo );
+
+ mainret = WinMain( GetModuleHandle(NULL),
+ NULL,
+ lpszCommandLine,
+ StartupInfo.dwFlags & STARTF_USESHOWWINDOW
+ ? StartupInfo.wShowWindow
+ : SW_SHOWDEFAULT
+ );
+#else
+ mainret = main(__argc, __argv, _environ);
+#endif
+ exit(mainret);
+ }
+ except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
+ {
+ /*
+ * Should never reach here
+ */
+ _exit( GetExceptionCode() );
+
+ } /* end of try - except */
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER, WIN32, MAC, OR POSIX TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
+
+#endif /* _POSIX_ */
+
+#endif /* ndef _MAC_ */
+
+
+#ifdef _CRUISER_
+
+/***
+*inherit() - obtain and process info on inherited file handles.
+*
+*Purpose:
+*
+* Locates and interprets the C_FILE_INFO environment variable.
+*
+* The value of the variable is written into the "_osfile" array.
+*
+* Format: _C_FILE_INFO=<AA><BB><CC><DD>...
+*
+* This variable is a environment variable where each pair of
+* successive letters from one byte in _osfile. The letters are
+* in the reange "A" through "P" representing the 0 though 15.
+* The first letter of each pair is the more significant 4 bits
+* of the result.
+*
+*Entry:
+* No parameters: reads the environment.
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 inherit (
+ void
+ )
+{
+ char *p; /* pointer to environment strings */
+ unsigned char byte; /* byte we build up */
+ int fh; /* handle we're on */
+
+ p = _aenvptr;
+ while (*p != '\0') {
+ if (strncmp(p, _acfinfo, CFI_LENGTH + 1) == 0) {
+ /* found the _C_FILE_INFO string, now parse it */
+ p += CFI_LENGTH + 1; /* point to value */
+ fh = 0;
+ do
+ {
+ byte = (*p++ - 'A') << 4;
+ byte += *p++ - 'A'; /* read byte */
+ _osfile[fh++] = byte;
+ }
+ while(byte);
+
+ break;
+ }
+ else
+ p += strlen(p) + 1; /* advance to next string */
+ }
+}
+
+#endif /* _CRUISER_ */
+
+
+/***
+*_amsg_exit(rterrnum) - Fast exit fatal errors
+*
+*Purpose:
+* Exit the program with error code of 255 and appropriate error
+* message.
+*
+*Entry:
+* int rterrnum - error message number (amsg_exit only).
+*
+*Exit:
+* Calls exit() (for integer divide-by-0) or _exit() indirectly
+* through _aexit_rtn [amsg_exit].
+* For multi-thread: calls _exit() function
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _amsg_exit (
+ int rterrnum
+ )
+{
+ _FF_MSGBANNER(); /* write run-time error banner */
+ _NMSG_WRITE(rterrnum); /* write message */
+
+ _aexit_rtn(255); /* normally _exit(255) */
+}
+
+#ifdef _POSIX_
+
+/***
+*RaiseException() - stub for posix FP routines
+*
+*Purpose:
+* Stub of a Win32 API that posix can't call
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+VOID
+WINAPI
+RaiseException(
+ DWORD dwExceptionCode,
+ DWORD dwExceptionFlags,
+ DWORD nNumberOfArguments,
+ LPDWORD lpArguments
+ )
+{
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/startup/crt0dat.c b/private/crt32/startup/crt0dat.c
new file mode 100644
index 000000000..42b6854bc
--- /dev/null
+++ b/private/crt32/startup/crt0dat.c
@@ -0,0 +1,794 @@
+/***
+*crt0dat.c - 32-bit C run-time initialization/termination routines
+*
+* Copyright (c) 1986-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains the routines _cinit, exit, and _exit
+* for C run-time startup and termination. _cinit and exit
+* are called from the _astart code in crt0.asm.
+* This module also defines several data variables used by the
+* runtime.
+*
+* [NOTE: Lock segment definitions are at end of module.]
+*
+* *** FLOATING POINT INITIALIZATION AND TERMINATION ARE NOT ***
+* *** YET IMPLEMENTED IN THIS FILE ***
+*
+*Revision History:
+* 06-28-89 PHG Module created, based on asm version
+* 04-09-90 GJF Added #include <cruntime.h>. Made calling type
+* explicit (_CALLTYPE1 or _CALLTYPE4). Also, fixed
+* the copyright.
+* 04-10-90 GJF Fixed compiler warnings (-W3).
+* 05-21-90 GJF Added #undef _NFILE_ (temporary hack) and fixed the
+* indents.
+* 08-31-90 GJF Removed 32 from API names.
+* 09-25-90 GJF Merged tree version with local (8-31 and 5-21 changes).
+* 10-08-90 GJF New-style function declarators.
+* 10-12-90 GJF Removed divide by 0 stuff.
+* 10-18-90 GJF Added _pipech[] array.
+* 11-05-90 GJF Added _umaskval.
+* 12-04-90 GJF Added _osfinfo[] definition for Win32 target. Note that
+* the Win32 support is still incomplete!
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-04-90 SRW Added _osfile back for win32. Changed _osfinfo from
+* an array of structures to an array of 32-bit handles
+* (_osfhnd)
+* 12-28-90 SRW Added _CRUISER_ conditional around pack pragmas
+* 01-29-91 GJF ANSI naming.
+* 01-29-91 SRW Added call to GetFileType [_WIN32_]
+* 02-18-91 SRW Removed duplicate defintion of _NFILE_ (see os2dll.h)
+* 04-04-91 GJF Added definitions for _base[version|major|minor]
+* (_WIN32_).
+* 04-08-91 GJF Temporary hack for Win32/DOS folks - added HeapDestroy
+* call to doexit to tear down the OS heap used by C
+* heap.
+* 04-09-91 PNT Added _MAC_ conditional
+* 04-26-91 SRW Removed level 3 warnings
+* 07-16-91 GJF Added fp initialization test-and-call [_WIN32_].
+* 07-26-91 GJF Revised initialization and termination stuff. In
+* particular, removed need for win32ini.c [_WIN32_].
+* 08-07-91 GJF Added init. for FORTRAN runtime, if present [_WIN32_].
+* 08-21-91 GJF Test _prmtmp against NULL, not _prmtmp().
+* 08-21-91 JCR Added _exitflag, _endstdio, _cpumode, etc.
+* 09-09-91 GJF Revised _doinitterm for C++ init. support and to make
+* _onexit/atexit compatible with C++ needs.
+* 09-16-91 GJF Must test __onexitend before calling _doinitterm.
+* 10-29-91 GJF Force in floating point initialization for MIPS
+* compiler [_WIN32_].
+* 11-13-91 GJF FORTRAN needs _onexit/atexit init. before call thru
+* _pFFinit.
+* 01-10-92 GJF Merged. Also, added _C_Termination_Done [_WIN32_].
+* 02-13-92 GJF Moved all lowio initialization to ioinit.c for Win32.
+* 03-12-92 SKS Major changes to initialization/termination scheme
+* 04-16-92 DJM POSIX support.
+* 04-17-92 SKS Export _initterm() for CRTDLL model
+* 05-07-92 DJM Removed _exit() from POSIX build.
+* 06-03-92 GJF Temporarily restored call to FORTRAN init.
+* 08-26-92 SKS Add _osver, _winver, _winmajor, _winminor
+* 08-28-92 GJF Use unistd.h for POSIX build.
+* 09-02-92 SKS Fix _onexit table traversal to be LIFO.
+* Since table is built forward (my changes 03-12-92)
+* the table must be traversed in reverse order.
+* 10-30-92 TVB Force in floating point initialization for ALPHA
+* compiler as was done for MIPS. [_WIN32_].
+* 11-12-92 SKS Remove hard-coded call to FORTRAN initializer
+* 05-11-93 SKS _C_Termination_Done is now used by DLLs in LIBC/LIBCMT
+* models, not just in CRTDLL.DLL.
+* Remove obsolete variable _child.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#else
+#include <msdos.h>
+#endif
+#include <dos.h>
+#include <oscalls.h>
+#include <os2dll.h>
+#include <internal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <process.h>
+
+/* define errno */
+#ifndef MTHREAD
+int _VARTYPE1 errno = 0; /* libc error value */
+#ifdef _CRUISER_
+int _VARTYPE1 _doserrno = 0; /* OS system error value */
+#else /* ndef _CRUISER_ */
+#ifdef _WIN32_
+unsigned long _VARTYPE1 _doserrno = 0; /* OS system error value */
+#endif /* _WIN32_ */
+#endif /* _CRUISER_ */
+#endif /* MTHREAD */
+
+/* define umask */
+int _umaskval = 0;
+
+/* define version info variables */
+
+unsigned int _VARTYPE1 _osver = 0;
+unsigned int _VARTYPE1 _winver = 0;
+unsigned int _VARTYPE1 _winmajor = 0;
+unsigned int _VARTYPE1 _winminor = 0;
+
+/* --------- The following block is OBSOLETE --------- */
+
+unsigned int _VARTYPE1 _osversion = 0;
+unsigned int _VARTYPE1 _osmajor = 0;
+unsigned int _VARTYPE1 _osminor = 0;
+
+#if defined(_WIN32_) || defined(_POSIX_)
+unsigned int _VARTYPE1 _baseversion = 0;
+unsigned int _VARTYPE1 _basemajor = 0;
+unsigned int _VARTYPE1 _baseminor = 0;
+#endif /* _WIN32_ || _POSIX_ */
+
+/* define _osmode/_cpumode */
+
+#ifdef _CRUISER_
+unsigned char _osmode = _OS2_20_MODE;
+#else /* ndef _CRUISER_ */
+#ifdef _DOSX32_
+unsigned char _osmode = _DOSX32_MODE;
+#else /* ndef _DOSX32_ */
+#ifdef _WIN32_
+unsigned char _osmode = _WIN_MODE;
+#else /* ndef _WIN32_ */
+#ifdef _POSIX_
+unsigned char _osmode = _POSIX_MODE_;
+#endif /* _POSIX_ */
+#endif /* _WIN32DOS_ */
+#endif /* _WIN32_ */
+#endif /* _CRUISER_ */
+
+unsigned char _cpumode = _FLAT_MODE;
+
+/* --------- The preceding block is OBSOLETE --------- */
+
+#ifdef _CRUISER_
+
+/* number of allowable file handles */
+int _nfile = _NFILE_;
+
+/* file handle database -- stdout, stdin, stderr are open */
+char _osfile[_NFILE_] = {FOPEN+FTEXT, FOPEN+FTEXT, FOPEN+FTEXT};
+
+#endif /* _CRUISER_ */
+
+#ifdef _WIN32DOS_
+extern HANDLE _HeapHandle;
+#endif /* _WIN32DOS_ */
+
+#ifdef _CRUISER_
+
+/* peek-ahead buffers for pipes, each initialized to a newline */
+
+char _pipech[_NFILE_] = {
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10
+#ifdef MTHREAD
+ , 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
+#endif
+ };
+#endif /* _CRUISER_ */
+
+/* argument vector and environment */
+int __argc = 0;
+char **__argv = NULL;
+#ifdef _POSIX_
+char **environ = NULL;
+#else
+char **_environ = NULL;
+#endif
+char *_pgmptr; /* ptr to program name */
+
+/* callable exit flag */
+char _exitflag = 0;
+
+#if defined(_WIN32_)
+/*
+ * flag indicating if C runtime termination has been done. set if exit,
+ * _exit, _cexit or _c_exit has been called. checked when _CRTDLL_INIT
+ * or user DLL's _CRT_INIT is called with DLL_PROCESS_DETACH.
+ */
+int _C_Termination_Done = FALSE;
+#endif
+
+/*
+ * useful type for initialization and termination declarations
+ */
+typedef void (_CALLTYPE1 *PF)(void);
+
+#ifdef _CRUISER_
+
+PF *__onexittable = NULL; /* ptr to on exit function table */
+
+#else /* ndef _CRUISER_ */
+
+#if defined(_WIN32_) || defined(_POSIX_)
+
+/*
+ * NOTE: THE USE OF THE POINTERS DECLARED BELOW DEPENDS ON THE PROPERTIES
+ * OF C COMMUNAL VARIABLES. SPECIFICALLY, THEY ARE NON-NULL IFF THERE EXISTS
+ * A DEFINITION ELSEWHERE INITIALIZING THEM TO NON-NULL VALUES.
+ */
+
+/*
+ * pointers to initialization functions
+ */
+
+PF _FPinit; /* floating point init. */
+
+/*
+ * pointers to initialization sections
+ */
+
+extern PF __xi_a[], __xi_z[]; /* C initializers */
+extern PF __xc_a[], __xc_z[]; /* C++ initializers */
+extern PF __xp_a[], __xp_z[]; /* C pre-terminators */
+extern PF __xt_a[], __xt_z[]; /* C terminators */
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+/*
+ * For MIPS or ALPHA compilers, must explicitly force in and call the floating
+ * point initialization (those system always have floating-point hardware).
+ */
+extern void _CALLTYPE1 _fpmath(void);
+#endif
+
+/*
+ * pointers to the start and finish of the _onexit/atexit table
+ */
+PF *__onexitbegin;
+PF *__onexitend;
+
+
+/*
+ * static (internal) function that walks a table of function pointers,
+ * calling each entry between the two pointers, skipping NULL entries
+ *
+ * Needs to be exported for CRT DLL so that C++ initializers in the
+ * client EXE / DLLs can be initialized
+ */
+#ifdef CRTDLL
+void _CALLTYPE1 _initterm(PF *, PF *);
+#else
+static void _CALLTYPE4 _initterm(PF *, PF *);
+#endif
+
+#else /* ndef _WIN32_ || _POSIX_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR POSIX TARGET SUPPORTED!
+
+#endif /* _WIN32_ || _POSIX_ */
+
+#endif /* _CRUISER_ */
+
+
+/***
+*_cinit - C initialization
+*
+*Purpose:
+* This routine performs the shared DOS and Windows initialization.
+* The following order of initialization must be preserved -
+*
+ifdef MTHREAD
+* 0. Call OS2 to bump max file count (mthread only)
+endif
+* 1. Check for devices for file handles 0 - 2
+* 2. Integer divide interrupt vector setup
+* 3. General C initializer routines
+*
+*Entry:
+* No parameters: Called from __crtstart and assumes data
+* set up correctly there.
+*
+*Exit:
+* Initializes C runtime data.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _cinit (
+ void
+ )
+{
+#ifdef _CRUISER_
+ int fh; /* file handle we're checking */
+ ULONG htype; /* handle type */
+
+#ifdef MTHREAD
+ /* 0. Call OS/2 to bump max file count --
+ even though the IO database supports _NFILE_ (256) files,
+ only bump the count to _NFILE_MAXFH_ (40) */
+
+ DOSSETMAXFH(_NFILE_MAXFH_);
+#else
+ #if 0
+ /* This code is intentionally commented out -- to access more
+ than 20 files re-enable this code */
+ DOSSETMAXFH(_NFILE_);
+ #endif
+#endif
+
+ /* 1. check for devices on file handles 0 - 2 */
+ for (fh = 0; fh <= 2; ++fh) {
+ ULONG devattr; /* device attributes */
+
+ /* default: neither pipe nor device */
+ _osfile[fh] &= ~(FDEV | FPIPE);
+
+ if (DOSQUERYHTYPE(fh, &htype, &devattr) == 0) {
+ /* check returned handle type -- only lo byte */
+ if ((htype & 0xFF) == HANDTYPE_DEVICE)
+ _osfile[fh] |= FDEV;
+ else if ((htype & 0xFF) == HANDTYPE_PIPE)
+ _osfile[fh] |= FPIPE;
+ }
+ }
+
+ /* 2. general C initializer routines */
+
+/******* FLOATING POINT INIT SHOULD GO HERE (before initclock) ******/
+
+ __doinits(); /* execute initializers */
+
+#else /* ndef _CRUISER_ */
+
+#if defined(_WIN32_) || defined(_POSIX_)
+ /*
+ * initialize floating point package, if present
+ */
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+ /*
+ * The Mips, Alpha, and PPC compilers don't emit external reference to
+ * _fltused. Therefore, must always force in the floating point
+ * initialization.
+ */
+ _fpmath();
+#else
+ if ( _FPinit != NULL )
+ (*_FPinit)();
+#endif
+
+ /*
+ * do initializations
+ */
+ _initterm( __xi_a, __xi_z );
+
+ /*
+ * do C++ initializations
+ */
+ _initterm( __xc_a, __xc_z );
+
+#else /* ndef _WIN32_ || _POSIX_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, MAC, OR POSIX TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+}
+
+
+/***
+*exit(status), _exit(status), _cexit(void), _c_exit(void) - C termination
+*
+*Purpose:
+*
+* Entry points:
+*
+* exit(code): Performs all the C termination functions
+* and terminates the process with the return code
+* supplied by the user.
+*
+* _exit(code): Performs a quick exit routine that does not
+* do certain 'high-level' exit processing. The _exit
+* routine terminates the process with the return code
+* supplied by the user.
+*
+* _cexit(): Performs the same C lib termination processing
+* as exit(code) but returns control to the caller
+* when done (i.e., does NOT terminate the process).
+*
+* _c_exit(): Performs the same C lib termination processing
+* as _exit(code) but returns control to the caller
+* when done (i.e., does NOT terminate the process).
+*
+* Termination actions:
+*
+* exit(), _cexit():
+*
+* 1. call user's terminator routines
+* 2. call C runtime preterminators
+*
+* _exit(), _c_exit():
+*
+* 3. call C runtime terminators
+* 4. return to DOS or caller
+*
+* Notes:
+*
+* The termination sequence is complicated due to the multiple entry
+* points sharing the common code body while having different entry/exit
+* sequences.
+*
+* Multi-thread notes:
+*
+* 1. exit() should NEVER be called when mthread locks are held.
+* The exit() routine can make calls that try to get mthread locks.
+*
+* 2. _exit()/_c_exit() can be called from anywhere, with or without locks held.
+* Thus, _exit() can NEVER try to get locks (otherwise, deadlock
+* may occur). _exit() should always 'work' (i.e., the process
+* should always terminate successfully).
+*
+* 3. Only one thread is allowed into the exit code (see _lockexit()
+* and _unlockexit() routines).
+*
+*Entry:
+* exit(), _exit()
+* int status - exit status (0-255)
+*
+* _cexit(), _c_exit()
+* <no input>
+*
+*Exit:
+* exit(), _exit()
+* <EXIT to DOS>
+*
+* _cexit(), _c_exit()
+* Return to caller
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+/* worker routine prototype */
+static void _CALLTYPE4 doexit (int code, int quick, int retcaller);
+
+void _CALLTYPE1 exit (
+ int code
+ )
+{
+ doexit(code, 0, 0); /* full term, kill process */
+}
+
+#ifndef _POSIX_
+
+void _CALLTYPE1 _exit (
+ int code
+ )
+{
+ doexit(code, 1, 0); /* quick term, kill process */
+}
+
+void _CALLTYPE1 _cexit (
+ void
+ )
+{
+ doexit(0, 0, 1); /* full term, return to caller */
+}
+
+void _CALLTYPE1 _c_exit (
+ void
+ )
+{
+ doexit(0, 1, 1); /* quick term, return to caller */
+}
+
+#endif /* _POSIX_ */
+
+
+static void _CALLTYPE4 doexit (
+ int code,
+ int quick,
+ int retcaller
+ )
+{
+#ifdef MTHREAD
+ _lockexit(); /* assure only 1 thread in exit path */
+#endif
+
+#if defined(_WIN32_) && defined(CRTDLL)
+ _C_Termination_Done = TRUE;
+#endif
+
+ /* save callable exit flag (for use by terminators) */
+ _exitflag = (char) retcaller; /* 0 = term, !0 = callable exit */
+
+ if (!quick) {
+
+#ifdef _CRUISER_
+ /*
+ * do _onexit/atexit() terminators
+ */
+ if ( __onexitend != NULL )
+ _doinitterm(__onexitend);
+
+ /* call pre-terminators (flushall, rmtmp) */
+ __dopreterms();
+ }
+
+ /* do C terminators */
+ __doterms();
+
+#else /* ndef _CRUISER_ */
+
+#if defined(_WIN32_) || defined(_POSIX_)
+ /*
+ * do _onexit/atexit() terminators
+ * (if there are any)
+ *
+ * These terminators MUST be executed in reverse order (LIFO)!
+ *
+ * NOTE:
+ * This code assumes that __onexitbegin points
+ * to the first valid onexit() entry and that
+ * __onexitend points past the last valid entry.
+ * If __onexitbegin == __onexitend, the table
+ * is empty and there are no routines to call.
+ */
+
+ if (__onexitbegin) {
+ PF * pfend = __onexitend;
+
+ while ( -- pfend >= __onexitbegin )
+ /*
+ * if current table entry is non-NULL,
+ * call thru it.
+ */
+ if ( *pfend != NULL )
+ (**pfend)();
+ }
+
+ /*
+ * do pre-terminators
+ */
+ _initterm(__xp_a, __xp_z);
+ }
+
+ /*
+ * do terminators
+ */
+ _initterm(__xt_a, __xt_z);
+
+#else /* ndef _WIN32_ || _POSIX_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR POSIX TARGET SUPPORTED!
+
+#endif /* _WIN32_ || _POSIX_ */
+
+#endif /* _CRUISER_ */
+
+
+#ifdef _WIN32DOS_
+
+/*
+ * TEMPORARY HACK! THE CODE BELOW IS INTENDED TO ALLOW LIMITED USE OF THE
+ * C RUNTIME ON WIN32/DOS. IT WILL BE DELETED AS SOON AS THEY IMPLEMENT
+ * VirtualAlloc()!
+ */
+
+ HeapDestroy(_HeapHandle);
+
+#endif /* _WIN32DOS_ */
+
+
+/********** FLOATING POINT TERMINATION SHOULD GO HERE ************/
+
+ /* return to OS/2 or to caller */
+ if (retcaller) {
+#ifdef MTHREAD
+ _unlockexit(); /* unlock the exit code path */
+#endif
+ return;
+ }
+
+#ifdef _CRUISER_
+
+ DOSEXIT(EXIT_PROCESS, code);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ ExitProcess(code);
+
+#else /* ndef _WIN32_ */
+
+#ifdef _POSIX_
+
+ _exit(code);
+
+#else /* ndef _POSIX_ */
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, MAC, OR POSIX TARGET SUPPORTED!
+
+#endif /* _POSIX_ */
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+}
+
+#ifdef MTHREAD
+/***
+* _lockexit - Aquire the exit code lock
+*
+*Purpose:
+* Makes sure only one thread is in the exit code at a time.
+* If a thread is already in the exit code, it must be allowed
+* to continue. All other threads must pend.
+*
+* Notes:
+*
+* (1) It is legal for a thread that already has the lock to
+* try and get it again(!). That is, consider the following
+* sequence:
+*
+* (a) program calls exit()
+* (b) thread locks exit code
+* (c) user onexit() routine calls _exit()
+* (d) same thread tries to lock exit code
+*
+* Since _exit() must ALWAYS be able to work (i.e., can be called
+* from anywhere with no regard for locking), we must make sure the
+* program does not deadlock at step (d) above.
+*
+* (2) If a thread executing exit() or _exit() aquires the exit lock,
+* other threads trying to get the lock will pend forever. That is,
+* since exit() and _exit() terminate the process, there is not need
+* for them to unlock the exit code path.
+*
+* (3) Note that onexit()/atexit() routines call _lockexit/_unlockexit
+* to protect mthread access to the onexit table.
+*
+* (4) The _lockexit/_unlockexit routines are very complicated in 286
+* OS/2 since a thread that held a lock could not request the lock again.
+* The 32-bit OS/2 semaphore calls DO allow a single thread to aquire the
+* same lock multiple times* thus, this version is straight forward.
+*
+*Entry: <none>
+*
+*Exit:
+* Calling thread has exit code path locked on return.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _lockexit (
+ void
+ )
+{
+ _mlock(_EXIT_LOCK1);
+}
+
+/***
+* _unlockexit - Release exit code lock
+*
+*Purpose:
+* [See _lockexit() description above.]
+*
+* This routine is called by _cexit(), _c_exit(), and onexit()/atexit().
+* The exit() and _exit() routines never unlock the exit code path since
+* they are terminating the process.
+*
+*Entry:
+* Exit code path is unlocked.
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _unlockexit (
+ void
+ )
+{
+ _munlock(_EXIT_LOCK1);
+}
+
+#endif /* MTHREAD */
+
+
+#if defined(_WIN32_) || defined(_POSIX_)
+
+/***
+* static void _initterm(PF * pfbegin, PF * pfend) - call entries in
+* function pointer table
+*
+*Purpose:
+* Walk a table of function pointers, calling each entry, as follows:
+*
+* 1. walk from beginning to end, pfunctbl is assumed to point
+* to the beginning of the table, which is currently a null entry,
+* as is the end entry.
+* 2. skip NULL entries
+* 3. stop walking when the end of the table is encountered
+*
+*Entry:
+* PF *pfbegin - pointer to the beginning of the table (first valid entry).
+* PF *pfend - pointer to the end of the table (after last valid entry).
+*
+*Exit:
+* No return value
+*
+*Notes:
+* This routine must be exported in the CRT DLL model so that the client
+* EXE and client DLL(s) can call it to initialize their C++ constructors.
+*
+*Exceptions:
+* If either pfbegin or pfend is NULL, or invalid, all bets are off!
+*
+*******************************************************************************/
+
+#ifdef CRTDLL
+void _CALLTYPE1 _initterm (
+#else
+static void _CALLTYPE4 _initterm (
+#endif
+ PF * pfbegin,
+ PF * pfend
+ )
+{
+ /*
+ * walk the table of function pointers from the bottom up, until
+ * the end is encountered. Do not skip the first entry. The initial
+ * value of pfbegin points to the first valid entry. Do not try to
+ * execute what pfend points to. Only entries before pfend are valid.
+ */
+ while ( pfbegin < pfend )
+ {
+ /*
+ * if current table entry is non-NULL, call thru it.
+ */
+ if ( *pfbegin != NULL )
+ (**pfbegin)();
+ ++pfbegin;
+ }
+}
+
+#endif /* _WIN32_ || _POSIX_ */
diff --git a/private/crt32/startup/crt0fp.c b/private/crt32/startup/crt0fp.c
new file mode 100644
index 000000000..ba8a2eb0c
--- /dev/null
+++ b/private/crt32/startup/crt0fp.c
@@ -0,0 +1,57 @@
+/***
+*crt0fp.asm - floating point not loaded trap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* To trap certain cases where certain necessary floating-point
+* software is not loaded. Two specific cases are when no emulator
+* is linked in but no coprocessor is present, and when floating
+* point i/o conversions are done, but no floating-point variables
+* or expressions are used in the program.
+*
+*Revision History:
+* 06-29-89 PHG module created, based on asm version
+* 04-09-90 GJF Added #include <cruntime.h>. Made calling type
+* _CALLTYPE1. Also, fixed the copyright.
+* 04-10-90 GJF Fixed compiler warnings (-W3).
+* 10-08-90 GJF New-style function declarator.
+* 10-11-90 GJF Changed _amsg_exit() interface.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <rterr.h>
+
+
+/***
+*_fptrap - trap for missing floating-point software
+*
+*Purpose:
+* Catches these cases of incomplete f.p. software linked into a program.
+*
+* (1) no coprocessor present, and no emulator linked in
+*
+* (2) "%e", "%f", and "%g" i/o conversion formats specified, but
+* not all conversion software has been linked in, because the
+* program did not use any floating-point variables or expressions.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Never returns.
+*
+*Exceptions:
+* Transfers control to _amsg_exit which ...
+* - Writes error message to standard error: "floating point not loaded"
+* - Terminates the program by calling _exit().
+*******************************************************************************/
+
+void _CALLTYPE1 _fptrap(
+ void
+ )
+{
+ _amsg_exit(_RT_FLOAT);
+}
diff --git a/private/crt32/startup/crt0init.c b/private/crt32/startup/crt0init.c
new file mode 100644
index 000000000..cabf03a5d
--- /dev/null
+++ b/private/crt32/startup/crt0init.c
@@ -0,0 +1,69 @@
+/***
+*crt0init.c - Initialization segment declarations.
+*
+* Copyright (c) 1992-1994, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Do initialization segment declarations.
+*
+*Notes:
+* In the 16-bit C world, the X*B and X*E segments were empty except for
+* a label. This will not work with COFF since COFF throws out empty
+* sections. Therefore we must put a zero value in them. (Zero because
+* the routine to traverse the initializers will skip over zero entries.)
+*
+*Revision History:
+* 03-19-92 SKS Module created.
+* 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+* 08-06-92 SKS Revised to use new section names and macros
+* 10-19-93 SKS Add .DiRECTiVE section for MIPS, too!
+* 10-28-93 GJF Rewritten in C
+* 10-28-94 SKS Add user32.lib as a default library
+* 02-27-95 CFW Remove user32.lib as a default library
+*
+*******************************************************************************/
+
+#ifdef _MSC_VER
+
+
+#include <stdio.h>
+#include <internal.h>
+
+#pragma data_seg(".CRT$XIA")
+_PVFV __xi_a[] = { NULL };
+
+
+#pragma data_seg(".CRT$XIZ")
+_PVFV __xi_z[] = { NULL };
+
+
+#pragma data_seg(".CRT$XCA")
+_PVFV __xc_a[] = { NULL };
+
+
+#pragma data_seg(".CRT$XCZ")
+_PVFV __xc_z[] = { NULL };
+
+
+#pragma data_seg(".CRT$XPA")
+_PVFV __xp_a[] = { NULL };
+
+
+#pragma data_seg(".CRT$XPZ")
+_PVFV __xp_z[] = { NULL };
+
+
+#pragma data_seg(".CRT$XTA")
+_PVFV __xt_a[] = { NULL };
+
+
+#pragma data_seg(".CRT$XTZ")
+_PVFV __xt_z[] = { NULL };
+
+
+#pragma data_seg(".drectve")
+static char __drectve_win32lib[] =
+ "-merge:.CRT=.rdata -ignore:4078";
+#pragma data_seg() /* reset */
+
+#endif /* _MSC_VER */
diff --git a/private/crt32/startup/crt0msg.c b/private/crt32/startup/crt0msg.c
new file mode 100644
index 000000000..5be8938e9
--- /dev/null
+++ b/private/crt32/startup/crt0msg.c
@@ -0,0 +1,231 @@
+/***
+*crt0msg.c - startup error messages
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Prints out banner for runtime error messages.
+*
+*Revision History:
+* 06-27-89 PHG Module created, based on asm version
+* 04-09-90 GJF Added #include <cruntime.h>. Made calling type
+* _CALLTYPE1. Also, fixed the copyright.
+* 04-10-90 GJF Fixed compiler warnings (-W3).
+* 06-04-90 GJF Revised to be more compatible with old scheme.
+* nmsghdr.c merged in.
+* 10-08-90 GJF New-style function declarators.
+* 10-11-90 GJF Added _RT_ABORT, _RT_FLOAT, _RT_HEAP.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 02-04-91 SRW Changed to call WriteFile (_WIN32_)
+* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_)
+* 04-10-91 PNT Added _MAC_ conditional
+* 09-09-91 GJF Added _RT_ONEXIT error.
+* 09-18-91 GJF Added 3 math errors, also corrected comments for
+* errors that were changed in rterr.h, cmsgs.h.
+* 03-31-92 DJM POSIX support.
+* 10-23-92 GJF Added _RT_PUREVIRT.
+* 04-29-93 GJF Removed rterrs[] entries for _RT_STACK, _RT_INTDIV,
+* _RT_NONCONT and _RT_INVALDISP.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stddef.h>
+#include <string.h>
+#include <rterr.h>
+#include <cmsgs.h>
+#include <oscalls.h>
+
+#ifdef _POSIX_
+#include <posix\sys\types.h>
+#include <posix\unistd.h>
+#endif
+
+/* struct used to lookup and access runtime error messages */
+
+struct rterrmsgs {
+ int rterrno; /* error number */
+ char *rterrtxt; /* text of error message */
+};
+
+/* runtime error messages */
+
+static struct rterrmsgs rterrs[] = {
+
+ /* 0 */
+ /* { _RT_STACK, _RT_STACK_TXT }, */
+
+ /* 2 */
+ { _RT_FLOAT, _RT_FLOAT_TXT },
+
+ /* 3 */
+ /* { _RT_INTDIV, _RT_INTDIV_TXT }, */
+
+ /* 8 */
+ { _RT_SPACEARG, _RT_SPACEARG_TXT },
+
+ /* 9 */
+ { _RT_SPACEENV, _RT_SPACEENV_TXT },
+
+ /* 10 */
+ { _RT_ABORT, _RT_ABORT_TXT },
+
+ /* 16 */
+ { _RT_THREAD, _RT_THREAD_TXT },
+
+ /* 17 */
+ { _RT_LOCK, _RT_LOCK_TXT },
+
+ /* 18 */
+ { _RT_HEAP, _RT_HEAP_TXT },
+
+ /* 19 */
+ { _RT_OPENCON, _RT_OPENCON_TXT },
+
+ /* 22 */
+ /* { _RT_NONCONT, _RT_NONCONT_TXT }, */
+
+ /* 23 */
+ /* { _RT_INVALDISP, _RT_INVALDISP_TXT }, */
+
+#ifdef _WIN32_
+
+ /* 24 */
+ { _RT_ONEXIT, _RT_ONEXIT_TXT },
+
+#endif
+
+ /* 25 */
+ { _RT_PUREVIRT, _RT_PUREVIRT_TXT },
+
+ /* 120 */
+ { _RT_DOMAIN, _RT_DOMAIN_TXT },
+
+ /* 121 */
+ { _RT_SING, _RT_SING_TXT },
+
+ /* 122 */
+ { _RT_TLOSS, _RT_TLOSS_TXT },
+
+ /* 252 */
+ { _RT_CRNL, _RT_CRNL_TXT },
+
+ /* 255 */
+ { _RT_BANNER, _RT_BANNER_TXT }
+
+};
+
+/* number of elements in rterrs[] */
+
+#define _RTERRCNT ( sizeof(rterrs) / sizeof(struct rterrmsgs) )
+
+/* For C, _FF_DBGMSG is inactive, so _adbgmsg is
+ set to null
+ For FORTRAN, _adbgmsg is set to point to
+ _FF_DBGMSG in dbginit initializer in dbgmsg.asm */
+
+void (*_adbgmsg)(void) = NULL;
+
+/***
+*_FF_MSGBANNER - writes out first part of run-time error messages
+*
+*Purpose:
+* This routine writes "\r\nrun-time error " to standard error.
+*
+* For FORTRAN $DEBUG error messages, it also uses the _FF_DBGMSG
+* routine whose address is stored in the _adbgmsg variable to print out
+* file and line number information associated with the run-time error.
+* If the value of _adbgmsg is found to be null, then the _FF_DBGMSG
+* routine won't be called from here (the case for C-only programs).
+*
+*Entry:
+* No arguments.
+*
+*Exit:
+* Nothing returned.
+*
+*Exceptions:
+* None handled.
+*
+*******************************************************************************/
+
+void _CRTAPI1 _FF_MSGBANNER (
+ void
+ )
+{
+ _NMSG_WRITE(_RT_CRNL); /* new line to begin error message */
+ if (_adbgmsg != 0)
+ _adbgmsg(); /* call __FF_DBGMSG for FORTRAN */
+ _NMSG_WRITE(_RT_BANNER); /* run-time error message banner */
+}
+
+
+/***
+*__NMSGWRITE(message) - write a given message to handle 2 (stderr)
+*
+*Purpose:
+* This routine writes the message associated with rterrnum
+* to stderr.
+*
+*Entry:
+* int rterrnum - runtime error number
+*
+*Exit:
+* no return value
+*
+*Exceptions:
+* none
+*
+*******************************************************************************/
+
+void _CRTAPI1 _NMSG_WRITE (
+ int rterrnum
+ )
+{
+ int tblindx;
+#ifndef _POSIX_
+ DWORD bytes_written; /* bytes written */
+#endif
+
+ for ( tblindx = 0 ; tblindx < _RTERRCNT ; tblindx++ )
+ if ( rterrnum == rterrs[tblindx].rterrno )
+ break;
+
+ if ( rterrnum == rterrs[tblindx].rterrno )
+#ifdef _CRUISER_
+
+ DOSWRITE(2, rterrs[tblindx].rterrtxt,
+ strlen(rterrs[tblindx].rterrtxt), &bytes_written);
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ WriteFile((HANDLE)_osfhnd[2], rterrs[tblindx].rterrtxt,
+ strlen(rterrs[tblindx].rterrtxt), &bytes_written, NULL);
+
+#else /* ndef _WIN32_ */
+
+#ifdef _POSIX_
+ write(STDERR_FILENO,rterrs[tblindx].rterrtxt,
+ strlen(rterrs[tblindx].rterrtxt));
+#else
+
+#ifdef _MAC_
+
+ TBD();
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, POSIX, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _POSIX_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+}
diff --git a/private/crt32/startup/dllcrt0.c b/private/crt32/startup/dllcrt0.c
new file mode 100644
index 000000000..9f3b7003a
--- /dev/null
+++ b/private/crt32/startup/dllcrt0.c
@@ -0,0 +1,306 @@
+#ifndef _POSIX_ /* not built for POSIX */
+#ifndef CRTDLL /* not built for CRTDLL */
+
+/***
+*dllcrt0.c - C runtime initialization routine for a DLL with linked-in C R-T
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This the startup routine for a DLL which is linked with its own
+* C run-time code. It is similar to the routine _mainCRTStartup()
+* in the file CRT0.C, except that there is no main() in a DLL.
+*
+*Revision History:
+* 05-04-92 SKS Based on CRT0.C (start-up code for EXE's)
+* 08-26-92 SKS Add _osver, _winver, _winmajor, _winminor
+* 09-16-92 SKS This module used to be enabled only in LIBCMT.LIB,
+* but it is now enabled for LIBC.LIB as well!
+* 09-29-92 SKS _CRT_INIT needs to be WINAPI, not cdecl
+* 10-16-92 SKS Call _heap_init before _mtinit (fix copied from CRT0.C)
+* 10-24-92 SKS Call to _mtdeletelocks() must be under #ifdef MTHREAD!
+* 04-16-93 SKS Call _mtterm instead of _mtdeletelocks on
+* PROCESS_DETACH to do all multi-thread cleanup
+* It will call _mtdeletelocks and free up the TLS index.
+* 04-27-93 GJF Removed support for _RT_STACK, _RT_INTDIV,
+* _RT_INVALDISP and _RT_NONCONT.
+* 05-11-93 SKS Add _DllMainCRTStartup to co-exist with _CRT_INIT
+* _mtinit now returns 0 or 1, no longer calls _amsg_exit
+* Delete obsolete variable _atopsp
+* 06-03-93 GJF Added __proc_attached flag.
+* 06-08-93 SKS Clean up failure handling in _CRT_INIT
+* 12-13-93 SKS Free up per-thread CRT data on DLL_THREAD_DETACH
+* using a call to _freeptd() in _CRT_INIT()
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <dos.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rterr.h>
+#include <oscalls.h>
+#define _DECL_DLLMAIN /* enable prototypes for DllMain and _CRT_INIT */
+#include <process.h>
+
+
+/*
+ * flag set iff _CRTDLL_INIT was called with DLL_PROCESS_ATTACH
+ */
+static int __proc_attached = 0;
+
+
+/*
+ * command line, environment, and a few other globals
+ */
+char *_acmdln; /* points to command line */
+char *_aenvptr; /* points to environment block */
+
+void (_CALLTYPE1 * _aexit_rtn)(int) = _exit; /* RT message return procedure */
+
+
+/*
+ * User routine DllMain is called on all notifications
+ */
+
+extern BOOL WINAPI DllMain(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ ) ;
+
+
+/***
+*BOOL WINAPI _CRT_INIT(hDllHandle, dwReason, lpreserved) - C Run-Time
+* initialization for a DLL linked with a C run-time library.
+*
+*Purpose:
+* This routine does the C run-time initialization.
+* For the multi-threaded run-time library, it also cleans up the
+* multi-threading locks on DLL termination.
+*
+*Entry:
+*
+*Exit:
+*
+*NOTES:
+* This routine should either be the entry-point for the DLL
+* or else be called by the entry-point routine for the DLL.
+*
+*******************************************************************************/
+
+BOOL WINAPI
+_CRT_INIT(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ )
+{
+ switch (dwReason) {
+ case DLL_PROCESS_DETACH:
+ /*
+ * make sure there has been prior process attach
+ * notification!
+ */
+ if ( __proc_attached > 0 ) {
+ __proc_attached--;
+
+ if ( _C_Termination_Done == FALSE ) {
+ /* do exit() time clean-up */
+ _cexit();
+ }
+
+#ifdef MTHREAD
+ /* delete MT locks, free TLS index, etc. */
+ _mtterm();
+#endif
+ if (_aenvptr) {
+ FreeEnvironmentStrings(_aenvptr);
+ _aenvptr=NULL;
+ }
+
+ return TRUE;
+
+ } else {
+ /* no prior process attach, just return */
+ return FALSE;
+ }
+
+#ifdef MTHREAD
+ case DLL_THREAD_DETACH:
+ _freeptd(NULL); /* free up per-thread CRT data */
+
+ case DLL_THREAD_ATTACH:
+ return TRUE;
+#endif
+
+ case DLL_PROCESS_ATTACH:
+
+ /*
+ * increment flag to indicate process attach notification has been
+ * received
+ */
+ __proc_attached++;
+
+ _acmdln = (char *)GetCommandLine();
+ _aenvptr = (char *)GetEnvironmentStrings();
+
+ /*
+ * Get the full Win32 version
+ */
+ _osversion = /* OBSOLETE */
+ _osver = GetVersion();
+
+ _winminor = (_osver >> 8) & 0x00FF ;
+ _winmajor = _osver & 0x00FF ;
+ _winver = (_winmajor << 8) + _winminor;
+ _osver = (_osver >> 16) & 0x00FFFF ;
+
+ /* --------- The following block is OBSOLETE --------- */
+
+ /*
+ * unpack base version info
+ */
+ _baseversion = (_osversion & 0xFFFF0000) >> 16;
+ _baseminor = _baseversion & 0x00FF;
+ _basemajor = (_baseversion & 0xFF00) >> 8;
+
+ /*
+ * unpack top-level version info (Windows version)
+ */
+ _osversion &= 0x0000FFFF;
+ _osmajor = _osversion & 0x00FF;
+ _osminor = (_osversion & 0xFF00) >> 8;
+
+ /* --------- The preceding block is OBSOLETE --------- */
+
+ _heap_init(); /* initialize heap */
+
+#ifdef MTHREAD
+ if(!_mtinit()) { /* initialize multi-thread */
+ FreeEnvironmentStrings(_aenvptr);
+ return FALSE; /* fail to load DLL */
+ }
+#endif
+ _ioinit(); /* initialize lowio */
+ _setargv(); /* get cmd line info */
+ _setenvp(); /* get environ info */
+
+ _cinit(); /* do C data initialize */
+
+ return TRUE; /* initialization succeeded */
+ }
+}
+
+
+/***
+*BOOL WINAPI _DllMainCRTStartup(hDllHandle, dwReason, lpreserved) -
+* C Run-Time initialization for a DLL linked with a C run-time library.
+*
+*Purpose:
+* This routine does the C run-time initialization or termination
+* and then calls the user code notification handler "DllMain".
+* For the multi-threaded run-time library, it also cleans up the
+* multi-threading locks on DLL termination.
+*
+*Entry:
+*
+*Exit:
+*
+*NOTES:
+* This routine should be the entry point for the DLL if
+* the user is not supplying one and calling _CRT_INIT.
+*
+*******************************************************************************/
+BOOL WINAPI _DllMainCRTStartup(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ )
+{
+ BOOL retcode = TRUE;
+
+ /*
+ * If this is a process attach notification, increment the process
+ * attached flag. If this is a process detach notification, check
+ * that there has been a prior process attach notification.
+ */
+ if ( dwReason == DLL_PROCESS_ATTACH )
+ __proc_attached++;
+ else if ( dwReason == DLL_PROCESS_DETACH ) {
+ if ( __proc_attached > 0 )
+ __proc_attached--;
+ else
+ /*
+ * no prior process attach notification. just return
+ * without doing anything.
+ */
+ return FALSE;
+ }
+
+ if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH )
+ retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved);
+
+ if ( retcode )
+ retcode = DllMain(hDllHandle, dwReason, lpreserved);
+
+ /*
+ * If _CRT_INIT successfully handles a Process Attach notification
+ * but the user's DllMain routine returns failure, we need to do
+ * clean-up of the C run-time similar to what _CRT_INIT does on a
+ * Process Detach Notification.
+ */
+
+ if ( retcode == FALSE && dwReason == DLL_PROCESS_ATTACH )
+ {
+ /* Failure to attach DLL - must clean up C run-time */
+#ifdef MTHREAD
+ _mtterm();
+#endif
+ if (_aenvptr) {
+ FreeEnvironmentStrings(_aenvptr);
+ _aenvptr=NULL;
+ }
+ }
+
+ if ( dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH )
+ {
+ if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE )
+ retcode = FALSE ;
+ }
+
+ return retcode ;
+}
+
+
+/***
+*_amsg_exit(rterrnum) - Fast exit fatal errors
+*
+*Purpose:
+* Exit the program with error code of 255 and appropriate error
+* message.
+*
+*Entry:
+* int rterrnum - error message number (amsg_exit only).
+*
+*Exit:
+* Calls exit() (for integer divide-by-0) or _exit() indirectly
+* through _aexit_rtn [amsg_exit].
+* For multi-thread: calls _exit() function
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _amsg_exit (
+ int rterrnum
+ )
+{
+ _FF_MSGBANNER(); /* write run-time error banner */
+ _NMSG_WRITE(rterrnum); /* write message */
+
+ _aexit_rtn(255); /* normally _exit(255) */
+}
+#endif /* CRTDLL */
+#endif /* _POSIX_ */
diff --git a/private/crt32/startup/dllmain.c b/private/crt32/startup/dllmain.c
new file mode 100644
index 000000000..8fd0ea706
--- /dev/null
+++ b/private/crt32/startup/dllmain.c
@@ -0,0 +1,42 @@
+/***
+*dllmain.c - Dummy DllMain for user DLLs that have no notification handler
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This object goes into LIBC.LIB and LIBCMT.LIB and MSVCRT.LIB for use
+* when linking a DLL with one of the three models of C run-time library.
+* If the user does not provide a DllMain notification routine, this
+* dummy handler will be linked in. It always returns TRUE (success).
+*
+*Revision History:
+* 04-14-93 SKS Initial version
+*
+******************************************************************************/
+
+#include <oscalls.h>
+
+/***
+*DllMain - dummy version DLLs linked with all 3 C Run-Time Library models
+*
+*Purpose:
+* The routine DllMain is always called by _DllMainCrtStartup. If
+* the user does not provide a routine named DllMain, this one will
+* get linked in so that _DllMainCRTStartup has something to call.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+******************************************************************************/
+
+BOOL WINAPI DllMain(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ )
+{
+ return TRUE ;
+}
diff --git a/private/crt32/startup/i386/atlssup.asm b/private/crt32/startup/i386/atlssup.asm
new file mode 100644
index 000000000..590930817
--- /dev/null
+++ b/private/crt32/startup/i386/atlssup.asm
@@ -0,0 +1,15 @@
+; SCCSID = \%Z\%\%M\%:\%I\%
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+.xlist
+include cruntime.inc
+.list
+
+; This symbol is being defined in the C language model
+; and will have an extra underscore character prepended.
+
+ public _tls_array
+_tls_array equ 2Ch ; TEB.ThreadLocalStoragePointer
+
+end
diff --git a/private/crt32/startup/i386/chkstk.asm b/private/crt32/startup/i386/chkstk.asm
new file mode 100644
index 000000000..bd05942d5
--- /dev/null
+++ b/private/crt32/startup/i386/chkstk.asm
@@ -0,0 +1,127 @@
+ page ,132
+ title chkstk - C stack checking routine
+;***
+;chkstk.asm - C stack checking routine
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Provides support for automatic stack checking in C procedures
+; when stack checking is enabled.
+;
+;Revision History:
+; 04-21-87 SKS Added conditional assembly switch for STKHQQ = 0
+; 07-23-87 MAG [1] Added run-time CS:IP error processing for QC
+; 08-17-87 JLS [2] Remove all references to DGROUP
+; 08-25-87 JLS [3] Shift include files
+; 11-13-87 SKS OS/2 Reentrant version, add thread ID check
+; 11-18-87 SKS Make STKHQQ an array (oops!)
+; 12-14-87 SKS add .286p to allow PUSH immediate value
+; 02-19-88 SKS Change minimum bottom limit to STACKSLOP, not 0
+; 06-01-88 PHG Merge DLL and normal versions
+; 09-21-88 WAJ initial 386 version
+; 10-18-88 JCR Chkstk was trashing bx... not good on 386
+; 06-06-89 JCR 386 mthread support
+; 06-20-89 JCR 386: Removed _LOAD_DGROUP code
+; 04-06-90 GJF Fixed the copyright.
+; 06-21-90 GJF Rewritten to probe pages
+; 10-15-90 GJF Restored _end and STKHQQ.
+; 03-19-91 GJF Revised to preserve all registers except eax. Note
+; this is _rchkstk functionality so there is no longer
+; a separate _rchkstk routine.
+; 08-01-91 GJF Got rid of _end and STKHQQ, except for Cruiser
+; (probably not needed for Cruiser either) [_WIN32_].
+; 09-27-91 JCR Merged Stevewo' changes from NT tree
+;
+;*******************************************************************************
+
+.xlist
+ include cruntime.inc
+ include msdos.inc
+.list
+
+; size of a page of memory
+
+_PAGESIZE_ equ 1000h
+
+
+ifdef _CRUISER_
+
+ .data
+
+extrn pascal _end:dword ; stack bottom
+
+ifndef MTHREAD
+
+public pascal STKHQQ ; used by parasitic heap
+STKHQQ dd dataoffset _end+STACKSLOP ; initial value
+
+endif ;MTHREAD
+
+endif ;_CRUISER_
+
+ CODESEG
+
+page
+;***
+;_chkstk - check stack upon procedure entry
+;
+;Purpose:
+; Provide stack checking on procedure entry. Method is to simply probe
+; each page of memory required for the stack in descending order. This
+; causes the necessary pages of memory to be allocated via the guard
+; page scheme, if possible. In the event of failure, the OS raises the
+; _XCPT_UNABLE_TO_GROW_STACK exception.
+;
+; NOTE: Currently, the (EAX < _PAGESIZE_) code path falls through
+; to the "lastpage" label of the (EAX >= _PAGESIZE_) code path. This
+; is small; a minor speed optimization would be to special case
+; this up top. This would avoid the painful save/restore of
+; ecx and would shorten the code path by 4-6 instructions.
+;
+;Entry:
+; EAX = size of local frame
+;
+;Exit:
+; ESP = new stackframe, if successful
+;
+;Uses:
+; EAX
+;
+;Exceptions:
+; _XCPT_GUARD_PAGE_VIOLATION - May be raised on a page probe. NEVER TRAP
+; THIS!!!! It is used by the OS to grow the
+; stack on demand.
+; _XCPT_UNABLE_TO_GROW_STACK - The stack cannot be grown. More precisely,
+; the attempt by the OS memory manager to
+; allocate another guard page in response
+; to a _XCPT_GUARD_PAGE_VIOLATION has
+; failed.
+;
+;*******************************************************************************
+
+labelP _alloca_probe, PUBLIC
+labelP _chkstk, PUBLIC
+
+ push ecx ; save ecx
+ mov ecx,esp ; compute new stack pointer in ecx
+ add ecx,8 ; correct for return address and saved
+ ; ecx value
+probepages:
+ cmp eax,_PAGESIZE_ ; more than one page requested?
+ jb short lastpage ; no
+ sub ecx,_PAGESIZE_ ; yes, move down a page and...
+ or dword ptr [ecx],0 ; ...probe it
+ sub eax,_PAGESIZE_ ; adjust request
+ jmp probepages
+
+lastpage:
+ sub ecx,eax ; move stack down by eax and do a...
+ or dword ptr [ecx],0 ; ...probe in case a page was crossed
+ mov eax,esp ; save pointer to current tos
+ mov esp,ecx ; set the new stack pointer
+ mov ecx,dword ptr [eax] ; recover ecx
+ mov eax,dword ptr [eax + 4] ; recover return address
+ jmp eax ; return
+
+ end
diff --git a/private/crt32/startup/makefile b/private/crt32/startup/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/startup/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/startup/makefile.inc b/private/crt32/startup/makefile.inc
new file mode 100644
index 000000000..3db9c8c1c
--- /dev/null
+++ b/private/crt32/startup/makefile.inc
@@ -0,0 +1,3 @@
+_setargv.c: stdargv.c
+
+wincrt0.c: crt0.c
diff --git a/private/crt32/startup/mips/chkstk.s b/private/crt32/startup/mips/chkstk.s
new file mode 100644
index 000000000..3ba199fea
--- /dev/null
+++ b/private/crt32/startup/mips/chkstk.s
@@ -0,0 +1,104 @@
+// TITLE("Runtime Stack Checking")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// chkstk.s
+//
+// Abstract:
+//
+// This module implements runtime stack checking.
+//
+// Author:
+//
+// David N. Cutler (davec) 14-Mar-1991
+//
+// Environment:
+//
+// User mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksmips.h"
+
+ SBTTL("Check Stack")
+//++
+//
+// ULONG
+// _RtlCheckStack (
+// IN ULONG Allocation
+// )
+//
+// Routine Description:
+//
+// This function provides runtime stack checking for local allocations
+// that are more than a page and for storage dynamically allocated with
+// the alloca function. Stack checking consists of probing downward in
+// the stack a page at a time. If the current stack commitment is exceeded,
+// then the system will automatically attempt to expand the stack. If the
+// attempt succeeds, then another page is committed. Otherwise, a stack
+// overflow exception is raised. It is the responsiblity of the caller to
+// handle this exception.
+//
+// N.B. This routine is called using a calling sequence that assumes that
+// all registers are preserved.
+//
+// Arguments:
+//
+// Allocation (t8) - Supplies the size of the allocation on the stack.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY(_RtlCheckStack, 0, ra)
+
+ sw t7,0(sp) // save temporary register
+ sw t8,4(sp) // save allocation size
+ sw t9,8(sp) // save temporary register
+
+ PROLOGUE_END
+
+ .set noreorder
+ .set noat
+ li t9,UsPcr // get address of user PCR
+ bgez sp,10f // if gez, running on user stack
+ subu t8,sp,t8 // compute new bottom of stack
+
+//
+// Running on kernel stack - compute stack limit from initial kernel stack.
+//
+
+ lw t9,KiPcr + PcInitialStack(zero) // get initial kernel stack
+ b 20f // finish in common code
+ subu t9,t9,KERNEL_STACK_SIZE // compute low limit of kernel stack
+
+//
+// Running on user stack - get stack limit from thread environment block.
+//
+
+10: lw t9,PcTeb(t9) // get address of environment block
+ nop // fill
+ lw t9,TeStackLimit(t9) // get low stack address
+ nop // fill
+20: sltu t7,t8,t9 // new stack address within limits?
+ beq zero,t7,40f // if eq, stack within limits
+ li t7,~(PAGE_SIZE - 1) // set address mask
+ and t8,t8,t7 // round down new stack address
+30: subu t9,t9,PAGE_SIZE // compute next address to check
+ bne t8,t9,30b // if ne, more pages to probe
+ sw zero,0(t9) // check stack address
+40: lw t7,0(sp) // restore temporary register
+ lw t8,4(sp) // restore allocation size
+ j ra // return
+ lw t9,8(sp) // restore temporary register
+ .set at
+ .set reorder
+
+ .end _RtlCheckStack
diff --git a/private/crt32/startup/mlock.c b/private/crt32/startup/mlock.c
new file mode 100644
index 000000000..8c8cf33ea
--- /dev/null
+++ b/private/crt32/startup/mlock.c
@@ -0,0 +1,382 @@
+#ifdef MTHREAD
+
+/***
+*mlock.c - Multi-thread locking routines
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 05-07-90 JCR Module created.
+* 06-04-90 GJF Changed error message interface.
+* 08-08-90 GJF Removed 32 from API names.
+* 08-08-90 SBM _lockmap no longer 8 times required size
+* 10-08-90 GJF New-style function declarators. Removed questionable
+* return statements from void functions (weren't needed
+* and the compiler was bitching).
+* 10-09-90 GJF Thread ids are unsigned longs.
+* 06-06-91 GJF Adapted for Win32 [_WIN32_].
+* 09-29-91 GJF Fixed infinite recursion problem with DEBUG version
+* of _lock [_WIN32_].
+* 03-06-92 GJF Removed _[un]lock_fh() and _[un]lock_stream for Win32
+* targets.
+* 05-28-92 GJF Added _mtdeletelocks() for Win32 for DLLs with contain
+* the C runtime (e.g., crtdll.dll).
+* 10-06-92 SRW Make _locktable an array of PCRITICAL_SECTION pointers
+* instead of structures. Allocate each critical section
+* as it is needed.
+* 02-25-93 GJF Substantially revised. Restored static critical section
+* structures for some locks. Replaced bit-array scheme
+* of keeping track of locks. Removed Cruiser support and
+* replaced obsolete DEBUG code.
+* 03-03-93 GJF Made CRITICAL_SECTION structure for _HEAP_LOCK static.
+* 03-08-93 SKS Fix ptr use error in DEBUG version of _mtdeletelocks
+* 03-08-93 SKS Fix deletion of the special critical sections,
+* especially the heap lock.
+* 05-05-93 GJF Turned DEBUG code off.
+* 06-03-93 SRW Disable FPO optimizations for this file so it can call
+* CriticalSection routines on a checked build even though
+* the C Runtimes are compiled free.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <rterr.h>
+#include <stddef.h>
+#include <malloc.h>
+#include <limits.h>
+
+
+/*
+ * Local routines
+ */
+void _CRTAPI3 _lockerr_exit(char *);
+
+
+/*
+ * Global Data
+ */
+
+/*
+ * Statically allocated critical section structures for _LOCKTAB_LOCK,
+ * _EXIT_LOCK1 and _HEAP_LOCK.
+ */
+static CRITICAL_SECTION ltlcritsect;
+static CRITICAL_SECTION xlcritsect;
+static CRITICAL_SECTION hlcritsect;
+
+/*
+ * Lock Table
+ * This table contains a pointer to the critical section management structure
+ * for each lock.
+ */
+PCRITICAL_SECTION _locktable[_TOTAL_LOCKS] = {
+ NULL, /* 0 == no lock defined *** OBSOLETE *** */
+ NULL, /* 1 == _SIGNAL_LOCK */
+ NULL, /* 2 == _IOB_SCAN_LOCK */
+ NULL, /* 3 == _TMPNAM_LOCK */
+ NULL, /* 4 == _INPUT_LOCK */
+ NULL, /* 5 == _OUTPUT_LOCK */
+ NULL, /* 6 == _CSCANF_LOCK */
+ NULL, /* 7 == _CPRINTF_LOCK */
+ NULL, /* 8 == _CONIO_LOCK */
+ &hlcritsect, /* 9 == _HEAP_LOCK */
+ NULL, /* 10 == _BHEAP_LOCK *** OBSOLETE *** */
+ NULL, /* 11 == _TIME_LOCK */
+ NULL, /* 12 == _ENV_LOCK */
+ &xlcritsect, /* 13 == _EXIT_LOCK1 */
+ NULL, /* 14 == _EXIT_LOCK2 *** OBSOLETE *** */
+ NULL, /* 15 == _THREADDATA_LOCK *** OBSOLETE *** */
+ NULL, /* 16 == _POPEN_LOCK */
+ &ltlcritsect, /* 17 == _LOCKTAB_LOCK */
+ NULL, /* 18 == _OSFHND_LOCK */
+ NULL, /* 19 == _SETLOCALE_LOCK */
+ NULL, /* 20 == _LC_COLLATE_LOCK */
+ NULL, /* 21 == _LC_CTYPE_LOCK */
+ NULL, /* 22 == _LC_MONETARY_LOCK */
+ NULL, /* 23 == _LC_NUMERIC_LOCK */
+ NULL, /* 24 == _LC_TIME_LOCK */
+ NULL, /* 25 == _STREAM_LOCKS */
+ NULL /* ... */
+ };
+
+
+#define _FATAL _amsg_exit(_RT_LOCK)
+
+#pragma optimize("y",off)
+
+/***
+*_mtinitlocks() - Initialize multi-thread lock scheme
+*
+*Purpose:
+* Perform whatever initialization is required for the multi-thread
+* locking (synchronization) scheme. This routine should be called
+* exactly once, during startup, and this must be before any requests
+* are made to assert locks.
+*
+* NOTES: In Win32, the multi-thread locks are created individually,
+* each upon its first use. That is when any particular lock is asserted
+* for the first time, the underlying critical section is then allocated,
+* initialized and (finally) entered. This allocation and initialization
+* is protected under _LOCKTAB_LOCK. It is _mtinitlocks' job to set up
+* _LOCKTAB_LOCK. _EXIT_LOCK1 is also set up by _mtinitlock
+*
+*Entry:
+* <none>
+*
+*Exit:
+* returns on success
+* calls _amsg_exit on failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _mtinitlocks (
+ void
+ )
+{
+#ifdef DEBUG
+ int i;
+
+ /*
+ * Scan _locktable[] and make sure everything was initialized properly
+ */
+ for ( i = 0 ; i < _TOTAL_LOCKS ; i++ ) {
+ if ( i == _LOCKTAB_LOCK ) {
+ if ( _locktable[i] != &ltlcritsect )
+ _lockerr_exit("fatal error in _mtinitlocks #1\n");
+ }
+ else if ( i == _EXIT_LOCK1 ) {
+ if ( _locktable[i] != &xlcritsect )
+ _lockerr_exit("fatal error in _mtinitlocks #2\n");
+ }
+ else if ( i == _HEAP_LOCK ) {
+ if ( _locktable[i] != &hlcritsect )
+ _lockerr_exit("fatal error in _mtinitlocks #3\n");
+ }
+ else if ( _locktable[i] != NULL )
+ _lockerr_exit("fatal error in _mtinitlocks #3\n");
+ }
+#endif /* DEBUG */
+
+ /*
+ * All we need to do is initialize _LOCKTAB_LOCK and _EXIT_LOCK1.
+ */
+ InitializeCriticalSection( _locktable[_LOCKTAB_LOCK] );
+ InitializeCriticalSection( _locktable[_EXIT_LOCK1] );
+ InitializeCriticalSection( _locktable[_HEAP_LOCK] );
+}
+
+
+/***
+*_mtdeletelocks() - Delete all initialized locks
+*
+*Purpose:
+* Walks _locktable[] and _lockmap, and deletes every 'lock' (i.e.,
+* critical section) which has been initialized.
+*
+* This function is intended for use in DLLs containing the C runtime
+* (i.e., crtdll.dll and user DLLs built using libcmt.lib and the
+* special startup objects). It is to be called from within the DLL's
+* entrypoint function when that function is called with
+* DLL_PROCESS_DETACH.
+*
+*Entry:
+* <none>
+*
+*Exit:
+*
+*Exceptions:
+* behavior undefined/unknown if a lock is being held when this routine
+* is called.
+*
+*******************************************************************************/
+
+void _CRTAPI1 _mtdeletelocks(
+ void
+ )
+{
+ int locknum;
+
+ for ( locknum = 0 ; locknum < _TOTAL_LOCKS ; locknum++ ) {
+
+ /*
+ * If the 'lock' has been created, delete it
+ */
+#ifdef DEBUG
+ /*
+ * See if the lock has already been deleted.
+ */
+ if ( _locktable[locknum] == (PCRITICAL_SECTION)(-1L) )
+ _lockerr_exit("fatal error in _mtdeletelocks #1\n");
+
+ /*
+ * Delete the lock if it had been created.
+ */
+ if ( _locktable[locknum] != NULL ) {
+ if ( (locknum != _LOCKTAB_LOCK) && (locknum !=
+ _EXIT_LOCK1) && (locknum != _HEAP_LOCK) )
+ {
+ PCRITICAL_SECTION pcs = _locktable[locknum];
+
+ /* mark as deleted */
+ _locktable[locknum] = (PCRITICAL_SECTION)(-1L);
+
+ /* double check that it wasn't already deleted */
+ if ( pcs == (PCRITICAL_SECTION)(-1L) )
+ _lockerr_exit("fatal error in _mtdeletelocks #2\n");
+
+ DeleteCriticalSection(pcs);
+ free(pcs);
+ }
+ }
+#else /* non DEBUG */
+ /*
+ * Delete the lock if it had been created
+ */
+ if ( _locktable[locknum] != NULL ) {
+ if ( (locknum != _LOCKTAB_LOCK) && (locknum !=
+ _EXIT_LOCK1) && (locknum != _HEAP_LOCK) )
+ {
+ /*
+ * Free the memory for the CritSect after deleting
+ * it. It is okay to call free() if the heap lock
+ * is kept valid until after all calls to the heap.
+ */
+ DeleteCriticalSection(_locktable[locknum]);
+ free(_locktable[locknum]);
+ }
+ }
+#endif /* DEBUG */
+
+ }
+
+ /*
+ * Finally, clean up the special locks
+ */
+ DeleteCriticalSection( _locktable[_HEAP_LOCK] );
+ DeleteCriticalSection( _locktable[_EXIT_LOCK1] );
+ DeleteCriticalSection( _locktable[_LOCKTAB_LOCK] );
+}
+
+
+/***
+* _lock - Acquire a multi-thread lock
+*
+*Purpose:
+* Note that it is legal for a thread to aquire _EXIT_LOCK1
+* multiple times.
+*
+*Entry:
+* locknum = number of the lock to aquire
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _lock (
+ int locknum
+ )
+{
+ PCRITICAL_SECTION pcs;
+
+#ifdef DEBUG
+ if ( _locktable[locknum] == (PCRITICAL_SECTION)(-1L) )
+ _lockerr_exit("fatal error in _lock #1\n");
+#endif /* DEBUG */
+
+ /*
+ * Create/open the lock, if necessary
+ */
+ if ( _locktable[locknum] == NULL ) {
+
+ if ( (pcs = malloc(sizeof(CRITICAL_SECTION))) == NULL )
+ _amsg_exit(_RT_LOCK);
+
+ _mlock(_LOCKTAB_LOCK); /*** WARNING: Recursive lock call ***/
+
+ if ( _locktable[locknum] == NULL ) {
+ InitializeCriticalSection(pcs);
+ _locktable[locknum] = pcs;
+ }
+ else {
+#ifdef DEBUG
+ if ( _locktable[locknum] == (PCRITICAL_SECTION)(-1L) )
+ _lockerr_exit("fatal error in _lock #2\n");
+#endif /* DEBUG */
+ free(pcs);
+ }
+
+ _munlock(_LOCKTAB_LOCK);
+ }
+
+ /*
+ * Enter the critical section.
+ */
+
+ EnterCriticalSection( _locktable[locknum] );
+}
+
+
+/***
+* _unlock - Release multi-thread lock
+*
+*Purpose:
+* Note that it is legal for a thread to aquire _EXIT_LOCK1
+* multiple times.
+*
+*Entry:
+* locknum = number of the lock to release
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _unlock (
+ int locknum
+ )
+{
+ /*
+ * leave the critical section.
+ */
+ LeaveCriticalSection( _locktable[locknum] );
+}
+
+#pragma optimize("y",)
+
+/***
+*_lockerr_exit() - Write error message and die
+*
+*Purpose:
+* Attempt to write out the unexpected lock error message, then terminate
+* the program by a direct API call. This function is used in place of
+* amsg_exit(_RT_LOCK) when it is judged unsafe to allow further lock
+* or unlock calls.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI3 _lockerr_exit (
+ char *msg
+ )
+{
+ FatalAppExit(0, msg); /* Die with message box */
+ ExitProcess(255); /* Just die */
+}
+
+
+#endif /* MTHREAD */
diff --git a/private/crt32/startup/ppc/chkstk.s b/private/crt32/startup/ppc/chkstk.s
new file mode 100644
index 000000000..ceec550f7
--- /dev/null
+++ b/private/crt32/startup/ppc/chkstk.s
@@ -0,0 +1,190 @@
+// TITLE("C-Runtime Stack Checking")
+//++
+//
+// Copyright (c) 1993,1994 IBM Corporation
+//
+// Module Name:
+//
+// chkstk.s
+//
+// Abstract:
+//
+// This module implements runtime stack checking.
+//
+// Author:
+//
+// Mark D. Johnson
+//
+// Environment:
+//
+// User/Kernel mode.
+//
+// Revision History:
+//
+//--
+
+#include <ksppc.h>
+
+
+ SBTTL("Check Stack")
+//++
+//
+// VOID _RtlCheckStack(in ULONG n_alloc)
+//
+// Routine Description:
+//
+// This function provides runtime stack checking for local allocations
+// that are more than a page and for storage dynamically allocated with
+// the alloca function. Stack checking consists of probing downward in
+// the stack a page at a time. If the current stack commitment is exceeded,
+// then the system will automatically attempt to expand the stack. If the
+// attempt succeeds, then another page is committed. Otherwise, a stack
+// overflow exception is raised. It is the responsiblity of the caller to
+// handle this exception.
+//
+// Two entry points are supported. The first/standard entry point
+// calls for n_alloc to be passed as single argument (in r.3). In
+// the second case, the single argument is the negative of the amount
+// requested (the amount by which to decrement the stack pointer), and
+// is passed in r.12.
+//
+// Registers r.0 and r.11 are modified.
+//
+// Arguments:
+//
+// n_alloc(r.3/r.12) - Supplies the size of the allocation on the stack.
+// With standard entry, passed in r.3. In alternate
+// entry, passed in r.12. In the latter case (r.12)
+// the value supplied is the quanitity by which to
+// decrement r.sp (a negative value).
+//
+// Return Value:
+//
+// None.
+//
+// Assumptions:
+//
+// The value of Teb_Ptr is provided in r.13.
+//
+// The bottom of stack "bot" (r.11) is multiple of PAGE_SIZE.
+//
+
+//
+// low
+// :
+// | :
+// | |
+// | |
+// |.......|<--- r.sp + r.12 - (PAGE_SIZE-1)
+// | ^ |
+// | |< -|- - - - - - always < PAGE_SIZE
+// | v |
+// +-------+<--- bot - m*PAGE_SIZE
+// | |
+// | : |
+// | |
+// +-------+<--- r.sp + r.12
+// | |
+// | |
+// | |
+// | : |
+// | : |
+// | : |
+// | : |
+// | |
+// | |
+// | |
+// | |
+// +=======+<--- bottom of stack "bot" (r.11)
+// | |
+// | |
+// | |
+// | : |
+// | : |
+// | : |
+// | |
+// | |
+// +-------+<--- r.sp
+// | |
+// | |
+// | : |
+// | :
+// | : high
+// : m is count for add'l pages to commit
+//
+//
+// m:=max(0,{bot-[(r.sp+r.12)-(PAGE_SIZE-1)]}/PAGE_SIZE)
+// =max(0,bot-[r.12-(PAGE_SIZE-1)+r.sp])/PAGE_SIZE
+//
+// Operands in expression [r.12-(PAGE_SIZE-1)+r.sp) are known upon entry
+// to routine. This intermediate quantity is calculated early in r.0,
+// behind user/kernel mode test.
+
+
+ .text
+ .align 5
+
+ // want entry for _RtlCheckStack aligned on a 2**5-1 byte boundary so that
+ // more commonly used (internal) entry _RtlCheckStack.12 is aligned on
+ // 2**5 byte (cache-line) boundary ... and most often used code fits in
+ // single cache-line
+
+ or r.11, r.11, r.11; or r.11, r.11, r.11
+ or r.11, r.11, r.11; or r.11, r.11, r.11
+
+ or r.11, r.11, r.11; or r.11, r.11, r.11
+ or r.11, r.11, r.11; or r.11, r.11, r.11
+
+ or r.11, r.11, r.11; or r.11, r.11, r.11
+ or r.11, r.11, r.11; or r.11, r.11, r.11
+
+ or r.11, r.11, r.11; or r.11, r.11, r.11
+ or r.11, r.11, r.11
+
+ LEAF_ENTRY(_RtlCheckStack)
+
+ neg r.12,r.3
+
+ ALTERNATE_ENTRY(_RtlCheckStack.12)
+
+ cmpwi r.sp,0 // user or kernel mode?
+
+ // partial comp of num pages to commit moved here for performance
+
+ subi r.0,r.12,(PAGE_SIZE-1)
+ add r.0,r.0,r.sp
+
+ bge+ UsrMode // sp >=0 indicates user mode
+
+ // kernel mode, KIPCR is system mode macro to get KiPcr
+
+ KIPCR(r.11)
+ lwz r.11,PcInitialStack(r.11)
+ subi r.11,r.11,KERNEL_STACK_SIZE
+ b CommonCode
+
+UsrMode:
+
+ // r.13 contains the TEB pointer
+
+ lwz r.11,TeStackLimit(r.13) // Get low stack address
+
+CommonCode:
+
+ // r.11 contains computed "bot" of stack
+
+ sub r.0,r.11,r.0
+ srawi. r.0,r.0,PAGE_SHIFT // Number pages to add/commit
+ blelr // if <=0, return
+
+ mtctr r.0
+
+PageLoop:
+
+ // Attempt to commit pages beyond the limit
+
+ lwzu r.0,-PAGE_SIZE(r.11)
+ bdnz PageLoop
+
+
+ LEAF_EXIT(_RtlCheckStack)
diff --git a/private/crt32/startup/ppc/sources b/private/crt32/startup/ppc/sources
new file mode 100644
index 000000000..d82d03db9
--- /dev/null
+++ b/private/crt32/startup/ppc/sources
@@ -0,0 +1,3 @@
+PPC_SOURCES=ppc\chkstk.s
+
+
diff --git a/private/crt32/startup/sources b/private/crt32/startup/sources
new file mode 100644
index 000000000..d9d8e2c6d
--- /dev/null
+++ b/private/crt32/startup/sources
@@ -0,0 +1,65 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=startup
+
+TARGETNAME=startup
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+!IF "$(CRTLIBTYPE)" == "POSIX"
+C_DEFINES=$(C_DEFINES) -D_KERNEL32_
+!ENDIF
+
+SOURCES=crt0.c \
+ crt0dat.c \
+ crt0init.c \
+ crt0fp.c \
+ crt0msg.c \
+ dllcrt0.c \
+ dllmain.c \
+ mlock.c \
+ stdargv.c \
+ stdenvp.c \
+ _setargv.c \
+ thread.c \
+ tidtable.c \
+ tlssup.c \
+ wild.c \
+ wincrt0.c
+
+i386_SOURCES=i386\chkstk.asm \
+ i386\atlssup.asm
+
+MIPS_SOURCES=mips\chkstk.s
+
+ALPHA_SOURCES=alpha\chkstk.s
+
+NTTARGETFILES=
+
diff --git a/private/crt32/startup/stdargv.c b/private/crt32/startup/stdargv.c
new file mode 100644
index 000000000..e75e98b77
--- /dev/null
+++ b/private/crt32/startup/stdargv.c
@@ -0,0 +1,501 @@
+/***
+*stdargv.c - standard & wildcard _setargv routine
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* processes program command line, with or without wildcard expansion
+*
+*Revision History:
+* 06-27-89 PHG module created, based on asm version
+* 04-09-90 GJF Added #include <cruntime.h>. Made calling types
+* explicit (_CALLTYPE1 or _CALLTYPE4). Also, fixed the
+* copyright.
+* 06-04-90 GJF Changed error message interface.
+* 08-31-90 GJF Removed 32 from API names.
+* 09-25-90 GJF Merged tree version with local version (8-31 change
+* with 6-4 change).
+* 10-08-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-25-91 SRW Include oscalls.h if _WIN32_ OR WILDCARD defined
+* 01-25-91 SRW Changed Win32 Process Startup [_WIN32_]
+* 01-25-91 MHL Fixed bug in Win32 Process Startup [_WIN32_]
+* 01-28-91 GJF Fixed call to DOSFINDFIRST (removed last arg).
+* 01-31-91 MHL Changed to call GetModuleFileName instead of NtCurrentPeb() [_WIN32_]
+* 02-18-91 SRW Fixed command line parsing bug [_WIN32_]
+* 03-11-91 GJF Fixed check of FindFirstFile return [_WIN32_].
+* 03-12-91 SRW Add FindClose call to _find [_WIN32_]
+* 04-16-91 SRW Fixed quote parsing logic for arguments.
+* 03-31-92 DJM POSIX support.
+* 05-12-92 DJM ifndefed for POSIX.
+* 06-02-92 SKS Add #include <dos.h> for CRTDLL definition of _pgmptr
+* 04-19-93 GJF Change test in the do-while loop in parse_cmdline to
+* NOT terminate on chars with high bit set.
+* 05-14-93 GJF Added support for quoted program names.
+* 05-28-93 KRS Added MBCS support under _MBCS switches.
+* 06-04-93 KRS Added more MBCS logic.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <internal.h>
+#include <rterr.h>
+#include <stdlib.h>
+#if defined(WILDCARD) || defined(_WIN32_)
+#include <dos.h>
+#include <oscalls.h>
+#endif
+#ifdef _MBCS
+#include <mbctype.h>
+#endif
+
+static void _CRTAPI3 parse_cmdline(char *cmdstart, char **argv, char *args,
+ int *numargs, int *numbytes);
+
+/***
+*_setargv, __setargv - set up "argc" and "argv" for C programs
+*
+*Purpose:
+* Read the command line and create the argv array for C
+* programs.
+*
+*Entry:
+* Arguments are retrieved from the program command line,
+* pointed to by _acmdln.
+*
+*Exit:
+* "argv" points to a null-terminated list of pointers to ASCIZ
+* strings, each of which is an argument from the command line.
+* "argc" is the number of arguments. The strings are copied from
+* the environment segment into space allocated on the heap/stack.
+* The list of pointers is also located on the heap or stack.
+* _pgmptr points to the program name.
+*
+*Exceptions:
+* Terminates with out of memory error if no memory to allocate.
+*
+*******************************************************************************/
+
+#ifdef WILDCARD
+void _CRTAPI1 __setargv (
+#else
+void _CRTAPI1 _setargv (
+#endif
+ void
+ )
+{
+ char *p;
+ char *cmdstart; /* start of command line to parse */
+ int numargs, numbytes;
+
+#ifdef _CRUISER_
+
+ /* OS/2 sets up memory like this:
+ <nul><full path of program><nul><prog name as typed><nul><arguments><nul>
+ ^
+ _acmdline
+ */
+
+ /* first we set _pgmptr to point to the full name of program */
+ p = _acmdln - 1;
+ while (*(p-1) != '\0')
+ --p;
+ _pgmptr = p;
+
+#else /* ndef _CRUISER_ */
+
+#if defined(_WIN32_)
+ static char _pgmname[ MAX_PATH ];
+
+ /* Get the program name pointer from Win32 Base */
+
+ GetModuleFileName( NULL, _pgmname, sizeof( _pgmname ));
+ _pgmptr = _pgmname;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* if there's no command line at all (won't happen from cmd.exe, but
+ possibly another program), then we use _pgmptr as the command line
+ to parse, so that argv[0] is initialized to the program name */
+ cmdstart = (*_acmdln == '\0') ? _pgmptr : _acmdln;
+
+ /* first find out how much space is needed to store args */
+ parse_cmdline(cmdstart, NULL, NULL, &numargs, &numbytes);
+
+ /* allocate space for argv[] vector and strings */
+ p = malloc(numargs * sizeof(char *) + numbytes);
+ if (p == NULL)
+ _amsg_exit(_RT_SPACEARG);
+
+ /* store args and argv ptrs in just allocated block */
+ parse_cmdline(cmdstart, (char **)p, p + numargs * sizeof(char *), &numargs, &numbytes);
+
+ /* set argv and argc */
+ __argc = numargs - 1;
+ __argv = (char **)p;
+#ifdef WILDCARD
+ /* call _cwild to expand wildcards in arg vector */
+ if (_cwild())
+ _amsg_exit(_RT_SPACEARG); /* out of space */
+#endif
+}
+
+
+/***
+*static void parse_cmdline(cmdstart, argv, args, numargs, numbytes)
+*
+*Purpose:
+* Parses the command line and sets up the argv[] array.
+* On entry, cmdstart should point to the command line,
+* argv should point to memory for the argv array, args
+* points to memory to place the text of the arguments.
+* If these are NULL, then no storing (only coujting)
+* is done. On exit, *numargs has the number of
+* arguments (plus one for a final NULL argument),
+* and *numbytes has the number of bytes used in the buffer
+* pointed to by args.
+*
+*Entry:
+* char *cmdstart - pointer to command line of the form
+* <progname><nul><args><nul>
+* char **argv - where to build argv array; NULL means don't
+* build array
+* char *args - where to place argument text; NULL means don't
+* store text
+*
+*Exit:
+* no return value
+* int *numargs - returns number of argv entries created
+* int *numbytes - number of bytes used in args buffer
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 parse_cmdline (
+ char *cmdstart,
+ char **argv,
+ char *args,
+ int *numargs,
+ int *numbytes
+ )
+{
+ char *p;
+ unsigned char c;
+ int inquote; /* 1 = inside quotes */
+ int copychar; /* 1 = copy char to *args */
+ unsigned numslash; /* num of backslashes seen */
+
+ *numbytes = 0;
+ *numargs = 1; /* the program name at least */
+
+ /* first scan the program name, copy it, and count the bytes */
+ p = cmdstart;
+ if (argv)
+ *argv++ = args;
+#ifdef WILDCARD
+ /* To handle later wild card expansion, we prefix each entry by
+ it's first character before quote handling. This is done
+ so _cwild() knows whether to expand an entry or not. */
+ if (args)
+ *args++ = *p;
+ ++*numbytes;
+
+#endif /* WILDCARD */
+ /* A quoted program name is handled here. The handling is much
+ simpler than for other arguments. Basically, whatever lies
+ between the leading double-quote and next one, or a terminal null
+ character is simply accepted. Fancier handling is not required
+ because the program name must be a legal NTFS/HPFS file name.
+ Note that the double-quote characters are not copied, nor do they
+ contribute to numbytes. */
+ if ( *p == '\"' ) {
+ /* scan from just past the first double-quote through the next
+ double-quote, or up to a null, whichever comes first */
+ while ( (*(++p) != '\"') && (*p != '\0') ) {
+
+#ifdef _MBCS
+ if (_ismbblead(*p)) {
+ *numbytes += 2;
+ if ( args ) {
+ *args++ = *p++;
+ *args++ = *p;
+ }
+ }
+ else {
+#endif
+ ++*numbytes;
+ if ( args )
+ *args++ = *p;
+#ifdef _MBCS
+ }
+#endif
+ }
+ /* append the terminating null */
+ ++*numbytes;
+ if ( args )
+ *args++ = '\0';
+
+ /* if we stopped on a double-quote (usual case), skip over it */
+ if ( *p == '\"' )
+ p++;
+ }
+ else {
+ /* Not a quoted program name */
+ do {
+ ++*numbytes;
+ if (args)
+ *args++ = *p;
+#ifdef _CRUISER_
+
+ } while (*p++ != '\0');
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ c = (unsigned char) *p++;
+#ifdef _MBCS
+ if (_ismbblead(c)) {
+ ++*numbytes;
+ if (args)
+ *args++ = *p; /* copy 2nd byte too */
+ p++; /* skip over trail byte */
+ }
+#endif
+
+ } while ( c > ' ' );
+
+ if ( c == '\0' ) {
+ p--;
+ } else {
+ if (args)
+ *(args-1) = '\0';
+ }
+ }
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER, OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ inquote = 0;
+
+ /* loop on each argument */
+ for(;;) {
+
+#ifdef _CRUISER_
+ /* skip blanks */
+ while (*p == ' ' || *p == '\t')
+ ++p;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ if ( *p ) {
+ while (*p == ' ' || *p == '\t')
+ ++p;
+ }
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER, OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ if (*p == '\0')
+ break; /* end of args */
+
+ /* scan an argument */
+ if (argv)
+ *argv++ = args; /* store ptr to arg */
+ ++*numargs;
+
+#ifdef WILDCARD
+ /* To handle later wild card expansion, we prefix each entry by
+ it's first character before quote handling. This is done
+ so _cwild() knows whether to expand an entry or not. */
+ if (args)
+ *args++ = *p;
+ ++*numbytes;
+
+#endif /* WILDCARD */
+
+ /* loop through scanning one argument */
+ for (;;) {
+ copychar = 1;
+ /* Rules: 2N backslashes + " ==> N backslashes and begin/end quote
+ 2N+1 backslashes + " ==> N backslashes + literal "
+ N backslashes ==> N backslashes */
+ numslash = 0;
+ while (*p == '\\') {
+ /* count number of backslashes for use below */
+ ++p;
+ ++numslash;
+ }
+ if (*p == '\"') {
+ /* if 2N backslashes before, start/end quote, otherwise
+ copy literally */
+ if (numslash % 2 == 0) {
+ if (inquote)
+ if (p[1] == '\"')
+ p++; /* Double quote inside quoted string */
+ else /* skip first quote char and copy second */
+ copychar = 0;
+ else
+ copychar = 0; /* don't copy quote */
+
+ inquote = !inquote;
+ }
+ numslash /= 2; /* divide numslash by two */
+ }
+
+ /* copy slashes */
+ while (numslash--) {
+ if (args)
+ *args++ = '\\';
+ ++*numbytes;
+ }
+
+ /* if at end of arg, break loop */
+ if (*p == '\0' || (!inquote && (*p == ' ' || *p == '\t')))
+ break;
+
+ /* copy character into argument */
+#ifdef _MBCS
+ if (copychar) {
+ if (args) {
+ if (_ismbblead(*p)) {
+ *args++ = *p++;
+ ++*numbytes;
+ }
+ *args++ = *p;
+ } else {
+ if (_ismbblead(*p)) {
+ ++p;
+ ++*numbytes;
+ }
+ }
+ ++*numbytes;
+ }
+ ++p;
+#else
+ if (copychar) {
+ if (args)
+ *args++ = *p;
+ ++*numbytes;
+ }
+ ++p;
+#endif
+ }
+
+ /* null-terminate the argument */
+
+ if (args)
+ *args++ = '\0'; /* terminate string */
+ ++*numbytes;
+ }
+
+ /* We put one last argument in -- a null ptr */
+ if (argv)
+ *argv++ = NULL;
+ ++*numargs;
+}
+
+
+#ifdef WILDCARD
+/***
+*_find(pattern) - find matching filename
+*
+*Purpose:
+* if argument is non-null, do a DOSFINDFIRST on that pattern
+* otherwise do a DOSFINDNEXT call. Return matching filename
+* or NULL if no more matches.
+*
+*Entry:
+* pattern = pointer to pattern or NULL
+* (NULL means find next matching filename)
+*
+*Exit:
+* returns pointer to matching file name
+* or NULL if no more matches.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CRTAPI1 _find (
+ char *pattern
+ )
+{
+ char *retval;
+
+#ifdef _CRUISER_
+ static FILEFINDBUF findbuf;
+ HDIR findhandle = HDIR_SYSTEM;
+ ULONG findcount = 1;
+ int rc;
+
+ if (pattern)
+ rc = DOSFINDFIRST(pattern, &findhandle, FILE_NORMAL | FILE_DIRECTORY,
+ &findbuf, sizeof(findbuf), &findcount, 1L);
+ else
+ rc = DOSFINDNEXT(findhandle, &findbuf, sizeof(findbuf), &findcount);
+
+ retval = rc ? NULL : findbuf.achName;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ static HANDLE _WildFindHandle;
+ static LPWIN32_FIND_DATA findbuf;
+
+ if (pattern) {
+ if (findbuf == NULL)
+ findbuf = (LPWIN32_FIND_DATA)malloc(MAX_PATH + sizeof(*findbuf));
+
+ if (_WildFindHandle != NULL) {
+ (void)FindClose( _WildFindHandle );
+ _WildFindHandle = NULL;
+ }
+
+ _WildFindHandle = FindFirstFile( (LPSTR)pattern, findbuf );
+ if (_WildFindHandle == (HANDLE)0xffffffff)
+ return NULL;
+ }
+ else
+ if (!FindNextFile( _WildFindHandle, findbuf )) {
+ (void)FindClose( _WildFindHandle );
+ _WildFindHandle = NULL;
+ return NULL;
+ }
+
+ retval = findbuf->cFileName;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER, OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ return retval;
+}
+
+#endif /* WILDCARD */
+
+#endif /* ndef _POSIX_ */
diff --git a/private/crt32/startup/stdenvp.c b/private/crt32/startup/stdenvp.c
new file mode 100644
index 000000000..7ebdfa806
--- /dev/null
+++ b/private/crt32/startup/stdenvp.c
@@ -0,0 +1,192 @@
+/***
+*stdenvp.c - OS/2 standard _setenvp routine
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module is called by the C start-up routine to set up "_environ".
+* Its sets up an array of pointers to strings in the environment.
+* The global symbol "_environ" is set to point to this array.
+*
+*Revision History:
+* 11-07-84 GFW initial version
+* 01-08-86 SKS Modified for OS/2
+* 05-21-86 SKS Call _stdalloc to get memory for strings
+* 09-04-86 SKS Added check to skip the "*C_FILE_INFO" string
+* 10-21-86 SKS Improved check for "*C_FILE_INFO"/"_C_FILE_INFO"
+* 02-19-88 SKS Handle case where environment starts with a single null
+* 05-10-88 JCR Modified code to accept far pointer from _stdalloc
+* 06-01-88 PHG Merged DLL and normal versions
+* 07-12-88 JCR Largely re-written: (1) split mem allocation into two
+* seperate malloc() calls to help simplify putenv(),
+* (2) stdalloc() no longer robs from stack, (3) cProc/cEnd
+* sequence, (4) misc cleanup
+* 09-20-88 WAJ Initial 386 version
+* 12-13-88 JCR Use rterr.inc parameters for runtime errors
+* 04-09-90 GJF Added #include <cruntime.h>. Made the calling type
+* _CALLTYPE1. Also, fixed the copyright and cleaned up
+* up the formatting a bit.
+* 06-05-90 GJF Changed error message interface.
+* 10-08-90 GJF New-style function declarator.
+* 10-31-90 GJF Fixed statement appending the final NULL (Stevewo
+* found the bug).
+* 12-11-90 SRW Changed to include <oscalls.h> and setup _environ
+* correctly for Win32
+* 01-21-91 GJF ANSI naming.
+* 02-07-91 SRW Change _WIN32_ specific code to allocate static copy (_WIN32_)
+* 02-18-91 SRW Change _WIN32_ specific code to allocate copy of
+* variable strings as well [_WIN32_]
+* 07-25-91 GJF Changed strupr to _strupr.
+* 03-31-92 DJM POSIX support.
+* 04-20-92 GJF Removed conversion to upper-case code for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <stdlib.h>
+#include <internal.h>
+#include <rterr.h>
+#include <oscalls.h>
+
+/* C file info string */
+extern char _cfinfo[];
+
+/***
+*_setenvp - set up "envp" for C programs
+*
+*Purpose:
+* Reads the environment and build the envp array for C programs.
+*
+*Entry:
+* The environment strings occur at _aenvptr.
+* The list of environment strings is terminated by an extra null
+* byte. Thus two null bytes in a row indicate the end of the
+* last environment string and the end of the environment, resp.
+*
+*Exit:
+* "environ" points to a null-terminated list of pointers to ASCIZ
+* strings, each of which is of the form "VAR=VALUE". The strings
+* are not copied from the environment area. Instead, the array of
+* pointers will point into the OS environment area. This array of
+* pointers will be malloc'ed
+*
+*Uses:
+* Allocates space on the heap for the environment pointers.
+*
+*Exceptions:
+* If space cannot be allocated, program is terminated.
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _setenvp (
+ void
+ )
+{
+ char *p;
+ char **env; /* _environ ptr traversal pointer */
+ int numstrings; /* number of environment strings */
+
+#ifdef _CRUISER_
+
+ numstrings = 0;
+ p = _aenvptr;
+
+ /* NOTE: starting with single null indicates no environ */
+ /* count the number of strings */
+ while (*p != '\0') {
+ p += strlen(p) + 1;
+ ++numstrings;
+ }
+
+ /* need pointer for each string, plus one null ptr at end */
+ _environ = env = malloc((numstrings+1) * sizeof(char *));
+ if (_environ == NULL)
+ _amsg_exit(_RT_SPACEENV);
+
+ p = _aenvptr;
+ /* copy pointers to strings into env - don't copy _C_FILEINFO string */
+ while (*p != '\0') {
+
+ if (strncmp(p, _acfinfo, CFI_LENGTH) != 0)
+ *env++ = p;
+ p += strlen(p) + 1;
+ }
+
+ /* and a final NULL pointer */
+ *env = NULL;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ int cb;
+
+ numstrings = 0;
+ p = _aenvptr;
+
+ /* NOTE: starting with single null indicates no environ */
+ /* count the number of strings */
+ while (*p != '\0') {
+ p += strlen(p) + 1;
+ ++numstrings;
+ }
+
+ /* need pointer for each string, plus one null ptr at end */
+ if ( (_environ = env = malloc((numstrings+1) * sizeof(char *)))
+ == NULL )
+ _amsg_exit(_RT_SPACEENV);
+
+ /* copy strings to malloc'd memory and save pointers in _environ */
+ for ( p = _aenvptr ; *p != '\0' ; env++, p += cb ) {
+ cb = strlen(p) + 1;
+ if ( (*env = malloc(cb)) == NULL )
+ _amsg_exit(_RT_SPACEENV);
+ strcpy(*env, p);
+ }
+
+ /* and a final NULL pointer */
+ *env = NULL;
+
+#else /* ndef _WIN32_ */
+
+#ifdef _POSIX_
+
+#if 0 /* it would seem that this code is unnecessary for POSIX */
+ /* since it is never called! */
+
+ numstrings = 0;
+ p = _aenvptr;
+
+ /* NOTE: starting with single null indicates no environ */
+ /* count the number of strings */
+ while (*p != '\0') {
+ p += strlen(p) + 1;
+ ++numstrings;
+ }
+
+ /* need pointer for each string, plus one null ptr at end */
+ _environ = env = malloc((numstrings+1) * sizeof(char *));
+
+ p = _aenvptr;
+ while (*p != '\0') {
+ *env = p++;
+ while (*p++ != '\0')
+ ;
+ env++;
+ }
+
+ /* and a final NULL pointer */
+ *env = NULL;
+
+#endif /* 0 */
+
+#else
+
+#error ERROR - ONLY CRUISER, POSIX, OR WIN32 TARGET SUPPORTED!
+
+#endif /* _POSIX_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+}
diff --git a/private/crt32/startup/thread.c b/private/crt32/startup/thread.c
new file mode 100644
index 000000000..5878eecc7
--- /dev/null
+++ b/private/crt32/startup/thread.c
@@ -0,0 +1,254 @@
+#ifdef MTHREAD
+
+
+/***
+*thread.c - Being and end a thread
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This source contains the _beginthread() and _endthread()
+* routines which are used to start and terminate a thread.
+*
+*Revision History:
+* 05-09-90 JCR Translated from ASM to C
+* 07-25-90 SBM Removed '32' from API names
+* 10-08-90 GJF New-style function declarators.
+* 10-09-90 GJF Thread ids are of type unsigned long.
+* 10-19-90 GJF Added code to set _stkhqq properly in stub().
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 06-03-91 GJF Win32 version [_WIN32_].
+* 07-18-91 GJF Fixed many silly errors [_WIN32_].
+* 08-19-91 GJF Allow for newly created thread terminating before
+* _beginthread returns
+* 09-30-91 GJF Add per-thread initialization and termination calls
+* for floating point.
+* 01-18-92 GJF Revised try - except statement.
+* 02-25-92 GJF Initialize _holdrand field to 1.
+* 09-30-92 SRW Add WINAPI keyword to _threadstart routine
+* 10-30-92 GJF Error ret for CreateThread is 0 (NULL), not -1.
+* 02-13-93 GJF Revised to use TLS API. Also, purged Cruiser support.
+* 03-26-93 GJF Fixed horribly embarrassing bug: ptd->pxcptacttab
+* must be initialized to _XcptActTab!
+* 04-27-93 GJF Removed support for _RT_STACK, _RT_INTDIV,
+* _RT_INVALDISP and _RT_NONCONT.
+* 12-14-93 SKS Free up per-thread data using a call to _freeptd()
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <msdos.h>
+#include <malloc.h>
+#include <process.h>
+#include <rterr.h>
+
+/*
+ * Startup code for new thread.
+ */
+static unsigned long WINAPI _threadstart(void *);
+
+/*
+ * useful type for initialization and termination declarations
+ */
+typedef void (_CRTAPI1 *PF)(void);
+
+/*
+ * declare pointers to per-thread FP initialization and termination routines
+ */
+PF _FPmtinit;
+PF _FPmtterm;
+
+
+/***
+*_beginthread() - Create a child thread
+*
+*Purpose:
+* Create a child thread.
+*
+*Entry:
+* initialcode = pointer to thread's startup code address
+* stacksize = size of stack
+* argument = argument to be passed to new thread
+*
+*Exit:
+* success = handle for new thread if successful
+*
+* failure = (unsigned long) -1L in case of error, errno and _doserrno
+* are set
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned long _CRTAPI1 _beginthread (
+ void (_CRTAPI1 * initialcode) (void *),
+ unsigned stacksize,
+ void * argument
+ )
+{
+ _ptiddata ptd; /* pointer to per-thread data */
+ unsigned long thdl; /* thread handle */
+
+ /*
+ * Allocate and initialize a per-thread data structure for the to-
+ * be-created thread.
+ */
+ if ( (ptd = calloc(1, sizeof(struct _tiddata))) == NULL )
+ goto error_return;
+
+ ptd->_initaddr = (void *) initialcode;
+ ptd->_initarg = argument;
+ ptd->_holdrand = 1L;
+ ptd->_pxcptacttab = (void *)_XcptActTab;
+
+ /*
+ * Create the new thread. Bring it up in a suspended state so that
+ * the _thandle and _tid fields are filled in before execution
+ * starts.
+ */
+ if ( (ptd->_thandle = thdl = (unsigned long)
+ CreateThread( NULL,
+ stacksize,
+ _threadstart,
+ (LPVOID)ptd,
+ CREATE_SUSPENDED,
+ (LPDWORD)&(ptd->_tid) ))
+ == 0L )
+ goto error_return;
+
+ /*
+ * Start the new thread executing
+ */
+ if ( ResumeThread( (HANDLE)thdl ) == (DWORD)(-1L) )
+ goto error_return;
+
+ /*
+ * Good return
+ */
+ return(thdl);
+
+ /*
+ * Error return
+ */
+error_return:
+ /***
+ *** MAP ERROR CODE!
+ ***/
+ return((unsigned long)-1L);
+}
+
+
+/***
+*_threadstart() - New thread begins here
+*
+*Purpose:
+* The new thread begins execution here. This routine, in turn,
+* passes control to the user's code.
+*
+*Entry:
+* void *ptd = pointer to _tiddata structure for this thread
+*
+*Exit:
+* Never returns - terminates thread!
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static unsigned long WINAPI _threadstart (
+ void * ptd
+ )
+{
+ /*
+ * Stash the pointer to the per-thread data stucture in TLS
+ */
+ if ( !TlsSetValue(__tlsindex, ptd) )
+ _amsg_exit(_RT_THREAD);
+
+ /*
+ * Call fp initialization, if necessary
+ */
+ if ( _FPmtinit != NULL )
+ (*_FPmtinit)();
+
+ /*
+ * Guard call to user code with a _try - _except statement to
+ * implement runtime errors and signal support
+ */
+ try {
+ ( (void(_CRTAPI1 *)(void *))(((_ptiddata)ptd)->_initaddr) )
+ ( ((_ptiddata)ptd)->_initarg );
+
+ _endthread();
+ }
+ except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
+ {
+ /*
+ * Should never reach here
+ */
+ _exit( GetExceptionCode() );
+
+ } /* end of _try - _except */
+
+ /*
+ * Never executed!
+ */
+ return(0L);
+}
+
+
+/***
+*_endthread() - Terminate the calling thread
+*
+*Purpose:
+*
+*Entry:
+* void
+*
+*Exit:
+* Never returns!
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _endthread (
+ void
+ )
+{
+ _ptiddata ptd; /* pointer to thread's _tiddata struct */
+
+ /*
+ * Call fp termination, if necessary
+ */
+ if ( _FPmtterm != NULL )
+ (*_FPmtterm)();
+
+ if ( (ptd = _getptd()) == NULL )
+ _amsg_exit(_RT_THREAD);
+
+ /*
+ * Close the thread handle (if there was one)
+ */
+ if ( ptd->_thandle != (unsigned long)(-1L) )
+ (void) CloseHandle( (HANDLE)(ptd->_thandle) );
+
+ /*
+ * Free up the _tiddata structure & its subordinate buffers
+ * _freeptd() will also clear the value for this thread
+ * of the TLS variable __tlsindex.
+ */
+ _freeptd(ptd);
+
+ /*
+ * Terminate the thread
+ */
+ ExitThread(0);
+
+}
+
+#endif /* MTHREAD */
diff --git a/private/crt32/startup/tidprint.c b/private/crt32/startup/tidprint.c
new file mode 100644
index 000000000..290a6288e
--- /dev/null
+++ b/private/crt32/startup/tidprint.c
@@ -0,0 +1,286 @@
+/***
+*tidprint.c - Dislpay thread data
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Display the per thread data table.
+*
+* [NOTE: This module is NOT included in the C runtime libraries but
+* is maintained for debugging analysis.]
+*
+*Revision History:
+* 11-17-88 JCR Module created.
+* 04-03-89 JCR Added _stackalloc to tid table
+* 06-06-89 JCR 386 version
+* 06-09-89 JCR 386: Added values to _tiddata struc (for _beginthread)
+* 04-09-90 GJF Added #include <cruntime.h>. Made the calling type
+* _CALLTYPE1. Also, fixed the copyright.
+* 04-10-90 GJF Removed #include <dos.h>.
+* 08-16-90 SBM Made _terrno and _tdoserrno int, not unsigned
+* 10-08-90 GJF New-style function declarators.
+* 10-09-90 GJF Thread ids are of type unsigned long!
+* 12-18-90 GJF Use real thread id, not thread id - 1.
+* 08-01-91 GJF Adapted for Win32 [_WIN32_].
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <os2dll.h>
+
+#ifdef _CRUISER_
+void _CALLTYPE1 _print_tiddata(unsigned long);
+void _CALLTYPE1 _print_tid(struct _tiddata *, unsigned long);
+
+extern unsigned long _tidtabmax;
+extern struct _tiddata * _threaddata;
+
+/***
+*void _print_tiddata(unsigned long) - Display data for a thread
+*
+*Purpose:
+* This routine displays the per thread data for one (or all)
+* threads in the table.
+*
+*Entry:
+* unsigned long = <n> = Threadid of tid to display
+* = -1 = Display all tids' data
+*
+*Exit:
+* <void>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _print_tiddata (
+ unsigned long tid
+ )
+{
+ unsigned long maxtid;
+ struct _tiddata * tdata;
+ unsigned long i;
+
+ /* Get and save current maxtid value */
+ maxtid = _tidtabmax;
+
+ /* See if user want's all threads or just a specific one. */
+ if (tid == (unsigned long) -1L) {
+
+ /* Print out all threads */
+
+ printf("\nPER THREAD DATA TABLE (NUMBER OF THREADS = %u)\n"
+ "----------------------------------------------\n", maxtid+1);
+
+ for (i=0; i<=maxtid; i++) {
+ /* Get pointer to tidtable entry */
+ tdata = &_threaddata[i];
+ _print_tid(tdata,i+1); /* print it out */
+ }
+
+ /* Make sure the table didn't change size while we processed it */
+ if (_tidtabmax > maxtid)
+ printf("*** WARNING: Tid data table grew while printing out data. ***\n\n");
+
+ printf("END THREAD TABLE\n"
+ "----------------\n\n");
+
+ }
+
+ else {
+
+ /* Print out the specific thread supplied by the user. */
+
+ if (tid > maxtid) {
+ printf("*** ERROR: Tid value outside thread data table. ***\n");
+ return;
+ }
+
+ /* point to tid data */
+ tdata = &_threaddata[tid-1];
+ _print_tid(tdata,tid); /* print it out */
+ }
+
+}
+
+
+/***
+* void _print_tid() - Print out thread data
+*
+*Purpose:
+* Given the address of a thread data entry, print out that
+* information.
+*
+*Entry:
+* struct _tiddata * = pointer to thread's data area
+* unsigned long = associated threadid (0-based)
+*
+*Exit:
+* <void>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _print_tid (
+ struct _tiddata * td,
+ unsigned long tid
+ )
+{
+
+ printf("TID %u DATA (%lp):\n", tid, td);
+
+ printf("\t_terrno = %d \t (errno value)\n", td->_terrno);
+ printf("\t_tdoserrno = %d \t (_doserrno value)\n", td->_tdoserrno);
+ printf("\t_stkhqq = %#x\t (stack limit)\n", td->_stkhqq);
+ printf("\t_fpds = %#x \t (Floating Point data segment)\n",
+ td->_fpds);
+ printf("\t_holdrand = %u \t (rand() seed value)\n", td->_holdrand);
+ printf("\t_token = %p\t (ptr to strtok() token)\n", td->_token);
+ printf("\t_errmsg = %p\t (ptr to strerror()/_strerror() buff)\n",
+ td->_errmsg);
+ printf("\t_namebuf = %p\t (ptr to tmpfile() buffer)\n",
+ td->_namebuf);
+ printf("\t_asctimebuf = %p\t (ptr to asctime() buffer)\n",
+ td->_asctimebuf);
+ printf("\t_gmtimebuf = %p\t (ptr to gmtime() structure)\n",
+ td->_gmtimebuf);
+ printf("\t_initaddr = %p\t (initial user thread addr)\n",
+ td->_initaddr);
+ printf("\t_initarg = %p\t (initial user thread arg)\n",
+ td->_initarg);
+ printf("\t_initstksz = %u \t (initial stack size)\n",
+ td->_initstksz);
+ putchar((int)'\n');
+
+}
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+void _CALLTYPE1 _print_tiddata(unsigned long);
+void _CALLTYPE1 _print_tiddata1(_ptiddata);
+
+/***
+*void _print_tiddata(unsigned long) - Display data for a thread
+*
+*Purpose:
+* This routine displays the per thread data for a specific, or all,
+* active threads in the _ptd[] table.
+*
+*Entry:
+* unsigned long = <n> = ID of the thread to display
+* = -1 = Display thread data for all threads
+*
+*Exit:
+* <void>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _print_tiddata (
+ unsigned long tid
+ )
+{
+ int i; /* loop index */
+ int threadcnt; /* number of active threads */
+
+ /*
+ * lock the _ptd[] table.
+ */
+ _mlock(_THREADDATA_LOCK);
+
+ /*
+ * see if caller want's all threads or just a specific one.
+ */
+ if (tid == (unsigned long) -1L) {
+ /*
+ * caller want's all threads!
+ */
+ for ( i = threadcnt = 0 ; i < 1024 ; i++ )
+ /*
+ * print out the fields of *_ptd[i] for each entry
+ * bound to an active thread (i.e., for each i st
+ * _ptd[i] non-NULL). also, count up the total number
+ * of active threads.
+ */
+ if ( _ptd[i] != NULL ) {
+ threadcnt++;
+ _print_tiddata1(_ptd[i]);
+ }
+
+ printf("\nTHERE ARE %d CURRENTLY ACTIVE THREADS!\n", threadcnt);
+ }
+ else {
+ /*
+ * caller just interested in a particular thread. search
+ * the _ptd[] table inline because a call to _getptd[] would
+ * have unpleasant side effects if tid is not (or no longer)
+ * valid.
+ */
+ for ( i = 0 ; (i < 1024) && ((_ptd[i] == NULL) ||
+ (_ptd[i] == (_ptiddata)1L) || (_ptd[i]->_tid != tid)) ;
+ i++ ) ;
+
+ if ( i < 1024 )
+ _print_tiddata1(_ptd[i]);
+ else
+ printf("\nTID INVALID OR THREAD HAS TERMINATED!\n");
+ }
+
+ /*
+ * unlock the _ptd[] table.
+ */
+ _munlock(_THREADDATA_LOCK);
+
+}
+
+
+/***
+* void _print_tiddata1(_ptiddata ptd) - print out _tiddata structure
+*
+*Purpose:
+* Given a pointer to a thread data structure, print out its contents
+*
+*Entry:
+* ptd = pointer to thread's data area
+*
+*Exit:
+* <void>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _print_tiddata1 (
+ _ptiddata ptd
+ )
+{
+ printf("\t_tid = %lu\n", ptd->_tid );
+ printf("\t_thandle = %lu\n", ptd->_thandle );
+ printf("\t_terrno = %d\n", ptd->_terrno);
+ printf("\t_tdoserrno = %d\n", ptd->_tdoserrno);
+ printf("\t_fpds = %#x\n", ptd->_fpds);
+ printf("\t_holdrand = %u\n", ptd->_holdrand);
+ printf("\t_token = %p\n", ptd->_token);
+ printf("\t_errmsg = %p\n", ptd->_errmsg);
+ printf("\t_namebuf = %p\n", ptd->_namebuf);
+ printf("\t_asctimebuf = %p\n", ptd->_asctimebuf);
+ printf("\t_gmtimebuf = %p\n", ptd->_gmtimebuf);
+ printf("\t_initaddr = %p\n", ptd->_initaddr);
+ printf("\t_initarg = %p\n", ptd->_initarg);
+ printf("\t_pxcptacttab = %p\n", ptd->_pxcptacttab);
+ printf("\t_tpxcptinfoptrs = %p\n", ptd->_tpxcptinfoptrs);
+ printf("\t_tfpecode = %p\n\n", ptd->_tfpecode);
+
+}
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
diff --git a/private/crt32/startup/tidtable.c b/private/crt32/startup/tidtable.c
new file mode 100644
index 000000000..077f42334
--- /dev/null
+++ b/private/crt32/startup/tidtable.c
@@ -0,0 +1,324 @@
+#ifdef MTHREAD
+
+
+/***
+*tidtable.c - Access thread data table
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains the following routines for multi-thread
+* data support:
+*
+* _mtinit = Initialize the mthread data
+* _getptd = get the pointer to the per-thread data structure for
+* the current thread
+* _freeptd = free up a per-thread data structure and its
+* subordinate structures
+* __threadid = return thread ID for the current thread
+* __threadhandle = return pseudo-handle for the current thread
+*
+*Revision History:
+* 05-04-90 JCR Translated from ASM to C for portable 32-bit OS/2
+* 06-04-90 GJF Changed error message interface.
+* 07-02-90 GJF Changed __threadid() for DCR 1024/2012.
+* 08-08-90 GJF Removed 32 from API names.
+* 10-08-90 GJF New-style function declarators.
+* 10-09-90 GJF Thread ids are of type unsigned long! Also, fixed a
+* bug in __threadid().
+* 10-22-90 GJF Another bug in __threadid().
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 05-31-91 GJF Win32 version [_WIN32_].
+* 07-18-91 GJF Fixed many silly errors [_WIN32_].
+* 09-29-91 GJF Conditionally added _getptd_lk/_getptd1_lk so that
+* DEBUG version of mlock doesn't infinitely recurse
+* the first time _THREADDATA_LOCK is asserted [_WIN32_].
+* 01-30-92 GJF Must init. _pxcptacttab field to _XcptActTab.
+* 02-25-92 GJF Initialize _holdrand field to 1.
+* 02-13-93 GJF Revised to use TLS API. Also, purged Cruiser support.
+* 03-26-93 GJF Initialize ptd->_holdrand to 1L (see thread.c).
+* 04-16-93 SKS Add _mtterm to do multi-thread termination
+* Set freed __tlsindex to -1 again to prevent mis-use
+* 12-13-93 SKS Add _freeptd(), which frees up the per-thread data
+* maintained by the C run-time library.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <memory.h>
+#include <msdos.h>
+#include <rterr.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+unsigned long __tlsindex = 0xffffffff;
+
+/*** TEMP ****/
+/*** MOVE TO OS2DLL.H??? ***/
+extern near * _CRTVAR1 end; /* Link symbol for end of BSS */
+/*** TEMP ****/
+
+
+/****
+*_mtinit() - Init multi-thread data bases
+*
+*Purpose:
+* (1) Call _mtinitlocks to create/open all lock semaphores.
+* (2) Allocate a TLS index to hold pointers to per-thread data
+* structure.
+*
+* NOTES:
+* (1) Only to be called ONCE at startup
+* (2) Must be called BEFORE any mthread requests are made
+*
+*Entry:
+* <NONE>
+*Exit:
+* returns TRUE on success
+* returns FALSE on failure
+* user code should call _amsg_exit if failure is returned
+*
+*Uses:
+* <any registers may be modified at init time>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mtinit (
+ void
+ )
+{
+
+ _ptiddata ptd;
+
+ /*
+ * Initialize the mthread lock data base
+ */
+
+ _mtinitlocks();
+
+ /*
+ * Allocate a TLS index to maintain pointers to per-thread data
+ */
+ if ( (__tlsindex = TlsAlloc()) == 0xffffffff )
+ return FALSE; /* fail to load DLL */
+
+ /*
+ * Create a per-thread data structure for this (i.e., the startup)
+ * thread.
+ */
+ if ( ((ptd = calloc(1, sizeof(struct _tiddata))) == NULL) ||
+ !TlsSetValue(__tlsindex, (LPVOID)ptd) )
+ return FALSE; /* fail to load DLL */
+
+ ptd->_tid = GetCurrentThreadId();
+ ptd->_thandle = (unsigned long)(-1L);
+ ptd->_pxcptacttab = (void *)_XcptActTab;
+ ptd->_holdrand = 1L;
+
+ return TRUE;
+}
+
+
+/****
+*_mtterm() - Clean-up multi-thread data bases
+*
+*Purpose:
+* (1) Call _mtdeletelocks to free up all lock semaphores.
+* (2) Free up the TLS index used to hold pointers to
+* per-thread data structure.
+*
+* NOTES:
+* (1) Only to be called ONCE at termination
+* (2) Must be called AFTER all mthread requests are made
+*
+*Entry:
+* <NONE>
+*Exit:
+* returns
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _mtterm (
+ void
+ )
+{
+ /*
+ * Clean up the mthread lock data base
+ */
+
+ _mtdeletelocks();
+
+ /*
+ * Free up the TLS index
+ *
+ * (Also set the variable __tlsindex back to the unused state = -1L.)
+ */
+
+ if ( __tlsindex != 0xffffffff )
+ {
+ TlsFree(__tlsindex);
+ __tlsindex = 0xffffffff;
+ }
+}
+
+
+
+/***
+*_ptiddata _getptd(void) - get per-thread data structure for the current thread
+*
+*Purpose:
+*
+*Entry:
+* unsigned long tid
+*
+*Exit:
+* success = pointer to _tiddata structure for the thread
+* failure = fatal runtime exit
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+_ptiddata _CRTAPI1 _getptd (
+ void
+ )
+{
+ _ptiddata ptd;
+
+ if ( (ptd = TlsGetValue(__tlsindex)) == NULL ) {
+ /*
+ * no per-thread data structure for this thread. try to create
+ * one.
+ */
+ if ( ((ptd = calloc(1, sizeof(struct _tiddata))) != NULL) &&
+ TlsSetValue(__tlsindex, (LPVOID)ptd) ) {
+ ptd->_tid = GetCurrentThreadId();
+ ptd->_thandle = (unsigned long)(-1L);
+ ptd->_holdrand = 1L;
+ ptd->_pxcptacttab = (void *)_XcptActTab;
+ }
+ else
+ _amsg_exit(_RT_THREAD); /* write message and die */
+ }
+
+ return(ptd);
+}
+
+
+/***
+*void _freeptd(_ptiddata) - free up a per-thread data structure
+*
+*Purpose:
+* Called from _endthread and from a DLL thread detach handler,
+* this routine frees up the per-thread buffer associated with a
+* thread that is going away. The tiddata structure itself is
+* freed, but not until its subordinate buffers are freed.
+*
+*Entry:
+* pointer to a per-thread data block (malloc-ed memory)
+* If NULL, the pointer for the current thread is fetched.
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _freeptd (
+ _ptiddata ptd
+ )
+{
+ /*
+ * Do nothing unless per-thread data has been allocated for this module!
+ */
+
+ if ( __tlsindex != 0xFFFFFFFF )
+ {
+ /*
+ * if parameter "ptd" is NULL, get the per-thread data pointer
+ * Must NOT call _getptd because it will allocate one if none exists!
+ */
+
+ if ( ! ptd )
+ ptd = TlsGetValue(__tlsindex );
+
+ /*
+ * Free up the _tiddata structure & its malloc-ed buffers.
+ */
+
+ if ( ptd )
+ {
+ if(ptd->_errmsg)
+ free((void *)ptd->_errmsg);
+
+ if(ptd->_namebuf0)
+ free((void *)ptd->_namebuf0);
+
+ if(ptd->_namebuf1)
+ free((void *)ptd->_namebuf1);
+
+ if(ptd->_asctimebuf)
+ free((void *)ptd->_asctimebuf);
+
+ if(ptd->_gmtimebuf)
+ free((void *)ptd->_gmtimebuf);
+
+ if(ptd->_cvtbuf)
+ free((void *)ptd->_cvtbuf);
+
+ free((void *)ptd);
+ }
+
+ /*
+ * Zero out the one pointer to the per-thread data block
+ */
+
+ TlsSetValue(__tlsindex, (LPVOID)0);
+ }
+}
+
+
+/***
+*__threadid() - Returns current thread ID
+*__threadhandle() - Returns "pseudo-handle" for current thread
+*
+*Purpose:
+* The two function are simply do-nothing wrappers for the corresponding
+* Win32 APIs (GetCurrentThreadId and GetCurrentThread, respectively).
+*
+*Entry:
+* void
+*
+*Exit:
+* thread ID value
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned long _CRTAPI1 __threadid (
+ void
+ )
+{
+ return( GetCurrentThreadId() );
+}
+
+unsigned long _CRTAPI1 __threadhandle(
+ void
+ )
+{
+ return( (unsigned long)GetCurrentThread() );
+}
+
+
+#endif
diff --git a/private/crt32/startup/tlssup.c b/private/crt32/startup/tlssup.c
new file mode 100644
index 000000000..783ef0d3a
--- /dev/null
+++ b/private/crt32/startup/tlssup.c
@@ -0,0 +1,52 @@
+#ifdef _MSC_VER
+
+
+/* tlssup.c - Thread Local Storage runtime support module */
+
+#include <nt.h>
+
+/* Thread Local Storage index for this .EXE or .DLL */
+
+ULONG _tls_index = 0;
+
+/* Special symbols to mark start and end of Thread Local Storage area.
+ * By convention, we initialize each with a pointer to it's own address.
+ */
+
+#pragma data_seg(".tls")
+
+PVOID _tls_start = &_tls_start;
+
+#pragma data_seg(".tls$ZZZ")
+
+PVOID _tls_end = &_tls_end;
+
+/* Start and end sections for Threadl Local Storage CallBack Array.
+ * Actual array is constructed using .CRT$XLA, .CRT$XLC, .CRT$XLL,
+ * .CRT$XLU, .CRT$XLZ similar to the way global
+ * static initializers are done for C++.
+ */
+
+#pragma data_seg(".CRT$XLA")
+
+PIMAGE_TLS_CALLBACK __xl_a = 0;
+
+#pragma data_seg(".CRT$XLZ")
+
+PIMAGE_TLS_CALLBACK __xl_z = 0;
+
+
+#pragma data_seg(".rdata$T")
+
+IMAGE_TLS_DIRECTORY _tls_used =
+{
+ (ULONG) &_tls_start, // start of tls data
+ (ULONG) &_tls_end, // end of tls data
+ &_tls_index, // address of tls_index
+ &__xl_a, // pointer to call back array
+ (ULONG) 0, // size of tls zero fill
+ (ULONG) 0 // characteristics
+};
+
+
+#endif /* _MSC_VER */
diff --git a/private/crt32/startup/wild.c b/private/crt32/startup/wild.c
new file mode 100644
index 000000000..a13c62d4e
--- /dev/null
+++ b/private/crt32/startup/wild.c
@@ -0,0 +1,341 @@
+/***
+*wild.c - wildcard expander
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* expands wildcards in argv
+*
+* handles '*' (none or more of any char) and '?' (exactly one char)
+*
+*Revision History:
+* 05-21-84 RN initial version
+* 06-07-85 TDC since dos accepts forward slash, added
+* code to accept forward slash in a manner consistent
+* with reverse slash.
+* 09-20-86 SKS Modified for OS/2
+* All argument strings to this function have a
+* leading flag character. If the flag is a quote,
+* that argument string was quoted on the command
+* line and should have not wildcard expansion. In all
+* cases the leading flag character is removed from
+* the string.
+* 11-11-86 JMB Added Kanji support under KANJI switch.
+* 09-21-88 WAJ initial 386 version
+* 04-09-90 GJF Added #include <cruntime.h> and removed #include
+* <register.h>. Made calling types explicit (_CALLTYPE1
+* or _CALLTYPE4). Also, fixed the copyright.
+* 04-10-90 GJF Added #include <internal.h> and fixed compiler warnings
+* (-W3).
+* 07-03-90 SBM Compiles cleanly with -W3 under KANJI, removed
+* redundant includes, removed #include <internal.h>
+* to keep wild.c free of private stuff, should we
+* decide to release it
+* 09-07-90 SBM put #include <internal.h> back in, reason for
+* removing it discovered to be horribly bogus
+* 10-08-90 GJF New-style function declarators.
+* 01-18-91 GJF ANSI naming.
+* 06-09-93 KRS Update _MBCS support.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <msdos.h>
+#include <internal.h>
+
+#ifdef _MBCS
+#include <mbdata.h>
+#include <mbstring.h>
+#define STRPBRK _mbspbrk
+#define STRCMP _mbscmp
+#define STRICMP _mbsicmp
+#else
+#define STRPBRK strpbrk
+#define STRCMP strcmp
+#define STRICMP _stricmp
+#endif
+
+/*
+** these are the data structures
+**
+** __argv
+** ------- ------
+** | |---->| |---->"arg0"
+** ------- ------
+** | |---->"arg1"
+** ------
+** ....
+** ------
+** | |---->"argn"
+** ------
+** |NULL|
+** ------
+** argend
+** -------
+** ------- | |
+** | | __argc -------
+** ------- |
+** |
+** arghead V
+** ------ --------- ----------
+** | |---->| | |----> .... ---->| |NULL|
+** ------ --------- ----------
+** | |
+** V V
+** "narg0" "nargn"
+*/
+
+#define SLASHCHAR '\\'
+#define FWDSLASHCHAR '/'
+#define SLASH "\\"
+#define FWDSLASH "/"
+#define STAR "*.*"
+
+#define WILDSTRING "*?"
+
+
+extern int __argc;
+extern char **__argv;
+
+struct argnode {
+ char *argptr;
+ struct argnode *nextnode;
+};
+
+static struct argnode *arghead;
+static struct argnode *argend;
+
+static int _CALLTYPE4 match(char *, char *);
+static int _CALLTYPE4 add(char *);
+static void _CALLTYPE4 sort(struct argnode *);
+
+/***
+*int _cwild() - wildcard expander
+*
+*Purpose:
+* expands wildcard in file specs in argv
+*
+* handles '*' (none or more of any char), '?' (exactly one char), and
+* '[string]' (chars which match string chars or between n1 and n2
+* if 'n1-n2' in string inclusive)
+*
+*Entry:
+*
+*Exit:
+* returns 0 if successful, -1 if any malloc() calls fail
+* if problems with malloc, the old argc and argv are not touched
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _cwild (
+ void
+ )
+{
+ REG1 char **argv = __argv;
+ REG2 struct argnode *nodeptr;
+ REG3 int argc;
+ REG4 char **tmp;
+ char *wchar;
+
+ arghead = argend = NULL;
+
+ for (argv = __argv; *argv; argv++) /* for each arg... */
+ if ( *(*argv)++ == '"' )
+ /* strip leading quote from quoted arg */
+ {
+ if (add(*argv))
+ return(-1);
+ }
+ else if (wchar = STRPBRK( *argv, WILDSTRING )) {
+ /* attempt to expand arg with wildcard */
+ if (match( *argv, wchar ))
+ return(-1);
+ }
+ else if (add( *argv )) /* normal arg, just add */
+ return(-1);
+
+ /* count the args */
+ for (argc = 0, nodeptr = arghead; nodeptr;
+ nodeptr = nodeptr->nextnode, argc++)
+ ;
+
+ /* try to get new arg vector */
+ if (!(tmp = (char **)malloc(sizeof(char *)*(argc+1))))
+ return(-1);
+
+ /* the new arg vector... */
+ __argv = tmp;
+
+ /* the new arg count... */
+ __argc = argc;
+
+ /* install the new args */
+ for (nodeptr = arghead; nodeptr; nodeptr = nodeptr->nextnode)
+ *tmp++ = nodeptr->argptr;
+
+ /* the terminal NULL */
+ *tmp = NULL;
+
+ /* free up local data */
+ for (nodeptr = arghead; nodeptr; nodeptr = arghead) {
+ arghead = arghead->nextnode;
+ free(nodeptr);
+ }
+
+ /* return success */
+ return(0);
+}
+
+
+/***
+*match(arg, ptr) - [STATIC]
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 match (
+ REG4 char *arg,
+ REG1 char *ptr
+ )
+{
+ REG2 char *new;
+ REG3 int length = 0;
+ char *all;
+ REG5 struct argnode *first;
+ REG6 int gotone = 0;
+
+ while (ptr != arg && *ptr != SLASHCHAR && *ptr != FWDSLASHCHAR
+ && *ptr != ':') {
+ /* find first slash or ':' before wildcard */
+#ifdef _MBCS
+ if (--ptr > arg)
+ ptr = _mbsdec(arg,ptr+1);
+#else
+ ptr--;
+#endif
+ }
+
+ if (*ptr == ':' && ptr != arg+1) /* weird name, just add it as is */
+ return(add(arg));
+
+ if (*ptr == SLASHCHAR || *ptr == FWDSLASHCHAR
+ || *ptr == ':') /* pathname */
+ length = ptr - arg + 1; /* length of dir prefix */
+
+ if (new = _find(arg)) { /* get the first file name */
+ first = argend;
+
+ do { /* got a file name */
+ if (strcmp(new, ".") && strcmp(new, "..")) {
+ if (*ptr != SLASHCHAR && *ptr != ':'
+ && *ptr != FWDSLASHCHAR ) {
+ /* current directory; don't need path */
+ if (!(arg = _strdup(new)) || add(arg))
+ return(-1);
+ }
+ else /* add full pathname */
+ if (!(all=malloc(length+strlen(new)+1))
+ || add(strcpy(strncpy(all,arg,length)+length,new)
+ - length))
+ return(-1);
+
+ gotone++;
+ }
+
+ }
+ while (new = _find(NULL)); /* get following files */
+
+ if (gotone) {
+ sort(first ? first->nextnode : arghead);
+ return(0);
+ }
+ }
+
+ return(add(arg)); /* no match */
+}
+
+/***
+*add(arg) - [STATIC]
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 add (
+ char *arg
+ )
+{
+ REG1 struct argnode *nodeptr;
+
+ if (!(nodeptr = (struct argnode *)malloc(sizeof(struct argnode))))
+ return(-1);
+
+ nodeptr->argptr = arg;
+ nodeptr->nextnode = NULL;
+
+ if (arghead)
+ argend->nextnode = nodeptr;
+ else
+ arghead = nodeptr;
+
+ argend = nodeptr;
+ return(0);
+}
+
+
+/***
+*sort(first) - [STATIC]
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CALLTYPE4 sort (
+ REG2 struct argnode *first
+ )
+{
+ REG1 struct argnode *nodeptr;
+ REG3 char *temp;
+
+ if (first) /* something to sort */
+ while (nodeptr = first->nextnode) {
+ do {
+#ifdef _POSIX
+ if (STRCMP(nodeptr->argptr, first->argptr) < 0) {
+#else
+ if (STRICMP(nodeptr->argptr, first->argptr) < 0) {
+#endif /* _POSIX_ */
+ temp = first->argptr;
+ first->argptr = nodeptr->argptr;
+ nodeptr->argptr = temp;
+ }
+ }
+ while (nodeptr = nodeptr->nextnode);
+
+ first = first->nextnode;
+ }
+}
diff --git a/private/crt32/startup/wincrt0.c b/private/crt32/startup/wincrt0.c
new file mode 100644
index 000000000..3286b94db
--- /dev/null
+++ b/private/crt32/startup/wincrt0.c
@@ -0,0 +1,6 @@
+#ifndef _POSIX_
+
+#define _WINMAIN_
+#include "crt0.c"
+
+#endif /* ndef _POSIX_ */
diff --git a/private/crt32/stdio/_filbuf.c b/private/crt32/stdio/_filbuf.c
new file mode 100644
index 000000000..152e4b960
--- /dev/null
+++ b/private/crt32/stdio/_filbuf.c
@@ -0,0 +1,195 @@
+/***
+*_filbuf.c - fill buffer and get character
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _filbuf() - fill buffer and read first character, allocate
+* buffer if there is none. Used from getc().
+* defines _filwbuf() - fill buffer and read first wide character, allocate
+* buffer if there is none. Used from getwc().
+*
+*Revision History:
+* 09-01-83 RN initial version
+* 06-26-85 TC added code to handle variable length buffers
+* 04-16-87 JCR added _IOUNGETC support
+* 08-04-87 JCR added _getbuff routine
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 11-06-87 JCR Multi-thread support; also, split _getbuf() off
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-11-88 JCR Merged mthread version into normal code
+* 01-13-88 SKS Changed bogus "_fileno_lk" to "fileno"
+* 03-04-88 JCR Read() return value must be considered unsigned, not
+* signed
+* 06-06-88 JCR Optimized _iob2 references
+* 06-13-88 JCR Use near pointer to reference _iob[] entries
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 06-20-89 PHG Re-activate C version, propogated fixes
+* 08-28-89 JCR Removed _NEAR_ for 386
+* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and
+* alignment.
+* 03-16-90 GJF Replaced cdecl _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>. Also,
+* removed some leftover 16-bit support.
+* 03-27-90 GJF Added #include <io.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+* 01-22-91 GJF ANSI naming.
+* 03-27-92 DJM POSIX support.
+* 08-26-92 GJF Include unistd.h for POSIX build.
+* 04-26-93 CFW Wide char enable.
+* 05-06-93 CFW Optimize wide char conversion.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <io.h>
+#include <assert.h>
+#include <malloc.h>
+#include <internal.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#include <errno.h>
+#else
+#include <msdos.h>
+#endif
+#ifdef MTHREAD
+#include <os2dll.h>
+#endif
+#include <wchar.h>
+#include <tchar.h>
+
+#ifndef _UNICODE
+
+/***
+*int _filbuf(stream) - fill buffer and get first character
+*
+*Purpose:
+* get a buffer if the file doesn't have one, read into it, return first
+* char. try to get a buffer, if a user buffer is not assigned. called
+* only from getc; intended for use only within library. assume no input
+* stream is to remain unbuffered when memory is available unless it is
+* marked _IONBF. at worst, give it a single char buffer. the need for a
+* buffer, no matter how small, becomes evident when we consider the
+* ungetc's necessary in scanf
+*
+* [NOTE: Multi-thread - _filbuf() assumes that the caller has aquired
+* the stream lock, if needed.]
+*
+*Entry:
+* FILE *stream - stream to read from
+*
+*Exit:
+* returns first character from buffer (next character to be read)
+* returns EOF if the FILE is actually a string, or not open for reading,
+* or if open for writing or if no more chars to read.
+* all fields in FILE structure may be changed except _file.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _filbuf (
+ FILE *str
+ )
+
+#else /* _UNICODE */
+
+/***
+*int _filwbuf(stream) - fill buffer and get first wide character
+*
+*Purpose:
+* get a buffer if the file doesn't have one, read into it, return first
+* char. try to get a buffer, if a user buffer is not assigned. called
+* only from getc; intended for use only within library. assume no input
+* stream is to remain unbuffered when memory is available unless it is
+* marked _IONBF. at worst, give it a single char buffer. the need for a
+* buffer, no matter how small, becomes evident when we consider the
+* ungetc's necessary in scanf
+*
+* [NOTE: Multi-thread - _filwbuf() assumes that the caller has aquired
+* the stream lock, if needed.]
+*
+*Entry:
+* FILE *stream - stream to read from
+*
+*Exit:
+* returns first wide character from buffer (next character to be read)
+* returns WEOF if the FILE is actually a string, or not open for reading,
+* or if open for writing or if no more chars to read.
+* all fields in FILE structure may be changed except _file.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _filwbuf (
+ FILE *str
+ )
+
+#endif /* _UNICODE */
+
+{
+#if defined _NTSUBSET_ && !defined _POSIX_
+ return(_TEOF);
+#else
+ REG1 FILE *stream;
+
+ assert(str != NULL);
+
+ /* Init pointer to _iob2 entry. */
+ stream = str;
+
+ if (!inuse(stream) || stream->_flag & _IOSTRG)
+ return(_TEOF);
+
+ if (stream->_flag & _IOWRT) {
+#ifdef _POSIX_
+ errno = EBADF;
+#endif
+ stream->_flag |= _IOERR;
+ return(_TEOF);
+ }
+
+ stream->_flag |= _IOREAD;
+
+ /* Get a buffer, if necessary. */
+
+ if (!anybuf(stream))
+ _getbuf(stream);
+ else
+ stream->_ptr = stream->_base;
+
+#ifdef _POSIX_
+ stream->_cnt = read(fileno(stream), stream->_base, stream->_bufsiz);
+#else
+ stream->_cnt = _read(_fileno(stream), stream->_base, stream->_bufsiz);
+#endif
+
+#ifndef _UNICODE
+ if ((stream->_cnt == 0) || (stream->_cnt == -1)) {
+#else /* _UNICODE */
+ if ((stream->_cnt == 0) || (stream->_cnt == 1) || stream->_cnt == -1) {
+#endif /* _UNICODE */
+ stream->_flag |= stream->_cnt ? _IOERR : _IOEOF;
+ stream->_cnt = 0;
+ return(_TEOF);
+ }
+
+#ifndef _POSIX_
+ if ( !(stream->_flag & (_IOWRT|_IORW)) &&
+ ((_osfile[_fileno(stream)] & (FTEXT|FEOFLAG)) == (FTEXT|FEOFLAG)) )
+ stream->_flag |= _IOCTRLZ;
+#endif
+
+#ifndef _UNICODE
+ stream->_cnt--;
+ return(0xff & *stream->_ptr++);
+#else /* _UNICODE */
+ stream->_cnt -= sizeof(wchar_t);
+ return (0xffff & *((wchar_t *)(stream->_ptr))++);
+#endif /* _UNICODE */
+#endif /* _NTSUBSET */
+}
diff --git a/private/crt32/stdio/_file.c b/private/crt32/stdio/_file.c
new file mode 100644
index 000000000..a4deae84b
--- /dev/null
+++ b/private/crt32/stdio/_file.c
@@ -0,0 +1,86 @@
+/***
+*_file.c - perprocess file and buffer data declarations
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* file and buffer data declarations
+*
+*Revision History:
+* 04-18-84 RN initial version
+* ??-??-?? TC added field _bifsiz to iob2 to allow variable
+* length buffers
+* 10-02-86 SKS _NFILE_ is now different for real-mode and prot-mode
+* _NFILE_ must be defined by compiler -D directory
+* 05-27-87 JCR Protected mode now uses only 3 pre-defined file handles,
+* not 5. Added PM (prot mode) to conditionalize handles.
+* 06-24-87 SKS Make "_bufin[]" and "_bufout[]" near for Compact/Large
+* models (MS real-mode version only)
+* 07-01-87 PHG Changed PM switch to PROTMODE
+* 11-05-87 JCR Added _buferr and modified stderr entry
+* 11-09-87 SKS Removed IBMC20 switch, Changed PROTMODE to OS2
+* 01-04-88 JCR Moved _NFILE_ definition from command line to file
+* 01-11-88 JCR Merged Mthread version into standard version
+* 01-21-88 JCR Removed reference to internal.h and added _NEAR_
+* (thus, internal.h doesn't get released in startup
+* sources even though _file.c does).
+* 06-28-88 JCR Remove static stdout/stderr buffers
+* 07-06-88 JCR Corrected _bufin declaration so it's always in BSS
+* 08-24-88 GJF Added check that OS2 is defined whenever M_I386 is.
+* 06-08-89 GJF Propagated SKS's fix of 02-08-89, and fixed copyright.
+* 07-25-89 GJF Cleanup (deleted DOS specific and OS/2 286 specific
+* stuff). Now specific to the 386.
+* 01-09-90 GJF _iob[], _iob2[] merge. Also, fixed copyright
+* 03-16-90 GJF Added #include <cruntime.h> and removed some (now)
+* useless preprocessor stuff.
+* 03-26-90 GJF Replaced _cdecl with _VARTYPE1.
+* 02-14-92 GJF Replaced _NFILE_ with _NSTREAM_ for Win32, with _NFILE
+* for non-Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+
+/*
+ * Buffer for stdin.
+ */
+
+char _bufin[BUFSIZ];
+
+
+/*
+ * FILE descriptors; preset for stdin/out/err (note that the __tmpnum field
+ * is not initialized)
+ */
+#ifdef _WIN32_
+FILE _VARTYPE1 _iob[_NSTREAM_] = {
+#else
+FILE _VARTYPE1 _iob[_NFILE] = {
+#endif
+ /* _ptr, _cnt, _base, _flag, _file, _charbuf, _bufsiz */
+
+ /* stdin (_iob[0]) */
+
+ { _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, BUFSIZ },
+
+ /* stdout (_iob[1]) */
+
+ { NULL, 0, NULL, _IOWRT, 1, 0, 0 },
+
+ /* stderr (_iob[3]) */
+
+ { NULL, 0, NULL, _IOWRT, 2, 0, 0 },
+
+};
+
+
+/*
+ * pointer to end of descriptors
+ */
+#ifdef _WIN32_
+FILE * _lastiob = &_iob[_NSTREAM_ - 1];
+#else
+FILE * _lastiob = &_iob[_NFILE - 1];
+#endif
diff --git a/private/crt32/stdio/_filwbuf.c b/private/crt32/stdio/_filwbuf.c
new file mode 100644
index 000000000..120676eb3
--- /dev/null
+++ b/private/crt32/stdio/_filwbuf.c
@@ -0,0 +1,25 @@
+/***
+*_filwbuf.c - fill buffer and get wide character
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _filwbuf() - fill buffer and read first character, allocate
+* buffer if there is none. Used from getwc().
+*
+*Revision History:
+* 04-27-93 CFW Module Created.
+*
+*******************************************************************************/
+
+
+#ifndef _UNICODE /* CRT flag */
+#define _UNICODE 1
+#endif
+
+#ifndef UNICODE /* NT flag */
+#define UNICODE 1
+#endif
+
+#define WPRFLAG 1
+#include "_filbuf.c"
diff --git a/private/crt32/stdio/_flsbuf.c b/private/crt32/stdio/_flsbuf.c
new file mode 100644
index 000000000..564f58625
--- /dev/null
+++ b/private/crt32/stdio/_flsbuf.c
@@ -0,0 +1,275 @@
+/***
+*_flsbuf.c - flush buffer and output character.
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _flsbuf() - flush a file buffer and output a character.
+* defines _flswbuf() - flush a file buffer and output a wide character.
+* If no buffer, make one.
+*
+*Revision History:
+* 09-01-83 RN initial version
+* 06-26-85 TC added code to handle variable length buffers
+* 06-08-87 JCR When buffer is allocated or when first write to buffer
+* occurs, if stream is in append mode, then position file
+* pointer to end.
+* 07-20-87 SKS Change first parameter "ch" from (char) to (int)
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 11-05-87 JCR Re-wrote for simplicity and for new stderr/stdout
+* handling
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-11-88 JCR Merged mthread version into normal code
+* 01-13-88 SKS Changed bogus "_fileno_lk" to "fileno"
+* 06-06-88 JCR Optimized _iob2 references
+* 06-13-88 JCR Use near pointer to reference _iob[] entries
+* 06-28-88 JCR Support for dynamic buffer allocation for stdout/stderr
+* 07-28-88 GJF Set stream->_cnt to 0 if _IOREAD is set.
+* 08-25-88 GJF Added checked that OS2 is defined whenever M_I386 is.
+* 06-20-89 PHG Removed FP_OFF macro call.
+* 08-28-89 JCR Removed _NEAR_ for 386
+* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and
+* indents.
+* 03-16-90 GJF Replaced cdecl _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>. Also,
+* removed some leftover 16-bit support.
+* 03-27-90 GJF Added #include <io.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 08-07-90 SBM Restored descriptive text in assertion
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-03-90 GJF New-style function declarator.
+* 01-22-91 GJF ANSI naming.
+* 03-25-91 DJM POSIX support
+* 08-26-92 GJF Include unistd.h for POSIX build.
+* 04-26-93 CFW Wide char enable.
+* 05-06-93 CFW Optimize wide char conversion.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <io.h>
+#include <assert.h>
+#include <malloc.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#include <errno.h>
+#else
+#include <msdos.h>
+#endif
+#include <internal.h>
+#ifdef MTHREAD
+#include <os2dll.h>
+#endif
+#include <wchar.h>
+#include <tchar.h>
+
+#ifndef _UNICODE
+
+/***
+*int _flsbuf(ch, stream) - flush buffer and output character.
+*
+*Purpose:
+* flush a buffer if this stream has one. if not, try to get one. put the
+* next output char (ch) into the buffer (or output it immediately if this
+* stream can't have a buffer). called only from putc. intended for use
+* only within library.
+*
+* [NOTE: Multi-thread - It is assumed that the caller has aquired
+* the stream lock.]
+*
+*Entry:
+* FILE *stream - stream to flish and write on
+* int ch - character to output.
+*
+*Exit:
+* returns -1 if FILE is actually a string, or if can't write ch to
+* unbuffered file, or if we flush a buffer but the number of chars
+* written doesn't agree with buffer size. Otherwise returns ch.
+* all fields in FILE struct can be affected except _file.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _flsbuf (
+ int ch,
+ FILE *str
+ )
+
+#else /* _UNICODE */
+
+/***
+*int _flswbuf(ch, stream) - flush buffer and output wide character.
+*
+*Purpose:
+* flush a buffer if this stream has one. if not, try to get one. put the
+* next output wide char (ch) into the buffer (or output it immediately if this
+* stream can't have a buffer). called only from putwc. intended for use
+* only within library.
+*
+* [NOTE: Multi-thread - It is assumed that the caller has aquired
+* the stream lock.]
+*
+*Entry:
+* FILE *stream - stream to flish and write on
+* int ch - wide character to output.
+*
+*Exit:
+* returns -1 if FILE is actually a string, or if can't write ch to
+* unbuffered file, or if we flush a buffer but the number of wide chars
+* written doesn't agree with buffer size. Otherwise returns ch.
+* all fields in FILE struct can be affected except _file.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _flswbuf (
+ int ch,
+ FILE *str
+ )
+
+#endif /* _UNICODE */
+
+{
+#if defined _NTSUBSET_ && !defined _POSIX_
+ str->_flag |= _IOERR;
+ return(_TEOF);
+#else
+ REG1 FILE *stream;
+ REG2 int charcount;
+ REG3 int written;
+ int fh;
+
+ assert(str != NULL);
+
+ /* Init file handle and pointers */
+ stream = str;
+#ifdef _POSIX_
+ fh = fileno(stream);
+#else
+ fh = _fileno(stream);
+#endif
+
+ if (!(stream->_flag & (_IOWRT|_IORW)) || (stream->_flag & _IOSTRG)) {
+#ifdef _POSIX_
+ errno = EBADF;
+#endif
+ stream->_flag |= _IOERR;
+ return(_TEOF);
+ }
+
+ /* Check that _IOREAD is not set or, if it is, then so is _IOEOF. Note
+ that _IOREAD and IOEOF both being set implies switching from read to
+ write at end-of-file, which is allowed by ANSI. Note that resetting
+ the _cnt and _ptr fields amounts to doing an fflush() on the stream
+ in this case. Note also that the _cnt field has to be reset to 0 for
+ the error path as well (i.e., _IOREAD set but _IOEOF not set) as
+ well as the non-error path. */
+
+ if (stream->_flag & _IOREAD) {
+ stream->_cnt = 0;
+ if (stream->_flag & _IOEOF) {
+ stream->_ptr = stream->_base;
+ stream->_flag &= ~_IOREAD;
+ }
+ else {
+ stream->_flag |= _IOERR;
+ return(_TEOF);
+ }
+ }
+
+ stream->_flag |= _IOWRT;
+ stream->_flag &= ~_IOEOF;
+ written = charcount = stream->_cnt = 0;
+
+ /* Get a buffer for this stream, if necessary. */
+ if (!anybuf(stream)) {
+
+ /* Do NOT get a buffer if (1) stream is stdout/stderr, and
+ (2) stream is NOT a tty.
+ [If stdout/stderr is a tty, we do NOT set up single char
+ buffering. This is so that later temporary buffering will
+ not be thwarted by the _IONBF bit being set (see
+ _stbuf/_ftbuf usage).]
+ */
+ if (!( ((stream==stdout) || (stream==stderr))
+#ifdef _POSIX_
+ && (isatty(fh)) ))
+#else
+ && (_isatty(fh)) ))
+#endif
+
+ _getbuf(stream);
+
+ } /* end !anybuf() */
+
+ /* If big buffer is assigned to stream... */
+ if (bigbuf(stream)) {
+
+ assert(("inconsistent IOB fields", stream->_ptr - stream->_base >= 0));
+
+ charcount = stream->_ptr - stream->_base;
+ stream->_ptr = stream->_base + sizeof(TCHAR);
+ stream->_cnt = stream->_bufsiz - sizeof(TCHAR);
+
+ if (charcount > 0)
+#ifdef _POSIX_
+ written = write(fh, stream->_base, charcount);
+#else
+ written = _write(fh, stream->_base, charcount);
+#endif
+ else
+#ifdef _POSIX_
+ if (stream->_flag & _IOAPPEND)
+ lseek(fh,0l,SEEK_END);
+#else
+ if (_osfile[fh] & FAPPEND)
+ _lseek(fh,0L,SEEK_END);
+#endif
+
+#ifndef _UNICODE
+ *stream->_base = (char)ch;
+#else /* _UNICODE */
+ *(wchar_t *)(stream->_base) = (wchar_t)(ch & 0xffff);
+#endif /* _UNICODE */
+ }
+
+ /* Perform single character output (either _IONBF or no buffering) */
+ else {
+ charcount = sizeof(TCHAR);
+#ifndef _UNICODE
+#ifdef _POSIX_
+ written = write(fh, &ch, charcount);
+#else
+ written = _write(fh, &ch, charcount);
+#endif
+#else /* _UNICODE */
+ {
+ char mbc[4];
+
+ *(wchar_t *)mbc = (wchar_t)(ch & 0xffff);
+#ifdef _POSIX_
+ written = write(fh, mbc, charcount);
+#else
+ written = _write(fh, mbc, charcount);
+#endif
+ }
+#endif /* _UNICODE */
+ }
+
+ /* See if the _write() was successful. */
+ if (written != charcount) {
+ stream->_flag |= _IOERR;
+ return(_TEOF);
+ }
+
+#ifndef _UNICODE
+ return(ch & 0xff);
+#else /* _UNICODE */
+ return(ch & 0xffff);
+#endif /* _UNICODE */
+#endif /* _NTSUBSET */
+}
diff --git a/private/crt32/stdio/_flswbuf.c b/private/crt32/stdio/_flswbuf.c
new file mode 100644
index 000000000..156da0487
--- /dev/null
+++ b/private/crt32/stdio/_flswbuf.c
@@ -0,0 +1,25 @@
+/***
+*_flswbuf.c - flush buffer and output wide character.
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _flswbuf() - flush a file buffer and output a wide character.
+* If no buffer, make one.
+*
+*Revision History:
+* 04-27-93 CFW Module Created.
+*
+*******************************************************************************/
+
+
+#ifndef _UNICODE /* CRT flag */
+#define _UNICODE 1
+#endif
+
+#ifndef UNICODE /* NT flag */
+#define UNICODE 1
+#endif
+
+#define WPRFLAG 1
+#include "_flsbuf.c"
diff --git a/private/crt32/stdio/_freebuf.c b/private/crt32/stdio/_freebuf.c
new file mode 100644
index 000000000..fc4f26c0f
--- /dev/null
+++ b/private/crt32/stdio/_freebuf.c
@@ -0,0 +1,72 @@
+/***
+*_freebuf.c - release a buffer from a stream
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _freebuf() - release a buffer from a stream
+*
+*Revision History:
+* 09-19-83 RN initial version
+* 02-15-90 GJF Fixed copyright, alignment.
+* 03-16-90 GJF Replaced cdecl _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+* 02-14-92 GJF Replaced _nfile with _nhandle for Win32.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#include <internal.h>
+#include <stdlib.h>
+
+/***
+*void _freebuf(stream) - release a buffer from a stream
+*
+*Purpose:
+* free a buffer if at all possible. free() the space if malloc'd by me.
+* forget about trying to free a user's buffer for him; it may be static
+* memory (not from malloc), so he has to take care of it. this function
+* is not intended for use outside the library.
+*
+#ifdef MTHREAD
+* Multi-thread notes:
+* _freebuf() does NOT get the stream lock; it is assumed that the
+* caller has already done this.
+#endif
+*
+*Entry:
+* FILE *stream - stream to free bufer on
+*
+*Exit:
+* Buffer may be freed.
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _freebuf (
+ REG1 FILE *stream
+ )
+{
+ assert(stream != NULL);
+#ifdef _WIN32_
+ assert( (unsigned)(stream->_file) < (unsigned)_nhandle );
+#else
+ assert(stream->_file >= 0);
+ assert(stream->_file < _nfile);
+#endif
+
+ if (inuse(stream) && mbuf(stream))
+ {
+ free(stream->_base);
+ stream->_flag &= ~_IOMYBUF;
+ stream->_base = stream->_ptr = NULL;
+ stream->_cnt = 0;
+ }
+}
diff --git a/private/crt32/stdio/_getbuf.c b/private/crt32/stdio/_getbuf.c
new file mode 100644
index 000000000..59ee055e2
--- /dev/null
+++ b/private/crt32/stdio/_getbuf.c
@@ -0,0 +1,102 @@
+/***
+*_getbuf.c - Get a stream buffer
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Allocate a buffer and init stream data bases.
+*
+*Revision History:
+* 11-06-87 JCR Initial version (split off from _filbuf.c)
+* 01-11-88 JCR Moved from mthread/dll only to main code
+* 06-06-88 JCR Optimized _iob2 references
+* 06-10-88 JCR Use near pointer to reference _iob[] entries
+* 07-27-88 GJF Added _cflush++ to force pre-terminator (necessary in
+* case stdout has been redirected to a file and acquires
+* a buffer here, and pre-terminator has not already been
+* forced).
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 08-28-89 JCR Removed _NEAR_ for 386
+* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and
+* indents.
+* 03-16-90 GJF Replaced near cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>. Also,
+* removed some leftover 16-bit support.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+* 04-27-93 CFW Change _IONBF size to 2 bytes to hold wide char.
+* 11-04-93 SRW Dont call malloc in _NTSUBSET_ version
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#include <malloc.h>
+#include <internal.h>
+
+/***
+*_getbuf() - Allocate a buffer and init stream data bases
+*
+*Purpose:
+* Allocates a buffer for a stream and inits the stream data bases.
+*
+* [NOTE 1: This routine assumes the caller has already checked to make
+* sure the stream needs a buffer.
+*
+* [NOTE 2: Multi-thread - Assumes caller has aquired stream lock, if
+* needed.]
+*
+*Entry:
+* FILE *stream = stream to allocate a buffer for
+*
+*Exit:
+* void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _getbuf (
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+
+ assert(str != NULL);
+
+#if !defined _NTSUBSET_ || defined _POSIX_
+ /* force library pre-termination procedure */
+ _cflush++;
+#endif // _NTSUBSET_ || _POSIX_
+
+ /* Init pointers */
+ stream = str;
+
+#if !defined _NTSUBSET_ || defined _POSIX_
+ /* Try to get a big buffer */
+
+ if (stream->_base = malloc(BUFSIZ)) {
+
+ /* Got a big buffer */
+ stream->_flag |= _IOMYBUF;
+ stream->_bufsiz = BUFSIZ;
+ }
+
+ else {
+#endif // _NTSUBSET_ || _POSIX_
+
+ /* Did NOT get a buffer - use single char buffering. */
+ stream->_flag |= _IONBF;
+ stream->_base = (char *)&(stream->_charbuf);
+ stream->_bufsiz = 2;
+#if !defined _NTSUBSET_ || defined _POSIX_
+ }
+#endif // _NTSUBSET_ || _POSIX_
+
+ stream->_ptr = stream->_base;
+ stream->_cnt = 0;
+
+ return;
+}
diff --git a/private/crt32/stdio/_open.c b/private/crt32/stdio/_open.c
new file mode 100644
index 000000000..0557bf6d0
--- /dev/null
+++ b/private/crt32/stdio/_open.c
@@ -0,0 +1,272 @@
+/***
+*_open.c - open a stream, with string mode
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _openfile() - opens a stream, with string arguments for mode
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 03-02-87 JCR made _openfile recognize "wb+" as equal to "w+b", etc.
+* got rid of intermediate _openfile flags (internal) and
+* now go straight from mode string to open system call
+* and system->_flags.
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 02-21-88 SKS Removed #ifdef IBMC20
+* 06-06-88 JCR Optimized _iob2 references
+* 06-10-88 JCR Use near pointer to reference _iob[] entries
+* 08-19-88 GJF Initial adaption for the 386.
+* 11-14-88 GJF Added shflag (file sharing flag) parameter, also some
+* cleanup (now specific to the 386).
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright.
+* 03-16-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-27-90 GJF Added const qualifier to types of filename and mode.
+* Added #include <io.h>.
+* 07-11-90 SBM Added support for 'c' and 'n' flags
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 03-11-92 GJF Replaced __tmpnum field with _tmpfname field for
+* Win32.
+* 03-25-92 DJM POSIX support.
+* 08-26-92 GJF Fixed POSIX support.
+* 05-24-93 PML Added support for 'D', 'R', 'S' and 'T' flags
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <file2.h>
+#include <io.h>
+#include <assert.h>
+#include <internal.h>
+
+#define CMASK 0644 /* rw-r--r-- */
+#define P_CMASK 0666 /* different for Posix */
+
+/***
+*FILE *_openfile(filename, mode, shflag, stream) - open a file with string
+* mode and file sharing flag.
+*
+*Purpose:
+* parse the string, looking for exactly one of {rwa}, at most one '+',
+* at most one of {tb}, at most one of {cn}, at most one of {SR}, at most
+* one 'T', and at most one 'D'. pass the result on as an int containing
+* flags of what was found. open a file with proper mode if permissions
+* allow. buffer not allocated until first i/o call is issued. intended
+* for use inside library only
+*
+*Entry:
+* char *filename - file to open
+* char *mode - mode to use (see above)
+* int shflag - file sharing flag
+* FILE *stream - stream to use for file
+*
+*Exit:
+* set stream's fields, and causes system file management by system calls
+* returns stream or NULL if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+FILE * _CRTAPI1 _openfile (
+ const char *filename,
+ REG3 const char *mode,
+#ifndef _POSIX_
+ int shflag,
+#endif
+ FILE *str
+ )
+{
+ REG2 int modeflag;
+#ifdef _POSIX_
+ int streamflag = 0;
+#else
+ int streamflag = _commode;
+ int commodeset = 0;
+ int scanset = 0;
+#endif
+ int whileflag;
+ int filedes;
+ REG1 FILE *stream;
+
+ assert(filename != NULL);
+ assert(mode != NULL);
+ assert(str != NULL);
+
+ /* Parse the user's specification string as set flags in
+ (1) modeflag - system call flags word
+ (2) streamflag - stream handle flags word. */
+
+ /* First mode character must be 'r', 'w', or 'a'. */
+
+ switch (*mode) {
+ case 'r':
+#ifdef _POSIX_
+ modeflag = O_RDONLY;
+#else
+ modeflag = _O_RDONLY;
+#endif
+ streamflag |= _IOREAD;
+ break;
+ case 'w':
+#ifdef _POSIX_
+ modeflag = O_WRONLY | O_CREAT | O_TRUNC;
+#else
+ modeflag = _O_WRONLY | _O_CREAT | _O_TRUNC;
+#endif
+ streamflag |= _IOWRT;
+ break;
+ case 'a':
+#ifdef _POSIX_
+ modeflag = O_WRONLY | O_CREAT | O_APPEND;
+ streamflag |= _IOWRT | _IOAPPEND;
+#else
+ modeflag = _O_WRONLY | _O_CREAT | _O_APPEND;
+ streamflag |= _IOWRT;
+#endif
+ break;
+ default:
+ return(NULL);
+ break;
+ }
+
+ /* There can be up to three more optional mode characters:
+ (1) A single '+' character,
+ (2) One of 't' and 'b' and
+ (3) One of 'c' and 'n'.
+ */
+
+ whileflag=1;
+
+ while(*++mode && whileflag)
+ switch(*mode) {
+
+ case '+':
+#ifdef _POSIX_
+ if (modeflag & O_RDWR)
+ whileflag=0;
+ else {
+ modeflag |= O_RDWR;
+ modeflag &= ~(O_RDONLY | O_WRONLY);
+#else
+ if (modeflag & _O_RDWR)
+ whileflag=0;
+ else {
+ modeflag |= _O_RDWR;
+ modeflag &= ~(_O_RDONLY | _O_WRONLY);
+#endif
+ streamflag |= _IORW;
+ streamflag &= ~(_IOREAD | _IOWRT);
+ }
+ break;
+
+ case 'b':
+#ifndef _POSIX_
+ if (modeflag & (_O_TEXT | _O_BINARY))
+ whileflag=0;
+ else
+ modeflag |= _O_BINARY;
+#endif
+ break;
+
+#ifndef _POSIX_
+ case 't':
+ if (modeflag & (_O_TEXT | _O_BINARY))
+ whileflag=0;
+ else
+ modeflag |= _O_TEXT;
+ break;
+
+ case 'c':
+ if (commodeset)
+ whileflag=0;
+ else {
+ commodeset = 1;
+ streamflag |= _IOCOMMIT;
+ }
+ break;
+
+ case 'n':
+ if (commodeset)
+ whileflag=0;
+ else {
+ commodeset = 1;
+ streamflag &= ~_IOCOMMIT;
+ }
+ break;
+
+ case 'S':
+ if (scanset)
+ whileflag=0;
+ else {
+ scanset = 1;
+ modeflag |= _O_SEQUENTIAL;
+ }
+ break;
+
+ case 'R':
+ if (scanset)
+ whileflag=0;
+ else {
+ scanset = 1;
+ modeflag |= _O_RANDOM;
+ }
+ break;
+
+ case 'T':
+ if (modeflag & _O_SHORT_LIVED)
+ whileflag=0;
+ else
+ modeflag |= _O_SHORT_LIVED;
+ break;
+
+ case 'D':
+ if (modeflag & _O_TEMPORARY)
+ whileflag=0;
+ else
+ modeflag |= _O_TEMPORARY;
+ break;
+#endif
+
+ default:
+ whileflag=0;
+ break;
+ }
+
+ /* Try to open the file. Note that if neither 't' nor 'b' is
+ specified, _sopen will use the default. */
+
+#ifdef _POSIX_
+ if ((filedes = open(filename, modeflag, P_CMASK)) < 0)
+#else
+ if ((filedes = _sopen(filename, modeflag, shflag, CMASK)) < 0)
+#endif
+ return(NULL);
+
+ /* Set up the stream data base. */
+
+ _cflush++; /* force library pre-termination procedure */
+
+ /* Init pointers */
+ stream = str;
+
+ stream->_flag = streamflag;
+#ifdef _CRUISER_
+ stream->_cnt = stream->__tmpnum = 0;
+ stream->_base = stream->_ptr = NULL;
+#else /* ndef _CRUISER_ */
+ stream->_cnt = 0;
+ stream->_tmpfname = stream->_base = stream->_ptr = NULL;
+#endif /* _CRUISER_ */
+
+ stream->_file = filedes;
+
+ return(stream);
+}
diff --git a/private/crt32/stdio/_sftbuf.c b/private/crt32/stdio/_sftbuf.c
new file mode 100644
index 000000000..ec81c7657
--- /dev/null
+++ b/private/crt32/stdio/_sftbuf.c
@@ -0,0 +1,223 @@
+/***
+*_sftbuf.c - temporary buffering initialization and flushing
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* temporary buffering initialization and flushing. if stdout/err is
+* unbuffered, buffer it temporarily so that string is sent to kernel as
+* a batch of chars, not char-at-a-time. if appropriate, make buffering
+* permanent.
+*
+* [NOTE 1: These routines assume that the temporary buffering is only
+* used for output. In particular, note that _stbuf() sets _IOWRT.]
+*
+* [NOTE 2: It is valid for this module to assign a value directly to
+* _flag instead of simply twiddling bits since we are initializing the
+* buffer data base.]
+*
+*Revision History:
+* 09-01-83 RN initial version
+* 06-26-85 TC added code to _stbuf to allow variable buffer lengths
+* ??-??-?? TC fixed case in _flbuf where flag is off, but a temporary
+* buffer still needs to be fflushed.
+* 05-27-87 JCR protect mode does not know about stdprn.
+* 06-26-87 JCR Conditionalized out code in _ftbuf that caused
+* redirected stdout to be flushed on every call.
+* 07-01-87 JCR Put in code to support re-entrant calling from
+* interrupt level (MSC only).
+* 08-06-87 JCR Fixed a _ftbuf() problem pertaining to stderr/stdprn
+* when _bufout is being used by stdout.
+* 08-07-87 JCR (1) When assigning _bufout to an _iob, we now set the
+* _IOWRT flag. This fixes a bug involving freopen()
+* issued against one of the std handles.
+* (2) Removed some annoying commented out code.
+* 08-13-87 JCR _ftbuf() does NOT clear _IOWRT now. Fixes a bug where
+* _getstream() would reassign stdout because none of the
+* flags were set.
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 11-05-87 JCR Re-written for multi-thread support and simplicity
+* 01-11-88 JCR Merged mthread version into normal version
+* 01-13-88 SKS Changed bogus "_fileno_lk" to "fileno"
+* 06-06-88 JCR Optimized _iob2 references
+* 06-10-88 JCR Use near pointer to reference _iob[] entries
+* 06-27-88 JCR Added stdprn temporary buffering support (DOS only),
+* and made buffer allocation dynamic; also added _IOFLRTN
+* (flush stream on per routine basis).
+* 08-25-88 GJF Modified to also work for the 386 (small model only).
+* 06-20-89 PHG Changed return value to void
+* 08-28-89 JCR Removed _NEAR_ for 386
+* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and
+* indents.
+* 03-16-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>. Also,
+* removed some leftover 16-bit DOS support.
+* 03-27-90 GJF Added #include <io.h>.
+* 05-29-90 SBM Use _flush, not [_]fflush[_lk]
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+* 01-22-91 GJF ANSI naming.
+* 03-27-92 DJM POSIX support.
+* 08-26-92 GJF Include unistd.h for POSIX build.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <file2.h>
+#include <io.h>
+#include <assert.h>
+#include <internal.h>
+#include <malloc.h>
+#ifdef MTHREAD
+#include <os2dll.h>
+#endif
+
+/* Buffer pointers for stdout and stderr */
+void *_stdbuf[2] = { NULL, NULL};
+
+/***
+*int _stbuf(stream) - set temp buffer on stdout, stdprn, stderr
+*
+*Purpose:
+* if stdout/stderr is still unbuffered, buffer it.
+* this function works intimately with _ftbuf, and accompanies it in
+* bracketing normally unbuffered output. these functions intended for
+* library use only.
+*
+* Multi-thread: It is assumed that the caller has already aquired the
+* stream lock.
+*
+*Entry:
+* FILE *stream - stream to temp buffer
+*
+*Exit:
+* returns 1 if buffer initialized, 0 if not
+* sets fields in stdout or stderr to indicate buffering
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _stbuf (
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ int index;
+
+ assert(str != NULL);
+
+ /* Init near stream pointer */
+ stream = str;
+
+ /* do nothing if not a tty device */
+#ifdef _POSIX_
+ if (!isatty(fileno(stream)))
+#else
+ if (!_isatty(_fileno(stream)))
+#endif
+ return(0);
+
+ /* Make sure stream is stdout/stderr and init _stdbuf index */
+ if (stream == stdout)
+ index = 0;
+ else if (stream == stderr)
+ index = 1;
+ else
+ return(0);
+
+ _cflush++; /* force library pre-termination procedure */
+
+ /* Make sure the stream is not already buffered. */
+ if (anybuf(stream))
+ return(0);
+
+ /* Allocate a buffer for this stream if we haven't done so yet. */
+ if (_stdbuf[index] == NULL)
+ if ( (_stdbuf[index]=malloc(BUFSIZ)) == NULL )
+ return(0); /* error */
+
+ /* Set up the buffer */
+ stream->_ptr = stream->_base = _stdbuf[index];
+ stream->_cnt = stream->_bufsiz = BUFSIZ;
+ stream->_flag |= (_IOWRT | _IOYOURBUF | _IOFLRTN);
+
+ return(1);
+}
+
+
+/***
+*void _ftbuf(flag, stream) - take temp buffering off a stream
+*
+*Purpose:
+* If stdout/stderr is being buffered and it is a device, _flush and
+* dismantle the buffer. if it's not a device, leave the buffering on.
+* This function works intimately with _stbuf, and accompanies it in
+* bracketing normally unbuffered output. these functions intended for
+* library use only
+*
+* Multi-thread: It is assumed that the caller has already aquired the
+* stream lock.
+*
+*Entry:
+* int flag - a flag to tell whether to dismantle temp buffering on a
+* stream
+* FILE *stream - the stream
+*
+*Exit:
+* no return value
+* sets fields in stdout/stderr
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _ftbuf (
+ int flag,
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+
+ assert(flag == 0 || flag == 1);
+
+ /* Init near stream pointers */
+ stream = str;
+
+ if (flag) {
+
+ if (stream->_flag & _IOFLRTN) {
+
+ /* Flush the stream and tear down temp buffering. */
+ _flush(stream);
+ stream->_flag &= ~(_IOYOURBUF | _IOFLRTN);
+ stream->_bufsiz = 0;
+ stream->_base = stream->_ptr = NULL;
+ }
+
+ /* Note: If we expand the functionality of the _IOFLRTN bit to
+ include other streams, we may want to clear that bit here under
+ an 'else' clause (i.e., clear bit in the case that we leave the
+ buffer permanently assigned. Given our current use of the bit,
+ the extra code is not needed. */
+
+ } /* end flag = 1 */
+
+#ifndef MTHREAD
+/* NOTE: Currently, writing to the same string at interrupt level does not
+ work in multi-thread programs. */
+
+/* The following code is needed if an interrupt occurs between calls
+ to _stbuf/_ftbuf and the interrupt handler also calls _stbuf/_ftbuf. */
+
+ else
+ if (stream->_flag & _IOFLRTN)
+ _flush(stream);
+
+#endif /* MTHREAD */
+
+}
diff --git a/private/crt32/stdio/clearerr.c b/private/crt32/stdio/clearerr.c
new file mode 100644
index 000000000..a5d651a7d
--- /dev/null
+++ b/private/crt32/stdio/clearerr.c
@@ -0,0 +1,77 @@
+/***
+*clearerr.c - clear error and eof flags
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines clearerr() - clear error and eof flags from a stream
+*
+*Revision History:
+* 11-30-83 RN initial version
+* 11-02-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-01-88 JCR Clear lowio flags as well as stdio flags
+* 02-15-90 GJF Fixed copyright and indents
+* 03-16-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarator.
+* 01-22-91 GJF ANSI naming.
+* 03-27-92 DJM POSIX support
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <os2dll.h>
+#include <internal.h>
+#ifndef _POSIX_
+#include <msdos.h>
+#endif
+
+/***
+*void clearerr(stream) - clear error and eof flags on a stream
+*
+*Purpose:
+* Resets the error and eof indicators for a stream to 0
+*
+*Entry:
+* FILE *stream - stream to set indicators on
+*
+*Exit:
+* No return value.
+* changes the _flag field of the FILE struct.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 clearerr (
+ FILE *stream
+ )
+{
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(stream != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+
+ _lock_str(index);
+
+ /* Clear stdio level flags */
+ stream->_flag &= ~(_IOERR|_IOEOF);
+
+ /* Clear lowio level flags */
+
+#ifndef _POSIX_
+ _osfile[_fileno(stream)] &= ~(FEOFLAG);
+#endif
+ _unlock_str(index);
+}
diff --git a/private/crt32/stdio/closeall.c b/private/crt32/stdio/closeall.c
new file mode 100644
index 000000000..391b63100
--- /dev/null
+++ b/private/crt32/stdio/closeall.c
@@ -0,0 +1,71 @@
+/***
+*closeall.c - close all open files
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _fcloseall() - closes all open files except stdin, stdout
+* stdprn, stderr, and stdaux.
+*
+*Revision History:
+* 09-19-83 RN initial version
+* 06-26-87 JCR Stream search starts with _iob[3] for OS/2
+* 11-02-87 JCR Multi-thread support
+* 11-08-87 SKS Changed PROTMODE to OS2
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-14-88 JCR Use near pointer to reference _iob[] entries
+* 08-24-88 GJF Added check that OS2 is defined whenever M_I386 is.
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-16-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 10-03-90 GJF New-style function declarator.
+* 01-21-91 GJF ANSI naming.
+* 03-25-92 DJM POSIX support
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+
+/***
+*int _fcloseall() - close all open streams
+*
+*Purpose:
+* Closes all streams currently open except for stdin/out/err/aux/prn.
+* tmpfile() files are among those closed.
+*
+*Entry:
+* None.
+*
+*Exit:
+* returns number of streams closed if OK
+* returns EOF if fails.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _fcloseall (
+ void
+ )
+{
+ REG1 FILE *stream = &_iob[3];
+ REG2 int count = 0;
+
+ _mlock(_IOB_SCAN_LOCK);
+
+ for (; stream <= _lastiob; stream++)
+ if (fclose(stream) != EOF)
+ count++;
+
+ _munlock(_IOB_SCAN_LOCK);
+
+ return(count);
+}
diff --git a/private/crt32/stdio/cprintf.c b/private/crt32/stdio/cprintf.c
new file mode 100644
index 000000000..30129663b
--- /dev/null
+++ b/private/crt32/stdio/cprintf.c
@@ -0,0 +1,15 @@
+/***
+*cprintf.c - Conio version of printf
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Perform formatted i/o directly to the console.
+*
+*Revision History:
+* 09-25-91 JCR Stub module created.
+*
+*******************************************************************************/
+
+#define CPRFLAG 1
+#include "output.c"
diff --git a/private/crt32/stdio/cscanf.c b/private/crt32/stdio/cscanf.c
new file mode 100644
index 000000000..72a89ce1f
--- /dev/null
+++ b/private/crt32/stdio/cscanf.c
@@ -0,0 +1,15 @@
+/***
+*cscanf.c - Conio version of scanf
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Perform formatted i/o directly to the keyboard.
+*
+*Revision History:
+* 09-25-91 JCR Stub module created.
+*
+*******************************************************************************/
+
+#define CPRFLAG 1
+#include "input.c"
diff --git a/private/crt32/stdio/fclose.c b/private/crt32/stdio/fclose.c
new file mode 100644
index 000000000..f6d93fd38
--- /dev/null
+++ b/private/crt32/stdio/fclose.c
@@ -0,0 +1,221 @@
+/***
+*fclose.c - close a file
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fclose() - close an open file
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 05-14-87 SKS error return from fflush must not be clobbered
+* 08-10-87 JCR Added code to support P_tmpdir with or without trailing '\'
+* 11-01-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-13-88 JCR Removed unnecessary calls to mthread fileno/feof/ferror
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-14-88 JCR Use near pointer to reference _iob[] entries
+* 08-24-88 GJF Don't use FP_OFF() macro for the 386
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-16-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 05-29-90 SBM Use _flush, not [_]fflush[_lk]
+* 07-25-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarator.
+* 01-21-91 GJF ANSI naming.
+* 03-11-92 GJF For Win32, revised temporary file cleanup.
+* 03-25-92 DJM POSIX support.
+* 08-26-92 GJF Include unistd.h for POSIX build.
+* 01-13-93 GJF Don't need/want to remove() tmp files on Windows NT
+* (file is removed by the OS when handle is closed).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#include <string.h>
+#include <io.h>
+#include <stdlib.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int fclose(stream) - close a stream
+*
+*Purpose:
+* Flushes and closes a stream and frees any buffer associated
+* with that stream, unless it was set with setbuf.
+*
+*Entry:
+* FILE *stream - stream to close
+*
+*Exit:
+* returns 0 if OK, EOF if fails (can't _flush, not a FILE, not open, etc.)
+* closes the file -- affecting FILE structure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD /* multi-thread; define both fclose and _fclose_lk */
+
+int _CRTAPI1 fclose (
+ FILE *stream
+ )
+{
+ int result = EOF;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(stream != NULL);
+
+ /* If stream is a string, simply clear flag and return EOF */
+ if (stream->_flag & _IOSTRG)
+ stream->_flag = 0; /* IS THIS REALLY NEEDED ??? */
+
+ /* Stream is a real file. */
+ else {
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ result = _fclose_lk(stream);
+ _unlock_str(index);
+ }
+
+ return(result);
+}
+
+/***
+*int _fclose_lk() - close a stream (lock already held)
+*
+*Purpose:
+* Core fclose() routine; assumes caller has stream lock held.
+*
+* [See fclose() above for more information.]
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _fclose_lk (
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ REG2 int result = EOF;
+#ifdef _CRUISER_
+ int tmp;
+ char tmpname[L_tmpnam];
+ char *ptmp;
+#endif /* _CRUISER_ */
+
+ /* Init near stream pointer */
+ stream = str;
+
+#else /* non multi-thread; just define fclose() */
+
+int _CRTAPI1 fclose (
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ REG2 int result = EOF;
+#ifdef _CRUISER_
+ int tmp;
+ char tmpname[L_tmpnam];
+ char *ptmp;
+#endif /* _CRUISER_ */
+
+ /* Init near stream pointer */
+ stream = str;
+
+ if (stream->_flag & _IOSTRG) {
+ stream->_flag = 0;
+ return(EOF);
+ }
+
+#endif
+
+ assert(str != NULL);
+
+ if (inuse(stream)) {
+
+ /* Stream is in use:
+ (1) flush stream
+ (2) free the buffer
+ (3) close the file
+ (4) delete the file if temporary
+ */
+
+#ifdef _POSIX_
+
+ result = _flush(stream);
+
+#else /* ndef _POSIX_ */
+
+ result = _flush(stream);
+#ifdef _CRUISER_
+ tmp = _tmpnum(stream);
+#endif /* _CRUISER_ */
+
+#endif /* _POSIX_ */
+ _freebuf(stream);
+
+#ifdef _POSIX_
+ if (close(fileno(stream)) <0)
+#else
+ if (_close(_fileno(stream)) < 0)
+#endif
+ result = EOF;
+#ifdef _CRUISER_
+ else if ( tmp ) {
+ /* File is temporary; build pathname and delete file */
+
+ strcpy( tmpname, _P_tmpdir );
+ ptmp = tmpname + sizeof(_P_tmpdir);
+
+ if (*(ptmp-2) != '\\')
+ strcat(tmpname,"\\");
+ else
+ ptmp--;
+
+ _itoa (tmp, ptmp, 10);
+
+ if ( _unlink( tmpname ) )
+ result = EOF ;
+ }
+#else /* ndef _CRUISER_ */
+ else if ( stream->_tmpfname != NULL ) {
+ /*
+ * temporary file (i.e., one created by tmpfile()
+ * call). delete, if necessary (don't have to on
+ * Windows NT because it was done by the system when
+ * the handle was closed). also, free up the heap
+ * block holding the pathname.
+ */
+#ifdef _POSIX_
+ if ( unlink(stream->_tmpfname) )
+ result = EOF;
+#endif
+ free(stream->_tmpfname);
+ }
+#endif /* _CRUISER_ */
+
+ }
+
+ stream->_flag = 0;
+ return(result);
+}
diff --git a/private/crt32/stdio/fdopen.c b/private/crt32/stdio/fdopen.c
new file mode 100644
index 000000000..25681f257
--- /dev/null
+++ b/private/crt32/stdio/fdopen.c
@@ -0,0 +1,191 @@
+/***
+*fdopen.c - open a file descriptor as stream
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _fdopen() - opens a file descriptor as a stream, thus allowing
+* buffering, etc.
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 03-02-87 JCR added support for 'b' and 't' embedded in mode strings
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 11-03-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-06-88 JCR Optimized _iob2 references
+* 11-20-89 GJF Fixed copyright, indents. Added const to type of mode.
+* 02-15-90 GJF _iob[], _iob2[] merge.
+* 03-16-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 08-24-90 SBM Added support for 'c' and 'n' flags
+* 10-02-90 GJF New-style function declarator.
+* 01-21-91 GJF ANSI naming.
+* 02-14-92 GJF Replaced _nfile with _nhandle for Win32.
+* 05-01-92 DJM Replaced _nfile with OPEN_MAX for POSIX.
+* 08-03-92 GJF Function name must be "fdopen" for POSIX.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#include <internal.h>
+#include <os2dll.h>
+#ifdef _POSIX_
+#include <limits.h>
+#endif
+
+/***
+*FILE *_fdopen(filedes, mode) - open a file descriptor as a stream
+*
+*Purpose:
+* associates a stream with a file handle, thus allowing buffering, etc.
+* The mode must be specified and must be compatible with the mode
+* the file was opened with in the low level open.
+*
+*Entry:
+* int filedes - handle referring to open file
+* char *mode - file mode to use ("r", "w", "a", etc.)
+*
+*Exit:
+* returns stream pointer and sets FILE struct fields if successful
+* returns NULL if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef _POSIX_
+FILE * _CALLTYPE1 fdopen (
+#else
+FILE * _CALLTYPE1 _fdopen (
+#endif
+ int filedes,
+ REG2 const char *mode
+ )
+{
+ REG1 FILE *stream;
+ int whileflag, tbflag, cnflag;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(mode != NULL);
+
+#ifdef _WIN32_
+ assert(filedes < _nhandle);
+
+ if ( (unsigned)filedes >= (unsigned)_nhandle )
+ return(NULL);
+#else
+
+#ifdef _POSIX_
+ assert(filedes < OPEN_MAX);
+
+ if (filedes < 0 || filedes >= OPEN_MAX)
+ return(NULL);
+#else
+ assert(filedes < _nfile);
+
+ if (filedes < 0 || filedes >= _nfile)
+ return(NULL);
+
+#endif /* _POSIX_ */
+
+#endif /* _WIN32_ */
+
+
+ /* Find a free stream; stream is returned 'locked'. */
+
+ if ((stream = _getstream()) == NULL)
+ return(NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+
+ /* First character must be 'r', 'w', or 'a'. */
+
+ switch (*mode) {
+ case 'r':
+ stream->_flag = _IOREAD;
+ break;
+ case 'w':
+ case 'a':
+ stream->_flag = _IOWRT;
+ break;
+ default:
+ stream = NULL; /* error */
+ goto done;
+ break;
+ }
+
+ /* There can be up to three more optional characters:
+ (1) A single '+' character,
+ (2) One of 'b' and 't' and
+ (3) One of 'c' and 'n'.
+
+ Note that currently, the 't' and 'b' flags are syntax checked
+ but ignored. 'c' and 'n', however, are correctly supported.
+ */
+
+ whileflag=1;
+ tbflag=cnflag=0;
+ stream->_flag |= _commode;
+
+ while(*++mode && whileflag)
+ switch(*mode) {
+
+ case '+':
+ if (stream->_flag & _IORW)
+ whileflag=0;
+ else {
+ stream->_flag |= _IORW;
+ stream->_flag &= ~(_IOREAD | _IOWRT);
+ }
+ break;
+
+ case 'b':
+ case 't':
+ if (tbflag)
+ whileflag=0;
+ else
+ tbflag=1;
+ break;
+
+ case 'c':
+ if (cnflag)
+ whileflag = 0;
+ else {
+ cnflag = 1;
+ stream->_flag |= _IOCOMMIT;
+ }
+ break;
+
+ case 'n':
+ if (cnflag)
+ whileflag = 0;
+ else {
+ cnflag = 1;
+ stream->_flag &= ~_IOCOMMIT;
+ }
+ break;
+
+ default:
+ whileflag=0;
+ break;
+ }
+
+ _cflush++; /* force library pre-termination procedure */
+ stream->_file = filedes;
+
+/* Common return */
+
+done:
+ _unlock_str(index);
+ return(stream);
+}
diff --git a/private/crt32/stdio/feoferr.c b/private/crt32/stdio/feoferr.c
new file mode 100644
index 000000000..09d27ea5b
--- /dev/null
+++ b/private/crt32/stdio/feoferr.c
@@ -0,0 +1,78 @@
+/***
+*feoferr.c - defines feof() and ferror()
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines feof() (test for end-of-file on a stream) and ferror() (test
+* for error on a stream).
+*
+*Revision History:
+* 03-13-89 GJF Module created
+* 03-27-89 GJF Moved to 386 tree
+* 02-15-90 GJF Fixed copyright
+* 03-16-90 GJF Made calling type _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 10-02-90 GJF New-style function declarators.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+
+/* remove macro definitions for feof() and ferror()
+ */
+#undef feof
+#undef ferror
+
+/***
+*int feof(stream) - test for end-of-file on stream
+*
+*Purpose:
+* Tests whether or not the given stream is at end-of-file. Normally
+* feof() is a macro, but it must also be available as a true function
+* for ANSI.
+*
+*Entry:
+* FILE *stream - stream to test
+*
+*Exit:
+* returns nonzero (_IOEOF to be more precise) if and only if the stream
+* is at end-of-file
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 feof (
+ FILE *stream
+ )
+{
+ return( ((stream)->_flag & _IOEOF) );
+}
+
+
+/***
+*int ferror(stream) - test error indicator on stream
+*
+*Purpose:
+* Tests the error indicator for the given stream. Normally, feof() is
+* a macro, but it must also be available as a true function for ANSI.
+*
+*Entry:
+* FILE *stream - stream to test
+*
+*Exit:
+* returns nonzero (_IOERR to be more precise) if and only if the error
+* indicator for the stream is set.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 ferror (
+ FILE *stream
+ )
+{
+ return( ((stream)->_flag & _IOERR) );
+}
diff --git a/private/crt32/stdio/fflush.c b/private/crt32/stdio/fflush.c
new file mode 100644
index 000000000..7eb01c67b
--- /dev/null
+++ b/private/crt32/stdio/fflush.c
@@ -0,0 +1,424 @@
+/***
+*fflush.c - flush a stream buffer
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fflush() - flush the buffer on a stream
+* _flushall() - flush all stream buffers
+*
+*Revision History:
+* 09-01-83 RN initial version
+* 11-02-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-13-88 JCR Removed unnecessary calls to mthread fileno/feof/ferror
+* 05-27-88 PHG Merge DLL and normal versions
+* 06-14-88 JCR Use near pointer to reference _iob[] entries
+* 08-24-88 GJF Don't use FP_OFF() macro for the 386
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 11-29-89 GJF Added support for fflush(NULL) (per ANSI). Merged in
+* flushall().
+* 01-24-90 GJF Fixed fflush(NULL) functionality to comply with ANSI
+* (must only call fflush() for output streams)
+* 03-16-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-26-90 GJF Made flsall() _CALLTYPE4.
+* 05-09-90 SBM _fflush_lk became _flush, added new [_]fflush[_lk]
+* 07-11-90 SBM Commit mode on a per stream basis
+* 10-02-90 GJF New-style function declarators.
+* 12-12-90 GJF Fixed mis-placed paran in ternary expr commiting the
+* buffers.
+* 01-16-91 SRW Reversed test of _commit return value
+* 01-21-91 GJF ANSI naming.
+* 06-05-91 GJF On a successful _flush of a read/write stream in write
+* mode, clear _IOWRT so that the next operation can be a
+* read. ANSI requirement (C700 bug #2531).
+* 07-30-91 GJF Added support for termination scheme used on
+* non-Cruiser targets [_WIN32_].
+* 08-19-91 JCR Added _exitflag, _endstdio
+* 03-16-92 SKS Moved _cflush to the initializer module (in assembler)
+* 03-27-92 DJM POSIX support.
+* 08-26-92 GJF Include unistd.h for POSIX build.
+* 03-18-93 CFW fflush_lk returns 0 before exit.
+* 03-19-93 GJF Revised flsall() so that, in multi-thread models,
+* unused streams are not locked unnecessarily.
+* 05-10-93 GJF Purged ftell call accidently checked in 3/10/93.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#include <fcntl.h>
+#endif
+#include <stdio.h>
+#include <file2.h>
+#include <io.h>
+#include <os2dll.h>
+#include <internal.h>
+
+
+#pragma data_seg(".CRT$XPX")
+
+const void (__cdecl *__pendstdio)(void) = _endstdio;
+
+#pragma data_seg()
+
+/*
+ * _cflush is a dummy variable used to pull in _endstdio() when any STDIO
+ * routine is included in the user program.
+ */
+int _cflush = 1;
+
+/* Values passed to flsall() to distinguish between _flushall() and
+ * fflush(NULL) behavior
+ */
+#define FLUSHALL 1
+#define FFLUSHNULL 0
+
+/* Core routine for fflush(NULL) and flushall()
+ */
+static int _CRTAPI3 flsall(int);
+
+/***
+*int fflush(stream) - flush the buffer on a stream
+*
+*Purpose:
+* if file open for writing and buffered, flush the buffer. if problems
+* flushing the buffer, set the stream flag to error
+* Always flushes the stdio stream and forces a commit to disk if file
+* was opened in commit mode.
+*
+*Entry:
+* FILE *stream - stream to flush
+*
+*Exit:
+* returns 0 if flushed successfully, or no buffer to flush
+* returns EOF and sets file error flag if fails.
+* FILE struct entries affected: _ptr, _cnt, _flag.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD
+
+int _CRTAPI1 fflush (
+ REG1 FILE *stream
+ )
+{
+ int rc;
+ int index;
+
+ /* if stream is NULL, flush all streams
+ */
+ if ( stream == NULL )
+ return(flsall(FFLUSHNULL));
+
+ index = _iob_index(stream);
+
+ _lock_str(index);
+
+ rc = _fflush_lk(stream);
+
+ _unlock_str(index);
+
+ return(rc);
+}
+
+
+/***
+*_fflush_lk() - Flush the buffer on a stream (stream is already locked)
+*
+*Purpose:
+* Core flush routine; assumes stream lock is held by caller.
+*
+* [See fflush() above for more information.]
+*
+*Entry:
+* [See fflush()]
+*Exit:
+* [See fflush()]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _fflush_lk (
+ REG1 FILE *str
+ )
+{
+
+#else /* non multi-thread */
+
+int _CRTAPI1 fflush (
+ REG1 FILE *str
+ )
+{
+
+ /* if stream is NULL, flush all streams */
+ if ( str == NULL ) {
+ return(flsall(FFLUSHNULL));
+ }
+
+#endif /* rejoin common code */
+
+ if (_flush(str) != 0) {
+ /* _flush failed, don't attempt to commit */
+ return(EOF);
+ }
+
+ /* lowio commit to ensure data is written to disk */
+#ifndef _POSIX_
+ if (str->_flag & _IOCOMMIT) {
+ return (_commit(_fileno(str)) ? EOF : 0);
+ }
+#endif
+ return 0;
+}
+
+
+/***
+*int _flush(stream) - flush the buffer on a single stream
+*
+*Purpose:
+* If file open for writing and buffered, flush the buffer. If
+* problems flushing the buffer, set the stream flag to error.
+* Multi-thread version assumes stream lock is held by caller.
+*
+*Entry:
+* FILE* stream - stream to flush
+*
+*Exit:
+* Returns 0 if flushed successfully, or if no buffer to flush.,
+* Returns EOF and sets file error flag if fails.
+* File struct entries affected: _ptr, _cnt, _flag.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _flush (
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ REG2 int rc = 0; /* assume good return */
+ REG3 int nchar;
+
+ /* Init pointer to stream */
+ stream = str;
+
+#ifdef _POSIX_
+
+ /*
+ * Insure that EBADF is returned whenever the underlying
+ * file descriptor is closed.
+ */
+
+ if (-1 == fcntl(fileno(stream), F_GETFL))
+ return(EOF);
+
+ /*
+ * Posix ignores read streams to insure that the result of
+ * ftell() is the same before and after fflush(), and to
+ * avoid seeking on pipes, ttys, etc.
+ */
+
+ if ((stream->_flag & (_IOREAD | _IOWRT)) == _IOREAD) {
+ return 0;
+ }
+
+#endif /* _POSIX_ */
+
+ if ((stream->_flag & (_IOREAD | _IOWRT)) == _IOWRT && bigbuf(stream)
+ && (nchar = stream->_ptr - stream->_base) > 0)
+ {
+#ifdef _POSIX_
+ if ( write(fileno(stream), stream->_base, nchar) == nchar ) {
+#else
+ if ( _write(_fileno(stream), stream->_base, nchar) == nchar ) {
+#endif
+ /* if this is a read/write file, clear _IOWRT so that
+ * next operation can be a read
+ */
+ if ( _IORW & stream->_flag )
+ stream->_flag &= ~_IOWRT;
+ }
+ else {
+ stream->_flag |= _IOERR;
+ rc = EOF;
+ }
+ }
+
+ stream->_ptr = stream->_base;
+ stream->_cnt = 0;
+
+ return(rc);
+}
+
+
+/***
+*int _flushall() - flush all output buffers
+*
+*Purpose:
+* flushes all the output buffers to the file, clears all input buffers.
+*
+*Entry:
+* None.
+*
+*Exit:
+* returns number of open streams
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _flushall (
+ void
+ )
+{
+ return(flsall(FLUSHALL));
+}
+
+
+/***
+*static int flsall(flushflag) - flush all output buffers
+*
+*Purpose:
+* Flushes all the output buffers to the file and, if FLUSHALL is passed,
+* clears all input buffers. Core routine for both fflush(NULL) and
+* flushall().
+*
+* MTHREAD Note: All the locking/unlocking required for both fflush(NULL)
+* and flushall() is performed in this routine.
+*
+*Entry:
+* int flushflag - flag indicating the exact semantics, there are two
+* legal values: FLUSHALL and FFLUSHNULL
+*
+*Exit:
+* if flushflag == FFLUSHNULL then flsbuf returns:
+ 0, if successful
+* EOF, if an error occurs while flushing one of the streams
+*
+* if flushflag == FLUSHALL then flsbuf returns the number of streams
+* successfully flushed
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CRTAPI3 flsall (
+ int flushflag
+ )
+{
+ REG1 FILE *stream = _iob;
+ REG2 int count = 0;
+ int errcode = 0;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ _mlock(_IOB_SCAN_LOCK);
+
+ for (; stream <= _lastiob; stream++)
+
+ if ( inuse(stream) ) {
+
+#ifdef MTHREAD
+ /*
+ * lock the stream. this is not done until testing
+ * the stream is in use to avoid unnecessarily creating
+ * a lock for every stream. the price is having to
+ * retest the stream after the lock has been asserted.
+ */
+ index = _iob_index(stream);
+ _lock_str(index);
+
+ /*
+ * if the stream is STILL in use (it may have been
+ * closed before the lock was asserted), see about
+ * flushing it.
+ */
+ if ( inuse(stream) ) {
+#endif
+
+ if ( flushflag == FLUSHALL ) {
+ /*
+ * FLUSHALL functionality: fflush the read or
+ * write stream and, if successful, update the
+ * count of flushed streams
+ */
+ if ( _fflush_lk(stream) != EOF )
+ /* update count of successfully flushed
+ * streams
+ */
+ count++;
+ }
+ else if ( (flushflag == FFLUSHNULL) &&
+ (stream->_flag & _IOWRT) ) {
+ /*
+ * FFLUSHNULL functionality: fflush the write
+ * stream and kept track of the error, if one
+ * occurs
+ */
+ if ( _fflush_lk(stream) == EOF )
+ errcode = EOF;
+ }
+
+#ifdef MTHREAD
+ }
+ _unlock_str(index);
+#endif
+
+ }
+
+ _munlock(_IOB_SCAN_LOCK);
+
+ if ( flushflag == FLUSHALL )
+ return(count);
+ else
+ return(errcode);
+}
+
+
+#ifndef _CRUISER_
+
+/***
+* _endstdio - Terminate the stdio system
+*
+*Purpose:
+* Terminate the stdio system
+*
+* (1) Flush all streams. (Do this even if we're going to
+* call fcloseall since that routine won't do anything to the
+* std streams.)
+*
+* (2) If returning to caller, close all streams. This is
+* not necessary if the exe is terminating because the OS will
+* close the files for us (much more efficiently, too).
+*
+*Entry: <void>
+*
+*Exit: <void>
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _endstdio(void)
+
+{
+ /* flush all streams */
+ _flushall(); /*flush all streams
+
+ /* if in callable exit, close all streams */
+ if (_exitflag)
+ _fcloseall();
+}
+
+#endif
diff --git a/private/crt32/stdio/fgetc.c b/private/crt32/stdio/fgetc.c
new file mode 100644
index 000000000..0f2e9a2e4
--- /dev/null
+++ b/private/crt32/stdio/fgetc.c
@@ -0,0 +1,79 @@
+/***
+*fgetc.c - get a character from a stream
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fgetc() and getc() - read a character from a stream
+*
+*Revision History:
+* 09-01-83 RN initial version
+* 11-09-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-21-89 PHG Added getc() function
+* 02-15-90 GJF Fixed copyright and indents
+* 03-16-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-16-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* 07-24-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarators.
+* 04-26-93 CFW Wide char enable.
+* 04-30-93 CFW Remove wide char support to fgetwc.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int fgetc(stream), getc(stream) - read a character from a stream
+*
+*Purpose:
+* reads a character from the given stream
+*
+*Entry:
+* FILE *stream - stream to read character from
+*
+*Exit:
+* returns the character read
+* returns EOF if at end of file or error occurred
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 fgetc (
+ REG1 FILE *stream
+ )
+{
+ int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(stream != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ retval = _getc_lk(stream);
+ _unlock_str(index);
+
+ return(retval);
+}
+
+#undef getc
+
+int _CRTAPI1 getc (
+ FILE *stream
+ )
+{
+ return fgetc(stream);
+}
+
diff --git a/private/crt32/stdio/fgetchar.c b/private/crt32/stdio/fgetchar.c
new file mode 100644
index 000000000..00959f455
--- /dev/null
+++ b/private/crt32/stdio/fgetchar.c
@@ -0,0 +1,62 @@
+/***
+*fgetchar.c - get a character from stdin
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _fgetchar() and getchar() - read a character from stdin
+* defines _fgetwchar() and getwchar() - read a wide character from stdin
+*
+*Revision History:
+* 11-20-83 RN initial version
+* 11-09-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-21-89 PHG Added getchar() function
+* 02-15-90 GJF Fixed copyright and indents
+* 03-16-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 10-03-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 04-26-93 CFW Wide char enable.
+* 04-30-93 CFW Move wide char support to fgetwchr.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <tchar.h>
+
+/***
+*int _fgetchar(), getchar() - read a character from stdin
+*
+*Purpose:
+* Reads the next character from stdin. Function version of
+* getchar() macro.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns character read or EOF if at end-of-file or an error occured,
+* in which case the appropriate flag is set in the FILE structure.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _fgetchar (
+ void
+ )
+{
+ return(getc(stdin));
+}
+
+#undef getchar
+
+int _CRTAPI1 getchar (
+ void
+ )
+{
+ return _fgetchar();
+}
diff --git a/private/crt32/stdio/fgetpos.c b/private/crt32/stdio/fgetpos.c
new file mode 100644
index 000000000..1d3e580b7
--- /dev/null
+++ b/private/crt32/stdio/fgetpos.c
@@ -0,0 +1,55 @@
+/***
+*fgetpos.c - Contains the fgetpos runtime
+*
+* Copyright (c) 1987-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Get file position (in an internal format).
+*
+*Revision History:
+* 01-16-87 JCR Module created.
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 02-15-90 GJF Fixed copyright and indents
+* 03-16-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+
+/***
+*int fgetpos(stream,pos) - Get file position (internal format)
+*
+*Purpose:
+* Fgetpos gets the current file position for the file identified by
+* [stream]. The file position is returned in the object pointed to
+* by [pos] and is in internal format; that is, the user is not supposed
+* to interpret the value but simply use it in the fsetpos call. Our
+* implementation simply uses fseek/ftell.
+*
+*Entry:
+* FILE *stream = pointer to a file stream value
+* fpos_t *pos = pointer to a file position value
+*
+*Exit:
+* Successful fgetpos call returns 0.
+* Unsuccessful fgetpos call returns non-zero (!0) value and sets
+* ERRNO (this is done by ftell and passed back by fgetpos).
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+int _CALLTYPE1 fgetpos (
+ FILE *stream,
+ fpos_t *pos
+ )
+{
+ if ((*pos=ftell(stream)) != -1)
+ return(0);
+ else
+ return(-1);
+}
diff --git a/private/crt32/stdio/fgets.c b/private/crt32/stdio/fgets.c
new file mode 100644
index 000000000..071848995
--- /dev/null
+++ b/private/crt32/stdio/fgets.c
@@ -0,0 +1,111 @@
+/***
+*fgets.c - get string from a file
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fgets() - read a string from a file
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-16-87 JCR changed count from an unsigned int to an int (ANSI)
+* and modified comparisons accordingly
+* 11-06-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-14-88 JCR Use near pointer to reference _iob[] entries
+* 08-24-88 GJF Don't use FP_OFF() macro for the 386
+* 08-28-89 JCR Removed _NEAR_ for 386
+* 02-15-90 GJF Fixed copyright and indents
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and added #include <register.h>. Also,
+* removed some leftover 16-bit support.
+* 07-24-90 SBM Replaced <assertm.h> by <assert.h>
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*char *fgets(string, count, stream) - input string from a stream
+*
+*Purpose:
+* get a string, up to count-1 chars or '\n', whichever comes first,
+* append '\0' and put the whole thing into string. the '\n' IS included
+* in the string. if count<=1 no input is requested. if EOF is found
+* immediately, return NULL. if EOF found after chars read, let EOF
+* finish the string as '\n' would.
+*
+*Entry:
+* char *string - pointer to place to store string
+* int count - max characters to place at string (include \0)
+* FILE *stream - stream to read from
+*
+*Exit:
+* returns string with text read from file in it.
+* if count <= 0 return NULL
+* if count == 1 put null string in string
+* returns NULL if error or end-of-file found immediately
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 fgets (
+ char *string,
+ int count,
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ REG2 char *pointer = string;
+ char *retval = string;
+ int ch;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(string != NULL);
+ assert(str != NULL);
+
+ if (count <= 0)
+ return(NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+
+ while (--count)
+ {
+ if ((ch = _getc_lk(stream)) == EOF)
+ {
+ if (pointer == string) {
+ retval=NULL;
+ goto done;
+ }
+
+ break;
+ }
+
+ if ((*pointer++ = (char)ch) == '\n')
+ break;
+ }
+
+ *pointer = '\0';
+
+/* Common return */
+done:
+ _unlock_str(index);
+ return(retval);
+}
diff --git a/private/crt32/stdio/fgetwc.c b/private/crt32/stdio/fgetwc.c
new file mode 100644
index 000000000..de7a37af4
--- /dev/null
+++ b/private/crt32/stdio/fgetwc.c
@@ -0,0 +1,154 @@
+/***
+*fgetwc.c - get a wide character from a stream
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fgetwc() - read a wide character from a stream
+*
+*Revision History:
+* 04-26-93 CFW Module created.
+* 04-30-93 CFW Bring wide char support from fgetc.c.
+* 05-03-93 CFW Add getwc function.
+* 05-10-93 CFW Optimize, fix error handling.
+* 06-02-93 CFW Wide get/put use wint_t.
+* 09-14-93 CFW Fix EOF cast bug.
+* 10-22-93 CFW Test for invalid MB chars using global preset flag.
+* 10-28-93 CFW Test for both IOSTRG and TEXT.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <msdos.h>
+#include <errno.h>
+#include <wchar.h>
+#include <tchar.h>
+#include <setlocal.h>
+
+#ifdef MTHREAD /* multi-thread; define both fgetwc and _getwc_lk */
+
+/***
+*wint_t fgetwc(stream) - read a wide character from a stream
+*
+*Purpose:
+* reads a wide character from the given stream
+*
+*Entry:
+* FILE *stream - stream to read wide character from
+*
+*Exit:
+* returns the wide character read
+* returns WEOF if at end of file or error occurred
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wint_t _CRTAPI1 fgetwc (
+ REG1 FILE *stream
+ )
+{
+ wint_t retval;
+ int index;
+
+ assert(stream != NULL);
+
+ index = _iob_index(stream);
+ _lock_str(index);
+ retval = _getwc_lk(stream);
+ _unlock_str(index);
+
+ return(retval);
+}
+
+/***
+*_getwc_lk() - getwc() core routine (locked version)
+*
+*Purpose:
+* Core getwc() routine; assumes stream is already locked.
+*
+* [See getwc() above for more info.]
+*
+*Entry: [See getwc()]
+*
+*Exit: [See getwc()]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wint_t _CRTAPI1 _getwc_lk (
+ REG1 FILE *stream
+ )
+{
+
+#else /* non multi-thread; just define fgetwc */
+
+wint_t _CRTAPI1 fgetwc (
+ REG1 FILE *stream
+ )
+{
+
+#endif /* rejoin common code */
+
+#ifndef _NTSUBSET_
+ if (!(stream->_flag & _IOSTRG) && (_osfile[_fileno(stream)] & FTEXT))
+ {
+ int size = 1;
+ int ch;
+ char mbc[4];
+ wchar_t wch;
+
+ /* text (multi-byte) mode */
+ if ((ch = _getc_lk(stream)) == EOF)
+ return WEOF;
+
+ mbc[0] = (char)ch;
+
+ if (isleadbyte((unsigned char)mbc[0]))
+ {
+ if ((ch = _getc_lk(stream)) == EOF)
+ {
+ ungetc(mbc[0], stream);
+ return WEOF;
+ }
+ mbc[1] = (char)ch;
+ size = 2;
+ }
+ if (MultiByteToWideChar(_lc_codepage,
+ MB_PRECOMPOSED|__invalid_mb_chars,
+ mbc,
+ size,
+ &wch,
+ 1) == 0)
+ {
+ /*
+ * Conversion failed! Set errno and return
+ * failure.
+ */
+ errno = EILSEQ;
+ return WEOF;
+ }
+ return wch;
+ }
+#endif
+ /* binary (Unicode) mode */
+ if ((stream->_cnt -= sizeof(wchar_t)) >= 0)
+ return *((wchar_t *)(stream->_ptr))++;
+ else
+ return _filwbuf(stream);
+}
+
+#undef getwc
+
+wint_t _CRTAPI1 getwc (
+ FILE *stream
+ )
+{
+ return fgetwc(stream);
+}
diff --git a/private/crt32/stdio/fgetwchr.c b/private/crt32/stdio/fgetwchr.c
new file mode 100644
index 000000000..9f01d3311
--- /dev/null
+++ b/private/crt32/stdio/fgetwchr.c
@@ -0,0 +1,52 @@
+/***
+*fgetwchr.c - get a wide character from stdin
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _fgetwchar() and getwchar() - read a wide character from stdin
+*
+*Revision History:
+* 04-26-93 CFW Module created.
+* 05-03-93 CFW Bring wide char support from fgetwchr.c.
+* 06-02-93 CFW Wide get/put use wint_t.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <tchar.h>
+
+/***
+*wint_t _fgetwchar(), getwchar() - read a wide character from stdin
+*
+*Purpose:
+* Reads the next wide character from stdin. Function version of
+* getwchar() macro.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns wide character read or WEOF if at end-of-file or an error occured,
+* in which case the appropriate flag is set in the FILE structure.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wint_t _CRTAPI1 _fgetwchar (
+ void
+ )
+{
+ return(getwc(stdin));
+}
+
+#undef getwchar
+
+wint_t _CRTAPI1 getwchar (
+ void
+ )
+{
+ return(_fgetwchar());
+}
diff --git a/private/crt32/stdio/fileno.c b/private/crt32/stdio/fileno.c
new file mode 100644
index 000000000..45b1e25e5
--- /dev/null
+++ b/private/crt32/stdio/fileno.c
@@ -0,0 +1,50 @@
+/***
+*fileno.c - defines _fileno()
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines fileno() - return the file handle for the specified stream
+*
+*Revision History:
+* 03-13-89 GJF Module created
+* 03-27-89 GJF Moved to 386 tree
+* 02-15-90 GJF _file is now an int. Also, fixed copyright.
+* 03-19-90 GJF Made calling type _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 10-02-90 GJF New-style function declarator.
+* 01-21-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+
+/* remove macro definition for fileno()
+ */
+#undef _fileno
+
+/***
+*int _fileno(stream) - return the file handle for stream
+*
+*Purpose:
+* Returns the file handle for the given stream is. Normally fileno()
+* is a macro, but it is also available as a true function (for
+* consistency with ANSI, though it is not required).
+*
+*Entry:
+* FILE *stream - stream to fetch handle for
+*
+*Exit:
+* returns the file handle for the given stream
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _fileno (
+ FILE *stream
+ )
+{
+ return( stream->_file );
+}
diff --git a/private/crt32/stdio/fopen.c b/private/crt32/stdio/fopen.c
new file mode 100644
index 000000000..b35b02ea5
--- /dev/null
+++ b/private/crt32/stdio/fopen.c
@@ -0,0 +1,125 @@
+/***
+*fopen.c - open a file
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fopen() and _fsopen() - open a file as a stream and open a file
+* with a specified sharing mode as a stream
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-13-87 JCR added const to declarations
+* 11-01-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 11-14-88 GJF Added _fsopen().
+* 02-15-90 GJF Fixed copyright and indents
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 03-26-92 DJM POSIX support
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <share.h>
+#include <assert.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <file2.h>
+
+/***
+*FILE *_fsopen(file, mode, shflag) - open a file
+*
+*Purpose:
+* Opens the file specified as a stream. mode determines file mode:
+* "r": read "w": write "a": append
+* "r+": read/write "w+": open empty for read/write
+* "a+": read/append
+* Append "t" or "b" for text and binary mode. shflag determines the
+* sharing mode. Values are the same as for sopen().
+*
+*Entry:
+* char *file - file name to open
+* char *mode - mode of file access
+*
+*Exit:
+* returns pointer to stream
+* returns NULL if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+FILE * _CALLTYPE1 _fsopen (
+ const char *file,
+ const char *mode
+#ifndef _POSIX_
+ ,int shflag
+#endif
+ )
+{
+ REG1 FILE *stream;
+ REG2 FILE *retval;
+
+ assert(file != NULL);
+ assert(*file != '\0');
+ assert(mode != NULL);
+ assert(*mode != '\0');
+
+ /* Get a free stream */
+ /* [NOTE: _getstream() returns a locked stream.] */
+
+ if ((stream = _getstream()) == NULL)
+ return(NULL);
+
+ /* open the stream */
+#ifdef _POSIX_
+ retval = _openfile(file,mode, stream);
+#else
+ retval = _openfile(file,mode,shflag,stream);
+#endif
+
+ /* unlock stream and return. */
+ _unlock_str(_iob_index(stream));
+ return(retval);
+}
+
+
+/***
+*FILE *fopen(file, mode) - open a file
+*
+*Purpose:
+* Opens the file specified as a stream. mode determines file mode:
+* "r": read "w": write "a": append
+* "r+": read/write "w+": open empty for read/write
+* "a+": read/append
+* Append "t" or "b" for text and binary mode
+*
+*Entry:
+* char *file - file name to open
+* char *mode - mode of file access
+*
+*Exit:
+* returns pointer to stream
+* returns NULL if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+FILE * _CALLTYPE1 fopen (
+ const char *file,
+ const char *mode
+ )
+{
+#ifdef _POSIX_
+ return( _fsopen(file, mode) );
+#else
+ return( _fsopen(file, mode, _SH_DENYNO) );
+#endif
+}
diff --git a/private/crt32/stdio/fprintf.c b/private/crt32/stdio/fprintf.c
new file mode 100644
index 000000000..2160bf6ef
--- /dev/null
+++ b/private/crt32/stdio/fprintf.c
@@ -0,0 +1,93 @@
+/***
+*fprintf.c - print formatted data to stream
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fprintf() - print formatted data to stream
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-13-87 JCR added const to declaration
+* 06-24-87 JCR (1) Made declaration conform to ANSI prototype and use
+* the va_ macros; (2) removed SS_NE_DS conditionals.
+* 11-05-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-14-88 JCR Use near pointer to reference _iob[] entries
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int fprintf(stream, format, ...) - print formatted data
+*
+*Purpose:
+* Prints formatted data on the given using the format string to
+* format data and getting as many arguments as called for
+* _output does the real work here
+*
+*Entry:
+* FILE *stream - stream to print on
+* char *format - format string to control data format/number of arguments
+* followed by arguments to print, number and type controlled by
+* format string
+*
+*Exit:
+* returns number of characters printed
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 fprintf (
+ FILE *str,
+ const char *format,
+ ...
+ )
+/*
+ * 'F'ile (stream) 'PRINT', 'F'ormatted
+ */
+{
+ va_list(arglist);
+ REG1 FILE *stream;
+ REG2 int buffing;
+ int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ va_start(arglist, format);
+
+ assert(str != NULL);
+ assert(format != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ buffing = _stbuf(stream);
+ retval = _output(stream,format,arglist);
+ _ftbuf(buffing, stream);
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/fputc.c b/private/crt32/stdio/fputc.c
new file mode 100644
index 000000000..acb204f2d
--- /dev/null
+++ b/private/crt32/stdio/fputc.c
@@ -0,0 +1,89 @@
+/***
+*fputc.c - write a character to an output stream
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fputc() - writes a character to a stream
+* defines fputwc() - writes a wide character to a stream
+*
+*Revision History:
+* 09-01-83 RN initial version
+* 11-09-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-14-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 06-21-89 PHG Added putc() function
+* 08-28-89 JCR Removed _NEAR_ for 386
+* 02-15-90 GJF Fixed copyright and indents.
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>. Also,
+* removed some leftover 16-bit support.
+* 07-24-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarators.
+* 04-26-93 CFW Wide char enable.
+* 04-30-93 CFW Remove wide char support to fputwc.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int fputc(ch, stream) - write a character to a stream
+*
+*Purpose:
+* Writes a character to a stream. Function version of putc().
+*
+*Entry:
+* int ch - character to write
+* FILE *stream - stream to write to
+*
+*Exit:
+* returns the character if successful
+* returns EOF if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 fputc (
+ int ch,
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ REG2 int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(str != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ retval = _putc_lk(ch,stream);
+ _unlock_str(index);
+
+ return(retval);
+}
+
+#undef putc
+
+int _CRTAPI1 putc (
+ int ch,
+ FILE *str
+ )
+{
+ return fputc(ch, str);
+}
diff --git a/private/crt32/stdio/fputchar.c b/private/crt32/stdio/fputchar.c
new file mode 100644
index 000000000..d5a941181
--- /dev/null
+++ b/private/crt32/stdio/fputchar.c
@@ -0,0 +1,63 @@
+/***
+*fputchar.c - write a character to stdout
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _fputchar(), putchar() - write a character to stdout, function version
+* defines _fputwchar(), putwchar() - write a wide character to stdout, function version
+*
+*Revision History:
+* 11-30-83 RN initial version
+* 11-09-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-21-89 PHG Added putchar() function
+* 02-15-90 GJF Fixed copyright and indents
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 10-02-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 04-26-93 CFW Wide char enable.
+* 04-30-93 CFW Move wide char support to fputwchr.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <tchar.h>
+
+/***
+*int _fputchar(ch), putchar() - put a character to stdout
+*
+*Purpose:
+* Puts the given characters to stdout. Function version of macro
+* putchar().
+*
+*Entry:
+* int ch - character to output
+*
+*Exit:
+* returns character written if successful
+* returns EOF if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _fputchar (
+ REG1 int ch
+ )
+{
+ return(putc(ch, stdout));
+}
+
+#undef putchar
+
+int _CRTAPI1 putchar (
+ int ch
+ )
+{
+ return _fputchar(ch);
+}
+
diff --git a/private/crt32/stdio/fputs.c b/private/crt32/stdio/fputs.c
new file mode 100644
index 000000000..dee2f09ed
--- /dev/null
+++ b/private/crt32/stdio/fputs.c
@@ -0,0 +1,81 @@
+/***
+*fputs.c - write a string to a stream
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fputs() - writes a string to a stream
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 08-31-84 RN modified to use the new, fast fwrite.
+* 04-13-87 JCR added const to declaration
+* 06-30-87 JCR made fputs return values conform to ANSI [MSC only]
+* 11-06-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-18-88 JCR Error return = EOF
+* 05-27-88 PHG Merged DLL and normal versions
+* 09-22-88 GJF Include internal.h to get prototypes for _[s|f]tbuf()
+* 02-15-90 GJF Fixed copyright and indents
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-26-90 GJF Added #include <string.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarators.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <string.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int fputs(string, stream) - write a string to a file
+*
+*Purpose:
+* Output the given string to the stream, don't write the '\0' or
+* supply a '\n'. Uses _stbuf and _ftbuf for efficiency reasons.
+*
+*Entry:
+* char *string - string to write
+* FILE *stream - stream to write to.
+*
+*Exit:
+* Good return = 0
+* Error return = EOF
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 fputs (
+ const char *string,
+ FILE *stream
+ )
+{
+ REG2 int buffing;
+ REG1 unsigned int length;
+ REG3 unsigned int ndone;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(string != NULL);
+ assert(stream != NULL);
+
+ length = strlen(string);
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ buffing = _stbuf(stream);
+ ndone = _fwrite_lk(string,1,length,stream);
+ _ftbuf(buffing, stream);
+ _unlock_str(index);
+
+ return(ndone == length ? 0 : EOF);
+}
diff --git a/private/crt32/stdio/fputwc.c b/private/crt32/stdio/fputwc.c
new file mode 100644
index 000000000..f28fb10b6
--- /dev/null
+++ b/private/crt32/stdio/fputwc.c
@@ -0,0 +1,159 @@
+/***
+*fputwc.c - write a wide character to an output stream
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fputwc() - writes a wide character to a stream
+*
+*Revision History:
+* 04-26-93 CFW Module created.
+* 04-30-93 CFW Bring wide char support from fputc.c.
+* 05-03-93 CFW Add putwc function.
+* 05-10-93 CFW Optimize, fix error handling.
+* 06-02-93 CFW Wide get/put use wint_t.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <msdos.h>
+#include <errno.h>
+#include <wchar.h>
+#include <tchar.h>
+#include <setlocal.h>
+
+#ifdef MTHREAD /* multi-thread; define both fputwc and _putwc_lk */
+
+/***
+*wint_t fputwc(ch, stream) - write a wide character to a stream
+*
+*Purpose:
+* Writes a wide character to a stream. Function version of putwc().
+*
+*Entry:
+* wint_t ch - wide character to write
+* FILE *stream - stream to write to
+*
+*Exit:
+* returns the wide character if successful
+* returns WEOF if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wint_t _CRTAPI1 fputwc (
+ wint_t ch,
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ REG2 wint_t retval;
+ int index;
+
+ assert(str != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+ index = _iob_index(stream);
+ _lock_str(index);
+ retval = _putwc_lk(ch,stream);
+ _unlock_str(index);
+
+ return(retval);
+}
+
+/***
+*_putwc_lk() - putwc() core routine (locked version)
+*
+*Purpose:
+* Core putwc() routine; assumes stream is already locked.
+*
+* [See putwc() above for more info.]
+*
+*Entry: [See putwc()]
+*
+*Exit: [See putwc()]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wint_t _CRTAPI1 _putwc_lk (
+ wint_t ch,
+ FILE *str
+ )
+{
+
+#else /* non multi-thread; just define fputwc */
+
+wint_t _CRTAPI1 fputwc (
+ wint_t ch,
+ FILE *str
+ )
+{
+
+#endif /* rejoin common code */
+
+#ifndef _NTSUBSET_
+ if (!(str->_flag & _IOSTRG) && (_osfile[_fileno(str)] & FTEXT))
+ {
+ int size, defused;
+ char mbc[4];
+
+ /* text (multi-byte) mode */
+ size = WideCharToMultiByte(_lc_codepage,
+ WC_COMPOSITECHECK | WC_SEPCHARS,
+ (wchar_t *)&ch,
+ 1,
+ mbc,
+ MB_CUR_MAX,
+ NULL,
+ &defused);
+
+ if ( (size == 0) || defused )
+ {
+ /*
+ * Conversion failed! Set errno and return
+ * failure.
+ */
+ errno = EILSEQ;
+ return WEOF;
+ }
+ else if ( size == 1 )
+ {
+ if ( _putc_lk(mbc[0], str) == EOF )
+ return WEOF;
+ return (wint_t)(0xffff & ch);
+ }
+ else { /* size == 2 */
+ if ( (_putc_lk(mbc[0], str) == EOF) ||
+ (_putc_lk(mbc[1], str) == EOF) )
+ return WEOF;
+ return (wint_t)(0xffff & ch);
+ }
+ }
+#endif
+ /* binary (Unicode) mode */
+ if ( (str->_cnt -= sizeof(wchar_t)) >= 0 )
+ return (wint_t) (0xffff & (*((wchar_t *)(str->_ptr))++ = (wchar_t)ch));
+ else
+ return _flswbuf(ch, str);
+}
+
+#undef putwc
+
+wint_t _CRTAPI1 putwc (
+ wint_t ch,
+ FILE *str
+ )
+{
+ return fputwc(ch, str);
+}
diff --git a/private/crt32/stdio/fputwchr.c b/private/crt32/stdio/fputwchr.c
new file mode 100644
index 000000000..83587a506
--- /dev/null
+++ b/private/crt32/stdio/fputwchr.c
@@ -0,0 +1,53 @@
+/***
+*fputwchr.c - write a wide character to stdout
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _fputwchar(), putwchar() - write a wide character to stdout,
+* function version
+*
+*Revision History:
+* 04-26-93 CFW Module created.
+* 04-30-93 CFW Bring wide char support from fputchar.c.
+* 06-02-93 CFW Wide get/put use wint_t.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <tchar.h>
+
+/***
+*wint_t _fputwchar(ch), putwchar() - put a wide character to stdout
+*
+*Purpose:
+* Puts the given wide character to stdout. Function version of macro
+* putwchar().
+*
+*Entry:
+* wint_t ch - character to output
+*
+*Exit:
+* returns character written if successful
+* returns WEOF if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wint_t _CRTAPI1 _fputwchar (
+ REG1 wint_t ch
+ )
+{
+ return(putwc(ch, stdout));
+}
+
+#undef putwchar
+
+wint_t _CRTAPI1 putwchar (
+ REG1 wint_t ch
+ )
+{
+ return(_fputwchar(ch));
+}
diff --git a/private/crt32/stdio/fread.c b/private/crt32/stdio/fread.c
new file mode 100644
index 000000000..c925264f5
--- /dev/null
+++ b/private/crt32/stdio/fread.c
@@ -0,0 +1,197 @@
+/***
+*fread.c - read from a stream
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Read from the specified stream into the user's buffer.
+*
+*Revision History:
+* 06-23-89 PHG Module created, based on asm version
+* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and
+* indents.
+* 03-19-90 GJF Made calling type _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-02-90 GJF New-style function declarators.
+* 01-22-91 GJF ANSI naming.
+* 03-27-92 DJM POSIX support.
+* 06-22-92 GJF Must return 0 if EITHER size-of-item or number-of-
+* item arguments is 0 (TNT Bug #523)
+* 08-26-92 GJF Include unistd.h for POSIX build.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <os2dll.h>
+#include <io.h>
+#include <string.h>
+#include <file2.h>
+
+/***
+*size_t fread(void *buffer, size_t size, size_t count, FILE *stream) -
+* read from specified stream into the specified buffer.
+*
+*Purpose:
+* Read 'count' items of size 'size' from the specified stream into
+* the specified buffer. Return when 'count' items have been read in
+* or no more items can be read from the stream.
+*
+*Entry:
+* buffer - pointer to user's buffer
+* size - size of the item to read in
+* count - number of items to read
+* stream - stream to read from
+*
+*Exit:
+* Returns the number of (whole) items that were read into the buffer.
+* This may be less than 'count' if an error or eof occurred. In this
+* case, ferror() or feof() should be used to distinguish between the
+* two conditions.
+*
+*Notes:
+* fread will attempt to buffer the stream (side effect of the _filbuf
+* call) if necessary.
+*
+* No more than 0xFFFE bytes may be read in at a time by a call to
+* read(). Further, read() does not handle huge buffers. Therefore,
+* in large data models, the read request is broken down into chunks
+* that do not violate these considerations. Each of these chunks is
+* processed much like an fread() call in a small data model (by a
+* call to _nfread()).
+*
+* MTHREAD/DLL - Handled in three layers. fread() handles the locking
+* and DS saving/loading/restoring (if required) and calls _fread_lk()
+* to do the work. _fread_lk() is the same as the single-thread,
+* large data model version of fread(). It breaks up the read request
+* into digestible chunks and calls _nfread() to do the actual work.
+*
+* 386/MTHREAD/DLL - Handled in just the two layers since it is small
+* data model. The outer layer, fread(), takes care of the stream locking
+* and calls _fread_lk() to do the actual work. _fread_lk() is the same
+* as the single-thread version of fread().
+*
+*******************************************************************************/
+
+
+#ifdef MTHREAD
+/* define locking/unlocking version */
+size_t _CALLTYPE1 fread (
+ void *buffer,
+ size_t size,
+ size_t count,
+ FILE *stream
+ )
+{
+ int index;
+ size_t retval;
+
+ index = _iob_index(stream);
+ _lock_str(index); /* lock stream */
+ retval = _fread_lk(buffer, size, count, stream); /* do the read */
+ _unlock_str(index); /* unlock stream */
+ return retval;
+}
+#endif
+
+/* define the normal version */
+#ifdef MTHREAD
+size_t _CALLTYPE1 _fread_lk (
+#else
+size_t _CALLTYPE1 fread (
+#endif
+ void *buffer,
+ size_t size,
+ size_t num,
+ FILE *stream
+ )
+{
+ char *data; /* point to where should be read next */
+ unsigned total; /* total bytes to read */
+ unsigned count; /* num bytes left to read */
+ unsigned bufsize; /* size of stream buffer */
+ unsigned nbytes; /* how much to read now */
+ unsigned nread; /* how much we did read */
+ int c; /* a temp char */
+
+ /* initialize local vars */
+ data = buffer;
+
+ if ( (count = total = size * num) == 0 )
+ return 0;
+
+ if (anybuf(stream))
+ /* already has buffer, use its size */
+ bufsize = stream->_bufsiz;
+ else
+ /* assume will get BUFSIZ buffer */
+ bufsize = BUFSIZ;
+
+ /* here is the main loop -- we go through here until we're done */
+ while (count != 0) {
+ /* if the buffer exists and has characters, copy them to user
+ buffer */
+ if (anybuf(stream) && stream->_cnt != 0) {
+ /* how much do we want? */
+ nbytes = (count < (unsigned)stream->_cnt) ? count : stream->_cnt;
+ memcpy(data, stream->_ptr, nbytes);
+
+ /* update stream and amt of data read */
+ count -= nbytes;
+ stream->_cnt -= nbytes;
+ stream->_ptr += nbytes;
+ data += nbytes;
+ }
+ else if (count >= bufsize) {
+ /* If we have more than bufsize chars to read, get data
+ by calling read with an integral number of bufsiz
+ blocks. Note that if the stream is text mode, read
+ will return less chars than we ordered. */
+
+ /* calc chars to read -- (count/bufsize) * bufsize */
+ nbytes = count - count % bufsize;
+
+#ifdef _POSIX_
+ nread = read(fileno(stream), data, nbytes);
+#else
+ nread = _read(_fileno(stream), data, nbytes);
+#endif
+ if (nread == 0) {
+ /* end of file -- out of here */
+ stream->_flag |= _IOEOF;
+ return (total - count) / size;
+ }
+ else if (nread == (unsigned)-1) {
+ /* error -- out of here */
+ stream->_flag |= _IOERR;
+ return (total - count) / size;
+ }
+
+ /* update count and data to reflect read */
+ count -= nread;
+ data += nread;
+ }
+ else {
+ /* less than bufsize chars to read, so call _filbuf to
+ fill buffer */
+ if ((c = _filbuf(stream)) == EOF) {
+ /* error or eof, stream flags set by _filbuf */
+ return (total - count) / size;
+ }
+
+ /* _filbuf returned a char -- store it */
+ *data++ = (char) c;
+ --count;
+
+ /* update buffer size */
+ bufsize = stream->_bufsiz;
+ }
+ }
+
+ /* we finished successfully, so just return num */
+ return num;
+}
diff --git a/private/crt32/stdio/freopen.c b/private/crt32/stdio/freopen.c
new file mode 100644
index 000000000..be547a03c
--- /dev/null
+++ b/private/crt32/stdio/freopen.c
@@ -0,0 +1,105 @@
+/***
+*freopen.c - close a stream and assign it to a new file
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines freopen() - close and reopen file, typically used to redirect
+* stdin/out/err/prn/aux.
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-13-87 JCR added const to declarations
+* 11-02-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 11-14-88 GJF _openfile() now takes a file sharing flag, also some
+* cleanup (now specific to the 386)
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarator.
+* 01-22-91 GJF ANSI naming.
+* 03-27-92 DJM POSIX support.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <share.h>
+#include <assert.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*FILE *freopen(filename, mode, stream) - reopen stream as new file
+*
+*Purpose:
+* Closes the file associated with stream and assigns stream to a new
+* file with current mode. Usually used to redirect a standard file
+* handle.
+*
+*Entry:
+* char *filename - new file to open
+* char *mode - new file mode, as in fopen()
+* FILE *stream - stream to close and reassign
+*
+*Exit:
+* returns stream if successful
+* return NULL if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+FILE * _CALLTYPE1 freopen (
+ const char *filename,
+ const char *mode,
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ FILE *retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(filename != NULL);
+ assert(*filename != '\0');
+ assert(mode != NULL);
+ assert(str != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+
+ _lock_str(index);
+
+ if (inuse(stream) && _fclose_lk(stream) == EOF) {
+ retval = NULL;
+ goto done;
+ }
+
+ stream->_ptr = stream->_base = NULL;
+ stream->_cnt = stream->_flag = 0;
+#ifdef _POSIX_
+ retval = _openfile(filename,mode,stream);
+#else
+ retval = _openfile(filename,mode,_SH_DENYNO,stream);
+#endif
+
+/* Common return code */
+
+done:
+ _unlock_str(index);
+ return(retval);
+}
diff --git a/private/crt32/stdio/fscanf.c b/private/crt32/stdio/fscanf.c
new file mode 100644
index 000000000..7e6dbb6dc
--- /dev/null
+++ b/private/crt32/stdio/fscanf.c
@@ -0,0 +1,83 @@
+/***
+*fscanf.c - read formatted data from stream
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fscanf() - reads formatted data from stream
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-13-87 JCR added const to declaration
+* 06-24-87 JCR (1) Made declaration conform to ANSI prototype and use
+* the va_ macros; (2) removed SS_NE_DS conditionals.
+* 11-06-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 02-15-90 GJF Fixed copyright and indents
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE2 and added #include
+* <cruntime.h>.
+* 03-26-90 GJF Added #include <internal.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int fscanf(stream, format, ...) - read formatted data from stream
+*
+*Purpose:
+* Reads formatted data from stream into arguments. _input does the real
+* work here.
+*
+*Entry:
+* FILE *stream - stream to read data from
+* char *format - format string
+* followed by list of pointers to storage for the data read. The number
+* and type are controlled by the format string.
+*
+*Exit:
+* returns number of fields read and assigned
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 fscanf (
+ FILE *stream,
+ const char *format,
+ ...
+ )
+/*
+ * 'F'ile (stream) 'SCAN', 'F'ormatted
+ */
+{
+ int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ va_list arglist;
+
+ va_start(arglist, format);
+
+ assert(stream != NULL);
+ assert(format != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ retval = (_input(stream,format,arglist));
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/fseek.c b/private/crt32/stdio/fseek.c
new file mode 100644
index 000000000..79a975870
--- /dev/null
+++ b/private/crt32/stdio/fseek.c
@@ -0,0 +1,258 @@
+/***
+*fseek.c - reposition file pointer on a stream
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fseek() - move the file pointer to new place in file
+*
+*Revision History:
+* 10-13-83 RN initial version
+* 06-26-85 TC added code to allow variable buffer lengths
+* 02-10-87 BCM fixed '%' mistakenly used for '/'
+* 03-04-87 JCR added errno settings
+* 04-16-87 JCR added _IOUNGETC support for bug fix and changes whence
+* from unsigned int to int (ANSI conformance)
+* 04-17-87 JCR fseek() now clears end-of-file indicator flag _IOEOF
+* (for ANSI conformance)
+* 04-21-87 JCR be smart about lseek'ing to the end of the file and
+* back
+* 09-17-87 SKS handle case of '\n' at beginning of buffer (FCRLF flag)
+* 09-24-87 JCR fixed an incorrect access to flag _IOEOF
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 09-30-87 JCR Fixed buffer allocation bug, now use _getbuf()
+* 11-04-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-13-88 JCR Removed unnecessary calls to mthread fileno/feof/ferror
+* 03-04-88 JCR Return value from read() must be treated as unsigned
+* value
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-06-88 JCR Optimized _iob2[] references
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 12-02-88 JCR Added _IOCTRLZ support (fixes bug pertaining to ^Z at
+* eof)
+* 04-12-89 JCR Ripped out all of the special read-only code. See the
+* comments in the routine header for more information.
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 05-29-90 SBM Use _flush, not [_]fflush[_lk]
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 03-27-92 DJM POSIX support.
+* 08-08-92 GJF Use seek method constants!
+* 08-26-92 GJF Include unistd.h for POSIX build.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#else
+#include <msdos.h>
+#endif
+#include <errno.h>
+#include <malloc.h>
+#include <io.h>
+#include <stddef.h>
+#include <internal.h>
+#ifndef _POSIX_
+#include <os2dll.h>
+#endif
+
+/***
+*int fseek(stream, offset, whence) - reposition file pointer
+*
+*Purpose:
+*
+* Reposition file pointer to the desired location. The new location
+* is calculated as follows:
+* { whence=0, beginning of file }
+* <offset> bytes + { whence=1, current position }
+* { whence=2, end of file }
+*
+* Be careful to coordinate with buffering.
+*
+* - - - - - - - - - - - - -
+*
+* [NOTE: We used to bend over backwards to try and preserve the current
+* buffer and maintain disk block alignment. This ended up making our
+* code big and slow and complicated, and slowed us down quite a bit.
+* Some of the things pertinent to the old implimentation:
+*
+* (1) Read-only: We only did the special code path if the file was
+* opened read-only (_IOREAD). If the file was writable, we didn't
+* try to optimize.
+*
+* (2) Buffering: We'd assign a buffer, if necessary, since the
+* later code might need it (i.e., call _getbuf).
+*
+* (3) Ungetc: Fseek had to be careful NOT to save the buffer if
+* an ungetc had ever been done on the buffer (flag _IOUNGETC).
+*
+* (4) Control ^Z: Fseek had to deal with ^Z after reading a
+* new buffer's worth of data (flag _IOCTRLZ).
+*
+* (5) Seek-to-end-and-back: To determine if the new seek was within
+* the current buffer, we had to 'normalize' the desired location.
+* This means that we sometimes had to seek to the end of the file
+* and back to determine what the 0-relative offset was. Two extra
+* lseek() calls hurt performance.
+*
+* (6) CR/LF accounting - When trying to seek within a buffer that
+* is in text mode, we had to go account for CR/LF expansion. This
+* required us to look at every character up to the new offset and
+* see if it was '\n' or not. In addition, we had to check the
+* FCRLF flag to see if the new buffer started with '\n'.
+*
+* Again, all of these notes are for the OLD implimentation just to
+* remind folks of some of the issues involving seeking within a buffer
+* and maintaining buffer alignment. As an aside, I think this may have
+* been a big win in the 'old days' on floppy-based systems but on newer
+* fast hard disks, the extra code/complexity overwhelmed any gain.
+*
+* - - - - - - - - - - - - -
+*
+*Entry:
+* FILE *stream - file to reposition file pointer on
+* long offset - offset to seek to
+* int whence - origin offset is measured from (0=beg, 1=current pos,
+* 2=end)
+*
+*Exit:
+* returns 0 if succeeds
+* returns -1 and sets errno if fails
+* fields of FILE struct will be changed
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD /* multi-thread; define both fseek() and _lk_fseek() */
+
+int _CALLTYPE1 fseek (
+ FILE *stream,
+ long offset,
+ int whence
+ )
+{
+ int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(stream != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+
+ _lock_str(index);
+
+ retval = _fseek_lk (stream, offset, whence);
+
+ _unlock_str(index);
+
+ return(retval);
+}
+
+
+/***
+*_fseek_lk() - Core fseek() routine (stream is locked)
+*
+*Purpose:
+* Core fseek() routine; assumes that caller has the stream locked.
+*
+* [See fseek() for more info.]
+*
+*Entry: [See fseek()]
+*
+*Exit: [See fseek()]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _fseek_lk (
+
+#else /* non multi-thread; just define fseek() */
+
+int _CALLTYPE1 fseek (
+
+#endif /* rejoin common code */
+
+ FILE *str,
+ long offset,
+ int whence
+ )
+{
+
+
+ REG1 FILE *stream;
+
+ assert(str != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+ if ( !inuse(stream) || ((whence != SEEK_SET) && (whence != SEEK_CUR) &&
+ (whence != SEEK_END)) ) {
+ errno=EINVAL;
+ return(-1);
+ }
+
+ /* Clear EOF flag */
+
+ stream->_flag &= ~_IOEOF;
+
+ /* If seeking relative to current location, then convert to
+ a seek relative to beginning of file. This accounts for
+ buffering, etc. by letting fseek() tell us where we are. */
+
+ if (whence == SEEK_CUR) {
+ offset += _ftell_lk(stream);
+ whence = SEEK_SET;
+ }
+
+ /* Flush buffer as necessary */
+
+#ifdef _POSIX_
+ /*
+ * If the stream was last read, we throw away the buffer so
+ * that a possible subsequent write will encounter a clean
+ * buffer. (The Win32 version of fflush() throws away the
+ * buffer if it's read.) Write buffers must be flushed.
+ */
+
+ if ((stream->_flag & (_IOREAD | _IOWRT)) == _IOREAD) {
+ stream->_ptr = stream->_base;
+ stream->_cnt = 0;
+ } else {
+ _flush(stream);
+ }
+#else
+ _flush(stream);
+#endif
+
+
+ /* If file opened for read/write, clear flags since we don't know
+ what the user is going to do next. */
+
+ if (stream->_flag & _IORW)
+ stream->_flag &= ~(_IOWRT|_IOREAD);
+
+ /* Seek to the desired locale and return. */
+
+#ifdef _POSIX_
+ return(lseek(fileno(stream), offset, whence) == -1L ? -1 : 0);
+#else
+ return(_lseek(_fileno(stream), offset, whence) == -1L ? -1 : 0);
+#endif
+}
diff --git a/private/crt32/stdio/fsetpos.c b/private/crt32/stdio/fsetpos.c
new file mode 100644
index 000000000..730d3b843
--- /dev/null
+++ b/private/crt32/stdio/fsetpos.c
@@ -0,0 +1,51 @@
+/***
+*fsetpos.c - Contains fsetpos runtime
+*
+* Copyright (c) 1987-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Fsetpos sets the file position using an internal value
+* returned by an earlier fgetpos call.
+*
+*Revision History:
+* 01-16-87 JCR Module created
+* 04-13-87 JCR Added const to declaration
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 02-15-90 GJF Fixed copyright and indents
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 10-02-90 GJF New-style function declarators.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+
+/***
+*int fsetpos(stream,pos) - Set file positioning
+*
+*Purpose:
+* Fsetpos sets the file position for the file indicated by [stream] to
+* the position indicated by [pos]. The [pos] value is defined to be in
+* an internal format (not to be interpreted by the user) and has been
+* generated by an earlier fgetpos call.
+*
+*Entry:
+* FILE *stream = pointer to a file stream value
+* fpos_t *pos = pointer to a file positioning value
+*
+*Exit:
+* Successful call returns 0.
+* Unsuccessful call returns non-zero (!0).
+*
+*Exceptions:
+* None.
+*******************************************************************************/
+
+int _CALLTYPE1 fsetpos (
+ FILE *stream,
+ const fpos_t *pos
+ )
+{
+ return(fseek(stream,*pos,SEEK_SET));
+}
diff --git a/private/crt32/stdio/ftell.c b/private/crt32/stdio/ftell.c
new file mode 100644
index 000000000..8f59e648a
--- /dev/null
+++ b/private/crt32/stdio/ftell.c
@@ -0,0 +1,257 @@
+/***
+*ftell.c - get current file position
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines ftell() - find current current position of file pointer
+*
+*Revision History:
+* 09-02-83 RN initial version
+* ??-??-?? TC added code to allow variable buffer sizes
+* 05-22-86 TC added code to seek to send if last operation was a
+* write and append mode specified
+* 11-20-86 SKS do not seek to end of file in append mode
+* 12-01-86 SKS fix off-by-1 problem in text mode when last byte in
+* buffer was a '\r', and it was followed by a '\n'. Since
+* the \n was pushed back and the \r was discarded, we
+* must adjust the computed position for the \r.
+* 02-09-87 JCR Added errno set code (if flag (_IORW not set)
+* 09-09-87 JCR Optimized to eliminate two lseek() calls in binary mode.
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 11-04-87 JCR Multi-thread version
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-13-88 JCR Removed unnecessary calls to mthread fileno/feof/ferror
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-06-88 JCR Use _iob2_ macro instead of _iob_index
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 07-27-88 JCR Changed some variables from int to unsigned (bug fix)
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 12-05-88 JCR Added _IOCTRLZ support (fixes bug pertaining to ^Z at
+* eof)
+* 08-17-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat
+* model), also fixed copyright
+* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and
+* indents.
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-02-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 03-27-92 DJM POSIX support.
+* 08-26-92 GJF Include unistd.h for POSIX build.
+* 09-01-92 GJF Fixed POSIX support (was returning -1 for all except
+* read-write streams).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#include <errno.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#else
+#include <msdos.h>
+#endif
+#include <stddef.h>
+#include <io.h>
+#include <internal.h>
+#ifndef _POSIX_
+#include <os2dll.h>
+#endif
+
+/***
+*long ftell(stream) - query stream file pointer
+*
+*Purpose:
+* Find out what stream's position is. coordinate with buffering; adjust
+* backward for read-ahead and forward for write-behind. This is NOT
+* equivalent to fseek(stream,0L,1), because fseek will remove an ungetc,
+* may flush buffers, etc.
+*
+*Entry:
+* FILE *stream - stream to query for position
+*
+*Exit:
+* return present file position if succeeds
+* returns -1L and sets errno if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef MTHREAD /* multi-thread; define both ftell() and _lk_ftell() */
+
+long _CALLTYPE1 ftell (
+ FILE *stream
+ )
+{
+ long retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(stream != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+
+ _lock_str(index);
+
+ retval = _ftell_lk (stream);
+
+ _unlock_str(index);
+
+ return(retval);
+}
+
+
+/***
+*_ftell_lk() - Ftell() core routine (assumes stream is locked).
+*
+*Purpose:
+* Core ftell() routine; assumes caller has aquired stream lock).
+*
+* [See ftell() above for more info.]
+*
+*Entry: [See ftell()]
+*
+*Exit: [See ftell()]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+long _CALLTYPE1 _ftell_lk (
+
+#else /* non multi-thread; define only ftell() */
+
+long _CALLTYPE1 ftell (
+
+#endif /* rejoin common code */
+
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ unsigned int offset;
+ long filepos;
+#ifndef _POSIX_
+ REG2 char *p;
+ char *max;
+#endif
+ int fd;
+ unsigned int rdcnt;
+
+ assert(str != NULL);
+
+ /* Init stream pointer and file descriptor */
+ stream = str;
+#ifdef _POSIX_
+ fd = fileno(stream);
+#else
+ fd = _fileno(stream);
+#endif
+
+ if (stream->_cnt < 0)
+ stream->_cnt = 0;
+
+#ifdef _POSIX_
+ if ((filepos = lseek(fd, 0L, SEEK_CUR)) < 0L)
+#else
+ if ((filepos = _lseek(fd, 0L, SEEK_CUR)) < 0L)
+#endif
+ return(-1L);
+
+ if (!bigbuf(stream)) /* _IONBF or no buffering designated */
+ return(filepos - stream->_cnt);
+
+ offset = stream->_ptr - stream->_base;
+
+#ifndef _POSIX_
+ if (stream->_flag & (_IOWRT|_IOREAD)) {
+ if (_osfile[fd] & FTEXT)
+ for (p = stream->_base; p < stream->_ptr; p++)
+ if (*p == '\n') /* adjust for '\r' */
+ offset++;
+ }
+ else if (!(stream->_flag & _IORW)) {
+ errno=EINVAL;
+ return(-1L);
+ }
+#endif
+
+ if (filepos == 0L)
+ return((long)offset);
+
+ if (stream->_flag & _IOREAD) /* go to preceding sector */
+
+ if (stream->_cnt == 0) /* filepos holds correct location */
+ offset = 0;
+
+ else {
+
+ /* Subtract out the number of unread bytes left in the
+ buffer. [We can't simply use _iob[]._bufsiz because
+ the last read may have hit EOF and, thus, the buffer
+ was not completely filled.] */
+
+ rdcnt = stream->_cnt + (stream->_ptr - stream->_base);
+
+#ifndef _POSIX_
+ /* If text mode, adjust for the cr/lf substitution. If
+ binary mode, we're outta here. */
+ if (_osfile[fd] & FTEXT) {
+ /* (1) If we're not at eof, simply copy _bufsiz
+ onto rdcnt to get the # of untranslated
+ chars read. (2) If we're at eof, we must
+ look through the buffer expanding the '\n'
+ chars one at a time. */
+
+ /* [NOTE: Performance issue -- it is faster to
+ do the two _lseek() calls than to blindly go
+ through and expand the '\n' chars regardless
+ of whether we're at eof or not.] */
+
+ if (_lseek(fd, 0L, 2) == filepos) {
+
+ max = stream->_base + rdcnt;
+ for (p = stream->_base; p < max; p++)
+ if (*p == '\n')
+ /* adjust for '\r' */
+ rdcnt++;
+
+ /* If last byte was ^Z, the lowio read
+ didn't tell us about it. Check flag
+ and bump count, if necessary. */
+
+ if (stream->_flag & _IOCTRLZ)
+ ++rdcnt;
+ }
+
+ else {
+
+ _lseek(fd, filepos, 0);
+ rdcnt = stream->_bufsiz;
+
+ /* If first byte in untranslated buffer
+ was a '\n', assume it was preceeded
+ by a '\r' which was discarded by the
+ previous read operation and count
+ the '\n'. */
+ if (_osfile[fd] & FCRLF)
+ ++rdcnt;
+ }
+
+ } /* end if FTEXT */
+#endif /* !_POSIX_ */
+
+ filepos -= (long)rdcnt;
+
+ } /* end else stream->_cnt != 0 */
+
+ return(filepos + (long)offset);
+}
diff --git a/private/crt32/stdio/fwprintf.c b/private/crt32/stdio/fwprintf.c
new file mode 100644
index 000000000..459fd1bd3
--- /dev/null
+++ b/private/crt32/stdio/fwprintf.c
@@ -0,0 +1,79 @@
+/***
+*fwprintf.c - print formatted data to stream
+*
+* Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fwprintf() - print formatted data to stream
+*
+*Revision History:
+* 05-16-92 KRS Created from fprintf.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int fwprintf(stream, format, ...) - print formatted data
+*
+*Purpose:
+* Prints formatted data on the given using the format string to
+* format data and getting as many arguments as called for
+* _output does the real work here
+*
+*Entry:
+* FILE *stream - stream to print on
+* wchar_t *format - format string to control data format/number of arguments
+* followed by arguments to print, number and type controlled by
+* format string
+*
+*Exit:
+* returns number of wide characters printed
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 fwprintf (
+ FILE *str,
+ const wchar_t *format,
+ ...
+ )
+/*
+ * 'F'ile (stream) 'W'char_t 'PRINT', 'F'ormatted
+ */
+{
+ va_list(arglist);
+ REG1 FILE *stream;
+ REG2 int buffing;
+ int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+// UNDONE: make va_start work with wchar_t format string
+ va_start(arglist, format);
+
+ assert(str != NULL);
+ assert(format != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ buffing = _stbuf(stream);
+ retval = _woutput(stream,format,arglist);
+ _ftbuf(buffing, stream);
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/fwrite.c b/private/crt32/stdio/fwrite.c
new file mode 100644
index 000000000..a0eec6a96
--- /dev/null
+++ b/private/crt32/stdio/fwrite.c
@@ -0,0 +1,202 @@
+/***
+*fwrite.c - read from a stream
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Write to the specified stream from the user's buffer.
+*
+*Revision History:
+* 06-23-89 PHG Module created, based on asm version
+* 01-18-90 GJF Must call _fflush_lk() rather than fflush().
+* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and
+* indents.
+* 03-19-90 GJF Made calling type _CALLTYPE1 and added #include
+* <cruntime.h>. Also, fixed compiler warning.
+* 05-29-90 SBM Use _flush, not [_]fflush[_lk]
+* 07-26-90 SBM Added #include <internal.h>
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-02-90 GJF New-style function declarators.
+* 01-22-91 GJF ANSI naming.
+* 03-27-92 DJM POSIX support.
+* 08-26-92 GJF Include unistd.h for POSIX build.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <os2dll.h>
+#include <io.h>
+#include <string.h>
+#include <file2.h>
+#include <internal.h>
+
+/***
+*size_t fwrite(void *buffer, size_t size, size_t count, FILE *stream) -
+* write to the specified stream from the specified buffer.
+*
+*Purpose:
+* Write 'count' items of size 'size' to the specified stream from
+* the specified buffer. Return when 'count' items have been written
+* or no more items can be written to the stream.
+*
+*Entry:
+* buffer - pointer to user's buffer
+* size - size of the item to write
+* count - number of items to write
+* stream - stream to write to
+*
+*Exit:
+* Returns the number of (whole) items that were written to the stream.
+* This may be less than 'count' if an error or eof occurred. In this
+* case, ferror() or feof() should be used to distinguish between the
+* two conditions.
+*
+*Notes:
+* fwrite will attempt to buffer the stream (side effect of the _flsbuf
+* call) if necessary.
+*
+* No more than 0xFFFE bytes may be written out at a time by a call to
+* write(). Further, write() does not handle huge buffers. Therefore,
+* in large data models, the write request is broken down into chunks
+* that do not violate these considerations. Each of these chunks is
+* processed much like an fwrite() call in a small data model (by a
+* call to _nfwrite()).
+*
+* This code depends on _iob[] being a near array.
+*
+* MTHREAD/DLL - Handled in just two layers since it is small data
+* model. The outer layer, fwrite(), handles stream locking/unlocking
+* and calls _fwrite_lk() to do the work. _fwrite_lk() is the same as
+* the single-thread, small data model version of fwrite().
+*
+*******************************************************************************/
+
+
+#ifdef MTHREAD
+/* define locking/unlocking version */
+size_t _CALLTYPE1 fwrite (
+ const void *buffer,
+ size_t size,
+ size_t count,
+ FILE *stream
+ )
+{
+ int index;
+ size_t retval;
+
+ index = _iob_index(stream);
+ _lock_str(index); /* lock stream */
+ retval = _fwrite_lk(buffer, size, count, stream); /* do the read */
+ _unlock_str(index); /* unlock stream */
+ return retval;
+}
+#endif
+
+/* define the normal version */
+#ifdef MTHREAD
+size_t _CALLTYPE1 _fwrite_lk (
+#else
+size_t _CALLTYPE1 fwrite (
+#endif
+ const void *buffer,
+ size_t size,
+ size_t num,
+ FILE *stream
+ )
+{
+ const char *data; /* point to where data comes from next */
+ unsigned total; /* total bytes to write */
+ unsigned count; /* num bytes left to write */
+ unsigned bufsize; /* size of stream buffer */
+ unsigned nbytes; /* number of bytes to write now */
+ unsigned nwritten; /* number of bytes written */
+ int c; /* a temp char */
+
+ /* initialize local vars */
+ data = buffer;
+ count = total = size * num;
+ if (anybuf(stream))
+ /* already has buffer, use its size */
+ bufsize = stream->_bufsiz;
+ else
+ /* assume will get BUFSIZ buffer */
+ bufsize = BUFSIZ;
+
+ /* here is the main loop -- we go through here until we're done */
+ while (count != 0) {
+ /* if the buffer is big and has room, copy data to buffer */
+ if (bigbuf(stream) && stream->_cnt != 0) {
+ /* how much do we want? */
+ nbytes = (count < (unsigned)stream->_cnt) ? count : stream->_cnt;
+ memcpy(stream->_ptr, data, nbytes);
+
+ /* update stream and amt of data written */
+ count -= nbytes;
+ stream->_cnt -= nbytes;
+ stream->_ptr += nbytes;
+ data += nbytes;
+ }
+ else if (count >= bufsize) {
+ /* If we have more than bufsize chars to write, write
+ data by calling write with an integral number of
+ bufsiz blocks. If we reach here and we have a big
+ buffer, it must be full so _flush it. */
+
+ if (bigbuf(stream)) {
+ if (_flush(stream)) {
+ /* error, stream flags set -- we're out
+ of here */
+ return (total - count) / size;
+ }
+ }
+
+ /* calc chars to read -- (count/bufsize) * bufsize */
+ nbytes = count - count % bufsize;
+
+#ifdef _POSIX_
+ nwritten = write(fileno(stream), data, nbytes);
+#else
+ nwritten = _write(_fileno(stream), data, nbytes);
+#endif
+ if (nwritten == (unsigned)EOF) {
+ /* error -- out of here */
+ stream->_flag |= _IOERR;
+ return (total - count) / size;
+ }
+
+ /* update count and data to reflect write */
+
+ count -= nwritten;
+ data += nwritten;
+
+ if (nwritten < nbytes) {
+ /* error -- out of here */
+ stream->_flag |= _IOERR;
+ return (total - count) / size;
+ }
+ }
+ else {
+ /* buffer full and not enough chars to do direct write,
+ so do a _flsbuf. */
+ c = *data; /* _flsbuf write one char, this is it */
+ if (_flsbuf(c, stream) == EOF) {
+ /* error or eof, stream flags set by _flsbuf */
+ return (total - count) / size;
+ }
+
+ /* _flsbuf wrote a char -- update count */
+ ++data;
+ --count;
+
+ /* update buffer size */
+ bufsize = stream->_bufsiz > 0 ? stream->_bufsiz : 1;
+ }
+ }
+
+ /* we finished successfully, so just return num */
+ return num;
+}
diff --git a/private/crt32/stdio/fwscanf.c b/private/crt32/stdio/fwscanf.c
new file mode 100644
index 000000000..640a865e9
--- /dev/null
+++ b/private/crt32/stdio/fwscanf.c
@@ -0,0 +1,72 @@
+/***
+*fwscanf.c - read formatted data from stream
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines fwscanf() - reads formatted data from stream
+*
+*Revision History:
+* 05-16-92 KRS Created from fscanf.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int fwscanf(stream, format, ...) - read formatted data from stream
+*
+*Purpose:
+* Reads formatted data from stream into arguments. _input does the real
+* work here.
+*
+*Entry:
+* FILE *stream - stream to read data from
+* wchar_t *format - format string
+* followed by list of pointers to storage for the data read. The number
+* and type are controlled by the format string.
+*
+*Exit:
+* returns number of fields read and assigned
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 fwscanf (
+ FILE *stream,
+ const wchar_t *format,
+ ...
+ )
+/*
+ * 'F'ile (stream) 'W'char_t 'SCAN', 'F'ormatted
+ */
+{
+ int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ va_list arglist;
+
+ va_start(arglist, format);
+
+ assert(stream != NULL);
+ assert(format != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ retval = (_winput(stream,format,arglist));
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/gets.c b/private/crt32/stdio/gets.c
new file mode 100644
index 000000000..fc2ac4886
--- /dev/null
+++ b/private/crt32/stdio/gets.c
@@ -0,0 +1,89 @@
+/***
+*gets.c - read a line from stdin
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines gets() - read a line from stdin into buffer
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 11-06-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 02-15-90 GJF Fixed copyright, indents
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-24-90 SBM Replaced <assertm.h> by <assert.h>
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <os2dll.h>
+
+/***
+*char *gets(string) - read a line from stdin
+*
+*Purpose:
+* Gets a string from stdin terminated by '\n' or EOF; don't include '\n';
+* append '\0'.
+*
+*Entry:
+* char *string - place to store read string, assumes enough room.
+*
+*Exit:
+* returns string, filled in with the line of input
+* null string if \n found immediately
+* NULL if EOF found immediately
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 gets (
+ REG3 char *string
+ )
+{
+ REG2 int ch;
+ REG1 char *pointer = string;
+ char *retval = string;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(string != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index((FILE *)stdin);
+#endif
+ _lock_str(index);
+
+ while ((ch = _getchar_lk()) != '\n')
+ {
+ if (ch == EOF)
+ {
+ if (pointer == string)
+ {
+ retval = NULL;
+ goto done;
+ }
+
+ break;
+ }
+
+ *pointer++ = (char)ch;
+ }
+
+ *pointer = '\0';
+
+/* Common return */
+done:
+ _unlock_str(index);
+ return(retval);
+
+}
diff --git a/private/crt32/stdio/getw.c b/private/crt32/stdio/getw.c
new file mode 100644
index 000000000..1cc43938d
--- /dev/null
+++ b/private/crt32/stdio/getw.c
@@ -0,0 +1,86 @@
+/***
+*getw.c - read a binary word from a stream
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _getw() - gets a binary integer from a stream
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 11-09-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-13-88 JCR Removed unnecessary calls to mthread fileno/feof/ferror
+* 05-27-88 PHG Merged DLL and normal versions
+* Fixed bug if EOF occurs in middle of word being read
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-24-88 GJF Don't use FP_OFF() macro for the 386
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 08-13-90 SBM Compiles cleanly with -W3
+* 10-02-90 GJF New-style function declarator.
+* 01-21-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int _getw(stream) - read an int from a stream
+*
+*Purpose:
+* get n bytes (n=sizeof(int)); OR them together in proper order; high
+* byte first. check for EOF between getc's.
+* this routine should be machine independent.
+*
+*Entry:
+* FILE *stream - stream to read integer from
+*
+*Exit:
+* returns the int read from the stream
+* returns EOF if fails (but this is a legit int value, so
+* should test feof() or ferror().
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _getw (
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ REG2 int bytecount = sizeof(int);
+ int word;
+ char *byteptr = (char *)&word;
+ int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(str != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+
+ while (bytecount--)
+ *byteptr++ = (char)_getc_lk(stream);
+ retval = ((feof(stream) || ferror(stream)) ? EOF : word);
+
+ _unlock_str(index);
+ return(retval);
+}
diff --git a/private/crt32/stdio/i386/_initstd.asm b/private/crt32/stdio/i386/_initstd.asm
new file mode 100644
index 000000000..4f20ca63e
--- /dev/null
+++ b/private/crt32/stdio/i386/_initstd.asm
@@ -0,0 +1,17 @@
+ page ,132
+
+;*******
+;
+; Alternate form of CINITSTD.ASM
+;
+; The MIPS C Compiler does not prepend underscores to C
+; variables and functions like the I386 C Compiler does.
+;
+; The EQUate below will yield an object file
+; which will be appropriate for MIPS COFF format.
+;
+;*******
+
+NO_UNDERSCORE equ 1
+
+include i386\cinitstd.asm
diff --git a/private/crt32/stdio/i386/_inittmp.asm b/private/crt32/stdio/i386/_inittmp.asm
new file mode 100644
index 000000000..2839c59f8
--- /dev/null
+++ b/private/crt32/stdio/i386/_inittmp.asm
@@ -0,0 +1,17 @@
+ page ,132
+
+;*******
+;
+; Alternate form of CINITTMP.ASM
+;
+; The MIPS C Compiler does not prepend underscores to C
+; variables and functions like the I386 C Compiler does.
+;
+; The EQUate below will yield an object file
+; which will be appropriate for MIPS COFF format.
+;
+;*******
+
+NO_UNDERSCORE equ 1
+
+include i386\cinittmp.asm
diff --git a/private/crt32/stdio/i386/cinitstd.asm b/private/crt32/stdio/i386/cinitstd.asm
new file mode 100644
index 000000000..b59dfaadf
--- /dev/null
+++ b/private/crt32/stdio/i386/cinitstd.asm
@@ -0,0 +1,88 @@
+ page ,132
+ title cinittmp - C Run-Time Termination for STDIO Buffer Flushing
+;***
+;cinittmp.asm - WIN32 C Run-Time Initialization for the temporary file function
+;
+; Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; This module defines the symbol _cflush which is referenced by those
+; modules that require the _endstdio() terminator. This module places
+; the address of the _endstdio() terminator in the pre-terminator table.
+;
+;Notes:
+;
+;Revision History:
+; 03-19-92 SKS Module created.
+; 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+; 04-29-92 SKS Changed erroneous XP$C to XP$X
+; 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+; 08-06-92 SKS Revised to use new section names and macros
+;
+;*******************************************************************************
+
+.xlist
+include cruntime.inc
+include defsects.inc
+.list
+
+ifndef _WIN32_
+.err
+%out _WIN32_ MUST be defined!
+endif
+
+
+ifndef NO_UNDERSCORE ; I386 VERSION *************************
+
+
+ extrn _endstdio:NEAR
+
+
+beginSection XPX
+
+ dd offset FLAT: _endstdio
+
+endSection XPX
+
+
+ .DATA
+
+;*
+;* _cflush is a dummy variable used to pull in _endstdio() when
+;* any STDIO routine is included in the user program.
+;*
+
+ public _cflush
+
+_cflush dd ?
+
+
+else ; NO_UNDERSCORE ; MIPS VERSION *************************
+
+
+ extrn endstdio:NEAR
+
+
+beginSection XPX
+
+ dd offset FLAT: endstdio
+
+endSection XPX
+
+
+ .DATA
+
+;*
+;* _cflush is a dummy variable used to pull in _endstdio() when
+;* any STDIO routine is included in the user program.
+;*
+
+ public cflush
+
+cflush dd ?
+
+
+endif ; NO_UNDERSCORE ; **** VERSION *************************
+
+
+ end
diff --git a/private/crt32/stdio/i386/cinittmp.asm b/private/crt32/stdio/i386/cinittmp.asm
new file mode 100644
index 000000000..de1c4854a
--- /dev/null
+++ b/private/crt32/stdio/i386/cinittmp.asm
@@ -0,0 +1,92 @@
+ page ,132
+ title cinittmp - C Run-Time Terminator for temp file functions
+;***
+;cinittmp.asm - WIN32 C Run-Time Terminator for the temporary file function
+;
+; Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Termination entry for the tmpnam() and _tempnam() functions
+;
+;Notes:
+; The three global variables included here are referenced by tmpnam()
+; and _tempnam() and will force the inclusion this module and _rmtmp()
+; if either of tmpnam() or _tempnam() is used. This module places the
+; address of _rmtmp() in the terminator table.
+;
+;Revision History:
+; 03-19-92 SKS Module created.
+; 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+; 04-29-92 SKS Changed erroneous XP$C to XP$X
+; 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+; 08-06-92 SKS Revised to use new section names and macros
+;
+;*******************************************************************************
+
+.xlist
+include cruntime.inc
+include defsects.inc
+.list
+
+ifndef _WIN32_
+.err
+%out _WIN32_ MUST be defined!
+endif
+
+
+ifndef NO_UNDERSCORE ; I386 VERSION *************************
+
+
+ extrn _rmtmp:NEAR
+
+
+beginSection XPX
+
+ dd offset FLAT: _rmtmp
+
+endSection XPX
+
+
+ .DATA
+;*
+;* Definitions for _tmpoff, _tempoff and _old_pfxlen. These will cause this
+;* module to be linked in whenever the termination code needs it.
+;*
+
+ public _tmpoff, _tempoff, _old_pfxlen
+
+_tmpoff dd 1
+_tempoff dd 1
+_old_pfxlen dd 0
+
+
+else ; NO_UNDERSCORE ; MIPS VERSION *************************
+
+
+ extrn rmtmp:NEAR
+
+
+beginSection XPX
+
+ dd offset FLAT: rmtmp
+
+endSection XPX
+
+
+ .DATA
+;*
+;* Definitions for _tmpoff, _tempoff and _old_pfxlen. These will cause this
+;* module to be linked in whenever the termination code needs it.
+;*
+
+ public tmpoff, tempoff, old_pfxlen
+
+tmpoff dd 1
+tempoff dd 1
+old_pfxlen dd 0
+
+
+endif ; NO_UNDERSCORE ; **** VERSION *************************
+
+
+ end
diff --git a/private/crt32/stdio/input.c b/private/crt32/stdio/input.c
new file mode 100644
index 000000000..595a364e5
--- /dev/null
+++ b/private/crt32/stdio/input.c
@@ -0,0 +1,1130 @@
+/***
+*input.c - C formatted input, used by scanf, etc.
+*
+* Copyright (c) 1987-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _input() to do formatted input; called from scanf(),
+* etc. functions. This module defines _cscanf() instead when
+* CPRFLAG is defined -- see makefile in lattice directory.
+*
+*Revision History:
+* 09-26-83 RN author
+* 11-01-85 TC added %F? %N? %?p %n %i
+* 11-20-86 SKS enlarged "table" to 256 bytes, to support chars > 0x7F
+* 12-12-86 SKS changed "s_in()" to pushback whitespace or other delimiter
+* 03-24-87 BCM Evaluation Issues:
+* SDS - needs #ifdef SS_NE_DS for the "number" buffer
+* (for S/M models only)
+* GD/TS : (not evaluated)
+* other INIT : (not evaluated)
+* needs _cfltcvt_init to have been called if
+* floating-point i/o conversions are being done
+* TERM - nothing
+* 06-25-87 PHG added check_stack pragma
+* 08-31-87 JCR Made %n conform to ANSI standard: (1) %n is supposed to
+* return the # of chars read so far by the current scanf(),
+* NOT the total read on the stream since open; (2) %n is NOT
+* supposed to affect the # of items read that is returned by
+* scanf().
+* 09-24-87 JCR Made cscanf() use the va_ macros (fixes cl warnings).
+* 11-04-87 JCR Multi-thread support
+* 11-16-87 JCR Cscanf() now gets _CONIO_LOCK
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 02-25-88 JCR If burn() char hits EOF, only return EOF if count==0.
+* 05-31-88 WAJ Now suports %Fs and %Ns
+* 06-01-88 PHG Merged DLL and normal versions
+* 06-08-88 SJM %D no longer means %ld. %[]ABC], %[^]ABC] work.
+* 06-14-88 SJM Fixed %p, and %F? and %N? code.
+* SJM Complete re-write of input/_input for 6.00
+* 09-15-88 JCR If we match a field but it's not assigned, then are
+* terminated by EOF, we must return 0 not EOF (ANSI).
+* 09-25-88 GJF Initial adaption for the 386
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 11-30-88 GJF Cleanup, now specific to 386
+* 06-09-89 GJF Propagated fixes of 03-06-89 and 04-05-89
+* 11-20-89 GJF Added const attribute to type of format. Also, fixed
+* copyright.
+* 12-21-89 GJF Allow null character in scanset
+* 02-14-90 KRS Fix suppressed-assignment pattern matching.
+* 03-20-90 GJF Made _cscanf() _CALLTYPE2 and _input() _CALLTYPE1. Added
+* #include <cruntime.h> and #include <register.h>.
+* 03-26-90 GJF Made static functions _CALLTYPE4. Placed prototype for
+* _input() in internal.h and #include-d it. Changed type of
+* arglist from void ** to va_list (to get rid of annoying
+* warnings). Added #include <string.h>. Elaborated prototypes
+* of static functions to get rid of compiler warnings.
+* 05-21-90 GJF Fixed stack checking pragma syntax.
+* 07-23-90 SBM Compiles cleanly with -W3, replaced <assertm.h> by
+* <assert.h>, moved _cfltcvt_tab to new header
+* <fltintrn.h>, formerly named <struct.h>
+* 08-13-90 SBM Compiles cleanly with -W3 with new build of compiler
+* 08-27-90 SBM Minor cleanup to agree with CRT7 version
+* 10-02-90 GJF New-style function declarators. Also, rewrote expr. to
+* avoid using casts as lvalues.
+* 10-22-90 GJF Added arglistsave, used to save and restore arglist pointer
+* without using pointer arithmetic.
+* 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragma
+* 01-16-91 GJF ANSI naming.
+* 03-14-91 GJF Fix to allow processing of %n, even at eof. Fix devised by
+* DanK of PSS.
+* 06-19-91 GJF Fixed execution of string, character and scan-set format
+* directives to avoid problem with line-buffered devices
+* (C700 bug 1441).
+* 10-22-91 ETC Int'l dec point; Under _INTL: wchar_t/mb support; fix bug
+* under !ALLOW_RANGE (never compiled).
+* 11-15-91 ETC Fixed bug with %f %lf %Lf (bad handling of longone).
+* 11-19-91 ETC Added support for _wsscanf with WPRFLAG; added %tc %ts.
+* 06-09-92 KRS Rip out %tc/%ts; conform to new ISO spec.
+* 08-17-92 KRS Further ISO changes: Add %lc/%ls/%hc/%hs/%C/%S.
+* 12-23-92 SKS Needed to handle %*n (suppressed storage of byte count)
+* 02-16-93 CFW Added wide character output for [] scanset.
+* 06-22-93 KRS Avoid mapping tchar macros incorrectly if _MBCS defined.
+*
+*******************************************************************************/
+
+#define ALLOW_RANGE /* allow "%[a-z]"-style scansets */
+
+#include <cruntime.h>
+#include <sizeptr.h>
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <cvt.h>
+#include <conio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <internal.h>
+#include <fltintrn.h>
+#include <os2dll.h>
+#include <stdlib.h>
+#include <nlsint.h>
+
+#ifdef _MBCS /* always want either Unicode or SBCS for tchar.h */
+#undef _MBCS
+#endif
+#include <tchar.h>
+
+#define HEXTODEC(chr) _hextodec(chr)
+#define LEFT_BRACKET ('[' | ('a' - 'A')) /* 'lowercase' version */
+
+#ifdef WPRFLAG
+static wchar_t _CALLTYPE4 _hextodec(wchar_t);
+#else
+static int _CALLTYPE4 _hextodec(int);
+#endif
+
+/*
+ * Note: CPRFLAG and WPRFLAG cases are currently mutually exclusive.
+ */
+
+#ifdef CPRFLAG
+
+#define INC() (++charcount, _inc())
+#define UN_INC(chr) (--charcount, _ungetch_lk(chr))
+#define EAT_WHITE() _whiteout(&charcount)
+
+static int _CALLTYPE4 _inc(void);
+static int _CALLTYPE4 _whiteout(int *);
+
+#else
+
+#define INC() (++charcount, _inc(stream))
+#define UN_INC(chr) (--charcount, _un_inc(chr, stream))
+#define EAT_WHITE() _whiteout(&charcount, stream)
+
+#ifndef WPRFLAG
+static int _CALLTYPE4 _inc(FILE *);
+static void _CALLTYPE4 _un_inc(int, FILE *);
+static int _CALLTYPE4 _whiteout(int *, FILE *);
+#else
+static wchar_t _CALLTYPE4 _inc(FILE *);
+static void _CALLTYPE4 _un_inc(wchar_t, FILE *);
+static wchar_t _CALLTYPE4 _whiteout(int *, FILE *);
+#endif /* WPRFLAG */
+
+#endif
+
+
+#ifdef WPRFLAG
+int _CALLTYPE4 _winput(FILE *, const wchar_t *, va_list);
+#endif
+
+#ifdef CPRFLAG
+static int _CALLTYPE4 input(const unsigned char *, va_list);
+
+
+/***
+*int _cscanf(format, arglist) - read formatted input direct from console
+*
+*Purpose:
+* Reads formatted data like scanf, but uses console I/O functions.
+*
+*Entry:
+* char *format - format string to determine data formats
+* arglist - list of POINTERS to where to put data
+*
+*Exit:
+* returns number of successfully matched data items (from input)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+int _CALLTYPE2 _cscanf (
+ const char *format,
+ ...
+ )
+{
+ va_list arglist;
+
+ va_start(arglist, format);
+
+ assert(format != NULL);
+
+ return input(format,arglist); /* get the input */
+}
+
+#endif /* CPRFLAG */
+
+
+#define ASCII 32 /* # of bytes needed to hold 256 bits */
+
+#define SCAN_SHORT 0 /* also for FLOAT */
+#define SCAN_LONG 1 /* also for DOUBLE */
+#define SCAN_L_DOUBLE 2 /* only for LONG DOUBLE */
+
+#define SCAN_NEAR 0
+#define SCAN_FAR 1
+
+#ifdef ALLOW_RANGE
+
+static TCHAR sbrackset[] = _T(" \t-\r]"); /* use range-style list */
+
+#else
+
+static TCHAR sbrackset[] = _T(" \t\n\v\f\r]"); /* chars defined by isspace() */
+
+#endif
+
+static TCHAR cbrackset[] = _T("]");
+
+
+
+/***
+*int _input(stream, format, arglist), static int input(format, arglist)
+*
+*Purpose:
+* get input items (data items or literal matches) from the input stream
+* and assign them if appropriate to the items thru the arglist. this
+* function is intended for internal library use only, not for the user
+*
+* The _input entry point is for the normal scanf() functions
+* The input entry point is used when compiling for _cscanf() [CPRFLAF
+* defined] and is a static function called only by _cscanf() -- reads from
+* console.
+*
+*Entry:
+* FILE *stream - file to read from
+* char *format - format string to determine the data to read
+* arglist - list of pointer to data items
+*
+*Exit:
+* returns number of items assigned and fills in data items
+* returns EOF if error or EOF found on stream before 1st data item matched
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef _CRUISER_
+#pragma check_stack(on) /* large auto vars -- put stack checking on */
+#endif /* ndef _CRUISER_ */
+
+#ifdef CPRFLAG
+
+static int _CALLTYPE4 input (
+ const unsigned char *format,
+ va_list arglist
+ )
+#elif WPRFLAG
+
+int _CALLTYPE4 _winput (
+ FILE *stream,
+ const wchar_t *format,
+ va_list arglist
+ )
+#else
+
+int _CALLTYPE1 _input (
+ FILE *stream,
+ const unsigned char *format,
+ va_list arglist
+ )
+#endif
+
+{
+#ifndef WPRFLAG
+ char table[ASCII]; /* which chars allowed for %[], %s */
+ char floatstring[CVTBUFSIZE + 1]; /* ASCII buffer for floats */
+#else
+ char table[256*ASCII];
+ wchar_t floatstring[CVTBUFSIZE + 1];
+#endif
+
+ unsigned long number; /* temp hold-value */
+ void *pointer; /* points to user data receptacle */
+ void *start; /* indicate non-empty string */
+
+
+#ifdef WPRFLAG
+ unsigned short *scanptr; /* for building "table" data */
+REG2 wchar_t ch;
+#else
+ wchar_t wctemp;
+ unsigned char *scanptr; /* for building "table" data */
+REG2 int ch;
+#endif
+ int charcount; /* total number of chars read */
+REG1 int comchr; /* holds designator type */
+ int count; /* return value. # of assignments */
+
+ int started; /* indicate good number */
+ int width; /* width of field */
+ int widthset; /* user has specified width */
+
+/* Neither coerceshort nor farone are need for the 386 */
+
+
+ char done_flag; /* general purpose loop monitor */
+ char longone; /* 0 = SHORT, 1 = LONG, 2 = L_DOUBLE */
+ signed char widechar; /* -1 = char, 0 = ????, 1 = wchar_t */
+ char reject; /* %[^ABC] instead of %[ABC] */
+ char negative; /* flag for '-' detected */
+ char suppress; /* don't assign anything */
+ char match; /* flag: !0 if any fields matched */
+ va_list arglistsave; /* save arglist value */
+
+ char fl_wchar_arg; /* flags wide char/string argument */
+#ifdef WPRFLAG
+#ifdef ALLOW_RANGE
+ unsigned short rngch; /* used while scanning range */
+#endif
+ unsigned short last; /* also for %[a-z] */
+ unsigned short prevchar; /* for %[a-z] */
+ wchar_t wdecimal; /* wide version of decimal point */
+ wchar_t *wptr; /* pointer traverses wide floatstring*/
+#else
+#ifdef ALLOW_RANGE
+ unsigned char rngch; /* used while scanning range */
+#endif
+ unsigned char last; /* also for %[a-z] */
+ unsigned char prevchar; /* for %[a-z] */
+#endif
+
+ assert(format != NULL);
+
+#ifndef CPRFLAG
+ assert(stream != NULL);
+#endif
+
+ /*
+ count = # fields assigned
+ charcount = # chars read
+ match = flag indicating if any fields were matched
+
+ [Note that we need both count and match. For example, a field
+ may match a format but have assignments suppressed. In this case,
+ match will get set, but 'count' will still equal 0. We need to
+ distinguish 'match vs no-match' when terminating due to EOF.]
+ */
+
+ count = charcount = match = 0;
+
+ while (*format) {
+
+ if (_istspace((int)*format)) {
+
+ UN_INC(EAT_WHITE()); /* put first non-space char back */
+
+ while ((_istspace)(*++format)); /* NULL */
+ /* careful: isspace macro may evaluate argument more than once! */
+
+ }
+
+ if (_T('%') == *format) {
+
+ number = width = widthset = started = done_flag =
+
+ /* ints are the same size as longs and all pointers are 'near' for
+ the 386 */
+
+ prevchar = 0;
+ suppress = negative = reject = 0;
+ widechar = 0;
+ fl_wchar_arg = 0;
+ longone = 1;
+
+ while (!done_flag) {
+
+ comchr = *++format;
+ if (_istdigit(comchr)) {
+ ++widthset;
+ width = MUL10(width) + (comchr - _T('0'));
+ } else
+ switch (comchr) {
+ case _T('F') :
+ case _T('N') : /* no way to push NEAR in large model */
+ break; /* NEAR is default in small model */
+ case _T('h') :
+ /* set longone to 0 */
+ --longone;
+ --widechar; /* set widechar = -1 */
+ break;
+
+ case _T('L') :
+ /* ++longone; */
+ ++longone;
+ break;
+
+ case _T('l') :
+ ++longone;
+ /* NOBREAK */
+ case _T('w') :
+ ++widechar; /* set widechar = 1 */
+ break;
+
+ case _T('*') :
+ ++suppress;
+ break;
+
+ default:
+ ++done_flag;
+ break;
+ }
+ }
+
+ if (!suppress) {
+ arglistsave = arglist;
+ pointer = va_arg(arglist,void *);
+ }
+
+ done_flag = 0;
+
+ if (!widechar) { /* use case if not explicitly specified */
+ if ((*format == _T('S')) || (*format == _T('C')))
+#ifdef WPRFLAG
+ --widechar;
+ else
+ ++widechar;
+#else
+ ++widechar;
+ else
+ --widechar;
+#endif
+ }
+
+ /* switch to lowercase to allow %E,%G, and to
+ keep the switch table small */
+
+ comchr = *format | (_T('a') - _T('A'));
+
+ if (_T('n') != comchr)
+ if (_T('c') != comchr && LEFT_BRACKET != comchr)
+ ch = EAT_WHITE();
+ else
+ ch = INC();
+
+#ifdef _POSIX_
+ if (EOF == ch) {
+ goto error_return;
+ }
+#endif
+
+ if (!widthset || width) {
+
+ switch(comchr) {
+
+ case _T('c'):
+ /* case _T('C'): */
+ if (!widthset) {
+ ++widthset;
+ ++width;
+ }
+ if (widechar>0)
+ fl_wchar_arg++;
+ scanptr = cbrackset;
+ --reject; /* set reject to 255 */
+ goto scanit2;
+
+ case _T('s'):
+ /* case _T('S'): */
+ if (widechar>0)
+ fl_wchar_arg++;
+ scanptr = sbrackset;
+ --reject; /* set reject to 255 */
+ goto scanit2;
+
+ case LEFT_BRACKET : /* scanset */
+ if (widechar>0)
+ fl_wchar_arg++;
+ scanptr = (TCHAR *)(++format);
+
+ if (_T('^') == *scanptr) {
+ ++scanptr;
+ --reject; /* set reject to 255 */
+ }
+
+
+scanit2:
+#ifdef WPRFLAG
+ memset(table, 0, ASCII*256);
+#else
+ memset(table, 0, ASCII);
+#endif
+
+#ifdef ALLOW_RANGE
+
+ if (LEFT_BRACKET == comchr)
+ if (_T(']') == *scanptr) {
+ prevchar = _T(']');
+ ++scanptr;
+
+ table[ _T(']') >> 3] = 1 << (_T(']') & 7);
+
+ }
+
+ while (_T(']') != *scanptr) {
+
+ rngch = *scanptr++;
+
+ if (_T('-') != rngch ||
+ !prevchar || /* first char */
+ _T(']') == *scanptr) /* last char */
+
+ table[(prevchar = rngch) >> 3] |= 1 << (rngch & 7);
+
+ else { /* handle a-z type set */
+
+ rngch = *scanptr++; /* get end of range */
+
+ if (prevchar < rngch) /* %[a-z] */
+ last = rngch;
+ else { /* %[z-a] */
+ last = prevchar;
+ prevchar = rngch;
+ }
+ for (rngch = prevchar; rngch <= last; ++rngch)
+ table[rngch >> 3] |= 1 << (rngch & 7);
+
+ prevchar = 0;
+
+ }
+ }
+
+
+#else
+ if (LEFT_BRACKET == comchr)
+ if (_T(']') == *scanptr) {
+ ++scanptr;
+ table[(prevchar = _T(']')) >> 3] |= 1 << (_T(']') & 7);
+ }
+
+ while (_T(']') != *scanptr) {
+ table[scanptr >> 3] |= 1 << (scanptr & 7);
+ ++scanptr;
+ }
+ /* code under !ALLOW_RANGE is probably never compiled */
+ /* and has probably never been tested */
+#endif
+ if (!*scanptr)
+ goto error_return; /* trunc'd format string */
+
+ /* scanset completed. Now read string */
+
+ if (LEFT_BRACKET == comchr)
+ format = scanptr;
+
+ start = pointer;
+
+ /*
+ * execute the format directive. that is, scan input
+ * characters until the directive is fulfilled, eof
+ * is reached, or a non-matching character is
+ * encountered.
+ *
+ * it is important not to get the next character
+ * unless that character needs to be tested! other-
+ * wise, reads from line-buffered devices (e.g.,
+ * scanf()) would require an extra, spurious, newline
+ * if the first newline completes the current format
+ * directive.
+ */
+ UN_INC(ch);
+
+ while ( !widthset || width-- ) {
+
+ ch = INC();
+ if (
+#ifndef WPRFLAG
+#ifndef CPRFLAG
+ (EOF != ch) &&
+#endif
+ ((table[ch >> 3] ^ reject) & (1 << (ch & 7)))
+#else
+ (WEOF != ch) &&
+ /* ((ch>>3 >= ASCII) ? reject : */
+ ((table[ch >> 3] ^ reject) &
+ (1 << (ch & 7))) /* ) */
+#endif /* WPRFLAG */
+ ) {
+ if (!suppress) {
+#ifndef WPRFLAG
+ if (fl_wchar_arg) {
+ char temp[2];
+ temp[0] = (char) ch;
+ if (isleadbyte(ch))
+ temp[1] = (char) INC();
+ mbtowc(&wctemp, temp,
+ MB_CUR_MAX);
+ *(wchar_t UNALIGNED *)pointer = wctemp;
+ /* do nothing if mbtowc fails */
+ pointer = (wchar_t *)pointer + 1;
+ } else
+#else
+ if (fl_wchar_arg) {
+ *(wchar_t UNALIGNED *)pointer = ch;
+ pointer = (wchar_t *)pointer + 1;
+ } else
+#endif
+ {
+#ifndef WPRFLAG
+ *(char *)pointer = (char)ch;
+ pointer = (char *)pointer + 1;
+#else
+ int temp;
+ /* convert wide to multibyte */
+ temp = wctomb((char *)pointer, ch);
+ /* do nothing if wctomb fails */
+ pointer = (char *)pointer + temp;
+#endif
+ }
+ } /* suppress */
+ else {
+ /* just indicate a match */
+ start = (TCHAR *)start + 1;
+ }
+ }
+ else {
+ UN_INC(ch);
+ break;
+ }
+ }
+
+ /* make sure something has been matched and, if
+ assignment is not suppressed, null-terminate
+ output string if comchr != c */
+
+ if (start != pointer) {
+ if (!suppress) {
+ ++count;
+ if ('c' != comchr) /* null-terminate strings */
+ if (fl_wchar_arg)
+ *(wchar_t UNALIGNED *)pointer = L'\0';
+ else
+ *(char *)pointer = '\0';
+ } else /*NULL*/;
+ }
+ else
+ goto error_return;
+
+ break;
+
+ case _T('i') : /* could be d, o, or x */
+
+ comchr = _T('d'); /* use as default */
+
+ case _T('x'):
+
+ if (_T('-') == ch) {
+ ++negative;
+
+ goto x_incwidth;
+
+ } else if (_T('+') == ch) {
+x_incwidth:
+ if (!--width && widthset)
+ ++done_flag;
+ else
+ ch = INC();
+ }
+
+ if (_T('0') == ch) {
+
+ if (_T('x') == (TCHAR)(ch = INC()) || _T('X') == (TCHAR)ch) {
+ ch = INC();
+ comchr = _T('x');
+ } else {
+ ++started;
+ if (_T('x') != comchr)
+ comchr = _T('o');
+ else {
+ /* scanning a hex number that starts */
+ /* with a 0. push back the character */
+ /* currently in ch and restore the 0 */
+ UN_INC(ch);
+ ch = _T('0');
+ }
+ }
+ }
+ goto getnum;
+
+ /* NOTREACHED */
+
+ case _T('p') :
+ /* force %hp to be treated as %p */
+ longone = 1;
+
+ case _T('o') :
+ case _T('u') :
+ case _T('d') :
+
+ if (_T('-') == ch) {
+ ++negative;
+
+ goto d_incwidth;
+
+ } else if (_T('+') == ch) {
+d_incwidth:
+ if (!--width && widthset)
+ ++done_flag;
+ else
+ ch = INC();
+ }
+
+getnum:
+ while (!done_flag) {
+
+ if (_T('x') == comchr || _T('p') == comchr)
+
+ if (_istxdigit(ch)) {
+ number = (number << 4);
+ ch = HEXTODEC(ch);
+ }
+ else
+ ++done_flag;
+
+ else if (_istdigit(ch))
+
+ if (_T('o') == comchr)
+ if (_T('8') > ch)
+ number = (number << 3);
+ else {
+ ++done_flag;
+ }
+ else /* _T('d') == comchr */
+ number = MUL10(number);
+
+ else
+ ++done_flag;
+
+ if (!done_flag) {
+ ++started;
+ number += ch - _T('0');
+
+ if (widthset && !--width)
+ ++done_flag;
+ else
+ ch = INC();
+ } else
+ UN_INC(ch);
+
+ } /* end of WHILE loop */
+
+ if (negative)
+ number = (unsigned long)(-(long)number);
+
+ if (_T('F')==comchr) /* expected ':' in long pointer */
+ started = 0;
+
+ if (started)
+ if (!suppress) {
+
+ ++count;
+assign_num:
+ if (longone)
+ *(long UNALIGNED *)pointer = (unsigned long)number;
+ else
+ *(short UNALIGNED *)pointer = (unsigned short)number;
+
+ } else /*NULL*/;
+ else
+ goto error_return;
+
+ break;
+
+ case _T('n') : /* char count, don't inc return value */
+ number = charcount;
+ if(!suppress)
+ goto assign_num; /* found in number code above */
+ break;
+
+
+ case _T('e') :
+ /* case _T('E') : */
+ case _T('f') :
+ case _T('g') : /* scan a float */
+ /* case _T('G') : */
+
+#ifndef WPRFLAG
+ scanptr = floatstring;
+
+ if (_T('-') == ch) {
+ *scanptr++ = _T('-');
+ goto f_incwidth;
+
+ } else if (_T('+') == ch) {
+f_incwidth:
+ --width;
+ ch = INC();
+ }
+
+ if (!widthset || width > CVTBUFSIZE) /* must watch width */
+ width = CVTBUFSIZE;
+
+
+ /* now get integral part */
+
+ while (_istdigit(ch) && width--) {
+ ++started;
+ *scanptr++ = (char)ch;
+ ch = INC();
+ }
+
+ /* now check for decimal */
+
+ if (*__decimal_point == (char)ch && width--) {
+ ch = INC();
+ *scanptr++ = *__decimal_point;
+
+ while (_istdigit(ch) && width--) {
+ ++started;
+ *scanptr++ = (char)ch;
+ ch = INC();
+ }
+ }
+
+ /* now check for exponent */
+
+ if (started && (_T('e') == ch || _T('E') == ch) && width--) {
+ *scanptr++ = 'e';
+
+ if (_T('-') == (ch = INC())) {
+
+ *scanptr++ = '-';
+ goto f_incwidth2;
+
+ } else if (_T('+') == ch) {
+f_incwidth2:
+ if (!width--)
+ ++width;
+ else
+ ch = INC();
+ }
+
+
+ while (_istdigit(ch) && width--) {
+ ++started;
+ *scanptr++ = (char)ch;
+ ch = INC();
+ }
+
+ }
+
+ UN_INC(ch);
+
+ if (started)
+ if (!suppress) {
+ ++count;
+ *scanptr = '\0';
+ _fassign( longone-1, pointer , floatstring);
+ } else /*NULL */;
+ else
+ goto error_return;
+
+#else /* WPRFLAG */
+ wptr = floatstring;
+
+ if (L'-' == ch) {
+ *wptr++ = L'-';
+ goto f_incwidthw;
+
+ } else if (L'+' == ch) {
+f_incwidthw:
+ --width;
+ ch = INC();
+ }
+
+ if (!widthset || width > CVTBUFSIZE)
+ width = CVTBUFSIZE;
+
+
+ /* now get integral part */
+
+ while (iswdigit(ch) && width--) {
+ ++started;
+ *wptr++ = ch;
+ ch = INC();
+ }
+
+ /* now check for decimal */
+
+ /* convert decimal point to wide-char */
+ /* assume result is single wide-char */
+ mbtowc (&wdecimal, __decimal_point, MB_CUR_MAX);
+
+ if (wdecimal == ch && width--) {
+ ch = INC();
+ *wptr++ = wdecimal;
+
+ while (iswdigit(ch) && width--) {
+ ++started;
+ *wptr++ = ch;
+ ch = INC();
+ }
+ }
+
+ /* now check for exponent */
+
+ if (started && (L'e' == ch || L'E' == ch) && width--) {
+ *wptr++ = L'e';
+
+ if (L'-' == (ch = INC())) {
+
+ *wptr++ = L'-';
+ goto f_incwidth2w;
+
+ } else if (L'+' == ch) {
+f_incwidth2w:
+ if (!width--)
+ ++width;
+ else
+ ch = INC();
+ }
+
+
+ while (iswdigit(ch) && width--) {
+ ++started;
+ *wptr++ = ch;
+ ch = INC();
+ }
+
+ }
+
+ UN_INC(ch);
+
+ if (started)
+ if (!suppress) {
+ ++count;
+ *wptr = '\0';
+ {
+ /* convert floatstring to char string */
+ /* and do the conversion */
+ size_t cfslength;
+ char *cfloatstring;
+ cfslength =(wptr-floatstring+1)*sizeof(wchar_t);
+ cfloatstring = (char *)malloc (cfslength);
+ wcstombs (cfloatstring, floatstring, cfslength);
+ _fassign( longone-1, pointer , cfloatstring);
+ free (cfloatstring);
+ }
+ } else /*NULL */;
+ else
+ goto error_return;
+
+#endif /* WPRFLAG */
+ break;
+
+
+ default: /* either found '%' or something else */
+
+ if ((int)*format != (int)ch) {
+ UN_INC(ch);
+ goto error_return;
+ }
+ else
+ match--; /* % found, compensate for inc below */
+
+ if (!suppress)
+ arglist = arglistsave;
+
+ } /* SWITCH */
+
+ match++; /* matched a format field - set flag */
+
+ } /* WHILE (width) */
+
+ else { /* zero-width field in format string */
+ UN_INC(ch); /* check for input error */
+ goto error_return;
+ }
+
+ ++format; /* skip to next char */
+
+ } else /* ('%' != *format) */
+ {
+
+ if ((int)*format++ != (int)(ch = INC()))
+ {
+ UN_INC(ch);
+ goto error_return;
+ }
+#ifndef WPRFLAG
+ if (isleadbyte(ch))
+ {
+ int ch2;
+ if ((int)*format++ != (ch2=INC()))
+ {
+ UN_INC(ch2);
+ UN_INC(ch);
+ goto error_return;
+ }
+
+ --charcount; /* only count as one character read */
+ }
+#endif
+ }
+
+#ifndef CPRFLAG
+ if ( (EOF == ch) && ((*format != '%') || (*(format + 1) != 'n')) )
+ break;
+#endif
+
+ } /* WHILE (*format) */
+
+error_return:
+
+#ifndef CPRFLAG
+ if (EOF == ch)
+ /* If any fields were matched or assigned, return count */
+ return ( (count || match) ? count : EOF);
+ else
+#endif
+ return count;
+
+}
+
+#ifdef _CRUISER_
+#pragma check_stack(off) /* don't bother checking for one local */
+#endif /* ndef _CRUISER_ */
+
+/* _hextodec() returns a value of 0-15 and expects a char 0-9, a-f, A-F */
+/* _inc() is the one place where we put the actual getc code. */
+/* _whiteout() returns the first non-blank character, as defined by isspace() */
+
+#ifndef WPRFLAG
+static int _CALLTYPE4 _hextodec (
+ int chr
+ )
+{
+ return _istdigit(chr) ? chr : (chr & ~(_T('a') - _T('A'))) - _T('A') + 10 + _T('0');
+}
+#else
+static TCHAR _CALLTYPE4 _hextodec (
+ TCHAR chr
+ )
+{
+ if (_istdigit(chr))
+ return chr;
+ if (_istlower(chr))
+ return (TCHAR)(chr - _T('a') + 10 + _T('0'));
+ else
+ return (TCHAR)(chr - _T('A') + 10 + _T('0'));
+}
+#endif
+
+
+#ifdef CPRFLAG
+
+static int _CALLTYPE4 _inc (
+ void
+ )
+{
+ return(_getche_lk());
+}
+
+static int _CALLTYPE4 _whiteout (
+ REG1 int *counter
+ )
+{
+ REG2 int ch;
+
+ while((_istspace)(ch = (++*counter, _inc())));
+ return ch;
+}
+
+#elif WPRFLAG
+
+/*
+ * Manipulate wide-chars in a file.
+ * A wide-char is hard-coded to be two chars for efficiency.
+ */
+
+static wchar_t _CALLTYPE4 _inc (
+ REG1 FILE *fileptr
+ )
+{
+ return(_getwc_lk(fileptr));
+}
+
+static void _CALLTYPE4 _un_inc (
+ wchar_t chr,
+ FILE *fileptr
+ )
+{
+ if (WEOF != chr)
+ _ungetwc_lk(chr, fileptr);
+}
+
+static wchar_t _CALLTYPE4 _whiteout (
+ REG1 int *counter,
+ REG3 FILE *fileptr
+ )
+{
+ REG2 wchar_t ch;
+
+ while((iswspace)(ch = (++*counter, _inc(fileptr))));
+ return ch;
+}
+
+#else
+
+static int _CALLTYPE4 _inc (
+ REG1 FILE *fileptr
+ )
+{
+ return(_getc_lk(fileptr));
+}
+
+static void _CALLTYPE4 _un_inc (
+ int chr,
+ FILE *fileptr
+ )
+{
+ if (EOF != chr)
+ _ungetc_lk(chr, fileptr);
+}
+
+static int _CALLTYPE4 _whiteout (
+ REG1 int *counter,
+ REG3 FILE *fileptr
+ )
+{
+ REG2 int ch;
+
+ while((_istspace)(ch = (++*counter, _inc(fileptr))));
+ return ch;
+}
+
+#endif
diff --git a/private/crt32/stdio/makefile b/private/crt32/stdio/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/stdio/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/stdio/makefile.inc b/private/crt32/stdio/makefile.inc
new file mode 100644
index 000000000..42a30734a
--- /dev/null
+++ b/private/crt32/stdio/makefile.inc
@@ -0,0 +1,17 @@
+cprintf.c: output.c
+
+cscanf.c: input.c
+
+snprintf.c: sprintf.c
+
+vsnprint.c: vsprintf.c
+
+woutput.c: output.c
+
+snwprint.c: swprintf.c
+
+vsnwprnt.c: vswprint.c
+
+_flswbuf.c: _flsbuf.c
+
+_filwbuf.c: _filbuf.c
diff --git a/private/crt32/stdio/maketab.c b/private/crt32/stdio/maketab.c
new file mode 100644
index 000000000..39e9b59e4
--- /dev/null
+++ b/private/crt32/stdio/maketab.c
@@ -0,0 +1,101 @@
+/* make the lookup table for output.asm */
+
+#define TABLESIZE ('x' - ' ' + 1)
+
+
+/* possible states to be in */
+#define NORMAL 0 /* normal character to be output */
+#define PERCENT 1 /* just read percent sign */
+#define FLAG 2 /* just read a flag character */
+#define WIDTH 3 /* just read a width specification character */
+#define DOT 4 /* just read a dot between width and precision */
+#define PRECIS 5 /* just read a precision specification character */
+#define SIZE 6 /* just read a size specification character */
+#define TYPE 7 /* just read a conversion specification character */
+#define BOGUS 0 /* bogus state - print the character literally */
+
+#define NUMSTATES 8
+
+/* possible types of characters to read */
+#define CH_OTHER 0 /* character with no special meaning */
+#define CH_PERCENT 1 /* '%' */
+#define CH_DOT 2 /* '.' */
+#define CH_STAR 3 /* '*' */
+#define CH_ZERO 4 /* '0' */
+#define CH_DIGIT 5 /* '1'..'9' */
+#define CH_FLAG 6 /* ' ', '+', '-', '#' */
+#define CH_SIZE 7 /* 'h', 'l', 'L', 'N', 'F', 'w' */
+#define CH_TYPE 8 /* conversion specified character */
+
+#define NUMCHARS 9
+
+unsigned char table[TABLESIZE]; /* the table we build */
+
+
+
+/* this is the state table */
+
+int statetable[NUMSTATES][NUMCHARS] = {
+/* state, other % . * 0 digit flag size type */
+
+/* NORMAL */ { NORMAL, PERCENT, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL },
+/* PERCENT */ { BOGUS, NORMAL, DOT, WIDTH, FLAG, WIDTH, FLAG, SIZE, TYPE },
+/* FLAG */ { BOGUS, BOGUS, DOT, WIDTH, FLAG, WIDTH, FLAG, SIZE, TYPE },
+/* WIDTH */ { BOGUS, BOGUS, DOT, BOGUS, WIDTH, WIDTH, BOGUS, SIZE, TYPE },
+/* DOT */ { BOGUS, BOGUS, BOGUS, PRECIS, PRECIS, PRECIS, BOGUS, SIZE, TYPE },
+/* PRECIS */ { BOGUS, BOGUS, BOGUS, BOGUS, PRECIS, PRECIS, BOGUS, SIZE, TYPE },
+/* SIZE */ { BOGUS, BOGUS, BOGUS, BOGUS, BOGUS, BOGUS, BOGUS, SIZE, TYPE },
+/* TYPE */ { NORMAL, PERCENT, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL }
+};
+
+/* this determines what type of character ch is */
+
+static int chartype (
+ int ch
+ )
+{
+ if (ch < ' ' || ch > 'z')
+ return CH_OTHER;
+ if (ch == '%')
+ return CH_PERCENT;
+ if (ch == '.')
+ return CH_DOT;
+ if (ch == '*')
+ return CH_STAR;
+ if (ch == '0')
+ return CH_ZERO;
+ if (strchr("123456789", ch))
+ return CH_DIGIT;
+ if (strchr(" +-#", ch))
+ return CH_FLAG;
+ if (strchr("hlLNFw", ch))
+ return CH_SIZE;
+ if (strchr("diouxXfeEgGcspnCSZ", ch))
+ return CH_TYPE;
+ return CH_OTHER;
+}
+
+
+main()
+{
+ int ch;
+ int state, class;
+ int i;
+
+ for (ch = ' '; ch <= 'x'; ++ch) {
+ table[ch-' '] = chartype(ch);
+ }
+
+ for (state = NORMAL; state <= TYPE; ++state)
+ for (class = CH_OTHER; class <= CH_TYPE; ++class)
+ table[class*8+state] |= statetable[state][class]<<4;
+
+ for (i = 0; i < TABLESIZE; ++i) {
+ if (i % 8 == 0)
+ printf("\ndb\t %.2xh", table[i]);
+ else
+ printf(", %.2xh", table[i]);
+ }
+
+ return 0;
+}
diff --git a/private/crt32/stdio/maketabc.c b/private/crt32/stdio/maketabc.c
new file mode 100644
index 000000000..243f63788
--- /dev/null
+++ b/private/crt32/stdio/maketabc.c
@@ -0,0 +1,128 @@
+/***
+*maketabc.c - program to generate printf format specifier lookup table for
+* output.c
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This program writes to stdout the lookuptable values needed by
+* output.c
+*
+*Revision History:
+* 06-01-89 PHG Module created
+* 1-16-91 SRW Added extra format codes (_WIN32_)
+* 1-16-91 SRW Fixed output loop to put trailing comma on a line
+*
+*******************************************************************************/
+
+#define TABLESIZE ('x' - ' ' + 1)
+
+
+/* possible states to be in */
+#define NORMAL 0 /* normal character to be output */
+#define PERCENT 1 /* just read percent sign */
+#define FLAG 2 /* just read a flag character */
+#define WIDTH 3 /* just read a width specification character */
+#define DOT 4 /* just read a dot between width and precision */
+#define PRECIS 5 /* just read a precision specification character */
+#define SIZE 6 /* just read a size specification character */
+#define TYPE 7 /* just read a conversion specification character */
+#define BOGUS 0 /* bogus state - print the character literally */
+
+#define NUMSTATES 8
+
+/* possible types of characters to read */
+#define CH_OTHER 0 /* character with no special meaning */
+#define CH_PERCENT 1 /* '%' */
+#define CH_DOT 2 /* '.' */
+#define CH_STAR 3 /* '*' */
+#define CH_ZERO 4 /* '0' */
+#define CH_DIGIT 5 /* '1'..'9' */
+#define CH_FLAG 6 /* ' ', '+', '-', '#' */
+#define CH_SIZE 7 /* 'h', 'l', 'L', 'N', 'F' */
+#define CH_TYPE 8 /* conversion specified character */
+
+#define NUMCHARS 9
+
+unsigned char table[TABLESIZE]; /* the table we build */
+
+
+
+/* this is the state table */
+
+int statetable[NUMSTATES][NUMCHARS] = {
+/* state, other % . * 0 digit flag size type */
+
+/* NORMAL */ { NORMAL, PERCENT, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL },
+/* PERCENT */ { BOGUS, NORMAL, DOT, WIDTH, FLAG, WIDTH, FLAG, SIZE, TYPE },
+/* FLAG */ { BOGUS, BOGUS, DOT, WIDTH, FLAG, WIDTH, FLAG, SIZE, TYPE },
+/* WIDTH */ { BOGUS, BOGUS, DOT, BOGUS, WIDTH, WIDTH, BOGUS, SIZE, TYPE },
+/* DOT */ { BOGUS, BOGUS, BOGUS, PRECIS, PRECIS, PRECIS, BOGUS, SIZE, TYPE },
+/* PRECIS */ { BOGUS, BOGUS, BOGUS, BOGUS, PRECIS, PRECIS, BOGUS, SIZE, TYPE },
+/* SIZE */ { BOGUS, BOGUS, BOGUS, BOGUS, BOGUS, BOGUS, BOGUS, SIZE, TYPE },
+/* TYPE */ { NORMAL, PERCENT, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL }
+};
+
+/* this determines what type of character ch is */
+
+static int chartype (
+ int ch
+ )
+{
+ if (ch < ' ' || ch > 'z')
+ return CH_OTHER;
+ if (ch == '%')
+ return CH_PERCENT;
+ if (ch == '.')
+ return CH_DOT;
+ if (ch == '*')
+ return CH_STAR;
+ if (ch == '0')
+ return CH_ZERO;
+ if (strchr("123456789", ch))
+ return CH_DIGIT;
+ if (strchr(" +-#", ch))
+ return CH_FLAG;
+ if (strchr("hlLNF", ch))
+ return CH_SIZE;
+ if (strchr("diouxXfeEgGcspn", ch))
+ return CH_TYPE;
+#ifdef _WIN32_
+ /* Win32 supports three additional format codes for debugging purposes */
+
+ if (strchr("BCS", ch))
+ return CH_TYPE;
+#endif /* ifdef _WIN32_ */
+
+ return CH_OTHER;
+}
+
+
+main()
+{
+ int ch;
+ int state, class;
+ int i;
+
+ for (ch = ' '; ch <= 'x'; ++ch) {
+ table[ch-' '] = chartype(ch);
+ }
+
+ for (state = NORMAL; state <= TYPE; ++state)
+ for (class = CH_OTHER; class <= CH_TYPE; ++class)
+ table[class*8+state] |= statetable[state][class]<<4;
+
+ for (i = 0; i < TABLESIZE; ++i) {
+ if (i % 8 == 0) {
+ if (i != 0)
+ printf(",");
+
+ printf("\n\t 0x%.2X", table[i]);
+ }
+ else
+ printf(", 0x%.2X", table[i]);
+ }
+ printf("\n");
+
+ return 0;
+}
diff --git a/private/crt32/stdio/ncommode.c b/private/crt32/stdio/ncommode.c
new file mode 100644
index 000000000..1b1f33f82
--- /dev/null
+++ b/private/crt32/stdio/ncommode.c
@@ -0,0 +1,18 @@
+/***
+*ncommode.c - set global file commit mode flag to nocommit
+*
+* Copyright (c) 1990-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Sets the global file commit mode flag to nocommit. This is the default.
+*
+*Revision History:
+* 07-11-90 SBM Module created, based on asm version.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+
+/* set default file commit mode to nocommit */
+int _commode = 0;
diff --git a/private/crt32/stdio/output.c b/private/crt32/stdio/output.c
new file mode 100644
index 000000000..b2f85638f
--- /dev/null
+++ b/private/crt32/stdio/output.c
@@ -0,0 +1,1393 @@
+/***
+*output.c - printf style output to a FILE
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the code that does all the work for the
+* printf family of functions. It should not be called directly, only
+* by the *printf functions. We don't make any assumtions about the
+* sizes of ints, longs, shorts, or long doubles, but if types do overlap,
+* we also try to be efficient. We do assume that pointers are the same
+* size as either ints or longs.
+* If CPRFLAG is defined, defines _cprintf instead.
+* **** DOESN'T CURRENTLY DO MTHREAD LOCKING ****
+*
+*Revision History:
+* 06-01-89 PHG Module created
+* 08-28-89 JCR Added cast to get rid of warning (no object changes)
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 03-26-90 GJF Changed LOCAL macro to incorporate _CALLTYPE4. Placed
+* prototype for _output() in internal.h and #include-d
+* it.
+* 08-01-90 SBM Compiles cleanly with -W3, moved _cfltcvt_tab and
+* typedefs DOUBLE and LONGDOUBLE to new header
+* <fltintrn.h>, formerly named <struct.h>
+* 09-05-90 SBM First attempt at adding CPRFLAG and code to generate
+* cprintf. Anything in #ifdef CPRFLAG untested.
+* Still needs to have locking added for MTHREAD case.
+* 10-03-90 GJF New-style function declarators.
+* 01-02-91 SRW Added _WIN32_ conditional for 'C' and 'S' format chars.
+* 01-16-91 GJF ANSI naming.
+* 01-16-91 SRW Added #include of maketabc.out (_WIN32_)
+* 04-09-91 PNT Use the _CRUISER_ mapping for _MAC_
+* 04-16-91 SRW Fixed #include of maketabc.out (_WIN32_)
+* 04-25-91 SRW Made nullstring static
+* 05-20-91 GJF Moved state table for Win32 inline (_WIN32_).
+* 09-12-91 JCR Bumped conversion buffer size to be ANSI-compliant
+* 09-17-91 IHJ Add partial UNICODE (%ws, %wc) support
+* 09-28-91 GJF Merged with crt32 and crtdll versions. For now, 9-17-91
+* change is built only for Win32, not Dosx32 (_WIN32_).
+* 10-22-91 ETC Complete wchar_t/mb support under _INTL. For now,
+* 9-28-91 change is additionally under !_INTL. Bug fix:
+* ints and pointers are longs.
+* 11-19-91 ETC Added support for _wsprintf, _vwsprintf with WPRFLAG;
+* added %tc %ts (generic string handling).
+* 12-05-91 GDP Bug fix: va_arg was used inconsistently for double
+* 12-19-91 ETC Added some comments on wsprintf optimization, undones;
+* check return on malloc.
+* 03-25-92 DJM POSIX support
+* 04-16-92 KRS Support new ISO {s|f}wprintf with Unicode format string.
+* 06-08-92 SRW Modified to not use free and malloc for mbtowc conversion.
+* 06-10-92 KRS Fix glitch in previous change.
+* 07-14-92 TVB Added Alpha support (quad stuff).
+* 07-17-92 KRS Fix typo which broke WPRFLAG support.
+* 04-16-93 SKS Fix bug in 'S' option logic.
+* 07-16-93 SRW ALPHA Merge
+* 08-17-93 CFW Avoid mapping tchar macros incorrectly if _MBCS defined.
+*
+*******************************************************************************/
+
+/* temporary hack to minimize changes. This should go into fltintrn.h */
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+#define DOUBLE double
+#endif
+
+
+#include <cruntime.h>
+#include <limits.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <cvt.h>
+#include <conio.h>
+#include <internal.h>
+#include <fltintrn.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+
+/* inline keyword is non-ANSI C7 extension */
+/* CONSIDER: move to cruntime.h! */
+#if !defined(_MSC_VER) || defined(__STDC__)
+#define __inline static
+#else
+/* UNDONE: compiler is broken */
+#define __inline static
+#endif
+
+#if defined(WPRFLAG) && !defined(_UNICODE)
+#define _UNICODE 1
+#endif
+#ifdef _MBCS /* always want either Unicode or SBCS for tchar.h */
+#undef _MBCS
+#endif
+#include <tchar.h>
+
+/* this macro defines a function which is private and as fast as possible: */
+/* for example, in C 6.0, it might be static _fastcall <type> near. */
+#define LOCAL(x) static x _CALLTYPE4
+
+/* int/long/short/pointer sizes */
+
+/* the following should be set depending on the sizes of various types */
+#define LONG_IS_INT 1 /* 1 means long is same size as int */
+#define SHORT_IS_INT 0 /* 1 means short is same size as int */
+#define LONGDOUBLE_IS_DOUBLE 1 /* 1 means long double is same as double */
+#define PTR_IS_INT 1 /* 1 means ptr is same size as int */
+#define PTR_IS_LONG 1 /* 1 means ptr is same size as long */
+
+#if LONG_IS_INT
+ #define get_long_arg(x) (long)get_int_arg(x)
+#endif
+
+#ifndef WPRFLAG
+#if SHORT_IS_INT
+ #define get_short_arg(x) (short)get_int_arg(x)
+#endif
+#endif
+
+#if PTR_IS_INT
+ #define get_ptr_arg(x) (void *)get_int_arg(x)
+#elif PTR_IS_LONG
+ #define get_ptr_arg(x) (void *)get_long_arg(x)
+#else
+ #error Size of pointer must be same as size of int or long
+#endif
+
+
+
+/* CONSTANTS */
+
+/* size of conversion buffer (ANSI-specified minimum is 509) */
+
+#define BUFFERSIZE 512
+
+#if (BUFFERSIZE < CVTBUFSIZE)
+#error Conversion buffer too small for max double.
+#endif
+
+/* flag definitions */
+#define FL_SIGN 0x0001 /* put plus or minus in front */
+#define FL_SIGNSP 0x0002 /* put space or minus in front */
+#define FL_LEFT 0x0004 /* left justify */
+#define FL_LEADZERO 0x0008 /* pad with leading zeros */
+#define FL_LONG 0x0010 /* long value given */
+#define FL_SHORT 0x0020 /* short value given */
+#define FL_SIGNED 0x0040 /* signed data given */
+#define FL_ALTERNATE 0x0080 /* alternate form requested */
+#define FL_NEGATIVE 0x0100 /* value is negative */
+#define FL_FORCEOCTAL 0x0200 /* force leading '0' for octals */
+#define FL_LONGDOUBLE 0x0400 /* long double value given */
+#define FL_WIDECHAR 0x0800 /* wide characters */
+
+/* state definitions */
+enum STATE {
+ ST_NORMAL, /* normal state; outputting literal chars */
+ ST_PERCENT, /* just read '%' */
+ ST_FLAG, /* just read flag character */
+ ST_WIDTH, /* just read width specifier */
+ ST_DOT, /* just read '.' */
+ ST_PRECIS, /* just read precision specifier */
+ ST_SIZE, /* just read size specifier */
+ ST_TYPE /* just read type specifier */
+};
+#define NUMSTATES (ST_TYPE + 1)
+
+/* character type values */
+enum CHARTYPE {
+ CH_OTHER, /* character with no special meaning */
+ CH_PERCENT, /* '%' */
+ CH_DOT, /* '.' */
+ CH_STAR, /* '*' */
+ CH_ZERO, /* '0' */
+ CH_DIGIT, /* '1'..'9' */
+ CH_FLAG, /* ' ', '+', '-', '#' */
+ CH_SIZE, /* 'h', 'l', 'L', 'N', 'F', 'w' */
+ CH_TYPE /* type specifying character */
+};
+
+/* static data (read only, since we are re-entrant) */
+#if defined(WPRFLAG) || defined(CPRFLAG)
+extern char *__nullstring; /* string to print on null ptr */
+extern wchar_t *__wnullstring; /* string to print on null ptr */
+#else /* WPRFLAG || CPRFLAG */
+char *__nullstring = "(null)"; /* string to print on null ptr */
+wchar_t *__wnullstring = L"(null)";/* string to print on null ptr */
+#endif /* WPRFLAG || CPRFLAG */
+
+/* The state table. This table is actually two tables combined into one. */
+/* The lower nybble of each byte gives the character class of any */
+/* character; while the uper nybble of the byte gives the next state */
+/* to enter. See the macros below the table for details. */
+/* */
+/* The table is generated by maketabc.c -- use this program to make */
+/* changes. */
+
+#if defined(WPRFLAG) || defined(CPRFLAG)
+extern const char __lookuptable[];
+#else /* WPRFLAG/CPRFLAG */
+#if defined(_CRUISER_) || defined(_MAC_)
+
+/* Table generated by maketabc.c built with -D_CRUISER_. */
+
+const char __lookuptable[] = {
+ 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
+ 0x10, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x10,
+ 0x04, 0x45, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x35, 0x30, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x20, 0x38, 0x50, 0x58, 0x07, 0x08,
+ 0x00, 0x30, 0x30, 0x30, 0x57, 0x50, 0x07, 0x00,
+ 0x00, 0x20, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
+ 0x00, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x08,
+ 0x07, 0x08, 0x00, 0x00, 0x07, 0x00, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07,
+ 0x08
+};
+
+#else /* ndef _CRUISER_ || _MAC_ */
+
+#if defined(_WIN32_) || defined(_POSIX_)
+
+/* Table generated by maketabc.c built with -D_WIN32_. Defines additional */
+/* format code %Z for counted string. */
+
+const char __lookuptable[] = {
+ 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
+ 0x10, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x10,
+ 0x04, 0x45, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x35, 0x30, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x20, 0x38, 0x50, 0x58, 0x07, 0x08,
+ 0x00, 0x30, 0x30, 0x30, 0x57, 0x50, 0x07, 0x00,
+ 0x00, 0x20, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x60, 0x68, 0x60, 0x60, 0x60, 0x60, 0x00,
+ 0x00, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x08,
+ 0x07, 0x08, 0x00, 0x00, 0x07, 0x00, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07,
+ 0x08
+};
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER, WIN32, POSIX, OR MAC TARGET SUPPORTED!
+
+#endif /* _WIN32_ || _POSIX_ */
+
+#endif /* _CRUISER_ || _MAC_ */
+
+#endif /* WPRFLAG || CPRFLAG */
+
+#define find_char_class(c) \
+ ((c) < _T(' ') || (c) > _T('x') ? \
+ CH_OTHER \
+ : \
+ __lookuptable[(c)-_T(' ')] & 0xF)
+
+#define find_next_state(class, state) \
+ (__lookuptable[(class) * NUMSTATES + (state)] >> 4)
+
+
+/*
+ * Note: CPRFLAG and WPRFLAG cases are currently mutually exclusive.
+ */
+
+/* prototypes */
+
+#ifdef CPRFLAG
+
+#define WRITE_CHAR(ch, pnw) write_char(ch, pnw)
+#define WRITE_MULTI_CHAR(ch, num, pnw) write_multi_char(ch, num, pnw)
+#define WRITE_STRING(s, len, pnw) write_string(s, len, pnw)
+#define WRITE_WSTRING(s, len, pnw) write_wstring(s, len, pnw)
+
+LOCAL(void) write_char(int ch, int *pnumwritten);
+LOCAL(void) write_multi_char(int ch, int num, int *pnumwritten);
+LOCAL(void) write_string(char *string, int len, int *numwritten);
+LOCAL(void) write_wstring(wchar_t *string, int len, int *numwritten);
+
+#elif WPRFLAG
+
+#define WRITE_CHAR(ch, pnw) write_char(ch, stream, pnw)
+#define WRITE_MULTI_CHAR(ch, num, pnw) write_multi_char(ch, num, stream, pnw)
+#define WRITE_STRING(s, len, pnw) write_string(s, len, stream, pnw)
+
+LOCAL(void) write_char(int ch, FILE *f, int *pnumwritten);
+LOCAL(void) write_multi_char(wchar_t ch, int num, FILE *f, int *pnumwritten);
+LOCAL(void) write_string(wchar_t *string, int len, FILE *f, int *numwritten);
+
+#else
+
+#define WRITE_CHAR(ch, pnw) write_char(ch, stream, pnw)
+#define WRITE_MULTI_CHAR(ch, num, pnw) write_multi_char(ch, num, stream, pnw)
+#define WRITE_STRING(s, len, pnw) write_string(s, len, stream, pnw)
+#define WRITE_WSTRING(s, len, pnw) write_wstring(s, len, stream, pnw)
+
+LOCAL(void) write_char(int ch, FILE *f, int *pnumwritten);
+LOCAL(void) write_multi_char(int ch, int num, FILE *f, int *pnumwritten);
+LOCAL(void) write_string(char *string, int len, FILE *f, int *numwritten);
+LOCAL(void) write_wstring(wchar_t *string, int len, FILE *f, int *numwritten);
+
+#endif
+
+__inline int _CALLTYPE4 get_int_arg(va_list *pargptr);
+
+#ifndef WPRFLAG
+#if !SHORT_IS_INT
+__inline short _CALLTYPE4 get_short_arg(va_list *pargptr);
+#endif
+#endif
+
+#if !LONG_IS_INT
+__inline long _CALLTYPE4 get_long_arg(va_list *pargptr);
+#endif
+
+#ifdef _ALPHA_
+__inline __int64 _CALLTYPE4 get_quad_arg(va_list *pargptr);
+#endif
+
+#ifdef CPRFLAG
+LOCAL(int) output(const char *, va_list);
+
+/***
+*int _cprintf(format, arglist) - write formatted output directly to console
+*
+*Purpose:
+* Writes formatted data like printf, but uses console I/O functions.
+*
+*Entry:
+* char *format - format string to determine data formats
+* arglist - list of POINTERS to where to put data
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 _cprintf (
+ const char * format,
+ ...
+ )
+{
+ va_list arglist;
+
+ va_start(arglist, format);
+
+ return output(format, arglist);
+}
+
+#endif /* CPRFLAG */
+
+
+/***
+*int _output(stream, format, argptr), static int output(format, argptr)
+*
+*Purpose:
+* Output performs printf style output onto a stream. It is called by
+* printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to so the dirty
+* work. In multi-thread situations, _output assumes that the given
+* stream is already locked.
+*
+* Algorithm:
+* The format string is parsed by using a finite state automaton
+* based on the current state and the current character read from
+* the format string. Thus, looping is on a per-character basis,
+* not a per conversion specifier basis. Once the format specififying
+* character is read, output is performed.
+*
+*Entry:
+* FILE *stream - stream for output
+* char *format - printf style format string
+* va_list argptr - pointer to list of subsidiary arguments
+*
+*Exit:
+* Returns the number of characters written, or -1 if an output error
+* occurs.
+#ifdef WPRFLAG
+* The wide-character flavour returns the number of wide-characters written.
+#endif
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef CPRFLAG
+LOCAL(int) output (
+#elif WPRFLAG
+int _CALLTYPE1 _woutput (
+ FILE *stream,
+#else
+int _CALLTYPE1 _output (
+ FILE *stream,
+#endif
+ const TCHAR *format,
+ va_list argptr
+ )
+{
+ int hexadd; /* offset to add to number to get 'a'..'f' */
+ TCHAR ch; /* character just read */
+ int flags; /* flag word -- see #defines above for flag values */
+ enum STATE state; /* current state */
+ enum CHARTYPE chclass; /* class of current character */
+ int radix; /* current conversion radix */
+ int charsout; /* characters currently written so far, -1 = IO error */
+ int fldwidth; /* selected field width -- 0 means default */
+ int precision; /* selected precision -- -1 means default */
+ TCHAR prefix[2]; /* numeric prefix -- up to two characters */
+ int prefixlen; /* length of prefix -- 0 means no prefix */
+ int capexp; /* non-zero = 'E' exponent signifient, zero = 'e' */
+ int no_output; /* non-zero = prodcue no output for this specifier */
+ union {
+ char *sz; /* pointer text to be printed, not zero terminated */
+ wchar_t *wz;
+ } text;
+
+ int textlen; /* length of the text in bytes/wchars to be printed.
+ textlen is in multibyte or wide chars if WPRFLAG */
+ union {
+ char sz[BUFFERSIZE];
+#ifdef WPRFLAG
+ wchar_t wz[BUFFERSIZE];
+#endif
+ } buffer;
+ wchar_t wchar; /* temp wchar_t */
+ int bufferiswide; /* non-zero = buffer contains wide chars already */
+
+ charsout = 0; /* no characters written yet */
+ state = ST_NORMAL; /* starting state */
+
+ /* main loop -- loop while format character exist and no I/O errors */
+ while ((ch = *format++) != _T('\0') && charsout >= 0) {
+ chclass = find_char_class(ch); /* find character class */
+ state = find_next_state(chclass, state); /* find next state */
+
+ /* execute code for each state */
+ switch (state) {
+
+ case ST_NORMAL:
+ /* normal state -- just write character */
+#ifdef WPRFLAG
+ bufferiswide = 1;
+#else
+ bufferiswide = 0;
+ if (isleadbyte((int)(unsigned char)ch)) {
+ WRITE_CHAR(ch, &charsout);
+ ch = *format++;
+ assert (ch != _T('\0')); /* UNDONE: don't fall off format string */
+ }
+#endif /* !WPRFLAG */
+ WRITE_CHAR(ch, &charsout);
+ break;
+
+ case ST_PERCENT:
+ /* set default value of conversion parameters */
+ prefixlen = fldwidth = no_output = capexp = 0;
+ flags = 0;
+ precision = -1;
+ bufferiswide = 0; /* default */
+ break;
+
+ case ST_FLAG:
+ /* set flag based on which flag character */
+ switch (ch) {
+ case _T('-'):
+ flags |= FL_LEFT; /* '-' => left justify */
+ break;
+ case _T('+'):
+ flags |= FL_SIGN; /* '+' => force sign indicator */
+ break;
+ case _T(' '):
+ flags |= FL_SIGNSP; /* ' ' => force sign or space */
+ break;
+ case _T('#'):
+ flags |= FL_ALTERNATE; /* '#' => alternate form */
+ break;
+ case _T('0'):
+ flags |= FL_LEADZERO; /* '0' => pad with leading zeros */
+ break;
+ }
+ break;
+
+ case ST_WIDTH:
+ /* update width value */
+ if (ch == _T('*')) {
+ /* get width from arg list */
+ fldwidth = get_int_arg(&argptr);
+ if (fldwidth < 0) {
+ /* ANSI says neg fld width means '-' flag and pos width */
+ flags |= FL_LEFT;
+ fldwidth = -fldwidth;
+ }
+ }
+ else {
+ /* add digit to current field width */
+ fldwidth = fldwidth * 10 + (ch - _T('0'));
+ }
+ break;
+
+ case ST_DOT:
+ /* zero the precision, since dot with no number means 0
+ not default, according to ANSI */
+ precision = 0;
+ break;
+
+ case ST_PRECIS:
+ /* update precison value */
+ if (ch == _T('*')) {
+ /* get precision from arg list */
+ precision = get_int_arg(&argptr);
+ if (precision < 0)
+ precision = -1; /* neg precision means default */
+ }
+ else {
+ /* add digit to current precision */
+ precision = precision * 10 + (ch - _T('0'));
+ }
+ break;
+
+ case ST_SIZE:
+ /* just read a size specifier, set the flags based on it */
+ switch (ch) {
+#if !LONG_IS_INT || !defined(_UNICODE)
+ case _T('l'):
+ flags |= FL_LONG; /* 'l' => long int or wchar_t */
+ break;
+#endif
+
+#if !LONGDOUBLE_IS_DOUBLE || defined(_ALPHA_)
+ /*
+ * Alpha has native 64-bit integer registers and operations.
+ * The int and long types are 32 bits and an Alpha specific
+ * __int64 type is 64 bits. We also use the 'L' flag for
+ * integer arguments to indicate 64-bit conversions (%Lx).
+ */
+
+ case _T('L'):
+ flags |= FL_LONGDOUBLE; /* 'L' => long double */
+ break;
+#endif
+
+#if !SHORT_IS_INT || defined(_UNICODE)
+ case _T('h'):
+ flags |= FL_SHORT; /* 'h' => short int or char */
+ break;
+#endif
+
+/* UNDONE: support %wc and %ws for now only for compatibility */
+ case _T('w'):
+ flags |= FL_WIDECHAR; /* 'w' => wide character */
+ break;
+
+ }
+ break;
+
+ case ST_TYPE:
+ /* we have finally read the actual type character, so we */
+ /* now format and "print" the output. We use a big switch */
+ /* statement that sets 'text' to point to the text that should */
+ /* be printed, and 'textlen' to the length of this text. */
+ /* Common code later on takes care of justifying it and */
+ /* other miscellaneous chores. Note that cases share code, */
+ /* in particular, all integer formatting is done in one place. */
+ /* Look at those funky goto statements! */
+
+ switch (ch) {
+
+ case _T('C'): /* ISO wide character */
+ if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
+#ifdef WPRFLAG
+ /* CONSIDER: non-standard */
+ flags |= FL_SHORT;
+#else
+ flags |= FL_WIDECHAR; /* ISO std. */
+#endif
+ /* fall into 'c' case */
+
+ case _T('c'): {
+ /* print a single character specified by int argument */
+#ifdef WPRFLAG
+ bufferiswide = 1;
+ wchar = (wchar_t) get_int_arg(&argptr);
+ if (flags & FL_SHORT)
+ {
+ /* format multibyte character */
+ /* this is an extension of ANSI */
+ char tempchar[2];
+#ifdef _OUT
+ if (isleadbyte(wchar >> 8))
+ {
+ tempchar[0] = (wchar >> 8);
+ tempchar[1] = (wchar & 0x00ff);
+ }
+ else
+#endif /* _OUT */
+ {
+ tempchar[0] = (char)(wchar & 0x00ff);
+ tempchar[1] = '\0';
+ }
+ if (mbtowc(buffer.wz,tempchar,MB_CUR_MAX) < 0)
+ {
+ /* ignore if conversion was unsuccessful */
+ no_output = 1;
+ }
+ }
+ else
+ {
+ buffer.wz[0] = wchar;
+ }
+ text.wz = buffer.wz;
+ textlen = 1; /* print just a single character */
+#else /* WPRFLAG */
+ if (flags & (FL_LONG|FL_WIDECHAR))
+ {
+ wchar = (wchar_t) get_short_arg(&argptr);
+ /* convert to multibyte character */
+ textlen = wctomb(buffer.sz, wchar);
+
+ /* check that conversion was successful */
+ if (textlen < 0)
+ no_output = 1;
+ }
+ else
+ {
+ /* format multibyte character */
+ /* this is an extension of ANSI */
+ unsigned short temp;
+ temp = (unsigned short) get_int_arg(&argptr);
+#ifdef _OUT
+ if (isleadbyte(temp >> 8))
+ {
+ buffer.sz[0] = temp >> 8;
+ buffer.sz[1] = temp & 0x00ff;
+ textlen = 2;
+ }
+ else
+#endif /* _OUT */
+ {
+ buffer.sz[0] = (char) temp;
+ textlen = 1;
+ }
+ }
+ text.sz = buffer.sz;
+#endif /* WPRFLAG */
+ }
+ break;
+
+#if defined(_WIN32_) && !defined(_DOSX32_) /* UNDONE: NT hack */
+ case _T('Z'): {
+ /* print a Counted String
+
+ int i;
+ char *p; /* temps */
+ struct string {
+ short Length;
+ short MaximumLength;
+ char *Buffer;
+ } *pstr;
+
+ pstr = get_ptr_arg(&argptr);
+ if (pstr == NULL || pstr->Buffer == NULL) {
+ /* null ptr passed, use special string */
+ text.sz = __nullstring;
+ textlen = strlen(text.sz);
+ } else {
+ if (flags & FL_WIDECHAR) {
+ text.wz = (wchar_t *)pstr->Buffer;
+ textlen = pstr->Length / sizeof(wchar_t);
+ bufferiswide = 1;
+ } else {
+ bufferiswide = 0;
+ text.sz = pstr->Buffer;
+ textlen = pstr->Length;
+ }
+ }
+ }
+ break;
+#endif
+
+ case _T('S'): /* ISO wide character string */
+#ifndef WPRFLAG
+ if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
+ flags |= FL_WIDECHAR;
+#else
+ if (!(flags & (FL_SHORT|FL_LONG|FL_WIDECHAR)))
+ flags |= FL_SHORT;
+#endif
+ case _T('s'): {
+ /* print a string -- */
+ /* ANSI rules on how much of string to print: */
+ /* all if precision is default, */
+ /* min(precision, length) if precision given. */
+ /* prints '(null)' if a null string is passed */
+
+ int i;
+ char *p; /* temps */
+ wchar_t *pwch;
+
+ /* At this point it is tempting to use strlen(), but */
+ /* if a precision is specified, we're not allowed to */
+ /* scan past there, because there might be no null */
+ /* at all. Thus, we must do our own scan. */
+
+ i = (precision == -1) ? INT_MAX : precision;
+ text.sz = get_ptr_arg(&argptr);
+
+/* UNDONE: handle '#' case properly */
+ /* scan for null upto i characters */
+#ifdef WPRFLAG
+ if (flags & FL_SHORT)
+ {
+ if (text.sz == NULL) /* NULL passed, use special string */
+ text.sz = __nullstring;
+ p = text.sz;
+ for (textlen=0; textlen<i && *p; textlen++)
+ {
+ if (isleadbyte((int)*p))
+ ++p;
+ ++p;
+ }
+ /* textlen now contains length in multibyte chars */
+ }
+ else
+ {
+ if (text.wz == NULL) /* NULL passed, use special string */
+ text.wz = __wnullstring;
+ bufferiswide = 1;
+ pwch = text.wz;
+ while (i-- && *pwch)
+ ++pwch;
+ textlen = pwch - text.wz; /* in wchar_ts */
+ /* textlen now contains length in wide chars */
+ }
+#else /* WPRFLAG */
+ if (flags & (FL_LONG|FL_WIDECHAR))
+ {
+ size_t temp;
+ char tchr[MB_LEN_MAX];
+ if (text.wz == NULL) /* NULL passed, use special string */
+ text.wz = __wnullstring;
+ bufferiswide = 1;
+ pwch = text.wz;
+ for (textlen=0; textlen<i && *pwch; pwch++)
+ {
+ if ((temp = wctomb(tchr, *pwch))<=0) break;
+ textlen += temp;
+ }
+ /* textlen now contains length in bytes */
+ }
+ else
+ {
+ if (text.sz == NULL) /* NULL passed, use special string */
+ text.sz = __nullstring;
+ p = text.sz;
+ while (i-- && *p)
+ ++p;
+ textlen = p - text.sz; /* length of the string */
+ }
+
+#endif /* WPRFLAG */
+ }
+ break;
+
+
+ case _T('n'): {
+ /* write count of characters seen so far into */
+ /* short/int/long thru ptr read from args */
+
+ void *p; /* temp */
+
+ p = get_ptr_arg(&argptr);
+
+ /* store chars out into short/long/int depending on flags */
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ *(long *)p = charsout;
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT)
+ *(short *)p = (short) charsout;
+ else
+#endif
+ *(int *)p = charsout;
+
+ no_output = 1; /* force no output */
+ }
+ break;
+
+
+ case _T('E'):
+ case _T('G'):
+ capexp = 1; /* capitalize exponent */
+ ch += _T('a') - _T('A'); /* convert format char to lower */
+ /* DROP THROUGH */
+ case _T('e'):
+ case _T('f'):
+ case _T('g'): {
+ /* floating point conversion -- we call cfltcvt routines */
+ /* to do the work for us. */
+ flags |= FL_SIGNED; /* floating point is signed conversion */
+ text.sz = buffer.sz; /* put result in buffer */
+
+ /* compute the precision value */
+ if (precision < 0)
+ precision = 6; /* default precision: 6 */
+ else if (precision == 0 && ch == _T('g'))
+ precision = 1; /* ANSI specified */
+
+#if !LONGDOUBLE_IS_DOUBLE
+ /* do the conversion */
+ if (flags & FL_LONGDOUBLE) {
+ LONGDOUBLE tmp;
+ tmp=va_arg(argptr, LONGDOUBLE);
+ /* Note: assumes ch is in ASCII range */
+ _cldcvt(&tmp, text.sz, (char)ch, precision, capexp);
+ }
+ else
+#endif
+ {
+ DOUBLE tmp;
+ tmp=va_arg(argptr, DOUBLE);
+ /* Note: assumes ch is in ASCII range */
+ _cfltcvt(&tmp,text.sz, (char)ch, precision, capexp);
+ }
+
+ /* '#' and precision == 0 means force a decimal point */
+ if ((flags & FL_ALTERNATE) && precision == 0)
+ _forcdecpt(text.sz);
+
+ /* 'g' format means crop zero unless '#' given */
+ if (ch == _T('g') && !(flags & FL_ALTERNATE))
+ _cropzeros(text.sz);
+
+ /* check if result was negative, save '-' for later */
+ /* and point to positive part (this is for '0' padding) */
+ if (*text.sz == '-') {
+ flags |= FL_NEGATIVE;
+ ++text.sz;
+ }
+
+ textlen = strlen(text.sz); /* compute length of text */
+ }
+ break;
+
+ case _T('d'):
+ case _T('i'):
+ /* signed decimal output */
+ flags |= FL_SIGNED;
+ radix = 10;
+ goto COMMON_INT;
+
+ case _T('u'):
+ radix = 10;
+ goto COMMON_INT;
+
+ case _T('p'):
+ /* write a pointer -- this is like an integer or long */
+ /* except we force precision to pad with zeros and */
+ /* output in big hex. */
+
+ precision = 2 * sizeof(void *); /* number of hex digits needed */
+#if !PTR_IS_INT
+ flags |= FL_LONG; /* assume we're converting a long */
+#endif
+ /* DROP THROUGH to hex formatting */
+
+ case _T('X'):
+ /* unsigned upper hex output */
+ hexadd = _T('A') - _T('9') - 1; /* set hexadd for uppercase hex */
+ goto COMMON_HEX;
+
+ case _T('x'):
+ /* unsigned lower hex output */
+ hexadd = _T('a') - _T('9') - 1; /* set hexadd for lowercase hex */
+ /* DROP THROUGH TO COMMON_HEX */
+
+ COMMON_HEX:
+ radix = 16;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means '0x' prefix */
+ prefix[0] = _T('0');
+ prefix[1] = (TCHAR)(_T('x') - _T('a') + _T('9') + 1 + hexadd); /* 'x' or 'X' */
+ prefixlen = 2;
+ }
+ goto COMMON_INT;
+
+ case _T('o'):
+ /* unsigned octal output */
+ radix = 8;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means force a leading 0 */
+ flags |= FL_FORCEOCTAL;
+ }
+ /* DROP THROUGH to COMMON_INT */
+
+ COMMON_INT: {
+ /* This is the general integer formatting routine. */
+ /* Basically, we get an argument, make it positive */
+ /* if necessary, and convert it according to the */
+ /* correct radix, setting text and textlen */
+ /* appropriately. */
+
+#ifdef _ALPHA_
+ unsigned __int64 number; /* number to convert */
+ int digit; /* ascii value of digit */
+ __int64 l; /* temp long value */
+#else
+ unsigned long number; /* number to convert */
+ int digit; /* ascii value of digit */
+ long l; /* temp long value */
+#endif
+
+ /* 1. read argument into l, sign extend as needed */
+#ifdef _ALPHA_
+ if (flags & FL_LONGDOUBLE)
+ l = get_quad_arg(&argptr);
+ else
+#endif
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ l = get_long_arg(&argptr);
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT) {
+ if (flags & FL_SIGNED)
+ l = (short) get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned short) get_int_arg(&argptr); /* zero-extend*/
+ }
+ else
+#endif
+ {
+ if (flags & FL_SIGNED)
+ l = get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned int) get_int_arg(&argptr); /* zero-extend*/
+ }
+
+ /* 2. check for negative; copy into number */
+ if ( (flags & FL_SIGNED) && l < 0) {
+ number = -l;
+ flags |= FL_NEGATIVE; /* remember negative sign */
+ }
+ else {
+ number = l;
+ }
+#ifdef _ALPHA_
+ if ((flags & FL_LONGDOUBLE) == 0) {
+ /*
+ * Unless printing a full 64-bit value, insure values
+ * here are not in cananical longword format to prevent
+ * the sign extended upper 32-bits from being printed.
+ */
+ number &= 0xffffffff;
+ }
+#endif
+
+ /* 3. check precision value for default; non-default */
+ /* turns off 0 flag, according to ANSI. */
+ if (precision < 0)
+ precision = 1; /* default precision */
+ else
+ flags &= ~FL_LEADZERO;
+
+ /* 4. Check if data is 0; if so, turn off hex prefix */
+ if (number == 0)
+ prefixlen = 0;
+
+ /* 5. Convert data to ASCII -- note if precision is zero */
+ /* and number is zero, we get no digits at all. */
+
+ text.sz = &buffer.sz[BUFFERSIZE-1]; /* last digit at end of buffer */
+
+ while (precision-- > 0 || number != 0) {
+ digit = (int)(number % radix) + '0';
+ number /= radix; /* reduce number */
+ if (digit > '9') {
+ /* a hex digit, make it a letter */
+ digit += hexadd;
+ }
+ *text.sz-- = (char)digit; /* store the digit */
+ }
+
+ textlen = (char *)&buffer.sz[BUFFERSIZE-1] - text.sz; /* compute length of number */
+ ++text.sz; /* text points to first digit now */
+
+
+ /* 6. Force a leading zero if FORCEOCTAL flag set */
+ if ((flags & FL_FORCEOCTAL) && (text.sz[0] != '0' || textlen == 0)) {
+ *--text.sz = '0';
+ ++textlen; /* add a zero */
+ }
+ }
+ break;
+ }
+
+ /* At this point, we have done the specific conversion, and */
+ /* 'text' points to text to print; 'textlen' is length. Now we */
+ /* justify it, put on prefixes, leading zeros, and then */
+ /* print it. */
+
+ if (!no_output) {
+ int padding; /* amount of padding, negative means zero */
+
+ if (flags & FL_SIGNED) {
+ if (flags & FL_NEGATIVE) {
+ /* prefix is a '-' */
+ prefix[0] = _T('-');
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGN) {
+ /* prefix is '+' */
+ prefix[0] = _T('+');
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGNSP) {
+ /* prefix is ' ' */
+ prefix[0] = _T(' ');
+ prefixlen = 1;
+ }
+ }
+
+ /* calculate amount of padding -- might be negative, */
+ /* but this will just mean zero */
+ padding = fldwidth - textlen - prefixlen;
+
+ /* put out the padding, prefix, and text, in the correct order */
+
+ if (!(flags & (FL_LEFT | FL_LEADZERO))) {
+ /* pad on left with blanks */
+ WRITE_MULTI_CHAR(_T(' '), padding, &charsout);
+ }
+
+ /* write prefix */
+ WRITE_STRING(prefix, prefixlen, &charsout);
+
+ if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) {
+ /* write leading zeros */
+ WRITE_MULTI_CHAR(_T('0'), padding, &charsout);
+ }
+
+ /* write text */
+#ifndef WPRFLAG
+ if (bufferiswide && (textlen > 0))
+ {
+ wchar_t *p;
+ int retval, count;
+ char buffer[MB_LEN_MAX+1];
+
+ p = text.wz;
+ count = textlen;
+ while (count--) {
+ retval = wctomb(buffer, *p++);
+ if (retval <= 0)
+ break;
+ WRITE_STRING(buffer, retval, &charsout);
+ }
+ }
+ else
+ {
+ WRITE_STRING(text.sz, textlen, &charsout);
+ }
+#else
+ if (!bufferiswide && textlen > 0) {
+ char *p;
+ int retval, count;
+
+ p = text.sz;
+ count = textlen;
+ while (count-- > 0) {
+ retval = mbtowc(&wchar, p, MB_CUR_MAX);
+ if (retval <= 0)
+ break;
+ WRITE_CHAR(wchar, &charsout);
+ p += retval;
+ }
+ } else {
+ WRITE_STRING(text.wz, textlen, &charsout);
+ }
+#endif /* WPRFLAG */
+
+ if (flags & FL_LEFT) {
+ /* pad on right with blanks */
+ WRITE_MULTI_CHAR(_T(' '), padding, &charsout);
+ }
+
+ /* we're done! */
+ }
+ break;
+ }
+ }
+
+ return charsout; /* return value = number of characters written */
+}
+
+/*
+ * Future Optimizations for swprintf:
+ * - Don't free the memory used for converting the buffer to wide chars.
+ * Use realloc if the memory is not sufficient. Free it at the end.
+ */
+
+/***
+*void write_char(int ch, int *pnumwritten)
+#ifdef WPRFLAG
+*void write_char(wchar_t ch, FILE *f, int *pnumwritten)
+#endif
+*void write_char(int ch, FILE *f, int *pnumwritten)
+*
+*Purpose:
+* Writes a single character to the given file/console. If no error occurs,
+* then *pnumwritten is incremented; otherwise, *pnumwritten is set
+* to -1.
+*
+*Entry:
+* int ch - character to write
+* FILE *f - file to write to
+* int *pnumwritten - pointer to integer to update with total chars written
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef CPRFLAG
+
+LOCAL(void) write_char (
+ int ch,
+ int *pnumwritten
+ )
+{
+ if (_putch_lk(ch) == EOF)
+ *pnumwritten = -1;
+ else
+ ++(*pnumwritten);
+}
+
+#elif WPRFLAG
+
+LOCAL(void) write_char (
+ int ch,
+ FILE *f,
+ int *pnumwritten
+ )
+{
+ if (_putwc_lk(ch, f) == WEOF)
+ *pnumwritten = -1;
+ else
+ ++(*pnumwritten);
+}
+
+#else
+
+LOCAL(void) write_char (
+ int ch,
+ FILE *f,
+ int *pnumwritten
+ )
+{
+ if (_putc_lk(ch, f) == EOF)
+ *pnumwritten = -1;
+ else
+ ++(*pnumwritten);
+}
+
+#endif
+
+/***
+*void write_multi_char(int ch, int num, int *pnumwritten)
+#ifdef WPRFLAG
+*void write_multi_char(wchar_t ch, int num, FILE *f, int *pnumwritten)
+#endif
+*void write_multi_char(int ch, int num, FILE *f, int *pnumwritten)
+*
+*Purpose:
+* Writes num copies of a character to the given file/console. If no error occurs,
+* then *pnumwritten is incremented by num; otherwise, *pnumwritten is set
+* to -1. If num is negative, it is treated as zero.
+*
+*Entry:
+* int ch - character to write
+* int num - number of times to write the characters
+* FILE *f - file to write to
+* int *pnumwritten - pointer to integer to update with total chars written
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef CPRFLAG
+
+LOCAL(void) write_multi_char (
+ int ch,
+ int num,
+ int *pnumwritten
+ )
+{
+ while (num-- > 0)
+ write_char(ch, pnumwritten);
+}
+
+#else /* CPRFLAG */
+#if WPRFLAG
+
+LOCAL(void) write_multi_char (
+ wchar_t ch,
+ int num,
+ FILE *f,
+ int *pnumwritten
+ )
+#else
+
+LOCAL(void) write_multi_char (
+ int ch,
+ int num,
+ FILE *f,
+ int *pnumwritten
+ )
+#endif /* WPRFLAG */
+{
+ while (num-- > 0)
+ write_char(ch, f, pnumwritten);
+}
+
+#endif /* CPRFLAG */
+
+/***
+*void write_string(char *string, int len, int *pnumwritten)
+*void write_string(char *string, int len, FILE *f, int *pnumwritten)
+#ifdef WPRFLAG
+*void write_string(wchar_t *string, int len, FILE *f, int *pnumwritten)
+#endif
+*void write_wstring(wchar_t *string, int len, int *pnumwritten)
+*void write_wstring(wchar_t *string, int len, FILE *f, int *pnumwritten)
+*
+*Purpose:
+* Writes a string of the given length to the given file. If no error occurs,
+* then *pnumwritten is incremented by len; otherwise, *pnumwritten is set
+* to -1. If len is negative, it is treated as zero.
+*
+*Entry:
+* char *string - string to write (NOT null-terminated)
+* int len - length of string
+* FILE *f - file to write to
+* int *pnumwritten - pointer to integer to update with total chars written
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef CPRFLAG
+
+LOCAL(void) write_string (
+ char *string,
+ int len,
+ int *pnumwritten
+ )
+{
+ while (len-- > 0)
+ write_char(*string++, pnumwritten);
+}
+
+#else /* CPRFLAG */
+#if WPRFLAG
+
+LOCAL(void) write_string (
+ wchar_t *string,
+ int len,
+ FILE *f,
+ int *pnumwritten
+ )
+#else
+
+LOCAL(void) write_string (
+ char *string,
+ int len,
+ FILE *f,
+ int *pnumwritten
+ )
+#endif /* WPRFLAG */
+{
+#ifdef _POSIX_
+ while (len-- > 0) {
+ write_char(*string++, f, pnumwritten);
+ if (*pnumwritten < 0)
+ return;
+ }
+#else
+ while (len-- > 0)
+ write_char(*string++, f, pnumwritten);
+#endif
+}
+#endif /* CPRFLAG */
+
+
+/***
+*int get_int_arg(va_list *pargptr)
+*
+*Purpose:
+* Gets an int argument off the given argument list and updates *pargptr.
+*
+*Entry:
+* va_list *pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the integer argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+__inline int _CALLTYPE4 get_int_arg (
+ va_list *pargptr
+ )
+{
+ return va_arg(*pargptr, int);
+}
+
+/***
+*long get_long_arg(va_list *pargptr)
+*
+*Purpose:
+* Gets an long argument off the given argument list and updates *pargptr.
+*
+*Entry:
+* va_list *pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the long argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#if !LONG_IS_INT
+__inline long _CALLTYPE4 get_long_arg (
+ va_list *pargptr
+ )
+{
+ return va_arg(*pargptr, long);
+}
+#endif
+
+#ifdef _ALPHA_
+__inline __int64 _CALLTYPE4 get_quad_arg (
+ va_list *pargptr
+ )
+{
+ return va_arg(*pargptr, __int64);
+}
+#endif
+
+#ifndef WPRFLAG
+/***
+*short get_short_arg(va_list *pargptr)
+*
+*Purpose:
+* Gets a short argument off the given argument list and updates *pargptr.
+* *** CURRENTLY ONLY USED TO GET A WCHAR_T, IFDEF _INTL ***
+*
+*Entry:
+* va_list *pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the short argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#if !SHORT_IS_INT
+__inline short _CALLTYPE4 get_short_arg (
+ va_list *pargptr
+ )
+{
+ return va_arg(*pargptr, short);
+}
+#endif
+#endif
diff --git a/private/crt32/stdio/popen.c b/private/crt32/stdio/popen.c
new file mode 100644
index 000000000..5a4b69405
--- /dev/null
+++ b/private/crt32/stdio/popen.c
@@ -0,0 +1,562 @@
+/***
+*popen.c - initiate a pipe and a child command
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines _popen() and _pclose().
+*
+*Revision History:
+* 01-06-89 GJF Initial version (I plead temporary insanity).
+* 01-09-89 GJF Fixed several bugs.
+* 01-10-89 GJF Implemented several improvements from Trapper.
+* 01-12-89 GJF Added underscores to function names. Also, in _pclose,
+* pstream must be close before the cwait call if it is
+* attached to the write handle of the pipe (otherwise,
+* may get a deadlock).
+* 01-13-89 GJF Added multi-thread/dll support.
+* 02-09-89 GJF Prevent child process from inheriting unwanted handles.
+* Also, always close pstream before doing the cwait.
+* 05-10-89 GJF Ported to 386 (OS/2 2.0)
+* 08-14-89 GJF Use DOSCALLS.H for API prototypes, fixed _rotl call
+* in _pclose (rotate 24 bits for 386!), re-tested.
+* 11-16-89 GJF Changed DOS32SETFILEHSTATE to DOS32SETFHSTATE
+* 11-20-89 GJF Added const attribute to types of _popen()'s args.
+* Also, fixed copyright.
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 03-26-90 GJF Made ibtab() and setinherit() _CALLTYPE4.
+* 07-25-90 SBM Compiles cleanly with -W3 (removed unreferenced
+* variables), removed '32' from API names
+* 08-13-90 SBM Compiles cleanly with -W3 with new build of compiler
+* 10-03-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-18-91 GJF ANSI naming.
+* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_]
+* 09-29-91 GJF Picked up NT implementation (_WIN32_).
+* 04-06-92 SRW Fixed to not rely on setinherit function (_WIN32_).
+* 04-28-92 DJM ifndef for POSIX
+* 05-06-92 GJF Set _osfile[stddup] so that _get_osfhandle knows it's
+* open (bug found by Markl).
+* 05-15-92 GJF Fixed regression Markl found - _close(stddup) to ensure
+* that _osfile[] entry is cleared.
+* 01-07-93 GJF Substantially revised: purged Cruiser support, removed
+* needlessly repeated API calls, closed down a pipe
+* handle accidently left open at end of _popen, removed
+* reduntant CloseHandle call from _pclose, tried to clean
+* up the format and reduce the number of silly casts,
+* and added or revised many comments.
+* 04-10-93 GJF Removed redundant close of child process handle in
+* _pclose().
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <process.h>
+#include <io.h>
+#include <fcntl.h>
+#include <internal.h>
+#include <errno.h>
+#include <msdos.h>
+#include <os2dll.h>
+#include <oscalls.h>
+
+/* size for pipe buffer
+ */
+#define PSIZE 1024
+
+#define STDIN 0
+#define STDOUT 1
+
+
+/* definitions for table of stream pointer - process handle pairs. the table
+ * is created, maintained and accessed by the idtab function. _popen and
+ * _pclose gain access to table entries only by calling idtab. Note that the
+ * table is expanded as necessary (by idtab) and free table entries are reused
+ * (an entry is free if its stream field is NULL), but the table is never
+ * contracted.
+ */
+
+typedef struct {
+ FILE *stream;
+ int prochnd;
+} IDpair;
+
+/* number of entries in idpairs table
+ */
+static unsigned idtabsiz = 0;
+
+/* pointer to first table entry
+ */
+static IDpair *idpairs = NULL;
+
+/* function to find specified table entries. also, creates and maintains
+ * the table.
+ */
+static IDpair * _CRTAPI3 idtab(FILE *);
+
+
+/***
+*FILE *_popen(cmdstring,type) - initiate a pipe and a child command
+*
+*Purpose:
+* Creates a pipe and asynchronously executes a child copy of the command
+* processor with cmdstring (see system()). If the type string contains
+* an 'r', the calling process can read child command's standard output
+* via the returned stream. If the type string contains a 'w', the calling
+* process can write to the child command's standard input via the
+* returned stream.
+*
+*Entry:
+* char *cmdstring - command to be executed
+* char *type - string of the form "r|w[b|t]", determines the mode
+* of the returned stream (i.e., read-only vs write-only,
+* binary vs text mode)
+*
+*Exit:
+* If successful, returns a stream associated with one end of the created
+* pipe (the other end of the pipe is associated with either the child
+* command's standard input or standard output).
+*
+* If an error occurs, NULL is returned.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+FILE * _CRTAPI1 _popen (
+ const char *cmdstring,
+ const char *type
+ )
+{
+
+ int phdls[2]; /* I/O handles for pipe */
+ int ph_open[2]; /* flags, set if correspond phdls is open */
+ int i1; /* index into phdls[] */
+ int i2; /* index into phdls[] */
+
+ int tm = 0; /* flag indicating text or binary mode */
+
+ int stdhdl; /* either STDIN or STDOUT */
+ HANDLE osfhndsv1; /* used to save _osfhnd[stdhdl] */
+ long osfhndsv2; /* used to save _osfhnd[phdls[i2] */
+ char osfilesv1; /* used to save _osfile[stdhdl] */
+ char osfilesv2; /* used to save _osfile[phdls[i2]] */
+
+ HANDLE oldhnd; /* used to hold OS file handle values... */
+ HANDLE newhnd; /* ...in calls to DuplicateHandle API */
+
+ FILE *pstream; /* stream to be associated with pipe */
+
+ HANDLE prochnd; /* handle for current process */
+
+ char *cmdexe; /* pathname for the command processor */
+ int childhnd; /* handle for child process (cmd.exe) */
+
+ IDpair *locidpair; /* pointer to IDpair table entry */
+
+
+ /* first check for errors in the arguments
+ */
+ if ( (cmdstring == NULL) || (type == NULL) || ((*type != 'w') &&
+ (*type != 'r')) )
+ goto error1;
+
+ /* do the _pipe(). note that neither of the resulting handles will
+ * be inheritable.
+ */
+
+ if ( *(type + 1) == 't' )
+ tm = _O_TEXT;
+ else if ( *(type + 1) == 'b' )
+ tm = _O_BINARY;
+
+ tm |= _O_NOINHERIT;
+
+ if ( _pipe( phdls, PSIZE, tm ) == -1 )
+ goto error1;
+
+ /* test *type and set stdhdl, i1 and i2 accordingly.
+ */
+ if ( *type == 'w' ) {
+ stdhdl = STDIN;
+ i1 = 0;
+ i2 = 1;
+ }
+ else {
+ stdhdl = STDOUT;
+ i1 = 1;
+ i2 = 0;
+ }
+
+ /* the pipe now exists. the following steps must be carried out before
+ * the child process (cmd.exe) may be spawned:
+ *
+ * 1. save a non-inheritable dup of stdhdl
+ *
+ * 2. force stdhdl to be a dup of ph[i1]. close both ph[i1] and
+ * the original OS handle underlying stdhdl
+ *
+ * 3. associate a stdio-level stream with ph[i2].
+ */
+
+ /* set flags to indicate pipe handles are open. note, these are only
+ * used for error recovery.
+ */
+ ph_open[ 0 ] = ph_open[ 1 ] = 1;
+
+
+ /* get the process handle, it will be needed in some API calls
+ */
+ prochnd = GetCurrentProcess();
+
+ /* MULTI-THREAD: ASSERT LOCK ON STDHDL HERE!!!!
+ */
+ _lock_fh( stdhdl );
+
+ /* save a non-inheritable copy of stdhdl for later restoration.
+ */
+
+ oldhnd = (HANDLE)_osfhnd[ stdhdl ];
+
+ if ( (oldhnd == INVALID_HANDLE_VALUE) ||
+ !DuplicateHandle( prochnd,
+ oldhnd,
+ prochnd,
+ &osfhndsv1,
+ 0L,
+ FALSE, /* non-inheritable */
+ DUPLICATE_SAME_ACCESS )
+ ) {
+ goto error2;
+ }
+
+ osfilesv1 = _osfile[ stdhdl ];
+
+ /* force stdhdl to an inheritable dup of phdls[i1] (i.e., force
+ * STDIN to the pipe read handle or STDOUT to the pipe write handle)
+ * and close phdls[i1] (so there won't be a stray open handle on the
+ * pipe after a _pclose). also, clear ph_open[i1] flag so that error
+ * recovery won't try to close it again.
+ */
+
+ if ( !DuplicateHandle( prochnd,
+ (HANDLE)_osfhnd[ phdls[i1] ],
+ prochnd,
+ &newhnd,
+ 0L,
+ TRUE, /* inheritable */
+ DUPLICATE_SAME_ACCESS )
+ ) {
+ goto error3;
+ }
+
+ (void)CloseHandle( (HANDLE)_osfhnd[stdhdl] );
+ _free_osfhnd( stdhdl );
+
+ _set_osfhnd( stdhdl, (long)newhnd );
+ _osfile[ stdhdl ] = _osfile[ phdls[i1] ];
+
+ (void)_close( phdls[i1] );
+ ph_open[ i1 ] = 0;
+
+
+ /* associate a stream with phdls[i2]. note that if there are no
+ * errors, pstream is the return value to the caller.
+ */
+ if ( (pstream = _fdopen( phdls[i2], type )) == NULL )
+ goto error4;
+
+ /* MULTI-THREAD: ASSERT LOCK ON IDPAIRS HERE!!!!
+ */
+ _mlock( _POPEN_LOCK );
+
+ /* next, set locidpair to a free entry in the idpairs table.
+ */
+ if ( (locidpair = idtab( NULL )) == NULL )
+ goto error5;
+
+
+ /* temporarily change the _osfhnd[] and _osfile[] entries so that
+ * the child doesn't get any entries for phdls[i2].
+ */
+ osfhndsv2 = _osfhnd[ phdls[i2] ];
+ _osfhnd[ phdls[i2] ] = (long)INVALID_HANDLE_VALUE;
+ osfilesv2 = _osfile[ phdls[i2] ];
+ _osfile[ phdls[i2] ] = 0;
+
+ /* spawn the child copy of cmd.exe. the algorithm is adapted from
+ * SYSTEM.C, and behaves the same way.
+ */
+ if ( ((cmdexe = getenv("COMSPEC")) == NULL) ||
+ (((childhnd = _spawnl( _P_NOWAIT,
+ cmdexe,
+ cmdexe,
+ "/c",
+ cmdstring,
+ NULL ))
+ == -1) && ((errno == ENOENT) || (errno == EACCES))) ) {
+ /* either COMSPEC wasn't defined, or the spawn failed because
+ * cmdexe wasn't found or was inaccessible. in either case,
+ * try to spawn "cmd.exe" instead. note that spawnlp is used
+ * here so that the path is searched.
+ */
+ cmdexe = "cmd.exe";
+ childhnd = _spawnlp( _P_NOWAIT,
+ cmdexe,
+ cmdexe,
+ "/c",
+ cmdstring,
+ NULL);
+ }
+
+ _osfhnd[ phdls[i2] ] = osfhndsv2;
+ _osfile[ phdls[i2] ] = osfilesv2;
+
+ /* check if the last (perhaps only) spawn attempt was successful
+ */
+ if ( childhnd == -1 )
+ goto error6;
+
+ /* restore stdhdl for the current process, set value of *locidpair,
+ * close osfhndsv1 (note that CloseHandle must be used instead of close)
+ * and return pstream to the caller
+ */
+
+ (void)DuplicateHandle( prochnd,
+ osfhndsv1,
+ prochnd,
+ &newhnd,
+ 0L,
+ TRUE, /* inheritable */
+ DUPLICATE_CLOSE_SOURCE | /* close osfhndsv1 */
+ DUPLICATE_SAME_ACCESS );
+
+ (void)CloseHandle( (HANDLE)_osfhnd[stdhdl] );
+ _free_osfhnd( stdhdl );
+
+ _set_osfhnd( stdhdl, (long)newhnd );
+ _osfile[stdhdl] = osfilesv1;
+
+ /* MULTI-THREAD: RELEASE LOCK ON STDHDL HERE!!!!
+ */
+ _unlock_fh( stdhdl );
+
+ locidpair->prochnd = childhnd;
+ locidpair->stream = pstream;
+
+ /* MULTI-THREAD: RELEASE LOCK ON IDPAIRS HERE!!!!
+ */
+ _munlock( _POPEN_LOCK );
+
+ /* all successful calls to _popen return to the caller via this return
+ * statement!
+ */
+ return( pstream );
+
+ /**
+ * error handling code. all detected errors end up here, entering
+ * via a goto one of the labels. note that the logic is currently
+ * a straight fall-thru scheme (e.g., if entered at error5, the
+ * code for error5, error4,...,error1 is all executed).
+ **********************************************************************/
+
+ error6: /* make sure locidpair is reusable
+ */
+ locidpair->stream = NULL;
+
+ error5: /* close pstream (also, clear ph_open[i2] since the stream
+ * close will also close the pipe handle)
+ */
+ (void)fclose( pstream );
+ ph_open[ i2 ] = 0;
+
+ /* MULTI-THREAD: RELEASE LOCK ON IDPAIRS HERE!!!!
+ */
+ _munlock(_POPEN_LOCK);
+
+ error4: /* restore stdhdl
+ */
+
+ (void)DuplicateHandle( prochnd,
+ osfhndsv1,
+ prochnd,
+ &newhnd,
+ 0L,
+ TRUE,
+ DUPLICATE_SAME_ACCESS );
+
+ (void)CloseHandle( (HANDLE)_osfhnd[stdhdl] );
+ _free_osfhnd( stdhdl );
+
+ _set_osfhnd( stdhdl, (long)newhnd );
+ _osfile[ stdhdl ] = osfilesv1;
+
+ /* MULTI-THREAD: RELEASE LOCK ON STDHDL HERE!!!!
+ */
+ _unlock_fh( stdhdl );
+
+ error3: /* close osfhndsv1
+ */
+
+ CloseHandle( osfhndsv1 );
+
+ error2: /* close handles on pipe (if they are still open)
+ */
+ if ( ph_open[i1] )
+ _close( phdls[i1] );
+ if ( ph_open[i2] )
+ _close( phdls[i2] );
+
+ error1: /* return NULL to the caller indicating failure
+ */
+ return( NULL );
+}
+
+
+/***
+*int _pclose(pstream) - wait on a child command and close the stream on the
+* associated pipe
+*
+*Purpose:
+* Closes pstream then waits on the associated child command. The
+* argument, pstream, must be the return value from a previous call to
+* _popen. _pclose first looks up the process handle of child command
+* started by that _popen and does a cwait on it. Then, it closes pstream
+* and returns the exit status of the child command to the caller.
+*
+*Entry:
+* FILE *pstream - file stream returned by a previous call to _popen
+*
+*Exit:
+* If successful, _pclose returns the exit status of the child command.
+* The format of the return value is that same as for cwait, except that
+* the low order and high order bytes are swapped.
+*
+* If an error occurs, -1 is returned.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _pclose (
+ FILE *pstream
+ )
+{
+ IDpair *locidpair; /* pointer to entry in idpairs table */
+ int termstat; /* termination status word */
+ int retval = -1; /* return value (to caller) */
+
+ /* MULTI-THREAD: LOCK IDPAIRS HERE!!!!
+ */
+ _mlock(_POPEN_LOCK);
+
+ if ( (pstream == NULL) || ((locidpair = idtab(pstream)) == NULL) )
+ /* invalid pstream, exit with retval == -1
+ */
+ goto done;
+
+ /* close pstream
+ */
+ (void)fclose(pstream);
+
+ /* wait on the child (copy of the command processor) and all of its
+ * children.
+ */
+ if ( (_cwait(&termstat, locidpair->prochnd, _WAIT_GRANDCHILD) != -1) ||
+ (errno == EINTR) )
+ retval = termstat;
+
+ /* Mark the IDpairtable entry as free (note: prochnd was closed by the
+ * preceding call to _cwait).
+ */
+ locidpair->stream = NULL;
+ locidpair->prochnd = 0;
+
+ /* only return path!
+ */
+ done:
+ /* MULTI-THREAD: RELEASE LOCK ON IDPAIRS HERE!!!!
+ */
+ _munlock(_POPEN_LOCK);
+ return(retval);
+}
+
+
+/***
+* static IDpair * idtab(FILE *pstream) - find an idpairs table entry
+*
+*Purpose:
+* Find an entry in the idpairs table. This function finds the entry the
+* idpairs table entry corresponding to pstream. In the case where pstream
+* is NULL, the entry being searched for is any free entry. In this case,
+* idtab will create the idpairs table if it doesn't exist, or expand it (by
+* exactly one entry) if there are no free entries.
+*
+* [MTHREAD NOTE: This routine assumes that the caller has acquired the
+* idpairs table lock.]
+*
+*Entry:
+* FILE *pstream - stream corresponding to table entry to be found (if NULL
+* then find any free table entry)
+*
+*Exit:
+* if successful, returns a pointer to the idpairs table entry. otherwise,
+* returns NULL.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static IDpair * _CRTAPI3 idtab (
+ FILE *pstream
+ )
+{
+
+ IDpair * pairptr; /* ptr to entry */
+ IDpair * newptr; /* ptr to newly malloc'd memory */
+
+
+ /* search the table. if table is empty, appropriate action should
+ * fall out automatically.
+ */
+ for ( pairptr = idpairs ; pairptr < (idpairs+idtabsiz) ; pairptr++ )
+ if ( pairptr->stream == pstream )
+ break;
+
+ /* if we found an entry, return it.
+ */
+ if ( pairptr < (idpairs + idtabsiz) )
+ return(pairptr);
+
+ /* did not find an entry in the table. if pstream was NULL, then try
+ * creating/expanding the table. otherwise, return NULL. note that
+ * when the table is created or expanded, exactly one new entry is
+ * produced. this must not be changed unless code is added to mark
+ * the extra entries as being free (i.e., set their stream fields to
+ * to NULL).
+ */
+ if ( (pstream != NULL) || ((newptr = (IDpair *)realloc((void *)idpairs,
+ (idtabsiz + 1)*sizeof(IDpair))) == NULL) )
+ /* either pstream was non-NULL or the attempt to create/expand
+ * the table failed. in either case, return a NULL to indicate
+ * failure.
+ */
+ return( NULL );
+
+ idpairs = newptr; /* new table ptr */
+ pairptr = newptr + idtabsiz; /* first new entry */
+ idtabsiz++; /* new table size */
+
+ return( pairptr );
+
+}
+
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/stdio/ppc/cinitstd.s b/private/crt32/stdio/ppc/cinitstd.s
new file mode 100644
index 000000000..cef95550e
--- /dev/null
+++ b/private/crt32/stdio/ppc/cinitstd.s
@@ -0,0 +1,47 @@
+// page ,132
+// title cinittmp - C Run-Time Termination for STDIO Buffer Flushing
+//
+//cinittmp.asm - WIN32 C Run-Time Initialization for the temporary file function
+//
+// Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+//
+//Purpose:
+// This module defines the symbol __cflush which is referenced by those
+// modules that require the __endstdio() terminator. This module places
+// the address of the __endstdio() terminator in the pre-terminator table.
+//
+//Notes:
+//
+//Revision History:
+// 03-19-92 SKS Module created.
+// 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+// 04-29-92 SKS Changed erroneous XP$C to XP$X
+// 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+// 08-06-92 SKS Revised to use new section names and macros
+//
+// ****************************************************************************/
+
+#include "kxppc.h"
+
+ .extern _endstdio
+
+
+beginSection(XPX)
+
+ .long _endstdio
+
+endSection(XPX)
+
+
+ .data
+ .align 2
+
+//
+// _cflush is a dummy variable used to pull in _endstdio() when
+// any STDIO routine is included in the user program.
+//
+
+ .globl _cflush
+
+_cflush: .long 0
+
diff --git a/private/crt32/stdio/ppc/cinittmp.s b/private/crt32/stdio/ppc/cinittmp.s
new file mode 100644
index 000000000..533c399d1
--- /dev/null
+++ b/private/crt32/stdio/ppc/cinittmp.s
@@ -0,0 +1,52 @@
+// ***
+// cinittmp.asm - WIN32 C Run-Time Terminator for the temporary file function
+//
+// Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+//
+// Purpose:
+// Termination entry for the tmpnam() and _tempnam() functions
+//
+// Notes:
+// The three global variables included here are referenced by tmpnam()
+// and _tempnam() and will force the inclusion this module and _rmtmp()
+// if either of tmpnam() or _tempnam() is used. This module places the
+// address of _rmtmp() in the terminator table.
+//
+// Revision History:
+// 03-19-92 SKS Module created.
+// 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+// 04-29-92 SKS Changed erroneous XP$C to XP$X
+// 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+// 08-06-92 SKS Revised to use new section names and macros
+// 10-27-93 MDJ Wrote (this) ppc version ... based on code in i386 tree
+//
+// ***************************************************************************
+
+#include "kxppc.h"
+
+
+ .extern _rmtmp
+
+
+beginSection(XPX)
+
+ .long _rmtmp
+
+endSection(XPX)
+
+
+ .data
+ .align 2
+//
+// Definitions for tmpoff, tempoff and old_pfxlen. These will cause this
+// module to be linked in whenever the termination code needs it.
+//
+
+ .globl _tmpoff
+ .globl _tempoff
+ .globl _old_pfxlen
+
+_tmpoff: .long 1
+_tempoff: .long 1
+_old_pfxlen: .long 0
+
diff --git a/private/crt32/stdio/printf.c b/private/crt32/stdio/printf.c
new file mode 100644
index 000000000..b1bc01baa
--- /dev/null
+++ b/private/crt32/stdio/printf.c
@@ -0,0 +1,92 @@
+/***
+*printf.c - print formatted
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines printf() - print formatted data
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-13-87 JCR added const to declaration
+* 06-24-87 JCR (1) Made printf conform to ANSI prototype and use the
+* va_ macros; (2) removed SS_NE_DS conditionals.
+* 11-04-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-14-88 JCR Use near pointer to reference _iob[] entries
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int printf(format, ...) - print formatted data
+*
+*Purpose:
+* Prints formatted data on stdout using the format string to
+* format data and getting as many arguments as called for
+* Uses temporary buffering to improve efficiency.
+* _output does the real work here
+*
+*Entry:
+* char *format - format string to control data format/number of arguments
+* followed by list of arguments, number and type controlled by
+* format string
+*
+*Exit:
+* returns number of characters printed
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 printf (
+ const char *format,
+ ...
+ )
+/*
+ * stdout 'PRINT', 'F'ormatted
+ */
+{
+ va_list arglist;
+ REG1 FILE *stream = stdout;
+ REG2 int buffing;
+ REG3 int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ va_start(arglist, format);
+
+ assert(format != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+
+ _lock_str(index);
+
+ buffing = _stbuf(stream);
+
+ retval = _output(stream,format,arglist);
+
+ _ftbuf(buffing, stream);
+
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/puts.c b/private/crt32/stdio/puts.c
new file mode 100644
index 000000000..8373e5756
--- /dev/null
+++ b/private/crt32/stdio/puts.c
@@ -0,0 +1,91 @@
+/***
+*puts.c - put a string to stdout
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines puts() - put a string to stdout
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 08-31-84 RN modified to use new, blazing fast fwrite
+* 07-01-87 JCR made return values conform to ANSI [MSC only]
+* 09-24-87 JCR Added 'const' to declaration [ANSI]
+* 11-05-87 JCR Multi-thread version
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-18-88 JCR Error return = EOF
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-26-90 GJF Added #include <string.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarators.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <string.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int puts(string) - put a string to stdout with newline
+*
+*Purpose:
+* Write a string to stdout; don't include '\0' but append '\n'. Uses
+* temporary buffering for efficiency on stdout if unbuffered.
+*
+*Entry:
+* char *string - string to output
+*
+*Exit:
+* Good return = 0
+* Error return = EOF
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 puts (
+ const char *string
+ )
+{
+ REG1 FILE *stream = stdout;
+ REG4 int buffing;
+ REG2 unsigned int length;
+ REG3 unsigned int ndone;
+ int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(string != NULL);
+
+ length = strlen(string);
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ buffing = _stbuf(stream);
+
+ ndone = _fwrite_lk(string,1,length,stream);
+
+ if (ndone == length) {
+ _putc_lk('\n',stream);
+ retval = 0; /* success */
+ }
+ else
+ retval = EOF; /* error */
+
+ _ftbuf(buffing, stream);
+ _unlock_str(index);;
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/putw.c b/private/crt32/stdio/putw.c
new file mode 100644
index 000000000..db5600417
--- /dev/null
+++ b/private/crt32/stdio/putw.c
@@ -0,0 +1,87 @@
+/***
+*putw.c - put a binary int to output stream
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _putw() - puts a binary int to an output stream
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 11-09-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-13-88 JCR Removed unnecessary calls to mthread fileno/feof/ferror
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int _putw(word, stream) - write a binary int to an output stream
+*
+*Purpose:
+* Writes sizeof(int) bytes to the output stream, high byte first.
+* This routine should be machine independent.
+*
+*Entry:
+* int word - integer to write
+* FILE *stream - stream to write to
+*
+*Exit:
+* returns the word put to the stream
+* returns EOF if error, but this is a legit int value, so should
+* test with feof() or ferror().
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _putw (
+ int word,
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ REG3 int bytecount = sizeof(int);
+ REG2 char *byteptr = (char *)&word;
+ int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(str != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+
+ while (bytecount--)
+ {
+ _putc_lk(*byteptr,stream);
+ ++byteptr;
+ }
+ retval = (ferror(stream) ? EOF : word);
+
+ _unlock_str(index);
+ return(retval);
+}
diff --git a/private/crt32/stdio/rewind.c b/private/crt32/stdio/rewind.c
new file mode 100644
index 000000000..15c52be2f
--- /dev/null
+++ b/private/crt32/stdio/rewind.c
@@ -0,0 +1,117 @@
+/***
+*rewind.c - rewind a stream
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines rewind() - rewinds a stream to the beginning.
+*
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 11-02-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL/normal versions
+* 06-01-88 JCR Clear lowio flags as well as stdio flags
+* 06-14-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 05-29-90 SBM Use _flush, not [_]fflush[_lk]
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarators.
+* 01-22-91 GJF ANSI naming.
+* 03-27-92 DJM POSIX support.
+* 08-26-92 GJF Include unistd.h for POSIX build.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#include <io.h>
+#include <os2dll.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#else
+#include <msdos.h>
+#endif
+#include <internal.h>
+
+/***
+*void rewind(stream) - rewind a string
+*
+*Purpose:
+* Back up a stream to the beginning (if not terminal). First flush it.
+* If read/write, allow next i/o operation to set mode.
+*
+*Entry:
+* FILE *stream - file to rewind
+*
+*Exit:
+* returns 0 if success
+* returns -1 if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 rewind (
+ FILE *str
+ )
+{
+ REG1 FILE *stream;
+ REG2 int fd;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(str != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef _POSIX_
+ fd = fileno(stream);
+#else
+ fd = _fileno(stream);
+#endif
+
+ /* Get the stream index and lock the file */
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+
+ /* Flush the stream */
+ _flush(stream);
+
+ /* Clear errors */
+ stream->_flag &= ~(_IOERR|_IOEOF);
+#ifndef _POSIX_
+ _osfile[fd] &= ~(FEOFLAG);
+#endif
+
+ /* Set flags */
+ /* [note: _flush set _cnt=0 and _ptr=_base] */
+ if (stream->_flag & _IORW)
+ stream->_flag &= ~(_IOREAD|_IOWRT);
+
+ /* Position to beginning of file */
+#ifdef _POSIX_
+ /* [note: posix _flush doesn't discard buffer */
+
+ stream->_ptr = stream->_base;
+ stream->_cnt = 0;
+ lseek(fd,0L,0);
+#else
+ _lseek(fd,0L,0);
+#endif
+
+ /* unlock stream */
+ _unlock_str(index);
+}
diff --git a/private/crt32/stdio/rmtmp.c b/private/crt32/stdio/rmtmp.c
new file mode 100644
index 000000000..5dca9e723
--- /dev/null
+++ b/private/crt32/stdio/rmtmp.c
@@ -0,0 +1,116 @@
+/***
+*rmtmp.c - remove temporary files created by tmpfile.
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 09-15-83 TC initial version
+* 11-02-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged normal and DLL versions
+* 06-10-88 JCR Use near pointer to reference _iob[] entries
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 10-03-90 GJF New-style function declarator.
+* 01-21-91 GJF ANSI naming.
+* 07-30-91 GJF Added support for termination scheme used on
+* non-Cruiser targets [_WIN32_].
+* 03-11-92 GJF Replaced _tmpnum(stream) with stream->_tmpfname for
+* Win32.
+* 03-17-92 GJF Got rid of definition of _tmpoff.
+* 03-31-92 GJF Merged with Stevesa's changes.
+* 04-16-92 GJF Merged with Darekm's changes.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+
+#if defined(_MSC_VER) && defined(_WIN32)
+
+#pragma data_seg(".CRT$XPX")
+static void (__cdecl *pterm)(void) = _rmtmp;
+#pragma data_seg()
+
+#endif /* _MSC_VER */
+
+#ifdef _WIN32
+
+/*
+ * Definitions for _tmpoff, _tempoff and _old_pfxlen. These will cause this
+ * module to be linked in whenever the termination code needs it.
+ */
+unsigned _tmpoff = 1;
+unsigned _tempoff = 1;
+unsigned _old_pfxlen = 0;
+#else /* ndef _WIN32 */
+/*
+ * Definitions for _tmpoff, _tempoff and _old_pfxlen. These will cause this
+ * module to be linked in whenever the termination code needs it.
+ */
+extern unsigned _tmpoff; /* = 1 */
+extern unsigned _tempoff; /* = 1 */
+extern unsigned _old_pfxlen; /* = 0 */
+
+#endif
+
+/***
+*int _rmtmp() - closes and removes temp files created by tmpfile
+*
+*Purpose:
+* closes and deletes all open files that were created by tmpfile.
+*
+*Entry:
+* None.
+*
+*Exit:
+* returns number of streams closed
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _rmtmp (
+ void
+ )
+{
+ REG1 FILE *stream = _iob;
+ REG2 int count = 0;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ _mlock(_IOB_SCAN_LOCK);
+
+ for (; stream <= _lastiob; stream++) {
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+
+#ifdef _CRUISER_
+ if (inuse(stream) && _tmpnum(stream) ) {
+#else /* ndef _CRUISER_ */
+ if (inuse(stream) && (stream->_tmpfname != NULL) ) {
+#endif /* _CRUISER_ */
+ _fclose_lk(stream);
+ count++;
+ }
+
+ _unlock_str(index);
+ }
+
+ _munlock(_IOB_SCAN_LOCK);
+
+ return(count);
+}
diff --git a/private/crt32/stdio/scanf.c b/private/crt32/stdio/scanf.c
new file mode 100644
index 000000000..f9c3f39d9
--- /dev/null
+++ b/private/crt32/stdio/scanf.c
@@ -0,0 +1,86 @@
+/***
+*scanf.c - read formatted data from stdin
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines scanf() - reads formatted data from stdin
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-13-87 JCR added const to declaration
+* 06-24-87 JCR (1) Made declaration conform to ANSI prototype and use
+* the va_ macros; (2) removed SS_NE_DS conditionals.
+* 11-04-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int scanf(format, ...) - read formatted data from stdin
+*
+*Purpose:
+* Reads formatted data from stdin into arguments. _input does the real
+* work here.
+*
+*Entry:
+* char *format - format string
+* followed by list of pointers to storage for the data read. The number
+* and type are controlled by the format string.
+*
+*Exit:
+* returns number of fields read and assigned
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 scanf (
+ const char *format,
+ ...
+ )
+/*
+ * stdin 'SCAN', 'F'ormatted
+ */
+{
+ REG1 FILE *stream = stdin;
+ REG2 int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ va_list arglist;
+
+ va_start(arglist, format);
+
+ assert(format != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+
+ _lock_str(index);
+
+ retval = (_input(stream,format,arglist));
+
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/setbuf.c b/private/crt32/stdio/setbuf.c
new file mode 100644
index 000000000..096049ade
--- /dev/null
+++ b/private/crt32/stdio/setbuf.c
@@ -0,0 +1,61 @@
+/***
+*setbuf.c - give new file buffer
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines setbuf() - given a buffer to a stream or make it unbuffered
+*
+*Revision History:
+* 09-19-83 RN initial version
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 11-02-87 JCR Re-wrote to use setvbuf()
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 02-15-90 GJF Fixed copyright and indents
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <assert.h>
+#include <stdio.h>
+
+/***
+*void setbuf(stream, buffer) - give a buffer to a stream
+*
+*Purpose:
+* Allow user to assign his/her own buffer to a stream.
+* if buffer is not NULL, it must be BUFSIZ in length.
+* if buffer is NULL, stream will be unbuffered.
+*
+* Since setbuf()'s functionality is a subset of setvbuf(), simply
+* call the latter routine to do the actual work.
+*
+*Entry:
+* FILE *stream - stream to be buffered or unbuffered
+* char *buffer - buffer of size BUFSIZ or NULL
+*
+*Exit:
+* None.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 setbuf (
+ FILE *stream,
+ char *buffer
+ )
+{
+ assert(stream != NULL);
+
+ if (buffer == NULL)
+ setvbuf(stream, NULL, _IONBF, 0);
+ else
+ setvbuf(stream, buffer, _IOFBF, BUFSIZ);
+
+}
diff --git a/private/crt32/stdio/setvbuf.c b/private/crt32/stdio/setvbuf.c
new file mode 100644
index 000000000..665cee028
--- /dev/null
+++ b/private/crt32/stdio/setvbuf.c
@@ -0,0 +1,180 @@
+/***
+*setvbuf.c - set buffer size for a stream
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines setvbuf() - set the buffering mode and size for a stream.
+*
+*Revision History:
+* 09-19-83 RN initial version
+* 06-26-85 TC modified to allow user defined buffers of various sizes
+* 06-24-86 DFW kludged to fix incompatability with Xenix values of
+* _IOFBF, _IOLBF
+* 02-09-87 JCR added "buffer=&(_iob2[fileno(stream)]._charbuf);"
+* to handle _IONBF case
+* 02-25-87 JCR added support for default buffer and IBMC20-condition
+* code
+* 04-13-87 JCR changed type of szie from int to size_t (unsigned int)
+* and changed a related comparison
+* 06-29-87 JCR Took out the _OLD_IOFBF/_OLD_IOLBF kludge for MSC.
+* Should be taken out for IBM too...
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 11-02-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-06-88 JCR Optimized _iob2 references
+* 06-14-88 JCR Use near pointer to reference _iob[] entries
+* 08-09-88 JCR Buffer size can't be greater than INT_MAX
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-15-90 GJF _iob[], _iob2[] merge. Also, cleanup, a little tuning
+* and fixed copyright.
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 05-29-90 SBM Use _flush, not [_]fflush[_lk]
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+* 04-27-93 CFW Change _IONBF size to 2 bytes to hold wide char.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#include <malloc.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <limits.h>
+
+/***
+*int setvbuf(stream, buffer, type, size) - set buffering for a file
+*
+*Purpose:
+* Controls buffering and buffer size for the specified stream. The
+* array pointed to by buf is used as a buffer, unless NULL, in which
+* case we'll allocate a buffer automatically. type specifies the type
+* of buffering: _IONBF = no buffer, _IOFBF = buffered, _IOLBF = same
+* as _IOFBF.
+*
+*Entry:
+* FILE *stream - stream to control buffer on
+* char *buffer - pointer to buffer to use (NULL means auto allocate)
+* int type - type of buffering (_IONBF, _IOFBF or _IOLBF)
+* size_t size - size of buffer
+*
+*Exit:
+* return 0 if successful
+* returns non-zero if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 setvbuf (
+ FILE *str,
+ char *buffer,
+ int type,
+ size_t size
+ )
+{
+ REG1 FILE *stream;
+#ifdef MTHREAD
+ int index;
+#endif
+ int retval=0; /* assume good return */
+
+ assert(str != NULL);
+
+ /*
+ * (1) Make sure type is one of the three legal values.
+ * (2) If we are buffering, make sure size is greater than 0.
+ */
+ if ( (type != _IONBF) && ((size == 0) || (size > INT_MAX) ||
+ ((type != _IOFBF) && (type != _IOLBF))) )
+ return(-1);
+
+ /* force size to be even */
+ size &= (size_t)~1;
+
+ /*
+ * Init stream pointers
+ */
+ stream = str;
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ /*
+ * Lock the file
+ */
+ _lock_str(index);
+
+ /*
+ * Flush the current buffer and free it, if it is ours.
+ */
+ _flush(stream);
+ _freebuf(stream);
+
+ /*
+ * Clear a bunch of bits in stream->_flag (all bits related to
+ * buffering and those which used to be in stream2->_flag2). Most
+ * of these should never be set when setvbuf() is called, but it
+ * doesn't cost anything to be safe.
+ */
+ stream->_flag &= ~(_IOMYBUF | _IOYOURBUF | _IONBF | _IOFEOF |
+ _IOFLRTN | _IOCTRLZ);
+
+ /*
+ * CASE 1: No Buffering.
+ */
+ if (type & _IONBF) {
+ stream->_flag |= _IONBF;
+ buffer = (char *)&(stream->_charbuf);
+ size = 2;
+ }
+
+ /*
+ * NOTE: Cases 2 and 3 (below) cover type == _IOFBF or type == _IOLBF
+ * Line buffering is treated as the same as full buffering, so the
+ * _IOLBF bit in stream->_flag is never set. Finally, since _IOFBF is
+ * defined to be 0, full buffering is simply assumed whenever _IONBF
+ * is not set.
+ */
+
+ /*
+ * CASE 2: Default Buffering -- Allocate a buffer for the user.
+ */
+ else if ( buffer == NULL ) {
+ if ( (buffer = malloc(size)) == NULL ) {
+ /*
+ * force library pre-termination procedure (placed here
+ * because the code path should almost never be hit)
+ */
+ _cflush++;
+
+ retval = -1;
+ goto done;
+ }
+ stream->_flag |= _IOMYBUF;
+ }
+
+ /*
+ * CASE 3: User Buffering -- Use the buffer supplied by the user.
+ */
+ else {
+ stream->_flag |= _IOYOURBUF;
+ }
+
+ /*
+ * Common return for all cases.
+ */
+ stream->_bufsiz = size;
+ stream->_ptr = stream->_base = buffer;
+ stream->_cnt = 0;
+done:
+ _unlock_str(index);
+ return(retval);
+}
diff --git a/private/crt32/stdio/snprintf.c b/private/crt32/stdio/snprintf.c
new file mode 100644
index 000000000..2c1744b2c
--- /dev/null
+++ b/private/crt32/stdio/snprintf.c
@@ -0,0 +1,17 @@
+/***
+*snprintf.c - "Count" version of sprintf
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The _snprintf() flavor takes a count argument that is
+* the max number of bytes that should be written to the
+* user's buffer.
+*
+*Revision History:
+* 09-25-91 JCR Stub module created.
+*
+*******************************************************************************/
+
+#define _COUNT_ 1
+#include "sprintf.c"
diff --git a/private/crt32/stdio/snwprint.c b/private/crt32/stdio/snwprint.c
new file mode 100644
index 000000000..f7618e295
--- /dev/null
+++ b/private/crt32/stdio/snwprint.c
@@ -0,0 +1,17 @@
+/***
+*snwprintf.c - "Count" version of swprintf
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The _snwprintf() flavor takes a count argument that is
+* the max number of wide characters that should be written to
+* the user's buffer.
+*
+*Revision History:
+* 05-16-92 KRS Created from snprintf.c.
+*
+*******************************************************************************/
+
+#define _COUNT_ 1
+#include "swprintf.c"
diff --git a/private/crt32/stdio/sources b/private/crt32/stdio/sources
new file mode 100644
index 000000000..77ed5d374
--- /dev/null
+++ b/private/crt32/stdio/sources
@@ -0,0 +1,115 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=stdio
+
+TARGETNAME=stdio
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=feoferr.c \
+ popen.c \
+ fgetchar.c \
+ fgetwchr.c \
+ fileno.c \
+ fgetc.c \
+ fgetwc.c \
+ fputc.c \
+ fputwc.c \
+ fputs.c \
+ fputchar.c \
+ fputwchr.c \
+ _filbuf.c \
+ _filwbuf.c \
+ _file.c \
+ _flsbuf.c \
+ _flswbuf.c \
+ _freebuf.c \
+ _getbuf.c \
+ _open.c \
+ _sftbuf.c \
+ ncommode.c \
+ clearerr.c \
+ closeall.c \
+ cprintf.c \
+ cscanf.c \
+ fclose.c \
+ fdopen.c \
+ fflush.c \
+ fgetpos.c \
+ fgets.c \
+ fopen.c \
+ fprintf.c \
+ fread.c \
+ freopen.c \
+ fscanf.c \
+ fseek.c \
+ fsetpos.c \
+ ftell.c \
+ fwrite.c \
+ gets.c \
+ getw.c \
+ input.c \
+ printf.c \
+ puts.c \
+ putw.c \
+ rewind.c \
+ rmtmp.c \
+ scanf.c \
+ setbuf.c \
+ setvbuf.c \
+ snprintf.c \
+ sprintf.c \
+ sscanf.c \
+ stream.c \
+ tempnam.c \
+ tmpfile.c \
+ vprintf.c \
+ vfprintf.c \
+ vsprintf.c \
+ vsnprint.c \
+ ungetc.c \
+ ungetwc.c \
+ output.c \
+ winput.c \
+ woutput.c \
+ fwscanf.c \
+ swscanf.c \
+ wscanf.c \
+ wprintf.c \
+ swprintf.c \
+ fwprintf.c \
+ snwprint.c \
+ vwprintf.c \
+ vswprint.c \
+ vfwprint.c \
+ vsnwprnt.c
+
+NTTARGETFILE0=
+
diff --git a/private/crt32/stdio/sprintf.c b/private/crt32/stdio/sprintf.c
new file mode 100644
index 000000000..7f1577586
--- /dev/null
+++ b/private/crt32/stdio/sprintf.c
@@ -0,0 +1,130 @@
+/***
+*sprintf.c - print formatted to string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines sprintf() and _snprintf() - print formatted data to string
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-13-87 JCR added const to declaration
+* 06-24-87 JCR (1) Made declaration conform to ANSI prototype and use
+* the va_ macros; (2) removed SS_NE_DS conditionals.
+* 11-07-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-13-88 JCR Fake _iob entry is now static so that other routines
+* can assume _iob entries are in DGROUP.
+* 08-25-88 GJF Define MAXSTR to be INT_MAX (from LIMITS.H).
+* 06-06-89 JCR 386 mthread support
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-16-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+* 09-24-91 JCR Added _snprintf()
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <limits.h>
+#include <os2dll.h>
+
+#define MAXSTR INT_MAX
+
+
+/***
+#ifndef _COUNT_
+*int sprintf(string, format, ...) - print formatted data to string
+#else
+*int _snprintf(string, cnt, format, ...) - print formatted data to string
+#endif
+*
+*Purpose:
+* Prints formatted data to the using the format string to
+* format data and getting as many arguments as called for
+* Sets up a FILE so file i/o operations can be used, make
+* string look like a huge buffer to it, but _flsbuf will
+* refuse to flush it if it fills up. Appends '\0' to make
+* it a true string. _output does the real work here
+*
+* Allocate the 'fake' _iob[] entry statically instead of on
+* the stack so that other routines can assume that _iob[]
+* entries are in are in DGROUP and, thus, are near.
+*
+#ifdef _COUNT_
+* The _snprintf() flavor takes a count argument that is
+* the max number of bytes that should be written to the
+* user's buffer.
+#endif
+*
+* Multi-thread: (1) Since there is no stream, this routine must
+* never try to get the stream lock (i.e., there is no stream
+* lock either). (2) Also, since there is only one statically
+* allocated 'fake' iob, we must lock/unlock to prevent collisions.
+*
+*Entry:
+* char *string - pointer to place to put output
+#ifdef _COUNT_
+* size_t count - max number of bytes to put in buffer
+#endif
+* char *format - format string to control data format/number
+* of arguments followed by list of arguments, number and type
+* controlled by format string
+*
+*Exit:
+* returns number of characters printed
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifndef _COUNT_
+
+int _CALLTYPE2 sprintf (
+ char *string,
+ const char *format,
+ ...
+ )
+#else
+
+int _CALLTYPE2 _snprintf (
+ char *string,
+ size_t count,
+ const char *format,
+ ...
+ )
+#endif
+
+{
+ FILE str;
+ REG1 FILE *outfile = &str;
+ va_list arglist;
+ REG2 int retval;
+
+ va_start(arglist, format);
+
+ assert(string != NULL);
+ assert(format != NULL);
+
+ outfile->_flag = _IOWRT|_IOSTRG;
+ outfile->_ptr = outfile->_base = string;
+#ifndef _COUNT_
+ outfile->_cnt = MAXSTR;
+#else
+ outfile->_cnt = count;
+#endif
+
+ retval = _output(outfile,format,arglist);
+
+ _putc_lk('\0',outfile); /* no-lock version */
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/sscanf.c b/private/crt32/stdio/sscanf.c
new file mode 100644
index 000000000..218a0246c
--- /dev/null
+++ b/private/crt32/stdio/sscanf.c
@@ -0,0 +1,95 @@
+/***
+*sscanf.c - read formatted data from string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines scanf() - reads formatted data from string
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-13-87 JCR added const to declaration
+* 06-24-87 JCR (1) Made declaration conform to ANSI prototype and use
+* the va_ macros; (2) removed SS_NE_DS conditionals.
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 06-13-88 JCR Fake _iob entry is now static so that other routines can
+* assume _iob entries are in DGROUP.
+* 06-06-89 JCR 386 mthread support -- threads share one locked iob.
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed indents.
+* 02-16-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE2, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-26-90 GJF Added #include <string.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 10-03-90 GJF New-style function declarator.
+* 02-18-93 SRW Make FILE a local and remove lock usage.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int sscanf(string, format, ...) - read formatted data from string
+*
+*Purpose:
+* Reads formatted data from string into arguments. _input does the real
+* work here. Sets up a FILE so file i/o operations can be used, makes
+* string look like a huge buffer to it, but _filbuf will refuse to refill
+* it if it is exhausted.
+*
+* Allocate the 'fake' _iob[] entryit statically instead of on
+* the stack so that other routines can assume that _iob[] entries are in
+* are in DGROUP and, thus, are near.
+*
+* Multi-thread: (1) Since there is no stream, this routine must never try
+* to get the stream lock (i.e., there is no stream lock either). (2)
+* Also, since there is only one staticly allocated 'fake' iob, we must
+* lock/unlock to prevent collisions.
+*
+*Entry:
+* char *string - string to read data from
+* char *format - format string
+* followed by list of pointers to storage for the data read. The number
+* and type are controlled by the format string.
+*
+*Exit:
+* returns number of fields read and assigned
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 sscanf (
+ REG2 const char *string,
+ const char *format,
+ ...
+ )
+/*
+ * 'S'tring 'SCAN', 'F'ormatted
+ */
+{
+ va_list arglist;
+ FILE str;
+ REG1 FILE *infile = &str;
+ REG2 int retval;
+
+ va_start(arglist, format);
+
+ assert(string != NULL);
+ assert(format != NULL);
+
+ infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF;
+ infile->_ptr = infile->_base = (char *) string;
+ infile->_cnt = strlen(string);
+
+ retval = (_input(infile,format,arglist));
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/stream.c b/private/crt32/stdio/stream.c
new file mode 100644
index 000000000..96946a3cf
--- /dev/null
+++ b/private/crt32/stdio/stream.c
@@ -0,0 +1,95 @@
+/***
+*stream.c - find a stream not in use
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _getstream() - find a stream not in use
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 11-01-87 JCR Multi-thread support
+* 05-24-88 PHG Merged DLL and normal versions
+* 06-10-88 JCR Use near pointer to reference _iob[] entries
+* 08-17-89 GJF Removed _NEAR_, fixed copyright and indenting.
+* 02-16-90 GJF Fixed copyright
+* 03-19-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 10-03-90 GJF New-style function declarator.
+* 12-31-91 GJF Improved multi-thread lock usage [_WIN32_].
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*FILE *_getstream() - find a stream not in use
+*
+*Purpose:
+* find a stream not in use and make it available to caller. _lastiob is
+* the last FILE address. intended for use inside library only
+*
+*Entry:
+* None. Reads _iob.
+*
+*Exit:
+* returns a pointer to a free stream, or NULL if all are in use. A
+* stream becomes allocated if the caller decided to use it by setting
+* any r, w, r/w mode.
+*
+* Note: Optimized the code to use a near pointer for the stream. This
+* is especially helpful in large model. However, the drawback is that we
+* need another temporary 'retval' so that when we return NULL, we return
+* 0:0, not DS:0.
+*
+* [Multi-thread note: If a free stream is found, it is returned in a
+* LOCKED state. It is the caller's responsibility to unlock the stream.]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+FILE * _CALLTYPE1 _getstream (
+ void
+ )
+{
+ REG1 FILE *stream = _iob;
+ REG2 FILE *retval = NULL;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ /* Get the iob[] scan lock */
+ _mlock(_IOB_SCAN_LOCK);
+
+ /* Loop through the _iob table looking for a free stream.*/
+ for (; stream <= _lastiob; stream++) {
+
+ if ( !inuse(stream) ) {
+#ifdef MTHREAD
+ index = _iob_index(stream);
+ _lock_str(index);
+
+ /* make sure the _iob entry is still free */
+ if ( inuse(stream) ) {
+ /* no longer free! release the lock and
+ continue looping */
+ _unlock_str(index);
+ continue;
+ }
+#endif
+ stream->_flag = stream->_cnt = 0;
+ stream->_ptr = stream->_base = NULL;
+ stream->_file = -1;
+ retval = stream;
+ break;
+ }
+ }
+
+ _munlock(_IOB_SCAN_LOCK);
+ return(retval);
+}
diff --git a/private/crt32/stdio/swprintf.c b/private/crt32/stdio/swprintf.c
new file mode 100644
index 000000000..b50550edf
--- /dev/null
+++ b/private/crt32/stdio/swprintf.c
@@ -0,0 +1,115 @@
+/***
+*swprintf.c - print formatted to string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines swprintf() and _snwprintf() - print formatted data to string
+*
+*Revision History:
+* 05-16-92 KRS Created from sprintf.c
+* 02-18-93 SRW Make FILE a local and remove lock usage.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <limits.h>
+#include <os2dll.h>
+
+#define MAXSTR INT_MAX
+
+
+/***
+#ifndef _COUNT_
+*int swprintf(string, format, ...) - print formatted data to string
+#else
+*int _snwprintf(string, cnt, format, ...) - print formatted data to string
+#endif
+*
+*Purpose:
+* Prints formatted data to the using the format string to
+* format data and getting as many arguments as called for
+* Sets up a FILE so file i/o operations can be used, make
+* string look like a huge buffer to it, but _flsbuf will
+* refuse to flush it if it fills up. Appends '\0' to make
+* it a true string. _output does the real work here
+*
+* Allocate the 'fake' _iob[] entry statically instead of on
+* the stack so that other routines can assume that _iob[]
+* entries are in are in DGROUP and, thus, are near.
+*
+#ifdef _COUNT_
+* The _snwprintf() flavor takes a count argument that is
+* the max number of wide characters that should be written to the
+* user's buffer.
+#endif
+*
+* Multi-thread: (1) Since there is no stream, this routine must
+* never try to get the stream lock (i.e., there is no stream
+* lock either). (2) Also, since there is only one statically
+* allocated 'fake' iob, we must lock/unlock to prevent collisions.
+*
+*Entry:
+* wchar_t *string - pointer to place to put output
+#ifdef _COUNT_
+* size_t count - max number of wide characters to put in buffer
+#endif
+* wchar_t *format - format string to control data format/number
+* of arguments followed by list of arguments, number and type
+* controlled by format string
+*
+*Exit:
+* returns number of wide characters printed
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifndef _COUNT_
+
+int _CALLTYPE2 swprintf (
+ wchar_t *string,
+ const wchar_t *format,
+ ...
+ )
+#else
+
+int _CALLTYPE2 _snwprintf (
+ wchar_t *string,
+ size_t count,
+ const wchar_t *format,
+ ...
+ )
+#endif
+
+{
+ FILE str;
+ REG1 FILE *outfile = &str;
+ va_list arglist;
+ REG2 int retval;
+
+ va_start(arglist, format);
+
+ assert(string != NULL);
+ assert(format != NULL);
+
+ outfile->_flag = _IOWRT|_IOSTRG;
+ outfile->_ptr = outfile->_base = (char *) string;
+#ifndef _COUNT_
+ outfile->_cnt = MAXSTR;
+#else
+ outfile->_cnt = count*sizeof(wchar_t);
+#endif
+
+ retval = _woutput(outfile,format,arglist);
+
+ _putc_lk('\0',outfile); /* no-lock version */
+ _putc_lk('\0',outfile); /* 2nd null byte for wchar_t version */
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/swscanf.c b/private/crt32/stdio/swscanf.c
new file mode 100644
index 000000000..65d99a69e
--- /dev/null
+++ b/private/crt32/stdio/swscanf.c
@@ -0,0 +1,81 @@
+/***
+*swscanf.c - read formatted data from wide-character string
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _swscanf() - reads formatted data from wide-character string
+*
+*Revision History:
+* 11-21-91 ETC Created from sscanf.c
+# 05-16-92 KRS Revised for new ISO spec. format is wchar_t * now.
+* 02-18-93 SRW Make FILE a local and remove lock usage.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int swscanf(string, format, ...) - read formatted data from wide-char string
+*
+*Purpose:
+* Same as sscanf (described below) from reads from a wide-char string.
+*
+* Reads formatted data from string into arguments. _winput does the real
+* work here. Sets up a FILE so file i/o operations can be used, makes
+* string look like a huge buffer to it, but _filbuf will refuse to refill
+* it if it is exhausted.
+*
+* Allocate the 'fake' _iob[] entryit statically instead of on
+* the stack so that other routines can assume that _iob[] entries are in
+* are in DGROUP and, thus, are near.
+*
+* Multi-thread: (1) Since there is no stream, this routine must never try
+* to get the stream lock (i.e., there is no stream lock either). (2)
+* Also, since there is only one staticly allocated 'fake' iob, we must
+* lock/unlock to prevent collisions.
+*
+*Entry:
+* wchar_t *string - wide-character string to read data from
+* wchar_t *format - format string
+* followed by list of pointers to storage for the data read. The number
+* and type are controlled by the format string.
+*
+*Exit:
+* returns number of fields read and assigned
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 swscanf (
+ REG2 const wchar_t *string,
+ const wchar_t *format,
+ ...
+ )
+{
+ va_list arglist;
+ FILE str;
+ REG1 FILE *infile = &str;
+ REG2 int retval;
+
+ va_start(arglist, format);
+
+ assert(string != NULL);
+ assert(format != NULL);
+
+ infile->_flag = _IOREAD|_IOSTRG|_IOMYBUF;
+ infile->_ptr = infile->_base = (char *) string;
+ infile->_cnt = wcslen(string)*sizeof(wchar_t);
+
+ retval = (_winput(infile,format,arglist));
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/tempnam.c b/private/crt32/stdio/tempnam.c
new file mode 100644
index 000000000..4539ba870
--- /dev/null
+++ b/private/crt32/stdio/tempnam.c
@@ -0,0 +1,262 @@
+/***
+*tempnam.c - generate unique file name
+*
+* Copyright (c) 1986-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* ??-??-?? TC initial version
+* 04-17-86 JMB changed directory of last resort from \tmp to tmp.
+* eliminated use of L_tmpnam (it was incoorectly defined
+* in stdio.h and should not be used in tempnam; see
+* System V definition of tempnam.
+* 04-23-86 TC changed last try directory from tmp to current directory
+* 04-29-86 JMB bug fix: pfxlength was being set from strlen(pfx)
+* even if pfx was NULL. Fixed to set pfxlength to zero
+* if pfx is NULL, strlen(pfx) otherwise.
+* 05-28-86 TC changed stat's to access's, and optimized code a bit
+* 12-01-86 JMB added support for Kanji file names until KANJI switch
+* 12-15-86 JMB free malloced memory if (++_tmpoff == first)
+* 07-15-87 JCR Re-init _tempoff based on length of pfx (fixes infinate
+* loop bug; also, tempnam() now uses _tempoff instead of
+* _tmpoff (used by tmpnam()).
+* 10-16-87 JCR Fixed bug in _tempoff re-init code if pfx is NULL.
+* 11-09-87 JCR Multi-thread version
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-09-89 GJF Propagated MT's change of 05-17-89 (Kanji)
+* 02-16-90 GJF Fixed copyright and indents
+* 03-19-90 GJF Replaced _LOAD_DS and _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 03-26-90 GJF Added #include <io.h>.
+* 08-13-90 SBM Compiles cleanly with -W3, replaced explicit register
+* declarations by REGn references
+* 10-03-90 GJF New-style function declarator.
+* 01-21-91 GJF ANSI naming.
+* 08-19-91 JCR Allow quotes in TMP variable path
+* 08-27-91 JCR ANSI naming
+* 08-25-92 GJF Don't build for POSIX.
+* 11-30-92 KRS Generalize KANJI support to MBCS. Port 16-bit bug fix.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <internal.h>
+#include <os2dll.h>
+
+#ifdef _MBCS
+#include <mbstring.h>
+#endif
+
+static char * _stripquote (char *);
+
+/***
+*char *_tempnam(dir, prefix) - create unique file name
+*
+*Purpose:
+* Create a file name that is unique in the specified directory.
+* The semantics of directory specification is as follows:
+* Use the directory specified by the TMP environment variable
+* if that exists, else use the dir argument if non-NULL, else
+* use _P_tmpdir if that directory exists, else use the current
+* working directory), else return NULL.
+*
+*Entry:
+* char *dir - directory to be used for temp file if TMP env var
+* not set
+* char *prefix - user provided prefix for temp file name
+*
+*Exit:
+* returns ptr to constructed file name if successful
+* returns NULL if unsuccessful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _tempnam (
+ char *dir,
+ char *pfx
+ )
+{
+ REG1 char *ptr;
+ REG2 unsigned int pfxlength=0;
+ char *s;
+ char *pfin;
+ unsigned int first;
+ char * qptr = NULL; /* ptr to TMP path with quotes stripped out */
+
+ /* try TMP path */
+ if ( ( ptr = getenv( "TMP" ) ) && ( _access( ptr, 0 ) != -1 ) )
+ dir = ptr;
+
+ /* try stripping quotes out of TMP path */
+ else if ( (ptr != NULL) && (qptr = _stripquote(ptr)) &&
+ (_access(qptr, 0) != -1 ) )
+ dir = qptr;
+
+ /* TMP path not available, use alternatives */
+ else if (!( dir != NULL && ( _access( dir, 0 ) != -1 ) ) )
+ /* do not "simplify" this depends on side effects!! */
+ {
+ free(qptr); /* free buffer, if non-NULL */
+ if ( _access( _P_tmpdir, 0 ) != -1 )
+ dir = _P_tmpdir;
+ else
+ dir = ".";
+ }
+
+
+ if (pfx)
+ pfxlength = strlen(pfx);
+ if ( ( s = malloc(strlen(dir) + pfxlength + 8 ) ) == NULL )
+ /* the 8 above allows for a backslash, 6 char temp string and
+ a null terminator */
+ {
+ goto done2;
+ }
+ *s = '\0';
+ strcat( s, dir );
+ pfin = &(dir[ strlen( dir ) - 1 ]);
+#ifdef _MBCS
+ if (*pfin == '\\') {
+ if (pfin != _mbsrchr(dir,'\\'))
+ /* *pfin is second byte of a double-byte char */
+ strcat( s, "\\" );
+ }
+ else if (*pfin != '/')
+ strcat( s, "\\" );
+#else
+ if ( ( *pfin != '\\' ) && ( *pfin != '/' ) )
+ {
+ strcat( s, "\\" );
+ }
+#endif
+ if ( pfx != NULL )
+ {
+ strcat( s, pfx );
+ }
+ ptr = &s[strlen( s )];
+
+ /*
+ Re-initialize _tempoff if necessary. If we don't re-init _tempoff, we
+ can get into an infinate loop (e.g., (a) _tempoff is a big number on
+ entry, (b) prefix is a long string (e.g., 8 chars) and all tempfiles
+ with that prefix exist, (c) _tempoff will never equal first and we'll
+ loop forever).
+
+ [NOTE: To avoid a conflict that causes the same bug as that discussed
+ above, _tempnam() uses _tempoff; tmpnam() uses _tmpoff]
+ */
+
+ _mlock(_TMPNAM_LOCK); /* Lock access to _old_pfxlen and _tempoff */
+
+ if (_old_pfxlen < pfxlength)
+ _tempoff = 1;
+ _old_pfxlen = pfxlength;
+
+ first = _tempoff;
+
+ do {
+ if ( ++_tempoff == first ) {
+ free(s);
+ s = NULL;
+ goto done1;
+ }
+ _itoa( _tempoff, ptr, 10 );
+ if ( strlen( ptr ) + pfxlength > 8 )
+ {
+ *ptr = '\0';
+ _tempoff = 0;
+ }
+ }
+ while ( (_access( s, 0 ) == 0 ) || (errno == EACCES) );
+
+
+ /* Common return */
+done1:
+ _munlock(_TMPNAM_LOCK); /* release tempnam lock */
+done2:
+ free(qptr); /* free temp ptr, if non-NULL */
+ return(s);
+}
+
+
+
+/***
+*_stripquote() - Strip quotes out of a string
+*
+*Purpose:
+* This routine strips quotes out of a string. This is necessary
+* in the case where a file/path name has embedded quotes (i.e.,
+* new file system.)
+*
+* For example,
+* c:\tmp\"a b c"\d --> c:\tmp\a b d\d
+*
+* NOTE: This routine makes a copy of the string since it may be
+* passed a pointer to an environment variable that shouldn't be
+* changed. It is up to the caller to free up the memory (if the
+* return value is non-NULL).
+*
+*Entry:
+* char * ptr = pointer to string
+*
+*Exit:
+* char * ptr = pointer to copy of string with quotes gone.
+* NULL = no quotes in string.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _stripquote (src)
+char * src;
+{
+ char * dst;
+ char * ret;
+ unsigned int q = 0;
+
+
+ /* get a buffer for the new string */
+
+ if ((dst = malloc(strlen(src)+1)) == NULL)
+ return(NULL);
+
+ /* copy the string stripping out the quotes */
+
+ ret = dst; /* save base ptr */
+
+ while (*src) {
+
+ if (*src == '\"') {
+ src++; q++;
+ }
+ else
+ *dst++ = *src++;
+ }
+
+ if (q) {
+ *dst = '\0'; /* final nul */
+ return(ret);
+ }
+ else {
+ free(ret);
+ return(NULL);
+ }
+
+}
+
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/stdio/test_out.c b/private/crt32/stdio/test_out.c
new file mode 100644
index 000000000..b2fd59bd4
--- /dev/null
+++ b/private/crt32/stdio/test_out.c
@@ -0,0 +1,224 @@
+/***
+*test_out.c - test output.c
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains a small test suite for output.c. Although
+* it is certainly not comprehensive, it should catch most major bugs.
+*
+*Revision History:
+* 06-05-89 PHG Module created
+* 03-19-90 GJF Fixed copyright.
+* 10-03-90 GJF New-style function declarator.
+* 06-08-92 KRS Updated for 32-bit sizes and wchar_t specifiers.
+*
+*******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+void test (
+ char *shouldbe,
+ char *format,
+ ...
+ )
+{
+ va_list argptr;
+ char buffer[500];
+
+ va_start(argptr, format);
+
+ vsprintf(buffer, format, argptr);
+ if (strcmp(shouldbe, buffer) != 0)
+ printf("Was: \"%s\"\nShould be: \"%s\"\n", buffer, shouldbe);
+}
+
+main()
+{
+ int i;
+ long l;
+
+ /* normal */
+ test("Hello, world!", "Hello, world!");
+
+ /* test %s */
+ test("Hello, world!", "%s", "Hello, world!");
+ test("Hello, world!", "%.20s", "Hello, world!");
+ test("Hello", "%.5s", "Hello, world!");
+ test("", "%.s", "Hello, world!");
+ test("(null)", "%s", NULL);
+ test(" Hello, world!", "%20s", "Hello, world!");
+ test("Hello, world! ", "%-20s", "Hello, world!");
+ test(" Hello", "%20.5s", "Hello, world!");
+ test("Hello ", "%-20.5s", "Hello, world!");
+ test("Hello", "%3.5s", "Hello, world!");
+ test("Hello", "%-3.5s", "Hello, world!");
+ test("Hello, world!", "%-8s", "Hello, world!");
+ test("Hello, world!", "%8s", "Hello, world!");
+
+ /* test %ws, %ls, %Zi (should be %S) */
+ test("Hello, world!", "%ws", L"Hello, world!");
+ test("Hello, world!", "%.20Z", L"Hello, world!");
+ test("Hello", "%.5ls", L"Hello, world!");
+ test("", "%.ws", L"Hello, world!");
+ test("(null)", "%ls", NULL);
+ test("(null)", "%ws", NULL);
+ test("(null)", "%Z", NULL);
+ test(" Hello, world!", "%20ls", L"Hello, world!");
+ test("Hello, world! ", "%-20ws", L"Hello, world!");
+ test(" Hello", "%20.5Z", L"Hello, world!");
+ test("Hello ", "%-20.5ls", L"Hello, world!");
+ test("Hello", "%3.5ws", L"Hello, world!");
+ test("Hello", "%-3.5Z", L"Hello, world!");
+ test("Hello, world!", "%-8ls", L"Hello, world!");
+ test("Hello, world!", "%8ws", L"Hello, world!");
+
+
+ /* test %wc, %lc, should also add %C */
+ test("H", "%lc", L'H');
+ test(" H", "%5lc", L'H');
+ test("H ", "%-5lc", L'H');
+ test("H", "%wc", L'H');
+ test(" H", "%5wc", L'H');
+ test("H ", "%-5wc", L'H');
+
+ /* test %d/%u */
+ test("54", "%d", 54);
+ test("-42", "%i", -42);
+ test(" -102", "%6d", -102);
+ test("0 ", "%-6d", 0);
+ test("00000", "%.5d", 0);
+ test("-0345", "%.4d", -345);
+ test("-345", "%.3d", -345);
+ test("00345", "%.5d", 345);
+ test("00345", "%05d", 345);
+ test("345 ", "%-05d", 345);
+ test(" -00055", "%10.5d", -55);
+ test("-00055 ", "%-10.5d", -55);
+ test(" ", "%5.0d", 0);
+ test("12345678", "%ld", 12345678);
+ test("+123", "%+d", 123);
+ test("-123", "%+d", -123);
+ test("+000123", "%+07d", 123);
+ test(" 000123", "% 07d", 123);
+ test("+123 ", "%+-7d", 123);
+ test(" +0123", "%+7.4i", 123);
+ test("-1", "%d", 0xFFFFFFFF);
+ test("65535", "%u", 0xFFFF);
+
+ /* test %x */
+ test("DEF", "%X", 0xdef);
+ test("14d ", "%-6x", 0x14d);
+ test(" 0X14D", "%#6X", 0x14d);
+ test("0x00014d ", "%#-10.6x", 0x14d);
+ test("0", "%#x", 0);
+ test("", "%.0x", 0);
+ test(" ", "%#2.0X", 0);
+ test("000000014d", "%010x", 0x14d);
+ test("14d ", "%-010x", 0x14d);
+ test("0x0000014d", "%#010x", 0x14d);
+ test("FFFF", "%X", 0xffff);
+
+ /* temp: %B/%C should go away */
+ test("DEF", "%B", 0xdef);
+ test("14D ", "%-6C", 0x14d);
+ test(" 0X14D", "%#6B", 0x14d);
+ test("0X00014D ", "%#-10.6C", 0x14d);
+ test("0", "%#B", 0);
+ test("", "%.0C", 0);
+ test(" ", "%#2.0B", 0);
+ test("000000014D", "%010C", 0x14d);
+ test("14D ", "%-010B", 0x14d);
+ test("0X0000014D", "%#010C", 0x14d);
+ test("FFFF", "%B", 0xffff);
+
+ /* test %o */
+ test("703", "%o", 0703);
+ test(" 703", "%6o", 0703);
+ test(" 0703", "%#6o", 0703);
+ test("0703 ", "%#-6o", 0703);
+ test("000703", "%06o", 0703);
+ test("00703 ", "%-#6.5o", 0703);
+ test("0703 ", "%-#06o", 0703);
+ test(" 00703", "%#6.5o", 0703);
+ test("0", "%#.0o", 0);
+ test("", "%.0o", 0);
+ test("177777", "%o", 0xFFFF);
+
+ /* test %p */
+ test("000000FE", "%p", (char *)0x00fe);
+ test("00003DFE ", "%-10p", (char *)0x3dfe);
+ test(" 00009DF4", "%12p", (char *)0x9df4);
+
+ /* test %n */
+ test("Hello, world", "Hello, world%n", &i);
+ test("12", "%i", i);
+ test("This is 423 characters ", "This is %d characters %ln", 423, &l);
+ test("23", "%ld", l);
+ test("0x0003f", "%#.5x%n", 0x3f, &i);
+ test("7", "%d", i);
+
+ /* test multiple specifiers */
+ test("24 43", "%d %d", 24, 43);
+ test("24 43", "%ld %ld", 24l, 43L);
+ test("00004ABC 43", "%p %d", (char *)0x4abc, 43);
+ test("43", "%n%d", &i, 43);
+ test("43", "%ln%d", &l, 43);
+
+ printf("Completed all non-FP format specifiers\n");
+
+ printf("Processing %%e\n");
+
+ /* test %e */
+ test("-4.000000e+000", "%e", -4.0);
+ test("4.000000E+000", "%E", 4.0);
+ test("-7E+001", "%.0E", -68.5);
+ test("-7.E+001", "%#.0E", -74.5);
+ test(" 6.78e+004 ", "% -12.2e", 67844.324);
+ test(" +6.78e+004", "%+12.2e", 67844.324);
+ test(" 0.000000e+000", "%17e", 0.0);
+ test("-00007.467e-001", "%015.3e", -0.74673);
+
+ printf("Processing %%f\n");
+
+ /* test %f */
+ test("-4.000000", "%f", -4.0);
+ test("4.000000", "%f", 4.0);
+ test("0.400000", "%f", 0.4);
+ test("-69", "%.0f", -68.7);
+ test("-74.", "%#.0f", -74.3);
+ test(" 67844.32 ", "% -12.2f", 67844.324);
+ test(" +67844.32", "%+12.2f", 67844.324);
+ test(" 0.000000", "%17f", 0.0);
+ test("-0000000000.747", "%015.3f", -0.74673);
+
+ printf("Processing %%g\n");
+
+ /* test %g */
+ test("3.14159E-005", "%G", 0.000031415926535);
+ test("0.000314159", "%g", 0.00031415926535);
+ test("0.00314159", "%g", 0.0031415926535);
+ test("0.0314159", "%g", 0.031415926535);
+ test("0.314159", "%g", 0.31415926535);
+ test("3.14159", "%g", 3.1415926535);
+ test("31.4159", "%g", 31.415926535);
+ test("314.159", "%g", 314.15926535);
+ test("3141.59", "%g", 3141.5926535);
+ test("31415.9", "%g", 31415.926535);
+ test("314159", "%g", 314159.26535);
+ test("3.14159e+006" , "%g", 3141592.6535);
+ test("3", "%g", 3.0);
+ test("3e+006", "%g", 3000000.0);
+ test(" 3.14", "%7.4g", 3.1402);
+ test(" 3.14 ", "% -7.4g", 3.1402);
+ test("+0023.000", "%+#09.5g", 23.0);
+ test("23.", "%#.2g", 23.0);
+ test("23", "%.2g", 23.0);
+
+ /* more multiples */
+ test("3.1 43", "%g %d", 3.1, 43);
+ test("3.1 43", "%Lg %d", (long double)3.1, 43);
+
+}
diff --git a/private/crt32/stdio/tmpfile.c b/private/crt32/stdio/tmpfile.c
new file mode 100644
index 000000000..da6f15307
--- /dev/null
+++ b/private/crt32/stdio/tmpfile.c
@@ -0,0 +1,418 @@
+/***
+*tmpfile.c - create unique file name or file
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines tmpnam() and tmpfile().
+*
+*Revision History:
+* ??-??-?? TC initial version
+* 04-17-86 JMB tmpnam - brought semantics in line with System V
+* definition as follows: 1) if tmpnam paramter is NULL,
+* store name in static buffer (do NOT use malloc); (2)
+* use P_tmpdir as the directory prefix to the temp file
+* name (do NOT use current working directory)
+* 05-26-87 JCR fixed bug where tmpnam was modifying errno
+* 08-10-87 JCR Added code to support P_tmpdir with or without trailing
+* '\'.
+* 11-09-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-22-88 JCR Added per thread static namebuf area (mthread bug fix)
+* 05-27-88 PHG Merged DLL/normal versions
+* 11-14-88 GJF _openfile() now takes a file sharing flag, also some
+* cleanup (now specific to the 386)
+* 06-06-89 JCR 386 mthread support
+* 11-28-89 JCR Added check to _tmpnam so it can't loop forever
+* 02-16-90 GJF Fixed copyright and indents
+* 03-19-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-26-90 GJF Added #include <io.h>.
+* 10-03-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 07-22-91 GJF Multi-thread support for Win32 [_WIN32_].
+* 03-17-92 GJF Completely rewrote Win32 version.
+* 03-27-92 DJM POSIX support.
+* 05-02-92 SRW Use _O_TEMPORARY flag for tmpfile routine.
+* 05-04-92 GJF Force cinittmp.obj in for Win32.
+* 08-26-92 GJF Fixed POSIX build.
+* 08-28-92 GJF Oops, forgot about getpid...
+* 11-06-92 GJF Use '/' for POSIX, '\\' otherwise, as the path
+* separator. Also, backed out JHavens' bug fix of 6-14,
+* which was itself a bug (albeit a less serious one).
+* 02-26-93 GJF Put in per-thread buffers, purged Cruiser support.
+*
+*******************************************************************************/
+
+
+#include <cruntime.h>
+#ifdef _POSIX_
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <process.h>
+#include <fcntl.h>
+#include <io.h>
+#include <os2dll.h>
+#include <share.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <file2.h>
+#include <internal.h>
+
+/*
+ * Pointers to buffers used by tmpnam() and tmpfile() to build filenames.
+ * Each is initialized on first use.
+ */
+#ifdef MTHREAD
+
+/*
+ * The following macros ASSSUME that ptd is the name local _ptiddata variable
+ * in each frame!
+ */
+#define namebuf0 (ptd->_namebuf0)
+#define namebuf1 (ptd->_namebuf1)
+
+#else /* not MTHREAD */
+
+static char *namebuf0 = NULL; /* used by tmpnam() */
+static char *namebuf1 = NULL; /* used by tmpfile() */
+
+#endif /* MTHREAD */
+
+/*
+ * Initializing function for namebuf0 and namebuf1.
+ */
+static int _CRTAPI3 init_namebuf(int, char **);
+
+/*
+ * Generator function that produces temporary filenames
+ */
+static int _CRTAPI3 genfname(char *);
+
+
+/***
+*char *tmpnam(char *s) - generate temp file name
+*
+*Purpose:
+* Creates a file name that is unique in the directory specified by
+* _P_tmpdir in stdio.h. Places file name in string passed by user or
+* in static mem if pass NULL.
+*
+*Entry:
+* char *s - ptr to place to put temp name
+*
+*Exit:
+* returns pointer to constructed file name (s or address of static mem)
+* returns NULL if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CRTAPI1 tmpnam (
+ char *s
+ )
+{
+#ifdef MTHREAD
+ _ptiddata ptd = _getptd();
+#endif
+
+ _mlock(_TMPNAM_LOCK);
+
+ /*
+ * Initialize namebuf0, if needed. Otherwise, call genfname() to
+ * generate the next filename.
+ */
+ if ( namebuf0 == NULL ) {
+ if ( init_namebuf(0, &namebuf0) )
+ goto tmpnam_err;
+ }
+ else if ( genfname(namebuf0) )
+ goto tmpnam_err;
+
+ /*
+ * Generate a filename that doesn't already exist.
+ */
+ while ( access(namebuf0, 0) == 0 )
+ if ( genfname(namebuf0) )
+ goto tmpnam_err;
+
+ /*
+ * Filename has successfully been generated.
+ */
+ if ( s == NULL )
+ s = namebuf0;
+ else
+ strcpy(s, namebuf0);
+
+ _munlock(_TMPNAM_LOCK);
+ return s;
+
+ /*
+ * Error return path. All errors exit through here.
+ */
+tmpnam_err:
+ _munlock(_TMPNAM_LOCK);
+ return NULL;
+}
+
+
+/***
+*FILE *tmpfile() - create a temporary file
+*
+*Purpose:
+* Creates a temporary file with the file mode "w+b". The file
+* will be automatically deleted when closed or the program terminates
+* normally.
+*
+*Entry:
+* None.
+*
+*Exit:
+* Returns stream pointer to opened file.
+* Returns NULL if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+FILE * _CRTAPI1 tmpfile (
+ void
+ )
+{
+ FILE *stream;
+ int fh;
+#ifdef MTHREAD
+ _ptiddata ptd = _getptd();
+#endif
+
+ _mlock(_TMPNAM_LOCK);
+
+ /*
+ * Initialize namebuf1, if needed. Otherwise, call genfname() to
+ * generate the next filename.
+ */
+ if ( namebuf1 == NULL ) {
+ if ( init_namebuf(1, &namebuf1) )
+ goto tmpfile_err0;
+ }
+ else if ( genfname(namebuf1) )
+ goto tmpfile_err0;
+
+ /*
+ * Get a free stream.
+ *
+ * Note: In multi-thread models, the stream obtained below is locked!
+ */
+ if ( (stream = _getstream()) == NULL )
+ goto tmpfile_err0;
+
+ /*
+ * Create a temporary file.
+ *
+ * Note: The loop below will only create a new file. It will NOT
+ * open and truncate an existing file. Either behavior is probably
+ * legal under ANSI (4.9.4.3 says tmpfile "creates" the file, but
+ * also says it is opened with mode "wb+"). However, the behavior
+ * implemented below is compatible with prior versions of MS-C and
+ * makes error checking easier.
+ */
+#ifdef _POSIX_
+ while ( ((fh = open(namebuf1,
+ O_CREAT | O_EXCL | O_RDWR,
+ S_IRUSR | S_IWUSR
+ ))
+ == -1) && (errno == EEXIST) )
+#else
+ while ( ((fh = _sopen(namebuf1,
+ _O_CREAT | _O_EXCL | _O_RDWR | _O_BINARY |
+ _O_TEMPORARY,
+ _SH_DENYNO,
+ _S_IREAD | _S_IWRITE
+ ))
+ == -1) && (errno == EEXIST) )
+#endif
+ if ( genfname(namebuf1) )
+ break;
+
+ /*
+ * Check that the loop above did indeed create a temporary
+ * file.
+ */
+ if ( fh == -1 )
+ goto tmpfile_err1;
+
+ /*
+ * Initialize stream
+ */
+ if ( (stream->_tmpfname = _strdup(namebuf1)) == NULL ) {
+ /* close the file, then branch to error handling */
+#ifdef _POSIX_
+ close(fh);
+#else
+ _close(fh);
+#endif
+ goto tmpfile_err1;
+ }
+ stream->_cnt = 0;
+ stream->_base = stream->_ptr = NULL;
+ stream->_flag = _commode | _IORW;
+ stream->_file = fh;
+
+ _unlock_str(_iob_index(stream));
+ _munlock(_TMPNAM_LOCK);
+ return stream;
+
+ /*
+ * Error return. All errors paths branch to one of the two
+ * labels below.
+ */
+tmpfile_err1:
+ _unlock_str(_iob_index(stream));
+tmpfile_err0:
+ _munlock(_TMPNAM_LOCK);
+ return NULL;
+}
+
+
+/***
+*static int init_namebuf(flag, pnamebuf) - initializes the namebuf
+* pointers
+*
+*Purpose:
+* Called once each for namebuf0 and namebuf1, to initialize
+* them.
+*
+*Entry:
+* int flag - flag set to 0 if namebuf0 is to be initialized,
+* non-zero (1) if namebuf1 is to be initialized.
+* char **pnamebuf - pointer to namebuf0 iff flag is 0,
+* pointer to namebuf1 iff flag is 1
+*
+*Exit:
+* Returns 0 if successful, nonzero (-1) otherwise.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CRTAPI3 init_namebuf(
+ int flag,
+ char **pnamebuf
+ )
+{
+ char *p, *q;
+
+ /*
+ * Allocate space to hold the filename stem
+ */
+ if ( (p = malloc(L_tmpnam)) == NULL )
+ return -1;
+
+ /*
+ * Put in the path prefix. Make sure it ends with a slash or
+ * backslash character.
+ */
+ strcpy(p, _P_tmpdir);
+ q = p + sizeof(_P_tmpdir) - 1; /* same as p + strlen(p) */
+
+#ifdef _POSIX_
+ if ( *(q - 1) != '/' )
+ *(q++) = '/';
+#else
+ if ( (*(q - 1) != '\\') && (*(q - 1) != '/') )
+ *(q++) = '\\';
+#endif
+
+ /*
+ * Append the leading character of the filename.
+ */
+ if ( flag )
+ /* for tmpfile() */
+ *(q++) = 't';
+ else
+ /* for tmpnam() */
+ *(q++) = 's';
+
+ /*
+ * Append the process id, encoded in base 32. Note this makes
+ * p back into a string again (i.e., terminated by a '\0').
+ */
+#ifdef _POSIX_
+ _ultoa((unsigned long)getpid(), q, 32);
+#else
+ _ultoa((unsigned long)_getpid(), q, 32);
+#endif
+ strcat(p, ".");
+
+ *pnamebuf = p;
+
+ return(0);
+}
+
+
+/***
+*static int genfname(char *fname) -
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CRTAPI3 genfname (
+ char *fname
+ )
+{
+ char *p;
+ char pext[4];
+ unsigned long extnum;
+
+ p = strrchr(fname, '.');
+
+ p++;
+
+ if ( (extnum = strtoul(p, NULL, 32) + 1) >= (unsigned long)TMP_MAX )
+ return -1;
+
+ strcpy(p, _ultoa(extnum, pext, 32));
+
+ return 0;
+}
+
+
+/***
+*void __inc_tmpoff(void) - force external reference for _tmpoff
+*
+*Purpose:
+* Forces an external reference to be generate for _tmpoff, which is
+* is defined in cinittmp.obj. This has the forces cinittmp.obj to be
+* pulled in, making a call to rmtmp part of the termination.
+*
+* Yes, yes, I KNOW this is a hack...but it's quick and it works.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+extern int _tmpoff;
+
+void __inc_tmpoff(
+ void
+ )
+{
+ _tmpoff++;
+}
diff --git a/private/crt32/stdio/ungetc.c b/private/crt32/stdio/ungetc.c
new file mode 100644
index 000000000..e8b912ffe
--- /dev/null
+++ b/private/crt32/stdio/ungetc.c
@@ -0,0 +1,174 @@
+/***
+*ungetc.c - unget a character from a stream
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines ungetc() - pushes a character back onto an input stream
+*
+*Revision History:
+* 09-02-83 RN initial version
+* 04-16-87 JCR added support for _IOUNGETC flag
+* 08-04-87 JCR (1) Added _IOSTRG check before setting _IOUNGETC flag.
+* (2) Allow an ugnetc() before a read has occurred (get a
+* buffer (ANSI). [MSC only]
+* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
+* 11-04-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-25-88 JCR Allow an ungetc() before read for file opened "r+".
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-06-88 JCR Optimized _iob2 references
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 04-11-89 JCR Removed _IOUNGETC flag, fseek() no longer needs it
+* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-16-90 GJF Fixed copyright
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
+* 08-13-90 SBM Compiles cleanly with -W3
+* 10-03-90 GJF New-style function declarators.
+* 11-07-92 SRW Dont modify buffer if stream opened by sscanf
+* 04-26-93 CFW Wide char enable.
+* 04-30-93 CFW Remove wide char support to ungetwc.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#include <internal.h>
+#include <os2dll.h>
+
+#ifdef MTHREAD /* multi-thread; define both ungetc and _lk_ungetc */
+
+/***
+*int ungetc(ch, stream) - put a character back onto a stream
+*
+*Purpose:
+* Guaranteed one char pushback on a stream as long as open for reading.
+* More than one char pushback in a row is not guaranteed, and will fail
+* if it follows an ungetc which pushed the first char in buffer. Failure
+* causes return of EOF.
+*
+*Entry:
+* char ch - character to push back
+* FILE *stream - stream to push character onto
+*
+*Exit:
+* returns ch
+* returns EOF if tried to push EOF, stream not opened for reading or
+* or if we have already ungetc'd back to beginning of buffer.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 ungetc (
+ REG2 int ch,
+ REG1 FILE *stream
+ )
+{
+ int retval;
+ int index;
+
+ assert(stream != NULL);
+
+ index = _iob_index(stream);
+
+ _lock_str(index);
+
+ retval = _ungetc_lk (ch, stream);
+
+ _unlock_str(index);
+
+ return(retval);
+}
+
+/***
+*_ungetc_lk() - Ungetc() core routine (locked version)
+*
+*Purpose:
+* Core ungetc() routine; assumes stream is already locked.
+*
+* [See ungetc() above for more info.]
+*
+*Entry: [See ungetc()]
+*
+*Exit: [See ungetc()]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ungetc_lk (
+ REG2 int ch,
+ FILE *str
+ )
+
+{
+
+#else /* non multi-thread; just define ungetc */
+
+int _CRTAPI1 ungetc (
+ REG2 int ch,
+ FILE *str
+ )
+
+{
+
+#endif /* rejoin common code */
+
+ REG1 FILE *stream;
+
+ assert(str != NULL);
+
+ /* Init stream pointer and file descriptor */
+ stream = str;
+
+ /* Stream must be open for read and can NOT be currently in write mode.
+ Also, ungetc() character cannot be EOF. */
+
+ if (
+ (ch == EOF) ||
+ !(
+ (stream->_flag & _IOREAD) ||
+ ((stream->_flag & _IORW) && !(stream->_flag & _IOWRT))
+ )
+ )
+ return(EOF);
+
+ /* If stream is unbuffered, get one. */
+
+ if (stream->_base == NULL)
+ _getbuf(stream);
+
+ /* now we know _base != NULL; since file must be buffered */
+
+ if (stream->_ptr == stream->_base) {
+ if (stream->_cnt)
+ /* my back is against the wall; i've already done
+ * ungetc, and there's no room for this one
+ */
+ return(EOF);
+
+ stream->_ptr++;
+ }
+
+ if (stream->_flag & _IOSTRG) {
+ /* If stream opened by sscanf do not modify buffer */
+ if (*--stream->_ptr != (char)ch) {
+ ++stream->_ptr;
+ return(EOF);
+ }
+ } else
+ *--stream->_ptr = (char)ch;
+
+ stream->_cnt++;
+ stream->_flag &= ~_IOEOF;
+ stream->_flag |= _IOREAD; /* may already be set */
+
+ return(0xff & ch);
+}
diff --git a/private/crt32/stdio/ungetwc.c b/private/crt32/stdio/ungetwc.c
new file mode 100644
index 000000000..5d3c82994
--- /dev/null
+++ b/private/crt32/stdio/ungetwc.c
@@ -0,0 +1,206 @@
+/***
+*ungetc.c - unget a character from a stream
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines ungetc() - pushes a character back onto an input stream
+*
+*Revision History:
+* 04-26-93 CFW Module created.
+* 04-30-93 CFW Bring wide char support from ungetc.c.
+* 05-10-93 CFW Optimize, fix error handling.
+* 06-02-93 CFW Wide get/put use wint_t.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <file2.h>
+#include <assert.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <msdos.h>
+#include <errno.h>
+#include <wchar.h>
+#include <setlocal.h>
+
+#ifdef MTHREAD /* multi-thread; define both ungetwc and _lk_ungetwc */
+
+/***
+*wint_t ungetwc(ch, stream) - put a wide character back onto a stream
+*
+*Purpose:
+* Guaranteed one char pushback on a stream as long as open for reading.
+* More than one char pushback in a row is not guaranteed, and will fail
+* if it follows an ungetc which pushed the first char in buffer. Failure
+* causes return of WEOF.
+*
+*Entry:
+* wint_t ch - wide character to push back
+* FILE *stream - stream to push character onto
+*
+*Exit:
+* returns ch
+* returns WEOF if tried to push WEOF, stream not opened for reading or
+* or if we have already ungetc'd back to beginning of buffer.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wint_t _CRTAPI1 ungetwc (
+ REG2 wint_t ch,
+ REG1 FILE *stream
+ )
+{
+ wint_t retval;
+ int index;
+
+ assert(stream != NULL);
+
+ index = _iob_index(stream);
+
+ _lock_str(index);
+
+ retval = _ungetwc_lk (ch, stream);
+
+ _unlock_str(index);
+
+ return(retval);
+}
+
+/***
+*_ungetwc_lk() - Ungetwc() core routine (locked version)
+*
+*Purpose:
+* Core ungetwc() routine; assumes stream is already locked.
+*
+* [See ungetwc() above for more info.]
+*
+*Entry: [See ungetwc()]
+*
+*Exit: [See ungetwc()]
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wint_t _CRTAPI1 _ungetwc_lk (
+ wint_t ch,
+ FILE *str
+ )
+{
+
+#else /* non multi-thread; just define ungetc */
+
+wint_t _CRTAPI1 ungetwc (
+ wint_t ch,
+ FILE *str
+ )
+{
+
+#endif /* rejoin common code */
+
+ assert(str != NULL);
+
+ /*
+ * Requirements for success:
+ *
+ * 1. Character to be pushed back on the stream must not be WEOF.
+ *
+ * 2. The stream must currently be in read mode, or must be open for
+ * update (i.e., read/write) and must NOT currently be in write
+ * mode.
+ */
+ if ( (ch != WEOF) &&
+ ( (str->_flag & _IOREAD) || ((str->_flag & _IORW) &&
+ !(str->_flag & _IOWRT))
+ )
+ )
+ {
+ /* If stream is unbuffered, get one. */
+ if (str->_base == NULL)
+ _getbuf(str);
+
+#ifndef _NTSUBSET_
+ if (!(str->_flag & _IOSTRG) && _osfile[_fileno(str)] & FTEXT)
+ {
+ /*
+ * Text mode, sigh... Convert the wc to a mbc.
+ */
+ int size, defused;
+ char mbc[4];
+
+ size = WideCharToMultiByte(_lc_codepage,
+ WC_COMPOSITECHECK | WC_SEPCHARS,
+ (wchar_t *)&ch,
+ 1,
+ mbc,
+ MB_CUR_MAX,
+ NULL,
+ &defused);
+
+ if ( (size == 0) || defused )
+ {
+ /*
+ * Conversion failed! Set errno and return
+ * failure.
+ */
+ errno = EILSEQ;
+ return WEOF;
+ }
+
+ /* we know _base != NULL; since file is buffered */
+ if (str->_ptr == str->_base)
+ {
+ if (str->_cnt)
+ /* my back is against the wall; i've already done
+ * ungetwc, and there's no room for this one
+ */
+ return WEOF;
+ str->_ptr += size;
+ }
+
+ if ( size == 1 )
+ {
+ *--str->_ptr = mbc[0];
+ }
+ else /* size == 2 */
+ {
+ *--str->_ptr = mbc[1];
+ *--str->_ptr = mbc[0];
+ }
+
+ str->_cnt += size;
+
+ str->_flag &= ~_IOEOF;
+ str->_flag |= _IOREAD; /* may already be set */
+ return (wint_t) (0x0ffff & ch);
+ }
+#endif
+ /*
+ * Binary mode - push back the wide char.
+ */
+ /* we know _base != NULL; since file is buffered */
+ if (str->_ptr == str->_base)
+ {
+ if (str->_cnt)
+ /* my back is against the wall; i've already done
+ * ungetc, and there's no room for this one
+ */
+ return WEOF;
+ str->_ptr += sizeof(wchar_t);
+ }
+
+ str->_cnt += sizeof(wchar_t);
+
+ str->_flag &= ~_IOEOF;
+ str->_flag |= _IOREAD; /* may already be set */
+
+ return (wint_t) (*--((wchar_t *)(str->_ptr)) = (wchar_t)(ch & 0xffff));
+
+ }
+ return WEOF;
+}
diff --git a/private/crt32/stdio/vfprintf.c b/private/crt32/stdio/vfprintf.c
new file mode 100644
index 000000000..3fe2ba262
--- /dev/null
+++ b/private/crt32/stdio/vfprintf.c
@@ -0,0 +1,90 @@
+/***
+*vfprintf.c - fprintf from variable arg list
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines vfprintf() - print formatted output, but take args from
+* a stdargs pointer.
+*
+*Revision History:
+* 09-02-83 RN original fprintf
+* 06-17-85 TC rewrote to use new varargs macros, and to be vfprintf
+* 04-13-87 JCR added const to declaration
+* 11-06-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-25-88 GJF Don't use FP_OFF() macro for the 386
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-16-90 GJF Fixed copyright
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-25-90 SBM Replaced <assertm.h> by <assert.h>, <varargs.h> by
+* <stdarg.h>
+* 10-03-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int vfprintf(stream, format, ap) - print to file from varargs
+*
+*Purpose:
+* Performs formatted output to a file. The arg list is a variable
+* argument list pointer.
+*
+*Entry:
+* FILE *stream - stream to write data to
+* char *format - format string containing data format
+* va_list ap - variable arg list pointer
+*
+*Exit:
+* returns number of correctly output characters
+* returns negative number if error occurred
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 vfprintf (
+ FILE *str,
+ const char *format,
+ va_list ap
+ )
+/*
+ * 'V'ariable argument 'F'ile (stream) 'PRINT', 'F'ormatted
+ */
+{
+ REG1 FILE *stream;
+ REG2 int buffing;
+ REG3 int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(str != NULL);
+ assert(format != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef MTHREAD
+ index=_iob_index(stream);
+#endif
+ _lock_str(index);
+ buffing = _stbuf(stream);
+ retval = _output(stream,format,ap );
+ _ftbuf(buffing, stream);
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/vfwprint.c b/private/crt32/stdio/vfwprint.c
new file mode 100644
index 000000000..0979617b6
--- /dev/null
+++ b/private/crt32/stdio/vfwprint.c
@@ -0,0 +1,76 @@
+/***
+*vfwprintf.c - fwprintf from variable arg list
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines vfwprintf() - print formatted output, but take args from
+* a stdargs pointer.
+*
+*Revision History:
+* 05-16-92 KRS Created from vfprintf.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int vfwprintf(stream, format, ap) - print to file from varargs
+*
+*Purpose:
+* Performs formatted output to a file. The arg list is a variable
+* argument list pointer.
+*
+*Entry:
+* FILE *stream - stream to write data to
+* wchar_t *format - format string containing data format
+* va_list ap - variable arg list pointer
+*
+*Exit:
+* returns number of correctly output wide characters
+* returns negative number if error occurred
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 vfwprintf (
+ FILE *str,
+ const wchar_t *format,
+ va_list ap
+ )
+/*
+ * 'V'ariable argument 'F'ile (stream) 'W'char_t 'PRINT', 'F'ormatted
+ */
+{
+ REG1 FILE *stream;
+ REG2 int buffing;
+ REG3 int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(str != NULL);
+ assert(format != NULL);
+
+ /* Init stream pointer */
+ stream = str;
+
+#ifdef MTHREAD
+ index=_iob_index(stream);
+#endif
+ _lock_str(index);
+ buffing = _stbuf(stream);
+ retval = _woutput(stream,format,ap );
+ _ftbuf(buffing, stream);
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/vprintf.c b/private/crt32/stdio/vprintf.c
new file mode 100644
index 000000000..e5cd2095d
--- /dev/null
+++ b/private/crt32/stdio/vprintf.c
@@ -0,0 +1,81 @@
+/***
+*vprintf.c - printf from a var args pointer
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines vprintf() - print formatted data from an argument list pointer
+*
+*Revision History:
+* 09-02-83 RN original printf
+* 06-17-85 TC rewrote to use new varargs macros to be vprintf
+* 04-13-87 JCR added const to declaration
+* 11-06-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-31-88 PHG Merged DLL and normal versions
+* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-16-90 GJF Fixed copyright
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-25-90 SBM Replaced <assertm.h> by <assert.h>, <varargs.h> by
+* <stdarg.h>
+* 10-03-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <file2.h>
+#include <os2dll.h>
+
+/***
+*int vprintf(format, ap) - print formatted data from an argument list pointer
+*
+*Purpose:
+* Prints formatted data items to stdout. Uses a pointer to a
+* variable length list of arguments instead of an argument list.
+*
+*Entry:
+* char *format - format string, describes data format to write
+* va_list ap - pointer to variable length arg list
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 vprintf (
+ const char *format,
+ va_list ap
+ )
+/*
+ * stdout 'V'ariable, 'PRINT', 'F'ormatted
+ */
+{
+ REG1 FILE *stream = stdout;
+ REG2 int buffing;
+ REG3 int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(format != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ buffing = _stbuf(stream);
+ retval = _output(stream, format, ap );
+ _ftbuf(buffing, stream);
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/vsnprint.c b/private/crt32/stdio/vsnprint.c
new file mode 100644
index 000000000..021c394a6
--- /dev/null
+++ b/private/crt32/stdio/vsnprint.c
@@ -0,0 +1,17 @@
+/***
+*vsnprintf.c - "Count" version of vsprintf
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The _vsnprintf() flavor takes a count argument that is
+* the max number of bytes that should be written to the
+* user's buffer.
+*
+*Revision History:
+* 09-25-91 JCR Stub module created.
+*
+*******************************************************************************/
+
+#define _COUNT_ 1
+#include "vsprintf.c"
diff --git a/private/crt32/stdio/vsnwprnt.c b/private/crt32/stdio/vsnwprnt.c
new file mode 100644
index 000000000..fac8af112
--- /dev/null
+++ b/private/crt32/stdio/vsnwprnt.c
@@ -0,0 +1,17 @@
+/***
+*vsnwprnt.c - "Count" version of vswprintf
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The _vsnwprintf() flavor takes a count argument that is
+* the max number of wide characters that should be written to the
+* user's buffer.
+*
+*Revision History:
+* 05-16-91 KRS Created from vsnprint.c
+*
+*******************************************************************************/
+
+#define _COUNT_ 1
+#include "vswprint.c"
diff --git a/private/crt32/stdio/vsprintf.c b/private/crt32/stdio/vsprintf.c
new file mode 100644
index 000000000..e19ee5064
--- /dev/null
+++ b/private/crt32/stdio/vsprintf.c
@@ -0,0 +1,126 @@
+/***
+*vsprintf.c - print formatted data into a string from var arg list
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines vsprintf() and _vsnprintf() - print formatted output to
+* a string, get the data from an argument ptr instead of explicit
+* arguments.
+*
+*Revision History:
+* 09-02-83 RN original sprintf
+* 06-17-85 TC rewrote to use new varargs macros, and to be vsprintf
+* 04-13-87 JCR added const to declaration
+* 11-07-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-13-88 JCR Fake _iob entry is now static so that other routines
+* can assume _iob entries are in DGROUP.
+* 08-25-88 GJF Define MAXSTR to be INT_MAX (from LIMITS.H).
+* 06-06-89 JCR 386 mthread support
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-16-90 GJF Fixed copyright
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 07-25-90 SBM Replaced <assertm.h> by <assert.h>, <varargs.h> by
+* <stdarg.h>
+* 10-03-90 GJF New-style function declarator.
+* 09-24-91 JCR Added _vsnprintf()
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <limits.h>
+#include <os2dll.h>
+
+#define MAXSTR INT_MAX
+
+
+/***
+#ifndef _COUNT_
+*int vsprintf(string, format, ap) - print formatted data to string from arg ptr
+#else
+*int _vsnprintf(string, format, ap) - print formatted data to string from arg ptr
+#endif
+*
+*Purpose:
+* Prints formatted data, but to a string and gets data from an argument
+* pointer.
+* Sets up a FILE so file i/o operations can be used, make string look
+* like a huge buffer to it, but _flsbuf will refuse to flush it if it
+* fills up. Appends '\0' to make it a true string.
+*
+* Allocate the 'fake' _iob[] entryit statically instead of on
+* the stack so that other routines can assume that _iob[] entries are in
+* are in DGROUP and, thus, are near.
+*
+#ifdef _COUNT_
+* The _vsnprintf() flavor takes a count argument that is
+* the max number of bytes that should be written to the
+* user's buffer.
+#endif
+*
+* Multi-thread: (1) Since there is no stream, this routine must never try
+* to get the stream lock (i.e., there is no stream lock either). (2)
+* Also, since there is only one staticly allocated 'fake' iob, we must
+* lock/unlock to prevent collisions.
+*
+*Entry:
+* char *string - place to put destination string
+#ifdef _COUNT_
+* size_t count - max number of bytes to put in buffer
+#endif
+* char *format - format string, describes format of data
+* va_list ap - varargs argument pointer
+*
+*Exit:
+* returns number of characters in string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifndef _COUNT_
+
+int _CALLTYPE1 vsprintf (
+ char *string,
+ const char *format,
+ va_list ap
+ )
+#else
+
+int _CALLTYPE1 _vsnprintf (
+ char *string,
+ size_t count,
+ const char *format,
+ va_list ap
+ )
+#endif
+
+{
+ FILE str;
+ REG1 FILE *outfile = &str;
+ REG2 int retval;
+
+ assert(string != NULL);
+ assert(format != NULL);
+
+ outfile->_flag = _IOWRT|_IOSTRG;
+ outfile->_ptr = outfile->_base = string;
+#ifndef _COUNT_
+ outfile->_cnt = MAXSTR;
+#else
+ outfile->_cnt = count;
+#endif
+
+ retval = _output(outfile,format,ap );
+ _putc_lk('\0',outfile);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/vswprint.c b/private/crt32/stdio/vswprint.c
new file mode 100644
index 000000000..230880851
--- /dev/null
+++ b/private/crt32/stdio/vswprint.c
@@ -0,0 +1,111 @@
+/***
+*vswprint.c - print formatted data into a string from var arg list
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines vswprintf() and _vsnwprintf() - print formatted output to
+* a string, get the data from an argument ptr instead of explicit
+* arguments.
+*
+*Revision History:
+* 05-16-92 KRS Created from vsprintf.c.
+* 02-18-93 SRW Make FILE a local and remove lock usage.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <limits.h>
+#include <os2dll.h>
+
+#define MAXSTR INT_MAX
+
+
+/***
+#ifndef _COUNT_
+*int vswprintf(string, format, ap) - print formatted data to string from arg ptr
+#else
+*int _vsnwprintf(string, format, ap) - print formatted data to string from arg ptr
+#endif
+*
+*Purpose:
+* Prints formatted data, but to a string and gets data from an argument
+* pointer.
+* Sets up a FILE so file i/o operations can be used, make string look
+* like a huge buffer to it, but _flsbuf will refuse to flush it if it
+* fills up. Appends '\0' to make it a true string.
+*
+* Allocate the 'fake' _iob[] entryit statically instead of on
+* the stack so that other routines can assume that _iob[] entries are in
+* are in DGROUP and, thus, are near.
+*
+#ifdef _COUNT_
+* The _vsnwprintf() flavor takes a count argument that is
+* the max number of bytes that should be written to the
+* user's buffer.
+#endif
+*
+* Multi-thread: (1) Since there is no stream, this routine must never try
+* to get the stream lock (i.e., there is no stream lock either). (2)
+* Also, since there is only one staticly allocated 'fake' iob, we must
+* lock/unlock to prevent collisions.
+*
+*Entry:
+* wchar_t *string - place to put destination string
+#ifdef _COUNT_
+* size_t count - max number of bytes to put in buffer
+#endif
+* wchar_t *format - format string, describes format of data
+* va_list ap - varargs argument pointer
+*
+*Exit:
+* returns number of wide characters in string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifndef _COUNT_
+
+int _CALLTYPE1 vswprintf (
+ wchar_t *string,
+ const wchar_t *format,
+ va_list ap
+ )
+#else
+
+int _CALLTYPE1 _vsnwprintf (
+ wchar_t *string,
+ size_t count,
+ const wchar_t *format,
+ va_list ap
+ )
+#endif
+
+{
+ FILE str;
+ REG1 FILE *outfile = &str;
+ REG2 int retval;
+
+ assert(string != NULL);
+ assert(format != NULL);
+
+ outfile->_flag = _IOWRT|_IOSTRG;
+ outfile->_ptr = outfile->_base = (char *) string;
+#ifndef _COUNT_
+ outfile->_cnt = MAXSTR;
+#else
+ outfile->_cnt = count*sizeof(wchar_t);
+#endif
+
+ retval = _woutput(outfile,format,ap );
+ _putc_lk('\0',outfile); /* no-lock version */
+ _putc_lk('\0',outfile); /* 2nd byte for wide char version */
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/vwprintf.c b/private/crt32/stdio/vwprintf.c
new file mode 100644
index 000000000..f8ef83e8b
--- /dev/null
+++ b/private/crt32/stdio/vwprintf.c
@@ -0,0 +1,68 @@
+/***
+*vwprintf.c - wprintf from a var args pointer
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines vwprintf() - print formatted data from an argument list pointer
+*
+*Revision History:
+* 05-16-92 KRS Created from vprintf.c
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <internal.h>
+#include <file2.h>
+#include <os2dll.h>
+
+/***
+*int vwprintf(format, ap) - print formatted data from an argument list pointer
+*
+*Purpose:
+* Prints formatted data items to stdout. Uses a pointer to a
+* variable length list of arguments instead of an argument list.
+*
+*Entry:
+* wchar_t *format - format string, describes data format to write
+* va_list ap - pointer to variable length arg list
+*
+*Exit:
+* returns number of wide characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 vwprintf (
+ const wchar_t *format,
+ va_list ap
+ )
+/*
+ * stdout 'V'ariable, 'W'char_t 'PRINT', 'F'ormatted
+ */
+{
+ REG1 FILE *stream = stdout;
+ REG2 int buffing;
+ REG3 int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ assert(format != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+ _lock_str(index);
+ buffing = _stbuf(stream);
+ retval = _woutput(stream, format, ap );
+ _ftbuf(buffing, stream);
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/winput.c b/private/crt32/stdio/winput.c
new file mode 100644
index 000000000..a8a178b24
--- /dev/null
+++ b/private/crt32/stdio/winput.c
@@ -0,0 +1,29 @@
+/***
+*winput.c - wscanf style input from a FILE (wchar_t version)
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the code that does all the work for the
+* wscanf family of functions. It should not be called directly, only
+* by the *wscanf functions. We don't make any assumtions about the
+* sizes of ints, longs, shorts, or long doubles, but if types do overlap,
+* we also try to be efficient.
+* **** DOESN'T CURRENTLY DO MTHREAD LOCKING ****
+*
+*Revision History:
+* 04-27-93 CFW Module created.
+*
+*******************************************************************************/
+
+#define WPRFLAG 1
+
+#ifndef _UNICODE /* CRT flag */
+#define _UNICODE 1
+#endif
+
+#ifndef UNICODE /* NT flag */
+#define UNICODE 1
+#endif
+
+#include "input.c"
diff --git a/private/crt32/stdio/woutput.c b/private/crt32/stdio/woutput.c
new file mode 100644
index 000000000..f11425391
--- /dev/null
+++ b/private/crt32/stdio/woutput.c
@@ -0,0 +1,31 @@
+/***
+*woutput.c - wprintf style output to a FILE (wchar_t version)
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the code that does all the work for the
+* wprintf family of functions. It should not be called directly, only
+* by the *wprintf functions. We don't make any assumtions about the
+* sizes of ints, longs, shorts, or long doubles, but if types do overlap,
+* we also try to be efficient. We do assume that pointers are the same
+* size as either ints or longs.
+* If CPRFLAG is defined, defines _cprintf instead.
+* **** DOESN'T CURRENTLY DO MTHREAD LOCKING ****
+*
+*Revision History:
+* 04-27-93 CFW Module created.
+*
+*******************************************************************************/
+
+#define WPRFLAG 1
+
+#ifndef _UNICODE /* CRT flag */
+#define _UNICODE 1
+#endif
+
+#ifndef UNICODE /* NT flag */
+#define UNICODE 1
+#endif
+
+#include "output.c"
diff --git a/private/crt32/stdio/wprintf.c b/private/crt32/stdio/wprintf.c
new file mode 100644
index 000000000..b11e8406f
--- /dev/null
+++ b/private/crt32/stdio/wprintf.c
@@ -0,0 +1,79 @@
+/***
+*wprintf.c - print formatted
+*
+* Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wprintf() - print formatted data
+*
+*Revision History:
+* 05-16-92 KRS Created from printf.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int wprintf(format, ...) - print formatted data
+*
+*Purpose:
+* Prints formatted data on stdout using the format string to
+* format data and getting as many arguments as called for
+* Uses temporary buffering to improve efficiency.
+* _output does the real work here
+*
+*Entry:
+* wchar_t *format - format string to control data format/number of arguments
+* followed by list of arguments, number and type controlled by
+* format string
+*
+*Exit:
+* returns number of wide characters printed
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 wprintf (
+ const wchar_t *format,
+ ...
+ )
+/*
+ * stdout 'W'char_t 'PRINT', 'F'ormatted
+ */
+{
+ va_list arglist;
+ REG1 FILE *stream = stdout;
+ REG2 int buffing;
+ REG3 int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+// UNDONE: make va_start work with wchar_t format string
+ va_start(arglist, format);
+
+ assert(format != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+
+ _lock_str(index);
+
+ buffing = _stbuf(stream);
+
+ retval = _woutput(stream,format,arglist);
+
+ _ftbuf(buffing, stream);
+
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/stdio/wscanf.c b/private/crt32/stdio/wscanf.c
new file mode 100644
index 000000000..84b26b94e
--- /dev/null
+++ b/private/crt32/stdio/wscanf.c
@@ -0,0 +1,74 @@
+/***
+*wscanf.c - read formatted data from stdin
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wscanf() - reads formatted data from stdin
+*
+*Revision History:
+* 05-16-92 KRS Created from scanf.c.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <file2.h>
+#include <internal.h>
+#include <os2dll.h>
+
+/***
+*int wscanf(format, ...) - read formatted data from stdin
+*
+*Purpose:
+* Reads formatted data from stdin into arguments. _input does the real
+* work here.
+*
+*Entry:
+* char *format - format string
+* followed by list of pointers to storage for the data read. The number
+* and type are controlled by the format string.
+*
+*Exit:
+* returns number of fields read and assigned
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE2 wscanf (
+ const wchar_t *format,
+ ...
+ )
+/*
+ * stdin 'W'char_t 'SCAN', 'F'ormatted
+ */
+{
+ REG1 FILE *stream = stdin;
+ REG2 int retval;
+#ifdef MTHREAD
+ int index;
+#endif
+
+ va_list arglist;
+
+// UNDONE: make va_start work with wchar_t format string
+ va_start(arglist, format);
+
+ assert(format != NULL);
+
+#ifdef MTHREAD
+ index = _iob_index(stream);
+#endif
+
+ _lock_str(index);
+
+ retval = (_winput(stream,format,arglist));
+
+ _unlock_str(index);
+
+ return(retval);
+}
diff --git a/private/crt32/string/alpha/strcat.c b/private/crt32/string/alpha/strcat.c
new file mode 100644
index 000000000..307b83837
--- /dev/null
+++ b/private/crt32/string/alpha/strcat.c
@@ -0,0 +1,63 @@
+/***
+*strcat.c - contains strcat()
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+* Strcat() concatenates (appends) a copy of the source string to the
+* end of the destination string, returning the destination string.
+*
+*Revision History:
+* 04-29-94 DEC Removed strcpy
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 04-05-91 GJF Speed up strcat() a bit (got rid of call to strcpy()).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(strcat)
+#endif /* ndef _CRUISER_ */
+
+/***
+*char *strcat(dst, src) - concatenate (append) one string to another
+*
+*Purpose:
+* Concatenates src onto the end of dest. Assumes enough
+* space in dest.
+*
+*Entry:
+* char *dst - string to which "src" is to be appended
+* const char *src - string to be appended to the end of "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strcat (
+ char * dst,
+ const char * src
+ )
+{
+ char * cp = dst;
+
+ while( *cp )
+ cp++; /* find end of dst */
+
+ while( *cp++ = *src++ ) ; /* Copy src to end of dst */
+
+ return( dst ); /* return dst */
+
+}
+
diff --git a/private/crt32/string/alpha/strcmps.s b/private/crt32/string/alpha/strcmps.s
new file mode 100644
index 000000000..0c7859727
--- /dev/null
+++ b/private/crt32/string/alpha/strcmps.s
@@ -0,0 +1,357 @@
+ #****************************************************************************
+ #* *
+ #* Copyright (c) 1991 by *
+ #* DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
+ #* All rights reserved. *
+ #* *
+ #* This software is furnished under a license and may be used and copied *
+ #* only in accordance with the terms of such license and with the *
+ #* inclusion of the above copyright notice. This software or any other *
+ #* copies thereof may not be provided or otherwise made available to any *
+ #* other person. No title to and ownership of the software is hereby *
+ #* transferred. *
+ #* *
+ #* The information in this software is subject to change without notice *
+ #* and should not be construed as a commitment by Digital Equipment *
+ #* Corporation. *
+ #* *
+ #* Digital assumes no responsibility for the use or reliability of its *
+ #* software on equipment which is not supplied by Digital. *
+ #* *
+ #* *
+ #****************************************************************************
+ #
+ #++
+ # Facility:
+ # DEC C Run Time Library on the Alpha/WNT Platform
+ #
+ # Abstract:
+ #
+ # Implements the C RTL function strcmp().
+ #
+ # Author:
+ # Bill Noyce 9-Aug-1991
+ #
+ # Modified by:
+ #
+ # 001 Kevin Routley 10-Sep-1991
+ # Modified to C RTL Coding standards.
+ #
+ # 002 Chris Bord 30 September 1991
+ # Add decc$ prefixes.
+ #
+ # 003 Chris Bord 24 January 1992
+ # Add second parameter to .procedure_descriptor directive
+ #
+ # 004 John Parks 22 January 1993
+ # Ported to Alpha/NT.
+ #--
+
+//
+// Although the spec says the return value may be <0/0/>0, we now return
+// -1/0/+1 to reduce NT combatibility problems.
+//
+
+ .globl strcmp
+ .ent strcmp
+
+ # r16 = A
+ # r17 = B
+ # returns r0<0 if A<B, R0=0 if A=B, r0>0 if A>B (unsigned chars)
+ # destroys r16-r21, r27-r28
+ #
+
+strcmp:
+ .set noat
+ .set noreorder
+
+ .frame $30, 0, $26
+
+ ldq_u $27, ($16) # Get first A QW
+ and $16, 7, $21 # Alignment of A
+
+ ldq_u $18, ($17) # Get first B QW
+ and $17, 7, $20 # Alignment of B
+
+ subq $20, $21, $0 # B_alignment geq A_alignment?
+
+ cmpbge $31, $27, $19 # Any nulls in A?
+
+ insql $27, $0, $28 # Position A like B if B_align geq
+ bgt $0, more_a # Skip if enough A bytes available
+
+ srl $19, $21, $19 # Discard nulls preceding start of A
+ bne $0, more_b # Go handle opposite mismatch
+
+match: xor $27, $18, $28 # Do A and B differ?
+
+ mskqh $28, $21, $28 # Ignore differences before start
+
+ sll $19, $21, $0 # Line up nulls with differences
+ bne $19, null # Skip out if nulls seen
+
+loop_s: bne $28, diff # Skip out if difference seen
+ ldq_u $27, 8($16) # Get next A QW
+
+ ldq_u $18, 8($17) # Get next B QW
+ addq $16, 8, $16 # Bump A pointer
+
+ addq $17, 8, $17 # Bump B pointer
+
+ cmpbge $31, $27, $0 # Any nulls in A?
+
+ xor $27, $18, $28 # Do A and B differ?
+ beq $0, loop_s # Repeat if no nulls
+
+ # Enter here if null seen.
+ # r0 = mask of nulls
+ # r27= A
+ # r18 = B
+ # r28= xor
+ #
+null: subq $0, 1, $19 # Flip bits up thru first null
+
+ cmpbge $31, $28, $28 # Mask of 1's where A=B
+
+ xor $0, $19, $0 # Mask of 1's thru first null
+
+ andnot $0, $28, $0 # Differences thru first null
+
+ cmpbge $27, $18, $27 # Mask of 1's where A >= B
+ beq $0, done # Exit with R0=0 if no differences
+
+ subq $31, $0, $19 # R19<0, first diff=1, others=0
+
+ and $27, $0, $28 # Mask of A>B thru first null
+
+ and $28, $19, $0 # Keep only first difference
+
+ cmoveq $0, $19, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+done: ret $31, ($26) # All done
+
+ # Enter here if difference seen, but no nulls.
+ # r27= A
+ # r18 = B
+ # R28= xor
+ #
+diff: cmpbge $31, $28, $21 # Where is A = B?
+
+ cmpbge $27, $18, $0 # Where is A >= B?
+
+ subq $21, 255, $19 # R19<0, first diff=1, others=0
+
+ andnot $0, $21, $28 # Mask of A > B
+
+ and $28, $19, $0 # Keep only first difference
+
+ cmoveq $0, $19, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+ ret $31, ($26)
+
+ #.align quad
+
+ # Enter here if A and B alignments differ, and B's is greater (so there are
+ # more A bytes in its first QW than B bytes in its first QW).
+
+more_a: srl $19, $21, $19 # Discard nulls preceding start of A
+
+ xor $28, $18, $21 # Do A and B differ?
+
+ mskqh $21, $20, $21 # Discard diffs preceding start of B
+ bne $19, null_a # Skip if A has nulls
+
+ mov $18, $19 # Put B where common code expects
+
+ bne $21, diff_d # Handle diffs in B
+
+ ldq_u $18, 8($17) # No nulls in A or B, get next QW of B
+ addq $17, 8, $17 # Bump B pointer
+
+ insqh $27, $0, $28 # Position high part of A like B
+
+ #stall
+
+ mskql $18, $0, $19 # Keep low part of B
+
+ # Loop comparing A and B when alignment differs.
+ # Register use:
+ # r16 --> A
+ # r17 --> B
+ # r27 = QW of A
+ # r28 = current piece of A
+ # r18 = QW of B
+ # r19 = current piece of B
+ # r0 = alignment difference (B-A)
+ # r21 = xor of pieces
+ # r20 = mask of null locations
+ #
+ # If a string contains a null, we are careful not to read the following
+ # quadword in that string. But we are willing to read the quadword that
+ # follows the first difference, because this read-ahead improves performance.
+ #
+loop_d: xor $28, $19, $21 # Do A and B pieces differ?
+ ldq_u $27, 8($16) # Get next QW of A
+
+ cmpbge $31, $18, $20 # Any nulls in B?
+ bne $21, diff_d # Skip if difference seen
+
+ent_d: mskqh $18, $0, $19 # Trim B for next compare
+
+ insql $27, $0, $28 # Position A like B
+
+ addq $16, 8, $16 # Bump A pointer
+ bne $20, null_d # Skip if null seen in B
+
+ xor $28, $19, $21 # Do A and B pieces differ?
+ ldq_u $18, 8($17) # Get next QW of B
+
+ cmpbge $31, $27, $20 # Any nulls in A?
+ bne $21, diff_d # Skip if difference seen
+
+ insqh $27, $0, $28 # Position A for next compare
+
+ mskql $18, $0, $19 # Trim B like A
+
+ addq $17, 8, $17 # Bump B pointer
+ beq $20, loop_d # Repeat if no nulls in A
+
+ # We saw a null in A. Since we've already compared the lower part with B,
+ # and B had no nulls, the null is in the upper part of A. We've moved that
+ # part of A to the lower part of r28. Re-compare so the mask of nulls will
+ # be positioned properly for the following code.
+ #
+ cmpbge $31, $28, $20 # Find nulls in repositioned A
+
+ # Null seen and alignments differ.
+ # r28 = positioned A
+ # r19 = positioned B
+ # r20 = mask of nulls
+ # r21 = xor (at entry null_e)
+ #
+ #.odd
+null_d: xor $28, $19, $21 # Where do A and B differ?
+
+null_e: subq $20, 1, $27 # Flip bits up thru first null
+
+ cmpbge $31, $21, $18 # Mask of 1's where A=B
+
+ xor $20, $27, $0 # Mask of 1's thru first null
+
+ andnot $0, $18, $0 # Differences thru first null
+
+ cmpbge $28, $19, $27 # Mask of 1's where A >= B
+ beq $0, done_d # Exit with R0=0 if no differences
+
+ subq $31, $0, $19 # R19<0, first diff=1, others=0
+
+ and $27, $0, $0 # Mask of A>B thru first null
+
+ and $0, $19, $0 # Keep only first difference
+
+ cmoveq $0, $19, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+done_d: ret $31, ($26) # All done
+
+
+ # Null seen in first QW of A, when B alignment greater.
+ # r19 = nulls in A, shifted
+ # r27 = A
+ # r28 = A positioned like B
+ # r18 = B
+ # r21 = xor, masked
+ #
+ #.odd
+null_a: sll $19, $20, $20 # Position nulls like B
+
+ mov $18, $19 # Move B for common code
+ bne $21, null_e # Comparison done if difference seen
+
+ and $20, 255, $18 # Any nulls in first part of A?
+
+ bne $18, null_e # Comparison done if so
+
+ ldq_u $19, 8($17) # Get another B QW
+ insqh $27, $0, $28 # Position A to match
+
+ srl $20, 8, $20 # Shift nulls again to match
+ br $31, null_d # Now we must be at end
+
+
+ # Enter here if A and B alignments differ, and B's is less (so there are more
+ # B bytes in its first QW than A bytes in its first QW).
+
+ #.align quad
+more_b: cmpbge $31, $18, $28 # We'll want to know about nulls in B
+ bne $19, null_b # Skip if null seen in A
+
+ extqh $18, $0, $19 # Position B like A
+
+ srl $28, $20, $28 # Discard nulls preceding start of B
+
+ xor $27, $19, $27 # Do A and B differ?
+
+ mskqh $27, $21, $21 # Discard diffs preceding start of A
+
+ sll $28, $20, $20 # Position null mask for common code
+ ldq_u $27, 8($16) # Get next QW of A
+
+ xor $19, $21, $28 # Recover A for compare
+ beq $21, ent_d # Enter loop if A=B so far
+
+
+ # Enter here if difference seen, but no nulls.
+ # r28 = A piece
+ # r19 = B piece
+ # r21 = xor
+ #
+diff_d: cmpbge $31, $21, $21 # Where is A = B?
+
+ cmpbge $28, $19, $0 # Where is A >= B?
+
+ subq $21, 255, $27 # R27<0, first diff=1, others=0
+
+ andnot $0, $21, $0 # Mask of A > B
+
+ and $0, $27, $0 # Keep only first difference
+
+ cmoveq $0, $27, $0 # If A<B, set R0 negative
+
+ cmplt $31, $0, $20 // set 1 if result > 0, otherwise 0
+ cmplt $0, $31, $21 // set 1 if result < 0, otherwise 0
+ subq $20, $21, $0 // set return value to -1/0/+1
+
+ ret $31, ($26)
+
+ # Null seen in first QW of A, when B alignment less.
+ # r19 = nulls in A, shifted
+ # r27 = A
+ # r18 = original B
+ #
+ nop #.align 8
+null_b: sll $19, $21, $20 # Position null mask like A
+
+ extqh $18, $0, $19 # Position B like A
+
+ mov $27, $28 # Put A where common code expects
+
+ xor $27, $19, $27 # Find differences
+
+ mskqh $27, $21, $21 # Discard diffs preceding A
+ br $31, null_e # Comparison is done
+
+ .set at
+ .set reorder
+ .end strcmp
diff --git a/private/crt32/string/alpha/strcpys.s b/private/crt32/string/alpha/strcpys.s
new file mode 100644
index 000000000..c326688eb
--- /dev/null
+++ b/private/crt32/string/alpha/strcpys.s
@@ -0,0 +1,257 @@
+ #****************************************************************************
+ #* *
+ #* Copyright (c) 1991 by *
+ #* DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
+ #* All rights reserved. *
+ #* *
+ #* This software is furnished under a license and may be used and copied *
+ #* only in accordance with the terms of such license and with the *
+ #* inclusion of the above copyright notice. This software or any other *
+ #* copies thereof may not be provided or otherwise made available to any *
+ #* other person. No title to and ownership of the software is hereby *
+ #* transferred. *
+ #* *
+ #* The information in this software is subject to change without notice *
+ #* and should not be construed as a commitment by Digital Equipment *
+ #* Corporation. *
+ #* *
+ #* Digital assumes no responsibility for the use or reliability of its *
+ #* software on equipment which is not supplied by Digital. *
+ #* *
+ #* *
+ #****************************************************************************
+ #
+ #++
+ # Facility:
+ # DEC C Run Time Library on the Alpha/WNT Platform
+ #
+ # Abstract:
+ #
+ # Implements the C RTL function strcpy().
+ #
+ # Author:
+ # Bill Noyce 9-Aug-1991
+ #
+ # Modified by:
+ #
+ # 001 Kevin Routley 10-Sep-1991
+ # Modified to C RTL Coding standards.
+ #
+ # 002 Chris Bord 30 September 1991
+ # Add decc$ prefixes.
+ #
+ # 003 Chris Bord 24 January 1992
+ # Add second parameter to .procedure_descriptor directive
+ #
+ # 004 John Parks 22 January 1993
+ # Ported to Alpha/NT.
+ #--
+
+ .globl strcpy
+ .ent strcpy
+
+ # r16 = dst
+ # r17 = src
+ # returns r0 = src
+ # destroys r16-r21, r27-r28
+
+strcpy:
+ .set noat
+ .set noreorder
+
+ ldq_u $27, ($17) # Get first src QW
+ and $16, 7, $28 #/ Is dst aligned?
+ lda $18, -1($31) # Get a mask of all 1's
+ bne $28, dst_unaligned #/ Go handle unaligned dst
+ and $17, 7, $19 # Is src aligned too?
+ nop
+ mov $16, $0 # Set up function result
+ bne $19, src_unaligned #/ Go handle aligned dst, unaligned src
+
+a_loop:
+ cmpbge $31, $27, $18 # Any nulls in src QW?
+ bne $18, a_exit_1 # Finish up if so
+ ldq $21, 8($17) # Load next QW if not
+match: # Enter if src matches unaligned dst
+ addq $17, 16, $17 #/ Update src pointer for unrolled loop
+ stq_u $27, ($16) # Store a whole QW
+ addq $16, 16, $16 #/ Update dst pointer for unrolled loop
+ cmpbge $31, $21, $18 # Any nulls in src QW?
+ bne $18, a_exit_2 # Finish up if so
+ ldq $27, ($17) # Load next QW if not
+ stq_u $21, -8($16) # Store a whole QW
+ br $31, a_loop # Repeat during load latency
+
+a_exit_1:
+ ldq_u $21, ($16) # Get dst QW to update
+ subq $18, 1, $17 #/ Use location of null byte...
+ xor $18, $17, $18 # ... to compute mask of what to keep
+ zapnot $27, $18, $27 # Keep src up to & including null
+ zap $21, $18, $21 # Make room for new data
+ nop
+ or $21, $27, $21 # Combine src & dst...
+ stq_u $21, ($16) #/ ... and store
+ ret $31, ($26)
+
+ nop
+a_exit_2:
+ ldq_u $27, -8($16) # Get dst QW to update
+ subq $18, 1, $17 #/ Use location of null byte...
+ xor $18, $17, $18 # ... to compute mask of what to keep
+ zapnot $21, $18, $21 # Keep src up to & including null
+ zap $27, $18, $27 # Make room for new data
+ nop
+ or $27, $21, $27 # Combine src & dst...
+ stq_u $27, -8($16) #/ ... and store
+ ret $31, ($26)
+
+src_unaligned: # dst_unaligned code would work; is this faster?
+ mskqh $18, $17, $18 # Zeros where src to be ignored
+ ornot $27, $18, $19 # Make ignored bytes nonzero
+ cmpbge $31, $19, $21 # Any null bytes in src data?
+ extql $27, $17, $27 # Move src to position of dst
+ bne $21, short_ld #/ Finish up if nulls seen
+ ldq_u $19, 8($17) # Next src QW needed to fill dst
+ br $31, u_entry_2 # Enter loop for mismatched alignment
+
+ # Here's the hard part. Enter with
+ # r16 = dst address
+ # r17 = src address
+ # r18 = -1
+ # r27 = first src QW
+ # r28 = dst alignment (>0)
+ # Check whether the first src QW has any nulls, and load the next one.
+ # Combine these if needed to fill the first dst QW, and enter a loop
+ # that fetches src QWs and checks them, while storing dst QWs.
+
+dst_unaligned:
+ ldq_u $20, ($16) # Load dst to be updated
+ mskqh $18, $17, $18 #/ Zeros where src to be ignored
+ mov $16, $0 # Set up function result
+ ornot $27, $18, $19 # Make ignored bytes of src nonzero
+ cmpbge $31, $19, $21 # Any null bytes in src data?
+ extql $27, $17, $27 # Get only interesting src data
+ bne $21, short # Finish up if nulls seen
+ mskql $20, $16, $20 #/ Make room in dst
+ ldq_u $21, 8($17) # Load next src QW if no nulls
+ mskql $18, $16, $18 #/ Need two src QWs for first dst QW?
+ insql $27, $16, $27 # Move src data to position of dst
+ subq $17, $28, $17 # Adjust src ptr for partial move
+ and $17, 7, $28 # Is src now aligned?
+ bne $18, u_loop #/ Enter loop if one src QW fills dst
+ or $27, $20, $27 # Combine first src QW with dst
+ extqh $21, $17, $20 # Position 2nd src QW in 1st dst QW
+ cmpbge $31, $21, $18 # Any nulls in next src QW?
+ beq $28, match #/ If src aligned, use quick loop
+ mov $21, $19 # Put src QW where loop expects
+ bne $18, short_a #/ Finish up if nulls seen
+
+ # r16 = address of next dst to store
+ # r17 = address-16 of next src to load
+ # r18
+ # r19 = last loaded src QW
+ # r20 = one piece of dst QW
+ # r21
+ # r27 = other piece of dst QW
+ # r28
+
+u_loop:
+ ldq_u $28, 16($17) # Load another src QW
+ addq $17, 16, $17 #/ Update src pointer for unrolled loop
+ or $27, $20, $27 # Combine pieces
+ extql $19, $17, $20 # Get second part of prior src QW
+ stq_u $27, ($16) # Store a dst QW
+ cmpbge $31, $28, $19 #/ Any nulls in this src QW?
+ extqh $28, $17, $27 # Get first part of this src QW
+ bne $19, u_exit_2 #/ Finish up if nulls seen
+ ldq_u $19, 8($17) # Load another src QW
+ addq $16, 16, $16 #/ Update dst pointer for unrolled loop
+ or $27, $20, $20 # Combine pieces
+ extql $28, $17, $27 # Get second piece of prior src QW
+ stq_u $20, -8($16) # Store a dst QW
+u_entry_2:
+ cmpbge $31, $19, $28 #/ Any nulls in this src QW?
+ extqh $19, $17, $20 # Get first part of this src QW
+ beq $28, u_loop #/ Repeat if no nulls seen
+
+ subq $16, 8, $16 # Undo part of pointer update
+ mov $19, $28 # Move src QW to expected place
+u_exit_2:
+ or $27, $20, $27 # Combine pieces
+ ldq_u $18, 8($16) #/ Load dst to update
+ cmpbge $31, $27, $21 # Is null in first dst QW?
+ bne $21, u_exit_3 # Skip if so
+ stq_u $27, 8($16) # Store a whole dst QW
+ extql $28, $17, $27 #/ Get second part of src QW
+ ldq_u $18, 16($16) # We'll update next dst QW
+ cmpbge $31, $27, $21 # Find location of null there
+ addq $16, 8, $16 # Update dst pointer
+u_exit_3:
+ subq $21, 1, $28 # Using position of null byte...
+ xor $21, $28, $21 # ... make mask for desired src data
+ zapnot $27, $21, $27 # Trim src data after null
+ zap $18, $21, $18 # Make room for it in dst
+ nop
+ or $27, $18, $27 # Combine pieces
+ stq_u $27, 8($16) #/ Store dst QW
+ ret $31, ($26)
+short_ld:
+ ldq_u $20, ($16) # Load dst QW to update
+short:
+ cmpbge $31, $27, $17 #/ Get mask showing location of null
+ insql $27, $16, $18 # Move src data to position of dst
+ mskql $20, $16, $19 # Get dst bytes preceding string
+ sll $17, $28, $17 # Move mask in the same way
+ or $18, $19, $18 # Combine src & dst
+ and $17, 255, $28 # Null byte in first dst QW?
+ subq $17, 1, $19 # Using position of null byte...
+ xor $17, $19, $17 # ... make mask for desired src data
+ bne $28, short_2 #/ Skip if null in first dst QW
+ ldq_u $20, 8($16) # Load second dst QW
+ srl $17, 8, $17 #/ Move mask down for use
+ stq_u $18, ($16) # Store first dst QW
+ insqh $27, $16, $18 #/ Move src data to position of dst
+ addq $16, 8, $16 # Advance dst pointer
+short_2:
+ zap $20, $17, $20 # Preserve dst data following null
+ zapnot $18, $17, $18 # Trim src data after null
+ nop
+ or $18, $20, $18 # Combine pieces
+ stq_u $18, ($16) #/ Store dst QW
+ ret $31, ($26)
+
+ # r16 = dst address
+ # r17 = updated src address
+ # r18 = null position
+ # r19 = next src QW
+ # r20 = first part of r19, positioned for dst
+ # r21
+ # r27 = dst QW so far
+ # r28 = low bits of updated src address
+
+short_a:
+ sll $18, 8, $18 # Shift location of null byte...
+ ldq_u $21, ($16) #/ Reload first dst QW
+ or $27, $20, $27 # Combine pieces
+ srl $18, $28, $18 # ... to position in dst QW's
+ nop
+ and $18, 255, $20 # Is null in first dst QW?
+ subq $18, 1, $28 # Using position of null byte...
+ xor $18, $28, $18 # ... make mask for desired src data
+ bne $20, short_a1 #/ Skip if null in first QW
+ stq_u $27, ($16) # Store a whole dst QW
+ extql $19, $17, $27 #/ Prepare next piece of src
+ ldq_u $21, 8($16) # Load second dst QW for update
+ srl $18, 8, $18 #/ Look at next 8 bits of mask
+ addq $16, 8, $16 # Update dst pointer
+short_a1:
+ zapnot $27, $18, $27 # Keep src data
+ zap $21, $18, $21 # Keep end of dst QW
+ nop
+ or $27, $21, $27 # Combine pieces
+ stq_u $27, ($16) # Store last dst QW
+ ret $31, ($26)
+
+ .set at
+ .set reorder
+ .end strcpy
diff --git a/private/crt32/string/alpha/strlens.s b/private/crt32/string/alpha/strlens.s
new file mode 100644
index 000000000..238699f7d
--- /dev/null
+++ b/private/crt32/string/alpha/strlens.s
@@ -0,0 +1,95 @@
+ #****************************************************************************
+ #* *
+ #* Copyright (c) 1991 by *
+ #* DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. *
+ #* All rights reserved. *
+ #* *
+ #* This software is furnished under a license and may be used and copied *
+ #* only in accordance with the terms of such license and with the *
+ #* inclusion of the above copyright notice. This software or any other *
+ #* copies thereof may not be provided or otherwise made available to any *
+ #* other person. No title to and ownership of the software is hereby *
+ #* transferred. *
+ #* *
+ #* The information in this software is subject to change without notice *
+ #* and should not be construed as a commitment by Digital Equipment *
+ #* Corporation. *
+ #* *
+ #* Digital assumes no responsibility for the use or reliability of its *
+ #* software on equipment which is not supplied by Digital. *
+ #* *
+ #* *
+ #****************************************************************************
+ #
+ #++
+ # Facility:
+ # DEC C Run Time Library on the Alpha/WNT Platform
+ #
+ # Abstract:
+ #
+ # Implements the C RTL function strlen().
+ #
+ # Author:
+ # Bill Noyce 9-Aug-1991
+ #
+ # Modified by:
+ #
+ # 001 Kevin Routley 10-Sep-1991
+ # Modified to C RTL Coding standards.
+ #
+ # 002 Chris Bord 30 September 1991
+ #
+ # 003 Chris Bord 24 January 1992
+ # Add second parameter to .procedure_descriptor directive
+ #
+ # 004 John Parks 22 January 1993
+ # Ported to Alpha/NT.
+ #--
+
+ .globl strlen
+ .ent strlen
+
+ # r16 = src pointer
+ # Returns r0 = length
+ # Destroys r16,r27-r28
+
+strlen:
+ .set noat
+ .set noreorder
+
+ ldq_u $27, ($16) # Get QW containing start of string
+ lda $28, -1($31) # Mask of all ones
+ mskql $28, $16, $28 # Nonzeros in low bytes to be ignored
+ and $16, 7, $0 # Alignment = bytes not to be counted
+ or $27, $28, $27 # Fill ignored bytes with nonzeros
+ cmpbge $31, $27, $27 # Any null bytes in this QW?
+ subq $31, $0, $0 # Initialize count to -alignment
+ bne $27, bottom # Skip if null byte seen
+
+loop: ldq_u $27, 8($16) # Load next QW of string
+ addq $16, 8, $16 # Advance pointer
+ addq $0, 8, $0 # Increment length
+ cmpbge $31, $27, $27 # Any nulls in this QW?
+ beq $27, loop # Repeat if not
+
+bottom: and $27, 0xF, $28 # Null in low longword?
+ subq $27, 1, $16 # Complement the lowest 1-bit in mask
+ blbs $27, done # Exit if null appears in first byte
+ andnot $27, $16, $27 # Make single-bit mask of null location
+ beq $28, geq_4 # Skip if null is in high longword
+ srl $27, 2, $27 # Map 2/4/8 --> 0/1/2
+ addq $0, 1, $0 # Bump length by one...
+ addq $0, $27, $0 # ... and then by null location
+
+done: ret $31, ($26)
+
+geq_4: srl $27, 5, $28 # Map 10/20/40/80 --> 0/1/2/4
+ srl $27, 7, $27 # Map 10/20/40/80 --> 0/0/0/1
+ addq $0, 4, $0 # Bump length by four
+ subq $28, $27, $28 # Compute location within high LW...
+ addq $0, $28, $0 # ... and add to length
+ ret $31, ($26)
+
+ .set at
+ .set reorder
+ .end strlen
diff --git a/private/crt32/string/i386/memccpy.asm b/private/crt32/string/i386/memccpy.asm
new file mode 100644
index 000000000..728f4ce23
--- /dev/null
+++ b/private/crt32/string/i386/memccpy.asm
@@ -0,0 +1,103 @@
+ page ,132
+ title memccpy - copy bytes until character found
+;***
+;memccpy.asm - copy bytes until a character is found
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _memccpy() - copies bytes until a specifed character
+; is found, or a maximum number of characters have been copied.
+;
+;Revision History:
+; 05-16-84 RN initial version
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 adjustments
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-17-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+; 10-27-92 SKS Avoid using a MASM keyword ("C") as a parameter name
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_memccpy(dest, src, _c, count) - copy bytes until character found
+;
+;Purpose:
+; Copies bytes from src to dest until count bytes have been
+; copied, or up to and including the character _c, whichever
+; comes first.
+;
+; Algorithm:
+; char *
+; _memccpy (dest, sorc, _c, count)
+; char *dest, *sorc, _c;
+; unsigned int count;
+; {
+; while (count && (*dest++ = *sorc++) != _c)
+; count--;
+;
+; return(count ? dest : NULL);
+; }
+;
+;Entry:
+; char *dest - pointer to memory to receive copy
+; char *src - source of bytes
+; char _c - character to stop copy at
+; int count - max number of bytes to copy
+;
+;Exit:
+; returns pointer to byte immediately after _c in dest;
+; returns NULL if _c was never found
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _memccpy
+_memccpy proc \
+ uses edi esi, \
+ dest:ptr byte, \
+ sorc:ptr byte, \
+ _c:byte, \
+ count:IWORD
+
+ mov edi,dest ; di = dest
+ mov esi,sorc ; si = source
+
+ mov ah,_c ; ah = byte to look for
+ mov ecx,count ; cx = max byte count
+ jecxz short retnull ; don't do loop if nothing to move
+
+lupe:
+ lodsb ; get byte into al and kick si
+ stosb ; store byte from al and kick di
+ cmp al,ah ; see if we just moved the byte
+ je short toend ; end of string
+
+ loop lupe ; dec cx & jmp to lupe if nonzero
+ ; else drop out & return NULL
+retnull:
+ xor edi,edi ; null pointer
+toend:
+ mov eax,edi ; return value
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + 2*ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_memccpy endp
+ end
diff --git a/private/crt32/string/i386/memchr.asm b/private/crt32/string/i386/memchr.asm
new file mode 100644
index 000000000..3e20583c2
--- /dev/null
+++ b/private/crt32/string/i386/memchr.asm
@@ -0,0 +1,96 @@
+ page ,132
+ title memchr - search memory for a given character
+;***
+;memchr.asm - search block of memory for a given character
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines memchr() - search memory until a character is
+; found or a limit is reached.
+;
+;Revision History:
+; 05-16-84 RN initial version
+; 07-20-87 SKS rewritten for speed
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *memchr(buf, chr, cnt) - search memory for given character.
+;
+;Purpose:
+; Searched at buf for the given character, stopping when chr is
+; first found or cnt bytes have been searched through.
+;
+; Algorithm:
+; char *
+; memchr (buf, chr, cnt)
+; char *buf;
+; int chr;
+; unsigned cnt;
+; {
+; while (cnt && *buf++ != c)
+; cnt--;
+; return(cnt ? --buf : NULL);
+; }
+;
+;Entry:
+; char *buf - memory buffer to be searched
+; char chr - character to search for
+; unsigned cnt - max number of bytes to search
+;
+;Exit:
+; returns pointer to first occurence of chr in buf
+; returns NULL if chr not found in the first cnt bytes
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public memchr
+memchr proc \
+ buf:ptr, \
+ chr:byte, \
+ cnt:IWORD
+
+ xor eax,eax ; return NULL if cnt == 0
+
+ mov ecx,(cnt) ; cx = count
+ jecxz short empty
+
+ push edi ; Preserve DI
+
+ mov edi,buf ; di = buffer
+ mov al,chr ; al = search char
+
+ repne scasb ; scan for byte
+ mov eax,0 ; assume not found (ax=NULL)
+ jne short done ; not found -- return NULL
+ lea eax,[edi-1] ; found - return address of matching byte
+done:
+ pop edi ; Restore DI
+empty:
+
+ifdef _STDCALL_
+ ret DPSIZE + 2*ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+memchr endp
+ end
diff --git a/private/crt32/string/i386/memcmp.asm b/private/crt32/string/i386/memcmp.asm
new file mode 100644
index 000000000..cd419fd2e
--- /dev/null
+++ b/private/crt32/string/i386/memcmp.asm
@@ -0,0 +1,101 @@
+ page ,132
+ title memcmp - compare to blocks of memory
+;***
+;memcmp.asm - compare two blocks of memory
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines memcmp() - compare two memory blocks lexically and
+; find their order.
+;
+;Revision History:
+; 05-16-83 RN initial version
+; 07-20-87 SKS rewritten for speed
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int memcmp(buf1, buf2, count) - compare memory for lexical order
+;
+;Purpose:
+; Compares count bytes of memory starting at buf1 and buf2
+; and find if equal or which one is first in lexical order.
+;
+; Algorithm:
+; int
+; memcmp (buf1, buf2, count)
+; char *buf1, *buf2;
+; unsigned count;
+; {
+; if (!count)
+; return(0);
+; while (--count && *buf1 == *buf2)
+; {
+; buf1++;
+; buf2++;
+; }
+; return(*buf1 - *buf2);
+; }
+;
+;Entry:
+; char *buf1, *buf2 - pointers to memory sections to compare
+; unsigned count - length of sections to compare
+;
+;Exit:
+; returns -1 if buf1 < buf2
+; returns 0 if buf1 == buf2
+; returns +1 if buf1 > buf2
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public memcmp
+memcmp proc \
+ uses edi esi, \
+ buf1:ptr byte, \
+ buf2:ptr byte, \
+ count:IWORD
+
+ mov esi,buf1 ; si = buf1
+ mov edi,buf2 ; di = buf2
+
+;
+; choose ds:si=buf1 and es:di=buf2 so that the CARRY flag
+; gets the right way by the REP CMPSB instruction below.
+;
+ xor eax,eax
+ mov ecx,count
+ jecxz short done
+
+ repe cmpsb ; compare while equal, at most "count" bytes
+ je short done ; buf1 == buf2? (AX = 0)
+ ; buf1 < buf2 buf1 > buf2
+ sbb eax,eax ; AX=-1, CY=1 AX=0, CY=0
+ sbb eax,-1 ; AX=-1 AX=1
+done:
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+memcmp endp
+ end
diff --git a/private/crt32/string/i386/memcpy.asm b/private/crt32/string/i386/memcpy.asm
new file mode 100644
index 000000000..4cde3cf72
--- /dev/null
+++ b/private/crt32/string/i386/memcpy.asm
@@ -0,0 +1,354 @@
+ page ,132
+ title memcpy - Copy source memory bytes to destination
+;***
+;memcpy.asm - contains memcpy and memmove routines
+;
+; Copyright (c) 1986-1991, Microsoft Corporation. All right reserved.
+;
+;Purpose:
+; memcpy() copies a source memory buffer to a destination buffer.
+; Overlapping buffers are not treated specially, so propogation may occur.
+; memmove() copies a source memory buffer to a destination buffer.
+; Overlapping buffers are treated specially, to avoid propogation.
+;
+;Revision History:
+; 02-06-87 JCR Added memmove entry
+; 04-08-87 JCR Conditionalized memmove/memcpy entries
+; 06-30-87 SKS Rewritten for speed and size
+; 08-21-87 SKS Fix return value for overlapping copies
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-19-88 JCR Minor 386 corrections/enhancements
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+; 11-13-92 SRW Make it fast with unaligned arguments
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+M_EXIT macro
+ mov eax,[dst] ; return pointer to destination
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+ endm ; M_EXIT
+
+ CODESEG
+
+page
+;***
+;memcpy - Copy source buffer to destination buffer
+;
+;Purpose:
+; memcpy() copies a source memory buffer to a destination memory buffer.
+; This routine does NOT recognize overlapping buffers, and thus can lead
+; to propogation.
+; For cases where propogation must be avoided, memmove() must be used.
+;
+; Algorithm:
+;
+; void * memcpy(void * dst, void * src, size_t count)
+; {
+; void * ret = dst;
+;
+; /*
+; * copy from lower addresses to higher addresses
+; */
+; while (count--)
+; *dst++ = *src++;
+;
+; return(ret);
+; }
+;
+;memmove - Copy source buffer to destination buffer
+;
+;Purpose:
+; memmove() copies a source memory buffer to a destination memory buffer.
+; This routine recognize overlapping buffers to avoid propogation.
+; For cases where propogation is not a problem, memcpy() can be used.
+;
+; Algorithm:
+;
+; void * memmove(void * dst, void * src, size_t count)
+; {
+; void * ret = dst;
+;
+; if (dst <= src || dst >= (src + count)) {
+; /*
+; * Non-Overlapping Buffers
+; * copy from lower addresses to higher addresses
+; */
+; while (count--)
+; *dst++ = *src++;
+; }
+; else {
+; /*
+; * Overlapping Buffers
+; * copy from higher addresses to lower addresses
+; */
+; dst += count - 1;
+; src += count - 1;
+;
+; while (count--)
+; *dst-- = *src--;
+; }
+;
+; return(ret);
+; }
+;
+;
+;Entry:
+; void *dst = pointer to destination buffer
+; const void *src = pointer to source buffer
+; size_t count = number of bytes to copy
+;
+;Exit:
+; Returns a pointer to the destination buffer in AX/DX:AX
+;
+;Uses:
+; CX, DX
+;
+;Exceptions:
+;*******************************************************************************
+
+ifdef MEM_MOVE
+ _MEM_ equ <memmove>
+else
+ _MEM_ equ <memcpy>
+endif
+
+% public _MEM_
+_MEM_ proc \
+ uses edi esi, \
+ dst:ptr byte, \
+ src:ptr byte, \
+ count:IWORD
+
+ ; destination pointer
+ ; source pointer
+ ; number of bytes to copy
+
+ mov esi,[src] ; esi = source
+ mov edi,[dst] ; edi = dest
+ mov ecx,[count] ; ecx = number of bytes to move
+
+;
+; Check for overlapping buffers:
+; If (dst <= src) Or (dst >= src + Count) Then
+; Do normal (Upwards) Copy
+; Else
+; Do Downwards Copy to avoid propagation
+;
+
+ cmp edi,esi ; dst <= src ?
+ jbe short CopyUp ; yes, copy toward higher addresses
+
+ mov eax,esi
+ add eax,ecx
+ cmp edi,eax ; dst >= (src + count) ?
+ jnae CopyDown ; no, copy toward lower addresses
+
+;
+; Copy toward higher addresses.
+;
+CopyUp:
+
+;
+; The algorithm for forward moves is to align the destination to a dword
+; boundary and so we can move dwords with an aligned destination. This
+; occurs in 3 steps.
+;
+; - move x = ((4 - Dest & 3) & 3) bytes
+; - move y = ((L-x) >> 2) dwords
+; - move (L - x - y*4) bytes
+;
+ test edi,11b ; destination dword aligned?
+ jnz short byterampup ; if we are not dword aligned already, align
+
+ mov edx,ecx ; byte count
+ and edx,11b ; trailing byte count
+ shr ecx,2 ; shift down to dword count
+ rep movsd ; move all of our dwords
+
+ jmp dword ptr TrailingVecs[edx*4]
+
+ align @WordSize
+TrailingVecs dd Trail0, Trail1, Trail2, Trail3
+
+ align @WordSize
+Trail3:
+ mov ax,[esi]
+ mov [edi],ax
+ mov al,[esi+2]
+ mov [edi+2],al
+
+ M_EXIT
+
+ align @WordSize
+Trail2:
+ mov ax,[esi]
+ mov [edi],ax
+
+ M_EXIT
+
+ align @WordSize
+Trail1:
+ mov al,[esi]
+ mov [edi],al
+
+Trail0:
+ M_EXIT
+
+;
+; Code to do optimal memory copies for non-dword-aligned destinations.
+;
+ align @WordSize
+byterampup:
+
+; The following length check is done for two reasons:
+;
+; 1. to ensure that the actual move length is greater than any possiale
+; alignment move, and
+;
+; 2. to skip the multiple move logic for small moves where it would
+; be faster to move the bytes with one instruction.
+;
+; Leading bytes could be handled faster via split-out optimizations and
+; a jump table (as trailing bytes are), at the cost of size.
+;
+; At this point, ECX is the # of bytes to copy, and EDX is the # of leading
+; bytes to copy.
+;
+ cmp ecx,12 ; check for reasonable length
+ jbe short ShortMove ; do short move if appropriate
+ mov edx,edi
+ neg edx
+ and edx,11b ; # of leading bytes
+ sub ecx,edx ; subtract out leading bytes
+ mov eax,ecx ; # of bytes remaining after leading
+ mov ecx,edx ; # of leading bytes
+ rep movsb ; copy leading bytes
+ mov ecx,eax ; compute number of dwords to move
+ and eax,11b ; # of trailing bytes
+ shr ecx,2 ; # of whole dwords
+ rep movsd ; move whole dwords
+ jmp dword ptr TrailingVecs[eax*4] ; copy trailing bytes
+
+;
+; Simple copy, byte at a time. This could be faster with a jump table and
+; split-out optimizations, copying as much as possible a dword/word at a
+; time and using MOV with displacements, but such short cases are unlikely
+; to be called often (it seems silly to call a function to copy less than
+; three dwords).
+;
+ align @WordSize
+ShortMove:
+ rep movsb
+
+ M_EXIT
+
+;
+; Copy down to avoid propogation in overlapping buffers.
+;
+ align @WordSize
+CopyDown:
+ std ; Set Direction Flag = Down
+ add esi,ecx ; point to byte after end of source buffer
+ add edi,ecx ; point to byte after end of dest buffer
+;
+; See if the destination start is dword aligned
+;
+
+ test edi,11b
+ jnz short byterampup_copydown ; not dword aligned
+;
+; Destination start is dword aligned
+;
+ mov edx,ecx ; set aside count of bytes to copy
+ and edx,11b ; # of trailing bytes to copy
+ sub esi,4 ; point to start of first dword to copy
+ sub edi,4 ; point to start of first dword to copy to
+ shr ecx,2 ; dwords to copy
+ rep movsd ; copy as many dwords as possible
+ jmp dword ptr TrailingVecs_copydown[edx*4] ;do any trailing bytes
+
+ align @WordSize
+TrailingVecs_copydown label dword
+ dd Trail0_copydown
+ dd Trail1_copydown
+ dd Trail2_copydown
+ dd Trail3_copydown
+
+ align @WordSize
+Trail3_copydown:
+ mov ax,[esi+2]
+ mov [edi+2],ax
+ mov al,[esi+1]
+ mov [edi+1],al
+ cld ; Set Direction Flag = Up
+
+ M_EXIT
+
+ align @WordSize
+Trail2_copydown:
+ mov ax,[esi+2]
+ mov [edi+2],ax
+ cld ; Set Direction Flag = Up
+
+ M_EXIT
+
+ align @WordSize
+Trail1_copydown:
+ mov al,[esi+3]
+ mov [edi+3],al
+Trail0_copydown:
+ cld ; Set Direction Flag = Up
+
+ M_EXIT
+
+;
+; Destination start is not dword aligned.
+;
+; Leading bytes could be handled faster via split-out optimizations and
+; a jump table (as trailing bytes are), at the cost of size.
+;
+; At this point, ECX is the # of bytes to copy, and EDX is the # of leading
+; bytes to copy.
+;
+ align @WordSize
+byterampup_copydown:
+ dec esi ; point to first leading src byte
+ dec edi ; point to first leading dest byte
+ cmp ecx,12 ; check for reasonable length
+ jbe short ShortMove_copydown ; do short move if appropriate
+ neg edx
+ and edx,11b
+ sub ecx,edx ; # of bytes after leading bytes
+ mov eax,ecx ; set aside # of bytes remaining
+ mov ecx,edx ; # of leading bytes
+ rep movsb ; copy leading odd bytes
+ mov ecx,eax ; # of remaining bytes
+ and eax,11b ; # of trailing bytes
+ sub esi,3 ; point to start of first whole src dword
+ sub edi,3 ; point to start of first whole dest dword
+ shr ecx,2 ; # of whole dwords
+ rep movsd ; copy whole dwords
+ jmp dword ptr TrailingVecs_copydown[eax*4]
+
+ align @WordSize
+ShortMove_copydown:
+ rep movsb
+ cld ; Set Direction Flag = Up
+
+ M_EXIT
+
+_MEM_ endp
+ end
+
+
diff --git a/private/crt32/string/i386/memicmp.asm b/private/crt32/string/i386/memicmp.asm
new file mode 100644
index 000000000..e87427660
--- /dev/null
+++ b/private/crt32/string/i386/memicmp.asm
@@ -0,0 +1,132 @@
+ page ,132
+ title memicmp - compare blocks of memory, ignore case
+;***
+;memicmp.asm - compare memory, ignore case
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _memicmp() - compare two blocks of memory for lexical
+; order. Case is ignored in the comparison.
+;
+;Revision History:
+; 05-16-83 RN initial version
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Cleanup...
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-17-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int _memicmp(first, last, count) - compare two blocks of memory, ignore case
+;
+;Purpose:
+; Compares count bytes of the two blocks of memory stored at first
+; and last. The characters are converted to lowercase before
+; comparing (not permanently), so case is ignored in the search.
+;
+; Algorithm:
+; int
+; _memicmp (first, last, count)
+; char *first, *last;
+; unsigned count;
+; {
+; if (!count)
+; return(0);
+; while (--count && tolower(*first) == tolower(*last))
+; {
+; first++;
+; last++;
+; }
+; return(tolower(*first) - tolower(*last));
+; }
+;
+;Entry:
+; char *first, *last - memory buffers to compare
+; unsigned count - maximum length to compare
+;
+;Exit:
+; returns <0 if first < last
+; returns 0 if first == last
+; returns >0 if first > last
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _memicmp
+_memicmp proc \
+ uses edi esi ebx, \
+ first:ptr byte, \
+ last:ptr byte, \
+ count:IWORD
+
+ mov esi,[first] ; si = first
+ mov edi,[last] ; di = last
+
+ mov ecx,[count] ; cx = count
+ jecxz short toend ; if count=0, nothing to do
+
+ mov bh,'A'
+ mov bl,'Z'
+ mov dh,'a'-'A' ; add to cap to make lower
+
+lupe:
+ mov ah,[esi] ; ah = *first
+ mov al,[edi] ; al = *last
+ inc esi ; first++
+ inc edi ; last++
+ cmp ah,bh ; ah < 'A' ??
+ jb short skip1
+
+ cmp ah,bl ; ah > 'Z' ??
+ ja short skip1
+
+ add ah,dh ; make lower case
+
+skip1:
+ cmp al,bh ; al < 'A' ??
+ jb short skip2
+
+ cmp al,bl ; al > 'Z' ??
+ ja short skip2
+
+ add al,dh ; make lower case
+
+skip2:
+ cmp ah,al ; *first == *last ??
+ jne short differ ; nope, found mismatched chars
+
+ loop lupe
+ jmp short toend ; cx = 0, return 0
+
+differ:
+ mov ecx,-1 ; assume last is bigger
+ ; *** can't use "or ecx,-1" due to flags ***
+ jb short toend ; last is, in fact, bigger (return -1)
+ neg ecx ; first is bigger (return 1)
+
+toend:
+ mov eax,ecx ; move return value to ax
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_memicmp endp
+ end
diff --git a/private/crt32/string/i386/memmove.asm b/private/crt32/string/i386/memmove.asm
new file mode 100644
index 000000000..39863a1db
--- /dev/null
+++ b/private/crt32/string/i386/memmove.asm
@@ -0,0 +1,19 @@
+;***
+;memmove.asm -
+;
+; Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; memmove() copies a source memory buffer to a destination buffer.
+; Overlapping buffers are treated specially, to avoid propogation.
+;
+; NOTE: This stub module scheme is compatible with NT build
+; procedure.
+;
+;Revision History:
+; 09-25-91 JCR Stub module created.
+;
+;*******************************************************************************
+
+MEM_MOVE EQU 1
+INCLUDE I386\MEMCPY.ASM
diff --git a/private/crt32/string/i386/memset.asm b/private/crt32/string/i386/memset.asm
new file mode 100644
index 000000000..6a6f2ca58
--- /dev/null
+++ b/private/crt32/string/i386/memset.asm
@@ -0,0 +1,127 @@
+ page ,132
+ title memset - set sections of memory all to one byte
+;***
+;memset.asm - set a section of memory to all one byte
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; contains the memset() routine
+;
+;Revision History:
+; 05-07-84 RN initial version
+; 06-30-87 SKS faster algorithm
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-19-88 JCR Enable word alignment code for all models/CPUs,
+; Some code improvement
+; 10-25-88 JCR General cleanup for 386-only code
+; 10-27-88 JCR More optimization (dword alignment, no ebx usage, etc)
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *memset(dst, val, count) - sets "count" bytes at "dst" to "val"
+;
+;Purpose:
+; Sets the first "count" bytes of the memory starting
+; at "dst" to the character value "val".
+;
+; Algorithm:
+; char *
+; memset (dst, val, count)
+; char *dst;
+; char val;
+; unsigned int count;
+; {
+; char *start = dst;
+;
+; while (count--)
+; *dst++ = val;
+; return(start);
+; }
+;
+;Entry:
+; char *dst - pointer to memory to fill with val
+; char val - value to put in dst bytes
+; int count - number of bytes of dst to fill
+;
+;Exit:
+; returns dst, with filled bytes
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public memset
+memset proc \
+ uses edi, \
+ dst:ptr byte, \
+ value:byte, \
+ count:IWORD
+
+ mov ecx,[count] ; cx = count
+ jecxz short toend ; if no work to do
+
+ ; set all 4 bytes of eax to [value]
+ mov al,[value] ; the byte value to be stored
+ mov ah,al ; store it as a word
+ mov edx,eax ; lo 16 bits dx=ax=val/val
+ ror eax,16 ; move val/val to hi 16-bits
+ mov ax,dx ; eax = all 4 bytes = [value]
+
+; Align address on dword boundary
+
+ mov edi,[dst] ; di = dest pointer
+ mov edx,edi ; dx = di = *dst
+ neg edx
+ and edx,(ISIZE-1) ; dx = # bytes before dword boundary
+ jz short dwords ; jump if address already aligned
+
+ cmp ecx,edx ; count >= # leading bytes??
+ jb short tail ; nope, just move ecx bytes
+
+ sub ecx,edx ; cx = adjusted count (for later)
+ xchg ecx,edx ; cx = leading byte count / dx = adjusted count
+ rep stosb ; store leading bytes
+ mov ecx,edx ; cx = count of remaining bytes
+ ;jecxz short toend ; jump out if nothing left to do
+
+; Move dword-sized blocks
+
+dwords:
+ mov edx,ecx ; save original count
+ shr ecx,ISHIFT ; cx = dword count
+ rep stos IWORD ptr [edi] ; fill 'em up
+ mov ecx,edx ; retrieve original byte count
+
+; Move remaining bytes
+
+tail: ; store remaining 1,2, or 3 bytes
+ and ecx,(ISIZE-1) ; get byte count
+ rep stosb ; store remaining bytes, if necessary
+
+; Done
+
+toend:
+ mov eax,[dst] ; return dest pointer
+
+ifdef _STDCALL_
+ ret DPSIZE + 2*ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+memset endp
+ end
diff --git a/private/crt32/string/i386/strcat.asm b/private/crt32/string/i386/strcat.asm
new file mode 100644
index 000000000..9781440c1
--- /dev/null
+++ b/private/crt32/string/i386/strcat.asm
@@ -0,0 +1,155 @@
+ page ,132
+ title strcat - concatenate (append) one string to another
+;***
+;strcat.asm - contains strcat() and strcpy() routines
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; STRCAT concatenates (appends) a copy of the source string to the
+; end of the destination string, returning the destination string.
+;
+;Revision History:
+; 04-21-87 SKS Rewritten to be fast and small, added file header
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 07-27-88 SJM Rewritten to be 386-specific and to include strcpy
+; 08-29-88 JCR 386 cleanup...
+; 10-07-88 JCR Correct off-by-1 strcat bug; optimize ecx=-1
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+
+page
+;***
+;char *strcat(dst, src) - concatenate (append) one string to another
+;
+;Purpose:
+; Concatenates src onto the end of dest. Assumes enough
+; space in dest.
+;
+; Algorithm:
+; char * strcat (char * dst, char * src)
+; {
+; char * cp = dst;
+;
+; while( *cp )
+; ++cp; /* Find end of dst */
+; while( *cp++ = *src++ )
+; ; /* Copy src to end of dst */
+; return( dst );
+; }
+;
+;Entry:
+; char *dst - string to which "src" is to be appended
+; const char *src - string to be appended to the end of "dst"
+;
+;Exit:
+; The address of "dst" in AX/DX:AX
+;
+;Uses:
+; BX, CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+page
+;***
+;char *strcpy(dst, src) - copy one string over another
+;
+;Purpose:
+; Copies the string src into the spot specified by
+; dest; assumes enough room.
+;
+; Algorithm:
+; char * strcpy (char * dst, char * src)
+; {
+; char * cp = dst;
+;
+; while( *cp++ = *src++ )
+; ; /* Copy src over dst */
+; return( dst );
+; }
+;
+;Entry:
+; char * dst - string over which "src" is to be copied
+; const char * src - string to be copied over "dst"
+;
+;Exit:
+; The address of "dst" in AX/DX:AX
+;
+;Uses:
+; BX, CX, DX
+;
+;Exceptions:
+;*******************************************************************************
+
+
+ CODESEG
+
+% public strcat, strcpy ; make both functions available
+
+strcat label proc ;--- strcat ---
+
+ clc ; carry clear = append
+ jmp short _docat
+
+ align @wordsize ; want to come in on a nice boundary...
+strcpy label proc ;--- strcpy ---
+
+ stc ; carry set = don't append to end of string
+ ;fall thru
+
+
+; --- Common code ---
+
+_docat proc private \
+ uses esi edi, \
+ dst:ptr byte, \
+ src:ptr byte
+
+ mov edi, dst ; di = dest pointer
+ jc short @F ; jump if not appending
+
+ ; now skip to end of destination string
+
+ xor eax, eax ; search for the null terminator
+ or ecx,-1 ; ecx = -1
+repne scasb
+ dec edi ; edi points to null terminator
+
+ ; copy source string
+
+@@: mov esi, src
+ xchg esi, edi ; now ds:esi->dst and es:edi->src
+ xor eax, eax ; search for null
+ or ecx,-1 ; ecx = -1
+
+repne scasb ; find the length of the src string
+ not ecx
+ sub edi, ecx
+ xchg esi, edi ; now es:edi->dst and ds:esi->src
+
+ mov eax, ecx
+ shr ecx, ISHIFT ; get the double-word count
+rep movsd
+ and eax, (ISIZE-1) ; get the byte cound
+ xchg ecx, eax
+rep movsb ; move remaining bytes, if any
+ mov eax, dst ; returned address
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_docat endp
+ end
diff --git a/private/crt32/string/i386/strchr.asm b/private/crt32/string/i386/strchr.asm
new file mode 100644
index 000000000..b2b6a5b56
--- /dev/null
+++ b/private/crt32/string/i386/strchr.asm
@@ -0,0 +1,94 @@
+ page ,132
+ title strchr - search string for given character
+;***
+;strchr.asm - search a string for a given character
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strchr() - search a string for a character
+;
+;Revision History:
+; 10-27-83 RN initial version
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strchr(string, c) - search a string for a character
+;
+;Purpose:
+; Searches a string for a given character, which may be the
+; null character '\0'.
+;
+; Algorithm:
+; char *
+; strchr (string, ch)
+; char *string, ch;
+; {
+; while (*string && *string != ch)
+; string++;
+; if (*string == ch)
+; return(string);
+; return((char *)0);
+; }
+;
+;Entry:
+; char *string - string to search in
+; char c - character to search for
+;
+;Exit:
+; returns pointer to the first occurence of c in string
+; returns NULL if c does not occur in string
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strchr
+strchr proc \
+ uses edi, \
+ string:ptr char, \
+ chr:byte
+
+ mov edi,[string] ; edi = string
+
+ push edi ; save string pointer
+ xor eax,eax ; null byte to search for
+ mov ecx, -1
+repne scasb ; find string length by scanning for null
+ not ecx ; cx = length of string
+ mov al,[chr] ; al=byte to search for
+ pop edi ; restore saved string pointer
+repne scasb ; find that byte (if it exists)!
+ ; edi points one past byte which stopped scan
+ dec edi ; edi points to byte which stopped scan
+
+ cmp [edi],al ; take one last look to be sure
+ je short retdi ; return edi if it matches
+ xor edi,edi ; no match, so return NULL
+retdi:
+ mov eax,edi ; ret value: pointer to matching byte
+
+ifdef _STDCALL_
+ ret DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strchr endp
+ end
diff --git a/private/crt32/string/i386/strcmp.asm b/private/crt32/string/i386/strcmp.asm
new file mode 100644
index 000000000..6024848b5
--- /dev/null
+++ b/private/crt32/string/i386/strcmp.asm
@@ -0,0 +1,104 @@
+ page ,132
+ title strcmp.asm - compare two strings
+;***
+;strcmp.asm - routine to compare two strings (for equal, less, or greater)
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; STRCMP compares two strings and returns an integer
+; to indicate whether the first is less than the second, the two are
+; equal, or whether the first is greater than the second, respectively.
+; Comparison is done byte by byte on an UNSIGNED basis, which is to
+; say that Null (0) is less than any other character (1-255).
+;
+;Revision History:
+; 04-21-87 SKS Module rewritten to be fast and small
+; 05-17-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;strcmp - compare two strings, returning less than, equal to, or greater than
+;
+;Purpose:
+; Compares two string, determining their lexical order. Unsigned
+; comparison is used.
+;
+; Algorithm:
+; int strcmp ( src , dst )
+; unsigned char *src;
+; unsigned char *dst;
+; {
+; int ret = 0 ;
+;
+; while( ! (ret = *src - *dst) && *dst)
+; ++src, ++dst;
+;
+; if ( ret < 0 )
+; ret = -1 ;
+; else if ( ret > 0 )
+; ret = 1 ;
+;
+; return( ret );
+; }
+;
+;Entry:
+; const char * src - string for left-hand side of comparison
+; const char * dst - string for right-hand side of comparison
+;
+;Exit:
+; AX < 0, 0, or >0, indicating whether the first string is
+; Less than, Equal to, or Greater than the second string.
+;
+;Uses:
+; CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ .lall
+
+ public strcmp
+strcmp proc \
+ uses edi esi, \
+ src:ptr byte, \
+ dst:ptr byte
+
+
+ mov esi,[src] ; si = source
+ xor eax,eax ; mingle register instr with mem instr.
+ mov edi,[dst] ; di = dest
+
+ or ecx,-1 ; cx = -1
+ repne scasb ; compute length of "dst"
+ not ecx ; CX = strlen(dst)+1
+ sub edi,ecx ; restore DI = dst
+ repe cmpsb ; compare while equal, at most length of "dst"
+ je short toend ; dst == src? (AX = 0)
+ ; dst < src dst > src
+ sbb eax,eax ; AX=-1, CY=1 AX=0, CY=0
+ sbb eax,-1 ; AX=-1 AX=1
+toend:
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strcmp endp
+ end
diff --git a/private/crt32/string/i386/strcspn.asm b/private/crt32/string/i386/strcspn.asm
new file mode 100644
index 000000000..39554147f
--- /dev/null
+++ b/private/crt32/string/i386/strcspn.asm
@@ -0,0 +1,19 @@
+;***
+;strcspn.asm -
+;
+; Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strcspn()- finds the length of the initial substring of
+; a string consisting entirely of characters not in a control string.
+;
+; NOTE: This stub module scheme is compatible with NT build
+; procedure.
+;
+;Revision History:
+; 09-25-91 JCR Stub module created.
+;
+;*******************************************************************************
+
+SSTRCSPN EQU 1
+INCLUDE I386\STRSPN.ASM
diff --git a/private/crt32/string/i386/strdup.asm b/private/crt32/string/i386/strdup.asm
new file mode 100644
index 000000000..04f388e4a
--- /dev/null
+++ b/private/crt32/string/i386/strdup.asm
@@ -0,0 +1,126 @@
+ page ,132
+ title strdup - duplicate string in malloc'd memory
+;***
+;strdup.asm - duplicate a string in malloc'd memory
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strdup() - grab new memory, and duplicate the string into it.
+;
+;Revision History:
+; 10-27-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 cleanup
+; 10-25-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+ extrn strlen:proc
+ extrn strcpy:proc
+ extrn malloc:proc
+
+
+page
+;***
+;char *_strdup(string) - duplicate string into malloc'd memory
+;
+;Purpose:
+; Allocates enough storage via malloc() for a copy of the
+; string, copies the string into the new memory, and returns
+; a pointer to it.
+;
+; Algorithm:
+; char *
+; _strdup (string)
+; char *string;
+; {
+; char *memory;
+;
+; if (!string)
+; return(NULL);
+; if (memory = malloc(strlen(string) + 1))
+; return(strcpy(memory,string));
+; return(NULL);
+; }
+;
+;Entry:
+; char *string - string to copy into new memory
+;
+;Exit:
+; returns a pointer to the newly allocated storage with the
+; string in it.
+; returns NULL if enough memory could not be allocated, or
+; string was NULL.
+;
+;Uses:
+; eax, edx
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+% public _strdup
+_strdup proc \
+ uses edi, \
+ string:ptr byte
+
+
+ mov edi,[string] ; edi=pointer to string
+ push edi ; stack parameter: string pointer
+ call strlen ; eax = string length
+
+ifndef _STDCALL_
+ pop edx ; caller cleans stack (_cdecl)
+;else
+ ; callee cleaned stack (_stdcall)
+endif
+
+ inc eax ; need space for null byte too
+ push eax ; stack parameter: string length (with null)
+ call malloc ; eax = pointer to space
+
+ifndef _STDCALL_
+ pop edx ; caller cleans stack (_cdecl)
+;else
+ ; callee cleaned stack (_stdcall)
+endif
+
+ or eax,eax ; offset == NULL ??
+ jz short toend ; error -- couldn't malloc space
+
+okay:
+ push edi ; push address of original string
+ push eax ; push address of dest string
+ ; source string addr is still on stack
+ call strcpy ; duplicate the string
+
+ifndef _STDCALL_
+ pop edx ; caller cleans stack (_cdecl)
+ pop edx
+;else
+ ; callee cleaned stack (_stdcall)
+endif
+
+ ; pointer to duplicate is in eax
+
+toend: ; eax = return value
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strdup endp
+ end
diff --git a/private/crt32/string/i386/stricmp.asm b/private/crt32/string/i386/stricmp.asm
new file mode 100644
index 000000000..80f384701
--- /dev/null
+++ b/private/crt32/string/i386/stricmp.asm
@@ -0,0 +1,127 @@
+ page ,132
+ title stricmp
+;***
+;strcmp.asm - contains case-insensitive string comparision routine
+; _stricmp/_strcmpi
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; contains _stricmpi(), also known as _strcmpi()
+;
+;Revision History:
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 cleanup
+; 10-10-88 JCR Added strcmpi() entry for compatiblity with early revs
+; 10-25-88 JCR General cleanup for 386-only code
+; 10-27-88 JCR Shuffled regs so no need to save/restore ebx
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int _stricmp(dst, src), _strcmpi(dst, src) - compare strings, ignore case
+;
+;Purpose:
+; _stricmp/_strcmpi perform a case-insensitive string comparision.
+; For differences, upper case letters are mapped to lower case.
+; Thus, "abc_" < "ABCD" since "_" < "d".
+;
+; Algorithm:
+;
+; int _strcmpi (char * dst, char * src)
+; {
+; int f,l;
+;
+; do {
+; f = tolower(*dst);
+; l = tolower(*src);
+; dst++;
+; src++;
+; } while (f && f == l);
+;
+; return(f - l);
+; }
+;
+;Entry:
+; char *dst, *src - strings to compare
+;
+;Exit:
+; AX = -1 if dst < src
+; AX = 0 if dst = src
+; AX = +1 if dst > src
+;
+;Uses:
+; CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strcmpi ; alternate entry point for compatibility
+_strcmpi label proc
+
+ public _stricmp
+_stricmp proc \
+ uses esi, \
+ dst:ptr, \
+ src:ptr
+
+
+ mov esi,[src] ; SI = src
+ mov edx,[dst] ; DX = dst
+ mov al,-1 ; fall into loop
+
+chk_null:
+ or al,al
+ jz short done
+again:
+ lodsb ; al = next source byte
+ mov ah,[edx] ; ah = next dest byte
+ inc edx
+
+ cmp ah,al ; first try case-sensitive comparision
+ je short chk_null ; match
+
+ sub al,'A'
+ cmp al,'Z'-'A'+1
+ sbb cl,cl
+ and cl,'a'-'A'
+ add al,cl
+ add al,'A' ; tolower(*dst)
+
+ xchg ah,al ; operations on AL are shorter than AH
+
+ sub al,'A'
+ cmp al,'Z'-'A'+1
+ sbb cl,cl
+ and cl,'a'-'A'
+ add al,cl
+ add al,'A' ; tolower(*src)
+
+ cmp al,ah ; inverse of above comparison -- AL & AH are swapped
+ je short chk_null
+ ; dst < src dst > src
+ sbb al,al ; AL=-1, CY=1 AL=0, CY=0
+ sbb al,-1 ; AL=-1 AL=1
+done:
+ movsx eax,al ; extend al to eax
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_stricmp endp
+ end
diff --git a/private/crt32/string/i386/strlen.asm b/private/crt32/string/i386/strlen.asm
new file mode 100644
index 000000000..4ea531018
--- /dev/null
+++ b/private/crt32/string/i386/strlen.asm
@@ -0,0 +1,84 @@
+ page ,132
+ title strlen - return the length of a null-terminated string
+;***
+;strlen.asm - contains strlen() routine
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; strlen returns the length of a null-terminated string,
+; not including the null byte itself.
+;
+;Revision History:
+; 04-21-87 SKS Rewritten to be fast and small, added file header
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-02-88 SJM Add 32 bit code, use cruntime vs cmacros
+; 08-23-88 JCR 386 cleanup
+; 10-05-88 GJF Fixed off-by-2 error.
+; 10-10-88 JCR Minor improvement
+; 10-25-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;strlen - return the length of a null-terminated string
+;
+;Purpose:
+; Finds the length in bytes of the given string, not including
+; the final null character.
+;
+; Algorithm:
+; int strlen (const char * str)
+; {
+; int length = 0;
+;
+; while( *str++ )
+; ++length;
+;
+; return( length );
+; }
+;
+;Entry:
+; const char * str - string whose length is to be computed
+;
+;Exit:
+; AX = length of the string "str", exclusive of the final null byte
+;
+;Uses:
+; CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strlen
+strlen proc \
+ uses edi, \
+ string:ptr byte
+
+ mov edi,string ; edi -> string
+ xor eax,eax ; null byte
+ or ecx,-1 ; set ecx to -1
+repne scasb ; scan for null, ecx = -(1+strlen(str))
+ not ecx
+ dec ecx ; ecx = strlen(str)
+ mov eax,ecx ; eax = strlen(str)
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strlen endp
+ end
diff --git a/private/crt32/string/i386/strlwr.asm b/private/crt32/string/i386/strlwr.asm
new file mode 100644
index 000000000..edec61eb3
--- /dev/null
+++ b/private/crt32/string/i386/strlwr.asm
@@ -0,0 +1,104 @@
+ page ,132
+ title strlwr - map string to lower-case
+;***
+;strlwr.asm - routine to map lower-case characters in a string to upper-case
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; STRLWR converts upper-case characters in a null-terminated string
+; to their lower-case equivalents. Conversion is done in place and
+; characters other than upper-case letters are not modified.
+;
+; This function modifies only 7-bit ASCII characters
+; in the range 0x41 through 0x5A ('A' through 'Z').
+;
+;Revision History:
+; 04-21-87 SKS Rewritten to be fast and small, added file header
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-19-88 JCR Minor optimization
+; 10-10-88 JCR Changed an 'xchg' to 'mov'
+; 10-25-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strlwr(string) - map upper-case characters in a string to lower-case
+;
+;Purpose:
+; Converts all the upper case characters in a string to lower case,
+; in place.
+;
+; Algorithm:
+; char * _strlwr (char * string)
+; {
+; char * cp = string;
+;
+; while( *cp )
+; {
+; if ('A' <= *cp && *cp <= 'Z')
+; *cp += 'a' - 'A';
+; ++cp;
+; }
+; return(string);
+; }
+;
+;Entry:
+; char *string - string to change to lower case
+;
+;Exit:
+; The input string address is returned in AX or DX:AX
+;
+;Uses:
+; BX, CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strlwr
+_strlwr proc \
+ string:ptr byte
+
+
+ mov ecx,[string] ; ecx = *string
+ mov edx,ecx ; save return value
+ jmp short first_char; jump into the loop
+
+ align @WordSize
+check_char:
+ sub al,'A' ; 'A' <= al <= 'Z' ?
+ cmp al,'Z'-'A'+1
+ jnb short next_char
+ add al,'a' ; map to lower case
+ mov [ecx],al ; and store new value
+next_char:
+ inc ecx ; bump pointer
+first_char:
+ mov al,[ecx] ; get next character
+ or al,al
+ jnz short check_char
+
+done:
+ mov eax,edx ; AX = return value ("string")
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strlwr endp
+ end
diff --git a/private/crt32/string/i386/strncat.asm b/private/crt32/string/i386/strncat.asm
new file mode 100644
index 000000000..b6060bb12
--- /dev/null
+++ b/private/crt32/string/i386/strncat.asm
@@ -0,0 +1,117 @@
+ page ,132
+ title strncat - append n chars of string1 to string2
+;***
+;strncat.asm - append n chars of string to new string
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strncat() - appends n characters of string onto
+; end of other string
+;
+;Revision History:
+; 10-25-83 RN initial version
+; 08-05-87 SKS Fixed bug: extra null was stored if n > strlen(back)
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR Minor 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strncat(front, back, count) - append count chars of back onto front
+;
+;Purpose:
+; Appends at most count characters of the string back onto the
+; end of front, and ALWAYS terminates with a null character.
+; If count is greater than the length of back, the length of back
+; is used instead. (Unlike strncpy, this routine does not pad out
+; to count characters).
+;
+; Algorithm:
+; char *
+; strncat (front, back, count)
+; char *front, *back;
+; unsigned count;
+; {
+; char *start = front;
+;
+; while (*front++)
+; ;
+; front--;
+; while (count--)
+; if (!(*front++ = *back++))
+; return(start);
+; *front = '\0';
+; return(start);
+; }
+;
+;Entry:
+; char *front - string to append onto
+; char *back - string to append
+; unsigned count - count of max characters to append
+;
+;Exit:
+; returns a pointer to string appended onto (front).
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strncat
+strncat proc \
+ uses edi esi, \
+ front:ptr byte, \
+ back:ptr byte, \
+ count:IWORD
+
+
+ mov edi,[front] ; di=pointer to dest
+
+ mov edx,edi ; save return value in dx
+ xor eax,eax ; search value: null byte (assumed zero below!)
+ or ecx,-1 ; cx = -1, so won't stop scan
+repne scasb ; find null byte
+ dec edi ; di points to dest null terminator
+ mov esi,edi ; si " " " " "
+
+ mov edi,[back] ; di points to source
+
+ push edi ; save back pointer
+ mov ecx,[count] ; cx = count bytes negatively
+repne scasb ; find null byte & get source length
+ jne short nonull
+ inc ecx ; do NOT count null byte in length
+nonull:
+ ; cx=count of difference in bytes in source
+ ; with reference (without null)
+ sub ecx,[count] ; take the difference of bytes counted to expected
+ neg ecx ; away from expected
+ mov edi,esi ; di=pointer to dest null terminator
+ pop esi ; restore pointer to source
+rep movsb ; concatenate the strings
+ ; WARNING: AL must be zero at this point!
+ stosb ; attach null byte
+
+ mov eax,edx ; return value: dest addr
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strncat endp
+ end
diff --git a/private/crt32/string/i386/strncmp.asm b/private/crt32/string/i386/strncmp.asm
new file mode 100644
index 000000000..15b187651
--- /dev/null
+++ b/private/crt32/string/i386/strncmp.asm
@@ -0,0 +1,120 @@
+ page ,132
+ title strncmp - compare first n chars of two strings
+;***
+;strncmp.asm - compare first n characters of two strings
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strncmp() - compare first n characters of two strings
+; for lexical order.
+;
+;Revision History:
+; 10-26-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int strncmp(first, last, count) - compare first count chars of strings
+;
+;Purpose:
+; Compares two strings for lexical order. The comparison stops
+; after: (1) a difference between the strings is found, (2) the end
+; of the strings is reached, or (3) count characters have been
+; compared.
+;
+; Algorithm:
+; int
+; strncmp (first, last, count)
+; char *first, *last;
+; unsigned count;
+; {
+; if (!count)
+; return(0);
+; while (--count && *first && *first == *last)
+; {
+; first++;
+; last++;
+; }
+; return(*first - *last);
+; }
+;
+;Entry:
+; char *first, *last - strings to compare
+; unsigned count - maximum number of characters to compare
+;
+;Exit:
+; returns <0 if first < last
+; returns 0 if first == last
+; returns >0 if first > last
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strncmp
+strncmp proc \
+ uses edi esi ebx, \
+ first:ptr byte, \
+ last:ptr byte, \
+ count:IWORD
+
+
+ mov ecx,[count] ; cx=max number of bytes to compare
+ jecxz short toend ; it's as if strings are equal
+
+ mov ebx,ecx ; bx saves count
+
+ mov edi,[first] ; di=first pointer (es=segment part)
+
+ mov esi,edi ; si saves first pointer
+ xor eax,eax ; ax=0
+repne scasb ; count bytes
+ neg ecx ; cx=count - strlen
+ add ecx,ebx ; strlen + count - strlen
+
+okay:
+ mov edi,esi ; restore first pointer
+ mov esi,[last] ; si = last pointer
+repe cmpsb ; compare strings
+ mov al,[esi-1]
+ xor ecx,ecx ; set return value = 0
+
+ cmp al,[edi-1] ; last-first
+ ja short lastbig ; <last is bigger>
+ je short toend ; <equal>
+ ;jb short firstbig ; <first is bigger>
+
+firstbig:
+ dec ecx ; first string is bigger
+ dec ecx ; make FFFE so 'not' will give 0001
+
+lastbig: ; last string is bigger
+ not ecx ; return -1
+
+toend:
+ mov eax,ecx ; return value
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strncmp endp
+ end
diff --git a/private/crt32/string/i386/strncpy.asm b/private/crt32/string/i386/strncpy.asm
new file mode 100644
index 000000000..fcf882553
--- /dev/null
+++ b/private/crt32/string/i386/strncpy.asm
@@ -0,0 +1,108 @@
+ page ,132
+ title strncpy - copy at most n characters of string
+;***
+;strncpy.asm - copy at most n characters of string
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strncpy() - copy at most n characters of string
+;
+;Revision History:
+; 10-25-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strncpy(dest, source, count) - copy at most n characters
+;
+;Purpose:
+; Copies count characters from the source string to the
+; destination. If count is less than the length of source,
+; NO NULL CHARACTER is put onto the end of the copied string.
+; If count is greater than the length of sources, dest is padded
+; with null characters to length count.
+;
+; Algorithm:
+; char *
+; strncpy (dest, source, count)
+; char *dest, *source;
+; unsigned count;
+; {
+; char *start = dest;
+;
+; while (count && (*dest++ = *source++))
+; count--;
+; if (count)
+; while (--count)
+; *dest++ = '\0';
+; return(start);
+; }
+;
+;Entry:
+; char *dest - pointer to spot to copy source, enough space
+; is assumed.
+; char *source - source string for copy
+; unsigned count - characters to copy
+;
+;Exit:
+; returns dest, with the character copied there.
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strncpy
+strncpy proc \
+ uses edi esi, \
+ dest:ptr byte, \
+ sorc:ptr byte, \
+ count:IWORD
+
+
+ mov edi,[dest] ; di=pointer to dest
+ mov esi,[sorc] ; si=pointer to source
+
+ mov edx,edi ; dx saves dest pointer
+ mov ecx,[count] ; get the max char count
+ jecxz short toend ; don't do loop if nothing to move
+
+lupe:
+ lodsb ; get byte into al and kick si
+ or al,al ; see if we just moved a null
+ jz short outlupe ; end of string
+
+ stosb ; store byte from al and kick di
+ loop lupe ; dec cx & jmp to lupe if nonzero
+ ; else drop out
+outlupe:
+ xor al,al ; null byte to store
+rep stosb ; store null for all cx>0
+
+toend:
+ mov eax,edx ; return value: dest addr
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strncpy endp
+ end
diff --git a/private/crt32/string/i386/strnicmp.asm b/private/crt32/string/i386/strnicmp.asm
new file mode 100644
index 000000000..cec5ec5a6
--- /dev/null
+++ b/private/crt32/string/i386/strnicmp.asm
@@ -0,0 +1,153 @@
+ page ,132
+ title strnicmp - compare n chars of strings, ignore case
+;***
+;strnicmp.asm - compare n chars of strings, ignoring case
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strnicmp() - Compares at most n characters of two strings,
+; without regard to case.
+;
+;Revision History:
+; 04-04-85 RN initial version
+; 07-11-85 TC zeroed cx, to allow correct return value if not equal
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup and improved return value sequence
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+
+page
+;***
+;int _strnicmp(first, last, count) - compares count char of strings, ignore case
+;
+;Purpose:
+; Compare the two strings for lexical order. Stops the comparison
+; when the following occurs: (1) strings differ, (2) the end of the
+; strings is reached, or (3) count characters have been compared.
+; For the purposes of the comparison, upper case characters are
+; converted to lower case.
+;
+; Algorithm:
+; int
+; _strncmpi (first, last, count)
+; char *first, *last;
+; unsigned int count;
+; {
+; int f,l;
+; int result = 0;
+;
+; if (count) {
+; do {
+; f = tolower(*first);
+; l = tolower(*last);
+; first++;
+; last++;
+; } while (--count && f && l && f == l);
+; result = f - l;
+; }
+; return(result);
+; }
+;
+;Entry:
+; char *first, *last - strings to compare
+; unsigned count - maximum number of characters to compare
+;
+;Exit:
+; returns <0 if first < last
+; returns 0 if first == last
+; returns >0 if first > last
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strnicmp
+_strnicmp proc \
+ uses edi esi ebx, \
+ first:ptr byte, \
+ last:ptr byte, \
+ count:IWORD
+
+
+ mov esi,[first] ; si = first string
+ mov edi,[last] ; di = last string
+
+ mov ecx,[count] ; cx = byte count
+ jecxz short toend ; if count=0
+
+ mov bh,'A'
+ mov bl,'Z'
+ mov dh,'a'-'A' ; add to cap to make lower
+
+lupe:
+ mov ah,[esi] ; *first
+ mov al,[edi] ; *last
+
+ or ah,ah ; see if *first is null
+ jz short eject ; jump if so
+
+ or al,al ; see if *last is null
+ jz short eject ; jump if so
+
+ inc esi ; first++
+ inc edi ; last++
+
+ cmp ah,bh ; 'A'
+ jb short skip1
+
+ cmp ah,bl ; 'Z'
+ ja short skip1
+
+ add ah,dh ; make lower case
+
+skip1:
+ cmp al,bh ; 'A'
+ jb short skip2
+
+ cmp al,bl ; 'Z'
+ ja short skip2
+
+ add al,dh ; make lower case
+
+skip2:
+ cmp ah,al ; *first == *last ??
+ jne short differ
+
+ loop lupe
+
+eject:
+ xor ecx,ecx
+ cmp ah,al ; compare the (possibly) differing bytes
+ je short toend ; both zero; return 0
+
+differ:
+ mov ecx,-1 ; assume last is bigger (* can't use 'or' *)
+ jb short toend ; last is, in fact, bigger (return -1)
+ neg ecx ; first is bigger (return 1)
+
+toend:
+ mov eax,ecx
+
+ifdef _STDCALL_
+ ret 2*DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strnicmp endp
+ end
diff --git a/private/crt32/string/i386/strnset.asm b/private/crt32/string/i386/strnset.asm
new file mode 100644
index 000000000..ae8a1248d
--- /dev/null
+++ b/private/crt32/string/i386/strnset.asm
@@ -0,0 +1,104 @@
+ page ,132
+ title strnset - set first n characters to one char.
+;***
+;strnset.asm - set first n characters to single character
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strnset() - sets at most the first n characters of a string
+; to a given character.
+;
+;Revision History:
+; 11-18-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 05-23-88 WAJ If count = strlen(string)+1 then strlen+1 bytes were set.
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-23-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strnset(string, val, count) - set at most count characters to val
+;
+;Purpose:
+; Sets the first count characters of string the character value.
+; If the length of string is less than count, the length of
+; string is used in place of n.
+;
+; Algorithm:
+; char *
+; _strnset (string, val, count)
+; char *string,val;
+; unsigned int count;
+; {
+; char *start = string;
+;
+; while (count-- && *string)
+; *string++ = val;
+; return(start);
+; }
+;
+;Entry:
+; char *string - string to set characters in
+; char val - character to fill with
+; unsigned count - count of characters to fill
+;
+;Exit:
+; returns string, now filled with count copies of val.
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strnset
+_strnset proc \
+ uses edi ebx, \
+ string:ptr byte, \
+ val:byte, \
+ count:IWORD
+
+
+ mov edi,[string] ; di = string
+ mov edx,edi ; dx=string addr; save return value
+ mov ebx,[count] ; cx = max chars to set
+ xor eax,eax ; null byte
+ mov ecx,ebx
+ jecxz short done ; zero length specified
+
+repne scasb ; find null byte & count bytes in cx
+ jne short nonull ; null not found
+ inc ecx ; don't want the null
+
+nonull:
+ sub ebx,ecx ; bx=strlen (not null)
+ mov ecx,ebx ; cx=strlen (not null)
+
+ mov edi,edx ; restore string pointer
+ mov al,val ; byte value
+rep stosb ; fill 'er up
+
+done:
+ mov eax,edx ; return value: string addr
+
+ifdef _STDCALL_
+ ret DPSIZE + 2*ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strnset endp
+ end
diff --git a/private/crt32/string/i386/strpbrk.asm b/private/crt32/string/i386/strpbrk.asm
new file mode 100644
index 000000000..1ccde4d0b
--- /dev/null
+++ b/private/crt32/string/i386/strpbrk.asm
@@ -0,0 +1,19 @@
+;***
+;strpbrk.asm -
+;
+; Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strpbrk()- finds the index of the first character in a string
+; that is not in a control string
+;
+; NOTE: This stub module scheme is compatible with NT build
+; procedure.
+;
+;Revision History:
+; 09-25-91 JCR Stub module created.
+;
+;*******************************************************************************
+
+SSTRPBRK EQU 1
+INCLUDE I386\STRSPN.ASM
diff --git a/private/crt32/string/i386/strrchr.asm b/private/crt32/string/i386/strrchr.asm
new file mode 100644
index 000000000..3808b7b8b
--- /dev/null
+++ b/private/crt32/string/i386/strrchr.asm
@@ -0,0 +1,105 @@
+ page ,132
+ title strrchr - find last occurence of character in string
+;***
+;strrchr.asm - find last occurrence of character in string
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strrchr() - find the last occurrence of a given character
+; in a string.
+;
+;Revision History:
+; 10-27-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strrchr(string, ch) - find last occurrence of ch in string
+;
+;Purpose:
+; Finds the last occurrence of ch in string. The terminating
+; null character is used as part of the search.
+;
+; Algorithm:
+; char *
+; strrchr (string, ch)
+; char *string, ch;
+; {
+; char *start = string;
+;
+; while (*string++)
+; ;
+; while (--string != start && *string != ch)
+; ;
+; if (*string == ch)
+; return(string);
+; return(NULL);
+; }
+;
+;Entry:
+; char *string - string to search in
+; char ch - character to search for
+;
+;Exit:
+; returns a pointer to the last occurrence of ch in the given
+; string
+; returns NULL if ch does not occurr in the string
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strrchr
+strrchr proc \
+ uses edi, \
+ string:ptr byte, \
+ chr:byte
+
+ mov edi,[string] ; di = string
+ xor eax,eax ; al=null byte
+ or ecx,-1 ; cx = -1
+repne scasb ; find the null & count bytes
+ inc ecx ; cx=-byte count (with null)
+ neg ecx ; cx=+byte count (with null)
+ dec edi ; di points to terminal null
+ mov al,chr ; al=search byte
+ std ; count 'down' on string this time
+repne scasb ; find that byte
+ inc edi ; di points to byte which stopped scan
+
+ cmp [edi],al ; see if we have a hit
+ je short returndi ; yes, point to byte
+
+ xor eax,eax ; no, return NULL
+ jmp short toend ; do return sequence
+
+returndi:
+ mov eax,edi ; ax=pointer to byte
+
+toend:
+ cld
+
+ifdef _STDCALL_
+ ret DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strrchr endp
+ end
diff --git a/private/crt32/string/i386/strrev.asm b/private/crt32/string/i386/strrev.asm
new file mode 100644
index 000000000..09071834e
--- /dev/null
+++ b/private/crt32/string/i386/strrev.asm
@@ -0,0 +1,121 @@
+ page ,132
+ title strrev - reverse a string in place
+;***
+;strrev.asm - reverse a string in place
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strrev() - reverse a string in place (not including
+; '\0' character)
+;
+;Revision History:
+; 10-26-83 RN initial version
+; 07-16-87 JCR Added check for empty string (fixes large model bug)
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup, minor alterations
+; 10-26-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strrev(string) - reverse a string in place
+;
+;Purpose:
+; Reverses the order of characters in the string. The terminating
+; null character remains in place.
+;
+; Algorithm:
+; char *
+; _strrev (string)
+; char *string;
+; {
+; char *start = string;
+; char *left = string;
+; char ch;
+;
+; while (*string++)
+; ;
+; string -= 2;
+; while (left < string)
+; {
+; ch = *left;
+; *left++ = *string;
+; *string-- = ch;
+; }
+; return(start);
+; }
+;
+; NOTE: There is a check for an empty string in the following code.
+; Normally, this would fall out of the "cmp si,di" instruction in the
+; loop portion of the routine. However, if the offset of the empty
+; string is 0 (as it could be in large model), then the cmp does not
+; catch the empty string and the routine essentially hangs (i.e., loops
+; moving bytes one at a time FFFFh times). An explicit empty string
+; check corrects this.
+;
+;Entry:
+; char *string - string to reverse
+;
+;Exit:
+; returns string - now with reversed characters
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strrev
+_strrev proc \
+ uses edi esi, \
+ string:ptr byte
+
+ mov edi,[string] ; di = string
+ mov edx,edi ; dx=pointer to string; save return value
+
+ mov esi,edi ; si=pointer to string
+ xor eax,eax ; search value (null)
+ or ecx,-1 ; cx = -1
+repne scasb ; find null
+ cmp ecx,-2 ; is string empty? (if offset value is 0, the
+ je short done ; cmp below will not catch it and we'll hang).
+
+ dec edi ; string is not empty, move di pointer back
+ dec edi ; di points to last non-null byte
+
+lupe:
+ cmp esi,edi ; see if pointers have crossed yet
+ jae short done ; exit when pointers meet (or cross)
+
+ mov ah,[esi] ; get front byte...
+ mov al,[edi] ; and end byte
+ mov [esi],al ; put end byte in front...
+ mov [edi],ah ; and front byte at end
+ inc esi ; front moves up...
+ dec edi ; and end moves down
+ jmp short lupe ; keep switching bytes
+
+done:
+ mov eax,edx ; return value: string addr
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strrev endp
+ end
diff --git a/private/crt32/string/i386/strset.asm b/private/crt32/string/i386/strset.asm
new file mode 100644
index 000000000..8446a0812
--- /dev/null
+++ b/private/crt32/string/i386/strset.asm
@@ -0,0 +1,93 @@
+ page ,132
+ title strset - set all characters of string to character
+;***
+;strset.asm - sets all charcaters of string to given character
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines _strset() - sets all of the characters in a string (except
+; the '\0') equal to a given character.
+;
+;Revision History:
+; 11-18-83 RN initial version
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-23-88 JCR 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strset(string, val) - sets all of string to val
+;
+;Purpose:
+; Sets all of characters in string (except the terminating '/0'
+; character) equal to val.
+;
+; Algorithm:
+; char *
+; _strset (string, val)
+; char *string;
+; char val;
+; {
+; char *start = string;
+;
+; while (*string)
+; *string++ = val;
+; return(start);
+; }
+;
+;Entry:
+; char *string - string to modify
+; char val - value to fill string with
+;
+;Exit:
+; returns string -- now filled with val's
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strset
+_strset proc \
+ uses edi, \
+ string:ptr byte, \
+ val:byte
+
+
+ mov edi,[string] ; di = string
+ mov edx,edi ; dx=string addr; save return value
+
+ xor eax,eax ; ax = 0
+ or ecx,-1 ; cx = -1
+repne scasb ; scan string & count bytes
+ inc ecx
+ inc ecx ; cx=-strlen
+ neg ecx ; cx=strlen
+ mov al,[val] ; al = byte value to store
+ mov edi,edx ; di=string addr
+rep stosb
+
+ mov eax,edx ; return value: string addr
+
+ifdef _STDCALL_
+ ret DPSIZE + ISIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strset endp
+ end
diff --git a/private/crt32/string/i386/strspn.asm b/private/crt32/string/i386/strspn.asm
new file mode 100644
index 000000000..803e4a223
--- /dev/null
+++ b/private/crt32/string/i386/strspn.asm
@@ -0,0 +1,277 @@
+ page ,132
+ title strspn - search for init substring of chars from control str
+;***
+;strspn.asm - find length of initial substring of chars from a control string
+;
+; Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strspn() - finds the length of the initial substring of
+; a string consisting entirely of characters from a control string.
+;
+; defines strcspn()- finds the length of the initial substring of
+; a string consisting entirely of characters not in a control string.
+;
+; defines strpbrk()- finds the index of the first character in a string
+; that is not in a control string
+;
+;Revision History:
+; 10-28-83 RN initial version
+; 06-30-87 SKS Faster version -- also reentrant
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-02-88 SJM Created 386-specific version.
+; 08-23-88 JCR 386 cleanup
+; 10-10-88 JCR Misc bug fixes
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+; 09-25-91 JCR Build "strspn" if no other directives are given
+; 01-17-92 GJF Fixed build of "strspn".
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;int strspn(string, control) - find init substring of control chars
+;
+;Purpose:
+; Finds the index of the first character in string that does belong
+; to the set of characters specified by control. This is
+; equivalent to the length of the initial substring of string that
+; consists entirely of characters from control. The '\0' character
+; that terminates control is not considered in the matching process.
+;
+; Algorithm:
+; int
+; strspn (string, control)
+; unsigned char *string, *control;
+; {
+; unsigned char map[32];
+; int count;
+;
+; for (count = 0; count < 32; count++)
+; map[count] = 0;
+; while (*control)
+; {
+; map[*control >> 3] |= (1 << (*control & 7));
+; control++;
+; }
+; if (*string)
+; {
+; while (map[*string >> 3] & (1 << (*string & 7)))
+; {
+; count++;
+; string++;
+; }
+; return(count);
+; }
+; return(0);
+; }
+;
+;Entry:
+; char *string - string to search
+; char *control - string containing characters not to search for
+;
+;Exit:
+; returns index of first char in string not in control
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+;***
+;int strcspn(string, control) - search for init substring w/o control chars
+;
+;Purpose:
+; returns the index of the first character in string that belongs
+; to the set of characters specified by control. This is equivalent
+; to the length of the length of the initial substring of string
+; composed entirely of characters not in control. Null chars not
+; considered.
+;
+; Algorithm:
+; int
+; strcspn (string, control)
+; unsigned char *string, *control;
+; {
+; unsigned char map[32];
+; int count;
+;
+; for (count = 0; count < 32; count++)
+; map[count] = 0;
+; while (*control)
+; {
+; map[*control >> 3] |= (1 << (*control & 7));
+; control++;
+; }
+; map[0] |= 1;
+; while (!(map[*string >> 3] & (1 << (*string & 7))))
+; {
+; count++;
+; string++;
+; }
+; return(count);
+; }
+;
+;Entry:
+; char *string - string to search
+; char *control - set of characters not allowed in init substring
+;
+;Exit:
+; returns the index of the first char in string
+; that is in the set of characters specified by control.
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+;***
+;char *strpbrk(string, control) - scans string for a character from control
+;
+;Purpose:
+; Finds the first occurence in string of any character from
+; the control string.
+;
+; Algorithm:
+; char *
+; strpbrk (string, control)
+; unsigned char *string, *control;
+; {
+; unsigned char map[32];
+; int count;
+;
+; for (count = 0; count < 32; count++)
+; map[count] = 0;
+; while (*control)
+; {
+; map[*control >> 3] |= (1 << (*control & 7));
+; control++;
+; }
+; while (*string)
+; {
+; if (map[*string >> 3] & (1 << (*string & 7)))
+; return(string);
+; string++;
+; }
+; return(NULL);
+; }
+;
+;Entry:
+; char *string - string to search in
+; char *control - string containing characters to search for
+;
+;Exit:
+; returns a pointer to the first character from control found
+; in string.
+; returns NULL if string and control have no characters in common.
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+
+ifdef SSTRCSPN
+
+ _STRSPN_ equ <strcspn>
+
+elseifdef SSTRPBRK
+
+ _STRSPN_ equ <strpbrk>
+
+else
+
+; Default is to build strspn()
+
+ SSTRSPN equ 1
+ _STRSPN_ equ <strspn>
+
+endif
+
+% public _STRSPN_
+
+ CODESEG
+
+_STRSPN_ proc \
+ uses edi esi, \
+ string:ptr byte, \
+ control:ptr byte
+
+ local map[8]:dword ; 8*4*8 = 256 bits
+
+; Zero out char bit map
+
+ mov ecx, 8 ; clear the 256 bits
+ xor eax, eax
+ lea edi, [map]
+rep stosd
+
+; Set control char bits in map
+
+ mov esi,control ; si = control string
+
+ align @WordSize
+lab listnext ; init char bit map
+ lodsb
+ or al,al
+ jz short listdone
+ bts map, eax
+ jmp short listnext
+
+lab listdone
+
+; Loop through comparing source string with control bits
+
+ mov esi, string ; si = string
+
+_ifnd SSTRPBRK <dec ecx> ; set ecx to -1
+
+ align @WordSize
+lab dstnext
+
+_ifnd SSTRPBRK <inc ecx>
+
+ lodsb
+ or al,al
+ jz short dstdone
+ bt map, eax
+
+ifdef SSTRSPN
+ jc short dstnext ; strspn: found char, continue
+elseifdef SSTRCSPN
+ jnc short dstnext ; strcspn: did not find char, continue
+elseifdef SSTRPBRK
+ jnc short dstnext ; strpbrk: did not find char, continue
+ lea eax,[esi-1] ; found char, return address of it
+ jmp short done
+endif
+
+; Return code
+
+lab dstdone
+
+ifndef SSTRPBRK
+ mov eax,ecx ; strspn/strcspn: return index
+else
+ xor eax,eax ; strpbrk: no chars in common, return NULL
+done:
+
+endif
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_STRSPN_ endp
+ end
diff --git a/private/crt32/string/i386/strstr.asm b/private/crt32/string/i386/strstr.asm
new file mode 100644
index 000000000..81a9b76bd
--- /dev/null
+++ b/private/crt32/string/i386/strstr.asm
@@ -0,0 +1,135 @@
+ page ,132
+ title strstr - search for one string inside another
+;***
+;strstr.asm - search for one string inside another
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; defines strstr() - search for one string inside another
+;
+;Revision History:
+; 02-02-88 SKS Rewritten from scratch. Now works correctly with
+; strings > 32 KB in length. Also smaller and faster.
+; 03-01-88 SKS Ensure that ES = DS right away (Small/Medium models)
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-18-88 PHG Corrected return value when src is empty string
+; to conform with ANSI.
+; 08-23-88 JCR Minor 386 cleanup
+; 10-26-88 JCR General cleanup for 386-only code
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *strstr(string1, string2) - search for string2 in string1
+;
+;Purpose:
+; finds the first occurrence of string2 in string1
+;
+;Entry:
+; char *string1 - string to search in
+; char *string2 - string to search for
+;
+;Exit:
+; returns a pointer to the first occurrence of string2 in
+; string1, or NULL if string2 does not occur in string1
+;
+;Uses:
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public strstr
+strstr proc \
+ uses esi edi ebx, \
+ dst:ptr byte, \
+ src:ptr byte
+
+ local srclen:IWORD
+
+
+ mov edi, (src) ; di = src
+ xor eax,eax ; Scan for null at end of (src)
+ or ecx,-1 ; cx = -1
+repnz scasb
+ not ecx
+ dec ecx
+ jecxz short empty_src ; src == "" ?
+ dec ecx ; CX = strlen(src)-1
+ mov (srclen),ecx
+
+ mov edi,(dst)
+ mov ebx,edi ; BX will keep the current offset into (dst)
+
+ xor eax,eax ; Scan for null at end of (dst)
+ or ecx,-1 ; cx = -1
+repnz scasb
+ not ecx
+ dec ecx ; CX = strlen(dst)
+
+ mov edx,ecx ; Save strlen(dst) in DX
+
+ sub edx,(srclen) ; DX = strlen(dst) - (strlen(src)-1)
+ jbe short not_found ; strlen(dst) <= (strlen(src)-1)
+ ; target is longer than source?
+ mov edi,ebx ; restore ES:DI = (dst)
+
+findnext:
+ mov esi,IWORD ptr (src)
+ lodsb ; Get the first byte of the source
+ mov edi,ebx ; restore position in source
+ mov ecx,edx ; count of possible starting bytes in src
+;
+; CX, DX = number of bytes left in source where target can still fit
+; DI, BX = current position in (dst)
+; DS:SI = (src) + 1
+; AL = *(src)
+;
+
+repne scasb ; find next occurrence of *(target) in dst
+ jne short not_found ; out of string -- return NULL
+
+ mov edx,ecx ; update count of acceptable bytes left in dst
+ mov ebx,edi ; save current offset in dst
+
+ mov ecx,(srclen)
+ jecxz short match ; single character src string?
+
+repe cmpsb
+ jne short findnext
+
+;
+; Match! Return (BX-1)
+;
+match:
+ lea eax,[ebx-1]
+ jmp short retval
+
+empty_src: ; empty src string, return dst (ANSI mandated)
+ mov eax,(dst) ; eax = dst
+ jmp short retval ; return
+
+not_found:
+ xor eax,eax
+
+retval:
+
+ifdef _STDCALL_
+ ret 2*DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+strstr endp
+ end
diff --git a/private/crt32/string/i386/strupr.asm b/private/crt32/string/i386/strupr.asm
new file mode 100644
index 000000000..c8b66243f
--- /dev/null
+++ b/private/crt32/string/i386/strupr.asm
@@ -0,0 +1,104 @@
+ page ,132
+ title strupr - map string to upper-case
+;***
+;strupr.asm - routine to map lower-case characters in a string to upper-case
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; _strupr() converts lower-case characters in a null-terminated string
+; to their upper-case equivalents. Conversion is done in place and
+; characters other than lower-case letters are not modified.
+;
+; This function modifies only 7-bit ASCII characters
+; in the range 0x61 through 0x7A ('a' through 'z').
+;
+;Revision History:
+; 04-21-87 SKS Rewritten to be fast and small, added file header
+; 05-18-88 SJM Add model-independent (large model) ifdef
+; 08-04-88 SJM convert to cruntime/ add 32-bit support
+; 08-19-88 JCR Minor optimization
+; 10-10-88 JCR Changed an 'xchg' to 'mov'
+; 10-26-88 JCR General cleanup for 386-only code
+; 10-26-88 JCR Re-arrange regs to avoid push/pop ebx
+; 03-26-90 GJF Changed to _stdcall. Also, fixed the copyright.
+; 01-18-91 GJF ANSI naming.
+; 05-10-91 GJF Back to _cdecl, sigh...
+;
+;*******************************************************************************
+
+ .xlist
+ include cruntime.inc
+ .list
+
+page
+;***
+;char *_strupr(string) - map lower-case characters in a string to upper-case
+;
+;Purpose:
+; Converts all the lower case characters in string to upper case
+; in place.
+;
+; Algorithm:
+; char * _strupr (char * string)
+; {
+; char * cp = string;
+;
+; while( *cp )
+; {
+; if ('a' <= *cp && *cp <= 'z')
+; *cp += 'A' - 'a';
+; ++cp;
+; }
+; return(string);
+; }
+;
+;Entry:
+; char *string - string to change to upper case
+;
+;Exit:
+; The input string address is returned in AX or DX:AX
+;
+;Uses:
+; BX, CX, DX
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+ public _strupr
+_strupr proc \
+ string:ptr byte
+
+
+ mov ecx,[string] ; cx = *string
+ mov edx,ecx ; save return value
+ jmp short first_char; jump into the loop
+
+ align @WordSize
+check_char:
+ sub al,'a' ; 'a' <= al <= 'z' ?
+ cmp al,'z'-'a'+1
+ jnb short next_char
+ add al,'A' ; map to upper case
+ mov [ecx],al ; and store new value
+next_char:
+ inc ecx ; bump pointer
+first_char:
+ mov al,[ecx] ; get next character
+ or al,al
+ jnz short check_char
+
+done:
+ mov eax,edx ; ax = return value ("string")
+
+ifdef _STDCALL_
+ ret DPSIZE ; _stdcall return
+else
+ ret ; _cdecl return
+endif
+
+_strupr endp
+ end
diff --git a/private/crt32/string/makefile b/private/crt32/string/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/string/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/string/makefile.inc b/private/crt32/string/makefile.inc
new file mode 100644
index 000000000..84afc0560
--- /dev/null
+++ b/private/crt32/string/makefile.inc
@@ -0,0 +1,9 @@
+strcspn.c: strspn.c
+
+strpbrk.c: strspn.c
+
+i386\memmove.asm: i386\memcpy.asm
+
+i386\strcspn.asm: i386\strspn.asm
+
+i386\strpbrk.asm: i386\strspn.asm
diff --git a/private/crt32/string/memccpy.c b/private/crt32/string/memccpy.c
new file mode 100644
index 000000000..2fd8f63cd
--- /dev/null
+++ b/private/crt32/string/memccpy.c
@@ -0,0 +1,59 @@
+/***
+*memccpy.c - copy bytes until a character is found
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _memccpy() - copies bytes until a specifed character
+* is found, or a maximum number of characters have been copied.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright. Also, fixed compiler warning.
+* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant
+* #include <stddef.h>
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 01-17-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *_memccpy(dest, src, c, count) - copy bytes until character found
+*
+*Purpose:
+* Copies bytes from src to dest until count bytes have been
+* copied, or up to and including the character c, whichever
+* comes first.
+*
+*Entry:
+* void *dest - pointer to memory to receive copy
+* void *src - source of bytes
+* int c - character to stop copy at
+* unsigned int count - max number of bytes to copy
+*
+*Exit:
+* returns pointer to byte immediately after c in dest
+* returns NULL if c was never found
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 _memccpy (
+ void * dest,
+ const void * src,
+ int c,
+ unsigned count
+ )
+{
+ while ( count && (*((char *)(dest = (char *)dest + 1) - 1) =
+ *((char *)(src = (char *)src + 1) - 1)) != (char)c )
+ count--;
+
+ return(count ? dest : NULL);
+}
diff --git a/private/crt32/string/memchr.c b/private/crt32/string/memchr.c
new file mode 100644
index 000000000..b79097e79
--- /dev/null
+++ b/private/crt32/string/memchr.c
@@ -0,0 +1,57 @@
+/***
+*memchr.c - search block of memory for a given character
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines memchr() - search memory until a character is
+* found or a limit is reached.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant
+* #include <stddef.h>
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 04-26-91 SRW Removed level 3 warnings
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *memchr(buf, chr, cnt) - search memory for given character.
+*
+*Purpose:
+* Searches at buf for the given character, stopping when chr is
+* first found or cnt bytes have been searched through.
+*
+*Entry:
+* void *buf - memory buffer to be searched
+* int chr - character to search for
+* size_t cnt - max number of bytes to search
+*
+*Exit:
+* returns pointer to first occurence of chr in buf
+* returns NULL if chr not found in the first cnt bytes
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 memchr (
+ const void * buf,
+ int chr,
+ size_t cnt
+ )
+{
+ while ( cnt && *(char *)buf != (char)chr ) {
+ buf = (char *)buf + 1;
+ cnt--;
+ }
+
+ return(cnt ? (void *)buf : NULL);
+}
diff --git a/private/crt32/string/memcmp.c b/private/crt32/string/memcmp.c
new file mode 100644
index 000000000..478ecabab
--- /dev/null
+++ b/private/crt32/string/memcmp.c
@@ -0,0 +1,65 @@
+/***
+*memcmp.c - compare two blocks of memory
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines memcmp() - compare two memory blocks lexically and
+* find their order.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(memcmp)
+#endif /* ndef _CRUISER_ */
+
+/***
+*int memcmp(buf1, buf2, count) - compare memory for lexical order
+*
+*Purpose:
+* Compares count bytes of memory starting at buf1 and buf2
+* and find if equal or which one is first in lexical order.
+*
+*Entry:
+* void *buf1, *buf2 - pointers to memory sections to compare
+* size_t count - length of sections to compare
+*
+*Exit:
+* returns < 0 if buf1 < buf2
+* returns 0 if buf1 == buf2
+* returns > 0 if buf1 > buf2
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 memcmp (
+ const void * buf1,
+ const void * buf2,
+ size_t count
+ )
+{
+ if (!count)
+ return(0);
+
+ while ( --count && *(char *)buf1 == *(char *)buf2 ) {
+ buf1 = (char *)buf1 + 1;
+ buf2 = (char *)buf2 + 1;
+ }
+
+ return( *((unsigned char *)buf1) - *((unsigned char *)buf2) );
+}
diff --git a/private/crt32/string/memcpy.c b/private/crt32/string/memcpy.c
new file mode 100644
index 000000000..a4348e74e
--- /dev/null
+++ b/private/crt32/string/memcpy.c
@@ -0,0 +1,80 @@
+/***
+*memcpy.c - contains memcpy routine
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All right reserved.
+*
+*Purpose:
+* memcpy() copies a source memory buffer to a destination buffer.
+* Overlapping buffers are not treated specially, so propogation may occur.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 04-05-91 GJF Speed up for large buffers by moving int-sized chunks
+* as much as possible.
+* 08-06-91 GJF Backed out 04-05-91 change. Pointers would have to be
+* dword-aligned for this to work on MIPS.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#ifdef _MSC_VER
+#pragma function(memcpy)
+#endif
+
+/***
+*memcpy - Copy source buffer to destination buffer
+*
+*Purpose:
+* memcpy() copies a source memory buffer to a destination memory buffer.
+* This routine does NOT recognize overlapping buffers, and thus can lead
+* to propogation.
+*
+* For cases where propogation must be avoided, memmove() must be used.
+*
+*Entry:
+* void *dst = pointer to destination buffer
+* const void *src = pointer to source buffer
+* size_t count = number of bytes to copy
+*
+*Exit:
+* Returns a pointer to the destination buffer
+*
+*Exceptions:
+*******************************************************************************/
+
+void * _CALLTYPE1 memcpy (
+ void * dst,
+ const void * src,
+ size_t count
+ )
+{
+ void * ret = dst;
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+ {
+ extern void RtlMoveMemory( void *, const void *, size_t count );
+
+ RtlMoveMemory( dst, src, count );
+ }
+#else
+ /*
+ * copy from lower addresses to higher addresses
+ */
+ while (count--) {
+ *(char *)dst = *(char *)src;
+ dst = (char *)dst + 1;
+ src = (char *)src + 1;
+ }
+#endif
+
+ return(ret);
+}
diff --git a/private/crt32/string/memicmp.c b/private/crt32/string/memicmp.c
new file mode 100644
index 000000000..d38bf717f
--- /dev/null
+++ b/private/crt32/string/memicmp.c
@@ -0,0 +1,77 @@
+/***
+*memicmp.c - compare memory, ignore case
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _memicmp() - compare two blocks of memory for lexical
+* order. Case is ignored in the comparison.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright. Also, fixed compiler warnings.
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 01-17-91 GJF ANSI naming.
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+* 06-28-94 SRW Rewrite to use same ANSI specific tolower logic as x86
+* assembler version is i386\memicmp.asm
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+#include <string.h>
+
+/***
+*int _memicmp(first, last, count) - compare two blocks of memory, ignore case
+*
+*Purpose:
+* Compares count bytes of the two blocks of memory stored at first
+* and last. The characters are converted to lowercase before
+* comparing (not permanently), so case is ignored in the search.
+*
+*Entry:
+* char *first, *last - memory buffers to compare
+* unsigned count - maximum length to compare
+*
+*Exit:
+* returns < 0 if first < last
+* returns 0 if first == last
+* returns > 0 if first > last
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _memicmp (
+ const void * first,
+ const void * last,
+ unsigned int count
+ )
+{
+ unsigned char f,l;
+
+ if (count) do {
+ f = *((const char *)first)++;
+ l = *((const char *)last)++;
+ if (f != l) {
+ if (f>='A' && f<='Z') {
+ f = f - 'A' + 'a';
+ }
+ if (l>='A' && l<='Z') {
+ l = l - 'A' + 'a';
+ }
+ if (f!=l) {
+ return f-l;
+ }
+ }
+ }
+ while (--count);
+
+ return 0;
+}
diff --git a/private/crt32/string/memmove.c b/private/crt32/string/memmove.c
new file mode 100644
index 000000000..efb0ab9b3
--- /dev/null
+++ b/private/crt32/string/memmove.c
@@ -0,0 +1,93 @@
+/***
+*memmove.c - contains memmove routine
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All right reserved.
+*
+*Purpose:
+* memmove() copies a source memory buffer to a destination buffer.
+* Overlapping buffers are treated specially, to avoid propogation.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 04-09-91 GJF Speed up a little for large buffers.
+* 08-06-91 GJF Backed out 04-09-91 change. Pointers would have to be
+* dword-aligned for this to work on MIPS.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_M_ALPHA)
+#pragma function(memmove)
+#endif
+
+/***
+*memmove - Copy source buffer to destination buffer
+*
+*Purpose:
+* memmove() copies a source memory buffer to a destination memory buffer.
+* This routine recognize overlapping buffers to avoid propogation.
+* For cases where propogation is not a problem, memcpy() can be used.
+*
+*Entry:
+* void *dst = pointer to destination buffer
+* const void *src = pointer to source buffer
+* size_t count = number of bytes to copy
+*
+*Exit:
+* Returns a pointer to the destination buffer
+*
+*Exceptions:
+*******************************************************************************/
+
+void * _CALLTYPE1 memmove (
+ void * dst,
+ const void * src,
+ size_t count
+ )
+{
+ void * ret = dst;
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+ {
+ extern void RtlMoveMemory( void *, const void *, size_t count );
+
+ RtlMoveMemory( dst, src, count );
+ }
+#else
+ if (dst <= src || (char *)dst >= ((char *)src + count)) {
+ /*
+ * Non-Overlapping Buffers
+ * copy from lower addresses to higher addresses
+ */
+ while (count--) {
+ *(char *)dst = *(char *)src;
+ dst = (char *)dst + 1;
+ src = (char *)src + 1;
+ }
+ }
+ else {
+ /*
+ * Overlapping Buffers
+ * copy from higher addresses to lower addresses
+ */
+ dst = (char *)dst + count - 1;
+ src = (char *)src + count - 1;
+
+ while (count--) {
+ *(char *)dst = *(char *)src;
+ dst = (char *)dst - 1;
+ src = (char *)src - 1;
+ }
+ }
+#endif
+
+ return(ret);
+}
diff --git a/private/crt32/string/memset.c b/private/crt32/string/memset.c
new file mode 100644
index 000000000..5a04554a9
--- /dev/null
+++ b/private/crt32/string/memset.c
@@ -0,0 +1,70 @@
+/***
+*memset.c - set a section of memory to all one byte
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains the memset() routine
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-01-90 GJF New-style function declarator. Also, rewrote expr. to
+* avoid using cast as an lvalue.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#ifdef _MSC_VER
+#pragma function(memset)
+#endif
+
+/***
+*char *memset(dst, val, count) - sets "count" bytes at "dst" to "val"
+*
+*Purpose:
+* Sets the first "count" bytes of the memory starting
+* at "dst" to the character value "val".
+*
+*Entry:
+* void *dst - pointer to memory to fill with val
+* int val - value to put in dst bytes
+* size_t count - number of bytes of dst to fill
+*
+*Exit:
+* returns dst, with filled bytes
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 memset (
+ void *dst,
+ int val,
+ size_t count
+ )
+{
+ void *start = dst;
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+ {
+ extern void RtlFillMemory( void *, size_t count, char );
+
+ RtlFillMemory( dst, count, (char)val );
+ }
+#else
+ while (count--) {
+ *(char *)dst = (char)val;
+ dst = (char *)dst + 1;
+ }
+#endif
+
+ return(start);
+}
diff --git a/private/crt32/string/mips/memcmpm.s b/private/crt32/string/mips/memcmpm.s
new file mode 100644
index 000000000..961939432
--- /dev/null
+++ b/private/crt32/string/mips/memcmpm.s
@@ -0,0 +1,125 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+#ident "$Header"
+
+/*
+ * Copyright 1985 by MIPS Computer Systems, Inc.
+ */
+
+/* bcmp(s1, s2, n) */
+
+#include "kxmips.h"
+
+/*
+ * bcmp(src, dst, bcount)
+ *
+ * MINCMP is minimum number of byte that its worthwhile to try and
+ * align cmp into word transactions
+ *
+ * Calculating MINCMP
+ * Overhead =~ 15 instructions => 90 cycles
+ * Byte cmp =~ 38 cycles/word
+ * Word cmp =~ 17 cycles/word
+ * Breakeven =~ 16 bytes
+ */
+#define MINCMP 16
+#define NBPW 4
+
+LEAF_ENTRY(memcmp)
+ xor v0,a0,a1
+ blt a2,MINCMP,bytecmp # too short, just byte cmp
+ and v0,NBPW-1
+ subu t8,zero,a0 # number of bytes til aligned
+ bne v0,zero,unalgncmp # src and dst not alignable
+/*
+ * src and dst can be simultaneously word aligned
+ */
+ and t8,NBPW-1
+ subu a2,t8
+ beq t8,zero,wordcmp # already aligned
+ move v0,v1 # lw[lr] don't clear target reg
+ lwr v0,0(a0)
+ lwr v1,0(a1)
+ addu a0,t8
+ addu a1,t8
+ bne v0,v1,cmpne
+
+/*
+ * word cmp loop
+ */
+wordcmp:
+ and a3,a2,~(NBPW-1)
+ subu a2,a3
+ beq a3,zero,bytecmp
+ addu a3,a0 # src1 endpoint
+1: lw v0,0(a0)
+ lw v1,0(a1)
+ addu a0,NBPW # 1st BDSLOT
+ addu a1,NBPW # 2nd BDSLOT (asm doesn't move)
+ bne v0,v1,cmpne
+ bne a0,a3,1b # at least one more word
+ b bytecmp
+
+/*
+ * deal with simultaneously unalignable cmp by aligning one src
+ */
+unalgncmp:
+ subu a3,zero,a1 # calc byte cnt to get src2 aligned
+ and a3,NBPW-1
+ subu a2,a3
+ beq a3,zero,partaligncmp # already aligned
+ addu a3,a0 # src1 endpoint
+1: lbu v0,0(a0)
+ lbu v1,0(a1)
+ addu a0,1
+ addu a1,1
+ bne v0,v1,cmpne
+ bne a0,a3,1b
+
+/*
+ * src unaligned, dst aligned loop
+ */
+partaligncmp:
+ and a3,a2,~(NBPW-1)
+ subu a2,a3
+ beq a3,zero,bytecmp
+ addu a3,a0
+1:
+ lwr v0,0(a0)
+ lwl v0,3(a0)
+ lw v1,0(a1)
+ addu a0,NBPW
+ addu a1,NBPW
+ bne v0,v1,cmpne
+ bne a0,a3,1b
+
+/*
+ * brute force byte cmp loop
+ */
+bytecmp:
+ addu a3,a2,a0 # src1 endpoint; BDSLOT
+ ble a2,zero,cmpdone
+1: lbu v0,0(a0)
+ lbu v1,0(a1)
+ addu a0,1
+ addu a1,1
+ bne v0,v1,cmpne
+ bne a0,a3,1b
+cmpdone:
+ move v0,zero
+ j ra
+
+cmpne:
+ sltu a2,v1,v0
+ bne a2,zero,9f
+ li v0,-1
+ j ra
+9:
+ li v0,1
+ j ra
+.end bcmp
diff --git a/private/crt32/string/mips/memcmpt.c b/private/crt32/string/mips/memcmpt.c
new file mode 100644
index 000000000..3adb427b9
--- /dev/null
+++ b/private/crt32/string/mips/memcmpt.c
@@ -0,0 +1,334 @@
+/*
+ * Test memcpy() function.
+ */
+
+char buffer[100];
+#include <stdio.h>
+#include <memory.h>
+
+#define FALSE 0
+#define TRUE 1
+
+#define NTUL 7
+#define TEST16 4
+#define TEST32 8
+
+#define BUFSIZE 256
+
+void printbuf(char *identifier, char *buf, int length)
+{
+ int i;
+ printf("%s = '", identifier);
+ for (i = 0; i < length; i++)
+ printf("%c", buf[i]);
+ printf("'\n");
+}
+
+void main()
+{
+ int i, j, n, k, l;
+ int rc;
+ char *s1, *s2;
+
+ char TavEqFailed = FALSE;
+ char TvaEqFailed = FALSE;
+ char TavltFailed = FALSE;
+ char TvaltFailed = FALSE;
+ char TavgtFailed = FALSE;
+ char TvagtFailed = FALSE;
+
+ char TvveqFailed = FALSE;
+ char TvvltFailed = FALSE;
+ char TvvgtFailed = FALSE;
+
+ int Tmisc = 0;
+
+ unsigned long source1_16[TEST16] = {
+ 0x00003000,
+ 0x30003000,
+ 0x30003000,
+ 0x36003000
+ };
+
+ unsigned long source2_16[TEST16] = {
+ 0x00003000,
+ 0x30003000,
+ 0x30003000,
+ 0x00000000
+ };
+
+ unsigned long tul[NTUL] = {
+ 0x35004600,
+ 0x37004600,
+ 0x36002f00,
+ 0x37002f00,
+ 0x30004600,
+ 0x30003000,
+ 0x36003000
+ };
+ int tul_test[NTUL] = {
+ -1,
+ -1,
+ +1,
+ +1,
+ -1,
+ +1,
+ 0
+ };
+
+ struct {
+ double dummy;
+ char source1[BUFSIZE];
+ char source2[BUFSIZE];
+ } buffer;
+
+ char source32[32] = "0X0042036C 002477CD BREAK 0x91DF";
+ char source[BUFSIZE];
+
+ for (j = 0; j < BUFSIZE; ) {
+ for (i = 0; i <= j % 32; i++, j++) {
+ buffer.source1[j] = source32[i];
+ buffer.source2[j] = source32[i];
+ }
+ }
+
+ j = BUFSIZE;
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ while (j--) {
+ if (*s1++ != *s2++) {
+ printf("\n\nbuffer.source1 != buffer.source2, exiting test!!!\n");
+ exit(-1);
+ }
+ }
+
+ if (memcmp(buffer.source1, buffer.source2, BUFSIZE) != 0) {
+ printf("\n\tbuffer.source1 != buffer.source2, exiting test!!!\n");
+ exit(-1);
+ }
+
+ /* Test for zero length */
+ for (i = 0; i < BUFSIZE; i++ ) {
+ int l;
+
+ s1 = &(buffer.source1[i]);
+ s2 = &(buffer.source2[i]);
+ l = 0;
+ rc = memcmp(s1, s2, l);
+ if (rc) {
+ printf("%s, line #%d: Zero length test failed!!!\n", __FILE__, __LINE__);
+ break;
+ }
+ }
+
+
+ for (k = BUFSIZE; k > 0; k-- ) {
+ for (n = 0; n < k; n++) {
+ char c;
+ int l;
+ int m;
+
+ /* Test with aligned start and variable end */
+ if (!TavEqFailed) {
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ l = k;
+ rc = memcmp(s1, s2, l);
+ if (rc != 0) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte aligned block equal test failed!!!\n", __FILE__, __LINE__, k);
+ TavEqFailed = TRUE;
+ }
+ }
+
+ /* Test with variable start and aligned end */
+ if (!TvaEqFailed) {
+ s1 = &(buffer.source1[n]);
+ s2 = &(buffer.source2[n]);
+ l = k - n;
+ rc = memcmp(s1, s2, l);
+ if (rc != 0) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte unaligned block equal test failed!!!\n", __FILE__, __LINE__, k);
+ TvaEqFailed = TRUE;
+ }
+ }
+
+ /* Test with aligned start and variable end */
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ l = k - n;
+ for (m = 0; m < l && !TavltFailed; m++) {
+ c = s1[m];
+ s1[m] -= 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != -1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte aligned block less than test failed!!!\n", __FILE__, __LINE__, k);
+ TavltFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+
+ /* Test with variable start and aligned end */
+ s1 = &(buffer.source1[n]);
+ s2 = &(buffer.source2[n]);
+ l = k - n;
+ for (m = 0; m < l && !TvaltFailed; m++) {
+ c = s1[m];
+ s1[m] -= 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != -1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte unaligned block less than test failed!!!\n", __FILE__, __LINE__, k);
+ TvaltFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+
+ /* Test with aligned start and variable end */
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ l = k - n;
+ for (m = 0; m < l && !TavgtFailed; m++) {
+ c = s1[m];
+ s1[m] += 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != 1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte aligned block greater than test failed!!!\n", __FILE__, __LINE__, k);
+ TavgtFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+
+ /* Test with variable start and aligned end */
+ s1 = &(buffer.source1[n]);
+ s2 = &(buffer.source2[n]);
+ l = k - n;
+ for (m = 0; m < l && !TvagtFailed; m++) {
+ c = s1[m];
+ s1[m] += 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != 1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte unaligned block greater than test failed!!!\n", __FILE__, __LINE__, k);
+ TvagtFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+ }
+ }
+
+ for (k = BUFSIZE; k > 0; k-- ) {
+ for (n = 0; n < k/2; n++) {
+ char c;
+ int m;
+
+ /* Test equal with variable start and end */
+ if (!TvveqFailed) {
+ l = k - 2*n;
+ s1 = &(buffer.source1[n]);
+ s2 = &(buffer.source2[n]);
+ rc = memcmp(s1, s2, l);
+ if (rc != 0) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte variable block equal test failed!!!\n", __FILE__, __LINE__, l);
+ TvveqFailed = TRUE;
+ }
+ }
+
+ /* Test less than with variable start and end */
+ l = k - 2*n;
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ for (m = 0; m < l && !TvvltFailed; m++) {
+ c = s1[m];
+ s1[m] -= 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != -1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte variable block less than test failed!!!\n", __FILE__, __LINE__, l);
+ TvvltFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+
+ /* Test greater than with variable start and end */
+ l = k - 2*n;
+ s1 = buffer.source1;
+ s2 = buffer.source2;
+ for (m = 0; m < l && !TvvgtFailed; m++) {
+ c = s1[m];
+ s1[m] += 1;
+ rc = memcmp(s1, s2, l);
+ if (rc != 1) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: %d byte variable block greater than test failed!!!\n", __FILE__, __LINE__, l);
+ TvvgtFailed = TRUE;
+ }
+ s1[m] = c;
+ }
+ }
+ }
+
+
+ /* Misc test1 */
+ for (k = 0; k < NTUL; k++) {
+
+ source2_16[3] = tul[k];
+
+ rc = memcmp(source1_16,source2_16,TEST16*sizeof(unsigned long));
+ if (rc != tul_test[k]) {
+
+ printf("source1_16 = ");
+ for (i = 0; i < TEST16*sizeof(unsigned long); i++)
+ printf("%2.2x ", ((char *)source1_16)[i]);
+ printf("\n");
+
+ printf("source2_16 = ");
+ for (i = 0; i < TEST16*sizeof(unsigned long); i++)
+ printf("%2.2x ", ((char *)source2_16)[i]);
+ printf("%s, line #%d: Misc Test #1, case #%d of %d failed!!!\n", __FILE__, __LINE__, k+1, NTUL);
+ printf("Return Code = %d, Should be = %d\n",rc,tul_test[k]);
+ Tmisc++;
+ }
+ }
+
+
+ /* Misc test2 */
+ l = 32;
+ buffer.source2[0] = '"';
+ for (i = 0; i < l; i++) {
+ buffer.source1[i] = source32[i];
+ buffer.source2[i+1] = source32[i];
+ }
+ buffer.source2[l+1] = '"';
+ s1 = &(buffer.source1[0]);
+ s2 = &(buffer.source2[1]);
+ if (0 != memcmp(s1, s2, l)) {
+ printbuf("source1", s1, l);
+ printbuf("source2", s2, l);
+ printf("%s, line #%d: Misc Test #2 failed!!!\n", __FILE__, __LINE__);
+ Tmisc++;
+ }
+
+
+ rc = TavEqFailed + TvaEqFailed + TavltFailed + TvaltFailed + TavgtFailed + TvagtFailed + TvveqFailed + TvvltFailed + TvvgtFailed + Tmisc;
+ if (rc) {
+ printf("\n\tMEMCMP failed %d tests!!!\n", rc);
+ exit(rc);
+ } else {
+ printf("\n\tMEMCMP passed all tests!!!\n");
+ exit(0);
+ }
+}
diff --git a/private/crt32/string/mips/memcpym.s b/private/crt32/string/mips/memcpym.s
new file mode 100644
index 000000000..ca0f8fe78
--- /dev/null
+++ b/private/crt32/string/mips/memcpym.s
@@ -0,0 +1,298 @@
+/*
+ * Fast bcopy code which supports overlapped copies.
+ * Not fully optimized yet.
+ *
+ * Written by: Kipp Hickman
+ *
+ * $Source: /proj/sherwood/isms/irix/lib/libc/src/strings/RCS/bcopy.s,v $
+ * $Revision: 1.7 $
+ * $Date: 1993/11/20 19:23:11 $
+ */
+
+#include <kxmips.h>
+
+/*
+ * char *bcopy(from, to, count);
+ * unsigned char *from, *to;
+ * unsigned long count;
+ *
+ * OR
+ *
+ * void *memcpy/memmove(to, from, count);
+ * void *to, *from;
+ * unsigned long count;
+ *
+ * Both functions return "to"
+ */
+
+#define MINCOPY 16
+
+/* registers used */
+
+#define to a0
+#define from a1
+#define count a2
+
+LEAF_ENTRY(memcpy)
+ALTERNATE_ENTRY(memmove)
+ move a3,to # Save to in a3
+ beq count,zero,ret # Test for zero count
+ beq from,to,ret # Test for from == to
+
+ /* use backwards copying code if the from and to regions overlap */
+ blt to,from,goforwards # If to < from then use forwards copy
+ add v0,from,count # v0 := from + count
+ bge to,v0,goforwards # If to >= from + count; no overlap
+ b gobackwards # Oh well, go backwards
+
+/*****************************************************************************/
+
+/*
+ * Forward copy code. Check for pointer alignment and try to get both
+ * pointers aligned on a long boundary.
+ */
+goforwards:
+ /* small byte counts use byte at a time copy */
+ blt count,MINCOPY,forwards_bytecopy
+ and v0,from,3 # v0 := from & 3
+ and v1,to,3 # v1 := to & 3
+ beq v0,v1,forwalignable # low bits are identical
+/*
+ * Byte at a time copy code. This is used when the pointers are not
+ * alignable, when the byte count is small, or when cleaning up any
+ * remaining bytes on a larger transfer.
+ */
+forwards_bytecopy:
+ beq count,zero,ret # If count is zero, then we are done
+ addu v1,from,count # v1 := from + count
+
+99: lb v0,0(from) # v0 = *from
+ addu from,1 # advance pointer
+ sb v0,0(to) # Store byte
+ addu to,1 # advance pointer
+ bne from,v1,99b # Loop until done
+ret: move v0,a3 # Set v0 to old "to" pointer
+ j ra # return to caller
+
+/*
+ * Pointers are alignable, and may be aligned. Since v0 == v1, we need only
+ * check what value v0 has to see how to get aligned. Also, since we have
+ * eliminated tiny copies, we know that the count is large enough to
+ * encompass the alignment copies.
+ */
+forwalignable:
+ beq v0,zero,forwards # If v0==v1 && v0==0 then aligned
+ beq v0,1,forw_copy3 # Need to copy 3 bytes to get aligned
+ beq v0,2,forw_copy2 # Need to copy 2 bytes to get aligned
+
+/* need to copy 1 byte */
+ lb v0,0(from) # get one byte
+ addu from,1 # advance pointer
+ sb v0,0(to) # store one byte
+ addu to,1 # advance pointer
+ subu count,1 # and reduce count
+ b forwards # Now pointers are aligned
+
+/* need to copy 2 bytes */
+forw_copy2:
+ lh v0,0(from) # get one short
+ addu from,2 # advance pointer
+ sh v0,0(to) # store one short
+ addu to,2 # advance pointer
+ subu count,2 # and reduce count
+ b forwards
+
+/* need to copy 3 bytes */
+forw_copy3:
+ lb v0,0(from) # get one byte
+ lh v1,1(from) # and one short
+ addu from,3 # advance pointer
+ sb v0,0(to) # store one byte
+ sh v1,1(to) # and one short
+ addu to,3 # advance pointer
+ subu count,3 # and reduce count
+ /* FALLTHROUGH */
+/*
+ * Once we are here, the pointers are aligned on long boundaries.
+ * Begin copying in large chunks.
+ */
+forwards:
+
+/* 32 byte at a time loop */
+forwards_32:
+ blt count,32,forwards_16 # do 16 bytes at a time
+ lw v0,0(from)
+ lw v1,4(from)
+ lw t0,8(from)
+ lw t1,12(from)
+ lw t2,16(from)
+ lw t3,20(from)
+ lw t4,24(from)
+ lw t5,28(from) # Fetch 8*4 bytes
+ addu from,32 # advance from pointer now
+ sw v0,0(to)
+ sw v1,4(to)
+ sw t0,8(to)
+ sw t1,12(to)
+ sw t2,16(to)
+ sw t3,20(to)
+ sw t4,24(to)
+ sw t5,28(to) # Store 8*4 bytes
+ addu to,32 # advance to pointer now
+ subu count,32 # Reduce count
+ b forwards_32 # Try some more
+
+/* 16 byte at a time loop */
+forwards_16:
+ blt count,16,forwards_4 # Do rest in words
+ lw v0,0(from)
+ lw v1,4(from)
+ lw t0,8(from)
+ lw t1,12(from)
+ addu from,16 # advance from pointer now
+ sw v0,0(to)
+ sw v1,4(to)
+ sw t0,8(to)
+ sw t1,12(to)
+ addu to,16 # advance to pointer now
+ subu count,16 # Reduce count
+ b forwards_16 # Try some more
+
+/* 4 bytes at a time loop */
+forwards_4:
+ blt count,4,forwards_bytecopy # Do rest
+ lw v0,0(from)
+ addu from,4 # advance pointer
+ sw v0,0(to)
+ addu to,4 # advance pointer
+ subu count,4
+ b forwards_4
+
+/*****************************************************************************/
+
+/*
+ * Backward copy code. Check for pointer alignment and try to get both
+ * pointers aligned on a long boundary.
+ */
+gobackwards:
+ add from,count # Advance to end + 1
+ add to,count # Advance to end + 1
+
+ /* small byte counts use byte at a time copy */
+ blt count,MINCOPY,backwards_bytecopy
+ and v0,from,3 # v0 := from & 3
+ and v1,to,3 # v1 := to & 3
+ beq v0,v1,backalignable # low bits are identical
+/*
+ * Byte at a time copy code. This is used when the pointers are not
+ * alignable, when the byte count is small, or when cleaning up any
+ * remaining bytes on a larger transfer.
+ */
+backwards_bytecopy:
+ beq count,zero,ret # If count is zero quit
+ subu from,1 # Reduce by one (point at byte)
+ subu to,1 # Reduce by one (point at byte)
+ subu v1,from,count # v1 := original from - 1
+
+99: lb v0,0(from) # v0 = *from
+ subu from,1 # backup pointer
+ sb v0,0(to) # Store byte
+ subu to,1 # backup pointer
+ bne from,v1,99b # Loop until done
+ move v0,a3 # Set v0 to old "to" pointer
+ j ra # return to caller
+
+/*
+ * Pointers are alignable, and may be aligned. Since v0 == v1, we need only
+ * check what value v0 has to see how to get aligned. Also, since we have
+ * eliminated tiny copies, we know that the count is large enough to
+ * encompass the alignment copies.
+ */
+backalignable:
+ beq v0,zero,backwards # If v0==v1 && v0==0 then aligned
+ beq v0,3,back_copy3 # Need to copy 3 bytes to get aligned
+ beq v0,2,back_copy2 # Need to copy 2 bytes to get aligned
+
+/* need to copy 1 byte */
+ lb v0,-1(from) # get one byte
+ subu from,1 # backup pointer
+ sb v0,-1(to) # store one byte
+ subu to,1 # backup pointer
+ subu count,1 # and reduce count
+ b backwards # Now pointers are aligned
+
+/* need to copy 2 bytes */
+back_copy2:
+ lh v0,-2(from) # get one short
+ subu from,2 # backup pointer
+ sh v0,-2(to) # store one short
+ subu to,2 # backup pointer
+ subu count,2 # and reduce count
+ b backwards
+
+/* need to copy 3 bytes */
+back_copy3:
+ lb v0,-1(from) # get one byte
+ lh v1,-3(from) # and one short
+ subu from,3 # backup pointer
+ sb v0,-1(to) # store one byte
+ sh v1,-3(to) # and one short
+ subu to,3 # backup pointer
+ subu count,3 # and reduce count
+ /* FALLTHROUGH */
+/*
+ * Once we are here, the pointers are aligned on long boundaries.
+ * Begin copying in large chunks.
+ */
+backwards:
+
+/* 32 byte at a time loop */
+backwards_32:
+ blt count,32,backwards_16 # do 16 bytes at a time
+ lw v0,-4(from)
+ lw v1,-8(from)
+ lw t0,-12(from)
+ lw t1,-16(from)
+ lw t2,-20(from)
+ lw t3,-24(from)
+ lw t4,-28(from)
+ lw t5,-32(from) # Fetch 8*4 bytes
+ subu from,32 # backup from pointer now
+ sw v0,-4(to)
+ sw v1,-8(to)
+ sw t0,-12(to)
+ sw t1,-16(to)
+ sw t2,-20(to)
+ sw t3,-24(to)
+ sw t4,-28(to)
+ sw t5,-32(to) # Store 8*4 bytes
+ subu to,32 # backup to pointer now
+ subu count,32 # Reduce count
+ b backwards_32 # Try some more
+
+/* 16 byte at a time loop */
+backwards_16:
+ blt count,16,backwards_4 # Do rest in words
+ lw v0,-4(from)
+ lw v1,-8(from)
+ lw t0,-12(from)
+ lw t1,-16(from)
+ subu from,16 # backup from pointer now
+ sw v0,-4(to)
+ sw v1,-8(to)
+ sw t0,-12(to)
+ sw t1,-16(to)
+ subu to,16 # backup to pointer now
+ subu count,16 # Reduce count
+ b backwards_16 # Try some more
+
+/* 4 byte at a time loop */
+backwards_4:
+ blt count,4,backwards_bytecopy # Do rest
+ lw v0,-4(from)
+ subu from,4 # backup from pointer
+ sw v0,-4(to)
+ subu to,4 # backup to pointer
+ subu count,4 # Reduce count
+ b backwards_4
+.end memcpy
diff --git a/private/crt32/string/mips/memorym.s b/private/crt32/string/mips/memorym.s
new file mode 100644
index 000000000..6f98423dc
--- /dev/null
+++ b/private/crt32/string/mips/memorym.s
@@ -0,0 +1,1218 @@
+// TITLE("Compare, Move, and Fill Memory Support")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+//
+// Module Name:
+//
+// memory.s
+//
+// Abstract:
+//
+// This module implements functions to compare, move, zero, and fill
+// blocks of memory. If the memory is aligned, then these functions
+// are very efficient.
+//
+// N.B. These routines MUST preserve all floating state since they are
+// frequently called from interrupt service routines that normally
+// do not save or restore floating state.
+//
+// Author:
+//
+// David N. Cutler (davec) 11-Apr-1990
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+// 02/02/94 RDL This is a cloned version of ntos\rtl\mips\xxmvmem.s
+// Used RtlMoveMemory and RtlFillMemory.
+// 02/15/94 RDL Used RtlCompareMemory, changed return code for memcmp.
+// 02/22/94 RDL Fixed memcmp, zero length and equal aligned 32-byte
+// buffers return wrong code.
+//
+//--
+
+#include "ksmips.h"
+ SBTTL("Compare Memory")
+
+//++
+//
+// ULONG
+// RtlCompareMemory (
+// IN PVOID Source1,
+// IN PVOID Source2,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function compares two blocks of memory and returns the number
+// of bytes that compared equal.
+//
+// Arguments:
+//
+// Source1 (a0) - Supplies a pointer to the first block of memory to
+// compare.
+//
+// Source2 (a1) - Supplies a pointer to the second block of memory to
+// compare.
+//
+// Length (a2) - Supplies the length, in bytes, of the memory to be
+// compared.
+//
+// Return Value:
+//
+// zero if source1 == source2
+// -1 if source1 < source2
+// 1 if source1 > source2
+// value. If all bytes compared equal, then the length of the orginal
+// block of memory is returned.
+//
+//--
+
+ LEAF_ENTRY(memcmp)
+
+ addu a3,a0,a2 // compute ending address of source1
+ move v0,a2 // save length of comparison
+ and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t4,a0,t1 // compute ending block address
+ beq zero,t1,100f // if eq, no 32-byte block to compare
+ or t0,a0,a1 // merge and isolate alignment bits
+ and t0,t0,0x3 //
+ bne zero,t0,CompareUnaligned // if ne, unalignment comparison
+
+//
+// Compare memory aligned.
+//
+
+CompareAligned: //
+
+ .set noreorder
+10: lw t0,0(a0) // compare 32-byte block
+ lw t1,0(a1) //
+ lw t2,4(a0) //
+ bne t0,t1,90f // if ne, first word not equal
+ lw t3,4(a1) //
+ lw t0,8(a0) //
+ bne t2,t3,20f // if ne, second word not equal
+ lw t1,8(a1) //
+ lw t2,12(a0) //
+ bne t0,t1,30f // if ne, third word not equal
+ lw t3,12(a1) //
+ lw t0,16(a0) //
+ bne t2,t3,40f // if ne, fourth word not equal
+ lw t1,16(a1) //
+ lw t2,20(a0) //
+ bne t0,t1,50f // if ne, fifth word not equal
+ lw t3,20(a1) //
+ lw t0,24(a0) //
+ bne t2,t3,60f // if ne, sixth word not equal
+ lw t1,24(a1) //
+ lw t2,28(a0) //
+ bne t0,t1,70f // if ne, seventh word not equal
+ lw t3,28(a1) //
+ addu a0,a0,32 // advance source1 to next block
+ bne t2,t3,80f // if ne, eighth word not equal
+ nop //
+ bne a0,t4,10b // if ne, more 32-byte blocks to compare
+ addu a1,a1,32 // update source2 address
+ .set reorder
+
+ subu a2,a3,a0 // compute remaining bytes
+ b 100f //
+
+//
+// Compare memory unaligned.
+//
+
+CompareUnaligned: //
+ and t0,a0,0x3 // isolate source1 alignment
+ bne zero,t0,CompareUnalignedS1 // if ne, source1 unaligned
+
+//
+// Source1 is aligned and Source2 is unaligned.
+//
+
+CompareUnalignedS2: //
+
+ .set noreorder
+10: lw t0,0(a0) // compare 32-byte block
+ lwr t1,0(a1) //
+ lwl t1,3(a1) //
+ lw t2,4(a0) //
+ bne t0,t1,90f // if ne, first word not equal
+ lwr t3,4(a1) //
+ lwl t3,7(a1) //
+ lw t0,8(a0) //
+ bne t2,t3,20f // if ne, second word not equal
+ lwr t1,8(a1) //
+ lwl t1,11(a1) //
+ lw t2,12(a0) //
+ bne t0,t1,30f // if ne, third word not equal
+ lwr t3,12(a1) //
+ lwl t3,15(a1) //
+ lw t0,16(a0) //
+ bne t2,t3,40f // if ne, fourth word not equal
+ lwr t1,16(a1) //
+ lwl t1,19(a1) //
+ lw t2,20(a0) //
+ bne t0,t1,50f // if ne, fifth word not equal
+ lwr t3,20(a1) //
+ lwl t3,23(a1) //
+ lw t0,24(a0) //
+ bne t2,t3,60f // if ne, sixth word not equal
+ lwr t1,24(a1) //
+ lwl t1,27(a1) //
+ lw t2,28(a0) //
+ bne t0,t1,70f // if ne, seventh word not equal
+ lwr t3,28(a1) //
+ lwl t3,31(a1) //
+ addu a0,a0,32 // advance source1 to next block
+ bne t2,t3,80f // if ne, eighth word not equal
+ nop //
+ bne a0,t4,10b // if ne, more 32-byte blocks to compare
+ addu a1,a1,32 // update source2 address
+ .set reorder
+
+ subu a2,a3,a0 // compute remaining bytes
+ b 100f //
+
+//
+// Source1 is unaligned, check Source2 alignment.
+//
+
+CompareUnalignedS1: //
+ and t0,a1,0x3 // isolate Source2 alignment
+ bne zero,t0,CompareUnalignedS1AndS2 // if ne, Source2 unaligned
+
+//
+// Source1 is unaligned and Source2 is aligned.
+//
+
+ .set noreorder
+10: lwr t0,0(a0) // compare 32-byte block
+ lwl t0,3(a0) //
+ lw t1,0(a1) //
+ lwr t2,4(a0) //
+ lwl t2,7(a0) //
+ bne t0,t1,90f // if ne, first word not equal
+ lw t3,4(a1) //
+ lwr t0,8(a0) //
+ lwl t0,11(a0) //
+ bne t2,t3,20f // if ne, second word not equal
+ lw t1,8(a1) //
+ lwr t2,12(a0) //
+ lwl t2,15(a0) //
+ bne t0,t1,30f // if ne, third word not equal
+ lw t3,12(a1) //
+ lwr t0,16(a0) //
+ lwl t0,19(a0) //
+ bne t2,t3,40f // if ne, fourth word not equal
+ lw t1,16(a1) //
+ lwr t2,20(a0) //
+ lwl t2,23(a0) //
+ bne t0,t1,50f // if ne, fifth word not equal
+ lw t3,20(a1) //
+ lwr t0,24(a0) //
+ lwl t0,27(a0) //
+ bne t2,t3,60f // if ne, sixth word not equal
+ lw t1,24(a1) //
+ lwr t2,28(a0) //
+ lwl t2,31(a0) //
+ bne t0,t1,70f // if ne, seventh word not equal
+ lw t3,28(a1) //
+ addu a0,a0,32 // advance source1 to next block
+ bne t2,t3,80f // if ne, eighth word not equal
+ nop //
+ bne a0,t4,10b // if ne, more 32-byte blocks to compare
+ addu a1,a1,32 // update source2 address
+ .set reorder
+
+ subu a2,a3,a0 // compute remaining bytes
+ b 100f //
+
+//
+// Source1 and Source2 are unaligned.
+//
+
+CompareUnalignedS1AndS2: //
+
+ .set noreorder
+10: lwr t0,0(a0) // compare 32-byte block
+ lwl t0,3(a0) //
+ lwr t1,0(a1) //
+ lwl t1,3(a1) //
+ lwr t2,4(a0) //
+ lwl t2,7(a0) //
+ bne t0,t1,90f // if ne, first word not equal
+ lwr t3,4(a1) //
+ lwl t3,7(a1) //
+ lwr t0,8(a0) //
+ lwl t0,11(a0) //
+ bne t2,t3,20f // if ne, second word not equal
+ lwr t1,8(a1) //
+ lwl t1,11(a1) //
+ lwr t2,12(a0) //
+ lwl t2,15(a0) //
+ bne t0,t1,30f // if ne, third word not equal
+ lwr t3,12(a1) //
+ lwl t3,15(a1) //
+ lwr t0,16(a0) //
+ lwl t0,19(a0) //
+ bne t2,t3,40f // if ne, fourth word not equal
+ lwr t1,16(a1) //
+ lwl t1,19(a1) //
+ lwr t2,20(a0) //
+ lwl t2,23(a0) //
+ bne t0,t1,50f // if ne, fifth word not equal
+ lwr t3,20(a1) //
+ lwl t3,23(a1) //
+ lwr t0,24(a0) //
+ lwl t0,27(a0) //
+ bne t2,t3,60f // if ne, sixth word not equal
+ lwr t1,24(a1) //
+ lwl t1,27(a1) //
+ lwr t2,28(a0) //
+ lwl t2,31(a0) //
+ bne t0,t1,70f // if ne, seventh word not equal
+ lwr t3,28(a1) //
+ lwl t3,31(a1) //
+ addu a0,a0,32 // advance source1 to next block
+ bne t2,t3,80f // if ne, eighth word not equal
+ nop //
+ bne a0,t4,10b // if ne, more 32-byte blocks to compare
+ addu a1,a1,32 // update source2 address
+ .set reorder
+
+ subu a2,a3,a0 // compute remaining bytes
+ b 100f //
+
+//
+// Adjust source1 and source2 pointers dependent on position of miscompare in
+// block.
+//
+
+20: addu a0,a0,4 // mismatch on second word
+ addu a1,a1,4 //
+ b 90f //
+
+30: addu a0,a0,8 // mismatch on third word
+ addu a1,a1,8 //
+ b 90f //
+
+40: addu a0,a0,12 // mistmatch on fourth word
+ addu a1,a1,12 //
+ b 90f //
+
+50: addu a0,a0,16 // mismatch on fifth word
+ addu a1,a1,16 //
+ b 90f //
+
+60: addu a0,a0,20 // mismatch on sixth word
+ addu a1,a1,20 //
+ b 90f //
+
+70: addu a0,a0,24 // mismatch on seventh word
+ addu a1,a1,24 //
+ b 90f //
+
+80: subu a0,a0,4 // mismatch on eighth word
+ addu a1,a1,28 //
+90: subu a2,a3,a0 // compute remaining bytes
+
+//
+// Compare 1-byte blocks.
+//
+
+100: addu t2,a0,a2 // compute ending block address
+ beq zero,a2,120f // if eq, buffers equal
+110: lb t0,0(a0) // compare 1-byte block
+ lb t1,0(a1) //
+ addu a1,a1,1 // advance pointers to next block
+ bne t0,t1,130f // if ne, byte not equal
+ addu a0,a0,1 //
+ bne a0,t2,110b // if ne, more 1-byte block to zero
+
+120: move v0,zero // source1 == source2
+ j ra // return
+
+130: sltu v0,t1,t0 // compare source1 to source2
+ beq v0,zero,140f
+ j ra // return, source1 > source2
+140:
+ li v0,-1
+ j ra // return, source1 < source2
+
+ .end memcmp
+
+ SBTTL("Move Memory")
+//++
+//
+// VOID
+// RtlMoveMemory (
+// IN PVOID Destination,
+// IN PVOID Source,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function moves memory either forward or backward, aligned or
+// unaligned, in 32-byte blocks, followed by 4-byte blocks, followed
+// by any remaining bytes.
+//
+// Arguments:
+//
+// Destination (a0) - Supplies a pointer to the destination address of
+// the move operation.
+//
+// Source (a1) - Supplies a pointer to the source address of the move
+// operation.
+//
+// Length (a2) - Supplies the length, in bytes, of the memory to be moved.
+//
+// Return Value:
+//
+// None.
+//
+// N.B. The C runtime entry points memmove and memcpy are equivalent to
+// RtlMoveMemory thus alternate entry points are provided for these
+// routines.
+//--
+
+ LEAF_ENTRY(memmove)
+ j memcpy
+ .end memmove
+
+ LEAF_ENTRY(memcpy)
+
+ move v0,a0 // return destination
+
+//
+// If the source address is less than the destination address and source
+// address plus the length of the move is greater than the destination
+// address, then the source and destination overlap such that the move
+// must be performed backwards.
+//
+
+10: bgeu a1,a0,MoveForward // if geu, no overlap possible
+ addu t0,a1,a2 // compute source ending address
+ bgtu t0,a0,MoveBackward // if gtu, source and destination overlap
+
+//
+// Move memory forward aligned and unaligned.
+//
+
+MoveForward: //
+ sltu t0,a2,4 // check if less than four bytes
+ bne zero,t0,50f // if ne, less than four bytes to move
+ xor t0,a0,a1 // compare alignment bits
+ and t0,t0,0x3 // isolate alignment comparison
+ bne zero,t0,MoveForwardUnaligned // if ne, incompatible alignment
+
+//
+// Move memory forward aligned.
+//
+
+MoveForwardAligned: //
+ subu t0,zero,a0 // compute bytes until aligned
+ and t0,t0,0x3 // isolate residual byte count
+ subu a2,a2,t0 // reduce number of bytes to move
+ beq zero,t0,10f // if eq, already aligned
+ lwr t1,0(a1) // move unaligned bytes
+ swr t1,0(a0) //
+ addu a0,a0,t0 // align destination address
+ addu a1,a1,t0 // align source address
+
+//
+// Check for 32-byte blocks to move.
+//
+
+10: and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t8,a0,t1 // compute ending block address
+ beq zero,t1,30f // if eq, no 32-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 32-byte blocks.
+//
+
+#if defined(R4000)
+
+ and t0,a0,1 << 2 // check if destination quadword aligned
+ beq zero,t0,15f // if eq, destination quadword aligned
+ lw t0,0(a1) // get source longword
+ addu a1,a1,4 // align source address
+ sw t0,0(a0) // store destination longword
+ addu a0,a0,4 // align destination address
+ addu a2,a2,t1 // recompute bytes to move
+ subu a2,a2,4 // reduce count by 4
+ b 10b //
+
+//
+// The destination is quadword aligned, check the source operand.
+//
+
+15: and t0,a1,1 << 2 // check if source quadword aligned
+ beq zero,t0,22f // if eq, source quadword aligned
+
+//
+// The source is longword aligned and the destination is quadword aligned.
+//
+
+ .set noreorder
+20: lwc1 f0,0(a1) // move 32-byte block
+ lwc1 f1,4(a1) //
+ lwc1 f2,8(a1) //
+ lwc1 f3,12(a1) //
+ lwc1 f4,16(a1) //
+ lwc1 f5,20(a1) //
+ lwc1 f6,24(a1) //
+ lwc1 f7,28(a1) //
+ sdc1 f0,0(a0) //
+ sdc1 f2,8(a0) //
+ sdc1 f4,16(a0) //
+ sdc1 f6,24(a0) //
+ addu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ addu a1,a1,32 //
+ .set reorder
+
+ b 30f //
+
+//
+// Both the source and the destination are quadword aligned.
+//
+
+22: and t0,t1,1 << 5 // test if even number of 32-byte blocks
+ beq zero,t0,26f // if eq, even number of 32-byte blocks
+
+//
+// Move one 32-byte block quadword aligned.
+//
+
+ .set noreorder
+ ldc1 f0,0(a1) // move 32-byte block
+ ldc1 f2,8(a1) //
+ ldc1 f4,16(a1) //
+ ldc1 f6,24(a1) //
+ sdc1 f0,0(a0) //
+ sdc1 f2,8(a0) //
+ sdc1 f4,16(a0) //
+ sdc1 f6,24(a0) //
+ addu a0,a0,32 // advance pointers to next block
+ beq a0,t8,30f // if eq, end of block
+ addu a1,a1,32 //
+ .set reorder
+
+//
+// Move 64-byte blocks quadword aligned.
+//
+
+ .set noreorder
+26: ldc1 f0,0(a1) // move 64-byte block
+ ldc1 f2,8(a1) //
+ ldc1 f4,16(a1) //
+ ldc1 f6,24(a1) //
+ ldc1 f8,32(a1) //
+ ldc1 f10,40(a1) //
+ ldc1 f12,48(a1) //
+ ldc1 f14,56(a1) //
+ sdc1 f0,0(a0) //
+ sdc1 f2,8(a0) //
+ sdc1 f4,16(a0) //
+ sdc1 f6,24(a0) //
+ sdc1 f8,32(a0) //
+ sdc1 f10,40(a0) //
+ sdc1 f12,48(a0) //
+ sdc1 f14,56(a0) //
+ addu a0,a0,64 // advance pointers to next block
+ bne a0,t8,26b // if ne, more 64-byte blocks to zero
+ addu a1,a1,64 //
+ .set reorder
+
+#endif
+
+//
+// The source is longword aligned and the destination is longword aligned.
+//
+
+#if defined(R3000)
+
+ .set noreorder
+20: lw t0,0(a1) // move 32-byte block
+ lw t1,4(a1) //
+ lw t2,8(a1) //
+ lw t3,12(a1) //
+ lw t4,16(a1) //
+ lw t5,20(a1) //
+ lw t6,24(a1) //
+ lw t7,28(a1) //
+ sw t0,0(a0) //
+ sw t1,4(a0) //
+ sw t2,8(a0) //
+ sw t3,12(a0) //
+ sw t4,16(a0) //
+ sw t5,20(a0) //
+ sw t6,24(a0) //
+ sw t7,28(a0) //
+ addu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ addu a1,a1,32 //
+ .set reorder
+
+#endif
+
+//
+// Check for 4-byte blocks to move.
+//
+
+30: and t0,a2,4 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,50f // if eq, no 4-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 4-byte block.
+//
+
+ .set noreorder
+40: lw t0,0(a1) // move 4-byte block
+ addu a0,a0,4 // advance pointers to next block
+ sw t0,-4(a0) //
+ bne a0,t2,40b // if ne, more 4-byte blocks to zero
+ addu a1,a1,4 //
+ .set reorder
+
+//
+// Move 1-byte blocks.
+//
+
+50: addu t2,a0,a2 // compute ending block address
+ beq zero,a2,70f // if eq, no bytes to zero
+
+ .set noreorder
+60: lb t0,0(a1) // move 1-byte block
+ addu a0,a0,1 // advance pointers to next block
+ sb t0,-1(a0) //
+ bne a0,t2,60b // if ne, more 1-byte block to zero
+ addu a1,a1,1 //
+ .set reorder
+
+70: j ra // return
+
+//
+// Move memory forward unaligned.
+//
+
+MoveForwardUnaligned: //
+ subu t0,zero,a0 // compute bytes until aligned
+ and t0,t0,0x3 // isolate residual byte count
+ subu a2,a2,t0 // reduce number of bytes to move
+ beq zero,t0,10f // if eq, already aligned
+ lwr t1,0(a1) // move unaligned bytes
+ lwl t1,3(a1) //
+ swr t1,0(a0) //
+ addu a0,a0,t0 // align destination address
+ addu a1,a1,t0 // update source address
+
+//
+// Check for 32-byte blocks to move.
+//
+
+10: and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t8,a0,t1 // compute ending block address
+ beq zero,t1,30f // if eq, no 32-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 32-byte block.
+//
+
+ .set noreorder
+20: lwr t0,0(a1) // move 32-byte block
+ lwl t0,3(a1) //
+ lwr t1,4(a1) //
+ lwl t1,7(a1) //
+ lwr t2,8(a1) //
+ lwl t2,11(a1) //
+ lwr t3,12(a1) //
+ lwl t3,15(a1) //
+ lwr t4,16(a1) //
+ lwl t4,19(a1) //
+ lwr t5,20(a1) //
+ lwl t5,23(a1) //
+ lwr t6,24(a1) //
+ lwl t6,27(a1) //
+ lwr t7,28(a1) //
+ lwl t7,31(a1) //
+ sw t0,0(a0) //
+ sw t1,4(a0) //
+ sw t2,8(a0) //
+ sw t3,12(a0) //
+ sw t4,16(a0) //
+ sw t5,20(a0) //
+ sw t6,24(a0) //
+ sw t7,28(a0) //
+ addu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ addu a1,a1,32 //
+ .set reorder
+
+//
+// Check for 4-byte blocks to move.
+//
+
+30: and t0,a2,4 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,50f // if eq, no 4-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 4-byte block.
+//
+
+ .set noreorder
+40: lwr t0,0(a1) // move 4-byte block
+ lwl t0,3(a1) //
+ addu a0,a0,4 // advance pointers to next block
+ sw t0,-4(a0) //
+ bne a0,t2,40b // if ne, more 4-byte blocks to zero
+ addu a1,a1,4 //
+ .set reorder
+
+//
+// Move 1-byte blocks.
+//
+
+50: addu t2,a0,a2 // compute ending block address
+ beq zero,a2,70f // if eq, no bytes to zero
+
+ .set noreorder
+60: lb t0,0(a1) // move 1-byte block
+ addu a0,a0,1 // advance pointers to next block
+ sb t0,-1(a0) //
+ bne a0,t2,60b // if ne, more 1-byte block to zero
+ addu a1,a1,1 //
+ .set reorder
+
+70: j ra // return
+
+//
+// Move memory backward.
+//
+
+MoveBackward: //
+ addu a0,a0,a2 // compute ending destination address
+ addu a1,a1,a2 // compute ending source address
+ sltu t0,a2,4 // check if less than four bytes
+ bne zero,t0,50f // if ne, less than four bytes to move
+ xor t0,a0,a1 // compare alignment bits
+ and t0,t0,0x3 // isolate alignment comparison
+ bne zero,t0,MoveBackwardUnaligned // if ne, incompatible alignment
+
+//
+// Move memory backward aligned.
+//
+
+MoveBackwardAligned: //
+ and t0,a0,0x3 // isolate residual byte count
+ subu a2,a2,t0 // reduce number of bytes to move
+ beq zero,t0,10f // if eq, already aligned
+ lwl t1,-1(a1) // move unaligned bytes
+ swl t1,-1(a0) //
+ subu a0,a0,t0 // align destination address
+ subu a1,a1,t0 // align source address
+
+//
+// Check for 32-byte blocks to move.
+//
+
+10: and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ subu t8,a0,t1 // compute ending block address
+ beq zero,t1,30f // if eq, no 32-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 32-byte block.
+//
+
+#if defined(R4000)
+
+ and t0,a0,1 << 2 // check if destination quadword aligned
+ beq zero,t0,15f // if eq, destination quadword aligned
+ lw t0,-4(a1) // get source longword
+ subu a1,a1,4 // align source address
+ sw t0,-4(a0) // store destination longword
+ subu a0,a0,4 // align destination address
+ addu a2,a2,t1 // recompute byte to move
+ subu a2,a2,4 // reduce count by 4
+ b 10b //
+
+//
+// The destination is quadword aligned, check the source operand.
+//
+
+15: and t0,a1,1 << 2 // check if source quadword aligned
+ beq zero,t0,22f // if eq, source quadword aligned
+
+//
+// The source is longword aligned and the destination is quadword aligned.
+//
+
+ .set noreorder
+20: lwc1 f1,-4(a1) // move 32-byte block
+ lwc1 f0,-8(a1) //
+ lwc1 f3,-12(a1) //
+ lwc1 f2,-16(a1) //
+ lwc1 f5,-20(a1) //
+ lwc1 f4,-24(a1) //
+ lwc1 f7,-28(a1) //
+ lwc1 f6,-32(a1) //
+ sdc1 f0,-8(a0) //
+ sdc1 f2,-16(a0) //
+ sdc1 f4,-24(a0) //
+ sdc1 f6,-32(a0) //
+ subu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ subu a1,a1,32 //
+ .set reorder
+
+ b 30f //
+
+//
+// Both the source and the destination are quadword aligned.
+//
+
+22: and t0,t1,1 << 5 // test if even number of 32-byte blocks
+ beq zero,t0,26f // if eq, even number of 32-byte blocks
+
+//
+// Move one 32-byte block quadword aligned.
+//
+
+ .set noreorder
+ ldc1 f0,-8(a1) // move 32-byte block
+ ldc1 f2,-16(a1) //
+ ldc1 f4,-24(a1) //
+ ldc1 f6,-32(a1) //
+ sdc1 f0,-8(a0) //
+ sdc1 f2,-16(a0) //
+ sdc1 f4,-24(a0) //
+ sdc1 f6,-32(a0) //
+ subu a0,a0,32 // advance pointers to next block
+ beq a0,t8,30f // if eq, end of block
+ subu a1,a1,32 //
+ .set reorder
+
+//
+// Move 64-byte blocks quadword aligned.
+//
+
+ .set noreorder
+26: ldc1 f0,-8(a1) // move 64-byte block
+ ldc1 f2,-16(a1) //
+ ldc1 f4,-24(a1) //
+ ldc1 f6,-32(a1) //
+ ldc1 f8,-40(a1) //
+ ldc1 f10,-48(a1) //
+ ldc1 f12,-56(a1) //
+ ldc1 f14,-64(a1) //
+ sdc1 f0,-8(a0) //
+ sdc1 f2,-16(a0) //
+ sdc1 f4,-24(a0) //
+ sdc1 f6,-32(a0) //
+ sdc1 f8,-40(a0) //
+ sdc1 f10,-48(a0) //
+ sdc1 f12,-56(a0) //
+ sdc1 f14,-64(a0) //
+ subu a0,a0,64 // advance pointers to next block
+ bne a0,t8,26b // if ne, more 64-byte blocks to zero
+ subu a1,a1,64 //
+ .set reorder
+
+#endif
+
+//
+// The source is longword aligned and the destination is longword aligned.
+//
+
+#if defined(R3000)
+
+ .set noreorder
+20: lw t0,-4(a1) // move 32-byte block
+ lw t1,-8(a1) //
+ lw t2,-12(a1) //
+ lw t3,-16(a1) //
+ lw t4,-20(a1) //
+ lw t5,-24(a1) //
+ lw t6,-28(a1) //
+ lw t7,-32(a1) //
+ sw t0,-4(a0) //
+ sw t1,-8(a0) //
+ sw t2,-12(a0) //
+ sw t3,-16(a0) //
+ sw t4,-20(a0) //
+ sw t5,-24(a0) //
+ sw t6,-28(a0) //
+ sw t7,-32(a0) //
+ subu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ subu a1,a1,32 //
+ .set reorder
+
+#endif
+
+//
+// Check for 4-byte blocks to move.
+//
+
+30: and t0,a2,4 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ subu t2,a0,t1 // compute ending block address
+ beq zero,t1,50f // if eq, no 4-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 4-byte block.
+//
+
+ .set noreorder
+40: lw t0,-4(a1) // move 4-byte block
+ subu a0,a0,4 // advance pointers to next block
+ sw t0,0(a0) //
+ bne a0,t2,40b // if ne, more 4-byte blocks to zero
+ subu a1,a1,4 //
+ .set reorder
+
+//
+// Move 1-byte blocks.
+//
+
+50: subu t2,a0,a2 // compute ending block address
+ beq zero,a2,70f // if eq, no bytes to zero
+
+ .set noreorder
+60: lb t0,-1(a1) // move 1-byte block
+ subu a0,a0,1 // advance pointers to next block
+ sb t0,0(a0) //
+ bne a0,t2,60b // if ne, more 1-byte block to zero
+ subu a1,a1,1 //
+ .set reorder
+
+70: j ra // return
+
+//
+// Move memory backward unaligned.
+//
+
+MoveBackwardUnaligned: //
+ and t0,a0,0x3 // isolate residual byte count
+ subu a2,a2,t0 // reduce number of bytes to move
+ beq zero,t0,10f // if eq, already aligned
+ lwl t1,-1(a1) // move unaligned bytes
+ lwr t1,-4(a1) //
+ swl t1,-1(a0) //
+ subu a0,a0,t0 // align destination address
+ subu a1,a1,t0 // update source address
+
+//
+// Check for 32-byte blocks to move.
+//
+
+10: and t0,a2,32 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ subu t8,a0,t1 // compute ending block address
+ beq zero,t1,30f // if eq, no 32-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 32-byte block.
+//
+
+ .set noreorder
+20: lwr t0,-4(a1) // move 32-byte block
+ lwl t0,-1(a1) //
+ lwr t1,-8(a1) //
+ lwl t1,-5(a1) //
+ lwr t2,-12(a1) //
+ lwl t2,-9(a1) //
+ lwr t3,-16(a1) //
+ lwl t3,-13(a1) //
+ lwr t4,-20(a1) //
+ lwl t4,-17(a1) //
+ lwr t5,-24(a1) //
+ lwl t5,-21(a1) //
+ lwr t6,-28(a1) //
+ lwl t6,-25(a1) //
+ lwr t7,-32(a1) //
+ lwl t7,-29(a1) //
+ sw t0,-4(a0) //
+ sw t1,-8(a0) //
+ sw t2,-12(a0) //
+ sw t3,-16(a0) //
+ sw t4,-20(a0) //
+ sw t5,-24(a0) //
+ sw t6,-28(a0) //
+ sw t7,-32(a0) //
+ subu a0,a0,32 // advance pointers to next block
+ bne a0,t8,20b // if ne, more 32-byte blocks to zero
+ subu a1,a1,32 //
+ .set reorder
+
+//
+// Check for 4-byte blocks to move.
+//
+
+30: and t0,a2,4 - 1 // isolate residual bytes
+ subu t1,a2,t0 // subtract out residual bytes
+ subu t2,a0,t1 // compute ending block address
+ beq zero,t1,50f // if eq, no 4-byte block to zero
+ move a2,t0 // set residual number of bytes
+
+//
+// Move 4-byte block.
+//
+
+ .set noreorder
+40: lwr t0,-4(a1) // move 4-byte block
+ lwl t0,-1(a1) //
+ subu a0,a0,4 // advance pointers to next block
+ sw t0,0(a0) //
+ bne a0,t2,40b // if ne, more 4-byte blocks to zero
+ subu a1,a1,4 //
+ .set reorder
+
+//
+// Move 1-byte blocks.
+//
+
+50: subu t2,a0,a2 // compute ending block address
+ beq zero,a2,70f // if eq, no bytes to zero
+
+ .set noreorder
+60: lb t0,-1(a1) // move 1-byte block
+ subu a0,a0,1 // advance pointers to next block
+ sb t0,0(a0) //
+ bne a0,t2,60b // if ne, more 1-byte block to zero
+ subu a1,a1,1 //
+ .set reorder
+
+70: j ra // return
+
+ .end memcpy
+
+ SBTTL("Fill Memory")
+//++
+//
+// VOID
+// RtlFillMemory (
+// IN PVOID Destination,
+// IN ULONG Length,
+// IN UCHAR Fill
+// )
+//
+// Routine Description:
+//
+// This function fills memory by first aligning the destination address to
+// a longword boundary, and then filling 32-byte blocks, followed by 4-byte
+// blocks, followed by any remaining bytes.
+//
+// Arguments:
+//
+// Destination (a0) - Supplies a pointer to the memory to fill.
+//
+// Length (a1) - Supplies the length, in bytes, of the memory to be filled.
+//
+// Fill (a2) - Supplies the fill byte.
+//
+// N.B. The alternate entry memset expects the length and fill arguments
+// to be reversed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(memset)
+
+ move a3,a1 // swap length and fill arguments
+ move a1,a2 //
+ move a2,a3 //
+ move v0,a0 // return destination
+
+ and a2,a2,0xff // clear excess bits
+ sll t0,a2,8 // duplicate fill byte
+ or a2,a2,t0 // generate fill word
+ sll t0,a2,16 // duplicate fill word
+ or a2,a2,t0 // generate fill longword
+
+//
+// Fill memory with the pattern specified in register a2.
+//
+
+#if DBG
+
+ mtc1 a2,f0 // set pattern to store
+ mtc1 a2,f1 //
+
+#endif
+
+ subu t0,zero,a0 // compute bytes until aligned
+ and t0,t0,0x3 // isolate residual byte count
+ subu t1,a1,t0 // reduce number of bytes to fill
+ blez t1,60f // if lez, less than 4 bytes to fill
+ move a1,t1 // set number of bytes to fill
+ beq zero,t0,10f // if eq, already aligned
+ swr a2,0(a0) // fill unaligned bytes
+ addu a0,a0,t0 // align destination address
+
+//
+// Check for 32-byte blocks to fill.
+//
+
+10: and t0,a1,32 - 1 // isolate residual bytes
+ subu t1,a1,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,40f // if eq, no 32-byte blocks to fill
+ move a1,t0 // set residual number of bytes
+
+//
+// Fill 32-byte blocks.
+//
+
+#if defined(R4000)
+
+ and t0,a0,1 << 2 // check if destintion quadword aligned
+ beq zero,t0,20f // if eq, yes
+ sw a2,0(a0) // store destination longword
+ addu a0,a0,4 // align destination address
+ addu a1,a1,t1 // recompute bytes to fill
+ subu a1,a1,4 // reduce count by 4
+ b 10b //
+
+//
+// The destination is quadword aligned.
+//
+
+20: mtc1 a2,f0 // set pattern value
+ mtc1 a2,f1 //
+ and t0,t1,1 << 5 // test if even number of 32-byte blocks
+ beq zero,t0,30f // if eq, even number of 32-byte blocks
+
+//
+// Fill one 32-byte block.
+//
+
+ .set noreorder
+ sdc1 f0,0(a0) // fill 32-byte block
+ sdc1 f0,8(a0) //
+ sdc1 f0,16(a0) //
+ addu a0,a0,32 // advance pointer to next block
+ beq a0,t2,40f // if ne, no 64-byte blocks to fill
+ sdc1 f0,-8(a0) //
+ .set reorder
+
+//
+// Fill 64-byte block.
+//
+
+ .set noreorder
+30: sdc1 f0,0(a0) // fill 32-byte block
+ sdc1 f0,8(a0) //
+ sdc1 f0,16(a0) //
+ sdc1 f0,24(a0) //
+ sdc1 f0,32(a0) //
+ sdc1 f0,40(a0) //
+ sdc1 f0,48(a0) //
+ addu a0,a0,64 // advance pointer to next block
+ bne a0,t2,30b // if ne, more 32-byte blocks to fill
+ sdc1 f0,-8(a0) //
+ .set reorder
+
+#endif
+
+//
+// Fill 32-byte blocks.
+//
+
+#if defined(R3000)
+
+ .set noreorder
+20: sw a2,0(a0) // fill 32-byte block
+ sw a2,4(a0) //
+ sw a2,8(a0) //
+ sw a2,12(a0) //
+ addu a0,a0,32 // advance pointer to next block
+ sw a2,-4(a0) //
+ sw a2,-8(a0) //
+ sw a2,-12(a0) //
+ bne a0,t2,20b // if ne, more 32-byte blocks to fill
+ sw a2,-16(a0) //
+ .set reorder
+
+#endif
+
+//
+// Check for 4-byte blocks to fill.
+//
+
+40: and t0,a1,4 - 1 // isolate residual bytes
+ subu t1,a1,t0 // subtract out residual bytes
+ addu t2,a0,t1 // compute ending block address
+ beq zero,t1,60f // if eq, no 4-byte block to fill
+ move a1,t0 // set residual number of bytes
+
+//
+// Fill 4-byte blocks.
+//
+
+ .set noreorder
+50: addu a0,a0,4 // advance pointer to next block
+ bne a0,t2,50b // if ne, more 4-byte blocks to fill
+ sw a2,-4(a0) // fill 4-byte block
+ .set reorder
+
+//
+// Check for 1-byte blocks to fill.
+//
+
+60: addu t2,a0,a1 // compute ending block address
+ beq zero,a1,80f // if eq, no bytes to fill
+
+//
+// Fill 1-byte blocks.
+//
+
+ .set noreorder
+70: addu a0,a0,1 // advance pointer to next block
+ bne a0,t2,70b // if ne, more 1-byte block to fill
+ sb a2,-1(a0) // fill 1-byte block
+ .set reorder
+
+#if DBG
+
+80: mfc1 t0,f0 // get fill pattern
+ mfc1 t1,f1 //
+ bne t0,a2,90f // if ne, pattern altered
+ bne t1,a2,90f // if ne, pattern altered
+ j ra // return
+
+90: break KERNEL_BREAKPOINT //
+
+#else
+
+80: j ra // return
+
+#endif
+
+ .end memset
diff --git a/private/crt32/string/mips/memsetm.s b/private/crt32/string/mips/memsetm.s
new file mode 100644
index 000000000..a53f8f0a1
--- /dev/null
+++ b/private/crt32/string/mips/memsetm.s
@@ -0,0 +1,105 @@
+/* --------------------------------------------------- */
+/* | Copyright (c) 1986 MIPS Computer Systems, Inc. | */
+/* | All Rights Reserved. | */
+/* --------------------------------------------------- */
+/* $Revision: 1.3 $ */
+
+/*
+ * char *
+ * memset(s, c, n)
+ * register char * s;
+ * register c, n;
+ * {
+ * register char * p = s;
+ *
+ * while (--n >= 0)
+ * *s++ = c;
+ *
+ * return (p);
+ * }
+ */
+
+/*
+ * Copyright 1986 by MIPS Computer Systems, Inc.
+ */
+
+#include <kxmips.h>
+
+#define NBPW 4
+
+/*
+ * memset(dst, c, bcount)
+ * set block of memory with blanks
+ *
+ * Calculating MINSET, assuming 10% cache-miss on non-loop code:
+ * Overhead =~ 18 instructions => 28 (30) cycles
+ * Byte set =~ 12 (24) cycles/word for 08M44 (08V11)
+ * Word set =~ 3 (5) cycles/word for 08M44 (08V11)
+ * If I-cache-miss nears 0, MINSET ==> 4 bytes; otherwise, times are:
+ * breakeven (MEM) = 28 / (12 - 3) =~ 3 words
+ * breakeven (VME) = 30 / (24 - 5) =~ 1.5 words
+ * Since the overhead is pessimistic (worst-case alignment), and many calls
+ * will be for well-aligned data, and since Word-set at least leaves
+ * the set in the cache, we shade these values (6-12) down to 8 bytes
+ */
+#define MINSET 8
+
+/* It turns out better to think of lwl/lwr and swl/swr as
+ smaller-vs-bigger address rather than left-vs-right.
+ Such a representation makes the code endian-independent. */
+
+#define LWS lwr
+#define LWB lwl
+#define SWS swr
+#define SWB swl
+
+LEAF_ENTRY(memset)
+ move v0,a0 # return first argument; BDSLOT
+ blt a2,MINSET,byteset
+ subu v1,zero,a0 # number of bytes til aligned; BDSLOT
+ beq a1,$0,1f # make memset(s, 0, n) faster
+ sll t0,a1,8
+ or a1,t0
+ sll t0,a1,16
+ or a1,t0
+1: and v1,NBPW-1
+ subu a2,v1 # adjust count; BDSLOT
+ beq v1,zero,blkset # already aligned
+ SWS a1,0(a0)
+ addu a0,v1
+
+/*
+ * set 8 byte, aligned block (no point in unrolling further,
+ * since maximum write rate in M/500 is two cycles/word write)
+ */
+blkset:
+ and t0,a2,NBPW+NBPW-1 # count after by-8-byte loop done
+ subu a3,a2,t0 # total in 8 byte chunks; BDSLOT
+ beq a2,t0,wordset # less than 8 bytes to set
+ addu a3,a0 # dst endpoint
+1: addu a0,NBPW+NBPW
+ sw a1,-NBPW-NBPW(a0)
+ sw a1,-NBPW(a0)
+ bne a0,a3,1b
+ move a2,t0 # set end-of loop count
+
+/*
+ * do a word (if required) this is not a loop since loop above
+ * guarantees that at most one word must be written here.
+ */
+wordset:
+ and t0,a2,NBPW # count after by-word non-loop done
+ subu a2,t0 # adjust count; BDSLOT
+ beq t0,zero,byteset # less than word to set
+ sw a1,0(a0)
+ addu a0,NBPW
+
+byteset:
+ addu a3,a2,a0 # dst endpoint; BDSLOT
+ ble a2,zero,setdone
+1: addu a0,1
+ sb a1,-1(a0)
+ bne a0,a3,1b
+setdone:
+ j ra
+.end memset
diff --git a/private/crt32/string/mips/memsett.c b/private/crt32/string/mips/memsett.c
new file mode 100644
index 000000000..c653803ab
--- /dev/null
+++ b/private/crt32/string/mips/memsett.c
@@ -0,0 +1,20 @@
+char buffer[100];
+#include <stdio.h>
+#include <string.h>
+
+void main()
+{
+ char *f = buffer;
+ char *g = buffer;
+
+ printf("%8.8x\n", f);
+ f=(char*)memset(f,0x0a,12);
+ printf("%8.8x\n", f);
+
+ if (f == g) {
+ int k = 12;
+ while (k--)
+ printf("%2.2x", *f++);
+ }
+}
+
diff --git a/private/crt32/string/mips/strcatm.s b/private/crt32/string/mips/strcatm.s
new file mode 100644
index 000000000..0c22c47de
--- /dev/null
+++ b/private/crt32/string/mips/strcatm.s
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+/* strcat.s 1.1 */
+
+/* This function is an assembly-code replacement for the libc function
+ * strcat.
+
+ * strcat and strcpy are very similar, but we waste about 40 words of
+ * code when both are used, so that they can be independently replaced.
+
+ * There are one caveat to consider: this function is written in
+ * assembler code, and as such, cannot be merged using the U-code
+ * loader. */
+
+/* Craig Hansen - 3-September-86 */
+
+#include <kxmips.h>
+
+/* It turns out better to think of lwl/lwr and swl/swr as
+ smaller-vs-bigger address rather than left-vs-right.
+ Such a representation makes the code endian-independent. */
+
+#define LWS lwr
+#define LWB lwl
+#define SWS swr
+#define SWB swl
+
+.text
+
+LEAF_ENTRY(strcat)
+.set noreorder
+ // a0/ destination
+ // a1/ source
+ move v0, a0 # a copy of destination address is returned
+$findz: lb t0,0(a0)
+ nop
+ bne t0,0,$findz
+ add a0,1
+ // go back over null byte
+ add a0,-1
+ // start up first word
+ // adjust pointers so that a0 points to next word
+ // t7 = a1 adjusted by same amount minus one
+ // t0,t1,t2,t3 are filled with 4 consecutive bytes
+ // t4 is filled with the same 4 bytes in a single word
+ lb t0, 0(a1)
+ ori t5, a0, 3 # get an early start
+ beq t0, 0, $doch0
+ sub t6, t5, a0 # number of char in 1st word of dest - 1
+ lb t1, 1(a1)
+ add t7, a1, t6 # offset starting point for source string
+ beq t1, 0, $doch1
+ nop
+ lb t2, 2(a1)
+ nop
+ beq t2, 0, $doch2
+ LWS t4, 0(a1) # safe: always in same word as 0(a1)
+ lb t3, 3(a1)
+ LWB t4, 3(a1) # fill out word
+ beq t3, 0, $doch3
+ SWS t4, 0(a0) # store entire or part word
+ addi a0, t5, 1-4 # adjust destination ptr
+
+ // inner loop
+1: lb t0, 1(t7)
+ addi t7, 4
+ beq t0, 0, $doch0
+ addi a0, 4
+ lb t1, 1+1-4(t7)
+ nop
+ beq t1, 0, $doch1
+ nop
+ lb t2, 2+1-4(t7)
+ nop
+ beq t2, 0, $doch2
+ LWS t4, 0+1-4(t7)
+ lb t3, 3+1-4(t7)
+ LWB t4, 3+1-4(t7)
+ bne t3, 0, 1b
+ sw t4, 0(a0)
+ j ra
+ nop
+
+ // store four bytes using swl/swr
+$doch3: j ra
+ SWB t4, 3(a0)
+ // store up to three bytes, a byte at a time.
+$doch2: sb t2, 2(a0)
+$doch1: sb t1, 1(a0)
+$doch0: j ra
+ sb t0, 0(a0)
+
+.end strcat
diff --git a/private/crt32/string/mips/strchrm.s b/private/crt32/string/mips/strchrm.s
new file mode 100644
index 000000000..b92f79fd6
--- /dev/null
+++ b/private/crt32/string/mips/strchrm.s
@@ -0,0 +1,26 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+#ident "$Header: /disks/bits/5.1isms/irix/lib/libc/src/strings/RCS/index.s,v 1.3 1992/03/07 15:37:04 jleong Exp $"
+
+/*
+ * Copyright 1985 by MIPS Computer Systems, Inc.
+ */
+
+#include "kxmips.h"
+
+LEAF_ENTRY(strchr)
+1: lbu a2,0(a0)
+ addu a0,1
+ beq a2,a1,2f
+ bne a2,zero,1b
+ move v0,zero
+ j ra
+
+2: subu v0,a0,1
+ j ra
+.end strchr
diff --git a/private/crt32/string/mips/strchrt.c b/private/crt32/string/mips/strchrt.c
new file mode 100644
index 000000000..1da4e1d0d
--- /dev/null
+++ b/private/crt32/string/mips/strchrt.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+void main( int argc, char **argv )
+ {
+ int c;
+ unsigned char *pstr;
+ unsigned char string[100];
+
+ strcpy(string, "ABCDEFGHIJKLMNOPQRST");
+ for (c = 'a'; c <= UCHAR_MAX; c++)
+ {
+ string[9] = c;
+ pstr = strchr( string, c);
+ if (!pstr)
+ printf("Fail - Could not find %d in %s\n", c, string);
+ }
+ return;
+ }
diff --git a/private/crt32/string/mips/strcmpm.s b/private/crt32/string/mips/strcmpm.s
new file mode 100644
index 000000000..dfaaa9c39
--- /dev/null
+++ b/private/crt32/string/mips/strcmpm.s
@@ -0,0 +1,50 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+/* strcmp.s 1.1 */
+
+/* This function is an assembly-code replacement for
+ the libc function "strcmp." */
+/* Libc currently has a mips-specific C version that uses 7 instructions/byte.
+ (It claims to use 6 cycles/byte, but is wrong!)
+ This function uses an unrolled loop, which uses 5 instructions per byte.
+
+ Under some circumstances more characters are read than are
+ required for determining the collating order, but it
+ never reads beyond the end of either string.
+
+ There are one caveat to consider: this function is written
+ in assembler code, and as such, cannot be merged
+ using the U-code loader. */
+
+/* Craig Hansen - 6-June-86 */
+
+#include <kxmips.h>
+
+ .text
+
+LEAF_ENTRY(strcmp)
+
+ .set noreorder
+ lbu t0,0(a0)
+1: lbu t1,0(a1)
+ beq t0,0,2f
+ addi a0,2
+ bne t0,t1,3f
+ lbu t2,-1(a0) # ok to load since -2(a0)!=0
+ lbu t1,1(a1)
+ beq t2,0,2f
+ addi a1,2
+ beq t2,t1,1b
+ lbu t0,0(a0) # ok to load since -1(a0) != 0
+ j ra
+ subu v0,t2,t1
+2: j ra
+ subu v0,zero,t1
+3: j ra
+ subu v0,t0,t1
+ .end strcmp
diff --git a/private/crt32/string/mips/strcpym.s b/private/crt32/string/mips/strcpym.s
new file mode 100644
index 000000000..4f5bc416a
--- /dev/null
+++ b/private/crt32/string/mips/strcpym.s
@@ -0,0 +1,148 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+/* strcpy.s 1.2 */
+
+/* This function is an assembly-code replacement for the libc function
+ * strcpy. It uses the MIPS special instructions "lwl", "lwr", "swl",
+ * and "swr", which handle unaligned words.
+
+ * The standard C version of this function is a 5-instruction loop,
+ * working one byte at a time:
+
+ * Copy string s2 to s1. s1 must be large enough.
+ * return s1
+ * char *strcpy(s1, s2)
+ * register char *s1, *s2;
+ * {
+ * register char *os1;
+ * os1 = s1;
+ * while (*s1++ = *s2++);
+ * return(os1);
+ * }
+
+ * A better C version is 4 cycles/byte. Loop is unrolled once.
+ * char *
+ * strcpy(s1, s2)
+ * register char *s1, *s2;
+ * {
+ * register char *os1 = s1;
+ * while (1) {
+ * register unsigned c;
+ * c = s2[0];
+ * s2 += 2;
+ * s1[0] = c;
+ * if (c == 0) break;
+ * c = s2[1-2];
+ * s1 += 2;
+ * s1[1-2] = c;
+ * if (c == 0) break;
+ * }
+ * return(os1);
+ * }
+
+ * This function starts with an unrolled loop, which uses 5
+ * instructions per byte (including the store bytes at the end) for
+ * the first few bytes.
+
+ * After filling a word, the first word or portion of a word is saved
+ * using a "swl" instruction. If the start of destination string is at
+ * a word boundary, this leaves the result valid in the cache. Because
+ * this replaces up to 4 store byte instructions, we are still near 3
+ * instructions per byte, but there is only one write.
+
+ * The inner loop moves 4 bytes in 16 cycles, an average of 4 cycles
+ * per byte. This is 1 cycle faster than the standard C code, the
+ * same speed as the unrolled version, and it also leaves the result
+ * valid in the cache.
+
+ * Finally, when a zero byte is found, the end of the string is stored
+ * using store byte instructions. This adds one instruction per byte
+ * for as much as three bytes, but elminates the up to four cycles of
+ * overhead we counted before.
+
+ * The end result is that this function is never slower than the C
+ * function, is faster by up to 30% in instruction count, uses up to
+ * 75% fewer writes, and leaves most of the result valid in the cache.
+
+ * There are one caveat to consider: this function is written in
+ * assembler code, and as such, cannot be merged using the U-code
+ * loader. */
+
+/* Craig Hansen - 3-September-86 */
+
+#include <kxmips.h>
+
+/* It turns out better to think of lwl/lwr and swl/swr as
+ smaller-vs-bigger address rather than left-vs-right.
+ Such a representation makes the code endian-independent. */
+
+#define LWS lwr
+#define LWB lwl
+#define SWS swr
+#define SWB swl
+
+.text
+
+LEAF_ENTRY(strcpy)
+.set noreorder
+ // a0/ destination
+ // a1/ source
+ move v0, a0 # a copy of destination address is returned
+ // start up first word
+ // adjust pointers so that a0 points to next word
+ // t7 = a1 adjusted by same amount minus one
+ // t0,t1,t2,t3 are filled with 4 consecutive bytes
+ // t4 is filled with the same 4 bytes in a single word
+ lb t0, 0(a1)
+ ori t5, a0, 3 # get an early start
+ beq t0, 0, $doch0
+ sub t6, t5, a0 # number of char in 1st word of dest - 1
+ lb t1, 1(a1)
+ add t7, a1, t6 # offset starting point for source string
+ beq t1, 0, $doch1
+ nop
+ lb t2, 2(a1)
+ nop
+ beq t2, 0, $doch2
+ LWS t4, 0(a1) # safe: always in same word as 0(a1)
+ lb t3, 3(a1)
+ LWB t4, 3(a1) # fill out word
+ beq t3, 0, $doch3
+ SWS t4, 0(a0) # store entire or part word
+ addi a0, t5, 1-4 # adjust destination ptr
+
+ // inner loop
+1: lb t0, 1(t7)
+ addi t7, 4
+ beq t0, 0, $doch0
+ addi a0, 4
+ lb t1, 1+1-4(t7)
+ nop
+ beq t1, 0, $doch1
+ nop
+ lb t2, 2+1-4(t7)
+ nop
+ beq t2, 0, $doch2
+ LWS t4, 0+1-4(t7)
+ lb t3, 3+1-4(t7)
+ LWB t4, 3+1-4(t7)
+ bne t3, 0, 1b
+ sw t4, 0(a0)
+ j ra
+ nop
+
+ // store four bytes using swl/swr
+$doch3: j ra
+ SWB t4, 3(a0)
+ // store up to three bytes, a byte at a time.
+$doch2: sb t2, 2(a0)
+$doch1: sb t1, 1(a0)
+$doch0: j ra
+ sb t0, 0(a0)
+
+.end strcpy
diff --git a/private/crt32/string/mips/strcpyt.c b/private/crt32/string/mips/strcpyt.c
new file mode 100644
index 000000000..4d0d99279
--- /dev/null
+++ b/private/crt32/string/mips/strcpyt.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <limits.h>
+
+#define SRCLEN 21 /* to avoid complicating errors */
+
+void main( int argc, char **argv )
+{
+ int c;
+ unsigned char *psrc, *pdst;
+ unsigned char src[SRCLEN] = "ABCDEFGHIJKLMNOPQRST";
+ unsigned char dst[100];
+
+ for (c = 'a'; c <= UCHAR_MAX; c++) {
+ src[9] = c;
+ strcpy( dst, src);
+ for (psrc = src, pdst = dst; *psrc; psrc++, pdst++) {
+ if (*psrc != *pdst) {
+ printf("Fail - Could not find '%c' 0x%x in %s\n", c, c, src);
+ break;
+ }
+ }
+ }
+}
diff --git a/private/crt32/string/mips/strlenm.s b/private/crt32/string/mips/strlenm.s
new file mode 100644
index 000000000..24027e0fc
--- /dev/null
+++ b/private/crt32/string/mips/strlenm.s
@@ -0,0 +1,19 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+/* strlen.s 1.1 */
+
+#include <kxmips.h>
+
+LEAF_ENTRY(strlen)
+ subu v0,a0,1
+1: lbu v1,1(v0)
+ add v0,1
+ bne v1,zero,1b
+ subu v0,v0,a0
+ j ra
+ .end strlen
diff --git a/private/crt32/string/mips/strrchrm.s b/private/crt32/string/mips/strrchrm.s
new file mode 100644
index 000000000..feb1f7945
--- /dev/null
+++ b/private/crt32/string/mips/strrchrm.s
@@ -0,0 +1,24 @@
+/* ------------------------------------------------------------------ */
+/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
+/* | Reserved. This software contains proprietary and confidential | */
+/* | information of MIPS and its suppliers. Use, disclosure or | */
+/* | reproduction is prohibited without the prior express written | */
+/* | consent of MIPS. | */
+/* ------------------------------------------------------------------ */
+#ident "$Header: /disks/bits/5.1isms/irix/lib/libc/src/strings/RCS/rindex.s,v 1.3 1992/03/07 15:37:36 jleong Exp $"
+
+/*
+ * Copyright 1985 by MIPS Computer Systems, Inc.
+ */
+
+#include "kxmips.h"
+
+LEAF_ENTRY(strrchr)
+ move v0,zero
+1: lbu a3,0(a0)
+ addu a0,1
+ bne a3,a1,2f
+ subu v0,a0,1
+2: bne a3,zero,1b
+ j ra
+.end strrchr
diff --git a/private/crt32/string/mips/strrchrt.c b/private/crt32/string/mips/strrchrt.c
new file mode 100644
index 000000000..f608c2fc6
--- /dev/null
+++ b/private/crt32/string/mips/strrchrt.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+void main( int argc, char **argv )
+ {
+ int c;
+ unsigned char *pstr;
+ unsigned char string[100];
+
+ strcpy(string, "ABCDEFGHIJKLMNOPQRST");
+ for (c = 'a'; c <= UCHAR_MAX; c++)
+ {
+ string[9] = c;
+ pstr = strrchr( string, c);
+ if (!pstr)
+ printf("Fail - Could not find %d in %s\n", c, string);
+ }
+ return;
+ }
diff --git a/private/crt32/string/mips/wcscmpm.s b/private/crt32/string/mips/wcscmpm.s
new file mode 100644
index 000000000..d3997945d
--- /dev/null
+++ b/private/crt32/string/mips/wcscmpm.s
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * wcscmpm.s - contains wcscmp()
+ *
+ * ------------------------------------------------------------------
+ * | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights |
+ * | Reserved. This software contains proprietary and confidential |
+ * | information of MIPS and its suppliers. Use, disclosure or |
+ * | reproduction is prohibited without the prior express written |
+ * | consent of MIPS. |
+ * ------------------------------------------------------------------
+ * strcmp.s 1.1
+ *
+ * Purpose:
+ * wcscmp() compares two wide-character strings and returns an integer
+ * to indicate whether the first is less than the second, the two are
+ * equal, or whether the first is greater than the second.
+ *
+ * Comparison is done wchar_t by wchar_t on an UNSIGNED basis, which is to
+ * say that Null wchar_t(0) is less than any other character.
+ *
+ * This function is a MIPS assembly-code replacement for the C version.
+ *
+ * Entry:
+ *
+ * const wchar_t * src - string for left-hand side of comparison
+ * const wchar_t * dst - string for right-hand side of comparison
+ *
+ *Exit:
+ * returns -1 if src < dst
+ * returns 0 if src == dst
+ * returns +1 if src > dst
+ *
+ *Exceptions:
+ *
+ *Revision History:
+ * Craig Hansen (MIPS) 06-June-86 Created.
+ * Roger Lanser (MS) 02-April-94 Cloned for Wide Characters (16-bits).
+ *
+ ******************************************************************************/
+
+#include <kxmips.h>
+
+ .text
+
+LEAF_ENTRY(wcscmp)
+
+ lhu t0,0(a0)
+1: lhu t1,0(a1)
+ addi a0,4
+ beq t0,0,2f
+ lhu t2,-2(a0) # ok to load since -4(a0)!=0
+ bne t0,t1,2f
+ lhu t1,2(a1)
+ addi a1,4
+ beq t2,0,2f
+ lhu t0,0(a0) # ok to load since -2(a0) != 0
+ beq t2,t1,1b
+ move v0,zero
+ j ra // source1 == source2, return 0
+2:
+ sltu v0,t1,t0 // compare source1 to source2
+ beq v0,zero,3f
+ j ra // source1 > source2, return 1
+3:
+ li v0,-1
+ j ra // source1 < source2, return 1
+ .end wcscmp
diff --git a/private/crt32/string/mips/wcscmpt.c b/private/crt32/string/mips/wcscmpt.c
new file mode 100644
index 000000000..629f61ca5
--- /dev/null
+++ b/private/crt32/string/mips/wcscmpt.c
@@ -0,0 +1,62 @@
+char buffer[100];
+#include <stdio.h>
+#include <memory.h>
+
+#define NTUL 7
+
+void main()
+{
+ int i, k;
+ int rc;
+
+ unsigned long source1[4] = {
+ 0x30003000,
+ 0x30003000,
+ 0x30003000,
+ 0x36003000
+ };
+
+ unsigned long source2[4] = {
+ 0x30003000,
+ 0x30003000,
+ 0x30003000,
+ 0x00000000
+ };
+
+ unsigned long tul[NTUL] = {
+ 0x35004600,
+ 0x37004600,
+ 0x36002f00,
+ 0x37002f00,
+ 0x30004600,
+ 0x30003000,
+ 0x36003000
+ };
+
+
+ for (k = 0; k < NTUL; k++) {
+ unsigned short *s1 = (unsigned short *)source1;
+ unsigned short *s2 = (unsigned short *)source2;
+
+ source2[3] = tul[k];
+
+ printf("source1 = ");
+ for (i = 0; i < 4*sizeof(unsigned long); i++)
+ printf("%2.2x ", ((char *)source1)[i]);
+ printf("\n");
+
+ printf("source2 = ");
+ for (i = 0; i < 4*sizeof(unsigned long); i++)
+ printf("%2.2x ", ((char *)source2)[i]);
+
+ rc = wcscmp(source1,source2);
+ if (rc < 0) {
+ printf(" source1 < source2\n");
+ } else if (rc > 0) {
+ printf(" source1 > source2\n");
+ } else {
+ printf(" source1 == source2\n");
+ }
+ printf("Return Code = %d\n",rc);
+ }
+}
diff --git a/private/crt32/string/mips/wcscpym.s b/private/crt32/string/mips/wcscpym.s
new file mode 100644
index 000000000..41b3544ec
--- /dev/null
+++ b/private/crt32/string/mips/wcscpym.s
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * wcscpym.s - contains wcscpy()
+ *
+ * Copyright (c) 1994, Microsoft Corporation. All rights reserved.
+ *
+ * Purpose:
+ * wcscpy() copies one wchar_t string into another.
+ *
+ * wcscpy() copies the source string to the destination string
+ * assuming no overlap and enough room in the destination. The
+ * destination string is returned. Strings are wide-character
+ * strings.
+ *
+ * This function is a MIPS assembly-code replacement for the C version.
+ * The only thing that this code tries to do is to produce a loop that
+ * uses a lw/sw pair versus running a lhu/sh loop twice. A small
+ * penality will be paid for very short wide-character strings due
+ * to the setup tests.
+ *
+ * Entry:
+ *
+ * wchar_t *wcscpy(dst, src)
+ * wchar_t * dst - wchar_t string over which "src" is to be copied
+ * const wchar_t * src - wchar_t string to be copied over "dst"
+ *
+ *Exit:
+ * The address of "dst".
+ *
+ *Exceptions:
+ *
+ *Revision History:
+ * 02-08-97 RDL Created initial version.
+ *
+ ******************************************************************************/
+
+#include <kxmips.h>
+
+.text
+
+LEAF_ENTRY(wcscat)
+
+ .set noreorder
+
+ // a0 destination
+ // a1 source
+
+ move v0, a0 // a copy of destination address is returned
+1: lhu t2,0(a0)
+ bnel zero,t2,1b
+ addiu a0,a0,2
+ b 2f
+ nop
+
+ALTERNATE_ENTRY(wcscpy)
+
+ // a0 destination
+ // a1 source
+
+ move v0, a0 // a copy of destination address is returned
+
+2: andi t1,a1,2 // assume at least halfword alignment
+3: andi t0,a0,2 // assume at least halfword alignment
+5: bne t0,t1,30f
+ nop
+
+10: // buffers start on same alignment
+ beq zero,t0,20f
+ nop
+ // halfword alignment
+ lhu t1,0(a1)
+ addiu a0,2
+ addiu a1,2
+ beq zero,t1,99f
+ sh t1,-2(a0)
+
+20: // word alignment
+ lw t0,0(a1)
+ addiu a0,4
+ addiu a1,4
+ andi t1,t0,0xffff
+ beq zero,t1,92f
+ srl t2,t0,16
+ bne zero,t2,20b
+ sw t0,-4(a0)
+ j ra
+ nop
+
+30: // buffers start on different alignment
+ beq zero,t1,40f
+ nop
+ // destination on word boundary, source on halfword boundary
+ lhu t0,0(a1)
+ addiu a1,2
+35: beq zero,t0,92f
+ addiu a0,4
+ lw t1,0(a1)
+ addiu a1,4
+ srl t2,t1,16
+ andi t1,0xffff
+ sll t3,t1,16
+ or t0,t0,t3
+ sw t0,-4(a0)
+ bne zero,t1,35b
+ or t0,zero,t2
+ j ra
+ nop
+
+40: // destination on halfword boundary, source on word boundary
+ lw t3,0(a1)
+ addiu a0,2
+ addiu a1,4
+ srl t2,t3,16
+ andi t0,t3,0xffff
+ beq zero,t0,99f
+ sh t0,-2(a0)
+45: lw t3,0(a1)
+ addiu a0,4
+ addiu a1,4
+ srl t1,t3,16
+ sll t3,t3,16
+ beq zero,t3,94f
+ or t0,t2,t3
+ sw t0,-4(a0)
+ bne zero,t1,45b
+ or t2,t1,zero
+ j ra
+ sh t1,0(a0)
+
+92: j ra
+ sh t0,-4(a0)
+
+94: j ra
+ sw t0,-4(a0)
+
+99: j ra
+ nop
+ .set reorder
+
+ .end wcscat
diff --git a/private/crt32/string/mips/wcslenm.s b/private/crt32/string/mips/wcslenm.s
new file mode 100644
index 000000000..ef45c114e
--- /dev/null
+++ b/private/crt32/string/mips/wcslenm.s
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * wcslenm.s - contains wcslen()
+ *
+ * ------------------------------------------------------------------
+ * | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights |
+ * | Reserved. This software contains proprietary and confidential |
+ * | information of MIPS and its suppliers. Use, disclosure or |
+ * | reproduction is prohibited without the prior express written |
+ * | consent of MIPS. |
+ * ------------------------------------------------------------------
+ * strlen.s 1.1
+ *
+ * Purpose:
+ * Finds the length in wchar_t's of the given string, not including
+ * the final null wchar_t (wide-characters).
+ *
+ * This function is a MIPS assembly-code replacement for the C version.
+ *
+ * Entry:
+ *
+ * wchar_t *wcslen(wcs)
+ * wchar_t * wcs - wchar_t string
+ *
+ *Exit:
+ * The "length" of wcs in wchar_t's.
+ *
+ *Exceptions:
+ *
+ *Revision History:
+ * Craig Hansen (MIPS) 06-June-86 Created.
+ * Roger Lanser (MS) 02-April-94 Cloned for Wide Characters (16-bits).
+ *
+ ******************************************************************************/
+
+#include <kxmips.h>
+
+LEAF_ENTRY(wcslen)
+ subu v0,a0,2
+1: lhu v1,2(v0)
+ addiu v0,v0,2
+ bne v1,zero,1b
+ subu v0,v0,a0
+ srl v0,v0,1
+ j ra
+ .end wcslen
diff --git a/private/crt32/string/ppc/memccpyp.s b/private/crt32/string/ppc/memccpyp.s
new file mode 100644
index 000000000..3690a0bd5
--- /dev/null
+++ b/private/crt32/string/ppc/memccpyp.s
@@ -0,0 +1,78 @@
+// TITLE("memccpy")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// memccpy.s
+//
+// Routine Description:
+//
+// Copies bytes from src to dest until count bytes have been
+// copied, or up to and including the character c, whichever
+// comes first.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// Arguments:
+//
+// SRC1 (r.3) - A pointer to the memory destination
+//
+// SRC1 (r.4) - A pointer to the memory source
+//
+// CHAR (r.5) - A character to stop copy
+//
+// LNGTH (r.6) - Max number of comparison in bytes
+//
+// Return Value:
+//
+// NULL if search character is not found or not copied
+// ptr to byte immediately after search character ...
+// ... if character found AND copied
+//
+// void * _CALLTYPE1 _memccpyc (
+// void * dest,
+// const void * src,
+// int c,
+// unsigned count
+// )
+//
+
+ LEAF_ENTRY(_memccpy)
+
+ addi r7,r6,1 # incr count, artificial
+ mtctr r7 # move count to ctr
+ bdz L..7A # if 0, finish up
+ lbz r8,0(r4) # read 1st char
+ subi r3,r3,1 # prep r3 for update form
+
+L..3:
+ stbu r8,1(r3) # copy char
+ cmp 0x0,0x0,r8,r5 # compare to char c
+ beq L..5 # found char c, say goodbye
+ bdz L..7A # count 0, say goodbye
+ lbzu r8,1(r4) # read next char
+ b L..3 # do another
+
+L..5:
+ addi r3,r3,1 # ret r3+1
+ b L..7 # all done, one exit pt.
+L..7A:
+ addi r3,r0,0 # return null
+L..7:
+
+ LEAF_EXIT(_memccpy)
diff --git a/private/crt32/string/ppc/memchrp.s b/private/crt32/string/ppc/memchrp.s
new file mode 100644
index 000000000..05a78105b
--- /dev/null
+++ b/private/crt32/string/ppc/memchrp.s
@@ -0,0 +1,74 @@
+// TITLE("memchr")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// memchr.s
+//
+// Routine Description:
+//
+// Searches buffer for character, stopping when found
+// or after checking count bytes.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// void * memchr (
+// const void * buffer,
+// int character,
+// size_t count
+// )
+//
+// Arguments:
+//
+// SRC1 (r.3) - A pointer to the block of memory
+//
+// SRC2 (r.4) - A character to base search
+//
+// LNGTH (r.5) - Max number of comparison in bytes
+//
+// Return Value:
+//
+// NULL if not found after count bytes
+// ptr to character in buffer, if character is found
+//
+//
+
+ LEAF_ENTRY(memchr)
+
+ cmpi 0x7,0x0,r5,0 # chk cnt
+ cmpi 0x1,0x0,r5,1 # finish early
+ beq 0x7,Null # all done
+
+ lbz r6,0(r3) # read char
+ cmp 0x6,0x0,r6,r4 # char ?= c
+ subi r5,r5,1 # decr cnt
+ beq 0x6,Fini # all done
+ beq 0x1,Null # rd 1 char only
+
+ mtctr r5 # init ctr
+
+L..1:
+ lbzu r6,1(r3)
+ cmp 0x0,0x0,r6,r4 # char ?= c
+ bdnzf eq,L..1 # dec ctr & ...
+ beq Fini # br ctr != 0 & !char
+Null:
+ addi r3,r0,0 # return null
+Fini:
+
+ LEAF_EXIT(memchr)
diff --git a/private/crt32/string/ppc/memcmpp.s b/private/crt32/string/ppc/memcmpp.s
new file mode 100644
index 000000000..ce1b003ff
--- /dev/null
+++ b/private/crt32/string/ppc/memcmpp.s
@@ -0,0 +1,71 @@
+// TITLE("memcmp")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// memcmp.s
+//
+// Routine Description:
+//
+// This function lexically determines two blocks of memory and
+// returns an integer indicating order.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// int memcmp (
+// void * src1,
+// void * src2,
+// int
+// )
+//
+// Arguments:
+//
+// SRC1 (r.3) - A pointer to the first block of memory
+//
+// SRC2 (r.4) - A pointer to the second block of memory
+//
+// LNGTH (r.5) - Max number of comparison in bytes
+//
+// Return Value:
+//
+// < 0 if SRC1 < SRC2
+// = 0 if SRC1 = SRC2 for LNGTH bytes, or if LNGTH == 0
+// > 0 if SRC1 > SRC2
+//
+//
+
+ LEAF_ENTRY(memcmp)
+
+ cmpwi r.5,0 // we'll do the first iteration
+ mtctr r.5 // by hand, iff length > 0
+ beq zip // branch if nothing to check
+ lbz r.6,0(r.4) // read first byte
+ lbz r.5,0(r.3) // of both strings
+ b comp
+
+next: lbzu r.6,1(r.4) // get next byte (src2)
+ lbzu r.5,1(r.3) // get next byte (src1)
+comp: cmpw r.5,r.6 // bytes equal?
+ bdnzt eq,next // branch equal AND length not exhausted
+
+ subf r.3,r.6,r.5 // r7 ?= r8
+ blr
+
+zip: li r.3,0 // return null when length == 0
+
+ LEAF_EXIT(memcmp)
diff --git a/private/crt32/string/ppc/strcatp.s b/private/crt32/string/ppc/strcatp.s
new file mode 100644
index 000000000..bbbfd7a96
--- /dev/null
+++ b/private/crt32/string/ppc/strcatp.s
@@ -0,0 +1,137 @@
+// TITLE("strcpy strcat")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strcatp.s
+//
+// Abstract:
+//
+// The module implements the routines strcpy and strcat.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Peter Johnston (plj@vnet.ibm.com) 08-Aug-1994
+//
+// Minor optimization.
+//
+//--
+
+#include <kxppc.h>
+
+//++
+//
+// PUCHAR
+// strcpy (
+// PUCHAR dest;
+// PUCHAR src;
+// )
+//
+// Routine Description:
+//
+// Copies an ANSI (null terminated) string from src to dest.
+//
+// Arguments:
+//
+// dest (r.3) - A pointer to the string destination
+//
+// src (r.4) - A pointer to the string source
+//
+//
+// Return Value:
+//
+// dest Pointer to the destination string.
+//
+//--
+
+ LEAF_ENTRY(strcpy)
+
+ lbz r.5,0(r.4) // get first byte
+ addi r.9,r.3,-1 // pref for store with update
+ cmpwi r.5,0 // check if first byte was last
+ beq cpdone // jif so
+
+cploop: lbzu r.6,1(r.4) // get next byte
+ stbu r.5,1(r.9) // store previous byte
+ or. r.5,r.6,r.6 // mv to store reg and check if done
+ bne cploop
+
+cpdone: stbu r.5,1(r.9) // store last byte
+
+ LEAF_EXIT(strcpy)
+
+//++
+//
+// PUCHAR
+// strcat (
+// PUCHAR str1;
+// PUCHAR str2;
+//
+// Routine Description:
+//
+// This function concatenates a source string (str2) to the end of
+// the desintation string (str1).
+//
+// Arguments:
+//
+// str1 (r.3) - A pointer to the string destination
+//
+// str2 (r.4) - A pointer to the string source
+//
+//
+// Return Value:
+//
+// str1 Pointer to the destination string.
+//
+//--
+
+
+ LEAF_ENTRY(strcat)
+
+ lbz r.5,0(r.4) // Load 1st char str2
+ lbz r.6,0(r.3) // Load 1st char str1
+ cmpwi cr.1,r.5,0 // check if str2 null
+ cmpwi r.6,0 // check if str1 null
+ mr r.9,r.3 // copy char ptr
+
+//
+// If str2 is empty, we have nothing to do, return early.
+//
+
+ beqlr cr.1 // return if str2 empty
+
+//
+// If str 1 empty, we're done scanning already.
+//
+
+ beq ctcpy // if str1 null start cat
+
+//
+// Scan str1 until we find its null terminator.
+//
+
+ctscan: lbzu r.6,1(r.9) // get next byte str1
+ cmpwi r.6,0 // test for null
+ bne ctscan // if not null, continue scan
+
+//
+// We found the end of str1, we know we have data in str2, all that
+// remains is to strcpy str2 to the end of str1, set up for and use
+// the body of strcpy (above) to do this.
+//
+
+ctcpy: addi r.9,r.9,-1 // prep for store with update
+ b cploop // finish in strcpy
+
+ LEAF_EXIT(strcat)
+
diff --git a/private/crt32/string/ppc/strchrp.s b/private/crt32/string/ppc/strchrp.s
new file mode 100644
index 000000000..0f03dc54a
--- /dev/null
+++ b/private/crt32/string/ppc/strchrp.s
@@ -0,0 +1,70 @@
+// TITLE("strchr")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strchr.s
+//
+// Routine Description:
+//
+// Searches a string for a given character, which may be the
+// null character '\0'.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// *char *strchr(
+// char *str,
+// char c)
+// Arguments:
+//
+// SRC1 (r.3) - A pointer to the first block of memory
+//
+// SRC2 (r.4) - A search character
+//
+//
+// Return Value:
+//
+// returns pointer to the first occurence of c in string
+// returns NULL if c does not occur in string
+//
+//
+
+ LEAF_ENTRY(strchr)
+
+ lbz r6,0(r3) # read char
+ cmpi 0x0,0x0,r4,0 # c ?= null
+ beq L..3A # use special loop
+
+L..3:
+ cmpi 0x1,0x0,r6,0 # char ?= null
+ cmp 0x0,0x0,r6,r4 # char ?= c
+ beq 0x1,L..5A # b, if char is null
+ beq Fini
+ lbzu r6,1(r3) # read char
+ b L..3
+L..3A:
+ cmpi 0x0,0x0,r6,0 # char ?= null
+ beq Fini
+ lbzu r6,1(r3) # read char
+ b L..3A
+L..5A:
+ addi r3,r0,0 # return null
+
+Fini:
+
+ LEAF_EXIT(strchr)
diff --git a/private/crt32/string/ppc/strcmpp.s b/private/crt32/string/ppc/strcmpp.s
new file mode 100644
index 000000000..0d57279e0
--- /dev/null
+++ b/private/crt32/string/ppc/strcmpp.s
@@ -0,0 +1,74 @@
+// TITLE("strcmp")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strcmp.s
+//
+// Routine Description:
+//
+// This function lexically determines two blocks of memory and
+// returns an integer indicating order.
+// STRCMP compares two strings and returns an integer
+// to indicate whether the first is less than the second, the two are
+// equal, or whether the first is greater than the second.
+//
+// Comparison is done byte by byte on an UNSIGNED basis, which is to
+// say that Null (0) is less than any other character (1-255).
+//
+// Author:
+//
+// Jeff Simon (jhs) 03-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+//
+// int strcmp (
+// const char * src,
+// const char * dst
+// )
+//
+// Arguments:
+//
+// STR1 (r.3) - A pointer to the first string
+//
+// STR2 (r.4) - A pointer to the second string
+//
+// Return Value:
+//
+// < 0 if STR1 < STR2
+// = 0 if STR1 = STR2 for LNGTH bytes, or if LNGTH == 0
+// > 0 if STR1 > STR2
+//
+//
+ LEAF_ENTRY(strcmp)
+
+ lbz r5,0(r3) # init r5
+ lbz r6,0(r4) # init r6
+ or r9,r3,r3 # cp ptr
+L..3:
+ cmpi 0x7,0x0,r6,0x0 # end of string ?
+ subf. r3,r6,r5 # lexical compare
+ bc 0xc,0x1e,L..4 # b, if null detected
+ bne L..4 # b, if not equal
+ lbzu r5,1(r9) # next char
+ lbzu r6,1(r4) # next char
+ b L..3 # loop
+
+L..4:
+ beqlr
+ addi r3,r0,-1 #?I hate doing this, but intel
+ bltlr #?ret -1, +1, so ...
+ addi r3,r0,1 #?
+
+ LEAF_EXIT(strcmp)
diff --git a/private/crt32/string/ppc/stricmpp.s b/private/crt32/string/ppc/stricmpp.s
new file mode 100644
index 000000000..a61d23573
--- /dev/null
+++ b/private/crt32/string/ppc/stricmpp.s
@@ -0,0 +1,89 @@
+// TITLE("_stricmp _strcmpi")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// _stricmp.s
+// _strcmpi.s
+//
+// Routine Description:
+//
+// The functions are synomns. The functions return an integer
+// indicating case-insensitive string comparision, as the function
+// maps characters from upper to lower case. Note that the
+// mapping from upper to lower affects outcome when comparison
+// strings contain characters 91-96 as compared
+// to mapping lower to upper.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+
+// int _stricmp _strcmpi
+// (
+// char *str1,
+// char *str2
+// )
+//
+// Arguments:
+//
+// STR1 (r.3) - A pointer to the first string
+//
+// STR2 (r.4) - A pointer to the second string
+//
+//
+// Return Value:
+//
+// < 0 if STR1 < STR2
+// = 0 if STR1 = STR2
+// > 0 if STR1 > STR2
+//
+//
+
+ LEAF_ENTRY(_stricmp)
+ ALTERNATE_ENTRY(_strcmpi)
+
+ addi r9,r3,-1 # copy ptr
+ addi r4,r4,-1
+Loop1:
+
+ lbzu r6,1(r4) # read char
+ lbzu r5,1(r9) # read char
+ cmpi 0x7,0x0,r6,0 # Is char null?
+ subf. r3,r6,r5 # Calc result
+
+ bc 0xc,0x1e,Loop20 # b if !=
+ bc 0xc,0x2,Loop1 # b if r5 ?= r6
+
+Loop4:
+ cmpi 0x5,0x0,r6,0x41 # Is r5 > 60
+ cmpi 0x6,0x0,r6,0x5A # Is r6 < 7B
+ blt 0x5,Loop2 # ? >
+ bgt 0x6,Loop2 # ? <
+
+ ori r6,r6,0x20 # cvrt to lower case
+Loop2:
+ cmpi 0x0,0x0,r5,0x41 # Is r5 > 60
+ cmpi 0x1,0x0,r5,0x5A # Is r6 < 7B
+ blt 0x0,Loop3 # ?
+ bgt 0x1,Loop3 # ?
+
+ ori r5,r5,0x20 # cvrt to lower case
+Loop3:
+ subf. r3,r6,r5 # Is r6 = r5
+ beq Loop1 # !=, done
+
+Loop20:
+ LEAF_EXIT(_stricmp)
diff --git a/private/crt32/string/ppc/strlenp.s b/private/crt32/string/ppc/strlenp.s
new file mode 100644
index 000000000..94553997a
--- /dev/null
+++ b/private/crt32/string/ppc/strlenp.s
@@ -0,0 +1,164 @@
+// TITLE("strlen")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strlen.s
+//
+// Routine Description:
+//
+// This function returns the length of a string excluding the
+// terminating null.
+//
+// The algorithm used here merits some explanation. It turns
+// out to be quite fast on a 32 bit processor but it is known
+// to be extremely fast on a 64 bit processor. I have seen this
+// algorithm used elsewhere but the best description I have seen
+// for it is in a document entitled "Hacker's Delight" by
+// Henry S. Warren, Jr. IBM Thomas J. Watson Research Center.
+//
+// I have found (by experimentation) that it is faster to just
+// get on with it and do the first few bytes as single bytes
+// rather than trying to work out the alignment up front.
+//
+// Once word aligned, we can process the string a word at a time.
+// The hard part is to figure out if the word contains a zero byte.
+//
+// Given x where x is the word being examined, consider
+//
+// y = x & 0x7f7f7f7f we have reduced each byte in x to a
+// value of 7f or less.
+//
+// y += 0x7f7f7f7f each byte whose lower 7 bits were non
+// zero now has its left most bit set.
+//
+// y |= x each byte whose value was 0x80 now
+// also has its upper bit set.
+//
+// y |= 0x7f7f7f7f each non zero byte now has the value
+// 0xff. (Each zero byte is now 0x7f).
+//
+// Note the last two "or" operations can be rewritten as
+//
+// x |= 0x7f7f7f7f
+//
+// y |= x
+//
+// making the operations to independent which allows them to run in
+// parrallel on a superscalar machine with multiple boolean functional
+// units.
+//
+// This value can now be checked for equality with -1, or its
+// complement with 0. If equal, then this word contains no zero
+// bytes.
+//
+// The complement is more interesting. On a big endian machine, a
+// count leading zeroes on the complement gives you 8 times the number
+// of non-zero bytes before the zero byte. Little endian, no such
+// luxury. Given that a non-zero complement means one or more bytes
+// are zero, we only need check the first three (starting at the
+// right). On PowerPC we can easily do this by moving the complement
+// to the condition register (after suitably rotating so we do not
+// overwrite any non-volatile condition register fields) then testing
+// one bit for each byte.
+//
+// I have found this method to be about the same speed (no slower) for
+// very short strings and almost (not quite) twice as fast as checking
+// each byte individually for long strings.
+//
+//
+// Author:
+//
+// Peter L Johnston (plj@vnet.ibm.com) 15-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Arguments:
+//
+// addr (r.3) - A pointer to the string
+//
+// Return Value:
+//
+// length (r.3) - length of the string excluding the terminating null
+//
+
+#include <kxppc.h>
+
+ LEAF_ENTRY(strlen)
+
+//
+// Do the first 1, 2, 3 or 4 bytes individually while we try to figure
+// out the real alignment.
+//
+
+ lbz r.4, 0(r.3) // get first byte
+ addi r.7, r.3, 1 // bump and move address
+ cmpwi cr.1, r.4, 0 // first byte zero?
+ andi. r.8, r.7, 0x3 // check alignment of next byte
+ li r.3, 0 // initialize length
+ beqlr cr.1 // return if byte is zero
+ beq wds // switch to word oriented count if
+ // now word aligned.
+nxbyte: lbz r.4, 0(r.7) // get next byte
+ addi r.7, r.7, 1 // bump address
+ cmpwi cr.1, r.4, 0 // byte equal zero?
+ andi. r.8, r.7, 0x3 // check new alignment
+ addi r.3, r.3, 1 // bump length
+ beqlr cr.1 // return if byte is zero
+ bne nxbyte
+
+//
+// We can look at the rest on a word by word basis
+//
+
+wds: lwz r.4, 0(r.7) // get first word
+
+ lis r.6, 0x7f7f // setup magic constant
+ ori r.6, r.6, 0x7f7f
+
+ addi r.3, r.3, 1 // count was one short by here
+
+//
+// See introductory comments for an explanation of the following.
+//
+
+chkwd: and r.8, r.4, r.6 // y = x & 0x7f7f7f7f
+ or r.4, r.4, r.6 // x = x | 0x7f7f7f7f
+ add r.8, r.8, r.6 // y += 0x7f7f7f7f
+ or r.8, r.8, r.4 // y |= x
+ not. r.8, r.8 // if complement = 0 then no zero bytes
+ bne bytes // non-zero means one of the bytes IS
+
+ lwzu r.4, 4(r.7) // get next word
+ addi r.3, r.3, 4 // bump count
+ b chkwd
+
+//
+// When we get here, we encountered a word that contains a zero byte. As
+// a result of the above algorithm, the zero byte is now represented within
+// the word as 0x80. All non-zero bytes are now 0x00.
+//
+// We have up to 4 bits in r.8 (if we were big endian we could use count
+// leading zeros for this), we'll slam them in the condition register and
+// look at them individually. We know at least one of them is set so we
+// only bother checking the first three.
+//
+
+bytes: rlwinm r.8, r.8, 20, 0xff000fff// posn so dont use non-volatile
+ mtcrf 0x45, r.8 // fields in CR
+ btlr 4 // jif right most is terminator
+ addi r.3, r.3, 1 // bump count
+ btlr 28 // jif 2nd from right
+ addi r.3, r.3, 1 // bump
+ btlr 20 // jif 3rd from right
+ addi r.3, r.3, 1 // bump
+
+ blr
+
+ LEAF_EXIT(strlen)
diff --git a/private/crt32/string/ppc/strrchrp.s b/private/crt32/string/ppc/strrchrp.s
new file mode 100644
index 000000000..e3b5991c5
--- /dev/null
+++ b/private/crt32/string/ppc/strrchrp.s
@@ -0,0 +1,87 @@
+// TITLE("strrchr")
+//++
+//
+// Copyright (c) 1994 IBM Corporation
+//
+// Module Name:
+//
+// strrchr.s
+//
+// Routine Description:
+//
+// This function searches a null-terminated string for the
+// last occurence of a character.
+//
+// Author:
+//
+// Jeff Simon (jhs) 02-Aug-1994
+//
+// Environment:
+//
+// User or Kernel mode.
+//
+// Revision History:
+//
+// Includes
+
+#include <kxppc.h>
+//
+// char * strrchr
+// (
+// const char * string,
+// int ch
+// )
+//
+//
+// Arguments:
+//
+// STR1 (r.3) - A pointer to the first block of memory
+//
+// CHAR (r.4) - A search character
+//
+// Return Value:
+//
+// NULL if character is never found
+// ptr to the character in string where last match is found
+//
+//
+
+ LEAF_ENTRY(strrchr)
+
+
+ lbz r5,0(r3) # read 1st char
+ or r9,r3,r3 # cp char ptr
+ cmpi 0x6,0x0,r4,0x0 # ch ?= Null
+ cmp 0x0,0x0,r5,r4 # r5 ?= ch
+ bc 0xc,0x1a,L..2
+ addi r3,r0,0 # init to Null
+ beq L..1A # b if 1st ch matched
+
+L..1: # CASE: ch != Null
+
+ cmpi 0x6,0x0,r5,0x0 # end of str ?
+ bc 0xc,0x1a,Fini # all done
+ lbzu r5,1(r9) # read nxt char
+ cmp 0x0,0x0,r4,r5 # r4 ?= r5
+ bne L..1
+
+L..1A: # CASE: match found
+
+ or r3,r9,r9 # Update char ptr
+ lbzu r5,1(r9) # load next char
+ cmp 0x0,0x0,r4,r5 # r4 ?= r5
+ beq L..1A
+ b L..1
+
+
+L..2: # CASE: char = Null
+
+ bc 0xc,0x2,Fini # ret if null found
+ lbzu r5,1(r3)
+ cmpi 0x0,0x0,r5,0x0 # Is r5 ?= Null
+ b L..2
+
+
+Fini:
+
+ LEAF_EXIT(strrchr)
diff --git a/private/crt32/string/sources b/private/crt32/string/sources
new file mode 100644
index 000000000..3b7d2ea7c
--- /dev/null
+++ b/private/crt32/string/sources
@@ -0,0 +1,175 @@
+!IF 0
+
+Copyright (c) 1989 - 1992, Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+ karlsi 07-Apr-1992, add wide character routines, intl support
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=string
+
+TARGETNAME=string
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+NTTARGETFILE0=strcspn.c strpbrk.c
+!IF $386
+NTTARGETFILE0=$(NTTARGETFILE) i386\memmove.asm i386\strcspn.asm i386\strpbrk.asm
+!ENDIF
+
+SOURCES=strcoll.c \
+ stricoll.c \
+ strlwr.c \
+ strtok.c \
+ strupr.c \
+ strxfrm.c \
+ wcscat.c \
+ wcschr.c \
+ wcscmp.c \
+ wcscoll.c \
+ wcscspn.c \
+ wcsdup.c \
+ wcsicmp.c \
+ wcsicoll.c \
+ wcslen.c \
+ wcslwr.c \
+ wcsncat.c \
+ wcsncmp.c \
+ wcsncpy.c \
+ wcsnicmp.c \
+ wcsnset.c \
+ wcspbrk.c \
+ wcsrchr.c \
+ wcsrev.c \
+ wcsset.c \
+ wcsspn.c \
+ wcsstr.c \
+ wcstok.c \
+ wcsupr.c \
+ wcsxfrm.c
+
+i386_SOURCES=i386\memccpy.asm \
+ i386\memchr.asm \
+ i386\memcmp.asm \
+ i386\memcpy.asm \
+ i386\memicmp.asm \
+ i386\memmove.asm \
+ i386\memset.asm \
+ i386\strcat.asm \
+ i386\strchr.asm \
+ i386\strcmp.asm \
+ i386\strcspn.asm \
+ i386\strdup.asm \
+ i386\stricmp.asm \
+ i386\strlen.asm \
+ i386\strncat.asm \
+ i386\strncmp.asm \
+ i386\strncpy.asm \
+ i386\strnicmp.asm \
+ i386\strnset.asm \
+ i386\strpbrk.asm \
+ i386\strrchr.asm \
+ i386\strrev.asm \
+ i386\strset.asm \
+ i386\strspn.asm \
+ i386\strstr.asm
+
+MIPS_SOURCES=memccpy.c \
+ memchr.c \
+ memicmp.c \
+ strcspn.c \
+ strdup.c \
+ stricmp.c \
+ strncat.c \
+ strncmp.c \
+ strncpy.c \
+ strnicmp.c \
+ strnset.c \
+ strpbrk.c \
+ strrev.c \
+ strset.c \
+ strspn.c \
+ strstr.c \
+ mips\memorym.s \
+ mips\strcatm.s \
+ mips\strchrm.s \
+ mips\strcmpm.s \
+ mips\strcpym.s \
+ mips\strlenm.s \
+ mips\strrchrm.s
+
+ALPHA_SOURCES=memccpy.c \
+ memchr.c \
+ memcmp.c \
+ memcpy.c \
+ memicmp.c \
+ memmove.c \
+ memset.c \
+ alpha\strcat.c \
+ strchr.c \
+ alpha\strcmps.s \
+ strcspn.c \
+ strdup.c \
+ stricmp.c \
+ alpha\strlens.s \
+ strncat.c \
+ strncmp.c \
+ strncpy.c \
+ alpha\strcpys.s \
+ strnicmp.c \
+ strnset.c \
+ strpbrk.c \
+ strrchr.c \
+ strrev.c \
+ strset.c \
+ strspn.c \
+ strstr.c
+
+PPC_SOURCES= ppc\memccpyp.s \
+ ppc\memchrp.s \
+ ppc\memcmpp.s \
+ memcpy.c \
+ memicmp.c \
+ memmove.c \
+ memset.c \
+ ppc\strcatp.s \
+ ppc\strchrp.s \
+ ppc\strcmpp.s \
+ strcspn.c \
+ strdup.c \
+ ppc\stricmpp.s \
+ ppc\strlenp.s \
+ strncat.c \
+ strncmp.c \
+ strncpy.c \
+ strnicmp.c \
+ strnset.c \
+ strpbrk.c \
+ ppc\strrchrp.s \
+ strrev.c \
+ strset.c \
+ strspn.c \
+ strstr.c
+
diff --git a/private/crt32/string/strcat.c b/private/crt32/string/strcat.c
new file mode 100644
index 000000000..ada29471d
--- /dev/null
+++ b/private/crt32/string/strcat.c
@@ -0,0 +1,90 @@
+/***
+*strcat.c - contains strcat() and strcpy()
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Strcpy() copies one string onto another.
+*
+* Strcat() concatenates (appends) a copy of the source string to the
+* end of the destination string, returning the destination string.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 04-05-91 GJF Speed up strcat() a bit (got rid of call to strcpy()).
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(strcat,strcpy)
+#endif /* ndef _CRUISER_ */
+
+/***
+*char *strcat(dst, src) - concatenate (append) one string to another
+*
+*Purpose:
+* Concatenates src onto the end of dest. Assumes enough
+* space in dest.
+*
+*Entry:
+* char *dst - string to which "src" is to be appended
+* const char *src - string to be appended to the end of "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strcat (
+ char * dst,
+ const char * src
+ )
+{
+ char * cp = dst;
+
+ while( *cp )
+ cp++; /* find end of dst */
+
+ while( *cp++ = *src++ ) ; /* Copy src to end of dst */
+
+ return( dst ); /* return dst */
+
+}
+
+
+/***
+*char *strcpy(dst, src) - copy one string over another
+*
+*Purpose:
+* Copies the string src into the spot specified by
+* dest; assumes enough room.
+*
+*Entry:
+* char * dst - string over which "src" is to be copied
+* const char * src - string to be copied over "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*******************************************************************************/
+
+char * _CALLTYPE1 strcpy(char * dst, const char * src)
+{
+ char * cp = dst;
+
+ while( *cp++ = *src++ )
+ ; /* Copy src over dst */
+
+ return( dst );
+}
diff --git a/private/crt32/string/strchr.c b/private/crt32/string/strchr.c
new file mode 100644
index 000000000..bbabf62b2
--- /dev/null
+++ b/private/crt32/string/strchr.c
@@ -0,0 +1,52 @@
+/***
+*strchr.c - search a string for a given character
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines strchr() - search a string for a character
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant
+* #include <stddef.h>
+* 10-01-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *strchr(string, c) - search a string for a character
+*
+*Purpose:
+* Searches a string for a given character, which may be the
+* null character '\0'.
+*
+*Entry:
+* char *string - string to search in
+* char c - character to search for
+*
+*Exit:
+* returns pointer to the first occurence of c in string
+* returns NULL if c does not occur in string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strchr (
+ const char * string,
+ int ch
+ )
+{
+ while (*string && *string != (char)ch)
+ string++;
+
+ if (*string == (char)ch)
+ return((char *)string);
+ return(NULL);
+}
diff --git a/private/crt32/string/strcmp.c b/private/crt32/string/strcmp.c
new file mode 100644
index 000000000..6d41fe4cd
--- /dev/null
+++ b/private/crt32/string/strcmp.c
@@ -0,0 +1,68 @@
+/***
+*strcmp.c - routine to compare two strings (for equal, less, or greater)
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compares two string, determining their lexical order.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(strcmp)
+#endif /* ndef _CRUISER_ */
+
+/***
+*strcmp - compare two strings, returning less than, equal to, or greater than
+*
+*Purpose:
+* STRCMP compares two strings and returns an integer
+* to indicate whether the first is less than the second, the two are
+* equal, or whether the first is greater than the second.
+*
+* Comparison is done byte by byte on an UNSIGNED basis, which is to
+* say that Null (0) is less than any other character (1-255).
+*
+*Entry:
+* const char * src - string for left-hand side of comparison
+* const char * dst - string for right-hand side of comparison
+*
+*Exit:
+* returns -1 if src < dst
+* returns 0 if src == dst
+* returns +1 if src > dst
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 strcmp (
+ const char * src,
+ const char * dst
+ )
+{
+ int ret = 0 ;
+
+ while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
+ ++src, ++dst;
+
+ if ( ret < 0 )
+ ret = -1 ;
+ else if ( ret > 0 )
+ ret = 1 ;
+
+ return( ret );
+}
diff --git a/private/crt32/string/strcoll.c b/private/crt32/string/strcoll.c
new file mode 100644
index 000000000..9f9a7590e
--- /dev/null
+++ b/private/crt32/string/strcoll.c
@@ -0,0 +1,103 @@
+/***
+*strcoll.c - Collate locale strings
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare two strings using the locale LC_COLLATE information.
+*
+*Revision History:
+* 03-21-89 JCR Module created.
+* 06-20-89 JCR Removed _LOAD_DGROUP code
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-01-90 GJF New-style function declarator.
+* 10-01-91 ETC Non-C locale support under _INTL switch.
+* 12-09-91 ETC Updated api; added multithread.
+* 08-19-92 KRS Activate NLS support.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-16-92 KRS Optimize for CompareStringW by using -1 for string len.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int strcoll() - Collate locale strings
+*
+*Purpose:
+* Compare two strings using the locale LC_COLLATE information.
+* [ANSI].
+*
+* Non-C locale support available under _INTL switch.
+* In the C locale, strcoll() simply resolves to strcmp().
+*Entry:
+* const char *s1 = pointer to the first string
+* const char *s2 = pointer to the second string
+*
+*Exit:
+* Less than 0 = first string less than second string
+* 0 = strings are equal
+* Greater than 0 = first string greater than second string
+*
+*Exceptions:
+* NLSCMPERROR = error
+*
+*******************************************************************************/
+
+int _CRTAPI1 strcoll (
+ const char *_string1,
+ const char *_string2
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ size_t size1, size2;
+ wchar_t *wstring1, *wstring2;
+ int ret;
+
+ _mlock (_LC_CTYPE_LOCK);
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_CTYPE_LOCK);
+ _munlock (_LC_COLLATE_LOCK);
+ return strcmp(_string1, _string2);
+ }
+
+ size1 = (strlen(_string1) + 1) * sizeof(wchar_t);
+ size2 = (strlen(_string2) + 1) * sizeof(wchar_t);
+ wstring1 = malloc (size1);
+ wstring2 = malloc (size2);
+ if (!wstring1 || !wstring2)
+ goto error_cleanup;
+ if (!MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, _string1, -1,
+ wstring1, size1)) goto error_cleanup;
+ if (!MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, _string2, -1,
+ wstring2, size2)) goto error_cleanup;
+ if (!(ret=CompareStringW(_lc_handle[LC_COLLATE], 0, wstring1, -1,
+ wstring2, -1))) goto error_cleanup;
+
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ free (wstring1);
+ free (wstring2);
+ return (ret - 2);
+
+error_cleanup:
+
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ free (wstring1);
+ free (wstring2);
+ return NLSCMPERROR;
+
+#else
+ return strcmp(_string1,_string2);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/strcspn.c b/private/crt32/string/strcspn.c
new file mode 100644
index 000000000..7bd92963f
--- /dev/null
+++ b/private/crt32/string/strcspn.c
@@ -0,0 +1,2 @@
+#define SSTRCSPN
+#include "strspn.c"
diff --git a/private/crt32/string/strdup.c b/private/crt32/string/strdup.c
new file mode 100644
index 000000000..2e15d16cd
--- /dev/null
+++ b/private/crt32/string/strdup.c
@@ -0,0 +1,60 @@
+/***
+*strdup.c - duplicate a string in malloc'd memory
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _strdup() - grab new memory, and duplicate the string into it.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Removed now redundant #include <stddef.h>
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <string.h>
+
+/***
+*char *_strdup(string) - duplicate string into malloc'd memory
+*
+*Purpose:
+* Allocates enough storage via malloc() for a copy of the
+* string, copies the string into the new memory, and returns
+* a pointer to it.
+*
+*Entry:
+* char *string - string to copy into new memory
+*
+*Exit:
+* returns a pointer to the newly allocated storage with the
+* string in it.
+*
+* returns NULL if enough memory could not be allocated, or
+* string was NULL.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strdup (
+ const char * string
+ )
+{
+ char *memory;
+
+ if (!string)
+ return(NULL);
+
+ if (memory = malloc(strlen(string) + 1))
+ return(strcpy(memory,string));
+
+ return(NULL);
+}
diff --git a/private/crt32/string/stricmp.c b/private/crt32/string/stricmp.c
new file mode 100644
index 000000000..8565e25e3
--- /dev/null
+++ b/private/crt32/string/stricmp.c
@@ -0,0 +1,80 @@
+/***
+*stricmp.c - contains case-insensitive string comp routine _stricmp/_strcmpi
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains _stricmp(), also known as _strcmpi()
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 07-25-90 SBM Added #include <ctype.h>
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+* 11-08-91 GJF Fixed compiler warning.
+* 09-27-93 CFW Avoid cast bug.
+* 06-28-94 SRW Rewrite to use same ANSI specific tolower logic as x86
+* assembler version is i386\stricmp.asm
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <ctype.h>
+
+/***
+*int _stricmp(dst, src), _strcmpi(dst, src) - compare strings, ignore case
+*
+*Purpose:
+* _stricmp/_strcmpi perform a case-insensitive string comparision.
+* For differences, upper case letters are mapped to lower case.
+* Thus, "abc_" < "ABCD" since "_" < "d".
+*
+*Entry:
+* char *dst, *src - strings to compare
+*
+*Return:
+* <0 if dst < src
+* 0 if dst = src
+* >0 if dst > src
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _stricmp (
+ const char * dst,
+ const char * src
+ )
+{
+ return( _strcmpi(dst,src) );
+}
+
+
+int _CALLTYPE1 _strcmpi(const char * dst, const char * src)
+{
+ unsigned char f,l;
+
+ do {
+ f = *dst++;
+ l = *src++;
+ if (f != l) {
+ if (f>='A' && f<='Z') {
+ f = f - 'A' + 'a';
+ }
+ if (l>='A' && l<='Z') {
+ l = l - 'A' + 'a';
+ }
+ if (f!=l) {
+ return f-l;
+ }
+ }
+ }
+ while (f);
+
+ return(0);
+}
diff --git a/private/crt32/string/stricoll.c b/private/crt32/string/stricoll.c
new file mode 100644
index 000000000..ec4465d77
--- /dev/null
+++ b/private/crt32/string/stricoll.c
@@ -0,0 +1,95 @@
+/***
+*stricoll.c - Collate locale strings without regard to case
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare two strings using the locale LC_COLLATE information.
+*
+*Revision History:
+* 10-16-91 ETC Created from strcoll.c
+* 12-08-91 ETC Remove availability under !_INTL; updated api; add mt.
+* 04-06-92 KRS Make work without _INTL switches too.
+* 08-19-92 KRS Activate NLS support.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-16-92 KRS Optimize for CompareStringW by using -1 for string len.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int _stricoll() - Collate locale strings without regard to case
+*
+*Purpose:
+* Compare two strings using the locale LC_COLLATE information
+* without regard to case.
+*
+*Entry:
+* const char *s1 = pointer to the first string
+* const char *s2 = pointer to the second string
+*
+*Exit:
+* Less than 0 = first string less than second string
+* 0 = strings are equal
+* Greater than 0 = first string greater than second string
+*
+*Exceptions:
+* NLSCMPERROR = error
+*
+*******************************************************************************/
+
+int _CRTAPI1 _stricoll (
+ const char *_string1,
+ const char *_string2
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ size_t size1, size2;
+ wchar_t *wstring1, *wstring2;
+ int ret;
+
+ _mlock (_LC_CTYPE_LOCK);
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ return _stricmp(_string1, _string2);
+ }
+
+ size1 = strlen(_string1) + 1;
+ size2 = strlen(_string2) + 1;
+ wstring1 = malloc (size1 * sizeof(wchar_t));
+ wstring2 = malloc (size2 * sizeof(wchar_t));
+ if (!wstring1 || !wstring2)
+ goto error_cleanup;
+ if (!MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, _string1, -1,
+ wstring1, size1)) goto error_cleanup;
+ if (!MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, _string2, -1,
+ wstring2, size2)) goto error_cleanup;
+ if (!(ret=CompareStringW(_lc_handle[LC_COLLATE], NORM_IGNORECASE,
+ wstring1, -1, wstring2, -1))) goto error_cleanup;
+
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ free (wstring1);
+ free (wstring2);
+ return (ret - 2);
+
+error_cleanup:
+ _munlock (_LC_COLLATE_LOCK);
+ _munlock (_LC_CTYPE_LOCK);
+ free (wstring1);
+ free (wstring2);
+ return NLSCMPERROR;
+#else
+ return _stricmp(_string1, _string2);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/strlen.c b/private/crt32/string/strlen.c
new file mode 100644
index 000000000..362173dc7
--- /dev/null
+++ b/private/crt32/string/strlen.c
@@ -0,0 +1,54 @@
+/***
+*strlen.c - contains strlen() routine
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* strlen returns the length of a null-terminated string,
+* not including the null byte itself.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 04-01-91 SRW Add #pragma function for i386 _WIN32_ and _CRUISER_
+* builds
+* 04-05-91 GJF Speed up just a little bit.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_CRUISER_) || defined(i386)
+#pragma function(strlen)
+#endif /* ndef _CRUISER_ */
+
+/***
+*strlen - return the length of a null-terminated string
+*
+*Purpose:
+* Finds the length in bytes of the given string, not including
+* the final null character.
+*
+*Entry:
+* const char * str - string whose length is to be computed
+*
+*Exit:
+* length of the string "str", exclusive of the final null byte
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 strlen (
+ const char * str
+ )
+{
+ const char *eos = str;
+
+ while( *eos++ ) ;
+
+ return( (int)(eos - str - 1) );
+}
diff --git a/private/crt32/string/strlwr.c b/private/crt32/string/strlwr.c
new file mode 100644
index 000000000..24bc08368
--- /dev/null
+++ b/private/crt32/string/strlwr.c
@@ -0,0 +1,137 @@
+/***
+*strlwr.c - routine to map upper-case characters in a string to lower-case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts all the upper case characters in a string to lower case,
+* in place.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 09-18-91 ETC Locale support under _INTL switch.
+* 12-08-91 ETC Updated nlsapi; added multithread.
+* 08-19-92 KRS Activated NLS support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <limits.h> // for INT_MAX
+#include <os2dll.h>
+
+/***
+*char *_strlwr(string) - map upper-case characters in a string to lower-case
+*
+*Purpose:
+* _strlwr() converts upper-case characters in a null-terminated string
+* to their lower-case equivalents. Conversion is done in place and
+* characters other than upper-case letters are not modified.
+*
+* In the C locale, this function modifies only 7-bit ASCII characters
+* in the range 0x41 through 0x5A ('A' through 'Z').
+*
+* If the locale is not the 'C' locale, MapString() is used to do
+* the work. Assumes enough space in the string to hold result.
+*
+*Entry:
+* char *string - string to change to lower case
+*
+*Exit:
+* input string address
+*
+*Exceptions:
+* The original string is returned unchanged on any error.
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strlwr (
+ char * string
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ char *cp; /* traverses string for C locale conversion */
+ wchar_t *wsrc = NULL; /* wide version of string in original case */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP))
+ {
+ _munlock (_LC_CTYPE_LOCK);
+
+ for (cp=string; *cp; ++cp)
+ {
+ if ('A' <= *cp && *cp <= 'Z')
+ *cp += 'a' - 'A';
+ }
+
+ return(string);
+ } /* C locale */
+
+ /* Algorithm for non-C locale: */
+ /* Convert string to wide-character wsrc string */
+ /* Map wrc string to wide-character wdst string in alternate case */
+ /* Convert wdst string to char string and place in user buffer */
+
+ /* Allocate maximum required space for wsrc */
+ srclen = strlen(string) + 1;
+ if ((wsrc = (wchar_t *) malloc(srclen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Convert string to wide-character wsrc string */
+ if ((srclen=MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, string,
+ srclen, wsrc, srclen)) == 0)
+ goto error_cleanup;
+
+ /* Inquire size of wdst string */
+ if ((dstlen=LCMapStringW (_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc,
+ srclen, wdst, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst */
+ if ((wdst = (wchar_t *) malloc(dstlen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if (LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc,
+ srclen, wdst, dstlen) == 0)
+ goto error_cleanup;
+
+ /* Convert wdst string to char string and place in user buffer */
+ srclen = INT_MAX; /* may overwrite length of user string */
+ if (WideCharToMultiByte(_lc_codepage, WC_COMPOSITECHECK|WC_SEPCHARS,
+ wdst, dstlen, string, srclen, NULL, NULL) == 0)
+ goto error_cleanup; /* can't recover here if fail */
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ free (wsrc);
+ free (wdst);
+ return (string);
+
+#else
+ char * cp;
+
+ for (cp=string; *cp; ++cp)
+ {
+ if ('A' <= *cp && *cp <= 'Z')
+ *cp += 'a' - 'A';
+ }
+
+ return(string);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/strncat.c b/private/crt32/string/strncat.c
new file mode 100644
index 000000000..a1e79343a
--- /dev/null
+++ b/private/crt32/string/strncat.c
@@ -0,0 +1,63 @@
+/***
+*strncat.c - append n chars of string to new string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines strncat() - appends n characters of string onto
+* end of other string
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *strncat(front, back, count) - append count chars of back onto front
+*
+*Purpose:
+* Appends at most count characters of the string back onto the
+* end of front, and ALWAYS terminates with a null character.
+* If count is greater than the length of back, the length of back
+* is used instead. (Unlike strncpy, this routine does not pad out
+* to count characters).
+*
+*Entry:
+* char *front - string to append onto
+* char *back - string to append
+* unsigned count - count of max characters to append
+*
+*Exit:
+* returns a pointer to string appended onto (front).
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strncat (
+ char * front,
+ const char * back,
+ size_t count
+ )
+{
+ char *start = front;
+
+ while (*front++)
+ ;
+ front--;
+
+ while (count--)
+ if (!(*front++ = *back++))
+ return(start);
+
+ *front = '\0';
+ return(start);
+}
diff --git a/private/crt32/string/strncmp.c b/private/crt32/string/strncmp.c
new file mode 100644
index 000000000..3987ff769
--- /dev/null
+++ b/private/crt32/string/strncmp.c
@@ -0,0 +1,61 @@
+/***
+*strncmp.c - compare first n characters of two strings
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines strncmp() - compare first n characters of two strings
+* for lexical order.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*int strncmp(first, last, count) - compare first count chars of strings
+*
+*Purpose:
+* Compares two strings for lexical order. The comparison stops
+* after: (1) a difference between the strings is found, (2) the end
+* of the strings is reached, or (3) count characters have been
+* compared.
+*
+*Entry:
+* char *first, *last - strings to compare
+* unsigned count - maximum number of characters to compare
+*
+*Exit:
+* returns <0 if first < last
+* returns 0 if first == last
+* returns >0 if first > last
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 strncmp (
+ const char * first,
+ const char * last,
+ size_t count
+ )
+{
+ if (!count)
+ return(0);
+
+ while (--count && *first && *first == *last)
+ {
+ first++;
+ last++;
+ }
+
+ return( *(unsigned char *)first - *(unsigned char *)last );
+}
diff --git a/private/crt32/string/strncpy.c b/private/crt32/string/strncpy.c
new file mode 100644
index 000000000..96b75a155
--- /dev/null
+++ b/private/crt32/string/strncpy.c
@@ -0,0 +1,59 @@
+/***
+*strncpy.c - copy at most n characters of string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines strncpy() - copy at most n characters of string
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *strncpy(dest, source, count) - copy at most n characters
+*
+*Purpose:
+* Copies count characters from the source string to the
+* destination. If count is less than the length of source,
+* NO NULL CHARACTER is put onto the end of the copied string.
+* If count is greater than the length of sources, dest is padded
+* with null characters to length count.
+*
+*
+*Entry:
+* char *dest - pointer to destination
+* char *source - source string for copy
+* unsigned count - max number of characters to copy
+*
+*Exit:
+* returns dest
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strncpy (
+ char * dest,
+ const char * source,
+ size_t count
+ )
+{
+ char *start = dest;
+
+ while (count && (*dest++ = *source++)) /* copy string */
+ count--;
+
+ if (count) /* pad out with zeroes */
+ while (--count)
+ *dest++ = '\0';
+
+ return(start);
+}
diff --git a/private/crt32/string/strnicmp.c b/private/crt32/string/strnicmp.c
new file mode 100644
index 000000000..bdba31dd9
--- /dev/null
+++ b/private/crt32/string/strnicmp.c
@@ -0,0 +1,76 @@
+/***
+*strnicmp.c - compare n chars of strings, ignoring case
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _strnicmp() - Compares at most n characters of two strings,
+* without regard to case.
+*
+*Revision History:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 10-11-91 GJF Bug fix! Comparison of final bytes must use unsigned
+* chars.
+* 09-27-93 CFW Avoid cast bug.
+* 06-28-94 SRW Rewrite to use same ANSI specific tolower logic as x86
+* assembler version is i386\strnicmp.asm
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+#include <string.h>
+
+/***
+*int _strnicmp(first, last, count) - compares count char of strings, ignore case
+*
+*Purpose:
+* Compare the two strings for lexical order. Stops the comparison
+* when the following occurs: (1) strings differ, (2) the end of the
+* strings is reached, or (3) count characters have been compared.
+* For the purposes of the comparison, upper case characters are
+* converted to lower case.
+*
+*Entry:
+* char *first, *last - strings to compare
+* unsigned count - maximum number of characters to compare
+*
+*Exit:
+* returns <0 if first < last
+* returns 0 if first == last
+* returns >0 if first > last
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _strnicmp (
+ const char * first,
+ const char * last,
+ size_t count
+ )
+{
+ unsigned char f,l;
+
+ if (count) do {
+ f = *first++;
+ l = *last++;
+ if (f != l) {
+ if (f>='A' && f<='Z') {
+ f = f - 'A' + 'a';
+ }
+ if (l>='A' && l<='Z') {
+ l = l - 'A' + 'a';
+ }
+ if (f!=l) {
+ return f-l;
+ }
+ }
+ }
+ while (--count && f);
+
+ return(0);
+}
diff --git a/private/crt32/string/strnset.c b/private/crt32/string/strnset.c
new file mode 100644
index 000000000..400ff2e7f
--- /dev/null
+++ b/private/crt32/string/strnset.c
@@ -0,0 +1,54 @@
+/***
+*strnset.c - set first n characters to single character
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _strnset() - sets at most the first n characters of a string
+* to a given character.
+*
+*Revision History:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *_strnset(string, val, count) - set at most count characters to val
+*
+*Purpose:
+* Sets the first count characters of string the character value.
+* If the length of string is less than count, the length of
+* string is used in place of n.
+*
+*Entry:
+* char *string - string to set characters in
+* char val - character to fill with
+* unsigned count - count of characters to fill
+*
+*Exit:
+* returns string, now filled with count copies of val.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strnset (
+ char * string,
+ int val,
+ size_t count
+ )
+{
+ char *start = string;
+
+ while (count-- && *string)
+ *string++ = (char)val;
+
+ return(start);
+}
diff --git a/private/crt32/string/strpbrk.c b/private/crt32/string/strpbrk.c
new file mode 100644
index 000000000..e28815571
--- /dev/null
+++ b/private/crt32/string/strpbrk.c
@@ -0,0 +1,2 @@
+#define SSTRPBRK
+#include "strspn.c"
diff --git a/private/crt32/string/strrchr.c b/private/crt32/string/strrchr.c
new file mode 100644
index 000000000..e533aa34e
--- /dev/null
+++ b/private/crt32/string/strrchr.c
@@ -0,0 +1,59 @@
+/***
+*strrchr.c - find last occurrence of character in string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines strrchr() - find the last occurrence of a given character
+* in a string.
+*
+*Revision History:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3, removed now redundant
+* #include <stddef.h>
+* 10-02-90 GJF New-style function declarator.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *strrchr(string, ch) - find last occurrence of ch in string
+*
+*Purpose:
+* Finds the last occurrence of ch in string. The terminating
+* null character is used as part of the search.
+*
+*Entry:
+* char *string - string to search in
+* char ch - character to search for
+*
+*Exit:
+* returns a pointer to the last occurrence of ch in the given
+* string
+* returns NULL if ch does not occurr in the string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strrchr (
+ const char * string,
+ int ch
+ )
+{
+ char *start = (char *)string;
+
+ while (*string++) /* find end of string */
+ ;
+ /* search towards front */
+ while (--string != start && *string != (char)ch)
+ ;
+
+ if (*string == (char)ch) /* char found ? */
+ return( (char *)string );
+
+ return(NULL);
+}
diff --git a/private/crt32/string/strrev.c b/private/crt32/string/strrev.c
new file mode 100644
index 000000000..5c5642b58
--- /dev/null
+++ b/private/crt32/string/strrev.c
@@ -0,0 +1,58 @@
+/***
+*strrev.c - reverse a string in place
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _strrev() - reverse a string in place (not including
+* '\0' character)
+*
+*Revision History:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *_strrev(string) - reverse a string in place
+*
+*Purpose:
+* Reverses the order of characters in the string. The terminating
+* null character remains in place.
+*
+*Entry:
+* char *string - string to reverse
+*
+*Exit:
+* returns string - now with reversed characters
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strrev (
+ char * string
+ )
+{
+ char *start = string;
+ char *left = string;
+ char ch;
+
+ while (*string++) /* find end of string */
+ ;
+ string -= 2;
+
+ while (left < string)
+ {
+ ch = *left;
+ *left++ = *string;
+ *string-- = ch;
+ }
+
+ return(start);
+}
diff --git a/private/crt32/string/strset.c b/private/crt32/string/strset.c
new file mode 100644
index 000000000..957f28163
--- /dev/null
+++ b/private/crt32/string/strset.c
@@ -0,0 +1,58 @@
+/***
+*strset.c - sets all characters of string to given character
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _strset() - sets all of the characters in a string (except
+* the '\0') equal to a given character.
+*
+*Revision History:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Compiles cleanly with -W3
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+#if defined(_M_ALPHA) || defined(_M_MRX000) || defined(_M_PPC)
+#pragma function(_strset)
+#endif
+
+/***
+*char *_strset(string, val) - sets all of string to val
+*
+*Purpose:
+* Sets all of characters in string (except the terminating '/0'
+* character) equal to val.
+*
+*
+*Entry:
+* char *string - string to modify
+* char val - value to fill string with
+*
+*Exit:
+* returns string -- now filled with val's
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strset (
+ char * string,
+ int val
+ )
+{
+ char *start = string;
+
+ while (*string)
+ *string++ = (char)val;
+
+ return(start);
+}
diff --git a/private/crt32/string/strspn.c b/private/crt32/string/strspn.c
new file mode 100644
index 000000000..f49e8f90c
--- /dev/null
+++ b/private/crt32/string/strspn.c
@@ -0,0 +1,179 @@
+/***
+*strspn.c - find length of initial substring of chars from a control string
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines strspn() - finds the length of the initial substring of
+* a string consisting entirely of characters from a control string.
+*
+* defines strcspn()- finds the length of the initial substring of
+* a string consisting entirely of characters not in a control string.
+*
+* defines strpbrk()- finds the index of the first character in a string
+* that is not in a control string
+*
+*Revision History:
+* 06-01-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Removed now redundant #include <stddef.h>
+* 10-02-90 GJF New-style function declarators.
+* 12-04-90 SRW Made it default to compiling for strspn
+* 05-21-93 GJF Used unsigned char pointers to access control and
+* source strings.
+*
+********************************************************************************
+
+/* Determine which routine we're compiling for (default to STRSPN) */
+
+#define _STRSPN 1
+#define _STRCSPN 2
+#define _STRPBRK 3
+
+#if defined(SSTRCSPN)
+#define ROUTINE _STRCSPN
+#elif defined(SSTRPBRK)
+#define ROUTINE _STRPBRK
+#else
+#define ROUTINE _STRSPN
+#endif
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*int strspn(string, control) - find init substring of control chars
+*
+*Purpose:
+* Finds the index of the first character in string that does belong
+* to the set of characters specified by control. This is
+* equivalent to the length of the initial substring of string that
+* consists entirely of characters from control. The '\0' character
+* that terminates control is not considered in the matching process.
+*
+*Entry:
+* char *string - string to search
+* char *control - string containing characters not to search for
+*
+*Exit:
+* returns index of first char in string not in control
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+/***
+*int strcspn(string, control) - search for init substring w/o control chars
+*
+*Purpose:
+* returns the index of the first character in string that belongs
+* to the set of characters specified by control. This is equivalent
+* to the length of the length of the initial substring of string
+* composed entirely of characters not in control. Null chars not
+* considered.
+*
+*Entry:
+* char *string - string to search
+* char *control - set of characters not allowed in init substring
+*
+*Exit:
+* returns the index of the first char in string
+* that is in the set of characters specified by control.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+/***
+*char *strpbrk(string, control) - scans string for a character from control
+*
+*Purpose:
+* Finds the first occurence in string of any character from
+* the control string.
+*
+*Entry:
+* char *string - string to search in
+* char *control - string containing characters to search for
+*
+*Exit:
+* returns a pointer to the first character from control found
+* in string.
+* returns NULL if string and control have no characters in common.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+
+/* Routine prototype */
+#if (ROUTINE == _STRSPN)
+size_t _CALLTYPE1 strspn (
+#elif (ROUTINE == _STRCSPN)
+size_t _CALLTYPE1 strcspn (
+#else /* (ROUTINE == STRPBRK) */
+char * _CALLTYPE1 strpbrk (
+#endif
+ const char * string,
+ const char * control
+ )
+{
+ const unsigned char *str = string;
+ const unsigned char *ctrl = control;
+
+ unsigned char map[32];
+ int count;
+
+ /* Clear out bit map */
+ for (count=0; count<32; count++)
+ map[count] = 0;
+
+ /* Set bits in control map */
+ while (*ctrl)
+ {
+ map[*ctrl >> 3] |= (1 << (*ctrl & 7));
+ ctrl++;
+ }
+
+#if (ROUTINE == _STRSPN)
+
+ /* 1st char NOT in control map stops search */
+ if (*str)
+ {
+ count=0;
+ while (map[*str >> 3] & (1 << (*str & 7)))
+ {
+ count++;
+ str++;
+ }
+ return(count);
+ }
+ return(0);
+
+#elif (ROUTINE == _STRCSPN)
+
+ /* 1st char in control map stops search */
+ count=0;
+ map[0] |= 1; /* null chars not considered */
+ while (!(map[*str >> 3] & (1 << (*str & 7))))
+ {
+ count++;
+ str++;
+ }
+ return(count);
+
+#else /* (ROUTINE == _STRPBRK) */
+
+ /* 1st char in control map stops search */
+ while (*str)
+ {
+ if (map[*str >> 3] & (1 << (*str & 7)))
+ return((char *)str);
+ str++;
+ }
+ return(NULL);
+
+#endif
+
+}
diff --git a/private/crt32/string/strstr.c b/private/crt32/string/strstr.c
new file mode 100644
index 000000000..d523dbbef
--- /dev/null
+++ b/private/crt32/string/strstr.c
@@ -0,0 +1,68 @@
+/***
+*strstr.c - search for one string inside another
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines strstr() - search for one string inside another
+*
+*Revision History:
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Removed now redundant #include <stddef.h>
+* 10-02-90 GJF New-style function declarator.
+* 03-14-94 GJF If string2 is empty, return string1.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*char *strstr(string1, string2) - search for string2 in string1
+*
+*Purpose:
+* finds the first occurrence of string2 in string1
+*
+*Entry:
+* char *string1 - string to search in
+* char *string2 - string to search for
+*
+*Exit:
+* returns a pointer to the first occurrence of string2 in
+* string1, or NULL if string2 does not occur in string1
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 strstr (
+ const char * str1,
+ const char * str2
+ )
+{
+ char *cp = (char *) str1;
+ char *s1, *s2;
+
+ if ( !*str2 )
+ return(str1);
+
+ while (*cp)
+ {
+ s1 = cp;
+ s2 = (char *) str2;
+
+ while ( *s1 && *s2 && !(*s1-*s2) )
+ s1++, s2++;
+
+ if (!*s2)
+ return(cp);
+
+ cp++;
+ }
+
+ return(NULL);
+
+}
diff --git a/private/crt32/string/strtok.c b/private/crt32/string/strtok.c
new file mode 100644
index 000000000..8c51d4f94
--- /dev/null
+++ b/private/crt32/string/strtok.c
@@ -0,0 +1,125 @@
+/***
+*strtok.c - tokenize a string with given delimiters
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines strtok() - breaks string into series of token
+* via repeated calls.
+*
+*Revision History:
+* 06-01-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 08-14-90 SBM Removed now redundant #include <stddef.h>
+* 10-02-90 GJF New-style function declarator.
+* 07-17-91 GJF Multi-thread support for Win32 [_WIN32_].
+* 10-26-91 GJF Fixed nasty bug - search for end-of-token could run
+* off the end of the string.
+* 02-17-93 GJF Changed for new _getptd().
+* 05-21-93 GJF Used unsigned char pointers to access control and
+* source strings.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#ifdef MTHREAD
+#include <os2dll.h>
+#endif
+
+/***
+*char *strtok(string, control) - tokenize string with delimiter in control
+*
+*Purpose:
+* strtok considers the string to consist of a sequence of zero or more
+* text tokens separated by spans of one or more control chars. the first
+* call, with string specified, returns a pointer to the first char of the
+* first token, and will write a null char into string immediately
+* following the returned token. subsequent calls with zero for the first
+* argument (string) will work thru the string until no tokens remain. the
+* control string may be different from call to call. when no tokens remain
+* in string a NULL pointer is returned. remember the control chars with a
+* bit map, one bit per ascii char. the null char is always a control char.
+*
+*Entry:
+* char *string - string to tokenize, or NULL to get next token
+* char *control - string of characters to use as delimiters
+*
+*Exit:
+* returns pointer to first token in string, or if string
+* was NULL, to next token
+* returns NULL when no more tokens remain.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CRTAPI1 strtok (
+ char * string,
+ const char * control
+ )
+{
+ unsigned char *str = string;
+ const unsigned char *ctrl = control;
+
+ unsigned char map[32];
+ int count;
+ char *token;
+
+#ifdef MTHREAD
+ _ptiddata ptd = _getptd();
+#else
+ static char *nextoken;
+#endif
+
+ /* Clear control map */
+ for (count = 0; count < 32; count++)
+ map[count] = 0;
+
+ /* Set bits in delimiter table */
+ do {
+ map[*ctrl >> 3] |= (1 << (*ctrl & 7));
+ } while (*ctrl++);
+
+ /* If string==NULL, continue with previous string */
+ if (!str)
+
+#ifdef MTHREAD
+ str = ptd->_token;
+#else
+ str = nextoken;
+#endif
+
+ /* Find beginning of token (skip over leading delimiters). Note that
+ * there is no token iff this loop sets string to point to the terminal
+ * null (*string == '\0') */
+ while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
+ str++;
+
+ token = str;
+
+ /* Find the end of the token. If it is not the end of the string,
+ * put a null there. */
+ for ( ; *str ; str++ )
+ if ( map[*str >> 3] & (1 << (*str & 7)) ) {
+ *str++ = '\0';
+ break;
+ }
+
+ /* Update nextoken (or the corresponding field in the per-thread data
+ * structure */
+#ifdef MTHREAD
+ ptd->_token = str;
+#else
+ nextoken = str;
+#endif
+
+ /* Determine if a token has been found. */
+ if ( token == str )
+ return NULL;
+ else
+ return token;
+}
diff --git a/private/crt32/string/strupr.c b/private/crt32/string/strupr.c
new file mode 100644
index 000000000..fcab9dbde
--- /dev/null
+++ b/private/crt32/string/strupr.c
@@ -0,0 +1,138 @@
+/***
+*strupr.c - routine to map lower-case characters in a string to upper-case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts all the lower case characters in string to upper case
+* in place.
+*
+*Revision History:
+* 05-31-89 JCR C version created.
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 01-18-91 GJF ANSI naming.
+* 09-18-91 ETC Locale support under _INTL switch.
+* 12-08-91 ETC Updated nlsapi; added multithread.
+* 08-19-92 KRS Activated NLS Support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 03-10-93 CFW Remove UNDONE comment.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <limits.h> /* for INT_MAX */
+#include <os2dll.h>
+
+/***
+*char *_strupr(string) - map lower-case characters in a string to upper-case
+*
+*Purpose:
+* _strupr() converts lower-case characters in a null-terminated string
+* to their upper-case equivalents. Conversion is done in place and
+* characters other than lower-case letters are not modified.
+*
+* In the C locale, this function modifies only 7-bit ASCII characters
+* in the range 0x61 through 0x7A ('a' through 'z').
+*
+* If the locale is not the 'C' locale, MapStringW() is used to do
+* the work. Assumes enough space in the string to hold result.
+*
+*Entry:
+* char *string - string to change to upper case
+*
+*Exit:
+* input string address
+*
+*Exceptions:
+* The original string is returned unchanged on any error.
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strupr (
+ char * string
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ char *cp; /* traverses string for C locale conversion */
+ wchar_t *wsrc = NULL; /* wide version of string in original case */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP))
+ {
+ _munlock (_LC_CTYPE_LOCK);
+
+ for (cp=string; *cp; ++cp)
+ {
+ if ('a' <= *cp && *cp <= 'z')
+ *cp += 'A' - 'a';
+ }
+
+ return(string);
+ } /* C locale */
+
+ /* Algorithm for non-C locale: */
+ /* Convert string to wide-character wsrc string */
+ /* Map wrc string to wide-character wdst string in alternate case */
+ /* Convert wdst string to char string and place in user buffer */
+
+ /* Allocate maximum required space for wsrc */
+ srclen = strlen(string) + 1;
+ if ((wsrc = (wchar_t *) malloc(srclen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Convert string to wide-character wsrc string */
+ if ((srclen=MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED, string,
+ srclen, wsrc, srclen)) == 0)
+ goto error_cleanup;
+
+ /* Inquire size of wdst string */
+ if ((dstlen=LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_UPPERCASE, wsrc,
+ srclen, wdst, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst */
+ if ((wdst = (wchar_t *) malloc(dstlen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if ((dstlen=LCMapStringW (_lc_handle[LC_CTYPE], LCMAP_UPPERCASE, wsrc,
+ srclen, wdst, dstlen)) == 0)
+ goto error_cleanup;
+
+ /* Convert wdst string to char string and place in user buffer */
+ srclen = INT_MAX; /* may overwrite length of user string */
+ if (WideCharToMultiByte(_lc_codepage, WC_COMPOSITECHECK|WC_SEPCHARS,
+ wdst, dstlen, string, srclen, NULL, NULL) == 0)
+ goto error_cleanup; /* can't recover here if fail */
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ free (wsrc);
+ free (wdst);
+ return (string);
+
+#else
+ char * cp;
+
+ for (cp=string; *cp; ++cp)
+ {
+ if ('a' <= *cp && *cp <= 'z')
+ *cp += 'A' - 'a';
+ }
+
+ return(string);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/strxfrm.c b/private/crt32/string/strxfrm.c
new file mode 100644
index 000000000..9a3d4dd86
--- /dev/null
+++ b/private/crt32/string/strxfrm.c
@@ -0,0 +1,149 @@
+/***
+*strxfrm.c - Transform a string using locale information
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Transform a string using the locale information as set by
+* LC_COLLATE.
+*
+*Revision History:
+* 03-21-89 JCR Module created.
+* 06-20-89 JCR Removed _LOAD_DGROUP code
+* 02-27-90 GJF Fixed calling type, #include <cruntime.h>, fixed
+* copyright.
+* 10-02-90 GJF New-style function declarator.
+* 10-02-91 ETC Non-C locale support under _INTL switch.
+* 12-09-91 ETC Updated api; added multithread.
+* 12-18-91 ETC Don't convert output of LCMapString.
+* 08-18-92 KRS Activate NLS API. Fix behavior.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-11-92 SKS Need to handle count=0 in non-INTL code
+* 12-15-92 KRS Handle return value according to ANSI.
+* 01-18-93 CFW Removed unreferenced variable "dummy".
+* 09-27-93 CFW Use NLS API calls properly.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <limits.h>
+#include <malloc.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*size_t strxfrm() - Transform a string using locale information
+*
+*Purpose:
+* Transform the string pointer to by _string2 and place the
+* resulting string into the array pointer to by _string1.
+* No more than _count characters are place into the
+* resulting string (including the null).
+*
+* The transformation is such that if strcmp() is applied to
+* the two transformed strings, the return value is equal to
+* the result of strcoll() applied to the two original strings.
+* Thus, the conversion must take the locale LC_COLLATE info
+* into account.
+* [ANSI]
+*
+* The value of the following expression is the size of the array
+* needed to hold the transformation of the source string:
+*
+* 1 + strxfrm(NULL,string,0)
+*
+* NOTE: Currently, the C libraries support the "C" locale only.
+* Thus, strxfrm() simply resolves to strncpy()/strlen().
+*
+*Entry:
+* char *_string1 = result string
+* const char *_string2 = source string
+* size_t _count = max chars to move
+*
+* [If _count is 0, _string1 is permitted to by NULL.]
+*
+*Exit:
+* Length of the transformed string (not including the terminating
+* null). If the value returned is >= _count, the contents of the
+* _string1 array are indeterminate.
+*
+*Exceptions:
+* Non-standard: if OM/API error, return INT_MAX.
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 strxfrm (
+ char *_string1,
+ const char *_string2,
+ size_t _count
+ )
+{
+#ifndef _INTL
+ strncpy(_string1, _string2, _count);
+ return strlen(_string2);
+#else
+ wchar_t *wsrc = NULL; /* wide version of string in original case */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+ int retval = INT_MAX; /* NON-ANSI: default if OM or API error */
+
+ _mlock (_LC_CTYPE_LOCK);
+ _mlock (_LC_COLLATE_LOCK);
+
+ if ((_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP)) {
+ _munlock (_LC_CTYPE_LOCK);
+ _munlock (_LC_COLLATE_LOCK);
+ strncpy(_string1, _string2, _count);
+ return strlen(_string2);
+ }
+
+ /* Algorithm for non-C locale: */
+ /* Convert string to wide-character wsrc string */
+ /* Map wrc string to wide-character wdst string in alternate case */
+ /* Convert wdst string to char string and place in user buffer */
+
+ /* Allocate maximum required space for wsrc */
+ srclen = strlen(_string2) * sizeof(wchar_t);
+ if ((wsrc = (wchar_t *) malloc(srclen)) == NULL)
+ goto error_cleanup;
+
+ /* Convert string to wide-character wsrc string */
+ if ((srclen=MultiByteToWideChar(_lc_codepage,MB_PRECOMPOSED, _string2,
+ -1, wsrc, srclen)) == 0)
+ goto error_cleanup;
+
+ /* Need to transform into a buffer and then copy _count bytes
+ from the buffer to user string; API will fail if target string
+ not long enough */
+
+ /* Inquire size of wdst string */
+ if ((dstlen = LCMapStringW(_lc_handle[LC_COLLATE],
+ LCMAP_SORTKEY, wsrc, srclen, NULL, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst - dstlen is in bytes */
+ if ((wdst = (wchar_t *) malloc(dstlen)) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if (LCMapStringW(_lc_handle[LC_COLLATE], LCMAP_SORTKEY,
+ wsrc, srclen, wdst, dstlen) == 0)
+ goto error_cleanup;
+
+ retval = strlen((char *)wdst);
+ /* Copy _count bytes to user buffer, or up to first null */
+ strncpy (_string1, (char *) wdst, _count);
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ _munlock (_LC_COLLATE_LOCK);
+ free (wsrc);
+ free (wdst);
+ return (size_t)retval;
+
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/wcscat.c b/private/crt32/string/wcscat.c
new file mode 100644
index 000000000..925492aa3
--- /dev/null
+++ b/private/crt32/string/wcscat.c
@@ -0,0 +1,87 @@
+/***
+*wcscat.c - contains wcscat() and wcscpy()
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* wcscat() appends one wchar_t string onto another.
+* wcscpy() copies one wchar_t string into another.
+*
+* wcscat() concatenates (appends) a copy of the source string to the
+* end of the destination string, returning the destination string.
+* Strings are wide-character strings.
+*
+* wcscpy() copies the source string to the spot pointed to be
+* the destination string, returning the destination string.
+* Strings are wide-character strings.
+*
+*Revision History:
+* 09-09-91 ETC Created from strcat.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcscat(dst, src) - concatenate (append) one wchar_t string to another
+*
+*Purpose:
+* Concatenates src onto the end of dest. Assumes enough
+* space in dest.
+*
+*Entry:
+* wchar_t *dst - wchar_t string to which "src" is to be appended
+* const wchar_t *src - wchar_t string to be appended to the end of "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcscat (
+ wchar_t * dst,
+ const wchar_t * src
+ )
+{
+ wchar_t * cp = dst;
+
+ while( *cp )
+ cp++; /* find end of dst */
+
+ while( *cp++ = *src++ ) ; /* Copy src to end of dst */
+
+ return( dst ); /* return dst */
+
+}
+
+
+/***
+*wchar_t *wcscpy(dst, src) - copy one wchar_t string over another
+*
+*Purpose:
+* Copies the wchar_t string src into the spot specified by
+* dest; assumes enough room.
+*
+*Entry:
+* wchar_t * dst - wchar_t string over which "src" is to be copied
+* const wchar_t * src - wchar_t string to be copied over "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcscpy(wchar_t * dst, const wchar_t * src)
+{
+ wchar_t * cp = dst;
+
+ while( *cp++ = *src++ )
+ ; /* Copy src over dst */
+
+ return( dst );
+}
diff --git a/private/crt32/string/wcschr.c b/private/crt32/string/wcschr.c
new file mode 100644
index 000000000..3f5814859
--- /dev/null
+++ b/private/crt32/string/wcschr.c
@@ -0,0 +1,48 @@
+/***
+*wcschr.c - search a wchar_t string for a given wchar_t character
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcschr() - search a wchar_t string for a wchar_t character
+*
+*Revision History:
+* 09-09-91 ETC Created from strchr.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcschr(string, c) - search a string for a wchar_t character
+*
+*Purpose:
+* Searches a wchar_t string for a given wchar_t character,
+* which may be the null character L'\0'.
+*
+*Entry:
+* wchar_t *string - wchar_t string to search in
+* wchar_t c - wchar_t character to search for
+*
+*Exit:
+* returns pointer to the first occurence of c in string
+* returns NULL if c does not occur in string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcschr (
+ const wchar_t * string,
+ wchar_t ch
+ )
+{
+ while (*string && *string != (wchar_t)ch)
+ string++;
+
+ if (*string == (wchar_t)ch)
+ return((wchar_t *)string);
+ return(NULL);
+}
diff --git a/private/crt32/string/wcscmp.c b/private/crt32/string/wcscmp.c
new file mode 100644
index 000000000..7b9d3b26c
--- /dev/null
+++ b/private/crt32/string/wcscmp.c
@@ -0,0 +1,59 @@
+/***
+*wcscmp.c - routine to compare two wchar_t strings (for equal, less, or greater)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compares two wide-character strings, determining their lexical order.
+*
+*Revision History:
+* 09-09-91 ETC Created from strcmp.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wcscmp - compare two wchar_t strings,
+* returning less than, equal to, or greater than
+*
+*Purpose:
+* wcscmp compares two wide-character strings and returns an integer
+* to indicate whether the first is less than the second, the two are
+* equal, or whether the first is greater than the second.
+*
+* Comparison is done wchar_t by wchar_t on an UNSIGNED basis, which is to
+* say that Null wchar_t(0) is less than any other character.
+*
+*Entry:
+* const wchar_t * src - string for left-hand side of comparison
+* const wchar_t * dst - string for right-hand side of comparison
+*
+*Exit:
+* returns -1 if src < dst
+* returns 0 if src == dst
+* returns +1 if src > dst
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 wcscmp (
+ const wchar_t * src,
+ const wchar_t * dst
+ )
+{
+ int ret = 0 ;
+
+ while( ! (ret = (int)(*src - *dst)) && *dst)
+ ++src, ++dst;
+
+ if ( ret < 0 )
+ ret = -1 ;
+ else if ( ret > 0 )
+ ret = 1 ;
+
+ return( ret );
+}
diff --git a/private/crt32/string/wcscoll.c b/private/crt32/string/wcscoll.c
new file mode 100644
index 000000000..8b24fc7b8
--- /dev/null
+++ b/private/crt32/string/wcscoll.c
@@ -0,0 +1,70 @@
+/***
+*wcscoll.c - Collate wide-character locale strings
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare two wchar_t strings using the locale LC_COLLATE information.
+*
+*Revision History:
+* 09-09-91 ETC Created from strcoll.c.
+* 04-06-92 KRS Make work without _INTL also.
+* 08-19-92 KRS Activate NLS support.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int wcscoll() - Collate wide-character locale strings
+*
+*Purpose:
+* Compare two wchar_t strings using the locale LC_COLLATE information.
+* In the C locale, wcscmp() is used to make the comparison.
+*
+*Entry:
+* const wchar_t *s1 = pointer to the first string
+* const wchar_t *s2 = pointer to the second string
+*
+*Exit:
+* -1 = first string less than second string
+* 0 = strings are equal
+* 1 = first string greater than second string
+* This range of return values may differ from other *cmp/*coll functions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 wcscoll (
+ const wchar_t *_string1,
+ const wchar_t *_string2
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ int ret;
+
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_COLLATE_LOCK);
+ return (wcscmp(_string1, _string2));
+ }
+ if (!(ret = CompareStringW(_lc_handle[LC_COLLATE], 0, _string1, -1,
+ _string2, -1))) {
+ _munlock (_LC_COLLATE_LOCK);
+ return (NLSCMPERROR);
+ }
+
+ _munlock (_LC_COLLATE_LOCK);
+ return (ret - 2);
+#else
+ return wcscmp(_string1, _string2);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/wcscspn.c b/private/crt32/string/wcscspn.c
new file mode 100644
index 000000000..fde1815a3
--- /dev/null
+++ b/private/crt32/string/wcscspn.c
@@ -0,0 +1,61 @@
+/***
+*wcscspn.c - find length of initial substring of wide characters
+* not in a control string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcscspn()- finds the length of the initial substring of
+* a string consisting entirely of characters not in a control string
+* (wide-character strings).
+*
+*Revision History:
+* 11-04-91 ETC Created with source from crtdll.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*size_t wcscspn(string, control) - search for init substring w/o control wchars
+*
+*Purpose:
+* returns the index of the first character in string that belongs
+* to the set of characters specified by control. This is equivalent
+* to the length of the length of the initial substring of string
+* composed entirely of characters not in control. Null chars not
+* considered (wide-character strings).
+*
+*Entry:
+* wchar_t *string - string to search
+* wchar_t *control - set of characters not allowed in init substring
+*
+*Exit:
+* returns the index of the first wchar_t in string
+* that is in the set of characters specified by control.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 wcscspn (
+ const wchar_t * string,
+ const wchar_t * control
+ )
+{
+ wchar_t *str = (wchar_t *) string;
+ wchar_t *wcset;
+
+ /* 1st char in control string stops search */
+ while (*str) {
+ for (wcset = (wchar_t *)control; *wcset; wcset++) {
+ if (*wcset == *str) {
+ return str - string;
+ }
+ }
+ str++;
+ }
+ return str - string;
+}
diff --git a/private/crt32/string/wcsdup.c b/private/crt32/string/wcsdup.c
new file mode 100644
index 000000000..22238df23
--- /dev/null
+++ b/private/crt32/string/wcsdup.c
@@ -0,0 +1,57 @@
+/***
+*wcsdup.c - duplicate a wide-character string in malloc'd memory
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsdup() - grab new memory, and duplicate the string into it
+* (wide-character).
+*
+*Revision History:
+* 09-09-91 ETC Created from strdup.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <string.h>
+
+/***
+*wchar_t *_wcsdup(string) - duplicate string into malloc'd memory
+*
+*Purpose:
+* Allocates enough storage via malloc() for a copy of the
+* string, copies the string into the new memory, and returns
+* a pointer to it (wide-character).
+*
+*Entry:
+* wchar_t *string - string to copy into new memory
+*
+*Exit:
+* returns a pointer to the newly allocated storage with the
+* string in it.
+*
+* returns NULL if enough memory could not be allocated, or
+* string was NULL.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsdup (
+ const wchar_t * string
+ )
+{
+ wchar_t *memory;
+
+ if (!string)
+ return(NULL);
+
+ if (memory = (wchar_t *) malloc((wcslen(string)+1) * sizeof(wchar_t)))
+ return(wcscpy(memory,string));
+
+ return(NULL);
+}
diff --git a/private/crt32/string/wcsicmp.c b/private/crt32/string/wcsicmp.c
new file mode 100644
index 000000000..7b85d6595
--- /dev/null
+++ b/private/crt32/string/wcsicmp.c
@@ -0,0 +1,90 @@
+/***
+*wcsicmp.c - contains case-insensitive wide string comp routine _wcsicmp
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains _wcsicmp()
+*
+*Revision History:
+* 09-09-91 ETC Created from stricmp.c.
+* 12-09-91 ETC Use C for neutral locale.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+* 08-19-92 KRS Actived use of CompareStringW.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-15-92 KRS Added robustness to non-_INTL code. Optimize.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <locale.h>
+#include <ctype.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int _wcsicmp(dst, src) - compare wide-character strings, ignore case
+*
+*Purpose:
+* _wcsicmp perform a case-insensitive wchar_t string comparision.
+* _wcsicmp is independent of locale.
+*
+* *** NOTE: the comparison should be done in a neutral locale,
+* provided by the NLSAPI. ****
+*
+*Entry:
+* wchar_t *dst, *src - strings to compare
+*
+*Return:
+* <0 if dst < src
+* 0 if dst = src
+* >0 if dst > src
+* This range of return values may differ from other *cmp/*coll functions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _wcsicmp (
+ const wchar_t * dst,
+ const wchar_t * src
+ )
+{
+ wchar_t f,l;
+ int ret;
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+/* _mlock (_LC_CTYPE_LOCK); */
+
+ if ((_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) &&
+ (_lc_codepage == _CLOCALECP))
+ {
+#endif /* _INTL */
+ do {
+ f = ((*dst <= L'Z') && (*dst >= L'A'))
+ ? *dst + ((wchar_t)(L'a' - L'A'))
+ : *dst;
+ l = ((*src <= L'Z') && (*src >= L'A'))
+ ? *src + ((wchar_t)(L'a' - L'A'))
+ : *src;
+ dst++;
+ src++;
+ } while ((f) && (f == l));
+ ret = (int)((unsigned int)f - (unsigned int)l);
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ }
+ else
+ {
+ ret = CompareStringW(LANG_NEUTRAL,NORM_IGNORECASE,dst,-1,src,-1);
+ /* map return into normal CMP area (-1,0, 1 or ERROR) */
+ ret = (ret) ? (ret-2) : NLSCMPERROR;
+ }
+
+/* _munlock (_LC_CTYPE_LOCK); */
+#endif /* _INTL */
+
+ return ret;
+}
diff --git a/private/crt32/string/wcsicoll.c b/private/crt32/string/wcsicoll.c
new file mode 100644
index 000000000..995a81309
--- /dev/null
+++ b/private/crt32/string/wcsicoll.c
@@ -0,0 +1,73 @@
+/***
+*wcsicoll.c - Collate wide-character locale strings without regard to case
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Compare two wchar_t strings using the locale LC_COLLATE information
+* without regard to case.
+*
+*Revision History:
+* 10-16-91 ETC Created from wcscoll.c.
+* 12-08-91 ETC Added multithread lock.
+* 04-06-92 KRS Make work without _INTL also.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*int _wcsicoll() - Collate wide-character locale strings without regard to case
+*
+*Purpose:
+* Compare two wchar_t strings using the locale LC_COLLATE information
+* without regard to case.
+* In the C locale, _wcsicmp() is used to make the comparison.
+*
+*Entry:
+* const wchar_t *s1 = pointer to the first string
+* const wchar_t *s2 = pointer to the second string
+*
+*Exit:
+* -1 = first string less than second string
+* 0 = strings are equal
+* 1 = first string greater than second string
+* This range of return values may differ from other *cmp/*coll functions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _wcsicoll (
+ const wchar_t *_string1,
+ const wchar_t *_string2
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ int ret;
+
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_COLLATE_LOCK);
+ return (_wcsicmp(_string1, _string2));
+ }
+ ret = CompareStringW(_lc_handle[LC_COLLATE], NORM_IGNORECASE,
+ _string1, -1, _string2, -1);
+
+ _munlock (_LC_COLLATE_LOCK);
+
+ if (!ret)
+ return NLSCMPERROR;
+ else
+ return (ret - 2);
+#else
+ return _wcsicmp(_string1, _string2);
+#endif /* _INTL */
+}
diff --git a/private/crt32/string/wcslen.c b/private/crt32/string/wcslen.c
new file mode 100644
index 000000000..5395f8b07
--- /dev/null
+++ b/private/crt32/string/wcslen.c
@@ -0,0 +1,45 @@
+/***
+*wcslen.c - contains wcslen() routine
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* wcslen returns the length of a null-terminated wide-character string,
+* not including the null wchar_t itself.
+*
+*Revision History:
+* 09-09-91 ETC Created from strlen.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wcslen - return the length of a null-terminated wide-character string
+*
+*Purpose:
+* Finds the length in wchar_t's of the given string, not including
+* the final null wchar_t (wide-characters).
+*
+*Entry:
+* const wchar_t * wcs - string whose length is to be computed
+*
+*Exit:
+* length of the string "wcs", exclusive of the final null wchar_t
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 wcslen (
+ const wchar_t * wcs
+ )
+{
+ const wchar_t *eos = wcs;
+
+ while( *eos++ ) ;
+
+ return( (size_t)(eos - wcs - 1) );
+}
diff --git a/private/crt32/string/wcslwr.c b/private/crt32/string/wcslwr.c
new file mode 100644
index 000000000..b8cf567cc
--- /dev/null
+++ b/private/crt32/string/wcslwr.c
@@ -0,0 +1,100 @@
+/***
+*wcslwr.c - routine to map upper-case characters in a wchar_t string
+* to lower-case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts all the upper case characters in a wchar_t string
+* to lower case, in place.
+*
+*Revision History:
+* 09-09-91 ETC Created from strlwr.c.
+* 04-06-92 KRS Make work without _INTL also.
+* 08-19-92 KRS Activate NLS support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <ctype.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*wchar_t *_wcslwr(string) - map upper-case characters in a string to lower-case
+*
+*Purpose:
+* wcslwr converts upper-case characters in a null-terminated wchar_t
+* string to their lower-case equivalents. The result may be longer or
+* shorter than the original string. Assumes enough space in string
+* to hold the result.
+*
+*Entry:
+* wchar_t *wsrc - wchar_t string to change to lower case
+*
+*Exit:
+* input string address
+*
+*Exceptions:
+* on an error, the original string is unaltered
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcslwr (
+ wchar_t * wsrc
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ wchar_t *p; /* traverses string for C locale conversion */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) {
+ _munlock (_LC_CTYPE_LOCK);
+ for (p=wsrc; *p; p++)
+ if (iswupper(*p))
+ *p = *p - L'A' + L'a';
+ return (wsrc);
+ } /* C locale */
+
+ /* Inquire size of wdst string */
+ srclen = wcslen(wsrc) + 1;
+ if ((dstlen=LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc,
+ srclen, wdst, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst */
+ if ((wdst = (wchar_t *) malloc(dstlen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if (LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_LOWERCASE, wsrc,
+ srclen, wdst, dstlen) == 0)
+ goto error_cleanup;
+
+ /* Copy wdst string to user string */
+ wcscpy (wsrc, wdst);
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ free (wdst);
+#else
+ wchar_t * p;
+
+ for (p=wsrc; *p; ++p)
+ {
+ if (L'A' <= *p && *p <= L'Z')
+ *p += (wchar_t)L'a' - (wchar_t)L'A';
+ }
+#endif /* _INTL */
+ return (wsrc);
+}
diff --git a/private/crt32/string/wcsncat.c b/private/crt32/string/wcsncat.c
new file mode 100644
index 000000000..98b8e5ba4
--- /dev/null
+++ b/private/crt32/string/wcsncat.c
@@ -0,0 +1,61 @@
+/***
+*wcsncat.c - append n chars of string to new string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsncat() - appends n characters of string onto
+* end of other string
+*
+*Revision History:
+* 09-09-91 ETC Created from strncat.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcsncat(front, back, count) - append count chars of back onto front
+*
+*Purpose:
+* Appends at most count characters of the string back onto the
+* end of front, and ALWAYS terminates with a null character.
+* If count is greater than the length of back, the length of back
+* is used instead. (Unlike wcsncpy, this routine does not pad out
+* to count characters).
+*
+*Entry:
+* wchar_t *front - string to append onto
+* wchar_t *back - string to append
+* size_t count - count of max characters to append
+*
+*Exit:
+* returns a pointer to string appended onto (front).
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcsncat (
+ wchar_t * front,
+ const wchar_t * back,
+ size_t count
+ )
+{
+ wchar_t *start = front;
+
+ while (*front++)
+ ;
+ front--;
+
+ while (count--)
+ if (!(*front++ = *back++))
+ return(start);
+
+ *front = L'\0';
+ return(start);
+}
diff --git a/private/crt32/string/wcsncmp.c b/private/crt32/string/wcsncmp.c
new file mode 100644
index 000000000..b9fd8db65
--- /dev/null
+++ b/private/crt32/string/wcsncmp.c
@@ -0,0 +1,57 @@
+/***
+*wcsncmp.c - compare first n characters of two wide-character strings
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsncmp() - compare first n characters of two wchar_t strings
+* for lexical order.
+*
+*Revision History:
+* 09-09-91 ETC Created from strncmp.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*int wcsncmp(first, last, count) - compare first count chars of wchar_t strings
+*
+*Purpose:
+* Compares two strings for lexical order. The comparison stops
+* after: (1) a difference between the strings is found, (2) the end
+* of the strings is reached, or (3) count characters have been
+* compared (wide-character strings).
+*
+*Entry:
+* wchar_t *first, *last - strings to compare
+* size_t count - maximum number of characters to compare
+*
+*Exit:
+* returns <0 if first < last
+* returns 0 if first == last
+* returns >0 if first > last
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 wcsncmp (
+ const wchar_t * first,
+ const wchar_t * last,
+ size_t count
+ )
+{
+ if (!count)
+ return(0);
+
+ while (--count && *first && *first == *last)
+ {
+ first++;
+ last++;
+ }
+
+ return((int)(*first - *last));
+}
diff --git a/private/crt32/string/wcsncpy.c b/private/crt32/string/wcsncpy.c
new file mode 100644
index 000000000..2d23573a5
--- /dev/null
+++ b/private/crt32/string/wcsncpy.c
@@ -0,0 +1,57 @@
+/***
+*wcsncpy.c - copy at most n characters of wide-character string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsncpy() - copy at most n characters of wchar_t string
+*
+*Revision History:
+* 09-09-91 ETC Created from strncpy.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcsncpy(dest, source, count) - copy at most n wide characters
+*
+*Purpose:
+* Copies count characters from the source string to the
+* destination. If count is less than the length of source,
+* NO NULL CHARACTER is put onto the end of the copied string.
+* If count is greater than the length of sources, dest is padded
+* with null characters to length count (wide-characters).
+*
+*
+*Entry:
+* wchar_t *dest - pointer to destination
+* wchar_t *source - source string for copy
+* size_t count - max number of characters to copy
+*
+*Exit:
+* returns dest
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcsncpy (
+ wchar_t * dest,
+ const wchar_t * source,
+ size_t count
+ )
+{
+ wchar_t *start = dest;
+
+ while (count && (*dest++ = *source++)) /* copy string */
+ count--;
+
+ if (count) /* pad out with zeroes */
+ while (--count)
+ *dest++ = L'\0';
+
+ return(start);
+}
diff --git a/private/crt32/string/wcsnicmp.c b/private/crt32/string/wcsnicmp.c
new file mode 100644
index 000000000..98a68620d
--- /dev/null
+++ b/private/crt32/string/wcsnicmp.c
@@ -0,0 +1,91 @@
+/***
+*wcsnicmp.c - compare n chars of wide-character strings, ignoring case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsnicmp() - Compares at most n characters of two wchar_t
+* strings, without regard to case.
+*
+*Revision History:
+* 09-09-91 ETC Created from strnicmp.c and wcsicmp.c.
+* 12-09-91 ETC Use C for neutral locale.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <ctype.h>
+#include <locale.h>
+#ifdef _INTL
+#include <setlocal.h>
+#include <os2dll.h>
+#endif
+
+/***
+*int _wcsnicmp(first, last, count) - compares count wchar_t of strings,
+* ignore case
+*
+*Purpose:
+* Compare the two strings for lexical order. Stops the comparison
+* when the following occurs: (1) strings differ, (2) the end of the
+* strings is reached, or (3) count characters have been compared.
+* For the purposes of the comparison, upper case characters are
+* converted to lower case (wide-characters).
+*
+* *** NOTE: the comparison should be done in a neutral locale,
+* provided by the NLSAPI. Currently, the comparison is done
+* in the C locale. ***
+*
+*Entry:
+* wchar_t *first, *last - strings to compare
+* size_t count - maximum number of characters to compare
+*
+*Exit:
+* -1 if first < last
+* 0 if first == last
+* 1 if first > last
+* This range of return values may differ from other *cmp/*coll functions.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _wcsnicmp (
+ const wchar_t * first,
+ const wchar_t * last,
+ size_t count
+ )
+{
+ wchar_t f,l;
+ int result = 0;
+
+ if (count)
+ {
+#if defined(_INTL) && !defined(_NTSUBSET_)
+
+ _mlock (_LC_CTYPE_LOCK);
+#endif
+
+ do
+ {
+ f = iswupper(*first)
+ ? *first - (wchar_t)L'A' + (wchar_t)L'a'
+ : *first;
+ l = iswupper(*last)
+ ? *last - (wchar_t)L'A' + (wchar_t)L'a'
+ : *last;
+ first++;
+ last++;
+ } while (--count && f && l && f == l);
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ _munlock (_LC_CTYPE_LOCK);
+#endif
+
+ result = (int)(f - l);
+ }
+ return result ;
+}
diff --git a/private/crt32/string/wcsnset.c b/private/crt32/string/wcsnset.c
new file mode 100644
index 000000000..415f14b45
--- /dev/null
+++ b/private/crt32/string/wcsnset.c
@@ -0,0 +1,51 @@
+/***
+*wcsnset.c - set first n wide-characters to single wide-character
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsnset() - sets at most the first n characters of a
+* wchar_t string to a given character.
+*
+*Revision History:
+* 09-09-91 ETC Created from strnset.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *_wcsnset(string, val, count) - set at most count characters to val
+*
+*Purpose:
+* Sets the first count characters of string the character value.
+* If the length of string is less than count, the length of
+* string is used in place of n (wide-characters).
+*
+*Entry:
+* wchar_t *string - string to set characters in
+* wchar_t val - character to fill with
+* size_t count - count of characters to fill
+*
+*Exit:
+* returns string, now filled with count copies of val.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsnset (
+ wchar_t * string,
+ wchar_t val,
+ size_t count
+ )
+{
+ wchar_t *start = string;
+
+ while (count-- && *string)
+ *string++ = (wchar_t)val;
+
+ return(start);
+}
diff --git a/private/crt32/string/wcspbrk.c b/private/crt32/string/wcspbrk.c
new file mode 100644
index 000000000..52e801e31
--- /dev/null
+++ b/private/crt32/string/wcspbrk.c
@@ -0,0 +1,56 @@
+/***
+*wcspbrk.c - scans wide character string for a character from control string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcspbrk()- returns pointer to the first wide-character in
+* a wide-character string in the control string.
+*
+*Revision History:
+* 11-04-91 ETC Created with source from crtdll.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcspbrk(string, control) - scans string for a character from control
+*
+*Purpose:
+* Returns pointer to the first wide-character in
+* a wide-character string in the control string.
+*
+*Entry:
+* wchar_t *string - string to search in
+* wchar_t *control - string containing characters to search for
+*
+*Exit:
+* returns a pointer to the first character from control found
+* in string.
+* returns NULL if string and control have no characters in common.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcspbrk (
+ const wchar_t * string,
+ const wchar_t * control
+ )
+{
+ wchar_t *wcset;
+
+ /* 1st char in control string stops search */
+ while (*string) {
+ for (wcset = (wchar_t *) control; *wcset; wcset++) {
+ if (*wcset == *string) {
+ return (wchar_t *) string;
+ }
+ }
+ string++;
+ }
+ return NULL;
+}
diff --git a/private/crt32/string/wcsrchr.c b/private/crt32/string/wcsrchr.c
new file mode 100644
index 000000000..9dc3b004a
--- /dev/null
+++ b/private/crt32/string/wcsrchr.c
@@ -0,0 +1,56 @@
+/***
+*wcsrchr.c - find last occurrence of wchar_t character in wide string
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsrchr() - find the last occurrence of a given character
+* in a string (wide-characters).
+*
+*Revision History:
+* 09-09-91 ETC Created from strrchr.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcsrchr(string, ch) - find last occurrence of ch in wide string
+*
+*Purpose:
+* Finds the last occurrence of ch in string. The terminating
+* null character is used as part of the search (wide-characters).
+*
+*Entry:
+* wchar_t *string - string to search in
+* wchar_t ch - character to search for
+*
+*Exit:
+* returns a pointer to the last occurrence of ch in the given
+* string
+* returns NULL if ch does not occurr in the string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcsrchr (
+ const wchar_t * string,
+ wchar_t ch
+ )
+{
+ wchar_t *start = (wchar_t *)string;
+
+ while (*string++) /* find end of string */
+ ;
+ /* search towards front */
+ while (--string != start && *string != (wchar_t)ch)
+ ;
+
+ if (*string == (wchar_t)ch) /* wchar_t found ? */
+ return( (wchar_t *)string );
+
+ return(NULL);
+}
diff --git a/private/crt32/string/wcsrev.c b/private/crt32/string/wcsrev.c
new file mode 100644
index 000000000..0ea09b944
--- /dev/null
+++ b/private/crt32/string/wcsrev.c
@@ -0,0 +1,56 @@
+/***
+*wcsrev.c - reverse a wide-character string in place
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsrev() - reverse a wchar_t string in place (not including
+* L'\0' character)
+*
+*Revision History:
+* 09-09-91 ETC Created from strrev.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *_wcsrev(string) - reverse a wide-character string in place
+*
+*Purpose:
+* Reverses the order of characters in the string. The terminating
+* null character remains in place (wide-characters).
+*
+*Entry:
+* wchar_t *string - string to reverse
+*
+*Exit:
+* returns string - now with reversed characters
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsrev (
+ wchar_t * string
+ )
+{
+ wchar_t *start = string;
+ wchar_t *left = string;
+ wchar_t ch;
+
+ while (*string++) /* find end of string */
+ ;
+ string -= 2;
+
+ while (left < string)
+ {
+ ch = *left;
+ *left++ = *string;
+ *string-- = ch;
+ }
+
+ return(start);
+}
diff --git a/private/crt32/string/wcsset.c b/private/crt32/string/wcsset.c
new file mode 100644
index 000000000..c5e6d9f88
--- /dev/null
+++ b/private/crt32/string/wcsset.c
@@ -0,0 +1,51 @@
+/***
+*wcsset.c - sets all characters of wchar_t string to given character
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _wcsset() - sets all of the characters in a string (except
+* the L'\0') equal to a given character (wide-characters).
+*
+*Revision History:
+* 09-09-91 ETC Created from strset.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *_wcsset(string, val) - sets all of string to val (wide-characters)
+*
+*Purpose:
+* Sets all of wchar_t characters in string (except the terminating '/0'
+* character) equal to val (wide-characters).
+*
+*
+*Entry:
+* wchar_t *string - string to modify
+* wchar_t val - value to fill string with
+*
+*Exit:
+* returns string -- now filled with val's
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsset (
+ wchar_t * string,
+ wchar_t val
+ )
+{
+ wchar_t *start = string;
+
+ while (*string)
+ *string++ = (wchar_t)val;
+
+ return(start);
+}
diff --git a/private/crt32/string/wcsspn.c b/private/crt32/string/wcsspn.c
new file mode 100644
index 000000000..7aed8505e
--- /dev/null
+++ b/private/crt32/string/wcsspn.c
@@ -0,0 +1,67 @@
+/***
+*wcsspn.c - find length of initial substring of chars from a control string
+* (wide-character strings)
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsspn() - finds the length of the initial substring of
+* a string consisting entirely of characters from a control string
+* (wide-character strings).
+*
+*Revision History:
+* 11-04-91 ETC Created with source from crtdll.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*int wcsspn(string, control) - find init substring of control chars
+*
+*Purpose:
+* Finds the index of the first character in string that does belong
+* to the set of characters specified by control. This is
+* equivalent to the length of the initial substring of string that
+* consists entirely of characters from control. The L'\0' character
+* that terminates control is not considered in the matching process
+* (wide-character strings).
+*
+*Entry:
+* wchar_t *string - string to search
+* wchar_t *control - string containing characters not to search for
+*
+*Exit:
+* returns index of first wchar_t in string not in control
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 wcsspn (
+ const wchar_t * string,
+ const wchar_t * control
+ )
+{
+ wchar_t *str = (wchar_t *) string;
+ wchar_t *ctl;
+
+ /* 1st char not in control string stops search */
+ while (*str) {
+ for (ctl = (wchar_t *)control; *ctl != *str; ctl++) {
+ if (*ctl == (wchar_t)0) {
+ /*
+ * reached end of control string without finding a match
+ */
+ return str - string;
+ }
+ }
+ str++;
+ }
+ /*
+ * The whole string consisted of characters from control
+ */
+ return str - string;
+}
diff --git a/private/crt32/string/wcsstr.c b/private/crt32/string/wcsstr.c
new file mode 100644
index 000000000..df6d3d638
--- /dev/null
+++ b/private/crt32/string/wcsstr.c
@@ -0,0 +1,62 @@
+/***
+*wcsstr.c - search for one wide-character string inside another
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsstr() - search for one wchar_t string inside another
+*
+*Revision History:
+* 09-09-91 ETC Created from strstr.c.
+* 04-07-92 KRS Updated and ripped out _INTL switches.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+
+/***
+*wchar_t *wcsstr(string1, string2) - search for string2 in string1
+* (wide strings)
+*
+*Purpose:
+* finds the first occurrence of string2 in string1 (wide strings)
+*
+*Entry:
+* wchar_t *string1 - string to search in
+* wchar_t *string2 - string to search for
+*
+*Exit:
+* returns a pointer to the first occurrence of string2 in
+* string1, or NULL if string2 does not occur in string1
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 wcsstr (
+ const wchar_t * wcs1,
+ const wchar_t * wcs2
+ )
+{
+ wchar_t *cp = (wchar_t *) wcs1;
+ wchar_t *s1, *s2;
+
+ while (*cp)
+ {
+ s1 = cp;
+ s2 = (wchar_t *) wcs2;
+
+ while ( *s1 && *s2 && !(*s1-*s2) )
+ s1++, s2++;
+
+ if (!*s2)
+ return(cp);
+
+ cp++;
+ }
+
+ return(NULL);
+}
diff --git a/private/crt32/string/wcstok.c b/private/crt32/string/wcstok.c
new file mode 100644
index 000000000..4d1c324ae
--- /dev/null
+++ b/private/crt32/string/wcstok.c
@@ -0,0 +1,174 @@
+/***
+*wcstok.c - tokenize a wide-character string with given delimiters
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcstok() - breaks wide-character string into series of token
+* via repeated calls.
+*
+*Revision History:
+* 09-09-91 ETC Created from strtok.c.
+* 08-17-92 KRS Activate multithread support.
+* 02-17-93 GJF Changed for new _getptd().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#ifdef MTHREAD
+#include <os2dll.h>
+#endif
+
+/***
+*wchar_t *wcstok(string, control) - tokenize string with delimiter in control
+* (wide-characters)
+*
+*Purpose:
+* wcstok considers the string to consist of a sequence of zero or more
+* text tokens separated by spans of one or more control chars. the first
+* call, with string specified, returns a pointer to the first wchar_t of
+* the first token, and will write a null wchar_t into string immediately
+* following the returned token. subsequent calls with zero for the first
+* argument (string) will work thru the string until no tokens remain. the
+* control string may be different from call to call. when no tokens remain
+* in string a NULL pointer is returned. remember the control chars with a
+* bit map, one bit per wchar_t. the null wchar_t is always a control char
+* (wide-characters).
+*
+*Entry:
+* wchar_t *string - wchar_t string to tokenize, or NULL to get next token
+* wchar_t *control - wchar_t string of characters to use as delimiters
+*
+*Exit:
+* returns pointer to first token in string, or if string
+* was NULL, to next token
+* returns NULL when no more tokens remain.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CRTAPI1 wcstok (
+ wchar_t * string,
+ const wchar_t * control
+ )
+{
+ wchar_t *token;
+ const wchar_t *ctl;
+
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ struct _tiddata * tdata;
+
+ tdata = _gettidtab(); /* init tid's data address */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ _ptiddata ptd = _getptd();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#else
+
+ static wchar_t *nextoken;
+
+#endif
+
+ /* If string==NULL, continue with previous string */
+ if (!string)
+
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ string = tdata->_wtoken;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ string = ptd->_wtoken;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#else
+
+ string = nextoken;
+
+#endif
+
+ /* Find beginning of token (skip over leading delimiters). Note that
+ * there is no token iff this loop sets string to point to the terminal
+ * null (*string == '\0') */
+
+ while (*string) {
+ for (ctl=control; *ctl && *ctl != *string; ctl++)
+ ;
+ if (!*ctl) break;
+ string++;
+ }
+
+ token = string;
+
+ /* Find the end of the token. If it is not the end of the string,
+ * put a null there. */
+ for ( ; *string ; string++ ) {
+ for (ctl=control; *ctl && *ctl != *string; ctl++)
+ ;
+ if (*ctl) {
+ *string++ = '\0';
+ break;
+ }
+ }
+
+ /* Update nextoken (or the corresponding field in the per-thread data
+ * structure */
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ tdata->_wtoken = string;
+
+#else /* _CRUISER_ */
+
+#ifdef _WIN32_
+
+ ptd->_wtoken = string;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+#else
+ nextoken = string;
+#endif
+
+ /* Determine if a token has been found. */
+ if ( token == string )
+ return NULL;
+ else
+ return token;
+}
diff --git a/private/crt32/string/wcsupr.c b/private/crt32/string/wcsupr.c
new file mode 100644
index 000000000..5a302db66
--- /dev/null
+++ b/private/crt32/string/wcsupr.c
@@ -0,0 +1,104 @@
+/***
+*wcsupr.c - routine to map lower-case characters in a wchar_t string
+* to upper-case
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts all the lower case characters in a wchar_t string
+* to upper case, in place.
+*
+*Revision History:
+* 09-09-91 ETC Created from strupr.c and wcslwr.c
+# 04-06-92 KRS Make work without _INTL also.
+# 08-19-92 KRS Activate NLS support.
+* 08-22-92 SRW Allow INTL definition to be conditional for building ntcrt.lib
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 02-16-93 CFW Optimize test for lowercase in "C" locale.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <string.h>
+#include <malloc.h>
+#include <locale.h>
+#include <ctype.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*wchar_t *_wcsupr(string) - map lower-case characters in a string to upper-case
+*
+*Purpose:
+* wcsupr converts lower-case characters in a null-terminated wchar_t
+* string to their upper-case equivalents. The result may be longer or
+* shorter than the original string. Assumes enough space in string
+* to hold the result.
+*
+*Entry:
+* wchar_t *wsrc - wchar_t string to change to upper case
+*
+*Exit:
+* input string address
+*
+*Exceptions:
+* on an error, the original string is unaltered
+*
+*******************************************************************************/
+
+wchar_t * _CALLTYPE1 _wcsupr (
+ wchar_t * wsrc
+ )
+{
+#if defined(_INTL) && !defined(_NTSUBSET_)
+ wchar_t *p; /* traverses string for C locale conversion */
+ wchar_t *wdst = NULL; /* wide version of string in alternate case */
+ int srclen; /* general purpose length of source string */
+ int dstlen; /* len of wdst string, wide chars, no null */
+
+ _mlock (_LC_CTYPE_LOCK);
+
+ if (_lc_handle[LC_CTYPE] == _CLOCALEHANDLE) {
+ _munlock (_LC_CTYPE_LOCK);
+ for (p=wsrc; *p; p++)
+ {
+ if (*p >= (wchar_t)L'a' && *p <= (wchar_t)L'z')
+ *p = *p - (L'a' - L'A');
+ }
+ return (wsrc);
+ } /* C locale */
+
+ /* Inquire size of wdst string */
+ srclen = wcslen(wsrc) + 1;
+ if ((dstlen=LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_UPPERCASE, wsrc,
+ srclen, wdst, 0)) == 0)
+ goto error_cleanup;
+
+ /* Allocate space for wdst */
+ if ((wdst = (wchar_t *) malloc(dstlen*sizeof(wchar_t))) == NULL)
+ goto error_cleanup;
+
+ /* Map wrc string to wide-character wdst string in alternate case */
+ if (LCMapStringW(_lc_handle[LC_CTYPE], LCMAP_UPPERCASE, wsrc,
+ srclen, wdst, dstlen) == 0)
+ goto error_cleanup;
+
+ /* Copy wdst string to user string */
+ wcscpy (wsrc, wdst);
+
+error_cleanup:
+ _munlock (_LC_CTYPE_LOCK);
+ free (wdst);
+#else
+ wchar_t * p;
+
+ for (p=wsrc; *p; ++p)
+ {
+ if (L'a' <= *p && *p <= L'z')
+ *p += (wchar_t)(L'A' - L'a');
+ }
+
+#endif /* _INTL */
+ return (wsrc);
+}
diff --git a/private/crt32/string/wcsxfrm.c b/private/crt32/string/wcsxfrm.c
new file mode 100644
index 000000000..b812450ca
--- /dev/null
+++ b/private/crt32/string/wcsxfrm.c
@@ -0,0 +1,126 @@
+/***
+*wcsxfrm.c - Transform a wide-character string using locale information
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Transform a wide-character string using the locale information as set by
+* LC_COLLATE.
+*
+*Revision History:
+* 09-09-91 ETC Created from strxfrm.c.
+* 12-09-91 ETC Updated api; Added multithread lock.
+* 12-18-91 ETC Changed back LCMAP_SORTKEYA --> LCMAP_SORTKEY.
+* 04-06-92 KRS Fix so it works without _INTL too.
+* 08-19-92 KRS Activate use of NLS API.
+* 09-02-92 SRW Get _INTL definition via ..\crt32.def
+* 12-15-92 KRS Fix return value to match ANSI/ISO Std.
+* 09-23-93 CFW Complete re-write. Non-C locale totally broken.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <locale.h>
+#include <setlocal.h>
+#include <os2dll.h>
+
+/***
+*size_t wcsxfrm() - Transform a string using locale information
+*
+*Purpose:
+* Transform the wide string pointed to by _string2 and place the
+* resulting wide string into the array pointed to by _string1.
+* No more than _count wide characters are placed into the
+* resulting string (including the null).
+*
+* The transformation is such that if wcscmp() is applied to
+* the two transformed strings, the return value is equal to
+* the result of wcscoll() applied to the two original strings.
+* Thus, the conversion must take the locale LC_COLLATE info
+* into account.
+*
+* In the C locale, wcsxfrm() simply resolves to wcsncpy()/wcslen().
+*
+*Entry:
+* wchar_t *_string1 = result string
+* const wchar_t *_string2 = source string
+* size_t _count = max wide chars to move
+*
+* [If _count is 0, _string1 is permitted to be NULL.]
+*
+*Exit:
+* Length of the transformed string (not including the terminating
+* null). If the value returned is >= _count, the contents of the
+* _string1 array are indeterminate.
+*
+*Exceptions:
+* Non-standard: if OM/API error, return INT_MAX.
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 wcsxfrm (
+ wchar_t *_string1,
+ const wchar_t *_string2,
+ size_t _count
+ )
+{
+#ifndef _INTL
+ if (_string1)
+ wcsncpy(_string1, _string2, _count);
+ return wcslen(_string2);
+#else
+ int size;
+ unsigned char *bbuffer;
+
+
+ _mlock (_LC_COLLATE_LOCK);
+
+ if (_lc_handle[LC_COLLATE] == _CLOCALEHANDLE) {
+ _munlock (_LC_COLLATE_LOCK);
+ wcsncpy(_string1, _string2, _count);
+ return wcslen(_string2);
+ }
+
+ /*
+ * When using LCMAP_SORTKEY, LCMapStringW handles BYTES not wide
+ * chars. We use a byte buffer to hold bytes and then convert the
+ * byte string to a wide char string and return this so it can be
+ * compared using wcscmp(). User's buffer is _count wide chars, so
+ * use an internal buffer of _count bytes.
+ */
+
+ if (NULL == (bbuffer = (unsigned char *)malloc(_count)))
+ {
+ size = INT_MAX;
+ goto error_cleanup;
+ }
+
+ if (0 == (size = LCMapStringW(_lc_handle[LC_COLLATE], LCMAP_SORTKEY,
+ _string2, -1, (wchar_t *)bbuffer, _count)))
+ {
+ /* buffer not big enough, get size required. */
+
+ if (0 == (size = LCMapStringW(_lc_handle[LC_COLLATE], LCMAP_SORTKEY,
+ _string2, -1, NULL, 0)))
+ size = INT_MAX; /* default error */
+ else
+ size--; /* don't count NULL */
+
+ } else {
+ int i;
+ /* string successfully mapped, convert to wide char */
+
+ for (i = 0; i < size; i++)
+ _string1[i] = (wchar_t)bbuffer[i];
+
+ size--; /* don't count NULL */
+ }
+
+error_cleanup:
+ _munlock (_LC_COLLATE_LOCK);
+ return (size_t)size;
+#endif /* _INTL */
+}
diff --git a/private/crt32/time/asctime.c b/private/crt32/time/asctime.c
new file mode 100644
index 000000000..01fb992c2
--- /dev/null
+++ b/private/crt32/time/asctime.c
@@ -0,0 +1,194 @@
+/***
+*asctime.c - convert date/time structure to ASCII string
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains asctime() - convert a date/time structure to ASCII string.
+*
+*Revision History:
+* 03-??-84 RLB Module created
+* 05-??-84 DCW Removed use of sprintf, to avoid loading stdio
+* functions
+* 04-13-87 JCR Added "const" to declarations
+* 05-21-87 SKS Declare the static buffer and helper routines as NEAR
+* Replace store_year() with in-line code
+*
+* 11-24-87 WAJ allocated a static buffer for each thread.
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-24-88 PHG Merged DLL and normal versions; Removed initializers to
+* save memory
+* 06-06-89 JCR 386 mthread support
+* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h>, fixed
+* the copyright and removed some leftover 16-bit support.
+* Also, cleaned up the formatting a bit.
+* 08-16-90 SBM Compiles cleanly with -W3
+* 10-04-90 GJF New-style function declarators.
+* 07-17-91 GJF Multi-thread support for Win32 [_WIN32_].
+* 02-17-93 GJF Changed for new _getptd().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <time.h>
+#include <internal.h>
+#include <os2dll.h>
+#ifdef MTHREAD
+#include <malloc.h>
+#include <stddef.h>
+#endif
+
+#define _ASCBUFSIZE 26
+static char buf[_ASCBUFSIZE];
+
+/*
+** This prototype must be local to this file since the procedure is static
+*/
+
+static char * _CRTAPI3 store_dt(char *, int);
+
+static char * _CRTAPI3 store_dt (
+ REG1 char *p,
+ REG2 int val
+ )
+{
+ *p++ = (char)('0' + val / 10);
+ *p++ = (char)('0' + val % 10);
+ return(p);
+}
+
+
+/***
+*char *asctime(time) - convert a structure time to ascii string
+*
+*Purpose:
+* Converts a time stored in a struct tm to a charcater string.
+* The string is always exactly 26 characters of the form
+* Tue May 01 02:34:55 1984\n\0
+*
+*Entry:
+* struct tm *time - ptr to time structure
+*
+*Exit:
+* returns pointer to static string with time string.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CRTAPI1 asctime (
+ REG1 const struct tm *tb
+ )
+{
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ struct _tiddata * tdata; /* pointer to tid's data */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ _ptiddata ptd = _getptd();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ REG2 char *p; /* will point to asctime buffer */
+ char *retval; /* holds retval pointer */
+
+#else
+
+ REG2 char *p = buf;
+
+#endif
+
+ int day, mon;
+ int i;
+
+#ifdef MTHREAD
+
+#ifdef _CRUISER_
+
+ /* Use per thread buffer area (malloc space, if necessary) */
+ tdata = _gettidtab(); /* get tid's data address */
+ if (tdata->_asctimebuf == NULL) {
+ if ( (tdata->_asctimebuf = malloc(_ASCBUFSIZE)) == NULL)
+ p = buf; /* error: use static buffer */
+ else
+ p = tdata->_asctimebuf;
+ }
+ else
+ p = tdata->_asctimebuf;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ /* Use per thread buffer area (malloc space, if necessary) */
+
+ if ( (ptd->_asctimebuf != NULL) || ((ptd->_asctimebuf =
+ malloc(_ASCBUFSIZE)) != NULL) )
+ p = ptd->_asctimebuf;
+ else
+ p = buf; /* error: use static buffer */
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ retval = p; /* save return value for later */
+
+#endif
+
+ /* copy day and month names into the buffer */
+
+ day = tb->tm_wday * 3; /* index to correct day string */
+ mon = tb->tm_mon * 3; /* index to correct month string */
+ for (i=0; i < 3; i++,p++) {
+ *p = *(__dnames + day + i);
+ *(p+4) = *(__mnames + mon + i);
+ }
+
+ *p = ' '; /* blank between day and month */
+
+ p += 4;
+
+ *p++ = ' ';
+ p = store_dt(p, tb->tm_mday); /* day of the month (1-31) */
+ *p++ = ' ';
+ p = store_dt(p, tb->tm_hour); /* hours (0-23) */
+ *p++ = ':';
+ p = store_dt(p, tb->tm_min); /* minutes (0-59) */
+ *p++ = ':';
+ p = store_dt(p, tb->tm_sec); /* seconds (0-59) */
+ *p++ = ' ';
+ p = store_dt(p, 19 + (tb->tm_year/100)); /* year (after 1900) */
+ p = store_dt(p, tb->tm_year%100);
+ *p++ = '\n';
+ *p = '\0';
+
+#ifdef _POSIX_
+ /* Date should be padded with spaces instead of zeroes. */
+
+ if ('0' == buf[8])
+ buf[8] = ' ';
+#endif
+
+#ifdef MTHREAD
+ return (retval);
+#else
+ return ((char *) buf);
+#endif
+}
diff --git a/private/crt32/time/clock.c b/private/crt32/time/clock.c
new file mode 100644
index 000000000..cf94837c5
--- /dev/null
+++ b/private/crt32/time/clock.c
@@ -0,0 +1,169 @@
+/***
+*clock.c - Contains the clock runtime
+*
+* Copyright (c) 1987-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The clock runtime returns the processor time used by
+* the current process.
+*
+*Revision History:
+* 01-17-87 JCR Module created
+* 06-01-87 SKS "itime" must be declared static
+* 07-20-87 JCR Changes "inittime" to "_inittime"
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 10-04-90 GJF New-style function declarators.
+* 01-22-91 GJF ANSI naming.
+* 07-25-91 GJF Added _pinittime definition for new initialization
+* scheme [_WIN32_].
+* 03-13-92 SKS Changed itime from static local to external as
+* a part of return to initializer table scheme.
+* Changed _inittime to __inittime.
+* 05-19-92 DJM POSIX support.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdio.h>
+#include <time.h>
+
+#ifdef _POSIX_
+#include <posix/sys/times.h>
+#else
+#include <sys\timeb.h>
+#include <sys\types.h>
+#endif /* _POSIX_ */
+
+
+#ifndef _POSIX_
+
+void __cdecl __inittime(void);
+
+#ifdef _MSC_VER
+
+#pragma data_seg(".CRT$XIC")
+static void (__cdecl *pinit)(void) = __inittime;
+
+#pragma data_seg()
+
+#endif /* _MSC_VER */
+
+struct _timeb __itimeb = { 0, 0, 0, 0 };
+
+/***
+*clock_t clock() - Return the processor time used by this process.
+*
+*Purpose:
+* This routine calculates how much time the calling process
+* has used. At startup time, startup calls __inittime which stores
+* the initial time. The clock routine calculates the difference
+* between the current time and the initial time.
+*
+* Clock must reference _cinitime so that _cinitim.asm gets linked in.
+* That routine, in turn, puts __inittime in the startup initialization
+* routine table.
+*
+*Entry:
+* No parameters.
+* itime is a static structure of type timeb.
+*
+*Exit:
+* If successful, clock returns the number of CLK_TCKs (milliseconds)
+* that have elapsed. If unsuccessful, clock returns -1.
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+clock_t _CALLTYPE1 clock (
+ void
+ )
+{
+ struct _timeb now;
+ clock_t elapsed;
+
+#ifdef _CRUISER_
+
+ extern int _citime;
+
+ /* Reference _citime so __inittime gets executed at startup time.*/
+
+ _citime=0;
+
+#endif /* _CRUISER_ */
+
+ /* Calculate the difference between the initial time and now. */
+
+ _ftime(&now);
+ elapsed = (now.time - __itimeb.time) * CLOCKS_PER_SEC;
+ elapsed += (int)now.millitm - (int)__itimeb.millitm;
+ return(elapsed);
+
+}
+
+/***
+*void __inittime() - Initialize the time location
+*
+*Purpose:
+* This routine stores the time of the process startup.
+* It is only linked in if the user issues a clock runtime call.
+*
+*Entry:
+* No arguments.
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+void _CALLTYPE1 __inittime (
+ void
+ )
+{
+ _ftime(&__itimeb);
+}
+
+#else /* _POSIX_ */
+
+/***
+*clock_t clock() - Return the processor time used by this process.
+*
+*Purpose:
+* This routine calculates how much time the calling process
+* has used. It uses the POSIX system call times().
+*
+*
+*Entry:
+* No parameters.
+*
+*Exit:
+* If successful, clock returns the number of CLK_TCKs (milliseconds)
+* that have elapsed. If unsuccessful, clock returns -1.
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+clock_t _CALLTYPE1 clock (
+ void
+ )
+{
+ struct tms now;
+ clock_t elapsed;
+
+ elapsed= times(&now);
+ if (elapsed == (clock_t) -1)
+ return((clock_t) -1);
+ else
+ return(now.tms_utime+now.tms_stime);
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/ctime.c b/private/crt32/time/ctime.c
new file mode 100644
index 000000000..28e48c43b
--- /dev/null
+++ b/private/crt32/time/ctime.c
@@ -0,0 +1,56 @@
+/***
+*ctime.c - convert time argument into ASCII string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains ctime() - convert time value to string
+*
+*Revision History:
+* 03-??-84 RLB initial version
+* 05-??-84 DFW split off into seperate module
+* 02-18-87 JCR put in NULL ptr support
+* 04-10-87 JCR changed long declaration ot time_t and added const.
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 05-21-90 GJF Fixed compiler warning.
+* 10-04-90 GJF New-style function declarators.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <time.h>
+#include <stddef.h>
+
+/***
+*char *ctime(time) - converts a time stored as a long to a ASCII string
+*
+*Purpose:
+* Converts a time stored as a long (time_t) to an ASCII string of
+* the form:
+* Tue May 1 14:25:03 1984
+*
+*Entry:
+* long *time - time value in XENIX format
+*
+*Exit:
+* returns pointer to static string or NULL if time is before
+* Jan 1 1980.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 ctime (
+ const time_t *timp
+ )
+{
+ struct tm *tmtemp;
+
+ if ((tmtemp=localtime(timp)) != NULL)
+ return(asctime((const struct tm *)tmtemp));
+ else
+ return(NULL);
+}
diff --git a/private/crt32/time/days.c b/private/crt32/time/days.c
new file mode 100644
index 000000000..c259f996c
--- /dev/null
+++ b/private/crt32/time/days.c
@@ -0,0 +1,26 @@
+/***
+*days.c - static arrays with days from beg of year for each month
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains static arrays used by gmtime and statconv to determine
+* date and time values. Shows days from beg of year.
+*
+*Revision History:
+* 03-??-84 RLB initial version
+* 05-??-84 DFW split out definitions from ctime routines
+* 07-03-89 PHG removed _NEAR_ for 386
+* 03-20-90 GJF Fixed copyright.
+*
+*******************************************************************************/
+
+#include <internal.h>
+
+int _lpdays[] = {
+ -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+};
+
+int _days[] = {
+ -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364
+};
diff --git a/private/crt32/time/difftime.c b/private/crt32/time/difftime.c
new file mode 100644
index 000000000..76797028f
--- /dev/null
+++ b/private/crt32/time/difftime.c
@@ -0,0 +1,53 @@
+/***
+*difftime.c - return difference between two times as a double
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Find difference between two time in seconds.
+*
+*Revision History:
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 08-15-89 PHG Made MTHREAD version _pascal
+* 11-20-89 JCR difftime() always _cdecl (not pascal even under
+* mthread)
+* 03-20-90 GJF Replaced _LOAD_DS with CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 10-04-90 GJF New-style function declarator.
+* 05-19-92 DJM ifndef for POSIX build.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <time.h>
+
+/***
+*double difftime(b, a) - find difference between two times
+*
+*Purpose:
+* returns difference between two times (b-a)
+*
+* Multi-thread version must use pascal calling convention to be re-entrant.
+*
+*Entry:
+* long a, b - times to difference (actually are time_t values)
+*
+*Exit:
+* returns a double with the time in seconds between two times
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+double _CALLTYPE1 difftime (
+ time_t b,
+ time_t a
+ )
+{
+ return( (double)( b - a ) );
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/dtoxtime.c b/private/crt32/time/dtoxtime.c
new file mode 100644
index 000000000..8343fb23f
--- /dev/null
+++ b/private/crt32/time/dtoxtime.c
@@ -0,0 +1,113 @@
+/***
+*dtoxtime.c - convert broken-down UTC time to time_t
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines __gmtotime_t() - convert broken-down UTC time to internal
+* format (time_t).
+*
+*Revision History:
+* 03-??-84 RLB written
+* 11-18-87 SKS change tzset() to __tzset(), change source file name
+* make _dtoxtime a near procedure
+* 01-26-88 SKS _dtoxtime is no longer a near procedure (for QC)
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 10-04-90 GJF New-style function declarator.
+* 01-21-91 GJF ANSI naming.
+* 05-19-92 DJM ifndef for POSIX build.
+* 03-30-93 GJF Revised. Old _dtoxtime is replaced by __gmtotime_t,
+* which is more useful on Win32.
+* 04-06-93 GJF Rewrote computation to avoid compiler warnings.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <time.h>
+#include <ctime.h>
+#include <internal.h>
+
+/***
+*time_t __gmtotime_t(yr, mo, dy, hr, mn, sc) - convert broken down time (UTC)
+* to time_t
+*
+*Purpose:
+* Converts a broken down UTC (GMT) time to time_t. This is similar to
+* _mkgmtime() except there is minimal overflow checking and no updating
+* of the input values (i.e., the fields of tm structure).
+*
+*Entry:
+* int yr, mo, dy - date
+* int hr, mn, sc - time
+*
+*Exit:
+* returns time_t value
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+time_t _CRTAPI1 __gmtotime_t (
+ int yr, /* 0 based */
+ int mo, /* 1 based */
+ int dy, /* 1 based */
+ int hr,
+ int mn,
+ int sc
+ )
+{
+ int tmpdays;
+ long tmptim;
+
+ /*
+ * Do a quick range check on the year and convert it to a delta
+ * off of 1900.
+ */
+ if ( ((long)(yr -= 1900) < _BASE_YEAR) || ((long)yr > _MAX_YEAR) )
+ return (time_t)(-1);
+
+ /*
+ * Compute the number of elapsed days in the current year minus
+ * one. Note the test for leap year and the would fail in the year 2100
+ * if this was in range (which it isn't).
+ */
+ tmpdays = dy + _days[mo - 1];
+ if ( !(yr & 3) && (mo > 2) )
+ /*
+ * in a leap year, after Feb. add one day for elapsed
+ * Feb 29.
+ */
+ tmpdays++;
+
+ /*
+ * Compute the number of elapsed seconds since the Epoch. Note the
+ * computation of elapsed leap years would break down after 2100
+ * if such values were in range (fortunately, they aren't).
+ */
+ tmptim = /* 365 days for each year */
+ (((long)yr - _BASE_YEAR) * 365L
+
+ /* one day for each elapsed leap year */
+ + (long)((yr - 1) >> 2) - _LEAP_YEAR_ADJUST
+
+ /* number of elapsed days in yr */
+ + tmpdays)
+
+ /* convert to hours and add in hr */
+ * 24L + hr;
+
+ tmptim = /* convert to minutes and add in mn */
+ (tmptim * 60L + mn)
+
+ /* convert to seconds and add in sec */
+ * 60L + sc;
+
+ return (tmptim >= 0) ? (time_t)tmptim : (time_t)(-1);
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/ftime.c b/private/crt32/time/ftime.c
new file mode 100644
index 000000000..c1e04f5a1
--- /dev/null
+++ b/private/crt32/time/ftime.c
@@ -0,0 +1,107 @@
+/***
+*ftime.c - OS/2 return system time
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Returns the system date/time in a structure form.
+*
+*Revision History:
+* 03-??-84 RLB initial version
+* 05-17-86 SKS ported to OS/2
+* 03-09-87 SKS correct Daylight Savings Time flag
+* 11-18-87 SKS Change tzset() to __tzset()
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 10-03-88 JCR 386: Change DOS calls to SYS calls
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 10-10-88 GJF Made API names match DOSCALLS.H
+* 04-12-89 JCR New syscall interface
+* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
+* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed some leftover 16-bit support
+* and fixed the copyright. Also, cleaned up the
+* formatting a bit.
+* 07-25-90 SBM Removed '32' from API names
+* 08-13-90 SBM Compiles cleanly with -W3
+* 08-20-90 SBM Removed old incorrect, redundant tp->dstflag assignment
+* 10-04-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-21-91 GJF ANSI naming.
+* 01-23-92 GJF Change in time zone field name for Win32, to support
+* crtdll.dll [_WIN32_].
+* 03-30-93 GJF Revised to use mktime(). Also purged Cruiser support.
+* 06-08-93 SKS Change "tmzone" back to "timezone". See h/sys/timeb.h.
+* 07-15-93 GJF Call __tzset() instead of _tzset().
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <time.h>
+#include <dostypes.h>
+#include <msdos.h>
+#include <dos.h>
+#include <stdlib.h>
+#include <oscalls.h>
+#include <internal.h>
+
+/***
+*void _ftime(timeptr) - return DOS time in a structure
+*
+*Purpose:
+* returns the current DOS time in a struct timeb structure
+*
+*Entry:
+* struct timeb *timeptr - structure to fill in with time
+*
+*Exit:
+* no return value -- fills in structure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _ftime (
+ struct _timeb *tp
+ )
+{
+ struct tm tb;
+ SYSTEMTIME dt;
+
+ __tzset();
+
+ /*
+ * NOTE: The "timezone" field was renamed "tmzone" for a while because
+ * of the conflict with the global variable "_timezone". Since we use
+ * #define to alias the old name "timezone" to "_timezone" and to
+ * alias _timezone to (*_timezone_dll) in the CRTDLL model, we cannot
+ * compatibility in both areas. See sys/timeb.h for more information.
+ */
+ tp->timezone = (short)(_timezone / 60);
+
+ GetLocalTime(&dt);
+
+ tp->millitm = (unsigned short)(dt.wMilliseconds);
+
+ tb.tm_year = dt.wYear - 1900;
+ tb.tm_mday = dt.wDay;
+ tb.tm_mon = dt.wMonth - 1;
+ tb.tm_hour = dt.wHour;
+ tb.tm_min = dt.wMinute;
+ tb.tm_sec = dt.wSecond;
+ tb.tm_isdst = -1;
+
+ /*
+ * Call mktime() to compute time_t value and Daylight Savings Time
+ * flag.
+ */
+ tp->time = mktime(&tb);
+
+ tp->dstflag = (short)(tb.tm_isdst);
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/gmtime.c b/private/crt32/time/gmtime.c
new file mode 100644
index 000000000..8faacaf34
--- /dev/null
+++ b/private/crt32/time/gmtime.c
@@ -0,0 +1,185 @@
+/***
+*gmtime.c - breaks down a time value into GMT date/time info
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines gmtime() - breaks the clock value down into GMT time/date
+* information; return pointer to structure with the data.
+*
+*Revision History:
+* 01-??-84 RLB Module created
+* 05-??-84 DCW Split off from rest off ctime routines.
+* 02-18-87 JCR For MS C, gmtime now returns NULL for out of range
+* time/date. (This is for ANSI compatibility.)
+* 04-10-87 JCR Changed long declaration to time_t and added const
+* 05-21-87 SKS Declare "struct tm tb" as NEAR data
+* 11-10-87 SKS Removed IBMC20 switch
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-24-88 PHG Merge DLL and regular versions
+* 06-06-89 JCR 386 mthread support
+* 11-06-89 KRS Add (unsigned) to handle years 2040-2099 correctly
+* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 10-04-90 GJF New-style function declarator.
+* 07-17-91 GJF Multi-thread support for Win32 [_WIN32_].
+* 02-17-93 GJF Changed for new _getptd().
+* 03-24-93 GJF Propagated changes from 16-bit tree.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <time.h>
+#include <ctime.h>
+#include <stddef.h>
+#include <internal.h>
+#include <os2dll.h>
+#ifdef MTHREAD
+#include <malloc.h>
+#include <stddef.h>
+#endif
+
+static struct tm tb = { 0 }; /* time block */
+
+/***
+*struct tm *gmtime(timp) - convert *timp to a structure (UTC)
+*
+*Purpose:
+* Converts the calendar time value, in internal format (time_t), to
+* broken-down time (tm structure) with the corresponding UTC time.
+*
+*Entry:
+* const time_t *timp - pointer to time_t value to convert
+*
+*Exit:
+* returns pointer to filled-in tm structure.
+* returns NULL if *timp < 0L
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+struct tm * _CRTAPI1 gmtime (
+ const time_t *timp
+ )
+{
+
+ long caltim = *timp; /* calendar time to convert */
+ int islpyr = 0; /* is-current-year-a-leap-year flag */
+ REG1 int tmptim;
+ REG3 int *mdays; /* pointer to days or lpdays */
+
+#ifdef MTHREAD
+
+ REG2 struct tm *ptb; /* will point to gmtime buffer */
+ _ptiddata ptd = _getptd();
+
+#else
+ REG2 struct tm *ptb = &tb;
+#endif
+
+ if ( caltim < 0L )
+ return(NULL);
+
+#ifdef MTHREAD
+
+ /* Use per thread buffer area (malloc space, if necessary) */
+
+ if ( (ptd->_gmtimebuf != NULL) || ((ptd->_gmtimebuf =
+ malloc(sizeof(struct tm))) != NULL) )
+ ptb = ptd->_gmtimebuf;
+ else
+ ptb = &tb; /* malloc error: use static buffer */
+
+#endif
+
+ /*
+ * Determine years since 1970. First, identify the four-year interval
+ * since this makes handling leap-years easy (note that 2000 IS a
+ * leap year and 2100 is out-of-range).
+ */
+ tmptim = (int)(caltim / _FOUR_YEAR_SEC);
+ caltim -= ((long)tmptim * _FOUR_YEAR_SEC);
+
+ /*
+ * Determine which year of the interval
+ */
+ tmptim = (tmptim * 4) + 70; /* 1970, 1974, 1978,...,etc. */
+
+ if ( caltim >= _YEAR_SEC ) {
+
+ tmptim++; /* 1971, 1975, 1979,...,etc. */
+ caltim -= _YEAR_SEC;
+
+ if ( caltim >= _YEAR_SEC ) {
+
+ tmptim++; /* 1972, 1976, 1980,...,etc. */
+ caltim -= _YEAR_SEC;
+
+ /*
+ * Note, it takes 366 days-worth of seconds to get past a leap
+ * year.
+ */
+ if ( caltim >= (_YEAR_SEC + _DAY_SEC) ) {
+
+ tmptim++; /* 1973, 1977, 1981,...,etc. */
+ caltim -= (_YEAR_SEC + _DAY_SEC);
+ }
+ else {
+ /*
+ * In a leap year after all, set the flag.
+ */
+ islpyr++;
+ }
+ }
+ }
+
+ /*
+ * tmptim now holds the value for tm_year. caltim now holds the
+ * number of elapsed seconds since the beginning of that year.
+ */
+ ptb->tm_year = tmptim;
+
+ /*
+ * Determine days since January 1 (0 - 365). This is the tm_yday value.
+ * Leave caltim with number of elapsed seconds in that day.
+ */
+ ptb->tm_yday = (int)(caltim / _DAY_SEC);
+ caltim -= (long)(ptb->tm_yday) * _DAY_SEC;
+
+ /*
+ * Determine months since January (0 - 11) and day of month (1 - 31)
+ */
+ if ( islpyr )
+ mdays = _lpdays;
+ else
+ mdays = _days;
+
+
+ for ( tmptim = 1 ; mdays[tmptim] < ptb->tm_yday ; tmptim++ ) ;
+
+ ptb->tm_mon = --tmptim;
+
+ ptb->tm_mday = ptb->tm_yday - mdays[tmptim];
+
+ /*
+ * Determine days since Sunday (0 - 6)
+ */
+ ptb->tm_wday = ((int)(*timp / _DAY_SEC) + _BASE_DOW) % 7;
+
+ /*
+ * Determine hours since midnight (0 - 23), minutes after the hour
+ * (0 - 59), and seconds after the minute (0 - 59).
+ */
+ ptb->tm_hour = (int)(caltim / 3600);
+ caltim -= (long)ptb->tm_hour * 3600L;
+
+ ptb->tm_min = (int)(caltim / 60);
+ ptb->tm_sec = (int)(caltim - (ptb->tm_min) * 60);
+
+ ptb->tm_isdst = 0;
+ return( (struct tm *)ptb );
+
+}
diff --git a/private/crt32/time/i386/_initclk.asm b/private/crt32/time/i386/_initclk.asm
new file mode 100644
index 000000000..b837872bc
--- /dev/null
+++ b/private/crt32/time/i386/_initclk.asm
@@ -0,0 +1,17 @@
+ page ,132
+
+;*******
+;
+; Alternate form of CINITCLK.ASM
+;
+; The MIPS C Compiler does not prepend underscores to C
+; variables and functions like the I386 C Compiler does.
+;
+; The EQUate below will yield an object file
+; which will be appropriate for MIPS COFF format.
+;
+;*******
+
+NO_UNDERSCORE equ 1
+
+include i386\cinitclk.asm
diff --git a/private/crt32/time/i386/cinitclk.asm b/private/crt32/time/i386/cinitclk.asm
new file mode 100644
index 000000000..e303447fc
--- /dev/null
+++ b/private/crt32/time/i386/cinitclk.asm
@@ -0,0 +1,93 @@
+ page ,132
+ title cinitclk - C Run-Time Initialization for clock()
+;***
+;cinitclk.asm - WIN32 C Run-Time Initialization for the clock() function
+;
+; Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Initialization entry for the clock() function
+;
+;Notes:
+; The variable _itimeb, used in clock.c, is declared in this module
+; to force the inclusion of the initializer entry if clock() is
+; referenced.
+;
+; This file declares a structure of type timeb.
+;
+; The include file "timeb.inc" must be kept in synch with sys/timeb.h
+; and depends on the alignment behavior of the Intel 386.
+;
+;Revision History:
+; 03-19-92 SKS Module created.
+; 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+; 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+; 08-06-92 SKS Revised to use new section names and macros
+;
+;*******************************************************************************
+
+.xlist
+include cruntime.inc
+include defsects.inc
+.list
+
+ifndef _WIN32_
+.err
+%out _WIN32_ MUST be defined!
+endif
+
+
+ifndef NO_UNDERSCORE ; I386 VERSION *************************
+
+
+ extrn __inittime:NEAR
+
+
+beginSection XIC
+
+ dd offset FLAT: __inittime
+
+endSection XIC
+
+
+ .DATA
+
+ public __itimeb
+
+__itimeb label dword
+ dd 0
+ dw 0
+ dw 0
+ dw 0
+ dw 0 ; struct _timeb has four fields plus padding
+
+
+else ; NO_UNDERSCORE ; MIPS VERSION *************************
+
+
+ extrn _inittime:NEAR
+
+
+beginSection XIC
+
+ dd offset FLAT: _inittime
+
+endSection XIC
+
+
+ .DATA
+
+ public _itimeb
+
+_itimeb label dword
+ dd 0
+ dw 0
+ dw 0
+ dw 0
+ dw 0 ; struct _timeb has four fields plus padding
+
+
+endif ; NO_UNDERSCORE ; **** VERSION *************************
+
+
+ end
diff --git a/private/crt32/time/localtim.c b/private/crt32/time/localtim.c
new file mode 100644
index 000000000..59727b1ba
--- /dev/null
+++ b/private/crt32/time/localtim.c
@@ -0,0 +1,252 @@
+/***
+*localtim.c - Convert time_t value to time structure
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Converts time stored as a time_t value to a structure of type
+* struct tm expressed as local time.
+*
+*Revision History:
+* 01-??-84 RLB Module created
+* 05-??-84 DCW split off from the rest of the ctime routines
+* 02-18-87 JCR made localtime work when gmtime returns null
+* 03-31-87 JCR fixed bug pertaining to uninitialized _isindst(tb)
+* 04-10-87 JCR changed long declaration to time_t and added const
+* 11-10-87 SKS Removed IBMC20 switch
+* 11-18-87 SKS Change tzset() to __tzset()
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 11-06-89 KRS Added (unsigned) to handle years 2040-2099 correctly.
+* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* fixed the copyright. Also, cleaned up the formatting
+* a bit.
+* 10-04-90 GJF New-style function declarator. Also, rewrote expr.
+* to avoid using cast as lvalue.
+* 01-21-91 GJF ANSI naming.
+* 08-10-92 PBS Posix support (TZ stuff).
+* 03-24-93 GJF Ported C8-16 version and adapted for exotic Daylight
+* Savings Time conversions which are legal under POSIX.
+* 07-15-93 GJF Replaced _tzset() call with __tzset() call.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <limits.h>
+#include <time.h>
+#include <stddef.h>
+#include <ctime.h>
+#include <internal.h>
+
+/***
+*struct tm *localtime(ptime) - convert time_t value to tm structure
+*
+*Purpose:
+* Convert a value in internal (time_t) format to a tm struct
+* containing the corresponding local time.
+*
+* NOTES:
+* (1) gmtime must be called before _isindst to ensure that the tb time
+* structure is initialized.
+* (2) gmtime and localtime use a single statically allocated buffer.
+* Each call to one of these routines destroys the contents of the
+* previous call.
+* (3) It is assumed that time_t is a 32-bit long integer representing
+* the number of seconds since 00:00:00, 01-01-70 (UTC) (i.e., the
+* Posix/Unix Epoch. Only non-negative values are supported.
+* (4) It is assumed that the maximum adjustment for local time is
+* less than three days (include Daylight Savings Time adjustment).
+* This only a concern in Posix where the specification of the TZ
+* environment restricts the combined offset for time zone and
+* Daylight Savings Time to 2 * (24:59:59), just under 50 hours.
+*
+*Entry:
+* time_t *ptime - pointer to a long time value
+*
+*Exit:
+* If *ptime is non-negative, returns a pointer to the tm structure.
+* Otherwise, returns NULL.
+*
+*Exceptions:
+* See items (3) and (4) in the NOTES above. If these assumptions are
+* violated, behavior is undefined.
+*
+*******************************************************************************/
+
+struct tm * _CRTAPI1 localtime (
+ const time_t *ptime
+ )
+{
+ REG1 struct tm *ptm;
+ long ltime;
+
+ /*
+ * Check for illegal time_t value
+ */
+ if ( (long)*ptime < 0L )
+ return( NULL );
+
+#ifdef _POSIX_
+ tzset();
+#else
+ __tzset();
+#endif
+
+ if ( (*ptime > 3 * _DAY_SEC) && (*ptime < LONG_MAX - 3 * _DAY_SEC) ) {
+ /*
+ * The date does not fall within the first three, or last
+ * three, representable days of the Epoch. Therefore, there
+ * is no possibility of overflowing or underflowing the
+ * time_t representation as we compensate for timezone and
+ * Daylight Savings Time.
+ */
+
+ ltime = (long)*ptime - _timezone;
+ ptm = gmtime( &ltime );
+
+ /*
+ * Check and adjust for Daylight Saving Time.
+ */
+ if ( _daylight && _isindst( ptm ) ) {
+#ifdef _POSIX_
+ ltime -= _dstoffset - _timezone;
+#else
+ ltime += 3600L;
+#endif
+ ptm = gmtime( (time_t *)&ltime );
+ ptm->tm_isdst = 1;
+ }
+ }
+ else {
+ ptm = gmtime( ptime );
+ /*
+ * The date falls with the first three, or last three days
+ * of the Epoch. It is possible the time_t representation
+ * would overflow or underflow while compensating for
+ * timezone and Daylight Savings Time. Therefore, make the
+ * timezone and Daylight Savings Time adjustments directly
+ * in the tm structure. The beginning of the Epoch is
+ * 00:00:00, 01-01-70 (UTC) and the last representable second
+ * in theEpoch is 03:14:07, 01-19-2038 (UTC). This will be
+ * used in the calculations below.
+ *
+ * First, adjust for the timezone.
+ */
+ ltime = (long)ptm->tm_sec - _timezone;
+ ptm->tm_sec = (int)(ltime % 60);
+ if ( ptm->tm_sec < 0 ) {
+ ptm->tm_sec += 60;
+ ltime -= 60;
+ }
+
+ ltime = (long)ptm->tm_min + ltime/60;
+ ptm->tm_min = (int)(ltime % 60);
+ if ( ptm->tm_min < 0 ) {
+ ptm->tm_min += 60;
+ ltime -= 60;
+ }
+
+ ltime = (long)ptm->tm_hour + ltime/60;
+ ptm->tm_hour = (int)(ltime % 24);
+ if ( ptm->tm_hour < 0 ) {
+ ptm->tm_hour += 24;
+ ltime -=24;
+ }
+
+ ltime /= 24;
+
+ if ( ltime > 0L ) {
+ /*
+ * There is no possibility of overflowing the tm_mday
+ * and tm_yday fields since the date can be no later
+ * than January 19.
+ */
+ ptm->tm_wday = (ptm->tm_wday + ltime) % 7;
+ ptm->tm_mday += ltime;
+ ptm->tm_yday += ltime;
+ }
+ else if ( ltime < 0L ) {
+ /*
+ * It is possible to underflow the tm_mday and tm_yday
+ * fields. If this happens, then adjusted date must
+ * lie in December 1969.
+ */
+ ptm->tm_wday = (ptm->tm_wday + 7 + ltime) % 7;
+ if ( (ptm->tm_mday += ltime) <= 0 ) {
+ ptm->tm_mday += 31;
+ ptm->tm_yday = 365;
+ ptm->tm_mon = 11;
+ ptm->tm_year--;
+ }
+ else {
+ ptm->tm_yday += ltime;
+ }
+ }
+
+#ifdef _POSIX_
+ /*
+ * In Posix, it is possible either the first or last three
+ * days of the Epoch might lie with Daylight Savings Time in
+ * certain time zones.
+ */
+ if ( _isindst(ptm) ) {
+
+ ltime = (long)ptm->tm_sec + _dstoffset;
+ ptm->tm_sec = (int)(ltime % 60);
+ if ( ptm->tm_sec < 0 ) {
+ ptm->tm_sec += 60;
+ ltime -= 60;
+ }
+
+ ltime = (long)ptm->tm_min + ltime/60;
+ ptm->tm_min = (int)(ltime % 60);
+ if ( ptm->tm_min < 0 ) {
+ ptm->tm_min += 60;
+ ltime -= 60;
+ }
+
+ ltime = (long)ptm->tm_hour + ltime/60;
+ ptm->tm_hour = (int)(ltime % 24);
+ if ( ptm->tm_hour < 0 ) {
+ ptm->tm_hour += 24;
+ ltime -=24;
+ }
+
+ ltime /= 24;
+
+ if ( ltime > 0L ) {
+ /*
+ * There is no possibility of overflowing the
+ * tm_mday and tm_yday fields since the date
+ * can be no later than January 19.
+ */
+ ptm->tm_wday = (ptm->tm_wday + ltime) % 7;
+ ptm->tm_mday += ltime;
+ ptm->tm_yday += ltime;
+ }
+ else if ( ltime < 0L ) {
+ /*
+ * It is possible to underflow the tm_mday
+ * and tm_yday fields. If this happens, then
+ * adjusted date must lie in December 1969.
+ */
+ ptm->tm_wday = (ptm->tm_wday + 7 + ltime) % 7;
+ if ( (ptm->tm_mday += ltime) <= 0 ) {
+ ptm->tm_mday += 31;
+ ptm->tm_yday = 365;
+ ptm->tm_mon = 12;
+ ptm->tm_year--;
+ }
+ else {
+ ptm->tm_yday += ltime;
+ }
+ }
+ }
+
+#endif
+
+ }
+
+
+ return(ptm);
+}
diff --git a/private/crt32/time/makefile b/private/crt32/time/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/time/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/time/mktime.c b/private/crt32/time/mktime.c
new file mode 100644
index 000000000..7eb6e4e11
--- /dev/null
+++ b/private/crt32/time/mktime.c
@@ -0,0 +1,315 @@
+/***
+*mktime.c - Convert struct tm value to time_t value.
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines mktime() and _mkgmtime(), routines to converts a time value
+* in a tm structure (possibly incomplete) into a time_t value, then
+* update (all) the structure fields with "normalized" values.
+*
+*Revision History:
+* 01-14-87 JCR Module created
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 06-15-89 PHG Now allows negative values and does DST by ANSI rules
+* 11-06-89 KRS Added (unsigned) to handle years 2040-2099 correctly.
+* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 10-04-90 GJF New-style function declarator. Also, rewrote expr.
+* to avoid using casts as lvalues.
+* 10-26-90 GJF Added ulscount to avoid overflows. Ugly, temporary
+* hack (whole function needs to be revised for ANSI
+* conformance).
+* 01-22-91 GJF ANSI naming.
+* 03-24-93 GJF Propagated changes from 16-bit tree. Modified to
+* expose _mkgmtime() routine.
+* 07-15-93 GJF Replaced _tzset() call with __tzset() call.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stddef.h>
+#include <ctime.h>
+#include <time.h>
+#include <internal.h>
+
+/*
+ * ChkAdd evaluates to TRUE if dest = src1 + src2 has overflowed
+ */
+#define ChkAdd(dest, src1, src2) ( ((src1 >= 0L) && (src2 >= 0L) \
+ && (dest < 0L)) || ((src1 < 0L) && (src2 < 0L) && (dest >= 0L)) )
+
+/*
+ * ChkMul evaluates to TRUE if dest = src1 * src2 has overflowed
+ */
+#define ChkMul(dest, src1, src2) ( src1 ? (dest/src1 != src2) : 0 )
+
+
+/*
+ * Core function for both mktime() and _mkgmtime()
+ */
+static time_t _CRTAPI3 _make_time_t( struct tm *, int);
+
+
+/***
+*time_t mktime(tb) - Normalize user time block structure
+*
+*Purpose:
+* Mktime converts a time structure, passed in as an argument, into a
+* calendar time value in internal format (time_t). It also completes
+* and updates the fields the of the passed in structure with 'normalized'
+* values. There are three practical uses for this routine:
+*
+* (1) Convert broken-down time to internal time format (time_t).
+* (2) To have mktime fill in the tm_wday, tm_yday, or tm_isdst fields.
+* (3) To pass in a time structure with 'out of range' values for some
+* fields and have mktime "normalize" them (e.g., pass in 1/35/87 and
+* get back 2/4/87).
+*Entry:
+* struct tm *tb - pointer to a tm time structure to convert and
+* normalize
+*
+*Exit:
+* If successful, mktime returns the specified calender time encoded as
+* a time_t value. Otherwise, (time_t)(-1) is returned to indicate an
+* error.
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+
+time_t _CRTAPI1 mktime (
+ struct tm *tb
+ )
+{
+ return( _make_time_t(tb, 1) );
+}
+
+
+/***
+*time_t _mkgmtime(tb) - Convert broken down UTC time to time_t
+*
+*Purpose:
+* Convert a tm structure, passed in as an argument, containing a UTC
+* time value to internal format (time_t). It also completes and updates
+* the fields the of the passed in structure with 'normalized' values.
+
+*Entry:
+* struct tm *tb - pointer to a tm time structure to convert and
+* normalize
+*
+*Exit:
+* If successful, _mkgmtime returns the calender time encoded as time_t
+* Otherwise, (time_t)(-1) is returned to indicate an error.
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+time_t _CRTAPI1 _mkgmtime (
+ struct tm *tb
+ )
+{
+ return( _make_time_t(tb, 0) );
+}
+
+
+/***
+*static time_t make_time_t(tb, ultflag) -
+*
+*Purpose:
+* Converts a struct tm value to a time_t value, then updates the struct
+* tm value. Either local time or UTC is supported, based on ultflag.
+* This is the routine that actually does the work for both mktime() and
+* _mkgmtime().
+*
+*Entry:
+* struct tm *tb - pointer to a tm time structure to convert and
+* normalize
+* int ultflag - use local time flag. the tb structure is assumed
+* to represent a local date/time if ultflag > 0.
+* otherwise, UTC is assumed.
+*
+*Exit:
+* If successful, mktime returns the specified calender time encoded as
+* a time_t value. Otherwise, (time_t)(-1) is returned to indicate an
+* error.
+*
+*Exceptions:
+* None.
+*
+*******************************************************************************/
+
+static time_t _CRTAPI3 _make_time_t (
+ struct tm *tb,
+ int ultflag
+ )
+{
+ long tmptm1, tmptm2, tmptm3;
+ struct tm *tbtemp;
+
+ /*
+ * First, make sure tm_year is reasonably close to being in range.
+ */
+ if ( ((tmptm1 = tb->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR
+ + 1) )
+ goto err_mktime;
+
+
+ /*
+ * Adjust month value so it is in the range 0 - 11. This is because
+ * we don't know how many days are in months 12, 13, 14, etc.
+ */
+
+ if ( (tmptm2 = tb->tm_mon/12) != 0L ) {
+ /*
+ * no danger of overflow because the range check above.
+ */
+ tmptm1 += tmptm2;
+
+ if ( (tb->tm_mon %= 12) < 0 ) {
+ tb->tm_mon += 12;
+ tmptm1--;
+ }
+
+ /*
+ * Make sure year count is still in range.
+ */
+ if ( (tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR + 1) )
+ goto err_mktime;
+ }
+
+ /***** HERE: tmptm1 holds number of elapsed years *****/
+
+ /*
+ * Calculate days elapsed minus one, in the given year, to the given
+ * month. Check for leap year and adjust if necessary.
+ */
+ tmptm2 = _days[tb->tm_mon];
+ if ( !(tmptm1 & 3) && (tb->tm_mon > 1) )
+ tmptm2++;
+
+ /*
+ * Calculate elapsed days since base date (midnight, 1/1/70, UTC)
+ *
+ *
+ * 365 days for each elapsed year since 1970, plus one more day for
+ * each elapsed leap year. no danger of overflow because of the range
+ * check (above) on tmptm1.
+ */
+ tmptm3 = (tmptm1 - _BASE_YEAR) * 365L + ((tmptm1 - 1L) >> 2)
+ - _LEAP_YEAR_ADJUST;
+
+ /*
+ * elapsed days to current month (still no possible overflow)
+ */
+ tmptm3 += tmptm2;
+
+ /*
+ * elapsed days to current date. overflow is now possible.
+ */
+ tmptm1 = tmptm3 + (tmptm2 = (long)(tb->tm_mday));
+ if ( ChkAdd(tmptm1, tmptm3, tmptm2) )
+ goto err_mktime;
+
+ /***** HERE: tmptm1 holds number of elapsed days *****/
+
+ /*
+ * Calculate elapsed hours since base date
+ */
+ tmptm2 = tmptm1 * 24L;
+ if ( ChkMul(tmptm2, tmptm1, 24L) )
+ goto err_mktime;
+
+ tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_hour);
+ if ( ChkAdd(tmptm1, tmptm2, tmptm3) )
+ goto err_mktime;
+
+ /***** HERE: tmptm1 holds number of elapsed hours *****/
+
+ /*
+ * Calculate elapsed minutes since base date
+ */
+
+ tmptm2 = tmptm1 * 60L;
+ if ( ChkMul(tmptm2, tmptm1, 60L) )
+ goto err_mktime;
+
+ tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_min);
+ if ( ChkAdd(tmptm1, tmptm2, tmptm3) )
+ goto err_mktime;
+
+ /***** HERE: tmptm1 holds number of elapsed minutes *****/
+
+ /*
+ * Calculate elapsed seconds since base date
+ */
+
+ tmptm2 = tmptm1 * 60L;
+ if ( ChkMul(tmptm2, tmptm1, 60L) )
+ goto err_mktime;
+
+ tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_sec);
+ if ( ChkAdd(tmptm1, tmptm2, tmptm3) )
+ goto err_mktime;
+
+ /***** HERE: tmptm1 holds number of elapsed seconds *****/
+
+ if ( ultflag ) {
+ /*
+ * Adjust for timezone. No need to check for overflow since
+ * localtime() will check its arg value
+ */
+
+#ifdef _POSIX_
+ tzset();
+#else
+ __tzset();
+#endif
+ tmptm1 += _timezone;
+
+ /*
+ * Convert this second count back into a time block structure.
+ * If localtime returns NULL, return an error.
+ */
+ if ( (tbtemp = localtime(&tmptm1)) == NULL )
+ goto err_mktime;
+
+ /*
+ * Now must compensate for DST. The ANSI rules are to use the
+ * passed-in tm_isdst flag if it is non-negative. Otherwise,
+ * compute if DST applies. Recall that tbtemp has the time without
+ * DST compensation, but has set tm_isdst correctly.
+ */
+ if ( (tb->tm_isdst > 0) || ((tb->tm_isdst < 0) &&
+ (tbtemp->tm_isdst > 0)) ) {
+#ifdef _POSIX_
+ tmptm1 -= _timezone;
+ tmptm1 += _dstoffset;
+#else
+ tmptm1 -= 3600L;
+#endif
+ tbtemp = localtime(&tmptm1); /* reconvert, can't get NULL */
+ }
+ }
+ else {
+ if ( (tbtemp = gmtime(&tmptm1)) == NULL )
+ goto err_mktime;
+ }
+
+ /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/
+ /***** for local time if requested *****/
+
+ *tb = *tbtemp;
+ return (time_t)tmptm1;
+
+err_mktime:
+ /*
+ * All errors come to here
+ */
+ return (time_t)(-1);
+}
diff --git a/private/crt32/time/ppc/cinitclk.s b/private/crt32/time/ppc/cinitclk.s
new file mode 100644
index 000000000..72f68c49c
--- /dev/null
+++ b/private/crt32/time/ppc/cinitclk.s
@@ -0,0 +1,49 @@
+// ***
+// cinitclk.asm - WIN32 C Run-Time Initialization for the clock() function
+//
+// Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+//
+// Purpose:
+// Initialization entry for the clock() function
+//
+// Notes:
+// The variable _itimeb, used in clock.c, is declared in this module
+// to force the inclusion of the initializer entry if clock() is
+// referenced.
+//
+// This file declares a structure of type timeb.
+//
+// The include file "timeb.inc" must be kept in synch with sys/timeb.h
+// and depends on the alignment behavior of the Intel 386.
+//
+// Revision History:
+// 03-19-92 SKS Module created.
+// 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+// 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+// 08-06-92 SKS Revised to use new section names and macros
+// 10-27-93 MDJ Wrote (this) ppc version based on code in i386 tree
+//
+// *****************************************************************************
+
+#include "kxppc.h"
+
+ .extern __inittime
+
+
+beginSection(XIC)
+
+ .long __inittime
+
+endSection(XIC)
+
+ .globl __itimeb
+
+ .data
+ .align 2
+
+__itimeb:
+ .long 0
+ .short 0
+ .short 0
+ .short 0
+ .short 0 // struct timeb has four fields plus padding
diff --git a/private/crt32/time/sources b/private/crt32/time/sources
new file mode 100644
index 000000000..ee74a5740
--- /dev/null
+++ b/private/crt32/time/sources
@@ -0,0 +1,54 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=time
+
+TARGETNAME=time
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=asctime.c \
+ clock.c \
+ ctime.c \
+ days.c \
+ difftime.c \
+ dtoxtime.c \
+ ftime.c \
+ gmtime.c \
+ localtim.c \
+ mktime.c \
+ strftime.c \
+ strdate.c \
+ strtime.c \
+ systime.c \
+ time.c \
+ timeset.c \
+ tzset.c \
+ utime.c \
+ wcsftime.c
diff --git a/private/crt32/time/strdate.c b/private/crt32/time/strdate.c
new file mode 100644
index 000000000..ca106b12a
--- /dev/null
+++ b/private/crt32/time/strdate.c
@@ -0,0 +1,99 @@
+/***
+*strdate.c - contains the function "_strdate()" for OS/2
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains the function _strdate()
+*
+*Revision History:
+* 06-07-89 PHG Module created, base on asm version
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 07-25-90 SBM Removed '32' from API names
+* 10-04-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 05-19-92 DJM ifndef for POSIX build.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <time.h>
+#include <oscalls.h>
+
+/***
+*char *_strdate(buffer) - return date in string form
+*
+*Purpose:
+* _strdate() returns a string containing the date in "MM/DD/YY" form
+*
+*Entry:
+* char *buffer = the address of a 9-byte user buffer
+*
+*Exit:
+* returns buffer, which contains the date in "MM/DD/YY" form
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strdate (
+ char *buffer
+ )
+{
+ int month, day, year;
+
+#ifdef _CRUISER_
+ DATETIME os2time; /* OS/2 time structure */
+
+ /* get time from OS/2, no error possible */
+ DOSGETDATETIME(&os2time);
+
+ month = os2time.month;
+ day = os2time.day;
+ year = os2time.year % 100; /* change year into 0-99 value */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ SYSTEMTIME dt; /* Win32 time structure */
+
+ GetLocalTime(&dt);
+ month = dt.wMonth;
+ day = dt.wDay;
+ year = dt.wYear % 100; /* change year into 0-99 value */
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* store the components of the date into the string */
+ /* store seperators */
+ buffer[2] = buffer[5] = '/';
+ /* store end of string */
+ buffer[8] = '\0';
+ /* store tens of month */
+ buffer[0] = (char) (month / 10 + '0');
+ /* store units of month */
+ buffer[1] = (char) (month % 10 + '0');
+ /* store tens of day */
+ buffer[3] = (char) (day / 10 + '0');
+ /* store units of day */
+ buffer[4] = (char) (day % 10 + '0');
+ /* store tens of year */
+ buffer[6] = (char) (year / 10 + '0');
+ /* store units of year */
+ buffer[7] = (char) (year % 10 + '0');
+
+ return buffer;
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/strftime.c b/private/crt32/time/strftime.c
new file mode 100644
index 000000000..516f0f88e
--- /dev/null
+++ b/private/crt32/time/strftime.c
@@ -0,0 +1,891 @@
+/***
+*strftime.c - String Format Time
+*
+* Copyright (c) 1988-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 03-09-89 JCR Initial version.
+* 03-15-89 JCR Changed day/month strings from all caps to leading cap
+* 06-20-89 JCR Removed _LOAD_DGROUP code
+* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* removed some leftover 16-bit support. Also, fixed
+* the copyright.
+* 03-23-90 GJF Made static functions _CALLTYPE4.
+* 07-23-90 SBM Compiles cleanly with -W3 (removed unreferenced
+* variable)
+* 08-13-90 SBM Compiles cleanly with -W3 with new build of compiler
+* 10-04-90 GJF New-style function declarators.
+* 01-22-91 GJF ANSI naming.
+* 08-15-91 MRM Calls tzset() to set timezone info in case of %z.
+* 08-16-91 MRM Put appropriate header file for tzset().
+* 10-10-91 ETC Locale support under _INTL switch.
+* 12-18-91 ETC Use localized time strings structure.
+* 02-10-93 CFW Ported to Cuda tree, change _CALLTYPE4 to _CRTAPI3.
+* 02-16-93 CFW Massive changes: bug fixes & enhancements.
+* 03-08-93 CFW Changed _expand to _expandtime.
+* 03-09-93 CFW Handle string literals inside format strings.
+* 03-09-93 CFW Alternate form cleanup.
+* 03-17-93 CFW Change *count > 0, to *count != 0, *count is unsigned.
+* 03-22-93 CFW Change "C" locale time format specifier to 24-hour.
+* 03-30-93 GJF Call _tzset instead of __tzset (which no longer
+* exists).
+* 04-14-93 CFW Disable _alternate_form for 'X' specifier, fix count bug.
+* 07-15-93 GJF Call __tzset() in place of _tzset().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <time.h>
+#include <locale.h>
+#include <setlocal.h>
+#ifdef _INTL
+#include <ctype.h>
+#include <string.h>
+#endif
+
+/* Prototypes for local routines */
+static void _CRTAPI3 _expandtime (char specifier, const struct tm *tmptr, char **out, size_t *count);
+static void _CRTAPI3 _store_str (char *in, char **out, size_t *count);
+static void _CRTAPI3 _store_num (int num, int digits, char **out, size_t *count);
+#ifndef _INTL
+static void _CRTAPI3 _store_time (const struct tm *tmptr, char **out, size_t *count);
+static void _CRTAPI3 _store_date (const struct tm *tmptr, char **out, size_t *count);
+#else /* _INTL */
+static void _CRTAPI3 _store_number (int num, char **out, size_t *count);
+static void _CRTAPI3 _store_winword (const char *format, const struct tm *tmptr, char **out, size_t *count);
+#endif
+
+
+/* LC_TIME data for local "C" */
+
+struct _lc_time_data _lc_time_c = {
+
+ {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
+
+ {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+ "Friday", "Saturday", },
+
+ {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec"},
+
+ {"January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October",
+ "November", "December"},
+
+ {"AM", "PM"}
+
+#ifdef _INTL
+ , { "M/d/yy" }
+ , { "dddd, MMMM dd, yyyy" }
+ , { "H:mm:ss" }
+#endif
+ };
+
+
+/* Pointer to the current LC_TIME data structure. */
+
+struct _lc_time_data *_lc_time_curr = &_lc_time_c;
+
+/* Flags */
+unsigned _alternate_form = 0;
+#ifdef _INTL
+unsigned _no_lead_zeros = 0;
+#endif
+
+
+/***
+*size_t strftime(string, maxsize, format, timeptr) - Format a time string
+*
+*Purpose:
+* Place characters into the user's output buffer expanding time
+* format directives as described in the user's control string.
+* Use the supplied 'tm' structure for time data when expanding
+* the format directives.
+* [ANSI]
+*
+*Entry:
+* char *string = pointer to output string
+* size_t maxsize = max length of string
+* const char *format = format control string
+* const struct tm *timeptr = pointer to tb data structure
+*
+*Exit:
+* !0 = If the total number of resulting characters including the
+* terminating null is not more than 'maxsize', then return the
+* number of chars placed in the 'string' array (not including the
+* null terminator).
+*
+* 0 = Otherwise, return 0 and the contents of the string are
+* indeterminate.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 strftime (
+ char *string,
+ size_t maxsize,
+ const char *format,
+ const struct tm *timeptr
+ )
+{
+
+ size_t left; /* space left in output string */
+
+
+ /* Copy maxsize into temp. */
+ left = maxsize;
+
+ _mlock (_LC_TIME_LOCK);
+
+ /* Copy the input string to the output string expanding the format
+ designations appropriately. Stop copying when one of the following
+ is true: (1) we hit a null char in the input stream, or (2) there's
+ no room left in the output stream. */
+
+ while (left > 0)
+ {
+ switch(*format)
+ {
+
+ case('\0'):
+
+ /* end of format input string */
+ goto done;
+
+ case('%'):
+
+ /* Format directive. Take appropriate action based
+ on format control character. */
+
+ format++; /* skip over % char */
+
+#ifdef _INTL
+ /* process flags */
+ _alternate_form = 0;
+ if (*format == '#')
+ {
+ _alternate_form = 1;
+ format++;
+ }
+#endif
+ _expandtime(*format, timeptr, &string, &left);
+ format++; /* skip format char */
+ break;
+
+
+ default:
+
+ /* store character, bump pointers, dec the char count */
+#ifdef _INTL
+ if (isleadbyte((int)(*format)) && left > 1)
+ {
+ *string++ = *format++;
+ left--;
+ }
+#endif
+ *string++ = *format++;
+ left--;
+ break;
+ }
+ }
+
+
+ /* All done. See if we terminated because we hit a null char or because
+ we ran out of space */
+
+ done:
+
+ _munlock (_LC_TIME_LOCK);
+
+ if (left > 0) {
+
+ /* Store a terminating null char and return the number of chars
+ we stored in the output string. */
+
+ *string = '\0';
+ return(maxsize-left);
+ }
+
+ else
+ return(0);
+
+}
+
+
+/***
+*_expandtime() - Expand the conversion specifier
+*
+*Purpose:
+* Expand the given strftime conversion specifier using the time struct
+* and store it in the supplied buffer.
+*
+* The expansion is locale-dependent.
+*
+* *** For internal use with strftime() only ***
+*
+*Entry:
+* char specifier = strftime conversion specifier to expand
+* const struct tm *tmptr = pointer to time/date structure
+* char **string = address of pointer to output string
+* size_t *count = address of char count (space in output area)
+*
+*Exit:
+* none
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 _expandtime (
+ char specifier,
+ const struct tm *timeptr,
+ char **string,
+ size_t *left
+ )
+{
+ struct _lc_time_data *lc_time; /* lc_time data pointer */
+ unsigned temp; /* temps */
+ int wdaytemp;
+
+ /* Get a copy of the current _lc_time_data pointer. This
+ should prevent the necessity of locking/unlocking in mthread
+ code (if we can guarantee that the various _lc_time data
+ structures are always in the same segment). */
+ /* _INTL: contents of time strings structure can now change,
+ so thus we do use locking */
+
+ lc_time = _lc_time_curr;
+
+ switch(specifier) { /* switch on specifier */
+
+ case('a'): /* abbreviated weekday name */
+ _store_str((char *)(lc_time->wday_abbr[timeptr->tm_wday]),
+ string, left);
+ break;
+
+ case('A'): /* full weekday name */
+ _store_str((char *)(lc_time->wday[timeptr->tm_wday]),
+ string, left);
+ break;
+
+ case('b'): /* abbreviated month name */
+ _store_str((char *)(lc_time->month_abbr[timeptr->tm_mon]),
+ string, left);
+ break;
+
+ case('B'): /* full month name */
+ _store_str((char *)(lc_time->month[timeptr->tm_mon]),
+ string, left);
+ break;
+
+ case('c'): /* date and time display */
+#ifdef _INTL
+ if (_alternate_form)
+ {
+ _alternate_form = FALSE;
+ _store_winword(lc_time->ww_ldatefmt, timeptr, string, left);
+ if (*left == 0)
+ return;
+ *(*string)++=' ';
+ (*left)--;
+ _store_winword(lc_time->ww_timefmt, timeptr, string, left);
+ }
+ else {
+ _store_winword(lc_time->ww_sdatefmt, timeptr, string, left);
+ if (*left == 0)
+ return;
+ *(*string)++=' ';
+ (*left)--;
+ _store_winword(lc_time->ww_timefmt, timeptr, string, left);
+ }
+#else
+ if ((_DATE_LENGTH+_TIME_LENGTH+1) < *left)
+ {
+ _store_date(timeptr, string, left);
+ *(*string)++=' ';
+ (*left)--;
+ _store_time(timeptr, string, left);
+ }
+ else
+ *left=0;
+#endif /* _INTL */
+ break;
+
+ case('d'): /* mday in decimal (01-31) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ _store_num(timeptr->tm_mday, 2, string, left);
+ break;
+
+ case('H'): /* 24-hour decimal (00-23) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ _store_num(timeptr->tm_hour, 2, string, left);
+ break;
+
+ case('I'): /* 12-hour decimal (01-12) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ if (!(temp = timeptr->tm_hour%12))
+ temp=12;
+ _store_num(temp, 2, string, left);
+ break;
+
+ case('j'): /* yday in decimal (001-366) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ _store_num(timeptr->tm_yday+1, 3, string, left);
+ break;
+
+ case('m'): /* month in decimal (01-12) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ _store_num(timeptr->tm_mon+1, 2, string, left);
+ break;
+
+ case('M'): /* minute in decimal (00-59) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ _store_num(timeptr->tm_min, 2, string, left);
+ break;
+
+ case('p'): /* AM/PM designation */
+ if (timeptr->tm_hour <= 11)
+ _store_str((char *)(lc_time->ampm[0]), string, left);
+ else
+ _store_str((char *)(lc_time->ampm[1]), string, left);
+ break;
+
+ case('S'): /* secs in decimal (00-59) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ _store_num(timeptr->tm_sec, 2, string, left);
+ break;
+
+ case('U'): /* sunday week number (00-53) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ wdaytemp = timeptr->tm_wday;
+ goto weeknum; /* join common code */
+
+ case('w'): /* week day in decimal (0-6) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ _store_num(timeptr->tm_wday, 1, string, left);
+ break;
+
+ case('W'): /* monday week number (00-53) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ if (timeptr->tm_wday == 0) /* monday based */
+ wdaytemp = 6;
+ else
+ wdaytemp = timeptr->tm_wday-1;
+ weeknum:
+ if (timeptr->tm_yday < wdaytemp)
+ temp=0;
+ else {
+ temp = timeptr->tm_yday/7;
+ if ((timeptr->tm_yday%7) >= wdaytemp)
+ temp++;
+ }
+ _store_num(temp, 2, string, left);
+ break;
+
+ case('x'): /* date display */
+#ifdef _INTL
+ if (_alternate_form)
+ {
+ _alternate_form = FALSE;
+ _store_winword(lc_time->ww_ldatefmt, timeptr, string, left);
+ }
+ else
+ {
+ _store_winword(lc_time->ww_sdatefmt, timeptr, string, left);
+ }
+#else
+ _store_date(timeptr, string, left);
+#endif
+ break;
+
+ case('X'): /* time display */
+#ifdef _INTL
+ _alternate_form = FALSE;
+ _store_winword(lc_time->ww_timefmt, timeptr, string, left);
+#else
+ _store_time(timeptr, string, left);
+#endif
+ break;
+
+ case('y'): /* year w/o century (00-99) */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ temp = timeptr->tm_year%100;
+ _store_num(temp, 2, string, left);
+ break;
+
+ case('Y'): /* year w/ century */
+#ifdef _INTL
+ _no_lead_zeros = _alternate_form;
+#endif
+ temp = (((timeptr->tm_year/100)+19)*100) +
+ (timeptr->tm_year%100);
+ _store_num(temp, 4, string, left);
+ break;
+
+ case('Z'): /* time zone name, if any */
+ case('z'): /* time zone name, if any */
+#ifdef _POSIX_
+ tzset(); /* Set time zone info */
+ _store_str(tzname[((timeptr->tm_isdst)?1:0)],
+ string, left);
+#else
+ __tzset(); /* Set time zone info */
+ _store_str(_tzname[((timeptr->tm_isdst)?1:0)],
+ string, left);
+#endif
+ break;
+
+ case('%'): /* percent sign */
+ *(*string)++ = '%';
+ (*left)--;
+ break;
+
+ default: /* unknown format directive */
+ /* ignore the directive and continue */
+ /* [ANSI: Behavior is undefined.] */
+ break;
+
+ } /* end % switch */
+}
+
+
+/***
+*_store_str() - Copy a time string
+*
+*Purpose:
+* Copy the supplied time string into the output string until
+* (1) we hit a null in the time string, or (2) the given count
+* goes to 0.
+*
+* *** For internal use with strftime() only ***
+*
+*Entry:
+* char *in = pointer to null terminated time string
+* char **out = address of pointer to output string
+* size_t *count = address of char count (space in output area)
+*
+*Exit:
+* none
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 _store_str (
+ char *in,
+ char **out,
+ size_t *count
+ )
+{
+
+while ((*count != 0) && (*in != '\0')) {
+ *(*out)++ = *in++;
+ (*count)--;
+ }
+}
+
+
+/***
+*_store_num() - Convert a number to ascii and copy it
+*
+*Purpose:
+* Convert the supplied number to decimal and store
+* in the output buffer. Update both the count and
+* buffer pointers.
+*
+* *** For internal use with strftime() only ***
+*
+*Entry:
+* int num = pointer to integer value
+* int digits = # of ascii digits to put into string
+* char **out = address of pointer to output string
+* size_t *count = address of char count (space in output area)
+*
+*Exit:
+* none
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 _store_num (
+ int num,
+ int digits,
+ char **out,
+ size_t *count
+ )
+{
+int temp=0;
+
+#ifdef _INTL
+ if (_no_lead_zeros) {
+ _store_number (num, out, count);
+ return;
+ }
+#endif
+
+if ((size_t)digits < *count) {
+ for (digits--; (digits+1); digits--) {
+ (*out)[digits] = (char)('0' + num % 10);
+ num /= 10;
+ temp++;
+ }
+ *out += temp;
+ *count -= temp;
+ }
+else
+ *count = 0;
+}
+
+
+#ifndef _INTL
+
+/***
+*_store_time() - Store time in appropriate format
+*
+*Purpose:
+* Format the time in the current locale's format
+* and store it in the supplied buffer.
+*
+* [*** Currently, this routine assumes standard "C"
+* locale. When full localization support is introduced,
+* this functionality will have to be expanded.]
+*
+* Standard "C" locale time format:
+*
+* hh:mm:ss
+*
+* *** For internal use with strftime() only ***
+*
+*Entry:
+*
+* const struct tm *tmptr = pointer to time/date structure
+* char **out = address of pointer to output string
+* size_t *count = address of char count (space in output area)
+*
+*Exit:
+* none
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 _store_time (
+ const struct tm *tmptr,
+ char **out,
+ size_t *count
+ )
+{
+
+if (_TIME_LENGTH < *count) {
+
+ _store_num(tmptr->tm_hour, 2, out, count);
+ *(*out)++ = ':';
+ _store_num(tmptr->tm_min, 2, out, count);
+ *(*out)++ = ':';
+ _store_num(tmptr->tm_sec, 2, out, count);
+
+ *count -= 2; /* count the colons */
+}
+
+else
+ *count = 0;
+
+}
+
+
+/***
+*_store_date() - Store date in appropriate format
+*
+*Purpose:
+* Format the date in the current locale's format
+* and store it in the supplied buffer.
+*
+* [*** Currently, this routine assumes standard "C"
+* locale. When full localization support is introduced,
+* this functionality will have to be expanded.]
+*
+* Standard "C" locale date format:
+*
+* mm/dd/yy
+*
+* *** For internal use with strftime() only ***
+*
+*Entry:
+*
+* const struct tm *tmptr = pointer to time/date structure
+* char **out = address of pointer to output string
+* size_t *count = address of char count (space in output area)
+*
+*Exit:
+* none
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 _store_date (
+ const struct tm *tmptr,
+ char **out,
+ size_t *count
+ )
+{
+
+if (_DATE_LENGTH < *count) {
+
+ _store_num(tmptr->tm_mon+1, 2, out, count);
+ *(*out)++ = '/';
+ _store_num(tmptr->tm_mday, 2, out, count);
+ *(*out)++ = '/';
+ _store_num(tmptr->tm_year%100, 2, out, count);
+
+ *count -= 2; /* count the backslashes */
+ }
+
+else
+ *count = 0;
+
+}
+
+#else /* _INTL */
+
+/***
+*_store_number() - Convert positive integer to string
+*
+*Purpose:
+* Convert positive integer to a string and store it in the output
+* buffer with no null terminator. Update both the count and
+* buffer pointers.
+*
+* Differs from _store_num in that the precision is not specified,
+* and no leading zeros are added.
+*
+* *** For internal use with strftime() only ***
+*
+* Created from xtoi.c
+*
+*Entry:
+* int num = pointer to integer value
+* char **out = address of pointer to output string
+* size_t *count = address of char count (space in output area)
+*
+*Exit:
+* none
+*
+*Exceptions:
+* The buffer is filled until it is out of space. There is no
+* way to tell beforehand (as in _store_num) if the buffer will
+* run out of space.
+*
+*******************************************************************************/
+
+static void _CRTAPI3 _store_number (
+ int num,
+ char **out,
+ size_t *count
+ )
+{
+ char *p; /* pointer to traverse string */
+ char *firstdig; /* pointer to first digit */
+ char temp; /* temp char */
+
+ p = *out;
+
+ /* put the digits in the buffer in reverse order */
+ if (*count > 1)
+ {
+ do {
+ *p++ = (char) (num % 10 + '0');
+ (*count)--;
+ } while ((num/=10) > 0 && *count > 1);
+ }
+
+ firstdig = *out; /* firstdig points to first digit */
+ *out = p; /* return pointer to next space */
+ p--; /* p points to last digit */
+
+ /* reverse the buffer */
+ do {
+ temp = *p;
+ *p-- = *firstdig;
+ *firstdig++ = temp; /* swap *p and *firstdig */
+ } while (firstdig < p); /* repeat until halfway */
+}
+
+
+/***
+*_store_winword() - Store date/time in WinWord format
+*
+*Purpose:
+* Format the date/time in the supplied WinWord format
+* and store it in the supplied buffer.
+*
+* *** For internal use with strftime() only ***
+*
+* The WinWord format is converted token by token to
+* strftime conversion specifiers. _expandtime is then called to
+* do the work. The WinWord format is expected to be a
+* character string (not wide-chars).
+*
+*Entry:
+* const char **format = address of pointer to WinWord format
+* const struct tm *tmptr = pointer to time/date structure
+* char **out = address of pointer to output string
+* size_t *count = address of char count (space in output area)
+*
+*Exit:
+* none
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CRTAPI3 _store_winword (
+ const char *format,
+ const struct tm *tmptr,
+ char **out,
+ size_t *count
+ )
+{
+ char specifier;
+ const char *p;
+ int repeat;
+
+ while (*format && *count != 0)
+ {
+ specifier = 0; /* indicate no match */
+ _no_lead_zeros = 0; /* default is print leading zeros */
+
+ /* count the number of repetitions of this character */
+ for (repeat=0, p=format; *p++ == *format; repeat++);
+ /* leave p pointing to the beginning of the next token */
+ p--;
+
+ /* switch on ascii format character and determine specifier */
+ switch (*format)
+ {
+ case 'M':
+ switch (repeat)
+ {
+ case 1: _no_lead_zeros = 1; /* fall thru */
+ case 2: specifier = 'm'; break;
+ case 3: specifier = 'b'; break;
+ case 4: specifier = 'B'; break;
+ } break;
+ case 'd':
+ switch (repeat)
+ {
+ case 1: _no_lead_zeros = 1; /* fall thru */
+ case 2: specifier = 'd'; break;
+ case 3: specifier = 'a'; break;
+ case 4: specifier = 'A'; break;
+ } break;
+ case 'y':
+ switch (repeat)
+ {
+ case 2: specifier = 'y'; break;
+ case 4: specifier = 'Y'; break;
+ } break;
+ case 'h':
+ switch (repeat)
+ {
+ case 1: _no_lead_zeros = 1; /* fall thru */
+ case 2: specifier = 'I'; break;
+ } break;
+ case 'H':
+ switch (repeat)
+ {
+ case 1: _no_lead_zeros = 1; /* fall thru */
+ case 2: specifier = 'H'; break;
+ } break;
+ case 'm':
+ switch (repeat)
+ {
+ case 1: _no_lead_zeros = 1; /* fall thru */
+ case 2: specifier = 'M'; break;
+ } break;
+ case 's': /* for compatibility; not strictly WinWord */
+ switch (repeat)
+ {
+ case 1: _no_lead_zeros = 1; /* fall thru */
+ case 2: specifier = 'S'; break;
+ } break;
+ case 'A':
+ case 'a':
+ if (!_stricmp(format, "am/pm"))
+ p = format + 5;
+ else if (!_stricmp(format, "a/p"))
+ p = format + 3;
+ specifier = 'p';
+ break;
+ case '\'': /* literal string */
+ if (repeat & 1) /* odd number */
+ {
+ format += repeat;
+ while (*format && *count != 0)
+ {
+ if (*format == '\'')
+ {
+ format++;
+ break;
+ }
+ if (isleadbyte((int)*format))
+ {
+ *(*out)++ = *format++;
+ (*count)--;
+ }
+ *(*out)++ = *format++;
+ (*count)--;
+ }
+ }
+ else { /* even number */
+ format += repeat;
+ }
+ continue;
+
+ default: /* non-control char, print it */
+ break;
+ } /* switch */
+
+ /* expand specifier, or copy literal if specifier not found */
+ if (specifier)
+ {
+ _expandtime(specifier, tmptr, out, count);
+ format = p; /* bump format up to the next token */
+ } else {
+ if (isleadbyte((int)*format))
+ {
+ *(*out)++ = *format++;
+ (*count)--;
+ }
+ *(*out)++ = *format++;
+ (*count)--;
+ }
+ } /* while */
+}
+
+#endif /* _INTL */
diff --git a/private/crt32/time/strtime.c b/private/crt32/time/strtime.c
new file mode 100644
index 000000000..7525b672d
--- /dev/null
+++ b/private/crt32/time/strtime.c
@@ -0,0 +1,98 @@
+/***
+*strtime.c - contains the function "_strtime()" for OS/2
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* contains the function _strtime()
+*
+*Revision History:
+* 06-07-89 PHG Module created, based on asm version
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 07-25-90 SBM Removed '32' from API names
+* 10-04-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 05-19-92 DJM ifndef for POSIX build.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <time.h>
+#include <oscalls.h>
+
+/***
+*char *_strtime(buffer) - return time in string form
+*
+*Purpose:
+* _strtime() returns a string containing the time in "HH:MM:SS" form
+*
+*Entry:
+* char *buffer = the address of a 9-byte user buffer
+*
+*Exit:
+* returns buffer, which contains the time in "HH:MM:SS" form
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+char * _CALLTYPE1 _strtime (
+ char *buffer
+ )
+{
+ int hours, minutes, seconds;
+
+#ifdef _CRUISER_
+ DATETIME os2time; /* OS/2 time structure */
+
+ /* ask OS/2 for the time, no error possible */
+ DOSGETDATETIME(&os2time);
+ hours = os2time.hours;
+ minutes = os2time.minutes;
+ seconds = os2time.seconds;
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ SYSTEMTIME dt; /* Win32 time structure */
+
+ GetLocalTime(&dt);
+ hours = dt.wHour;
+ minutes = dt.wMinute;
+ seconds = dt.wSecond;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* store the components of the time into the string */
+ /* store separators */
+ buffer[2] = buffer[5] = ':';
+ /* store end of string */
+ buffer[8] = '\0';
+ /* store tens of hour */
+ buffer[0] = (char) (hours / 10 + '0');
+ /* store units of hour */
+ buffer[1] = (char) (hours % 10 + '0');
+ /* store tens of minute */
+ buffer[3] = (char) (minutes / 10 + '0');
+ /* store units of minute */
+ buffer[4] = (char) (minutes % 10 + '0');
+ /* store tens of second */
+ buffer[6] = (char) (seconds / 10 + '0');
+ /* store units of second */
+ buffer[7] = (char) (seconds % 10 + '0');
+
+ return buffer;
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/systime.c b/private/crt32/time/systime.c
new file mode 100644
index 000000000..cd7590cd0
--- /dev/null
+++ b/private/crt32/time/systime.c
@@ -0,0 +1,104 @@
+/***
+*systime.c - _getsystime and _setsystime
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _getsystime() and _setsystime()
+*
+*Revision History:
+* 08-22-91 BWM Wrote module.
+* 05-19-92 DJM ifndef for POSIX build.
+* 09-25-92 SKS Use SetLocalTime(), not SetSystemTime().
+* Fix bug: daylight flag must be initialized to -1.
+* Replace C++ comments with C-style comments
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <time.h>
+
+#if !defined(_WIN32_)
+#error ERROR - ONLY WIN32 TARGET SUPPORTED!
+#endif
+
+/***
+*unsigned _getsystime(timestruc, milliseconds) - Get current system time
+*
+*Purpose:
+*
+*Entry:
+ struct tm * ptm - time structure
+*
+*Exit:
+* milliseconds of current time
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned _CALLTYPE1 _getsystime(struct tm * ptm)
+{
+ SYSTEMTIME st;
+
+ GetLocalTime(&st);
+
+ ptm->tm_isdst = -1; /* mktime() computes whether this is */
+ /* during Standard or Daylight time. */
+ ptm->tm_sec = (int)st.wSecond;
+ ptm->tm_min = (int)st.wMinute;
+ ptm->tm_hour = (int)st.wHour;
+ ptm->tm_mday = (int)st.wDay;
+ ptm->tm_mon = (int)st.wMonth - 1;
+ ptm->tm_year = (int)st.wYear - 1900;
+ ptm->tm_wday = (int)st.wDayOfWeek;
+
+ /* Normalize uninitialized fields */
+ mktime(ptm);
+
+ return (st.wMilliseconds);
+}
+
+/***
+*unsigned _setsystime(timestruc, milliseconds) - Set new system time
+*
+*Purpose:
+*
+*Entry:
+* struct tm * ptm - time structure
+* unsigned milliseconds - milliseconds of current time
+*
+*Exit:
+* 0 if succeeds
+* system error if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+unsigned _CALLTYPE1 _setsystime(struct tm * ptm, unsigned uMilliseconds)
+{
+ SYSTEMTIME st;
+
+ /* Normalize uninitialized fields */
+ mktime(ptm);
+
+ st.wYear = (WORD)(ptm->tm_year + 1900);
+ st.wMonth = (WORD)(ptm->tm_mon + 1);
+ st.wDay = (WORD)ptm->tm_mday;
+ st.wHour = (WORD)(ptm->tm_hour);
+ st.wMinute = (WORD)ptm->tm_min;
+ st.wSecond = (WORD)ptm->tm_sec;
+ st.wMilliseconds = (WORD)uMilliseconds;
+
+ if (!SetLocalTime(&st)) {
+ return ((int)GetLastError());
+ }
+
+ return (0);
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/time.c b/private/crt32/time/time.c
new file mode 100644
index 000000000..8a77b538e
--- /dev/null
+++ b/private/crt32/time/time.c
@@ -0,0 +1,78 @@
+/***
+*time.c - get current system time
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines time() - gets the current system time and converts it to
+* internal (time_t) format time.
+*
+*Revision History:
+* 06-07-89 PHG Module created, based on asm version
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also, cleaned
+* up the formatting a bit.
+* 07-25-90 SBM Removed '32' from API names
+* 10-04-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 05-19-92 DJM ifndef for POSIX build.
+* 03-30-93 GJF Replaced dtoxtime() reference by __gmtotime_t. Also
+* purged Cruiser support.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <time.h>
+#include <oscalls.h>
+#include <internal.h>
+
+/***
+*time_t time(timeptr) - Get current system time and convert to time_t value.
+*
+*Purpose:
+* Gets the current date and time and stores it in internal (time_t)
+* format. The time is returned and stored via the pointer passed in
+* timeptr. If timeptr == NULL, the time is only returned, not stored in
+* *timeptr. The internal (time_t) format is the number of seconds since
+* 00:00:00, Jan 1 1970 (UTC).
+*
+*Entry:
+* time_t *timeptr - pointer to long to store time in.
+*
+*Exit:
+* returns the current time.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+time_t _CRTAPI1 time (
+ time_t *timeptr
+ )
+{
+ time_t tim;
+
+ SYSTEMTIME dt;
+
+ /* ask Win32 for the time, no error possible */
+
+ GetSystemTime(&dt);
+
+ /* convert using our private routine */
+ tim = __gmtotime_t((int)dt.wYear,
+ (int)dt.wMonth,
+ (int)dt.wDay,
+ (int)dt.wHour,
+ dt.wMinute,
+ dt.wSecond);
+
+ if (timeptr)
+ *timeptr = tim; /* store time if requested */
+
+ return tim;
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/timeset.c b/private/crt32/time/timeset.c
new file mode 100644
index 000000000..86a9f3cd1
--- /dev/null
+++ b/private/crt32/time/timeset.c
@@ -0,0 +1,92 @@
+/***
+*timeset.c - contains defaults for timezone setting
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the timezone values for default timezone.
+* Also contains month and day name three letter abbreviations.
+*
+*Revision History:
+* 12-03-86 JMB added Japanese defaults and module header
+* 09-22-87 SKS fixed declarations, include <time.h>
+* 02-21-88 SKS Clean up ifdef-ing, change IBMC20 to IBMC2
+* 07-05-89 PHG Remove _NEAR_ for 386
+* 08-15-89 GJF Fixed copyright, indents. Got rid of _NEAR.
+* 03-20-90 GJF Added #include <cruntime.h> and fixed the copyright.
+* 05-18-90 GJF Added _VARTYPE1 to publics to match declaration in
+* time.h (picky 6.0 front-end!).
+* 01-21-91 GJF ANSI naming.
+* 08-10-92 PBS Posix support(TZ stuff).
+* 06-08-93 KRS Tie JAPAN switch to _KANJI switch.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <time.h>
+#include <internal.h>
+
+#ifndef _POSIX_
+
+#ifdef _KANJI
+#define JAPAN
+#endif
+
+#ifdef JAPAN
+static char tzstd[11] = { "JST" };
+static char tzdst[11] = { "\0\0\0" };
+#else
+static char tzstd[11] = { "PST" };
+static char tzdst[11] = { "PDT" };
+#endif
+
+
+#ifdef JAPAN
+
+long _timezone = (-9)*3600L; /* Japanese Time */
+int _daylight = 0; /* no Daylight Savings Time */
+
+#else /* JAPAN */
+#ifdef IBMC2
+
+long _timezone = 5*3600L; /* Eastern Time */
+int _daylight = 1; /* Daylight Savings Time */
+ /* when appropriate */
+#else /* IBMC2 */
+
+long _timezone = 8*3600L; /* Pacific Time */
+int _daylight = 1; /* Daylight Savings Time */
+ /* when appropriate */
+#endif /* IBMC2 */
+#endif /* JAPAN */
+
+char * _tzname[2] = {tzstd, tzdst };
+
+#else /* _POSIX_ */
+
+long _timezone = 8*3600L; /* Pacific Time */
+int _daylight = 1; /* Daylight Savings Time */
+ /* when appropriate */
+
+static char tzstd[11] = { "PST" };
+static char tzdst[11] = { "PDT" };
+
+char * tzname[2] = {tzstd, tzdst };
+
+char *_rule;
+long _dstoffset = 3600L;
+
+#endif /* _POSIX_ */
+
+/* Day names must be Three character abbreviations strung together */
+
+char __dnames[] = {
+ "SunMonTueWedThuFriSat"
+};
+
+/* Month names must be Three character abbreviations strung together */
+
+char __mnames[] = {
+ "JanFebMarAprMayJunJulAugSepOctNovDec"
+};
diff --git a/private/crt32/time/tzset.c b/private/crt32/time/tzset.c
new file mode 100644
index 000000000..d5b5c711e
--- /dev/null
+++ b/private/crt32/time/tzset.c
@@ -0,0 +1,927 @@
+/***
+*tzset.c - set timezone information and see if we're in daylight time
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _tzset() - set timezone and daylight saving time vars
+*
+*Revision History:
+* 03-??-84 RLB initial version
+* 03-26-86 TC added minus capability to time difference w.r.t GMT
+* 03-27-86 TC fixed daylight davings time calculation, off by a day
+* error
+* 12-03-86 SKS daylight savings time is different starting april 1987
+* Fixed off-by-1 errors when either Apr 30 or Oct 31 is
+* Sat. Simplified leap year check: this works for
+* 1970-2099 only!
+* 11-19-87 SKS Add __tzset() which calls tzset only the first time
+* Made _isindst() a near procedure
+* 11-25-87 WAJ Added calls to _lock and _unlock
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 01-27-88 SKS Made _isindst() and _dtoxtime() are no longer near (for
+* QC)
+* 05-24-88 PHG Merged DLL and normal versions
+* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h>, removed
+* some leftover 16-bit support and fixed the copyright.
+* Also, cleaned up the formatting a bit.
+* 03-23-90 GJF Made static functions _CALLTYPE4.
+* 07-30-90 SBM Added void to empty function arg lists to create
+* prototypes
+* 10-04-90 GJF New-style function declarators.
+* 01-21-91 GJF ANSI naming.
+* 08-10-92 PBS Posix Support (TZ stuff).
+* 03-30-93 GJF Ported C8-16 version to Win32.
+* 06-28-93 GJF Limited support for system's notion of time zone
+* in Windows NT.
+* 07-15-93 GJF Resurrected __tzset().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+#include <ctime.h>
+#include <time.h>
+#include <stdlib.h>
+#include <internal.h>
+#ifdef _POSIX_
+#include <limits.h>
+#else
+#include <os2dll.h>
+#include <windows.h>
+#endif
+#include <string.h>
+
+#ifndef _POSIX_
+/*
+ * Pointer to a saved copy of the TZ value obtained in the previous call
+ * to tzset() set (if any).
+ */
+static char * lastTZ = NULL;
+#endif
+
+
+/***
+*void tzset() - sets timezone information and calc if in daylight time
+*
+*Purpose:
+* Sets the timezone information from the TZ environment variable
+* and then sets _timezone, _daylight, and _tzname. If we're in daylight
+* time is automatically calculated.
+*
+*Entry:
+* None, reads TZ environment variable.
+*
+*Exit:
+* sets _daylight, _timezone, and _tzname global vars, no return value
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#ifdef MTHREAD
+static void _CRTAPI3 _tzset_lk(void);
+#else
+#define _tzset_lk _tzset
+#endif
+
+void _CRTAPI1 __tzset(void)
+{
+ static int first_time;
+
+ if ( !first_time ) {
+
+ _mlock( _TIME_LOCK );
+
+ if ( !first_time ) {
+ _tzset_lk();
+ first_time++;
+ }
+
+ _munlock(_TIME_LOCK );
+
+ }
+}
+
+
+#ifdef MTHREAD /* multi-thread; define both tzset and _tzset_lk */
+void _CRTAPI1 _tzset (
+ void
+ )
+{
+ _mlock( _TIME_LOCK );
+
+ _tzset_lk();
+
+ _munlock( _TIME_LOCK );
+}
+
+
+static void _CRTAPI3 _tzset_lk (
+
+#else /* non multi-thread; only define tzset */
+
+void _CRTAPI1 _tzset (
+
+#endif /* rejoin common code */
+
+ void
+ )
+{
+ REG1 char *TZ;
+ REG2 int negdiff = 0;
+
+ _mlock(_ENV_LOCK);
+
+ /*
+ * Fetch the value of the TZ environment variable.
+ */
+ if ( (TZ = _getenv_lk("TZ")) == NULL ) {
+ /*
+ * If there is no TZ environment variable, try to use the
+ * time zone information from the system.
+ */
+ TIME_ZONE_INFORMATION tzinfo;
+
+ if ( GetTimeZoneInformation( &tzinfo ) != 0xffffffff ) {
+ /*
+ * Derive _timezone value from Bias and StandardBias fields.
+ */
+ _timezone = tzinfo.Bias * 60L;
+
+ if ( tzinfo.StandardDate.wMonth != 0 )
+ _timezone += (tzinfo.StandardBias * 60L);
+
+ /*
+ * Check to see if there is a daylight time bias. If so, we
+ * ASSUME it is USA daylight saving time (that is all we
+ * support for rev. one).
+ */
+ if ( (tzinfo.DaylightDate.wMonth != 0) &&
+ (tzinfo.DaylightBias != 0) )
+ _daylight = 1;
+ else
+ _daylight = 0;
+
+ /*
+ * Remove the default names, but don't try to determine
+ * suitable replacements (NT does not enforce any standard
+ * or convention for timezone naming).
+ */
+ *_tzname[0] = '\0';
+ *_tzname[1] = '\0';
+ }
+
+ /*
+ * Time zone information is unavailable, just return.
+ */
+ _munlock(_ENV_LOCK);
+ return;
+ }
+
+
+ if ( (*TZ == '\0') || ((lastTZ != NULL) && (strcmp(TZ, lastTZ) == 0)) )
+ {
+ /*
+ * Either TZ is NULL, pointing to '\0', or is the unchanged
+ * from a earlier call (to this function). In any case, there
+ * is no work to do, so just return
+ */
+ _munlock(_ENV_LOCK);
+ return;
+ }
+
+ /*
+ * Update lastTZ
+ */
+ if (lastTZ != NULL) {
+ free(lastTZ);
+ }
+ lastTZ = strdup(TZ);
+
+ _munlock(_ENV_LOCK);
+
+ /*
+ * Process TZ value and update _tzname, _timezone and _daylight.
+ */
+
+ strncpy(_tzname[0], TZ, 3);
+
+ /*
+ * time difference is of the form:
+ *
+ * [+|-]hh[:mm[:ss]]
+ *
+ * check minus sign first.
+ */
+ if ( *(TZ += 3) == '-' ) {
+ negdiff++;
+ TZ++;
+ }
+
+ /*
+ * process, then skip over, the hours
+ */
+ _timezone = atol(TZ) * 3600L;
+
+ while ( (*TZ == '+') || ((*TZ >= '0') && (*TZ <= '9')) ) TZ++;
+
+ /*
+ * check if minutes were specified
+ */
+ if ( *TZ == ':' ) {
+ /*
+ * process, then skip over, the minutes
+ */
+ _timezone += atol(++TZ) * 60L;
+ while ( (*TZ >= '0') && (*TZ <= '9') ) TZ++;
+
+ /*
+ * check if seconds were specified
+ */
+ if ( *TZ == ':' ) {
+ /*
+ * process, then skip over, the seconds
+ */
+ _timezone += atol(++TZ);
+ while ( (*TZ >= '0') && (*TZ <= '9') ) TZ++;
+ }
+ }
+
+ if ( negdiff )
+ _timezone = -_timezone;
+
+ /*
+ * finally, check for a DST zone suffix
+ */
+ if ( _daylight = *TZ )
+ strncpy(_tzname[1], TZ, 3);
+ else
+ *_tzname[1] = '\0';
+
+}
+
+
+/***
+*int _isindst(tb) - determine if broken-down time falls in DST
+*
+*Purpose:
+* Determine if the given broken-down time falls within DST. Only
+* modern, summer-time DST is handled (USA, post 1967).
+*
+* This is the rule for years before 1987:
+* a time is in DST iff it is on or after 02:00:00 on the last Sunday
+* in April and before 01:00:00 on the last Sunday in October.
+* This is the rule for years starting with 1987:
+* a time is in DST iff it is on or after 02:00:00 on the first Sunday
+* in April and before 01:00:00 on the last Sunday in October.
+*
+*Entry:
+* struct tm *tb - structure holding broken-down time value
+*
+*Exit:
+* 1, if time represented is in DST
+* 0, otherwise
+*
+*******************************************************************************/
+
+int _CRTAPI1 _isindst (
+ REG1 struct tm *tb
+ )
+{
+ int mdays;
+ REG2 int yr;
+ int critsun;
+
+ /*
+ * Handle easy cases.
+ *
+ * Modern DST was put into effect by Congress in 1967. Also, if the
+ * month is before April or after October, it cannot be DST.
+ */
+ if ( (tb->tm_year < 67) || (tb->tm_mon < 3) || (tb->tm_mon > 9) )
+ return(0);
+
+ /*
+ * If the month is after April and before October, it must be DST.
+ */
+ if ( (tb->tm_mon > 3) && (tb->tm_mon < 9) )
+ return(1);
+
+ /*
+ * Now for the hard part. Month is April or October; see if date
+ * falls between appropriate Sundays.
+ */
+
+ /*
+ * The objective for years before 1987 (after 1986) is to determine
+ * if the day is on or after 2:00 am on the last (first) Sunday in
+ * April, or before 1:00 am on the last Sunday in October.
+ *
+ * We know the year-day (0..365) of the current time structure. We must
+ * determine the year-day of the last (first) Sunday in this month,
+ * April or October, and then do the comparison.
+ *
+ * To determine the year-day of the last Sunday, we do the following:
+ * 1. Get the year-day of the last day of the current month (Apr
+ * or Oct)
+ * 2. Determine the week-day number of #1,
+ * which is defined as 0 = Sun, 1 = Mon, ... 6 = Sat
+ * 3. Subtract #2 from #1
+ *
+ * To determine the year-day of the first Sunday, we do the following:
+ * 1. Get the year-day of the 7th day of the current month
+ * (April)
+ * 2. Determine the week-day number of #1,
+ * which is defined as 0 = Sun, 1 = Mon, ... 6 = Sat
+ * 3. Subtract #2 from #1
+ */
+
+ /*
+ * First we get #1. The year-days for each month are stored in _days[]
+ * they're all off by -1
+ */
+ if ( ((yr = tb->tm_year) > 86) && (tb->tm_mon == 3) )
+ mdays = 7 + _days[tb->tm_mon];
+ else
+ mdays = _days[tb->tm_mon+1];
+
+ /*
+ * if this is a leap-year, add an extra day
+ */
+ if ( !(yr & 3) )
+ mdays++;
+
+ /*
+ * mdays now has #1
+ */
+
+ /* Now get #2. We know the week-day number of January 1, 1970, which is
+ * defined as the constant _BASE_DOW. Add to this the number of elapsed
+ * days since then, take the result mod 7, and we have our day number.
+ *
+ * To obtain #3, we just subtract this from mdays.
+ */
+
+ critsun = mdays - ((mdays + 365 * (yr - 70) + ((yr - 1) >> 2) -
+ _LEAP_YEAR_ADJUST + _BASE_DOW) % 7);
+
+ /* Now we know 1 and 3; we're golden: */
+
+ return ( (tb->tm_mon == 3)
+ ? ((tb->tm_yday > critsun) ||
+ ((tb->tm_yday == critsun) && (tb->tm_hour >= 2)))
+ : ((tb->tm_yday < critsun) ||
+ ((tb->tm_yday == critsun) && (tb->tm_hour < 1))) );
+}
+
+
+#else /* _POSIX_ */
+
+/*
+ * The following is an implementation of the TZ grammar specified in the
+ * document:
+ *
+ * 8.1.1 Extension to Time Functions
+ * IEEE Std 1003.1 - 1990
+ * Page 152 - 153
+ *
+ * The TZ grammar looks like:
+ *
+ * stdoffset[dst[offset][,start[/time],end[/time]]]
+ *
+ * Variables used in code:
+ *
+ * tzname[0] ==> std
+ * _timezone ==> offset(the one after 'std')
+ * tzname[1] ==> dst
+ * _dstoffset ==> offset(the one after 'dst')
+ * _startdate ==> start
+ * _starttime ==> time(the one after 'start')
+ * _enddate ==> end
+ * _endtime ==> time(the one after 'end')
+ *
+ */
+
+/*
+ * Refer to the document for the detailed description of fields of _DSTDATE.
+ * Two of Jn, n, and Mm are -1, indicating the one(not -1) is a vaild value.
+ */
+
+typedef struct _DSTDATE {
+ int Jn; /* -1 or [1, 365](year day and leap day shall not be counted) */
+ int n; /* -1 or [0, 365](year day and leap day shall be counted) */
+ int Mm; /* -1 or [1, 12](month) */
+ int Mn; /* [1, 5] if Mm != -1 (week) */
+ int Md; /* [0, 6] if Mm != -1 (weekday, Sunday == 0) */
+} DSTDATE, *PDSTDATE;
+
+#define SEC_PER_HOUR (60 * 60)
+#define SEC_PER_DAY (SEC_PER_HOUR * 24)
+
+
+/*
+ * The default TZ in tzset() should look like:
+ *
+ * TZ = "PST8PDT,M4.1.0/2:00,M10.5.0/2:00";
+ */
+
+/* Day light saving start/end date and default vaules */
+static DSTDATE _startdate = { -1, -1, 4, 1, 0};
+static DSTDATE _enddate = {-1, -1, 10, 5, 0};
+
+
+/* Seconds since midnight on _startdate/_enddate with default values.
+ * _endtime is 1am instead of 2am because the DST end time is 2am
+ * local time, which by default is 1am standard time.
+ */
+long _starttime = 7200L, _endtime = 7200L;
+
+/*
+ * If we are only interested in years between 1901 and 2099, we could use this:
+ *
+ * #define IS_LEAP_YEAR(y) (y % 4 == 0)
+ */
+
+#define IS_LEAP_YEAR(y) ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
+
+
+/*
+ * ParsePosixStdOrDst - parse the std or dst element in TZ.
+ *
+ * ENTRY pch - beginning of the substring in TZ.
+ *
+ * RETURN pointer to one position after the std or dst element parsed,
+ * or NULL if failed.
+ */
+
+
+static char * _CRTAPI3
+ParsePosixStdOrDst(
+ REG1 char *pch
+ )
+{
+#define UNWANTED(x) (isdigit(x) || x=='\0' || x==',' || x=='-' || x=='+')
+ int i;
+
+ /*
+ * Check against the rule.
+ */
+
+ if(*pch == ':' || UNWANTED(*pch)) {
+ return NULL;
+ }
+
+ /*
+ * Get a valid std or dst(i.e. 3 <= lenth_of(std | dst) <= TZNAME_MAX).
+ */
+
+ for(i=1, ++pch; (i < TZNAME_MAX) && !UNWANTED(*pch); i++, pch++) {
+ ;
+ }
+
+ /*
+ * pch now point to 1 position after the valid std or dst.
+ */
+
+ return (i >= 3) ? pch : NULL;
+}
+
+
+/*
+ * ParsePosixOffset - parse the offset element in TZ. The format of time is:
+ *
+ * [- | +]hh[:mm[:ss]]
+ *
+ * ENTRY pch - beginning of the substring in TZ.
+ *
+ * ptime - pointer to a variable(_timezone or _dstoffset) storing the
+ * time(in seconds) parsed.
+ *
+ * RETURN pointer to one position after the end of the offset element parsed.
+ */
+
+
+static char * _CRTAPI3
+ParsePosixOffset(
+ REG1 char *pch,
+ REG2 long *poffset
+ )
+{
+ int fNegative;
+ long offset;
+
+ if((fNegative = (*pch == '-')) || *pch == '+') {
+ pch++;
+ }
+
+ offset = atol(pch)*3600L; /* hh */
+
+ while(*pch && isdigit(*pch)) {
+ pch++;
+ }
+
+ if(*pch == ':') {
+ offset += atol(++pch)*60L; /* mm */
+ while(*pch && isdigit(*pch)) {
+ pch++;
+ }
+
+ if(*pch == ':') {
+ offset += atol(++pch); /* ss */
+ while(*pch && isdigit(*pch)) {
+ pch++;
+ }
+ }
+ }
+
+ *poffset = fNegative ? -offset : offset;
+
+ return pch;
+}
+
+
+
+/*
+ * ParsePosixDate - parse the date element in TZ. The format of date is one
+ * of following:
+ *
+ * Jn, n, and Mm.n.d
+ *
+ * ENTRY pch - beginning of the substring in TZ.
+ *
+ * pDstDate - pointer to _startdate or _enddate storing the result.
+ *
+ * RETURN pointer to one position after the end of the date element parsed,
+ * or NULL if failed.
+ */
+
+static char * _CRTAPI3
+ParsePosixDate(
+ REG1 char *pch,
+ REG2 PDSTDATE pDstDate
+ )
+{
+ pDstDate->Jn = -1;
+ pDstDate->n = -1;
+ pDstDate->Mn = -1;
+
+ /*
+ * Two out of the three -1's will remain.
+ */
+
+ if(*pch == 'J') { /* Jn */
+ pDstDate->Jn = atoi(++pch);
+ } else if(*pch != 'M') { /* n */
+ pDstDate->n = atoi(pch);
+ } else { /* Mm.n.d */
+
+ pDstDate->Mm = atoi(++pch);
+
+ if(*++pch != '.') {
+ pch++;
+ }
+ pDstDate->Mn = atoi(++pch);
+
+ if(*++pch != '.') {
+ pch++;
+ }
+ pDstDate->Md = atoi(++pch);
+ }
+
+ while(*pch && isdigit(*pch)) {
+ pch++;
+ }
+
+#define IN_RANGE(x, a, b) (x >= a && x <= b)
+
+ return ((pDstDate->Jn != -1 && IN_RANGE(pDstDate->Jn, 1, 365)) ||
+ (pDstDate->n != -1 && IN_RANGE(pDstDate->n, 0, 365)) ||
+ (pDstDate->Mm != -1 && IN_RANGE(pDstDate->Mm, 1, 12) &&
+ IN_RANGE(pDstDate->Mn, 1, 5) && IN_RANGE(pDstDate->Md, 0, 6)))
+ ? pch : NULL;
+}
+
+/*
+ * ParsePosixTime - parse the time element in TZ. The format of time is:
+ *
+ * hh[:mm[:ss]]
+ *
+ * ENTRY pch - beginning of the substring in TZ.
+ *
+ * ptime - pointer to a variable(_starttime or _endtime) storing the
+ * time(in seconds) parsed.
+ *
+ * RETURN pointer to one position after the end of the time element parsed.
+ */
+
+static char * _CRTAPI3
+ParsePosixTime(
+ REG1 char *pch,
+ REG2 long *ptime
+ )
+{
+ long time;
+
+ time = atol(pch)*SEC_PER_HOUR; /* hh */
+
+ while(*pch && isdigit(*pch)) {
+ pch++;
+ }
+
+ if(*pch == ':') {
+
+ time += atol(++pch)*60L; /* mm */
+ while(*pch && isdigit(*pch)) {
+ pch++;
+ }
+
+ if(*pch == ':') {
+
+ time += atol(++pch); /* ss */
+ while(*pch && isdigit(*pch)) {
+ pch++;
+ }
+ }
+ }
+
+ *ptime = time;
+
+ return pch;
+}
+
+/*
+ * tzset - sets the timezone information from the TZ environment variable.
+ * Global tzname[], _timezone, _daylight, and _dstoffset will be
+ * set. Static _startdate, _enddate, _starttime, and _endtime will
+ * also be set. TZ string looks like:
+ *
+ * stdoffset[dst[offset][,start[/time],end[/time]]]
+ *
+ * In form of variables: tzname[0]_timezone[tzname[1][_dstoffset]
+ * [,_startdate[/_starttime],_enddate[/_endtime]]]
+ *
+ * ENTRY none.
+ *
+ * RETURN none.
+ */
+
+void _CRTAPI1 tzset(
+ void
+ )
+{
+ /* pch points to the beginning of an element to be parsed. */
+ REG1 char *pch;
+
+ /* pchCurr points to one position after the end of last element parsed. */
+ REG2 char *pchCurr;
+
+ char *TZ;
+
+ _endtime = 7200L;
+ _starttime = 7200L;
+
+ if (!(TZ = getenv("TZ")) || !*TZ) {
+ TZ = "PST8PDT7,M4.1.0/2:00,M10.5.0/2:00"; /* use default */
+ }
+
+ if((pchCurr = ParsePosixStdOrDst(pch=TZ)) == NULL) {
+ return;
+ }
+
+ memcpy(tzname[0], pch, (int)(pchCurr-pch));
+ tzname[0][(int)(pchCurr-pch)] = '\0';
+
+ if((pchCurr = ParsePosixOffset(pch=pchCurr, &_timezone)) == NULL) {
+ return;
+ }
+
+ _daylight = (*pchCurr != '\0');
+
+ if(!_daylight) {
+ return;
+ }
+
+ if((pchCurr = ParsePosixStdOrDst(pch=pchCurr)) == NULL) {
+ return;
+ }
+
+ memcpy(tzname[1], pch, (int)(pchCurr-pch));
+ tzname[1][(int)(pchCurr-pch)] = '\0';
+
+ if(isdigit(*pchCurr) || *pchCurr == '-' || *pchCurr == '+') {
+ if((pchCurr = ParsePosixOffset(pch=pchCurr, &_dstoffset)) == NULL) {
+ return;
+ }
+ } else {
+ /* default: 1 hour ahead of standard time */
+ _dstoffset = _timezone - SEC_PER_HOUR;
+ }
+
+ if(*pchCurr == ',') { /* ,start[/time],end[/time] */
+
+ if((pchCurr = ParsePosixDate(pchCurr+1, &_startdate)) == NULL) {
+ goto out;
+ }
+
+ if(*pchCurr == '/') {
+ if(!(pchCurr = ParsePosixTime(pchCurr+1, &_starttime))) {
+ goto out;
+ }
+ }
+
+ if(*pchCurr != ',') {
+ goto out;
+ }
+
+ if ((pchCurr = ParsePosixDate(pchCurr+1, &_enddate)) == NULL) {
+ goto out;
+ }
+
+ if (*pchCurr == '/') {
+ if(!(pchCurr = ParsePosixTime(pchCurr+1, &_endtime))) {
+ goto out;
+ }
+ }
+ }
+out:
+ /*
+ * Adjust the _endtime to account for the fact that
+ * dst ends at _endtime local time, rather than
+ * standard time.
+ */
+
+ _endtime -= (_timezone - _dstoffset);
+}
+
+
+#define DAY1 (4) /* Jan 1 1970 was a Thursday */
+
+/*
+ * GetDstStartOrEndYearDay - Converts day info from DSTDATE into 0-based
+ * year-day.
+ *
+ * ENTRY tm_year - the year concerned(tb->tm_year).
+ *
+ * pDstDate - pointer to either _startdate or _enddate.
+ *
+ * RETURN the year-day calculated.
+ */
+
+static int _CRTAPI3
+GetDstStartOrEndYearDay(
+ REG1 int tm_year,
+ REG2 PDSTDATE pDstDate
+ )
+{
+ REG1 int yday; /* year-day */
+ REG2 int theyear;
+
+ theyear = tm_year + 1900;
+
+ if(pDstDate->Jn != -1) {
+
+ /*
+ * Jn is in [1, 365] and leap day is not counted.
+ * Convert Jn to 0-based yday; Note: 60 is March 1.
+ */
+
+
+ yday = (IS_LEAP_YEAR(theyear) && (pDstDate->Jn >= 60))
+ ? pDstDate->Jn : pDstDate->Jn - 1;
+
+ } else if(pDstDate->n != -1) {
+
+ /*
+ * n is in [0, 365] and leap day is counted.
+ */
+
+ yday = pDstDate->n;
+
+ } else { /* Mm.n.d */
+
+ int *ptrday;
+ int years;
+ int wday;
+
+ /*
+ * We first need to calculate year-day(yday) and week-day
+ * (wday) of 1st day of month pDstDate->Mm. We then figure
+ * out year-day(yday) of Md day of week Mn of month Mm.
+ */
+
+ ptrday = IS_LEAP_YEAR(theyear) ? _lpdays : _days;
+
+ yday = ptrday[pDstDate->Mm-1] + 1; /* ptrday[i] are all by -1 off */
+
+ years = tm_year - 70;
+
+ /*
+ * Here constant Day1 is the week-day of Jan 1, 1970.
+ * (years+1)/4 is for correcting the leap years.
+ */
+
+ wday = (yday + 365*years + (years+1)/4 + DAY1) % 7;
+
+ /*
+ * Calculate yday of Md day of week 1 of month Mm.
+ */
+
+ yday += pDstDate->Md - wday;
+ if(pDstDate->Md < wday) {
+ yday += 7;
+ }
+
+ /*
+ * Calculate yday of Md day of week Mn of month Mm.
+ */
+
+ yday += (pDstDate->Mn-1)*7;
+
+ /*
+ * Adjust if yday goes beyond the end of the month.
+ */
+
+ if(pDstDate->Md == 5 && yday >= ptrday[pDstDate->Mm] + 1) {
+ yday -= 7;
+ }
+
+ }
+
+ return yday;
+}
+
+/*
+ * _isindst - Tells whether Xenix-type time value falls under DST.
+ *
+ * ENTRY tb - 'time' structure holding broken-down time value.
+ *
+ * RETURN 1 if time represented is in DST, else 0.
+ */
+
+int _CRTAPI1 _isindst (
+ REG1 struct tm *tb
+ )
+{
+ int st_yday, end_yday;
+ int st_sec, end_sec;
+
+ int check_time;
+
+ /*
+ * We need start/end year-days of DST in syday/eyday which are converted
+ * from one of the format Jn, n, and Mm.n.d. We already have start/end
+ * time (in seconds) of DST in _starttime/_endtime.
+ */
+
+ st_yday = GetDstStartOrEndYearDay(tb->tm_year, &_startdate);
+ end_yday = GetDstStartOrEndYearDay(tb->tm_year, &_enddate);
+
+ st_sec = st_yday * SEC_PER_DAY + _starttime;
+ end_sec = end_yday * SEC_PER_DAY + _endtime;
+
+ check_time = tb->tm_yday * SEC_PER_DAY + tb->tm_hour * SEC_PER_HOUR
+ + tb->tm_min * 60 + tb->tm_sec;
+
+ if (check_time >= st_sec && check_time < end_sec)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * _isskiptime - Tells whether the given time is skipped at the
+ * dst change. For instance, we set our clocks forward one
+ * hour at 2am to 3am... This function returns true for
+ * the times between 1:59:59 and 3:00:00.
+ *
+ * ENTRY tb - 'time' structure holding broken-down time value.
+ *
+ * RETURN 1 if time represented is in the skipped period, 0
+ * otherwise.
+ */
+
+int _CRTAPI1 _isskiptime (
+ REG1 struct tm *tb
+ )
+{
+ int st_yday;
+ int st_sec;
+ int check_time;
+
+ st_yday = GetDstStartOrEndYearDay(tb->tm_year, &_startdate);
+ st_sec = st_yday * SEC_PER_DAY + _starttime;
+
+ check_time = tb->tm_yday * SEC_PER_DAY + tb->tm_hour * SEC_PER_HOUR
+ + tb->tm_min * 60 + tb->tm_sec;
+
+ if (check_time >= st_sec && check_time < st_sec - _dstoffset) {
+ return 1;
+ }
+ return 0;
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/utime.c b/private/crt32/time/utime.c
new file mode 100644
index 000000000..c30c77733
--- /dev/null
+++ b/private/crt32/time/utime.c
@@ -0,0 +1,202 @@
+/***
+*utime.c - set modification time for a file
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Sets the access/modification times for a file.
+*
+*Revision History:
+* 03-??-84 RLB initial version
+* 05-17-86 SKS ported to OS/2
+* 08-21-87 JCR error return if localtime() returns NULL.
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 10-03-88 JCR 386: Change DOS calls to SYS calls
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 10-10-88 GJF Made API names match DOSCALLS.H
+* 10-11-88 GJF Made API arg types match DOSCALLS.H
+* 04-12-89 JCR New syscall interface
+* 05-01-89 JCR Corrected OS/2 time/date interpretation
+* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
+* 08-16-89 PHG moved date validation above open() so file isn't left
+* open if the date is invalid
+* 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h>, removed
+* some leftover 16-bit support and fixed the copyright.
+* Also, cleaned up the formatting a bit.
+* 07-25-90 SBM Compiles cleanly with -W3 (added include, removed
+* unreferenced variable), removed '32' from API names
+* 10-04-90 GJF New-style function declarator.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 01-18-91 GJF ANSI naming.
+* 02-14-91 SRW Fix Mips compile error (_WIN32_)
+* 02-26-91 SRW Fix SetFileTime parameter ordering (_WIN32_)
+* 08-21-91 BWM Add _futime to set time on open file
+* 08-26-91 BWM Change _utime to call _futime
+* 05-19-92 DJM ifndef for POSIX build.
+* 08-18-92 SKS SystemTimeToFileTime now takes UTC/GMT, not local time.
+* Remove _CRUISER_ conditional
+* 04-02-93 GJF Changed interpretation of error on SetFileTime call.
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+
+#include <cruntime.h>
+#include <sys/types.h>
+#include <sys/utime.h>
+#include <msdos.h>
+#include <dostypes.h>
+#include <time.h>
+#include <fcntl.h>
+#include <io.h>
+#include <dos.h>
+#include <oscalls.h>
+#include <errno.h>
+#include <stddef.h>
+#include <internal.h>
+
+#include <stdio.h>
+
+/***
+*int _utime(pathname, time) - set modification time for file
+*
+*Purpose:
+* Sets the modification time for the file specified by pathname.
+* Only the modification time from the _utimbuf structure is used
+* under MS-DOS.
+*
+*Entry:
+* struct _utimbuf *time - new modification date
+*
+*Exit:
+* returns 0 if successful
+* returns -1 and sets errno if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _utime (
+ char *fname,
+ struct _utimbuf *times
+ )
+{
+ int fh;
+ int retval;
+
+ /* open file, fname, since filedate system call needs a handle. Note
+ * _utime definition says you must have write permission for the file
+ * to change its time, so open file for write only. Also, must force
+ * it to open in binary mode so we dont remove ^Z's from binary files.
+ */
+
+ if ((fh = _open(fname, _O_RDWR | _O_BINARY)) < 0)
+ return(-1);
+
+ retval = _futime(fh, times);
+
+ _close(fh);
+ return(retval);
+}
+
+/***
+*int _futime(fh, time) - set modification time for open file
+*
+*Purpose:
+* Sets the modification time for the open file specified by fh.
+* Only the modification time from the _utimbuf structure is used
+* under MS-DOS.
+*
+*Entry:
+* struct _utimbuf *time - new modification date
+*
+*Exit:
+* returns 0 if successful
+* returns -1 and sets errno if fails
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _futime (
+ int fh,
+ struct _utimbuf *times
+ )
+{
+ REG1 struct tm *tmb;
+
+#ifndef _WIN32_
+
+#error ERROR - ONLY WIN32 TARGET SUPPORTED!
+
+#else /* def _WIN32_ */
+
+ SYSTEMTIME SystemTime;
+ FILETIME LastWriteTime;
+ FILETIME LastAccessTime;
+ struct _utimbuf deftimes;
+
+ if (times == NULL) {
+ time(&deftimes.modtime);
+ deftimes.actime = deftimes.modtime;
+ times = &deftimes;
+ }
+
+ if ((tmb = gmtime(&times->modtime)) == NULL) {
+ errno = EINVAL;
+ return(-1);
+ }
+
+ SystemTime.wYear = (WORD)(tmb->tm_year + 1900);
+ SystemTime.wMonth = (WORD)(tmb->tm_mon + 1);
+ SystemTime.wDay = (WORD)(tmb->tm_mday);
+ SystemTime.wHour = (WORD)(tmb->tm_hour);
+ SystemTime.wMinute = (WORD)(tmb->tm_min);
+ SystemTime.wSecond = (WORD)(tmb->tm_sec);
+ SystemTime.wMilliseconds = 0;
+ if (!SystemTimeToFileTime( &SystemTime, &LastWriteTime )) {
+ errno = EINVAL;
+ return(-1);
+ }
+
+ if ((tmb = gmtime(&times->actime)) == NULL) {
+ errno = EINVAL;
+ return(-1);
+ }
+
+ SystemTime.wYear = (WORD)(tmb->tm_year + 1900);
+ SystemTime.wMonth = (WORD)(tmb->tm_mon + 1);
+ SystemTime.wDay = (WORD)(tmb->tm_mday);
+ SystemTime.wHour = (WORD)(tmb->tm_hour);
+ SystemTime.wMinute = (WORD)(tmb->tm_min);
+ SystemTime.wSecond = (WORD)(tmb->tm_sec);
+ SystemTime.wMilliseconds = 0;
+ if (!SystemTimeToFileTime( &SystemTime, &LastAccessTime )) {
+ errno = EINVAL;
+ return(-1);
+ }
+
+ /* set the date via the filedate system call and return. failing
+ * this call implies the new file times are not supported by the
+ * underlying file system.
+ */
+
+ if (!SetFileTime((HANDLE)_get_osfhandle(fh),
+ NULL,
+ &LastAccessTime,
+ &LastWriteTime
+ ))
+ {
+ errno = EINVAL;
+ return(-1);
+ }
+
+#endif /* _WIN32_ */
+
+ return(0);
+}
+
+#endif /* _POSIX_ */
diff --git a/private/crt32/time/wcsftime.c b/private/crt32/time/wcsftime.c
new file mode 100644
index 000000000..ab046af58
--- /dev/null
+++ b/private/crt32/time/wcsftime.c
@@ -0,0 +1,67 @@
+/***
+*wcsftime.c - String Format Time
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 03-08-93 CFW Module Created.
+* 03-10-93 CFW Fixed up properly.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+/***
+*size_t wcsftime(wstring, maxsize, format, timeptr) - Format a time string
+*
+*Purpose:
+* The wcsftime functions is equivalent to to the strftime function, except
+* that the argument 'wstring' specifies an array of a wide string into
+* which the generated output is to be placed. The wcsftime acts as if
+* strftime were called and the result string converted by mbstowcs().
+* [ISO]
+*
+*Entry:
+* wchar_t *wstring = pointer to output string
+* size_t maxsize = max length of string
+* const char *format = format control string
+* const struct tm *timeptr = pointer to tb data structure
+*
+*Exit:
+* !0 = If the total number of resulting characters including the
+* terminating null is not more than 'maxsize', then return the
+* number of wide chars placed in the 'wstring' array (not including the
+* null terminator).
+*
+* 0 = Otherwise, return 0 and the contents of the string are
+* indeterminate.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 wcsftime (
+ wchar_t *wstring,
+ size_t maxsize,
+ const char *format,
+ const struct tm *timeptr
+ )
+{
+ /* assumes no multi-byte strings returned from strftime */
+ char *string = (char *)malloc(sizeof(char) * maxsize);
+ size_t retval = 0;
+
+ if (strftime(string, maxsize, format, timeptr))
+ {
+ if ((retval = mbstowcs(wstring, string, maxsize)) == -1)
+ retval = 0;
+ free(string);
+ }
+ return retval;
+}
diff --git a/private/crt32/tools/i386mips.c b/private/crt32/tools/i386mips.c
new file mode 100644
index 000000000..3ad3875d7
--- /dev/null
+++ b/private/crt32/tools/i386mips.c
@@ -0,0 +1,368 @@
+/*
+** I386MIPS - change the machine ID on a COFF object from I386 to R3000
+** Steve Salisbury, 03/24/1992
+*/
+
+#include <fcntl.h>
+#include <io.h>
+#include <stdio.h>
+#include <nt.h>
+
+int main(int argc, char **argv);
+
+IMAGE_FILE_HEADER ifh ;
+IMAGE_SECTION_HEADER ish ;
+IMAGE_RELOCATION reloc ;
+
+const char * RelocName ( int reloctype ) ;
+
+int main(int argc, char **argv)
+{
+ FILE *fileptr;
+ char * name ;
+ char * cp ;
+ int errors = 0 ;
+ int WriteFlag = 0 ;
+
+ -- argc , ++ argv ;
+
+ if ( setvbuf ( stderr , NULL , _IONBF , 0 ) )
+ {
+ printf ( "setvbuf error\n" ) ;
+ exit ( 1 ) ;
+ }
+
+ if ( argc == 0 || ( cp = * argv ) && * cp == '-'
+ && ( * cp == 'h' || * cp == 'H' || * cp == '?' ) )
+ {
+ fprintf ( stderr ,
+ "usage: i386mips [-w] <objectfile> ...\n"
+ "each object file listed is converted from I386 to MIPS\n"
+ "-w specifies that i386 objects should be changed to MIPS objects\n"
+ "NOTE: This only works for files containing data but no code!\n"
+ );
+ exit ( 1 ) ;
+ }
+
+ if ( argc > 1 && ! strcmp ( "-w" , * argv ) )
+ {
+ -- argc , ++ argv ;
+ WriteFlag = 1 ;
+ }
+
+ for ( ; * argv ; )
+ {
+ char * name ;
+ int sect ;
+
+ name = * argv ++ ;
+
+ ++ errors ; /* increment on principle */
+
+ if ( WriteFlag )
+ {
+ if ( ( fileptr = fopen ( name , "r+b" ) ) == NULL )
+ {
+ fprintf ( stderr ,
+ "i386mips: cannot open \"%s\" for modification\n" ,
+ name ) ;
+ continue ;
+ }
+ }
+ else
+ {
+ if ( ( fileptr = fopen ( name , "rb" ) ) == NULL )
+ {
+ fprintf ( stderr ,
+ "i386mips: cannot open \"%s\" for reading\n" ,
+ name ) ;
+ continue ;
+ }
+ }
+
+ if ( 1 != fread ( & ifh , sizeof ( ifh ) , 1 , fileptr ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: cannot read first %d bytes from \"%s\"\n" ,
+ sizeof ( ifh ) , name ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ printf ( "Machine ID = 0x%X (%s)\n" ,
+ ifh.Machine ,
+ ifh.Machine == IMAGE_FILE_MACHINE_I386 ? "i386" :
+ ifh.Machine == IMAGE_FILE_MACHINE_R3000 ? "MIPS" :
+ "?Unknown?" ) ;
+
+ printf ( "%d Sections, TimeDate=%08lX, SizeOptHdr=%u, Flags=0x%X" ,
+ ifh.NumberOfSections, ifh.TimeDateStamp,
+ ifh.SizeOfOptionalHeader , ifh.Characteristics);
+
+ if ( ifh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED )
+ printf ( " NoRelocs" ) ;
+ if ( ifh.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE )
+ printf ( " EXECUTABLE" ) ;
+ if ( ifh.Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED )
+ printf ( " NoLineNums" ) ;
+ if ( ifh.Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED )
+ printf ( " NoLocalSyms" ) ;
+ printf ( "\n" ) ;
+
+ printf ( "\n" ) ;
+
+ if ( WriteFlag )
+ {
+ if ( ifh.Machine != IMAGE_FILE_MACHINE_I386 )
+ {
+ if ( ifh.Machine == IMAGE_FILE_MACHINE_R3000 )
+ fprintf ( stderr ,
+ "i386mips: \"%s\" is already a MIPS COFF file (machine type = 0x%X)\n" ,
+ name , ifh.Machine ) ;
+ else
+ fprintf ( stderr ,
+ "i386mips: \"%s\" is not an i386 COFF file (machine type = 0x%X)\n" ,
+ name , ifh.Machine ) ;
+
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ if ( fseek ( fileptr , 0L , SEEK_SET ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: fseek() error on \"%s\"\n" , name ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ ifh.Machine = IMAGE_FILE_MACHINE_R3000 ;
+
+ if ( 1 != fwrite ( & ifh.Machine , sizeof ( ifh.Machine ) , 1 , fileptr ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: cannot re-write first %d bytes of \"%s\"\n" ,
+ sizeof ( ifh.Machine ) , name ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ printf ( "Machine ID on \"%s\" changed from 0x%X (i386) to 0x%X (MIPS)\n" ,
+ name , IMAGE_FILE_MACHINE_I386 , IMAGE_FILE_MACHINE_R3000 ) ;
+
+ if ( fseek ( fileptr , (long) sizeof ( ifh ) , SEEK_SET ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: fseek() error on \"%s\" (@%ld)\n" , name , sizeof ( ifh ) ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+ }
+
+ for ( sect = 1 ; sect <= ifh.NumberOfSections ; ++ sect )
+ {
+ int s ;
+ long savedpos ;
+
+ if ( 1 != fread ( & ish , sizeof ( ish ) , 1 , fileptr ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: cannot read section header %d from \"%s\"\n" ,
+ sect , name ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ printf ( "Section %d: \"%s\": VirtSize=0x%lX, VirtAdddr=0x%lX\n" ,
+ sect , ish.Name , ish.Misc.VirtualSize, ish.VirtualAddress);
+
+ printf ( "PtrRawData=0x%lX, PtrRelocs=0x%lX, PtrLineNums=0x%lX\n" ,
+ ish.PointerToRawData, ish.PointerToRelocations,
+ ish.PointerToLinenumbers ) ;
+
+ printf ( "#Relocs=%u, #LineNums=%u, Flags=0x%lX" ,
+ ish.NumberOfRelocations, ish.NumberOfLinenumbers, ish.Characteristics);
+ if ( ish.Characteristics & IMAGE_SCN_CNT_CODE )
+ printf ( " Text" ) ;
+ if ( ish.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA )
+ printf ( " Data" ) ;
+ if ( ish.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA )
+ printf ( " BSS" ) ;
+ printf ( "\n" ) ;
+
+ printf ( "\n" ) ;
+
+ savedpos = 0 ;
+
+ if ( ish.PointerToRawData )
+ {
+ int b ;
+
+ savedpos = ftell ( fileptr ) ;
+
+ if ( fseek ( fileptr , ish.PointerToRawData , SEEK_SET ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: fseek() error on \"%s\" (Raw Data at 0x%lX)\n" , name ,
+ ish.PointerToRawData ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ printf ( "Raw Data for Section %d: " , sect ) ;
+
+ for ( b = 0 ; b < ish.Misc.VirtualSize ; ++ b )
+ printf ( " %02X" , getc ( fileptr ) ) ;
+
+ printf ( "\n\n" ) ;
+ }
+
+ if ( ish.NumberOfRelocations )
+ {
+ int r ;
+
+ if ( ! savedpos )
+ savedpos = ftell ( fileptr ) ;
+
+ if ( fseek ( fileptr , ish.PointerToRelocations , SEEK_SET ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: fseek() error on \"%s\" (Relocs at 0x%lX)\n" , name ,
+ ish.PointerToRelocations ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ for ( r = 1 ; r <= ish.NumberOfRelocations ; ++ r )
+ {
+ if ( 1 != fread ( & reloc , sizeof ( reloc ) , 1 , fileptr ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: cannot read relocation %d in section %d from \"%s\"\n" ,
+ r , sect , name ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ printf ( "Relocation %d: Addr=0x%lX, Symbol=%ld, Type=0x%X %s\n" ,
+ r , reloc.VirtualAddress , reloc.SymbolTableIndex ,
+ reloc.Type , RelocName ( reloc.Type ) ) ;
+
+ if ( WriteFlag && reloc.Type == IMAGE_REL_I386_DIR32 )
+ {
+ if ( fseek ( fileptr , ish.PointerToRelocations , SEEK_SET ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: fseek() error on \"%s\" (Reloc %d in Section %d at 0x%lX)\n" , name ,
+ sect , r , ish.PointerToRelocations ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ reloc.Type = IMAGE_REL_MIPS_REFWORD ;
+
+ if ( 1 != fwrite ( & reloc , sizeof ( reloc ) , 1 , fileptr ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: cannot re-write relocation %d in section %d from \"%s\"\n" ,
+ r , sect , name ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ if ( fseek ( fileptr , 0L , SEEK_CUR ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: fseek() error on \"%s\" (after Reloc %d in Section %d at 0x%lX)\n" , name ,
+ sect , r , ish.PointerToRelocations ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+
+ printf ( "===> relocation changed to type %d (%s)\n" ,
+ reloc.Type , RelocName ( reloc.Type ) ) ;
+ }
+
+ }
+
+ printf ( "\n" ) ;
+ }
+
+ printf ( "\n" ) ;
+
+ if ( ! savedpos )
+ savedpos = ftell ( fileptr ) ;
+
+
+ if ( savedpos && fseek ( fileptr , savedpos , SEEK_SET ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: fseek() error on \"%s\" (return to 0x%lX)\n" , name ,
+ savedpos ) ;
+ fclose ( fileptr ) ;
+ continue ;
+ }
+ }
+
+ if ( fclose ( fileptr ) )
+ {
+ fprintf ( stderr ,
+ "i386mips: fclose () error on \"%s\"\n" , name ) ;
+ continue ;
+ }
+
+ -- errors ; /* undo increment on principle */
+
+ }
+
+ return errors ;
+}
+
+const char * RelocName ( int reloctype )
+{
+ char * name ;
+
+ switch ( reloctype )
+ {
+ case 0 :
+ name = "Absolute" ;
+ break ;
+ case 1 :
+ name = "I386_DIR16 / MIPS_REFHALF" ;
+ break ;
+ case 2 :
+ name = "I386_REL16 / MIPS_REFWORD" ;
+ break ;
+ case 3 :
+ name = "MIPS_JMPADDR" ;
+ break ;
+ case 4 :
+ name = "MIPS_REFHI" ;
+ break ;
+ case 5 :
+ name = "MIPS_REFLO" ;
+ break ;
+ case 6 :
+ name = "I386_DIR32 / MIPS_GPREL" ;
+ break ;
+ case 7 :
+ name = "I386_DIR32NB / MIPS_LITERAL" ;
+ break ;
+ case 011 :
+ name = "I386_SEG12" ;
+ break ;
+ case 024 :
+ name = "I386_REL32" ;
+ break ;
+ case 042 :
+ name = "MIPS_REFWORDNB" ;
+ break ;
+ case 045 :
+ name = "MIPS_PAIR" ;
+ break ;
+ default :
+ name = "*** ??? ***" ;
+ }
+
+ return name ;
+}
diff --git a/private/crt32/tools/win32/relinc.cmd b/private/crt32/tools/win32/relinc.cmd
new file mode 100644
index 000000000..8be759b1d
--- /dev/null
+++ b/private/crt32/tools/win32/relinc.cmd
@@ -0,0 +1,172 @@
+@SETLOCAL
+@echo off
+if %CRTDIR%.==. set CRTDIR=\nt\private\crt32
+
+echo.
+echo Release Includes (WIN32/386)
+echo ----------------------------
+if %1.==. goto HELP
+
+rem Set up variables
+rem ----------------
+set IFSCRPT=%CRTDIR%\tools\win32\relinc.if
+set SEDSCRPT=%CRTDIR%\tools\win32\relinc.sed
+set SED=%CRTDIR%\tools\sed
+set IFSTRIP=%CRTDIR%\tools\ifstrip
+set STRIPHDR=%CRTDIR%\tools\striphdr
+
+:DOIT
+rem Make sure the new directories exist
+rem -----------------------------------
+echo Creating directories %1 and %1\sys...
+mkdir %1
+mkdir %1\sys
+
+rem Copy the files to the new directory
+rem -----------------------------------
+echo Copying include files to %1...
+copy %CRTDIR%\H\ASSERT.H %1 > NUL
+copy %CRTDIR%\H\CONIO.H %1 > NUL
+copy %CRTDIR%\H\CTYPE.H %1 > NUL
+copy %CRTDIR%\H\DIRECT.H %1 > NUL
+copy %CRTDIR%\H\DOS.H %1 > NUL
+copy %CRTDIR%\H\ERRNO.H %1 > NUL
+copy %CRTDIR%\H\EXCPT.H %1 > NUL
+copy %CRTDIR%\H\FCNTL.H %1 > NUL
+copy %CRTDIR%\H\FLOAT.H %1 > NUL
+copy %CRTDIR%\H\FPIEEE.H %1 > NUL
+copy %CRTDIR%\H\FSTREAM.H %1 > NUL
+copy %CRTDIR%\H\IO.H %1 > NUL
+copy %CRTDIR%\H\IOMANIP.H %1 > NUL
+copy %CRTDIR%\H\IOS.H %1 > NUL
+copy %CRTDIR%\H\IOSTREAM.H %1 > NUL
+copy %CRTDIR%\H\ISTREAM.H %1 > NUL
+copy %CRTDIR%\H\LIMITS.H %1 > NUL
+copy %CRTDIR%\H\LOCALE.H %1 > NUL
+copy %CRTDIR%\H\MALLOC.H %1 > NUL
+copy %CRTDIR%\H\MATH.H %1 > NUL
+copy %CRTDIR%\H\MBCTYPE.H %1 > NUL
+copy %CRTDIR%\H\MBSTRING.H %1 > NUL
+copy %CRTDIR%\H\MEMORY.H %1 > NUL
+copy %CRTDIR%\H\NEW.H %1 > NUL
+copy %CRTDIR%\H\OSTREAM.H %1 > NUL
+copy %CRTDIR%\H\PROCESS.H %1 > NUL
+copy %CRTDIR%\H\SEARCH.H %1 > NUL
+copy %CRTDIR%\H\SETJMP.H %1 > NUL
+copy %CRTDIR%\H\SETJMPEX.H %1 > NUL
+copy %CRTDIR%\H\SHARE.H %1 > NUL
+copy %CRTDIR%\H\SIGNAL.H %1 > NUL
+copy %CRTDIR%\H\STDARG.H %1 > NUL
+copy %CRTDIR%\H\STDDEF.H %1 > NUL
+copy %CRTDIR%\H\STDIO.H %1 > NUL
+copy %CRTDIR%\H\STDIOSTR.H %1 > NUL
+copy %CRTDIR%\H\STDLIB.H %1 > NUL
+copy %CRTDIR%\H\STREAMB.H %1 > NUL
+copy %CRTDIR%\H\STRING.H %1 > NUL
+copy %CRTDIR%\H\STRSTREA.H %1 > NUL
+copy %CRTDIR%\H\TCHAR.H %1 > NUL
+copy %CRTDIR%\H\TIME.H %1 > NUL
+copy %CRTDIR%\H\WCHAR.H %1 > NUL
+copy %CRTDIR%\H\VARARGS.H %1 > NUL
+copy %CRTDIR%\H\SYS\LOCKING.H %1\sys > NUL
+copy %CRTDIR%\H\SYS\STAT.H %1\sys > NUL
+copy %CRTDIR%\H\SYS\TIMEB.H %1\sys > NUL
+copy %CRTDIR%\H\SYS\TYPES.H %1\sys > NUL
+copy %CRTDIR%\H\SYS\UTIME.H %1\sys > NUL
+rem Strip off the headers
+rem ---------------------
+echo Stripping out the headers...
+%STRIPHDR% -r %1\*.h
+%STRIPHDR% -r %1\sys\*.h
+
+Echo tchar.h is not ifstripped
+copy %1\tchar.new %1\tchar.tmp >NUL
+
+del %1\*.h
+del %1\sys\*.h
+rename %1\*.new *.h
+rename %1\sys\*.new *.h
+rem Strip out the mthread functionality
+rem -----------------------------------
+echo Stripping conditionals...
+%IFSTRIP% -w -f %IFSCRPT% %1\*.h
+%IFSTRIP% -w -f %IFSCRPT% %1\sys\*.h
+del %1\*.h
+del %1\sys\*.h
+rem Sed the files
+rem -------------
+echo Sed'ing include files...
+%SED% -f %SEDSCRPT% <%1\ASSERT.NEW >%1\ASSERT.H
+%SED% -f %SEDSCRPT% <%1\CONIO.NEW >%1\CONIO.H
+%SED% -f %SEDSCRPT% <%1\CTYPE.NEW >%1\CTYPE.H
+%SED% -f %SEDSCRPT% <%1\DIRECT.NEW >%1\DIRECT.H
+%SED% -f %SEDSCRPT% <%1\DOS.NEW >%1\DOS.H
+%SED% -f %SEDSCRPT% <%1\ERRNO.NEW >%1\ERRNO.H
+%SED% -f %SEDSCRPT% <%1\EXCPT.NEW >%1\EXCPT.H
+%SED% -f %SEDSCRPT% <%1\FCNTL.NEW >%1\FCNTL.H
+%SED% -f %SEDSCRPT% <%1\FLOAT.NEW >%1\FLOAT.H
+%SED% -f %SEDSCRPT% <%1\FPIEEE.NEW >%1\FPIEEE.H
+%SED% -f %SEDSCRPT% <%1\FSTREAM.NEW >%1\FSTREAM.H
+%SED% -f %SEDSCRPT% <%1\IO.NEW >%1\IO.H
+%SED% -f %SEDSCRPT% <%1\IOMANIP.NEW >%1\IOMANIP.H
+%SED% -f %SEDSCRPT% <%1\IOS.NEW >%1\IOS.H
+%SED% -f %SEDSCRPT% <%1\IOSTREAM.NEW >%1\IOSTREAM.H
+%SED% -f %SEDSCRPT% <%1\ISTREAM.NEW >%1\ISTREAM.H
+%SED% -f %SEDSCRPT% <%1\LIMITS.NEW >%1\LIMITS.H
+%SED% -f %SEDSCRPT% <%1\LOCALE.NEW >%1\LOCALE.H
+%SED% -f %SEDSCRPT% <%1\MALLOC.NEW >%1\MALLOC.H
+%SED% -f %SEDSCRPT% <%1\MATH.NEW >%1\MATH.H
+%SED% -f %SEDSCRPT% <%1\MBCTYPE.NEW >%1\MBCTYPE.H
+%SED% -f %SEDSCRPT% <%1\MBSTRING.NEW >%1\MBSTRING.H
+%SED% -f %SEDSCRPT% <%1\MEMORY.NEW >%1\MEMORY.H
+%SED% -f %SEDSCRPT% <%1\NEW.NEW >%1\NEW.H
+%SED% -f %SEDSCRPT% <%1\OSTREAM.NEW >%1\OSTREAM.H
+%SED% -f %SEDSCRPT% <%1\PROCESS.NEW >%1\PROCESS.H
+%SED% -f %SEDSCRPT% <%1\SEARCH.NEW >%1\SEARCH.H
+%SED% -f %SEDSCRPT% <%1\SETJMP.NEW >%1\SETJMP.H
+%SED% -f %SEDSCRPT% <%1\SETJMPEX.NEW >%1\SETJMPEX.H
+%SED% -f %SEDSCRPT% <%1\SHARE.NEW >%1\SHARE.H
+%SED% -f %SEDSCRPT% <%1\SIGNAL.NEW >%1\SIGNAL.H
+%SED% -f %SEDSCRPT% <%1\STDARG.NEW >%1\STDARG.H
+%SED% -f %SEDSCRPT% <%1\STDDEF.NEW >%1\STDDEF.H
+%SED% -f %SEDSCRPT% <%1\STDIO.NEW >%1\STDIO.H
+%SED% -f %SEDSCRPT% <%1\STDIOSTR.NEW >%1\STDIOSTR.H
+%SED% -f %SEDSCRPT% <%1\STDLIB.NEW >%1\STDLIB.H
+%SED% -f %SEDSCRPT% <%1\STREAMB.NEW >%1\STREAMB.H
+%SED% -f %SEDSCRPT% <%1\STRING.NEW >%1\STRING.H
+%SED% -f %SEDSCRPT% <%1\STRSTREA.NEW >%1\STRSTREA.H
+%SED% -f %SEDSCRPT% <%1\TIME.NEW >%1\TIME.H
+%SED% -f %SEDSCRPT% <%1\WCHAR.NEW >%1\WCHAR.H
+%SED% -f %SEDSCRPT% <%1\VARARGS.NEW >%1\VARARGS.H
+%SED% -f %SEDSCRPT% <%1\SYS\LOCKING.NEW >%1\SYS\LOCKING.H
+%SED% -f %SEDSCRPT% <%1\SYS\STAT.NEW >%1\SYS\STAT.H
+%SED% -f %SEDSCRPT% <%1\SYS\TIMEB.NEW >%1\SYS\TIMEB.H
+%SED% -f %SEDSCRPT% <%1\SYS\TYPES.NEW >%1\SYS\TYPES.H
+%SED% -f %SEDSCRPT% <%1\SYS\UTIME.NEW >%1\SYS\UTIME.H
+del %1\*.new
+del %1\sys\*.new
+
+copy %1\tchar.tmp %1\tchar.h >NUL
+
+rem clean up
+rem --------
+set IFSCRPT=
+set SEDSCRPT=
+echo Done!
+goto EXIT
+
+:HELP
+echo Relinc.bat cleanses include files for release.
+echo You must be on the CRT32 drive to execute this batch file.
+echo.
+echo relinc "pathname"
+echo.
+echo where:
+echo "pathname" = complete pathname of destination directory
+echo.
+echo Environment variables:
+echo CRTDIR = path of CRT32 project root (default is \NT\PRIVATE\CRT32)
+echo.
+
+:EXIT
+@ENDLOCAL
diff --git a/private/crt32/tools/win32/relinc.if b/private/crt32/tools/win32/relinc.if
new file mode 100644
index 000000000..ca6875e45
--- /dev/null
+++ b/private/crt32/tools/win32/relinc.if
@@ -0,0 +1,74 @@
+COMBOINC
+IBM
+_INTERNAL_IFSTRIP_
+_INTL
+SPEC_NULL
+_WIN32_
+_MBCS
+_KANJI
+-
+CRTDLL
+_CRUISER_
+_DOSX32_
+_CRTHEAP_
+-
+_DLL
+_I386_
+_MIPS_
+_ALPHA_
+_PPC_
+_M_PPC
+_M_ALPHA
+_M_MRX000
+M_MRX000
+_M_RX000
+_M_IX86
+_MSC_VER
+DLL
+MTHREAD
+_CHAR_UNSIGNED
+_UNICODE
+_QC
+_INC_ASSERT
+_INC_CONIO
+_INC_CTYPE
+_INC_DIRECT
+_INC_DOS
+_INC_ERRNO
+_INC_FCNTL
+_INC_FLOAT
+_INC_FSTREAM
+_INC_IO
+_INC_IOMANIP
+_INC_IOS
+_INC_IOSTREAM
+_INC_ISTREAM
+_INC_LIMITS
+_INC_MALLOC
+_INC_MATH
+_INC_MEMORY
+_INC_LOCALE
+_INC_OSCALLS
+_INC_OSTREAM
+_INC_SEARCH
+_INC_SETJMP
+_INC_SHARE
+_INC_SIGNAL
+_INC_STDARG
+_INC_STDDEF
+_INC_STDIO
+_INC_STDIOSTR
+_INC_STDLIB
+_INC_STREAMB
+_INC_STRING
+_INC_STRSTREA
+_INC_TIME
+_INC_VARARGS
+_INC_PROCESS
+_INC_LOCKING
+_INC_STAT
+_INC_TCHAR
+_INC_TIMEB
+_INC_TYPES
+_INC_UTIME
+_INC_WCHAR
diff --git a/private/crt32/tools/win32/relinc.sed b/private/crt32/tools/win32/relinc.sed
new file mode 100644
index 000000000..e0aa7c275
--- /dev/null
+++ b/private/crt32/tools/win32/relinc.sed
@@ -0,0 +1,8 @@
+/_MTHREAD_ONLY/d
+/_LOAD_DGROUP/d
+/_FAR_DEFINED/d
+s/_LOAD_DS //g
+s/MTHREAD/_MT/g
+s/_VARTYPE1 //g
+s/_CRTVAR1 //g
+s/_VA_LIST_T/char */p
diff --git a/private/crt32/winheap/calloc.c b/private/crt32/winheap/calloc.c
new file mode 100644
index 000000000..ad93d8c55
--- /dev/null
+++ b/private/crt32/winheap/calloc.c
@@ -0,0 +1,81 @@
+/***
+*calloc.c - Win32 calloc heap routines
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 01-10-92 JCR Module created.
+* 02-04-92 GJF Replaced windows.h with oscalls.h.
+* 05-06-92 DJM POSIX support.
+* 06-15-92 KRS Enable C++ support.
+* 09-09-92 SRW _POSIX_ not even close.
+* 09-23-92 SRW Change winheap code to call NT directly always
+* 10-28-92 SRW Change winheap code to call Heap????Ex calls
+* 11-05-92 SKS Change name of variable "CrtHeap" to "_crtheap"
+* 11-07-92 SRW _NTIDW340 replaced by linkopts\betacmp.c
+* 11-16-92 SRW Heap???Ex functions renamed to Heap???
+*
+*******************************************************************************/
+
+#include <malloc.h>
+#include <winheap.h>
+#include <os2dll.h>
+#include <oscalls.h>
+
+#ifndef _POSIX_
+#include <new.h>
+extern _PNH _pnhHeap;
+#endif
+
+/***
+*void *calloc(size_t num, size_t size) - allocate storage for an array from
+* the heap
+*
+*Purpose:
+* Allocate a block of memory from heap big enough for an array of num
+* elements of size bytes each, initialize all bytes in the block to 0
+* and return a pointer to it.
+*
+*Entry:
+* size_t num - number of elements in the array
+* size_t size - size of each element
+*
+*Exit:
+* Success: void pointer to allocated block block
+* Failure: NULL
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 calloc ( num, size )
+size_t num;
+size_t size;
+
+{
+ HANDLE h;
+ size_t n;
+
+ if (!(n = num * size)) n = 1;
+
+#ifndef _POSIX_
+ for (;;) {
+#endif /* ndef _POSIX_ */
+
+ h = HeapAlloc(_crtheap,
+ HEAP_ZERO_MEMORY,
+ n
+ );
+#ifndef _POSIX_
+ if ((h != 0) || (_pnhHeap == NULL) || (*_pnhHeap)(n) == 0)
+#endif /* ndef _POSIX_ */
+ return((void *)h);
+
+#ifndef _POSIX_
+ }
+#endif /* ndef _POSIX_ */
+}
diff --git a/private/crt32/winheap/delete.cxx b/private/crt32/winheap/delete.cxx
new file mode 100644
index 000000000..bc2d73e7a
--- /dev/null
+++ b/private/crt32/winheap/delete.cxx
@@ -0,0 +1,28 @@
+/***
+*delete.cxx - defines C++ delete routine
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines C++ delete routine.
+*
+*Revision History:
+* 05-07-90 WAJ Initial version.
+* 08-30-90 WAJ new now takes unsigned ints.
+* 08-08-91 JCR call _halloc/_hfree, not halloc/hfree
+* 08-13-91 KRS Change new.hxx to new.h. Fix copyright.
+* 08-13-91 JCR ANSI-compatible _set_new_handler names
+* 10-30-91 JCR Split new, delete, and handler into seperate sources
+* 11-13-91 JCR 32-bit version
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <new.h>
+
+
+void operator delete( void * p )
+{
+ free( p );
+}
diff --git a/private/crt32/winheap/expand.c b/private/crt32/winheap/expand.c
new file mode 100644
index 000000000..8b142e194
--- /dev/null
+++ b/private/crt32/winheap/expand.c
@@ -0,0 +1,92 @@
+/***
+*expand.c - Win32 expand heap routine
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 01-15-92 JCR Module created.
+* 02-04-92 GJF Replaced windows.h with oscalls.h.
+* 05-06-92 DJM ifndef out of POSIX build.
+* 09-23-92 SRW Change winheap code to call NT directly always
+* 10-15-92 SKS Removed the ill-named HEAP_GROWTH_ALLOWED flag
+* which was causing a bug: _expand was behaving like
+* realloc(), by moving the block when it could not be
+* grown in place. _expand() must NEVER move the block.
+* Also added a safety check to work around a bug in
+* HeapReAlloc, where it returns success even
+* when it fails to grow the block in place.
+* 10-28-92 SRW Change winheap code to call Heap????Ex calls
+* 11-05-92 SKS Change name of variable "CrtHeap" to "_crtheap"
+* 11-07-92 SRW _NTIDW340 replaced by linkopts\betacmp.c
+* 11-16-92 SRW Heap???Ex functions renamed to Heap???
+*
+*******************************************************************************/
+
+#ifndef _POSIX_
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <winheap.h>
+#include <oscalls.h>
+
+/***
+*void *_expand(void *pblck, size_t newsize) - expand/contract a block of memory
+* in the heap
+*
+*Purpose:
+* Resizes a block in the heap to newsize bytes. newsize may be either
+* greater (expansion) or less (contraction) than the original size of
+* the block. The block is NOT moved.
+*
+* NOTES:
+*
+* (1) In this implementation, if the block cannot be grown to the
+* desired size, the resulting block will NOT be grown to the max
+* possible size. (That is, either it works or it doesn't.)
+*
+* (2) Unlike other implementations, you can NOT pass a previously
+* freed block to this routine and expect it to work.
+*
+*Entry:
+* void *pblck - pointer to block in the heap previously allocated
+* by a call to malloc(), realloc() or _expand().
+*
+* size_t newsize - requested size for the resized block
+*
+*Exit:
+* Success: Pointer to the resized memory block (i.e., pblck)
+* Failure: NULL
+*
+*Uses:
+*
+*Exceptions:
+* If pblck does not point to a valid allocation block in the heap,
+* _expand() will behave unpredictably and probably corrupt the heap.
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 _expand(pblock, n)
+void * pblock;
+size_t n;
+
+{
+ void * p;
+
+ p = HeapReAlloc(_crtheap,
+ HEAP_REALLOC_IN_PLACE_ONLY,
+ pblock,
+ n ? n : 1
+ );
+
+ /**
+ * Temporary BUG work-around:
+ * HeapReAlloc sometimes (often?) returns success
+ * even when there has been a failure to grow in place.
+ * This conditional will recognize this case and handle it.
+ **/
+ return ( p == pblock ) && ( _msize(pblock) >= n ) ? pblock : NULL;
+}
+
+#endif /* !_POSIX_ */
diff --git a/private/crt32/winheap/handler.cxx b/private/crt32/winheap/handler.cxx
new file mode 100644
index 000000000..91db57522
--- /dev/null
+++ b/private/crt32/winheap/handler.cxx
@@ -0,0 +1,53 @@
+/***
+*handler.cxx - defines C++ setHandler routine
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines C++ setHandler routine.
+*
+*Revision History:
+* 05-07-90 WAJ Initial version.
+* 08-30-90 WAJ new now takes unsigned ints.
+* 08-08-91 JCR call _halloc/_hfree, not halloc/hfree
+* 08-13-91 KRS Change new.hxx to new.h. Fix copyright.
+* 08-13-91 JCR ANSI-compatible _set_new_handler names
+* 10-30-91 JCR Split new, delete, and handler into seperate sources
+* 11-13-91 JCR 32-bit version
+* 06-15-92 KRS Break MTHREAD support for NT BETA
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <os2dll.h>
+#include <new.h>
+
+/* Warning! MTHREAD is broken! */
+/* Warning! MTHREAD is broken! */
+/* Warning! MTHREAD is broken! */
+
+/* #ifndef MTHREAD */
+/* pointer to C++ new handler */
+extern "C" _PNH _pnhHeap;
+/* #endif */
+
+_PNH _set_new_handler( _PNH pnh )
+{
+_PNH pnhOld;
+
+/* #ifdef MTHREAD
+
+ _pptiddata tdata;
+ tdata = _getptd();
+ pnhOld = ((*tdata)->_tpnhHeap);
+ ((*tdata)->_tpnhHeap) = pnh;
+
+#else */ /* ndef MTHREAD */
+
+ pnhOld = _pnhHeap;
+ _pnhHeap = pnh;
+
+/* #endif */
+
+ return(pnhOld);
+}
diff --git a/private/crt32/winheap/heapchk.c b/private/crt32/winheap/heapchk.c
new file mode 100644
index 000000000..e1479827b
--- /dev/null
+++ b/private/crt32/winheap/heapchk.c
@@ -0,0 +1,131 @@
+/***
+*heapchk.c - perform a consistency check on the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the _heapchk() and _heapset() functions
+*
+*Revision History:
+* 06-30-89 JCR Module created.
+* 07-28-89 GJF Added check for free block preceding the rover
+* 11-13-89 GJF Added MTHREAD support, also fixed copyright
+* 12-13-89 GJF Added check for descriptor order, did some tuning,
+* changed header file name to heap.h
+* 12-15-89 GJF Purged DEBUG286 stuff. Also added explicit _cdecl to
+* function definitions.
+* 12-19-89 GJF Got rid of checks involving plastdesc (revised check
+* of proverdesc and DEBUG errors accordingly)
+* 03-09-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-29-90 GJF Made _heap_checkset() _CALLTYPE4.
+* 09-27-90 GJF New-style function declarators.
+* 03-05-91 GJF Changed strategy for rover - old version available
+* by #define-ing _OLDROVER_.
+* 06-27-94 SRW Ported to Win32 Heap API
+* 07-06-94 SRW Chicago compatibility changes.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stddef.h>
+#include <string.h>
+
+#ifndef _POSIX_
+
+/***
+*int _heapchk() - Validate the heap
+*int _heapset(_fill) - Validate the heap and fill in free entries
+*
+*Purpose:
+* Performs a consistency check on the heap.
+*
+*Entry:
+* For heapchk()
+* No arguments
+* For heapset()
+* int _fill - value to be used as filler in free entries
+*
+*Exit:
+* Returns one of the following values:
+*
+* _HEAPOK - completed okay
+* _HEAPEMPTY - heap not initialized
+* _HEAPBADBEGIN - can't find initial header info
+* _HEAPBADNODE - malformed node somewhere
+*
+* Debug version prints out a diagnostic message if an error is found
+* (see errmsg[] above).
+*
+* NOTE: Add code to support memory regions.
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heapchk(void)
+{
+ if (!HeapValidate( GetProcessHeap(), 0, NULL )) {
+ return _HEAPBADNODE;
+ }
+ else {
+ return _HEAPOK;
+ }
+}
+
+/******************************************************************************/
+
+int _CALLTYPE1 _heapset (
+ unsigned int _fill
+ )
+{
+ int _retval = _HEAPOK;
+ PROCESS_HEAP_ENTRY Entry;
+
+ if (!HeapValidate( GetProcessHeap(), 0, NULL )) {
+ return _HEAPBADNODE;
+ }
+
+ if (!HeapLock( GetProcessHeap() )) {
+ return _HEAPBADBEGIN;
+ }
+
+ Entry.lpData = NULL;
+ try {
+ while (TRUE) {
+ if (!HeapWalk( GetProcessHeap(), &Entry )) {
+ if (GetLastError() != ERROR_NO_MORE_ITEMS) {
+ _retval = _HEAPBADNODE;
+ }
+
+ break;
+ }
+
+ if (Entry.wFlags & (PROCESS_HEAP_REGION | PROCESS_HEAP_UNCOMMITTED_RANGE)) {
+ continue;
+ }
+
+
+ if (!(Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)) {
+ try {
+ memset( Entry.lpData, _fill, Entry.cbData );
+ }
+ except( EXCEPTION_EXECUTE_HANDLER ) {
+ // Chicago free blocks may contain uncommitted pages. Punt
+ }
+ }
+ }
+ }
+ finally {
+ HeapUnlock( GetProcessHeap() );
+ }
+
+ return _retval;
+}
+
+#endif /* !_POSIX_ */
diff --git a/private/crt32/winheap/heapinit.c b/private/crt32/winheap/heapinit.c
new file mode 100644
index 000000000..775317c9c
--- /dev/null
+++ b/private/crt32/winheap/heapinit.c
@@ -0,0 +1,52 @@
+/***
+*heapinit.c - Initialze the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 01-10-92 JCR Module created.
+* 05-12-92 DJM POSIX calls RtlProcessHeap.
+* 09-23-92 SRW Change winheap code to call NT directly always
+* 10-28-92 SRW Change winheap code to call Heap????Ex calls
+* 11-05-92 SKS Change name of variable "CrtHeap" to "_crtheap"
+* 11-07-92 SRW _NTIDW340 replaced by linkopts\betacmp.c
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <winheap.h>
+
+HANDLE _crtheap;
+
+/***
+*_heap_init() - Initialize the heap
+*
+*Purpose:
+* Setup the initial C library heap.
+*
+* NOTES:
+* (1) This routine should only be called once!
+* (2) This routine must be called before any other heap requests.
+* (3) NOTHING TO DO FOR THIS WIN32 HEAP!
+*
+*Entry:
+* <void>
+*Exit:
+* <void>
+*
+*Exceptions:
+* If heap cannot be initialized, the program will be terminated
+* with a fatal runtime error.
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _heap_init (
+ void
+ )
+{
+ _crtheap = GetProcessHeap();
+ return;
+}
diff --git a/private/crt32/winheap/heapmin.c b/private/crt32/winheap/heapmin.c
new file mode 100644
index 000000000..6073adf21
--- /dev/null
+++ b/private/crt32/winheap/heapmin.c
@@ -0,0 +1,73 @@
+/***
+*heapmin.c - Minimize the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Minimize the heap freeing as much memory as possible back
+* to the OS.
+*
+*Revision History:
+* 08-28-89 JCR Module created.
+* 11-06-89 JCR Improved, partitioned
+* 11-13-89 GJF Added MTHREAD support, also fixed copyright
+* 12-14-89 GJF Couple of bug fixes, some tuning, cleaned up the
+* formatting a bit and changed header file name to
+* heap.h
+* 12-20-89 GJF Removed references to plastdesc
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 03-29-90 GJF Made _heapmin_region() and _free_partial_region()
+* _CALLTYPE4.
+* 07-24-90 SBM Compiles cleanly with -W3 (tentatively removed
+* unreferenced labels and unreachable code), removed
+* '32' from API names
+* 09-28-90 GJF New-style function declarators. Also, rewrote expr.
+* to avoid using cast as lvalue.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 03-05-91 GJF Changed strategy for rover - old version available
+* by #define-ing _OLDROVER_.
+* 06-27-94 SRW Ported to Win32 Heap API
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stdlib.h>
+
+#ifndef _POSIX_
+
+/***
+*_heapmin() - Minimize the heap
+*
+*Purpose:
+* Minimize the heap freeing as much memory as possible back
+* to the OS.
+*
+*Entry:
+* (void)
+*
+*Exit:
+*
+* 0 = no error has occurred
+* -1 = an error has occurred (errno is set)
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heapmin(void)
+{
+ if (HeapCompact( GetProcessHeap(), 0 ) == 0) {
+ return -1;
+ }
+ else {
+ return 0;
+ }
+}
+
+#endif /* !_POSIX_ */
diff --git a/private/crt32/winheap/heapwalk.c b/private/crt32/winheap/heapwalk.c
new file mode 100644
index 000000000..4d2175299
--- /dev/null
+++ b/private/crt32/winheap/heapwalk.c
@@ -0,0 +1,101 @@
+/***
+*heapwalk.c - walk the heap
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the _heapwalk() function
+*
+*Revision History:
+* 07-05-89 JCR Module created.
+* 11-13-89 GJF Added MTHREAD support, also fixed copyright.
+* 11-14-89 JCR Fixed bug -- returned address was off by HDRSIZE
+* 12-18-89 GJF Removed DEBUG286 stuff, also some tuning, cleaned up
+* format a bit, changed header file name to heap.h, added
+* explicit _cdecl to function definition
+* 12-20-89 GJF Removed references to plastdesc
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and removed #include <register.h>.
+* 09-28-90 GJF New-style function declarator.
+* 06-27-94 SRW Ported to Win32 Heap API
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <oscalls.h>
+#include <malloc.h>
+#include <os2dll.h>
+#include <stddef.h>
+
+#ifndef _POSIX_
+
+/***
+*int _heapwalk() - Walk the heap
+*
+*Purpose:
+* Walk the heap returning information on one entry at a time.
+*
+*Entry:
+* struct _heapinfo {
+* int * _pentry; heap entry pointer
+* size_t size; size of heap entry
+* int _useflag; free/inuse flag
+* } *entry;
+*
+*Exit:
+* Returns one of the following values:
+*
+* _HEAPOK - completed okay
+* _HEAPEMPTY - heap not initialized
+* _HEAPBADPTR - _pentry pointer is bogus
+* _HEAPBADBEGIN - can't find initial header info
+* _HEAPBADNODE - malformed node somewhere
+* _HEAPEND - end of heap successfully reached
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _heapwalk (
+ struct _heapinfo *_entry
+ )
+{
+ PROCESS_HEAP_ENTRY Entry;
+ int retval = _HEAPOK;
+
+ Entry.wFlags = 0;
+ Entry.iRegionIndex = 0;
+ if ((Entry.lpData = _entry->_pentry) == NULL) {
+ if (!HeapWalk( GetProcessHeap(), &Entry )) {
+ return _HEAPBADBEGIN;
+ }
+ }
+ else {
+ if (_entry->_useflag == _USEDENTRY) {
+ Entry.wFlags = PROCESS_HEAP_ENTRY_BUSY;
+ }
+nextBlock:
+ if (!HeapWalk( GetProcessHeap(), &Entry )) {
+ return _HEAPBADNODE;
+ }
+ }
+
+ if (Entry.wFlags & (PROCESS_HEAP_REGION | PROCESS_HEAP_UNCOMMITTED_RANGE)) {
+ goto nextBlock;
+ }
+
+ _entry->_pentry = Entry.lpData;
+ _entry->_size = Entry.cbData;
+ if (Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) {
+ _entry->_useflag = _USEDENTRY;
+ }
+ else {
+ _entry->_useflag = _FREEENTRY;
+ }
+
+ return(retval);
+}
+
+#endif /* !_POSIX_ */
diff --git a/private/crt32/winheap/hpabort.c b/private/crt32/winheap/hpabort.c
new file mode 100644
index 000000000..9227a5b4b
--- /dev/null
+++ b/private/crt32/winheap/hpabort.c
@@ -0,0 +1,47 @@
+/***
+* hpabort.c - Abort process due to fatal heap error
+*
+* Copyright (c) 1988-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 11-13-89 JCR Module created
+* 12-18-89 GJF #include-ed heap.h, also added explicit _cdecl to
+* function definition.
+* 03-11-90 GJF Replaced _cdecl with _CALLTYPE1 and added #include
+* <cruntime.h>.
+* 10-03-90 GJF New-style function declarator.
+* 10-11-90 GJF Changed interface to _amsg_exit().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <heap.h>
+#include <internal.h>
+#include <rterr.h>
+
+
+/***
+* _heap_abort() - Abort process due to fatal heap error
+*
+*Purpose:
+* Terminate the process and output a heap error message
+*
+*Entry:
+* Void
+*
+*Exit:
+* Never returns
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _heap_abort (
+ void
+ )
+{
+ _amsg_exit(_RT_HEAP); /* heap error */
+ /*** PROCESS TERMINATED ***/
+}
diff --git a/private/crt32/winheap/makefile b/private/crt32/winheap/makefile
new file mode 100644
index 000000000..9e18c9a05
--- /dev/null
+++ b/private/crt32/winheap/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+BLDCRT=1
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/winheap/malloc.c b/private/crt32/winheap/malloc.c
new file mode 100644
index 000000000..ae3907656
--- /dev/null
+++ b/private/crt32/winheap/malloc.c
@@ -0,0 +1,104 @@
+/***
+*malloc.c - Win32 malloc/free heap routines
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 01-10-92 JCR Module created.
+* 02-04-92 GJF Replaced windows.h with oscalls.h.
+* 05-06-92 DJM POSIX support.
+* 06-15-92 KRS Enable C++ support.
+* 09-09-92 SRW _POSIX_ not even close.
+* 09-23-92 SRW Change winheap code to call NT directly always
+* 10-28-92 SRW Change winheap code to call Heap????Ex calls
+* 11-05-92 SKS Change name of variable "CrtHeap" to "_crtheap"
+* 11-07-92 SRW _NTIDW340 replaced by linkopts\betacmp.c
+* 11-16-92 SRW Heap???Ex functions renamed to Heap???
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <winheap.h>
+#include <os2dll.h>
+#include <oscalls.h>
+
+#ifndef _POSIX_
+#include <new.h>
+_PNH _pnhHeap = NULL;
+#endif
+
+/***
+*void *malloc(size_t size) - Get a block of memory from the heap
+*
+*Purpose:
+* Allocate of block of memory of at least size bytes from the heap and
+* return a pointer to it.
+*
+*Entry:
+* size_t size - size of block requested
+*
+*Exit:
+* Success: Pointer to memory block
+* Failure: NULL (or some error value)
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 malloc(n)
+size_t n;
+
+{
+ HANDLE h;
+ n = (n ? n : 1); /* if n == 0, n = 1 */
+
+#ifndef _POSIX_
+ for (;;) {
+#endif /* ndef _POSIX_ */
+
+ h = HeapAlloc(_crtheap,
+ 0,
+ n
+ );
+#ifndef _POSIX_
+ if ((h != 0) || (_pnhHeap == NULL) || (*_pnhHeap)(n) == 0)
+#endif /* ndef _POSIX_ */
+ return((void *)h);
+
+#ifndef _POSIX_
+ }
+#endif /* ndef _POSIX_ */
+}
+
+/***
+*void free(pblock) - free a block in the heap
+*
+*Purpose:
+* Free a memory block in the heap.
+*
+* Special ANSI Requirements:
+*
+* (1) free(NULL) is benign.
+*
+*Entry:
+* void *pblock - pointer to a memory block in the heap
+*
+*Return:
+* <void>
+*
+*******************************************************************************/
+
+void _CALLTYPE1 free(pblock)
+void * pblock;
+
+{
+ HeapFree(_crtheap,
+ 0,
+ pblock
+ );
+}
diff --git a/private/crt32/winheap/msize.c b/private/crt32/winheap/msize.c
new file mode 100644
index 000000000..37752cf46
--- /dev/null
+++ b/private/crt32/winheap/msize.c
@@ -0,0 +1,49 @@
+/***
+*msize.c - Win32 malloc/free heap routines
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 01-10-92 JCR Module created.
+* 02-04-92 GJF Replaced windows.h with oscalls.h.
+* 05-06-92 DJM ifndef out for POSIX.
+* 09-23-92 SRW Change winheap code to call NT directly always
+* 10-28-92 SRW Change winheap code to call Heap????Ex calls
+* 11-05-92 SKS Change name of variable "CrtHeap" to "_crtheap"
+* 11-07-92 SRW _NTIDW340 replaced by linkopts\betacmp.c
+* 11-16-92 SRW Heap???Ex functions renamed to Heap???
+* 12-02-94 MJB POSIX back in.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <winheap.h>
+#include <oscalls.h>
+
+/***
+*size_t _msize(pblock) - calculate the size of specified block in the heap
+*
+*Purpose:
+* Calculates the size of memory block (in the heap) pointed to by
+* pblock.
+*
+*Entry:
+* void *p - pointer to a memory block in the heap
+*
+*Return:
+* size of the block
+*
+*******************************************************************************/
+
+size_t _CALLTYPE1 _msize(pblock)
+void * pblock;
+
+{
+ return((size_t)HeapSize(_crtheap,
+ 0,
+ pblock
+ ));
+}
diff --git a/private/crt32/winheap/new.cxx b/private/crt32/winheap/new.cxx
new file mode 100644
index 000000000..4a47fb1c5
--- /dev/null
+++ b/private/crt32/winheap/new.cxx
@@ -0,0 +1,28 @@
+/***
+*new.cxx - defines C++ new routine
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines C++ new routine.
+*
+*Revision History:
+* 05-07-90 WAJ Initial version.
+* 08-30-90 WAJ new now takes unsigned ints.
+* 08-08-91 JCR call _halloc/_hfree, not halloc/hfree
+* 08-13-91 KRS Change new.hxx to new.h. Fix copyright.
+* 08-13-91 JCR ANSI-compatible _set_new_handler names
+* 10-30-91 JCR Split new, delete, and handler into seperate sources
+* 11-13-91 JCR 32-bit version
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <new.h>
+
+
+void * operator new( unsigned int cb )
+{
+ return malloc( cb );
+}
diff --git a/private/crt32/winheap/realloc.c b/private/crt32/winheap/realloc.c
new file mode 100644
index 000000000..ac66611a4
--- /dev/null
+++ b/private/crt32/winheap/realloc.c
@@ -0,0 +1,85 @@
+/***
+*realloc.c - Win32 realloc heap routine
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 01-10-92 JCR Module created.
+* 02-04-92 GJF Replaced windows.h with oscalls.h.
+* 05-06-92 DJM POSIX support.
+* 09-09-92 SRW Fixed _POSIX_ to allow movement when growing.
+* 09-23-92 SRW Change winheap code to call NT directly always
+* 10-28-92 SRW Change winheap code to call Heap????Ex calls
+* 11-05-92 SKS Change name of variable "CrtHeap" to "_crtheap"
+* 11-07-92 SRW _NTIDW340 replaced by linkopts\betacmp.c
+* 11-16-92 SRW Heap???Ex functions renamed to Heap???
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <malloc.h>
+#include <winheap.h>
+#include <oscalls.h>
+
+/***
+*void *realloc(void *pblock, size_t newsize) - reallocate a block of memory in
+* the heap
+*
+*Purpose:
+* Re-allocates a block in the heap to newsize bytes. newsize may be
+* either greater or less than the original size of the block. The
+* re-allocation may result in moving the block as well as changing
+* the size. If the block is moved, the contents of the original block
+* are copied over.
+*
+* Special ANSI Requirements:
+*
+* (1) realloc(NULL, newsize) is equivalent to malloc(newsize)
+*
+* (2) realloc(pblock, 0) is equivalent to free(pblock) (except that
+* NULL is returned)
+*
+* (3) if the realloc() fails, the object pointed to by pblock is left
+* unchanged
+*
+*Entry:
+* void *pblock - pointer to block in the heap previously allocated
+* by a call to malloc(), realloc() or _expand().
+*
+* size_t newsize - requested size for the re-allocated block
+*
+*Exit:
+* Success: Pointer to the re-allocated memory block
+* Failure: NULL
+*
+*Uses:
+*
+*Exceptions:
+* If pblock does not point to a valid allocation block in the heap,
+* realloc() will behave unpredictably and probably corrupt the heap.
+*
+*******************************************************************************/
+
+void * _CALLTYPE1 realloc(pblock, n)
+void * pblock;
+size_t n;
+
+{
+ /* if ptr is NULL, call malloc */
+ if (pblock == (void *) NULL)
+ return(malloc(n));
+
+ /* if ptr is !NULL and size is 0, call free and return NULL */
+ if (n == 0) {
+ free(pblock);
+ return((void *) NULL);
+ }
+
+ return HeapReAlloc(_crtheap,
+ 0,
+ pblock,
+ n
+ );
+}
diff --git a/private/crt32/winheap/sources b/private/crt32/winheap/sources
new file mode 100644
index 000000000..add361dd9
--- /dev/null
+++ b/private/crt32/winheap/sources
@@ -0,0 +1,51 @@
+!IF 0
+
+Copyright (c) 1989 - 1992, Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+ Set MAKEFILE. for BLDCRT=1 definition that forces use of MS C8 C++ compiler
+ for all platforms to compile these files.
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+ karlsi 15-Jun-92, added new.cxx/delete.cxx/handler.cxx.
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=winheap
+
+TARGETNAME=winheap
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=calloc.c \
+ delete.cxx \
+ expand.c \
+ handler.cxx \
+ heapinit.c \
+ heapchk.c \
+ heapmin.c \
+ heapwalk.c \
+ hpabort.c \
+ malloc.c \
+ msize.c \
+ new.cxx \
+ realloc.c
diff --git a/private/crt32/wstring/makefile b/private/crt32/wstring/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/crt32/wstring/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/crt32/wstring/sources b/private/crt32/wstring/sources
new file mode 100644
index 000000000..f324011d5
--- /dev/null
+++ b/private/crt32/wstring/sources
@@ -0,0 +1,53 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+ karlsi 06-Jun-1992, wstring dir no longer used--could be deleted.
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=wstring
+
+TARGETNAME=wstring
+TARGETPATH=..\obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+SOURCES=
+
+!IF 0
+ wcscat.c \
+ wcschr.c \
+ wcscmp.c \
+ wcslen.c \
+ wcsncat.c \
+ wcsncmp.c \
+ wcsnicmp.c \
+ wcsncpy.c \
+ wcsrchr.c \
+ wcsspn.c \
+ wcscspn.c \
+ wcspbrk.c \
+ wcswcs.c
+!ENDIF